# 📋 Alur Kerja Komprehensif Sistem Amandemen Invoice (Everest ERP) — Developer & Technical Architecture

Dokumen ini merangkum seluruh arsitektur teknis, alur logika sistem, lapisan gerbang validasi, perlakuan akuntansi & perpajakan, serta sinkronisasi database untuk modul **Amandemen Invoice** sejak inisiasi awal hingga cetakan invoice fisik.

> [!NOTE]
> Untuk panduan praktis operasional berbasis tampilan layar antarmuka bagi Pengguna / Operator, silakan buka: [WORKFLOW_AMANDEMEN_INVOICE_PENGGUNA.md](file:///w:/everest_11sept/application/modules/amandemen_invoice/WORKFLOW_AMANDEMEN_INVOICE_PENGGUNA.md).

---

## 1. Arsitektur & Komponen Modul

Fitur amandemen invoice terdistribusi dalam arsitektur HMVC CI3 dan model domain service:

```
application/
├── models/Coms/
│   └── ComAmandemenInvoice.php          # Domain Model: Snapshot, kalkulasi, mutasi jurnal, audit trail
├── modules/
│   ├── amandemen_invoice/               # Modul Utama Amandemen
│   │   ├── controllers/
│   │   │   ├── Modul_Controller.php     # Base controller amandemen
│   │   │   ├── Create.php               # Form input revisi, drag & drop item, live preview
│   │   │   ├── FollowUp.php             # Gerbang validasi (Fail-Fast) & eksekusi ACID
│   │   │   └── Report.php               # Histori amandemen, audit trail, fungsi restore/rollback
│   │   └── views/
│   │       ├── v_amandemen_form.php     # Antarmuka interaktif drag & drop item amandemen
│   │       ├── v_amandemen_report.php   # Tampilan audit log riwayat amandemen
│   │       └── v_amandemen_selector.php # Modal picker pemilihan item dari SPK/RAB proyek
│   ├── invoicing/                       # Modul Invoice Asli
│   │   ├── controllers/Printing.php     # Controller pencetakan nota/invoice resmi
│   │   └── views/printing.php           # Template render HTML nota (opsi 1 s/d 6)
│   └── penerimaanprojek/                # Modul Induk Penerimaan & Rekonsiliasi Finansial
│       └── controllers/Transaksi.php    # viewResume, rekonsiliasi proyek & link buku besar
```

---

## 2. Diagram Alur Kerja End-to-End (Mermaid Workflow)

```mermaid
flowchart TD
    Start["User Membuka Invoice Terbit"]
    CheckNeed{"Perlu Revisi Tagihan?"}
    Selesai["Gunakan Invoice Normal"]
    OpenForm["Buka Modul Amandemen Invoice (Create::index)"]
    LoadData["Baca Data Header, Detail, Registry, dan e-Faktur DJP"]
    UserEdit["User Mengubah Nilai / Item (Harga, Qty, Reorder, Notes Client)"]
    SubmitAmandemen["Submit Form ke Backend (FollowUp::validate_and_save)"]

    Start --> CheckNeed
    CheckNeed -- "Tidak" --> Selesai
    CheckNeed -- "Ya" --> OpenForm
    OpenForm --> LoadData
    LoadData --> UserEdit
    UserEdit --> SubmitAmandemen

    subgraph Gatekeeper [Layer Validasi Gerbang Fail-Fast]
        ValItems{"Item Valid dan Tagihan Positif?"}
        RejectZero["Tolak: Tagihan Nol atau Negatif"]

        ValTaxStatus{"Status e-Faktur APPROVED_DJP?"}
        TaxChoice{"User Setuju Serap Selisih Pajak?"}
        RejectTax["Tolak: Wajib Pembatalan Faktur DJP atau Faktur Pengganti 011"]

        UnderreportCheck{"Tagihan Baru Tidak Melebihi Tagihan Awal?"}
        RejectOmzet["Tolak Keras: Kenaikan Omzet Wajib Faktur Pengganti di DJP"]

        SetAbsorb["Set Flag: absorb_tax = TRUE (Selisih PPN Diserap ke Biaya Usaha)"]
        TaxNormal["Set Flag: absorb_tax = FALSE (Reset Antrean Pajak 110r)"]

        ValCashReceipt{"Tagihan Baru Tidak Kurang Dari Kasir Terbayar?"}
        RejectCash["Tolak: Terjadi Lebih Bayar Kasir"]

        ValItems -- "Tidak" --> RejectZero
        ValItems -- "Ya" --> ValTaxStatus

        ValTaxStatus -- "Ya" --> TaxChoice
        TaxChoice -- "Tidak" --> RejectTax
        TaxChoice -- "Ya" --> UnderreportCheck

        UnderreportCheck -- "Kenaikan Omzet" --> RejectOmzet
        UnderreportCheck -- "Penurunan / Tetap" --> SetAbsorb

        ValTaxStatus -- "Belum Approved / Draft" --> TaxNormal

        SetAbsorb --> ValCashReceipt
        TaxNormal --> ValCashReceipt

        ValCashReceipt -- "Kurang Dari Kasir" --> RejectCash
    end

    SubmitAmandemen --> ValItems

    subgraph Execution [Eksekusi Transaksi Database ACID]
        ExecStart["Mulai Transaksi Database ($this->db->trans_start)"]
        StepSnap["1. Simpan Snapshot Audit Lengkap (transaksi_amandemen_history)"]
        StepRel["2. Reorganisasi Data Relasional (Soft-delete & Insert Urutan Baru)"]
        StepHeader["3. Update Header Transaksi (transaksi_nilai, DPP, PPN, Notes)"]
        StepSyncParent["4. Sinkronisasi Parent & SPK (Trx #7499, Proyek #235, Payment Source)"]
        StepAccounting["5. Rekonsiliasi Jurnal & Mutasi (Piutang, Penjualan, Beban Pajak 601000036)"]
        StepRegistry["6. Update Blob NoSQL Registry (main, items5_sum, master_values)"]
        ExecEnd["Selesaikan Transaksi Database ($this->db->trans_complete)"]

        ExecStart --> StepSnap
        StepSnap --> StepRel
        StepRel --> StepHeader
        StepHeader --> StepSyncParent
        StepSyncParent --> StepAccounting
        StepAccounting --> StepRegistry
        StepRegistry --> ExecEnd
    end

    ValCashReceipt -- "Valid" --> ExecStart

    CheckCommit{"Transaksi DB Berhasil?"}
    Rollback["Rollback Database Otomatis"]
    Reload["Reload Halaman Invoice (?saved=1)"]

    ExecEnd --> CheckCommit
    CheckCommit -- "Gagal" --> Rollback
    CheckCommit -- "Berhasil" --> Reload

    subgraph PrintingView [Pencetakan dan Rekonsiliasi]
        PrintInvoice["Cetak Invoice Resmi (Printing::viewReceiptReg)"]
        LayoutRender["Format Cetak Opsi 1-6: Tabel Rapi, DPP, PPN, Grand Total & Terbilang Valid"]
        ReconResume["Lihat Resume Finansial Proyek (penerimaanprojek/Transaksi/viewResume)"]
        HistoryLog["Rincian Audit Amandemen Muncul dan Link Buku Besar Bersih (date2 Y-m-d)"]

        PrintInvoice --> LayoutRender
        ReconResume --> HistoryLog
    end

    Reload --> PrintInvoice
    PrintInvoice --> ReconResume

    classDef startEnd fill:#2d3748,stroke:#1a202c,stroke-width:2px,color:#fff;
    classDef process fill:#3182ce,stroke:#2b6cb0,stroke-width:2px,color:#fff;
    classDef decision fill:#d69e2e,stroke:#b7791f,stroke-width:2px,color:#fff;
    classDef danger fill:#e53e3e,stroke:#9b2c2c,stroke-width:2px,color:#fff;
    classDef success fill:#38a169,stroke:#276749,stroke-width:2px,color:#fff;
    classDef db fill:#4a5568,stroke:#2d3748,stroke-width:2px,color:#fff;

    class Start,Selesai startEnd;
    class OpenForm,LoadData,UserEdit,SubmitAmandemen,SetAbsorb,TaxNormal,ExecStart,ExecEnd,PrintInvoice,ReconResume process;
    class CheckNeed,ValItems,ValTaxStatus,TaxChoice,UnderreportCheck,ValCashReceipt,CheckCommit decision;
    class RejectZero,RejectTax,RejectOmzet,RejectCash,Rollback danger;
    class Reload,LayoutRender,HistoryLog success;
    class StepSnap,StepRel,StepHeader,StepSyncParent,StepAccounting,StepRegistry db;
```

---

## 3. Tahapan Rinci Alur Kerja Teknis

### Tahap 1: Inisiasi & Pengambilan Data (`Create.php`)
1. User mengklik tombol **"Amandemen Invoice"** pada antarmuka cetak atau daftar invoice.
2. Endpoint `amandemen_invoice/Create/index/$invoice_id` membaca:
   - Header transaksi asli dari tabel `transaksi`.
   - Data fisik item dari `transaksi_data` dan blob `transaksi_data_registry` (khususnya field `items5_sum` untuk project).
   - Status e-Faktur dari tabel `transaksi_efaktur` (apakah sudah berstatus `APPROVED_DJP`).
3. Antarmuka formulir menampilkan:
   - Tabel interaktif dengan kemampuan **Drag & Drop reorder**.
   - Input harga satuan dan kuantitas per baris material/jasa.
   - Textarea **Notes Client** (teks yang dicetak pada invoice fisik konsumen).
   - Textarea **Catatan Amandemen Internal** (khusus riwayat audit internal).
   - Jika faktur telah `APPROVED_DJP`, sistem memunculkan checkbox peringatan **Penyerapan Selisih Pajak Perusahaan**.

---

### Tahap 2: Gerbang Validasi Berlapis (`FollowUp.php`)
Sebelum transaksi database dieksekusi, sistem menjalankan 3 lapis validasi ketat (*Early Validation Pattern*):

| Lapisan Validasi | Kondisi yang Diuji | Tindakan Jika Gagal |
|---|---|---|
| **Lapis 0: Integritas Input** | Tagihan baru harus berupa angka positif (`> Rp 0`). | Ditolak seketika (*fail-fast*). |
| **Lapis 1: Status Pajak (PER-03/PJ/2022)** | Jika status `APPROVED_DJP`, user **wajib** mencentang persetujuan penyerapan pajak. | Ditolak dengan instruksi Faktur Pengganti (011). |
| **Lapis 1b: Anti-Underreporting Guard** | Penyerapan pajak **hanya boleh** jika nilai tagihan baru $\le$ tagihan awal. Jika omzet naik, tidak boleh diserap internal karena ada kewajiban setor PPN lebih besar ke negara. | Ditolak keras untuk mencegah pidana pajak kurang bayar. |
| **Lapis 2: Anti-Overpayment Guard** | Tagihan baru tidak boleh lebih kecil dari uang kasir yang telah diterima (`transaksi_dibayar`). | Ditolak agar tidak timbul lebih bayar liar tanpa retur kasir resmi. |

---

### Tahap 3: Eksekusi Transaksi ACID (`ComAmandemenInvoice.php`)
Setelah seluruh validasi lolos, sistem menjalankan transaksi DB terbungkus `$this->db->trans_start()`:

```mermaid
sequenceDiagram
    autonumber
    participant C as FollowUp Controller
    participant M as ComAmandemenInvoice
    participant DB as MySQL Database
    participant H as Audit History

    C->>M: createAuditSnapshot(invoice_id)
    M->>DB: Baca Header, Data, Jurnal, Registry
    M->>H: Simpan Snapshot JSON ke transaksi_amandemen_history
    
    C->>M: processAmandemenJSON(params, absorb_tax)
    
    Note over M,DB: 1. Penataan Data Fisik Relasional
    M->>DB: UPDATE transaksi_data SET trash='1' (Soft Delete)
    M->>DB: INSERT transaksi_data baru (Urutan Drag & Drop Terjaga)
    M->>DB: UPDATE transaksi (Nilai, DPP, PPN, Notes, indexing_details)

    Note over M,DB: 2. Rekonsiliasi Pajak & Keuangan
    alt absorb_tax bernilai TRUE (Penyerapan Pajak)
        M->>DB: Jurnal Storno Piutang Dagang (1010020010) Kredit
        M->>DB: Jurnal Penyesuaian Penjualan (4010) Debet
        M->>DB: Jurnal Selisih PPN ke Beban Penjualan Lainnya (601000036) Debet
        M->>DB: e-Faktur Asli DJP Dipertahankan Utuh
    else absorb_tax bernilai FALSE (Prosedur Normal)
        M->>DB: Jurnal Penyesuaian Normal (Piutang, Penjualan, PPN 2030060)
        M->>DB: Reset Antrean Pajak 110r & Nonaktifkan Draft 110e
    end

    Note over M,DB: 3. Sinkronisasi Kartu Piutang & Registry
    M->>DB: UPDATE transaksi_payment_source (Plafon, Tagihan Asal, Sisa Tagihan)
    M->>DB: UPDATE project_produk (Nilai Kontrak Proyek)
    M->>DB: UPDATE transaksi_data_registry (main, items5_sum, tableIn_master_values)

    M-->>C: Return Tagihan Baru
    C->>DB: trans_complete (Commit Otomatis)
```

---

### Tahap 4: Skema Akuntansi Penyerapan Pajak (Kasus Khusus)

Jika invoice yang diamandemen telah terbit faktur pajak resminya di DJP dan perusahaan memilih menyerap selisih PPN internal:

* **Nilai Awal:** DPP Rp 4.655.000, PPN Rp 512.050, Grand Total Rp 5.167.050
* **Nilai Amandemen:** DPP Rp 4.355.000, PPN Pajak Rp 512.050 (Tetap), Grand Total Tagihan Baru Rp 4.834.050
* **Selisih Penurunan Tagihan Konsumen:** Rp 333.000
* **Komposisi Jurnal Penyesuaian:**
  1. **Piutang Dagang (1010020010):** **Kredit Rp 333.000** (Mengurangi tagihan konsumen)
  2. **Penjualan (4010):** **Debet Rp 300.000** (Koreksi omzet sebenarnya)
  3. **Beban Penjualan Lainnya (601000036):** **Debet Rp 33.000** (Penyerapan selisih PPN internal yang tidak dibatalkan ke DJP)

Dengan pola ini, saldo buku besar, kartu piutang konsumen, dan laporan laba rugi perusahaan tetap seimbang (*balance*) tanpa melanggar kepatuhan perpajakan DJP.

---

### Tahap 5: Pencetakan Invoice Fisik (`Printing.php` & `printing.php`)

Saat invoice dicetak kembali via `invoicing/Printing/viewReceiptReg/4822/[nomor_invoice]?opsi_cetak=5`:
1. Sistem membaca blob `items5_sum` yang telah disusun ulang berdasarkan urutan drag & drop baru.
2. Sistem mengekstrak key `mainValues`:
   - `nett1`: Total DPP Baru (Rp 4.355.000)
   - `ppn_out_bulat`: Total PPN Baru (Rp 479.050)
   - `grand_pembulatan`: Grand Total Baru (Rp 4.834.050)
3. **Mekanisme Fallback Anti-Nol:** Jika key `grand_pembulatan` belum terdefinisi di data lama, sistem secara otomatis membaca fallback bertingkat:
   $$\text{grand\_total} \longrightarrow \text{new\_net3} \longrightarrow \text{piutang\_dagang} \longrightarrow \text{piutang\_usaha} \longrightarrow (\text{DPP} + \text{PPN})$$
4. Fungsi `inWordInd` membaca nilai `grand_pembulatan` yang valid dan menerbitkan kalimat terbilang:
   *`"--- Empat Juta Delapan Ratus Tiga Puluh Empat Ribu Lima Puluh Rupiah ---"`*
5. Bagian **NOTES** mencetak teks deskripsi proyek serta catatan penagihan client yang diinput user pada saat amandemen.

---

### Tahap 6: Audit Trail & Kemampuan Rollback (`Report.php`)

1. Seluruh perubahan tercatat pada tabel `transaksi_amandemen_history` dengan snapshot biner utuh.
2. Pada modul `penerimaanprojek/Transaksi/viewResume`, tabel **Rekonsiliasi Finansial Proyek** menampilkan riwayat amandemen secara transparan.
3. Tautan audit menuju buku besar (`Ledger/viewMoveDetails_1`) telah dibersihkan menggunakan format tanggal ISO murni (`date2=YYYY-MM-DD`) tanpa residu timestamp `%20 00:00:00`.
4. Jika sewaktu-waktu revisi dibatalkan oleh manajemen, supervisor dapat menekan tombol **"Pulihkan ke Versi Ini"** untuk mengembalikan invoice ke keadaan semula dengan aman, asalkan belum ada penerimaan kasir yang mengunci transaksi.

---

## 4. Matriks Ringkasan Dampak Komponen

| Komponen | Status Sebelum Amandemen | Status Sesudah Amandemen |
|---|---|---|
| **Katalog Produk Cetak** | Daftar item lama | Daftar item baru (urutan & harga baru) |
| **Header Transaksi** | `transaksi_nilai` lama | `transaksi_nilai` baru (sinkron dengan DP & termin) |
| **Kartu Piutang (`transaksi_payment_source`)** | Plafon & sisa lama | `tagihan` baru, `tagihan_asal` tersimpan, `amandemen_nilai` tercatat |
| **Realisasi Kontrak Proyek** | Nilai kontrak awal | `project_produk.harga` tersinkronisasi otomatis |
| **e-Faktur DJP** | Approved DJP | Tetap sah / Approved DJP (selisih diserap ke akun 601000036) |
| **Jurnal Akuntansi** | Jurnal asli invoice | Jurnal asli tetap ada + Jurnal penyesuaian/storno resmi |
| **Cetakan Nota Fisik** | Cetakan versi lama | Cetakan mutakhir, Grand Total valid, Terbilang rupiah valid |
