// prisma/seeds/DemographicsSeeder.ts import { PrismaClient } from '@prisma/client'; import path from 'path'; import XLSX from 'xlsx'; export class DemographicsSeeder { constructor(private prisma: PrismaClient) {} async run(): Promise { console.log('📥 Seeding demographics data from Excel...'); // Clear existing data await this.prisma.demographics.deleteMany({}); const districts = await this.prisma.districts.findMany(); // await this.prisma.$executeRaw`TRUNCATE TABLE "demographics" CASCADE`; // Load Excel const filePath = path.join( __dirname, '../data/excels/administrations/demographics.xlsx' ); const workbook = XLSX.readFile(filePath); const sheet = workbook.Sheets[workbook.SheetNames[0]]; const data = XLSX.utils.sheet_to_json(sheet) as any[]; let counter = 0; for (const row of data) { const districtName = String(row['Kecamatan']).trim(); const year = Number(row['Tahun']); const population = Number(row['Jumlah_Penduduk']); const unemployed = Number(row['Jumlah_Pengangguran']); const district = districts.find( (d) => d.name.toLowerCase() === districtName.toLowerCase() ); if (!district) { console.warn(`⚠️ District "${districtName}" not found in database.`); continue; } const districtLandArea = await this.getDistrictLandArea(district.id); const populationDensity = districtLandArea > 0 ? population / districtLandArea : 0; await this.prisma.demographics.create({ data: { district_id: district.id, year, population, population_density: populationDensity, number_of_unemployed: unemployed, }, }); counter++; console.log( `Seeding demographic data for district: ${districtName}, year: ${year}` ); } console.log(`✅ ${counter} demographic records seeded from Excel`); } private getRandomNumber(min: number, max: number): number { return Math.random() * (max - min) + min; } private async getDistrictLandArea(districtId: string): Promise { const geo = await this.prisma.geographics.findFirst({ where: { district_id: districtId }, select: { land_area: true, }, }); if (!geo) { console.error(`⚠️ Land area not found for district ID: ${districtId}`); return 0; } return geo.land_area || 0; } private async getCityLandArea(): Promise { const districtsGeo = await this.prisma.locations.findMany({}); return districtsGeo.reduce((sum, geo) => sum + (geo.land_area || 0), 0); } }