# BLUEPRINT UPGRADE MODUL `konversi` MENJADI SUPPORT PRODUK VARIAN

## 1. Tujuan

Meng-upgrade modul [konversi](../application/modules/konversi/) yang saat ini berperilaku non-varian agar bisa memproses konversi produk berbasis varian secara aman, tanpa merusak flow existing non-varian.

Target bisnis utama:

1. Konversi source produk/varian ke target produk/varian dengan kontrol qty yang ketat.
2. Integritas stok: `total qty source = total qty target`.
3. Integritas posting stok & accounting tetap atomik dan bisa rollback.
4. Backward compatibility: flow lama non-varian tetap jalan.

## 2. Scope

### In Scope

1. Flow product conversion pusat (`1334`) dan cabang (`334`) di [coTransaksiUi.php](../application/modules/konversi/config/coTransaksiUi.php).
2. Layer selector + shopping cart + validate + followup.
3. Value gate `items`, `items2`, `items2_sum` untuk data varian.
4. Posting stock/accounting agar varian-aware.

### Out of Scope

1. Rewrite total modul `konversi`.
2. Penggantian seluruh UI template.
3. Perubahan skema besar lintas modul di luar kebutuhan varian.

## 3. Baseline Saat Ini (Root Cause Teknis)

### 3.1 Kontrak UI masih non-varian

1. Flow `1334` memakai selector source `MdlProduk2` dan target pairing `MdlProduk2` tanpa kontrak varian:
   - [application/modules/konversi/config/coTransaksiUi.php:39](../application/modules/konversi/config/coTransaksiUi.php:39)
   - [application/modules/konversi/config/coTransaksiUi.php:232](../application/modules/konversi/config/coTransaksiUi.php:232)
2. `shoppingCartValidatorsPairedItem` membandingkan source `items` vs target `items2_sum`, tapi belum level varian per parent:
   - [application/modules/konversi/config/coTransaksiUi.php:275](../application/modules/konversi/config/coTransaksiUi.php:275)

### 3.2 Processor target belum memuat stok varian

1. `resultSelect()` menerima `id2` sebagai `produk_id` target biasa, lalu lookup ke model produk umum:
   - [application/modules/konversi/controllers/_processSelectProductConvertion.php:824](../application/modules/konversi/controllers/_processSelectProductConvertion.php:824)
   - [application/modules/konversi/controllers/_processSelectProductConvertion.php:844](../application/modules/konversi/controllers/_processSelectProductConvertion.php:844)
2. Belum ada loader `MdlProdukVarian` dan belum ada query `stock_locker_variant`.

### 3.3 Cart edit target bersifat generik, belum varian-distribution

1. `recordPairedItem()` dan `recordPairedItemSatuan()` menulis `items2_sum` generik per baris, belum mengelola child-variant per parent:
   - [application/modules/konversi/controllers/_shoppingCart.php:2918](../application/modules/konversi/controllers/_shoppingCart.php:2918)
   - [application/modules/konversi/controllers/_shoppingCart.php:3117](../application/modules/konversi/controllers/_shoppingCart.php:3117)
2. Tidak ada guard eksplisit `total qty varian <= qty parent` per parent product dalam path ini.

### 3.4 Core posting masih non-varian

1. Komponen target masih memakai:
   - `FifoProdukJadi`
   - `LockerStock`
   - `LockerStockMutasi`
   - [application/modules/konversi/config/coTransaksiCore.php:590](../application/modules/konversi/config/coTransaksiCore.php:590)
   - [application/modules/konversi/config/coTransaksiCore.php:616](../application/modules/konversi/config/coTransaksiCore.php:616)
   - [application/modules/konversi/config/coTransaksiCore.php:637](../application/modules/konversi/config/coTransaksiCore.php:637)
2. Belum ada `variant_id` sebagai identity posting.

### 3.5 Dampak bisnis jika tetap non-varian

1. Risiko salah posting ke produk parent/produk umum, bukan ke SKU varian.
2. Risiko qty mismatch antar source vs target varian.
3. Risiko audit trail parent-variant tidak traceable.

## 4. Opsi Implementasi Native

### Opsi A (Recommended): Satu flow dengan mode resolver

Inti:

1. Flow `1334` dan `334` tetap dipakai.
2. Sistem menentukan mode konversi dari tipe source dan target:
   - Varian -> Varian
   - Non-Varian -> Varian
   - Varian -> Non-Varian
   - Non-Varian -> Non-Varian
3. Validator dan komponen posting dipilih berdasarkan mode tersebut.

Kelebihan:

