generator client {
  provider = "prisma-client-js"
  binaryTargets = ["native", "debian-openssl-1.1.x", "debian-openssl-3.0.x", "rhel-openssl-1.0.x"]
}

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

// ============================================================
// CABANG & PENGGUNA
// ============================================================

model Branch {
  id       Int     @id @default(autoincrement())
  name     String // Nama cabang
  code     String  @unique // Kode cabang, e.g., CBG-01
  address  String?
  phone    String?
  isActive Boolean @default(true)

  users          User[]
  stocks         Stock[]
  userAccess UserBranchAccess[]
  sales          Sale[]
  purchases      Purchase[]
  stockMovements StockMovement[]

  createdAt DateTime   @default(now())
  updatedAt DateTime   @updatedAt
  Category       Category[]
  Product        Product[]
  Supplier       Supplier[]
  Customer       Customer[]
  payables       Payable[]
}

model Module {
  id          Int              @id @default(autoincrement())
  name        String           @unique // e.g., 'Products', 'Sales', 'Reports'
  group       String           @default("General")
  permissions RolePermission[]
}

model Role {
  id          Int              @id @default(autoincrement())
  name        String           @unique // e.g., 'Super Admin', 'Admin Cabang', 'Kasir'
  description String?
  users       User[]
  permissions RolePermission[]
}

model RolePermission {
  id         Int     @id @default(autoincrement())
  roleId     Int
  moduleId   Int
  canView    Boolean @default(false)
  canCreate  Boolean @default(false)
  canEdit    Boolean @default(false)
  canDelete  Boolean @default(false)
  canApprove Boolean @default(false)
  canCancel  Boolean @default(false)
  canPrint   Boolean @default(false)
  canSpecial Boolean @default(false) // Untuk akses global, hapus permanen, dll

  role   Role   @relation(fields: [roleId], references: [id], onDelete: Cascade)
  module Module @relation(fields: [moduleId], references: [id], onDelete: Cascade)

  @@unique([roleId, moduleId])
}

model User {
  id       Int     @id @default(autoincrement())
  email    String  @unique
  password String
  name     String
  pinCode  String? // Kode PIN untuk otorisasi (khusus Super Admin/Admin)
  roleId   Int
  branchId Int? // null = Super Admin (akses semua cabang)
  isActive Boolean @default(true)

  role      Role       @relation(fields: [roleId], references: [id])
  branch    Branch?    @relation(fields: [branchId], references: [id], onDelete: SetNull)
  sales     Sale[]
  purchases Purchase[]
  auditLogs AuditLog[]
  branchAccess UserBranchAccess[]

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model AuditLog {
  id        Int      @id @default(autoincrement())
  userId    Int
  branchId  Int?
  action    String // CREATE, UPDATE, DELETE
  entity    String // PRODUCT, SALE, PURCHASE, etc.
  entityId  Int?
  details   String?
  createdAt DateTime @default(now())

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)
  @@index([userId])


  @@index([createdAt])
}

// ============================================================
// PRODUK & INVENTORY
// ============================================================

model Category {
  branchId      Int?
  branch        Branch?       @relation(fields: [branchId], references: [id])
  id            Int           @id @default(autoincrement())
  name          String        // Pestisida, Pupuk, Benih, dll.
  subcategories Subcategory[]
  products      Product[]

  @@unique([name, branchId])
  @@index([name])

}

model Subcategory {
  id         Int       @id @default(autoincrement())
  name       String
  categoryId Int
  category   Category  @relation(fields: [categoryId], references: [id], onDelete: Cascade)
  products   Product[]

  @@unique([categoryId, name])
  @@index([categoryId])

}

model Unit {
  id              Int              @id @default(autoincrement())
  name            String           @unique // pcs, kg, liter, karung, botol, dll.
  productVariants ProductVariant[]
}

