hp-prod-tracker/prisma/seed.ts
2026-04-06 14:35:56 -05:00

580 lines
25 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",
estimatedDays: 1,
},
{
name: "File Delivery",
slug: "file-delivery",
order: 2,
isCriticalGate: false,
isOptional: false,
description: "Receive source files (CAD, textures, reference materials)",
estimatedDays: 1,
},
{
name: "Model Prep",
slug: "model-prep",
order: 3,
isCriticalGate: true,
isOptional: false,
description: "Prepare 3D models for rendering pipeline",
estimatedDays: 5,
},
{
name: "Early Images",
slug: "early-images",
order: 4,
isCriticalGate: false,
isOptional: true,
description: "Optional early preview renders for client feedback",
estimatedDays: 1,
},
{
name: "Catalog Images",
slug: "catalog-images",
order: 5,
isCriticalGate: true,
isOptional: false,
description: "Standard catalog product imagery",
estimatedDays: 1,
},
{
name: "Hero Images",
slug: "hero-images",
order: 6,
isCriticalGate: false,
isOptional: false,
description: "High-impact hero product shots",
estimatedDays: 2,
},
{
name: "Packaging Images",
slug: "packaging-images",
order: 7,
isCriticalGate: false,
isOptional: false,
description: "Product packaging renders",
estimatedDays: 2,
},
{
name: "Photocomps",
slug: "photocomps",
order: 8,
isCriticalGate: false,
isOptional: false,
description: "Photo composite renders with lifestyle backgrounds",
estimatedDays: 3,
},
{
name: "360 Spin Animations",
slug: "360-spin-animations",
order: 9,
isCriticalGate: false,
isOptional: false,
description: "Interactive 360-degree product spin animations",
estimatedDays: 3.5,
},
{
name: "Dynamic Spin",
slug: "dynamic-spin",
order: 10,
isCriticalGate: false,
isOptional: false,
description: "Dynamic animated product spins with effects",
estimatedDays: 7,
},
];
// 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",
domain: "dev.localhost",
},
});
await prisma.user.upsert({
where: { id: "dev-user-001" },
update: { department: "CG Production", role: "ADMIN" },
create: {
id: "dev-user-001",
name: "Dev User",
email: "dev@localhost",
role: "ADMIN",
department: "CG Production",
organizationId: devOrg.id,
},
});
// ─── Phase 6: Seed Team Members ───────────────────────
console.log("Seeding team members...");
const TEAM_MEMBERS: {
id: string;
name: string;
email: string;
role: "ADMIN" | "PRODUCER" | "ARTIST";
department: string;
maxCapacity: number;
}[] = [
// Producers
{ id: "user-producer-001", name: "Bohdana Phillips", email: "bohdana.phillips@oliver.agency", role: "PRODUCER", department: "CG Production", maxCapacity: 8 },
{ id: "user-producer-002", name: "Gaurav Singh", email: "gaurav.singh@oliver.agency", role: "PRODUCER", department: "CG Production", maxCapacity: 8 },
{ id: "user-producer-003", name: "Ishan Jinsi", email: "ishan.jinsi@oliver.agency", role: "PRODUCER", department: "CG Production", maxCapacity: 8 },
{ id: "user-producer-004", name: "Manan Aggarwal", email: "manan.aggarwal@oliver.agency", role: "PRODUCER", department: "CG Production", maxCapacity: 8 },
{ id: "user-producer-005", name: "Mohd Iqbal", email: "mohd.iqbal@oliver.agency", role: "PRODUCER", department: "CG Production", maxCapacity: 8 },
{ id: "user-producer-006", name: "Neha Sayana", email: "neha.sayana@oliver.agency", role: "PRODUCER", department: "CG Production", maxCapacity: 8 },
{ id: "user-producer-007", name: "Vivek Singh", email: "vivek.singh@oliver.agency", role: "PRODUCER", department: "CG Production", maxCapacity: 8 },
// CGI Stills Artists
{ id: "user-artist-001", name: "Aditya Varma", email: "aditya.varma@oliver.agency", role: "ARTIST", department: "CGI Stills", maxCapacity: 6 },
{ id: "user-artist-002", name: "Ameya Bhagwat", email: "ameya.bhagwat@oliver.agency", role: "ARTIST", department: "CGI Stills", maxCapacity: 6 },
{ id: "user-artist-004", name: "Amit Sharma", email: "amit.sharma@oliver.agency", role: "ARTIST", department: "CGI Stills", maxCapacity: 5 },
{ id: "user-artist-006", name: "Ankit Kumar", email: "ankit.kumar@oliver.agency", role: "ARTIST", department: "CGI Stills", maxCapacity: 6 },
{ id: "user-artist-010", name: "Bharat Bhushan", email: "bharat.bhushan@oliver.agency", role: "ARTIST", department: "CGI Stills", maxCapacity: 6 },
{ id: "user-artist-011", name: "Eric Rodriguez", email: "eric.rodriguez@oliver.agency", role: "ARTIST", department: "CGI Stills", maxCapacity: 8 },
{ id: "user-artist-013", name: "Ishan Aneja", email: "ishan.aneja@oliver.agency", role: "ARTIST", department: "CGI Stills", maxCapacity: 5 },
{ id: "user-artist-014", name: "Jinesh Thacker", email: "jinesh.thacker@oliver.agency", role: "ARTIST", department: "CGI Stills", maxCapacity: 6 },
{ id: "user-artist-015", name: "Juan Garcia", email: "juan.garcia@oliver.agency", role: "ARTIST", department: "CGI Stills", maxCapacity: 6 },
{ id: "user-artist-016", name: "Krishna Nand", email: "krishna.nand@oliver.agency", role: "ARTIST", department: "CGI Stills", maxCapacity: 4 },
{ id: "user-artist-019", name: "Nizam P", email: "nizam.p@oliver.agency", role: "ARTIST", department: "CGI Stills", maxCapacity: 5 },
{ id: "user-artist-021", name: "Prateek Kaushik", email: "prateek.kaushik@oliver.agency", role: "ARTIST", department: "CGI Stills", maxCapacity: 8 },
{ id: "user-artist-025", name: "Xavier Plasso", email: "xavier.plasso@oliver.agency", role: "ARTIST", department: "CGI Stills", maxCapacity: 6 },
{ id: "user-artist-026", name: "Yash Vaidya", email: "yash.vaidya@oliver.agency", role: "ARTIST", department: "CGI Stills", maxCapacity: 4 },
// CGI Animation Artists
{ id: "user-artist-003", name: "Ameya Kandivkar", email: "ameya.kandivkar@oliver.agency", role: "ARTIST", department: "CGI Animation", maxCapacity: 5 },
{ id: "user-artist-007", name: "Ankit Kumar Gupta", email: "ankit.gupta@oliver.agency", role: "ARTIST", department: "CGI Animation", maxCapacity: 5 },
{ id: "user-artist-009", name: "Babon Ghosh", email: "babon.ghosh@oliver.agency", role: "ARTIST", department: "CGI Animation", maxCapacity: 5 },
{ id: "user-artist-012", name: "Hujef Bagwan", email: "hujef.bagwan@oliver.agency", role: "ARTIST", department: "CGI Animation", maxCapacity: 5 },
{ id: "user-artist-018", name: "Niteen Veer", email: "niteen.veer@oliver.agency", role: "ARTIST", department: "CGI Animation", maxCapacity: 5 },
{ id: "user-artist-020", name: "Pankaj Duragkar", email: "pankaj.duragkar@oliver.agency", role: "ARTIST", department: "CGI Animation", maxCapacity: 5 },
{ id: "user-artist-022", name: "Sandeep Sidhu", email: "sandeep.sidhu@oliver.agency", role: "ARTIST", department: "CGI Animation", maxCapacity: 8 },
{ id: "user-artist-024", name: "Sonu Kumar", email: "sonu.kumar@oliver.agency", role: "ARTIST", department: "CGI Animation", maxCapacity: 5 },
// Model Prep Artists
{ id: "user-artist-005", name: "Anantha Krishnan", email: "anantha.krishnan@oliver.agency", role: "ARTIST", department: "Model Prep", maxCapacity: 8 },
{ id: "user-artist-008", name: "Arun Prakash", email: "arun.prakash@oliver.agency", role: "ARTIST", department: "Model Prep", maxCapacity: 5 },
{ id: "user-artist-017", name: "Nijil Rajithan", email: "nijil.rajithan@oliver.agency", role: "ARTIST", department: "Model Prep", maxCapacity: 5 },
{ id: "user-artist-023", name: "Soham Baviskar", email: "soham.baviskar@oliver.agency", role: "ARTIST", department: "Model Prep", maxCapacity: 4 },
];
for (const member of TEAM_MEMBERS) {
await prisma.user.upsert({
where: { id: member.id },
update: { name: member.name, department: member.department, maxCapacity: member.maxCapacity, role: member.role },
create: {
id: member.id,
name: member.name,
email: member.email,
role: member.role,
department: member.department,
maxCapacity: member.maxCapacity,
organizationId: devOrg.id,
},
});
}
console.log(`Created/updated ${TEAM_MEMBERS.length} team members`);
console.log("Created dev organization and users");
// ─── Phase 6: Seed Skills ─────────────────────────────
console.log("Seeding skills...");
const SKILLS = [
"Model Prep",
"Lighting",
"Photocomp",
"Animation",
];
const skillMap = new Map<string, string>();
for (const name of SKILLS) {
const skill = await prisma.skill.upsert({
where: { name },
update: {},
create: { name },
});
skillMap.set(skill.name, skill.id);
}
console.log(`Created/updated ${SKILLS.length} skills`);
// Map stage templates to recommended skills
// Format: [stageSlug, [skillName, importance (1-3)]]
const STAGE_SKILL_MAP: [string, [string, number][]][] = [
["brief-intake", []],
["file-delivery", []],
["model-prep", [["Model Prep", 3]]],
["early-images", [["Lighting", 2]]],
["catalog-images", [["Lighting", 3]]],
["hero-images", [["Lighting", 3]]],
["packaging-images", [["Lighting", 2]]],
["photocomps", [["Photocomp", 3], ["Lighting", 1]]],
["360-spin-animations", [["Animation", 3], ["Lighting", 2]]],
["dynamic-spin", [["Animation", 3], ["Lighting", 2]]],
];
// Clear existing stage skill requirements
await prisma.stageSkillRequirement.deleteMany();
for (const [slug, skillReqs] of STAGE_SKILL_MAP) {
const templateId = stageMap.get(slug);
if (!templateId || skillReqs.length === 0) continue;
for (const [skillName, importance] of skillReqs) {
const skillId = skillMap.get(skillName);
if (!skillId) continue;
await prisma.stageSkillRequirement.create({
data: { stageTemplateId: templateId, skillId, importance },
});
}
}
const totalReqs = STAGE_SKILL_MAP.reduce((sum, [, reqs]) => sum + reqs.length, 0);
console.log(`Created ${totalReqs} stage skill requirements`);
// ─── Phase 6: Assign Skills to Team Members ───────────
console.log("Assigning skills to team members...");
// Clear existing user skills
await prisma.userSkill.deleteMany();
// [userId, [skillName, level]]
const USER_SKILLS: [string, [string, "JUNIOR" | "INTERMEDIATE" | "SENIOR" | "LEAD"][]][] = [
// ── CGI Stills ────────────────────────────────────────
// Aditya Varma — Senior, Photocomps specialty
["user-artist-001", [["Lighting", "SENIOR"], ["Photocomp", "SENIOR"]]],
// Ameya Bhagwat — Senior
["user-artist-002", [["Lighting", "SENIOR"]]],
// Amit Sharma — Intermediate
["user-artist-004", [["Lighting", "INTERMEDIATE"]]],
// Ankit Kumar — Senior
["user-artist-006", [["Lighting", "SENIOR"]]],
// Bharat Bhushan — Senior
["user-artist-010", [["Lighting", "SENIOR"]]],
// Eric Rodriguez — Stills Team Lead
["user-artist-011", [["Lighting", "LEAD"]]],
// Ishan Aneja — Intermediate
["user-artist-013", [["Lighting", "INTERMEDIATE"]]],
// Jinesh Thacker — Senior
["user-artist-014", [["Lighting", "SENIOR"]]],
// Juan Garcia — Senior
["user-artist-015", [["Lighting", "SENIOR"]]],
// Krishna Nand — Entry/Junior
["user-artist-016", [["Lighting", "JUNIOR"]]],
// Nizam P — Intermediate
["user-artist-019", [["Lighting", "INTERMEDIATE"]]],
// Prateek Kaushik — Stills Team Lead
["user-artist-021", [["Lighting", "LEAD"]]],
// Xavier Plasso — Senior
["user-artist-025", [["Lighting", "SENIOR"]]],
// Yash Vaidya — Entry/Junior
["user-artist-026", [["Lighting", "JUNIOR"]]],
// ── CGI Animation ─────────────────────────────────────
// Ameya Kandivkar — Intermediate
["user-artist-003", [["Animation", "INTERMEDIATE"]]],
// Ankit Kumar Gupta — Intermediate
["user-artist-007", [["Animation", "INTERMEDIATE"]]],
// Babon Ghosh — Intermediate
["user-artist-009", [["Animation", "INTERMEDIATE"]]],
// Hujef Bagwan — Intermediate
["user-artist-012", [["Animation", "INTERMEDIATE"]]],
// Niteen Veer — Intermediate
["user-artist-018", [["Animation", "INTERMEDIATE"]]],
// Pankaj Duragkar — Intermediate
["user-artist-020", [["Animation", "INTERMEDIATE"]]],
// Sandeep Sidhu — Animation Team Lead
["user-artist-022", [["Animation", "LEAD"]]],
// Sonu Kumar — Intermediate
["user-artist-024", [["Animation", "INTERMEDIATE"]]],
// ── Model Prep ────────────────────────────────────────
// Anantha Krishnan — Model Prep Team Lead
["user-artist-005", [["Model Prep", "LEAD"]]],
// Arun Prakash — Intermediate
["user-artist-008", [["Model Prep", "INTERMEDIATE"]]],
// Nijil Rajithan — Intermediate
["user-artist-017", [["Model Prep", "INTERMEDIATE"]]],
// Soham Baviskar — Entry/Junior
["user-artist-023", [["Model Prep", "JUNIOR"]]],
];
let userSkillCount = 0;
for (const [userId, skills] of USER_SKILLS) {
for (const [skillName, level] of skills) {
const skillId = skillMap.get(skillName);
if (!skillId) continue;
await prisma.userSkill.create({
data: { userId, skillId, level },
});
userSkillCount++;
}
}
console.log(`Created ${userSkillCount} user skill assignments`);
// ─── Phase 6: Seed Sample Assignments ─────────────────
console.log("Seeding sample stage assignments...");
// Get active project stages to assign
const activeStages = await prisma.deliverableStage.findMany({
where: {
status: { in: ["IN_PROGRESS", "IN_REVIEW", "NOT_STARTED"] },
deliverable: { project: { organizationId: devOrg.id, status: "ACTIVE" } },
},
include: { template: true },
take: 60, // grab a decent sample
orderBy: { createdAt: "asc" },
});
// Map stages to appropriate artists by stage type
const stageToArtists: Record<string, string[]> = {
"model-prep": ["user-artist-005", "user-artist-008", "user-artist-017", "user-artist-023"],
"early-images": ["user-artist-002", "user-artist-006", "user-artist-010"],
"catalog-images": ["user-artist-011", "user-artist-021", "user-artist-014", "user-artist-015", "user-artist-002"],
"hero-images": ["user-artist-011", "user-artist-021", "user-artist-001", "user-artist-002"],
"packaging-images": ["user-artist-006", "user-artist-010", "user-artist-013", "user-artist-019"],
"photocomps": ["user-artist-001", "user-artist-015", "user-artist-014"],
"360-spin-animations": ["user-artist-022", "user-artist-003", "user-artist-009", "user-artist-024"],
"dynamic-spin": ["user-artist-022", "user-artist-020", "user-artist-018", "user-artist-007"],
};
// Clear existing assignments (to allow re-runs)
await prisma.stageAssignment.deleteMany();
let assignmentCount = 0;
const artistAssignmentCounts = new Map<string, number>();
for (const stage of activeStages) {
const candidates = stageToArtists[stage.template.slug];
if (!candidates || candidates.length === 0) continue;
// Pick the artist with the least assignments so far
let bestArtist = candidates[0];
let lowestCount = artistAssignmentCounts.get(bestArtist) || 0;
for (const candidate of candidates) {
const count = artistAssignmentCounts.get(candidate) || 0;
if (count < lowestCount) {
bestArtist = candidate;
lowestCount = count;
}
}
// Don't exceed maxCapacity (roughly)
const member = TEAM_MEMBERS.find((m) => m.id === bestArtist);
if (member && lowestCount >= member.maxCapacity) continue;
try {
await prisma.stageAssignment.create({
data: {
deliverableStageId: stage.id,
userId: bestArtist,
role: "LEAD",
},
});
artistAssignmentCounts.set(bestArtist, lowestCount + 1);
assignmentCount++;
} catch {
// Skip duplicate assignments
}
}
console.log(`Created ${assignmentCount} stage assignments`);
// ─── Phase 2: Seed RBAC Default Permissions ──────────
console.log("Seeding RBAC default permissions...");
const DEFAULT_PERMISSIONS: Record<string, string[]> = {
ADMIN: [
"PROJECT_CREATE", "PROJECT_UPDATE", "PROJECT_DELETE", "PROJECT_VIEW",
"DELIVERABLE_CREATE", "DELIVERABLE_UPDATE", "DELIVERABLE_DELETE",
"STAGE_UPDATE_STATUS", "STAGE_ASSIGN", "STAGE_SCHEDULE",
"REVISION_CREATE", "REVISION_REVIEW",
"COMMENT_CREATE", "COMMENT_DELETE_ANY",
"PIPELINE_MANAGE", "USER_MANAGE", "ROLE_MANAGE", "ORG_SETTINGS",
"AUTOMATION_MANAGE", "FIELD_CUSTOMIZE",
],
PRODUCER: [
"PROJECT_CREATE", "PROJECT_UPDATE", "PROJECT_VIEW",
"DELIVERABLE_CREATE", "DELIVERABLE_UPDATE", "DELIVERABLE_DELETE",
"STAGE_UPDATE_STATUS", "STAGE_ASSIGN", "STAGE_SCHEDULE",
"REVISION_CREATE", "REVISION_REVIEW",
"COMMENT_CREATE", "COMMENT_DELETE_ANY",
"AUTOMATION_MANAGE",
],
ARTIST: [
"PROJECT_VIEW",
"STAGE_UPDATE_STATUS",
"REVISION_CREATE",
"COMMENT_CREATE",
],
};
// Clear existing and re-seed
await prisma.orgRolePermission.deleteMany({
where: { organizationId: devOrg.id },
});
const permData: { organizationId: string; role: any; permission: any }[] = [];
for (const [role, permissions] of Object.entries(DEFAULT_PERMISSIONS)) {
for (const permission of permissions) {
permData.push({ organizationId: devOrg.id, role, permission });
}
}
await prisma.orgRolePermission.createMany({ data: permData });
console.log(`Created ${permData.length} role permission entries for dev org`);
// ─── Phase 8: Seed HP CG Standard Dynamic Pipeline Template ──
console.log("Seeding HP CG Standard dynamic pipeline template...");
const HP_CG_TEMPLATE_ID = "pipeline-hp-cg-standard";
const hpCgTemplate = await prisma.pipelineTemplate.upsert({
where: { id: HP_CG_TEMPLATE_ID },
update: {
name: "HP CG Standard",
description: "Standard HP CG production pipeline with 10 stages",
isDefault: true,
isArchived: false,
},
create: {
id: HP_CG_TEMPLATE_ID,
name: "HP CG Standard",
description: "Standard HP CG production pipeline with 10 stages",
organizationId: devOrg.id,
isDefault: true,
isArchived: false,
},
});
const HP_CG_STAGES = [
{ id: "stage-def-brief-intake", name: "Brief Intake", slug: "brief-intake", order: 1, isCriticalGate: true, isOptional: false, description: "Receive and review the project brief from HP", estimatedDays: 1 },
{ id: "stage-def-file-delivery", name: "File Delivery", slug: "file-delivery", order: 2, isCriticalGate: false, isOptional: true, description: "Receive source files (CAD, textures, reference materials)", estimatedDays: 1 },
{ id: "stage-def-model-prep", name: "Model Prep", slug: "model-prep", order: 3, isCriticalGate: true, isOptional: false, description: "Prepare 3D models for rendering pipeline", estimatedDays: 5 },
{ id: "stage-def-early-images", name: "Early Images", slug: "early-images", order: 4, isCriticalGate: false, isOptional: true, description: "Optional early preview renders for client feedback", estimatedDays: 1 },
{ id: "stage-def-catalog-images", name: "Catalog Images", slug: "catalog-images", order: 5, isCriticalGate: true, isOptional: false, description: "Standard catalog product imagery", estimatedDays: 1 },
{ id: "stage-def-hero-images", name: "Hero Images", slug: "hero-images", order: 6, isCriticalGate: false, isOptional: false, description: "High-impact hero product shots", estimatedDays: 2 },
{ id: "stage-def-packaging-images", name: "Packaging Images", slug: "packaging-images", order: 7, isCriticalGate: false, isOptional: false, description: "Product packaging renders", estimatedDays: 2 },
{ id: "stage-def-photocomps", name: "Photocomps", slug: "photocomps", order: 8, isCriticalGate: false, isOptional: false, description: "Photo composite renders with lifestyle backgrounds", estimatedDays: 3 },
{ id: "stage-def-360-spin", name: "360 Spin Animations", slug: "360-spin-animations", order: 9, isCriticalGate: false, isOptional: false, description: "Interactive 360-degree product spin animations", estimatedDays: 3.5 },
{ id: "stage-def-dynamic-spin", name: "Dynamic Spin", slug: "dynamic-spin", order: 10, isCriticalGate: false, isOptional: false, description: "Dynamic animated product spins with effects", estimatedDays: 7 },
{ id: "stage-def-misc", name: "Misc", slug: "misc", order: 11, isCriticalGate: false, isOptional: true, description: "Screenswaps, logo updates, file renaming, etc", estimatedDays: 2 },
];
const hpCgStageMap = new Map<string, string>();
for (const stage of HP_CG_STAGES) {
const created = await prisma.pipelineStageDefinition.upsert({
where: { pipelineId_slug: { pipelineId: hpCgTemplate.id, slug: stage.slug } },
update: { name: stage.name, order: stage.order, isCriticalGate: stage.isCriticalGate, isOptional: stage.isOptional, description: stage.description, estimatedDays: stage.estimatedDays },
create: { id: stage.id, pipelineId: hpCgTemplate.id, name: stage.name, slug: stage.slug, order: stage.order, isCriticalGate: stage.isCriticalGate, isOptional: stage.isOptional, description: stage.description, estimatedDays: stage.estimatedDays },
});
hpCgStageMap.set(stage.slug, created.id);
}
console.log(`Created/updated ${HP_CG_STAGES.length} HP CG Standard pipeline stages`);
// Clear and recreate HP CG Standard dependencies
await prisma.pipelineStageDependencyV2.deleteMany({
where: { stage: { pipelineId: hpCgTemplate.id } },
});
const HP_CG_DEPS: [string, string][] = [
["file-delivery", "brief-intake"],
["model-prep", "brief-intake"],
["model-prep", "file-delivery"],
["early-images", "model-prep"],
["catalog-images", "model-prep"],
["hero-images", "catalog-images"],
["packaging-images", "catalog-images"],
["photocomps", "catalog-images"],
["360-spin-animations", "catalog-images"],
["dynamic-spin", "catalog-images"],
["misc", "catalog-images"],
];
for (const [stageSlug, prereqSlug] of HP_CG_DEPS) {
const stageId = hpCgStageMap.get(stageSlug)!;
const prerequisiteId = hpCgStageMap.get(prereqSlug)!;
await prisma.pipelineStageDependencyV2.create({
data: { stageId, prerequisiteId },
});
}
console.log(`Created ${HP_CG_DEPS.length} HP CG Standard stage dependencies`);
console.log("Seed complete!");
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});