/** * seed-vacations.ts * Populates 15 vacation days per resource per year (2025, 2026, 2027-partial). * Spread across 3 blocks: * – Spring/Easter (5 days, fixed) * – Summer (5 days, staggered by resource index so teams don't all leave at once) * – Christmas/NYE (5 days, fixed) */ import { PrismaClient } from "@prisma/client"; import { loadWorkspaceEnv } from "./load-workspace-env.js"; import { assertSafeSeedTarget } from "./safe-destructive-env.js"; loadWorkspaceEnv(); const prisma = new PrismaClient(); // ─── Helpers ────────────────────────────────────────────────────────────────── /** ISO date string → Date at midnight UTC */ function d(iso: string): Date { return new Date(iso + "T00:00:00.000Z"); } /** Add calendar days to a Date */ function addDays(date: Date, n: number): Date { const r = new Date(date); r.setUTCDate(r.getUTCDate() + n); return r; } // ─── Vacation blocks per year ───────────────────────────────────────────────── // Each block is { start, end } of a Mon–Fri week (5 working days). // Summer has multiple offsets so resources are staggered (offset chosen by index % 4). const BLOCKS: Record< number, { spring: { start: string; end: string }; summer: { start: string; end: string }[]; christmas: { start: string; end: string }; } > = { 2025: { spring: { start: "2025-04-14", end: "2025-04-18" }, // Mon–Fri Easter week summer: [ { start: "2025-07-07", end: "2025-07-11" }, { start: "2025-07-21", end: "2025-07-25" }, { start: "2025-08-04", end: "2025-08-08" }, { start: "2025-08-18", end: "2025-08-22" }, ], christmas: { start: "2025-12-22", end: "2025-12-26" }, // Mon–Fri }, 2026: { spring: { start: "2026-03-30", end: "2026-04-03" }, // Mon–Fri Easter week summer: [ { start: "2026-07-06", end: "2026-07-10" }, { start: "2026-07-20", end: "2026-07-24" }, { start: "2026-08-03", end: "2026-08-07" }, { start: "2026-08-17", end: "2026-08-21" }, ], christmas: { start: "2026-12-21", end: "2026-12-25" }, // Mon–Fri }, 2027: { // Partial year — spring only (for future view context) spring: { start: "2027-03-29", end: "2027-04-02" }, summer: [ { start: "2027-07-05", end: "2027-07-09" }, { start: "2027-07-19", end: "2027-07-23" }, { start: "2027-08-02", end: "2027-08-06" }, { start: "2027-08-16", end: "2027-08-20" }, ], christmas: { start: "2027-12-20", end: "2027-12-24" }, }, }; const YEARS = [2025, 2026, 2027]; // ─── Main ───────────────────────────────────────────────────────────────────── async function main() { assertSafeSeedTarget("db:seed:vacations"); // Get admin user to act as approver (fall back to manager, then any user) const admin = (await prisma.user.findFirst({ where: { systemRole: "ADMIN" }, select: { id: true } })) ?? (await prisma.user.findFirst({ where: { systemRole: "MANAGER" }, select: { id: true } })) ?? (await prisma.user.findFirst({ select: { id: true } })); if (!admin) { throw new Error("No users found — run the main seed first."); } // Get all resources ordered by eid for stable staggering const resources = await prisma.resource.findMany({ where: { isActive: true }, select: { id: true, eid: true }, orderBy: { eid: "asc" }, }); console.log(`Found ${resources.length} active resources. Admin id: ${admin.id}`); // Delete existing vacations to allow re-running const deleted = await prisma.vacation.deleteMany({}); console.log(`Deleted ${deleted.count} existing vacation records.`); let created = 0; for (let i = 0; i < resources.length; i++) { const resource = resources[i]!; const summerOffset = i % 4; // 0-3 → pick one of the 4 staggered summer weeks for (const year of YEARS) { const blocks = BLOCKS[year]!; const summerBlock = blocks.summer[summerOffset]!; const vacationBlocks = [ { type: "ANNUAL" as const, ...blocks.spring }, { type: "ANNUAL" as const, ...summerBlock }, { type: "ANNUAL" as const, ...blocks.christmas }, ]; for (const block of vacationBlocks) { await prisma.vacation.create({ data: { resourceId: resource.id, type: block.type, status: "APPROVED", startDate: d(block.start), endDate: d(block.end), requestedById: admin.id, approvedById: admin.id, approvedAt: new Date(), note: `${year} annual leave`, }, }); created++; } } console.log(` ✓ ${resource.eid} — ${YEARS.length * 3} vacation blocks`); } console.log(`\nDone! Created ${created} vacation records.`); console.log(` ${resources.length} resources × ${YEARS.length} years × 3 blocks = ${resources.length * YEARS.length * 3} expected`); } main() .catch((e) => { console.error(e); process.exit(1); }) .finally(() => void prisma.$disconnect());