# Dokumentasi Teknis: Analisis & Solusi Perhitungan Notifikasi Badge Tray

## 1. Ringkasan Masalah (Problem Statement)
Terdapat ketidaksinkronan angka antara counter badge notifikasi pada **menu samping/sidebar kiri** dengan **total penjumlahan badge pada tab action step di halaman utama**.

### Contoh Kasus (Modul Taxes / Transaksi Jenis 110 - E-Faktur PPN Keluaran):
* **Halaman Utama (`taxes/Transaksi/index/110`)**:
  * Tab 1: **PREPARE E-FAKTUR** = `289`
  * Tab 2: **PREPARE GUNGGUNGAN** = `296`
  * Tab 3: **ENTRY E-FAKTUR** = `27`
  * **Total Dokumen Transaksi Riil** = `289 + 296 + 27 = 612 transaksi`.
* **Menu Samping Kiri (Sidebar)**:
  * Badge **E-Faktur Ppn Keluaran** menampilkan angka **`2.958`**.

---

## 2. Arsitektur Komponen Tray Pasca Refactor

Untuk mengatasi beban *high-concurrency slow query* dan *database lock* pada polling notifikasi real-time, arsitektur `_tray` dipecah menjadi beberapa komponen:

```
[Cron / Background Worker]
        │
        ▼
   CronTray.php ────► Menghasilkan Tabel Cache Agregasi:
                      - sys_cache_tray_transaksi
                      - sys_cache_tray_duedate
                      - sys_cache_tray_payment
        │
        ▼
[Client Polling Request: _tray]
        │
        ▼
   _tray.php (Controller Orkestrator)
        │
        ▼
he_tray_helper.php ──► Mengambil data agregasi dari cache
  (Business Logic)     Mengevaluasi wewenang (Todo vs Undone)
        │
        ▼
  js_tray.php ───────► Mengupdate DOM / Badge di browser client
 (View Component)
```

---

## 3. Akar Masalah Teknis (Root Cause Analysis)

### A. Perbedaan Relasi Header vs Detail
* Tabel `transaksi` ($t$) adalah header dokumen transaksi.
* Tabel `transaksi_data` ($d$) adalah detail baris barang/item per transaksi (Relasi **1 to Many**).

### B. Kesalahan Agregasi pada `CronTray.php`
Pada file `application/controllers/CronTray.php` (baris 74–85):

```sql
INSERT INTO sys_cache_tray_transaksi (cabang_id, cabang2_id, jenis_master, next_step_num, next_step_code, next_substep_num, jenis_label, oleh_id, qty)
SELECT 
    t.cabang_id, t.cabang2_id, t.jenis_master, t.next_step_num, t.next_step_code, 
    d.next_substep_num, t.jenis_label, t.oleh_id, COUNT(1) as qty
FROM transaksi t
JOIN transaksi_data d ON d.transaksi_id = t.id
WHERE t.status = '1' AND t.trash = '0' AND t.link_id = '0' 
AND d.trash = '0' AND d.sub_step_number > 0 AND d.valid_qty > 0
GROUP BY t.cabang_id, t.cabang2_id, t.jenis_master, t.next_step_num, t.next_step_code, d.next_substep_num, t.jenis_label, t.oleh_id
```

* **Pemicu Masalah**: Penggunaan **`COUNT(1) as qty`** saat melakukan `JOIN transaksi_data`.
* Karena 1 dokumen transaksi memiliki rata-rata ~4,8 baris item barang di `transaksi_data`, maka `COUNT(1)` menghitung **total baris item detail (2.958 item)**, bukan jumlah dokumen transaksi.

### C. Efek Berantai pada `he_tray_helper.php`
Pada `he_tray_helper.php` baris 102–145:
```php
$qty = isset($row->qty) ? (int)$row->qty : 1;
...
for ($it = 0; $it < $qty; $it++) {
    $todoTrans[] = 1;
    $subTodoTrans[$jenisTr][] = 1;
    $subTodoTransName[$jenisTr][] = $row->jenis_label;
}
```
Helper mengulang penambahan elemen array sebanyak nilai `$qty` ($2.958$ kali), sehingga badge menu kiri menampilkan angka total baris item alih-alih jumlah dokumen transaksi.

---

## 4. Perbandingan Logika Transaksi: Versi Lama vs Versi Refactor

| Fitur / Logika | `_tray_old.php` (Sebelum Refactor) | `_tray.php` + `he_tray_helper.php` (Sesudah Refactor) | Status Kesesuaian |
| :--- | :--- | :--- | :--- |
| **Evaluasi Wewenang** | Cek `alowedAccess()` & fallback ke `membership` user | Cek `alowedAccess()` & fallback ke `membership` user | **AS-IS (Identik)** |
| **Pemisahan Todo & Undone** | Masuk `subTodoTrans` jika berhak followup, masuk `subUndoneTrans` jika pending | Masuk `subTodoTrans` jika berhak followup, masuk `subUndoneTrans` jika pending | **AS-IS (Identik)** |
| **Relasi Pasangan (`pairChild`)** | Menambahkan `subUndoneTransEx` ke transaksi terkait | Menambahkan `subUndoneTransEx` ke transaksi terkait | **AS-IS (Identik)** |
| **Integrasi Piutang & Jatuh Tempo** | Menggabungkan `extraSrc` dari sumber pembayaran | Menggabungkan `extraSrc` dari tabel cache payment | **AS-IS (Identik)** |
| **Unit Perhitungan Transaksi** | `GROUP BY transaksi_id` $\rightarrow$ menghitung **Jumlah Dokumen** | `COUNT(1)` pada `CronTray` $\rightarrow$ terhitung **Jumlah Baris Item** (Perlu diperbaiki) | **Memerlukan Fix Agregasi** |

---

## 5. Solusi & Langkah Perbaikan

### A. Perbaikan Query pada `CronTray.php`
Ubah baris 78 pada `application/controllers/CronTray.php`:

```diff
-   d.next_substep_num, t.jenis_label, t.oleh_id, COUNT(1) as qty
+   d.next_substep_num, t.jenis_label, t.oleh_id, COUNT(DISTINCT t.id) as qty
```

### B. Regenerasi Cache Tray
Jalankan regenerasi cache secara manual atau via cron:
* **Via CLI**:
  ```bash
  php index.php CronTray generate_cache
  ```
* **Via Browser / URL**:
  ```
  http://<domain>/CronTray/generate_cache?secure_key=cron_tray_cache_123
  ```

### C. Hasil Setelah Perbaikan
1. Nilai `$row->qty` pada `sys_cache_tray_transaksi` akan menyimpan jumlah dokumen unik (`DISTINCT t.id`).
2. Badge menu samping kiri untuk jenis `110` akan berubah dari **`2.958`** menjadi **`612`**.
3. Total badge di menu kiri akan **100% konsisten** dengan penjumlahan tab step action di halaman utama ($289 + 296 + 27 = 612$).
