> ## Documentation Index
> Fetch the complete documentation index at: https://docs.quinnsambal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

<style>
  {`
    [class*="max-w-none"][class*="table"] {
      display: block !important;
      overflow-x: auto !important;
      max-width: 100% !important;
      width: 100% !important;
      flex-grow: 0 !important;
    }
    [class*="max-w-none"][class*="table"] > table {
      width: 100% !important;
      max-width: 100% !important;
      table-layout: fixed !important;
    }
    .mermaid {
      max-width: 100% !important;
      overflow-x: auto !important;
    }
    article svg[role="img"] {
      max-width: 100% !important;
      height: auto !important;
    }
    article img, .prose img {
      max-width: 100% !important;
      height: auto !important;
    }
    img[src*="LOGO"], img[src*="logo"] {
      max-width: 120px !important;
      max-height: 40px !important;
      width: auto !important;
      height: auto !important;
      object-fit: contain !important;
    }
    `}
</style>

***

title: "Keuangan Overview"
description: "Arsitektur modul keuangan SNISHOP ERP — double-entry bookkeeping, GL auto-journaling, invoice lifecycle, expense approval, budget tracking, AI forecasting, dan integrasi lintas modul."
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

# Keuangan Overview

<img src="https://mintcdn.com/quinnofspicy/ny1xnfpEa_OBdv6T/docs/mintlify/screenshots/finance/finance.png?fit=max&auto=format&n=ny1xnfpEa_OBdv6T&q=85&s=f08caee61e6de067c5518238b3abd27a" alt="Keuangan Dashboard" width="1920" height="1080" data-path="docs/mintlify/screenshots/finance/finance.png" />

Modul keuangan SNISHOP ERP adalah tulang punggung pencatatan finansial perusahaan PT Selera Pedas Nusantara. Sistem ini menerapkan **double-entry bookkeeping** dengan Chart of Accounts (COA) hierarkis, auto-journaling dari setiap transaksi lintas modul, dan verifikasi tiga tahap untuk pembayaran invoice. Seluruh data keuangan tersimpan dalam **19 entity** terpisah yang saling terhubung melalui `GLJournalEntry`, `FinancialRecord`, dan `Account`.

## Arsitektur Keuangan End-to-End

```mermaid theme={null}
graph TB
    subgraph INPUT["Input Transaksi"]
        POS["POS Transaction"]
        MFG["Production Batch"]
        EXP["Expense Claim"]
        INV["Invoice Payment"]
        PO["Purchase Order"]
        MANUAL["Manual Journal"]
    end

    subgraph CORE["Core Finance Engine"]
        FR["FinancialRecord<br/>10+ reference types"]
        GL["GLJournalEntry<br/>Double-entry enforced"]
        COA["Chart of Accounts<br/>5 types × 3 levels"]
        ACC["Account<br/>Cash/Bank/E-Wallet"]
    end

    subgraph PROCESS["Business Logic"]
        APPROVE["Approval Workflow<br/>Owner/Admin/Finance"]
        VERIFY["Payment Verification<br/>Verified/Pending/Rejected"]
        IDEM["Idempotency Key<br/>Safe replay"]
        RECON["Reconciliation Marker<br/>RECONCILIATION_REQUIRED"]
    end

    subgraph OUTPUT["Output & Reporting"]
        PL["Laba Rugi<br/>P&L"]
        BS["Neraca<br/>Balance Sheet"]
        TB["Neraca Saldo<br/>Trial Balance"]
        BVA["Budget vs Actual"]
        AI["AI Insights Engine<br/>3-level analysis"]
        KPI["Executive KPI<br/>4 cards"]
    end

    POS --> FR
    MFG --> GL
    EXP --> GL
    INV --> FR
    PO --> FR
    MANUAL --> GL

    FR --> ACC
    GL --> COA
    COA --> ACC

    APPROVE --> GL
    VERIFY --> FR
    IDEM --> FR
    RECON --> GL

    GL --> PL
    GL --> BS
    GL --> TB
    FR --> BVA
    FR --> AI
    FR --> KPI
```

## 11 Tab Modul Keuangan

Halaman utama Finance (`/finance`) terdiri dari **11 tab** yang masing-masing menangani aspek berbeda:

| Tab | Fungsi | Entity Utama |
| - | - | - |
| Dashboard | Ringkasan saldo, arus kas, laba rugi | Account, FinancialRecord |
| Pencatatan | Input transaksi manual (income/expense/transfer/debt/investment) | FinancialRecord |
| Rekening | Kelola rekening bank, kas, e-wallet | Account |
| Lap. Detail | Detail transaksi per akun | GLJournalEntry |
| Anggaran | Budget per kategori & periode | Budget |
| Laporan | P\&L, Neraca, Trial Balance, Budget vs Actual | FinancialReportSnapshot |
| Riwayat | History semua transaksi | FinancialRecord |
| AI Tips | Rekomendasi AI dari Gemini/OpenAI | — |
| Kas Harian | Buku kas harian dengan drill-down | FinancialRecord |
| Piutang | AR aging 5 bucket | Invoice, InvoicePayment |
| Pengaturan | Konfigurasi kategori, threshold | TransactionCategory |

## Double-Entry Bookkeeping

Setiap transaksi di SNISHOP ERP mengikuti prinsip **double-entry**: total debit harus selalu sama dengan total kredit. Sistem memvalidasi ini di level server dengan toleransi Rp 0.01.

### 5 Tipe Akun COA

| Tipe | Saldo Normal | Kode COA | Contoh Akun |
| - | - | - | - |
| **Asset** | Debit | 1-xxxx | Kas, Bank, Piutang, Persediaan, Aset Tetap |
| **Liability** | Kredit | 2-xxxx | Hutang Usaha, Hutang Pajak, Hutang Lainnya |
| **Equity** | Kredit | 3-xxxx | Modal, Laba Ditahan, Prive |
| **Revenue** | Kredit | 4-xxxx | Penjualan, Pendapatan Jasa, Pendapatan Lain |
| **Expense** | Debit | 5-xxxx | HPP, Gaji, Sewa, Listrik, Marketing |

### 3 Level Hierarki Akun

```mermaid theme={null}
graph LR
    L0["Level 0<br/>HEADER<br/>Aset Lancar"] --> L1A["Level 1<br/>MAIN<br/>Kas & Bank"]
    L0 --> L1B["Level 1<br/>MAIN<br/>Piutang Usaha"]
    L1A --> L2A["Level 2<br/>SUB<br/>Kas IDR"]
    L1A --> L2B["Level 2<br/>SUB<br/>BCA Rupiah"]
    L1A --> L2C["Level 2<br/>SUB<br/>Mandiri Rupiah"]
    L1B --> L2D["Level 2<br/>SUB<br/>Piutang B2B"]
```

## Auto-Journaling dari Lintas Modul

SNISHOP ERP otomatis membuat jurnal GL dari transaksi di modul lain. Ini memastikan pembukuan selalu sinkron tanpa input manual.

```mermaid theme={null}
sequenceDiagram
    participant M as Modul Lain
    participant F as Finance Engine
    participant GL as GLJournalEntry
    participant ACC as Account

    Note over M: POS Transaction
    M->>F: source='pos'
    F->>GL: Debit: Kas/Bank<br/>Kredit: Pendapatan
    F->>ACC: Update current_balance

    Note over M: Expense Approved
    M->>F: resolveExpenseGLMapping()
    F->>GL: Debit: Expense (by category)<br/>Kredit: Kas/Bank
    F->>ACC: Update current_balance

    Note over M: Production Complete
    M->>F: MATERIALS_TO_WIP
    F->>GL: Debit: WIP (asset)<br/>Kredit: Persediaan (asset)
    Note over GL: Asset-only, no P&L impact

    Note over M: Invoice Payment Verified
    M->>F: verification_status='verified'
    F->>GL: Debit: Kas/Bank<br/>Kredit: Piutang
    F->>ACC: Update current_balance
```

### Anti-Double-Counting

Sistem mencegah pencatatan ganda melalui beberapa mekanisme:

| Mekanisme | Fungsi |
| - | - |
| `is_inventory_material` flag | Mencegah expense bahan baku dihitung sebagai HPP sekaligus expense |
| `hasBookedCogs` check | Mencegah COGS dihitung dua kali di laporan P\&L |
| `isRevenueRecord()` | Exclude stock opname, invoice payment, HPP dari revenue |
| `isCashInflowRecord()` | Exclude receivables dari cash inflow |

