feat: Add user data import feature (Fixes #26) #27

Merged
egullickson merged 11 commits from issue-26-add-user-data-import into main 2026-01-12 03:22:32 +00:00
Showing only changes of commit 62b4dc31ab - Show all commits

View File

@@ -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,
});
}
/**