This commit is contained in:
yotakii
2026-03-05 11:57:04 +03:00
58 changed files with 5302 additions and 1608 deletions

View File

@@ -69,10 +69,59 @@ model User {
assignedTasks Task[]
projectMembers ProjectMember[]
campaigns Campaign[]
userRoles UserRole[]
@@map("users")
}
// Optional roles - user can belong to multiple permission groups (Phase 3 multi-group)
model Role {
id String @id @default(uuid())
name String @unique
nameAr String?
description String?
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
permissions RolePermission[]
userRoles UserRole[]
@@map("roles")
}
model RolePermission {
id String @id @default(uuid())
roleId String
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
module String
resource String
actions Json // ["read", "create", "update", "delete", ...]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([roleId, module, resource])
@@map("role_permissions")
}
model UserRole {
id String @id @default(uuid())
userId String
roleId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
@@unique([userId, roleId])
@@index([userId])
@@index([roleId])
@@map("user_roles")
}
model Employee {
id String @id @default(uuid())
uniqueEmployeeId String @unique // رقم الموظف الموحد
@@ -129,6 +178,9 @@ model Employee {
// Documents
documents Json? // Array of document references
// ZK Tico / Attendance device - maps to employee pin on device
attendancePin String? @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@ -143,6 +195,10 @@ model Employee {
disciplinaryActions DisciplinaryAction[]
allowances Allowance[]
commissions Commission[]
loans Loan[]
purchaseRequests PurchaseRequest[]
leaveEntitlements LeaveEntitlement[]
employeeContracts EmployeeContract[]
@@index([departmentId])
@@index([positionId])
@@ -221,12 +277,18 @@ model Attendance {
status String // PRESENT, ABSENT, LATE, HALF_DAY, etc.
notes String?
// ZK Tico / External device sync
sourceDeviceId String?
externalId String?
rawData Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([employeeId, date])
@@index([employeeId])
@@index([date])
@@index([sourceDeviceId])
@@map("attendances")
}
@@ -369,6 +431,115 @@ model DisciplinaryAction {
@@map("disciplinary_actions")
}
model Loan {
id String @id @default(uuid())
employeeId String
employee Employee @relation(fields: [employeeId], references: [id])
loanNumber String @unique
type String // SALARY_ADVANCE, EQUIPMENT, PERSONAL, etc.
amount Decimal @db.Decimal(12, 2)
currency String @default("SAR")
installments Int @default(1)
monthlyAmount Decimal? @db.Decimal(12, 2)
reason String?
status String @default("PENDING") // PENDING, APPROVED, REJECTED, ACTIVE, PAID_OFF
approvedBy String?
approvedAt DateTime?
rejectedReason String?
startDate DateTime? @db.Date
endDate DateTime? @db.Date
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
installmentsList LoanInstallment[]
@@index([employeeId])
@@index([status])
@@map("loans")
}
model LoanInstallment {
id String @id @default(uuid())
loanId String
loan Loan @relation(fields: [loanId], references: [id], onDelete: Cascade)
installmentNumber Int
dueDate DateTime @db.Date
amount Decimal @db.Decimal(12, 2)
paidDate DateTime? @db.Date
status String @default("PENDING") // PENDING, PAID, OVERDUE
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([loanId, installmentNumber])
@@index([loanId])
@@map("loan_installments")
}
model PurchaseRequest {
id String @id @default(uuid())
requestNumber String @unique
employeeId String
employee Employee @relation(fields: [employeeId], references: [id])
items Json // Array of { description, quantity, estimatedPrice, etc. }
totalAmount Decimal? @db.Decimal(12, 2)
reason String?
priority String @default("NORMAL") // LOW, NORMAL, HIGH, URGENT
status String @default("PENDING") // PENDING, APPROVED, REJECTED, ORDERED
approvedBy String?
approvedAt DateTime?
rejectedReason String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([employeeId])
@@index([status])
@@map("purchase_requests")
}
model LeaveEntitlement {
id String @id @default(uuid())
employeeId String
employee Employee @relation(fields: [employeeId], references: [id])
year Int
leaveType String // ANNUAL, SICK, EMERGENCY, etc.
totalDays Int @default(0)
usedDays Int @default(0)
carriedOver Int @default(0)
notes String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([employeeId, year, leaveType])
@@index([employeeId])
@@map("leave_entitlements")
}
model EmployeeContract {
id String @id @default(uuid())
employeeId String
employee Employee @relation(fields: [employeeId], references: [id])
contractNumber String @unique
type String // FIXED, UNLIMITED, PROBATION, etc.
startDate DateTime @db.Date
endDate DateTime? @db.Date
salary Decimal @db.Decimal(12, 2)
currency String @default("SAR")
documentUrl String?
status String @default("ACTIVE") // DRAFT, ACTIVE, EXPIRED, TERMINATED
notes String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([employeeId])
@@index([status])
@@map("employee_contracts")
}
// ============================================
// MODULE 1: CONTACT MANAGEMENT
// ============================================