// This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema // Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? // Try Prisma Accelerate: https://pris.ly/cli/accelerate-init generator client { provider = "prisma-client-js" previewFeatures = ["views"] } datasource db { provider = "postgresql" url = env("DATABASE_URL_DEV") } model Users { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid first_name String last_name String email String @unique phone_number String @unique residence String? role Roles @default(GUEST) employee Employees? @relation("UserEmployee") oauth_sessions OAuthSessions[] @relation("UserOAuthSessions") preferences Preferences? @relation("UserPreferences") @@map("users") } model Employees { id Int @id @default(autoincrement()) user Users @relation("UserEmployee", fields: [user_id], references: [id]) user_id String @unique @db.Uuid supervisor Employees? @relation("EmployeeSupervisor", fields: [supervisor_id], references: [id]) supervisor_id Int? external_payroll_id Int company_code Int first_work_day DateTime @db.Date last_work_day DateTime? @db.Date job_title String? is_supervisor Boolean @default(false) crew Employees[] @relation("EmployeeSupervisor") timesheet Timesheets[] @relation("TimesheetEmployee") leave_request LeaveRequests[] @relation("LeaveRequestEmployee") schedule_presets SchedulePresets[] @relation("SchedulePreset") @@map("employees") } model LeaveRequests { id Int @id @default(autoincrement()) employee Employees @relation("LeaveRequestEmployee", fields: [employee_id], references: [id]) employee_id Int bank_code BankCodes @relation("LeaveRequestBankCodes", fields: [bank_code_id], references: [id]) bank_code_id Int comment String date DateTime @db.Date payable_hours Decimal? @db.Decimal(5, 2) requested_hours Decimal? @db.Decimal(5, 2) approval_status LeaveApprovalStatus @default(PENDING) leave_type LeaveTypes archive LeaveRequestsArchive[] @relation("LeaveRequestToArchive") @@unique([employee_id, leave_type, date], name: "leave_per_employee_date") @@index([employee_id, date]) @@map("leave_requests") } model LeaveRequestsArchive { id Int @id @default(autoincrement()) leave_request LeaveRequests @relation("LeaveRequestToArchive", fields: [leave_request_id], references: [id]) leave_request_id Int archived_at DateTime @default(now()) employee_id Int date DateTime @db.Date payable_hours Decimal? @db.Decimal(5, 2) requested_hours Decimal? @db.Decimal(5, 2) comment String leave_type LeaveTypes approval_status LeaveApprovalStatus @@unique([leave_request_id]) @@index([employee_id, date]) @@map("leave_requests_archive") } //pay-period vue view PayPeriods { pay_year Int pay_period_no Int label String payday DateTime @db.Date period_start DateTime @db.Date period_end DateTime @db.Date @@map("pay_period") } model Timesheets { id Int @id @default(autoincrement()) employee Employees @relation("TimesheetEmployee", fields: [employee_id], references: [id]) employee_id Int start_date DateTime @db.Date is_approved Boolean @default(false) shift Shifts[] @relation("ShiftTimesheet") expense Expenses[] @relation("ExpensesTimesheet") archive TimesheetsArchive[] @relation("TimesheetsToArchive") @@unique([employee_id, start_date], name: "employee_id_start_date") @@map("timesheets") } model TimesheetsArchive { id Int @id @default(autoincrement()) timesheet Timesheets @relation("TimesheetsToArchive", fields: [timesheet_id], references: [id]) timesheet_id Int employee_id Int is_approved Boolean archive_at DateTime @default(now()) @@map("timesheets_archive") } model SchedulePresets { id Int @id @default(autoincrement()) employee Employees @relation("SchedulePreset", fields: [employee_id], references: [id]) employee_id Int name String is_default Boolean @default(false) shifts SchedulePresetShifts[] @relation("SchedulePresetShiftsSchedulePreset") @@unique([employee_id, name], name: "unique_preset_name_per_employee") @@map("schedule_presets") } model SchedulePresetShifts { id Int @id @default(autoincrement()) preset SchedulePresets @relation("SchedulePresetShiftsSchedulePreset",fields: [preset_id], references: [id]) preset_id Int bank_code BankCodes @relation("SchedulePresetShiftsBankCodes",fields: [bank_code_id], references: [id]) bank_code_id Int sort_order Int start_time DateTime @db.Time(0) end_time DateTime @db.Time(0) is_remote Boolean @default(false) week_day Weekday @@unique([preset_id, week_day, sort_order], name: "unique_preset_shift_per_day_order") @@index([preset_id, week_day]) @@map("schedule_preset_shifts") } model Shifts { id Int @id @default(autoincrement()) timesheet Timesheets @relation("ShiftTimesheet", fields: [timesheet_id], references: [id]) timesheet_id Int bank_code BankCodes @relation("ShiftBankCodes", fields: [bank_code_id], references: [id]) bank_code_id Int date DateTime @db.Date start_time DateTime @db.Time(0) end_time DateTime @db.Time(0) is_approved Boolean @default(false) is_remote Boolean @default(false) comment String? archive ShiftsArchive[] @relation("ShiftsToArchive") @@map("shifts") } model ShiftsArchive { id Int @id @default(autoincrement()) shift Shifts @relation("ShiftsToArchive", fields: [shift_id], references: [id]) shift_id Int date DateTime @db.Date start_time DateTime @db.Time(0) end_time DateTime @db.Time(0) timesheet_id Int bank_code_id Int comment String? archive_at DateTime @default(now()) @@map("shifts_archive") } model BankCodes { id Int @id @default(autoincrement()) type String categorie String modifier Float bank_code String shifts Shifts[] @relation("ShiftBankCodes") expenses Expenses[] @relation("ExpenseBankCodes") leaveRequests LeaveRequests[] @relation("LeaveRequestBankCodes") SchedulePresetShifts SchedulePresetShifts[] @relation("SchedulePresetShiftsBankCodes") @@map("bank_codes") } model Expenses { id Int @id @default(autoincrement()) timesheet Timesheets @relation("ExpensesTimesheet", fields: [timesheet_id], references: [id]) timesheet_id Int bank_code BankCodes @relation("ExpenseBankCodes", fields: [bank_code_id], references: [id]) bank_code_id Int attachment_record Attachments? @relation("ExpenseAttachment", fields: [attachment], references: [id], onDelete: SetNull) attachment Int? date DateTime @db.Date amount Decimal? @db.Decimal(12,2) mileage Decimal? @db.Decimal(12,2) comment String supervisor_comment String? is_approved Boolean @default(false) archive ExpensesArchive[] @relation("ExpensesToArchive") @@map("expenses") } model ExpensesArchive { id Int @id @default(autoincrement()) expense Expenses @relation("ExpensesToArchive", fields: [expense_id], references: [id]) expense_id Int attachment_record Attachments? @relation("ExpenseArchiveAttachment", fields: [attachment], references: [id], onDelete: SetNull) attachment Int? timesheet_id Int archived_at DateTime @default(now()) bank_code_id Int date DateTime @db.Date amount Decimal? @db.Decimal(12,2) mileage Decimal? @db.Decimal(12,2) comment String? is_approved Boolean supervisor_comment String? @@map("expenses_archive") } model OAuthSessions { id String @id @default(cuid()) user Users @relation("UserOAuthSessions", fields: [user_id], references: [id]) user_id String @db.Uuid application String access_token String @unique refresh_token String @unique sid String @unique access_token_expiry DateTime refresh_token_expiry DateTime? is_revoked Boolean @default(false) scopes Json @default("[]") created_at DateTime @default(now()) updated_at DateTime? @@map("oauth_sessions") } model Blobs { sha256 String @id @db.Char(64) size Int mime String storage_path String refcount Int @default(0) created_at DateTime @default(now()) attachments Attachments[] @relation("AttachmnentBlob") @@map("blobs") } model Attachments { id Int @id @default(autoincrement()) blob Blobs @relation("AttachmnentBlob",fields: [sha256], references: [sha256], onUpdate: Cascade) sha256 String @db.Char(64) owner_type String //EXPENSES ou éventuellement autre chose comme scan ONU ou photos d'employés, etc owner_id String //expense_id, employee_id, etc original_name String status AttachmentStatus @default(ACTIVE) retention_policy RetentionPolicy created_by String created_at DateTime @default(now()) expenses Expenses[] @relation("ExpenseAttachment") expenses_archive ExpensesArchive[] @relation("ExpenseArchiveAttachment") AttachmentVariants AttachmentVariants[] @relation("attachmentVariantAttachment") @@index([owner_type, owner_id, created_at]) @@index([sha256]) @@map("attachments") } model AttachmentVariants { id Int @id @default(autoincrement()) attachment_id Int attachment Attachments @relation("attachmentVariantAttachment",fields: [attachment_id], references: [id], onDelete: Cascade) variant String path String bytes Int width Int? height Int? created_at DateTime @default(now()) @@unique([attachment_id, variant]) @@map("attachment_variants") } model Preferences { id Int @id @default(autoincrement()) user Users @relation("UserPreferences", fields: [user_id], references: [id]) user_id String @unique @db.Uuid notifications Int @default(0) dark_mode Int @default(0) lang_switch Int @default(0) lefty_mode Int @default(0) employee_list_display Int @default(0) validation_display Int @default(0) timesheet_display Int @default(0) @@map("preferences") } enum AttachmentStatus { ACTIVE DELETED } enum RetentionPolicy { EXPENSE_7Y TICKET_2Y PROFILE_KEEP_LAST3 } enum Roles { ADMIN SUPERVISOR HR ACCOUNTING EMPLOYEE DEALER CUSTOMER GUEST @@map("roles") } enum LeaveTypes { SICK // maladie ou repos VACATION // paye UNPAID // non-paye BEREAVEMENT // deuil de famille PARENTAL // maternite/paternite/adoption LEGAL // obligations legales comme devoir de juree WEDDING // mariage HOLIDAY // férier @@map("leave_types") } enum LeaveApprovalStatus { PENDING APPROVED DENIED CANCELLED ESCALATED @@map("leave_approval_status") } enum Weekday { SUN MON TUE WED THU FRI SAT }