# 📊 ALUR KALKULASI & PENELUSURAN DATA TIMELINE PROYEK

Dokumen ini menjelaskan secara visual dan terperinci mengenai **alur penelusuran data (*Data Flow*)**, **pemetaan tabel database (*Database Schema Mapping*)**, **klasifikasi transaksi**, dan **metode kalkulasi nilai** pada modul Laporan Timeline Proyek (`Printing::viewTimelinePdf`).

---

## 🗄️ Pemetaan Tabel Database (*Database Tables & Schema Mapping*)

Berikut adalah daftar lengkap tabel database MariaDB Everest yang diakses oleh modul ini beserta fungsi dan kolom-kolom utamanya:

### 1. `transaksi` (Tabel Master Transaksi Utama)
Tabel utama yang menyimpan seluruh riwayat transaksi (SO, SPK, Invoice Termin, dan Kuitansi Pembayaran).
* `id` *(Primary Key)*: ID unik transaksi (contoh: `890738`).
* `jenis` / `jenis_master`: Kode jenis transaksi (contoh: `588st` = Start Project, `7499` = Termin Invoice, `749` = Kuitansi RPC, `4467` / `583` = DP).
* `nomer2` / `nomer`: Nomor dokumen resmi (contoh: `INV-PJ.1.210.89`, `RPC.1.210.83`, `588st.1.210.55`).
* `transaksi_nilai`: Nilai DPP (Excl. PPN) untuk invoice, atau Net Cash untuk kuitansi.
* `transaksi_ppn`: Nilai PPN (11%).
* `transaksi_net`: Nilai bersih Incl. PPN (jika terisi di DB).
* `id_master` / `id_top`: Pointer ID transaksi induk utama (SO/Quotation Header).
* `ids_prev` / `ids_ref` / `ids_his`: Blob/string referensi rantai transaksi sebelumnya (*Parent Chain*).
* `customers_nama` / `pihak_nama`: Nama pelanggan / konsumen.
* `oleh_nama`: Nama petugas/user yang membuat transaksi.
* `dtime`: Tanggal & waktu pembuatan transaksi.
---

### 1b. `transaksi_payment_source` (Tabel Gateway Relasi Proyek & Tagihan)
Tabel relasional penghubung langsung antara ID Transaksi Termin (`890738`), ID Proyek (`project_id = 46`), dan Master Penawaran/SPK (`588so` / `588st`).
* `transaksi_id`: ID transaksi target (contoh: `890738`).
* `project_id`: ID Proyek terikat (contoh: `46`).
* `project_nama`: Nama Proyek (contoh: `PASADENA VILLAGE TAHAP 2`).
* `jenis`: Jenis transaksi (contoh: `7499` = Invoice Termin, `588so` = Quotation Approval Master, `4467` = DP).
* `target_jenis`: Jenis target turunan (contoh: `749` = Kuitansi RPC).
* `nomer`: Nomor dokumen teknis (contoh: `7499.1.210.89`, `588so.1.210.27`).
* `tagihan`: Nilai total tagihan Incl. PPN (contoh: `150.240.526,86`).
* `dpp_ppn`: Nilai DPP Excl. PPN (contoh: `135.351.826,00`).
* `ppn`: Nilai PPN (contoh: `14.888.700,86`).

---

### 2. `project_produk` (Tabel Master Proyek Utama)
Tabel master yang menyimpan data header proyek fisik/kontrak.
* `id` *(Primary Key)*: ID unik proyek (contoh: `46` ➔ ditampilkan sebagai `PASADENA VILLAGE TAHAP 2 (46)`).
* `nama`: Nama proyek (contoh: `PASADENA VILLAGE TAHAP 2`).
* `transaksi_id` / `quot_id` / `project_start_id`: Referensi ID transaksi yang terhubung ke proyek ini.
* `persen_progress`: Persentase penyelesaian fisik pekerjaan (contoh: `100.0000000000%`).
* `nomor_kontrak`: Nomor kontrak proyek resmi jika ada.
* `tanggal_kontrak`: Tanggal penandatanganan kontrak.
* `alamat`: Alamat/lokasi site pekerjaan proyek.
* `closing_status`: Status akhir proyek (contoh: `AKTIF`, `CLOSED`).

---

### 3. `project_produk_items3` (Tabel Pembantu - Skema Termin Proyek)
Menyimpan rincian bobot persentase & jadwal invoice termin proyek.
* `transaksi_id` / `nomer`: Referensi transaksi / quotation proyek.
* `nama`: Nama termin (contoh: `TERMIN 1`, `TERMIN 2`).
* `persen`: Bobot persentase termin (contoh: `70%`).
* `harga` / `jumlah`: Nominal acuan termin jika di-lock secara tetap.

---

### 4. `project_produk_items4` (Tabel Pembantu - Uang Muka / DP Proyek)
Menyimpan rincian bobot persentase & nominal Uang Muka (DP) proyek.
* `transaksi_id` / `nomer`: Referensi transaksi / quotation proyek.
* `persen`: Bobot persentase DP (contoh: `30%`).
* `harga` / `jumlah`: Nominal acuan DP proyek.
* `keterangan_dp`: Catatan / rincian DP.

