# 📋 BLUEPRINT ARSITEKTUR REVISI: INTEGRASI AUTOPURCHASE FG PROJECT INLINE UI (`pembelianfgproject` / 1466)

Dokumen ini merupakan cetak biru teknis (*technical blueprint*) revisi resmi untuk fitur **Integrasi Autopurchase FG Project**, yaitu mekanisme penarikan barang dari wadah **`project_purchase_pool`** (hasil Kickoff di `master_project`) ke dalam alur transaksi penerbitan Purchase Order (PO) pada modul **`pembelianfgproject`** (Trjenis: `1466` / Pre-PO: `1466r`).

Blueprint ini mengadopsi pendekatan **Direct Inline UI** dan mematuhi aturan bisnis **1 PO = 1 Supplier (Relasi Supplier-Produk)** serta mengintegrasikan seluruh hasil penyempurnaan fitur dan kesepakatan operasional terbaru.

---

## 1. Latar Belakang & Tujuan Arsitektur

1. **Pemisahan Peran (Separation of Concerns):**
   - Tim Estimator / PM di `master_project` menentukan komposisi barang & jumlah kebutuhan teknis proyek.
   - Tim Purchasing di `pembelianfgproject` berwenang penuh memilih supplier, menegosiasikan harga beli aktual, dan memecah pemesanan ke vendor yang sesuai.
2. **Strict Supplier Isolation & Flexible Default View:**
   - Setiap Surat Purchase Order (PO) hanya diterbitkan untuk 1 Supplier tertentu (1 PO = 1 Supplier).
   - Secara default (saat Supplier Header belum dipilih), tabel Kebutuhan Project (`project_purchase_pool`) **menampilkan SELURUH produk kebutuhan proyek yang terbuka** agar Tim Purchasing memiliki gambaran utuh.
   - Begitu Supplier dipilih, tabel secara otomatis tersaring presisi hanya untuk barang berelasi dengan supplier tersebut.
3. **Auto-Assign Supplier & Ergonomi ISO 9001 (Zero Extra Click):**
   - Mendukung **Auto-Assign Header Supplier** (Opsi A): Jika Supplier Header masih kosong, mengklik tombol `+` pada baris produk akan otomatis mengeset Supplier Header transaksi sesuai vendor produk tersebut sekaligus memasukkan barang ke keranjang belanja.
   - **Notifikasi Konfirmasi Wajib**: Jika Supplier Header aktif berbeda dengan vendor produk yang diklik, sistem wajib memunculkan dialog konfirmasi interaktif untuk mencegah pergantian vendor yang tidak disengaja.
4. **Pelacakan & Pemenuhan Pengadaan (Procurement Tracking & Fulfillment):**
   - Pelacakan status real-time per item kebutuhan: `OPEN` (belum dipesan), `PARTIAL` (dipesan sebagian), atau `CLOSED` (tuntas dipesan).
5. **Desain Antarmuka Terintegrasi (Direct Inline UI Outside ShoppingCart):**
   - Menggantikan pop-up modal. Tabel kebutuhan proyek ditampilkan **secara langsung (Inline)** di area tengah layar utama Pre-PO (`Create/index/1466`) pada `col-md-12`, persis di bawah tombol hijau `✓ Continue PRE PURCHASE ORDER` dan di atas area `TRANSAKSI YANG PERLU ACTION`.
6. **Smart Quantity Formatting (Tanpa Desimal `.00`):**
   - Angka jumlah kebutuhan (`Qty RAB`), jumlah terpesan (`Qty PO`), sisa (`Qty Sisa`), serta isi *input field* diformat bersih bulat tanpa akhiran `.00` (contoh: `23 Unit` & `5 Unit`, bukan `23.00`). Pecahan desimal non-nol (*e.g.* `2.5`) tetap dipertahankan.

---

## 2. Diagram Alur Transaksi (End-to-End Workflow)

