# Analisis Modul Pembatalan - Locker dan Alur Pembatalan

## 1. Konteks Utama

Modul `pembatalan` berfungsi untuk membatalkan transaksi yang sudah tercatat dalam sistem. Pembahasan ini meliputi:
- mekanisme locker (penguncian stok/transaksi)
- alur pembatalan nota/transaksi
- pengecekan validasi sebelum pembatalan

## 2. Ringkasan Temuan dari `_processSelectNotaRevert.php`

### 2.1 Locker Stok Produk

Fungsi `select()` di `application/modules/pembatalan/controllers/_processSelectNotaRevert.php` memiliki logika locker produk.

Jika `lockerCheck.enabled == true`, modul melakukan:
- lookup `MdlLockerStock` atau model locker sesuai konfigurasi
- validasi ketersediaan stok
- update `active` stock untuk mengurangi jumlah yang tersedia
- update/insert `hold` stock untuk user saat seleksi barang

Ini berfungsi sebagai perlindungan stok produk agar tidak terambil ganda.

### 2.2 Tidak Ada Locker Transaksi di `select()`

Pada path `select()` tidak ditemukan mekanisme untuk:
- mengunci nomor nota atau transaksi pembatalan secara keseluruhan
- mencegah notifikasi/nota yang sama dipilih ulang oleh user lain

Dengan demikian, ada perbedaan antara:
- `locker stock`: melindungi stok item
- `locker transaksi`: melindungi dokumen nota atau transaksi secara langsung

### 2.3 Locker Transaksi Spesifik di Post-Processing

Hanya pada konfigurasi post-processing tertentu (`16677`, `16678`) ditemukan `LockerTransaksi` yang mengubah status hold untuk transaksi komisi.

Itu adalah mekanisme khusus setelah save, bukan bagian dari proses `select()`.

## 3. Alur Pembatalan yang Dibahas

### 3.1 Validasi Sebelum Pembatalan

Pada modul ini, beberapa validasi yang sudah ada antara lain:
- FIFO stock validation untuk jenis nota tertentu
- cek apakah ada registri yang menunjukkan transaksi sudah dikirim/diproses
- cek detail qty (`produk_ord_jml` vs `valid_qty`) saat `detailCekQty` diaktifkan
- pemeriksaan hubungan transaksi dengan payment source, sales order, packing list, dan retur

### 3.2 Kasus Umum Pembatalan

Faktor pembatalan yang relevan untuk sistem operasi:
- salah barang
- salah orang
- salah metode pembayaran
- stok tidak tersedia / barang habis
- transaksi sudah diproses lebih lanjut (faktur, kirim, retur)
- masalah invoice/payment source

### 3.3 Kondisi Pembatalan Dibatalkan

Beberapa kondisi khusus yang memblokir pembatalan:
- transaksi sudah dikirim sebagai packing list (`5822spd`, `5823spd`)
- faktur PPN keluaran sudah dibuat
- retur pembelian atau retur penjualan sudah tercatat
- nota/so sudah cancel/reject sebelumnya

## 4. Rekomendasi Teknis

### 4.1 Tambahkan Locker Transaksi untuk Nota Pembatalan

Untuk mencegah `select` ulang nota `9912` atau `9911`, disarankan:
- buat validasi locker transaksi di awal `select()`
- gunakan model `LockerTransaksi` atau model serupa untuk cek `state='hold'` dan `jumlah=1`
- bila ada lock aktif, tampilkan pesan bahwa nota sedang diproses oleh user lain
- lepas lock saat user membatalkan atau proses pembatalan selesai

### 4.2 Pertajam Validasi Pembatalan

Sebaiknya sistem melakukan validasi tambahan seperti:
- cek status transaksi induk/referensi sebelum membatalkan
- cek kembali ketersediaan stok jika pembatalan akan mengembalikan stok
- verifikasi apakah pembayaran terkait sudah dibatalkan atau belum

### 4.3 Dokumentasi dan Tim Lanjutan

File ini bisa digunakan sebagai dasar diskusi bagi tim teknis:
- programmer dapat implementasi mekanisme locker transaksi
- analis bisnis dapat memutuskan alasan pembatalan mana yang wajib ditangani
- tim QA dapat membuat skenario uji untuk kasus `select` ulang dan pembatalan nota

## 5. File Terkait

- `application/modules/pembatalan/controllers/_processSelectNotaRevert.php`
- `application/modules/pembatalan/controllers/Create.php`
- `application/config/heTransaksi_pembatalanValidate.php` (atau konfigurasi terkait)
- `application/config/heTransaksi_pembatalanChecker.php` (atau konfigurasi terkait)

## 6. Pembahasan & Rekomendasi Tambahan (Hasil Diskusi)

### 6.1 Antisipasi Kondisi Balapan (Race Condition)
Jika dua user membuka nota yang sama pada saat yang bersamaan, query `SELECT` biasa tidak cukup.
- **Rekomendasi**: Gunakan **MariaDB Row Locking (`FOR UPDATE`)** di dalam transaksi database (`$this->db->trans_start()` ... `$this->db->trans_complete()`).
- Skema query:
  ```sql
  SELECT id, oleh_id, oleh_nama 
  FROM stock_locker_transaksi 
  WHERE transaksi_id = ? 
    AND state = 'hold' 
    AND jumlah = '1' 
  FOR UPDATE
  ```
  Ini memaksa database mengantrekan request kedua hingga transaksi pertama selesai, sehingga menjamin hanya 1 user yang mendapatkan akses edit.

### 6.2 Desain Notifikasi Ramah Pengguna Awam
Menghindari istilah teknis seperti "database lock" atau "conflict".
- **Judul**: ⚠️ Dokumen Sedang Digunakan
- **Pesan**: *"Maaf, Nota ini sedang diproses oleh [Nama Pengguna] ([Cabang]). Mohon tunggu beberapa saat atau hubungi rekan Anda untuk bergantian memproses nota ini agar data tidak tumpang tindih."*
- **Opsi Ambil Alih (Idle > 5 Menit)**: Tampilkan tombol *"Ambil Alih Dokumen"* dengan penjelasan ramah jika petugas pertama terdeteksi pasif.