---

### 5. `project_produk_items5` (Tabel Pembantu - Retensi / Garansi Proyek)
Menyimpan rincian garansi pemeliharaan & nilai retensi proyek.
* `transaksi_id` / `nomer`: Referensi transaksi / quotation proyek.
* `persen`: Bobot persentase retensi (contoh: `5%` atau `0%`).
* `tgl_akhir_garansi`: Tanggal berakhirnya masa garansi pemeliharaan proyek.
* `keterangan_garansi`: Catatan garansi.

---

### 6. `transaksi_data_registry` (Tabel Registry Blob)
Tabel pendukung penyimpanan data registrasi transaksi dalam bentuk blob base64/serialized PHP.
* `transaksi_id`: ID transaksi target.
* `main`: Serialized blob berisi elemen-elemen form bawaan & item pendukung.

---

## 🎨 Diagram Visual Alur Pengambilan & Kalkulasi Data

```mermaid
flowchart TD
    A["👤 User Membuka Link Laporan Timeline<br><i>(Contoh: /viewTimelinePdf/749/890738)</i>"] --> B

    subgraph PHASE1 ["1️⃣ PHASE 1: Penelusuran Rantai Induk (Parent Chain)"]
        B["Ambil Data Transaksi Aktif <i>$startTrx</i> dari <b>transaksi</b>"] --> C["Trace Ke Belakang (Upward Traversal)<br>Ikuti <i>id_master</i>, <i>id_top</i>, <i>ids_prev</i>, <i>ids_his</i><br><b>Hasil:</b> [890738 ➔ 251011 (SPK) ➔ 250977 (SOA) ➔ 250925 (SO)]"]
    end

    C --> PHASE2

    subgraph PHASE2 ["2️⃣ PHASE 2: Penelusuran Sibling & Kuitansi (Forward Discovery)"]
        D["<b>Sibling Discovery (Fast Indexed Query):</b><br>Cari semua Invoice Termin (7499) di <b>transaksi</b> yang <i>id_master/id_top</i>-nya cocok dengan Rantai Induk Proyek"]
        E["<b>Receipt Discovery (Fast Indexed Query):</b><br>Cari Kuitansi Pembayaran (749/RPC, 4467/DP) di <b>transaksi</b> yang <i>id_master/id_top/ids_prev</i>-nya merujuk ke Invoice Proyek Ini"]
        D --> E
    end

    E --> PHASE3

    subgraph PHASE3 ["3️⃣ PHASE 3: Pengayaan Data Master Proyek (Enrichment)"]
        F["Query ke <b>project_produk</b> & <b>project_produk_items3/4/5</b><br>Ambil: Nama Proyek, ID Proyek (46), Nomor Kontrak, Progress %, dan Tabel Skema Termin (DP %, Termin %, Retensi %)"]
    end

    F --> PHASE4

    subgraph PHASE4 ["4️⃣ PHASE 4: Klasifikasi & Pemisahan Perhitungan"]
        G1["<b>a. Dokumen Header SPK (588st, 588so):</b><br>• Label: <i>Nilai Total Kontrak Proyek</i><br>• 🚫 <b>Dikecualikan dari Total Tagihan</b><br><i>(Mencegah Double Counting)</i>"]
        G2["<b>b. Dokumen Invoice Termin (7499 / 4822):</b><br>• Nilai = <i>transaksi_nilai</i> + PPN 11% (Jika Excl PPN)<br>• ➕ <b>Diakumulasikan ke Total Nilai Tagihan</b>"]
        G3["<b>c. Dokumen Kuitansi Pembayaran (749 / RPC):</b><br>• Nilai = <i>Net Cash Diterima</i> (Sudah Incl PPN)<br>• ➕ <b>Diakumulasikan ke Total Pembayaran Diterima</b>"]
    end

    G1 & G2 & G3 --> PHASE5

    subgraph PHASE5 ["5️⃣ PHASE 5: Tabel Ringkasan Akhir (Summary Table)"]
        H["• <b>Total Tagihan Invoice (Incl. PPN)</b> = Sum(Invoice 7499)<br>• <b>Total Pembayaran Diterima</b> = Sum(Kuitansi 749)<br>• <b>Sisa Piutang / Kurang Bayar</b> = Total Tagihan - Total Diterima"]
    end
```

---

## 📋 Rincian Tahapan & Logika Penelusuran Data

### 1️⃣ Phase 1: Penelusuran Rantai Induk (*Parent Chain Discovery*)
* **Tujuan:** Menemukan seluruh dokumen silsilah proyek ke belakang (mulai dari Invoice Termin ➔ SPK/Start Project ➔ Quotation Approval ➔ Sales Order).
* **Metode:**
  1. Menelusuri kolom `id_master`, `id_top`, `ids_prev`, dan `ids_his` pada tabel `transaksi`.
  2. Hasil ID disimpan ke dalam array `$parentChainIds` (contoh: `[890738, 251011, 250977, 250925]`).
  3. **Sanitasi ID:** Hanya ID murni integer angka yang diproses untuk menjamin keamanan SQL dan performa.