model Product {
  branchId      Int?
  branch        Branch? @relation(fields: [branchId], references: [id])
  id            Int     @id @default(autoincrement())
  name          String
  categoryId    Int
  subcategoryId Int?
  description   String?
  isActive      Boolean @default(true)

  category    Category         @relation(fields: [categoryId], references: [id])
  subcategory Subcategory?     @relation(fields: [subcategoryId], references: [id], onDelete: SetNull)
  variants    ProductVariant[]

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  @@index([subcategoryId])
  @@index([isActive])


  @@index([categoryId])
  @@index([name])
}

model ProductVariant {
  id             Int     @id @default(autoincrement())
  productId      Int
  name           String // e.g., "1 kg", "5 kg", "50 kg"
  barcode        String? @unique
  unitId         Int
  costPrice      Float?  // Harga beli terakhir (auto-update dari PO)
  priceRetail    Float // Harga eceran
  priceWholesale Float // Harga grosir
  wholesaleMin   Int     @default(1) // Minimal qty untuk harga grosir
  isActive       Boolean @default(true)

  product       Product         @relation(fields: [productId], references: [id], onDelete: Cascade)
  unit          Unit            @relation(fields: [unitId], references: [id])
  stocks        Stock[]
  saleItems     SaleItem[]
  purchaseItems PurchaseItem[]
  movements     StockMovement[]
  @@index([productId])


  @@index([isActive])
}

model Stock {
  id        Int   @id @default(autoincrement())
  variantId Int
  branchId  Int
  quantity  Float @default(0)

  variant ProductVariant @relation(fields: [variantId], references: [id], onDelete: Cascade)
  branch  Branch         @relation(fields: [branchId], references: [id], onDelete: Cascade)

  updatedAt DateTime @updatedAt

  @@unique([variantId, branchId])
  @@index([branchId])
  @@index([variantId])

}

model StockMovement {
  id            Int      @id @default(autoincrement())
  variantId     Int
  branchId      Int
  type          String // IN, OUT, TRANSFER_IN, TRANSFER_OUT, OPNAME
  quantity      Float
  notes         String?
  referenceId   Int? // ID transaksi terkait (sale/purchase)
  referenceType String? // SALE, PURCHASE, TRANSFER, OPNAME
  createdAt     DateTime @default(now())

  variant ProductVariant @relation(fields: [variantId], references: [id])
  branch  Branch         @relation(fields: [branchId], references: [id])

  @@index([branchId])
  @@index([createdAt])
}

// ============================================================
// SUPPLIER & PEMBELIAN
// ============================================================

