STINV V2.10.241 - HOTFIX IMPORT FINAL MODE 2 / SHADOW LEDGER TEMPORARY SIGN INVERSION
Tanggal: 31 Oktober 2026
Versi dan changelog TIDAK diubah.

TARGET
- PHP 8.x + MariaDB/MySQL.
- Metode inventory_cost_method=periodic_weighted_average.
- Setting allow_negative_stock=1 bila memang mengizinkan stok minus sementara.
- Import Histori Penjualan Mode 2 pada historical_migration_import.php?type=sales&mode=operational.

FILE PATCH
- includes/historical_migration_periodic.php
- includes/historical_migration_operational.php

PENYEBAB
Pada Import Final tanggal 2026-10-31 19:38, produk #796 (BRG-202608-0796 MACAN 1L)
gagal pada saldo berjalan stock_movements #2779. Baris ini dibuat ketika proses
import yang kemudian di-rollback. Backup 2026-10-31 18:53 (lebih lama dari kegagalan)
tidak mencakup mutasi #2779 sehingga nilai persis saat gagal belum tersedia.

Shadow ledger menggabungkan nilai HPP existing (tidak boleh ditulis ulang)
dengan nilai HPP Periodic untuk mutasi migrasi baru. Dalam urutan tanggal
kronologis, sementara dapat muncul qty<0 dengan value>0 atau qty>0 dengan
value<0. Kondisi sementara ini bukan bukti selisih agregat; pengecekan tanda
sebelumnya menganggapnya fatal tanpa menilai saldo akhir.

PERUBAHAN
1. Jika setting stok minus aktif, catat anomali tanda positif/negatif pada
   saldo ANTARA sebagai PROVISIONAL_SHADOW_ONLY (maksimum 12 contoh/produk).
2. Seluruh saldo berjalan tetap dihitung ulang berdasarkan tanggal + ID
   mutasi, tanpa menulis ulang nilai HPP lama (qty_in, qty_out, value_in,
   value_out, unit_cost lama TIDAK diubah).
3. Tulis perubahan HANYA setelah SELURUH validasi saldo satu produk lulus.
4. Selisih agregat dengan product_stocks existing tetap memblokir import.
5. Saldo AKHIR dengan qty>0/value<0, qty<0/value>0, atau qty=0/value tidak
   nol tetap diblokir; error menyebut angka akhir untuk diagnosis.
6. Mutasi HPP Periodic, preflight pve_*, transaksi database/rollback dan
   pembatasan FINAL/Tutup Buku tetap aktif.
7. Peringatan sign inversion dicatat ke historical_migration_batches.notes
   dalam ShadowInversionWarnings; tersedia pula di hasil return import.
8. Tidak mengubah versi aplikasi atau changelog.

PENTING
- Ini bukan izin untuk memfinalisasi HPP saat stok minus.
- Saldo shadow yang anomali hanya dianggap catatan sementara. Laporan nilai
  Periodic/HPP berpatokan pada pve_*; selesaikan stok minus sebelum tutup buku.
- Jangan mengubah mutasi #2779 melalui SQL manual. Mutasi tersebut belum tentu
  ada, sebab log menyatakan seluruh batch ROLLBACK.
- Backup SQL terlampir sebelumnya mengecualikan pve_*; sebelum import final
  wajib verifikasi Safety Backup mencakup snapshot Periodic.

INSTALASI
1. Salin source, backup database operasional, dan snapshot pve_* dari database aktif.
2. Ekstrak PATCH ke root folder stinv di XAMPP/cPanel, pertahankan struktur includes/.
3. Restart Apache / reset OPcache apabila ada.
4. Jalankan Preview & Validasi Mode 2 ulang dengan XLSX yang sama.
5. Jalankan Import Final dahulu pada salinan database; setelah berhasil verifikasi:
   product_stocks vs SUM(stock_movements qty/value), stock card, laporan
   Periodic, negative_stock_lots, negative_stock_settlements, dan invoice batch.
6. Bila gagal lagi, lampirkan log + backup sebelum import terbaru yang juga
   mencakup pve_* agar saldo tiap mutasi dapat ditelusuri.

PENGUJIAN
- php -l kedua file: OK
- Mocked function test: 6/6 PASS (interim inversion positive/negative,
  final invalid states blocked, stok minus OFF blocked, agregat mismatch blocked).
- Regression mocked ALIKA/YOTO + mismatch + negative: 4/4 PASS.
- Belum diuji end-to-end pada MySQL/XAMPP/database nyata pengguna.