```mermaid
flowchart TD
    A["Kickoff Project (master_project / 588)"] -->|"Insert Batch (status='OPEN')"| B[("Tabel: project_purchase_pool")]
    
    subgraph "Modul pembelianfgproject (1466) - Alur Autopurchase Inline UI"
        C["User Buka Form Pre-PO (1466r)"] --> D["Tabel Autopurchase Pool Tampil (Default: Semua Barang Proyek)"]
        D --> E{"Apakah Supplier Header Dipilih?"}
        
        E -- "Belum Dipilih (ID=0)" --> F["Tabel Menampilkan Seluruh Item OPEN/PARTIAL"]
        E -- "Sudah Dipilih (ID>0)" --> G["Tabel Otomatis Ter-Filter Spesifik Supplier"]
        
        F --> H["User Klik [+] pada Baris Produk"]
        G --> H
        
        H --> I{"Cek Header Supplier Aktif"}
        I -- "Header Kosong" --> J["Auto-Assign Header Supplier & Masukkan Item ke Cart"]
        I -- "Header Sesuai" --> K["Masukkan Item ke Cart"]
        I -- "Header Beda Vendor" --> L["Dialog Konfirmasi Wajib Pergantian Supplier"]
        
        L -- "User Klik OK" --> M["Switch Header Supplier & Masukkan Item ke Cart"]
        L -- "User Klik Batal" --> N["Aksi Dibatalkan"]
        
        J --> O["Item Masuk Shopping Cart & Auto-Refresh Sync"]
        K --> O
        M --> O
        
        O --> P["Simpan Draft Pre-PO & Approval PO (1466)"]
    end

    P -->|"Update qty_po, qty_sisa, status"| B
    P --> Q["Sync HPP Balik & Audit Trail (project_hpp_history)"]
    P --> R["Penerimaan Barang / GRN (1467)"]
```

---

## 3. Detail Antarmuka (UI Layout & Direct Inline Panel)

### A. Tata Letak Layar Utama `Create/index/1466`
Tabel kebutuhan proyek diletakkan secara **Inline (Direct View)** pada template utama `transaksi.html` via tag `{project_pool_inline}`:
* **Posisi Atas**: Berada DI BAWAH tombol hijau `✓ Continue PRE PURCHASE ORDER (project)`.
* **Posisi Bawah**: Berada DI ATAS area merah `⚠️ TRANSAKSI YANG PERLU ACTION`.
* **Ukuran**: Membentang selebar 100% halaman (`col-md-12`).

```
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 📦 DAFTAR KEBUTUHAN PROJECT (Autopurchase Pool)                                                                                        │
│ Filter Proyek: [ Semua Proyek Aktif  ▼ ][✕]  Cari Barang / Kode / Proyek: [               ] [✕][🔍 Cari] [🔄 Refresh]                  │
├───────┬──────────────────────────┬─────────────────────────────────────┬─────────┬─────────┬──────────┬─────────────┬──────────────┬──────────┬─────────────┤
│ ID    │ Proyek & No. Kontrak     │ Kode & Nama Produk                  │ Qty RAB │ Qty PO  │ Qty Sisa │ Stok DC     │ Stok Supplier│ Status   │ Action      │
├───────┼──────────────────────────┼─────────────────────────────────────┼─────────┼─────────┼──────────┼─────────────┼──────────────┼──────────┼─────────────┤
│ 5     │ LILY - UNIT              │ [CS/CU-YN9AKJ] PANASONIC CS/CU-YN9AKJ│ 23 Unit │ 0       │ 23       │ 15          │ 0            │ OPEN     │ [23 ][+][🗑️]│
│       │ 588so.1.3777.6           │ 🚚 PT. PANASONIC GOBEL INDONESIA    │         │         │          │             │              │          │             │
├───────┼──────────────────────────┼─────────────────────────────────────┼─────────┼─────────┼──────────┼─────────────┼──────────────┼──────────┼─────────────┤
│ 6     │ COBA HPP 1               │ [AP48KC1QRA] AQUA STANDING FLOOR 5PK│ 5 Unit  │ 0       │ 5        │ 0           │ 10           │ OPEN     │ [5  ][+][🗑️]│
│       │ 588so.1.11.2             │ 🚚 PT. HAIER SALES INDONESIA        │         │         │          │             │              │          │             │
└───────┴──────────────────────────┴─────────────────────────────────────┴─────────┴─────────┴──────────┴─────────────┴──────────────┴──────────┴─────────────┘
```

