feat: Add user data import feature (Fixes #26) #27
@@ -231,6 +231,8 @@ export class UserImportService {
|
||||
): Promise<void> {
|
||||
const vehicles = await this.archiveService.readDataFile<any>(extractedPath, 'vehicles.json');
|
||||
|
||||
logger.info('Merge vehicles starting', { userId, vehicleCount: vehicles.length });
|
||||
|
||||
if (vehicles.length === 0) {
|
||||
return;
|
||||
}
|
||||
@@ -242,11 +244,22 @@ export class UserImportService {
|
||||
|
||||
for (const vehicle of chunk) {
|
||||
try {
|
||||
logger.debug('Processing vehicle', {
|
||||
userId,
|
||||
vin: vehicle.vin,
|
||||
make: vehicle.make,
|
||||
model: vehicle.model,
|
||||
year: vehicle.year,
|
||||
});
|
||||
|
||||
let existing = null;
|
||||
|
||||
// Try to find existing vehicle by VIN first
|
||||
if (vehicle.vin && vehicle.vin.trim().length > 0) {
|
||||
existing = await this.vehiclesRepo.findByUserAndVIN(userId, vehicle.vin.trim());
|
||||
if (existing) {
|
||||
logger.debug('Found existing vehicle by VIN', { vehicleId: existing.id, vin: vehicle.vin });
|
||||
}
|
||||
}
|
||||
|
||||
// If not found by VIN and license plate exists, try license plate
|
||||
@@ -255,10 +268,17 @@ export class UserImportService {
|
||||
existing = allUserVehicles.find(
|
||||
(v) => v.licensePlate && v.licensePlate.toLowerCase() === vehicle.licensePlate.toLowerCase()
|
||||
) || null;
|
||||
if (existing) {
|
||||
logger.debug('Found existing vehicle by license plate', {
|
||||
vehicleId: existing.id,
|
||||
licensePlate: vehicle.licensePlate,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (existing) {
|
||||
// Update existing vehicle
|
||||
logger.debug('Updating existing vehicle', { vehicleId: existing.id });
|
||||
await this.vehiclesRepo.update(existing.id, {
|
||||
make: vehicle.make,
|
||||
model: vehicle.model,
|
||||
@@ -278,7 +298,14 @@ export class UserImportService {
|
||||
}
|
||||
|
||||
// Insert new vehicle using service (enforces tier limits)
|
||||
await this.vehiclesService.createVehicle(
|
||||
logger.debug('Creating new vehicle via service', {
|
||||
userId,
|
||||
vin: vehicle.vin || '',
|
||||
make: vehicle.make,
|
||||
model: vehicle.model,
|
||||
});
|
||||
|
||||
const result = await this.vehiclesService.createVehicle(
|
||||
{
|
||||
vin: vehicle.vin || '',
|
||||
make: vehicle.make,
|
||||
@@ -296,18 +323,34 @@ export class UserImportService {
|
||||
},
|
||||
userId
|
||||
);
|
||||
|
||||
logger.info('Vehicle created successfully', { vehicleId: result.id });
|
||||
summary.imported++;
|
||||
} catch (error) {
|
||||
if (error instanceof VehicleLimitExceededError) {
|
||||
summary.errors.push(
|
||||
`Vehicle limit exceeded: ${error.upgradePrompt} (current: ${error.currentCount}/${error.limit})`
|
||||
);
|
||||
} else {
|
||||
summary.errors.push(`Vehicle import failed: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
const errorMsg =
|
||||
error instanceof VehicleLimitExceededError
|
||||
? `Vehicle limit exceeded: ${error.upgradePrompt} (current: ${error.currentCount}/${error.limit})`
|
||||
: `Vehicle import failed: ${error instanceof Error ? error.message : String(error)}`;
|
||||
|
||||
logger.error('Vehicle import error', {
|
||||
userId,
|
||||
vin: vehicle.vin,
|
||||
make: vehicle.make,
|
||||
model: vehicle.model,
|
||||
error: errorMsg,
|
||||
});
|
||||
|
||||
summary.errors.push(errorMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info('Merge vehicles completed', {
|
||||
userId,
|
||||
imported: summary.imported,
|
||||
updated: summary.updated,
|
||||
errors: summary.errors.length,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user