95 lines
2.6 KiB
TypeScript
95 lines
2.6 KiB
TypeScript
// 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<void> {
|
|
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<number> {
|
|
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<number> {
|
|
const districtsGeo = await this.prisma.locations.findMany({});
|
|
return districtsGeo.reduce((sum, geo) => sum + (geo.land_area || 0), 0);
|
|
}
|
|
}
|