1. User tetap di modul `konversi`, minim perubahan operasional.
2. Backward compatible: non-varian tetap lewat path lama.
3. Tidak perlu memindahkan user ke modul lain.

Konsekuensi:

1. Perlu penambahan logic bercabang di beberapa file legacy.

### Opsi B: Split flow per mode

Inti:

1. Buat flow/config terpisah untuk masing-masing mode.
2. Setiap mode punya selector, validator, dan core config sendiri.

Kelebihan:

1. Lebih mudah dibaca per mode.
2. Risiko salah cabang logic lebih kecil.

Konsekuensi:

1. Maintenance lebih berat karena konfigurasi berulang.
2. Perubahan rule global harus disalin ke banyak flow.

Catatan keputusan: delegasi proses varian ke modul `variant_cutover` tidak dipakai dalam blueprint ini. Modul `variant_cutover` hanya menjadi referensi pola implementasi.

## 5. Rekomendasi Blueprint

Pilih **Opsi A** dengan mode resolver native + feature flag.

Alasan:

1. Menjaga alur user existing di `konversi`.
2. Lebih aman untuk migrasi bertahap (canary per flow/per cabang).
3. Blast radius bisa dikendalikan tanpa memindahkan proses ke modul lain.

## 6. Desain Teknis Target

### 6.1 Contract Session (baru)

1. `items_source`:
   - Sumber stok yang akan dikurangi.
   - Field minimal: `item_type`, `produk_id`, `variant_id`, `parent_produk_id`, `jml`, `current_stok`, `hpp`.
   - `item_type` berisi `produk` atau `variant`.
2. `items_target`:
   - Tujuan stok yang akan ditambah.
   - Field minimal: `item_type`, `produk_id`, `variant_id`, `parent_produk_id`, `jml`, `hpp_injector`.
3. `items`:
   - Tetap dipakai sebagai gate legacy untuk source supaya flow lama tidak rusak.
4. `items2`:
   - Dipakai untuk detail target dan detail varian per parent jika target/source berupa varian.
   - Struktur varian: `items2[parent_produk_id][variant_id] = {variant_id, sku, current_stok, jml, ...}`.
5. `items2_sum`:
   - Gate agregat untuk posting target.
   - Untuk item varian wajib membawa `variant_id`.
   - Untuk item non-varian `variant_id` harus kosong/null.
6. `conversion_mode`:
   - Disimpan di session/main value agar validate dan followup membaca mode yang sama.
   - Nilai valid: `M1`, `M2`, `M3`, `M4`.

### 6.2 Contract Validasi

Rule global:

1. `sum(items_source.*.jml) == sum(items_target.*.jml)`.
2. `jml` setiap baris harus `> 0`.
3. Source dan target yang identik harus ditolak.
4. Source stock wajib cukup:
   - source `produk` dicek ke `stock_locker`.
   - source `variant` dicek ke `stock_locker_variant`.
5. Target stock tidak dipakai sebagai batas penambahan, kecuali target juga menjadi source pada baris lain dalam transaksi yang sama.
6. `variant_id` wajib valid dan sesuai `parent_produk_id` untuk semua item bertipe `variant`.
7. Jika gagal, blokir tombol approve dengan pesan spesifik per source/target.

### 6.3 Contract Posting

Komponen ditentukan dari `item_type`, bukan hanya dari flow:

1. Source `produk`:
   - `LockerStock`
   - `LockerStockMutasi`
2. Source `variant`:
   - `LockerStockVariant`
   - `LockerStockMutasiVariant`
3. Target `produk`:
   - `FifoProdukJadi`
   - `LockerStock`
   - `LockerStockMutasi`
4. Target `variant`:
   - `FifoProdukJadiVarian`
   - `LockerStockVariant`
   - `LockerStockMutasiVariant`
5. `variant_id` wajib ikut di gate/table mapping hanya untuk item bertipe `variant`.
6. Jika engine config tidak bisa bercabang dalam satu gate, buat gate terpisah:
   - `items_source_produk`
   - `items_source_variant`
   - `items_target_produk`
   - `items_target_variant`

## 7. Mapping Perubahan File

### 7.1 Config UI

File: [application/modules/konversi/config/coTransaksiUi.php](../application/modules/konversi/config/coTransaksiUi.php)

1. Tambah flag mode varian untuk flow `1334` dan `334`, contoh:
   - `variant_mode_enabled = true`
