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

389 lines
9.8 KiB
TypeScript

import {
PrismaClient,
crime_rates,
events,
session_status,
users,
} from '@prisma/client';
import fs from 'fs';
import path from 'path';
import { parse } from 'csv-parse/sync';
import { generateId } from '../../app/_utils/common';
export class CrimesSeeder {
constructor(private prisma: PrismaClient) {}
async run(): Promise<void> {
console.log('🌱 Seeding crimes data...');
// Clear existing data
try {
// Create test user
const user = await this.createUsers();
// Create 5 events
const events = await this.createEvents(user);
// Create 5 sessions with completed status
await this.createSessions(user, events);
// Import monthly crime data
await this.importMonthlyCrimeData();
// Import yearly crime data from CSV file
await this.importYearlyCrimeData();
// Import all-year crime summaries (2020-2024)
await this.importAllYearSummaries();
console.log('✅ Crime seeding completed successfully.');
} catch (error) {
console.error('❌ Error seeding crimes:', error);
throw error;
}
}
private async createUsers() {
// Check if test users already exist
const existingUser = await this.prisma.users.findFirst({
where: { email: 'admin@sigap.id' },
});
if (existingUser) {
console.log('Users already exist, skipping creation.');
return existingUser;
}
// Get admin role ID
let roleId = await this.prisma.roles.findFirst({
where: { name: 'admin' },
});
if (!roleId) {
roleId = await this.prisma.roles.create({
data: {
name: 'admin',
description: 'Administrator role',
},
});
}
// Create test users
const user = await this.prisma.users.create({
data: {
email: `admin@gmail.com`,
roles_id: roleId.id,
confirmed_at: new Date(),
email_confirmed_at: new Date(),
is_anonymous: false,
profile: {
create: {
first_name: 'Admin',
last_name: 'Sigap',
username: 'admin',
},
},
},
});
return user;
}
private async createEvents(user: users) {
// Check if events already exist
const existingEvent = await this.prisma.events.findFirst({
where: {
user_id: user.id,
},
});
if (existingEvent) {
console.log('Events already exist, skipping creation.');
return existingEvent;
}
const event = await this.prisma.events.create({
data: {
name: `Crime Inserting Event For Crime 2020 - 2024`,
description: `Event for inserting crimes in region Jember`,
user_id: user.id,
},
});
return event;
}
private async createSessions(user: users, events: events) {
// Check if sessions already exist
const existingSession = await this.prisma.sessions.findFirst();
if (existingSession) {
console.log('Sessions already exist, skipping creation.');
return;
}
const newSession = await this.prisma.sessions.create({
data: {
user_id: user.id,
event_id: events.id,
status: session_status.completed,
},
});
return newSession;
}
private async importMonthlyCrimeData() {
console.log('Importing monthly crime data...');
// Check if crimes already exist
const existingCrimes = await this.prisma.crimes.findFirst();
if (existingCrimes) {
console.log('Crimes data already exists, skipping import.');
return;
}
// Read CSV file
const csvFilePath = path.resolve(
__dirname,
'../data/excels/crimes/crime_monthly.csv'
);
const fileContent = fs.readFileSync(csvFilePath, { encoding: 'utf-8' });
// Parse CSV
const records = parse(fileContent, {
columns: true,
skip_empty_lines: true,
});
// Store unique district IDs to avoid duplicates
const processedDistricts = new Set<string>();
// Import records
for (const record of records) {
const crimeRate = record.level.toLowerCase() as crime_rates;
const city = await this.prisma.cities.findFirst({
where: {
name: 'Jember',
},
});
if (!city) {
console.error('City not found: Jember');
return;
}
const year = parseInt(record.year);
// Create a unique ID for monthly crime data
const crimeId = await generateId({
prefix: 'CR',
segments: {
codes: [city.id],
sequentialDigits: 4,
year,
},
format: '{prefix}-{codes}-{sequence}-{year}',
separator: '-',
randomSequence: false,
uniquenessStrategy: 'counter',
storage: 'database',
tableName: 'crimes',
});
await this.prisma.crimes.create({
data: {
id: crimeId,
district_id: record.district_id,
level: crimeRate,
method: record.method || null,
month: parseInt(record.month_num),
year: parseInt(record.year),
number_of_crime: parseInt(record.number_of_crime),
score: parseFloat(record.score),
},
});
// Keep track of unique districts for later creation of crime incidents
processedDistricts.add(record.district_id);
}
console.log(`Imported ${records.length} monthly crime records.`);
}
private async importYearlyCrimeData() {
console.log('Importing yearly crime data...');
// Check if yearly summaries already exist (records with null month)
const existingYearlySummary = await this.prisma.crimes.findFirst({
where: { month: null },
});
if (existingYearlySummary) {
console.log('Yearly crime data already exists, skipping import.');
return;
}
// Read CSV file
const csvFilePath = path.resolve(
__dirname,
'../data/excels/crimes/crime_yearly.csv'
);
const fileContent = fs.readFileSync(csvFilePath, { encoding: 'utf-8' });
// Parse CSV
const records = parse(fileContent, {
columns: true,
skip_empty_lines: true,
});
// Import records
for (const record of records) {
const crimeRate = record.level.toLowerCase() as crime_rates;
const year = parseInt(record.year);
const city = await this.prisma.cities.findFirst({
where: {
districts: {
some: {
id: record.district_id,
},
},
},
});
if (!city) {
console.error(`City not found for district ${record.district_id}`);
continue;
}
// Create a unique ID for yearly crime data
const crimeId = await generateId({
prefix: 'CR',
segments: {
codes: [city.id],
sequentialDigits: 4,
year,
},
format: '{prefix}-{codes}-{sequence}-{year}',
separator: '-',
randomSequence: false,
uniquenessStrategy: 'counter',
storage: 'database',
tableName: 'crimes',
});
await this.prisma.crimes.create({
data: {
id: crimeId,
district_id: record.district_id,
level: crimeRate,
method: record.method || 'kmeans',
month: null,
year: year,
number_of_crime: parseInt(record.number_of_crime),
score: parseInt(record.score),
},
});
}
console.log(`Imported ${records.length} yearly crime records.`);
}
private async importAllYearSummaries() {
console.log('Importing all-year (2020-2024) crime summaries...');
// Check if all-year summaries already exist (records with null month and null year)
const existingAllYearSummaries = await this.prisma.crimes.findFirst({
where: { month: null, year: null },
});
if (existingAllYearSummaries) {
console.log('All-year crime summaries already exist, skipping import.');
return;
}
// Read CSV file
const csvFilePath = path.resolve(
__dirname,
'../data/excels/crimes/district_summary_2020_2024.csv'
);
const fileContent = fs.readFileSync(csvFilePath, { encoding: 'utf-8' });
// Parse CSV
const records = parse(fileContent, {
columns: true,
skip_empty_lines: true,
});
for (const record of records) {
const crimeRate = record.level.toLowerCase() as crime_rates;
const districtId = record.district_id;
const city = await this.prisma.cities.findFirst({
where: {
districts: {
some: {
id: districtId,
},
},
},
});
if (!city) {
console.error(`City not found for district ${districtId}`);
continue;
}
// Create a unique ID for all-year summary data
const crimeId = await generateId({
prefix: 'CR',
segments: {
codes: [city.id],
sequentialDigits: 4,
},
format: '{prefix}-{codes}-{sequence}',
separator: '-',
randomSequence: false,
uniquenessStrategy: 'counter',
storage: 'database',
tableName: 'crimes',
});
await this.prisma.crimes.create({
data: {
id: crimeId,
district_id: districtId,
level: crimeRate,
method: 'kmeans',
month: null,
year: null,
number_of_crime: parseInt(record.crime_total),
score: parseFloat(record.avg_score),
},
});
}
console.log(`Imported ${records.length} all-year crime summaries.`);
}
}
// This allows the file to be executed standalone for testing
if (require.main === module) {
const testSeeder = async () => {
const prisma = new PrismaClient();
const seeder = new CrimesSeeder(prisma);
try {
await seeder.run();
} catch (e) {
console.error('Error during seeding:', e);
process.exit(1);
} finally {
await prisma.$disconnect();
}
};
testSeeder();
}