import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); // ====== Config ====== const PREVIOUS_WEEKS = 5; // nombre de semaines à générer avant la semaine actuelle const INCLUDE_CURRENT = false; // passe à true si tu veux aussi générer la semaine actuelle // Stocker une heure (Postgres TIME) via Date (UTC 1970-01-01) function timeAt(hour: number, minute: number) { return new Date(Date.UTC(1970, 0, 1, hour, minute, 0)); } // Lundi de la semaine (en UTC) pour la date courante function mondayOfThisWeekUTC(now = new Date()) { const d = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate())); const day = d.getUTCDay(); // 0=Dim, 1=Lun, ... const diffToMonday = (day + 6) % 7; // 0 si lundi d.setUTCDate(d.getUTCDate() - diffToMonday); d.setUTCHours(0, 0, 0, 0); return d; } // Retourne les 5 dates Lundi→Vendredi (UTC, à minuit) à partir d’un lundi donné function weekDatesFromMonday(monday: Date) { return Array.from({ length: 5 }, (_, i) => { const d = new Date(monday); d.setUTCDate(monday.getUTCDate() + i); return d; }); } // Lundi n semaines avant un lundi donné function mondayNWeeksBefore(monday: Date, n: number) { const d = new Date(monday); d.setUTCDate(d.getUTCDate() - n * 7); return d; } // Random int inclusif function rndInt(min: number, max: number) { return Math.floor(Math.random() * (max - min + 1)) + min; } async function main() { // Bank codes utilisés const BANKS = ['G1', 'G305', 'G105'] as const; const bcRows = await prisma.bankCodes.findMany({ where: { bank_code: { in: BANKS as unknown as string[] } }, select: { id: true, bank_code: true }, }); const bcMap = new Map(bcRows.map(b => [b.bank_code, b.id])); for (const c of BANKS) { if (!bcMap.has(c)) throw new Error(`Bank code manquant: ${c}`); } // Employés + cache des timesheets par employé (évite un findMany dans les boucles) const employees = await prisma.employees.findMany({ select: { id: true } }); if (!employees.length) { console.log('Aucun employé — rien à insérer.'); return; } const tsByEmp = new Map(); { const allTs = await prisma.timesheets.findMany({ where: { employee_id: { in: employees.map(e => e.id) } }, select: { id: true, employee_id: true }, orderBy: { id: 'asc' }, }); for (const e of employees) { tsByEmp.set(e.id, allTs.filter(t => t.employee_id === e.id).map(t => ({ id: t.id }))); } } // Construit la liste des semaines à insérer const mondayThisWeek = mondayOfThisWeekUTC(); const mondays: Date[] = []; if (INCLUDE_CURRENT) mondays.push(mondayThisWeek); for (let n = 1; n <= PREVIOUS_WEEKS; n++) { mondays.push(mondayNWeeksBefore(mondayThisWeek, n)); } let created = 0; // Pour chaque semaine à générer for (let wi = 0; wi < mondays.length; wi++) { const monday = mondays[wi]; const weekDays = weekDatesFromMonday(monday); for (let ei = 0; ei < employees.length; ei++) { const e = employees[ei]; const tss = tsByEmp.get(e.id) ?? []; if (!tss.length) continue; // Base horaire spécifique à l’employé (garantit la diversité) // Heures: 6..10 (selon l'index employé) const baseStartHour = 6 + (ei % 5); // 6,7,8,9,10 // Minutes: 0, 15, 30, 45 (selon l'index employé) const baseStartMinute = (ei * 15) % 60; // 0,15,30,45 (répète) // 1 employé sur 5 a un jour spécial (G305/G105) par semaine const isSpecial = (ei % 5) === 0; const specialDayIdx = isSpecial ? ((ei + wi) % 5) : -1; const specialCode = isSpecial ? ((ei + wi) % 2 === 0 ? 'G305' : 'G105') : 'G1'; // 5 jours (lun→ven) for (let di = 0; di < weekDays.length; di++) { const date = weekDays[di]; // Bank code du jour const codeToday = (di === specialDayIdx) ? specialCode : 'G1'; const bank_code_id = bcMap.get(codeToday)!; // Durée aléatoire entre 4 et 10 heures const duration = rndInt(4, 10); // Variation jour+semaine pour casser les patterns (décalage 0..2h) const dayWeekOffset = (di + wi + (ei % 3)) % 3; // 0,1,2 const startH = Math.min(12, baseStartHour + dayWeekOffset); // borne supérieure prudente const startM = baseStartMinute; const endH = startH + duration; // <= 22 en pratique const endM = startM; const ts = tss[(di + wi) % tss.length]; await prisma.shifts.create({ data: { timesheet_id: ts.id, bank_code_id, description: `Shift ${di + 1} (semaine du ${monday.toISOString().slice(0,10)}) emp ${e.id} — ${codeToday}`, date, // Date du jour (UTC minuit) start_time: timeAt(startH, startM), end_time: timeAt(endH, endM), is_approved: Math.random() < 0.5, }, }); created++; } } } const total = await prisma.shifts.count(); console.log(`✓ Shifts: ${created} nouvelles lignes, ${total} total rows (${INCLUDE_CURRENT ? 'courante +' : ''}${PREVIOUS_WEEKS} semaines précédentes, L→V)`); } main().finally(() => prisma.$disconnect());