# 📘 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']] = ...;
}
```
---
## 🌉 BAGIAN 1D: POLA JEMBATAN CONFIG-DRIVEN KE DOMAIN PIPELINE ENGINE
Untuk menyatukan arsitektur *Config-Driven ERP* (`coTransaksiCore.php`) dengan *Domain-Driven Design (DDD)*:
* **Konfigurasi (`coTransaksiCore.php`)** bertindak sebagai **Domain Policy & Strategy Specification**.
* **`ComTransactionPipelineEngine.php`** bertindak sebagai **Application Pipeline Orchestrator** yang mengeksekusi tahapan:
1. `executePreProcessors()` $\rightarrow$ Model `Pre*` dinamis.
2. Simpan Dokumen Primer (`transaksi`) & Rincian (`transaksi_data`).
3. `executeSubComponents()` $\rightarrow$ Kartu Piutang Customer (`ComRekeningPembantuCustomer`), Persediaan, HPP Riil.
4. `executeMainComponents()` $\rightarrow$ Jurnal GL Otomatis (`ComJurnal`, `ComRekening`).
5. `processPaymentSources()` $\rightarrow$ Alokasi uang muka & piutang (`payment_source`).
6. `writeDataRegistries()` $\rightarrow$ Pencatatan metadata serial & registri (`transaksi_data_registry`).
7. `executePostProcessors()` $\rightarrow$ Penandatanganan & update plafon kredit.
* **`ComSalesOrderService.php`** bertindak sebagai **Domain Use Case Entrypoint** yang membungkus seluruh siklus di dalam transaksi ketat CI3 (`trans_start()` / `trans_complete()`).
---
## 🚦 CHECKLIST STANDAR PENGERJAAN SETIAP SUB-MODUL (SOP)
Sebelum menyatakan 1 controller selesai di-refactor, ikuti 4 langkah verifikasi:
1. [x] **Load Engine:** Panggil `$this->load->model('Coms/NamaEngine');`.
2. [x] **Hapus Rumus Mentah:** Pastikan tidak ada operasi matematika manual (`-`, `+`, `*`, `%`) di controller.
3. [x] **Hapus Kueri Database Mentah:** Controller tidak boleh lagi melakukan manipulasi tabel mutasi keuangan secara langsung.
4. [x] **Preservasi Pipeline Transaksional:** Seluruh buku pembantu, payment source, registri, dan jurnal akuntansi tetap dieksekusi melalui `ComTransactionPipelineEngine`.