mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-09 10:58:14 +00:00
@@ -1,4 +1,4 @@
|
|||||||
import { Prisma, PrismaClient } from '@prisma/client';
|
import { PrismaClient } from '@prisma/client';
|
||||||
import * as bcrypt from 'bcrypt';
|
import * as bcrypt from 'bcrypt';
|
||||||
import { randomUUID as uuidv4 } from 'crypto';
|
import { randomUUID as uuidv4 } from 'crypto';
|
||||||
|
|
||||||
@@ -224,12 +224,10 @@ async function seedCoaches() {
|
|||||||
create: coach,
|
create: coach,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Rebuild the coach's seats from scratch. A plain upsert keyed on
|
// Idempotently reconcile the coach's seats. Upsert keyed on the
|
||||||
// coachId_seatNumber can't reconcile a changed layout (it's blind to the
|
// @@unique([coachId, row, col]) constraint so a re-seed updates existing
|
||||||
// @@unique([coachId, row, col]) constraint), so stale row/col data collides.
|
// rows in place instead of deleting them. Deleting Seats fails with a P2003
|
||||||
await prisma.seat.deleteMany({ where: { coachId: c.id } });
|
// FK violation once BookingSeat/SeatBlock/TicketSeat rows reference them.
|
||||||
|
|
||||||
const seats: Prisma.SeatCreateManyInput[] = [];
|
|
||||||
let seatIndex = 1;
|
let seatIndex = 1;
|
||||||
for (let row = 1; row <= Math.ceil(coach.capacity / 2); row++) {
|
for (let row = 1; row <= Math.ceil(coach.capacity / 2); row++) {
|
||||||
for (const col of ['A', 'B', 'C', 'D']) {
|
for (const col of ['A', 'B', 'C', 'D']) {
|
||||||
@@ -241,19 +239,21 @@ async function seedCoaches() {
|
|||||||
else bedPosition = 'lower';
|
else bedPosition = 'lower';
|
||||||
}
|
}
|
||||||
|
|
||||||
seats.push({
|
const seatData = {
|
||||||
coachId: c.id,
|
|
||||||
seatNumber: seatIndex.toString(),
|
seatNumber: seatIndex.toString(),
|
||||||
row,
|
|
||||||
col,
|
|
||||||
isWindow: col === 'A' || col === 'D',
|
isWindow: col === 'A' || col === 'D',
|
||||||
isAisle: col === 'B' || col === 'C',
|
isAisle: col === 'B' || col === 'C',
|
||||||
bedPosition,
|
bedPosition,
|
||||||
|
};
|
||||||
|
|
||||||
|
await prisma.seat.upsert({
|
||||||
|
where: { coachId_row_col: { coachId: c.id, row, col } },
|
||||||
|
update: seatData,
|
||||||
|
create: { coachId: c.id, row, col, ...seatData },
|
||||||
});
|
});
|
||||||
seatIndex++;
|
seatIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await prisma.seat.createMany({ data: seats });
|
|
||||||
totalSeats += coach.capacity;
|
totalSeats += coach.capacity;
|
||||||
}
|
}
|
||||||
console.log(` ✅ ${coaches.length} coaches with ${totalSeats} seats created`);
|
console.log(` ✅ ${coaches.length} coaches with ${totalSeats} seats created`);
|
||||||
@@ -552,25 +552,49 @@ async function seedFraudRules() {
|
|||||||
console.log(` ✅ ${rules.length} fraud detection rules created`);
|
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() {
|
async function main() {
|
||||||
console.log('🌱 Comprehensive EDR Seed Starting...\n');
|
console.log('🌱 Comprehensive EDR Seed Starting...\n');
|
||||||
|
|
||||||
await seedSystemUsers();
|
const steps: Array<[string, () => Promise<void>]> = [
|
||||||
await seedStations();
|
['system users', seedSystemUsers],
|
||||||
await seedCoachTypesAndClasses();
|
['stations', seedStations],
|
||||||
await seedRoute();
|
['coach types & classes', seedCoachTypesAndClasses],
|
||||||
await seedCoaches();
|
['route', seedRoute],
|
||||||
await seedTrips();
|
['coaches', seedCoaches],
|
||||||
await seedFareRules();
|
['trips', seedTrips],
|
||||||
await seedCurrency();
|
['fare rules', seedFareRules],
|
||||||
await seedPaymentMethods();
|
['currency', seedCurrency],
|
||||||
await seedNotificationTemplates();
|
['payment methods', seedPaymentMethods],
|
||||||
await seedMenuAndFood();
|
['notification templates', seedNotificationTemplates],
|
||||||
await seedPromotions();
|
['menu & food', seedMenuAndFood],
|
||||||
await seedFAQ();
|
['promotions', seedPromotions],
|
||||||
await seedFraudRules();
|
['FAQ', seedFAQ],
|
||||||
|
['fraud rules', seedFraudRules],
|
||||||
|
];
|
||||||
|
|
||||||
console.log('\n✅ Seed complete!\n');
|
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('🔑 System Users:');
|
||||||
console.log(' Admin: admin@edr-platform.com / admin123');
|
console.log(' Admin: admin@edr-platform.com / admin123');
|
||||||
console.log(' Passenger: kelemu@email.com / password123');
|
console.log(' Passenger: kelemu@email.com / password123');
|
||||||
@@ -581,8 +605,10 @@ async function main() {
|
|||||||
|
|
||||||
main()
|
main()
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error('❌ Seed failed:', e);
|
// Intentionally do NOT process.exit(1): the docker entrypoint runs under
|
||||||
process.exit(1);
|
// `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 () => {
|
.finally(async () => {
|
||||||
await prisma.$disconnect();
|
await prisma.$disconnect();
|
||||||
|
|||||||
@@ -37,4 +37,4 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -89,4 +89,4 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user