625 lines
15 KiB
Plaintext
625 lines
15 KiB
Plaintext
generator client {
|
|
provider = "prisma-client-js"
|
|
output = "../generated/prisma"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
model User {
|
|
id String @id @default(cuid())
|
|
email String @unique
|
|
name String?
|
|
emailVerified Boolean?
|
|
image String?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
role String? @default("user")
|
|
accounts Account[]
|
|
sessions Session[]
|
|
apiKeys ApiKey[]
|
|
|
|
// Relations
|
|
discussions Discussion[]
|
|
events Event[]
|
|
complaints Complaint[] @relation("ComplaintReporter")
|
|
assignedComplaints Complaint[] @relation("ComplaintAssignee")
|
|
complaintUpdates ComplaintUpdate[]
|
|
serviceLetters ServiceLetter[]
|
|
innovationIdeas InnovationIdea[] @relation("IdeaReviewer")
|
|
healthRecords HealthRecord[]
|
|
populationDynamics PopulationDynamic[]
|
|
budgetTransactions BudgetTransaction[]
|
|
posyandus Posyandu[]
|
|
securityReports SecurityReport[]
|
|
|
|
@@map("user")
|
|
}
|
|
|
|
// --- KATEGORI 1: KINERJA DIVISI & AKTIVITAS ---
|
|
|
|
model Division {
|
|
id String @id @default(cuid())
|
|
externalId String? @unique // ID asli dari server NOC
|
|
villageId String? @default("desa1") // ID Desa dari sistem NOC
|
|
name String @unique
|
|
description String?
|
|
color String @default("#1E3A5F")
|
|
isActive Boolean @default(true)
|
|
externalActivityCount Int @default(0) // Total kegiatan dari sistem NOC (misal: 47)
|
|
lastSyncedAt DateTime? // Terakhir kali sinkronisasi dilakukan
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
activities Activity[]
|
|
documents Document[]
|
|
discussions Discussion[]
|
|
divisionMetrics DivisionMetric[]
|
|
|
|
@@map("division")
|
|
}
|
|
|
|
model Activity {
|
|
id String @id @default(cuid())
|
|
externalId String? @unique // ID asli dari server NOC
|
|
villageId String? @default("desa1")
|
|
title String
|
|
description String?
|
|
divisionId String
|
|
startDate DateTime?
|
|
endDate DateTime?
|
|
dueDate DateTime?
|
|
progress Int @default(0) // 0-100
|
|
status ActivityStatus @default(BERJALAN)
|
|
priority Priority @default(SEDANG)
|
|
assignedTo String? // JSON array of user IDs
|
|
completedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
division Division @relation(fields: [divisionId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([divisionId])
|
|
@@index([status])
|
|
@@map("activity")
|
|
}
|
|
|
|
model Document {
|
|
id String @id @default(cuid())
|
|
externalId String? @unique // ID asli dari server NOC
|
|
villageId String? @default("desa1")
|
|
title String
|
|
category DocumentCategory
|
|
type String // "Gambar", "Dokumen", "PDF", etc
|
|
fileUrl String
|
|
fileSize Int? // in bytes
|
|
divisionId String?
|
|
uploadedBy String
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
division Division? @relation(fields: [divisionId], references: [id], onDelete: SetNull)
|
|
|
|
@@index([category])
|
|
@@index([divisionId])
|
|
@@map("document")
|
|
}
|
|
|
|
model Discussion {
|
|
id String @id @default(cuid())
|
|
externalId String? @unique // ID asli dari server NOC
|
|
villageId String? @default("desa1")
|
|
message String
|
|
senderId String
|
|
parentId String? // For threaded discussions
|
|
divisionId String?
|
|
isResolved Boolean @default(false)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
sender User @relation(fields: [senderId], references: [id], onDelete: Cascade)
|
|
parent Discussion? @relation("DiscussionThread", fields: [parentId], references: [id], onDelete: SetNull)
|
|
replies Discussion[] @relation("DiscussionThread")
|
|
division Division? @relation(fields: [divisionId], references: [id], onDelete: SetNull)
|
|
|
|
@@index([divisionId])
|
|
@@index([createdAt])
|
|
@@map("discussion")
|
|
}
|
|
|
|
model Event {
|
|
id String @id @default(cuid())
|
|
externalId String? @unique // ID asli dari server NOC
|
|
villageId String? @default("desa1")
|
|
title String
|
|
description String?
|
|
eventType EventType
|
|
startDate DateTime
|
|
endDate DateTime?
|
|
location String?
|
|
isAllDay Boolean @default(false)
|
|
isRecurring Boolean @default(false)
|
|
createdBy String
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
creator User @relation(fields: [createdBy], references: [id], onDelete: Cascade)
|
|
|
|
@@index([startDate])
|
|
@@index([eventType])
|
|
@@map("event")
|
|
}
|
|
|
|
model DivisionMetric {
|
|
id String @id @default(cuid())
|
|
divisionId String
|
|
period String // "2025-Q1", "2025-01"
|
|
activityCount Int @default(0)
|
|
completionRate Float @default(0)
|
|
avgProgress Float @default(0)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
division Division @relation(fields: [divisionId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([divisionId, period])
|
|
@@map("division_metric")
|
|
}
|
|
|
|
// --- KATEGORI 2: PENGADUAN & LAYANAN PUBLIK ---
|
|
|
|
model Complaint {
|
|
id String @id @default(cuid())
|
|
complaintNumber String @unique // Auto-generated: COMPLAINT-YYYYMMDD-XXX
|
|
title String
|
|
description String
|
|
category ComplaintCategory
|
|
status ComplaintStatus @default(BARU)
|
|
priority Priority @default(SEDANG)
|
|
|
|
reporterId String?
|
|
reporterPhone String?
|
|
reporterEmail String?
|
|
isAnonymous Boolean @default(false)
|
|
|
|
assignedTo String? // User ID
|
|
resolvedBy String? // User ID
|
|
resolvedAt DateTime?
|
|
|
|
location String?
|
|
imageUrl String[] // Array of image URLs
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
reporter User? @relation("ComplaintReporter", fields: [reporterId], references: [id], onDelete: SetNull)
|
|
assignee User? @relation("ComplaintAssignee", fields: [assignedTo], references: [id], onDelete: SetNull)
|
|
|
|
complaintUpdates ComplaintUpdate[]
|
|
|
|
@@index([status])
|
|
@@index([category])
|
|
@@index([createdAt])
|
|
@@map("complaint")
|
|
}
|
|
|
|
model ComplaintUpdate {
|
|
id String @id @default(cuid())
|
|
complaintId String
|
|
message String
|
|
status ComplaintStatus?
|
|
updatedBy String
|
|
createdAt DateTime @default(now())
|
|
|
|
complaint Complaint @relation(fields: [complaintId], references: [id], onDelete: Cascade)
|
|
updater User @relation(fields: [updatedBy], references: [id], onDelete: Cascade)
|
|
|
|
@@index([complaintId])
|
|
@@map("complaint_update")
|
|
}
|
|
|
|
model ServiceLetter {
|
|
id String @id @default(cuid())
|
|
letterNumber String @unique
|
|
letterType LetterType
|
|
applicantName String
|
|
applicantNik String
|
|
applicantAddress String
|
|
purpose String?
|
|
status ServiceStatus @default(BARU)
|
|
|
|
processedBy String?
|
|
completedAt DateTime?
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
processor User? @relation(fields: [processedBy], references: [id], onDelete: SetNull)
|
|
|
|
@@index([letterType])
|
|
@@index([status])
|
|
@@index([createdAt])
|
|
@@map("service_letter")
|
|
}
|
|
|
|
model InnovationIdea {
|
|
id String @id @default(cuid())
|
|
title String
|
|
description String
|
|
category String // "Teknologi", "Ekonomi", "Kesehatan", "Pendidikan"
|
|
submitterName String
|
|
submitterContact String?
|
|
status IdeaStatus @default(BARU)
|
|
reviewedBy String?
|
|
reviewedAt DateTime?
|
|
notes String?
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
reviewer User? @relation("IdeaReviewer", fields: [reviewedBy], references: [id], onDelete: SetNull)
|
|
|
|
@@index([category])
|
|
@@index([status])
|
|
@@map("innovation_idea")
|
|
}
|
|
|
|
// --- KATEGORI 3: DEMOGRAFI & KEPENDUDUKAN ---
|
|
|
|
model Resident {
|
|
id String @id @default(cuid())
|
|
nik String @unique
|
|
kk String
|
|
name String
|
|
birthDate DateTime
|
|
birthPlace String
|
|
gender Gender
|
|
religion Religion
|
|
maritalStatus MaritalStatus @default(BELUM_KAWIN)
|
|
education EducationLevel?
|
|
occupation String?
|
|
|
|
banjarId String
|
|
rt String
|
|
rw String
|
|
address String
|
|
|
|
isHeadOfHousehold Boolean @default(false)
|
|
isPoor Boolean @default(false)
|
|
isStunting Boolean @default(false)
|
|
|
|
deathDate DateTime?
|
|
moveInDate DateTime?
|
|
moveOutDate DateTime?
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
banjar Banjar @relation(fields: [banjarId], references: [id], onDelete: Cascade)
|
|
|
|
healthRecords HealthRecord[]
|
|
employmentRecords EmploymentRecord[]
|
|
|
|
@@index([banjarId])
|
|
@@index([religion])
|
|
@@index([occupation])
|
|
@@map("resident")
|
|
}
|
|
|
|
model Banjar {
|
|
id String @id @default(cuid())
|
|
name String @unique
|
|
code String @unique
|
|
description String?
|
|
|
|
totalPopulation Int @default(0)
|
|
totalKK Int @default(0)
|
|
totalPoor Int @default(0)
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
residents Resident[]
|
|
umkms Umkm[]
|
|
|
|
@@map("banjar")
|
|
}
|
|
|
|
// --- KATEGORI 4: KEUANGAN & ANGGARAN ---
|
|
|
|
model Budget {
|
|
id String @id @default(cuid())
|
|
category String // "Belanja", "Pangan", "Pembiayaan", "Pendapatan"
|
|
amount Float @default(0)
|
|
percentage Float @default(0)
|
|
color String @default("#3B82F6")
|
|
fiscalYear Int @default(2025)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@unique([category, fiscalYear])
|
|
@@map("budget")
|
|
}
|
|
|
|
// --- KATEGORI 5: METRIK DASHBOARD & SDGS ---
|
|
|
|
model SdgsScore {
|
|
id String @id @default(cuid())
|
|
title String @unique
|
|
score Float @default(0)
|
|
image String? // filename in public folder
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@map("sdgs_score")
|
|
}
|
|
|
|
model SatisfactionRating {
|
|
id String @id @default(cuid())
|
|
category String @unique // "Sangat Puas", "Puas", "Cukup", "Kurang"
|
|
value Int @default(0)
|
|
color String
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@map("satisfaction_rating")
|
|
}
|
|
|
|
// --- STUBS FOR PHASE 2+ (To maintain relations) ---
|
|
|
|
model HealthRecord {
|
|
id String @id @default(cuid())
|
|
residentId String
|
|
resident Resident @relation(fields: [residentId], references: [id])
|
|
recordedBy String
|
|
recorder User @relation(fields: [recordedBy], references: [id])
|
|
type String // "Pemeriksaan", "Imunisasi", "Ibu Hamil"
|
|
notes String?
|
|
createdAt DateTime @default(now())
|
|
}
|
|
|
|
model EmploymentRecord {
|
|
id String @id @default(cuid())
|
|
residentId String
|
|
resident Resident @relation(fields: [residentId], references: [id])
|
|
companyName String
|
|
position String
|
|
startDate DateTime
|
|
endDate DateTime?
|
|
isActive Boolean @default(true)
|
|
createdAt DateTime @default(now())
|
|
}
|
|
|
|
model PopulationDynamic {
|
|
id String @id @default(cuid())
|
|
documentedBy String
|
|
documentor User @relation(fields: [documentedBy], references: [id])
|
|
type String // "KELAHIRAN", "KEMATIAN", "KEDATANGAN", "KEPERGIAN"
|
|
residentName String
|
|
eventDate DateTime
|
|
description String?
|
|
createdAt DateTime @default(now())
|
|
}
|
|
|
|
model BudgetTransaction {
|
|
id String @id @default(cuid())
|
|
createdBy String
|
|
creator User @relation(fields: [createdBy], references: [id])
|
|
transactionNumber String @unique
|
|
type String // "PENGELUARAN", "PENDAPATAN"
|
|
category String
|
|
amount Float
|
|
description String?
|
|
date DateTime
|
|
createdAt DateTime @default(now())
|
|
}
|
|
|
|
model Umkm {
|
|
id String @id @default(cuid())
|
|
banjarId String?
|
|
banjar Banjar? @relation(fields: [banjarId], references: [id])
|
|
name String
|
|
owner String
|
|
productType String?
|
|
description String?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model Posyandu {
|
|
id String @id @default(cuid())
|
|
coordinatorId String?
|
|
coordinator User? @relation(fields: [coordinatorId], references: [id])
|
|
name String
|
|
location String
|
|
schedule String
|
|
type String // "Ibu dan Anak", "Lansia", etc.
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model SecurityReport {
|
|
id String @id @default(cuid())
|
|
assignedTo String?
|
|
assignee User? @relation(fields: [assignedTo], references: [id])
|
|
reportNumber String @unique
|
|
title String
|
|
description String
|
|
location String?
|
|
reportedBy String
|
|
status String @default("BARU") // BARU, DIPROSES, SELESAI
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
// --- ENUMS ---
|
|
|
|
enum ActivityStatus {
|
|
BERJALAN
|
|
SELESAI
|
|
TERTUNDA
|
|
DIBATALKAN
|
|
}
|
|
|
|
enum Priority {
|
|
RENDAH
|
|
SEDANG
|
|
TINGGI
|
|
DARURAT
|
|
}
|
|
|
|
enum DocumentCategory {
|
|
SURAT_KEPUTUSAN
|
|
DOKUMENTASI
|
|
LAPORAN_KEUANGAN
|
|
NOTULENSI_RAPAT
|
|
UMUM
|
|
}
|
|
|
|
enum EventType {
|
|
RAPAT
|
|
KEGIATAN
|
|
UPACARA
|
|
SOSIAL
|
|
BUDAYA
|
|
LAINNYA
|
|
}
|
|
|
|
enum ComplaintCategory {
|
|
KETERTIBAN_UMUM
|
|
PELAYANAN_KESEHATAN
|
|
INFRASTRUKTUR
|
|
ADMINISTRASI
|
|
KEAMANAN
|
|
LAINNYA
|
|
}
|
|
|
|
enum ComplaintStatus {
|
|
BARU
|
|
DIPROSES
|
|
SELESAI
|
|
DITOLAK
|
|
}
|
|
|
|
enum LetterType {
|
|
KTP
|
|
KK
|
|
DOMISILI
|
|
USAHA
|
|
KETERANGAN_TIDAK_MAMPU
|
|
SURAT_PENGANTAR
|
|
LAINNYA
|
|
}
|
|
|
|
enum ServiceStatus {
|
|
BARU
|
|
DIPROSES
|
|
SELESAI
|
|
DIAMBIL
|
|
}
|
|
|
|
enum IdeaStatus {
|
|
BARU
|
|
DIKAJI
|
|
DISETUJUI
|
|
DITOLAK
|
|
DIIMPLEMENTASI
|
|
}
|
|
|
|
enum Gender {
|
|
LAKI_LAKI
|
|
PEREMPUAN
|
|
}
|
|
|
|
enum Religion {
|
|
HINDU
|
|
ISLAM
|
|
KRISTEN
|
|
KATOLIK
|
|
BUDDHA
|
|
KONGHUCU
|
|
LAINNYA
|
|
}
|
|
|
|
enum MaritalStatus {
|
|
BELUM_KAWIN
|
|
KAWIN
|
|
CERAI_HIDUP
|
|
CERAI_MATI
|
|
}
|
|
|
|
enum EducationLevel {
|
|
TIDAK_SEKOLAH
|
|
SD
|
|
SMP
|
|
SMA
|
|
D3
|
|
S1
|
|
S2
|
|
S3
|
|
}
|
|
|
|
model Session {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
expiresAt DateTime
|
|
token String @unique
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
ipAddress String?
|
|
userAgent String?
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([userId])
|
|
@@map("session")
|
|
}
|
|
|
|
model Account {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
accountId String
|
|
providerId String
|
|
accessToken String?
|
|
refreshToken String?
|
|
expiresAt DateTime?
|
|
password String?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
idToken String?
|
|
accessTokenExpiresAt DateTime?
|
|
refreshTokenExpiresAt DateTime?
|
|
scope String?
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([userId])
|
|
@@map("account")
|
|
}
|
|
|
|
model Verification {
|
|
id String @id @default(cuid())
|
|
identifier String
|
|
value String
|
|
expiresAt DateTime
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@index([identifier])
|
|
@@map("verification")
|
|
}
|
|
|
|
model ApiKey {
|
|
id String @id @default(cuid())
|
|
name String
|
|
key String @unique
|
|
userId String
|
|
isActive Boolean @default(true)
|
|
expiresAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([userId])
|
|
@@map("api_key")
|
|
}
|