2. Tambah mode selector agar user bisa memilih tipe source dan target (`produk` atau `variant`).
3. Ganti `editHandlerMethod2` ke handler varian hanya jika salah satu sisi bertipe `variant`.
4. Tambah kolom UI:
   - source: `item_type`, `current_stok`, `distribute`, `sisa_distribute`
   - target: `item_type`, `sku`, `header_varian`, `current_stok`, `jml`
5. Sesuaikan `shoppingCartValidatorsPairedItem` agar validasi membaca `conversion_mode`.

### 7.2 Selector Processor

File: [application/modules/konversi/controllers/_processSelectProductConvertion.php](../application/modules/konversi/controllers/_processSelectProductConvertion.php)

1. Tambah `loadVarianProduk($produkId)` via `MdlProdukVarian`.
2. Tambah `getVariantCurrentStock($variantId)` dari tabel `stock_locker_variant` dengan Query Builder (binding-safe).
3. Tambah resolver mode:
   - `resolveConversionMode($sourceType, $targetType)`.
4. Saat source/target bertipe varian:
   - preload varian ke struktur session yang sesuai.
5. Pertahankan path lama bila source dan target sama-sama non-varian.

### 7.3 Shopping Cart Handler

File: [application/modules/konversi/controllers/_shoppingCart.php](../application/modules/konversi/controllers/_shoppingCart.php)

1. Tambah method `recordItemColumnVarian()` sebagai handler alokasi varian.
2. Guard qty:
   - update per varian.
   - cegah total target melebihi total source.
   - cegah total target kurang dari total source saat approve.
3. Rebuild `items_source`, `items_target`, dan `items2_sum` setiap kali alokasi berubah.
4. Update `items[parent].distribute` dan `items[parent].sisa_distribute` untuk mode yang memakai parent dengan banyak varian.

### 7.4 Validator Approval

File: [application/modules/konversi/controllers/Transaksi.php](../application/modules/konversi/controllers/Transaksi.php)

1. Tambah blok validasi varian untuk flow `1334`/`334`:
   - strict equality total source vs total target.
   - cek stok source sesuai `item_type`.
   - cek mapping `variant_id` ke parent.
2. Pertahankan validasi lama untuk flow non-varian.
3. Tambah pesan error yang actionable per parent/variant.

### 7.5 Core Posting

File: [application/modules/konversi/config/coTransaksiCore.php](../application/modules/konversi/config/coTransaksiCore.php)

1. Tambah mapping `variant_id` pada gate source dan target.
2. Pisahkan gate berdasarkan tipe item bila config engine tidak bisa branch:
   - source produk
   - source variant
   - target produk
   - target variant
3. Pakai komponen native untuk item `produk` dan komponen varian-aware untuk item `variant`.
4. Pastikan `tableIn detail/detail2/detail2_sum` membawa `item_type`, `produk_id`, dan `variant_id`.

### 7.6 Value Gate

File: [application/modules/konversi/config/coTransaksiValues.php](../application/modules/konversi/config/coTransaksiValues.php)

1. Pastikan transform source/target menyertakan `item_type`, `produk_id`, dan `variant_id`.
2. Pastikan builder nilai (`sub_*`, `hpp_injector`) tetap konsisten saat baris source/target berupa varian atau non-varian.

## 8. Rencana Implementasi Bertahap

### Fase 0 - Baseline & Toggle

1. Tambah feature flag `variant_mode_enabled` per flow.
2. Default `false` di production awal.
3. Tambah `conversion_mode` resolver tanpa mengubah posting.

### Fase 1 - Readiness Data

1. Implement loader varian + stok varian.
2. Implement session contract `items_source` dan `items_target`.
3. Pertahankan `items` dan `items2_sum` untuk compatibility legacy.

### Fase 2 - UI & Validator

1. Aktifkan `recordItemColumnVarian`.
2. Aktifkan validator strict qty balance.
3. Uji SoD:
   - `1334` perlu dipisahkan request vs approval (saat ini sama-sama `c_gudang`).

### Fase 3 - Posting Engine

1. Aktifkan komponen berdasarkan `item_type` pada core config.
2. Jalankan transaksi dalam `trans_start()/trans_complete()` existing flow followup.
3. Uji rollback path.

### Fase 4 - Canary Rollout

1. Aktifkan `variant_mode` hanya untuk flow cabang `334` dulu (lebih aman karena sudah beda role approval).
2. Setelah stabil, aktifkan `1334`.

## 9. Data Integrity Guardrails (Wajib)

1. Seluruh eksekusi followup tetap dalam 1 DB transaction per approval.
2. Tidak boleh ada SQL string manual untuk query varian; gunakan Query Builder / binding.
3. Blokir approve bila:
   - total source dan target kurang/lebih.
   - ada qty negatif.
   - stok source tidak cukup.
   - `variant_id` tidak sesuai parent.