model Supplier {
  branchId  Int?
  branch    Branch?    @relation(fields: [branchId], references: [id])
  id        Int        @id @default(autoincrement())
  name      String
  phone     String?
  address   String?
  email     String?
  isActive  Boolean    @default(true)
  purchases Purchase[]
  payables  Payable[]

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model Purchase {
  id            Int       @id @default(autoincrement())
  code          String    @unique // Nomor faktur/PO
  supplierId    Int
  branchId      Int
  userId        Int // Dibuat oleh
  totalAmount   Float
  paymentMethod String    @default("CASH") // CASH, TEMPO, TRANSFER
    transferBank  String?
    transferProof String?
  paidAmount    Float     @default(0)
  dueDate       DateTime?
  notes         String?
  status        String    @default("RECEIVED") // PENDING, RECEIVED, CANCELLED

  supplier Supplier       @relation(fields: [supplierId], references: [id])
  branch   Branch         @relation(fields: [branchId], references: [id])
  user     User           @relation(fields: [userId], references: [id])
  items    PurchaseItem[]
  payable  Payable?

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  @@index([supplierId])


  @@index([branchId])
  @@index([createdAt])
  @@index([status])
}

model PurchaseItem {
  id         Int   @id @default(autoincrement())
  purchaseId Int
  variantId  Int
  quantity   Float
  unitPrice  Float
  total      Float

  purchase Purchase       @relation(fields: [purchaseId], references: [id], onDelete: Cascade)
  variant  ProductVariant @relation(fields: [variantId], references: [id])
}

// ============================================================
// PELANGGAN & PENJUALAN
// ============================================================

model Customer {
  branchId    Int?
  branch      Branch?      @relation(fields: [branchId], references: [id])
  id          Int          @id @default(autoincrement())
  name        String
  phone       String?
  address     String?
  email       String?
  isActive    Boolean      @default(true)
  sales       Sale[]
  receivables Receivable[]

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model Sale {
  id            Int     @id @default(autoincrement())
  code          String  @unique // Nomor transaksi
  customerId    Int? // null = pelanggan umum
  branchId      Int
  userId        Int // Kasir
  totalAmount   Float
  discount      Float   @default(0)
  creditFee     Float   @default(0)
  grandTotal    Float
  paidAmount    Float   @default(0)
  changeAmount  Float   @default(0)
  paymentMethod String  @default("CASH") // CASH, TRANSFER, CREDIT
  transferBank  String?
  transferProof String?
  creditTenor   Int?
  status        String  @default("COMPLETED") // COMPLETED, CANCELLED, PARTIAL
  notes         String?

  customer   Customer?   @relation(fields: [customerId], references: [id], onDelete: SetNull)
  branch     Branch      @relation(fields: [branchId], references: [id])
  user       User        @relation(fields: [userId], references: [id])
  items      SaleItem[]
  receivable Receivable?

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  @@index([createdAt])
  @@index([status])


  @@index([branchId])
}

model SaleItem {
  id        Int   @id @default(autoincrement())
  saleId    Int
  variantId Int
  quantity  Float
  unitPrice Float
  discount  Float @default(0)
  total     Float

  sale    Sale           @relation(fields: [saleId], references: [id], onDelete: Cascade)
  variant ProductVariant @relation(fields: [variantId], references: [id])
}

// ============================================================
// PIUTANG (PELANGGAN)
// ============================================================

model Receivable {
  id              Int       @id @default(autoincrement())
  saleId          Int       @unique
  customerId      Int
  totalAmount     Float // Total piutang awal
  paidAmount      Float     @default(0)
  remainingAmount Float
  dueDate         DateTime?
  status          String    @default("OUTSTANDING") // OUTSTANDING, PARTIAL, PAID

  sale     Sale      @relation(fields: [saleId], references: [id])
  customer Customer  @relation(fields: [customerId], references: [id])
  payments Payment[]

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model Payment {
  id           Int      @id @default(autoincrement())
  receivableId Int
  amount       Float
  method       String   @default("CASH") // CASH, TRANSFER
  notes        String?
  paidAt       DateTime @default(now())

  receivable Receivable @relation(fields: [receivableId], references: [id], onDelete: Cascade)
}

// ============================================================
// HUTANG (SUPPLIER)
// ============================================================

model Payable {
  id              Int       @id @default(autoincrement())
  purchaseId      Int?      @unique
  supplierId      Int
  branchId        Int?
  totalAmount     Float // Total hutang awal
  paidAmount      Float     @default(0)
  remainingAmount Float
  dueDate         DateTime?
  status          String    @default("OUTSTANDING") // OUTSTANDING, PARTIAL, PAID
  notes           String?

  purchase Purchase?        @relation(fields: [purchaseId], references: [id], onDelete: SetNull)
  supplier Supplier         @relation(fields: [supplierId], references: [id])
  branch   Branch?          @relation(fields: [branchId], references: [id])
  payments PayablePayment[]

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model PayablePayment {
  id        Int      @id @default(autoincrement())
  payableId Int
  amount    Float
  method    String   @default("CASH") // CASH, TRANSFER
  notes     String?
  paidAt    DateTime @default(now())

  payable Payable @relation(fields: [payableId], references: [id], onDelete: Cascade)
}

model Setting {
  key   String @id
  value String
}


model UserBranchAccess {
  userId   Int
  branchId Int
  user     User   @relation(fields: [userId], references: [id], onDelete: Cascade)
  branch   Branch @relation(fields: [branchId], references: [id], onDelete: Cascade)

  @@id([userId, branchId])
}
