generator client {
  provider        = "prisma-client"
  output          = "generated/prisma/client/postgres"
  previewFeatures = ["views"]
}

datasource db {
  provider = "postgresql"
}

model Users {
  id                 String            @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  first_name         String
  last_name          String
  email              String            @unique
  phone_number       String
  residence          String?
  role               Roles             @default(EMPLOYEE)
  notifications      Notifications?    @relation("UserNotification")
  employee           Employees?        @relation("UserEmployee")
  oauth_sessions     OAuthSessions[]   @relation("UserOAuthSessions")
  preferences        Preferences?      @relation("UserPreferences")
  user_module_access userModuleAccess? @relation("UserModuleAccess")

  @@map("users")
}

model Notifications {
  id              Int       @id @default(autoincrement())
  user_id         String    @unique @db.Uuid
  affected_module Modules
  subject         String
  description     String
  metadata        Json      @db.JsonB
  created_at      DateTime  @default(now())
  viewed_at       DateTime?
  user            Users     @relation("UserNotification", fields: [user_id], references: [id])

  @@map("notifications")
}

model userModuleAccess {
  id                  Int     @id @default(autoincrement())
  user_id             String  @unique @db.Uuid
  timesheets          Boolean @default(true)
  timesheets_approval Boolean @default(false)
  employee_list       Boolean @default(true)
  employee_management Boolean @default(false)
  personal_profile    Boolean @default(true)
  dashboard           Boolean @default(true)
  chatbot             Boolean @default(false)
  ticket              Boolean @default(false)
  ticket_management   Boolean @default(false)
  user                Users   @relation("UserModuleAccess", fields: [user_id], references: [id])

  @@map("user_module_access")
}

model Employees {
  id                   Int                  @id @default(autoincrement())
  user_id              String               @unique @db.Uuid
  external_payroll_id  Int
  company_code         Int
  daily_expected_hours Int                  @default(24)
  first_work_day       DateTime             @db.Date
  last_work_day        DateTime?            @db.Date
  supervisor_id        Int?
  job_title            String?
  is_supervisor        Boolean              @default(false)
  applicable_overtime  ApplicableOvertime[] @default([WEEKLY])
  schedule_preset_id   Int?
  schedule_preset      SchedulePresets?     @relation("EmployeesSchedulePreset", fields: [schedule_preset_id], references: [id])
  supervisor           Employees?           @relation("EmployeeSupervisor", fields: [supervisor_id], references: [id])
  crew                 Employees[]          @relation("EmployeeSupervisor")
  user                 Users                @relation("UserEmployee", fields: [user_id], references: [id])
  leave_request        LeaveRequests[]      @relation("LeaveRequestEmployee")
  timesheet            Timesheets[]         @relation("TimesheetEmployee")
  paid_time_off        PaidTimeOff?         @relation("EmployeePaidTimeOff")

  @@map("employees")
}

model LeaveRequests {
  id              Int                   @id @default(autoincrement())
  employee_id     Int
  leave_type      LeaveTypes
  comment         String
  approval_status LeaveApprovalStatus   @default(PENDING)
  bank_code_id    Int
  payable_hours   Decimal?              @db.Decimal(5, 2)
  requested_hours Decimal?              @db.Decimal(5, 2)
  dates           DateTime[]            @db.Date
  bank_code       BankCodes             @relation("LeaveRequestBankCodes", fields: [bank_code_id], references: [id])
  employee        Employees             @relation("LeaveRequestEmployee", fields: [employee_id], references: [id])
  archive         LeaveRequestsArchive? @relation("LeaveRequestToArchive")

  @@unique([employee_id, leave_type, dates], name: "leave_per_employee_date")
  @@index([employee_id, dates])
  @@map("leave_requests")
}