4. Simpan relasi parent-variant dan `conversion_mode` di transaksi detail untuk audit.
5. Jangan pakai `current_stok` target sebagai batas penambahan stok. Batas stok hanya berlaku pada item yang dikurangi.

## 10. Skenario Verifikasi (UAT Teknis)

### 10.1 M1 Varian -> Varian

1. Source variant A qty 10.
2. Target variant B qty 10.
3. Approve sukses.
4. Verifikasi:
   - `stock_locker_variant` source berkurang 10.
   - `stock_locker_variant` target bertambah 10.
   - `variant_id` source dan target tersimpan di detail audit.

### 10.2 M2 Non-Varian -> Varian

1. Source parent qty 100.
2. Varian A=40, B=60.
3. Approve sukses.
4. Verifikasi:
   - source turun 100.
   - varian A/B naik sesuai.
   - jurnal/rekening balance.

### 10.3 M3 Varian -> Non-Varian

1. Source variant A qty 25.
2. Target non-varian qty 25.
3. Approve sukses.
4. Verifikasi:
   - `stock_locker_variant` source berkurang 25.
   - `stock_locker` target bertambah 25.
   - posting target tidak membawa `variant_id`.

### 10.4 M4 Non-Varian -> Non-Varian

1. Source produk X qty 50.
2. Target produk Y qty 50.
3. Approve sukses.
4. Verifikasi:
   - flow native tetap sama seperti sebelum upgrade.
   - tidak ada field varian wajib pada mode ini.

### 10.5 Over Allocation (harus gagal)

1. Source qty 100.
2. Input total target 101.
3. Approve diblokir dengan pesan detail.

### 10.6 Under Allocation (harus gagal)

1. Source qty 100.
2. Input total target 99.
3. Approve diblokir.

### 10.7 Stok Source Tidak Cukup (harus gagal)

1. Input jml source melebihi `current_stok`.
2. Simpan/approve diblokir.

### 10.8 Backward Compatibility

1. Source non-varian, pakai flow lama.
2. Pastikan request-approve tetap lolos seperti sebelum upgrade.

### 10.9 Concurrency

1. Dua user edit transaksi yang sama.
2. Pastikan qty tidak double-write dan hasil akhir tetap konsisten.

### 10.10 Mapping Varian Salah (harus gagal)

1. Pilih `variant_id` yang bukan child dari `parent_produk_id`.
2. Approve diblokir sebelum followup.

## 11. Risiko dan Mitigasi

1. Risiko: drift antara `items2` dan `items2_sum`.
   - Mitigasi: selalu rebuild `items2_sum` dari `items2` setelah edit varian.
2. Risiko: posting target masih ke komponen non-varian.
   - Mitigasi: test assertion pada comName aktif sebelum followup.
3. Risiko: SoD violation di `1334`.
   - Mitigasi: ubah `userGroup` step approval atau tambah hard-guard di `FollowUp`.

## 12. Deliverables

1. Dokumen blueprint ini.
2. Patch config + controller + validator + core mapping.
3. Checklist UAT flow `334` dan `1334`.
4. Catatan rollback plan (disable `variant_mode_enabled`).

## 13. Matriks Mode Konversi (Final Scope)

Empat mode upgrade yang disepakati:

1. `M1` Varian -> Varian
2. `M2` Non-Varian -> Varian
3. `M3` Varian -> Non-Varian
4. `M4` Non-Varian -> Non-Varian (native)

Resolver mode:

- `source_is_variant` = `{0|1}`
- `target_is_variant` = `{0|1}`
- mode ditentukan dari kombinasi source/target di atas.

### 13.1 Rule Global (Wajib semua mode)

1. Followup wajib atomic transaction (`trans_start` / `trans_complete`).
2. `total_qty_source == total_qty_target`.
3. Qty setiap baris harus `> 0`.
4. Cek stok real-time saat approve.
5. Concurrency guard wajib aktif.
6. Audit trail simpan tipe source/target + referensi item + qty + user + timestamp.
7. SoD: `requestor != approver`.

### 13.2 Rule per Mode

#### M1 Varian -> Varian

1. Source dari `stock_locker_variant`.
2. Target ke `stock_locker_variant`.
3. Jika lintas parent varian: default `ditolak`, hanya boleh jika flag `allow_cross_parent_variant=true`.
4. Pengurangan source dan penambahan target sama-sama pakai komponen varian-aware:
   - `FifoProdukJadiVarian`
   - `LockerStockVariant`
   - `LockerStockMutasiVariant`

