generator client { provider = "prisma-client-js" previewFeatures = ["relationJoins", "views"] output = "./generated/prisma-client" binaryTargets = ["native", "linux-musl-openssl-3.0.x"] } datasource db { provider = "postgresql" url = env("DB_URL") directUrl = env("DB_DIRECT_URL") } model profiles { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid user_id String @unique @db.Uuid avatar String? @db.VarChar(355) username String? @unique @db.VarChar(255) first_name String? @db.VarChar(255) last_name String? @db.VarChar(255) bio String? @db.VarChar address Json? @db.Json birth_date DateTime? nik String? @db.VarChar(100) birth_place String? users users @relation(fields: [user_id], references: [id]) @@index([user_id]) @@index([username]) } model users { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid roles_id String @db.Uuid email String @unique @db.VarChar(255) phone String? @unique @db.VarChar(20) encrypted_password String? @db.VarChar(255) invited_at DateTime? @db.Timestamptz(6) confirmed_at DateTime? @db.Timestamptz(6) email_confirmed_at DateTime? @db.Timestamptz(6) recovery_sent_at DateTime? @db.Timestamptz(6) last_sign_in_at DateTime? @db.Timestamptz(6) app_metadata Json? user_metadata Json? created_at DateTime @default(now()) @db.Timestamptz(6) updated_at DateTime @default(now()) @db.Timestamptz(6) banned_until DateTime? @db.Timestamptz(6) is_anonymous Boolean @default(false) banned_reason String? @db.VarChar(255) is_banned Boolean @default(false) panic_strike Int @default(0) spoofing_attempts Int @default(0) events events[] incident_logs incident_logs[] panic_button_logs panic_button_logs[] profile profiles? sessions sessions[] timelines timelines[] role roles @relation(fields: [roles_id], references: [id]) task task[] sentMessages messages[] @relation("sender_user_messages") receivedMessages messages[] @relation("recipient_user_messages") projects projects[] inbox inbox? @relation() @@index([is_anonymous]) @@index([created_at]) @@index([updated_at]) } model roles { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid name String @unique @db.VarChar(255) description String? created_at DateTime @default(now()) @db.Timestamptz(6) updated_at DateTime @default(now()) @db.Timestamptz(6) officers officers[] permissions permissions[] users users[] } model sessions { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid user_id String @db.Uuid event_id String @db.Uuid status session_status @default(active) created_at DateTime @default(now()) @db.Timestamptz(6) event events @relation(fields: [event_id], references: [id]) user users @relation(fields: [user_id], references: [id]) @@index([user_id], map: "idx_sessions_user_id") @@index([event_id], map: "idx_sessions_event_id") @@index([status], map: "idx_sessions_status") } model events { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid name String @db.VarChar(255) description String? @db.VarChar(255) code String @unique @default(nanoid(10)) created_at DateTime @default(now()) @db.Timestamptz(6) user_id String @db.Uuid users users @relation(fields: [user_id], references: [id]) locations locations[] sessions sessions[] @@index([name], map: "idx_events_name") @@index([code], map: "idx_events_code") @@index([id], map: "idx_events_id") } model resources { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid name String @unique @db.VarChar(255) type String? description String? instance_role String? relations String? attributes Json? created_at DateTime @default(now()) @db.Timestamptz(6) updated_at DateTime @default(now()) @db.Timestamptz(6) permissions permissions[] } model permissions { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid action String resource_id String @db.Uuid role_id String @db.Uuid created_at DateTime @default(now()) @db.Timestamptz(6) updated_at DateTime @updatedAt @db.Timestamptz(6) resource resources @relation(fields: [resource_id], references: [id]) role roles @relation(fields: [role_id], references: [id]) } model cities { id String @id @db.VarChar(20) name String @db.VarChar(100) created_at DateTime? @default(now()) @db.Timestamptz(6) updated_at DateTime? @default(now()) @db.Timestamptz(6) districts districts[] units units[] @@index([name], map: "idx_cities_name") } model crime_incidents { id String @id @db.VarChar(20) crime_id String @db.VarChar(20) crime_category_id String @db.VarChar(20) location_id String @db.Uuid description String victim_count Int status crime_status? @default(open) created_at DateTime? @default(now()) @db.Timestamptz(6) updated_at DateTime? @default(now()) @db.Timestamptz(6) timestamp DateTime @db.Timestamptz(6) crime_categories crime_categories @relation(fields: [crime_category_id], references: [id], onUpdate: NoAction) crimes crimes @relation(fields: [crime_id], references: [id], onDelete: Cascade, onUpdate: NoAction) locations locations @relation(fields: [location_id], references: [id], onDelete: Cascade, onUpdate: NoAction) evidences evidence[] timelines timelines[] witnesses witnesses[] @@index([crime_category_id], map: "idx_crime_incidents_crime_category_id") @@index([timestamp], map: "idx_crime_incidents_date") @@index([location_id], map: "idx_crime_incidents_location_id") @@index([crime_id], map: "idx_crime_incidents_crime_id") @@index([status], map: "idx_crime_incidents_status") } model crime_categories { id String @id @db.VarChar(20) name String @db.VarChar(255) description String created_at DateTime? @default(now()) @db.Timestamptz(6) updated_at DateTime? @default(now()) @db.Timestamptz(6) type String? @db.VarChar(100) crime_incidents crime_incidents[] incident_logs incident_logs[] @@index([name], map: "idx_crime_categories_name") } model crimes { id String @id @db.VarChar(20) district_id String @db.VarChar(20) created_at DateTime? @default(now()) @db.Timestamptz(6) level crime_rates @default(low) method String? @db.VarChar(100) month Int? number_of_crime Int @default(0) score Float @default(0) updated_at DateTime? @default(now()) @db.Timestamptz(6) year Int? source_type String? @db.VarChar(100) crime_cleared Int @default(0) avg_crime Float @default(0) crime_incidents crime_incidents[] districts districts @relation(fields: [district_id], references: [id], onDelete: Cascade, onUpdate: NoAction) @@index([district_id, year, month], map: "idx_crimes_district_id_year_month") @@index([month, year], map: "idx_crimes_month_year") @@index([month], map: "idx_crimes_month") @@index([year], map: "idx_crimes_year") @@index([district_id, month], map: "idx_crimes_district_id_month") } model demographics { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid district_id String @db.VarChar(20) population Int number_of_unemployed Int population_density Float year Int created_at DateTime? @default(now()) @db.Timestamptz(6) updated_at DateTime? @default(now()) @db.Timestamptz(6) districts districts @relation(fields: [district_id], references: [id], onDelete: Cascade, onUpdate: NoAction) @@unique([district_id, year]) @@index([year], map: "idx_demographics_year") } model districts { id String @id @db.VarChar(20) city_id String @db.VarChar(20) name String @db.VarChar(100) created_at DateTime? @default(now()) @db.Timestamptz(6) updated_at DateTime? @default(now()) @db.Timestamptz(6) crimes crimes[] demographics demographics[] district_clusters district_clusters[] cities cities @relation(fields: [city_id], references: [id], onDelete: Cascade, onUpdate: NoAction) geographics geographics[] locations locations[] units units? @@index([city_id], map: "idx_districts_city_id") @@index([name], map: "idx_districts_name") } model locations { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid district_id String @db.VarChar(20) event_id String @db.Uuid address String? @db.VarChar(255) type String? @db.VarChar(100) latitude Float longitude Float land_area Float? polygon Unsupported("geometry")? geometry Unsupported("geometry")? created_at DateTime? @default(now()) @db.Timestamptz(6) updated_at DateTime? @default(now()) @db.Timestamptz(6) location Unsupported("geography") distance_to_unit Float? crime_incidents crime_incidents[] incident_logs incident_logs[] location_logs location_logs[] districts districts @relation(fields: [district_id], references: [id], onDelete: Cascade, onUpdate: NoAction) event events @relation(fields: [event_id], references: [id]) patrol_units patrol_units[] @@index([district_id], map: "idx_locations_district_id") @@index([type], map: "idx_locations_type") @@index([location], map: "idx_locations_geography", type: Gist) @@index([location], map: "idx_locations_location_gist", type: Gist) } model incident_logs { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid user_id String @db.Uuid location_id String @db.Uuid category_id String @db.VarChar(20) description String? source String? @default("manual") time DateTime @db.Timestamptz(6) verified Boolean? @default(false) severity String? @default("low") created_at DateTime? @default(now()) @db.Timestamptz(6) updated_at DateTime? @default(now()) @db.Timestamptz(6) evidence evidence[] crime_categories crime_categories @relation(fields: [category_id], references: [id], map: "fk_incident_category") locations locations @relation(fields: [location_id], references: [id], onDelete: Cascade, onUpdate: NoAction) user users @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction) panic_button_logs panic_button_logs[] timelines timelines[] witnesses witnesses[] @@index([category_id], map: "idx_incident_logs_category_id") @@index([time], map: "idx_incident_logs_time") } model timelines { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid incident_logs_id String? @db.Uuid crime_incidents_id String? @db.VarChar(20) user_id String? @db.Uuid title String? @db.VarChar(255) description String? timestamp DateTime @db.Timestamptz(6) created_at DateTime? @default(now()) @db.Timestamptz(6) updated_at DateTime? @default(now()) @db.Timestamptz(6) crime_incidents crime_incidents? @relation(fields: [crime_incidents_id], references: [id], onDelete: Cascade, onUpdate: NoAction) incident incident_logs? @relation(fields: [incident_logs_id], references: [id], onDelete: Cascade, onUpdate: NoAction) user users? @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction) @@index([incident_logs_id], map: "idx_timelines_incident_logs_id") } model witnesses { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid incident_logs_id String? @db.Uuid crime_incidents_id String? @db.VarChar(20) name String? @db.VarChar(100) contact_info String? @db.VarChar(1000) statement String? created_at DateTime? @default(now()) @db.Timestamptz(6) updated_at DateTime? @default(now()) @db.Timestamptz(6) crime_incidents crime_incidents? @relation(fields: [crime_incidents_id], references: [id], onDelete: Cascade, onUpdate: NoAction) incident incident_logs? @relation(fields: [incident_logs_id], references: [id], onDelete: Cascade, onUpdate: NoAction) @@index([incident_logs_id], map: "idx_witnesses_incident_logs_id") } model evidence { incident_logs_id String? @db.Uuid crime_incidents_id String? @db.VarChar(20) type String @db.VarChar(50) url String status String? @default("pending") @db.VarChar(50) uploaded_at DateTime? @default(now()) @db.Timestamptz(6) updated_at DateTime? @default(now()) @db.Timestamptz(6) caption String? @db.VarChar(255) description String? @db.VarChar(1000) metadata Json? id String @id @unique @db.VarChar(20) crime_incidents crime_incidents? @relation(fields: [crime_incidents_id], references: [id], onDelete: Cascade, onUpdate: NoAction) incident incident_logs? @relation(fields: [incident_logs_id], references: [id], onDelete: Cascade) @@index([incident_logs_id], map: "idx_evidence_incident_logs_id") } model units { code_unit String @id @unique @db.VarChar(20) district_id String? @unique @db.VarChar(20) name String @db.VarChar(100) description String? type unit_type created_at DateTime? @default(now()) @db.Timestamptz(6) updated_at DateTime? @default(now()) @db.Timestamptz(6) address String? land_area Float? latitude Float longitude Float location Unsupported("geography") city_id String @db.VarChar(20) phone String? @db.VarChar(20) officers officers[] patrol_units patrol_units[] unit_statistics unit_statistics[] cities cities @relation(fields: [city_id], references: [id], onDelete: Cascade, onUpdate: NoAction) districts districts? @relation(fields: [district_id], references: [id], onDelete: Cascade, onUpdate: NoAction) @@index([name], map: "idx_units_name") @@index([type], map: "idx_units_type") @@index([code_unit], map: "idx_units_code_unit") @@index([district_id], map: "idx_units_district_id") @@index([location], map: "idx_unit_location", type: Gist) @@index([district_id, location], map: "idx_units_location_district") @@index([location], map: "idx_units_location_gist", type: Gist) } model patrol_units { unit_id String @db.VarChar(20) location_id String @db.Uuid name String @db.VarChar(100) type String @db.VarChar(50) status String @db.VarChar(50) radius Float created_at DateTime @default(now()) @db.Timestamptz(6) id String @id @unique @db.VarChar(100) category patrol_unit_category? @default(group) member_count Int? @default(0) updated_at DateTime? @db.Timestamptz(6) members officers[] location locations @relation(fields: [location_id], references: [id], onDelete: Cascade, onUpdate: NoAction) unit units @relation(fields: [unit_id], references: [code_unit], onDelete: Cascade, onUpdate: NoAction) @@index([unit_id], map: "idx_patrol_units_unit_id") @@index([location_id], map: "idx_patrol_units_location_id") @@index([name], map: "idx_patrol_units_name") @@index([type], map: "idx_patrol_units_type") @@index([status], map: "idx_patrol_units_status") } model officers { unit_id String? @db.VarChar(20) role_id String @db.Uuid nrp String? @unique @db.VarChar(100) name String @db.VarChar(100) rank String? @db.VarChar(100) position String? @db.VarChar(100) phone String? @db.VarChar(20) email String? @db.VarChar(255) avatar String? valid_until DateTime? qr_code String? created_at DateTime? @default(now()) @db.Timestamptz(6) updated_at DateTime? @default(now()) @db.Timestamptz(6) patrol_unit_id String? @db.VarChar(100) id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid banned_reason String? @db.VarChar(255) banned_until DateTime? is_banned Boolean @default(false) panic_strike Int @default(0) spoofing_attempts Int @default(0) place_of_birth String? date_of_birth DateTime? @db.Timestamptz(6) patrol_units patrol_units? @relation(fields: [patrol_unit_id], references: [id], onDelete: Restrict) roles roles @relation(fields: [role_id], references: [id], onDelete: Cascade, onUpdate: NoAction) units units? @relation(fields: [unit_id], references: [code_unit], onDelete: Cascade, onUpdate: NoAction) panic_button_logs panic_button_logs[] sentMessages messages[] @relation("sender_officer_messages") receivedMessages messages[] @relation("recipient_officer_messages") inbox inbox? @relation() @@index([unit_id], map: "idx_officers_unit_id") @@index([nrp], map: "idx_officers_nrp") @@index([name], map: "idx_officers_name") @@index([rank], map: "idx_officers_rank") @@index([position], map: "idx_officers_position") } model unit_statistics { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid crime_total Int crime_cleared Int percentage Float? pending Int? month Int year Int created_at DateTime? @default(now()) @db.Timestamptz(6) updated_at DateTime? @default(now()) @db.Timestamptz(6) code_unit String @db.VarChar(20) units units @relation(fields: [code_unit], references: [code_unit], onDelete: Cascade, onUpdate: NoAction) @@unique([code_unit, month, year]) @@index([year, month], map: "idx_unit_statistics_year_month") } model geographics { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid district_id String @db.VarChar(20) address String? longitude Float latitude Float land_area Float? polygon Unsupported("geometry")? geometry Unsupported("geometry")? created_at DateTime? @default(now()) @db.Timestamptz(6) updated_at DateTime? @default(now()) @db.Timestamptz(6) description String? type String? @db.VarChar(100) location Unsupported("geography") year Int? districts districts @relation(fields: [district_id], references: [id], onDelete: Cascade, onUpdate: NoAction) @@index([district_id], map: "idx_geographics_district_id") @@index([type], map: "idx_geographics_type") @@index([district_id, year], map: "idx_geographics_district_id_year") @@index([location], map: "idx_geographics_location", type: Gist) } model contact_messages { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid name String? @db.VarChar(255) email String? @db.VarChar(255) phone String? @db.VarChar(20) message_type String? @db.VarChar(50) message_type_label String? @db.VarChar(50) message String? status status_messages @default(new) created_at DateTime @default(now()) @db.Timestamptz(6) updated_at DateTime @db.Timestamptz(6) } model messages { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid subject String content String message_type String? message_type_label String? sender_user_id String? @db.Uuid sender_officer_id String? @db.Uuid recipient_user_id String? @db.Uuid recipient_officer_id String? @db.Uuid inbox_id String? @db.Uuid status status_messages @default(new) created_at DateTime @default(now()) updated_at DateTime @updatedAt file_url String? // URL ke file yang di-upload file_type String? // MIME type, misal: application/pdf, video/mp4, dll. file_name String? // Nama file asli is_starred Boolean @default(false) sender_user users? @relation("sender_user_messages", fields: [sender_user_id], references: [id]) sender_officer officers? @relation("sender_officer_messages", fields: [sender_officer_id], references: [id]) recipient_user users? @relation("recipient_user_messages", fields: [recipient_user_id], references: [id]) recipient_officer officers? @relation("recipient_officer_messages", fields: [recipient_officer_id], references: [id]) inbox inbox? @relation(fields: [inbox_id], references: [id]) } model inbox { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid user_id String @unique @db.Uuid officer_id String @unique @db.Uuid unread_count Int @default(0) last_updated DateTime @default(now()) created_at DateTime @default(now()) user users @relation(fields: [user_id], references: [id]) officer officers @relation(fields: [officer_id], references: [id]) messages messages[] } model logs { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid action String @db.VarChar(100) entity String @db.VarChar(100) entity_id String? @db.VarChar(100) changes Json? user_id String? @db.VarChar(100) ip_address String? @db.VarChar(100) user_agent String? @db.VarChar(255) created_at DateTime @default(now()) @db.Timestamptz(6) @@index([entity]) @@index([user_id]) } model panic_button_logs { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid user_id String @db.Uuid officer_id String? @db.Uuid incident_logs_id String @db.Uuid timestamp DateTime @db.Timestamptz(6) incidents incident_logs @relation(fields: [incident_logs_id], references: [id], onDelete: Cascade, onUpdate: NoAction) officers officers? @relation(fields: [officer_id], references: [id], onDelete: Cascade, onUpdate: NoAction) users users @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction) @@index([user_id], map: "idx_panic_buttons_user_id") } model location_logs { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid location_id String @db.Uuid latitude Float longitude Float location_geography Unsupported("geography") timestamp DateTime @db.Timestamptz(6) description String? @db.VarChar(255) created_at DateTime @default(now()) @db.Timestamptz(6) updated_at DateTime @default(now()) @db.Timestamptz(6) location locations @relation(fields: [location_id], references: [id], onDelete: Cascade) @@index([timestamp], map: "idx_location_logs_timestamp") @@index([location_id], map: "idx_location_logs_location_id") } model district_clusters { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid district_id String @db.VarChar(20) year Int month Int? risk_level crime_rates @default(low) total_crimes Int @default(0) population_density Float @default(0) unemployment_rate Float @default(0) crime_score Float @default(0) density_score Float @default(0) unemployment_score Float @default(0) cluster_score Float @default(0) centroid_features Json? member_count Int @default(1) last_update_type String @default("batch") @db.VarChar(20) update_count Int @default(0) needs_recompute Boolean @default(false) incidents_data Json? created_at DateTime @default(now()) @db.Timestamptz(6) updated_at DateTime @default(now()) @db.Timestamptz(6) district districts @relation(fields: [district_id], references: [id], onDelete: Cascade) @@unique([district_id, year, month]) @@index([year, month]) @@index([risk_level]) @@index([needs_recompute]) @@index([last_update_type]) } model cluster_updates { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid district_id String @db.VarChar(20) update_type String @db.VarChar(20) old_value Json? new_value Json? processed Boolean @default(false) timestamp DateTime @default(now()) @db.Timestamptz(6) @@index([processed]) @@index([timestamp]) @@index([district_id]) } model task { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid user_id String @db.Uuid code String @unique @db.VarChar(128) title String? @db.VarChar(128) status task_status @default(todo) label task_label @default(report) priority task_priority @default(low) estimated_hours Float @default(0) archived Boolean @default(false) created_at DateTime @default(now()) @db.Timestamptz(6) updated_at DateTime @default(now()) @updatedAt user users @relation(fields: [user_id], references: [id], onDelete: Cascade) @@index([user_id], map: "idx_task_user_id") @@index([status], map: "idx_task_status") @@index([priority], map: "idx_task_priority") @@index([archived], map: "idx_task_archived") @@index([created_at], map: "idx_task_created_at") @@index([updated_at], map: "idx_task_updated_at") @@index([title], map: "idx_task_title") @@index([user_id, status], map: "idx_task_user_id_status") // Indeks komposit } model projects { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid name String description String? user_id String @db.Uuid created_at DateTime @default(now()) @db.Timestamptz(6) updated_at DateTime @updatedAt users users @relation(fields: [user_id], references: [id]) datasets datasets[] analyses analyses[] } model datasets { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid project_id String @db.Uuid filename String original_name String file_size Int columns Json row_count Int metadata Json? created_at DateTime @default(now()) @db.Timestamptz(6) projects projects @relation(fields: [project_id], references: [id]) analyses analyses[] } model analyses { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid project_id String @db.Uuid dataset_id String @db.Uuid name String config Json results Json? status String @default("pending") created_at DateTime @default(now()) @db.Timestamptz(6) updated_at DateTime @updatedAt projects projects @relation(fields: [project_id], references: [id]) datasets datasets @relation(fields: [dataset_id], references: [id]) clusters clusters[] } model clusters { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid analysis_id String @db.Uuid cluster_id Int center_data Json point_count Int characteristics Json? analyses analyses @relation(fields: [analysis_id], references: [id]) } model analysis_templates { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid name String description String? config Json user_id String @db.Uuid is_public Boolean @default(false) created_at DateTime @default(now()) @db.Timestamptz(6) } enum task_status { todo in_progress done canceled } enum task_label { report investigation patrol evidence documentation coordination follow_up prevention other } enum task_priority { low medium high } enum patrol_unit_category { individual group } enum session_status { active completed } enum status_messages { new read replied closed } enum crime_rates { low medium high critical } enum crime_status { open closed under_investigation resolved unresolved } enum unit_type { polda polsek polres other }