import { PrismaClient } from '@prisma/client'; import { readFileSync } from 'node:fs'; import { resolve, dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; const __dirname = dirname(fileURLToPath(import.meta.url)); const prisma = new PrismaClient(); interface RegionRow { code: string; name_ko: string; full_name_ko: string; region_type: string; parent_code: string; depth: string; path_code: string; sort_order: string; is_active: string; is_beta_enabled: string; latitude: string; longitude: string; } interface IndustryRow { code: string; name_ko: string; parent_code: string; depth: string; sort_order: string; is_leaf: string; is_active: string; is_beta_enabled: string; } function parseCsv(filePath: string): Record[] { const content = readFileSync(filePath, 'utf-8'); const lines = content.trim().split('\n'); const headers = lines[0]!.split(','); return lines.slice(1).map((line) => { const values = line.split(','); const row: Record = {}; for (let i = 0; i < headers.length; i++) { row[headers[i]!] = values[i] ?? ''; } return row; }); } async function seedRegions(): Promise { const csvPath = resolve(__dirname, 'master-data/regions.v1.csv'); const rows = parseCsv(csvPath) as unknown as RegionRow[]; // code → id 매핑을 위한 맵 const codeToId = new Map(); // depth 순으로 정렬하여 부모를 먼저 upsert const sorted = [...rows].sort((a, b) => parseInt(a.depth) - parseInt(b.depth)); for (const row of sorted) { const parentId = row.parent_code ? (codeToId.get(row.parent_code) ?? null) : null; const result = await prisma.regionHierarchy.upsert({ where: { code: row.code }, update: { nameKo: row.name_ko, fullNameKo: row.full_name_ko || null, regionType: row.region_type as never, parentId, depth: parseInt(row.depth), pathCode: row.path_code, sortOrder: parseInt(row.sort_order), isActive: row.is_active === 'true', isBetaEnabled: row.is_beta_enabled === 'true', latitude: row.latitude ? parseFloat(row.latitude) : null, longitude: row.longitude ? parseFloat(row.longitude) : null, }, create: { code: row.code, nameKo: row.name_ko, fullNameKo: row.full_name_ko || null, regionType: row.region_type as never, parentId, depth: parseInt(row.depth), pathCode: row.path_code, sortOrder: parseInt(row.sort_order), isActive: row.is_active === 'true', isBetaEnabled: row.is_beta_enabled === 'true', latitude: row.latitude ? parseFloat(row.latitude) : null, longitude: row.longitude ? parseFloat(row.longitude) : null, }, }); codeToId.set(row.code, result.id); } console.log(`Seeded ${sorted.length} regions`); } async function seedIndustries(): Promise { const csvPath = resolve(__dirname, 'master-data/industries.v1.csv'); const rows = parseCsv(csvPath) as unknown as IndustryRow[]; const codeToId = new Map(); const sorted = [...rows].sort((a, b) => parseInt(a.depth) - parseInt(b.depth)); for (const row of sorted) { const parentId = row.parent_code ? (codeToId.get(row.parent_code) ?? null) : null; const result = await prisma.industryTaxonomy.upsert({ where: { code: row.code }, update: { nameKo: row.name_ko, parentId, depth: parseInt(row.depth), sortOrder: parseInt(row.sort_order), isLeaf: row.is_leaf === 'true', isActive: row.is_active === 'true', isBetaEnabled: row.is_beta_enabled === 'true', }, create: { code: row.code, nameKo: row.name_ko, parentId, depth: parseInt(row.depth), sortOrder: parseInt(row.sort_order), isLeaf: row.is_leaf === 'true', isActive: row.is_active === 'true', isBetaEnabled: row.is_beta_enabled === 'true', }, }); codeToId.set(row.code, result.id); } console.log(`Seeded ${sorted.length} industries`); } async function main(): Promise { console.log('Starting seed...'); await seedRegions(); await seedIndustries(); console.log('Seed completed successfully'); } main() .catch((e) => { console.error('Seed failed:', e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); });