import { PrismaClient } from '@prisma/client'; import bcrypt from 'bcryptjs'; import { AUDIT_MAP, PERIOD_TO_TYPE, ADDITIONAL_EQUIP_TYPES, CUSTOMERS, EQUIPMENT, SERVICE_RECORDS, } from './seed-data'; const prisma = new PrismaClient(); /** * Klasifikuje poznámku revízie na kód typu revízie. * Staré dáta používali voľný text na zaznamenanie druhu revízie. */ function classifyNote(note: string, basePeriodicity: number): string { const normalized = note.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, ''); // Štvrťročná (rôzne varianty s preklepmi) - musí byť pred ročnou, lebo "stvrtrocna" obsahuje "rocn" // s[trv]{1,4}rocn pokrýva: stvrtrocn, svrtrocn, strtrocn, strvtrocn a ďalšie preklepy if (/s[trv]{1,4}rocn/.test(normalized)) return 'QUARTERLY'; // Ročná (vrátane preklepu "Ričná") if (/rocn|ricn/.test(normalized)) return 'ANNUAL'; // Mesačná if (/mesacn/.test(normalized)) return 'MONTHLY'; // Východzia / Vychodisková → základný typ z auditu if (/vychodz|vychodisk/.test(normalized)) return PERIOD_TO_TYPE[basePeriodicity] || 'QUARTERLY'; // Default → typ z auditu return PERIOD_TO_TYPE[basePeriodicity] || 'QUARTERLY'; } /** * Zistí, či poznámka indikuje "Východziu revíziu". */ function isVychodziaNote(note: string): boolean { const normalized = note.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, ''); return /vychodz|vychodisk/.test(normalized); } async function seed() { console.log('Seeding database...'); // ===== USER ROLES ===== console.log('Creating user roles...'); const roles = await Promise.all([ prisma.userRole.upsert({ where: { code: 'ROOT' }, update: {}, create: { code: 'ROOT', name: 'Root Správca', level: 1, order: 1, permissions: { projects: ['*'], tasks: ['*'], equipment: ['*'], rma: ['*'], customers: ['*'], settings: ['*'], users: ['*'], logs: ['*'], }, }, }), prisma.userRole.upsert({ where: { code: 'ADMIN' }, update: {}, create: { code: 'ADMIN', name: 'Administrátor', level: 2, order: 2, permissions: { projects: ['create', 'read', 'update', 'delete', 'all'], tasks: ['create', 'read', 'update', 'delete', 'all'], equipment: ['create', 'read', 'update', 'delete', 'all'], rma: ['create', 'read', 'update', 'delete', 'approve'], customers: ['create', 'read', 'update', 'delete'], users: ['read'], }, }, }), prisma.userRole.upsert({ where: { code: 'USER' }, update: {}, create: { code: 'USER', name: 'Používateľ', level: 3, order: 3, permissions: { projects: ['read', 'update'], tasks: ['create', 'read', 'update'], equipment: ['read', 'update'], rma: ['create', 'read', 'update'], customers: ['read'], }, }, }), prisma.userRole.upsert({ where: { code: 'CUSTOMER' }, update: {}, create: { code: 'CUSTOMER', name: 'Zákazník', level: 4, order: 4, permissions: { projects: ['read'], tasks: ['read'], equipment: ['read'], rma: ['create', 'read'], }, }, }), ]); // ===== EQUIPMENT TYPES ===== console.log('Creating equipment types...'); await prisma.equipmentType.createMany({ skipDuplicates: true, data: [ { code: 'EPS', name: 'Elektrická požiarna signalizácia', color: '#3B82F6', order: 1 }, { code: 'HSP', name: 'Hlasová signalizácia požiaru', color: '#EF4444', order: 2 }, { code: 'CAMERA', name: 'Kamerový systém', color: '#10B981', order: 3 }, { code: 'ACCESS', name: 'Prístupový systém', color: '#F59E0B', order: 4 }, { code: 'OTHER', name: 'Iné zariadenie', color: '#6B7280', order: 5 }, // Additional types from old DB ...ADDITIONAL_EQUIP_TYPES.map((t, i) => ({ code: t.code, name: t.name, color: t.color, order: 6 + i, })), ], }); // ===== REVISION TYPES ===== console.log('Creating revision types...'); await prisma.revisionType.createMany({ skipDuplicates: true, data: [ { code: 'MONTHLY', name: 'Mesačná revízia', intervalDays: 30, reminderDays: 7, color: '#6366F1', order: 1 }, { code: 'QUARTERLY', name: 'Štvrťročná revízia', intervalDays: 90, reminderDays: 14, color: '#FFA500', order: 2 }, { code: 'BIANNUAL', name: 'Polročná revízia', intervalDays: 180, reminderDays: 21, color: '#FBBF24', order: 3 }, { code: 'ANNUAL', name: 'Ročná revízia', intervalDays: 365, reminderDays: 30, color: '#DC2626', order: 4 }, { code: 'BIENNIAL', name: 'Revízia každé 2 roky', intervalDays: 730, reminderDays: 60, color: '#8B5CF6', order: 5 }, { code: 'TRIENNIAL', name: 'Revízia každé 3 roky', intervalDays: 1095, reminderDays: 90, color: '#0EA5E9', order: 6 }, { code: 'QUADRENNIAL', name: 'Revízia každé 4 roky', intervalDays: 1460, reminderDays: 90, color: '#14B8A6', order: 7 }, { code: 'QUINQUENNIAL', name: 'Revízia každých 5 rokov', intervalDays: 1825, reminderDays: 120, color: '#F97316', order: 8 }, { code: 'EMERGENCY', name: 'Mimoriadna revízia', intervalDays: 0, reminderDays: 0, color: '#EF4444', order: 9 }, ], }); // ===== RMA STATUSES ===== console.log('Creating RMA statuses...'); await prisma.rMAStatus.createMany({ skipDuplicates: true, data: [ { code: 'NEW', name: 'Nová reklamácia', color: '#10B981', isInitial: true, canTransitionTo: ['IN_ASSESSMENT', 'REJECTED'], order: 1 }, { code: 'IN_ASSESSMENT', name: 'V posúdzovaní', color: '#F59E0B', canTransitionTo: ['APPROVED', 'REJECTED'], order: 2 }, { code: 'APPROVED', name: 'Schválená', color: '#3B82F6', canTransitionTo: ['IN_REPAIR', 'REPLACED', 'REFUNDED'], order: 3 }, { code: 'REJECTED', name: 'Zamietnutá', color: '#EF4444', isFinal: true, order: 4 }, { code: 'IN_REPAIR', name: 'V oprave', color: '#8B5CF6', canTransitionTo: ['REPAIRED', 'COMPLETED'], order: 5 }, { code: 'REPAIRED', name: 'Opravené', color: '#059669', canTransitionTo: ['COMPLETED'], order: 6 }, { code: 'REPLACED', name: 'Vymenené', color: '#059669', canTransitionTo: ['COMPLETED'], order: 7 }, { code: 'REFUNDED', name: 'Vrátené peniaze', color: '#059669', canTransitionTo: ['COMPLETED'], order: 8 }, { code: 'COMPLETED', name: 'Uzatvorená', color: '#059669', isFinal: true, order: 9 }, ], }); // ===== RMA SOLUTIONS ===== console.log('Creating RMA solutions...'); await prisma.rMASolution.createMany({ skipDuplicates: true, data: [ { code: 'ASSESSMENT', name: 'Posúdzovanie', color: '#F59E0B', order: 1 }, { code: 'REPAIR', name: 'Oprava', color: '#3B82F6', order: 2 }, { code: 'REPLACEMENT', name: 'Výmena', color: '#10B981', order: 3 }, { code: 'REFUND', name: 'Vrátenie peňazí', color: '#8B5CF6', order: 4 }, { code: 'REJECTED', name: 'Zamietnutie', color: '#EF4444', order: 5 }, { code: 'OTHER', name: 'Iné riešenie', color: '#6B7280', order: 6 }, ], }); // ===== TASK STATUSES ===== console.log('Creating task statuses...'); await prisma.taskStatus.createMany({ skipDuplicates: true, data: [ { code: 'NEW', name: 'Nová úloha', swimlaneColumn: 'NEW', color: '#10B981', isInitial: true, order: 1 }, { code: 'IN_PROGRESS', name: 'V riešení', swimlaneColumn: 'DOING', color: '#F59E0B', order: 2 }, { code: 'REVIEW', name: 'Na kontrolu', swimlaneColumn: 'DOING', color: '#8B5CF6', order: 3 }, { code: 'COMPLETED', name: 'Dokončená', swimlaneColumn: 'DONE', color: '#059669', isFinal: true, order: 4 }, ], }); // ===== PRIORITIES ===== console.log('Creating priorities...'); await prisma.priority.createMany({ skipDuplicates: true, data: [ { code: 'LOW', name: 'Nízka priorita', color: '#10B981', level: 1, order: 1 }, { code: 'MEDIUM', name: 'Stredná priorita', color: '#F59E0B', level: 5, order: 2 }, { code: 'HIGH', name: 'Vysoká priorita', color: '#EF4444', level: 8, order: 3 }, { code: 'URGENT', name: 'Urgentná', color: '#DC2626', level: 10, order: 4 }, ], }); // ===== SYSTEM SETTINGS ===== console.log('Creating system settings...'); await prisma.systemSetting.createMany({ skipDuplicates: true, data: [ { key: 'REVISION_REMINDER_DAYS', value: 14, category: 'NOTIFICATIONS', label: 'Pripomenúť revíziu X dní dopredu', dataType: 'number', validation: { min: 1, max: 365 }, }, { key: 'RMA_NUMBER_FORMAT', value: 'RMA-{YYYY}{MM}{DD}{XXX}', category: 'RMA', label: 'Formát RMA čísla', dataType: 'string', }, { key: 'RMA_CUSTOMER_REQUIRES_APPROVAL', value: true, category: 'RMA', label: 'Reklamácie od zákazníkov vyžadujú schválenie', dataType: 'boolean', }, { key: 'ADMIN_NOTIFICATION_EMAILS', value: ['admin@firma.sk'], category: 'NOTIFICATIONS', label: 'Email adresy pre admin notifikácie', dataType: 'json', }, { key: 'ENABLE_WEBSOCKET', value: false, category: 'GENERAL', label: 'Zapnúť real-time aktualizácie (WebSocket)', dataType: 'boolean', }, { key: 'NOTIFICATION_SNOOZE_OPTIONS', value: [ { label: '30 minút', minutes: 30 }, { label: '1 hodina', minutes: 60 }, { label: '3 hodiny', minutes: 180 }, { label: 'Dnes poobede o 13:00', type: 'today', hour: 13 }, { label: 'Zajtra ráno o 8:00', type: 'tomorrow', hour: 8 }, { label: 'Zajtra poobede o 13:00', type: 'tomorrow', hour: 13 }, ], category: 'NOTIFICATIONS', label: 'Možnosti odloženia notifikácií', description: 'Pole objektov. Každý má "label" a buď "minutes" (relatívny čas) alebo "type" + "hour" (konkrétny čas). Type: "today" (ak čas prešiel, skryje sa), "tomorrow".', dataType: 'json', }, { key: 'REVISION_STATUS_THRESHOLDS', value: [ { days: 30, label: 'Blíži sa', color: '#EAB308' }, { days: 14, label: 'Blíži sa!', color: '#F97316' }, { days: 7, label: 'Urgentné!', color: '#EF4444' }, ], category: 'REVISIONS', label: 'Prahy upozornení revízií', description: 'Pole prahov zoradených od najväčšieho po najmenší počet dní. Každý prah má: "days" (počet dní pred termínom), "label" (text), "color" (hex farba). Po termíne sa vždy zobrazuje červená.', dataType: 'json', }, ], }); // ===== USERS (demo + real from old DB) ===== console.log('Creating users...'); const rootRole = roles.find(r => r.code === 'ROOT'); const adminRole = roles.find(r => r.code === 'ADMIN'); const userRole = roles.find(r => r.code === 'USER'); const customerRole = roles.find(r => r.code === 'CUSTOMER'); if (!rootRole || !adminRole || !userRole || !customerRole) { throw new Error('Required roles not found'); } const [hashedPassword, hashedRoot, hashedAdmin, hashedUser, hashedZakaznik] = await Promise.all([ bcrypt.hash('heslo123', 10), bcrypt.hash('root123', 10), bcrypt.hash('admin123', 10), bcrypt.hash('user123', 10), bcrypt.hash('zakaznik123', 10), ]); const rootUser = await prisma.user.upsert({ where: { email: 'root@helpdesk.sk' }, update: {}, create: { email: 'root@helpdesk.sk', password: hashedPassword, name: 'Root Admin', roleId: rootRole.id, }, }); // Demo users - jeden pre každú rolu const [demoRoot, demoAdmin, user1, user2, user3, demoZakaznik] = await Promise.all([ prisma.user.upsert({ where: { email: 'root@root.sk' }, update: {}, create: { email: 'root@root.sk', password: hashedRoot, name: 'Root Používateľ', roleId: rootRole.id, }, }), prisma.user.upsert({ where: { email: 'admin@admin.sk' }, update: {}, create: { email: 'admin@admin.sk', password: hashedAdmin, name: 'Admin Používateľ', roleId: adminRole.id, }, }), prisma.user.upsert({ where: { email: 'user1@user.sk' }, update: {}, create: { email: 'user1@user.sk', password: hashedUser, name: 'Ján Technik', roleId: userRole.id, }, }), prisma.user.upsert({ where: { email: 'user2@user.sk' }, update: {}, create: { email: 'user2@user.sk', password: hashedUser, name: 'Peter Sieťar', roleId: userRole.id, }, }), prisma.user.upsert({ where: { email: 'user3@user.sk' }, update: {}, create: { email: 'user3@user.sk', password: hashedUser, name: 'Marek Montážnik', roleId: userRole.id, }, }), prisma.user.upsert({ where: { email: 'zakaznik@zakaznik.sk' }, update: {}, create: { email: 'zakaznik@zakaznik.sk', password: hashedZakaznik, name: 'Zákazník Demo', roleId: customerRole.id, }, }), ]); console.log(' Created demo users: root@root.sk, admin@admin.sk, user1-3@user.sk, zakaznik@zakaznik.sk'); // All service records are assigned to root user const defaultUserId = rootUser.id; // ===== CUSTOMERS FROM OLD DB ===== console.log('Creating customers from old DB...'); const customerMap: Record = {}; for (const c of CUSTOMERS) { const customer = await prisma.customer.upsert({ where: { externalId: String(c.oldId) }, update: {}, create: { name: c.name, ico: c.ico && c.ico !== '0' ? c.ico : undefined, dic: c.dic && c.dic !== '0' ? c.dic : undefined, address: c.address, email: c.email, contactPerson: c.contactPerson, contactPhone: c.phone, externalId: String(c.oldId), externalSource: 'old-helpdesk', createdById: rootUser.id, }, }); customerMap[c.oldId] = customer.id; } console.log(` Created ${Object.keys(customerMap).length} customers`); // ===== ANALYZE SERVICE RECORDS ===== // Zistiť pre každé zariadenie: aké typy revízií má a kedy bola východzia revízia console.log('Analyzing service records for revision metadata...'); interface EquipMeta { typeCodes: Set; vychodziaDate: string | null; } const equipMeta: Map = new Map(); for (const [auditId, date, , , note] of SERVICE_RECORDS) { const audit = AUDIT_MAP[auditId]; if (!audit) continue; const hwId = audit.equipmentHwId; if (!equipMeta.has(hwId)) { equipMeta.set(hwId, { typeCodes: new Set(), vychodziaDate: null }); } const meta = equipMeta.get(hwId)!; // Klasifikovať typ revízie z poznámky const typeCode = classifyNote(note, audit.periodicity); meta.typeCodes.add(typeCode); // Detekovať dátum "Východzej revízie" if (isVychodziaNote(note) && !meta.vychodziaDate) { meta.vychodziaDate = date; } } console.log(` Found revision metadata for ${equipMeta.size} equipment items`); for (const [hwId, meta] of equipMeta) { if (meta.vychodziaDate) { console.log(` hwId ${hwId}: východzia=${meta.vychodziaDate}, types=[${[...meta.typeCodes].join(', ')}]`); } } // ===== EQUIPMENT FROM OLD DB ===== console.log('Creating equipment from old DB...'); // Fetch equipment type IDs const equipTypes = await prisma.equipmentType.findMany(); const equipTypeMap: Record = {}; for (const t of equipTypes) { equipTypeMap[t.code] = t.id; } const equipmentIdMap: Record = {}; // hwId -> new ID for (const e of EQUIPMENT) { const typeId = equipTypeMap[e.typeCode] || equipTypeMap['OTHER']; const customerId = customerMap[e.companyId] || undefined; const meta = equipMeta.get(e.hwId); const equip = await prisma.equipment.create({ data: { name: e.name, typeId, brand: e.brand || undefined, customerId, address: e.location || '-', location: e.location || undefined, partNumber: e.partNumber && !['-', ' ', '', '0'].includes(e.partNumber.trim()) ? e.partNumber : undefined, serialNumber: e.serialNumber && !['-', ' ', '', '0', '.', '..', '...', ':', ',', '.,', ',.', ',,', '.-', '---', '-----', '-,'].includes(e.serialNumber.trim()) ? e.serialNumber : undefined, description: e.description && !['-', ' ', '', 'ok'].includes(e.description.trim()) ? e.description : undefined, installDate: e.installDate ? new Date(e.installDate) : undefined, revisionCycleStart: meta?.vychodziaDate ? new Date(meta.vychodziaDate) : undefined, createdById: rootUser.id, }, }); equipmentIdMap[e.hwId] = equip.id; } console.log(` Created ${Object.keys(equipmentIdMap).length} equipment items`); // ===== EQUIPMENT REVISION SCHEDULES ===== // Pre každé zariadenie vytvoriť záznamy o tom, aké typy revízií má priradené console.log('Creating equipment revision schedules...'); const revisionTypes = await prisma.revisionType.findMany(); const revTypeMap: Record = {}; for (const t of revisionTypes) { revTypeMap[t.code] = t.id; } let scheduleCount = 0; for (const [hwId, meta] of equipMeta) { const equipId = equipmentIdMap[hwId]; if (!equipId) continue; for (const typeCode of meta.typeCodes) { const revTypeId = revTypeMap[typeCode]; if (!revTypeId) continue; await prisma.equipmentRevisionSchedule.create({ data: { equipmentId: equipId, revisionTypeId: revTypeId, }, }); scheduleCount++; } } console.log(` Created ${scheduleCount} equipment revision schedules`); // ===== REVISION RECORDS FROM OLD DB ===== console.log('Creating revision records from old DB...'); let createdRevisions = 0; let skippedRevisions = 0; // Deduplicate: same equipment + type + date = duplicate in old data const seen = new Set(); const uniqueRevisions = SERVICE_RECORDS .map(([auditId, date, nextDate, _userEmail, note]) => { const audit = AUDIT_MAP[auditId]; if (!audit) return null; const equipId = equipmentIdMap[audit.equipmentHwId]; if (!equipId) return null; // Klasifikovať typ revízie podľa poznámky (nie len podľa audit periodicity) const typeCode = classifyNote(note, audit.periodicity); const typeId = revTypeMap[typeCode]; if (!typeId) return null; // Deduplicate by equipment + type + date const key = `${equipId}-${typeId}-${date}`; if (seen.has(key)) return null; seen.add(key); return { equipmentId: equipId, typeId, performedDate: new Date(date), nextDueDate: nextDate ? new Date(nextDate) : null, performedById: defaultUserId, notes: note && note.trim() ? note.trim() : undefined, result: 'OK', }; }) .filter((r): r is NonNullable => r !== null); // Process in batches const BATCH_SIZE = 50; for (let i = 0; i < uniqueRevisions.length; i += BATCH_SIZE) { const batch = uniqueRevisions.slice(i, i + BATCH_SIZE); await prisma.revision.createMany({ data: batch }); createdRevisions += batch.length; } skippedRevisions = SERVICE_RECORDS.length - uniqueRevisions.length; console.log(` Created ${createdRevisions} revisions (${skippedRevisions} duplicates skipped)`); // ===== DEMO TASKS ===== console.log('Creating demo tasks...'); const statuses = await prisma.taskStatus.findMany(); const priorities = await prisma.priority.findMany(); const statusByCode = (code: string) => statuses.find(s => s.code === code)!.id; const priorityByCode = (code: string) => priorities.find(p => p.code === code)!.id; const demoTasks = [ // --- Admin zadáva úlohy pre userov --- { title: 'Objednať UTP káble Cat6a (100m)', description: 'Objednať 3 balenia UTP káblov Cat6a po 100m pre nový serverový rack. Dodávateľ: Senetic alebo TS Bohemia.', statusCode: 'NEW', priorityCode: 'MEDIUM', createdById: demoAdmin.id, assignees: [user1.id], deadline: new Date('2026-03-10'), }, { title: 'Výmena UPS batérií v racku R3', description: 'APC Smart-UPS 1500VA - batérie sú po záruke, hlási "Replace Battery". Objednať RBC7 a vymeniť.', statusCode: 'NEW', priorityCode: 'URGENT', createdById: demoAdmin.id, assignees: [user2.id], deadline: new Date('2026-02-28'), }, { title: 'Inštalácia kamerového systému - vstupná hala', description: 'Namontovať 2x Hikvision DS-2CD2143G2 + nastaviť NVR záznam na 30 dní. Kabeláž už je pripravená.', statusCode: 'IN_PROGRESS', priorityCode: 'MEDIUM', createdById: demoAdmin.id, assignees: [user3.id], deadline: new Date('2026-03-15'), }, { title: 'Oprava Wi-Fi pokrytia v zasadačke B2', description: 'Zákazník hlási slabý signál. Skontrolovať site survey, prípadne pridať ďalší AP alebo presunúť existujúci.', statusCode: 'NEW', priorityCode: 'HIGH', createdById: demoAdmin.id, assignees: [user1.id, user2.id], deadline: new Date('2026-03-08'), }, { title: 'Objednať toner do tlačiarne HP LaserJet Pro', description: 'Kancelária 3. poschodie - toner CF259X je takmer prázdny. Objednať 2 kusy na sklad.', statusCode: 'COMPLETED', priorityCode: 'LOW', createdById: demoAdmin.id, assignees: [user1.id], }, // --- Root zadáva úlohy pre userov a admina --- { title: 'Nastaviť switch Cisco SG350 v serverovni', description: 'Konfigurácia VLAN 10, 20, 30. Trunk port na uplink. Nastaviť SNMP monitoring a port security na access portoch.', statusCode: 'IN_PROGRESS', priorityCode: 'HIGH', createdById: demoRoot.id, assignees: [demoAdmin.id, user1.id], deadline: new Date('2026-03-05'), }, { title: 'Nastaviť VPN tunel medzi pobočkami', description: 'IPSec site-to-site VPN medzi Bratislava a Košice. MikroTik RB4011 na oboch stranách. Zdieľaný subnet 10.10.0.0/24.', statusCode: 'IN_PROGRESS', priorityCode: 'HIGH', createdById: demoRoot.id, assignees: [user2.id, user3.id], deadline: new Date('2026-03-01'), }, { title: 'Migrácia mailboxov na Microsoft 365', description: 'Presunúť 25 mailboxov z on-prem Exchange na M365. Pripraviť migračný plán, otestovať na 3 pilotných užívateľoch.', statusCode: 'NEW', priorityCode: 'MEDIUM', createdById: demoRoot.id, assignees: [demoAdmin.id, user1.id, user2.id], deadline: new Date('2026-04-01'), }, // --- Úlohy kde admin robí sám --- { title: 'Zálohovanie konfigurácie sieťových zariadení', description: 'Exportovať running-config zo všetkých switchov a routerov. Uložiť do Git repozitára na NAS.', statusCode: 'COMPLETED', priorityCode: 'MEDIUM', createdById: demoAdmin.id, assignees: [demoAdmin.id], }, { title: 'Aktualizovať firmware na AP Ubiquiti U6-Pro', description: 'Nová verzia firmware opravuje bug s roamingom klientov. Aktualizovať všetkých 8 AP cez UniFi Controller.', statusCode: 'REVIEW', priorityCode: 'LOW', createdById: demoAdmin.id, assignees: [demoAdmin.id, user3.id], }, // --- Root + admin spoločne --- { title: 'Audit sieťovej infraštruktúry', description: 'Kompletný audit všetkých aktívnych prvkov, kontrola firmware verzií, kontrola prístupových práv na zariadeniach.', statusCode: 'NEW', priorityCode: 'MEDIUM', createdById: demoRoot.id, assignees: [demoAdmin.id], deadline: new Date('2026-03-20'), }, // --- User si vytvára vlastnú úlohu --- { title: 'Zdokumentovať zapojenie patch panelov v racku R1', description: 'Vytvoriť schému zapojenia patch panelov a označiť káble podľa štandardu TIA-606.', statusCode: 'IN_PROGRESS', priorityCode: 'LOW', createdById: user2.id, assignees: [user2.id], }, ]; for (const t of demoTasks) { const task = await prisma.task.create({ data: { title: t.title, description: t.description, statusId: statusByCode(t.statusCode), priorityId: priorityByCode(t.priorityCode), createdById: t.createdById, deadline: t.deadline, completedAt: t.statusCode === 'COMPLETED' ? new Date() : undefined, }, }); if (t.assignees.length > 0) { await prisma.taskAssignee.createMany({ data: t.assignees.map(userId => ({ taskId: task.id, userId, })), }); } } console.log(` Created ${demoTasks.length} demo tasks`); console.log('Seeding completed!'); } seed() .catch((error) => { console.error('Seeding failed:', error); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); });