# KONTEKS & HANDOVER TEKNIS: TIMESTAMP-BASED DELTA SYNC PRODUK

> **Tanggal Dokumen**: 30 Agustus 2026  
> **Status Sesi**: Selesai Diimplementasikan & Lolos Verifikasi API  
> **Lingkungan / Workspace**:
> * **Holding Company (Pusat / API Provider)**: `W:\san_29agus` (`ADM_DOMAIN = https://demo.mayagrahakencana.com/san_29agus/`)
> * **Branch / Subsidiary (Cabang / Client Sync)**: `W:\san_add_29agus` (`ADM_LOCAL_DOMAIN = https://demo.mayagrahakencana.com/san_add_29agus/`)

---

## 1. Latar Belakang & Keputusan Arsitektur

Sebelumnya, sinkronisasi produk antara Holding dan Cabang menggunakan metode **monolitik blocking** (`syncApiData`) yang mencoba membandingkan hash string MD5 secara menyeluruh dalam 1 request HTTP tunggal. Hal ini memiliki kelemahan:
1. **Risiko False Mismatch**: Perbedaan format desimal atau spasi pada string hash membuat seluruh produk selalu terdeteksi berubah.
2. **Risiko Timeout**: Jika jumlah produk yang berubah banyak, request HTTP dan transaksi database di cabang akan *freeze* atau terkena 504 Gateway Timeout.
3. **Penyebutan Domain**: Telah diklarifikasi bahwa Single Source of Truth (SSOT) untuk domain holding adalah konstanta `ADM_DOMAIN` di `application/helpers/he_url_helper.php`.

**Keputusan yang Disetujui (Opsi B):**
Mengimplementasikan **Timestamp-Based Delta Sync** dengan menambahkan endpoint baru di Holding (`seeUpdatedSince`) yang terintegrasi dengan antrean asynchronous **`sync_jobs`** di Cabang (lengkap dengan Live Progress Bar).

---

## 2. Perubahan Berkas & Implementasi Kode

### A. Sisi Holding Company (`san_29agus`)
* **Berkas**: `application/controllers/eusvc/Products.php`
* **Fitur**: Endpoint baru `seeUpdatedSince_get()` dan `seeUpdatedSince_post()`.
* **Mekanisme**:
  * Menerima parameter `since` (timestamp) dan `cabang_id`.
  * Memanfaatkan kolom timestamp otomatis MariaDB:
    * `produk.dtime` (timestamp `ON UPDATE current_timestamp()`)
    * `price.last_update` (datetime `ON UPDATE current_timestamp()`)
  * Menjalankan query delta:
    ```sql
    SELECT p.id, p.kode, p.nama, p.status, p.trash,
           GREATEST(IFNULL(p.dtime, '2000-01-01 00:00:00'), IFNULL(MAX(h.last_update), '2000-01-01 00:00:00')) as last_modified
    FROM produk p
    LEFT JOIN price h ON h.produk_id = p.id AND h.cabang_id = ? AND h.trash = 0
    WHERE (? IS NULL OR ? = '' OR p.dtime > ? OR h.last_update > ?)
    GROUP BY p.id
    ORDER BY last_modified ASC
    ```
  * Mengembalikan JSON berisi daftar ID produk yang berubah, `jml_total`, dan `server_time` holding.
* **Backward Compatibility**: Seluruh endpoint lama (`seeItemAll`, `seeItemByIds`, `seeItemHashes`, `seePrices`, dll) tetap 100% utuh tanpa perubahan.

---

## 3. Hasil Pengujian & Status Verifikasi

| Komponen yang Diuji | Parameter Uji | Hasil Verifikasi | Status |
| :--- | :--- | :--- | :--- |
| **Endpoint Holding (`seeUpdatedSince`)** | `since = 2026-08-29 00:00:00` | HTTP 200, mengembalikan 3 produk terupdate + `server_time: 2026-08-30 12:31:48` | ✅ **PASS** |
| **Detail Batch Fetch (`seeItemByIds`)** | `ids = 38,366` | HTTP 200, detail master produk & harga tier lengkap terbaca | ✅ **PASS** |
| **PHP Syntax Check (Linting)** | `Products.php`, `MdlProduk.php`, `Data.php` | 0 syntax errors di semua berkas | ✅ **PASS** |

---

## 4. Panduan & Langkah Kerja untuk Sesi Selanjutnya (To-Do List)

Saat melanjutkan sesi berikutnya, hal-hal yang dapat dilakukan:
1. **Verifikasi Melalui Browser UI**:
   * Buka browser pada menu Master Produk di `san_add_29agus`.
   * Klik tombol **Syncron Now** dan amati animasi progress bar polling hingga selesai.
   * Lakukan klik kedua untuk memastikan notifikasi *"Data sudah mutakhir (0 item perubahan)"* muncul dalam waktu $< 1$ detik.
2. **Uji Kasus Khusus (*Edge Cases*)**:
   * Ubah harga di holding tanpa mengubah produk $\rightarrow$ Pastikan terdeteksi di cabang.
   * Ubah status `trash = 1` di holding $\rightarrow$ Pastikan produk di cabang ikut nonaktif.