model LeaveRequestsArchive {
  id               Int                 @id @default(autoincrement())
  leave_request_id Int                 @unique
  archived_at      DateTime            @default(now())
  employee_id      Int
  leave_type       LeaveTypes
  comment          String
  approval_status  LeaveApprovalStatus
  date             DateTime            @db.Date
  payable_hours    Decimal?            @db.Decimal(5, 2)
  requested_hours  Decimal?            @db.Decimal(5, 2)
  leave_request    LeaveRequests       @relation("LeaveRequestToArchive", fields: [leave_request_id], references: [id])

  @@index([employee_id, date])
  @@map("leave_requests_archive")
}

model Timesheets {
  id          Int                 @id @default(autoincrement())
  employee_id Int
  is_approved Boolean             @default(false)
  start_date  DateTime            @db.Date
  // hours_to_bank Decimal?            @db.Decimal(5, 2) //will need to be implemented in the future
  expense     Expenses[]          @relation("ExpensesTimesheet")
  shift       Shifts[]            @relation("ShiftTimesheet")
  employee    Employees           @relation("TimesheetEmployee", fields: [employee_id], references: [id])
  archive     TimesheetsArchive[] @relation("TimesheetsToArchive")

  // @@unique([employee_id, start_date], name: "employee_id_start_date")
  @@map("timesheets")
}

model TimesheetsArchive {
  id           Int        @id @default(autoincrement())
  timesheet_id Int
  archive_at   DateTime   @default(now())
  employee_id  Int
  is_approved  Boolean
  timesheet    Timesheets @relation("TimesheetsToArchive", fields: [timesheet_id], references: [id])

  @@map("timesheets_archive")
}

model SchedulePresets {
  id         Int                    @id @default(autoincrement())
  name       String
  is_default Boolean                @default(false)
  employees  Employees[]            @relation("EmployeesSchedulePreset")
  shifts     SchedulePresetShifts[] @relation("SchedulePresetShiftsSchedulePreset")

  @@map("schedule_presets")
}

model SchedulePresetShifts {
  id           Int @id @default(autoincrement())
  preset_id    Int
  bank_code_id Int

  start_time DateTime        @db.Time(0)
  end_time   DateTime        @db.Time(0)
  is_remote  Boolean         @default(false)
  week_day   Weekday
  bank_code  BankCodes       @relation("SchedulePresetShiftsBankCodes", fields: [bank_code_id], references: [id])
  preset     SchedulePresets @relation("SchedulePresetShiftsSchedulePreset", fields: [preset_id], references: [id])

  @@index([preset_id, week_day])
  @@map("schedule_preset_shifts")
}

model Shifts {
  id           Int             @id @default(autoincrement())
  timesheet_id Int
  date         DateTime        @db.Date
  start_time   DateTime        @db.Time(0)
  end_time     DateTime        @db.Time(0)
  bank_code_id Int
  is_approved  Boolean         @default(false)
  is_remote    Boolean         @default(false)
  comment      String?
  bank_code    BankCodes       @relation("ShiftBankCodes", fields: [bank_code_id], references: [id])
  timesheet    Timesheets      @relation("ShiftTimesheet", fields: [timesheet_id], references: [id])
  archive      ShiftsArchive[] @relation("ShiftsToArchive")

  // @@unique([timesheet_id, date, start_time], name: "unique_ts_id_date_start_time")
  @@map("shifts")
}

model ShiftsArchive {
  id           Int      @id @default(autoincrement())
  shift_id     Int
  archive_at   DateTime @default(now())
  timesheet_id Int
  date         DateTime @db.Date
  start_time   DateTime @db.Time(0)
  end_time     DateTime @db.Time(0)
  bank_code_id Int
  comment      String?
  shift        Shifts   @relation("ShiftsToArchive", fields: [shift_id], references: [id])

  @@map("shifts_archive")
}

model BankCodes {
  id                   Int                    @id @default(autoincrement())
  type                 String
  categorie            String
  modifier             Float
  bank_code            String
  expenses             Expenses[]             @relation("ExpenseBankCodes")
  leaveRequests        LeaveRequests[]        @relation("LeaveRequestBankCodes")
  SchedulePresetShifts SchedulePresetShifts[] @relation("SchedulePresetShiftsBankCodes")
  shifts               Shifts[]               @relation("ShiftBankCodes")

  @@map("bank_codes")
}