#### Kolom & Elemen Tabel Inline:
1. **ID Pool (`id`)**: Primary Key unik record pool.
2. **Proyek & No. Kontrak**: Nama Proyek dan Nomor Kontrak referensi.
3. **Kode & Nama Produk + Supplier Tag**: Identitas barang FG + Tag Nama Supplier Rekomendasi RAB (`🚚 Nama Supplier`).
4. **Qty RAB**: Jumlah kebutuhan total hasil Kickoff (diformat bulat bersih tanpa `.00`).
5. **Qty PO**: Jumlah yang sudah dibuatkan PO (diformat bulat bersih tanpa `.00`).
6. **Qty Sisa**: Jumlah sisa kebutuhan yang belum di-PO-kan (`qty_kebutuhan - qty_po`) (diformat bulat bersih tanpa `.00`).
7. **Stok Project DC**: Kuantitas stok fisik aktif dari `stock_locker` pada gudang internal berkategori/jenis *"gudang project"* (`supplier_id = 0` / `NULL`).
8. **Stok Project Supplier**: Kuantitas stok fisik aktif dari `stock_locker` pada gudang transit yang terikat dengan `supplier_id` terkait dan berkategori *"project"*.
9. **Status**: Badge status (`OPEN` / `PARTIAL`).
10. **Action Direct**: Input field `Qty Order` + Tombol hijau **`[+]`** (Tambah ke Cart) + Tombol merah **`[🗑️]`** (Batalkan/Hapus Item Pool `status = 'CANCELLED'`).
11. **Clear Filter Buttons (`✕`)**: Tombol silang `✕` untuk mereset dropdown Filter Proyek ke `-- Semua Proyek Aktif --` dan mengosongkan kotak pencarian secara instan.

---

## 4. Aturan Logika & Penanganan Supplier

### A. Dual-Match Supplier Querying
Penapisan data `project_purchase_pool` mendukung pencocokan ganda (*dual match*) via `LEFT JOIN`:
```sql
SELECT project_purchase_pool.*
FROM project_purchase_pool
LEFT JOIN produk_per_supplier ON (produk_per_supplier.produk_id = project_purchase_pool.produk_id)
WHERE project_purchase_pool.status IN ('OPEN', 'PARTIAL')
  AND project_purchase_pool.qty_sisa > 0
  AND (
      '$supplierId' <= 0 
      OR project_purchase_pool.supplier_id = '$supplierId'
      OR produk_per_supplier.suppliers_id = '$supplierId'
  )
GROUP BY project_purchase_pool.id
ORDER BY project_purchase_pool.id ASC
```

### B. Auto-Assign Header Supplier (Opsi A)
Saat pengguna mengklik tombol hijau `+`:
- Jika Supplier Header aktif `supplier_id == 0`:
  Sistem membaca `supplier_id` dan `supplier_nama` dari `project_purchase_pool`, lalu secara otomatis memasang `$_SESSION[$cCode]['main']['pihakID']` dan `pihakName` pada header transaksi, serta memasukkan item ke dalam keranjang.

### C. Notifikasi Konfirmasi Wajib Pergantian Vendor
Jika Supplier Header aktif `supplier_id > 0` (misal: Daikin) dan pengguna mengklik `+` pada barang milik Vendor B (misal: Panasonic):
- Javascript memicu dialog konfirmasi interaktif:
  `Header transaksi saat ini ditujukan untuk Supplier lain.\n\nApakah Anda ingin mengganti Supplier Header menjadi [PT PANASONIC GOBEL INDONESIA] untuk membuat PO ini?`
- Jika pengguna memilih **OK**, request dikirim dengan parameter `force_supplier_id=1`, meng-overwrite header ke Panasonic, dan memasukkan barang ke keranjang.
- Jika pengguna memilih **Batal**, aksi dibatalkan tanpa mengubah data.

---

## 5. Hook Sinkronisasi Real-Time (Real-Time Sync Architecture)

Untuk menjamin antarmuka tersinkronisasi instan tanpa refresh browser manual (F5):
1. **Controller `_processPihak.php`**:
   - Method `select()` (pilih/ganti supplier) dan `remove()` (hapus supplier) memicu skrip `if (top.loadProjectPoolInline) { top.loadProjectPoolInline(); }`.
2. **View `shoppingCart.php`**:
   - Memasang hook trigger `top.loadProjectPoolInline()` saat area shopping cart dimuat ulang (*viewCart*).
3. **Perilaku Real-Time**:
   - Pilih Supplier A $\rightarrow$ Tabel otomatis ter-filter untuk Supplier A.
   - Hapus Supplier (tombol `X`) $\rightarrow$ Tabel otomatis kembali menampilkan seluruh produk kebutuhan proyek.