## Invoice Lifecycle & AR Aging

Invoice memiliki **6 status** dan **5 bucket aging** untuk piutang:

```mermaid theme={null}
stateDiagram-v2
    [*] --> Draft
    Draft --> Sent: Kirim
    Sent --> PartiallyPaid: Bayar sebagian
    Sent --> Paid: Bayar lunas
    Sent --> Overdue: Lewat due date
    PartiallyPaid --> Paid: Bayar sisa
    PartiallyPaid --> Overdue: Lewat due date
    Paid --> [*]
    Overdue --> Paid: Bayar (late)
    Draft --> Cancelled: Batal
    Sent --> Cancelled: Batal

    state "6 Status Invoice" as inv_status {
        [*] --> draft
        draft --> sent
        sent --> partially_paid
        sent --> paid
        sent --> overdue
        partially_paid --> paid
    }
```

| Aging Bucket | Umur Piutang | Warna | Aksi |
| - | - | - | - |
| Current | 0 hari | Hijau | Monitor |
| 1-30 days | 1-30 hari | Kuning | Reminder |
| 31-60 days | 31-60 hari | Oranye | Follow-up |
| 61-90 days | 61-90 hari | Merah | Escalate |
| >90 days | >90 hari | Merah Tua | Collection |

## Verifikasi Pembayaran Tiga Tahap

Pembayaran invoice melalui tiga status verifikasi untuk memastikan akurasi:

```mermaid theme={null}
graph LR
    A["Payment Received"] --> B{Verification}
    B -->|Verified| C["✓计入 paid_amount<br/>Create FinancialRecord<br/>Update Account balance"]
    B -->|Pending| D["⏳ Disimpan di history<br/>TIDAK计入 paid_amount<br/>Menunggu review"]
    B -->|Rejected| E["✗ Ditolak<br/>Need reconciliation<br/>Notify customer"]
```

## Integrasi Lintas Modul

```mermaid theme={null}
graph TB
    subgraph MODULES["Modul Penghasil Transaksi"]
        POS_M["POS<br/>8 channel penjualan"]
        MFG_M["Manufacturing<br/>2-phase journal"]
        INV_M["Inventory<br/>Stock opname, PO"]
        HR_M["HR/Payroll<br/>Gaji karyawan"]
        CRM_M["CRM<br/>Invoice B2B"]
    end

    subgraph FINANCE["Finance Engine"]
        FR2["FinancialRecord<br/>8 source types"]
        GL2["GLJournalEntry<br/>5 reference types"]
        ACC2["Account<br/>4 types"]
        COA2["COA<br/>5 types"]
    end

    subgraph REPORTS["Laporan & Analisis"]
        PL2["Laba Rugi"]
        BS2["Neraca"]
        TB2["Trial Balance"]
        BVA2["Budget vs Actual"]
        AI2["AI Insights"]
        KPI2["Executive KPI"]
        DQ["Data Quality<br/>Dashboard"]
    end

    POS_M --> FR2
    MFG_M --> GL2
    INV_M --> FR2
    HR_M --> GL2
    CRM_M --> FR2

    FR2 --> ACC2
    GL2 --> COA2
    COA2 --> ACC2

    GL2 --> PL2
    GL2 --> BS2
    GL2 --> TB2
    FR2 --> BVA2
    FR2 --> AI2
    FR2 --> KPI2
    FR2 --> DQ
```

### Manufacturing → Finance (Two-Phase Journal)

| Phase | Fungsi | Jurnal | Dampak |
| - | - | - | - |
| Phase 1: `completeProductionBatch` | Bahan baku → WIP | Debit: WIP, Kredit: Persediaan | Asset-only, no P\&L |
| Phase 2: `verifyAndReleaseProductionBatch` | WIP → Finished Goods | Debit: Finished Goods, Kredit: WIP | Asset-only, no P\&L |

**Segregation of duties**: Operator yang menyelesaikan batch tidak bisa merilis QC-nya sendiri.

## Role-Based Access Control

| Role | Dashboard | Jurnal | Expense | Invoice | Budget | Laporan |
| - | - | - | - | - | - | - |
| Owner | ✓ Full | ✓ Full | ✓ Auto-approve | ✓ Full | ✓ Full | ✓ Full |
| Admin | ✓ Full | ✓ Full | ✓ Auto-approve | ✓ Full | ✓ Full | ✓ Full |
| Finance | ✓ Full | ✓ Full | ✓ Auto-approve | ✓ Full | ✓ Full | ✓ Full |
| Finance Admin | ✓ Read | ✓ Create | ✓ Submit | ✓ Read | ✓ Read | ✓ Read |
| Kasir | ✗ | ✗ | ✗ | ✓ Read (own) | ✗ | ✗ |

## 19 Entity Keuangan

| Entity | Fungsi | Field Kunci |
| - | - | - |
| GLAccount | Chart of Accounts | account\_code, type, parent\_id, level |
| GLJournalEntry | Jurnal transaksi | entry\_number, line\_items, status, reference\_type |
| Account | Rekening (kas/bank/e-wallet) | type, current\_balance, is\_default\_pos |
| BankAccount | Rekening bank per company | company\_id, merged accounts |
| Expense | Pengeluaran | category, status, is\_inventory\_material |
| FinancialRecord | Transaksi universal | type, source, reference\_type, cogs\_amount |
| Invoice | Tagihan B2B | invoice\_type, status, paid\_amount, deliveries |
| InvoicePayment | Ledger pembayaran | verification\_status, amount, reconciliation\_reason |
| Budget | Anggaran | planned\_amount, actual\_amount, alert\_threshold |
| FinancialGoal | Target keuangan | goal\_type, target\_amount, current\_amount |
| PurchaseOrder | PO ke supplier | status (5 tahap), received\_status |
| Supplier | Data supplier | supplier\_type, validation\_score, is\_locked |
| FixedAsset | Aset tetap | depreciation\_method, gl\_account\_id |
| Investment | Portofolio investasi | asset\_type, purchase\_price, current\_price |
| FinancialReportSnapshot | Cache laporan | report\_type, snapshot\_data, period |
| TransactionCategory | Kategori transaksi | name, mode (personal/business), color |
| Discount | Diskon | discount\_type, applies\_to, usage\_limit |
| ApprovalWorkflow | Workflow approval | document\_type, approval\_levels, amount\_limits |
| ApprovalRequest | Request approval | approval\_history, overall\_status, current\_approval\_level |

## Laporan Keuangan

