dow-prod-tracker/prisma/seed.ts

173 lines
4.4 KiB
TypeScript

import "dotenv/config";
import { PrismaPg } from "@prisma/adapter-pg";
import { PrismaClient } from "../src/generated/prisma/client";
const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL! });
const prisma = new PrismaClient({ adapter });
const STAGES = [
{
name: "Brief Intake",
slug: "brief-intake",
order: 1,
isCriticalGate: false,
isOptional: false,
description: "Receive and review the project brief from HP",
},
{
name: "File Delivery",
slug: "file-delivery",
order: 2,
isCriticalGate: false,
isOptional: false,
description: "Receive source files (CAD, textures, reference materials)",
},
{
name: "Model Prep",
slug: "model-prep",
order: 3,
isCriticalGate: true,
isOptional: false,
description: "Prepare 3D models for rendering pipeline",
},
{
name: "Early Images",
slug: "early-images",
order: 4,
isCriticalGate: false,
isOptional: true,
description: "Optional early preview renders for client feedback",
},
{
name: "Catalog Images",
slug: "catalog-images",
order: 5,
isCriticalGate: true,
isOptional: false,
description: "Standard catalog product imagery",
},
{
name: "Hero Images",
slug: "hero-images",
order: 6,
isCriticalGate: false,
isOptional: false,
description: "High-impact hero product shots",
},
{
name: "Packaging Images",
slug: "packaging-images",
order: 7,
isCriticalGate: false,
isOptional: false,
description: "Product packaging renders",
},
{
name: "Photocomps",
slug: "photocomps",
order: 8,
isCriticalGate: false,
isOptional: false,
description: "Photo composite renders with lifestyle backgrounds",
},
{
name: "360 Spin Animations",
slug: "360-spin-animations",
order: 9,
isCriticalGate: false,
isOptional: false,
description: "Interactive 360-degree product spin animations",
},
{
name: "Dynamic Spin",
slug: "dynamic-spin",
order: 10,
isCriticalGate: false,
isOptional: false,
description: "Dynamic animated product spins with effects",
},
];
// Dependencies: [stageSlug, prerequisiteSlug]
const DEPENDENCIES: [string, string][] = [
// File Delivery depends on Brief Intake
["file-delivery", "brief-intake"],
// Model Prep depends on Brief Intake and File Delivery
["model-prep", "brief-intake"],
["model-prep", "file-delivery"],
// Early Images depends on Model Prep (optional stage)
["early-images", "model-prep"],
// Catalog Images depends on Model Prep (critical gate)
["catalog-images", "model-prep"],
// Stages 6-10 all depend on Catalog Images (critical gate)
["hero-images", "catalog-images"],
["packaging-images", "catalog-images"],
["photocomps", "catalog-images"],
["360-spin-animations", "catalog-images"],
["dynamic-spin", "catalog-images"],
];
async function main() {
console.log("Seeding pipeline stage templates...");
// Upsert stages
const stageMap = new Map<string, string>();
for (const stage of STAGES) {
const created = await prisma.pipelineStageTemplate.upsert({
where: { slug: stage.slug },
update: stage,
create: stage,
});
stageMap.set(created.slug, created.id);
}
console.log(`Created/updated ${STAGES.length} pipeline stages`);
// Clear existing dependencies and recreate
await prisma.pipelineStageDependency.deleteMany();
for (const [stageSlug, prerequisiteSlug] of DEPENDENCIES) {
const stageId = stageMap.get(stageSlug)!;
const prerequisiteId = stageMap.get(prerequisiteSlug)!;
await prisma.pipelineStageDependency.create({
data: { stageId, prerequisiteId },
});
}
console.log(`Created ${DEPENDENCIES.length} stage dependencies`);
// Seed dev organization and user (for local development with DEV_BYPASS_AUTH)
const devOrg = await prisma.organization.upsert({
where: { id: "dev-org-001" },
update: {},
create: {
id: "dev-org-001",
name: "Dev Organization",
},
});
await prisma.user.upsert({
where: { id: "dev-user-001" },
update: {},
create: {
id: "dev-user-001",
name: "Dev User",
email: "dev@localhost",
role: "ADMIN",
organizationId: devOrg.id,
},
});
console.log("Created dev organization and user");
console.log("Seed complete!");
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});