fix: Database schema fixes. CI/CD improvements.
This commit is contained in:
@@ -59,7 +59,7 @@ export class CatalogImportService {
|
||||
async previewImport(csvContent: string): Promise<ImportPreviewResult> {
|
||||
const previewId = uuidv4();
|
||||
const toCreate: ImportRow[] = [];
|
||||
const toUpdate: ImportRow[] = [];
|
||||
const toUpdate: ImportRow[] = []; // Kept for interface compatibility (will be empty)
|
||||
const errors: ImportError[] = [];
|
||||
|
||||
const lines = csvContent.trim().split('\n');
|
||||
@@ -146,21 +146,8 @@ export class CatalogImportService {
|
||||
transmissionType,
|
||||
};
|
||||
|
||||
// Check if record exists to determine create vs update (upsert logic)
|
||||
const existsResult = await this.pool.query(
|
||||
`SELECT id FROM vehicle_options
|
||||
WHERE year = $1 AND make = $2 AND model = $3 AND trim = $4
|
||||
LIMIT 1`,
|
||||
[year, make, model, trim]
|
||||
);
|
||||
const exists = (existsResult.rowCount || 0) > 0;
|
||||
|
||||
// Auto-detect: if exists -> update, else -> create
|
||||
if (exists) {
|
||||
toUpdate.push(row);
|
||||
} else {
|
||||
toCreate.push(row);
|
||||
}
|
||||
// All rows will be inserted with ON CONFLICT handling (proper upsert)
|
||||
toCreate.push(row);
|
||||
} catch (error: any) {
|
||||
errors.push({ row: rowNum, error: error.message || 'Parse error' });
|
||||
}
|
||||
@@ -239,61 +226,29 @@ export class CatalogImportService {
|
||||
transmissionId = transResult.rows[0].id;
|
||||
}
|
||||
|
||||
// Insert vehicle option
|
||||
await client.query(
|
||||
// Upsert vehicle option (insert or update if exists)
|
||||
const upsertResult = await client.query(
|
||||
`INSERT INTO vehicle_options (year, make, model, trim, engine_id, transmission_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)`,
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
ON CONFLICT (year, make, model, trim, engine_id, transmission_id)
|
||||
DO UPDATE SET updated_at = NOW()
|
||||
RETURNING (xmax = 0) AS inserted`,
|
||||
[row.year, row.make, row.model, row.trim, engineId, transmissionId]
|
||||
);
|
||||
|
||||
result.created++;
|
||||
// Check if this was an insert (xmax=0) or update (xmax!=0)
|
||||
const wasInserted = upsertResult.rows[0].inserted;
|
||||
if (wasInserted) {
|
||||
result.created++;
|
||||
} else {
|
||||
result.updated++;
|
||||
}
|
||||
} catch (error: any) {
|
||||
result.errors.push({ row: 0, error: `Failed to create ${row.year} ${row.make} ${row.model} ${row.trim}: ${error.message}` });
|
||||
result.errors.push({ row: 0, error: `Failed to upsert ${row.year} ${row.make} ${row.model} ${row.trim}: ${error.message}` });
|
||||
}
|
||||
}
|
||||
|
||||
// Process updates
|
||||
for (const row of preview.toUpdate) {
|
||||
try {
|
||||
// Get or create engine
|
||||
let engineId: number | null = null;
|
||||
if (row.engineName) {
|
||||
const engineResult = await client.query(
|
||||
`INSERT INTO engines (name, fuel_type)
|
||||
VALUES ($1, 'Gas')
|
||||
ON CONFLICT ((lower(name))) DO UPDATE SET name = EXCLUDED.name
|
||||
RETURNING id`,
|
||||
[row.engineName]
|
||||
);
|
||||
engineId = engineResult.rows[0].id;
|
||||
}
|
||||
|
||||
// Get or create transmission
|
||||
let transmissionId: number | null = null;
|
||||
if (row.transmissionType) {
|
||||
const transResult = await client.query(
|
||||
`INSERT INTO transmissions (type)
|
||||
VALUES ($1)
|
||||
ON CONFLICT ((lower(type))) DO UPDATE SET type = EXCLUDED.type
|
||||
RETURNING id`,
|
||||
[row.transmissionType]
|
||||
);
|
||||
transmissionId = transResult.rows[0].id;
|
||||
}
|
||||
|
||||
// Update vehicle option
|
||||
await client.query(
|
||||
`UPDATE vehicle_options
|
||||
SET engine_id = $5, transmission_id = $6, updated_at = NOW()
|
||||
WHERE year = $1 AND make = $2 AND model = $3 AND trim = $4`,
|
||||
[row.year, row.make, row.model, row.trim, engineId, transmissionId]
|
||||
);
|
||||
|
||||
result.updated++;
|
||||
} catch (error: any) {
|
||||
result.errors.push({ row: 0, error: `Failed to update ${row.year} ${row.make} ${row.model} ${row.trim}: ${error.message}` });
|
||||
}
|
||||
}
|
||||
// Note: Separate "Process updates" loop removed - ON CONFLICT handles both INSERT and UPDATE
|
||||
|
||||
await client.query('COMMIT');
|
||||
|
||||
@@ -306,13 +261,23 @@ export class CatalogImportService {
|
||||
logger.debug('Vehicle data cache invalidated after import');
|
||||
}
|
||||
|
||||
logger.info('Catalog import completed', {
|
||||
previewId,
|
||||
created: result.created,
|
||||
updated: result.updated,
|
||||
errors: result.errors.length,
|
||||
changedBy,
|
||||
});
|
||||
// Log completion with appropriate level
|
||||
if (result.errors.length > 0) {
|
||||
logger.warn('Catalog import completed with errors', {
|
||||
previewId,
|
||||
created: result.created,
|
||||
updated: result.updated,
|
||||
errors: result.errors.length,
|
||||
changedBy,
|
||||
});
|
||||
} else {
|
||||
logger.info('Catalog import completed successfully', {
|
||||
previewId,
|
||||
created: result.created,
|
||||
updated: result.updated,
|
||||
changedBy,
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user