fix(db): seed staff_id FK fix (GRO-369) #199

Merged
groombook-engineer[bot] merged 5 commits from fix/gro-369-staff-id-fk into main 2026-04-01 14:19:49 +00:00
2 changed files with 8 additions and 11 deletions
Showing only changes of commit eacf8abc3b - Show all commits
+1 -1
View File
@@ -141,7 +141,7 @@ export const pets = pgTable("pets", {
export const services = pgTable("services", { export const services = pgTable("services", {
id: uuid("id").primaryKey().defaultRandom(), id: uuid("id").primaryKey().defaultRandom(),
name: text("name").notNull(), name: text("name").notNull().unique(),
description: text("description"), description: text("description"),
basePriceCents: integer("base_price_cents").notNull(), basePriceCents: integer("base_price_cents").notNull(),
durationMinutes: integer("duration_minutes").notNull(), durationMinutes: integer("duration_minutes").notNull(),
+7 -10
View File
@@ -423,17 +423,14 @@ async function seed() {
} }
console.log(`✓ Created ${allStaff.length} staff (1 manager, 1 receptionist, 3 groomers, 3 bathers)`); console.log(`✓ Created ${allStaff.length} staff (1 manager, 1 receptionist, 3 groomers, 3 bathers)`);
// Truncate downstream tables before services dedup to avoid FK violation // Truncate downstream tables before services upsert — clears stale appointments
// from prior seed runs so the FK constraint on service_id is never violated
await db.execute(sql`TRUNCATE appointments, invoices, invoice_line_items, invoice_tip_splits, grooming_visit_logs CASCADE`); await db.execute(sql`TRUNCATE appointments, invoices, invoice_line_items, invoice_tip_splits, grooming_visit_logs CASCADE`);
// ── Services ── // ── Services ──
// Deduplicate existing services (keep lowest id per name) before inserting. // Upsert services using name as unique key. With deterministic IDs in
await db.execute(sql` // servicesDef and TRUNCATE clearing downstream tables first, this is
DELETE FROM services WHERE id NOT IN ( // idempotent: first run inserts, subsequent runs update existing rows.
SELECT (MIN(id::text))::uuid FROM services GROUP BY name
)
`);
const serviceIds: string[] = []; const serviceIds: string[] = [];
for (const s of servicesDef) { for (const s of servicesDef) {
serviceIds.push(s.id); serviceIds.push(s.id);
@@ -447,8 +444,8 @@ async function seed() {
active: true, active: true,
}) })
.onConflictDoUpdate({ .onConflictDoUpdate({
target: schema.services.id, target: schema.services.name,
set: { name: s.name, description: s.desc, basePriceCents: s.price, durationMinutes: s.dur, active: true }, set: { description: s.desc, basePriceCents: s.price, durationMinutes: s.dur, active: true },
}); });
} }
console.log(`✓ Created ${servicesDef.length} services`); console.log(`✓ Created ${servicesDef.length} services`);