model Expenses {
  id                 Int               @id @default(autoincrement())
  timesheet_id       Int
  date               DateTime          @db.Date
  amount             Decimal?          @db.Decimal(12, 2)
  is_approved        Boolean           @default(false)
  supervisor_comment String?
  bank_code_id       Int
  comment            String
  attachment_key     String?
  attachment_name    String?
  mileage            Decimal?          @db.Decimal(12, 2)
  bank_code          BankCodes         @relation("ExpenseBankCodes", fields: [bank_code_id], references: [id])
  timesheet          Timesheets        @relation("ExpensesTimesheet", fields: [timesheet_id], references: [id])
  archive            ExpensesArchive[] @relation("ExpensesToArchive")

  @@unique([timesheet_id, date, amount, mileage], name: "unique_ts_id_date_amount_mileage")
  @@map("expenses")
}

model ExpensesArchive {
  id                 Int      @id @default(autoincrement())
  expense_id         Int
  timesheet_id       Int
  archived_at        DateTime @default(now())
  date               DateTime @db.Date
  amount             Decimal? @db.Decimal(12, 2)
  is_approved        Boolean
  supervisor_comment String?
  bank_code_id       Int
  comment            String?
  mileage            Decimal? @db.Decimal(12, 2)
  expense            Expenses @relation("ExpensesToArchive", fields: [expense_id], references: [id])

  @@map("expenses_archive")
}

model OAuthSessions {
  id                   String    @id @default(cuid())
  user_id              String    @db.Uuid
  application          String
  access_token         String    @unique
  refresh_token        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?
  sid                  String    @unique
  user                 Users     @relation("UserOAuthSessions", fields: [user_id], references: [id])

  @@map("oauth_sessions")
}

model Sessions {
  id        String   @id
  sid       String   @unique
  data      String
  expiresAt DateTime

  @@map("sessions")
}

model Preferences {
  user_id                    String   @unique @db.Uuid
  id                         Int      @id @default(autoincrement())
  display_language           String   @default("fr-FR")
  is_dark_mode               Boolean? @default(false)
  is_employee_list_grid      Boolean  @default(true)
  is_lefty_mode              Boolean  @default(false)
  is_timesheet_approval_grid Boolean  @default(true)
  notifications              Boolean  @default(true)
  user                       Users    @relation("UserPreferences", fields: [user_id], references: [id])

  @@map("preferences")
}

model PaidTimeOff {
  id             Int       @id @default(autoincrement())
  employee_id    Int       @unique
  vacation_hours Decimal   @default(0) @db.Decimal(12, 2)
  banked_hours   Decimal   @default(0) @db.Decimal(12, 2)
  sick_hours     Decimal   @default(0) @db.Decimal(12, 2)
  last_updated   DateTime? @db.Date

  employee Employees @relation("EmployeePaidTimeOff", fields: [employee_id], references: [id])

  @@map("paid_time_off")
}

view PayPeriods {
  pay_year      Int
  pay_period_no Int
  period_start  DateTime @db.Date
  period_end    DateTime @db.Date
  payday        DateTime @db.Date
  label         String

  @@map("pay_period")
}

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 Modules {
  timesheets
  timesheets_approval
  employee_list
  employee_management
  personal_profile
  dashboard
  ticket
  ticket_management
  chatbot

  @@map("modules")
}

enum LeaveTypes {
  SICK
  VACATION
  UNPAID
  BEREAVEMENT
  PARENTAL
  LEGAL
  WEDDING
  HOLIDAY

  @@map("leave_types")
}

enum LeaveApprovalStatus {
  PENDING
  APPROVED
  DENIED
  CANCELLED
  ESCALATED

  @@map("leave_approval_status")
}

enum Weekday {
  SUN
  MON
  TUE
  WED
  THU
  FRI
  SAT
}

enum ApplicableOvertime {
  DAILY
  WEEKLY
  PAYPERIOD
}