#### M2 Non-Varian -> Varian

1. Source dari `stock_locker`.
2. Target ke `stock_locker_variant`.
3. Wajib ada distribusi varian dan total distribusi harus sama dengan qty source.
4. Pengurangan source non-varian tetap lewat komponen native source.
5. Penambahan target pakai komponen varian-aware.

#### M3 Varian -> Non-Varian

1. Source dari `stock_locker_variant`.
2. Target ke `stock_locker`.
3. Total qty source varian harus sama dengan qty target non-varian.
4. Pengurangan source pakai komponen varian-aware.
5. Penambahan target pakai komponen native non-varian (`FifoProdukJadi`, `LockerStock`, `LockerStockMutasi`).

#### M4 Non-Varian -> Non-Varian (Native)

1. Tetap memakai flow native existing.
2. Tidak boleh regress saat `variant_mode` aktif untuk mode lain.

### 13.3 Flag Konfigurasi Tambahan

1. `variant_mode_enabled` (global/per-flow)
2. `allow_cross_parent_variant` (default `false`)
3. `strict_qty_balance` (default `true`)
4. `enforce_sod` (default `true`)
5. `fallback_to_native_on_nonvariant` (default `true`)
6. `reject_self_conversion` (default `true`)
7. `validate_variant_parent_map` (default `true`)
8. `allow_decimal_qty` (default ikut konfigurasi satuan produk)
9. `allow_manual_hpp_override` (default `false`)
10. `allow_unit_ratio_conversion` (default `true`, wajib validasi rasio)

### 13.4 Acceptance Criteria UAT

Untuk tiap mode `M1..M4` minimal lulus:

1. Happy path.
2. Insufficient stock diblokir.
3. Over-allocation diblokir.
4. Under-allocation diblokir.
5. Rollback saat simulasi gagal di tengah.
6. Concurrency 2 user tidak menimbulkan double movement.
7. Jurnal dan stok akhir balance.

## 14. Rule Tambahan Wajib Sebelum Coding

### 14.1 Satuan dan Rasio Konversi

1. Jika source dan target berbeda satuan, sistem wajib menyimpan `jml_per_satuan`.
2. `jml_per_satuan` harus `> 0`.
3. Jika hasil konversi menghasilkan pecahan:
   - boleh hanya jika satuan produk mengizinkan decimal qty.
   - jika tidak ada konfigurasi satuan decimal, default ditolak.
4. Tidak boleh ada pembulatan diam-diam pada qty stok.

### 14.2 Konsistensi Nilai dan HPP

1. Total nilai source wajib sama dengan total nilai target.
2. Formula minimal:
   - `sum(source_qty * source_hpp) == sum(target_qty * hpp_injector)`
3. `hpp_injector` target harus berasal dari nilai source atau aturan costing yang jelas.
4. Manual override HPP hanya boleh jika `allow_manual_hpp_override=true` dan tercatat di audit.

### 14.3 Locker Hold dan Release

1. Source `produk` memakai hold di `stock_locker`.
2. Source `variant` memakai hold di `stock_locker_variant`.
3. Hold wajib dilepas saat:
   - item dihapus dari cart.
   - transaksi dibatalkan.
   - rollback.
   - sesi expired sebelum approve.
4. Target tidak perlu hold karena target adalah penambahan stok.

### 14.4 Audit Minimum

Setiap transaksi konversi wajib menyimpan:

1. `conversion_mode`.
2. source `item_type`, `produk_id`, `variant_id`, qty, HPP, stok sebelum.
3. target `item_type`, `produk_id`, `variant_id`, qty, HPP, stok sebelum.
4. user request, user approve, timestamp server.
5. status akhir: `APPROVED`, `FAILED`, atau `ROLLED_BACK`.

### 14.5 Tambahan UAT Edge Case

1. Self-conversion ditolak.
2. Financial mismatch diblokir.
3. Rasio satuan pecahan ditolak jika satuan tidak support decimal.
4. Hold source dilepas setelah rollback/cancel/remove item.

## 15. Kesesuaian terhadap `STANDAR_MODUL_PENJUALAN_ISO25010.md`

Standar penjualan dipakai sebagai baseline kontrol mutu ERP. Tidak semua kontrol sales relevan langsung untuk modul konversi stok, sehingga status memakai:

- `Lulus`: sudah tercakup eksplisit di blueprint.
- `Partial`: sudah ada arah kontrol, tetapi perlu detail implementasi/evidence.
- `Gap`: belum cukup tercakup dan perlu ditambahkan sebelum coding/release.
- `N/A`: tidak relevan untuk modul konversi stok.

