fix: ( seed ) add try catch

This commit is contained in:
Abubeker Yasin
2026-06-11 08:45:32 +03:00
parent 1e129de010
commit 216dd11d2f

View File

@@ -1,4 +1,4 @@
import { Prisma, PrismaClient } from '@prisma/client';
import { PrismaClient } from '@prisma/client';
import * as bcrypt from 'bcrypt';
import { randomUUID as uuidv4 } from 'crypto';
@@ -224,12 +224,10 @@ async function seedCoaches() {
create: coach,
});
// Rebuild the coach's seats from scratch. A plain upsert keyed on
// coachId_seatNumber can't reconcile a changed layout (it's blind to the
// @@unique([coachId, row, col]) constraint), so stale row/col data collides.
await prisma.seat.deleteMany({ where: { coachId: c.id } });
const seats: Prisma.SeatCreateManyInput[] = [];
// Idempotently reconcile the coach's seats. Upsert keyed on the
// @@unique([coachId, row, col]) constraint so a re-seed updates existing
// rows in place instead of deleting them. Deleting Seats fails with a P2003
// FK violation once BookingSeat/SeatBlock/TicketSeat rows reference them.
let seatIndex = 1;
for (let row = 1; row <= Math.ceil(coach.capacity / 2); row++) {
for (const col of ['A', 'B', 'C', 'D']) {
@@ -241,19 +239,21 @@ async function seedCoaches() {
else bedPosition = 'lower';
}
seats.push({
coachId: c.id,
const seatData = {
seatNumber: seatIndex.toString(),
row,
col,
isWindow: col === 'A' || col === 'D',
isAisle: col === 'B' || col === 'C',
bedPosition,
};
await prisma.seat.upsert({
where: { coachId_row_col: { coachId: c.id, row, col } },
update: seatData,
create: { coachId: c.id, row, col, ...seatData },
});
seatIndex++;
}
}
await prisma.seat.createMany({ data: seats });
totalSeats += coach.capacity;
}
console.log(`${coaches.length} coaches with ${totalSeats} seats created`);
@@ -552,25 +552,49 @@ async function seedFraudRules() {
console.log(`${rules.length} fraud detection rules created`);
}
// Run a seed step in isolation: if it throws (FK conflict, duplicate row,
// missing record, etc.) log the error and keep going so the rest of the seed —
// and the API startup that follows it — are never blocked by one bad step.
async function runStep(name: string, step: () => Promise<void>): Promise<boolean> {
try {
await step();
return true;
} catch (e) {
console.error(`⚠️ Seed step "${name}" failed — skipping and continuing:`, e);
return false;
}
}
async function main() {
console.log('🌱 Comprehensive EDR Seed Starting...\n');
await seedSystemUsers();
await seedStations();
await seedCoachTypesAndClasses();
await seedRoute();
await seedCoaches();
await seedTrips();
await seedFareRules();
await seedCurrency();
await seedPaymentMethods();
await seedNotificationTemplates();
await seedMenuAndFood();
await seedPromotions();
await seedFAQ();
await seedFraudRules();
const steps: Array<[string, () => Promise<void>]> = [
['system users', seedSystemUsers],
['stations', seedStations],
['coach types & classes', seedCoachTypesAndClasses],
['route', seedRoute],
['coaches', seedCoaches],
['trips', seedTrips],
['fare rules', seedFareRules],
['currency', seedCurrency],
['payment methods', seedPaymentMethods],
['notification templates', seedNotificationTemplates],
['menu & food', seedMenuAndFood],
['promotions', seedPromotions],
['FAQ', seedFAQ],
['fraud rules', seedFraudRules],
];
let failed = 0;
for (const [name, step] of steps) {
if (!(await runStep(name, step))) failed++;
}
if (failed > 0) {
console.warn(`\n⚠ Seed finished with ${failed}/${steps.length} step(s) failed (see logs above).\n`);
} else {
console.log('\n✅ Seed complete!\n');
}
console.log('🔑 System Users:');
console.log(' Admin: admin@edr-platform.com / admin123');
console.log(' Passenger: kelemu@email.com / password123');
@@ -581,8 +605,10 @@ async function main() {
main()
.catch((e) => {
console.error('❌ Seed failed:', e);
process.exit(1);
// Intentionally do NOT process.exit(1): the docker entrypoint runs under
// `set -e`, so a non-zero exit here would abort container startup and the
// API would never boot. Log and exit cleanly instead.
console.error('❌ Seed crashed unexpectedly — continuing so the API can start:', e);
})
.finally(async () => {
await prisma.$disconnect();