# 📘 PANDUAN KERJA OPERASIONAL: TAHAP 1 DOMAIN-DRIVEN REFACTORING
## Transformasi Controller Monolitik Menjadi Modular Domain Architecture
**Target Lingkungan:** CodeIgniter 3.1.8 / PHP 5.6 Legacy Compatibility
**Rujukan Ilmiah:**
* Eric Evans, *Domain-Driven Design* (Addison-Wesley, ISBN: `978-0321125217`)
* Martin Fowler, *Refactoring: Improving the Design of Existing Code* (ISBN: `978-0134757599`)
* Scott J. Ambler, *Refactoring Databases* (ISBN: `978-0321293534`)
* *Journal of Systems and Software* (Elsevier, DOI: [`10.1016/j.jss.2021.110968`](https://doi.org/10.1016/j.jss.2021.110968))
---
## 🎯 TUJUAN UTAMA TAHAP 1
1. Menghilangkan ketergantungan pada *Magic Strings* (`'pusat'`, `'center'`, `'dc'`).
2. Menghapus perhitungan rumus ganda di Controller, View, dan Helper.
3. Menjadikan Controller ramping (*Thin Controller* < 200 baris) yang hanya bertindak sebagai pengatur lalu lintas (*Router/Delegator*).
4. Mengisolasi seluruh akses data di balik **Model Domain (`Com*`)** sehingga tahap normalisasi database nantinya menjadi 100% aman dan bebas risiko.
---
```mermaid
graph TD
subgraph "BAGIAN 1A: IDENTITAS ENTITAS"
K["everest_constants.php
(Kamus ID & Status Baku)"]
end
subgraph "BAGIAN 1B: DOMAIN ENGINES (SINGLE SOURCE OF TRUTH)"
K --> SE["ComStockEngine.php
(Fisik, Avail, Booking, Intransit)"]
K --> PE["ComPricingEngine.php
(Diskon Bertingkat, DPP, PPN 11%)"]
K --> AE["ComAccountingEngine.php
(Jurnal Otomatis, Debit=Kredit)"]
end
subgraph "BAGIAN 1C: THIN CONTROLLERS (PENYAMBUNGAN)"
SE & PE & AE --> SC["_shoppingCart.php"]
SE & PE & AE --> SP["_processSelectProduct.php"]
SE & PE & AE --> SI["_selectorItem.php"]
SE & PE & AE --> CR["Create.php & FollowUp.php"]
end
```
---
## 📋 BAGIAN 1A: STANDARISASI KAMUS ID & KONSTANTA DOMAIN
### 1. Berkas Utama: [`application/config/everest_constants.php`](file:///w:/everest_10agus/application/config/everest_constants.php)
Seluruh identitas status, ID cabang khusus, dan tipe data **WAJIB** menggunakan konstanta baku.
```php
24.0,
'stok_booking' => 0.0,
'stok_intransit' => 0.0,
'stok_avail' => 24.0,
'sisa_siap_jual' => 23.0,
'is_minus' => false,
'is_pusat' => true,
'is_jasa' => false,
'warehouse_status' => 'pusat'
);
```
---
### 2. Engine 2: `ComPricingEngine.php` (Harga, Diskon & Pajak)
* **Lokasi Target:** `application/models/Coms/ComPricingEngine.php`
* **Tanggung Jawab:**
* Menghitung Diskon Bertingkat: $\text{Harga} \times (1 - d_1) \times (1 - d_2) - d_{\text{nominal}}$.
* Menghitung Dasar Pengenaan Pajak (DPP) dan PPN 11% Coretax DJP.
* Menjamin presisi toleransi pembulatan 0 rupiah.
---
### 3. Engine 3: `ComAccountingEngine.php` (Jurnal Otomatis & GL)
* **Lokasi Target:** `application/models/Coms/ComAccountingEngine.php`
* **Tanggung Jawab:**
* Menghasilkan pasangan Debit & Kredit yang seimbang (*balanced*).
* Menjamin *Immutable Audit Trail* (tidak ada UPDATE/DELETE pada tabel mutasi keuangan aktif).
---
## ✂️ BAGIAN 1C: MENYAMBUNGKAN CONTROLLER KE ENGINE (*THIN CONTROLLER*)
### 1. Pola Transformasi Kode: Sebelum vs Sesudah
#### 🔴 SEBELUM (Pola Monolitik Rentan Bug di `_shoppingCart.php`):
```php
// KODE LAMA: 30 baris logika kotor di controller
$stok_booking = isset($tmp['stok_booking']) ? ($tmp['stok_booking'] * 1) : 0;
if ($sesMains['pihakMainJenis'] == "center") { // ← Magic string rentan salah
$stokFisik = isset($tmp['stok_center']) ? ($tmp['stok_center'] * 1) : 0;
$tmp['stok_ready_input'] = ($stokFisik - $stok_booking) - $itemJml;
} else {
$stokFisik = isset($tmp['stok']) ? ($tmp['stok'] * 1) : 0;
$tmp['stok_ready_input'] = ($stokFisik - $stok_booking) - $itemJml;
}
if ($tmp['stok_ready_input'] < 0) { ... }
```
#### 🟢 SESUDAH (Pola Bersih Delegasi ke `ComStockEngine`):
```php
// KODE BARU: 5 baris bersih & bebas bug
$this->load->model('Coms/ComStockEngine');
$stockStatus = $this->ComStockEngine->getStockStatus(
$iSpec['id'],
isset($sesMains['gudang_status_id']) ? $sesMains['gudang_status_id'] : WH_STATUS_CABANG_ID,
my_cabang_id(),
isset($iSpec['jml']) ? $iSpec['jml'] : 0,
isset($tmp['kategori_id']) ? $tmp['kategori_id'] : null
);
$tmp['stok_ready_input'] = $stockStatus['sisa_siap_jual'];
$tmp['stok_ready'] = $stockStatus['sisa_siap_jual'];
$tmp['stok'] = $stockStatus['sisa_siap_jual'];
if ($stockStatus['is_minus']) {
$arrProdukStokKurang[$iSpec['id']] = ...;
}
```
---
## 🚦 CHECKLIST STANDAR PENGERJAAN SETIAP SUB-MODUL (SOP)
Sebelum menyatakan 1 controller selesai di-refactor, ikuti 4 langkah verifikasi:
1. [ ] **Load Engine:** Panggil `$this->load->model('Coms/NamaEngine');`.
2. [ ] **Hapus Rumus Mentah:** Pastikan tidak ada operasi matematika manual (`-`, `+`, `*`, `%`) di controller.
3. [ ] **Hapus Kueri Database Mentah:** Controller tidak boleh lagi melakukan `$this->db->get('stock_locker')` secara langsung.
4. [ ] **Uji Regresi Otomatis (*Unit Test*):** Jalankan skrip pengujian (seperti `test_com_stock_engine.php`) untuk memastikan hasil kalkulasi 100% cocok dengan skenario:
* Skenario Cabang (Pinang)
* Skenario Pusat (DC)
* Skenario Pengecualian Jasa
* Skenario Stok Minus / Over-order