| Laporan | Sumber Data | Komponen | Validasi | | |
| - | - | - | - | - | - |
| **Laba Rugi** | GL Journal (preferred) / FinancialRecord (fallback) | Revenue, COGS, Gross Profit, Operating Expenses, Net Profit | `evaluateCompleteness()` → audited/provisional | | |
| **Neraca** | GL Journal | Aset, Liabilitas, Ekuitas | \` | Assets - (Liabilities + Equity) | \< 1\` |
| **Neraca Saldo** | GL Journal line\_items | Per-account debit/kredit totals | \` | Total Debit - Total Credit | \< 1\` |
| **Budget vs Actual** | FinancialRecord + GL Journal | Per-category planned vs actual | Status: ok (≤80%), warning (80-100%), over (>100%) | | |

## AI & Forecasting

### AI Insights Engine (3 Level)

| Level | Fungsi | Contoh |
| - | - | - |
| **Descriptive** | Apa yang terjadi | "Revenue turun 15% vs bulan lalu" |
| **Diagnostic** | Mengapa terjadi | "Penurunan disebabkan oleh stock-out produk X selama 5 hari" |
| **Predictive** | Apa yang harus dilakukan | "Restock produk X sebelum tanggal 15 untuk menghindari kehilangan revenue Rp 5jt" |

### Forecasting Engine

Weighted ensemble: **50% Linear Regression** + **30% Growth Rate** + **20% Moving Average**

| Confidence | Data Points | Horizon |
| - | - | - |
| High | ≥6 data points | 3 bulan |
| Medium | 4-5 data points | 2 bulan |
| Low | 2-3 data points | 1 bulan |

## Halaman Keuangan

| Halaman | URL | Fungsi Utama |
| - | - | - |
| Finance Overview | `/finance` | Dashboard 11 tab |
| General Ledger | `/generalledger` | COA & jurnal manual |
| Expense Management | `/expensemanagement` | Expense claim & approval |
| Invoices | `/invoices` | Invoice B2B & AR aging |
| Budget Planner | `/budgetplanner` | Budget per kategori & periode |
| Financial Goals | `/financialgoals` | Target keuangan & progress |
| Financial Reports | `/financialreports` | P\&L, Neraca, Trial Balance |
| Saldo | `/saldo` | Rekening bank & cash flow |
| Reports | `/reports` | Custom report builder & forecasting |
| AI Profit Report | `/aiprofitreport` | AI insights & rekomendasi |

## Best Practices

### Monthly Close

1. Reconcile semua rekening bank
2. Review outstanding invoice & piutang
3. Post semua draft journal
4. Generate laporan keuangan
5. Analisis variance budget vs actual

### Yearly Close

1. Annual financial statements
2. Tax preparation
3. Audit preparation
4. Budget planning untuk tahun berikutnya
5. Review dan update COA

### Daily Operations

* Check cash flow harian
* Record expense sedekat mungkin dengan tanggal transaksi
* Verify invoice payment segera setelah diterima
* Monitor budget alert

***

# Entity Schema Reference

Bagian ini mendokumentasikan seluruh **19 entity** modul keuangan secara field-by-field, lengkap dengan tipe data, kewajiban isi, dan deskripsi.

## Entity Relationship Diagram

```mermaid theme={null}
erDiagram
    GLAccount ||--o{ GLAccount : "parent_account_id (hierarki COA)"
    GLAccount ||--o{ GLJournalEntry : "line_items.account_id"
    GLAccount ||--o{ FixedAsset : "gl_account_id"

    GLJournalEntry {
        string company_id
        date entry_date
        string reference_type
        array line_items
        string status
    }

    Account ||--o{ FinancialRecord : "account_id"
    Account ||--o{ Expense : "account_id"
    Account ||--o{ InvoicePayment : "account_id"

    Account {
        string user_id
        string name
        string type
        number current_balance
        string mode
    }

    FinancialRecord {
        string user_id
        string account_id
        string type
        number amount
        string source
        string reference_type
    }

    Invoice ||--o{ InvoicePayment : "payments (embedded & referenced)"
    Invoice {
        string invoice_number
        string invoice_type
        string customer_name
        string status
        number total
        number paid_amount
    }

    InvoicePayment {
        string invoice_id
        number amount
        string verification_status
        string status
    }

    ApprovalWorkflow ||--o{ ApprovalRequest : "workflow_id"
    ApprovalWorkflow ||--o{ Expense : "approval_workflow_id"

    ApprovalWorkflow {
        string company_id
        string workflow_name
        string document_type
        array approval_levels
    }

    ApprovalRequest {
        string workflow_id
        string document_type
        string document_id
        string overall_status
        number current_approval_level
    }

    Expense {
        string company_id
        string requester_id
        string category
        number amount
        string status
        string approval_status
    }

    Budget {
        string user_id
        string name
        string category
        number planned_amount
        number actual_amount
        string period
    }

    FinancialGoal {
        string user_id
        string title
        string goal_type
        number target_amount
        number current_amount
        string status
    }

    PurchaseOrder }o--|| Supplier : "supplier_id"
    PurchaseOrder {
        string company_id
        string po_number
        string supplier_id
        string status
        string received_status
    }

    Supplier {
        string company_id
        string company_name
        string supplier_type
        number validation_score
        boolean is_locked
    }

    FixedAsset {
        string company_id
        string asset_name
        string category
        number acquisition_cost
        string depreciation_method
        string status
    }

    Investment {
        string user_id
        string asset_name
        string asset_type
        number quantity
        number purchase_price
        number current_price
    }

    FinancialReportSnapshot {
        string company_id
        string report_type
        string report_name
        object report_data
    }

    TransactionCategory {
        string user_id
        string name
        string type
        string mode
    }

    Discount {
        string company_id
        string discount_name
        string discount_type
        number value
        string applies_to
    }

    BankAccount {
        string user_id
        string company_id
        string account_type
        string provider
        string account_number
    }
```

## State Machines

### Invoice Status

```mermaid theme={null}
stateDiagram-v2
    [*] --> draft
    draft --> sent: Kirim invoice
    draft --> cancelled: Batal
    sent --> partially_paid: Terima bayar sebagian
    sent --> paid: Terima bayar lunas
    sent --> overdue: Lewat due_date
    sent --> cancelled: Batal
    partially_paid --> paid: Terima sisa pembayaran
    partially_paid --> overdue: Lewat due_date
    overdue --> paid: Terima pembayaran (late)
    paid --> [*]
    cancelled --> [*]
```

### Invoice Delivery Status

```mermaid theme={null}
stateDiagram-v2
    [*] --> pending
    pending --> partially_delivered: Kirim sebagian
    pending --> delivered: Kirim semua
    partially_delivered --> delivered: Kirim sisa
    delivered --> [*]
```

### InvoicePayment Verification Status

```mermaid theme={null}
stateDiagram-v2
    [*] --> pending: Pembayaran dicatat
    pending --> verified: Finance memverifikasi
    pending --> rejected: Finance menolak
    verified --> [*]
    rejected --> [*]
```

### InvoicePayment Posting Status

```mermaid theme={null}
stateDiagram-v2
    [*] --> posted: Pembayaran terverifikasi
    [*] --> needs_reconciliation: Ada ketidakcocokan
    needs_reconciliation --> posted: Setelah rekonsiliasi
    posted --> [*]
```

### Expense Status

```mermaid theme={null}
stateDiagram-v2
    [*] --> draft: Buat expense
    draft --> submitted: Submit untuk approval
    submitted --> approved: Disetujui approver
    submitted --> rejected: Ditolak approver
    approved --> paid: Pembayaran diproses
    paid --> [*]
    rejected --> [*]
```

### Expense Approval Status

```mermaid theme={null}
stateDiagram-v2
    [*] --> pending: Submit expense
    pending --> approved: Approver menyetujui
    pending --> rejected: Approver menolak
    approved --> [*]
    rejected --> [*]
```

### PurchaseOrder Status

```mermaid theme={null}
stateDiagram-v2
    [*] --> draft: Buat PO
    draft --> sent: Kirim ke supplier
    sent --> confirmed: Supplier konfirmasi
    confirmed --> received: Barang diterima
    received --> invoiced: Invoice supplier diterima
    invoiced --> [*]
    draft --> cancelled: Batal
    sent --> cancelled: Batal
    cancelled --> [*]
```

### PurchaseOrder Received Status

```mermaid theme={null}
stateDiagram-v2
    [*] --> pending: PO dikirim
    pending --> partially_received: Barang diterima sebagian
    pending --> fully_received: Semua barang diterima
    partially_received --> fully_received: Sisa barang diterima
    fully_received --> [*]
```

### ApprovalRequest Overall Status

```mermaid theme={null}
stateDiagram-v2
    [*] --> pending: Request diajukan
    pending --> approved: Semua level approve
    pending --> rejected: Salah satu level reject
    pending --> on_hold: Ditunda sementara
    on_hold --> pending: Dilanjutkan kembali
    approved --> [*]
    rejected --> [*]
```

### Budget Status

```mermaid theme={null}
stateDiagram-v2
    [*] --> active: Budget dibuat
    active --> completed: Periode berakhir
    active --> archived: Diarsipkan manual
    completed --> [*]
    archived --> [*]
```

### FinancialGoal Status

```mermaid theme={null}
stateDiagram-v2
    [*] --> active: Goal dibuat
    active --> paused: Dijeda
    active --> completed: Target tercapai
    active --> failed: Gagal mencapai target
    paused --> active: Dilanjutkan
    completed --> [*]
    failed --> [*]
```

### GLJournalEntry Status

```mermaid theme={null}
stateDiagram-v2
    [*] --> draft: Jurnal dibuat
    draft --> posted: Jurnal diposting
    posted --> reversed: Jurnal dibalik
    reversed --> [*]
    posted --> [*]
```

### FixedAsset Status

```mermaid theme={null}
stateDiagram-v2
    [*] --> in_use: Aset diperoleh
    in_use --> maintenance: Perawatan
    in_use --> damaged: Rusak
    in_use --> disposed: Dilepas/dijual
    maintenance --> in_use: Selesai perawatan
    damaged --> in_use: Diperbaiki
    damaged --> disposed: Dilepas
    disposed --> [*]
```

***

## Entity Schema Tables

### 1. Account — Rekening (Kas/Bank/E-Wallet)

| Field | Type | Required | Description |
| - | - | - | - |
| `user_id` | string | Ya | ID pengguna pemilik rekening |
| `company_id` | string | Tidak | ID perusahaan (null untuk personal) |
| `name` | string | Ya | Nama rekening/kantong (e.g., Kas, BCA, Mandiri, Dompet) |
| `type` | enum: `cash`, `bank`, `e-wallet`, `other` | Ya | Jenis rekening (default: `cash`) |
| `account_number` | string | Tidak | Nomor rekening (opsional) |
| `bank_name` | string | Tidak | Nama bank (untuk type=bank) |
| `initial_balance` | number | Tidak | Saldo awal (default: 0) |
| `current_balance` | number | Tidak | Saldo saat ini; diupdate otomatis oleh server dari POS, invoice payment, expense, dan void |
| `currency` | string | Tidak | Mata uang (default: `IDR`) |
| `icon` | string | Tidak | Icon rekening (default: 💰) |
| `color` | string | Tidak | Warna untuk UI (default: `#3B82F6`) |
| `is_active` | boolean | Tidak | Status aktif rekening (default: `true`) |
| `is_default_pos` | boolean | Tidak | Rekening default untuk POS Kasir (default: `false`) |
| `notes` | string | Tidak | Catatan tambahan |
| `mode` | enum: `personal`, `business` | Tidak | Mode rekening (default: `personal`) |

### 2. ApprovalRequest — Request Persetujuan

| Field | Type | Required | Description |
| - | - | - | - |
| `company_id` | string | Ya | ID perusahaan |
| `workflow_id` | string | Ya | ID ApprovalWorkflow yang digunakan |
| `document_type` | string | Ya | Tipe dokumen yang diminta persetujuan |
| `document_id` | string | Ya | ID dokumen yang diminta persetujuan |
| `requester_id` | string | Ya | User yang mengajukan persetujuan |
| `submission_date` | date-time | Tidak | Tanggal pengajuan |
| `amount` | number | Tidak | Jumlah nominal (jika ada) |
| `description` | string | Tidak | Deskripsi request |
| `current_approval_level` | number | Tidak | Level persetujuan saat ini (default: 1) |
| `approval_history` | array\[object] | Tidak | Riwayat persetujuan per level |
| `approval_history[].level` | number | — | Urutan tingkat persetujuan |
| `approval_history[].approver_id` | string | — | ID approver |
| `approval_history[].approval_date` | date-time | — | Tanggal persetujuan |
| `approval_history[].status` | enum: `approved`, `rejected`, `pending` | — | Status approval di level ini |
| `approval_history[].comments` | string | — | Komentar approver |
| `overall_status` | enum: `pending`, `approved`, `rejected`, `on_hold` | Tidak | Status keseluruhan (default: `pending`) |
| `final_approval_date` | date-time | Tidak | Tanggal persetujuan final |

### 3. ApprovalWorkflow — Alur Persetujuan

| Field | Type | Required | Description |
| - | - | - | - |
| `company_id` | string | Ya | ID perusahaan |
| `workflow_name` | string | Ya | Nama alur persetujuan |
| `description` | string (max 1000) | Tidak | Penjelasan proses dan aturan alur persetujuan |
| `document_type` | enum: `expense_request`, `leave_request`, `purchase_order`, `discount_request`, `budget_adjustment` | Ya | Tipe dokumen yang memerlukan persetujuan |
| `approval_levels` | array\[object] | Ya | Daftar level persetujuan |
| `approval_levels[].level` | number | — | Urutan tingkat persetujuan |
| `approval_levels[].approver_role` | string | — | Role yang dapat melakukan persetujuan |
| `approval_levels[].approver_ids` | array\[string] | — | User ID spesifik sebagai approver (opsional) |
| `approval_levels[].required_approvals` | number | — | Jumlah persetujuan yang diperlukan (default: 1) |
| `approval_levels[].parallel_approval` | boolean | — | Apakah persetujuan bisa paralel (default: `false`) |
| `amount_limits` | object | Tidak | Limit jumlah per level |
| `amount_limits.level_1` | number | — | Limit amount level 1 |
| `amount_limits.level_2` | number | — | Limit amount level 2 |
| `amount_limits.level_3` | number | — | Limit amount level 3 |
| `is_active` | boolean | Tidak | Status aktif workflow (default: `true`) |

### 4. BankAccount — Rekening Bank per Company

| Field | Type | Required | Description |
| - | - | - | - |
| `user_id` | string | Tidak | ID pengguna pemilik akun |
| `company_id` | string | Tidak | ID perusahaan pemilik rekening (untuk rekening bersama) |
| `account_type` | enum: `bank`, `ewallet` | Ya | Jenis akun: Bank atau E-Wallet |
| `provider` | string | Ya | Nama penyedia (e.g., BRI, BNI, DANA, GOPAY) |
| `account_name` | string | Ya | Nama pemilik rekening |
| `account_number` | string | Ya | Nomor rekening atau nomor telepon E-Wallet |
| `description` | string (max 1000) | Tidak | Catatan tambahan mengenai rekening |
| `is_primary` | boolean | Tidak | Apakah ini rekening utama (default: `false`) |
| `balance` | number | Tidak | Saldo rekening perusahaan untuk tracking internal (default: 0) |
| `is_active` | boolean | Tidak | Apakah rekening masih aktif (default: `true`) |

### 5. Budget — Anggaran

| Field | Type | Required | Description |
| - | - | - | - |
| `user_id` | string | Ya | ID pengguna pemilik anggaran |
| `company_id` | string | Tidak | ID perusahaan (null untuk personal) |
| `name` | string | Ya | Nama anggaran |
| `description` | string (max 1000) | Tidak | Penjelasan tujuan dan detail anggaran |
| `category` | string | Ya | Kategori pengeluaran (makanan, transportasi, hiburan, dll) |
| `planned_amount` | number | Ya | Jumlah anggaran yang direncanakan |
| `actual_amount` | number | Tidak | Jumlah pengeluaran aktual (default: 0) |
| `period` | enum: `monthly`, `quarterly`, `yearly`, `custom` | Tidak | Periode anggaran (default: `monthly`) |
| `start_date` | date | Ya | Tanggal mulai periode anggaran |
| `end_date` | date | Ya | Tanggal akhir periode anggaran |
| `status` | enum: `active`, `completed`, `archived` | Tidak | Status anggaran (default: `active`) |
| `alert_threshold` | number | Tidak | Persentase threshold untuk alert, misal 80 (default: 80) |

### 6. Discount — Diskon

| Field | Type | Required | Description |
| - | - | - | - |
| `company_id` | string | Ya | ID perusahaan |
| `discount_name` | string | Ya | Nama diskon |
| `discount_type` | enum: `percentage`, `fixed_amount`, `buy_x_get_y`, `coupon_code` | Ya | Jenis diskon (default: `percentage`) |
| `value` | number | Ya | Nilai diskon (% atau nominal) |
| `buy_quantity` | number | Tidak | Untuk tipe buy\_x\_get\_y: jumlah beli |
| `get_quantity` | number | Tidak | Untuk tipe buy\_x\_get\_y: jumlah gratis |
| `min_purchase_amount` | number | Tidak | Minimum pembelian (default: 0) |
| `max_discount_amount` | number | Tidak | Batas maksimal nilai diskon |
| `applies_to` | enum: `all_products`, `specific_products`, `specific_categories` | Tidak | Target penerapan diskon (default: `all_products`) |
| `product_ids` | array\[string] | Tidak | Daftar ID produk (untuk specific\_products) |
| `category_names` | array\[string] | Tidak | Daftar nama kategori (untuk specific\_categories) |
| `coupon_code` | string | Tidak | Kode kupon unik |
| `usage_limit` | number | Tidak | Batas penggunaan (0 = unlimited) |
| `used_count` | number | Tidak | Jumlah sudah digunakan (default: 0) |
| `start_date` | date | Tidak | Tanggal mulai berlaku |
| `end_date` | date | Tidak | Tanggal berakhir |
| `is_active` | boolean | Tidak | Status aktif (default: `true`) |
| `description` | string | Tidak | Deskripsi diskon |

### 7. Expense — Pengeluaran

| Field | Type | Required | Description |
| - | - | - | - |
| `company_id` | string | Ya | ID perusahaan |
| `requester_id` | string | Ya | ID karyawan yang mengajukan |
| `expense_code` | string | Tidak | Kode pengeluaran unik |
| `expense_date` | date | Ya | Tanggal pengeluaran |
| `category` | enum: `salary`, `raw_material`, `operational`, `production_cost`, `travel`, `meals`, `accommodation`, `equipment`, `office_supplies`, `training`, `other` | Ya | Kategori pengeluaran |
| `description` | string | Tidak | Deskripsi pengeluaran |
| `amount` | number | Ya | Jumlah nominal pengeluaran |
| `currency` | string | Tidak | Mata uang (default: `IDR`) |
| `receipt_url` | string | Tidak | URL bukti pengeluaran/invoice |
| `status` | enum: `draft`, `submitted`, `approved`, `rejected`, `paid` | Tidak | Status expense (default: `draft`) |
| `approval_workflow_id` | string | Tidak | ID ApprovalWorkflow |
| `approval_request_id` | string | Tidak | ID ApprovalRequest terkait |
| `approval_status` | enum: `pending`, `approved`, `rejected` | Tidak | Status approval (default: `pending`) |
| `payment_method` | enum: `company_account`, `reimbursement`, `direct_payment` | Tidak | Metode pembayaran |
| `payment_date` | date | Tidak | Tanggal pembayaran |
| `reference_number` | string | Tidak | Nomor referensi pembayaran |
| `notes` | string | Tidak | Catatan tambahan |
| `account_id` | string | Tidak | ID rekening sumber dana pembayaran |
| `recipient_name` | string | Tidak | Nama penerima atau supplier |
| `is_inventory_material` | boolean | Tidak | Flag pembelian bahan baku persediaan (anti double-counting dengan HPP) (default: `false`) |
| `approved_by` | string | Tidak | User ID atau email approver |
| `idempotency_key` | string | Tidak | Kunci idempoten untuk mencegah double submission |

### 8. FinancialGoal — Target Keuangan

| Field | Type | Required | Description |
| - | - | - | - |
| `user_id` | string | Ya | ID pengguna pemilik tujuan |
| `company_id` | string | Tidak | ID perusahaan (null untuk personal) |
| `title` | string | Ya | Judul tujuan keuangan |
| `description` | string | Tidak | Deskripsi detail tujuan |
| `goal_type` | enum: `savings`, `debt_payoff`, `investment`, `expense_reduction` | Ya | Jenis tujuan keuangan |
| `target_amount` | number | Ya | Jumlah target yang ingin dicapai |
| `current_amount` | number | Tidak | Jumlah yang sudah terkumpul/terbayar (default: 0) |
| `deadline` | date | Ya | Tanggal target pencapaian |
| `status` | enum: `active`, `paused`, `completed`, `failed` | Tidak | Status goal (default: `active`) |
| `priority` | enum: `low`, `medium`, `high` | Tidak | Prioritas (default: `medium`) |
| `related_budget_id` | string | Tidak | ID Budget terkait (jika ada) |

### 9. FinancialRecord — Transaksi Universal

| Field | Type | Required | Description |
| - | - | - | - |
| `user_id` | string | Ya | ID pengguna |
| `company_id` | string | Tidak | ID perusahaan (null untuk personal) |
| `account_id` | string | Tidak | ID rekening/kantong sumber dana |
| `type` | enum: `income`, `expense`, `transfer` | Ya | Jenis transaksi |
| `amount` | number | Ya | Jumlah transaksi |
| `category` | string | Tidak | Kategori transaksi |
| `description` | string | Tidak | Deskripsi singkat |
| `date` | date-time | Ya | Tanggal transaksi |
| `attachment_url` | string | Tidak | URL bukti transaksi |
| `source` | enum: `manual`, `ai_text`, `ai_scan`, `pos`, `manufacturing`, `distribution`, `recall`, `stock_opname` | Tidak | Sumber transaksi (default: `manual`) |
| `mode` | enum: `personal`, `business` | Tidak | Mode pencatatan: Pribadi atau Bisnis (default: `personal`) |
| `transfer_to_account_id` | string | Tidak | ID rekening tujuan (untuk type=transfer) |
| `transfer_fee` | number | Tidak | Biaya transfer jika ada (default: 0) |
| `reference_id` | string | Tidak | ID referensi transaksi sumber (invoice, pos, expense) |
| `reference_type` | enum: `invoice_payment`, `pos_transaction`, `expense`, `manual`, `transfer`, `production_order`, `distribution_shipment`, `distribution_return`, `batch_recall`, `stock_opname` | Tidak | Tipe referensi transaksi sumber |
| `idempotency_key` | string | Tidak | Kunci idempoten transaksi keuangan |
| `is_inventory_material` | boolean | Tidak | Flag pembelian bahan baku persediaan (anti double-counting) (default: `false`) |
| `channel_fee` | number | Tidak | Potongan biaya marketplace / platform fee (default: 0) |
| `cogs_amount` | number | Tidak | Biaya pokok penjualan (HPP/COGS) yang dibekukan saat transaksi POS untuk perhitungan laba kotor |
| `tax_amount` | number | Tidak | Jumlah pajak dalam amount (untuk revenue: PPN keluaran) (default: 0) |

### 10. FinancialReportSnapshot — Cache Laporan Keuangan

| Field | Type | Required | Description |
| - | - | - | - |
| `company_id` | string | Ya | ID perusahaan |
| `report_type` | enum: `profit_loss`, `balance_sheet`, `cash_flow`, `budget_vs_actual`, `trial_balance`, `custom` | Ya | Jenis laporan |
| `report_name` | string | Ya | Nama laporan |
| `start_date` | date | Ya | Tanggal mulai periode laporan |
| `end_date` | date | Ya | Tanggal akhir periode laporan |
| `generated_by_user_id` | string | Ya | ID user yang generate laporan |
| `generated_date` | date-time | Ya | Tanggal dan waktu generate |
| `report_data` | object | Ya | JSON data laporan (snapshot) |
| `template_id` | string | Tidak | ID template laporan |
| `notes` | string | Tidak | Catatan tambahan |

### 11. FixedAsset — Aset Tetap

| Field | Type | Required | Description |
| - | - | - | - |
| `company_id` | string | Ya | ID perusahaan |
| `asset_code` | string | Tidak | Kode aset unik |
| `asset_name` | string | Ya | Nama aset tetap |
| `category` | enum: `building`, `equipment`, `vehicle`, `furniture`, `it_assets`, `other` | Ya | Kategori aset |
| `location` | string | Tidak | Lokasi aset di perusahaan |
| `acquisition_date` | date | Ya | Tanggal perolehan aset |
| `acquisition_cost` | number | Ya | Biaya perolehan aset |
| `useful_life_years` | number | Ya | Umur manfaat aset dalam tahun |
| `depreciation_method` | enum: `straight_line`, `declining_balance`, `units_of_production` | Tidak | Metode penyusutan (default: `straight_line`) |
| `depreciation_rate` | number | Tidak | Tarif penyusutan per tahun (%) |
| `accumulated_depreciation` | number | Tidak | Penyusutan terakumulasi (default: 0) |
| `book_value` | number | Tidak | Nilai buku (acquisition\_cost - accumulated\_depreciation) |
| `disposal_date` | date | Tidak | Tanggal pelepasan aset (jika ada) |
| `disposal_value` | number | Tidak | Nilai pelepasan aset |
| `status` | enum: `in_use`, `disposed`, `damaged`, `maintenance` | Tidak | Status aset (default: `in_use`) |
| `gl_account_id` | string | Tidak | ID GLAccount terkait untuk jurnal penyusutan |
| `notes` | string | Tidak | Catatan tambahan |

### 12. GLAccount — Chart of Accounts (COA)

| Field | Type | Required | Description |
| - | - | - | - |
| `company_id` | string | Ya | ID perusahaan |
| `account_code` | string | Ya | Kode akun unik (misalnya: 1000, 2100, 4001) |
| `account_name` | string | Ya | Nama akun |
| `account_type` | enum: `asset`, `liability`, `equity`, `revenue`, `expense` | Ya | Tipe akun untuk klasifikasi |
| `category` | string | Tidak | Kategori akun (misalnya: Current Asset, Fixed Asset, Receivable) |
| `sub_category` | string | Tidak | Sub-kategori akun |
| `parent_account_id` | string | Tidak | ID akun parent untuk hierarki COA |
| `normal_balance` | enum: `debit`, `credit` | Ya | Saldo normal akun |
| `is_active` | boolean | Tidak | Status aktif akun (default: `true`) |
| `description` | string | Tidak | Deskripsi akun |
| `level` | number | Tidak | Level hierarki: 0=HEADER, 1=MAIN, 2=SUB (default: 0) |

### 13. GLJournalEntry — Jurnal Transaksi

| Field | Type | Required | Description |
| - | - | - | - |
| `company_id` | string | Ya | ID perusahaan |
| `entry_date` | date | Ya | Tanggal entri jurnal |
| `reference_number` | string | Tidak | Nomor referensi (misalnya: TRX-001, INV-001) |
| `reference_type` | enum: `manual`, `invoice`, `purchase_order`, `transfer`, `expense` | Tidak | Tipe referensi sumber entri |
| `reference_id` | string | Tidak | ID dokumen sumber (jika ada) |
| `description` | string | Ya | Deskripsi jurnal |
| `line_items` | array\[object] | Ya | Line items dengan debit/credit |
| `line_items[].account_id` | string | — | ID GLAccount |
| `line_items[].account_code` | string | — | Kode akun (denormalized) |
| `line_items[].debit` | number | — | Jumlah debit (default: 0) |
| `line_items[].credit` | number | — | Jumlah kredit (default: 0) |
| `line_items[].description` | string | — | Deskripsi line item |
| `total_debit` | number | Tidak | Total debit (default: 0) |
| `total_credit` | number | Tidak | Total kredit (default: 0) |
| `is_balanced` | boolean | Tidak | Apakah debit = credit (default: `false`) |
| `status` | enum: `draft`, `posted`, `reversed` | Tidak | Status jurnal (default: `draft`) |
| `posted_date` | date | Tidak | Tanggal posting |
| `posted_by` | string | Tidak | User yang memposting |
| `notes` | string | Tidak | Catatan tambahan |

### 14. Investment — Portofolio Investasi

| Field | Type | Required | Description |
| - | - | - | - |
| `user_id` | string | Ya | ID pengguna pemilik investasi |
| `company_id` | string | Tidak | ID perusahaan (null untuk personal) |
| `asset_name` | string | Ya | Nama aset investasi |
| `asset_type` | enum: `stocks`, `mutual_fund`, `bond`, `crypto`, `property`, `other` | Ya | Jenis aset investasi |
| `quantity` | number | Ya | Jumlah/unit kepemilikan |
| `purchase_price` | number | Ya | Harga pembelian per unit |
| `purchase_date` | date | Ya | Tanggal pembelian |
| `current_price` | number | Tidak | Harga pasar saat ini per unit |
| `current_value` | number | Tidak | Total nilai investasi saat ini |
| `currency` | string | Tidak | Mata uang (default: `IDR`) |
| `platform` | string | Tidak | Platform atau perusahaan penyedia investasi |
| `notes` | string | Tidak | Catatan tambahan |

### 15. Invoice — Tagihan B2B

| Field | Type | Required | Description |
| - | - | - | - |
| `company_id` | string | Tidak | ID perusahaan (null untuk personal) |
| `invoice_number` | string | Ya | Nomor invoice unik |
| `invoice_type` | enum: `invoice`, `quotation`, `proforma` | Tidak | Tipe dokumen (default: `invoice`) |
| `customer_id` | string | Tidak | ID customer dari CRM |
| `customer_name` | string | Ya | Nama customer |
| `customer_email` | string | Tidak | Email customer |
| `customer_phone` | string | Tidak | Telepon customer |
| `customer_address` | string | Tidak | Alamat customer |
| `issue_date` | date | Ya | Tanggal invoice diterbitkan |
| `due_date` | date | Tidak | Tanggal jatuh tempo |
| `items` | array\[object] | Ya | Daftar item invoice |
| `items[].description` | string | — | Deskripsi item |
| `items[].quantity` | number | — | Jumlah |
| `items[].unit_price` | number | — | Harga satuan |
| `items[].total` | number | — | Total per item |
| `subtotal` | number | Tidak | Subtotal |
| `tax_percentage` | number | Tidak | Persentase pajak (default: 0) |
| `tax_amount` | number | Tidak | Jumlah pajak (default: 0) |
| `discount_percentage` | number | Tidak | Persentase diskon (default: 0) |
| `discount_amount` | number | Tidak | Jumlah diskon (default: 0) |
| `total` | number | Ya | Total tagihan |
| `notes` | string | Tidak | Catatan |
| `terms` | string | Tidak | Syarat dan ketentuan |
| `status` | enum: `draft`, `sent`, `partially_paid`, `paid`, `overdue`, `cancelled` | Tidak | Status invoice (default: `draft`) |
| `paid_amount` | number | Tidak | Jumlah sudah dibayar (default: 0) |
| `paid_date` | date | Tidak | Tanggal lunas |
| `po_number` | string | Tidak | Nomor Customer PO / Purchase Order rujukan |
| `source_type` | enum: `manual`, `customer_po`, `order`, `quotation`, `pos_transaction` | Tidak | Sumber pembentukan invoice untuk mencegah double-sale (default: `manual`) |
| `source_id` | string | Tidak | ID entitas sumber (CustomerPO id atau QuinnOrder id) |
| `delivery_status` | enum: `pending`, `partially_delivered`, `delivered` | Tidak | Status pengiriman barang fisik independen dari status bayar (default: `pending`) |
| `payment_term_days` | number | Tidak | Jangka waktu pembayaran dalam hari (default: 30) |
| `deliveries` | array\[object] | Tidak | Histori pengiriman bertahap (partial delivery) |
| `deliveries[].delivery_id` | string | — | ID pengiriman |
| `deliveries[].delivery_date` | string | — | Tanggal pengiriman |
| `deliveries[].recipient_name` | string | — | Nama penerima |
| `deliveries[].origin_location` | string | — | Lokasi asal |
| `deliveries[].tracking_reference` | string | — | Nomor resi/tracking |
| `deliveries[].proof_url` | string | — | URL bukti kirim |
| `deliveries[].notes` | string | — | Catatan pengiriman |
| `deliveries[].items` | array\[object] | — | Item yang dikirim |
| `deliveries[].items[].sku` | string | — | SKU produk |
| `deliveries[].items[].description` | string | — | Deskripsi item |
| `deliveries[].items[].quantity` | number | — | Jumlah dikirim |
| `deliveries[].items[].lot_id` | string | — | ID lot produksi |
| `snapshot` | object | Tidak | Snapshot data final saat invoice diterbitkan (immutable record) |
| `is_locked` | boolean | Tidak | Penanda draft telah diterbitkan dan tidak diedit bebas (default: `false`) |
| `payments` | array\[object] | Tidak | Histori pembayaran bertahap (ledger) |
| `payments[].id` | string | — | ID pembayaran |
| `payments[].date` | string | — | Tanggal pembayaran |
| `payments[].amount` | number | — | Jumlah bayar |
| `payments[].memo` | string | — | Memo pembayaran |
| `payments[].account_id` | string | — | ID rekening penerima |
| `payments[].payment_method` | string | — | Metode pembayaran |
| `payments[].recorded_by` | string | — | User yang mencatat |
| `payments[].recorded_at` | string | — | Waktu pencatatan |

### 16. InvoicePayment — Ledger Pembayaran Invoice

| Field | Type | Required | Description |
| - | - | - | - |
| `company_id` | string | Ya | ID perusahaan |
| `invoice_id` | string | Ya | ID invoice yang dibayar |
| `amount` | number | Ya | Jumlah pembayaran |
| `payment_date` | date | Ya | Tanggal pembayaran |
| `memo` | string | Tidak | Memo/catatan pembayaran |
| `account_id` | string | Tidak | ID rekening penerima |
| `payment_method` | string | Tidak | Metode pembayaran |
| `recorded_by` | string | Tidak | User yang mencatat pembayaran |
| `recorded_at` | date-time | Tidak | Waktu pencatatan |
| `idempotency_key` | string | Ya | Kunci idempoten untuk mencegah duplikasi |
| `financial_record_id` | string | Tidak | ID FinancialRecord terkait |
| `status` | enum: `posted`, `needs_reconciliation` | Ya | Status posting (default: `posted`) |
| `customer_id` | string | Tidak | ID customer |
| `customer_name` | string | Tidak | Nama customer |
| `reference_number` | string | Tidak | Nomor referensi pembayaran |
| `proof_url` | string | Tidak | URL bukti transfer |
| `verification_status` | enum: `verified`, `pending`, `rejected` | Tidak | Status verifikasi tiga tahap (default: `verified`) |
| `verified_by` | string | Tidak | User yang memverifikasi |
| `verified_at` | date-time | Tidak | Waktu verifikasi |
| `reconciliation_reason` | string | Tidak | Alasan rekonsiliasi (jika needs\_reconciliation) |

### 17. PurchaseOrder — Purchase Order ke Supplier

| Field | Type | Required | Description |
| - | - | - | - |
| `company_id` | string | Ya | ID perusahaan |
| `po_number` | string | Tidak | Nomor PO unik |
| `supplier_id` | string | Ya | ID supplier |
| `supplier_name` | string | Tidak | Nama supplier |
| `po_date` | date | Ya | Tanggal PO dibuat |
| `expected_delivery_date` | date | Tidak | Tanggal perkiraan pengiriman |
| `items` | array\[object] | Ya | Daftar item yang dipesan |
| `items[].product_id` | string | — | ID produk |
| `items[].product_name` | string | — | Nama produk |
| `items[].quantity` | number | — | Jumlah dipesan |
| `items[].unit` | string | — | Satuan |
| `items[].unit_price` | number | — | Harga satuan |
| `items[].total_price` | number | — | Total per item |
| `items[].received_quantity` | number | — | Jumlah sudah diterima (default: 0) |
| `subtotal` | number | Tidak | Subtotal (default: 0) |
| `tax_amount` | number | Tidak | Jumlah pajak (default: 0) |
| `shipping_cost` | number | Tidak | Biaya pengiriman (default: 0) |
| `total_amount` | number | Tidak | Total keseluruhan |
| `status` | enum: `draft`, `sent`, `confirmed`, `received`, `invoiced`, `cancelled` | Tidak | Status PO (default: `draft`) |
| `received_status` | enum: `pending`, `partially_received`, `fully_received` | Tidak | Status penerimaan barang (default: `pending`) |
| `notes` | string | Tidak | Catatan tambahan |

### 18. Supplier — Data Supplier

| Field | Type | Required | Description |
| - | - | - | - |
| `company_id` | string | Ya | ID perusahaan |
| `supplier_code` | string | Tidak | Kode supplier unik |
| `company_name` | string | Ya | Nama perusahaan supplier |
| `contact_person` | string | Tidak | Nama kontak |
| `email` | email | Tidak | Alamat email |
| `phone` | string | Tidak | Nomor telepon |
| `address` | string | Tidak | Alamat |
| `city` | string | Tidak | Kota |
| `country` | string | Tidak | Negara |
| `tax_id` | string | Tidak | NPWP atau Tax ID |
| `bank_account` | string | Tidak | Nomor rekening bank |
| `bank_name` | string | Tidak | Nama bank |
| `payment_terms` | string | Tidak | Syarat pembayaran (misalnya: NET 30, COD) |
| `currency` | string | Tidak | Mata uang (default: `IDR`) |
| `rating` | number | Tidak | Rating supplier (1-5) |
| `is_active` | boolean | Tidak | Status aktif (default: `true`) |
| `notes` | string | Tidak | Catatan tambahan |
| `supplied_materials` | array\[string] | Tidak | Daftar bahan baku/komoditas yang dipasok (RCV-01) |
| `is_locked` | boolean | Tidak | Data terkunci karena ada PO aktif; field nama, NPWP, rekening tidak bisa diedit (DQ-01) (default: `false`) |
| `last_validated_at` | date-time | Tidak | Terakhir validasi data supplier (DQ-01) |
| `validation_score` | number | Tidak | Skor validasi kelengkapan data supplier 0-100 (DQ-01) (default: 0) |
| `supplier_type` | enum: `general`, `farmer`, `distributor`, `importer` | Tidak | Klasifikasi supplier untuk aturan penerimaan berbeda (default: `general`) |

### 19. TransactionCategory — Kategori Transaksi

| Field | Type | Required | Description |
| - | - | - | - |
| `user_id` | string | Ya | ID pengguna yang membuat kategori |
| `name` | string | Ya | Nama kategori |
| `description` | string (max 1000) | Tidak | Penjelasan singkat mengenai jenis transaksi dalam kategori ini |
| `type` | enum: `income`, `expense` | Ya | Jenis kategori: pemasukan atau pengeluaran |
| `mode` | enum: `personal`, `business` | Ya | Mode kategori: Pribadi atau Bisnis |
| `company_id` | string | Tidak | ID perusahaan (null untuk kategori personal) |
| `icon` | string | Tidak | Emoji atau nama ikon untuk kategori |

***

## Enum Reference Tables

### FinancialRecord — `source` (Sumber Transaksi)

| Nilai | Deskripsi |
| - | - |
| `manual` | Input manual oleh pengguna |
| `ai_text` | Dari input teks AI (chatbot) |
| `ai_scan` | Dari scan gambar/struk oleh AI |
| `pos` | Dari transaksi POS (point of sale) |
| `manufacturing` | Dari modul manufacturing (production batch) |
| `distribution` | Dari modul distribusi (shipment/return) |
| `recall` | Dari batch recall |
| `stock_opname` | Dari stock opname inventory |

### FinancialRecord — `reference_type` (Tipe Referensi)

| Nilai | Deskripsi |
| - | - |
| `invoice_payment` | Pembayaran invoice B2B |
| `pos_transaction` | Transaksi POS kasir |
| `expense` | Expense claim |
| `manual` | Transaksi manual tanpa referensi |
| `transfer` | Transfer antar rekening |
| `production_order` | Production batch manufacturing |
| `distribution_shipment` | Pengiriman distribusi |
| `distribution_return` | Retur distribusi |
| `batch_recall` | Recall batch produk |
| `stock_opname` | Stock opname penyesuaian persediaan |

### FinancialRecord — `type` (Jenis Transaksi)

| Nilai | Deskripsi |
| - | - |
| `income` | Pemasukan (saldo bertambah) |
| `expense` | Pengeluaran (saldo berkurang) |
| `transfer` | Transfer antar rekening (satu rekening berkurang, yang lain bertambah) |

### GLAccount — `account_type` (Tipe Akun COA)

| Nilai | Saldo Normal | Kode COA | Deskripsi |
| - | - | - | - |
| `asset` | Debit | 1-xxxx | Aset: Kas, Bank, Piutang, Persediaan, Aset Tetap |
| `liability` | Kredit | 2-xxxx | Liabilitas: Hutang Usaha, Hutang Pajak, Hutang Lainnya |
| `equity` | Kredit | 3-xxxx | Ekuitas: Modal, Laba Ditahan, Prive |
| `revenue` | Kredit | 4-xxxx | Pendapatan: Penjualan, Pendapatan Jasa, Pendapatan Lain |
| `expense` | Debit | 5-xxxx | Beban: HPP, Gaji, Sewa, Listrik, Marketing |

### GLAccount — `level` (Level Hierarki COA)

| Nilai | Label | Deskripsi |
| - | - | - |
| 0 | HEADER | Akun ringkasan level atas (e.g., "Aset Lancar") |
| 1 | MAIN | Akun utama di bawah header (e.g., "Kas & Bank") |
| 2 | SUB | Akun detail/sub akun (e.g., "Kas IDR", "BCA Rupiah") |

### GLJournalEntry — `reference_type` (Tipe Referensi Jurnal)

| Nilai | Deskripsi |
| - | - |
| `manual` | Jurnal manual yang diinput langsung |
| `invoice` | Jurnal dari invoice B2B |
| `purchase_order` | Jurnal dari purchase order |
| `transfer` | Jurnal dari transfer antar rekening |
| `expense` | Jurnal dari expense claim |

### GLJournalEntry — `status` (Status Jurnal)

| Nilai | Deskripsi |
| - | - |
| `draft` | Jurnal belum diposting, masih bisa diedit |
| `posted` | Jurnal sudah diposting, masuk ke buku besar |
| `reversed` | Jurnal dibalik (reversal) untuk koreksi |

### Account — `type` (Tipe Rekening)

| Nilai | Deskripsi |
| - | - |
| `cash` | Kas tunai |
| `bank` | Rekening bank |
| `e-wallet` | Dompet elektronik (GoPay, DANA, OVO, dll) |
| `other` | Jenis lainnya |

### Invoice — `status` (Status Invoice)

| Nilai | Deskripsi |
| - | - |
| `draft` | Draft, belum dikirim ke customer |
| `sent` | Sudah dikirim, menunggu pembayaran |
| `partially_paid` | Sudah dibayar sebagian |
| `paid` | Sudah dibayar lunas |
| `overdue` | Lewat jatuh tempo, piutang |
| `cancelled` | Dibatalkan |

### Invoice — `invoice_type` (Tipe Dokumen)

| Nilai | Deskripsi |
| - | - |
| `invoice` | Tagihan resmi |
| `quotation` | Penawaran harga (belum final) |
| `proforma` | Invoice proforma (pernyataan harga awal) |

### Invoice — `source_type` (Sumber Invoice)

| Nilai | Deskripsi |
| - | - |
| `manual` | Dibuat manual oleh pengguna |
| `customer_po` | Dibuat dari Customer Purchase Order |
| `order` | Dibuat dari QuinnOrder |
| `quotation` | Dibuat dari quotation yang diterima |
| `pos_transaction` | Dibuat dari transaksi POS |

### Invoice — `delivery_status` (Status Pengiriman)

| Nilai | Deskripsi |
| - | - |
| `pending` | Belum ada pengiriman |
| `partially_delivered` | Sudah dikirim sebagian |
| `delivered` | Semua barang sudah dikirim |

### InvoicePayment — `verification_status` (Status Verifikasi)

| Nilai | Deskripsi |
| - | - |
| `verified` | Pembayaran terverifikasi,计入 paid\_amount |
| `pending` | Menunggu review finance, TIDAK计入 paid\_amount |
| `rejected` | Ditolak, perlu rekonsiliasi |

### InvoicePayment — `status` (Status Posting)

| Nilai | Deskripsi |
| - | - |
| `posted` | Pembayaran sudah diposting ke ledger |
| `needs_reconciliation` | Perlu rekonsiliasi karena ada ketidakcocokan |

### Expense — `category` (Kategori Pengeluaran)

| Nilai | Deskripsi |
| - | - |
| `salary` | Gaji dan upah karyawan |
| `raw_material` | Pembelian bahan baku |
| `operational` | Biaya operasional harian |
| `production_cost` | Biaya produksi |
| `travel` | Biaya perjalanan dinas |
| `meals` | Biaya makan dan konsumsi |
| `accommodation` | Biaya akomodasi |
| `equipment` | Pembelian peralatan |
| `office_supplies` | Perlengkapan kantor |
| `training` | Biaya pelatihan |
| `other` | Lainnya |

### Expense — `status` (Status Expense)

| Nilai | Deskripsi |
| - | - |
| `draft` | Draft, belum disubmit |
| `submitted` | Sudah disubmit untuk approval |
| `approved` | Disetujui oleh approver |
| `rejected` | Ditolak oleh approver |
| `paid` | Sudah dibayarkan |

### Expense — `approval_status` (Status Approval)

| Nilai | Deskripsi |
| - | - |
| `pending` | Menunggu approval |
| `approved` | Sudah disetujui |
| `rejected` | Sudah ditolak |

### Expense — `payment_method` (Metode Pembayaran)

| Nilai | Deskripsi |
| - | - |
| `company_account` | Dibayar dari rekening perusahaan |
| `reimbursement` | Reimbursement ke karyawan |
| `direct_payment` | Pembayaran langsung |

### PurchaseOrder — `status` (Status PO)

| Nilai | Deskripsi |
| - | - |
| `draft` | Draft, belum dikirim ke supplier |
| `sent` | Sudah dikirim ke supplier |
| `confirmed` | Supplier mengkonfirmasi pesanan |
| `received` | Barang sudah diterima |
| `invoiced` | Invoice supplier sudah diterima |
| `cancelled` | PO dibatalkan |

### PurchaseOrder — `received_status` (Status Penerimaan Barang)

| Nilai | Deskripsi |
| - | - |
| `pending` | Belum ada barang diterima |
| `partially_received` | Barang diterima sebagian |
| `fully_received` | Semua barang sudah diterima |

### ApprovalWorkflow — `document_type` (Tipe Dokumen Approval)

| Nilai | Deskripsi |
| - | - |
| `expense_request` | Pengajuan expense |
| `leave_request` | Pengajuan cuti |
| `purchase_order` | Purchase order |
| `discount_request` | Pengajuan diskon |
| `budget_adjustment` | Penyesuaian anggaran |

### ApprovalRequest — `overall_status` (Status Keseluruhan)

| Nilai | Deskripsi |
| - | - |
| `pending` | Menunggu approval |
| `approved` | Semua level sudah approve |
| `rejected` | Salah satu level menolak |
| `on_hold` | Ditunda sementara |

### Budget — `period` (Periode Anggaran)

| Nilai | Deskripsi |
| - | - |
| `monthly` | Bulanan |
| `quarterly` | Kuartalan (3 bulan) |
| `yearly` | Tahunan |
| `custom` | Periode kustom |

### Budget — `status` (Status Anggaran)

| Nilai | Deskripsi |
| - | - |
| `active` | Anggaran aktif |
| `completed` | Periode sudah berakhir |
| `archived` | Diarsipkan |

### FinancialGoal — `goal_type` (Jenis Tujuan)

| Nilai | Deskripsi |
| - | - |
| `savings` | Tabungan |
| `debt_payoff` | Pelunasan hutang |
| `investment` | Investasi |
| `expense_reduction` | Pengurangan pengeluaran |

### FinancialGoal — `status` (Status Goal)

| Nilai | Deskripsi |
| - | - |
| `active` | Sedang dijalankan |
| `paused` | Dijeda sementara |
| `completed` | Target tercapai |
| `failed` | Gagal mencapai target |

### FinancialGoal — `priority` (Prioritas)

| Nilai | Deskripsi |
| - | - |
| `low` | Prioritas rendah |
| `medium` | Prioritas sedang |
| `high` | Prioritas tinggi |

### FinancialReportSnapshot — `report_type` (Jenis Laporan)

| Nilai | Deskripsi |
| - | - |
| `profit_loss` | Laporan Laba Rugi |
| `balance_sheet` | Neraca (Laporan Posisi Keuangan) |
| `cash_flow` | Laporan Arus Kas |
| `budget_vs_actual` | Perbandingan Budget vs Aktual |
| `trial_balance` | Neraca Saldo |
| `custom` | Laporan kustom |

### FixedAsset — `category` (Kategori Aset)

| Nilai | Deskripsi |
| - | - |
| `building` | Bangunan |
| `equipment` | Peralatan |
| `vehicle` | Kendaraan |
| `furniture` | Perabot dan furnitur |
| `it_assets` | Aset IT (komputer, server, dll) |
| `other` | Lainnya |

### FixedAsset — `depreciation_method` (Metode Penyusutan)

| Nilai | Deskripsi |
| - | - |
| `straight_line` | Garis lurus (cost / useful\_life) |
| `declining_balance` | Saldo menurun (double declining) |
| `units_of_production` | Berdasarkan unit produksi |

### FixedAsset — `status` (Status Aset)

| Nilai | Deskripsi |
| - | - |
| `in_use` | Sedang digunakan |
| `disposed` | Sudah dilepas/dijual |
| `damaged` | Rusak |
| `maintenance` | Dalam perawatan |

### Investment — `asset_type` (Jenis Investasi)

| Nilai | Deskripsi |
| - | - |
| `stocks` | Saham |
| `mutual_fund` | Reksa dana |
| `bond` | Obligasi |
| `crypto` | Cryptocurrency |
| `property` | Properti |
| `other` | Lainnya |

### Discount — `discount_type` (Jenis Diskon)

| Nilai | Deskripsi |
| - | - |
| `percentage` | Persentase dari harga |
| `fixed_amount` | Nominal tetap |
| `buy_x_get_y` | Beli X gratis Y |
| `coupon_code` | Kode kupon |

### Discount — `applies_to` (Target Penerapan)

| Nilai | Deskripsi |
| - | - |
| `all_products` | Semua produk |
| `specific_products` | Produk tertentu (via product\_ids) |
| `specific_categories` | Kategori tertentu (via category\_names) |

### Supplier — `supplier_type` (Tipe Supplier)

| Nilai | Deskripsi |
| - | - |
| `general` | Supplier umum |
| `farmer` | Petani/pemasok hasil pertanian |
| `distributor` | Distributor |
| `importer` | Importir |

### TransactionCategory — `type` (Jenis Kategori)

| Nilai | Deskripsi |
| - | - |
| `income` | Kategori pemasukan |
| `expense` | Kategori pengeluaran |

### TransactionCategory — `mode` (Mode Kategori)

| Nilai | Deskripsi |
| - | - |
| `personal` | Kategori pribadi |
| `business` | Kategori bisnis/perusahaan |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.