---

## 6. Penyimpanan Metadata di Shopping Cart (`_TR_1466r`)

Setiap baris item yang ditarik dari tabel Inline ke dalam shopping cart (`$_SESSION['_TR_1466r']['items']`) mencatat referensi asal secara presisi:

```php
$cartItem = array(
    "produk_id"                => $row->produk_id,
    "nama"                     => $row->produk_nama,
    "satuan"                   => $row->satuan_nama,
    "qty"                      => $qtyOrder,
    "harga"                    => $hargaBeliSupplier,
    "project_purchase_pool_id" => $row->id,          // Link unik ke pool_id
    "project_id"               => $row->project_id,  // Link ke project_id
    "project_nama"             => $row->project_nama,
);
```

---

## 7. Sinkronisasi Backend & Reversal Handler

### A. Otorisasi / Pengesahan PO (`FollowUp.php` modul `pembelianfgproject`)
Saat PO (`1466`) disetujui (Approved):
```php
foreach ($itemsPO as $item) {
    if (isset($item['project_purchase_pool_id']) && $item['project_purchase_pool_id'] > 0) {
        $poolID = $item['project_purchase_pool_id'];
        $qtyOrdered = (float)$item['qty'];

        $pool = $this->db->get_where("project_purchase_pool", array("id" => $poolID))->row();
        if (!empty($pool)) {
            $newQtyPo = (float)$pool->qty_po + $qtyOrdered;
            $newQtySisa = (float)$pool->qty_kebutuhan - $newQtyPo;
            $newStatus = ($newQtySisa <= 0) ? 'CLOSED' : 'PARTIAL';

            $this->db->where("id", $poolID);
            $this->db->update("project_purchase_pool", array(
                "qty_po"             => $newQtyPo,
                "qty_sisa"           => ($newQtySisa > 0 ? $newQtySisa : 0),
                "status"             => $newStatus,
                "last_updated_dtime" => date("Y-m-d H:i:s")
            ));
        }
    }
}
```

### B. Sinkronisasi HPP Balik & Audit Trail (`project_hpp_history`)
1. Harga beli satuan yang disetujui dengan Supplier (`harga_beli_supplier`) menjadi **HPP Aktual**.
2. Sistem memperbarui HPP pada 2 tabel komposisi proyek terkait:
   - `project_komposisi_workoder`
   - `project_komposisi`
3. Catat riwayat perubahan harga ke `project_hpp_history` via `MdlProjectHppHistory`.
4. Rekalkulasi total HPP proyek pada `project_produk.harga_hpp_so`.

### C. Reversal Handler (Pembatalan / PO Reject / Void)
Jika PO dibatalkan sebelum penerimaan barang (GRN):
* Sistem mengurangi kembali akumulasi `qty_po` sebesar `qty` yang dibatalkan.
* Mengembalikan nilai `qty_sisa` (`qty_sisa = qty_kebutuhan - qty_po`).
* Rollback status pool dari `CLOSED` $\rightarrow$ `PARTIAL` atau `OPEN`.

---

## 8. Ringkasan Status Implemetasi Berkas

| Berkas Target | Peran / Penyesuaian Fitur | Status |
| :--- | :--- | :--- |
| `template/transaksi.html` | Menempatkan tag `{project_pool_inline}` pada `col-md-12` (bawah continue, atas action needed) | **SELESAI** |
| `controllers/_shoppingCart.php` | API `getProjectPoolItemsAjax()`, dual-match query, format Qty bulat bersih | **SELESAI** |
| `controllers/_processPihak.php` | Logic `select()` & `remove()` + hook reload real-time `top.loadProjectPoolInline()` | **SELESAI** |
| `controllers/_processSelectProduct.php` | Logic Auto-Assign Header Supplier dari record `project_purchase_pool` | **SELESAI** |
| `views/shoppingCart.php` | Event hook `loadProjectPoolInline()` saat reloaded | **SELESAI** |
| `views/transaksi.php` | Skrip `loadProjectPoolInline()` & `addPoolItemToCart()` dengan notifikasi konfirmasi wajib | **SELESAI** |
| `views/transaksi_modul.php` | Penyelarasan skrip `loadProjectPoolInline()` & `addPoolItemToCart()` | **SELESAI** |