---

### 2️⃣ Phase 2: Penelusuran Sibling & Kuitansi (*Forward Discovery*)
* **Tujuan:** Menemukan seluruh invoice termin sejajar (*siblings*) dan kuitansi pembayaran terkait (*receipts*).
* **Metode Optimasi Super Cepat (8 ms):**
  1. **Sibling Discovery:** Menyeleksi dokumen `jenis = 7499` yang memiliki `id_master IN ($parentChainIds)` atau `id_top IN ($parentChainIds)`.
  2. **Receipt Discovery:** Menyeleksi dokumen `jenis = 749` (RPC) atau `4467` (DP) yang memiliki `id_master IN ($parentChainIds)` atau `id_top IN ($parentChainIds)`.
  3. **Penyaringan Strict:** Kuitansi lama dari proyek lain milik pelanggan yang sama (misal: kuitansi tahun 2024 dari proyek lain) **otomatis diabaikan** karena `id_master`-nya tidak cocok.

---

### 3️⃣ Phase 3: Pengayaan Data Master Proyek (*Data Enrichment*)
* **Tujuan:** Menampilkan informasi detail proyek & tabel skema pembayaran di bagian atas laporan.
* **Tabel yang Di-query:**
  * `project_produk`: Menghasilkan Nama Proyek, ID Proyek `(46)`, Progress Pekerjaan `%`, Nomor Kontrak, dan Alamat Site.
  * `project_produk_items3`: Menghasilkan daftar persentase & bobot **Jadwal Termin**.
  * `project_produk_items4`: Menghasilkan persentase & nominal **Uang Muka (DP)**.
  * `project_produk_items5`: Menghasilkan persentase **Retensi/Garansi** dan Tanggal Akhir Garansi.

---

### 4️⃣ Phase 4: Klasifikasi Transaksi & Rules Perhitungan Nominal

| Tipe Dokumen | Modul / Jenis | Penanganan Nominal & PPN | Perlakuan pada Total Tagihan Bawah |
| :--- | :---: | :--- | :--- |
| **Dokumen Otorisasi Header** | `588st`, `588so`, `588spo` | Ditampilkan dengan label *Nilai Total Kontrak Proyek*. Nilai PPN dihitung 11%. | 🚫 **Dikecualikan / Tidak Ditambahkan** *(agar nilai proyek tidak terhitung 2x lipat)*. |
| **Invoice Tagihan Termin** | `7499`, `4822` | Nilai `transaksi_nilai` adalah DPP (Excl. PPN). Sistem menambahkan PPN 11% (`nilai * 1.11`) untuk mendapatkan nilai *Incl. PPN*. | ➕ **Diakumulasikan** ke **Total Nilai Tagihan Invoice**. |
| **Kuitansi Pembayaran** | `749` (RPC), `4467`, `583` | Nilai `transaksi_nilai` atau `transaksi_net` adalah **Net Cash Diterima (Incl. PPN)**. PPN tidak ditambahkan 11% lagi. | ➕ **Diakumulasikan** ke **Total Pembayaran Diterima**. |

---

### 5️⃣ Phase 5: Perhitungan Tabel Ringkasan Akhir (*Summary Table*)

Rumus kalkulasi pada tabel ringkasan bagian bawah laporan:

$$\text{Total Nilai Tagihan Invoice (Incl. PPN)} = \sum \text{Nominal Invoice } (7499)$$

$$\text{Total PPN (11\%)} = \sum \text{PPN Invoice } (7499)$$

$$\text{Total Nilai DPP (Excl. PPN)} = \text{Total Nilai Tagihan Invoice} - \text{Total PPN}$$

$$\text{Total Pembayaran Diterima} = \sum \text{Nominal Kuitansi } (749 / \text{RPC})$$

$$\text{Sisa Piutang / Kurang Bayar} = \text{Total Nilai Tagihan Invoice} - \text{Total Pembayaran Diterima}$$

---

### 💡 Catatan Penting Pencegahan Salah Hitung:
1. **Mencegah Double-Counting Header SPK:** Dokumen `588st` (Start Project) bernilai total proyek (misal: Rp 214,6 Juta). Jika dokumen ini dijumlahkan bersama invoice termin DP (Rp 64,3M) & Termin 1 (Rp 150,2M), totalnya akan menjadi Rp 429 Juta (2x lipat). Oleh karena itu, `588st` **wajib dikecualikan** dari penjumlahan tagihan invoice.
2. **Mencegah Kuitansi Nyasar:** Kuitansi lama pelanggan dari tahun/proyek lain **wajib disaring** berdasarkan kecocokan `id_master` / `id_top` dengan rantai proyek aktif.
3. **Mencegah PPN Berganda pada Kuitansi:** Uang kas/bank pada kuitansi `RPC` sudah bernilai *Incl. PPN*, sehingga tidak boleh dikalikan 1,11 lagi.
