chore(repo): initialize planarchy workspace

This commit is contained in:
2026-03-14 14:31:09 +01:00
commit dd55d0e78b
769 changed files with 166461 additions and 0 deletions
+146
View File
@@ -0,0 +1,146 @@
/**
* 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";
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 MonFri 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" }, // MonFri 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" }, // MonFri
},
2026: {
spring: { start: "2026-03-30", end: "2026-04-03" }, // MonFri 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" }, // MonFri
},
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() {
// 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());