# Modul Expenses

## Konsep

- Per hari (bukan per shift)
- Per item: kategori, jumlah, keterangan, bukti foto opsional
- Operator input → submit → Manager approve
- Approved = Locked: tidak bisa diedit/didelete. Hanya user dengan `expenses:approve` yang bisa unlock.

## Status Flow

```
Draft → Submitted → Approved (= Locked)
           ↑             ↓
        Recall        Rejected → edit → Re-submit
                                            ↑
                           Unlock (by approver, wajib isi alasan)
```

- **Submit**: operator/creator submit draft ke manager
- **Recall**: operator recall kembali ke draft (sebelum admin act)
- **Review**: approver bisa approve atau reject (dengan catatan)
- **Unlock**: approver unlock dari approved → draft (alasan wajib)

## BAST PDF

✅ `GET /api/v1/spbus/{spbu_id}/expenses/{id}/bast-pdf` — tersedia setelah approved.

## Schema

```sql
expense_kategori (id, spbu_id, nama, urutan, is_active, deleted_at)

expenses (id, spbu_id, laporan_shift_id,
          tanggal, kategori_id, keterangan, jumlah, bukti_url,
          -- Approval audit
          status,                   -- draft | submitted | approved | rejected
          submitted_by_id, submitted_at,
          reviewed_by_id, reviewed_at, catatan_review,
          recalled_by_id, recalled_at,
          unlocked_by_id, unlocked_at, unlock_reason,
          created_by_id, created_at, updated_at)
```

**Migration:** `f0i1j2k3l4m5` — tambah `StatusExpense` enum + 11 kolom audit.

## API Endpoints

```
GET/POST  /api/v1/spbus/{spbu_id}/expenses
GET       /api/v1/spbus/{spbu_id}/expenses/kategori
POST      /api/v1/spbus/{spbu_id}/expenses/kategori
GET       /api/v1/spbus/{spbu_id}/expenses/{id}
PATCH     /api/v1/spbus/{spbu_id}/expenses/{id}
DELETE    /api/v1/spbus/{spbu_id}/expenses/{id}
POST      /api/v1/spbus/{spbu_id}/expenses/{id}/bukti      ← upload foto nota
POST      /api/v1/spbus/{spbu_id}/expenses/{id}/submit
POST      /api/v1/spbus/{spbu_id}/expenses/{id}/recall
POST      /api/v1/spbus/{spbu_id}/expenses/{id}/review     ← { action: approve|reject, catatan? }
POST      /api/v1/spbus/{spbu_id}/expenses/{id}/unlock     ← { alasan: string }
GET       /api/v1/spbus/{spbu_id}/expenses/{id}/bast-pdf
```

## Files

- Model: `backend/app/models/expenses.py` — `ExpenseKategori`, `Expense`, `StatusExpense`
- Router: `backend/app/routers/expenses.py`
- Service: `backend/app/services/expense_service.py`
- Frontend: `frontend/src/app/(dashboard)/expenses/expenses-client.tsx`
- Hooks: `frontend/src/lib/hooks/useExpenses.ts`