| Area Standar | Status | Kesesuaian di Blueprint | Gap yang Perlu Ditutup |
|---|---|---|---|
| FS-01/02/03 Functional Suitability | Partial | Empat mode M1-M4, qty balance, HPP balance, dan UAT sudah didefinisikan | Perlu checklist release khusus konversi, bukan checklist sales |
| RL-01/03/04 Reliability | Partial | Atomic transaction, rollback, hold release, dan concurrency sudah ada | Belum ada error-state recovery formal jika proses crash di tengah followup |
| PE-01/02/03 Performance | Gap | Belum ada target performa spesifik | Tambah KPI: load varian <2 detik, approve 50 baris <10 detik, RAM <=256 MB |
| US-01/02/03/04 Usability | Partial | User error protection sudah kuat melalui validasi qty/stok/mapping | Belum ada standar ukuran tombol, responsif tablet/PC, dan pesan error final |
| SC-01/02/03 Security | Partial | Audit minimum, SoD, reject self-conversion sudah ada | Audit belum dinyatakan immutable, nomor unik/timestamp/hash belum menjadi release gate |
| SC-04/05 Authenticity/Confidentiality | Gap | Belum dibahas di blueprint | Perlu mapping role akses source/target/HPP dan timeout sesi approval |
| CP-01 Compatibility | Partial | Integrasi stok dan accounting sudah dipetakan via komponen `Locker/Fifo/Jurnal` | Perlu verifikasi posting jurnal/rekening per mode M1-M4 |
| MT-01/02/03 Maintainability | Partial | File impact dan mode resolver sudah ada | Belum ada standar error logging file/baris/stack trace/fase gagal |
| PT-01/02 Portability | Gap | Belum ada standar tampilan/responsif/install | Perlu UAT minimal PC 1024x768 dan tablet 800x1280 jika UI dipakai gudang |
| QU-01..05 Quality in Use | Partial | UAT edge case sudah ada | Belum ada KPI go-live: rollback rate, mismatch stock, waktu proses |
| SoD-01..10 | Partial | `requestor != approver` sudah ditetapkan | Flow `1334` masih perlu hard-guard karena baseline role bisa sama-sama `c_gudang` |
| CMP-01..15 Compliance | Partial | Audit minimum sudah ada | Belum ada retensi 5 tahun, change management, backup/recovery, incident response, evidence path |
| PRC-01..08 Price Control | N/A/Adapted | Diskon sales tidak relevan; HPP/value control dipakai sebagai adaptasi | Pastikan financial mismatch diblokir dan HPP override perlu approval |
| CL-01..06 Credit Limit | N/A | Tidak ada pelanggan/piutang di modul konversi | Tidak perlu dibawa ke blueprint |
| INV-01..07 Stock Allocation | Partial | Negative stock, real-time stock, soft lock/hold, release hold sudah ada | Perlu expiry hold dan aturan satu gudang per transaksi konversi |
| OPS-01..07 Delivery/Billing | N/A/Adapted | Over/under delivery tidak relevan; over/under qty konversi dipakai strict zero tolerance | Jika ada override qty/nilai, wajib alasan + approval |
| DPS-01..06 Dropship/Pre-order | N/A | Tidak relevan untuk konversi stok internal | Tidak perlu dibawa ke blueprint |
| L-01..08 Larangan Teknis | Partial | Negative stock, float/value, SoD, audit sudah tercakup sebagian | Tambah larangan hard delete, SQL manual tanpa transaksi, dan float untuk qty/nilai |
| LC-01..12 Lean Compliance | Gap | Belum ada evidence/risk register/CAPA/BIA/DR gate | Tambah section evidence minimum untuk release konversi |

Kesimpulan kesesuaian:

1. Blueprint sudah cukup kuat untuk aspek bisnis inti konversi: stok, qty balance, HPP balance, SoD dasar, dan 4 mode.
2. Blueprint belum cukup jika dipakai sebagai dokumen release audit setara standar penjualan.
3. Sebelum coding besar, tambahkan minimal:
   - release checklist konversi,
   - KPI performa,
   - error logging/recovery,
   - audit immutable + retensi,
   - evidence path,
   - larangan teknis eksplisit.

## 16. Adopsi Standar Existing sebagai Default

Keputusan: modul `konversi` upgrade varian mengikuti standar existing sebagai default. User/business hanya perlu override jika ada aturan bisnis yang berbeda.

Prioritas standar:

