Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 620b96470f | |||
| eb3f566aeb |
@@ -50,4 +50,5 @@ CMD ["pnpm", "--filter", "@groombook/db", "seed"]
|
|||||||
|
|
||||||
# Reset stage — drops all tables, re-runs migrations, and re-seeds
|
# Reset stage — drops all tables, re-runs migrations, and re-seeds
|
||||||
FROM builder AS reset
|
FROM builder AS reset
|
||||||
|
RUN corepack enable && corepack prepare pnpm@9.15.4 --activate
|
||||||
CMD ["pnpm", "--filter", "@groombook/db", "reset"]
|
CMD ["pnpm", "--filter", "@groombook/db", "reset"]
|
||||||
|
|||||||
+114
-2
@@ -20,6 +20,7 @@ import postgres from "postgres";
|
|||||||
import { drizzle } from "drizzle-orm/postgres-js";
|
import { drizzle } from "drizzle-orm/postgres-js";
|
||||||
import { eq, and, sql } from "drizzle-orm";
|
import { eq, and, sql } from "drizzle-orm";
|
||||||
import * as schema from "./schema.js";
|
import * as schema from "./schema.js";
|
||||||
|
import type { MedicalAlert } from "@groombook/types";
|
||||||
|
|
||||||
// ── Seed profile configuration ─────────────────────────────────────────────
|
// ── Seed profile configuration ─────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -243,6 +244,55 @@ const groomingNotes = [
|
|||||||
"Previous clipper burn — be gentle on belly",
|
"Previous clipper burn — be gentle on belly",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// ── Extended pet profile pools ─────────────────────────────────────────────────
|
||||||
|
|
||||||
|
const temperamentFlagPool: string[] = [
|
||||||
|
"friendly",
|
||||||
|
"anxious-with-strangers",
|
||||||
|
"good-with-kids",
|
||||||
|
"leash-reactive",
|
||||||
|
"vocal",
|
||||||
|
"high-energy",
|
||||||
|
"calm-on-table",
|
||||||
|
"treat-motivated",
|
||||||
|
];
|
||||||
|
|
||||||
|
const medicalAlertPool: MedicalAlert[] = [
|
||||||
|
{ id: "", type: "allergies", description: "Seasonal allergies — monitor skin", severity: "low" },
|
||||||
|
{ id: "", type: "allergies", description: "Chicken allergy — avoid poultry-based treats", severity: "high" },
|
||||||
|
{ id: "", type: "joint", description: "Hip dysplasia — handle with care", severity: "medium" },
|
||||||
|
{ id: "", type: "joint", description: "Arthritis — anti-inflammatory medication on file", severity: "medium" },
|
||||||
|
{ id: "", type: "dental", description: "Dental disease — extractions in history", severity: "medium" },
|
||||||
|
{ id: "", type: "dental", description: "Baby teeth retained — vet monitor", severity: "low" },
|
||||||
|
{ id: "", type: "heart", description: "Heart murmur grade II — avoid stress", severity: "high" },
|
||||||
|
{ id: "", type: "heart", description: "Murmur cleared by vet last year", severity: "low" },
|
||||||
|
{ id: "", type: "other", description: "Eye ulcer history — be careful around face", severity: "medium" },
|
||||||
|
{ id: "", type: "other", description: "Seizure history — avoid flashing lights", severity: "high" },
|
||||||
|
{ id: "", type: "other", description: "Luxating patella — short walks only", severity: "medium" },
|
||||||
|
{ id: "", type: "other", description: "Ear infections — dry thoroughly after bath", severity: "low" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const preferredCutPool: string[] = [
|
||||||
|
"Puppy Cut",
|
||||||
|
"Teddy Bear Cut",
|
||||||
|
"Lion Cut",
|
||||||
|
"Breed Standard",
|
||||||
|
"Summer Shave",
|
||||||
|
"Kennel Cut",
|
||||||
|
"Lamb Cut",
|
||||||
|
"Continental Clip",
|
||||||
|
"Sporting Clip",
|
||||||
|
"Sanitary Trim",
|
||||||
|
"Face & Feet Trim",
|
||||||
|
"Full Groom",
|
||||||
|
];
|
||||||
|
|
||||||
|
type CoatType = schema.coatTypeEnum.enumValues[number];
|
||||||
|
type PetSizeCategory = schema.petSizeCategoryEnum.enumValues[number];
|
||||||
|
|
||||||
|
const coatTypePool: CoatType[] = ["short", "medium", "long", "double", "wire", "silky", "curly", "hairless"];
|
||||||
|
const petSizeCategoryPool: PetSizeCategory[] = ["small", "medium", "large", "extra_large"];
|
||||||
|
|
||||||
const appointmentNotes = [
|
const appointmentNotes = [
|
||||||
null, null, null, null,
|
null, null, null, null,
|
||||||
"Client requested extra brushing",
|
"Client requested extra brushing",
|
||||||
@@ -853,6 +903,18 @@ async function seed() {
|
|||||||
specialCareNotes: rand() < 0.1 ? "Vet clearance required before grooming" : null,
|
specialCareNotes: rand() < 0.1 ? "Vet clearance required before grooming" : null,
|
||||||
customFields: {},
|
customFields: {},
|
||||||
image: petIndex < 250 ? pick(puggleImages) : pick(demoPetImages),
|
image: petIndex < 250 ? pick(puggleImages) : pick(demoPetImages),
|
||||||
|
temperamentScore: randInt(1, 5),
|
||||||
|
temperamentFlags: pickN(temperamentFlagPool, randInt(1, 3)),
|
||||||
|
medicalAlerts: (() => {
|
||||||
|
if (rand() < 0.3) {
|
||||||
|
const count = rand() < 0.7 ? 1 : 2;
|
||||||
|
return pickN(medicalAlertPool, count).map((a) => ({ ...a, id: uuid() }));
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
})(),
|
||||||
|
preferredCuts: pickN(preferredCutPool, randInt(1, 2)),
|
||||||
|
coatType: pick(coatTypePool),
|
||||||
|
petSizeCategory: pick(petSizeCategoryPool),
|
||||||
});
|
});
|
||||||
|
|
||||||
petRecords.push({ id: petId, clientId });
|
petRecords.push({ id: petId, clientId });
|
||||||
@@ -888,6 +950,12 @@ async function seed() {
|
|||||||
specialCareNotes: pet.specialCareNotes,
|
specialCareNotes: pet.specialCareNotes,
|
||||||
customFields: pet.customFields,
|
customFields: pet.customFields,
|
||||||
image: pet.image,
|
image: pet.image,
|
||||||
|
temperamentScore: pet.temperamentScore,
|
||||||
|
temperamentFlags: pet.temperamentFlags,
|
||||||
|
medicalAlerts: pet.medicalAlerts,
|
||||||
|
preferredCuts: pet.preferredCuts,
|
||||||
|
coatType: pet.coatType,
|
||||||
|
petSizeCategory: pet.petSizeCategory,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -922,8 +990,52 @@ async function seed() {
|
|||||||
.values({ id: uc.id, name: uc.name, email: uc.email, phone: uc.phone, address: uc.address })
|
.values({ id: uc.id, name: uc.name, email: uc.email, phone: uc.phone, address: uc.address })
|
||||||
.onConflictDoUpdate({ target: schema.clients.id, set: { name: uc.name, email: uc.email, phone: uc.phone, address: uc.address } });
|
.onConflictDoUpdate({ target: schema.clients.id, set: { name: uc.name, email: uc.email, phone: uc.phone, address: uc.address } });
|
||||||
await db.insert(schema.pets)
|
await db.insert(schema.pets)
|
||||||
.values({ id: uc.petId, clientId: uc.id, name: uc.petName, species: "Dog", breed: uc.petBreed, weightKg: "25.00", dateOfBirth: new Date("2021-03-15T00:00:00Z"), image: pick(demoPetImages) })
|
.values({
|
||||||
.onConflictDoUpdate({ target: schema.pets.id, set: { clientId: uc.id, name: uc.petName, species: "Dog", breed: uc.petBreed, weightKg: "25.00", dateOfBirth: new Date("2021-03-15T00:00:00Z"), image: pick(demoPetImages) } });
|
id: uc.petId,
|
||||||
|
clientId: uc.id,
|
||||||
|
name: uc.petName,
|
||||||
|
species: "Dog",
|
||||||
|
breed: uc.petBreed,
|
||||||
|
weightKg: "25.00",
|
||||||
|
dateOfBirth: new Date("2021-03-15T00:00:00Z"),
|
||||||
|
image: pick(demoPetImages),
|
||||||
|
temperamentScore: randInt(1, 5),
|
||||||
|
temperamentFlags: pickN(temperamentFlagPool, randInt(1, 3)),
|
||||||
|
medicalAlerts: (() => {
|
||||||
|
if (rand() < 0.3) {
|
||||||
|
const count = rand() < 0.7 ? 1 : 2;
|
||||||
|
return pickN(medicalAlertPool, count).map((a) => ({ ...a, id: uuid() }));
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
})(),
|
||||||
|
preferredCuts: pickN(preferredCutPool, randInt(1, 2)),
|
||||||
|
coatType: pick(coatTypePool),
|
||||||
|
petSizeCategory: pick(petSizeCategoryPool),
|
||||||
|
})
|
||||||
|
.onConflictDoUpdate({
|
||||||
|
target: schema.pets.id,
|
||||||
|
set: {
|
||||||
|
clientId: uc.id,
|
||||||
|
name: uc.petName,
|
||||||
|
species: "Dog",
|
||||||
|
breed: uc.petBreed,
|
||||||
|
weightKg: "25.00",
|
||||||
|
dateOfBirth: new Date("2021-03-15T00:00:00Z"),
|
||||||
|
image: pick(demoPetImages),
|
||||||
|
temperamentScore: randInt(1, 5),
|
||||||
|
temperamentFlags: pickN(temperamentFlagPool, randInt(1, 3)),
|
||||||
|
medicalAlerts: (() => {
|
||||||
|
if (rand() < 0.3) {
|
||||||
|
const count = rand() < 0.7 ? 1 : 2;
|
||||||
|
return pickN(medicalAlertPool, count).map((a) => ({ ...a, id: uuid() }));
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
})(),
|
||||||
|
preferredCuts: pickN(preferredCutPool, randInt(1, 2)),
|
||||||
|
coatType: pick(coatTypePool),
|
||||||
|
petSizeCategory: pick(petSizeCategoryPool),
|
||||||
|
},
|
||||||
|
});
|
||||||
// Create one completed appointment for this client
|
// Create one completed appointment for this client
|
||||||
const apptId = uuid();
|
const apptId = uuid();
|
||||||
const svcIdx = 0;
|
const svcIdx = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user