# 📦 Analisa Modul Opname (Stock Opname)

## 1. Gambaran Umum

Modul **opname** adalah modul **Stok Opname (Physical Inventory Count)** yang menangani proses penghitungan fisik persediaan barang, membandingkannya dengan stok di sistem (buku), dan mencatat selisihnya sebagai transaksi adjustment di jurnal akuntansi.

**Jenis barang yang di-opname:**
| Jenis | Kode Transaksi (Pusat) | Kode Transaksi (Cabang) | COA Rekening |
|-------|------------------------|------------------------|--------------|
| Produk | `1119` | `2229` | `1010030030` (Persediaan Produk) |
| Supplies | `1118` | `2228` | `1010030010` (Persediaan Supplies) |
| Produk Rakitan | `5559` | `5559` | `1010030070` (Persediaan Produk Rakitan) |

---

## 2. Struktur File

### 2.1 Controllers (23 file)

| File | Ukuran | Peran |
|------|--------|-------|
| [`Modul_Controller.php`](file:///w:/everest_26sep/application/modules/opname/controllers/Modul_Controller.php) | 4.6 KB | **Base controller HMVC** — extends `MX_Controller`, load 4 config wajib |
| [`Opname.php`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php) | 370 KB | **Controller utama** — extends `CI_Controller` (BUKAN Modul_Controller!), menangani index, download Excel, upload Excel, executeOpname, dashboard opname |
| [`Create.php`](file:///w:/everest_26sep/application/modules/opname/controllers/Create.php) | 541 KB | Pembuatan transaksi opname (draft) |
| [`FollowUp.php`](file:///w:/everest_26sep/application/modules/opname/controllers/FollowUp.php) | 1.37 MB | Follow-up / approval transaksi opname (terbesar!) |
| [`_shoppingCart.php`](file:///w:/everest_26sep/application/modules/opname/controllers/_shoppingCart.php) | 339 KB | Manajemen shopping cart item opname |
| [`_processSelectProduct.php`](file:///w:/everest_26sep/application/modules/opname/controllers/_processSelectProduct.php) | 95 KB | Proses seleksi produk |
| [`Transaksi.php`](file:///w:/everest_26sep/application/modules/opname/controllers/Transaksi.php) | 282 KB | Daftar transaksi opname |
| [`Printing.php`](file:///w:/everest_26sep/application/modules/opname/controllers/Printing.php) | 353 KB | Cetak dokumen opname |
| [`ActivityReport.php`](file:///w:/everest_26sep/application/modules/opname/controllers/ActivityReport.php) | 499 KB | Laporan aktivitas opname |
| [`History.php`](file:///w:/everest_26sep/application/modules/opname/controllers/History.php) | 67 KB | Riwayat opname |
| [`_followupLiveEdit.php`](file:///w:/everest_26sep/application/modules/opname/controllers/_followupLiveEdit.php) | 117 KB | Live edit saat followup |
| [`_selectorItem.php`](file:///w:/everest_26sep/application/modules/opname/controllers/_selectorItem.php) | 25 KB | Picker produk/item |
| [`_selectorPihak.php`](file:///w:/everest_26sep/application/modules/opname/controllers/_selectorPihak.php) | 18 KB | Picker pihak (cabang) |
| [`_selectorPihakMain.php`](file:///w:/everest_26sep/application/modules/opname/controllers/_selectorPihakMain.php) | 23 KB | Picker pihak utama |
| [`_processPihak.php`](file:///w:/everest_26sep/application/modules/opname/controllers/_processPihak.php) | 36 KB | Proses pihak |
| [`_processPihakMain.php`](file:///w:/everest_26sep/application/modules/opname/controllers/_processPihakMain.php) | 12 KB | Proses pihak utama |
| [`Create_total.php`](file:///w:/everest_26sep/application/modules/opname/controllers/Create_total.php) | 285 KB | Varian Create dengan total |
| [`ViewDetails.php`](file:///w:/everest_26sep/application/modules/opname/controllers/ViewDetails.php) | 28 KB | Detail view transaksi |
| [`Pembelian.php`](file:///w:/everest_26sep/application/modules/opname/controllers/Pembelian.php) | 29 KB | Pembelian terkait opname |
| [`Debug.php`](file:///w:/everest_26sep/application/modules/opname/controllers/Debug.php) | 935 B | Debugging |
| [`__Create.php`](file:///w:/everest_26sep/application/modules/opname/controllers/__Create.php) | 543 KB | Backup/versi lama Create |
| [`__FollowUp.php`](file:///w:/everest_26sep/application/modules/opname/controllers/__FollowUp.php) | 1.34 MB | Backup/versi lama FollowUp |

### 2.2 Config (5 file — 4 wajib + 1 backup)

| File | Ukuran | Isi |
|------|--------|-----|
| [`coTransaksiCore.php`](file:///w:/everest_26sep/application/modules/opname/config/coTransaksiCore.php) | 248 KB | Gateway mapping, components (Jurnal, Rekening, FIFO, dll), preProcessor, postProcessor |
| [`coTransaksiUi.php`](file:///w:/everest_26sep/application/modules/opname/config/coTransaksiUi.php) | 351 KB | Step definitions, UI labels, selector config, form fields |
| [`coTransaksiLayout.php`](file:///w:/everest_26sep/application/modules/opname/config/coTransaksiLayout.php) | 124 KB | Kolom tabel, rendering layout |
| [`coTransaksiValues.php`](file:///w:/everest_26sep/application/modules/opname/config/coTransaksiValues.php) | 116 KB | Value mapping, aturan kalkulasi |
| [`_coTransaksiCore.php`](file:///w:/everest_26sep/application/modules/opname/config/_coTransaksiCore.php) | 168 KB | Backup versi lama |

---

## 3. Alur Proses Opname (Workflow)

```mermaid
flowchart TD
    A["🏠 Index<br/>Opname.php::index()"] --> B{"Cek Transaksi Gantung<br/>(Transaksional::callTransaksiBeforeOpname)"}
    B -->|Ada gantungan| B1["⚠️ Modal Dialog<br/>Selesaikan transaksi dulu"]
    B -->|Tidak ada| C["📋 Pilih Jenis, Gudang, Kategori<br/>Opname.php::view()"]
    
    C --> D["📥 Download Excel<br/>Opname.php::doPrint()"]
    D --> D1["Ambil data produk + stok buku<br/>dari _rek_pembantu_*_cache"]
    D1 --> D2["Generate file .xlsx<br/>(Library Excel)"]
    D2 --> D3["Log ke dashboard_opname<br/>+ dashboard_opname_data"]
    D3 --> D4["📄 File Excel didownload user"]
    
    D4 --> E["✍️ User isi 'stok riil'<br/>di Excel offline"]
    
    E --> F["📤 Upload Excel<br/>Opname.php::doUpload()"]
    F --> F1["Simpan file ke /uploads/<br/>Log ke opname_xls"]
    F1 --> F2["🔄 Execute Opname<br/>Opname.php::executeOpname()"]
    
    F2 --> F3["Parse XLSX<br/>(PHPExcel_Reader_Excel2007)"]
    F3 --> F4["Update dashboard_opname_data<br/>(jml_stok_opname)"]
    F4 --> F5["Build session transaksi<br/>(items, main, qty selisih)"]
    F5 --> F6["Hitung selisih:<br/>qty_debet = max(opname-stok, 0)<br/>qty_kredit = max(stok-opname, 0)"]
    
    F6 --> G["📝 Create Transaksi<br/>Create.php::save()"]
    G --> G1["Insert ke tabel transaksi<br/>(step 1 = 1119r)"]
    
    G1 --> H["✅ FollowUp Authorization 1<br/>FollowUp.php::doFollowup()"]
    H --> H1["Step 2: 1119r → 1119ro<br/>preProcessor: ProdukSerialNumberExtractorOpname<br/>postProcessor: Opname, OpnameData"]
    
    H1 --> I["✅ FollowUp Authorization 2<br/>FollowUp.php::doFollowup()"]
    I --> I1["Step 3: 1119ro → 1119<br/>preProcessor: FifoAverageOpname<br/>Components: Jurnal, Rekening,<br/>RekeningPembantuProduk,<br/>RekeningPembantuLRLainlain,<br/>RekeningPembantuKerugian"]
    
    I1 --> J["✅ Selesai<br/>Stok & Jurnal terupdate"]
    
    style A fill:#2196F3,color:white
    style D fill:#FF9800,color:white
    style F fill:#4CAF50,color:white
    style G fill:#9C27B0,color:white
    style H fill:#795548,color:white
    style I fill:#607D8B,color:white
    style J fill:#009688,color:white
```

---

## 4. Step Transaksi (Approval Chain)

### 4.1 Produk Pusat (`1119`)

| Step | Label | Source → Target | User Group | State |
|------|-------|----------------|------------|-------|
| 1 | STOCK OPNAME | `""` → `1119r` | `c_gudang` | Pending Approval 1 🔴 |
| 2 | AUTHORIZATION 1 | `1119r` → `1119ro` | `c_holding` | Pending Approval 2 🟠 |
| 3 | AUTHORIZATION 2 | `1119ro` → `1119` | `c_holding` | Complete 🟢 |

### 4.2 Komponen Akuntansi (saat Step 3 Final)

**Jurnal & Rekening (Master level):**
| COA | Nama | Arah | Sumber Nilai |
|-----|------|------|-------------|
| `1010030030` | Persediaan Produk | **Debet** | Selisih lebih (qty_debet × hpp) |
| `7010150` | Laba Lain-lain | **Debet** | Selisih lebih (opname > stok buku) |
| `1010030030` | Persediaan Produk | **-Kredit** | Selisih kurang (qty_kredit × hpp_avg) |
| `7020020` | Kerugian | **Kredit** | Selisih kurang (stok buku > opname) |

**Rekening Pembantu (Detail level):**
- `RekeningPembantuProduk` — mutasi stok per-produk (kurangi kredit, tambah debet)
- `RekeningPembantuLRLainlain` — detail laba lain-lain opname
- `RekeningPembantuKerugian` — detail kerugian opname

### 4.3 PreProcessor & PostProcessor

| Tahap | Step | Component | Fungsi |
|-------|------|-----------|--------|
| PreProcessor | `1119ro` (Step 2) | `ProdukSerialNumberExtractorOpname` | Ekstrak serial number produk |
| PreProcessor | `1119` (Step 3) | `ProdukSerialNumberExtractorOpname` | Ekstrak serial number final |
| PreProcessor | `1119` (Step 3) | `FifoAverageOpname` | Hitung HPP Average untuk kredit |
| PostProcessor | `1119ro` (Step 2) | `Opname` + `OpnameData` | Update data opname ke dashboard |
| PostProcessor | `1119` (Step 3) | `Opname` + `OpnameData` | Finalisasi data opname |

---

## 5. Kalkulasi Nilai (Value Gates)

```
Selisih Stok:
├── qty_debet  = max(qty_opname - stok_buku, 0)  // stok riil > stok buku → LEBIH
├── qty_kredit = max(stok_buku - qty_opname, 0)  // stok buku > stok riil → KURANG

Nilai Transaksi:
├── debet  = hpp × qty_debet           // nilai persediaan yang masuk (riil)
├── kredit = hpp_avg × qty_kredit      // nilai persediaan yang keluar (FIFO Average)

PPV (Purchase Price Variance):
├── hpp_nppv      = hpp × ppv_index__nilai
├── debet_hpp_nppv = hpp_nppv × qty_debet
├── ppv_riil       = hpp_nppv - hpp
└── debet_ppv_riil = ppv_riil × qty_debet
```

---

## 6. Database Tables yang Terlibat

| Tabel | Fungsi |
|-------|--------|
| `dashboard_opname` | Header sesi opname (siapa download, upload, acc, status) |
| `dashboard_opname_data` | Detail per-produk per-sesi (stok buku, stok opname, selisih) |
| `opname_xls` | Log file Excel yang diupload |
| `transaksi` | Tabel transaksi utama (semua jenis) |
| `transaksi_data` | Detail item transaksi |
| `_rek_pembantu_produk_cache` | Cache stok produk per gudang per cabang |
| `_rek_pembantu_supplies_cache` | Cache stok supplies |
| `_rek_pembantu_produk_perserial_cache` | Cache serial number produk |
| `harga_produk` | Master harga (HPP) |

**MongoDB collections** (via `$this->mongoTableList`):
- `transaksi`, `transaksi_values`, `transaksi_data`, `transaksi_data_values`, `transaksi_sign`, `transaksi_extstep`, `transaksi_registry`

---

## 7. Fungsi-Fungsi Kunci di Opname.php

| Fungsi | Line | Deskripsi |
|--------|------|-----------|
| [`index()`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php#L182) | 182 | Halaman utama — cek transaksi gantung, tampilkan pilihan jenis/gudang |
| [`view()`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php#L315) | 315 | Tampilan detail per jenis — pilih kategori, gudang, download |
| [`doPrint()`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php#L1150) | 1150 | **Download Excel** — generate XLSX dengan stok buku + kolom stok riil + serial number + log dashboard_opname |
| [`doUpload()`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php#L1923) | 1923 | **Upload Excel** — simpan file + trigger executeOpname |
| [`executeOpname()`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php#L2026) | 2026 | **Proses Opname** — parse XLSX, hitung selisih, bangun session transaksi |
| [`executeOpname__()`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php#L3878) | 3878 | Versi lama executeOpname (deprecated) |
| [`executeOpnameSupplies()`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php#L5539) | 5539 | Executor khusus supplies |
| [`cekOpnameAktive()`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php#L7491) | 7491 | Cek sesi opname yang sedang aktif |
| [`viewOpnameAktive()`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php#L7525) | 7525 | Dashboard monitoring opname (auto-refresh 60 detik) |
| [`viewOpnameData()`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php#L7655) | 7655 | View detail data opname |
| [`doConfirmOpname()`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php#L7749) | 7749 | Konfirmasi seluruh opname selesai |
| [`historyDownloadOpname()`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php#L7793) | 7793 | Riwayat download (limit 10) |
| [`reDownloadXls()`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php#L7813) | 7813 | Re-download file Excel dari history |
| [`midValidate()`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php#L7080) | 7080 | Validasi tengah (shopping cart fields) |
| [`unionValidate()`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php#L7257) | 7257 | Validasi union |
| [`syncSatuan()`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php#L7327) | 7327 | Sinkronisasi satuan |

---

## 8. Fitur Khusus

### 8.1 RabbitMQ Toggle
```php
$config['opname_use_rabbitmq'] = false; // MATI — proses sinkron
```
Ada saklar fitur RabbitMQ di [`coTransaksiCore.php`](file:///w:/everest_26sep/application/modules/opname/config/coTransaksiCore.php#L10) line 10, saat ini **dimatikan** (proses berjalan sinkron).

### 8.2 Serial Number Support
- Download Excel menyertakan serial number dari `_rek_pembantu_produk_perserial_cache`
- Upload Excel membaca kolom "serial number" dan mendukung pemisah: koma, titik koma, enter, pipe
- PreProcessor `ProdukSerialNumberExtractorOpname` memproses serial number saat approval

### 8.3 Dashboard Monitoring
- [`viewOpnameAktive()`](file:///w:/everest_26sep/application/modules/opname/controllers/Opname.php#L7525) menampilkan dashboard real-time progress opname per cabang
- Auto-refresh setiap 60 detik (`header("refresh:60")`)
- Tracking status: Download → Upload → ACC I → ACC II

### 8.4 Proteksi Download Ganda
- Jika semua gudang sudah di-download (sesi opname aktif), tombol download di-disable
- User diarahkan ke History Download untuk re-download

---

## 9. Hierarki Controller

```mermaid
classDiagram
    CI_Controller <|-- MX_Controller
    MX_Controller <|-- Modul_Controller
    CI_Controller <|-- Opname
    
    Modul_Controller <|-- Create
    Modul_Controller <|-- FollowUp
    Modul_Controller <|-- Transaksi
    Modul_Controller <|-- Printing
    Modul_Controller <|-- ActivityReport
    Modul_Controller <|-- History
    Modul_Controller <|-- _shoppingCart
    Modul_Controller <|-- _processSelectProduct
    Modul_Controller <|-- _selectorItem
    Modul_Controller <|-- _processPihak
    
    class Opname {
        -y, x, z, h : array
        -priceConfig : array
        +index()
        +view()
        +doPrint()
        +doUpload()
        +executeOpname()
        +viewOpnameAktive()
        +doConfirmOpname()
    }
    
    class Modul_Controller {
        +configUi, configCore
        +configLayout, configValues
        +jenisTr, cCode
        +mongoTableList
    }
    
    note for Opname "⚠️ Extends CI_Controller langsung\n(bukan Modul_Controller)"
```

> [!IMPORTANT]
> **`Opname.php` extends `CI_Controller` langsung**, bukan `Modul_Controller`. Ini berbeda dari controller lain di modul ini (Create, FollowUp, Transaksi, dll) yang semua extends `Modul_Controller`. Ini berarti `Opname.php` tidak otomatis memiliki `configLayout`, `configValues`, `mongoTableList`, `allSteps`, `ppnFactor`, dan property lain dari base controller.

---

## 10. Ringkasan Alur Data

```
📥 Download Excel
    ├── Input: jenis produk, cabang, gudang, kategori
    ├── Proses: Query stok dari cache → Generate XLSX → Log dashboard_opname
    └── Output: File .xlsx (berisi stok buku, kolom riil kosong, serial number)

📤 Upload Excel  
    ├── Input: File .xlsx (user sudah isi kolom "stok riil")
    ├── Proses: Upload file → Simpan ke opname_xls → Trigger executeOpname
    └── Output: Session transaksi terbangun dengan selisih

🔄 Execute Opname
    ├── Input: File XLSX yang tersimpan
    ├── Proses: Parse XLSX → Hitung selisih → Build session → Redirect ke Create
    └── Output: Transaksi opname step 1 (draft) tersimpan

✅ Follow Up (2 tahap approval)
    ├── Step 2: Authorization 1 → Serial number extraction + Opname/OpnameData
    ├── Step 3: Authorization 2 → FIFO Average + Jurnal/Rekening + Stock mutation
    └── Output: Stok di rekening pembantu terupdate, jurnal akuntansi terbentuk
```