1. `application/modules/variant_cutover/STANDAR_MODUL_VARIANT_CUTOVER_ISO25010.md` untuk kontrol stok, varian, HPP, rollback, lock, dan audit konversi.
2. `STANDAR_MODUL_PENJUALAN_ISO25010.md` untuk kontrol mutu ERP umum: SoD, audit, release checklist, KPI, larangan teknis, dan evidence compliance.
3. Blueprint ini menjadi adaptasi khusus modul `konversi` dengan 4 mode M1-M4.

### 16.1 Status Adopsi Kontrol

| Kontrol | Status | Default yang Dipakai di Modul `konversi` |
|---|---|---|
| FS-01/02/03 | ADAPTED | Fitur minimal adalah M1-M4, qty source = qty target, nilai source = nilai target, rollback tersedia |
| RL-03/TPC-01/TPC-05 | ADOPTED | Followup harus dalam 1 DB transaction; gagal di tengah wajib rollback penuh |
| PE-01/02/03 | ADOPTED | Load varian/open check <3 detik, approve 50 baris <10 detik, rollback <5 detik, RAM <=256 MB |
| US-02/US-03 | ADOPTED | Tombol aksi utama minimal 48x48 px, konfirmasi sebelum approve/rollback, error harus menjelaskan item dan penyebab |
| SC-01/SC-02/CMP-01 | ADOPTED | Audit konversi immutable, tidak boleh diedit/hapus dari aplikasi, minimal simpan 5 tahun |
| SC-03/SoD-01/SoD-04 | ADOPTED | Requestor tidak boleh approve/rollback transaksi yang sama |
| CMP-02 | ADOPTED | Timestamp audit wajib dari server, timezone UTC+7 mengikuti server ERP |
| CMP-05 | ADOPTED | Perubahan kode production wajib tercatat siapa/kapan/apa dan approval minimal 2 orang |
| CMP-06/LC-05 | ADOPTED | Backup harian, RPO <=24 jam, RTO <=4 jam, BIA ringkas wajib ada untuk release besar |
| PST-02/INV-02 | ADOPTED | Cek stok source real-time saat approve, bukan hanya dari session/cache |
| PST-05 | ADOPTED | Satu transaksi konversi hanya untuk satu gudang |
| PST-06/PST-07/INV-03/INV-04 | ADOPTED | Source stock wajib hold/lock dan wajib release saat remove, cancel, rollback, timeout |
| FVC-01/FVC-02/FVC-03 | ADOPTED | Nilai inventory sebelum dan sesudah harus sama; HPP target berasal dari source atau override berapproval |
| FVC-04/L-04 | ADOPTED | Dilarang pakai FLOAT untuk qty, harga, HPP, dan total nilai; gunakan DECIMAL/string numeric |
| ODC-01..06 | ADAPTED | Cek open document wajib jika konversi mengubah status/mapping parent-varian; untuk stock-only conversion dipakai sebagai warning/block sesuai config |
| TPC-06/TPC-07 | ADOPTED | Status minimal: DRAFT, IN_PROGRESS, COMPLETED, FAILED, ROLLED_BACK; timeout proses default 30 menit |
| MT-02 | ADOPTED | Error log wajib berisi transaksi_id, mode, fase, file, line, timestamp, stack trace |
| LC-01..LC-04 | ADOPTED | Risk register, SOP incident, rekonsiliasi akun adjustment, dan CAPA log wajib tersedia sebagai evidence release |

### 16.2 Release Checklist Konversi

Release modul `konversi` upgrade varian ditolak jika salah satu item ini belum lulus:

1. M1 Varian -> Varian lulus happy path, rollback, dan insufficient stock.
2. M2 Non-Varian -> Varian lulus qty balance dan HPP balance.
3. M3 Varian -> Non-Varian lulus qty balance dan HPP balance.
4. M4 Non-Varian -> Non-Varian tidak regress dari flow native existing.
5. Source stock real-time dibaca dari `stock_locker` atau `stock_locker_variant` sesuai `item_type`.
6. Source hold/lock dibuat dan release saat remove/cancel/rollback/timeout.
7. `conversion_mode`, `item_type`, `produk_id`, `variant_id`, qty, HPP, user request, user approve, dan timestamp server tercatat di audit.
8. Audit log tidak bisa diedit/hapus dari aplikasi.
9. `requestor != approver` dan `requestor != rollback_user`.
10. Total qty source = total qty target.
11. Total nilai source = total nilai target.
12. Tidak ada penggunaan FLOAT untuk qty/nilai/HPP.
13. Semua query baru memakai Query Builder/binding.
14. Error logging mencatat fase gagal dan transaksi_id.
15. Evidence UAT dan compliance tersimpan di path standar.

