import 'dotenv/config'; import { PrismaClient } from '@prisma/client'; import { mapAllHrProjects } from '../prisma/mapHrProjects'; const prisma = new PrismaClient(); const API_BASE = process.env.TARGET_API_URL?.replace(/\/$/, ''); async function importViaPrisma(adminId: string, memberId: string) { const tasks = mapAllHrProjects(); await prisma.file.deleteMany({}); await prisma.taskDetail.deleteMany({}); await prisma.milestone.deleteMany({}); await prisma.kpiMetric.deleteMany({}); await prisma.task.deleteMany({}); for (const t of tasks) { const { milestones, detailContent, ...taskData } = t; const task = await prisma.task.create({ data: { ...taskData, creatorId: adminId, assigneeId: memberId, }, }); for (const [order, ms] of milestones.entries()) { await prisma.milestone.create({ data: { ...ms, taskId: task.id, order }, }); } if (detailContent) { await prisma.taskDetail.create({ data: { taskId: task.id, content: detailContent, updatedBy: adminId, }, }); } } console.log(`✅ Prisma import complete: ${tasks.length} tasks`); } async function importViaApi(adminId: string, memberId: string) { const base = API_BASE!; const tasks = mapAllHrProjects(); const existingRes = await fetch(`${base}/api/tasks`); if (!existingRes.ok) throw new Error(`GET /api/tasks failed: ${existingRes.status}`); const existing = (await existingRes.json()) as { id: string }[]; for (const task of existing) { const del = await fetch(`${base}/api/tasks/${task.id}`, { method: 'DELETE' }); if (!del.ok && del.status !== 204) throw new Error(`DELETE ${task.id} failed: ${del.status}`); } for (const t of tasks) { const { milestones, detailContent, ...taskData } = t; const body = { ...taskData, startDate: taskData.startDate?.toISOString() ?? null, dueDate: taskData.dueDate?.toISOString() ?? null, creatorId: adminId, assigneeId: memberId, }; const createRes = await fetch(`${base}/api/tasks`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }); if (!createRes.ok) { const err = await createRes.text(); throw new Error(`POST task "${t.title}" failed: ${createRes.status} ${err}`); } const created = (await createRes.json()) as { id: string }; for (const [order, ms] of milestones.entries()) { const msRes = await fetch(`${base}/api/milestones/${created.id}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ...ms, order }), }); if (!msRes.ok) console.warn(` ⚠ milestone skip: ${t.title} / ${ms.title}`); } if (detailContent) { const detailRes = await fetch(`${base}/api/details/${created.id}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content: detailContent, authorName: '관리자' }), }); if (!detailRes.ok) console.warn(` ⚠ detail skip: ${t.title}`); } } console.log(`✅ API import complete: ${tasks.length} tasks → ${base}`); } async function main() { const tasks = mapAllHrProjects(); console.log(`📦 HR_Dashboard → ${tasks.length} tasks mapped`); let adminId: string; let memberId: string; if (API_BASE) { const res = await fetch(`${API_BASE}/api/tasks`); const existing = res.ok ? ((await res.json()) as { creatorId: string; assigneeId: string | null }[]) : []; if (existing.length > 0) { adminId = existing[0].creatorId; memberId = existing[0].assigneeId ?? existing[0].creatorId; } else { throw new Error('API에 기존 task가 없어 creatorId를 확인할 수 없습니다.'); } await importViaApi(adminId, memberId); } else { const admin = await prisma.user.upsert({ where: { email: 'admin@eene.com' }, update: {}, create: { email: 'admin@eene.com', password: '!', name: '관리자', role: 'ADMIN', department: 'EENE' }, }); const member = await prisma.user.upsert({ where: { email: 'member@eene.com' }, update: { name: '정성호' }, create: { email: 'member@eene.com', password: '!', name: '정성호', role: 'MEMBER', department: 'EENE' }, }); adminId = admin.id; memberId = member.id; await importViaPrisma(adminId, memberId); } } main() .catch((err) => { console.error('❌ Import failed:', err); process.exit(1); }) .finally(() => prisma.$disconnect());