# 📘 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