### 16.3 KPI Performa Adopted

| KPI | Target |
|---|---|
| Load daftar source/target varian | < 3 detik |
| Approve konversi 50 detail | < 10 detik |
| Rollback konversi | < 5 detik |
| Memory proses PHP-FPM | <= 256 MB |
| Selisih stok akibat konversi | 0 kejadian per bulan |
| SoD violation | 0 kejadian per bulan |
| Konversi tanpa audit trail | 0 kejadian per bulan |
| Rollback rate | <= 5% dari total konversi |

### 16.4 Larangan Teknis Adopted

1. Dilarang hard delete transaksi/audit konversi.
2. Dilarang update/insert stok manual tanpa transaksi operasional.
3. Dilarang commit per fase; followup wajib atomic.
4. Dilarang pakai FLOAT untuk qty, harga, HPP, dan total nilai.
5. Dilarang approve source dan target yang identik.
6. Dilarang bypass mapping `variant_id` ke `parent_produk_id`.
7. Dilarang konversi tanpa audit trail.
8. Dilarang membiarkan hold source menggantung setelah gagal/cancel/rollback.
9. Dilarang memberi akses request dan approve ke user yang sama untuk transaksi yang sama.
10. Dilarang menebak alokasi varian otomatis tanpa input user atau rule config tertulis.

### 16.5 Evidence Path Adopted

Evidence release disimpan di:

`docs/evidence/konversi/<control_id>_<topik>_<yyyy-mm-dd>.md`

Evidence minimum:

1. `fs-02_m1_m2_m3_m4_qty_balance_<tanggal>.md`
2. `fvc-01_hpp_balance_<tanggal>.md`
3. `rl-03_atomic_rollback_<tanggal>.md`
4. `pst-06_hold_release_<tanggal>.md`
5. `sod-01_request_approve_separation_<tanggal>.md`
6. `cmp-01_audit_immutable_<tanggal>.md`
7. `pe-01_performance_50_detail_<tanggal>.md`
8. `mt-02_error_logging_recovery_<tanggal>.md`
9. `lc-01_risk_register_<tanggal>.md`
10. `lc-03_inventory_adjustment_reconciliation_<tanggal>.md`

## 17. Checklist Gap yang Ditutup Setelah Review

1. Delegasi ke `variant_cutover` dihapus dari rekomendasi implementasi.
2. Contract session diperluas dari parent->varian menjadi source/target generic.
3. Validasi stok diperbaiki: batas stok berlaku pada source yang dikurangi, bukan target yang ditambah.
4. Posting engine dibuat berbasis `item_type`, sehingga M1/M2/M3/M4 bisa memakai komponen yang benar.
5. UAT dibuat eksplisit untuk semua mode, bukan hanya Non-Varian -> Varian.
6. Rule satuan, HPP, hold/release, dan audit minimum ditambahkan.
7. Matriks kesesuaian terhadap standar penjualan ISO25010 ditambahkan.
8. Standar existing diadopsi sebagai default release gate modul `konversi`.

---

## Referensi pembanding varian-aware (internal)

Untuk implementasi detail, jadikan pola ini sebagai rujukan:

1. [application/modules/variant_cutover/config/coTransaksiUi.php:452](../application/modules/variant_cutover/config/coTransaksiUi.php:452) (`recordItemColumnVarian`)
2. [application/modules/variant_cutover/controllers/_processSelectProductConvertion.php:1156](../application/modules/variant_cutover/controllers/_processSelectProductConvertion.php:1156) (`loadVarianProduk`)
3. [application/modules/variant_cutover/controllers/_processSelectProductConvertion.php:1172](../application/modules/variant_cutover/controllers/_processSelectProductConvertion.php:1172) (`getVariantCurrentStock`)
4. [application/modules/variant_cutover/controllers/_shoppingCart.php:3373](../application/modules/variant_cutover/controllers/_shoppingCart.php:3373) (`recordItemColumnVarian`)
5. [application/modules/variant_cutover/config/coTransaksiCore.php:651](../application/modules/variant_cutover/config/coTransaksiCore.php:651) (`FifoProdukJadiVarian`)
6. [application/modules/variant_cutover/config/coTransaksiCore.php:678](../application/modules/variant_cutover/config/coTransaksiCore.php:678) (`LockerStockVariant`)
7. [application/modules/variant_cutover/config/coTransaksiCore.php:700](../application/modules/variant_cutover/config/coTransaksiCore.php:700) (`LockerStockMutasiVariant`)
