MIF_E31221222/sigap-website/prisma/seeds/units.ts

301 lines
8.0 KiB
TypeScript

import { locations, PrismaClient, unit_type, units } from '@prisma/client';
import * as XLSX from 'xlsx';
import * as fs from 'fs';
import * as path from 'path';
import axios from 'axios';
import { v4 as uuidv4 } from 'uuid';
import { createClient } from '../../app/_utils/supabase/client';
import { generateId, generateIdWithDbCounter } from '../../app/_utils/common';
// Interface untuk data Excel row
interface ExcelRow {
KESATUAN: string;
[key: string]: any; // Untuk kolom dinamis seperti "JAN CT", "JAN CC", dll
}
// Interface untuk mapping bulan
interface MonthMap {
[key: string]: number;
}
// Interface untuk statistik unit
interface UnitStatistics {
unit_id: string;
month: number;
year: number;
crime_total: number;
crime_cleared: number;
percentage: number;
pending: number;
}
interface CreateLocationDto {
district_id: string;
code_unit: string;
name?: string;
description?: string;
address?: string;
type?: string;
phone?: string;
latitude: number;
longitude: number;
land_area?: number;
polygon?: Record<string, any>;
geometry?: Record<string, any>;
location?: string;
}
export class UnitSeeder {
private mapboxToken: string;
constructor(
private prisma: PrismaClient,
private supabase = createClient()
) {
this.mapboxToken = process.env.NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN || '';
}
async run(): Promise<void> {
await this.prisma.units.deleteMany({});
const districts = await this.prisma.districts.findMany({
include: {
cities: true,
},
});
const city = await this.prisma.cities.findFirst({
where: {
name: 'Jember',
},
include: {
districts: true,
},
});
if (!city) {
console.error('City not found: Jember');
return;
}
const location = await this.getUnitsLocation(city.name);
if (!location) {
console.warn(`No location found for city: ${city.name}`);
return;
}
const [lng, lat] = [location.lng, location.lat];
const address = location.address;
const phone = location.telepon?.replace(/-/g, '');
const newId = await generateIdWithDbCounter('units', {
prefix: 'UT',
segments: {
sequentialDigits: 4,
},
format: '{prefix}-{sequence}',
separator: '-',
uniquenessStrategy: 'counter',
});
let locationData: CreateLocationDto = {
district_id: city.districts[0].id, // This will be replaced with Patrang's ID
code_unit: newId,
name: `Polres ${city.name}`,
description: `Unit ${city.name} is categorized as POLRES and operates in the ${city.name} area.`,
type: 'polres',
address,
phone,
longitude: lng,
latitude: lat,
location: `POINT(${lng} ${lat})`,
};
// Find the Patrang district
const patrangDistrict = await this.prisma.districts.findFirst({
where: {
name: 'Patrang',
city_id: city.id,
},
});
if (!patrangDistrict) {
console.error('District not found: Patrang');
return;
}
locationData.district_id = patrangDistrict.id;
const { error } = await this.supabase
.from('units')
.insert([locationData])
.select();
if (error) {
console.error(`Error inserting into Supabase locations:`, error);
return;
}
let district;
for (district of districts) {
const location = await this.getUnitsLocation(district.name);
if (!location) {
console.warn(`No location found for district: ${district.name}`);
continue;
}
const [lng, lat] = [location.lng, location.lat];
const address = location.address;
const phone = location.telepon?.replace(/-/g, '');
const newId = await generateIdWithDbCounter('units', {
prefix: 'UT',
segments: {
sequentialDigits: 4,
},
format: '{prefix}-{sequence}',
separator: '-',
uniquenessStrategy: 'counter',
});
const locationData: CreateLocationDto = {
district_id: district.id,
code_unit: newId,
name: `Polsek ${district.name}`,
description: `Unit ${district.name} is categorized as POLSEK and operates in the ${district.name} area.`,
type: 'polsek',
address: address,
phone,
longitude: lng,
latitude: lat,
location: `POINT(${lng} ${lat})`,
};
const { error } = await this.supabase
.from('units')
.insert([locationData])
.select();
if (error) {
console.error(`Error inserting into Supabase locations:`, error);
continue;
}
console.log(
`Inserted unit for district: ${district.name}, newId: ${newId} at ${lng}, ${lat}`
);
}
}
private parseNumber(value: any): number {
if (value === undefined || value === null) return 0;
const num = Number(value);
return isNaN(num) ? 0 : num;
}
private async getUnitsLocation(districtName: string): Promise<{
lng: number;
lat: number;
address: string;
telepon: string;
} | null> {
// const getCoordinatesFromMapbox = async (
// query: string
// ): Promise<{ lng: number; lat: number } | null> => {
// const suggestUrl = `https://api.mapbox.com/search/searchbox/v1/suggest?q=${encodeURIComponent(
// query
// )}&session_token=${uuidv4()}&access_token=${this.mapboxToken}`;
// // console.log(`Suggest URL: ${suggestUrl}`);
// const res = await axios.get(suggestUrl);
// const suggestions = res?.data?.suggestions;
// if (!suggestions || suggestions.length === 0) return null;
// const mapboxId = suggestions[0].mapbox_id;
// // console.log(`Mapbox ID for ${query}: ${mapboxId}`);
// if (!mapboxId) return null;
// const retrieveUrl = `https://api.mapbox.com/search/searchbox/v1/retrieve/${mapboxId}?session_token=${uuidv4()}&access_token=${this.mapboxToken}`;
// // console.log(`Retrieve URL: ${retrieveUrl}`);
// const retrieveResponse = await axios.get(retrieveUrl);
// const features = retrieveResponse?.data.features;
// const [lng, lat] = features[0].geometry.coordinates;
// return { lng, lat };
// };
// Buka file Excel untuk ambil data nama dan alamat Polsek
const fallbackFilePath = path.join(
__dirname,
'../data/excels/administrations/polsek_jember.xlsx'
);
const workbook = XLSX.readFile(fallbackFilePath);
const sheetName = workbook.SheetNames[0];
const sheet = workbook.Sheets[sheetName];
const rows = XLSX.utils.sheet_to_json(sheet) as {
'Nama Unit': string;
Alamat: string;
Telepon: string;
lat: number;
long: number;
}[];
// Temukan Polsek berdasarkan kecamatan (nama kecamatan ada dalam alamat)
const matchedRow = rows.find(
(row) =>
row.Alamat?.toLowerCase().includes(districtName.toLowerCase()) ||
row['Nama Unit'].toLowerCase().includes(districtName.toLowerCase())
);
// console.log(`Matched row for ${districtName}:`, matchedRow);
if (!matchedRow) {
console.warn(
`No matching Polsek found in sheet for district: ${districtName}`
);
return null;
}
const polsekName = matchedRow['Nama Unit'];
const polsekAddress = matchedRow.Alamat;
const telepon = matchedRow.Telepon;
const coordinates = {
lng: matchedRow.long,
lat: matchedRow.lat,
};
// Ambil koordinat dari Mapbox, tapi alamat tetap pakai dari sheet
// const coordinates = await getCoordinatesFromMapbox(polsekName);
// if (!coordinates) {
// console.warn(`Mapbox couldn't find coordinates for: ${polsekName}`);
// return null;
// }
// console.log(
// `Coordinates for ${polsekName} (${districtName}): ${coordinates.lng}, ${coordinates.lat}`
// );
console.log(
`Polsek Name: ${polsekName}, Address: ${polsekAddress}, Telepon: ${telepon}`
);
return {
...coordinates,
telepon,
address: polsekAddress, // ambil dari sheet, bukan dari Mapbox
};
}
}