V2.10.239 - 2026-09-27 - Bulk Import Koreksi HPP Historis Mode 1
- Menambahkan import XLSX/CSV untuk koreksi massal `sales_invoices.historical_cogs` berdasarkan No. Invoice tanpa re-import transaksi.
- Kolom wajib: No. Invoice dan HPP Historis Baru; opsional Alasan Koreksi, Referensi, dan Import?.
- Import? TIDAK/NO/SKIP akan dilewati; kosong/tidak ada dianggap diproses.
- Preview memvalidasi Mode 1, affect_stock=0, status Approved, batch aktif, duplikat, HPP > 0, dan periode akuntansi.
- Final import memakai satu password, satu Safety Backup, satu maintenance lock, dan satu database transaction untuk seluruh file.
- Row lock + post-check memastikan data selain historical_cogs dan historical_migration_batches.total_cogs tidak berubah.
- Audit dibuat per invoice dan tetap kompatibel dengan rollback Koreksi HPP V2.10.237.
- Menambahkan template `template_import_koreksi_hpp_historis_mode1_v210239.xlsx`.
- Tidak ada ALTER TABLE; schema canonical dan Backup/Restore tetap kompatibel dengan V2.10.238.
- VERSION.txt dinaikkan menjadi 2.10.239.

V2.10.238 - 2026-09-27 - Automatic Tax Export Detach for Historical Sales Deletion
- Relasi live Faktur Pajak Export tidak lagi menjadi blocker penghapusan Penjualan Historis Mode 1/2.
- Sistem otomatis membuat sales_invoice_id pada tax_invoice_exports dan tax_invoice_export_invoices menjadi NULL sebelum invoice batch/lineage dihapus; snapshot export dan file XLSX tetap dipertahankan.
- Export campuran tetap aman karena hanya relasi invoice yang sedang dihapus yang dilepas.
- Edit/Koreksi/Hapus per-invoice tidak lagi membutuhkan checkbox detach Faktur Pajak manual.
- Hapus batch Mode 1 tetap tidak menyentuh stok.
- Hapus batch Mode 2 menghapus stock movement batch lalu rebuild moving-average, HPP, product_stocks, dan valuasi secara kronologis sebelum COMMIT.
- TT, retur, pembayaran operasional eksternal, relasi transaksi eksternal, dan periode tertutup tetap menjadi blocker.
- Safety Backup, maintenance lock, database transaction, row lock, dan post-condition verification tetap wajib.
- Tidak ada ALTER TABLE; canonical schema dan Backup/Restore tetap kompatibel dengan V2.10.237.
- VERSION.txt dinaikkan menjadi 2.10.238.

V2.10.237 - 2026-09-25 - Historical Mode 1 COGS Correction
- Menambahkan tool khusus `historical_cogs_correction.php` untuk koreksi HPP Penjualan Historis Mode 1 / Passive per invoice.
- Hanya `sales_invoices.historical_cogs` yang dikoreksi; `historical_migration_batches.total_cogs` disinkronkan otomatis dari total HPP historis batch.
- Mode 2 / Operational dan lineage Mode 1 yang memiliki stock movement diblokir.
- Preview menampilkan HPP sebelum/sesudah, selisih HPP, estimasi laba kotor invoice, serta total HPP batch.
- Apply dan Rollback memakai Safety Backup, maintenance lock, database transaction, row lock, snapshot Activity Log, dan post-condition verification.
- Post-check memastikan stok, item, harga jual, pembayaran/piutang, retur, TT, Faktur Pajak, dan arus kas tidak berubah.
- Menambahkan permission `historical_migration.cogs_correction.view`, `.execute`, dan `.rollback`; Administrator mendapat default permission melalui Upgrade/Verifikasi.
- Backup/Restore menyinkronkan permission V2.10.237 setelah restore; tidak ada ALTER TABLE dan schema canonical tetap sama dengan V2.10.236.
- VERSION.txt dinaikkan menjadi 2.10.237.

V2.10.236 - 2026-09-25 - Historical Transaction Classification for Initial Data
- Memperbaiki false-positive Data Awal Perusahaan ketika PO/dokumen bertanggal lama sebelum cut-off dianggap sebagai awal operasional.
- Validator memakai cut-off sebagai batas histori: record bertanggal <= cut-off tidak menjadi hard blocker tanggal opening.
- Purchase Order hanya menjadi informasi karena belum mem-posting stok/hutang.
- Hard blocker menggunakan transaksi efektif sesudah cut-off: invoice approved, barang keluar approved, pembayaran approved non-historis, retur approved, biaya aktif, pendapatan lain/CN, kredit PPh, dan stock movement non-opening.
- Dokumen migrasi historis eksplisit tetap dikecualikan.
- Transaksi efektif yang jatuh setelah cut-off tetapi sebelum opening tetap memblokir untuk mencegah celah operasional.
- Menambahkan engine terpusat includes/initial_data_validation.php dan upgrade/verifikasi V2.10.236.
- Tidak ada perubahan schema; Backup/Restore tetap canonical 45 tabel dan kompatibel dengan backup V2.10.235 yang full schema-nya identik.
- VERSION.txt dinaikkan menjadi 2.10.236.

V2.10.230 - REVISI 2026-09-24 - Safe PO Cancellation + Supplier Credit Pembatalan Hutang
- VERSION tetap 2.10.230 (tidak naik versi).
- Fitur Batalkan PO tetap menutup PO Approved tanpa reversal penerimaan, Invoice Pembelian, pembayaran, stock movement, valuasi/HPP, maupun transaksi penjualan.
- Ditambahkan permission `purchase_invoices.cancel_payable` (default hanya Administrator).
- Invoice Pembelian Approved dari PO yang sudah `cancel` dapat memakai aksi `Batalkan Sisa Hutang`.
- Pembatalan sisa hutang TIDAK menghapus/reject Invoice Pembelian dan TIDAK membuat Retur Pembelian.
- Sistem otomatis membuat `Pembatalan Hutang / Kredit Supplier` sebagai Pendapatan Lain-Lain non-kas dan aplikasi `payable_offset` ke invoice sumber.
- Nilai Supplier Credit otomatis sebesar `balance_due` terbaru setelah pembayaran Approved, Retur Pembelian Approved, dan CN/potong hutang sebelumnya.
- Setelah Supplier Credit, `balance_due=0` dan `payment_status=paid`, sedangkan `paid_amount` tetap hanya mencerminkan pembayaran kas Approved.
- Stok masuk, `stock_movements`, `product_stocks`, moving weighted average, HPP penjualan, Barang Keluar, Surat Jalan, Invoice Penjualan, TT, dan pelunasan penjualan tidak disentuh.
- Jika masih ada Pelunasan Pembelian Draft/Pending, pembatalan sisa hutang diblokir sampai dokumen pembayaran tersebut diselesaikan/dihapus.
- Invoice Pembelian/print menampilkan baris `CN / Pembatalan Hutang` dan `Nilai Bersih Setelah Koreksi` bila terdapat Supplier Credit/CN.
- Laporan Hutang otomatis mengikuti `balance_due` dan `other_income_applications`, sehingga invoice yang hutangnya ditutup tidak lagi muncul sebagai outstanding.
- Upgrade/verifikasi V2.10.230 dapat dijalankan ulang untuk menyinkronkan permission dan master Supplier Credit tanpa ALTER TABLE.
- Canonical schema tetap 44 tabel / 725 kolom; backup/restore tetap kompatibel dengan basis V2.10.230.

V2.10.230 - 2026-09-23 - Safe Purchase Order Cancellation Tanpa Reversal
- Menambahkan tombol `Batalkan PO` untuk Purchase Order Approved yang masih berstatus Progress, termasuk PO yang sudah diterima partial.
- Pembatalan hanya menutup dokumen/order dengan mengubah `purchase_orders.status` menjadi `cancel`; `receiving_status`, `received_qty_small`, dan detail penerimaan tetap dipertahankan apa adanya.
- Invoice Pembelian, item invoice, pelunasan pembelian, stock_movements, product_stocks, moving weighted average/HPP, serta transaksi Penjualan yang sudah terjadi tidak diubah, tidak dihapus, dan tidak dibalik.
- PO Cancel otomatis tidak lagi aktif untuk membuat Barang Masuk/Invoice Pembelian baru karena jalur input baru hanya menerima PO Approved + Progress.
- Invoice Pembelian yang sudah dibuat dan masih Pending sebelum PO dibatalkan tetap boleh di-approve; setelah approval, realisasi qty/status penerimaan PO diperbarui tanpa membuka kembali sisa order yang dibatalkan.
- Alasan pembatalan wajib diisi dan dicatat pada notes PO serta activity_logs dengan snapshot nilai order/realisasi/sisa estimasi, jumlah invoice, dan jumlah stock movement.
- Menambahkan post-condition verification: jumlah invoice/mutasi stok serta received_qty/status penerimaan item harus identik sebelum dan sesudah cancel; bila berubah proses di-rollback.
- Menambahkan permission khusus `purchase_orders.cancel` / `Batalkan Purchase Order`; default awal hanya Administrator dan dapat diberikan ke role lain melalui Role & Permission.
- Daftar/detail PO sekarang menampilkan Status PO (`Progress` / `Cancel`) terpisah dari Approval dan Status Penerimaan.
- Backup/Restore mengenali backup V2.10.229 sebagai schema identik dan menyinkronkan permission pembatalan PO setelah restore.
- Tidak ada ALTER TABLE; schema canonical tetap 44 tabel / 725 kolom.
- VERSION.txt dinaikkan menjadi 2.10.230.

V2.10.229 - 2026-09-23 - Import Penjualan: Auto-Create Master Pelanggan
- Import Excel Penjualan dapat menambahkan Master Pelanggan otomatis apabila pelanggan belum ditemukan.
- Pencarian pelanggan tetap memprioritaskan NIK/NPWP, kemudian nama pelanggan persis.
- Kolom opsional baru: Nama Pelanggan Baru, Jenis Identitas Pelanggan, Nomor Identitas Pelanggan, Alamat Pelanggan, dan Keterangan Pelanggan.
- Untuk pelanggan baru, Nomor Identitas dan Alamat wajib diisi; Jenis Identitas kosong menggunakan default NPWP.
- Auto-create pelanggan hanya berjalan untuk user dengan permission customers.create.
- Pembuatan pelanggan baru dan Barang Keluar berada pada transaksi database yang sama; kegagalan import me-rollback keduanya.
- Pelanggan nonaktif atau pelanggan terhapus dengan identitas yang sama diblokir agar tidak membuat duplikat master.
- Template Import Penjualan diperbarui dan file import versi lama tetap kompatibel.
- Backup/Restore mengenali backup V2.10.228 sebagai schema identik dan target canonical disinkronkan ke V2.10.229.
- Tidak ada ALTER TABLE; schema canonical tetap 44 tabel / 725 kolom.
- VERSION.txt dinaikkan menjadi 2.10.229.

V2.10.228 - 2026-09-23 - Tool Koreksi Pelunasan Migrasi Historis Mode 1
- Menambahkan tool terpisah `historical_payment_correction.php` khusus koreksi nilai pelunasan Penjualan Historis Mode 1 / Passive.
- Tool tidak mengizinkan perubahan barang, qty, harga, HPP, Faktur Pajak, atau stok; Mode 2 / Operational diblokir.
- Menambahkan Preview Sebelum/Sesudah untuk pelunasan historis, paid amount invoice, sisa piutang, status pembayaran, dan ringkasan batch.
- Nilai baru divalidasi terhadap effective invoice total setelah retur dan pembayaran operasional lain agar tidak membuat overpayment.
- Eksekusi membuat Safety Backup, maintenance lock, database transaction, row lock, verifikasi batch, dan post-check stock movement sebelum COMMIT.
- Pembayaran historis tetap `is_historical=1` dan `affect_cash=0`, sehingga tidak menambah arus dana periode berjalan.
- Sinkron otomatis `sales_invoices.paid_amount`, `balance_due`, `payment_status`, `receivable_status`, `historical_migration_batches.total_paid_to_cutoff`, dan `total_balance`.
- Menambahkan histori koreksi menggunakan `activity_logs.metadata` tanpa tabel baru; snapshot before/after dapat di-rollback bila kondisi data masih aman.
- Menambahkan permission `historical_migration.payment_correction.view`, `.execute`, dan `.rollback`; default diberikan ke Administrator dan role lain dapat diatur melalui Role & Permission.
- Backup/Restore ikut menyinkronkan permission tool setelah restore.
- Tidak ada ALTER TABLE; canonical schema tetap 44 tabel / 725 kolom.
- VERSION.txt dinaikkan menjadi 2.10.228.

V2.10.227 - 2026-09-21 - Simple Financial Reports + Koreksi Kalkulasi Histori Penjualan
- Menyempurnakan Laporan Keuangan menjadi Simple Financial Reports tanpa mengubah J-Com Inventory menjadi full general-ledger accounting.
- Laba Rugi sekarang memisahkan Penjualan Bersih, Pendapatan Usaha Lain, HPP, Laba Kotor, Biaya Usaha, Laba Usaha, Pendapatan Lain-Lain, Biaya Lain-Lain, dan Laba Sebelum Pajak.
- Menambahkan filter periode Laba Rugi: Bulan Ini, Bulan Lalu, Triwulan Ini, Semester Ini, Tahun Ini, dan Custom/tanggal bebas. Preset periode berjalan berakhir pada tanggal hari ini agar aging tidak membaca tanggal masa depan.
- Mengganti penyebutan Arus Kas menjadi Arus Dana Operasional karena aplikasi belum memiliki master Kas/Bank dan saldo rekening awal/akhir. Pembayaran historis affect_cash=0 tetap tidak dihitung sebagai arus dana baru.
- Menambahkan Aging Piutang dan Aging Hutang: Belum Jatuh Tempo, 1-30 hari, 31-60 hari, 61-90 hari, dan >90 hari. Detail invoice menampilkan bucket aging masing-masing.
- Menambahkan rekonsiliasi Persediaan & HPP: Persediaan Awal, Mutasi Nilai Bersih, Persediaan Akhir, HPP Stock Movement, dan HPP Historis Mode 1.
- Menambahkan panel PPN & Kredit Pajak yang memisahkan PPN Keluaran, PPN Masukan Pembelian, PPN Masukan Tax Biaya mode Detail, PPN Kurang/(Lebih) Bayar, serta Kredit Pajak PPh dari income_tax_credits.
- Menambahkan status Tutup Buku berdasarkan accounting_period_closures dan menampilkan snapshot persediaan/piutang/hutang bila periode sudah ditutup.
- CSV Laporan Keuangan diperbarui mengikuti struktur Simple Financial Reports dan menyertakan aging serta status Tutup Buku.
- Memperbaiki Koreksi Migrasi Historis Penjualan: DPP Nilai Lain otomatis dihitung dari (Subtotal - Diskon) x 11/12, PPN dihitung ulang dari DPP tersebut, Grand Total dibulatkan dari Netto + PPN, dan rounding_adjustment disimpan.
- Field DPP Nilai Lain pada form Koreksi Histori Penjualan dibuat readonly karena nilainya dihitung otomatis saat simpan. Perbaikan ini mencegah pola salah yang ditemukan pada invoice histori seperti 121/JA/IV/2026 dan 345/JA/VII/2026.
- Backup/Restore mengenali backup resmi V2.10.226 sebagai schema-identik. Tidak ada ALTER TABLE: canonical schema tetap 44 tabel / 725 kolom.
- Menambahkan Upgrade & Verifikasi V2.10.227 dan menaikkan VERSION.txt menjadi 2.10.227.

V2.10.226 - 2026-09-17 - Edit/Hapus Aman Histori Migrasi Penjualan + Audit Backup/Restore
- Memperkuat menu Migrasi Historis > Penjualan agar satu lineage hasil migrasi dapat dikoreksi atau dihapus secara aman: Barang Keluar/Surat Jalan, item Barang Keluar, Invoice Penjualan, item invoice, pelunasan historis s.d. cut-off, ringkasan batch, dan HPP/stok sesuai mode.
- Menambahkan Pre-Flight Lineage Penjualan yang menampilkan jumlah item BK/invoice, pelunasan historis/eksternal, Tanda Terima, retur, stock movement, dan relasi Export Faktur Pajak sebelum Edit/Hapus.
- Mode 1 / Passive tetap tidak membuat atau membalik stock movement dan pelunasan historis tetap affect_cash=0.
- Mode 2 / Operasional menghapus stock movement lineage lama, membentuk movement baru saat koreksi, lalu rebuild moving-average/HPP/valuasi seluruh barang terdampak secara kronologis sebelum COMMIT. Proses di-rollback bila verifikasi gagal atau stok menjadi tidak valid.
- Tanda Terima, Retur Penjualan (termasuk histori item retur yang masih menyimpan FK), dan Pelunasan operasional/eksternal tetap menjadi blocker; sistem tidak melakukan cascade otomatis yang dapat merusak audit.
- Export Faktur Pajak tidak lagi selalu menjadi blocker. Bila file XLSX ada dan checksum cocok, user dapat menyetujui detach relasi live invoice; snapshot database + file XLSX tetap dipertahankan sebagai bukti audit. Bila file/checksum tidak valid, Edit/Hapus tetap diblokir.
- Nomor Pelunasan Historis turunan disinkronkan kembali secara deterministik ketika No. Invoice historis berubah.
- Menambahkan post-condition verification setelah Edit/Hapus untuk memastikan header, item, batch, pelunasan, relasi BK↔Invoice, dan jumlah stock movement sesuai Mode 1/Mode 2 sebelum transaksi di-COMMIT.
- Safety Backup otomatis tetap wajib sebelum Edit/Hapus, maintenance lock tetap digunakan, dan kegagalan proses menjalankan database transaction rollback.
- Audit Backup/Restore diperbarui ke canonical V2.10.226. Backup V2.10.225 dikenali eksplisit sebagai full-schema identik; backup V2.10.200–V2.10.212 tetap melalui jalur migrasi schema yang sudah ada.
- Upgrade & Verifikasi V2.10.226 menambahkan self-check fungsi Backup/Restore, full-schema fingerprint, kompatibilitas manifest V2.10.225, permission, dan kesiapan storage/backups.
- Schema database tidak berubah dari V2.10.225: tetap 44 tabel / 725 kolom. VERSION.txt dinaikkan menjadi 2.10.226.

V2.10.225 - 2026-09-09 - Restore Invoice Penjualan & Pembelian Terhapus
- Menambahkan Riwayat Invoice Terhapus untuk Penjualan dan Pembelian.
- Menambahkan permission `sales_invoices.view_deleted`, `sales_invoices.restore_deleted`, `purchase_invoices.view_deleted`, dan `purchase_invoices.restore_deleted`; default awal hanya Administrator.
- Restore hanya mengaktifkan kembali header + detail invoice (soft-delete); tidak membuat, menghapus, membalik, atau mengulang `stock_movements`.
- Invoice Draft/Rejected mempertahankan statusnya. Invoice yang dahulu Approved dipulihkan sebagai Rejected agar wajib diperiksa dan approval ulang, sehingga piutang/hutang/stok tidak aktif kembali secara otomatis.
- Restore Penjualan memvalidasi Barang Keluar masih Approved/aktif dan `stock_processed_at` masih tersedia; kasus seperti 071/ST/IX/2026 tidak mengembalikan stok.
- Restore Pembelian memvalidasi PO sumber masih Approved/aktif dan tidak memproses stok masuk ulang.
- Restore diblokir bila masih ada pelunasan/retur/TT/export Faktur Pajak aktif yang membuat lineage tidak aman.
- Invoice Historis tetap wajib melalui Koreksi Migrasi Historis.
- Menambahkan audit `restore_deleted_invoice`, verifier V2.10.225, kompatibilitas Backup/Restore, PATCH, dan FULL build.
- Schema database tetap 44 tabel / 725 kolom; tidak ada perubahan struktur tabel.

V2.10.224 - 2026-09-05 - Pricelist Harga per Satuan Volume/Isi
- Membuat ulang rilis V2.10.224 langsung dari basis V2.10.223 + hotfix upgrader; tidak membawa implementasi draft V2.10.224 sebelumnya.
- Pricelist sekarang memakai satuan harga volume/isi sebagai basis utama: barang cair per `L`, barang berat per `KG`, satuan isi lain mengikuti satuan isi barang, dan barang tanpa data isi fallback ke UOM kecil.
- Harga lama dikonversi secara ekuivalen berdasarkan `unit_multiplier`, sehingga nilai ekonominya tetap sama. Contoh Rp50.000/BOTOL 500 ml menjadi Rp100.000/L; Rp20.000/BKS 250 gram menjadi Rp80.000/KG.
- Form Pricelist, lookup HPP, Pricelist otomatis dari Stok Awal, approval Invoice Pembelian, Import Excel Pricelist, tampilan daftar, CSV export, dan harga default Penjualan memakai basis volume/isi yang sama.
- Pricelist Manual dan Markup tetap dipertahankan; konversi tidak mengubah metode, markup, tanggal berlaku, histori, soft-delete, distributor, atau relasi barang.
- Menambahkan `Upgrade & Verifikasi V2.10.224` untuk menormalisasi seluruh histori `price_lists` lama ke basis volume/isi.
- Restore backup V2.10.223 dan versi didukung sebelumnya otomatis menormalisasi Pricelist ke basis volume/isi setelah row-count sumber tervalidasi.
- Tidak ada perubahan struktur database: canonical schema tetap 44 tabel / 725 kolom dan full-schema fingerprint identik dengan V2.10.223.
- VERSION.txt dinaikkan menjadi 2.10.224.

V2.10.223 - 2026-09-05 - Aksi Edit PO Berdasarkan User Role
- Aksi Edit Purchase Order sekarang dikendalikan eksplisit berdasarkan User Role untuk status belum Approved maupun Approved.
- Permission `purchase_orders.edit` ditampilkan sebagai `Edit PO Belum Approved` dan berlaku untuk PO Draft, Rejected, dan Pending / Menunggu Approval.
- Permission `purchase_orders.edit_approved` ditampilkan sebagai `Edit PO Approved` dan hanya berlaku untuk PO Approved yang masih aman dikoreksi.
- Role yang diberi `Edit PO Approved` otomatis memperoleh dependency `purchase_orders.edit` dan `purchase_orders.view`; role tanpa permission yang sesuai tidak melihat tombol Edit dan backend tetap menolak URL/form langsung.
- PO Approved hanya dapat diedit bila `receiving_status` masih Pending dan belum memiliki Barang Masuk / Invoice Pembelian. Setelah disimpan, PO dikembalikan ke status Menunggu Approval dan wajib disetujui ulang.
- PO Pending dapat diedit langsung tanpa harus ditolak terlebih dahulu; statusnya tetap Menunggu Approval setelah disimpan.
- Hotfix V2.10.222 Edit PO semua status telah digabung permanen ke V2.10.223.
- Backup/Restore V2.10.223 menerima backup resmi V2.10.222 sebagai schema-identik tanpa migrasi.
- Tidak ada perubahan struktur database: canonical schema tetap 44 tabel / 725 kolom dan full-schema fingerprint identik dengan V2.10.222.
- Menambahkan Upgrade & Verifikasi V2.10.223 di Pengaturan dan menaikkan VERSION.txt menjadi 2.10.223.

V2.10.222 - 2026-09-05 - Singkatan Qty Satuan Isi Valuasi Stok
- Tampilan Qty Satuan Isi / Volume pada Valuasi Stok sekarang menyingkat Liter menjadi `L` dan Kilogram menjadi `KG`.
- Normalisasi kuantitas tidak berubah: 1.000 Sentimeter Kubik tetap dikonversi menjadi 1 L dan 1.000 Gram tetap dikonversi menjadi 1 KG.
- Perubahan hanya pada label penyajian; `products.content_unit`, UOM master, qty stok, HPP, average cost, dan nilai persediaan tidak diubah.
- Export XLSX Valuasi Stok memakai singkatan yang sama (`L` / `KG`) agar konsisten dengan tampilan aplikasi.
- Backup/Restore V2.10.222 menerima backup resmi V2.10.221 sebagai schema-identik tanpa migrasi.
- Tidak ada perubahan struktur database: canonical schema tetap 44 tabel / 725 kolom dan full-schema fingerprint identik dengan V2.10.221.
- Menambahkan Upgrade & Verifikasi V2.10.222 di Pengaturan dan menaikkan VERSION.txt menjadi 2.10.222.

V2.10.221 - 2026-09-05 - User Role Migrasi Historis Dipisah per Jalur
- Menambahkan tiga permission terpisah pada User Role / Role & Permission: Migrasi Historis Pembelian (`historical_migration.purchase`), Migrasi Historis Penjualan Mode 1 (`historical_migration.sales_mode1`), dan Migrasi Historis Penjualan Mode 2 (`historical_migration.sales_mode2`).
- Preview, Import Final, download template, pembatalan batch aman, serta akses koreksi/hapus lineage sekarang memeriksa permission jenis/mode yang sesuai; perubahan URL/POST tidak dapat dipakai untuk berpindah ke mode yang tidak diizinkan.
- Permission `historical_migration.edit` dan `historical_migration.delete` tetap menjadi lapisan tambahan. Contoh koreksi Mode 2 membutuhkan `historical_migration.sales_mode2` + `historical_migration.edit`.
- Role & Permission otomatis menambahkan dependency `historical_migration.view` ketika salah satu permission migrasi baru dipilih.
- Permission lama `historical_migration.create` dipertahankan sebagai `Import Migrasi Historis (Legacy)` untuk kompatibilitas backup/role lama, tetapi tidak lagi memberi hak Preview/Import mulai V2.10.221.
- Administrator otomatis mendapat ketiga permission baru. Role non-Administrator tidak diberi akses baru otomatis dan harus diatur eksplisit melalui Role & Permission agar pemisahan akses benar-benar berlaku.
- Tombol Import pada halaman Migrasi Historis dan Data Awal Perusahaan hanya tampil sesuai permission: Pembelian, Penjualan Mode 1, dan Penjualan Mode 2 masing-masing independen.
- Backup/Restore menyinkronkan ketiga permission baru setelah row-count sumber tervalidasi; backup V2.10.220 dikenali sebagai schema-identik tanpa migrasi.
- Tidak ada perubahan struktur database: canonical schema tetap 44 tabel / 725 kolom dan full-schema fingerprint identik dengan V2.10.220.
- Menambahkan Upgrade & Verifikasi V2.10.221 di Pengaturan dan menaikkan VERSION.txt menjadi 2.10.221.

V2.10.220 - 2026-09-05 - Font Tanda Terima Mengikuti V2.10.213
- Mengembalikan profil tipografi dokumen Tanda Terima mengikuti V2.10.213 tanpa menghapus penyempurnaan layout versi sesudahnya.
- Font utama dokumen tetap Arial/Helvetica 9,5 pt dengan line-height 1,08 seperti V2.10.213.
- Nama perusahaan dan judul TANDA TERIMA kembali 11 pt bold; underline tetap tidak digunakan sesuai revisi Tanda Terima sesudah V2.10.213.
- Keterangan kembali memakai font 9,5 pt dengan line-height 1,18; ukuran 8,75 pt dari V2.10.216-V2.10.219 tidak lagi dipakai.
- Metadata kembali memakai line-height 1,08; isi tabel memakai line-height 1,05; nomor halaman dan teks Bersambung kembali 8,5 pt; tanda tangan memakai line-height 1,0.
- Spacing 1 baris V2.10.219, pagination maksimal 7 invoice per halaman, mode idcom.txt, Terbilang, Keterangan editable, live search, dan hotfix anti-overlap tetap dipertahankan.
- View, Preview, Cetak Printer, dan Cetak/Simpan PDF tetap menggunakan renderer tunggal includes/tanda_terima_renderer.php dan CSS tunggal assets/css/tanda_terima.css agar hasil konsisten.
- Tidak ada perubahan database: canonical schema tetap 44 tabel / 725 kolom dan full-schema fingerprint identik dengan V2.10.219.
- Backup/Restore V2.10.220 menerima backup resmi V2.10.219 sebagai schema-identik tanpa migrasi.
- Menambahkan Upgrade & Verifikasi V2.10.220 di Pengaturan dan menaikkan VERSION.txt menjadi 2.10.220.

V2.10.219 - 2026-09-05 - Jarak Vertikal Tanda Terima 1 Baris
- Menurunkan identitas perusahaan/kop Tanda Terima satu baris dari batas atas area dokumen.
- Menurunkan judul TANDA TERIMA satu baris dari blok identitas perusahaan.
- Menambahkan jeda satu baris setelah Alamat pelanggan sebelum tabel Invoice Penjualan.
- Menambahkan jeda satu baris setelah Keterangan sebelum area tanda tangan.
- Satu baris didefinisikan konsisten sebagai 3,35 mm berdasarkan font utama 9,5 pt agar View, Preview, Printer, dan PDF memiliki jarak yang sama.
- Pagination tetap maksimal 7 invoice per halaman; Total, Terbilang, Keterangan, dan tanda tangan tetap hanya pada halaman terakhir.
- Mode cetak idcom.txt tetap menampilkan isi file sesuai teks dan hotfix anti-overlap tetap terintegrasi.
- Tidak ada perubahan database: canonical schema tetap 44 tabel / 725 kolom dan fingerprint tetap identik dengan V2.10.218.
- Backup/Restore V2.10.219 menerima backup resmi V2.10.218 sebagai schema-identik tanpa migrasi.
- Menambahkan Upgrade & Verifikasi V2.10.219 di Pengaturan dan menaikkan VERSION.txt menjadi 2.10.219.

V2.10.218 - 2026-09-05 - Cetak Tanda Terima idcom.txt Sesuai Isi Teks
- Memperbaiki renderer Tanda Terima: pilihan Header/Kop `idcom.txt` sekarang benar-benar menampilkan isi file `idcom.txt`, bukan lagi nama perusahaan dari setting.
- Isi `idcom.txt` dirender sebagai plain text yang di-escape, mempertahankan line break dan baris kosong, sehingga View, Preview, Printer, dan Simpan PDF menampilkan teks yang sama.
- Normalisasi line ending CRLF/CR ke LF tetap dilakukan; BOM UTF-8 dibuang. Fallback ke kop Default hanya bila `idcom.txt` kosong atau tidak dapat dibaca.
- CSS khusus `tt-idcom-text` ditambahkan dengan `white-space: pre-wrap`, wrapping aman, dan font dokumen agar teks panjang tidak keluar area cetak.
- Pagination Tanda Terima tetap maksimal 7 invoice per halaman, serta hotfix anti-overlap Terbilang–Keterangan–Tanda Tangan tetap terintegrasi.
- Tidak ada perubahan database: canonical schema tetap 44 tabel / 725 kolom dan full-schema fingerprint tetap identik dengan V2.10.217.
- Backup/Restore V2.10.218 menerima backup resmi V2.10.217 sebagai schema-identik tanpa migrasi.

V2.10.217 - 2026-09-04 - Pagination Tanda Terima 7 Baris per Halaman
- Mengubah pagination Tanda Terima menjadi maksimal 7 baris Invoice Penjualan per halaman, kemudian otomatis bersambung ke halaman berikutnya seperti pola multipage Faktur Penjualan.
- Header nama perusahaan, judul TANDA TERIMA, metadata No. TT/Tanggal/Pelanggan/Alamat, dan header tabel dicetak ulang pada setiap halaman agar dokumen lanjutan tetap mudah dibaca.
- Nomor urut item tetap berlanjut lintas halaman (1-7, 8-14, dan seterusnya), tanpa baris filler kosong.
- TOTAL, Terbilang, Keterangan editable, dan blok tanda tangan hanya tampil pada halaman terakhir. Halaman sebelumnya menampilkan indikator Bersambung ke halaman berikutnya.
- Renderer dan CSS TT dirapikan untuk kapasitas 7 baris pada halaman terakhir, sambil mempertahankan hotfix anti-overlap Terbilang + Keterangan + Tanda Tangan.
- View, Preview, Cetak Printer, dan Cetak/Simpan PDF tetap memakai satu renderer/CSS sehingga pagination dan hasil fisik konsisten.
- Canonical schema tidak berubah: tetap 44 tabel / 725 kolom; full-schema fingerprint tetap sama dengan V2.10.216.
- Backup/Restore diperbarui agar backup V2.10.216 dikenali eksplisit sebagai schema identik dan dapat direstore langsung ke V2.10.217 tanpa migrasi schema.
- Menambahkan Upgrade & Verifikasi V2.10.217 di Pengaturan dan menaikkan VERSION.txt menjadi 2.10.217.

V2.10.216 - 2026-09-04 - Pemadatan Tanda Terima + Hotfix Anti-Overlap Terintegrasi
- Menggabungkan hotfix V2.10.215 Keterangan anti-overlap ke basis rilis resmi sehingga renderer/CSS baru tidak bergantung pada hotfix terpisah.
- Merapatkan layout Tanda Terima secara vertikal: margin/padding halaman, kop nama perusahaan, judul, metadata, tabel item, Terbilang, Keterangan, dan area tanda tangan dibuat lebih padat terutama untuk kertas 8,5 x 5,5 inch.
- Keterangan diperkecil sedikit dari 9,5 pt menjadi 8,75 pt (bukan 50%), line-height dibuat 1,16, dan wrapping alamat/email panjang tetap aman menggunakan overflow-wrap.
- Blok Terbilang + Keterangan + Tanda Tangan tetap diperlakukan sebagai satu blok yang tidak boleh terpecah halaman untuk mencegah tulisan tertimpa.
- Kapasitas halaman terakhir kertas 8,5 x 5,5 tetap konservatif maksimal 5 invoice; pemadatan dipakai untuk memberi ruang aman tambahan, bukan memaksa lebih banyak item.
- Renderer dan CSS tetap satu sumber untuk View, Preview, Cetak Printer, dan Simpan PDF sehingga hasil antar-mode konsisten.
- Canonical schema tidak berubah: tetap 44 tabel / 725 kolom; full-schema fingerprint tetap sama dengan V2.10.215.
- Backup/Restore diperbarui agar backup V2.10.215 dikenali eksplisit sebagai schema identik dan dapat direstore langsung ke V2.10.216 tanpa migrasi schema.
- Menambahkan Upgrade & Verifikasi V2.10.216 di Pengaturan dan menaikkan VERSION.txt menjadi 2.10.216.

V2.10.215 - 2026-09-04 - Normalisasi Kop, Label & Keterangan Tanda Terima
- Mengubah label No. Tanda Terima menjadi No. TT pada daftar Tanda Terima, form input/edit, dan metadata dokumen cetak.
- Kop Tanda Terima disederhanakan: hanya nama perusahaan yang tampil di kiri atas. NPWP, alamat, kota, telepon, email, dan baris identitas lain tidak lagi dicetak pada kop TT.
- Pilihan header Default/idcom tetap dipertahankan untuk kompatibilitas alur cetak, tetapi kop TT yang tampil pada kedua mode kini hanya nama perusahaan; mode Tanpa Header tetap menyembunyikan kop.
- Ukuran teks Keterangan dikembalikan ke ukuran font normal dokumen (9.5pt), tidak lagi 50% dari font utama. Isi Keterangan tetap editable per dokumen dan default alamat/fax/email pengembalian nota tidak berubah.
- Terbilang tetap berada di atas Keterangan dengan jarak satu baris; tabel, total, tanda tangan, nomor otomatis TT, live search pelanggan bertagihan, dan snapshot invoice tidak diubah.
- Renderer includes/tanda_terima_renderer.php dan CSS assets/css/tanda_terima.css dirapikan sehingga View, Preview, Cetak Printer, dan Simpan PDF tetap menggunakan markup/style yang sama.
- Canonical schema tidak berubah: tetap 44 tabel / 725 kolom. Manifest V2.10.215 identik dengan V2.10.214 dan full-schema fingerprint tetap sama.
- Backup/Restore diperbarui agar backup V2.10.214 dikenali eksplisit sebagai schema identik dan dapat direstore langsung ke V2.10.215 tanpa migrasi schema.
- Menambahkan Upgrade & Verifikasi V2.10.215 di Pengaturan dan menaikkan VERSION.txt menjadi 2.10.215.

V2.10.214 - 2026-09-04 - Penyempurnaan Tanda Terima: Tagihan Aktif, Live Search & Renderer Cetak
- Pelanggan pada form Tanda Terima sekarang hanya menampilkan pelanggan yang memiliki Invoice Penjualan Approved dengan sisa tagihan (balance_due > 0). Saat Edit, pelanggan/invoice yang sudah menjadi anggota TT tetap dipertahankan agar dokumen lama dapat dikoreksi dengan aman.
- Live search pelanggan dipertahankan memakai searchable lookup bawaan aplikasi, minimum 3 huruf, dan pilihan pelanggan menampilkan jumlah invoice serta total sisa tagihan.
- Daftar invoice checklist juga dibatasi ke invoice Approved yang masih memiliki tagihan, kecuali invoice yang memang sudah terikat pada TT yang sedang diedit.
- Keterangan Cetak pada form TT sekarang editable dan disimpan per dokumen; nilai default tetap menggunakan alamat/fax/email pengembalian nota yang sudah ditetapkan pada V2.10.213.
- Renderer tunggal TT diperbaiki sehingga View, Preview, Cetak Printer, dan Simpan PDF tetap memakai markup/CSS yang sama.
- Identitas perusahaan pada header Default/idcom diposisikan di kiri atas.
- Judul TANDA TERIMA tidak lagi memakai underline.
- Menambahkan Terbilang dari total Tanda Terima di atas Keterangan, lalu memberi jarak satu baris sebelum Keterangan.
- Ukuran font blok Keterangan dicetak 50% dari font utama dokumen untuk merapikan area bawah form.
- No. Tanda Terima pada daftar menjadi clickable langsung ke detail/view dan link ditampilkan tanpa underline.
- Area tanda tangan Diserahkan oleh menampilkan nama perusahaan di bawah label, kemudian ruang tanda tangan dan placeholder (..............). Area Diterima oleh tetap menggunakan placeholder (..............).
- Canonical schema tidak berubah: tetap 44 tabel / 725 kolom. Manifest V2.10.214 identik dengan V2.10.213.
- Backup/Restore diperbarui agar backup V2.10.213 dikenali sebagai schema identik dan dapat direstore langsung ke V2.10.214 tanpa migrasi schema; backup V2.10.212 dan generasi lama tetap mengikuti jalur migrasi yang sudah ada.
- Menambahkan Upgrade & Verifikasi V2.10.214 di Pengaturan serta memperbarui changelog/version release.

V2.10.213 - 2026-09-04 - Modul Tanda Terima Penjualan Multi-Invoice
- Menambahkan modul Penjualan > Tanda Terima sebagai dokumen tersendiri di antara Invoice Penjualan dan Pelunasan Penjualan.
- Tanda Terima dibuat dengan sistem checklist dari Invoice Penjualan yang sudah Approved. Satu Tanda Terima dapat memuat beberapa invoice tetapi wajib untuk pelanggan yang sama.
- Menambahkan nomor otomatis bulanan format 001/ST/TT/IX/2026 menggunakan document_sequences dan generator slash yang sama prinsipnya dengan nomor Surat Jalan; sequence tidak bertambah sebelum dokumen benar-benar disimpan.
- Menambahkan tabel sales_receipts dan sales_receipt_items. Canonical schema naik dari 42 tabel / 707 kolom menjadi 44 tabel / 725 kolom.
- Detail Tanda Terima menyimpan snapshot No Invoice, No Surat Jalan, No Faktur Pajak, No PO, dan Jumlah agar dokumen yang sudah dibuat tetap dapat diaudit walaupun data referensi berubah kemudian.
- Field legacy sales_invoices.tt_number dan tt_date tetap disinkronkan saat TT dibuat/diedit/dihapus sehingga guard koreksi Approved, Migrasi Historis, dan laporan lama tetap kompatibel.
- Edit Tanda Terima dapat menambah/melepas invoice secara aman; invoice yang dilepas otomatis dikosongkan tt_number/tt_date bila masih menunjuk nomor TT tersebut. Hapus Tanda Terima melakukan soft-delete header, mempertahankan snapshot item, dan melepas live FK invoice.
- Koreksi/Hapus Invoice Penjualan Approved dan koreksi Migrasi Historis diblokir bila invoice masih terhubung ke Modul Tanda Terima, termasuk guard langsung terhadap sales_receipt_items.
- Pembatalan batch Penjualan Historis juga memeriksa relasi Modul Tanda Terima selain field tt_number/tt_date, sehingga batch tidak dapat dihapus saat dokumen TT masih mereferensikan invoice batch.
- Menambahkan renderer includes/tanda_terima_renderer.php dan CSS assets/css/tanda_terima.css sebagai satu sumber markup/style untuk View, Preview, Cetak Printer, dan Simpan PDF.
- Dokumen Tanda Terima menampilkan tabel: No, No Invoice, No Surat Jalan, No Faktur Pajak, No PO, Jumlah; total dokumen; keterangan pengembalian nota; serta tanda tangan Diterima oleh dan Diserahkan oleh dengan placeholder (..............).
- Keterangan default dicetak: Tolong dikirim kembali tanda terima ini ke Jl. Pasar 16 Ilir No. 101 ( Samp. Apotik Musi) Palembang atau di fax ke (0711)5556277/369545 atau email ke cv.sejatitani88@gmail.com apabila nota sudah diterima.
- Preview/Cetak mendukung 8,5 x 5,5 inch dan A4, multipage, Actual Size, pilihan Header Default / idcom.txt / Tanpa Header, dengan markup yang sama seperti View.
- Menambahkan permission sales_receipts.view/create/edit/delete. Administrator mendapat permission saat upgrade/fresh install; role lain dapat diberikan manual melalui Role & Permission.
- Menambahkan Upgrade & Verifikasi V2.10.213 untuk membuat schema TT, sinkron permission, memigrasikan referensi tt_number lama yang aman, dan memverifikasi full schema 44 tabel / 725 kolom.
- Backup/Restore V2.10.213 menerima backup resmi V2.10.200-V2.10.212. Backup schema 42 tabel dimigrasikan otomatis dengan menambahkan schema Tanda Terima sebelum full-schema verification; row-count sumber tetap diverifikasi sebelum permission/backfill TT ditambahkan.
- Reset Data Bisnis menambahkan kelompok Tanda Terima. Bila TT direset tetapi Invoice Penjualan dipertahankan, tt_number/tt_date pada invoice direkonsiliasi menjadi kosong.

V2.10.212 - 2026-09-04 - Backup/Restore Terpadu sampai Hotfix Migrasi Historis & Snapshot Audit Faktur Pajak
- Menaikkan versi aplikasi dari V2.10.211 ke V2.10.212 dengan fokus hardening Backup/Restore setelah fitur Edit/Hapus Migrasi Historis dan hotfix pembatalan batch yang memiliki dependency Export Faktur Pajak.
- Mempertahankan canonical schema 42 tabel / 707 kolom tanpa ALTER TABLE. schema_manifest_v210212 dan schema_full_manifest_v210212 identik dengan V2.10.211; fingerprint full-schema tetap sama.
- Backup V2.10.212 tetap memakai REPEATABLE READ + CONSISTENT SNAPSHOT, full-schema fingerprint, manifest row count per tabel, statement marker, whitelist SQL, SHA-256 file backup, dan proteksi storage/backups.
- Menambahkan Embedded Critical Files V1: file XLSX Faktur Pajak yang direferensikan tax_invoice_exports ikut ditulis secara streaming ke file backup SQL sebagai payload comment non-SQL dengan path whitelist, ukuran, dan SHA-256 per file.
- Embedded file dibatasi ketat ke storage/exports/faktur_pajak/*.xlsx; path traversal, hidden path, file non-XLSX, payload marker tidak cocok, base64 rusak, ukuran berbeda, atau checksum berbeda menyebabkan validasi payload gagal.
- Saat membuat backup, row tax_invoice_exports dan file audit dibaca ketika consistent database snapshot masih aktif. Bila file berubah selama backup, backup dibatalkan agar row file_path/hash dan payload tidak inkonsisten.
- Backup tetap dapat dibuat bila terdapat referensi Faktur Pajak lama yang file fisiknya sudah hilang/rusak; kondisi tersebut dicatat sebagai critical_file_issues dan ditampilkan sebagai warning. File yang valid tetap di-embed.
- Pre-Flight Restore V2.10.212 menambahkan pemeriksaan File Audit Faktur Pajak: payload embedded diverifikasi lengkap sebelum DDL restore. Backup legacy V2.10.211 dan sebelumnya tetap kompatibel dan diberi warning karena format lama tidak membawa file XLSX.
- Restore V2.10.212 menjalankan urutan: Pre-Flight -> Maintenance Lock -> Safety Backup -> restore database -> full-schema verification -> row-count verification -> restore embedded XLSX atomik -> rekonsiliasi tax_invoice_exports -> permission/master sync -> final verification.
- Restore embedded XLSX memakai temporary file, streaming decode, verifikasi ukuran + SHA-256, lalu atomic rename. File existing yang checksum-nya sudah sama tidak ditulis ulang.
- Rollback Restore diperluas: bila proses gagal setelah file audit dipulihkan, Safety Backup memulihkan database DAN embedded file Faktur Pajak, kemudian schema, row count, serta status file export direkonsiliasi ulang sebelum rollback dinyatakan berhasil.
- Untuk backup legacy tanpa embedded file, restore tidak diblokir. Setelah restore, setiap row tax_invoice_exports diperiksa terhadap file_path + file_sha256; status menjadi ready bila cocok atau missing bila file tidak tersedia/checksum tidak cocok.
- Hotfix pembatalan batch Penjualan Historis dengan dependency Faktur Pajak dipertahankan dan diperketat: sebelum relasi live export dilepas, file XLSX yang akan menjadi SNAPSHOT AUDIT wajib ada, dapat dibaca, dan SHA-256 harus cocok. Jika bukti file hilang/rusak, pembatalan batch diblokir.
- Snapshot Audit tetap mempertahankan export_number, invoice snapshot, customer, grand_total, file_name, file_path, file_sha256, dan file XLSX. Hanya live FK sales_invoice_id yang dilepas saat prosedur pembatalan batch aman dijalankan.
- Backup/Restore V2.10.212 menerima backup resmi V2.10.200-V2.10.211. V2.10.206-V2.10.211 memiliki full schema identik dan dapat direstore langsung; V2.10.200-V2.10.205 tetap menggunakan migrasi schema otomatis tervalidasi sebelum final verification.
- Post-restore tetap menyinkronkan permission Backup/Restore, Edit/Hapus Approved V2.10.210, dan Edit/Hapus Migrasi Historis V2.10.211 hanya setelah row-count backup sumber tervalidasi.
- Menambahkan halaman Pengaturan > Verifikasi Rilis V2.10.212 untuk memeriksa VERSION, full schema, permission, Administrator grant, Maintenance storage, hotfix batch/Faktur Pajak, serta kesiapan file audit XLSX untuk ikut backup.
- Tampilan Backup & Restore diperbarui untuk menampilkan jumlah/ukuran file Faktur Pajak yang embedded dan menjelaskan perbedaan format V2.10.212 dengan backup legacy database-only.

V2.10.211 - 2026-09-04 - Koreksi & Hapus Migrasi Historis Aman Beserta Turunannya
- Menambahkan permission historical_migration.edit dan historical_migration.delete. Administrator mendapat akses awal; role lain harus diberikan eksplisit melalui Role & Permission.
- Menambahkan halaman Koreksi Lineage Historis per invoice. Satu transaksi mengelola dokumen teknis turunannya secara konsisten: Pembelian = PO + item PO + Invoice + item Invoice + pembayaran historis; Penjualan = Barang Keluar/SJ + item + Invoice + item Invoice + pembayaran historis.
- Edit histori tidak lagi dilakukan dengan membuka bebas form transaksi operasional. Koreksi memakai jalur khusus agar flag is_historical, migration_batch_id, migration_cutoff_date, affect_stock, dan affect_cash tidak berubah menjadi transaksi normal.
- Pembayaran historis s.d. cut-off dapat diedit melalui nilai Sudah Dibayar s.d. Cut-off; nilai 0 menonaktifkan pembayaran historis turunan. Pembayaran tetap affect_cash=0 sehingga tidak menciptakan arus kas periode baru.
- Pembelian Historis Mode 1/passive tetap affect_stock=0. Edit item, qty, harga, distributor, tanggal, diskon, PPN, Faktur Pajak, jatuh tempo, dan pembayaran menyinkronkan PO/Invoice/saldo hutang tanpa membuat stock_movements.
- Penjualan Historis Mode 1/passive tetap affect_stock=0 dan menyediakan koreksi HPP Historis. Barang Keluar, Faktur, item, pembayaran, piutang, dan ringkasan batch disinkronkan atomik.
- Penjualan Historis Mode 2/operasional dapat dikoreksi dan dihapus dengan metode rebuild: Safety Backup dibuat sebelum perubahan, movement sales_delivery lama dilepas, lineage diperbarui, movement baru dibentuk, lalu moving weighted average, HPP, retur terdampak, product_stocks, historical_cogs dan total_cogs batch dihitung ulang kronologis sebelum COMMIT.
- Mode 2 otomatis ROLLBACK bila rebuild menghasilkan stok minus atau verifikasi batch tidak cocok. Safety Backup tetap tersedia untuk recovery manual.
- Hapus histori dilakukan per lineage invoice dan bersifat atomik. Mode 2 menghapus movement lineage lalu rebuild semua barang terdampak; Mode 1 tidak menyentuh stok.
- Koreksi/hapus diblokir bila invoice sudah memiliki dependency eksternal seperti Retur, Pelunasan operasional/non-batch, TT, pemakaian Nota Debet/CN, atau Export Faktur Pajak. Dependency harus dikoreksi dari dokumen paling akhir terlebih dahulu.
- Seluruh koreksi/hapus mengikuti Tutup Buku. Tanggal invoice hasil koreksi tidak boleh melewati migration cut-off; cut-off juga harus berada pada periode terbuka. Khusus Mode 2, koreksi/hapus diblokir bila barang terdampak mempunyai stock movement pada periode closed karena rebuild dapat menghitung ulang HPP movement tersebut.
- Menambahkan Safety Backup dan Maintenance Lock pada koreksi/hapus histori untuk mencegah transaksi lain menyelip selama rebuild/koreksi.
- Ringkasan historical_migration_batches disinkronkan ulang setelah edit/hapus; verifier V2.10.211 menghitung dokumen aktif sehingga soft-delete lineage tetap dapat diverifikasi tanpa menghilangkan audit record.
- Tidak menambah tabel/kolom. Canonical tetap 42 tabel / 707 kolom; manifest V2.10.211 identik dengan V2.10.210.
- Backup/Restore, Cek & Perbaiki Database, fresh install database.sql, Pengaturan, dan changelog disinkronkan untuk V2.10.211.

V2.10.210 - 2026-09-04 - Koreksi Edit/Hapus Transaksi Approved Berbasis Role & Permission
- Menambahkan permission elevated Edit Approved dan Hapus Approved untuk Purchase Order, Invoice Pembelian, Pelunasan Pembelian, Retur Pembelian, Barang Keluar, Invoice Penjualan, Pelunasan Penjualan, dan Retur Penjualan.
- Permission Edit/Hapus biasa tetap wajib. Permission elevated hanya diberikan otomatis kepada Administrator; role lain harus ditentukan eksplisit melalui Role & Permission.
- Pending tetap tidak dapat diedit/dihapus; dokumen harus ditolak terlebih dahulu. Transaksi historis passive tetap dikoreksi melalui pembatalan batch Migrasi Historis.
- Edit/Hapus Approved Purchase Order dibatasi bila sudah mempunyai penerimaan/Invoice Pembelian.
- Edit/Hapus Approved Invoice Pembelian membalik stock movement, saldo stok/HPP rata-rata, penerimaan PO, dan basis HPP Pricelist secara atomik; diblokir bila ada pelunasan/retur atau mutasi stok sesudahnya.
- Edit/Hapus Approved Barang Keluar membalik stock movement dan saldo persediaan secara atomik; diblokir bila sudah mempunyai Faktur Penjualan atau mutasi stok sesudahnya.
- Edit/Hapus Approved Invoice Penjualan diblokir bila sudah mempunyai TT, Pelunasan, Retur, histori referensi retur, atau pernah masuk Export Faktur Pajak. Koreksi mengembalikan invoice ke Pending untuk approval ulang.
- Edit/Hapus Approved Pelunasan Pembelian/Penjualan menghitung ulang saldo hutang/piutang setelah transaksi lama dilepas dari status Approved.
- Edit/Hapus Approved Retur Pembelian/Penjualan membalik mutasi stok dan efek hutang/piutang terlebih dahulu; diblokir bila mutasi retur bukan lagi mutasi terakhir barang.
- Menambahkan permission Hapus Retur Pembelian dan Hapus Retur Penjualan yang sebelumnya belum lengkap pada sebagian instalasi.
- Seluruh koreksi Approved mengikuti Tutup Buku: dokumen pada periode closed tetap diblokir.
- Menambahkan Upgrade & Verifikasi V2.10.210 untuk sinkron permission secara idempotent dan mengintegrasikannya ke Cek & Perbaiki Database serta Backup/Restore post-restore.
- Backup/Restore V2.10.210 mempertahankan canonical 42 tabel / 707 kolom dan menerima backup resmi V2.10.209 secara langsung karena full-schema identik; backup V2.10.208 dan generasi yang sudah didukung tetap mengikuti jalur pre-flight yang sama.
- Tidak ada perubahan tabel/kolom. Manifest V2.10.210 dipisahkan untuk audit rilis dengan fingerprint schema yang tetap identik.
- Rilis V2.10.210 ini direbase di atas Full V2.10.209 cumulative patch 209-01 s.d. 209-08; perbaikan multi-diskon migrasi, batalkan batch historis aman, Qty/Satuan sesuai XLSX, edit stok awal, ringkasan stok volume, dan audit Tutup Buku tetap dipertahankan.

V2.10.209 - 2026-09-02 - Konsolidasi Migrasi Historis, UOM Fisik, dan Perapian Form
- Mengonsolidasikan patch pasca-V2.10.208 menjadi rilis resmi V2.10.209 tanpa perubahan struktur database. Canonical tetap 42 tabel / 707 kolom.
- Migrasi Historis Pembelian: referensi barang/distributor lebih aman, kode menjadi prioritas dengan fallback nama unik, data header invoice multi-item mengikuti baris pertama, item barang duplikat digabung otomatis, cache resolver diperbaiki, dan diagnostic/validation log dipertahankan.
- Migrasi Historis Penjualan Mode 1/passive: data level invoice multi-item mengikuti baris pertama, barang duplikat digabung otomatis, dan alias kemasan suffix X<angka> dapat dipadankan secara terbatas tanpa fuzzy matching bebas.
- Migrasi Historis tetap menjaga sifat passive/non-stock/non-cash sesuai mode; validasi beda dimensi UOM tetap diblokir agar histori tidak salah konversi.
- Import Detil Barang/Stok Awal diperbarui dengan format sederhana Qty Awal + Harga Rata-rata berbasis L/KG/UNIT dan Tanggal Stok Awal, dengan kompatibilitas template lama.
- Input Penjualan menampilkan Stok Tersedia beserta ekuivalen basis fisik L/KG/UNIT sesuai Master Barang tanpa mengubah qty stok database.
- Form Pembelian dan Penjualan dirapikan/padatkan; keterangan bantuan di bawah Harga/Satuan Harga yang diminta dihapus tanpa mengubah perhitungan harga/UOM.
- Nama barang dan satuan pada view/cetak dokumen diseragamkan kapital melalui CSS dokumen yang terkait.
- Menambahkan/menyempurnakan pemeriksaan data mirip/duplikat untuk Pelanggan, Distributor, dan Barang serta export XLSX Data Barang dan Detil Barang/Stok sesuai tampilan.
- Mempertahankan perbaikan Laporan Nyonya, Valuasi Stok, quick-add Jenis Biaya, dan export XLSX laporan pajak tahunan yang diterapkan setelah V2.10.208.
- Backup/Restore V2.10.209 menerima backup resmi V2.10.208 sebagai full-schema identik. Manifest canonical V2.10.209 dipisahkan untuk audit rilis walaupun fingerprint schema tetap sama.
- Menambahkan Verifikasi Rilis V2.10.209 di Pengaturan untuk mengecek VERSION.txt dan full-schema canonical tanpa mengubah data transaksi.

V2.10.208 - 2026-08-31 - Dependency-Aware Checklist Reset Data Bisnis
- Mengubah Reset Data Bisnis dari reset seluruh data sekaligus menjadi checklist per kelompok data sehingga Administrator dapat memilih bagian yang benar-benar ingin dibersihkan.
- Menambahkan 29 kelompok checklist yang menutup seluruh 36 tabel bisnis canonical: Master Data, Pembelian, Penjualan, Keuangan & Pajak, Persediaan, serta Sistem Operasional.
- Menambahkan tombol cepat Reset Transaksi Saja, Reset Master + Transaksi, Pilih Semua Data Bisnis, dan Batalkan Semua.
- Dependency dihitung dari foreign key database dan jumlah data yang benar-benar ada. Child yang masih mereferensikan parent otomatis ikut dipilih; bila dependency tidak memiliki data, kelompok tersebut tidak dipaksa ikut.
- Menambahkan dependency logis di luar FK untuk menjaga konsistensi stok/HPP kronologis, snapshot Closing Periode, status penerimaan PO, dan Document Sequence.
- Transaksi yang memengaruhi stok (Invoice Pembelian, Retur Pembelian, Barang Keluar, Retur Penjualan, Stock Movements, dan saldo Product Stock) diperlakukan sebagai satu siklus konsistensi bila data terkait masih ada, sehingga Kartu Stok/HPP tidak dapat terputus karena partial reset yang tidak aman.
- Reset Document Sequence otomatis memperluas pilihan ke dokumen yang masih ada agar nomor urut tidak dimulai ulang ketika nomor lama masih digunakan.
- Reset Status Data Awal/Cut-off otomatis memperluas pilihan ke data bisnis inti sehingga status not_started tidak dapat diterapkan pada database yang masih berisi transaksi/master lama.
- Pelunasan Pembelian, Pelunasan Penjualan, serta Pemakaian CN/Potong Hutang dapat direset terpisah. Bila invoice induk dipertahankan, aplikasi otomatis merekonsiliasi ulang paid_amount, balance_due, payment_status, dan receivable_status yang relevan.
- Menambahkan verifikasi hash terhadap seluruh tabel yang tidak dipilih. Bila cascade/FK/bug menyebabkan data di luar checklist ikut berubah, reset dibatalkan dan transaksi database di-rollback.
- Master Jenis Biaya dan Master Jenis Pendapatan tetap memiliki mode RESET KE DEFAULT; master custom dihapus dan master bawaan direseed hanya bila checklist master tersebut dipilih.
- Safety Backup tetap wajib dibuat sebelum perubahan database; Maintenance Lock, transaksi InnoDB, dependency child->parent DELETE, rollback otomatis, dan validasi password Administrator tetap dipertahankan.
- Activity Log, Login Attempts, dan Remember Me Tokens sekarang dapat dipilih atau dipertahankan secara independen.
- User, Role, Permission, Role Permission, Dashboard Role, identitas perusahaan, dan konfigurasi sistem inti tetap tidak pernah masuk checklist reset.
- Menambahkan Upgrade/Sinkron Checklist Reset Data Bisnis V2.10.208 yang idempotent dan integrasi ke Cek & Perbaiki Database.
- Tidak ada perubahan tabel/kolom. Canonical V2.10.208 tetap 42 tabel / 707 kolom; manifest V2.10.208 dipisahkan tetapi full-schema identik dengan V2.10.206 dan V2.10.207.
- Backup/Restore V2.10.208 mendukung backup V2.10.206 dan V2.10.207 secara langsung karena full-schema identik. Backup V2.10.200-V2.10.205 tetap mengikuti jalur migrasi schema tervalidasi yang sudah ada.

V2.10.207 - 2026-08-31 - Reset Data Bisnis Aman dengan Safety Backup
- Menambahkan fitur resmi Pengaturan > Perawatan & Utilitas Sistem > Reset Data Bisnis khusus Administrator.
- Reset menghapus master dan transaksi operasional: distributor, pelanggan, UOM, barang, stok, Pricelist, PO, pembelian, penjualan, retur, pelunasan, biaya, pendapatan lain, kredit PPh, export Faktur Pajak, mutasi stok, migrasi historis, closing periode, sequence dokumen, remember token, activity log, login attempt, dan data bisnis canonical lain.
- Data keamanan yang dipertahankan dan diverifikasi sebelum/sesudah reset: users, roles, permissions, role_permissions, dan role_dashboard_widgets.
- Tabel settings tidak dikosongkan agar identitas perusahaan dan konfigurasi sistem tetap aman. Status Data Awal dikembalikan ke not_started, tanggal/cut-off Data Awal dikosongkan, dan penanda Data Contoh 30 Hari dihapus agar perusahaan dapat memulai ulang dari kondisi bersih.
- Master Jenis Biaya custom dihapus lalu direseed menjadi 99 Jenis Biaya bawaan. Master Jenis Pendapatan custom dihapus lalu direseed ke master pendapatan bawaan V2.10.205+.
- Sebelum reset, sistem wajib membuat Safety Backup resmi melalui engine Backup aplikasi. Jika Safety Backup gagal, tidak ada DELETE yang dijalankan.
- Menambahkan Maintenance Lock untuk Reset Data Bisnis sehingga user/session lain mendapat HTTP 503 selama proses dan tidak dapat melakukan input/approval/import bersamaan.
- Seluruh DELETE, reseed master, reset status Data Awal, serta verifikasi preservasi berjalan dalam satu transaksi InnoDB. Bila satu tahap gagal sebelum commit, seluruh perubahan database di-rollback otomatis dan Safety Backup tetap tersedia.
- Urutan DELETE dihitung berdasarkan foreign key child -> parent; reset tidak mematikan FOREIGN_KEY_CHECKS. Reset diblokir jika tabel target bukan InnoDB karena rollback tidak dapat dijamin.
- Menambahkan verifikasi hash SHA-256 isi tabel keamanan/konfigurasi yang dipertahankan. Bila user/role/permission/dashboard role atau setting non-operasional berubah, reset dibatalkan dan transaction rollback.
- Setelah commit, AUTO_INCREMENT tabel bisnis kosong dikembalikan ke 1; master bawaan dilanjutkan dari ID maksimum. Kegagalan merapikan AUTO_INCREMENT dicatat sebagai warning tanpa membatalkan data reset yang sudah tervalidasi.
- Setelah reset selesai, activity_logs mulai kembali dari audit event Reset Data Bisnis baru sehingga jejak siapa yang menjalankan reset tetap tersedia.
- Menambahkan permission business_reset.view dan business_reset.execute; akses default hanya Administrator.
- Menambahkan halaman sinkronisasi Upgrade Reset Data Bisnis V2.10.207 yang idempotent dan integrasi ke Cek & Perbaiki Database.
- Backup/Restore dinaikkan ke metadata V2.10.207. Schema canonical tetap 42 tabel / 707 kolom karena fitur tidak menambah tabel/kolom.
- Manifest V2.10.207 dipisahkan walaupun identik dengan V2.10.206. Backup V2.10.206 dapat direstore langsung karena full schema identik; permission V2.10.207 disinkronkan setelah row-count backup diverifikasi. Backup V2.10.200-V2.10.205 tetap mengikuti migrasi schema lama sampai canonical V2.10.207.
- Changelog, fresh install database.sql, Settings, Maintenance Mode, Cek & Perbaiki Database, dan Backup/Restore sudah disinkronkan.

V2.10.206 - 2026-08-30 - Kalkulasi PPh Otomatis DPP × Tarif
- Menambahkan mode Hitung Otomatis pada Detail Tax Biaya: Nilai PPh = DPP Pajak × Tarif PPh / 100 dengan ROUND HALF-UP 2 desimal.
- Menambahkan mode Hitung Otomatis pada Pendapatan Lain-Lain / Nota Debet / Bonus: Nilai PPh = DPP × Tarif PPh / 100.
- Transaksi baru default Hitung Otomatis. Nilai PPh langsung diperbarui saat DPP, tarif, atau jenis PPh berubah.
- Nilai PPh tetap dapat dikoreksi manual dengan mematikan Hitung Otomatis agar dapat disesuaikan dengan Bukti Potong.
- Validasi server menghitung ulang PPh pada mode otomatis saat Simpan, sehingga nominal tidak hanya bergantung pada JavaScript/browser.
- Histori V2.10.205 dan sebelumnya tidak dihitung ulang saat upgrade: mode transaksi lama di-set Manual untuk menjaga angka PPh yang sudah tersimpan.
- Menambah expenses.tax_withholding_auto_calc dan other_incomes.withholding_auto_calc. Canonical V2.10.206 menjadi 42 tabel / 707 kolom.
- Backup/Restore menyimpan manifest V2.10.205 sebagai schema historis. Backup resmi V2.10.200–V2.10.205 yang full-schema sumbernya valid dapat direstore lalu dimigrasikan otomatis sampai V2.10.206.
- Safety Backup, rollback otomatis, full-schema verification, dan row-count verification tetap digunakan.
- Cek & Perbaiki Database dan fresh install database.sql sudah disinkronkan dengan V2.10.206.

V2.10.205 - 2026-08-30 - Pendapatan Lain-Lain, Nota Debet/Bonus, Kredit PPh & Laba Rugi Tahunan Pajak
- Menambahkan modul Master Jenis Pendapatan untuk menentukan default kelompok laporan, pengaruh kas, dan perlakuan pajak Pendapatan Lain-Lain.
- Menambahkan modul Pendapatan Lain-Lain untuk Bonus Produk/Penghargaan, Kompensasi Perlindungan Harga, Nota Debet/Bonus Distributor, bunga bank/deposito, penjualan aset, dan pendapatan lain.
- Detail Pendapatan Lain-Lain menyimpan No. Dokumen/Nota Debet, distributor/pabrik, NPWP, DPP, PPN, jenis/tarif/nilai PPh 22/23, Faktur Pajak, Bukti Potong, tanggal bukti potong, dan perlakuan pajak.
- Menambahkan tabel pemakaian nilai bersih Nota Debet/Bonus agar satu pendapatan dapat memiliki banyak CN, potong hutang, penerimaan kas, atau pemakaian lain tanpa dibatasi jumlah kolom seperti template Excel.
- CN/Potong Hutang yang dihubungkan ke Invoice Pembelian Approved ikut mengurangi saldo hutang (`balance_due`). Penghapusan pemakaian atau Pendapatan Lain-Lain menghitung ulang saldo hutang secara otomatis.
- Laporan Hutang, Dashboard Sisa Hutang, reminder hutang +30 hari, Laporan Keuangan, dan snapshot Tutup Buku ikut memperhitungkan CN/Nota Debet/Potong Hutang per tanggal agar saldo hutang konsisten di seluruh aplikasi.
- Menambahkan validasi agar nilai CN/potong hutang tidak melebihi sisa pendapatan bersih maupun sisa hutang Invoice Pembelian.
- Menambahkan modul Kredit Pajak PPh manual untuk PPh 22, PPh 23, PPh 25, dan kredit pajak lain. PPh 22/23 yang sudah tercatat pada Pendapatan Lain-Lain direkap otomatis sehingga tidak perlu diinput ulang.
- Menambahkan Laporan Pendapatan Lain-Lain/Nota Debet mengikuti struktur contoh CV SEJATI TANI: bruto, DPP, PPN, PPh 22/23, bukti potong, pabrik/NPWP, nilai bersih, pemakaian CN, dan sisa.
- Menambahkan Rekap Kredit PPh yang menggabungkan PPh 22/23 otomatis dari Pendapatan Lain-Lain dengan kredit pajak manual.
- Menambahkan Laporan Laba Rugi Tahunan & Pajak mengikuti susunan contoh Excel: Penjualan PPN/Non-PPN, retur, HPP, Biaya Usaha, Pendapatan/Biaya Lain-Lain, laba sebelum pajak, rekonsiliasi fiskal, estimasi PPh, kredit PPh 22/23/25, kurang/(lebih) bayar, dan estimasi PPh 25 bulanan.
- HPP utama Laba Rugi Tahunan tetap memakai mutasi stok `sale - sales_return` dan HPP historis. Persediaan awal, pembelian, retur, persediaan akhir, dan adjustment ditampilkan sebagai rekonsiliasi sehingga tidak menggandakan HPP.
- Menambahkan kelompok laporan pada Master Jenis Biaya dan transaksi Biaya: `Biaya Usaha` atau `Biaya Lain-Lain`. Histori menyimpan snapshot kelompoknya.
- Laporan Keuangan reguler sekarang ikut memasukkan Pendapatan Lain-Lain ke laba bersih dan hanya memasukkan Pendapatan Lain-Lain bertanda Mempengaruhi Kas ke arus kas.
- Menambahkan export XLSX untuk Laporan Pendapatan Lain-Lain, Pemakaian CN/Potong Hutang, Rekap Kredit PPh, dan Laba Rugi Tahunan & Pajak.
- Tarif estimasi PPh Badan tidak di-hardcode: tersedia pengaturan default dan dapat dioverride saat membuka laporan. Angka ini hanya parameter estimasi dan bukan penetapan tarif pajak secara hukum.
- Fresh install database.sql diperbarui dengan 4 tabel baru, 2 kolom klasifikasi laporan biaya, master jenis pendapatan, permission, dan setting tarif estimasi.
- Canonical Backup/Restore V2.10.205 menjadi 42 tabel / 705 kolom. Manifest V2.10.204 disimpan sebagai manifest historis terpisah.
- Restore backup resmi V2.10.200-202, V2.10.203, dan V2.10.204 yang full-schema sumbernya valid dapat dimigrasikan otomatis berurutan sampai V2.10.205 lalu diverifikasi ulang dengan full-schema dan row-count.
- Safety Backup, rollback otomatis, verifikasi full schema, dan sinkronisasi master/permission setelah row-count tetap dipertahankan.
- Cek & Perbaiki Database ikut membuat/sinkron schema, master, dan permission V2.10.205.
- Mempertahankan patch khusus sebelumnya: Koreksi/Edit PO, Koreksi/Edit Penjualan, Koreksi/Edit Pembelian, serta Valuasi Stok tanpa icon/lingkaran pada kartu ringkasan.

JCOM INVENTORY - CHANGELOG LENGKAP
==================================

Riwayat perubahan disusun dengan versi terbaru di bagian paling atas.
Urutan: versi terbaru -> versi paling awal.
Mulai V2.10.182, setiap rilis baru ditambahkan di bagian paling atas changelog.
Versi yang tidak pernah dirilis/disertakan pada baseline produksi tidak dibuat sebagai entri baru.

V2.10.204 - 2026-08-28 - Detail Tax Biaya, Laporan Pajak & Restore Lintas Versi
------------------------------------------------------------------------------------------
- Menambahkan Detail Tax pada transaksi Biaya tanpa menghapus field TAX lama: mode Detail Tax dan Legacy TAX disimpan per transaksi.
- Transaksi baru default memakai Detail Tax; histori V2.10.203 dan lebih lama tetap Legacy TAX agar nilai pajak lama tidak ditebak sebagai PPN/PPh.
- Menambahkan data Vendor/Penerima, Jenis ID (NPWP/NIK/ID lain), Nomor ID, DPP Pajak, PPN Masukan, Jenis PPh, Tarif PPh, Nilai PPh Dipotong/Dibayar, Pajak Lain, No. Faktur Pajak, No. Bukti Potong, Tanggal Dokumen Pajak, dan Catatan Tax.
- Pada mode Detail Tax, field TAX kompatibilitas dihitung dari PPN Masukan + Pajak Lain; PPh withholding tidak ditambahkan ke Total Biaya.
- Menambahkan Laporan > Keuangan > Laporan Tax Biaya dengan filter periode, scope data pajak, mode Detail/Legacy, Jenis PPh, perlakuan fiskal, dan pencarian vendor/NPWP/dokumen.
- Laporan Tax menampilkan ringkasan DPP, PPN Masukan Tercatat, PPh Dipotong/Dibayar, Pajak Lain, TAX Legacy, detail dokumen pajak, serta rekap per Jenis PPh.
- Menambahkan Unduh XLSX Laporan Tax Biaya dengan sheet Ringkasan, Detail Tax, dan Rekap PPh.
- Menambahkan permission expense_tax_reports.view dan expense_tax_reports.export beserta default akses Administrator/Staff/Approver/Viewer yang konsisten dengan laporan biaya.
- Menambahkan upgrade_expense_tax_v210204.php yang idempotent dan menambahkan 14 kolom Detail Tax + 3 index baru pada expenses.
- Cek & Perbaiki Database diperbarui agar ikut menyinkronkan kolom/index/permission Detail Tax V2.10.204.
- Canonical Backup/Restore diperbarui ke schema V2.10.204. Backup resmi V2.10.203 mendapat manifest sumber tersendiri dan dapat direstore lalu dimigrasikan otomatis ke V2.10.204.
- Backup resmi V2.10.200-V2.10.202 tetap didukung: setelah restore schema sumber tervalidasi, sistem menjalankan migrasi Klasifikasi Biaya V2.10.203 lalu Detail Tax V2.10.204 sebelum full-schema verification final.
- Safety Backup, full-schema verification, row-count verification, dan rollback otomatis tetap dipertahankan.
- Fresh install database.sql sudah menyertakan seluruh field dan index Detail Tax V2.10.204.

V2.10.203 - 2026-08-28 - Klasifikasi Biaya, Master Default & Restore Lintas Versi
------------------------------------------------------------------------------------------
- Menambahkan Master Jenis Biaya sebagai menu tersendiri. Master menyimpan default Masuk Laba Rugi, Mempengaruhi Kas/Kas-Non-Kas, Perlakuan Fiskal, keterangan, dan status aktif/nonaktif.
- Menambahkan halaman Contoh Klasifikasi Biaya langsung di aplikasi, dapat dibuka dari menu Biaya dan Master Jenis Biaya. Halaman simulasi tidak menambah/mengubah data transaksi.
- Contoh mencakup gaji, listrik, internet, BBM, penyusutan, pembelian aset, deposit, cicilan pokok+bunga, denda pajak, konsumsi rapat, sumbangan, kerugian piutang, kredit pajak, prive, dan transfer antar rekening.
- Halaman contoh menampilkan simulasi dampak nilai terhadap Beban Laba Rugi, Catatan Terpisah, Kas, Non-Kas, Koreksi Fiskal Positif, serta contoh pemisahan cicilan bank dan pembelian aset.
- Menambahkan 99 Jenis Biaya bawaan rinci untuk perusahaan umum: SDM, kantor, sewa, transportasi/distribusi, kendaraan, perawatan, pemasaran, bank, jasa profesional/IT, asuransi, penyusutan/amortisasi, pajak, kerugian, sosial, serta transaksi terpisah dari Laba Rugi.
- Default master hanya diterapkan saat membuat transaksi baru. Transaksi Biaya menyimpan snapshot include_profit_loss, affect_cash, dan fiscal_treatment sehingga perubahan master di kemudian hari tidak mengubah histori.
- Kategori bawaan gabungan dari build awal V2.10.203 (mis. Gaji+Tunjangan+Bonus, Sewa Kantor/Gudang, Listrik+Air, Transportasi+BBM+Tol+Parkir) dinonaktifkan untuk input baru setelah master rinci disinkronkan; master tetap disimpan agar histori/referensi transaksi lama tidak rusak.
- Edit transaksi lama tetap dapat mempertahankan Jenis Biaya yang sudah nonaktif; Jenis Biaya nonaktif tidak dapat dipilih untuk transaksi baru.
- Biaya: pilihan Jenis Biaya sekarang berasal dari master aktif; default klasifikasi master terisi otomatis tetapi masih dapat disesuaikan per transaksi bila diperlukan.
- Menambahkan expenses.affect_cash untuk membedakan transaksi Kas dan Non-Kas. Penyusutan/amortisasi dapat masuk Laba Rugi tanpa salah mengurangi arus kas.
- Menambahkan expenses.fiscal_treatment dengan pilihan Dapat Dikurangkan/Tidak Koreksi, Koreksi Fiskal Positif, Koreksi Fiskal Negatif, Perlu Review Fiskal, dan Tidak Berlaku untuk transaksi Non-Laba-Rugi.
- Laporan Biaya diperluas dengan filter Laba Rugi/Terpisah, Kas/Non-Kas, Perlakuan Fiskal, dan Jenis Biaya; ringkasan menampilkan Beban Laba Rugi, Catatan Terpisah, Kas Keluar, Nilai Non-Kas, dan Koreksi Fiskal Positif.
- XLSX Laporan Biaya mengikuti filter baru dan membawa kolom klasifikasi Laba Rugi, Kas/Non-Kas, serta Perlakuan Fiskal.
- Laporan Keuangan: arus kas keluar Biaya sekarang hanya menjumlahkan expenses.affect_cash=1. Beban non-kas tetap dapat mengurangi Laba Rugi tetapi tidak mengurangi kas.
- Bukti/Cetak Biaya menampilkan status Mempengaruhi Kas dan Perlakuan Fiskal.
- Menambahkan permission expense_types.view/create/edit dan memastikan permission expense_reports.view/export tersinkron; Administrator mendapat seluruh akses, role lain mengikuti default read/report yang aman.
- Cek & Perbaiki Database diperbarui untuk membuat/memperbaiki kolom, index, permission, master bawaan, dan relasi klasifikasi Biaya V2.10.203 secara idempotent.
- Menambahkan upgrade_expense_classification_v210203.php untuk upgrade database existing V2.10.202. Data transaksi lama mempertahankan perilaku Kas seperti sebelumnya dan status fiskalnya tidak ditebak: default Perlu Review Fiskal.
- Backup/Restore canonical schema diperbarui dari 38 tabel / 622 kolom menjadi 38 tabel / 628 kolom dan tetap memverifikasi type/ENUM, NULL, DEFAULT, index, FK, engine, charset/collation, checksum, serta row count.
- Restore backup resmi V2.10.200-V2.10.202 yang CREATE TABLE-nya terbukti cocok dengan canonical schema sumber kini didukung tanpa mematikan proteksi full-schema. Restore dilakukan ke schema sumber tervalidasi, row count diverifikasi, kemudian schema dimigrasikan otomatis ke V2.10.203 dan master/permission baru disinkronkan.
- Safety Backup tetap dibuat sebelum Restore. Jika restore, migrasi schema, full-schema verification, atau row-count verification gagal, sistem mencoba rollback otomatis ke Safety Backup dan memverifikasi ulang hasil rollback.
- Backup generasi/struktur lain yang tidak cocok dengan manifest canonical tetap diblokir; perbedaan nomor versi tidak dapat digunakan untuk melewati ketidakcocokan schema.
- Fresh install database.sql sudah menyertakan kolom/index/master Jenis Biaya V2.10.203.

V2.10.202 - 2026-08-27 - Export Faktur Pajak Kode 08 Bibit & Dokumen Pendukung
------------------------------------------------------------------------------------------
- Sheet Faktur: kolom Dokumen Pendukung sekarang diisi sama persis dengan kolom Referensi.
- Kode Transaksi otomatis menjadi 08 untuk invoice yang seluruh itemnya bernama mengandung kata Bibit atau diawali pola B. (contoh B. BAYAM, B. JAGUNG).
- Invoice yang mencampur barang fasilitas Kode 08 dan barang biasa diblokir saat export agar kode transaksi level Faktur tidak salah diterapkan ke seluruh item.
- Invoice non-Bibit tetap memakai Kode Transaksi default dari Pengaturan.
- Label Kode 08 di Pengaturan diperjelas menjadi Penyerahan dengan fasilitas dibebaskan PPN atau PPN dan PPnBM.
- Berlaku pada export Faktur Pajak per invoice maupun per periode karena menggunakan renderer XLSX yang sama.
- Tidak ada perubahan database atau transaksi.

V2.10.201 - 2026-08-27 - Perbaikan Schema Validator Backup/Restore
- Memperbaiki false mismatch Backup/Restore V2.10.200 yang menganggap hampir seluruh tabel berbeda karena manifest canonical dibuat dari DDL sebelum normalisasi MySQL.
- Parser full schema sekarang menormalisasi PRIMARY KEY sebagai NOT NULL, DEFAULT NULL pada kolom nullable, DEFAULT DECIMAL sesuai scale, dan implicit index foreign key seperti SHOW CREATE TABLE.
- Manifest canonical dibangun kembali dari baseline live-compatible V2.10.198 + perubahan sah Master Jenis Biaya/Laba Rugi V2.10.199-200: 38 tabel / 622 kolom.
- database.sql ditambahkan idx_historical_migration_created_by agar fresh install dan database existing menghasilkan full schema yang identik.
- Backup/Restore menampilkan jumlah tabel canonical secara dinamis; tidak perlu menjalankan Cek/Perbaiki Database untuk false mismatch ini.
- Tidak ada perubahan data transaksi atau struktur database pada database existing V2.10.200.

V2.10.200 - 2026-08-25 - Checklist Laba Rugi & Laporan Biaya XLSX
--------------------------------------------------------------------------
- Keuangan > Biaya: menambahkan checklist Masuk Laba Rugi per transaksi. Data lama default Ya agar perhitungan Laba Rugi existing tidak berubah setelah upgrade.
- Laporan Keuangan sekarang hanya memasukkan biaya dengan Masuk Laba Rugi=Ya sebagai beban; biaya Terpisah tetap dihitung sebagai arus kas/pengeluaran tetapi tidak mengurangi laba.
- Dashboard Biaya Bulan Ini diubah menjadi Biaya Laba Rugi Bulan Ini.
- Menambahkan Laporan > Keuangan > Laporan Biaya dengan filter Periode, Jenis Transaksi (Semua/Laba Rugi/Terpisah), dan Jenis Biaya.
- Menambahkan kartu ringkasan Total Transaksi, Beban Laba Rugi, Pengeluaran Terpisah, dan Total Pengeluaran.
- Menambahkan Unduh XLSX Laporan Biaya dengan sheet Ringkasan, Biaya, dan Rekap Jenis.
- Tampilan form Biaya dan Laporan Biaya dirapatkan dan dirapikan agar lebih mudah dibaca.
- Menambahkan expenses.include_profit_loss beserta index untuk filter laporan dan sinkronisasi Backup/Restore.
- Menambahkan permission expense_reports.view dan expense_reports.export untuk pengaturan User Role.

V2.10.199 - 2026-08-25 - Master Jenis Biaya Database & Dropdown Biaya
--------------------------------------------------------------------------
- Keuangan > Biaya: field Jenis Biaya diubah dari input teks bebas menjadi dropdown yang bersumber dari master database expense_types.
- Menambahkan pilihan + Tambah Jenis Biaya Baru pada form Biaya. Jenis baru disimpan ke master database saat transaksi Biaya disimpan dan otomatis tersedia untuk user/transaksi berikutnya.
- Menambahkan tabel expense_types sebagai master Jenis Biaya dengan status aktif/nonaktif dan audit created_by/created_at/updated_at.
- Menambahkan expenses.expense_type_id sebagai foreign key ke expense_types. Kolom lama expenses.expense_type tetap dipertahankan sebagai snapshot nama jenis agar laporan/cetak dan histori lama tetap kompatibel.
- Upgrade otomatis mengimpor seluruh expense_type lama yang sudah pernah dipakai menjadi master expense_types dan memetakan transaksi lama ke expense_type_id tanpa mengubah nilai transaksi.
- Menambahkan upgrade_expense_types_v210199.php yang idempotent untuk database existing.
- database.sql dan setup.php fresh install sudah menyertakan master Jenis Biaya.
- Cek/Perbaiki Database diperbarui agar dapat membuat master Jenis Biaya, kolom relasi, index, foreign key, dan mapping jenis lama bila belum lengkap.
- Backup & Restore canonical schema diperbarui menjadi 38 tabel / 621 kolom agar expense_types dan relasi expenses.expense_type_id ikut dibackup dan diverifikasi.
- Tidak mengubah perhitungan jumlah biaya, TAX, total biaya, Laba Rugi, atau transaksi lama.

V2.10.198 - 2026-08-25 - Migrasi Penjualan: No. Invoice Otomatis & Barang Kode/Nama
------------------------------------------------------------------------------------------
- Migrasi Histori Penjualan Mode 1 dan Mode 2 sekarang mengizinkan No. Invoice dikosongkan; nomor final dibuat otomatis saat Import Final memakai generator Faktur Penjualan sistem dan tanggal invoice historis.
- Preview tidak mengambil nomor sequence. Nomor otomatis baru dialokasikan di dalam transaksi final; bila import rollback, sequence ikut rollback.
- Menambahkan kolom opsional Grup Invoice. Jika No. Invoice kosong dan beberapa baris memiliki Grup Invoice yang sama, baris tersebut dibentuk menjadi satu invoice otomatis multi-item. Jika Grup Invoice juga kosong, satu baris dianggap satu invoice otomatis.
- No. Invoice yang diisi manual tetap dipertahankan sebagai nomor custom dan tetap wajib unik.
- Identifikasi barang pada migrasi penjualan cukup mengisi salah satu: Kode Barang atau Nama Barang.
- Jika Kode Barang dan Nama Barang sama-sama diisi, keduanya wajib menunjuk master barang yang sama. Jika nama barang cocok dengan lebih dari satu master, sistem meminta Kode Barang agar tidak ambigu.
- Template XLSX migrasi penjualan diperbarui untuk menunjukkan No. Invoice otomatis, Grup Invoice multi-item, contoh Kode Barang saja, dan contoh Nama Barang saja.
- Migrasi Pembelian Historis tidak diubah: No. Invoice, Kode Distributor, dan Kode Barang tetap mengikuti aturan sebelumnya.
- Tidak ada perubahan struktur database.

V2.10.197 - 2026-08-25 - Perbaikan Mode 2 Migrasi Histori Penjualan
--------------------------------------------------------------------------
- Memperbaiki false popup Proses Gagal pada halaman Mode 2: banner penjelasan Operasional/Rebuild Stock sebelumnya memakai alert-danger dan tertangkap popup global sebagai error setelah submit.
- Menambahkan data-process-popup-ignore pada banner/alert informatif dan memperkuat app.js agar alert statis yang ditandai ignore tidak pernah diubah menjadi popup hasil proses.
- Memperbaiki pemeriksaan integritas average cost Mode 2. Selisih pecahan average cost akibat inventory_value 2 desimal vs avg_cost presisi tinggi sekarang dinilai berdasarkan dampak nilai persediaan, bukan toleransi absolut 1e-7 yang terlalu ketat.
- Qty stok dan inventory_value tetap diverifikasi ketat; mismatch nyata tetap memblokir Preview/Import Mode 2.
- Pesan integritas stok sekarang menampilkan selisih qty, nilai, dan dampak selisih average cost agar diagnosis lebih jelas.
- Verifikasi saldo akhir setelah rebuild menggunakan aturan toleransi ekonomi yang sama tanpa mengurangi proteksi rollback batch.
- Tidak ada perubahan struktur database.

V2.10.196 - 2026-08-25 - Migrasi Histori Penjualan Mode 2 / Rebuild Stock
----------------------------------------------------------------------------
- Menambahkan Mode 2 untuk migrasi histori Invoice Penjualan setelah perusahaan sudah berjalan: transaksi historis diperlakukan sebagai transaksi stok operasional, bukan histori pasif.
- Mode 2 wajib melalui Preview Impact sebelum import final; preview menampilkan barang terdampak, movement baru, jumlah movement yang akan dihitung ulang, stok akhir sebelum/sesudah, average cost sebelum/sesudah, valuasi stok sebelum/sesudah, dan perubahan HPP kumulatif.
- Preview Impact memblokir import bila stok akan minus pada titik kronologis mana pun atau bila qty/average cost/nilai product_stocks tidak konsisten dengan jejak stock_movements existing.
- Mode 2 memblokir tanggal invoice yang masuk periode akuntansi yang sudah ditutup; periode harus dibuka kembali sebelum migrasi backdated dilakukan.
- Sebelum perubahan data dimulai, sistem wajib membuat Safety Backup database melalui engine Backup resmi aplikasi. Kegagalan membuat backup otomatis membatalkan Mode 2.
- Menambahkan pengecekan engine tabel: seluruh tabel yang dapat berubah dalam Mode 2 wajib InnoDB agar rollback batch bersifat atomik.
- Pada import final, seluruh product_stocks dan rentang stock_movements barang terdampak dikunci lebih awal untuk mencegah transaksi stok user lain menyelip selama rebuild.
- Preview Impact dihitung ulang setelah lock. Fingerprint SHA-256 dibandingkan dengan preview yang telah dilihat user; jika dampak berubah sejak preview, import dibatalkan dan user wajib Preview ulang.
- Mode 2 membuat Barang Keluar, Surat Jalan, sales item, Faktur Penjualan, dan stock movement sale baru dengan tanggal histori; dokumen langsung tersimpan Approved sebagai transaksi migrasi operasional dengan is_historical=1 dan affect_stock=1.
- Nomor Surat Jalan historis dapat dipertahankan bila unik; bila kosong/tidak valid sistem membuat nomor MIG-SJ khusus batch tanpa mengubah generator nomor Surat Jalan operasional normal.
- Rebuild menghitung ulang seluruh stock_movements barang terdampak secara kronologis menggunakan moving weighted average; HPP sale, average cost, balance quantity, balance cost, balance value, dan product_stocks akhir disinkronkan.
- Retur Pembelian/Penjualan existing yang berada setelah titik histori ikut disinkronkan nilai persediaannya berdasarkan HPP sumber hasil rebuild, termasuk inventory_value_effect pada header retur.
- HPP historical_cogs Invoice Mode 2 dan total_cogs batch historis operasional ikut disinkronkan ulang bila batch backdated baru mengubah HPP batch Mode 2 yang lebih lama/lebih baru.
- Laporan Keuangan hanya menambahkan historical_cogs untuk Mode 1/affect_stock=0; Mode 2 mengambil HPP dari stock_movements nyata sehingga tidak terjadi double-count HPP.
- Invoice Mode 2 tetap muncul pada Laporan Penjualan dan Migrasi Historis. Detail invoice menampilkan label Histori Operasional — Stok + HPP Diproses.
- Retur Penjualan diizinkan untuk Faktur Mode 2 karena memiliki stock movement nyata; Histori Pasif/affect_stock=0 tetap tidak dapat menjadi sumber retur stok.
- Pembayaran historis awal tetap affect_cash=0 agar saldo piutang terbentuk tanpa menciptakan arus kas baru; pembayaran operasional berikutnya tetap dapat dilakukan melalui Pelunasan Penjualan normal.
- Menambahkan opsi sinkronisasi Pricelist Markup Otomatis terbaru dari average cost akhir setelah rebuild. Pricelist Manual tidak pernah diubah; opsi ini default aktif pada Mode 2.
- Seluruh perubahan Mode 2 berada dalam satu transaksi database. Jika satu tahap insert, rebuild, verifikasi, atau commit gagal, seluruh batch di-rollback; setelah rollback sistem memeriksa bahwa batch/dokumen baru tidak tersisa dan Safety Backup tetap tersedia untuk recovery.
- Verifikasi final membandingkan product_stocks dengan saldo stock_movements terakhir untuk qty, average cost, dan nilai persediaan sebelum COMMIT.
- Mode 1 Migrasi Historis lama tetap tersedia tanpa perubahan perilaku: tidak membuat movement stok dan tidak mempengaruhi average cost/valuasi.
- Tidak ada perubahan struktur database dan tidak memerlukan SQL upgrade.

V2.10.195 - 2026-08-25 - Popup Error Global Input dan Proses
---------------------------------------------------------------
- Menyamakan notifikasi kesalahan input/proses dengan popup global yang digunakan oleh pesan login berhasil.
- Flash error, warning, dan success hasil POST tetap tampil sebagai message box; alias flash lama `danger/fail/failed` dinormalisasi menjadi `error`.
- Validasi HTML5 seperti field wajib, format email/angka, minimum/maksimum, dan input tidak valid kini menampilkan popup `Input Belum Lengkap` serta menyorot field yang bermasalah.
- Form dengan validasi server per-field (`.form-error`) kini menggabungkan pesan kesalahan menjadi popup `Input Tidak Valid` setelah proses POST gagal.
- Memperbaiki Retur Pembelian dan Retur Penjualan yang sebelumnya memakai flash key `danger`, sehingga kegagalan proses sekarang selalu terlihat.
- Mengganti alert native pada validasi stok/barang utama dan menambahkan popup pada kegagalan AJAX penting: preview nomor PO/SJ/Faktur/Pelunasan, refresh barang/stok, serta lookup HPP Pricelist.
- Tidak ada perubahan struktur database, nominal transaksi, stok, hutang/piutang, approval, atau Backup & Restore. Tidak memerlukan SQL upgrade.

V2.10.194 - 2026-08-25 - Rapikan View Laporan Nyonya
--------------------------------------------------------
- Laporan Nyonya: menghapus filter/pencarian Distributor/Pabrik dari tampilan laporan.
- Laporan Nyonya: menghapus kolom pencarian No. Invoice/Pabrik/Keterangan; filter laporan kini fokus pada Jatuh Tempo Dari dan Jatuh Tempo Sampai.
- Parameter pencarian lama distributor_id/q diabaikan agar bookmark/link lama tidak lagi memfilter data secara tersembunyi.
- View laporan dirapikan: filter lebih ringkas, kartu ringkasan dipadatkan, header laporan/periode lebih terstruktur, serta lebar dan alignment kolom tabel dibuat lebih proporsional.
- Unduh XLSX tetap mengikuti periode jatuh tempo yang aktif dan format XLSX V2.10.192 yang sudah bebas calcChain/formula rusak.
- Tidak ada perubahan database, perhitungan hutang, pembayaran, retur, stok, atau approval. Tidak memerlukan SQL upgrade.

V2.10.193 - 2026-08-25 - Audit Full, Backup Restore, dan Hardening Setup
--------------------------------------------------------------------------
- Menjalankan audit ulang seluruh paket aplikasi, termasuk syntax PHP/JavaScript, referensi include/route literal, template XLSX, schema canonical, permission Backup & Restore, Setup, dan tool Cek/Perbaiki Database.
- Backup/Restore: memperbaiki Pre-Flight agar backup versi lama yang fingerprint header-nya legacy tidak ditolak apabila scanner FULL SCHEMA sudah membuktikan seluruh CREATE TABLE identik dengan schema canonical aplikasi tujuan.
- Backup/Restore: fingerprint yang berbeda tetap diblokir bila FULL SCHEMA tidak identik; backup tanpa fingerprint juga hanya boleh lanjut bila FULL SCHEMA dapat diverifikasi identik.
- Backup/Restore: memperkuat rollback otomatis Safety Backup. Rollback sekarang baru dinyatakan berhasil setelah FULL SCHEMA diverifikasi ulang dan row count setiap tabel dibandingkan kembali bila manifest row count tersedia.
- Backup/Restore: bila rollback Safety Backup tidak dapat diverifikasi, aplikasi memberi peringatan eksplisit untuk melakukan pemulihan manual dan tidak melanjutkan transaksi sebelum database diperiksa.
- Setup: menggunakan session_name yang sama dengan aplikasi agar instalasi existing dapat mengenali sesi Administrator.
- Setup: pada database yang sudah terinstal, halaman setup dikunci untuk Administrator aktif; mode recovery tetap tersedia bila koneksi database existing benar-benar tidak dapat dibuka.
- Setup: menghapus password awal tetap dari source. Akun baru pada fresh install menggunakan password acak sekali pakai yang ditampilkan setelah instalasi, sedangkan password akun existing tidak di-reset saat sinkronisasi.
- Tool Cek/Perbaiki Database: pembuatan akun sistem yang hilang juga memakai password acak sekali pakai; akun existing tidak lagi berisiko di-reset ke password tetap.
- Hardening webroot: storage/backups dan koneksi.php diblokir dari akses HTTP langsung melalui .htaccess, sementara download backup tetap melalui endpoint berpermission.
- Audit schema statis: database.sql dan schema manifest konsisten 37 tabel / 614 kolom dengan urutan kolom identik; seluruh tabel canonical menggunakan InnoDB.
- Tidak ada perubahan struktur database, data transaksi, stok, hutang/piutang, atau format dokumen transaksi. Tidak memerlukan SQL upgrade.

V2.10.192 - 2026-08-25 - Perbaikan XLSX Laporan Nyonya / CalcChain
---------------------------------------------------------------------
- Memperbaiki Unduh XLSX Laporan Nyonya yang sebelumnya dapat memunculkan pesan Microsoft Excel: "We found a problem with some content" dan "Removed Records: Formula from /xl/calcChain.xml".
- Penyebabnya adalah calcChain/formula lama dari template Laporan-Nyonya.xlsx tetap terbawa walaupun worksheet hasil export sudah seluruhnya berisi nilai statis.
- Generator sekarang menghapus xl/calcChain.xml, relasi calcChain pada xl/_rels/workbook.xml.rels, dan Content Type calcChain sebelum file disimpan.
- Menambahkan validasi fail-fast agar file export ditolak bila formula/calcChain template ikut terbawa kembali.
- Tampilan khusus Laporan Nyonya, grouping per pabrik, subtotal, format tanggal/nominal, dan No Invoice sebagai Text tetap dipertahankan.
- Mekanisme export dibuat konsisten dengan prinsip XLSX Laporan Pembelian/Penjualan: workbook hasil unduhan tidak membawa calculation metadata yang tidak digunakan.
- Tidak ada perubahan database, hutang, pembayaran, retur, atau perhitungan laporan.

V2.10.191 - 2026-08-25 - Prefix Rp Ringkasan Faktur Penjualan
-----------------------------------------------------------------
- Faktur Penjualan: nominal pada baris Jumlah sekarang memakai prefix Rp.
- Faktur Penjualan: nominal pada baris Discount sekarang memakai prefix Rp, termasuk nilai nol ditampilkan sebagai Rp 0.
- Faktur Penjualan: nominal pada baris DPP Nilai Lain sekarang memakai prefix Rp.
- Faktur Penjualan: nominal pada baris PPN sekarang memakai prefix Rp.
- Faktur Penjualan: nominal pada baris Total Jumlah sekarang memakai prefix Rp.
- Prefix Rp ditempatkan terpisah dari nilai editable agar fitur Edit Nominal dan Terbilang tetap bekerja normal.
- Perubahan hanya pada renderer/tampilan cetak; nominal transaksi dan database tidak berubah.

V2.10.190 - 2026-08-25 - Format Rp Kolom Jumlah Faktur dan Retur Penjualan
--------------------------------------------------------------------------------
- Faktur Penjualan: nilai pada kolom item Jumlah sekarang menampilkan prefix Rp seperti kolom Harga Satuan.
- Faktur Penjualan: label ringkasan "Jumlah Rp." diubah menjadi "Jumlah".
- Faktur Penjualan: label ringkasan "Total Jumlah Rp." diubah menjadi "Total Jumlah".
- Retur Penjualan: nilai pada kolom item Jumlah sekarang menampilkan prefix Rp seperti kolom Harga Satuan.
- Perubahan hanya pada renderer/tampilan cetak; nominal transaksi dan database tidak berubah.

V2.10.189 - 2026-08-25 - Laporan Nyonya / Pengajuan Pembayaran Hutang Jatuh Tempo
----------------------------------------------------------------------------------------
- Menambahkan menu Laporan > Pembelian > Laporan Nyonya untuk pengajuan pembayaran hutang jatuh tempo.
- Format tampilan mengikuti contoh Laporan-Nyonya.xlsx: No, Nama CV, Nama Pabrik, No Invoice, Tgl Terbit, Jatuh Tempo, Tgl Masuk Brg, Nominal, dan Keterangan.
- Data dikelompokkan per Distributor/Pabrik dengan subtotal per pabrik; Nama CV mengambil identitas perusahaan dari Pengaturan.
- Laporan hanya mengambil Invoice Pembelian Approved yang masih memiliki sisa hutang dan Jatuh Tempo; Invoice Lunas tidak ditampilkan.
- Nominal menggunakan balance_due/sisa hutang aktif sehingga Retur Pembelian Approved dan pembayaran Approved tidak diajukan dua kali.
- Tgl Masuk Brg mengambil Tanggal Surat Jalan dan fallback ke tanggal stock_processed_at bila tanggal SJ belum tersedia.
- Keterangan menggunakan Keterangan Invoice bila diisi; bila kosong mengambil ringkasan nama barang pada invoice.
- Menambahkan filter Jatuh Tempo Dari/Sampai, Distributor/Pabrik, dan pencarian No Invoice/Pabrik/Keterangan; filter tanggal bersifat opsional.
- Menambahkan Unduh XLSX menggunakan template Laporan-Nyonya.xlsx: judul/periode/warna/border/subtotal mengikuti contoh, dan No Invoice dipaksa sebagai Text agar nol depan/nomor panjang tetap aman.
- Hak lihat mengikuti financial_reports.view dan hak Unduh XLSX mengikuti purchase_reports.export sehingga user role existing tidak perlu diatur ulang.
- Tidak ada perubahan database, stok, hutang, pembayaran, retur, atau approval.

V2.10.188 - 2026-08-25 - Placeholder Tanda Tangan Pihak Eksternal
---------------------------------------------------------------------
- Invoice Pembelian: kolom tanda tangan Distributor tidak lagi mencetak nama distributor; diganti placeholder (..............................).
- Retur Pembelian: kolom tanda tangan Distributor tidak lagi mencetak nama distributor; diganti placeholder (..............................).
- Surat Jalan Penjualan: kolom tanda tangan Penerima diubah dari (Nama / Stempel) menjadi placeholder (..............................).
- Retur Penjualan: kolom tanda tangan Pelanggan tidak lagi mencetak nama pelanggan; diganti placeholder (..............................).
- Kolom internal Dibuat oleh / Disetujui oleh / Petugas Gudang tetap menampilkan nama user sesuai dokumen.
- Fallback print_document.php diselaraskan agar hasil cetak lama tetap menggunakan placeholder yang sama.
- Tidak ada perubahan database, stok, hutang/piutang, retur, approval, atau perhitungan transaksi.

V2.10.187 - 2026-08-25 - Layout Cetak PO, Retur, dan Surat Jalan
-----------------------------------------------------------------
- Purchase Order: setelah Keterangan diberi jarak setara 2 baris sebelum blok tanda tangan; dari label Diorder oleh ke nama diberi ruang setara 3 baris.
- Retur Pembelian ukuran 8,5 x 5,5 inch dibatasi maksimal 7 item aktual per halaman dan tetap multipage tanpa baris filler.
- Retur Pembelian A4 Portrait menggunakan tabel full/dinamis seperti Faktur Penjualan dengan maksimal 25 item aktual per halaman.
- Retur Pembelian: setelah batas akhir tabel diberi jarak 2 baris sebelum tanda tangan; Dibuat oleh, Disetujui oleh, dan Distributor disejajarkan, dengan ruang 3 baris dari label ke nama.
- Surat Jalan / Detail Barang Keluar ukuran 8,5 x 5,5 inch dibatasi maksimal 7 item aktual per halaman; A4 Portrait menggunakan tabel full/dinamis maksimal 25 item aktual per halaman.
- Surat Jalan: blok tanda tangan diberi jarak 2 baris dari area akhir tabel/keterangan; Keterangan dokumen yang kosong tidak lagi mencetak tanda '-'.
- Retur Penjualan ukuran 8,5 x 5,5 inch dibatasi maksimal 7 item aktual per halaman dan A4 Portrait menggunakan tabel full/dinamis maksimal 25 item aktual per halaman.
- Retur Penjualan: setelah batas akhir tabel diberi jarak 2 baris; Dibuat oleh, Disetujui oleh, dan Pelanggan disejajarkan dengan ruang 3 baris dari label ke nama.
- Menambahkan pilihan radio ukuran kertas 8,5 x 5,5 inch / A4 Portrait pada Preview/Cetak Surat Jalan dan Retur Penjualan; Retur Pembelian mempertahankan pilihan kertas yang sudah ada.
- Tidak ada perubahan database, stok, hutang, piutang, retur, approval, atau perhitungan transaksi.

V2.10.186 - 2026-08-24 - Import Excel Penjualan / Barang Keluar
----------------------------------------------------------------
- Menambahkan tombol Import Excel pada modul Penjualan / Barang Keluar menggunakan permission sales.create yang sudah ada, sehingga user role lama tidak perlu diatur ulang.
- Alur import mengikuti Import Distributor: Upload Excel/CSV -> Preview -> pemetaan kolom otomatis/manual -> Import -> hasil berhasil/gagal per Grup Import.
- Mendukung urutan kolom bebas dan header pada baris 1-30. Satu baris Excel mewakili satu item; beberapa baris dengan Grup Import yang sama dibuat menjadi satu Barang Keluar multi-item.
- Kolom wajib: Grup Import, Tanggal Barang Keluar, Pelanggan, Barang, dan Qty. Header transaksi boleh hanya diisi pada baris pertama setiap grup.
- Pelanggan dapat dicocokkan menggunakan NIK/NPWP atau Nama Pelanggan persis; Barang dapat dicocokkan menggunakan Kode Barang atau Nama Barang persis.
- Mendukung Jenis Penjualan FREE-MARKET/KEBUN/GG, No. PO Pelanggan, Keterangan Transaksi, Keterangan Item, Qty/UOM transaksi, Harga, dan Satuan Harga.
- No. Barang Keluar dan No. Surat Jalan boleh kosong untuk generator otomatis; bila diisi diperlakukan sebagai nomor custom bebas maksimal 60 karakter dan tetap wajib unik.
- Harga kosong otomatis memakai Pricelist terbaru barang; Satuan Qty/Harga membaca UOM kecil, UOM besar, KG/GRAM, LITER/ML/CC, dan satuan transaksi lain yang tersedia pada barang.
- Import memvalidasi periode akuntansi, pelanggan/barang aktif, konversi UOM, duplikasi barang per dokumen, stok tersedia, serta total permintaan stok antar-Grup Import dalam satu file.
- Dokumen hasil import dibuat dengan status Menunggu Approval seperti input manual. Stok belum berkurang saat import dan baru dikurangi saat Barang Keluar di-Approve.
- Menambahkan template template_import_penjualan_kolom_bebas.xlsx dengan sheet Penjualan dan Petunjuk; nomor dokumen serta NIK/NPWP menggunakan format Text.
- Tidak ada perubahan struktur database atau SQL.

V2.10.185 - 2026-08-24 - Laporan PO Pending / Stok Belum Diterima
--------------------------------------------------------------------
- Menambahkan Laporan PO Pending untuk memantau Purchase Order Approved yang penerimaan stoknya masih Pending atau Partial.
- Qty diterima pada laporan mengikuti qty yang benar-benar sudah diproses saat Invoice Pembelian Approved; Invoice Draft/Pending belum dianggap sebagai stok diterima.
- Menambahkan Ringkasan per PO: No. PO, tanggal, distributor, status penerimaan, jumlah item pending, nilai PO, estimasi nilai belum diterima, tanggal penerimaan terakhir, dan umur PO.
- Menambahkan Detail Barang Pending: Qty PO, Qty Sudah Diterima, Sisa Belum Diterima, UOM sesuai transaksi/master, nilai sisa, dan status penerimaan item.
- Filter laporan mendukung tanggal PO opsional, distributor, status Belum Diterima/Sebagian Diterima, serta pencarian No. PO/distributor/barang. Default menampilkan seluruh PO terbuka tanpa membatasi tanggal agar PO lama tidak tersembunyi.
- Menambahkan tombol Terima Barang dari laporan bagi user yang memiliki permission purchase_invoices.create.
- Menambahkan Unduh XLSX 3 sheet (Ringkasan, PO Pending, Detail Barang) menggunakan permission purchase_reports.export; No. PO dan Kode Barang disimpan sebagai format Text.
- Menambahkan menu Laporan > Pembelian > PO Pending dan shortcut PO Pending pada halaman Purchase Order bagi user dengan financial_reports.view.
- Tidak ada perubahan database atau SQL.

V2.10.184 - 2026-08-24 - No. Surat Jalan Custom Bebas
--------------------------------------------------------
- Mode Custom pada No. Surat Jalan Penjualan sekarang dapat diisi bebas dan tidak wajib mengikuti pola nomor otomatis.
- Nomor custom tetap dibatasi maksimal 60 karakter, menolak karakter kontrol, dan wajib unik agar tidak terjadi duplikasi dokumen.
- Nomor custom kosong atau hanya 0 tetap dialihkan ke generator otomatis agar Surat Jalan operasional tidak memiliki nomor kosong.
- Format nomor Otomatis tetap tidak berubah: FREE-MARKET memakai 001/ST/SP/VIII/2026, GG memakai 001/ST/SP/GG/VIII/2026, dan KEBUN memakai 001/ST/SP/KBN/VIII/2026 (sesuai bulan, tahun, serta kode perusahaan aktif).
- Nomor Surat Jalan yang sudah tersimpan dikunci apa adanya saat dokumen diedit; perubahan Jenis Penjualan atau tanggal tidak lagi mereformat nomor custom yang sudah tersimpan.
- Generator dan sequence nomor otomatis tetap terpisah dari mode Custom; tidak ada perubahan database atau SQL.

V2.10.183 - 2026-08-24 - Jarak Keterangan dan Tanda Tangan Pelunasan
-----------------------------------------------------------------------
- Pelunasan Pembelian: memberi jarak setara 2 baris setelah Keterangan sebelum blok tanda tangan.
- Pelunasan Penjualan: memberi jarak setara 2 baris setelah Keterangan sebelum blok tanda tangan.
- Label Dibuat oleh dan Disetujui oleh sekarang mempunyai ruang tanda tangan setara 3 baris sebelum nama.
- Posisi dua kolom tanda tangan tetap sejajar dan proporsional pada View, Preview, Printer, dan PDF.
- Tidak ada perubahan database, nominal, hutang, piutang, approval, atau perhitungan transaksi.

V2.10.182 - 2026-08-24 - Changelog Versi Terbaru di Atas
------------------------------------------------------------
- Menyusun ulang changelog.txt dengan urutan versi terbaru di bagian paling atas dan versi paling awal di bagian paling bawah.
- Seluruh 232 entri riwayat V1.0.0 sampai V2.10.181 dipertahankan tanpa menghapus versi yang sudah terdokumentasi.
- Pengurutan menggunakan nomor versi, sehingga V2.10.181 diikuti V2.10.180 dan seterusnya sampai V1.0.0.
- Menetapkan format changelog baru sebagai standar untuk rilis berikutnya: setiap versi baru ditambahkan di bagian paling atas.
- Tidak ada perubahan database, transaksi, stok, hutang, piutang, laporan, atau perhitungan aplikasi.

V2.10.181 - 2026-08-24 - Ringkasan Pelunasan Pembelian/Penjualan
-----------------------------------------------------------------
- Merapikan form, detail, View, Preview, Printer, dan PDF Pelunasan Pembelian menjadi urutan: Nilai Invoice, Pembayaran Sebelumnya, Sisa Hutang Invoice, Jumlah yang Dibayar, Sisa Hutang, dan Status.
- Merapikan Pelunasan Penjualan menjadi urutan: Nilai Invoice, Pembayaran Sebelumnya, Sisa Piutang Invoice, Jumlah yang Dibayar, Sisa Piutang, dan Status.
- Menghapus baris cetak lama yang redundan: Jumlah Sebelum Pembulatan, Pembulatan, Jumlah Pelunasan Ini, Total Dibayar pada Invoice, serta duplikasi Jumlah Dibayar/Jumlah Diterima.
- Pembayaran Sebelumnya dihitung dari pelunasan Approved sebelum transaksi yang sedang dilihat; pembayaran yang sedang dilihat tidak dihitung dua kali.
- Sisa Hutang/Piutang Invoice pada bukti pelunasan merepresentasikan saldo sebelum pembayaran saat ini, sedangkan Sisa Hutang/Piutang merepresentasikan saldo sesudah pembayaran saat ini.
- Saldo efektif pada form Pelunasan Pembelian/Penjualan sekarang memperhitungkan Retur Approved, konsisten dengan pemeriksaan saat approval.
- Draft/Pending pelunasan lain tetap diperhitungkan sebagai reservasi batas maksimum agar tidak terjadi pembayaran ganda; bila ada reservasi lain, form menampilkan informasi saldo maksimum yang masih tersedia.
- Status Lunas/Partial dihitung dari sisa saldo setelah Jumlah yang Dibayar.
- Tidak ada perubahan struktur database, stok, HPP, maupun nomor dokumen.

V2.10.180 - 2026-08-24 - Sembunyikan CSV Laporan Pembelian/Penjualan
---------------------------------------------------------------------
- Menyembunyikan tombol CSV Ringkasan dan CSV Detail Item pada halaman Laporan Pembelian.
- Menyembunyikan tombol CSV Ringkasan dan CSV Detail Item pada halaman Laporan Penjualan.
- Tombol Unduh XLSX menjadi satu-satunya pilihan unduh yang ditampilkan pada kedua laporan utama tersebut.
- Endpoint CSV lama tetap dipertahankan untuk kompatibilitas internal/legacy, tetapi tidak ditampilkan pada antarmuka pengguna.
- Label User Role diperjelas menjadi Unduh Laporan Pembelian (XLSX) dan Unduh Laporan Penjualan (XLSX).
- Permission key tetap menggunakan purchase_reports.export dan sales_reports.export sehingga assignment role lama tetap berlaku.
- Tidak ada perubahan database, transaksi, stok, hutang, piutang, maupun perhitungan laporan.

V2.10.179 - 2026-08-24 - XLSX Laporan Pembelian/Penjualan & Format ID Text
----------------------------------------------------------------------------
- Menambahkan tombol Unduh XLSX pada Laporan Pembelian dan Laporan Penjualan.
- Export XLSX dibuat dengan layout rapi mengikuti pola Valuasi Stok dan terdiri dari 3 sheet: Ringkasan, Invoice, dan Detail Item.
- Sheet Ringkasan menampilkan periode/filter aktif serta total transaksi utama; sheet Invoice berisi satu baris per invoice; sheet Detail Item berisi detail barang dan konversi UOM transaksi.
- Menambahkan format khusus `id_text` pada generator XLSX menggunakan format Excel Text (@) dan inline string.
- Nomor ID/NPWP/NIK, No. Invoice, No. PO, No. SJ, No. Barang Keluar, No. PO Pelanggan, No. Faktur Pajak, dan Kode Barang disimpan sebagai Text agar nol di depan tidak hilang dan nomor panjang tidak berubah menjadi scientific notation.
- Laporan Pembelian XLSX ikut memuat Tanggal Surat Jalan yang ditambahkan pada V2.10.177.
- Hak akses XLSX menggunakan permission existing `purchase_reports.export` dan `sales_reports.export`, sehingga assignment User Role lama tetap berlaku tanpa perlu membuat permission baru.
- Tombol XLSX hanya tampil bagi role yang mempunyai permission export dan endpoint XLSX juga melakukan pemeriksaan permission server-side.
- Tampilan Role & Permission diperjelas menjadi Unduh Laporan Pembelian/Penjualan (CSV/XLSX); dependency ke Lihat Laporan Keuangan tetap dipertahankan.
- Endpoint export_purchase_report_xlsx.php dan export_sales_report_xlsx.php yang sebelumnya hanya redirect ke CSV sekarang menjadi generator XLSX asli.
- Export CSV lama tetap dipertahankan.
- Tidak ada perubahan struktur database, stok, HPP, hutang, piutang, approval, retur, atau perhitungan transaksi.

V2.10.178 - 2026-08-24 - Audit Penuh & Sinkronisasi Backup/Restore
-----------------------------------------------------------------
- Melakukan audit ulang seluruh paket aplikasi setelah V2.10.177, termasuk syntax PHP/JS, include/route file, schema database, setup, dan Backup & Restore.
- Memperbaiki schema canonical Backup/Restore agar mengenali purchase_invoices.delivery_note_date yang ditambahkan pada V2.10.177.
- Menambahkan schema_manifest_v210178.php dan schema_full_manifest_v210178.php sebagai manifest canonical terbaru tanpa menimpa manifest historis lama.
- Backup Database kembali dapat dibuat setelah upgrade Tanggal Surat Jalan V2.10.177; validator tidak lagi menganggap delivery_note_date sebagai kolom tambahan yang tidak sah.
- Pre-Flight dan Restore sekarang memverifikasi full schema terbaru yang sudah mencakup Tanggal Surat Jalan Pembelian.
- Tool Pemeriksaan & Perbaikan Database diperbarui agar dapat menambahkan delivery_note_date bila kolom tersebut belum tersedia.
- Status integritas database tidak lagi memakai angka tabel/kolom/foreign key lama yang hard-coded; jumlah ditampilkan berdasarkan manifest canonical aktif.
- Setup instalasi lengkap diperbaiki agar accounting_period_closures ikut dihitung sebagai tabel wajib; total tabel setup kini sinkron dengan 37 tabel canonical database.sql.
- Data sample 30 hari diperbarui agar Tanggal Surat Jalan Pembelian ikut terisi dengan tanggal transaksi contoh.
- Membersihkan duplikasi assignment permission Restore pada backup_restore.php.
- Tidak mengubah perhitungan stok, HPP, hutang, piutang, retur, approval, pembulatan, atau data transaksi yang sudah ada.

V2.10.177 - 2026-08-24 - Tanggal Surat Jalan pada Detil Pembelian
-----------------------------------------------------------------
- Menambahkan field Tanggal Surat Jalan pada Detil Pembelian / Invoice Pembelian.
- Field menggunakan input tanggal (date) dan dapat diedit selama dokumen masih dalam status yang memang dapat diedit.
- Tanggal Surat Jalan ditampilkan bersama No. Surat Jalan pada detail/view Invoice Pembelian dan pada daftar Detil Pembelian.
- Unduh CSV Invoice Pembelian ditambah kolom Tanggal Surat Jalan agar data ekspor konsisten dengan transaksi.
- Menambahkan kolom database purchase_invoices.delivery_note_date bertipe DATE NULL; data lama tetap valid bila tanggal Surat Jalan belum tersedia.
- Menyediakan upgrade V2.10.177 yang aman dijalankan ulang untuk database instalasi lama.

V2.10.176 - 2026-08-24 - Format Nomor Pelunasan Pembelian BKU
----------------------------------------------------------------
- Mengubah nomor otomatis Pelunasan Pembelian menjadi format `001/BKU/ST/VIII/2026`.
- Struktur nomor: 3 digit nomor urut / BKU / kode perusahaan / bulan Romawi / tahun.
- Nomor urut BKU di-reset setiap bulan dan dipisahkan berdasarkan kode perusahaan.
- Generator tetap memakai row lock `document_sequences` saat Simpan agar aman untuk penggunaan multi-user.
- Preview nomor pada form dan saat tanggal pelunasan berubah memakai format BKU yang sama dengan nomor final.
- Nomor pelunasan lama tetap dipertahankan dan tidak dimigrasikan/diubah.
- Perubahan hanya berlaku untuk Pelunasan Pembelian; format Pelunasan Penjualan tidak diubah.
- Tidak ada perubahan struktur database atau SQL.

V2.10.175 - 2026-08-24 - Rapikan Tanda Tangan Pelunasan Pembelian/Penjualan
--------------------------------------------------------------------------------
- Cetak Pelunasan Pembelian: menghilangkan kolom tanda tangan Penerima.
- Sisa tanda tangan Pelunasan Pembelian menjadi dua kolom: Dibuat oleh dan Disetujui oleh.
- Kedua kolom Pelunasan Pembelian dilebarkan, dipusatkan, diberi jarak seimbang, dan menampilkan nama operator yang sudah tersedia pada transaksi.
- Cetak Pelunasan Penjualan: menghilangkan kolom tanda tangan Pembayar.
- Sisa tanda tangan Pelunasan Penjualan menjadi dua kolom: Dibuat oleh dan Disetujui oleh.
- Kedua kolom Pelunasan Penjualan dilebarkan dan dipusatkan agar sejajar serta proporsional pada View, Preview, Printer, dan PDF.
- Tidak ada perubahan database, nominal pelunasan, hutang, piutang, approval, stok, atau perhitungan transaksi.

V2.10.174 - 2026-08-24 - Master Detil Barang / Stok Lebih Rapat
----------------------------------------------------------------
- Master Detil Barang / Stok sekarang hanya menampilkan barang dengan qty stok lebih dari 0.
- Pencarian tetap dapat dilakukan berdasarkan kode atau nama barang, tetapi hasil dibatasi pada barang yang masih memiliki stok.
- Unduh CSV Detil Barang / Stok disamakan dengan tampilan: hanya mengekspor barang dengan stok lebih dari 0.
- Input Stok Awal dibuat sebagai panel buka/tutup agar halaman lebih hemat ruang tanpa menghilangkan fungsi input.
- Form Input Stok Awal dipadatkan menjadi grid yang lebih rapat pada desktop dan tetap responsif pada layar lebih kecil.
- Header filter, field pencarian, tombol, record count, padding tabel, ukuran teks tabel, dan jarak antarbaris dipadatkan khusus pada detil_barang.php.
- Tinggi area tabel diperbesar saat panel Input Stok Awal ditutup sehingga lebih banyak data stok terlihat tanpa scroll halaman berlebihan.
- Tidak ada perubahan database, perhitungan stok, HPP, transaksi, atau mutasi stok.

V2.10.173 - 2026-08-24 - Hapus Cetak Invoice Pembelian & Susun Ulang Changelog
------------------------------------------------------------------------------
- Menghilangkan tombol Preview / Cetak Invoice dari halaman Detail Invoice Pembelian.
- Menghilangkan pesan yang menawarkan Cetak Invoice Pembelian setelah approval.
- Menonaktifkan endpoint print_invoice_pembelian.php secara server-side agar URL langsung tidak dapat digunakan untuk mencetak Invoice Pembelian.
- Menonaktifkan routing legacy print_document.php?type=purchase_invoice; Invoice Pembelian tetap dapat dilihat sebagai dokumen transaksi pada halaman detail.
- Alur pembelian ditegaskan menjadi: Buat PO -> Approve -> Cetak PO; Terima Barang / Buat Invoice -> Approve -> stok bertambah dan hutang terbentuk; Pelunasan Pembelian -> Approve -> Cetak Pelunasan.
- Menyusun ulang changelog lengkap secara kronologis dari V1.0.0 sampai V2.10.173 dan memasukkan riwayat V2.10.20 Migrasi Invoice Historis yang sebelumnya tidak memiliki header tersendiri.
- Tidak ada perubahan database, stok, HPP, hutang, pembayaran, retur, maupun perhitungan transaksi.

V2.10.172 - Penertiban Alur Approval dan Cetak Pembelian/Penjualan
------------------------------------------------------------------
- Pembelian: Buat PO -> Approve -> Cetak PO; Terima Barang/Buat Invoice -> Approve -> stok bertambah dan hutang terbentuk; Pelunasan Pembelian -> Approve -> Cetak Pelunasan.
- Penjualan: Barang Keluar -> Approve -> Cetak Surat Jalan; Buat Faktur Penjualan -> Approve -> Cetak Faktur Penjualan; Pelunasan Penjualan -> Approve -> Cetak Pelunasan.
- Tombol cetak Surat Jalan, Faktur Penjualan, Pelunasan Pembelian, dan Pelunasan Penjualan hanya tampil setelah status Disetujui.
- URL print langsung juga dikunci server-side, sehingga dokumen Draft/Pending/Rejected tidak dapat dicetak hanya dengan membuka URL print.
- Cetak Surat Jalan juga mensyaratkan stock_processed_at agar dokumen benar-benar sudah melalui proses Barang Keluar.
- Cetak Invoice Pembelian dipertahankan sebagai fasilitas opsional tetapi hanya tersedia setelah invoice disetujui.
- Label aksi diperjelas menjadi Terima Barang / Buat Invoice dan Buat Faktur Penjualan.
- Informasi Alur Dokumen & Cetak ditambahkan pada Pengaturan untuk menjelaskan urutan resmi proses.
- Tidak ada perubahan struktur database, perhitungan stok/HPP, hutang, piutang, retur, maupun pembulatan transaksi.

V2.10.171 - Perataan Tanda Tangan Invoice Penjualan
---------------------------------------------------
- Memperbaiki blok tanda tangan Invoice Penjualan agar kolom Konsumen dan Hormat Kami benar-benar sejajar secara horizontal.
- Kedua kolom sekarang menggunakan ruang tanda tangan yang sama, setara 3 baris teks.
- Label dan tanda nama (..............................) berada pada baseline/garis horizontal yang sama.
- Berlaku konsisten pada View, Preview, Cetak Printer, dan PDF.
- Tidak mengubah pagination, ukuran kertas, nominal, pembulatan transaksi, atau database.

V2.10.170 - Opsi A4 Cetak Invoice Penjualan
-------------------------------------------
- Menambahkan radio button ukuran kertas pada Preview/Cetak Invoice Penjualan: 8,5 x 5,5 inch dan A4 Portrait.
- Ukuran 8,5 x 5,5 inch tetap menjadi default dan tetap maksimal 7 item aktual per halaman.
- Mode A4 memakai tabel langsung/dinamis tanpa baris kosong tambahan, dengan kapasitas maksimal 25 item aktual per halaman sebelum dilanjutkan ke halaman berikutnya.
- Ringkasan, Terbilang, Catatan, dan tanda tangan tetap hanya muncul pada halaman terakhir.
- Font header + item tabel tetap 10pt, baris Pembulatan tetap tidak dicetak, dan jarak Hormat Kami ke tanda tangan tetap 3 baris.
- View, Preview, Printer, dan PDF memakai renderer/CSS serta parameter ukuran kertas yang sama.
- Cetak menggunakan actual size sesuai pilihan kertas; tidak ada perubahan database atau perhitungan transaksi.

V2.10.169 - Invoice Penjualan Maks. 7 Item / Tanpa Pembulatan Cetak / Jarak TTD 3 Baris
---------------------------------------------------------------------------------------
- Membatasi tabel item Invoice Penjualan menjadi maksimal 7 item aktual per halaman.
- Jumlah baris tetap dinamis mengikuti banyaknya item tanpa penambahan baris kosong.
- Menghilangkan baris "Pembulatan" dari ringkasan cetak Invoice Penjualan tanpa mengubah nilai grand total atau logika transaksi.
- Mengubah jarak antara "Hormat Kami," dan garis nama menjadi setara 3 baris teks.
- Font header dan item tabel tetap 10pt.
- Tidak ada perubahan database.

V2.10.168 - Baris Item Invoice Penjualan Dinamis
------------------------------------------------
- Baris tabel item Faktur/Invoice Penjualan sekarang mengikuti jumlah item aktual.
- Baris kosong otomatis sampai 10 baris yang diperkenalkan pada V2.10.167 dihapus.
- Maksimal 10 item aktual per halaman tetap dipertahankan untuk layout multipage.
- Contoh: 6 item hanya mencetak 6 baris; 17 item mencetak 10 baris pada halaman pertama dan 7 baris pada halaman kedua.
- Ringkasan, terbilang, catatan, dan tanda tangan tetap hanya tampil pada halaman terakhir.
- Font tabel item tetap 10pt dan jarak Hormat Kami ke tanda tangan tetap 2 baris.
- View, Preview, Printer, dan PDF tetap memakai renderer/CSS Faktur Penjualan yang sama.
- Tidak ada perubahan database, transaksi, stok, piutang, retur, maupun nominal.

V2.10.167 - Tabel Item Invoice Penjualan 10 Baris
-------------------------------------------------
- Tabel item Faktur/Invoice Penjualan menyediakan tepat 10 slot/baris item pada setiap halaman.
- Jika jumlah barang kurang dari 10, sisa slot otomatis diisi baris kosong hingga total tetap 10 baris.
- Jika jumlah barang lebih dari 10, item otomatis dilanjutkan ke halaman berikutnya dalam kelompok maksimal 10 item per halaman.
- Contoh: 6 item menjadi 6 baris isi + 4 baris kosong; 17 item menjadi 10 baris halaman pertama dan 7 baris isi + 3 baris kosong pada halaman kedua.
- Ringkasan, terbilang, catatan, dan tanda tangan tetap hanya tampil pada halaman terakhir.
- Font header dan baris item tetap 10pt, sedangkan bagian lain tetap mengikuti pengaturan V2.10.166.
- Jarak Hormat Kami ke tanda tangan tetap 2 baris.
- View, Preview, Printer, dan PDF tetap memakai renderer/CSS Faktur Penjualan yang sama.
- Tidak ada perubahan database, transaksi, stok, piutang, retur, maupun nominal.

V2.10.166 - Penyesuaian Cetak Invoice Penjualan
-----------------------------------------------
- Perubahan khusus pada renderer dan CSS Faktur/Invoice Penjualan.
- Font header tabel item dan seluruh baris barang dibuat 10pt agar tabel lebih padat dan rapi pada kertas 8,5 x 5,5 inch.
- Bagian ringkasan, terbilang, metadata, header perusahaan, catatan, dan area tanda tangan tetap mengikuti font dokumen 11pt.
- Jarak antara teks "Hormat Kami," dan tanda tangan "(..............................)" dibuat setara 2 baris.
- Jarak tanda tangan Konsumen tidak diubah.
- Berlaku konsisten pada View, Preview, Cetak Printer, dan Cetak/Simpan PDF karena semuanya menggunakan renderer/CSS yang sama.
- Tidak ada perubahan database, transaksi, stok, piutang, retur, maupun perhitungan nominal.

V2.10.165 - Koreksi Invoice Pembelian & Retur Approved
------------------------------------------------------
- Perbaikan dibatasi pada renderer Invoice Pembelian, CSS Invoice Pembelian, halaman View, dan halaman Preview/Cetak; tidak ada perubahan database, stok, hutang, pembayaran, maupun proses approval retur.
- No. Faktur Pajak dan Tgl. Faktur Pajak dikembalikan ke metadata Invoice Pembelian.
- Nama Dibuat oleh, Disetujui oleh, dan Distributor kembali ditampilkan pada area tanda tangan tanpa menambah bold baru.
- Harga Satuan sekarang mempertahankan satuan harga transaksi (contoh Rp 15.000 / BTL) walaupun Qty memakai satuan berbeda (contoh DUS).
- View dan Preview/Cetak sekarang membawa pilihan ukuran kertas serta mode header yang sama melalui parameter paper/header.
- Perubahan mode header pada Preview memuat ulang renderer agar pagination dihitung ulang, terutama untuk idcom.txt yang lebih panjang.
- Pagination 8,5 x 5,5 inch dan A4 mempertimbangkan jumlah baris header, tambahan metadata Faktur Pajak, jumlah ringkasan, dan panjang Keterangan.
- Highlight Edit Nominal dipastikan hilang pada hasil Printer/PDF; perubahan nominal tetap hanya sementara dan tidak disimpan ke database.
- (-) Retur Pembelian Approved diverifikasi hanya mengambil grand_total retur dengan approval_status=approved dan deleted_at IS NULL. Draft/Pending/Rejected tidak mengurangi invoice.
- Urutan ringkasan dipertahankan konsisten: Total Invoice -> (-) Retur Pembelian Approved -> Nilai Bersih Setelah Retur -> Sudah Dibayar -> Sisa Hutang.
- Nilai Bersih Setelah Retur dihitung dari Total Invoice dikurangi grand_total seluruh Retur Pembelian Approved, konsisten dengan perhitungan hutang aplikasi.

V2.10.164 - Print Dokumen Pembelian Khusus
------------------------------------------
- Invoice Pembelian dipisahkan dari print_document.php ke print_invoice_pembelian.php dengan renderer includes/invoice_pembelian_renderer.php dan CSS assets/css/invoice_pembelian.css.
- Pelunasan Pembelian dipisahkan ke print_pelunasan_pembelian.php dengan renderer/CSS khusus.
- Retur Pembelian dipisahkan ke print_retur_pembelian.php dengan renderer/CSS khusus.
- Ketiga dokumen menyediakan ukuran 8,5 x 5,5 inch (default) dan A4 Portrait, actual size tanpa zoom/auto-fit aplikasi.
- Multi-page eksplisit; header, judul, metadata, dan header tabel diulang, sedangkan ringkasan/keterangan/tanda tangan berada di halaman terakhir.
- Pilihan header cetak: Default, idcom.txt, dan Tanpa Header.
- Identitas perusahaan dibuat rata kiri seperti Faktur Penjualan.
- Metadata dirapikan menjadi label : nilai yang sejajar dan konsisten.
- View, Preview, Cetak Printer, dan Cetak/Simpan PDF menggunakan renderer + CSS dokumen yang sama.
- Invoice Pembelian menambahkan Edit Nominal sementara untuk Harga Satuan, Jumlah item, dan ringkasan; perubahan tidak disimpan ke database dan dapat di-reset.
- Bold di dalam dokumen hanya Nama Perusahaan dan judul dokumen masing-masing.
- URL legacy print_document.php untuk purchase_invoice, purchase_payment, dan purchase_return tetap kompatibel melalui redirect.
- Tidak ada perubahan database maupun data transaksi.

V2.10.163 - 2026-08-23
----------------------
- Purchase Order: posisi "Diorder oleh" dipindahkan setelah Keterangan dan ditempatkan di sisi kanan.
- Identitas perusahaan pada PO diberi garis dua (double line) di bagian bawah.
- Ditambahkan jarak sekitar satu baris antara identitas perusahaan/garis dua dan judul PURCHASE ORDER.
- Layout berlaku konsisten pada View, Preview, Cetak Printer, dan Cetak PDF melalui renderer/CSS PO khusus yang sama.
- Pagination half-form 8,5 x 5,5 inch disesuaikan agar area Keterangan + Diorder oleh tetap muat pada halaman terakhir.
- Tidak ada perubahan database maupun data transaksi.

V2.10.162 - Default Kertas PO 8,5 x 5,5 Inch
--------------------------------------------
- Purchase Order menambahkan pilihan ukuran kertas 8,5 x 5,5 inch dan A4 Portrait.
- Ukuran default PO diubah menjadi 8,5 x 5,5 inch actual size; A4 Portrait tetap tersedia sebagai opsi.
- View, Preview, Cetak Printer, dan Cetak/Simpan PDF memakai pilihan ukuran dan renderer/CSS PO yang sama.
- Pagination PO dihitung ulang sesuai ukuran kertas: kapasitas halaman half-form lebih kecil dan halaman terakhir tetap menyisakan ruang untuk Keterangan serta Diorder oleh.
- Header Default/idcom.txt tetap rata tengah dan pilihan header tidak berubah.
- Tidak ada perubahan database atau transaksi.

V2.10.161 - Print Purchase Order Khusus
---------------------------------------
- Purchase Order dipisahkan dari print_document.php menjadi print_po.php.
- Dibuat includes/po_renderer.php dan assets/css/po.css khusus Purchase Order.
- View, Preview, Cetak Printer, dan Cetak/Simpan PDF memakai renderer + CSS PO yang sama.
- Ukuran fisik PO dikunci A4 Portrait actual size 210 x 297 mm tanpa zoom/auto-fit aplikasi.
- Multi-page eksplisit: header perusahaan, judul, metadata, dan header tabel diulang; Keterangan dan Diorder oleh hanya di halaman terakhir.
- Pilihan header cetak: Default, idcom.txt, dan Tanpa Header.
- Informasi perusahaan Default/idcom.txt dibuat rata tengah.
- Metadata PO dirapikan menjadi label : nilai yang sejajar dan konsisten.
- Bold di dokumen hanya Nama Perusahaan dan PURCHASE ORDER.
- URL legacy print_document.php?type=purchase_order tetap kompatibel melalui redirect ke print_po.php.
- Tidak ada perubahan database atau transaksi.

V2.10.160 - Backup/Restore Hardening
------------------------------------
- Kompatibilitas Restore sekarang ditentukan dari FULL SCHEMA fingerprint, bukan rentang nomor versi. Backup lama dengan versi berbeda tetap dapat direstore tanpa override bila seluruh CREATE TABLE identik dengan schema canonical.
- Verifikasi schema diperluas ke type/ENUM, NULL/NOT NULL, DEFAULT, AUTO_INCREMENT/ON UPDATE, PRIMARY/UNIQUE/index, FOREIGN KEY + ON DELETE/UPDATE, engine, charset, dan collation.
- Backup baru menulis SCHEMA-FINGERPRINT-MODE full-v2 serta legacy fingerprint untuk kompatibilitas audit backup lama.
- Restore menolak multi-statement tersembunyi di dalam satu marker SQL; PDO MySQL juga dikonfigurasi dengan MYSQL_ATTR_MULTI_STATEMENTS=false bila tersedia.
- Restore Maintenance Lock dipindahkan dari storage/ ke storage/private/ dan dilindungi .htaccess.
- config/app.php di-hardening ke permission 0640 pada server Unix/cPanel; paket Full juga membawa mode file 0640.
- VERSION.txt tidak lagi fallback diam-diam ke 2.10.109 pada engine Backup/Restore; file versi yang hilang/tidak valid akan memblokir Backup/Restore agar metadata tidak salah.
- Tidak ada perubahan struktur database atau data transaksi.

V2.10.159 - Tabel Retur Penjualan Menyerupai Faktur Penjualan
-------------------------------------------------------------
- Tabel Retur Penjualan diubah menjadi 5 kolom: Banyaknya, Satuan, Nama Barang, Harga Satuan, dan Jumlah.
- Proporsi kolom, tinggi baris, padding, alignment, dan border mengikuti pola tabel Faktur Penjualan.
- Kolom No dan Kemasan terpisah dihilangkan; Qty dan satuan ditampilkan seperti Faktur Penjualan berdasarkan UOM transaksi retur.
- Harga Satuan dihitung dari nilai transaksi retur asal dan ditampilkan terpisah dari satuan.
- Ringkasan Subtotal sampai Nilai Credit Note kembali menyatu di tabel yang sama seperti pola Faktur Penjualan.
- Area kiri ringkasan digunakan untuk Keterangan sehingga tidak ada sel kosong/border kosong.
- Berlaku sama pada View, Preview, Cetak Printer, dan Cetak PDF melalui renderer/CSS Retur Penjualan yang sama.
- Tidak ada perubahan database, stok, HPP, nilai retur, credit note, maupun alur approval.

V2.10.158 - 2026-08-23
----------------------
- Retur Penjualan: memperbaiki garis border penutup tabel item agar utuh pada View, Preview, Printer, dan PDF.
- Ringkasan Subtotal sampai Nilai Credit Note tidak lagi menggunakan sel kosong/colspan di tabel item.
- Ringkasan ditempel tepat di bawah dan rata kanan dengan lebar 37%, sehingga batas label sejajar dengan kolom Harga Faktur dan batas nominal sejajar dengan kolom Jumlah.
- Area kosong di sebelah kiri ringkasan tetap tanpa border, sementara tabel item memiliki garis penutup penuh dan stabil saat dicetak.
- Tidak ada perubahan database, stok, HPP, nilai retur, credit note, maupun approval.

V2.10.157 - Border Sel Kosong Ringkasan Retur Penjualan Diperbaiki
------------------------------------------------------------------
- Mengubah model border tabel Retur Penjualan dari border-collapse menjadi border terpisah tanpa jarak agar sel kosong pada area ringkasan tidak mewarisi garis dari sel di sebelahnya.
- Empat kolom kosong di kiri Subtotal sampai Nilai Credit Note sekarang benar-benar tanpa border atas, bawah, kiri, maupun kanan.
- Border hanya tampil pada tabel item serta dua kolom ringkasan yang berisi label dan nominal.
- Berlaku konsisten pada View, Preview, Cetak Printer, dan Cetak/Simpan PDF.
- Tidak ada perubahan database, stok, HPP, nilai retur, credit note, maupun alur approval.

V2.10.156 - Border Kosong Ringkasan Retur Penjualan Dihilangkan
---------------------------------------------------------------
- Border pada empat kolom kosong di baris Subtotal sampai Nilai Credit Note dihilangkan.
- Border hanya dipertahankan pada kolom label ringkasan dan kolom nominal yang berisi data.
- Berlaku konsisten pada View, Preview, Cetak Printer, dan Cetak/Simpan PDF.
- Tidak ada perubahan database, stok, HPP, nilai retur, credit note, maupun alur approval.

V2.10.155 - Ringkasan Retur Penjualan Menyatu dengan Tabel Item
---------------------------------------------------------------
- Subtotal, (-) Alokasi Diskon, DPP Nilai Lain Dibalik, PPN Keluaran Dibalik, dan Nilai Credit Note dipindahkan menjadi baris lanjutan pada tabel item Retur Penjualan yang sama.
- Label ringkasan menggunakan kolom Harga Faktur dan nilai menggunakan kolom Jumlah; empat kolom sebelumnya digabung agar garis tabel menyatu rapi.
- Tabel/kotak ringkasan terpisah di bawah item dihilangkan.
- Keterangan dan tanda tangan tetap berada di bawah tabel pada halaman terakhir.
- Berlaku konsisten pada View, Preview, Cetak Printer, dan Cetak/Simpan PDF karena memakai renderer/CSS Retur Penjualan yang sama.
- Tidak ada perubahan database, stok, HPP, nilai retur, credit note, maupun alur approval.

V2.10.154 - 22 Agustus 2026
---------------------------
- Retur Penjualan dipisahkan dari print_document.php ke print_retur_penjualan.php.
- Menambahkan renderer includes/retur_penjualan_renderer.php dan CSS assets/css/retur_penjualan.css khusus Retur Penjualan.
- View, Preview, Cetak Printer, dan PDF menggunakan renderer/CSS yang sama.
- Actual Size 8,5 x 5,5 inch dan multi-page eksplisit tanpa auto-fit/zoom.
- Header cetak dapat dipilih: Default, idcom.txt, atau Tanpa Header.
- Metadata Retur Penjualan dirapikan menjadi label : nilai yang konsisten.
- Bold hanya Nama Perusahaan dan RETUR PENJUALAN.

V2.10.153 - Jumlah Diterima Menyatu di Tabel Pelunasan Penjualan
----------------------------------------------------------------
- Bagian Jumlah Diterima pada dokumen Pelunasan Penjualan dipindahkan menjadi baris terakhir pada tabel nilai yang sama.
- Lebar kolom, border, tinggi baris, dan alignment Jumlah Diterima sekarang identik dengan tabel Keterangan/Nilai di atasnya.
- Kotak/blok Jumlah Diterima terpisah di bawah tabel dihilangkan.
- Berlaku konsisten pada View, Preview, Cetak Printer, dan Cetak/Simpan PDF karena memakai renderer/CSS Pelunasan Penjualan yang sama.
- Tidak ada perubahan database, nilai transaksi, piutang, maupun alur approval.

V2.10.152 - 2026-08-22
----------------------
- Pelunasan Penjualan: jarak tambahan antara No. Faktur dan Pelanggan dihapus.
- Jarak tambahan antara Tanggal Faktur dan Status juga dihapus.
- Metadata tetap memakai alignment label, titik dua, dan nilai yang rapi/konsisten.
- Berlaku pada View, Preview, Cetak Printer, dan PDF melalui renderer/CSS khusus yang sama.
- Tidak ada perubahan database.

V2.10.151 - 2026-08-22
----------------------
- Pelunasan Penjualan: metadata cetak dirapikan dengan jarak visual antara No. Faktur dan Pelanggan.
- Baris Status pada kolom kanan diberi jarak yang sama agar kedua kolom metadata tetap sejajar.
- Berlaku konsisten pada View, Preview, Cetak Printer, dan PDF melalui CSS/renderer Pelunasan Penjualan yang sama.
- Tidak ada perubahan database.

V2.10.150 - Print Pelunasan Penjualan Terpisah & Actual Size
------------------------------------------------------------
- Pelunasan Penjualan dipisahkan dari print_document.php ke print_pelunasan_penjualan.php.
- View, Preview, Cetak Printer, dan Cetak/Simpan PDF memakai satu renderer khusus includes/pelunasan_penjualan_renderer.php dan satu CSS assets/css/pelunasan_penjualan.css.
- Link Cetak pada daftar dan detail Pelunasan Penjualan langsung memakai print_pelunasan_penjualan.php; URL lama print_document.php?type=sales_payment tetap kompatibel melalui redirect otomatis.
- Pelunasan Penjualan dikunci Actual Size 8.5 x 5.5 inch (215,9 x 139,7 mm), tanpa zoom/transform/auto-fit aplikasi; @page margin 0 dan margin aman berada pada padding internal lembar yang sama dengan View/Preview.
- Multi-page dibuat eksplisit: header perusahaan, metadata, judul, dan header tabel diulang; Jumlah Diterima, Keterangan, dan tanda tangan hanya di halaman terakhir.
- Pilihan Header Cetak: Default, idcom.txt, dan Tanpa Header tersedia langsung di Preview/Cetak.
- Metadata dirapikan menjadi kolom label, tanda (:), dan nilai dengan jarak konsisten pada No. Pelunasan, No. Faktur, Pelanggan, Tanggal Pelunasan, Tanggal Faktur, dan Status.
- Semua isi Pelunasan Penjualan memakai Arial 11pt normal; bold hanya Nama Perusahaan dan judul PELUNASAN PENJUALAN.
- Tabel nilai memakai proporsi Keterangan 66% dan Nilai 34%, numeric alignment rata kanan, border seragam, dan pagination aman untuk actual size.
- Tidak ada perubahan database, nilai transaksi, piutang, maupun alur approval.

V2.10.149 - Spasi Metadata Surat Jalan
--------------------------------------
- Merapikan jarak antara label metadata, tanda titik dua (:), dan nilainya pada Surat Jalan.
- No. Surat Jalan tidak lagi terlihat terlalu rapat dengan tanda (:).
- Jarak yang sama diterapkan konsisten pada No. Barang Keluar, No. PO Pelanggan, Tanggal, Pelanggan, Jenis Penjualan, dan Alamat.
- Berlaku sama pada View, Preview, Cetak Printer, dan PDF melalui CSS/renderer khusus Surat Jalan.
- Tidak ada perubahan database, stok, nilai transaksi, maupun alur approval.

V2.10.148 - Jarak Keterangan & Tanda Tangan Surat Jalan
-------------------------------------------------------
- Ditambahkan jarak satu baris/spasi antara bagian Keterangan dan area tanda tangan Surat Jalan.
- Jarak diterapkan dari CSS/renderer Surat Jalan yang sama sehingga View, Preview, Cetak Printer, dan PDF tetap konsisten.
- Kapasitas item halaman terakhir disesuaikan agar tambahan jarak tidak menyebabkan overflow pada actual size 8.5 x 5.5 inch.
- Tidak ada perubahan database, stok, nilai transaksi, maupun alur approval.

V2.10.147 - Print Surat Jalan Terpisah & Actual Size
----------------------------------------------------
- Surat Jalan dipisahkan dari print_document.php ke print_surat_jalan.php.
- View, Preview, Cetak Printer, dan Cetak/Simpan PDF memakai satu renderer khusus includes/surat_jalan_renderer.php dan satu CSS assets/css/surat_jalan.css.
- print_document.php?type=sale tetap kompatibel dan otomatis diarahkan ke print_surat_jalan.php.
- Surat Jalan dikunci Actual Size 8.5 x 5.5 inch (215,9 x 139,7 mm), tanpa zoom/transform/auto-fit aplikasi; @page margin 0 dan margin aman berada di padding internal lembar yang sama dengan View/Preview.
- Multi-page dibuat eksplisit: header perusahaan, metadata, judul, dan header tabel diulang; Keterangan dan tanda tangan hanya di halaman terakhir.
- Pilihan Header Cetak: Default, idcom.txt, dan Tanpa Header tersedia langsung di Preview/Cetak.
- Semua isi Surat Jalan memakai Arial 11pt normal; bold hanya Nama Perusahaan dan judul SURAT JALAN.
- Tabel Surat Jalan dirapikan: No 7%, Nama Produk 35%, Kemasan 15%, Qty 18%, Keterangan 25%; wrapping nama/keterangan ikut diperhitungkan dalam pagination.
- Tidak ada perubahan database, stok, nilai transaksi, maupun alur approval.

V2.10.146
--------------------
- Faktur Penjualan: pilihan Header Cetak Default / idcom.txt / Tanpa Header pada print_faktur_penjualan.php.
- idcom.txt dibaca server-side maksimal 16 KB; akses HTTP langsung tetap diblokir .htaccess.
- Faktur Penjualan: Harga Satuan, Jumlah item, Subtotal, Discount, DPP Nilai Lain, PPN, Pembulatan, dan Total dapat diedit sementara di Preview sebelum cetak/PDF.
- Edit nominal tidak menjalankan INSERT/UPDATE dan tidak menyimpan perubahan ke database; Reset Nominal mengembalikan nilai asli.
- Jika Total Jumlah diedit, Terbilang pada halaman aktif ikut disesuaikan hanya untuk hasil cetak.

V2.10.145 - Font 11pt & Tabel Faktur Penjualan Normal
-----------------------------------------------------
- Seluruh isi Faktur Penjualan diseragamkan menjadi Arial 11pt pada View, Preview, Cetak Printer, dan Cetak/Simpan PDF.
- Hanya Nama Perusahaan dan judul FAKTUR PENJUALAN yang dicetak bold.
- Header tabel, metadata pelanggan, No Faktur, Nama Barang, Terbilang, ringkasan nominal, catatan, nomor halaman, Konsumen, dan Hormat Kami dicetak normal (tidak bold).
- Proporsi tabel dirapikan untuk 11pt: Banyaknya 12%, Satuan 11%, Nama Barang 34%, Harga Satuan 22%, Jumlah 21%.
- Tinggi baris dan padding tabel dipadatkan secara proporsional tanpa auto-scale/zoom; actual size 8.5 x 5.5 inch tetap dipertahankan.
- Pagination disesuaikan untuk font 11pt: halaman biasa berbobot maksimum 12 baris dan halaman terakhir maksimum 6 baris agar summary/tanda tangan tetap muat.
- View, Preview, Printer, dan PDF tetap memakai renderer dan CSS khusus Faktur Penjualan yang sama.
- Tidak ada perubahan database atau nilai transaksi.

V2.10.144 - Font 12pt & Perapihan Tabel Faktur Penjualan
--------------------------------------------------------
- Seluruh teks isi Faktur Penjualan diseragamkan menjadi Arial 12pt pada View, Preview, Cetak Printer, dan Cetak/Simpan PDF.
- Nama perusahaan, identitas perusahaan, judul, metadata pelanggan, No Faktur, tabel, Terbilang, ringkasan nominal, catatan, nomor halaman, dan tanda tangan semuanya 12pt.
- Tabel disusun ulang untuk font 12pt: Banyaknya 13%, Satuan 11%, Nama Barang 30%, Harga Satuan 24%, Jumlah 22%.
- Tinggi/padding baris, border, numeric alignment, dan wrapping Nama Barang dirapikan agar Actual Size 8.5 x 5.5 inch tetap stabil.
- Pagination dihitung ulang untuk font 12pt: halaman biasa maksimum berbobot 10 baris dan halaman terakhir maksimum berbobot 5 baris agar summary/tanda tangan tidak terpotong.
- Nama barang tetap font normal (tidak bold). Tidak ada auto-scale/zoom; View, Preview, Printer, dan PDF tetap memakai renderer/CSS khusus yang sama.
- Tidak ada perubahan database atau nilai transaksi.

V2.10.143 - Print Faktur Penjualan Terpisah & Actual Size
---------------------------------------------------------
- Faktur Penjualan dipisahkan dari print_document.php ke print_faktur_penjualan.php.
- View, Preview, Printer, dan PDF memakai satu renderer khusus includes/faktur_penjualan_renderer.php dan satu CSS assets/css/faktur_penjualan.css.
- CSS legacy print.css tidak lagi dimuat pada Preview/Printer/PDF Faktur Penjualan sehingga tidak dapat menimpa ukuran, border, font, atau posisi.
- No: Faktur dibuat satu baris flex, rata kanan, colon dan nomor sejajar.
- Multi-page memakai ukuran fisik 8.5 x 5.5 inch, page break eksplisit, header diulang, dan summary/tanda tangan hanya di halaman terakhir.
- Actual size tanpa zoom/transform/fit; @page 8.5in 5.5in margin 0 dan margin aman berada pada padding internal lembar yang sama dengan View/Preview.
- print_document.php?type=sales_invoice tetap kompatibel dengan redirect otomatis ke print_faktur_penjualan.php.
- Tidak ada perubahan database atau nilai transaksi.

V2.10.142 - Faktur Penjualan WYSIWYG Printer/PDF
------------------------------------------------
- Printer/PDF Faktur Penjualan Continuous 8.5 x 5.5 memakai ukuran lembar 215,9 x 139,7 mm yang identik dengan View/Preview.
- Margin @page khusus Faktur Penjualan diubah menjadi 0; margin aman printer menjadi padding internal lembar yang sama dengan View/Preview (atas 4,5 mm, kanan/kiri 13 mm, bawah 5 mm).
- Menonaktifkan perbedaan geometri wrapper/zoom/transform khusus saat print.
- Menyamakan ulang font, header, metadata, ukuran tabel, border, terbilang, summary, catatan, dan tanda tangan pada Printer/PDF dengan renderer bersama View/Preview.
- Tidak ada perubahan database atau nilai transaksi.
- Faktur Penjualan pada print_document.php dilepas dari wrapper legacy trade-unified/purchase-reference yang sebelumnya menimpa CSS renderer bersama.
- Preview/Printer/PDF kini memakai host netral sales-invoice-render-host, sama dengan renderer yang dipakai halaman View.

V2.10.141 - Faktur Penjualan Baris Dinamis & Satu Renderer
----------------------------------------------------------
- Baris item Faktur Penjualan sekarang benar-benar dinamis mengikuti jumlah barang; filler/blank row dihilangkan.
- View, Preview, Cetak Printer, dan Cetak/Simpan PDF memakai renderer HTML Faktur Penjualan yang sama.
- Keempat mode memakai stylesheet khusus yang sama sehingga ukuran kolom, border, font, header, terbilang, summary, dan tanda tangan konsisten.
- Preview/View menampilkan lembar fisik 8.5 x 5.5 inch; saat print area isi mengikuti margin @page yang sama.
- Invoice lebih dari 15 item tetap dipaginasi otomatis; header diulang per halaman dan summary hanya berada di halaman terakhir.
- Tidak mengubah database, transaksi, stok, HPP, pajak, atau piutang.

V2.10.140
--------------------
- Faktur Penjualan Continuous 8.5x5.5: pagination eksplisit untuk >15 item.
- Header perusahaan, No Faktur dan header tabel diulang per halaman.
- Menampilkan Halaman X / Y.
- Terbilang, total, catatan dan tanda tangan hanya pada halaman terakhir.
- Tidak ada perubahan database.

V2.10.139 - 2026-08-21
----------------------
- Nama Perusahaan pada Faktur Penjualan dipertahankan 12pt.
- Nama Barang pada Faktur Penjualan tidak lagi dicetak bold; menggunakan font-weight normal.
- Berlaku konsisten pada View, Preview, Cetak Printer, dan Simpan PDF.
- One Sheet Fix 8.5 x 5.5, border, Terbilang, nilai transaksi, dan database tidak diubah.

V2.10.138 - 2026-08-21
----------------------
- Nama perusahaan pada header Faktur Penjualan dibuat 12pt.
- Berlaku pada View, Preview, Cetak, dan Simpan PDF, termasuk mode Continuous 8.5 x 5.5 inch.
- Layout One Sheet V2.10.137, ukuran tabel, Terbilang, tanda tangan, dan perhitungan transaksi tidak diubah.
- Tidak ada perubahan database.

V2.10.137 - 2026-08-21
----------------------
- Faktur Penjualan Continuous 8.5x5.5 diperbaiki agar transaksi normal tidak terdorong ke lembar kedua.
- Slot item minimum khusus 8.5x5.5 menjadi 6 baris (A4/9.5x11 tetap 9).
- Ditambahkan auto-fit tinggi saat Print/PDF hanya bila konten nyata melebihi printable height.
- Layout visual, border, Terbilang, dan format tanda tangan V2.10.135 tetap dipertahankan.
- Tidak ada perubahan database.

V2.10.136 - Kunci Ukuran Cetak Faktur Penjualan 8.5 x 5.5
---------------------------------------------------------
- Mengunci Faktur Penjualan Continuous Half ke ukuran fisik 8.5 x 5.5 inch (215,9 x 139,7 mm) tanpa auto-rotate berdasarkan orientasi A4.
- Memperbaiki overflow Preview: lebar 215,9 mm sekarang memakai box-sizing:border-box sehingga padding kiri/kanan tidak menambah lebar fisik kertas.
- Area isi Preview dan Cetak disamakan: 189,9 mm pada margin kiri/kanan 13 mm.
- Menambahkan pembatas max-width/min-width yang aman pada container dan tabel Faktur Penjualan agar tidak melewati printable width.
- Grid header/meta dibuat min-width:0 dan teks panjang dapat wrap sehingga tidak memaksa halaman melebar.
- Tidak mengubah font, tinggi baris, jumlah baris kosong, susunan tabel, Terbilang, tanda tangan, nilai transaksi, maupun database dari V2.10.135.

V2.10.135 - Kembalikan Garis Atas Terbilang Faktur Penjualan
------------------------------------------------------------
- Mengembalikan garis/border hanya pada sisi atas area Terbilang Faktur Penjualan.
- Sisi kiri dan bawah area Terbilang tetap tanpa border.
- Garis sisi kanan tetap dipertahankan sebagai pemisah dengan tabel ringkasan nominal.
- Format "Terbilang: ..." tetap otomatis mengikuti Grand Total invoice.
- Berlaku pada View, Preview, Cetak, dan Simpan PDF.
- Tidak ada perubahan database, transaksi, stok, HPP, pajak, atau piutang.

V2.10.134 - Hilangkan Border Terbilang Faktur Penjualan
-------------------------------------------------------
- Menghilangkan garis/border yang masih dapat terlihat pada area Terbilang akibat mekanisme border-collapse tabel.
- Area Terbilang tetap menampilkan format "Terbilang: ..." dan tetap tanpa kotak pada sisi atas, kiri, dan bawah.
- Garis pemisah di sisi kanan tetap dipertahankan sebagai batas dengan tabel ringkasan nominal.
- Berlaku pada View, Preview, Cetak, dan Simpan PDF.
- Tidak ada perubahan database, transaksi, stok, HPP, pajak, atau piutang.

V2.10.133 - Label Terbilang Faktur Penjualan
--------------------------------------------
- Mengembalikan label "Terbilang:" pada bagian terbilang Faktur Penjualan.
- Nilai setelah label tetap dihitung otomatis dari Grand Total invoice, sehingga selalu menyesuaikan nilai invoice.
- Area terbilang tetap tanpa garis/border; tabel ringkasan nominal di sisi kanan tetap dipertahankan.
- Berlaku pada View, Preview, Cetak, dan Simpan PDF.
- Tidak ada perubahan database, transaksi, stok, HPP, pajak, atau piutang.

V2.10.132 - Tanda Tangan Titik-Titik Faktur Penjualan
-----------------------------------------------------
- Area tanda tangan Faktur Penjualan tidak lagi mencetak nama pelanggan maupun operator.
- Di bawah label Konsumen dan Hormat Kami selalu ditampilkan garis titik dalam tanda kurung: (..............................).
- Ruang tanda tangan tetap dipertahankan pada View, Preview, Cetak, dan Simpan PDF.
- Tidak ada perubahan database, transaksi, stok, HPP, pajak, atau piutang.

V2.10.131 - Perapihan Terbilang Faktur Penjualan
------------------------------------------------
- Menghilangkan label "Terbilang :" sehingga bagian kiri langsung menampilkan kalimat terbilang.
- Menghilangkan seluruh garis/border tabel pada area Terbilang (tiga kolom kiri).
- Tabel ringkasan Jumlah Rp., Discount, DPP Nilai Lain, PPN, Pembulatan, dan Total Jumlah pada dua kolom kanan tetap dipertahankan.
- Berlaku pada View, Preview, Cetak, dan Simpan PDF Faktur Penjualan.
- Tidak ada perubahan database, transaksi, stok, HPP, pajak, atau piutang.

V2.10.130 - Perapihan Alignment Header Faktur Penjualan
-------------------------------------------------------
- Alamat Perusahaan Baris 1, Baris 2, Baris 3, dan Kota pada Faktur Penjualan sekarang dimulai dari posisi kiri yang sama.
- Menghilangkan efek center/flex alignment pada baris alamat yang membuat baris lebih pendek terlihat bergeser ke kanan.
- Berlaku pada View, Preview, Cetak, dan Simpan PDF Faktur Penjualan.
- Tidak ada perubahan database, transaksi, stok, HPP, pajak, atau piutang.

V2.10.129 - Revisi Faktur Penjualan Header Kiri & Summary Menyatu
-----------------------------------------------------------------
- Header identitas perusahaan Faktur Penjualan dibuat rata kiri seperti referensi fisik.
- Menghilangkan garis horizontal/double line di atas judul FAKTUR PENJUALAN.
- Ringkasan Jumlah Rp., Discount, DPP Nilai Lain, PPN, Pembulatan, dan Total Jumlah tidak lagi berupa tabel terpisah.
- Ringkasan nilai menjadi kelanjutan dari tabel item pada kolom Harga Satuan dan Jumlah.
- Area Terbilang digabung pada tiga kolom kiri tabel sehingga keseluruhan bagian bawah menjadi satu tabel utuh.
- Catatan "Barang yang sudah dibeli tidak dapat ditukar/dikembalikan." dibuat rata kiri sejajar batas kiri header.
- View/Preview/Cetak/PDF Faktur Penjualan diselaraskan.
- Tidak ada perubahan database, stok, HPP, harga, pajak, piutang, atau proses approval.

V2.10.128 - Revisi Layout Faktur Penjualan Continuous Form
----------------------------------------------------------
- Mengubah View/Preview/Cetak/PDF Faktur Penjualan mengikuti contoh faktur fisik continuous form.
- Header menampilkan identitas perusahaan di kiri; pada Faktur Penjualan urutan NPWP ditempatkan setelah nama perusahaan lalu alamat/kota.
- Judul FAKTUR PENJUALAN dipusatkan; informasi utama dipadatkan menjadi Tanggal, Nama Konsumen, Alamat, dan No Faktur.
- Tabel barang menjadi 5 kolom: Banyaknya, Satuan, Nama Barang, Harga Satuan, dan Jumlah.
- Harga Satuan menampilkan Rupiah 2 desimal; Jumlah baris dan ringkasan menampilkan Rupiah bulat seperti referensi.
- Menambahkan Terbilang otomatis dari Total Faktur.
- Ringkasan mengikuti referensi: Jumlah Rp., Discount, Dpp Nilai Lain, PPN, Pembulatan bila ada, dan Total Jumlah Rp.
- Menambahkan catatan tetap "Barang yang sudah dibeli tidak dapat ditukar/dikembalikan.".
- Tanda tangan Faktur Penjualan menjadi dua kolom: Konsumen dan Hormat Kami.
- Continuous 8.5 x 5.5 inch tetap menjadi mode kertas default Faktur Penjualan; A4 dan continuous full tetap tersedia.
- Tidak ada perubahan database, stok, HPP, harga transaksi, pajak, piutang, atau proses approval.

V2.10.127 - FORMAT SURAT JALAN BERDASARKAN JENIS PENJUALAN
----------------------------------------------------------
- Input Penjualan FREE-MARKET tetap menggunakan format Surat Jalan NNN/KODE-PERUSAHAAN/SP/BULAN-ROMAWI/TAHUN.
- Input Penjualan GG menggunakan format NNN/KODE-PERUSAHAAN/SP/GG/BULAN-ROMAWI/TAHUN, contoh 001/ST/SP/GG/VIII/2026.
- Input Penjualan KEBUN menggunakan format NNN/KODE-PERUSAHAAN/SP/KBN/BULAN-ROMAWI/TAHUN, contoh 001/ST/SP/KBN/VIII/2026.
- Sequence nomor otomatis dipisahkan per Jenis Penjualan dan per bulan, menggunakan database lock agar aman pada input multi-user.
- Unique key sales.delivery_note_number tetap menjadi pengaman terakhir agar No. Surat Jalan tidak dapat tersimpan ganda.
- Mode Custom untuk GG/KEBUN wajib mengikuti kode jenis, bulan Romawi, dan tahun dari Tanggal Barang Keluar; angka urut dapat dipilih manual selama belum pernah digunakan.
- Preview No. Surat Jalan diperbarui langsung saat Jenis Penjualan atau periode Tanggal Barang Keluar berubah.
- Saat Jenis Penjualan dokumen yang masih editable diubah, No. Surat Jalan diselaraskan ke format seri yang baru.
- Utility Perbaiki No. Surat Jalan ikut menghasilkan format berdasarkan Jenis Penjualan.
- Tidak ada perubahan struktur database.

V2.10.126 - JENIS PENJUALAN FREE-MARKET / KEBUN / GG
----------------------------------------------------
- Revisi V2.10.126: memperbaiki filter Jenis Penjualan pada Laporan Penjualan dan CSV agar FREE-MARKET / KEBUN / GG terbaca konsisten dari kolom ENUM.
- Input Penjualan / Barang Keluar memiliki radio button Jenis Penjualan: FREE-MARKET, KEBUN, dan GG; default FREE-MARKET.
- Menambahkan kolom sales.sales_type dengan default FREE-MARKET; seluruh transaksi lama dinormalisasi menjadi FREE-MARKET.
- Laporan Penjualan menampilkan dan dapat difilter berdasarkan Jenis Penjualan.
- CSV Ringkasan dan CSV Detail Item Laporan Penjualan menambahkan kolom Jenis Penjualan.
- CSV Barang Keluar juga membawa kolom Jenis Penjualan agar data ekspor konsisten.
- XLSX Faktur Pajak per Periode hanya mengambil invoice dengan Jenis Penjualan FREE-MARKET.
- XLSX Faktur Pajak per Invoice tetap dapat dipilih per invoice sesuai hak akses; pembatasan FREE-MARKET hanya berlaku pada export per periode.
- Menambahkan Utility Upgrade Jenis Penjualan V2.10.126 untuk instalasi yang sudah berjalan.
- Revisi paket V2.10.126: No. Surat Jalan kosong atau bernilai 0 tidak lagi dapat tersimpan; nilai kosong dialihkan ke nomor otomatis.
- Generator nomor SJ membaca sequence terbesar yang sudah ada pada bulan yang sama sebelum membuat nomor baru.
- Menambahkan Utility Perbaiki No. Surat Jalan V2.10.126 untuk memperbaiki data lama dan menyinkronkan nomor ke Invoice Penjualan terkait tanpa menaikkan versi aplikasi.
- Hotfix V2.10.126: Migrasi Histori Penjualan menambahkan Jenis Penjualan FREE-MARKET / KEBUN / GG; kosong tetap default FREE-MARKET dan satu invoice wajib konsisten pada semua baris item.
- Template XLSX Migrasi Histori Penjualan ditambah kolom Jenis Penjualan dan dropdown FREE-MARKET / KEBUN / GG.
- XLSX Faktur Pajak per Periode hanya mengambil FREE-MARKET non-historis; invoice hasil Migrasi Historis selalu dikecualikan dari export periode.
- Backup database memakai InnoDB REPEATABLE READ + CONSISTENT SNAPSHOT agar seluruh tabel berasal dari snapshot waktu yang sama.
- Backup baru menyimpan manifest jumlah baris setiap tabel di header SQL untuk verifikasi setelah restore.
- Restore mengaktifkan Maintenance Mode sebelum Safety Backup/DDL sehingga user lain tidak dapat input/approve/import selama proses berlangsung.
- Setelah Restore, schema dan jumlah baris tiap tabel diverifikasi; mismatch memicu rollback otomatis ke Safety Backup. Backup lama tanpa manifest row count tetap didukung dengan warning.

V2.10.125 - VALUASI STOK RETUR MENGIKUTI TRANSAKSI ASAL
-------------------------------------------------------
- Retur Pembelian tidak lagi memakai avg_cost stok pada tanggal retur; nilai persediaan diambil dari mutasi Invoice Pembelian sumber.
- Retur Penjualan mengembalikan HPP berdasarkan mutasi Barang Keluar sumber dan tidak lagi fallback ke avg_cost tanggal retur.
- Retur parsial memakai proporsi nilai sumber; retur terakhir mengambil sisa nilai sumber persis agar tidak ada selisih pembulatan kumulatif.
- Harga rata-rata persediaan setelah Retur Pembelian dihitung ulang dari Nilai Saldo / Qty Saldo.
- Menambahkan tool upgrade_return_stock_valuation_v210125.php untuk menyinkronkan retur Approved lama beserta stock_movements, balance snapshot, product_stocks, dan inventory_value_effect.
- Tool tersebut dapat dibuka langsung dari Pengaturan > Perawatan & Utilitas Sistem; ini revisi paket V2.10.125 dan tidak membuat nomor versi baru.
- Valuasi Stok menampilkan peringatan sampai sinkronisasi retur lama diverifikasi oleh Administrator.
- Tidak mengubah nilai jual/credit note retur, hutang/piutang, Qty retur, atau struktur database.

V2.10.124 - 2026-08-21
----------------------
- CSV Laporan Penjualan dan Pembelian: kolom Nomor ID dipaksa sebagai teks Excel.
- Berlaku pada Unduh CSV Ringkasan dan Detail Item laporan.
- NIK/NPWP 15-16 digit dan nol di depan dipertahankan.
- Tidak ada perubahan database.

V2.10.123 - NILAI RETUR DIKUNCI DARI INVOICE SUMBER
---------------------------------------------------
- Retur Pembelian dan Retur Penjualan tidak membaca pricelist/master harga untuk menentukan nilai retur.
- Nilai item retur berasal dari snapshot Total Harga baris invoice/faktur yang diretur.
- Retur penuh mengambil persis sisa nilai baris invoice; retur sebagian dihitung proporsional terhadap Qty invoice.
- Retur bertahap memakai sisa nilai baris pada retur terakhir untuk mencegah selisih pembulatan.
- Diskon, DPP Nilai Lain, PPN, pembulatan, hutang/piutang, dan credit note tetap mengikuti proporsi invoice sumber.
- Tidak ada perubahan struktur database.

V2.10.122 - Tampilan Error Detail Migrasi Invoice Historis
----------------------------------------------------------
- Menampilkan hasil Preview & Validasi gagal dalam tabel: No., Baris, Kolom/Area, Pesan Error, dan Saran Perbaikan.
- Menampilkan badge jumlah error, 0 data disimpan, dan Import belum dijalankan agar status proses tidak ambigu.
- Jika Kode Barang kosong tetapi Nama Barang cocok persis dengan Master Barang, validasi menyebutkan kode barang yang harus diisi.
- Jika Kode Distributor kosong tetapi Nama Distributor cocok persis dengan Master Distributor, validasi menyebutkan kode distributor yang harus diisi.
- Popup error tetap menampilkan ringkasan error; daftar detail lengkap tersedia pada halaman import.
- Tidak mengubah database, stok, HPP, hutang/piutang, atau logika final import historis.

V2.10.121 - Notifikasi Preview & Validasi Migrasi Invoice Historis
------------------------------------------------------------------
- Preview & Validasi migrasi historis kini mengumpulkan sampai 100 error sekaligus.
- Popup error menampilkan sampai 20 masalah pertama; daftar lengkap tetap tampil di halaman import.
- Error dilengkapi nomor baris dan penyebab: tanggal/cut-off, master, qty/harga, UOM, duplikat, konsistensi invoice, dan pembayaran.
- Preview sukses menampilkan ringkasan hasil validasi dan menegaskan bahwa data belum disimpan.
- Warning validasi ditampilkan terpisah sebelum tombol Import Sekarang.
- Pesan error upload dibuat lebih rinci.
- Tidak ada perubahan struktur database.

V2.10.120 - Perbaikan Nomor ID CSV Ringkasan Pembelian/Penjualan
----------------------------------------------------------------
- CSV Ringkasan Penjualan sekarang memakai formatter Nomor ID khusus agar NIK/NPWP panjang tampil utuh saat dibuka langsung di Excel.
- CSV Ringkasan Pembelian sekarang memakai formatter Nomor ID khusus agar NPWP distributor tampil utuh saat dibuka langsung di Excel.
- Tidak ada perubahan database, transaksi, stok, pajak, maupun perhitungan laporan.

V2.10.119 - Format Nomor ID pada CSV Jual/Beli
----------------------------------------------
- Memperbaiki format Nomor ID pada seluruh CSV Penjualan/Pembelian agar Excel menampilkan seluruh digit NIK/NPWP secara utuh.
- Mencegah Nomor ID 15-16 digit berubah menjadi notasi ilmiah atau kehilangan digit karena batas presisi angka Excel.
- Nol di depan pada Nomor ID tetap dipertahankan saat file CSV dibuka langsung di Excel.
- Perubahan hanya pada format output CSV; data identitas di database tidak berubah.
- Tidak ada perubahan database.

V2.10.118 - Jenis ID & Nomor ID pada Laporan/Unduh Jual Beli
------------------------------------------------------------
- Menambahkan kolom Jenis ID dan Nomor ID pada tampilan Laporan Penjualan dan Laporan Pembelian.
- Menambahkan Jenis ID dan Nomor ID pada CSV Ringkasan dan CSV Detail Item laporan Penjualan/Pembelian.
- Menambahkan Jenis ID dan Nomor ID pada Unduh CSV Barang Keluar, Purchase Order, Invoice Penjualan, dan Invoice Pembelian.
- Data Penjualan mengambil identity_type dan identity_number dari Master Pelanggan.
- Data Pembelian menggunakan Jenis ID NPWP dan Nomor ID dari kolom NPWP Master Distributor.
- Tidak ada perubahan database, stok, harga, pajak, atau alur approval.

V2.10.117 - Perbaikan Tampilan Kolom Kemasan UNIT
-------------------------------------------------
- Mengubah label UOM Coretax UM.0018 pada kolom Kemasan dari "1 UM.0018 - Unit" menjadi "UNIT".
- Perubahan diterapkan melalui helper label kemasan pusat sehingga konsisten pada View/Preview/Cetak dokumen yang memakai kolom Kemasan.
- Kode UM.0018 tetap dipertahankan untuk data dan export Faktur Pajak/Coretax; yang berubah hanya tampilan dokumen.
- Tidak ada perubahan database, Qty, harga, stok, HPP, atau transaksi.

V2.10.116 - Perbaikan Notifikasi Export Faktur Pajak
----------------------------------------------------
- Memperbaiki pesan sukses export Faktur Pajak yang sebelumnya tersimpan sebagai flash session.
- Karena endpoint download XLSX tidak merender layout aplikasi, pesan sukses lama baru muncul saat user membuka menu berikutnya, misalnya Penjualan.
- Export sukses kini langsung mengunduh file tanpa meninggalkan flash notification di session.
- Pesan error export tetap tampil di halaman Faktur Pajak jika proses gagal.
- Tidak ada perubahan database, transaksi, stok, maupun perhitungan Faktur Pajak.

V2.10.115 - Perbaikan Badge Notifikasi Sidebar Pembelian & Penjualan
--------------------------------------------------------------------
- Memisahkan badge sidebar dari lonceng approval.
- Badge parent Pembelian/Penjualan dan badge submenu tampil berdasarkan permission VIEW.
- Staff/Viewer yang dapat membuka modul tetap dapat melihat jumlah dokumen pending.
- Lonceng header tetap dibatasi VIEW + APPROVE sehingga hak approval tidak berubah.
- Query badge lebih kompatibel dengan schema lama dengan pemeriksaan kolom approval_status/deleted_at.
- Tidak ada perubahan database.

V2.10.114 - NORMALISASI SATUAN KHUSUS FAKTUR PAJAK
--------------------------------------------------
- Khusus export XLSX Faktur Pajak/Coretax, ML/CC/Sentimeter Kubik (UM.0011) dinormalisasi menjadi Liter (UM.0007).
- Khusus export XLSX Faktur Pajak/Coretax, Gram (UM.0004) dinormalisasi menjadi Kilogram (UM.0003).
- Kuantitas dibagi 1.000 dan harga satuan disesuaikan berlawanan sehingga Qty x Harga dan nilai rupiah baris tetap sama.
- Normalisasi tetap berlaku untuk jumlah di bawah 1.000, misalnya 500 ML menjadi 0,5 Liter dan 250 Gram menjadi 0,25 Kilogram.
- Menambahkan alias fallback ML/MILILITER/MILLILITER serta G/GR/GM/GRAM pada exporter Faktur Pajak.
- Tidak mengubah Master UOM, Master Barang, transaksi, stok, HPP, pricelist, cetak invoice biasa, maupun struktur database.

V2.10.113 - Perbaikan Badge Pembelian & Penjualan
-------------------------------------------------
- Menambahkan badge total pending approval pada parent sidebar Pembelian dan Penjualan.
- Badge total mengikuti role/permission: hanya modul dengan permission View + Approve yang dihitung.
- Badge per submenu PO/Invoice/Pelunasan/Retur tetap ditampilkan.
- Perhitungan badge parent memakai sumber hitungan yang sama dengan lonceng header agar konsisten.
- Tidak ada perubahan database atau alur approval.

V2.10.112
--------------------
- Menyamakan layout purchase_return_view.php dengan detil_pembelian_view.php: page heading, action bar, card Informasi Retur, detail-list, tabel transaksi 4 kolom, document-summary, pembukuan, dan card approval.
- Menghilangkan kartu statistik lama pada Detail Retur Pembelian agar hierarki tampilannya konsisten dengan Detail Invoice Pembelian.
- Menyamakan sales_return_view.php dengan detil_penjualan_view.php: badan dokumen Penjualan, identitas perusahaan, caption, info dua kolom, tabel 6 kolom, keterangan, summary, tanda tangan, system status, dan card approval.
- Harga retur pada View mengikuti satuan retur yang dipilih (BOTOL/DUS/LITER/ML/KG/GRAM) agar konsisten dengan Qty dan nilai baris.
- Informasi pembukuan retur tetap dipertahankan di luar badan dokumen utama agar fungsi audit tidak hilang.
- Tidak ada perubahan struktur database, stok, HPP, hutang/piutang, credit note, atau proses approval.

V2.10.111
--------------------
- Menghilangkan kartu ringkasan Retur Approved dan kartu summary lain pada halaman daftar Retur Pembelian dan Retur Penjualan agar tampil lebih ringkas.
- Menyamakan struktur halaman Retur Pembelian dengan pembelian.php dan Retur Penjualan dengan penjualan.php: page heading, action bar, shortcut Persetujuan Pending, filter di card-header, tabel transaksi, status, dan tombol Detail.
- Menambahkan jumlah Persetujuan Pending pada action bar sesuai permission approve user.
- Menyederhanakan kolom pembukuan retur menjadi ringkasan Hutang/Piutang Dikurangi serta Kredit Supplier/Pelanggan bila ada.
- Tidak ada perubahan struktur database, stok, HPP, credit note, hutang/piutang, atau proses approval.

V2.10.110
--------------------
- Menyamakan dokumen cetak Retur Pembelian dengan template Faktur Pembelian yang aktif: kop, blok informasi, tabel Nama Produk/Kemasan/Qty/Harga/Jumlah, ringkasan credit note, catatan, dan tanda tangan.
- Menyamakan dokumen cetak Retur Penjualan dengan pola Faktur Penjualan yang aktif dan mempertahankan struktur 6 kolom yang sama.
- Qty retur pada cetak mengikuti satuan yang dipilih pada form retur (BOTOL/DUS/LITER/ML/KG/GRAM sesuai Master Barang).
- Harga Faktur pada retur dihitung ekuivalen terhadap satuan retur yang dipilih agar Qty x Harga tetap konsisten dengan nilai baris/credit note.
- Menghilangkan format generic Kode/Nama Barang pada cetak Retur Pembelian; cetak kini hanya menampilkan Nama Produk seperti dokumen Pembelian/Penjualan aktif.
- Tidak ada perubahan database, stok, HPP, hutang/piutang, atau nilai credit note.

V2.10.109
--------------------
- Menyingkat satuan barang khusus dokumen cetak agar lebih ringkas dan konsisten, antara lain KILOGRAM -> KG, GRAM -> GR, LITER -> L, MILILITER/CC -> ML, BOTOL -> BTL, BUNGKUS -> BKS, KARUNG -> KRG, KALENG -> KLNG, JERIGEN -> JRG, DRUM -> DRM, LEMBAR -> LBR, ROLL -> ROL.
- Singkatan satuan berlaku pada Qty, Harga per Satuan, Kemasan, Preview, Print Preview, Cetak Printer, dan Save/Cetak PDF tanpa mengubah UOM/data transaksi di database.
- Menambah jarak vertikal antara Keterangan/Catatan dan area Tanda Tangan agar dokumen Pembelian/Penjualan lebih lega dan profesional.
- Mode Continuous 8.5x5.5 memakai jarak lebih padat agar tidak mudah pecah halaman.
- Tidak ada perubahan struktur database.

V2.10.108
--------------------
- Menambahkan warning Hutang dengan jendela reminder +30 hari: invoice outstanding yang jatuh tempo dalam 30 hari ke depan atau sudah overdue.
- Menambahkan warning Piutang H-1: faktur outstanding mulai diingatkan 1 hari sebelum jatuh tempo dan tetap aktif jika overdue.
- Kartu Dashboard Sisa Hutang/Piutang menampilkan jumlah dokumen dan nominal yang masuk reminder.
- Icon lonceng header menampilkan Reminder Hutang/Piutang sesuai permission user, terpisah dari notifikasi approval.
- Laporan Hutang/Piutang memiliki filter Reminder dan kolom Warning per dokumen.
- Saldo warning tetap dihitung neto setelah retur approved dan pelunasan approved.
- Tidak ada perubahan struktur database.

V2.10.107
--------------------
- Menghilangkan label UOM kecil seperti BKS/BTL di bawah nama barang pada tabel Valuasi Stok.
- Memperbaiki generator XLSX transaksi/laporan: autoFilter sekarang ditulis sebelum mergeCells sesuai urutan OOXML CT_Worksheet.
- Memperbaiki XLSX Valuasi Stok yang sebelumnya dibuka Excel dengan pesan Repair pada sheet1.xml, sheet2.xml, dan sheet3.xml.
- Menambahkan validasi internal urutan autoFilter/mergeCells agar XLSX rusak yang sama tidak kembali dihasilkan.
- Struktur database tidak berubah.

V2.10.106 - VALUASI STOK RINGKAS + EXPORT XLSX BERBASIS ROLE
------------------------------------------------------------
- Menghilangkan kode barang dari tampilan Valuasi Stok; nama barang hanya didampingi label UOM/satuan isi yang relevan.
- Memperkecil sekitar 30% lebar kolom Qty pada kelompok Stok Awal agar tabel lebih ringkas dan memberi ruang lebih besar untuk nama barang.
- Menambahkan tombol Unduh XLSX pada Valuasi Stok dengan permission baru stock_reports.export.
- Export XLSX terdiri dari 3 sheet: Ringkasan, UOM Kecil, dan Satuan Isi / Volume.
- Sheet UOM Kecil menyajikan Qty numerik dalam UOM kecil Master Barang untuk seluruh mutasi dan stok akhir.
- Sheet Satuan Isi / Volume mengonversi Qty berdasarkan Isi per 1 UOM Kecil dan satuan isi Coretax; ML dinormalisasi ke Liter dan Gram ke Kilogram.
- Barang yang belum memiliki konfigurasi satuan isi tetap tercantum dengan nilai persediaan, tetapi Qty volume dibiarkan kosong dan diberi status Belum dikonfigurasi agar tidak ada konversi tebakan.
- Administrator, Staff, dan Approver mendapat permission export secara default setelah upgrade V2.10.106; Viewer tidak. Role custom dapat diatur melalui Role & Permission.
- Permission stock_reports.export otomatis membutuhkan stock_reports.view saat role disimpan.
- Tidak ada perubahan struktur tabel transaksi, stok, HPP, Moving Average, atau pembukuan.

V2.10.105 - REVISI VALUASI STOK: RETUR DIPISAHKAN
-------------------------------------------------
- Mengubah Laporan Valuasi Stok agar Pembelian, Retur Pembelian, Penjualan/HPP, dan Retur Penjualan ditampilkan sebagai mutasi terpisah.
- Menghilangkan label Pembelian Bersih dan Penjualan/HPP Bersih dari tabel utama karena retur lintas periode dapat membuat Qty/nilai terlihat negatif dan membingungkan.
- Nilai stok akhir tetap memakai rumus persediaan yang sama: Stok Awal + Pembelian - Retur Pembelian - HPP Penjualan + HPP Retur Penjualan +/- Penyesuaian.
- Penyesuaian/Mutasi Lain hanya ditampilkan sebagai kelompok kolom bila terdapat mutasi selain purchase, purchase_return, sale, dan sales_return pada periode.
- Ringkasan menampilkan Pembelian Masuk beserta Retur dan Dampak Neto, serta HPP Penjualan beserta Retur dan HPP Neto.
- Mode Qty Kemasan/UOM dan Satuan Isi/Volume tetap dipertahankan.
- Periode default tetap bulan berjalan dan tetap dapat diubah menjadi periode custom.
- Tidak ada perubahan struktur database, Moving Average, HPP, saldo stok, transaksi, atau pembukuan.

V2.10.104 - PERBAIKAN RESTORE LINTAS SERVER / URUTAN KOLOM
----------------------------------------------------------
- Memperbaiki false failure Backup & Restore ketika database lama memiliki urutan fisik kolom berbeda dari fresh install, walaupun nama kolom sama lengkap.
- Verifikasi schema sekarang membandingkan keberadaan nama kolom (missing/extra) dan tidak lagi menganggap perbedaan urutan kolom sebagai schema rusak.
- Menambahkan informasi column_order_differences untuk audit tanpa memblokir Restore.
- Pre-Flight memvalidasi kolom pada setiap CREATE TABLE di file backup sebelum Restore dijalankan.
- Backup baru dibatalkan jika schema sumber benar-benar kehilangan/menambah kolom canonical; perbedaan urutan fisik tetap diterima.
- Rentang kompatibilitas schema Backup/Restore diperluas V2.10.78 sampai V2.10.104 karena tidak ada perubahan canonical schema pada rentang tersebut.
- File backup V2.10.102 dengan kolom lengkap tetapi urutan berbeda dapat direstore ke V2.10.104 tanpa false rollback.
- Tidak ada ALTER TABLE dan database.sql tidak berubah.

V2.10.103 - Perbaikan Nilai Hutang & Piutang Dashboard
------------------------------------------------------
- Kartu Sisa Hutang tidak lagi menjumlahkan balance_due tersimpan secara langsung.
- Sisa Hutang dihitung ulang dari Invoice Pembelian Approved dikurangi Retur Pembelian Approved dan Pelunasan Pembelian Approved sampai hari ini.
- Kartu Sisa Piutang tidak lagi bergantung pada balance_due/receivable_posted_at tersimpan.
- Sisa Piutang dihitung ulang dari Faktur Penjualan Approved dikurangi Retur Penjualan Approved dan Pelunasan Penjualan Approved sampai hari ini.
- Invoice/Faktur historis yang masih memiliki saldo ikut dihitung sesuai Laporan Hutang/Piutang.
- Kartu mengarah ke Laporan Hutang/Piutang jika user memiliki permission financial_reports.view; fallback tetap ke modul Pelunasan.
- Tidak ada perubahan struktur database.

V2.10.102
--------------------
- Memperbaiki tanda tangan pada print_document modul Penjualan agar benar-benar sejajar.
- Mengganti struktur tanda tangan Penjualan dari CSS Grid menjadi tabel 3 kolom x 3 baris tetap (Label, Ruang Tanda Tangan, Nama).
- Menyamakan geometri tanda tangan pada Preview, Print Preview, Cetak Printer, dan Save/Cetak PDF.
- Menetapkan lebar ketiga kolom tanda tangan sama persis 33,333%.
- Menetapkan tinggi baris label, ruang tanda tangan, dan nama secara konsisten agar baseline tidak bergeser karena nama pelanggan panjang.
- Tetap mempertahankan mode Continuous 8.5x5.5 dengan tinggi tanda tangan yang lebih ringkas.
- Tidak ada perubahan database, transaksi, stok, HPP, retur, piutang, atau pembukuan.

V2.10.101
--------------------
- Menyeragamkan View, Preview, Print Preview, Cetak Printer, dan Save/Cetak PDF pada seluruh dokumen Penjualan.
- Memindahkan identitas perusahaan dan area tanda tangan View ke dalam badan dokumen agar urutannya sama dengan template cetak.
- Menyeragamkan proporsi tabel View dengan Preview/Cetak untuk Surat Jalan, Faktur Penjualan, Retur Penjualan, dan Pelunasan Penjualan.
- Menyeragamkan ukuran caption, metadata, tabel, catatan, dan ringkasan View dengan tipografi template cetak.
- Membuat tanda tangan tiga kolom menggunakan geometri yang sama: gap 10 mm, ruang tanda tangan 16 mm, tinggi minimum 31 mm.
- Menyamakan label Dibuat oleh / Disetujui oleh serta baseline label, ruang tanda tangan, dan nama pada semua mode.
- Status sistem/pembukuan tetap ditampilkan di View tetapi dipisahkan dari badan dokumen agar tidak mengubah hasil visual dokumen cetak.
- Tidak ada perubahan database, transaksi, stok, HPP, retur, piutang, atau pembukuan.

V2.10.100 - HILANGKAN CETAK INVOICE PEMBELIAN PADA INPUT BARANG MASUK / INVOICE
-------------------------------------------------------------------------------
- Menghilangkan tombol Cetak dari daftar Invoice Pembelian / Input Barang Masuk.
- Menghilangkan tombol Cetak Invoice dari halaman Detail Invoice Pembelian.
- Menambahkan guard server-side agar URL print_document.php?type=purchase_invoice tidak dapat digunakan untuk bypass.
- Cetak Purchase Order, Retur Pembelian, Pelunasan Pembelian, dan seluruh dokumen Penjualan tetap tersedia sesuai hak akses/alur masing-masing.
- Tidak ada perubahan database, stok, HPP, hutang, retur, atau pembukuan.

V2.10.99 - TANDA TANGAN PENJUALAN SEJAJAR VIEW / PREVIEW / CETAK / PDF
----------------------------------------------------------------------
- Menyamakan area tanda tangan bagian bawah modul Penjualan antara View, Preview, Print Preview, Cetak Printer, dan Save/Cetak PDF.
- Tiga area tanda tangan sekarang selalu sejajar horizontal dengan lebar yang sama pada desktop.
- Label tanda tangan, ruang tanda tangan, dan nama/stempel memakai tinggi baris yang sama sehingga baseline tidak turun-naik.
- View tidak lagi memakai card/header Tanda Tangan Dokumen yang berbeda dari cetak; tampilannya dibuat langsung seperti area tanda tangan dokumen.
- Pada layar kecil, tiga area tanda tangan tetap sejajar dan dapat digeser horizontal daripada ditumpuk satu per satu.
- Surat Jalan, Faktur Penjualan, Retur Penjualan, dan Pelunasan Penjualan memakai aturan tanda tangan yang sama.
- Tidak mengubah database, transaksi, stok, HPP, retur, piutang, pembukuan, atau nilai dokumen.

V2.10.98 - VIEW / PREVIEW PENJUALAN SESUAI CETAK + RUPIAH TANPA DESIMAL
-----------------------------------------------------------------------
- Menyamakan struktur View modul Penjualan dengan template cetak: Surat Jalan, Faktur Penjualan, Retur Penjualan, dan Pelunasan Penjualan.
- View Surat Jalan memakai tabel No / Nama Produk / Kemasan / Qty / Keterangan seperti cetak.
- View Faktur dan Retur Penjualan memakai tabel No / Nama Produk / Kemasan / Qty / Harga / Jumlah seperti cetak.
- View Pelunasan Penjualan memakai tabel Keterangan / Nilai seperti cetak.
- Menyamakan caption dokumen, blok informasi, catatan, ringkasan, dan area tanda tangan antara View dan Preview.
- Seluruh nominal Rupiah pada View, Preview, Print Preview, Cetak Printer, dan Save PDF modul Penjualan ditampilkan tanpa 2 angka desimal.
- Nilai asli di database dan perhitungan transaksi tetap menggunakan presisi yang tersimpan; perubahan hanya format tampilan dokumen Penjualan.
- Menambahkan helper format Rupiah bulat dan label harga transaksi tanpa desimal tanpa mengubah b_money() global.
- Tidak mengubah database, stok, HPP, retur, piutang, atau pembukuan.

V2.10.97 - CETAK PO SETELAH PERSETUJUAN
---------------------------------------
- Tombol Cetak PO hanya ditampilkan jika Purchase Order berstatus Disetujui/approved.
- PO Draft, Menunggu Persetujuan/Pending, dan Ditolak tidak dapat dicetak.
- Menambahkan guard server-side pada print_document.php agar URL cetak PO langsung tidak dapat digunakan sebelum approval.
- Menambahkan informasi pada Detail PO bahwa cetak tersedia setelah dokumen disetujui.
- Tidak mengubah database, transaksi, stok, HPP, retur, atau pembukuan.

V2.10.96 - RETUR MULTI-SATUAN (DIRECT DARI V2.10.90)
----------------------------------------------------
- Baseline source dikembalikan ke V2.10.90; perubahan V2.10.91 sampai V2.10.95 tidak disertakan.
- Retur Pembelian dan Retur Penjualan memakai engine satuan transaksi yang sama dengan Pembelian/Penjualan.
- Qty retur dapat dipilih per UOM kecil/besar maupun satuan isi/volume/berat yang tersedia, misalnya BOTOL, DUS, LITER, ML, KILOGRAM, dan GRAM.
- Default satuan retur mengikuti satuan Qty pada invoice/faktur sumber bila tersedia.
- Qty input dikonversi ke qty_small sebagai basis stok sebelum disimpan; approval stok, HPP, hutang/piutang, dan credit note tetap konsisten.
- Form retur menampilkan ekuivalen basis stok, batas maksimum pada satuan terpilih, harga ekuivalen, dan estimasi nilai dasar retur.
- Data retur lama dengan qty_unit small/large tetap kompatibel.
- Tidak ada perubahan struktur database dari V2.10.90.

V2.10.90 - NOTIFIKASI LONCENG HEADER SESUAI ROLE & PERMISSION
-------------------------------------------------------------
- Memperbaiki icon lonceng/notifikasi header agar benar-benar mengikuti Role & Permission user, bukan sekadar tampil untuk semua user.
- Lonceng hanya ditampilkan bila user memiliki pasangan permission VIEW + APPROVE pada minimal satu modul approval yang tersedia.
- Administrator/Approver melihat notifikasi sesuai permission aktual; Staff/Viewer tanpa hak approval tidak lagi melihat lonceng approval.
- Custom role hanya melihat badge, total, dan daftar pending dari modul yang benar-benar dapat dilihat dan disetujui oleh role tersebut.
- Menambahkan scope notifikasi untuk PO Pembelian, Invoice Pembelian, Pelunasan Pembelian, Retur Pembelian, Barang Keluar, Faktur Penjualan, Pelunasan Penjualan, dan Retur Penjualan.
- Dropdown notifikasi menampilkan nama role aktif dan jumlah modul approval yang menjadi scope role tersebut.
- Sidebar badge pending tetap menggunakan sumber hitungan yang sama sehingga angka sidebar dan lonceng konsisten per role.
- Memperketat Role Form: Create/Edit/Approve Retur Pembelian dan Retur Penjualan otomatis membutuhkan permission View modul terkait.
- Tidak mengubah struktur database, transaksi, stok, HPP, retur, pembukuan, atau workflow approval.

V2.10.89 - AUDIT & HARDENING BACKUP/RESTORE SAMPAI V2.10.88
-----------------------------------------------------------
- Mengaudit penuh Backup & Restore terhadap schema aplikasi V2.10.88: 37 tabel canonical dan 74 foreign key termasuk Retur Pembelian, Retur Penjualan, serta Tutup Buku Akhir Bulan.
- Backup resmi sekarang hanya mengambil 37 tabel canonical aplikasi; tabel legacy/non-aplikasi pada database yang sama tidak ikut dimasukkan dan dicatat sebagai excluded table.
- Backup dibatalkan bila ada tabel canonical yang hilang agar tidak menghasilkan snapshot yang tampak berhasil tetapi sebenarnya tidak lengkap.
- Menambahkan SCHEMA-FINGERPRINT pada backup baru untuk memverifikasi kesesuaian tabel/kolom/foreign key dengan aplikasi tujuan.
- Memperketat validasi header TABLE-COUNT, daftar tabel duplikat, marker statement, dan target tabel setiap DROP/CREATE/INSERT.
- Setiap tabel declared wajib memiliki tepat satu DROP dan satu CREATE; statement tidak boleh menyentuh tabel di luar header backup.
- Engine Restore mengulang validasi statement secara internal, tidak hanya mengandalkan halaman Pre-Flight.
- Pre-Flight sekarang memeriksa schema database tujuan sebelum Safety Backup dibuat dan menolak restore bila tabel/kolom canonical tujuan belum lengkap.
- Setelah Restore, sistem memverifikasi ulang seluruh 37 tabel dan seluruh kolom canonical; mismatch memicu rollback otomatis dari Safety Backup.
- Versi V2.10.78 sampai V2.10.89 ditandai satu generasi schema sehingga backup V2.10.88 dapat direstore ke V2.10.89 tanpa override beda versi, tetap dengan peringatan dan verifikasi schema penuh.
- Memperbaiki fallback versi Backup/Restore yang masih tertulis 2.10.81 menjadi helper versi aplikasi terkini.
- Mempertahankan parser privilege cPanel V2.10.79 untuk escaped database name dan status permission tidak-terverifikasi.
- Mempertahankan pemeriksaan utf8mb4/utf8mb4_unicode_ci, upload limit, storage permission, ruang disk, password user, konfirmasi RESTORE, serta Safety Backup otomatis.
- Tidak mengubah struktur database aplikasi, transaksi, stok, HPP, retur, tutup buku, atau pembukuan.

V2.10.88
--------------------
- Mengoreksi pendekatan tabel adaptif V2.10.87 yang membuat proporsi kolom berubah-ubah mengikuti isi.
- Mengembalikan tabel View/Preview/Cetak/PDF Pembelian dan Penjualan ke layout kolom stabil per jenis dokumen.
- Teks panjang tetap wrap aman di dalam sel dan tidak melewati border.
- Nama produk/keterangan memperoleh porsi ruang tetap; Qty/Harga/Jumlah tidak mengubah geometri tabel.
- Menambahkan class layout View khusus untuk tabel 4 kolom, 6 kolom operasional, dan 6 kolom retur.
- Menyamakan proporsi Preview, Print Preview, printer, dan Save PDF.
- Database, transaksi, stok, HPP, retur, dan pembukuan tidak berubah.

V2.10.87 - TABEL PEMBELIAN / PENJUALAN ADAPTIF TERHADAP ISI
-----------------------------------------------------------
- Memperbaiki View, Preview, Print Preview, Cetak Printer, dan Save/Cetak PDF pada modul Pembelian dan Penjualan agar teks/isi tidak melewati border tabel.
- Mengubah tabel dokumen transaksi dari layout fixed menjadi content-aware/auto layout; kolom Nama Produk/Deskripsi menerima ruang sisa, sedangkan No/Qty/Nilai tetap rapat.
- Menambahkan safe wrapping untuk nama barang, UOM, harga per satuan, alamat, nomor dokumen, catatan, ringkasan, dan nama tanda tangan.
- Harga yang memuat nama UOM boleh turun baris agar tidak mendorong kolom Jumlah keluar area kertas; nominal total tetap satu baris dengan angka tabular.
- Menyamakan perilaku tabel Pembelian dan Penjualan pada A4, Continuous 8.5x5.5, Continuous 9.5x11, Preview layar, printer, dan PDF.
- Merapikan tabel View Pembelian (PO, Invoice, Retur) agar menggunakan class document-view-table yang sama dengan modul Penjualan.
- Pada layar kecil tabel tetap dapat digeser horizontal tanpa teks menembus border atau merusak layout halaman.
- Template generic seperti Retur Pembelian juga mendapat safe wrapping agar kolom panjang tetap berada di dalam area cetak.
- Tidak mengubah database, transaksi, stok, HPP, retur, pembukuan, permission, atau rumus.

V2.10.86 - KARTU STOK / VALUASI STOK SIDEBAR PARITY
---------------------------------------------------
- Memperbaiki akar penyebab sidebar Valuasi Stok menjadi gelap setelah halaman dibuka.
- `print.js` memang menambahkan class `print-stock-valuation-list` ke body untuk menyiapkan cetak, tetapi V2.10.74 masih memiliki selector screen-level `body.print-stock-valuation-list * { color: #000 !important; }` yang ikut mengubah warna teks/icon sidebar.
- Membatasi tinta/penajaman khusus Valuasi Stok hanya ke konten laporan (ringkasan, periode, tabel, dan formula), tidak lagi ke sidebar atau topbar.
- Kartu Stok dan Valuasi Stok sekarang memakai state sidebar yang sama persis: warna normal, hover, parent aktif, submenu aktif, icon, dot, dan chevron.
- Rule hitam solid untuk printer/PDF tetap dipertahankan di dalam `@media print`, sehingga hasil cetak/PDF tidak berubah.
- Tidak mengubah route, permission, rumus Valuasi Stok, stok/HPP, transaksi, atau database.

V2.10.85 - SIDEBAR SERAGAM TANPA REDUP
--------------------------------------
- Menyatukan state visual seluruh menu sidebar: Dashboard, Master Data, Pembelian, Penjualan, Keuangan, Faktur Pajak, Laporan, Manajemen Sistem, dan Akun.
- State normal memakai warna teks yang sama, hover memakai background gelap yang sama, dan state aktif memakai biru solid yang sama.
- Menghilangkan opacity, filter, shadow, gradient/transparansi khusus, serta transform yang dapat membuat menu tampak redup ketika diklik atau ketika submenu aktif.
- Menyamakan icon, chevron, dot submenu, border, dan warna aktif pada desktop maupun mobile.
- Valuasi Stok tidak lagi memiliki perilaku visual berbeda dari menu lainnya.
- Pengelompokan submenu Laporan tetap dipertahankan hanya sebagai label kategori non-klik.
- Tidak mengubah route, permission, transaksi, laporan, perhitungan stok/HPP, atau database.

V2.10.84 - PERBAIKAN FINAL SIDEBAR LAPORAN / VALUASI STOK
---------------------------------------------------------
- Menghapus override global V2.10.82 pada `.nav-group.active` yang masih tertinggal dan memakai `!important`, sehingga state aktif Laporan/Valuasi Stok tidak lagi memakai style khusus.
- Menghapus sisa selector `nav-submenu-reports` dan `nav-subitem-featured` yang sudah tidak digunakan sejak V2.10.83.
- Mengembalikan parent Laporan dan item Valuasi Stok ke active state standar sidebar yang sama dengan Pembelian, Penjualan, Master Data, dan menu lainnya.
- Menjamin container sidebar/sidebar-nav tetap opacity 100% dan tanpa filter saat halaman laporan aktif.
- Pengelompokan Persediaan/Pembelian/Penjualan/Keuangan tetap dipertahankan.
- Tidak mengubah route, permission, perhitungan Valuasi Stok, transaksi, atau database.

V2.10.83 - SIDEBAR LAPORAN KONSISTEN
------------------------------------
- Menyamakan tampilan submenu Laporan dengan submenu sidebar lainnya.
- Menghapus class khusus/favorit pada Valuasi Stok sehingga Kartu Stok, Valuasi Stok, dan seluruh item laporan memakai style nav-subitem yang sama.
- Mengembalikan tinggi baris, padding, hover, active state, dot indikator, dan lebar fly-out Laporan ke standar sidebar umum.
- Tetap mempertahankan pengelompokan Persediaan, Pembelian, Penjualan, dan Keuangan agar daftar laporan mudah dipindai.
- State aktif parent Laporan tetap menggunakan mekanisme nav-group aktif yang sama dengan menu sidebar lainnya.
- Tidak mengubah route stock_valuation.php, permission stock_reports.view, perhitungan valuasi stok, transaksi, atau database.

V2.10.82 - SIDEBAR ACTIVE STATE TANPA REDUP
-------------------------------------------
- Memperbaiki sidebar yang tampak redup ketika Valuasi Stok atau submenu Laporan aktif.
- Mengganti state aktif parent Laporan dari background biru transparan menjadi biru solid/kontras.
- Menjamin opacity dan filter item aktif tetap 100% sehingga tidak berubah redup setelah halaman reload.
- Mempertegas label, icon, chevron, dot, dan submenu aktif Valuasi Stok tanpa mengubah route atau permission.
- Perbaikan berlaku konsisten pada desktop dan mobile tanpa mengubah database atau perhitungan Valuasi Stok.

V2.10.81 - SIDEBAR LAPORAN / VALUASI STOK
-----------------------------------------
- Merapikan submenu Laporan pada sidebar agar Valuasi Stok lebih mudah ditemukan dan dibaca.
- Mengelompokkan menu Laporan menjadi Persediaan, Pembelian, Penjualan, dan Keuangan.
- Menempatkan Kartu Stok dan Valuasi Stok pada kelompok Persediaan di posisi paling atas.
- Memperjelas state aktif Valuasi Stok dengan indikator aktif yang konsisten pada desktop dan mobile.
- Memperlebar fly-out Laporan pada desktop agar label laporan tidak mudah terpotong.
- Memendekkan label submenu Retur/Pelunasan/Hutang/Piutang karena konteksnya sudah berada di dalam kelompok terkait.
- Menambahkan aria-current pada Kartu Stok/Valuasi Stok ketika aktif untuk navigasi yang lebih jelas.
- Tidak mengubah permission, route, perhitungan valuasi stok, transaksi, atau database.

V2.10.80
--------------------
- Merapikan tampilan Laporan Valuasi Stok agar lebih mudah dibaca pada desktop, tablet, dan mobile.
- Mengubah tabel Valuasi Stok pada layar menjadi content-aware/auto layout sehingga lebar kolom mengikuti isi dan tidak lagi memaksa lebar persentase yang sempit.
- Nama barang dapat membungkus dengan aman, sedangkan Qty dan nominal tetap satu baris agar mudah dibandingkan.
- Memperbaiki judul kelompok Pembelian dan Penjualan/HPP agar tidak melewati batas kolom.
- Menambahkan safe wrapping pada Print/PDF agar teks header tidak keluar atau menabrak kolom.
- Menambahkan indikator periode Bulan Berjalan / Custom.
- Default Laporan Valuasi Stok sekarang selalu membuka periode bulan berjalan (tanggal 1 sampai hari ini).
- Menambahkan tombol Bulan Ini untuk kembali cepat ke periode default.
- Filter tanggal tetap dapat digunakan untuk periode custom tanpa mengubah perhitungan valuasi, HPP, stok, atau database.

V2.10.79 - RESTORE PREFLIGHT CPANEL & UTF8MB4 SETUP
---------------------------------------------------
- Memperbaiki parser SHOW GRANTS agar mengenali database cPanel yang menampilkan underscore/persen sebagai identifier escaped seperti `database\_name`.*.
- Permission Pre-Flight sekarang membedakan privilege yang terdeteksi langsung, privilege yang benar-benar kurang, dan kondisi privilege yang tidak dapat dipastikan karena role/kebijakan hosting.
- Kondisi SHOW GRANTS yang tidak dapat dipastikan menjadi PERINGATAN, bukan false GAGAL; GAGAL hanya diberikan bila scope database/global terdeteksi tetapi privilege wajib SELECT, INSERT, CREATE, DROP, atau REFERENCES memang kurang.
- Detail Pre-Flight menyimpan mode deteksi dan output SHOW GRANTS untuk audit/troubleshooting.
- setup.php otomatis menormalkan DEFAULT database existing menjadi utf8mb4/utf8mb4_unicode_ci sebelum konfigurasi disimpan.
- Setup memverifikasi kembali charset/collation setelah ALTER DATABASE dan menghentikan proses dengan petunjuk cPanel/phpMyAdmin bila privilege ALTER tidak tersedia.
- ALTER DATABASE hanya mengubah default schema dan tidak mengonversi tabel existing secara diam-diam; tabel fresh install/restore tetap dibuat dari schema utf8mb4 aplikasi.
- Tidak mengubah tabel transaksi, stok, HPP, retur, tutup buku, atau struktur database aplikasi.

V2.10.78 - TUTUP BUKU AKHIR BULAN MANUAL
----------------------------------------
- Menambahkan modul Tutup Buku Akhir Bulan manual pada menu Laporan.
- Menambahkan Pre-Flight Check sebelum closing: Draft/Pending transaksi, transaksi stok Approved yang belum diproses, dan saldo stok negatif per akhir periode.
- Menyimpan snapshot akhir bulan: Persediaan, Hutang, Piutang, Pembelian/Retur/Neto, Penjualan/Retur/Neto, HPP, Biaya, PPN Masukan, dan PPN Keluaran.
- Setelah periode ditutup, seluruh transaksi bertanggal sampai akhir periode dikunci dari tambah, edit, hapus, submit, approve, proses stok, retur, pelunasan, TT, edit Faktur Pajak Approved, stok awal/import, dan migrasi historis.
- Pelunasan/retur pada bulan berikutnya terhadap invoice/faktur bulan yang sudah ditutup tetap diperbolehkan selama tanggal transaksi baru berada pada periode terbuka.
- Penutupan dilakukan berurutan. Penutupan pertama boleh memilih bulan awal; setelah itu hanya bulan berikutnya yang dapat ditutup.
- Hanya periode closed terakhir yang dapat dibuka kembali. Buka kembali memerlukan alasan, konfirmasi BUKA PERIODE, dan password user saat ini.
- Tutup buku memerlukan konfirmasi TUTUP BUKU dan password user saat ini.
- Menambahkan permission period_closing.view, period_closing.close, period_closing.reopen; fresh install/upgrade awal memberikan akses hanya kepada Administrator.
- Menambahkan tabel accounting_period_closures dan memasukkannya ke schema canonical, foreign-key audit, serta Backup/Restore.
- Menambahkan upgrade satu klik upgrade_month_end_closing_v21078.php untuk instalasi V2.10.77 yang sudah berjalan.
- Saldo bulan berikutnya tetap merupakan carry-forward alami dari transaksi/mutasi sebelumnya; sistem tidak membuat transaksi stok/hutang/piutang baru saat closing sehingga tidak terjadi saldo ganda.

V2.10.77 - LAPORAN PELUNASAN, HUTANG & PIUTANG
----------------------------------------------
- Menambahkan Laporan Pelunasan Pembelian dengan filter periode, distributor, approval, jenis data operasional/historis, pencarian, ringkasan total, dampak kas, Cetak/PDF, dan CSV.
- Menambahkan Laporan Pelunasan Penjualan dengan filter periode, pelanggan, approval, jenis data operasional/historis, pencarian, ringkasan total, dampak kas, Cetak/PDF, dan CSV.
- Menambahkan Laporan Hutang supplier berbasis posisi per tanggal (as-of), bukan hanya saldo invoice saat ini.
- Laporan Hutang menghitung ulang Nilai Invoice - Retur Pembelian Approved - Pelunasan Approved sampai tanggal laporan = Saldo Hutang.
- Menambahkan aging Hutang: Belum Jatuh Tempo, 1-30 hari, 31-60 hari, 61-90 hari, dan >90 hari serta Kredit Supplier.
- Menambahkan Laporan Piutang pelanggan berbasis posisi per tanggal (as-of).
- Laporan Piutang menghitung ulang Nilai Faktur - Retur Penjualan Approved - Pelunasan Approved sampai tanggal laporan = Saldo Piutang.
- Menambahkan aging Piutang: Belum Jatuh Tempo, 1-30 hari, 31-60 hari, 61-90 hari, dan >90 hari serta Kredit Pelanggan.
- Menambahkan submenu Laporan Pelunasan Pembelian, Laporan Hutang, Laporan Pelunasan Penjualan, dan Laporan Piutang pada menu Laporan.
- Menambahkan shortcut Laporan Pelunasan pada modul Pelunasan Pembelian dan Pelunasan Penjualan bila user memiliki permission Laporan Keuangan.
- Laporan Pelunasan membedakan data Historis/Migrasi dan dampak kas agar pembayaran histori tidak salah dianggap sebagai arus kas operasional.
- Menggunakan permission laporan yang sudah ada; tidak menambah permission atau struktur tabel baru.
- Tidak mengubah database, saldo transaksi, stok, HPP, retur, approval, atau pembukuan yang sudah berjalan.

V2.10.76 - LAPORAN RETUR PEMBELIAN & PENJUALAN
----------------------------------------------
- Menambahkan Laporan Retur Pembelian dengan filter periode, distributor, approval, pencarian, ringkasan credit note, efek stok, pengurangan hutang, dan kredit supplier.
- Menambahkan Laporan Retur Penjualan dengan filter periode, pelanggan, approval, pencarian, ringkasan credit note, HPP/stok kembali, pengurangan piutang, dan kredit pelanggan.
- Menambahkan CSV Ringkasan dan CSV Detail Item untuk laporan retur pembelian/penjualan dengan permission export laporan yang sudah ada.
- Menambahkan tombol Cetak / PDF pada kedua laporan retur dan memakai template laporan landscape yang sama dengan Laporan Pembelian/Penjualan.
- Menambahkan submenu Laporan Retur Pembelian dan Laporan Retur Penjualan pada menu Laporan.
- Menambahkan shortcut Laporan Retur pada halaman daftar Retur Pembelian dan Retur Penjualan.
- Default status laporan retur adalah Approved agar nilai laporan langsung merefleksikan transaksi yang sudah memengaruhi stok dan pembukuan.
- Tidak mengubah schema database, stok, HPP, hutang/piutang, approval, nomor retur, atau transaksi yang sudah ada.

V2.10.75 - PARITY TEMPLATE CETAK MODUL PENJUALAN DENGAN PEMBELIAN
-----------------------------------------------------------------
- Menyamakan keluarga template dokumen Penjualan dengan Pembelian pada View, Preview, Print Preview, printer, dan Save/Cetak PDF.
- Surat Jalan/Barang Keluar, Faktur Penjualan, Pelunasan Penjualan, dan Retur Penjualan kini memakai kop identitas perusahaan, judul, informasi dokumen, tabel barang, catatan/ringkasan, dan area tanda tangan yang konsisten.
- Menetapkan A4 dokumen Penjualan ke orientasi portrait dengan margin fisik yang sama seperti Pembelian saat A4 dipilih; pilihan continuous 8.5x5.5 dan 9.5x11 tetap tersedia.
- Merapikan identitas perusahaan pada halaman View menjadi kop dokumen ringkas: nama perusahaan, alamat baris 1-3, kota, dan NPWP tanpa telepon/fax.
- Menambahkan area tanda tangan pada View Barang Keluar, Faktur Penjualan, Pelunasan Penjualan, dan Retur Penjualan.
- Merapikan kolom tabel Penjualan: Nama Produk, Kemasan, Qty, Harga/Jumlah atau Keterangan sesuai jenis dokumen.
- Menambahkan ringkasan Faktur Penjualan dan Retur Penjualan pada template yang sama, termasuk Retur Approved dan Sisa Piutang bila relevan.
- Memperbaiki query renderer Pelunasan Penjualan agar tanggal invoice ikut diambil sehingga informasi cetak tidak bergantung pada field yang tidak dipilih.
- Menyamakan cache-busting CSS/JS cetak ke V2.10.75 agar browser tidak memakai template V2.10.74 dari cache.
- Tidak mengubah database, struktur tabel, transaksi, stok, HPP, hutang/piutang, retur, Coretax, nomor dokumen, atau alur approval.

V2.10.74 - FONT & BORDER LEBIH TAJAM + PDF TANPA BAYANGAN
---------------------------------------------------------
- Menegaskan warna teks View dan area dokumen cetak agar huruf tampak lebih solid tanpa mengubah ukuran font atau hierarki weight.
- Mempertajam warna border tabel/elemen cetak menjadi hitam solid sambil mempertahankan ketebalan dan struktur border yang sudah ada.
- Menghapus box-shadow, text-shadow, filter, dan efek transparansi dari seluruh area dokumen saat Print Preview, printer, dan Save/Cetak PDF.
- Menghilangkan bayangan halaman pada preview dokumen agar tampilan layar lebih dekat dengan hasil PDF.
- Menyamakan text rendering dan font smoothing pada jalur Preview/Cetak/PDF menggunakan default font Arial/Helvetica V2.10.73.
- Tidak mengubah ukuran kertas, margin, layout, data, transaksi, stok, HPP, retur, pembukuan, atau database.

V2.10.73 - SATU DEFAULT FONT UNTUK SEMUA MODE
---------------------------------------------
- Menetapkan Arial sebagai default font utama dengan fallback Helvetica/sans-serif untuk seluruh aplikasi.
- Menyamakan jenis font pada View, form, tabel, detail dokumen, Preview, Print Preview, printer, Save/Cetak PDF, Valuasi Stok, Retur, laporan, serta field kode/slug.
- Menghapus efek perbedaan font legacy Times New Roman, Courier New, Tahoma, Verdana, Trebuchet, Inter, Calibri/Carlito/Segoe UI dengan mengganti seluruh deklarasi font-family aktif di app.css dan print.css ke satu variabel --jcom-default-font.
- Menambahkan override final yang juga berlaku pada input/select/textarea/button/code/pre sehingga tidak ada komponen yang memakai keluarga font berbeda.
- Ketebalan 500/600/700 dan ukuran font dari V2.10.72 tetap dipertahankan sebagai hierarki visual; yang diseragamkan adalah jenis/kategori font.
- Menyamakan fallback asset version layout/header dan print_document ke V2.10.73 agar browser tidak memakai CSS versi lama.
- Tidak mengubah database, transaksi, stok, HPP, retur, pembukuan, ukuran kertas, margin, atau struktur layout.

V2.10.72 - PENEGASAN FONT + PARITY VIEW / PREVIEW / CETAK / PDF
---------------------------------------------------------------
- Menegaskan teks utama dari bobot Regular 400 menjadi Medium 500 agar huruf lebih jelas pada layar, printer, dan PDF tanpa memperbesar ukuran font.
- Menetapkan hierarki tipografi final yang sama di seluruh jalur: isi 500, label/header tabel 600, judul dan grand total 700.
- Menyamakan font-family, font-weight, ligature, kerning, text-rendering, dan font smoothing antara View, Preview, Print Preview, printer, dan Save/Cetak PDF.
- Menambahkan override @media print paling akhir agar rule cetak legacy tidak lagi menurunkan isi dokumen ke font-weight 400.
- Mempertahankan font stack Calibri/Carlito/Segoe UI/Arial/sans-serif dari V2.10.71.
- Memperbarui fallback asset version layout/header dan print_document ke V2.10.72 agar CSS lama tidak tertahan cache.
- Tidak mengubah ukuran font, ukuran kertas, margin, struktur tabel, database, transaksi, stok, HPP, retur, pembukuan, atau rumus laporan.

V2.10.71 - PENYAMAAN FONT VIEW / PREVIEW / CETAK / PDF
------------------------------------------------------
- Menetapkan satu font stack final Calibri/Carlito/Segoe UI/Arial/sans-serif untuk seluruh tampilan aplikasi.
- Menyamakan font pada View, form, tabel, detail dokumen, Preview, Print Preview, printer, Save/Cetak PDF, dan Valuasi Stok.
- Menghilangkan pengecualian font monospace pada field kode/slug di tampilan agar seluruh teks memakai jenis font yang sama.
- Menempatkan override font final di akhir app.css dan print.css agar rule font legacy Times New Roman, Courier New, Tahoma, Trebuchet, atau Arial tidak dapat menimpa hasil akhir.
- Menyamakan fallback asset version layout/header dan print_document ke V2.10.71 agar browser tidak kembali memakai cache CSS versi lama.
- Tidak mengubah ukuran font, ketebalan, margin, ukuran kertas, struktur layout, database, transaksi, stok, HPP, retur, pembukuan, atau rumus laporan.

V2.10.70 - AUDIT DATABASE/MODUL + BROKEN LINK + GLYPH HARDENING
---------------------------------------------------------------
- Melakukan audit sinkronisasi penuh database.sql dengan schema manifest: 36/36 tabel dan seluruh kolom cocok.
- Melakukan audit foreign key: 72/72 foreign key cocok dengan FK manifest.
- Melakukan audit referensi route/menu/form/AJAX PHP: tidak ditemukan broken link ke file PHP yang hilang.
- Melakukan audit permission literal yang digunakan modul: seluruh permission memiliki definisi pada schema/seed aplikasi.
- Melakukan audit seluruh jenis dokumen cetak: 9/9 type mempunyai handler di print_document.php.
- Melakukan audit query SQL statis terhadap tabel/kolom schema: tidak ditemukan referensi kolom yang tidak tersedia setelah cleanup.
- Membersihkan jalur legacy import_barang.php agar tidak lagi menyusun query ke kolom lama products.content_quantity; V2.10.70 hanya memakai content_quantity_per_small + content_unit sesuai schema aktif.
- Menormalkan asset-version fallback layout_header.php ke V2.10.70 agar cache CSS/JS tidak kembali ke fallback versi lama bila VERSION.txt tidak terbaca.
- Memperkeras font/glyph View, Preview, Print Preview, printer, Save PDF dan Valuasi Stok dengan stack Calibri/Carlito/Segoe UI/Tahoma/Arial yang konsisten.
- Menonaktifkan ligature pada konten bisnis dan menormalkan kerning/letter spacing ringan untuk memperjelas huruf l, I, angka 1 dan karakter |.
- Tidak mengubah struktur database, transaksi, stok, HPP, hutang/piutang, retur, penomoran dokumen, approval, Coretax, atau rumus laporan.

V2.10.69 - RETUR PEMBELIAN & PENJUALAN TERINTEGRASI
---------------------------------------------------
- Menambahkan modul Retur Pembelian berbasis Invoice Pembelian approved dengan alur Draft, Ajukan, Approve, dan Reject.
- Menambahkan modul Retur Penjualan berbasis Faktur Penjualan approved dengan alur Draft, Ajukan, Approve, dan Reject.
- Menambahkan tabel purchase_returns, purchase_return_items, sales_returns, dan sales_return_items agar header, detail barang, nilai credit note, efek stok, serta efek hutang/piutang tersimpan permanen di database.
- Nomor retur otomatis memakai document_sequences dan row lock: Retur Pembelian `001/KODE/RPB/BULAN_ROMAWI/TAHUN`, Retur Penjualan `001/KODE/RPJ/BULAN_ROMAWI/TAHUN`.
- Retur Pembelian approved mengurangi stok berdasarkan HPP moving-average berjalan dan mencatat mutasi `purchase_return`; qty retur tidak boleh melebihi qty invoice maupun stok yang tersedia.
- Retur Penjualan approved menambah stok kembali dan mencatat mutasi `sales_return`; HPP barang kembali memakai unit cost mutasi penjualan sumber bila tersedia agar pembalikan HPP konsisten.
- Mengurangi saldo Hutang/Piutang invoice secara otomatis berdasarkan nilai credit note approved tanpa mengubah grand total invoice sumber untuk menjaga audit trail.
- Bila invoice telah dibayar dan nilai retur melebihi saldo Hutang/Piutang, selisih disimpan sebagai Kredit Supplier atau Kredit Pelanggan; tidak otomatis dianggap kas masuk/keluar.
- Pembayaran baru divalidasi terhadap nilai efektif invoice setelah retur approved sehingga tidak dapat melunasi melebihi saldo bersih setelah credit note.
- Laporan Keuangan menampilkan Penjualan/Pembelian, PPN, HPP, Hutang/Piutang, Kredit Supplier/Pelanggan, dan posisi bersih setelah retur approved.
- Laporan Pembelian/Penjualan menampilkan Grand Total Invoice, Retur Approved, dan Neto Setelah Retur; CSV detail menambahkan Qty Retur Approved serta Qty Bersih per item.
- Laporan Valuasi Stok memperhitungkan purchase_return sebagai stok keluar dan sales_return sebagai stok masuk agar Qty dan Nilai Stok Akhir tetap rekonsiliasi.
- Menambahkan View, Preview/Cetak/PDF credit note Retur Pembelian dan Retur Penjualan serta shortcut Buat Retur dari invoice sumber.
- Draft/Rejected retur dapat dihapus agar Qty yang sebelumnya di-reserve kembali tersedia untuk dokumen retur lain.
- Menambahkan permission view/create/edit/approve untuk Retur Pembelian dan Retur Penjualan, notifikasi approval, menu Pembelian/Penjualan, serta audit trail.
- Retur operasional tidak dapat dibuat dari invoice historis/cut-off/non-stok dan tanggal retur tidak boleh lebih awal dari invoice sumber.
- Menambahkan upgrade_returns_v21069.php untuk instalasi PATCH; FULL V2.10.69 sudah memiliki schema retur pada database.sql.
- Menambahkan tabel retur ke manifest Backup/Restore dan Foreign Key Integrity agar backup/restore lintas server tetap mencakup seluruh data retur.

V2.10.68 - NORMALISASI FONT VIEW / PREVIEW / CETAK / PDF
--------------------------------------------------------
- Menormalkan font pada area konten View agar huruf tipis seperti l, I dan angka 1 lebih mudah dibedakan dari karakter garis vertikal |.
- Menetapkan satu font akhir yang konsisten untuk Preview Dokumen, Print Preview, printer, dan Save PDF sehingga rule lama Times New Roman, Courier New, Tahoma/Verdana, atau Arial tidak lagi saling menimpa pada hasil akhir dokumen.
- Menggunakan font stack Trebuchet MS dengan fallback DejaVu Sans/Arial/Helvetica untuk keterbacaan glyph dan kompatibilitas browser/printer/PDF.
- Menonaktifkan ligature dan font synthesis pada konten dokumen agar bentuk karakter tidak berubah karena substitusi/sintesis browser.
- Menambahkan letter spacing sangat kecil pada tabel/detail untuk mencegah stroke tipis terlihat menyatu dengan border tanpa mengubah ukuran font atau layout dokumen.
- Field teknis seperti slug/kode tetap memakai monospace pada tampilan aplikasi.
- Tidak mengubah ukuran font, ukuran kertas, margin, lebar kolom, transaksi, stok, HPP, database, atau perhitungan dokumen.

V2.10.67 - HASIL CETAK SESUAI PREVIEW LAYAR
-------------------------------------------
- Menyamakan hasil Print Preview, printer, dan Save PDF dengan desain preview dokumen yang terlihat di layar.
- Menetralkan aturan @media print lama yang sebelumnya mengecilkan atau merapatkan header, informasi dokumen, tabel, ringkasan, dan area tanda tangan.
- Menyamakan spacing, border, grid, tinggi area, ketebalan teks, warna netral, dan hierarchy elemen pada Faktur Penjualan, Surat Jalan/Barang Keluar, pelunasan, serta dokumen transaksi terkait.
- Menyamakan kembali template umum/biaya berbasis accurate-inspired agar spacing, border tabel, overview, total, dan tanda tangan mengikuti preview layar.
- Template Pembelian/PO yang sudah memakai parity dipertahankan; keterangan dan area cetak tetap mengikuti layout preview.
- Margin fisik kertas tetap ditangani oleh @page sehingga A4 dan continuous form mempertahankan ukuran kertas yang dipilih tanpa mengubah layout isi.
- Edit Nominal Cetak V2.10.66 tetap bekerja dan nilai edit tetap ikut ke printer/PDF.
- Tidak mengubah database, transaksi, stok, HPP, hutang/piutang, Coretax, atau perhitungan dokumen.

V2.10.66 - EDIT NOMINAL KHUSUS FORM CETAK
-----------------------------------------
- Menambahkan pengecualian format/pembulatan 2 desimal khusus pada Form Cetak melalui fitur Edit Nominal Cetak.
- Nilai transaksi di database tetap mengikuti presisi dan pembulatan sistem; perubahan manual hanya memengaruhi preview, printer, dan Save PDF pada sesi cetak tersebut.
- Nominal Rupiah seperti Harga, Jumlah, Subtotal, PPN, Pembulatan, Total, Sisa Hutang/Piutang dan nilai pembayaran dapat diedit langsung pada preview cetak.
- Menambahkan tombol Reset Nominal untuk mengembalikan seluruh nominal cetak ke nilai asli dari database.
- Qty, tanggal, nomor dokumen, persentase dan data transaksi non-nominal tidak ikut editable.
- Tidak ada perubahan struktur database, HPP, stok, hutang/piutang, approval, Coretax, atau perhitungan transaksi.

V2.10.65 - PERBAIKAN SCROLL MOUSE & KEYBOARD
--------------------------------------------
- Memperbaiki halaman compact-workspace yang sebelumnya dapat terasa tidak bergerak ketika mouse wheel/trackpad digunakan di atas tabel responsive.
- Mengubah overscroll tabel agar hanya menahan gerakan horizontal dan tetap meneruskan scroll vertikal ke area konten utama.
- Menambahkan fallback wheel handler untuk tabel horizontal yang tidak memiliki scroll vertikal sendiri.
- Menambahkan navigasi keyboard Arrow Up/Down, Page Up/Page Down, Home, dan End untuk menggulir page-content pada desktop compact-workspace.
- Navigasi keyboard tidak mengambil alih input, textarea, select, live lookup, menu, atau submenu agar interaksi form tetap normal.
- Berlaku global pada Valuasi Stok dan halaman lain yang menggunakan tabel responsive/compact-workspace.
- Tidak mengubah data, transaksi, perhitungan stok/HPP, database, permission, atau template cetak.

V2.10.64 - NORMALISASI LABEL SATUAN VALUASI STOK
------------------------------------------------
- Menormalkan label Qty mode Satuan Isi pada Laporan Valuasi Stok agar hanya menampilkan nama satuan bisnis tanpa kode teknis Coretax.
- Contoh `200 UM.0003 - KILOGRAM` sekarang tampil sebagai `200 KILOGRAM`.
- Contoh `140 UM.0007 - LITER` sekarang tampil sebagai `140 LITER`.
- Berlaku untuk seluruh kode `UM.0001` sampai `UM.0033` pada Valuasi Stok; kode tetap tersimpan dan tetap dipakai untuk kebutuhan Coretax di belakang layar.
- Mempertahankan normalisasi 1.000 Sentimeter Kubik menjadi 1 Liter dan 1.000 Gram menjadi 1 Kilogram pada mode Satuan Isi.
- Tidak mengubah Qty stok, konversi UOM, HPP, nilai persediaan, transaksi, database, atau ekspor Coretax.

V2.10.63 - PILIHAN QTY KEMASAN / SATUAN ISI PADA VALUASI STOK
-------------------------------------------------------------
- Menambahkan pilihan Tampilan Qty pada Laporan Valuasi Stok: Kemasan/UOM atau Satuan Isi/Volume.
- Mode Kemasan/UOM mempertahankan tampilan ringkas seperti 14 DUS atau 1 DUS / 5 BOTOL.
- Mode Satuan Isi membaca konversi langsung dari Master Barang: small_factor/large_factor, content_quantity_per_small, dan content_unit.
- Contoh barang 1 LITER per botol dengan 10 BOTOL per DUS akan menampilkan 14 DUS sebagai 140 LITER pada mode Satuan Isi.
- Satuan ML/Sentimeter Kubik dinormalisasi ke Liter dan Gram dinormalisasi ke Kilogram untuk tampilan laporan yang konsisten; satuan lain mengikuti Master Barang.
- Harga Rata-rata Stok Awal/Akhir ikut dihitung per satuan tampilan pada mode Satuan Isi agar Qty x Harga Rata-rata tetap konsisten dengan Nilai Persediaan.
- Barang yang belum memiliki konfigurasi Satuan Isi lengkap otomatis fallback ke Kemasan/UOM dan ditandai melalui peringatan ringkas pada layar.
- Pilihan Qty ikut berlaku pada tampilan layar dan hasil cetak/PDF Valuasi Stok.
- Tidak mengubah qty yang tersimpan, stock_movements, HPP moving average, nilai persediaan, transaksi, atau struktur database.

V2.10.62 - PENYEMPURNAAN LAPORAN VALUASI STOK
---------------------------------------------
- Merapikan tampilan Laporan Valuasi Stok agar lebih cepat dibaca pada layar maupun hasil cetak/PDF.
- Menata periode laporan menjadi baris informasi yang lebih jelas dan menampilkan jumlah barang bersaldo.
- Menyederhanakan informasi barang pada tabel menjadi Nama Barang serta Kode · UOM tanpa label teknis yang berulang.
- Memisahkan kelompok Stok Awal, Pembelian, Penjualan/HPP, dan Stok Akhir dengan garis pembatas serta hierarchy header yang lebih jelas.
- Menonjolkan Stok Akhir dan Total Nilai menggunakan latar netral agar saldo akhir lebih mudah ditemukan tanpa warna mencolok.
- Menetapkan lebar kolom melalui colgroup sehingga Qty, Harga Rata-rata, Nilai, dan kolom Barang lebih stabil saat tabel digeser maupun dicetak.
- Menggunakan tabular number pada nilai numerik agar angka antarbaris lebih mudah dibandingkan.
- Merapikan kartu ringkasan Nilai Stok Awal, Pembelian, HPP Penjualan, dan Nilai Stok Akhir menjadi lebih formal dan ringkas.
- Meningkatkan ukuran font tabel cetak Valuasi Stok dari sekitar 5,35 pt menjadi 7 pt serta memperbesar header, ringkasan, dan rumus agar lebih terbaca pada A4 landscape/PDF.
- Mempertahankan rumus valuasi, stok, HPP, data transaksi, filter periode, permission, dan struktur database tanpa perubahan.

V2.10.61 - PENGUNCIAN MODE NOMOR FAKTUR PENJUALAN & SURAT JALAN
---------------------------------------------------------------
- Mempertahankan format V2.10.13 untuk Faktur Penjualan: `001/KODE_PERUSAHAAN/BULAN_ROMAWI/TAHUN`.
- Mempertahankan format V2.10.13 untuk Surat Jalan: `001/KODE_PERUSAHAAN/SP/BULAN_ROMAWI/TAHUN`.
- Menambahkan pilihan eksplisit Otomatis / Custom pada No. Faktur Penjualan dan No. Surat Jalan.
- Mode Otomatis menjadi default; field nomor tampil readonly dan nilai POST diabaikan server sehingga nomor preview/default/draft tidak dapat dianggap custom secara tidak sengaja.
- Mode Custom hanya aktif setelah user memilih Custom; pemeriksaan UNIQUE tetap mencakup seluruh record termasuk soft-delete.
- Preview nomor otomatis tetap mengikuti perubahan bulan/tahun tanggal dokumen tanpa menimpa nomor yang sedang diketik pada mode Custom.
- Memperbaiki draft browser Barang Keluar agar hanya menyimpan/memulihkan No. Surat Jalan bila mode Custom; draft lama tanpa penanda mode dianggap Otomatis.
- Generator otomatis tetap menggunakan `document_sequences`, row lock, company_code, reset bulanan, dan melewati kandidat yang sudah pernah digunakan.
- Nomor internal Barang Keluar/BKO tetap memakai mekanisme sebelumnya dan tidak diubah.
- Tidak mengubah nomor dokumen lama, transaksi, stok, approval, Coretax, maupun struktur database.

V2.10.60 - ROLE FORM RINGKAS
----------------------------
- Meringkas tampilan Tambah/Edit Role agar lebih padat dan cepat digunakan.
- Menghilangkan deskripsi permission dari daftar akses, misalnya teks “Melihat audit trail”.
- Menghilangkan slug permission teknis seperti `activity.view` dari tampilan Role Form.
- Permission sekarang hanya menampilkan nama akses yang mudah dipahami di bawah kelompok modul.
- Pencarian permission hanya berdasarkan nama akses dan modul; slug/deskripsi tetap digunakan internal dan tidak ditampilkan.
- Memadatkan ringkasan role, field konfigurasi, dashboard widget, module header, Permission Manager, dan action bar.
- Menampilkan permission dalam maksimal 3 kolom pada desktop agar halaman lebih pendek tanpa mengurangi fungsi checklist.
- Mempertahankan permission slug, dependency akses, CSRF, audit trail, role system, dashboard widget, serta validasi server-side.
- Tidak mengubah database, transaksi, stok, approval, Coretax, atau template cetak.

V2.10.59 - PENYEMPURNAAN ROLE FORM
----------------------------------
- Merapikan halaman Tambah/Edit Role menjadi form administrasi yang lebih profesional tanpa mengubah mekanisme permission.
- Menambahkan ringkasan Tipe Role, Status, Hak Akses terpilih, dan Widget Dashboard di bagian atas form.
- Memperbesar ruang dan keterbacaan field Nama Role, Slug, Deskripsi, serta Status dengan label, helper, dan hierarchy yang lebih jelas.
- Menampilkan Slug sebagai identitas teknis dengan prefix visual role/ tanpa mengubah nilai slug yang disimpan.
- Menambahkan penghitung karakter deskripsi sebagai bantuan visual tanpa membatasi panjang data yang sebelumnya diperbolehkan.
- Merapikan pilihan Tampilan Dashboard menjadi checkbox-card yang konsisten dan menambahkan counter widget terpilih secara real-time.
- Menyempurnakan Permission Manager dengan toolbar pencarian, preset cepat, ringkasan akses, module header, indikator checkbox, dan state permission terpilih yang lebih jelas.
- Menambahkan ringkasan permission/dashboard real-time pada bagian atas form ketika pilihan diubah.
- Membuat sidebar konfigurasi sticky pada layar desktop dan action bar Simpan lebih tegas, serta tetap responsif pada tablet/mobile.
- Mempertahankan seluruh dependency permission, perlindungan Administrator, dashboard role widgets, CSRF, audit trail, permission slug, dan validasi server-side.
- Tidak mengubah database, tabel role/permission, transaksi, stok, approval, Coretax, maupun template cetak.

V2.10.58 - PENYEMPURNAAN ROLE & PERMISSION
------------------------------------------
- Merapikan Manajemen Sistem > Role & Permission menjadi workspace administrasi yang lebih profesional tanpa mengubah mekanisme hak akses.
- Mengubah daftar role dari kartu besar menjadi ringkasan statistik dan tabel administrasi yang menampilkan status, jumlah user, cakupan permission, tipe Sistem/Custom, dan aksi.
- Menambahkan progress cakupan permission per role agar administrator lebih cepat melihat tingkat akses setiap role.
- Merapikan halaman Tambah/Edit Role menjadi layout dua area: Informasi Role & Dashboard di sisi kiri, Permission Manager di area utama.
- Menambahkan pencarian permission berdasarkan nama, modul, deskripsi, atau slug.
- Menambahkan counter permission terpilih secara real-time dan jumlah permission terpilih per modul.
- Menambahkan Pilih Semua per modul dengan status checked/indeterminate agar pengaturan permission lebih cepat dan mudah diaudit.
- Mempertahankan tombol akses cepat Edit Pembelian, Edit Penjualan, dan Edit Faktur Pajak Approved dalam tampilan yang lebih ringkas.
- Memperjelas perlindungan role Administrator dan role bawaan sistem.
- Merapikan tampilan widget Dashboard per role dan action bar Simpan/Batal.
- Tidak mengubah tabel database, permission slug, dependency permission, validasi server-side, role user, transaksi, stok, atau workflow approval.

V2.10.57 - PENYEMPURNAAN TOMBOL & AKSI SISTEM
---------------------------------------------
- Merapikan tampilan tombol administrasi agar lebih konsisten, ringkas, dan profesional tanpa mengubah fungsi atau permission.
- Mengubah halaman Pengaturan dari deretan tombol panjang menjadi panel Akses Cepat untuk Data Awal Perusahaan, Backup & Restore Data, Akun Sistem, serta Cek & Perbaiki Database.
- Memindahkan tool upgrade/maintenance yang jarang dipakai ke bagian Perawatan & Utilitas Sistem yang dapat dibuka saat diperlukan.
- Menambahkan gaya tombol Warning dan Ghost yang konsisten; aksi destruktif tetap merah, aksi utama tetap biru, dan aksi netral memakai outline/ghost.
- Menghilangkan efek tombol naik saat hover dan shadow berlebihan untuk tampilan administrasi yang lebih formal.
- Merapikan tombol pada Data Awal Perusahaan, Backup & Restore, Akun Sistem, Manajemen User, dan Role & Permission.
- Menambahkan Akun Sistem ke submenu Akun untuk Administrator dan memperjelas label Backup & Restore Data.
- Tidak mengubah database, alur transaksi, permission, stok, HPP, hutang/piutang, atau template cetak.

V2.10.56 - PENYEDERHANAAN TAMPILAN UOM / VOLUME
-----------------------------------------------
- Menghilangkan informasi rantai konversi dari tampilan normal, misalnya "1 DUS = 24 BOTOL = 12 LITER".
- Qty stok pada dashboard, stok awal, valuasi, dan workspace transaksi kini memakai label ringkas; contoh 24 BOTOL yang tepat 1 DUS tampil sebagai "1 DUS", sedangkan sisa kemasan tetap dapat tampil "1 DUS / 5 BOTOL".
- Menghilangkan kolom Konversi UOM dan teks Setara pada View PO, Invoice Pembelian, Barang Keluar/Surat Jalan, dan Invoice Penjualan.
- Menghilangkan kolom Konversi UOM pada Preview/Cetak/Simpan PDF Surat Jalan/Barang Keluar.
- Form PO dan Barang Keluar hanya menampilkan nama UOM kecil/besar tanpa rumus "1 DUS = ..." dan tanpa akumulasi volume/berat di bawah Qty.
- Form Invoice Pembelian/Penjualan tidak lagi menampilkan definisi konversi panjang di bawah nama barang atau ekuivalen Qty UOM kecil.
- Hasil Import Master Barang/Stok Awal tidak lagi menampilkan rantai ekuivalen kemasan/volume pada pesan hasil import.
- Master Data Barang menampilkan UOM Kecil/Besar sebagai nama satuan saja; nilai Isi per UOM Kecil dan Satuan Ukur Coretax tetap tersedia pada kolom/formnya.
- Rumus konversi UOM, volume/berat, transaksi, harga per satuan, stok, HPP, validasi, serta data database tetap dipertahankan dan tidak diubah.
- Export/audit/tool integritas tetap mempertahankan data konversi untuk kebutuhan teknis dan pelacakan.
- Tidak memerlukan ALTER TABLE atau perubahan database.sql.

V2.10.55 - WIZARD INPUT DATA AWAL PERUSAHAAN
--------------------------------------------
- Menambahkan menu Data Awal Perusahaan pada Akun/Pengaturan untuk perusahaan baru dan migrasi awal.
- Menambahkan wizard 6 tahap: Identitas Perusahaan, Periode Data Awal, Master Data, Stok Awal & Pricelist, Hutang/Piutang Historis, serta Verifikasi & Selesai.
- Menyimpan Tanggal Cut-off Histori dan Tanggal Stok Awal/Mulai Operasional melalui tabel settings key-value, tanpa ALTER TABLE.
- Tanggal Stok Awal dari wizard menjadi default pada Input Stok Awal; Tanggal Cut-off menjadi default pada Import Invoice Historis.
- Menampilkan ringkasan jumlah Distributor, Pelanggan, UOM, Barang, mutasi opening, Pricelist, invoice historis, nilai persediaan, sisa hutang, dan sisa piutang.
- Menambahkan validasi agar tanggal opening tidak sebelum cut-off dan tidak sesudah transaksi operasional pertama yang sudah tersimpan.
- Menambahkan status BELUM DIMULAI / SEDANG DIPROSES / DATA AWAL SELESAI beserta user dan waktu penyelesaian.
- Penyelesaian memerlukan konfirmasi eksplisit Master, Stok Awal, Pricelist, dan Hutang/Piutang Historis; kelompok tanpa saldo tetap dapat dikonfirmasi sebagai memang tidak ada.
- Data awal yang sudah selesai dapat dibuka kembali dengan konfirmasi teks BUKA KEMBALI dan dicatat di audit trail.
- Menambahkan default settings data awal pada database.sql untuk instalasi baru; instalasi lama tidak membutuhkan ALTER TABLE atau upgrade schema.
- Tidak mengubah rumus stok, HPP, hutang/piutang, transaksi, approval, atau template cetak.

V2.10.54 - PRE-FLIGHT CHECK BACKUP / RESTORE LINTAS SERVER
----------------------------------------------------------
- Menambahkan Pre-Flight Check wajib sebelum Restore Database dapat dijalankan.
- Restore dari upload sekarang memakai alur 2 tahap: Upload & Pre-Flight terlebih dahulu; password dan konfirmasi RESTORE baru tampil jika status AMAN UNTUK RESTORE.
- Pre-Flight memeriksa validitas file backup resmi JCOM, checksum, versi aplikasi, versi PHP, versi MySQL/MariaDB, privilege database, kecocokan tabel canonical, charset/collation, ukuran backup terhadap upload limit PHP, ruang penyimpanan, dan permission storage/backups.
- Status akhir menampilkan AMAN UNTUK RESTORE atau TIDAK AMAN UNTUK RESTORE lengkap dengan hasil LULUS / PERINGATAN / GAGAL per pemeriksaan.
- Tombol Restore otomatis dinonaktifkan selama masih ada pemeriksaan wajib berstatus GAGAL.
- Pre-Flight dijalankan ulang di sisi server tepat sebelum restore untuk mencegah bypass dari browser.
- Safety Backup otomatis sebelum restore dan auto-recovery bila restore gagal tetap dipertahankan.
- Restore beda versi tetap tersedia sebagai override eksplisit dan menampilkan peringatan; setelah restore wajib menjalankan Cek/Perbaiki Database.
- Backup baru V2.10.54 menambahkan metadata sumber PHP, MySQL/MariaDB, charset, dan collation untuk membantu migrasi antar-server.
- Tidak mengubah tabel transaksi, rumus stok/hutang/piutang, layout cetak, atau schema database. Tidak memerlukan ALTER TABLE.

V2.10.53 - STANDARDISASI FONT TEMPLATE CETAK
--------------------------------------------
- Menormalkan jenis font template cetak menjadi Arial/Helvetica agar konsisten di browser, printer, dan Save PDF.
- Menghapus efek campuran Times New Roman, Courier New, Tahoma/Verdana, dan override konten 12 pt pada hasil akhir melalui standardisasi CSS terakhir.
- Menetapkan hierarki umum dokumen bisnis: nama perusahaan 16 pt; judul dokumen 14 pt; data transaksi 9.5 pt; header/isi tabel 9 pt; catatan dan tanda tangan 9 pt; grand total 11 pt.
- Laporan/master data menggunakan body 10 pt dan tabel 8.5 pt agar tetap terbaca tanpa terlalu besar.
- Preview dokumen, Print Preview, printer, dan Save/Cetak PDF menggunakan keluarga font dan skala yang konsisten.
- Layout adaptif V2.10.52, ukuran kertas, orientasi, margin, lebar kolom, struktur tabel, data, rumus, dan database tidak diubah.

V2.10.52 - TEMPLATE CETAK ADAPTIF SESUAI UKURAN KERTAS
------------------------------------------------------
- Menyamakan ukuran fisik preview dengan hasil Print Preview / printer / Save PDF.
- Memperbaiki preview A4 agar mengikuti Portrait atau Landscape sesuai jenis dokumen.
- Menyesuaikan lebar tabel, kolom, padding sel, blok informasi, summary, dan tanda tangan berdasarkan kertas.
- Mendukung A4 Portrait/Landscape, Continuous 8.5 x 5.5 inch, dan Continuous 9.5 x 11 inch.
- Margin cetak dipindahkan ke @page agar margin tetap konsisten pada halaman lanjutan tabel panjang.
- Header tabel diulang pada halaman berikutnya dan baris item dicegah terpotong di tengah.
- Ukuran font konten tetap 12 pt sesuai V2.10.51.
- Tidak mengubah data, rumus transaksi, atau struktur database.

V2.10.51 - FONT KONTEN CETAK 12 PT
----------------------------------
- Menurunkan ukuran huruf bagian konten cetak dari 14 pt menjadi 12 pt.
- Berlaku pada preview dokumen di browser, Print Preview, Cetak, dan Simpan/Cetak ke PDF.
- Mencakup PO, Invoice Pembelian, Pelunasan Pembelian, Barang Keluar/Surat Jalan, Invoice Penjualan, Pelunasan Penjualan, biaya/dokumen terkait, dan konten laporan cetak umum.
- Konten 12 pt mencakup data transaksi, tabel item, keterangan/catatan, ringkasan/total, status/badge yang tercetak, dan area tanda tangan.
- Judul dokumen dan identitas perusahaan tetap mengikuti ukuran header masing-masing.
- Ukuran kertas, margin, orientasi, lebar kolom, border, struktur layout, rumus, dan database tidak diubah.
- Mode Continuous 8.5x5.5 dan 9.5x11 menggunakan konten 12 pt agar lebih seimbang antara keterbacaan dan kapasitas halaman.

V2.10.50 - FONT KONTEN CETAK 14 PT
----------------------------------
- Memperbesar ukuran huruf bagian konten cetak dari 11 pt menjadi 14 pt.
- Berlaku konsisten pada preview dokumen di browser, Print Preview, Cetak, dan Simpan PDF.
- Berlaku pada PO, Invoice Pembelian, Pelunasan Pembelian, Barang Keluar/Surat Jalan, Invoice Penjualan, Pelunasan Penjualan, dokumen transaksi Accurate-inspired, serta tabel/detail/ringkasan laporan cetak umum.
- Konten 14 pt mencakup data transaksi, tabel item, keterangan, catatan, ringkasan/total, status/badge yang tercetak, dan area tanda tangan.
- Judul dokumen dan identitas/header perusahaan tetap mengikuti ukuran khusus yang sudah ada agar hierarki dokumen tidak berubah.
- Tidak mengubah ukuran kertas, orientasi, margin, lebar kolom, border, rumus, nilai transaksi, atau database.
- Mode Continuous 8.5x5.5 dan 9.5x11 tetap menggunakan konten 14 pt; dokumen panjang dapat bertambah halaman atau membutuhkan lebih banyak ruang vertikal.
- Tidak memerlukan ALTER TABLE / upgrade database.

V2.10.49 - FONT KONTEN CETAK 11 PT
----------------------------------
- Menetapkan ukuran huruf bagian konten hasil cetak menjadi 11 pt pada Print Preview browser, Cetak, dan Simpan PDF.
- Berlaku pada PO, Invoice Pembelian, Pelunasan Pembelian, Barang Keluar/Surat Jalan, Invoice Penjualan, Pelunasan Penjualan, dokumen transaksi Accurate-inspired, serta tabel/detail/ringkasan laporan cetak umum.
- Konten 11 pt mencakup data transaksi, tabel item, keterangan, catatan, ringkasan/total, status/badge yang tercetak, serta area tanda tangan.
- Judul dokumen dan identitas/header perusahaan tetap menggunakan ukuran khusus masing-masing agar hierarki dokumen tetap jelas.
- Tidak mengubah ukuran kertas, orientasi, margin, lebar kolom, border, rumus, nilai transaksi, atau database.
- Continuous 8.5x5.5 dan 9.5x11 juga menggunakan konten 11 pt sesuai permintaan; jumlah halaman dapat bertambah jika isi dokumen panjang.
- Tidak memerlukan ALTER TABLE / upgrade database.

V2.10.48 - PERBAIKAN UKURAN HURUF KONTEN VIEW / PREVIEW / CETAK / PDF
---------------------------------------------------------------------
- Memperbesar ukuran huruf bagian konten pada halaman detail/view PO, Invoice Pembelian, Pelunasan Pembelian, Barang Keluar/Surat Jalan, Invoice Penjualan, dan Pelunasan Penjualan agar lebih nyaman dibaca.
- Memperbesar teks label/nilai detail, isi tabel transaksi, keterangan UOM, ringkasan total, dan status tanpa mengubah struktur card/tabel.
- Memperbaiki ukuran huruf preview print_document.php untuk dokumen Pembelian, Penjualan, dan template dokumen transaksi terkait.
- Memperbesar ukuran huruf hasil Cetak/Simpan PDF secara terukur; Continuous 8.5x5.5 tetap memakai ukuran sedikit lebih padat agar proporsi dokumen terjaga.
- Tidak mengubah ukuran kertas, orientasi, margin, lebar kolom, border, posisi tanda tangan, nilai transaksi, rumus, atau database.
- Tidak memerlukan ALTER TABLE / upgrade database.

V2.10.47 - IDENTITAS PERUSAHAAN VIEW / PREVIEW / CETAK / PDF
------------------------------------------------------------
- Menambahkan Alamat Perusahaan Baris 3 pada setup.php dan Pengaturan Identitas Perusahaan.
- Menyimpan company_address_line3 melalui tabel settings key-value tanpa ALTER TABLE atau perubahan schema transaksi.
- Header default PO, Invoice Pembelian, Bukti Pelunasan Pembelian, Barang Keluar/Surat Jalan, Invoice Penjualan, Bukti Pelunasan Penjualan, biaya, laporan, dan halaman yang mendukung cetak kini dapat menampilkan Alamat Baris 1-3, Kota, Email bila tersedia, serta NPWP perusahaan.
- Halaman detail/view PO, Invoice Pembelian, Pelunasan Pembelian, Barang Keluar/Surat Jalan, Invoice Penjualan, dan Pelunasan Penjualan menampilkan identitas perusahaan ringkas (Nama, Alamat Baris 1-3/Kota, NPWP) tanpa Telepon/Fax.
- Menghilangkan Nomor Telepon dan Fax dari header default view/preview/cetak/Simpan PDF. Data Telepon/Fax tetap tersimpan di Setup/Pengaturan dan tidak dihapus dari database.
- Renderer print_document.php tetap menjadi sumber yang sama untuk preview browser, proses cetak, dan Simpan PDF sehingga hasil identitas konsisten.
- Tidak mengubah tabel item, nilai transaksi, perhitungan, ukuran kertas, orientasi, kolom, garis, tanda tangan, atau layout transaksi selain area identitas perusahaan.
- Tidak membutuhkan upgrade database; schema audit tetap menggunakan tool V2.10.46 karena tidak ada perubahan tabel/kolom/foreign key.

V2.10.46 - Audit Foreign Key & Sinkronisasi stinv5
--------------------------------------------------
- Audit source PHP terhadap database stinv5.sql: 32 tabel / 493 kolom lengkap.
- Tambah pemeriksaan seluruh 57 foreign key canonical database.
- Tool Cek/Perbaiki Database sekarang mendeteksi dan memperbaiki foreign key yang hilang hanya jika tidak ada data orphan.
- Memperbaiki gap upgrade pada historical_migration_batches.created_by -> users.id.
- Route audit V2.10.44 diarahkan ke audit V2.10.46.
- Tidak mengubah transaksi, stok, hutang/piutang, atau data historis secara otomatis.

V2.10.45 - BACKUP & RESTORE DATA DATABASE
-----------------------------------------
- Menambahkan modul Backup & Restore Data terpusat pada menu Akun/Pengaturan.
- Backup dibuat langsung melalui PDO tanpa ketergantungan mysqldump/shell_exec sehingga cocok untuk shared hosting/cPanel.
- Backup mencakup struktur dan seluruh data semua tabel database aktif.
- File backup SQL disimpan di storage/backups dan dilindungi .htaccess; download hanya melalui endpoint aplikasi dengan permission.
- Menambahkan permission backup_restore.view/create/download/restore/delete; Administrator mendapat akses awal, role lain dapat diatur dari Role & Permission.
- Restore hanya menerima file backup resmi JCOM Inventory dengan Backup ID/statement marker dan whitelist statement SQL.
- Restore mewajibkan password user saat ini serta konfirmasi teks RESTORE.
- Sistem otomatis membuat Safety Backup sebelum restore dan mencoba mengembalikan Safety Backup bila restore gagal di tengah proses.
- Restore lintas versi membutuhkan konfirmasi tambahan; setelah restore lintas versi disarankan menjalankan Cek/Perbaiki Database.
- Menambahkan riwayat backup server, ukuran file, jumlah tabel/baris, SHA-256, download, restore, dan hapus backup.
- Tidak memerlukan tabel metadata backup baru; riwayat file disimpan pada filesystem agar backup database tidak bergantung pada tabel yang sedang dipulihkan.

V2.10.44 - AUDIT PENUH PHP / 32 TABEL / 493 KOLOM / PERMISSION / INDEX
----------------------------------------------------------------------
- Audit ulang 119 file PHP V2.10.43: syntax PHP/JS, 271 include/require literal, 276 route literal, serta 607 query SQL statis dibandingkan dengan database.sql.
- Source SQL cocok dengan schema V2.10.43/V2.10.44; hanya referensi legacy products.content_quantity yang tetap dipertahankan dan selalu dilindungi table_has_column().
- Database stinv.sql yang diaudit masih tertinggal 2 tabel (historical_migration_batches, role_dashboard_widgets) dan 43 kolom fitur ROUND HALF-UP/Migrasi Historis.
- Ditemukan 2 permission yang dibutuhkan source tetapi belum ada pada stinv.sql dan belum diperiksa tool V2.10.43: purchase_invoices.edit_tax_invoice dan sales_invoices.edit_tax_invoice.
- Tool integritas V2.10.44 sekarang memeriksa seluruh 32 tabel dan seluruh 493 kolom canonical database.sql, bukan hanya subset kolom fitur terbaru.
- Sinkron permission V2.10.44 mencakup seluruh 89 permission canonical dan memastikan Administrator memiliki seluruh permission.
- Menambahkan pemeriksaan/perbaikan 6 index Migrasi Historis pada tabel transaksi Pembelian/Penjualan.
- Audit data stinv.sql: tidak ditemukan orphan foreign-key logis, duplikasi pada unique business key yang diuji, atau selisih product_stocks terhadap saldo stock_movements terakhir.
- Tidak menghapus/reset data transaksi. Jalankan Pengaturan > Cek/Perbaiki Database V2.10.44 setelah backup database.

V2.10.43 - AUDIT INTEGRITAS PHP & DATABASE / HOTFIX BROKEN PATH
---------------------------------------------------------------
- Audit statis seluruh 118+ script PHP, JavaScript, require/include, route PHP, query SQL, placeholder INSERT, permission, dan database.sql.
- Memperbaiki INSERT activity_logs extended yang memiliki 1 placeholder PDO berlebih; sebelumnya audit trail extended dapat gagal diam-diam karena exception sengaja tidak menghentikan transaksi utama.
- Menghapus broken upgrade path/404 dan mengarahkan upgrade legacy yang masih dipakai modul ke satu halaman terpusat: upgrade_database_integrity_v21043.php.
- Halaman integritas V2.10.43 memeriksa/memperbaiki tabel fitur tambahan, kolom Coretax/UOM, snapshot volume transaksi, Pricelist markup/satuan harga, permission CSV/Faktur Pajak/Migrasi Historis, Dashboard Role, akun sistem, serta ROUND HALF-UP.
- setup.php sekarang menganggap seluruh 32 tabel schema V2.10.43 sebagai bagian database lengkap, termasuk role_dashboard_widgets, remember_tokens, login_attempts, historical_migration_batches, dan product_uom_content_conversions.
- Menambahkan tombol Cek/Perbaiki Database V2.10.43 di Pengaturan untuk Administrator.
- database.sql lolos audit struktur: 32 tabel, foreign key target valid, dan tidak ditemukan referensi INSERT/UPDATE ke kolom yang tidak tersedia pada schema terbaru.
- Referensi legacy products.content_quantity tetap dipertahankan secara bersyarat untuk kompatibilitas database lama dan hanya dieksekusi jika kolom lama memang tersedia.
- Tidak mengubah nilai transaksi, stok, HPP, hutang/piutang, atau saldo keuangan ketika hanya memasang patch. Perubahan database baru terjadi bila Administrator menjalankan tool integritas.

V2.10.42 - Koneksi Database Terpusat
------------------------------------
- Menambahkan file root koneksi.php sebagai satu-satunya pembuat koneksi PDO aplikasi.
- includes/bootstrap.php sekarang menggunakan koneksi.php; seluruh modul yang memakai bootstrap otomatis memakai koneksi yang sama.
- Host, port, database, username, password terenkripsi, dan charset tetap dibaca dari config/app.php hasil setup.
- Menambahkan validasi konfigurasi dan satu instance PDO per request untuk mencegah koneksi ganda.
- Menyediakan alias $pdo dan $koneksi untuk kompatibilitas script integrasi, sementara helper db() tetap menggunakan instance PDO yang sama.
- setup.php tetap melakukan koneksi instalasi tersendiri karena harus membuat/mengetes database sebelum konfigurasi final tersedia.
- Tidak ada perubahan schema database.

V2.10.41 - HOTFIX SIMPAN DATABASE MIGRASI HISTORIS (14 AGUSTUS 2026)
--------------------------------------------------------------------
- Memperbaiki INSERT Invoice Pembelian Historis: satu placeholder PDO berlebih menyebabkan SQL gagal dan seluruh transaksi di-ROLLBACK.
- Memperbaiki pola yang sama pada INSERT Invoice Penjualan Historis.
- Menambahkan penanda tahap proses database sehingga popup gagal menyebut tahap SQL yang bermasalah.
- Menjaga audit trail agar kegagalan pencatatan audit setelah COMMIT tidak mengubah import yang sudah berhasil menjadi status gagal.
- Tidak mengubah stok; verifikasi batch tetap mewajibkan 0 stock movement.
- Tidak memerlukan perubahan struktur database.

V2.10.40 - PERBAIKAN NOMOR BATCH MIGRASI HISTORIS (14 AGUSTUS 2026)
-------------------------------------------------------------------
- Memastikan nomor Batch tersimpan dan ditampilkan tegas setelah import final.
- Redirect hasil import membawa batch_id dan batch_code; session recovery membantu bila parameter URL hilang.
- Menampilkan kartu NOMOR BATCH MIGRASI pada hasil import/verifikasi.
- Daftar invoice historis menampilkan status BELUM ADA BATCH jika relasi batch kosong/rusak.
- Menambahkan deteksi invoice historis orphan: is_historical=1 tetapi migration_batch_id kosong atau batch tidak ditemukan.
- Menambahkan tombol Perbaiki Nomor Batch untuk membuat batch recovery tanpa mengimport ulang invoice dan tanpa mengubah stok.
- Recovery membuat satu batch audit per invoice orphan, menghubungkan dokumen sumber dan pembayaran historis sebelum cut-off, lalu memverifikasi Stock Movement tetap 0.
- Import baru memeriksa kembali identitas batch pada database sebelum menampilkan hasil.
- Tidak ada perubahan schema database / tidak perlu SQL upgrade.

V2.10.39 - VERIFIKASI HASIL IMPORT MIGRASI HISTORIS (14 AGUSTUS 2026)
---------------------------------------------------------------------
- Memperjelas dua tahap Migrasi Historis: Preview/Validasi tidak menyimpan data, sedangkan tombol 2. IMPORT SEKARANG adalah proses final.
- Preview yang berhasil menampilkan pesan tegas "VALIDASI BERHASIL — DATA BELUM DISIMPAN".
- Setelah import final berhasil, popup menampilkan Batch, cut-off, jumlah invoice/item, total invoice, pembayaran s.d. cut-off, sisa hutang/piutang, dan hasil verifikasi stok.
- Menambahkan verifikasi transaksi di dalam database sebelum commit: jumlah invoice, jumlah item, total nominal, pembayaran historis, sisa pada cut-off, flag is_historical/affect_stock/affect_cash, dan stock movement.
- Jika verifikasi hasil import tidak cocok, seluruh transaksi import di-rollback dan ditampilkan sebagai gagal; tidak boleh ada status berhasil semu.
- Menambahkan tombol Periksa pada setiap Riwayat Batch Import untuk memverifikasi batch lama maupun batch baru.
- Verifikasi batch memastikan stock movement terkait batch historis = 0.
- Pesan error import menegaskan bahwa data tidak disimpan serta menampilkan penyebab asli, termasuk nomor baris Excel bila berasal dari validasi file.
- Tidak ada perubahan database / tidak perlu SQL upgrade.

V2.10.38 - POPUP MESSAGE BOX PROSES (14 AGUSTUS 2026)
-----------------------------------------------------
- Menambahkan popup message box global untuk hasil proses berhasil, gagal, peringatan, dan informasi.
- Flash message setelah redirect otomatis tampil sebagai popup dengan judul dan pesan yang jelas.
- Error validasi yang kembali ke form setelah submit POST ikut ditampilkan sebagai popup tanpa menghilangkan alert inline.
- Popup kegagalan menampilkan detail pesan exception/validasi yang sudah diberikan modul agar penyebab lebih mudah diketahui.
- Popup tidak hilang otomatis; user menutup dengan tombol OK, tombol X, klik backdrop, atau tombol Esc.
- Menambahkan API JavaScript global window.JComPopup.show(type, message, title) untuk proses AJAX/fitur baru.
- Setup.php dan Login ikut mendukung popup proses.
- Popup tidak ikut tercetak pada printer atau Print to PDF.
- Tidak ada perubahan database.

V2.10.37 - HOTFIX AKTIVASI MIGRASI HISTORIS & ROUND HALF-UP (14 AGUSTUS 2026)
-----------------------------------------------------------------------------
- Memperbaiki patch gabungan V2.10.15→V2.10.36 yang dapat menyisakan setting pembulatan lama karena UPSERT setting sebelumnya tidak memperbarui nilai existing.
- Menambahkan Aktivasi V2.10.37 yang memastikan rounding_mode default database = auto, rounding_unit = 1, setting aplikasi = auto/Rp1, dan melakukan self-test ROUND HALF-UP.
- Self-test: Rp100.000,49 menjadi Rp100.000 dan Rp100.000,50 menjadi Rp100.001.
- Memperkuat aktivasi Migrasi Historis: tabel batch dibuat tanpa ketergantungan FK saat tahap awal, seluruh kolom historis dan index disinkronkan, permission dipastikan tersedia, dan Administrator diberi akses awal.
- Menambahkan status AKTIF/PERLU AKTIVASI di Pengaturan untuk ROUND HALF-UP dan Migrasi Invoice Historis.
- Memperbaiki halaman Migrasi Historis agar memeriksa tabel benar-benar dapat dibuka, bukan hanya tercatat pada information_schema.
- Data transaksi lama tidak dihitung ulang; hotfix hanya menyinkronkan schema/default untuk transaksi baru dan modul Migrasi Historis.

PAKET GABUNGAN V2.10.15 → V2.10.36 + MIGRASI HISTORIS V2.10.20 (14 AGUSTUS 2026)
- Menyatukan jalur utama V2.10.15 → V2.10.18, seluruh revisi cetak Pembelian V2.10.19 → V2.10.36, dan cabang Migrasi Invoice Historis V2.10.20 dalam satu source V2.10.36.
- Menambahkan satu halaman Upgrade Gabungan yang menyiapkan checklist Dashboard per Role V2.10.16/V2.10.17 serta struktur/permission Migrasi Historis V2.10.20 secara idempotent.
- Migrasi Historis tetap tidak mempengaruhi stok; pembayaran pembuka dapat membentuk hutang/piutang tanpa menjadi arus kas periode, dan Penjualan Historis mendukung HPP Historis untuk laporan laba kotor.
- Mempertahankan pembulatan otomatis nominal transaksi dari revisi V2.10.15 serta notifikasi Pending V2.10.18.
- Mempertahankan seluruh template PO/Invoice Pembelian/Pelunasan Pembelian sampai V2.10.36: view/preview/print/PDF seragam, Times New Roman, hitam-putih, A4/continuous form, dan area tanda tangan operator.
- Paket gabungan ditujukan untuk upgrade langsung dari database/source V2.10.15 tanpa perlu menerapkan seluruh patch antara satu per satu.

V2.10.36 - INVOICE & PELUNASAN PEMBELIAN VIEW/PREVIEW/PRINT/PDF IDENTIK (14 AGUSTUS 2026)
-----------------------------------------------------------------------------------------
- Menjadikan layout Purchase Order sebagai acuan tunggal untuk Invoice Pembelian dan Pelunasan Pembelian.
- View/preview dokumen, browser print preview, cetak printer, dan Print to PDF memakai ukuran sheet fisik, padding, font, line-height, border, warna, dan spacing yang sama.
- Menyatukan geometri A4 Portrait, Continuous 8.5 x 5.5, dan Continuous 9.5 x 11 pada ketiga dokumen Pembelian.
- Memperbaiki pergantian pilihan kertas pada preview agar semua dokumen Pembelian memakai default A4 yang sama dan tidak terkena error variabel JavaScript.
- Menyamakan header identitas, informasi dokumen, tabel, Keterangan, ringkasan Invoice, serta area tanda tangan antara layar dan hasil print/PDF.
- Seluruh output tetap Times New Roman, hitam-putih, tanpa background dekoratif.
- Tidak mengubah database, stok, HPP, hutang, approval, atau nilai transaksi.

V2.10.35 - NAMA OPERATOR TETAP TAMPIL PADA TANDA TANGAN PEMBELIAN (14 AGUSTUS 2026)
-----------------------------------------------------------------------------------
- Purchase Order tetap menampilkan nama user pembuat pada bagian Diorder Oleh di sisi kanan.
- Invoice Pembelian kembali menampilkan nama user pembuat pada Dibuat Oleh dan nama user approver pada Disetujui Oleh.
- Pelunasan Pembelian kembali menampilkan nama user pembuat pada Dibuat Oleh dan nama user approver pada Disetujui Oleh.
- Jika dokumen belum memiliki approver, bagian Disetujui Oleh menampilkan placeholder (........................).
- Nama perusahaan tetap tidak ditampilkan pada kolom tanda tangan.
- Tidak mengubah database, transaksi, stok, HPP, hutang, maupun proses approval.

V2.10.34 - AREA TANDA TANGAN PEMBELIAN DIRAPIKAN (14 AGUSTUS 2026)
------------------------------------------------------------------
- Memindahkan area Diorder Oleh pada Purchase Order ke sisi kanan.
- Nama user pembuat PO tetap ditampilkan sebagai identitas Diorder Oleh.
- Memberi jarak lebih longgar antara ringkasan Sisa Hutang dan area Dibuat Oleh / Disetujui Oleh pada Invoice Pembelian.
- Menghilangkan nama perusahaan dari kolom tanda tangan Invoice Pembelian dan Pelunasan Pembelian.
- Nama operator pada Invoice Pembelian dan Pelunasan Pembelian tidak dicetak; diganti placeholder (........................) untuk tanda tangan manual.
- Tidak mengubah database, stok, HPP, hutang, transaksi, maupun proses approval.

V2.10.33 - KETERANGAN PO RAPI & FONT PEMBELIAN SERAGAM (14 AGUSTUS 2026)
------------------------------------------------------------------------
- Memperbaiki Keterangan Purchase Order yang dapat terlihat berantakan karena line-break sebelumnya diproses sekaligus oleh nl2br dan white-space CSS.
- Keterangan sekarang memakai satu mekanisme line-break; setiap Enter menghasilkan tepat satu baris, isi tetap berada di bawah label Keterangan dengan indent kiri.
- Menyamakan font PO, Faktur Pembelian, dan Pelunasan Pembelian menjadi Times New Roman dengan ukuran, line-height, dan weight body/tabel yang konsisten.
- Nama produk pada Invoice Pembelian tidak lagi tampil bold berbeda dari item PO hanya karena markup strong.
- Menyamakan tipografi info dokumen, tabel, Keterangan, ringkasan, dan area tanda tangan pada view/preview, printer, dan Print to PDF.
- Tetap mendukung A4 Portrait, Continuous 8.5 x 5.5, dan Continuous 9.5 x 11.
- Tidak mengubah database, stok, HPP, hutang, approval, atau nilai transaksi.

V2.10.32 - TEMPLATE PEMBELIAN VIEW/PREVIEW/CETAK/PDF SERAGAM
------------------------------------------------------------
- Menerapkan template hitam-putih Times New Roman ke seluruh dokumen Pembelian: PO, Faktur Pembelian, dan Pelunasan Pembelian.
- View/preview memakai ukuran fisik kertas yang sama dengan hasil cetak dan Print to PDF.
- Mendukung A4 Portrait, Continuous 8.5 x 5.5 inch, dan Continuous 9.5 x 11 inch pada seluruh dokumen Pembelian.
- Header identitas perusahaan seragam: nama 18pt bold, alamat 2 baris 14pt, Telp/Fax 14pt, Kota 14pt.
- Garis header dua garis hitam tipis; border tabel hitam seragam tanpa background warna.
- Keterangan berada di bawah label dengan indent kiri.
- Faktur Pembelian mempertahankan ringkasan Subtotal, Diskon, PPN, Total Invoice, Sudah Dibayar, dan Sisa Hutang.
- Pelunasan Pembelian memakai layout yang sama dan tetap menampilkan nilai invoice/pelunasan/sisa hutang.
- Tidak mengubah database, stok, HPP, hutang, approval, atau nilai transaksi.

V2.10.31 - 14 Agustus 2026
--------------------------
- Template cetak Purchase Order kembali mendukung pilihan kertas A4 Portrait dan continuous form.
- Continuous form tersedia dalam ukuran 8.5 x 5.5 inch (215.9 x 139.7 mm) dan 9.5 x 11 inch (241.3 x 279.4 mm).
- Preview dan hasil print/PDF memakai ukuran fisik, padding, border, font, dan layout yang sama sesuai kertas yang dipilih.
- A4 Portrait tetap menjadi pilihan default.
- Mode 8.5 x 5.5 dibuat lebih padat agar header, tabel, keterangan, dan area Diorder Oleh lebih sesuai continuous form.
- Tidak ada perubahan database maupun logika transaksi.

V2.10.30 - PERBAIKAN GARIS HEADER & BORDER TABEL PO (14 AGUSTUS 2026)
---------------------------------------------------------------------
- Garis di bawah identitas perusahaan pada cetak PO dirapikan menjadi dua garis hitam tipis yang terpisah dan presisi.
- Menghilangkan penggunaan CSS double-border yang dapat dirender berbeda pada preview, printer, dan Print to PDF.
- Border luar tabel barang dibuat sedikit lebih tegas dan seragam.
- Garis grid antar sel dibuat tipis konsisten agar tabel tidak terlihat terlalu tebal.
- Garis pemisah header tabel dibuat lebih tegas untuk meningkatkan keterbacaan.
- Tampilan preview dan hasil print/PDF menggunakan aturan border yang sama.
- Tetap A4 Portrait, Times New Roman, teks hitam, dan tanpa background warna.
- Tidak ada perubahan database atau logika transaksi.

V2.10.29 - FONT TIMES NEW ROMAN CETAK PO (14 AGUSTUS 2026)
----------------------------------------------------------
- Mengubah font Purchase Order dari Courier New menjadi Times New Roman untuk view/preview, cetak printer, dan Print to PDF.
- Menggunakan fallback Times/Liberation Serif bila Times New Roman tidak tersedia pada sistem operasi.
- Nama perusahaan tetap 18pt bold; alamat, telepon/fax, dan kota tetap 14pt regular.
- Seluruh teks tetap hitam murni dan preview = hasil cetak A4 Portrait.
- Tidak mengubah database, transaksi, stok, HPP, maupun isi dokumen.

V2.10.28 - KETERANGAN PO BERTINGKAT + TEKS HITAM PRINT/PDF (14 AGUSTUS 2026)
----------------------------------------------------------------------------
- Label "Keterangan :" pada cetak Purchase Order tetap berada di baris pertama.
- Isi keterangan dipindahkan ke baris berikutnya dan diberi indent/jarak kiri 8 mm agar lebih rapi.
- Preview, print printer, dan Print to PDF dipaksa menggunakan warna teks hitam murni (#000).
- Menonaktifkan filter, text-shadow, opacity turunan, mix-blend-mode, dan forced color adjustment yang dapat membuat teks terlihat abu-abu pada PDF.
- Preview dan hasil cetak tetap menggunakan layout A4 Portrait dan geometri yang sama.
- Tidak ada perubahan database, stok, HPP, transaksi, atau perhitungan. Tidak memerlukan upgrade SQL.

V2.10.27 - LABEL KETERANGAN PO TANPA UNDERLINE + FONT HITAM (14 AGUSTUS 2026)
-----------------------------------------------------------------------------
- Mengubah label keterangan umum pada cetak Purchase Order dari "NB :" menjadi "Keterangan :".
- Menghilangkan underline/garis bawah pada label Keterangan.
- Memperlebar area label agar "Keterangan :" tetap satu baris dan tidak mengganggu isi catatan.
- Memastikan seluruh font Purchase Order memakai warna hitam default (#000) pada preview dan hasil cetak.
- Mempertahankan A4 Portrait, Courier New, preview = print, background putih/transparan, dan isi transaksi tanpa perubahan.
- Tidak ada perubahan database atau upgrade SQL.

V2.10.26 - LABEL KETERANGAN PO NB (13 AGUSTUS 2026)
---------------------------------------------------
- Mengembalikan label keterangan umum pada cetak Purchase Order.
- Label sebelumnya NR diubah menjadi NB, sehingga tampil sebagai "NB :".
- Isi keterangan umum PO tetap menggunakan field yang sama dan tidak mengubah data transaksi.
- Mempertahankan A4 Portrait, preview = print, font Courier New, teks hitam, dan background putih/transparan dari V2.10.25.
- Tidak ada perubahan database atau upgrade SQL.

V2.10.25 - WARNA TEKS CETAK PO HITAM DEFAULT (13 AGUSTUS 2026)
--------------------------------------------------------------
- Memaksa seluruh teks template Purchase Order menggunakan warna hitam murni (#000) pada preview dan hasil cetak.
- Berlaku untuk kop perusahaan, informasi PO, tabel item, keterangan umum, area Diorder Oleh, link, label, dan teks turunan lainnya.
- Menambahkan -webkit-text-fill-color hitam dan opacity 1 untuk menghindari teks abu-abu/pudar akibat style browser atau printer.
- Tidak mengubah background, layout A4 portrait, font Courier New, isi transaksi, database, stok, HPP, maupun perhitungan.

V2.10.24 - CETAK PO TANPA LABEL NR (13 AGUSTUS 2026)
----------------------------------------------------
- Menghilangkan label "NR :" pada template cetak Purchase Order.
- Isi keterangan umum PO tetap ditampilkan tanpa label tambahan.
- Tidak mengubah layout A4 portrait, font, transaksi, database, stok, maupun perhitungan.

V2.10.23 - PREVIEW DAN HASIL CETAK PO IDENTIK + TANPA BACKGROUND (13 AGUSTUS 2026)
----------------------------------------------------------------------------------
- Menyamakan geometri preview dan hasil cetak Purchase Order: keduanya menggunakan kanvas A4 Portrait 210 x 297 mm dengan padding dokumen 12 mm atas, 15 mm kiri/kanan, dan 15 mm bawah.
- Khusus Purchase Order, @page menggunakan margin 0 sehingga margin isi tidak dihitung dua kali oleh browser; padding A4 berada pada dokumen yang sama di preview maupun print.
- Menghilangkan background abu-abu halaman preview, shadow kertas, warna latar header/tabel, dan seluruh background dekoratif pada area Purchase Order.
- Area cetak PO hanya menggunakan hitam, putih, garis/border hitam, dan background transparan/putih.
- Toolbar preview dibuat hitam-putih dan tetap tidak ikut tercetak.
- Font, ukuran, line-height, lebar tabel, padding, NR, dan area Diorder Oleh menggunakan aturan CSS yang sama antara preview dan hasil cetak.
- Tidak mengubah database, isi PO, Qty/UOM, harga, HPP, stok, approval, atau transaksi. Tidak memerlukan upgrade SQL.

V2.10.22 - IDENTITAS PERUSAHAAN DAPAT DIEDIT DARI PENGATURAN
------------------------------------------------------------
- Pengaturan > Identitas Aplikasi sekarang secara eksplisit menampilkan dan menyimpan Alamat Perusahaan Baris 1, Alamat Perusahaan Baris 2, No. Telepon, No. Fax, dan Kota.
- Field identitas tersebut dapat diedit kapan saja tanpa menjalankan setup ulang.
- Setup.php tetap menyediakan field yang sama pada instalasi awal dan menjelaskan bahwa data dapat diedit kembali melalui Pengaturan.
- Header cetak PO Default tetap menggunakan Nama Perusahaan 18 pt bold; alamat 2 baris, Telp/Fax, dan Kota 14 pt tanpa warna.
- Tidak ada perubahan struktur database; settings tetap memakai pola key-value.

V2.10.21 - IDENTITAS PERUSAHAAN & HEADER CETAK PO — VERSI TERPISAH (13 AGUSTUS 2026)
------------------------------------------------------------------------------------
- Menerbitkan revisi terakhir template cetak PO V2.10.19 sebagai versi baru V2.10.21 agar file V2.10.19 tidak tertimpa.
- V2.10.20 yang sebelumnya dipakai untuk cabang Migrasi Invoice Historis tetap dipertahankan dan tidak ditimpa.
- Fitur tetap sama dengan revisi terakhir V2.10.19: identitas perusahaan di Setup/Pengaturan, alamat 2 baris, No. Fax, Kota, serta header cetak PO hitam-putih.
- Header PO Default: Nama Perusahaan 18 pt bold; Alamat Baris 1/2, Telepon/Fax, dan Kota 14 pt regular.
- Cetak PO tetap A4 Portrait, Courier New, kode barang tidak ditampilkan, Dikirim Tgl/Ekspedisi kosong, dan Diorder Oleh memakai nama user pembuat.
- Tidak ada perubahan database, stok, HPP, transaksi, hutang/piutang, atau perhitungan. Tidak memerlukan upgrade SQL.
- Versi aplikasi dinaikkan menjadi V2.10.21 hanya untuk menjaga setiap paket versi tetap terpisah dan tidak saling menimpa.

V2.10.20 - Migrasi Invoice Historis
-----------------------------------
- Menambahkan import Invoice Pembelian Historis dan Invoice Penjualan Historis.
- Menambahkan Tanggal Cut-off untuk memisahkan transaksi historis dan transaksi operasional setelah go-live.
- Invoice historis tidak memengaruhi stok fisik maupun stock_movements; stok fisik dimasukkan melalui Stok Awal.
- Menambahkan migrasi saldo hutang dan piutang melalui pembayaran pembuka sampai tanggal cut-off tanpa membentuk arus kas baru.
- Menambahkan HPP Historis Item pada penjualan untuk menjaga akumulasi laba-rugi historis.
- Invoice historis tetap tampil di laporan dan sisa hutang/piutangnya dapat dilunasi melalui modul normal setelah go-live.
- Menambahkan permission, utility upgrade, halaman Migrasi Invoice Historis, template import, Preview, dan Import batch.
- Aturan validasi: tanggal invoice harus <= cut-off, master partner/barang harus sudah ada, dan nomor invoice duplikat ditolak.

V2.10.19 - TEMPLATE CETAK PURCHASE ORDER GAYA REFERENSI PORTRAIT — REVISI (13 AGUSTUS 2026)
-------------------------------------------------------------------------------------------
- Menambahkan identitas perusahaan di setup.php dan Pengaturan: Nama Perusahaan, Alamat Perusahaan Baris 1, Alamat Perusahaan Baris 2, No. Telepon, No. Fax, dan Kota.
- Header cetak PO Default memakai data identitas tersebut dengan layout hitam-putih tanpa warna dekoratif.
- Nama Perusahaan dicetak 18 pt bold; Alamat Baris 1/2, Telepon/Fax, dan Kota dicetak 14 pt regular.
- Telepon dan Fax dicetak dalam satu baris; field kosong otomatis tidak dicetak.
- Header PO tetap menggunakan Courier New agar huruf i/l/I/1 mudah dibedakan; hanya Nama Perusahaan yang bold sesuai permintaan.
- Data identitas baru disimpan sebagai setting key-value sehingga tidak memerlukan ALTER TABLE / upgrade struktur database.
- Revisi tetap pada V2.10.19 dan tidak mengubah data maupun logika transaksi.
- Revisi cetak PO: menyeragamkan seluruh ketebalan font menjadi regular agar tidak ada teks tebal/tipis pada preview maupun hasil cetak.
- Revisi tetap pada V2.10.19; tidak menaikkan versi aplikasi.
- Cetak Purchase Order dikunci ke ukuran A4 Portrait agar hasil konsisten dengan template referensi.
- Ukuran font kop, informasi PO, tabel item, NR, dan area tanda tangan diperbesar/dirapikan agar lebih mudah dibaca pada A4.
- Label `Status` diubah menjadi `Dikirim Tgl` dan nilainya dikosongkan untuk dapat diisi manual pada hasil cetak bila diperlukan.
- Label `Penerimaan` diubah menjadi `Ekspedisi` dan nilainya dikosongkan.
- Area `Disetujui oleh` diubah menjadi `Diorder oleh` dan otomatis menampilkan nama user pembuat PO.
- Keterangan per barang tidak lagi dicetak; hanya Keterangan/NR pada header PO yang tetap ditampilkan.
- Subtotal, Pembulatan, dan Total PO dihilangkan dari hasil cetak PO.
- Bagian bawah Nama Distributor, NPWP, Kode Distributor, PIC/Kontak, dan user pembuat dihilangkan.
- Tabel tetap menggunakan susunan `No | Nama Produk | Kemasan | Jumlah (Qty | Harga)` dan Qty/Harga tetap mengikuti satuan transaksi.
- Kop Default, By Text (`idcom.txt`), dan Tanpa Kop tetap didukung.
- Perubahan hanya pada cetak PO; database, transaksi, stok, HPP, hutang/piutang, serta modul lain tidak diubah. Tidak memerlukan upgrade SQL.


Revisi tambahan V2.10.19:
- Kode barang pada cetak PO dihilangkan; kolom Nama Produk hanya menampilkan nama barang.

[V2.10.19 - Revisi R6 Cetak PO]
- Font Purchase Order diganti ke Courier New regular untuk memperjelas perbedaan huruf i, l, I, dan angka 1.
- Ketebalan font tetap seragam (400) dan font synthesis/ligature dimatikan.
- Preview dan hasil print menggunakan font yang sama.

V2.10.18 - NOTIFIKASI PENDING PEMBELIAN & PENJUALAN BERDASARKAN ROLE (13 AGUSTUS 2026)
--------------------------------------------------------------------------------------
- Menyamakan notifikasi pending seperti Detil Pembelian ke seluruh alur Pembelian dan Penjualan.
- Sidebar sekarang menampilkan badge jumlah Menunggu Persetujuan pada Purchase Order, Invoice Pembelian, Pelunasan Pembelian, Barang Keluar/Penjualan, Invoice Penjualan, dan Pelunasan Penjualan.
- Badge hanya dihitung dan ditampilkan bila user memiliki permission Approve untuk modul terkait, sehingga notifikasi mengikuti Role & Permission dan tidak membocorkan antrean approval ke user lain.
- Ikon lonceng pada topbar sekarang aktif sebagai dropdown Persetujuan Pending dan menampilkan total serta rincian pending Pembelian/Penjualan yang dapat diakses langsung.
- Tombol Persetujuan Pending beserta jumlah antrean ditambahkan ke halaman PO, Pelunasan Pembelian, Barang Keluar, Invoice Penjualan, dan Pelunasan Penjualan agar konsisten dengan Detil Pembelian.
- Tautan notifikasi langsung membuka daftar dengan filter pending pada modul yang sesuai.
- Jika role tidak mempunyai antrean approval, dropdown menampilkan informasi bahwa tidak ada transaksi menunggu persetujuan dan tidak menampilkan badge angka.
- Tidak mengubah database, transaksi, Qty/UOM, stok, HPP, hutang, piutang, approval, maupun Dashboard checklist. Tidak memerlukan upgrade SQL.
- Versi aplikasi dinaikkan dari V2.10.17 menjadi V2.10.18.

V2.10.17 - DASHBOARD RINGKASAN CHECKLIST BERDASARKAN ROLE (13 AGUSTUS 2026)
---------------------------------------------------------------------------
- Menghapus sifat selalu-tampil pada kartu Total Barang, Nilai Persediaan, dan Biaya Bulan Ini di template Dashboard.
- Menambahkan ketiga kartu tersebut ke checklist Tampilan Dashboard pada Role & Permission dalam grup Ringkasan.
- Kartu Ringkasan hanya tampil jika dicentang untuk role dan user memiliki permission Lihat modul terkait.
- Query Total Barang, Nilai Persediaan, dan Biaya Bulan Ini hanya dijalankan jika kartunya benar-benar tampil, sehingga Dashboard lebih ringan.
- Menambahkan upgrade Dashboard Ringkasan V2.10.17 untuk menyinkronkan tiga widget baru ke role existing tanpa mengubah permission modul.
- Database instalasi baru langsung memiliki 13 widget Dashboard per role: 3 Ringkasan, 5 Pembelian, dan 5 Penjualan.
- Versi aplikasi dinaikkan dari V2.10.16 menjadi V2.10.17.

V2.10.16 - DASHBOARD CHECKLIST BERDASARKAN ROLE (13 AGUSTUS 2026)
-----------------------------------------------------------------
- Menambahkan checklist tampilan Dashboard pada setiap Role.
- Menambahkan 5 kartu Pembelian: PO Pending, Invoice Pembelian Pending, Pelunasan Pembelian Pending, Sisa Hutang, dan Pembelian Bulan Ini.
- Menambahkan 5 kartu Penjualan: Penjualan Pending, Invoice Penjualan Pending, Pelunasan Penjualan Pending, Sisa Piutang, dan Penjualan Bulan Ini.
- Checklist Dashboard tetap mengikuti permission modul; kartu tidak tampil bila role tidak memiliki permission Lihat terkait.
- Menambahkan tabel role_dashboard_widgets dan halaman upgrade Dashboard Role V2.10.16 untuk database existing.
- Kartu pending diarahkan langsung ke daftar transaksi dengan filter pending.
- Menambahkan filter status persetujuan pada daftar Pelunasan Pembelian dan Pelunasan Penjualan.
- Query Dashboard hanya dijalankan untuk kartu yang tampil sehingga lebih efisien untuk role dengan dashboard terbatas.
- Menambahkan layout grid 5 kartu yang responsif untuk desktop, tablet, dan mobile.
- Versi aplikasi dinaikkan dari V2.10.15 menjadi V2.10.16.

V2.10.15 - PEMBULATAN ROUND UP / ROUND DOWN TRANSAKSI (12 AGUSTUS 2026)
-----------------------------------------------------------------------
- Menambahkan pembulatan nilai akhir transaksi Pembelian dan Penjualan dengan tiga pilihan: Tanpa Pembulatan, Round Up, dan Round Down.
- Menambahkan pilihan kelipatan pembulatan Rp 1, Rp 10, Rp 100, dan Rp 1.000 pada Purchase Order, Barang Keluar/Penjualan, Invoice Pembelian, Invoice Penjualan, Pelunasan Pembelian, dan Pelunasan Penjualan.
- Round Up selalu menaikkan nilai akhir ke kelipatan berikutnya; Round Down selalu menurunkan nilai akhir ke kelipatan sebelumnya. Nilai yang sudah tepat pada kelipatan tidak berubah.
- Pembulatan Invoice diterapkan setelah Discount, DPP/PPN, dan perhitungan total dasar selesai. `rounding_adjustment` disimpan terpisah sehingga nilai sebelum pembulatan tetap dapat diaudit.
- Pembulatan PO/Barang Keluar diterapkan pada total dokumen setelah seluruh total item dijumlahkan; total harga per item tetap memakai presisi transaksi yang ada.
- Pembulatan Pelunasan diterapkan pada nominal pembayaran sebelum validasi sisa hutang/piutang. Nilai hasil pembulatan tidak boleh melebihi saldo invoice yang tersedia.
- Menambahkan setting Default Pembulatan Transaksi dan Default Kelipatan Pembulatan. Default dapat dioverride pada masing-masing transaksi.
- Menambahkan kolom `rounding_mode`, `rounding_unit`, dan `rounding_adjustment` pada `purchase_orders`, `purchase_invoices`, `purchase_payments`, `sales`, `sales_invoices`, dan `sales_payments`.
- Menambahkan tool `upgrade_transaction_rounding_v21015.php` untuk database existing. Data transaksi lama otomatis menggunakan `none`, kelipatan 1, dan adjustment 0 sehingga nilai lama tidak berubah.
- Tampilan detail dan template cetak menampilkan baris Pembulatan jika adjustment tidak nol.
- Pembulatan tidak mengubah Qty/UOM, harga per UOM kecil, HPP moving weighted average, mutasi stok, atau nilai valuasi stok; hanya nilai akhir dokumen/pembayaran yang dibulatkan.
- Versi aplikasi dinaikkan dari V2.10.14 menjadi V2.10.15.

V2.10.14 - TANGGAL STOK AWAL & KOREKSI VALUASI HISTORIS (12 AGUSTUS 2026)
-------------------------------------------------------------------------
- Menambahkan Tanggal Stok Awal eksplisit pada Input Stok Awal manual dan Import Master Barang; mutasi `opening` tidak lagi harus memakai tanggal saat file diimport.
- Template Import Master Barang menambahkan kolom `Tanggal Stok Awal`. Bila kolom tersebut kosong, Import Master Barang memakai `Tanggal Stok Awal Default` yang wajib dipilih pada halaman preview.
- Import Detil Barang/Stok sekarang mewajibkan kolom Tanggal Stok Awal agar histori persediaan tidak diam-diam mengikuti tanggal import.
- Tanggal Stok Awal tidak boleh melebihi tanggal hari ini dan digunakan juga sebagai tanggal basis Pricelist yang otomatis terbentuk dari HPP opening.
- Menambahkan tool `upgrade_opening_stock_history_v21014.php` untuk mengoreksi tanggal opening stock existing berdasarkan tanggal sumber tertentu ke tanggal cut-off baru tanpa mengubah Qty, HPP per UOM, value_in/value_out, atau nilai persediaan total.
- Tool koreksi memvalidasi agar tanggal cut-off berada sebelum transaksi stok pertama pada barang terdampak dan membangun ulang kolom running balance (`balance_qty`, `balance_cost`, `balance_value`) sesuai urutan tanggal historis.
- Laporan Valuasi Stok tetap memakai rumus historis yang benar: Stok Awal adalah seluruh mutasi sebelum tanggal Dari; ditambahkan deteksi/peringatan bila opening stock tercatat sama/lebih baru dari transaksi pertama.
- Halaman Detil Barang/Stok menampilkan Tanggal Stok Awal sehingga tanggal efektif saldo awal dapat diaudit langsung.
- Tidak mengubah struktur database, Qty transaksi, HPP transaksi, nilai opening, nilai pembelian/penjualan, hutang, piutang, PPN, maupun dokumen Approved. Tidak memerlukan ALTER TABLE.
- Versi aplikasi dinaikkan dari V2.10.13 menjadi V2.10.14.

V2.10.13 - NOMOR FAKTUR PENJUALAN & SURAT JALAN FORMAT PERUSAHAAN (12 AGUSTUS 2026)
-----------------------------------------------------------------------------------
- Mengubah nomor otomatis Faktur Penjualan menjadi format `001/KODE_PERUSAHAAN/BULAN_ROMAWI/TAHUN`, contoh `001/ST/VIII/2026`.
- Mengubah nomor otomatis Surat Jalan menjadi format `001/KODE_PERUSAHAAN/SP/BULAN_ROMAWI/TAHUN`, contoh `001/ST/SP/VIII/2026`; kode `SP` khusus Surat Jalan.
- Angka urut menggunakan tiga digit mulai dari 001 dan di-reset setiap bulan berdasarkan tanggal dokumen (Tanggal Invoice untuk Faktur Penjualan dan Tanggal Barang Keluar untuk Surat Jalan).
- Kode perusahaan diambil dari Pengaturan/Setup (`company_code`), sehingga contoh `ST` otomatis mengikuti identitas perusahaan aktif.
- Nomor otomatis menggunakan `document_sequences` dengan row lock di dalam transaksi database agar aman ketika beberapa user menyimpan dokumen secara bersamaan.
- Nomor Faktur Penjualan dan Nomor Surat Jalan tetap dapat diisi custom. Jika field dikosongkan, sistem menggunakan nomor otomatis sesuai format baru.
- Nomor custom diperiksa terhadap seluruh record termasuk data soft-delete karena kolom nomor memiliki UNIQUE KEY; nomor yang pernah dipakai tidak dapat digunakan kembali.
- Generator otomatis memeriksa kandidat nomor terhadap tabel transaksi dan melewati kandidat yang sudah ada, sehingga nomor otomatis maupun custom tidak dapat menghasilkan duplikat.
- Menambahkan preview nomor Faktur Penjualan dan Surat Jalan yang mengikuti perubahan bulan/tahun pada tanggal transaksi tanpa menimpa nomor custom yang sedang diketik.
- Label Invoice Penjualan pada daftar/detail/cetak diselaraskan menjadi Faktur Penjualan pada bagian nomor dokumen yang relevan.
- Nomor Barang Keluar internal tetap memakai mekanisme sebelumnya dan tidak diubah oleh format Faktur/SJ baru.
- Tidak mengubah struktur database, stok, HPP, Qty/UOM, harga, PPN, piutang, approval, atau data transaksi existing. Tidak memerlukan upgrade SQL.
- Versi aplikasi dinaikkan dari V2.10.12 menjadi V2.10.13.

V2.10.12 - EDIT FAKTUR PAJAK INVOICE APPROVED BERDASARKAN ROLE (12 AGUSTUS 2026)
--------------------------------------------------------------------------------
- Menambahkan permission khusus `purchase_invoices.edit_tax_invoice` dan `sales_invoices.edit_tax_invoice` untuk mengubah data Faktur Pajak pada Invoice Pembelian/Penjualan yang sudah berstatus Approved.
- Permission khusus hanya mengizinkan perubahan `No. Faktur Pajak` dan `Tanggal Faktur Pajak`; seluruh field transaksi lain tetap terkunci, termasuk Qty, barang, harga, diskon, PPN, jatuh tempo, pelanggan/distributor, status approval, stok, HPP, hutang, dan piutang.
- Menambahkan halaman terisolasi `invoice_tax_edit.php` yang melakukan pengecekan permission server-side dan menolak penggunaan pada invoice yang bukan Approved. Draft/Rejected tetap menggunakan form Edit transaksi biasa.
- No. Faktur Pajak dan Tanggal Faktur Pajak tetap bersifat opsional sesuai aturan V2.10.10 dan dapat dikosongkan tanpa mengubah status Approved.
- Menambahkan tombol `Edit Faktur Pajak` pada detail dan `Edit FP` pada daftar Invoice Pembelian/Penjualan hanya jika invoice Approved dan role mempunyai permission khusus terkait.
- Setiap perubahan Faktur Pajak Approved dicatat pada Audit Trail dengan nilai sebelum/sesudah, user, waktu, modul, dan ID invoice.
- Jika Invoice Penjualan pernah masuk export Faktur Pajak, halaman edit menampilkan peringatan jumlah export sebelumnya. File XLSX lama bersifat snapshot dan tidak diubah; user dapat melakukan export ulang setelah koreksi.
- Menambahkan `upgrade_tax_invoice_edit_roles_v21012.php` untuk database existing. Upgrade hanya membuat/sinkron permission; selain Administrator tidak ada role yang diberi akses khusus secara otomatis.
- Form Role menambahkan dependency agar permission Edit Faktur Pajak Approved selalu disertai permission Lihat invoice dan menyediakan tombol cepat terpisah untuk Pembelian/Penjualan.
- Instalasi baru melalui `database.sql` langsung mempunyai dua permission khusus; assignment default hanya Administrator sehingga akses terhadap dokumen Approved tetap bersifat elevated/terkontrol.
- Tidak mengubah struktur tabel transaksi, rumus Qty/UOM, stok, HPP, DPP, PPN, hutang, piutang, maupun nilai invoice.
- Versi aplikasi dinaikkan dari V2.10.11 menjadi V2.10.12.

V2.10.11 - EDIT MODUL PEMBELIAN & PENJUALAN BERDASARKAN ROLE (12 AGUSTUS 2026)
------------------------------------------------------------------------------
- Meresmikan kontrol Edit transaksi berdasarkan Role & Permission untuk seluruh alur Pembelian dan Penjualan: Purchase Order, Invoice Pembelian, Pelunasan Pembelian, Barang Keluar, Invoice Penjualan, dan Pelunasan Penjualan.
- Permission yang digunakan: `purchase_orders.edit`, `purchase_invoices.edit`, `purchase_payments.edit`, `sales.edit`, `sales_invoices.edit`, dan `sales_payments.edit`.
- Tombol/halaman Edit tetap diperiksa di sisi server dengan `require_permission()`, sehingga akses tidak dapat dilewati hanya dengan membuka URL form secara langsung.
- Menambahkan dependency Role: setiap permission Edit transaksi otomatis membutuhkan permission Lihat modul yang bersangkutan ketika Role disimpan.
- Menambahkan tombol cepat pada form Role untuk mengaktifkan/nonaktifkan kelompok Edit Pembelian atau Edit Penjualan tanpa menghilangkan kontrol granular per modul.
- Menambahkan `upgrade_transaction_edit_roles_v21011.php` untuk memastikan enam permission Edit tersedia pada database existing dan menyinkronkan role bawaan Administrator/Staff tanpa memberi akses Edit otomatis ke custom role.
- Dokumen berstatus Draft atau Rejected dapat diedit jika role memiliki permission Edit; dokumen Approved tetap dikunci untuk menjaga integritas stok, HPP, hutang, piutang, pelunasan, serta histori approval.
- Instalasi baru melalui `database.sql` langsung memiliki assignment Edit transaksi untuk Administrator dan Staff; Approver/Viewer tetap tidak mendapat Edit secara default.
- Tidak mengubah rumus transaksi, Qty/UOM, stok, HPP, PPN, hutang, piutang, maupun struktur tabel transaksi.
- Versi aplikasi dinaikkan dari V2.10.10 menjadi V2.10.11.

V2.10.10 - JATUH TEMPO SAAT INPUT INVOICE; FAKTUR PAJAK OPSIONAL (12 AGUSTUS 2026)
----------------------------------------------------------------------------------
- Modul Invoice Pembelian dan Invoice Penjualan sekarang mewajibkan Tanggal Jatuh Tempo pada saat transaksi invoice dibuat/disimpan, bukan saat approval.
- No. Faktur Pajak dan Tanggal Faktur Pajak pada Pembelian maupun Penjualan bersifat opsional walaupun transaksi menggunakan PPN; keduanya tidak lagi menjadi syarat simpan maupun syarat approval.
- No. Faktur Pajak dan Tanggal Faktur Pajak dapat diisi pada form Input/Edit Invoice. Keduanya divalidasi formatnya bila diisi, tetapi tidak diwajibkan diisi berpasangan.
- Tahap Approval tidak lagi menampilkan field Faktur Pajak atau Jatuh Tempo. Approver cukup menyetujui/menolak invoice berdasarkan data transaksi yang sudah tersimpan.
- Approval tetap melakukan validasi pengaman bahwa Tanggal Jatuh Tempo sudah tersedia. Invoice lama/pending yang belum memiliki jatuh tempo harus diedit terlebih dahulu sebelum dapat di-approve.
- Approval Invoice Pembelian tetap memproses stok masuk, moving average/HPP, pricelist, status PO, dan hutang; Approval Invoice Penjualan tetap membentuk piutang tanpa mengurangi stok kembali.
- Tidak mengubah rumus Qty/UOM, stok, HPP, DPP, PPN, subtotal, grand total, atau struktur database. Tidak memerlukan upgrade SQL.
- Versi aplikasi dinaikkan dari V2.10.9 menjadi V2.10.10.

V2.10.9 - PERBAIKAN SIMPAN INVOICE PEMBELIAN (12 AGUSTUS 2026)
--------------------------------------------------------------
- Memperbaiki Input Invoice Pembelian yang terlihat tidak tersimpan ketika PPN lebih dari 0% tetapi No. Faktur Pajak/Tanggal Faktur Pajak belum diisi.
- Invoice Pembelian sekarang tetap dapat disimpan dan langsung masuk status Menunggu Persetujuan walaupun data Faktur Pajak dan jatuh tempo belum dilengkapi.
- Jika No. Faktur Pajak atau Tanggal Faktur Pajak diisi saat input, keduanya tetap harus diisi berpasangan dan format tanggal divalidasi.
- Pada tahap Approval Invoice Pembelian, Tanggal Jatuh Tempo wajib diisi; No. Faktur Pajak dan Tanggal Faktur Pajak wajib bila PPN lebih dari 0%.
- Halaman Detail Invoice Pembelian menyediakan form Lengkapi & Approve agar approver dapat menyimpan data FP/jatuh tempo sekaligus memproses stok masuk dan hutang.
- Tombol approval pada daftar Invoice Pembelian diarahkan ke halaman Detail agar data final dapat diperiksa sebelum stok diproses.
- Nomor Invoice Pembelian otomatis sekarang dibuat dengan document sequence yang dikunci di dalam transaksi database sehingga lebih aman pada penggunaan multi-user.
- Nomor invoice custom diperiksa terhadap seluruh record termasuk data soft-delete agar tidak berbenturan dengan UNIQUE KEY database.
- Memperbaiki state form setelah rollback: kegagalan INSERT item tidak lagi membuat form seolah-olah berada pada mode Edit terhadap ID yang tidak tersimpan.
- Tidak mengubah rumus Qty, UOM, HPP moving average, PPN, stok, pricelist, hutang, atau struktur database.
- Tidak memerlukan upgrade SQL/database.
- Versi aplikasi dinaikkan dari V2.10.8 menjadi V2.10.9.

V2.10.8 - DATA FAKTUR PAJAK & JATUH TEMPO DIISI SAAT APPROVAL INVOICE PENJUALAN (12 AGUSTUS 2026)
-------------------------------------------------------------------------------------------------
- Memindahkan input No. Faktur Pajak, Tanggal Faktur Pajak, dan Tanggal Jatuh Tempo dari form Input/Edit Invoice Penjualan ke tahap Approval Invoice Penjualan.
- Form Input Invoice Penjualan sekarang hanya berfokus pada header transaksi, item, diskon, PPN, harga, qty, dan keterangan; tiga data approval tidak perlu diisi oleh pembuat invoice.
- Approver wajib mengisi Tanggal Jatuh Tempo sebelum approval. Untuk invoice dengan PPN > 0%, No. Faktur Pajak dan Tanggal Faktur Pajak juga wajib diisi; untuk PPN 0% keduanya opsional tetapi harus tetap diisi berpasangan jika digunakan.
- Data Faktur Pajak/Jatuh Tempo disimpan dalam transaksi database yang sama dengan perubahan status menjadi approved dan pembentukan piutang, sehingga approval tidak dapat selesai bila validasi data gagal.
- Tombol Approve pada daftar Invoice Penjualan sekarang mengarahkan ke bagian Approval pada halaman detail agar approver dapat melengkapi tiga field tersebut sebelum menyetujui.
- Export XLSX Faktur Pajak dari daftar/detail Invoice Penjualan hanya ditampilkan setelah invoice berstatus approved, sehingga dokumen pending yang belum memiliki data Faktur Pajak tidak diekspor prematur.
- Menghapus syarat No. Faktur Pajak/Tanggal Faktur Pajak/Jatuh Tempo pada proses pengajuan invoice; validasi dipindahkan sepenuhnya ke proses approval.
- Data lama tetap kompatibel: jika invoice pending/rejected lama sudah memiliki data Faktur Pajak atau jatuh tempo, nilai tersebut ditampilkan sebagai prefill pada form approval dan masih dapat dikoreksi sebelum Approve.
- Tidak mengubah struktur database, rumus PPN/DPP, stok, HPP, qty, nomor invoice, atau nilai piutang. Tidak memerlukan upgrade SQL.
- Versi aplikasi dinaikkan dari V2.10.7 menjadi V2.10.8.

V2.10.7 - PERBAIKAN INTEGRITAS QTY, SATUAN ISI, HPP & VALUASI STOK (11 AGUSTUS 2026)
------------------------------------------------------------------------------------
- Menambahkan pemeriksaan integritas untuk mendeteksi salah skala satuan isi pada data lama/import, khususnya pola high-confidence seperti barang bernama 100ML tetapi tersimpan sebagai 100 LITER, atau 400GR tetapi tersimpan sebagai 400 KILOGRAM.
- Pola salah skala tersebut dapat membuat Qty UOM kecil 1.000× terlalu kecil dan HPP per UOM kecil 1.000× terlalu besar, sementara nilai persediaan total tetap terlihat benar; hal ini kemudian memengaruhi ketersediaan stok, Qty pada Valuasi/Kartu Stok, dan multiplier Pricelist.
- Menambahkan helper deteksi `b_detect_measurement_scale_mismatch()` yang hanya aktif jika angka ML/CC atau GR/GRAM pada nama barang sama dengan nilai Isi per 1 UOM Kecil, sehingga representasi valid seperti 100ML = 0,1 LITER tidak dianggap salah.
- Import Master Barang sekarang otomatis mengoreksi pola high-confidence ML→Sentimeter Kubik (UM.0011) dan GRAM→Gram (UM.0004) sebelum stok awal/HPP dikonversi.
- Input/edit Master Barang menolak kombinasi yang terdeteksi salah skala dan memberi pesan koreksi agar data baru tidak mengulang kesalahan yang sama.
- Setelah barang mempunyai stock_movements, Isi per UOM Kecil dan Satuan Ukur Coretax tidak dapat diubah langsung dari Master Barang agar makna Qty historis tidak berubah; koreksi data lama dilakukan melalui tool integritas terkontrol.
- Menambahkan `upgrade_stock_measurement_integrity_v2107.php` di Pengaturan untuk preview dan perbaikan data existing secara aman. Barang yang sudah mempunyai mutasi stok selain opening atau sudah dipakai pada item transaksi dilewati dan harus diperiksa manual.
- Untuk opening stock yang terbukti diinput dalam LITER/KILOGRAM, tool memperbaiki Qty UOM kecil ×1.000 dan HPP/UOM kecil ÷1.000 tanpa mengubah nilai persediaan rupiah; saldo `product_stocks` dan `stock_movements` diperbaiki bersamaan.
- Multiplier Pricelist LITER/KILOGRAM/ML/GRAM pada barang terdampak ikut disesuaikan agar transaksi berikutnya memakai Qty dan harga per satuan yang benar; harga jual/cost basis per satuan pilihan tidak diubah.
- Laporan Valuasi Stok sekarang memeriksa indikasi salah skala sebelum menampilkan data dan memberi peringatan jelas beserta shortcut ke tool V2.10.7 bila ditemukan.
- Tampilan rantai Qty untuk UM.0011 dan UM.0004 sekarang juga menampilkan ekuivalen yang mudah dibaca, misalnya Sentimeter Kubik → Liter dan Gram → Kilogram, tanpa mengubah kode Satuan Ukur Coretax yang tersimpan.
- Tidak mengubah rumus nilai persediaan/moving weighted average. Perbaikan hanya menormalkan unit, Qty internal, HPP per UOM kecil, dan multiplier yang sebelumnya salah skala.
- Versi aplikasi dinaikkan dari V2.10.6 menjadi V2.10.7.

V2.10.6 - TEMPLATE CETAK PEMBELIAN & PENJUALAN GAYA FAKTUR (11 AGUSTUS 2026)
----------------------------------------------------------------------------
- Mendesain ulang template cetak transaksi Pembelian dan Penjualan mengikuti gaya visual referensi: identitas perusahaan di kiri, judul dokumen besar di kanan, garis pemisah header, informasi dokumen tiga kolom, tabel item rapat, catatan, tanda tangan, dan ringkasan total di kanan bawah.
- Faktur Penjualan menggunakan judul `FAKTUR PENJUALAN`; Faktur Pembelian menggunakan `FAKTUR PEMBELIAN`; Purchase Order, Surat Jalan, serta Bukti Pelunasan memakai bahasa visual yang sama.
- Faktur/PO menampilkan kolom No, Nama Barang, Quantity, Satuan, Harga, dan Jumlah. Surat Jalan hanya menampilkan data barang, Quantity, Satuan, dan Keterangan tanpa memaksakan kolom harga.
- Satuan yang dicetak mengikuti satuan transaksi yang dipilih (UOM kecil/UOM besar/LITER/KILOGRAM/dll), bukan selalu UOM kecil. Harga yang dicetak juga memakai harga input pada satuan transaksi tersebut.
- Keterangan per-item dicetak sebagai baris penuh di bawah barang seperti pada contoh, sehingga catatan panjang V2.10.2 tetap terbaca tanpa mempersempit kolom utama.
- Ringkasan Faktur Penjualan menampilkan Total, Disc Faktur, DPP Nilai Lain, PPN, Total Nett, dan Sisa Piutang; Faktur Pembelian menampilkan Total, Disc Faktur, PPN, Total Nett, Sudah Dibayar, dan Sisa Hutang.
- Area tanda tangan Faktur Penjualan/Surat Jalan disusun Penerima, Acc, dan Pengirim; dokumen pembelian disesuaikan dengan alur penerimaan/distributor.
- Tetap mendukung pilihan Kop Default, By Text (`idcom.txt`), atau Tanpa Kop serta pilihan kertas Epson LX-310 8.5×5.5, LX-310 9.5×11, dan A4.
- Dokumen PO, Faktur Pembelian, Surat Jalan, dan Faktur Penjualan menggunakan A4 landscape ketika mode A4 dipilih agar proporsi mendekati referensi; mode LX-310 tetap memakai ukuran continuous form yang sudah ada.
- Template baru hanya diterapkan pada dokumen transaksi Pembelian/Penjualan; cetak Biaya, Master Data, Laporan, dan modul lain tidak diubah.
- Tidak mengubah data transaksi, rumus subtotal/diskon/PPN, stok, HPP, approval, maupun struktur database. Tidak memerlukan upgrade SQL.
- Versi aplikasi dinaikkan dari V2.10.5 menjadi V2.10.6.

V2.10.5 - VALUASI STOK HANYA MENAMPILKAN BARANG YANG MASIH ADA STOK (11 AGUSTUS 2026)
-------------------------------------------------------------------------------------
- Memperbaiki Laporan Valuasi Stok agar hanya menampilkan barang dengan stok akhir lebih besar dari 0 pada tanggal akhir periode laporan.
- Barang dengan stok akhir 0 tidak lagi ditampilkan pada tabel valuasi.
- Barang dengan stok akhir negatif juga tidak ditampilkan karena tidak termasuk persediaan yang tersedia; kondisi stok minus tetap dapat ditelusuri melalui Kartu Stok/Detil Stok.
- Filter mengikuti tanggal `Sampai` yang dipilih. Pada laporan historis, barang ditampilkan berdasarkan saldo stok pada akhir periode tersebut, bukan berdasarkan stok hari ini.
- Jumlah barang pada kartu ringkasan dan header rincian sekarang hanya menghitung barang yang masih mempunyai stok pada akhir periode.
- Total Nilai Stok Awal, Pembelian, HPP Penjualan, dan Nilai Stok Akhir dihitung dari baris barang yang tampil sehingga footer tabel dan kartu ringkasan tetap konsisten.
- Mengubah empty-state menjadi informasi bahwa tidak ada barang dengan stok akhir lebih dari 0 pada periode yang dipilih.
- Tidak mengubah rumus moving weighted average, mutasi stok, HPP, transaksi, maupun struktur database.
- Tidak memerlukan upgrade SQL.
- Versi aplikasi dinaikkan dari V2.10.4 menjadi V2.10.5.

V2.10.4 - LAPORAN VALUASI STOK LEBIH RESPONSIVE (11 AGUSTUS 2026)
-----------------------------------------------------------------
- Memperbaiki tampilan Laporan Valuasi Stok agar lebih nyaman pada desktop, tablet, dan perangkat mobile tanpa mengubah rumus/perhitungan valuasi.
- Filter periode dibuat adaptif: dua tanggal dan tombol sejajar pada layar lebar, lalu otomatis menjadi satu kolom dengan tombol penuh pada layar kecil.
- Kartu ringkasan Nilai Stok Awal, Pembelian, HPP Penjualan, dan Nilai Stok Akhir dibuat lebih fleksibel; nominal menyesuaikan lebar kartu dan layout berubah 4/2/1 kolom sesuai ukuran layar.
- Tabel valuasi 11 kolom diberi lebar minimum yang stabil sehingga isi angka, Qty, dan nilai uang tidak terjepit atau pecah baris secara tidak wajar.
- Menambahkan horizontal scrolling yang lebih nyaman untuk tablet/HP beserta petunjuk geser pada layar <= 1024px.
- Kolom Barang dibuat sticky pada layar tablet/desktop agar nama barang tetap terlihat saat tabel digeser horizontal.
- Kolom numerik diratakan ke kanan dan dibuat nowrap; nama/kode barang tetap dapat membungkus dengan aman.
- Card header, period label, formula, padding tabel, dan ukuran font diringkas secara adaptif pada layar kecil.
- Perubahan hanya pada responsivitas/tampilan; query stok, HPP moving average, nilai awal, pembelian, penjualan, penyesuaian, dan nilai akhir tidak diubah.
- Tidak memerlukan perubahan database atau upgrade SQL.
- Versi aplikasi dinaikkan dari V2.10.3 menjadi V2.10.4.

V2.10.3 - SETUP OTOMATIS MEMBUAT DATABASE (11 AGUSTUS 2026)
-----------------------------------------------------------
- Memperbaiki alur setup instalasi baru agar nama database yang diinput tidak harus sudah tersedia sebelum tombol Simpan Koneksi ditekan.
- Setup sekarang membuka koneksi ke server MySQL tanpa `dbname` terlebih dahulu, mengecek `information_schema.schemata`, lalu membuat database sesuai nama yang diinput apabila database belum ada.
- Menghindari pola SQL `CREATE DATABASE ?` karena nama database/identifier tidak dapat dipasang sebagai prepared-statement placeholder dan dapat memicu SQLSTATE 42000 / error 1064.
- Nama database divalidasi maksimal 64 karakter dan dibatasi ke huruf, angka, underscore (_), minus (-), serta dollar ($), kemudian tetap di-quote dengan backtick sebelum CREATE DATABASE.
- Database baru dibuat dengan CHARACTER SET utf8mb4 dan COLLATE utf8mb4_unicode_ci.
- Setelah database dibuat/ditemukan, setup menguji koneksi langsung ke database tersebut, baru menyimpan host, port, nama database, username, serta password terenkripsi ke konfigurasi.
- Tombol setup diperjelas menjadi `Simpan Koneksi & Buat Database`.
- Jika user MySQL tidak memiliki privilege CREATE DATABASE (umum pada sebagian shared hosting/cPanel), setup menampilkan pesan khusus agar database/user dibuat atau diberi privilege melalui cPanel; database yang sudah tersedia tetap dapat digunakan seperti biasa.
- Proses `Instal Database Lengkap` tetap terpisah setelah koneksi disimpan, sehingga pembuatan database dan pembuatan/sinkronisasi tabel dapat didiagnosis dengan lebih aman.
- Tidak mengubah struktur tabel aplikasi, transaksi, stok, HPP, Coretax, atau data existing.
- Versi aplikasi dinaikkan dari V2.10.2 menjadi V2.10.3.

V2.10.2 - KETERANGAN DINAMIS PEMBELIAN & PENJUALAN (11 AGUSTUS 2026)
--------------------------------------------------------------------
- Membatasi perubahan hanya pada modul Pembelian dan Penjualan; Master Data, Biaya, Pengaturan, dan modul lain tidak diubah menjadi textarea dinamis.
- Mengubah Keterangan header menjadi textarea auto-grow pada Purchase Order, Invoice Pembelian, Barang Keluar/Penjualan, dan Invoice Penjualan.
- Keterangan Pelunasan Pembelian dan Pelunasan Penjualan juga menggunakan textarea auto-grow.
- Mengubah Keterangan per-item pada PO, Invoice Pembelian, Barang Keluar, dan Invoice Penjualan menjadi textarea dinamis; tinggi baris tabel bertambah otomatis mengikuti isi.
- Textarea dimulai ringkas dan bertambah tinggi saat teks/baris bertambah, tanpa scrollbar vertikal internal dan tanpa batas jumlah baris pada sisi antarmuka.
- Menambahkan handler global `.auto-grow-note` yang hanya aktif pada field transaksi yang ditandai, termasuk baris item yang dibuat dinamis melalui JavaScript.
- Mempertahankan line break Keterangan pada halaman detail transaksi agar paragraf/baris yang diketik tidak diratakan menjadi satu baris.
- Memperbesar kolom `notes` item transaksi dari VARCHAR(255) menjadi TEXT pada `purchase_order_items`, `purchase_invoice_items`, `sales_items`, dan `sales_invoice_items` agar Keterangan panjang tidak terpotong.
- Menambahkan `upgrade_transaction_notes_v2102.php` untuk upgrade database lama; instalasi baru langsung menggunakan TEXT melalui `database.sql`.
- Upgrade hanya mengubah kapasitas Keterangan item dan tidak mengubah qty, harga, stok, HPP, nomor dokumen, approval, atau transaksi yang sudah tersimpan.
- Versi aplikasi dinaikkan dari V2.10.1 menjadi V2.10.2.

V2.10.1 - NOMOR PEMBELIAN & PENJUALAN CUSTOM / OTOMATIS (11 AGUSTUS 2026)
-------------------------------------------------------------------------
- Menambahkan input opsional No. Pembelian / PO custom pada form Purchase Order baru.
- Menambahkan input opsional No. Penjualan / Barang Keluar custom pada form Penjualan baru.
- Jika field nomor custom dikosongkan, sistem tetap menggunakan nomor otomatis berdasarkan Kode Perusahaan, jenis dokumen, periode YYYYMM, dan sequence seperti versi sebelumnya.
- Preview nomor otomatis tetap ditampilkan di bawah field tanpa mengisi field custom, sehingga preview tidak salah dianggap sebagai nomor manual saat form disimpan.
- Perubahan tanggal dokumen hanya memperbarui preview nomor otomatis; nomor custom yang sedang diketik tidak ditimpa.
- Nomor custom maksimal 60 karakter, spasi di awal/akhir dibersihkan, dan karakter kontrol tidak diperbolehkan.
- Menambahkan validasi duplikat sebelum insert serta tetap mengandalkan UNIQUE KEY database sebagai pengaman race condition; nomor custom yang sudah pernah digunakan, termasuk record soft-delete, tidak dapat dipakai ulang.
- Nomor custom hanya dapat ditentukan saat pembuatan dokumen. Setelah PO/Penjualan tersimpan, nomor dikunci agar referensi approval, invoice, surat jalan, laporan, export, dan audit tetap konsisten.
- No. SJ pada Penjualan tetap otomatis dan tidak ikut menjadi custom pada versi ini.
- Multi-Tab Draft Workspace V2.10.0 ikut menyimpan/memulihkan No. PO atau No. Penjualan custom per tab.
- Nomor custom yang mengikuti pola nomor otomatis tetap terbaca oleh generator sequence, sehingga nomor otomatis berikutnya tidak bertabrakan.
- Tidak memerlukan perubahan struktur database atau upgrade SQL.
- Versi aplikasi dinaikkan dari V2.10.0 menjadi V2.10.1.

V2.10.0 - MULTI-TAB DRAFT WORKSPACE PO & BARANG KELUAR (11 AGUSTUS 2026)
------------------------------------------------------------------------
- Menambahkan Multi-Tab Draft Workspace pada Input Purchase Order dan Input Penjualan / Barang Keluar agar transaksi yang sedang diketik dapat ditinggalkan sementara tanpa harus mengulang dari awal.
- Setiap form transaksi baru mendapat `draft key` unik 32 karakter pada URL. Dua atau lebih tab PO/BKO dapat digunakan bersamaan tanpa saling menimpa draft.
- Header dan seluruh baris item disimpan otomatis ke `sessionStorage` browser per tab, termasuk distributor/pelanggan, tanggal, status, keterangan, barang, Qty, Satuan Qty, Harga, Satuan Harga, dan keterangan item.
- Reload pada tab transaksi dengan draft key yang sama akan memulihkan draft otomatis. Draft browser dihapus saat form benar-benar disubmit agar data lama tidak ikut terbawa ke transaksi berikutnya.
- Menambahkan tombol `＋ Barang di Tab Baru` pada Input PO dan Barang Keluar bagi user yang memiliki permission Tambah Barang.
- Pada Input PO, distributor yang sedang dipilih diteruskan ke form Tambah Barang di tab baru sehingga Nama Distributor otomatis terisi pada Master Barang baru.
- Setelah Master Barang disimpan dari mode workspace, halaman master memberi petunjuk untuk kembali ke tab transaksi serta tombol `Tutup Tab Ini`.
- Menambahkan tombol `↻ Refresh Barang` pada PO dan `↻ Refresh Barang & Stok` pada Barang Keluar tanpa reload penuh halaman transaksi.
- Daftar barang otomatis di-refresh ketika user kembali/fokus ke tab transaksi. PO mengambil ulang barang aktif sesuai distributor; Barang Keluar mengambil ulang barang, stok tersedia, konversi UOM, dan Pricelist terbaru.
- Menambahkan endpoint ringan `workspace_products.php` dengan permission check serta response JSON no-cache untuk refresh master barang tanpa memuat ulang seluruh form.
- Validasi stok V2.9.6 tetap berlaku setelah refresh: barang stok kosong pada Barang Keluar tetap tidak dapat diorder dan Qty tidak boleh melebihi stok tersedia.
- Nomor PO, BKO, dan SJ tetap hanya dikunci saat Simpan berhasil; autosave draft tidak mengonsumsi nomor dokumen.
- Tidak memerlukan perubahan struktur database atau upgrade SQL.
- Versi aplikasi dinaikkan dari V2.9.9 menjadi V2.10.0.

V2.9.9 - SINKRONISASI MARKUP DEFAULT KE PRICELIST OTOMATIS (11 AGUSTUS 2026)
----------------------------------------------------------------------------
- Memperbaiki perilaku Markup Default Pricelist: ketika persentase default diubah pada Pengaturan, administrator kini dapat langsung menerapkannya ke Pricelist metode Markup Otomatis yang sudah ada.
- Opsi `Terapkan ke Pricelist Markup Otomatis yang sudah ada` aktif secara default pada Pengaturan. Jika tidak dicentang, perubahan hanya menjadi default untuk Pricelist baru/transaksi berikutnya seperti perilaku versi sebelumnya.
- Saat opsi sinkronisasi aktif, sistem hanya memperbarui record Markup yang persentase/harga jualnya tidak sesuai dengan Markup Default. Karena itu, data yang default-nya sudah telanjur diubah sebelum memasang V2.9.9 dapat diperbaiki cukup dengan membuka Pengaturan lalu Simpan Pengaturan sekali.
- Sinkronisasi hanya memproses record Pricelist aktif dengan `pricing_method = markup`; Pricelist `manual` tidak diubah.
- Harga jual dihitung ulang dari snapshot HPP pada record yang sama: `unit_price = cost_basis × (1 + markup / 100)` dengan pembulatan 2 desimal.
- Sinkronisasi tidak mengubah `cost_basis`, Satuan Harga, multiplier UOM, tanggal berlaku, barang, distributor, maupun data transaksi penjualan/pembelian yang sudah tersimpan.
- Proses simpan Pengaturan dan sinkronisasi Pricelist dijalankan dalam satu transaksi database; jika sinkronisasi gagal, perubahan setting ikut dibatalkan agar data tetap konsisten.
- Menampilkan jumlah Pricelist Markup Otomatis yang akan mengikuti perubahan dan jumlah Pricelist Manual yang dilindungi langsung pada halaman Pengaturan.
- Menambahkan audit log perubahan markup lama → baru serta jumlah Pricelist otomatis yang disinkronkan.
- Sinkronisasi massal hanya tersedia bagi user yang memiliki permission Edit Pricelist; user yang hanya dapat mengubah Pengaturan tetap dapat mengganti default tanpa mengubah Pricelist lama.
- Tidak memerlukan perubahan struktur database atau upgrade SQL.
- Versi aplikasi dinaikkan dari V2.9.8 menjadi V2.9.9.

V2.9.8 - KONVERSI STOK AWAL & HARGA RATA-RATA BERDASARKAN SATUAN TRANSAKSI (11 AGUSTUS 2026)
--------------------------------------------------------------------------------------------
- Memperbaiki import Stok Awal dan Harga Rata-rata agar Qty serta harga dapat diinput menggunakan satuan transaksi yang tersedia pada Master Barang, termasuk UOM kecil, UOM besar, KG/KILOGRAM, GRAM, L/LITER, ML, CC, dan satuan ukur terkait.
- Menambahkan kolom opsional `Satuan Harga Rata-rata` pada Import Master Barang dan Import Detil Barang/Stok.
- Stok internal tetap dinormalisasi ke jumlah UOM kecil (`qty_small`) dan HPP rata-rata tetap disimpan sebagai harga per 1 UOM kecil (`avg_cost`) agar moving average, kartu stok, valuasi, pembelian, dan penjualan tetap konsisten.
- Harga yang diinput per KG/LITER/dll sekarang dikonversi ke HPP per UOM kecil sebelum disimpan. Contoh barang 500 ML: 2 LITER @ Rp40.000/LITER menjadi 4 UOM kecil, HPP Rp20.000/UOM kecil, nilai persediaan Rp80.000.
- Contoh barang 200 GRAM: 7 KILOGRAM @ Rp793.000/KILOGRAM menjadi 35 UOM kecil, HPP Rp158.600/UOM kecil, nilai persediaan Rp5.551.000.
- Jika template lama tidak memiliki `Satuan Harga Rata-rata` dan Satuan Stok Awal adalah satuan ukur seperti KG/LITER/GRAM/ML, importer otomatis menganggap Harga Rata-rata memakai satuan yang sama. Untuk UOM stok seperti BKS/BTL/DUS, perilaku lama tetap dipertahankan: Harga Rata-rata dianggap per UOM kecil.
- Pricelist otomatis dari stok awal sekarang mempertahankan satuan harga pilihan (misalnya LITER/KILOGRAM) beserta multiplier-nya, sementara cost basis tetap ekuivalen dengan HPP rata-rata internal.
- Input Stok Awal manual juga mempertahankan Satuan Harga yang dipilih ke Pricelist otomatis.
- Import Master Barang dengan opsi `Perbarui data lama` dapat menghitung ulang stok awal yang sebelumnya sudah diimport selama belum ada transaksi stok selain opening; hal ini memudahkan koreksi data V2.9.7 tanpa menghapus transaksi secara manual.
- Menambahkan resolver satuan import yang memahami key, label UOM, alias KG/KILOGRAM, L/LITER, GRAM, ML/CC, serta kode/nama Satuan Ukur Coretax.
- Memperbarui template Excel Master Barang dan Detil Barang/Stok beserta petunjuk contoh konversi.
- Tidak mengubah struktur database dan tidak mengubah stok yang sudah memiliki transaksi selain opening.
- Versi aplikasi dinaikkan dari V2.9.7 menjadi V2.9.8.

V2.9.7 - PRICELIST OTOMATIS DARI STOK AWAL / HARGA RATA-RATA (11 AGUSTUS 2026)
------------------------------------------------------------------------------
- Memperbaiki kasus setelah Import Master Barang beserta Stok Awal dan Harga Rata-rata: data stok sudah masuk tetapi barang belum muncul pada halaman Pricelist.
- Akar masalah: proses import sebelumnya hanya mengisi `product_stocks.avg_cost` dan mutasi opening, tanpa membuat record pada tabel `price_lists`.
- Import Master Barang sekarang otomatis membuat Pricelist saat Stok Awal memiliki Harga Rata-rata > 0.
- Import Stok Awal terpisah juga otomatis membuat / memperbarui Pricelist otomatis dari Harga Rata-rata.
- Input Stok Awal manual pada Detil Barang/Stok memakai perilaku yang sama agar hasil antara input manual dan import konsisten.
- HPP Dasar Pricelist menggunakan Harga Rata-rata per UOM kecil; Harga Jual dihitung memakai Markup Default perusahaan.
- Satuan harga awal Pricelist mengikuti UOM kecil barang sehingga nominal HPP stok tidak berubah akibat konversi tersembunyi.
- Pricelist manual atau Pricelist aktif hasil transaksi yang sudah tersedia tidak ditimpa oleh sinkronisasi stok awal.
- Pricelist otomatis dari stok awal diberi marker `[STOK_AWAL]` sehingga dapat dikenali dan diperbarui saat stok awal di-replace.
- Menambahkan tool `sync_pricelist_from_stock_v297.php` untuk membuat Pricelist dari data stok/harga rata-rata yang sudah terlanjur diimport pada versi sebelumnya; tidak perlu import ulang barang.
- Halaman Pricelist menampilkan peringatan bila masih ada barang dengan HPP rata-rata > 0 tetapi belum mempunyai Pricelist serta shortcut ke tool sinkronisasi bagi user yang berhak mengubah Pengaturan.
- Batas tampilan daftar Pricelist dinaikkan dari 500 menjadi 1.000 baris agar import master sekitar 786 barang dapat terlihat seluruhnya tanpa harus menggunakan pencarian satu per satu.
- Pengaturan Administrator ditambahkan shortcut `Sinkronkan Pricelist Stok Awal`.
- Tidak mengubah qty stok, nilai persediaan, HPP moving average, transaksi pembelian/penjualan, Coretax, permission, atau struktur database.
- Versi aplikasi dinaikkan dari V2.9.6 menjadi V2.9.7.

V2.9.6 - VALIDASI STOK PENJUALAN / BARANG KELUAR (11 AGUSTUS 2026)
------------------------------------------------------------------
- Memperketat Input Penjualan / Barang Keluar agar barang dengan stok kosong tidak dapat diorder.
- Barang aktif yang stoknya 0 tetap dikenali sistem, tetapi dinonaktifkan dari hasil pilihan barang baru dan diberi keterangan STOK KOSONG — TIDAK DAPAT DIORDER.
- Menambahkan validasi langsung pada form: Qty transaksi tidak boleh melebihi stok tersedia setelah memperhitungkan konversi UOM besar/kecil.
- Menampilkan batas Qty maksimum sesuai Satuan Qty yang dipilih dan pesan merah ketika Qty melebihi stok.
- Menambahkan validasi server-side saat Simpan & Ajukan Approval sehingga request manual/manipulasi browser tetap tidak dapat menyimpan barang stok kosong atau Qty di atas stok.
- Validasi server mengunci baris stok saat pengecekan penyimpanan untuk membaca saldo stok secara konsisten pada saat transaksi diproses.
- Validasi stok pada tahap approval tetap dipertahankan sebagai lapisan pengaman kedua bila stok berubah setelah Barang Keluar disimpan.
- Tidak mengubah perhitungan HPP, metode moving average, proses invoice, nomor dokumen, Coretax, permission, maupun struktur database.
- Versi aplikasi dinaikkan dari V2.9.5 menjadi V2.9.6.

V2.9.5 - PENGECEKAN DATA DISTRIBUTOR DOUBLE (11 AGUSTUS 2026)
-------------------------------------------------------------
- Menambahkan tool Cek Data Distributor Double pada Master Data Distributor.
- Pengecekan dilakukan tanpa menghapus atau mengubah data distributor.
- Mendeteksi Kode Distributor yang sama setelah normalisasi huruf/spasi.
- Mendeteksi NPWP yang sama berdasarkan digit sehingga titik, strip, dan spasi tidak memengaruhi hasil.
- Mendeteksi Nama Distributor yang sama setelah normalisasi huruf besar/kecil, tanda baca, dan spasi berlebih.
- Hasil dibagi menjadi tingkat Kritis untuk Kode/NPWP dan Perlu cek untuk Nama Distributor.
- Menampilkan jumlah pemakaian setiap distributor pada Data Barang, PO, Invoice Pembelian, dan Pricelist agar pemeriksaan data aman dilakukan.
- Menambahkan unduh hasil pengecekan ke CSV.
- Menambahkan tombol Cek Data Double pada halaman Data Distributor dan shortcut Cek Distributor Double pada Pengaturan untuk administrator.
- Tidak ada perubahan struktur database dan tidak ada proses merge/hapus otomatis.
- Versi aplikasi dinaikkan dari V2.9.4 menjadi V2.9.5.

JCOM INVENTORY — CHANGELOG LENGKAP

Urutan riwayat: versi terbaru sampai versi awal aplikasi.
Tanggal rilis awal V1 tidak seluruhnya tercatat. Bagian V1 direkonstruksi dari
source, database, README, QA report, dan riwayat pengembangan proyek.

V2.9.4 - OPTIMASI PERFORMA DATA BARANG & TRANSAKSI (10 AGUSTUS 2026)
--------------------------------------------------------------------
- Memperbaiki jeda saat membuka Input Purchase Order setelah Master Barang berisi ratusan data: konfigurasi isi/UOM seluruh barang sekarang dimuat secara bulk, bukan satu query per barang.
- Memperbaiki jeda utama pada Input Penjualan / Barang Keluar: pricelist terbaru seluruh barang dan konfigurasi UOM dimuat dengan query bulk. Pola sebelumnya dapat menghasilkan lebih dari 1.500 query saat ±786 barang aktif tersedia.
- Mengoptimalkan Detil Barang/Stok agar konfigurasi satuan seluruh barang tidak lagi dibaca satu per satu.
- Mengoptimalkan Pricelist: halaman daftar tidak lagi menghitung HPP seluruh Master Barang; pada form, HPP pembelian terakhir dimuat hanya untuk barang yang dipilih melalui lookup ringan.
- Mengoptimalkan live-search dropdown dengan menghapus pemanggilan computed style untuk setiap option pada setiap pengetikan dan menyimpan teks pencarian yang sudah dinormalisasi.
- Menambahkan `pricelist_basis_lookup.php` untuk lazy-load HPP/pricelist basis per barang.
- Menambahkan `upgrade_performance_v294.php` untuk index database pada products, price_lists, purchase_order_items, purchase_invoice_items, purchase_orders, sales, dan sales_invoice_items.
- Menambahkan index yang sama ke database.sql untuk instalasi baru.
- Index tambahan mempercepat pencarian pricelist terbaru, pemilihan PO yang masih terbuka, pemilihan BKO/SJ yang masih dapat ditagih, serta perhitungan qty reserved invoice.
- Perubahan tidak mengubah stok, HPP, nominal transaksi, data approval, format nomor dokumen, permission, maupun data Coretax.
- Versi aplikasi dinaikkan dari V2.9.3 menjadi V2.9.4.

V2.9.3 - SATUAN UKUR CORETAX PADA MASTER BARANG (10 AGUSTUS 2026)
-----------------------------------------------------------------
- Mengubah konsep "Satuan Volume / Isi" pada Data Barang menjadi "Satuan Ukur Coretax".
- Pilihan Satuan Ukur Data Barang sekarang memakai referensi kode Coretax UM.0001 sampai UM.0033 (Metrik Ton, Kilogram, Liter, Unit, Piece, Boks, Lembar, dan seterusnya).
- Kolom database `content_unit` dipertahankan untuk kompatibilitas, tetapi nilai baru disimpan sebagai kode UM.xxxx sehingga tidak memerlukan perubahan struktur transaksi lama.
- Menambahkan normalisasi kompatibilitas untuk data lama: ML/CC → UM.0011 Sentimeter Kubik, LITER → UM.0007 Liter, GRAM → UM.0004 Gram, dan KG/KILOGRAM → UM.0003 Kilogram.
- Mengubah export Faktur Pajak agar kuantitas Coretax dihitung langsung: Qty UOM Kecil × Isi per 1 UOM Kecil, lalu memakai Satuan Ukur Coretax yang dipilih pada barang.
- Menghapus konversi tersembunyi ML/CC → Liter serta Gram → Kilogram pada export Faktur Pajak; harga satuan Coretax tetap dihitung ulang agar total baris tidak berubah.
- Jika Satuan Ukur Coretax pada barang tidak diisi, export tetap menggunakan mapping manual Satuan Ukur Coretax pada Master UOM dan pemetaan otomatis sebagai fallback.
- Memperbarui Data Barang, validasi form, tampilan konversi, pencarian, import Excel, export CSV Master Barang, dan petunjuk Pengaturan agar memakai istilah Satuan Ukur Coretax.
- Memperbarui template Import Master Barang: kolom menjadi "Satuan Ukur Coretax" dan referensi berisi UM.0001–UM.0033.
- Menambahkan `upgrade_product_coretax_measurement_v293.php` untuk memigrasikan nilai legacy pada Master Barang serta snapshot PO, Invoice Pembelian, Barang Keluar, dan Invoice Penjualan.
- Menjaga kompatibilitas key transaksi volume/berat versi sebelumnya (`ml`, `cc`, `liter`, `gram`, `kilogram`) untuk transaksi yang sudah tersimpan.
- Memperbarui data contoh 30 hari agar snapshot Satuan Ukur menggunakan kode UM.xxxx.
- Versi aplikasi dinaikkan dari V2.9.2 menjadi V2.9.3.
- Tidak mengubah stok, HPP, nominal transaksi, approval, permission, config/app.php, atau storage/private.

V2.9.2 - STABILISASI TRANSAKSI, PRICELIST, CETAK, DAN LOG AKTIVITAS USER
------------------------------------------------------------------------
OPTIMASI CETAK DOKUMEN UNTUK EPSON LX-310 (10 AGUSTUS 2026)
- Menambahkan mode kertas khusus pada seluruh dokumen transaksi dari print_document.php: LX-310 8.5×5.5 inch, LX-310 9.5×11 inch, dan A4 fallback.
- Mode default dokumen diubah ke LX-310 8.5×5.5 inch (215,9 × 139,7 mm) untuk continuous form ringkas.
- Mode LX-310 9.5×11 inch (241,3 × 279,4 mm) tersedia untuk dokumen dengan item lebih banyak.
- Margin continuous disesuaikan dengan karakter narrow-carriage LX-310 dan lebar area cetak maksimum printer; mode half memakai kiri/kanan 13 mm, mode full memakai sekitar 19,1 mm per sisi.
- Tipografi dokumen LX-310 memakai font monospace Courier New/Liberation Mono agar karakter dan kolom nominal lebih stabil pada printer dot-matrix.
- Menghilangkan background abu-abu, rounded badge, shadow, gradient, dan efek visual pada mode LX-310; hasil cetak menjadi hitam-putih sederhana.
- Garis tabel, blok supplier/pelanggan, metadata, total, catatan, dan tanda tangan dibuat hitam solid dengan ketebalan ringan agar terbaca oleh head 9-pin tanpa terlalu menghitamkan pita.
- Header tabel otomatis berulang pada halaman berikutnya dan baris item dihindarkan dari pemotongan di tengah.
- Pilihan kertas dapat diubah langsung pada toolbar cetak tanpa mengubah data dokumen atau database.
- Master Data dan laporan tidak dipaksa memakai profil LX-310 ini; styling khusus hanya untuk dokumen transaksi agar layout laporan yang sudah dipadatkan tetap aman.
- Cache key print.css dan print.js diperbarui agar browser mengambil profil Epson terbaru.
- Tidak mengubah database, stok, HPP, nominal transaksi, approval, permission, config/app.php, atau storage/private.

PENYEMPURNAAN KUALITAS CETAK GLOBAL (PRINT POLISH V3)
- Menindaklanjuti hasil cetak PDF Data Distributor: grid tabel terlalu dominan, teks kecil kurang nyaman dibaca, dan header KETERANGAN dapat terpecah menjadi dua baris.
- Font cetak diprioritaskan ke Verdana dengan fallback Tahoma/Segoe UI/Arial untuk membedakan karakter l, I, dan 1 dengan lebih jelas.
- Menghaluskan garis tabel dan mencerahkan header tabel agar teks lebih dominan daripada grid.
- Menghilangkan zebra background pada baris saat print untuk hasil printer mono/fotokopi yang lebih bersih.
- Menaikkan ukuran minimum tabel Master Data, daftar transaksi, laporan, stok, dan Laporan Keuangan secara terkontrol; layout compact tetap dipertahankan.
- Memperbaiki kolom Keterangan Data Distributor agar header tidak pecah menjadi KETERANGA / N.
- Dokumen transaksi PO/Invoice/SJ/Pelunasan tetap memakai ukuran font lebih besar daripada tabel laporan.
- Cache key print.css dinaikkan ke printpolish3.
- Tidak mengubah database, data, rumus transaksi/laporan, stok, HPP, permission, config/app.php, atau storage/private.

PERBAIKAN KETERBACAAN FONT CETAK (GLYPH l / I / 1)
- Menindaklanjuti hasil cetak PDF yang menunjukkan batang huruf kecil/vertikal terlalu tipis pada ukuran tabel kecil.
- Font cetak global diprioritaskan ke Tahoma dengan fallback Verdana, Arial, dan Helvetica agar karakter kecil lebih jelas pada Windows/Chrome/Edge.
- Menghapus forced antialiased/grayscale font smoothing pada mode print yang dapat menipiskan stroke saat diraster ke PDF/printer.
- Teks tabel dicetak hitam penuh dengan header 700 dan isi 400 agar tegas tanpa membuat seluruh tabel menjadi bold.
- Layout compact, ukuran kertas, margin, dan perhitungan/data tidak diubah.
- Cache key print.css diperbarui agar browser tidak memakai aturan font lama.

- Standarisasi Font Cetak Seluruh Modul & Dokumen (10 Agustus 2026)
  * Menetapkan Arial/Helvetica sebagai keluarga font cetak global untuk seluruh modul, laporan, master data, kartu stok, dan dokumen transaksi.
  * Menyamakan bobot tipografi: isi 400, label/subtotal 600, judul/header/grand total 700 agar hierarki cetak lebih konsisten.
  * Mengaktifkan tabular/lining numerals pada tabel, nominal, harga, total, dan ringkasan agar posisi angka lebih lurus.
  * Menyamakan font kop default dan kop berbasis idcom.txt dengan tipografi dokumen.
  * Mempertahankan ukuran khusus tiap modul agar layout compact Data Barang, Pricelist, Laporan Keuangan, dan laporan lain tidak kembali melebar.
  * Mengganti cache key print.css pada layout aplikasi dan print_document.php agar font baru langsung terbaca browser.
  * Tidak mengubah database, angka transaksi/laporan, stok, HPP, permission, config/app.php, atau storage/private.

- Tampilan Label Data Flat / Tanpa Badge (10 Agustus 2026)
  * Master UOM: kolom Status ditampilkan sebagai teks biasa tanpa background, border, badge, shadow, transform, transition, atau animasi.
  * Pricelist: Satuan Harga dan Metode ditampilkan sebagai teks biasa, termasuk saat cetak.
  * Aturan yang sama diterapkan pada badge/status/role/approval/metode/jenis identitas dan label data sejenis di seluruh area konten aplikasi.
  * Badge jumlah pending pada sidebar tetap dipertahankan karena berfungsi sebagai indikator notifikasi.
  * Mode cetak memaksa semua label data menjadi plain text hitam tanpa dekorasi visual.

- Laporan Keuangan Tanpa Footer Cetak (10 Agustus 2026)
  • Menghilangkan footer cetak pada Laporan Keuangan sepenuhnya.
  • financial_report.php dimasukkan ke daftar route tanpa print footer sehingga elemen footer tidak lagi dibentuk oleh template.
  • Menghapus aturan CSS lama yang memaksa footer Laporan Keuangan tampil kembali dengan display:flex !important.
  • Menambahkan fallback CSS print untuk memastikan footer tetap tersembunyi pada cache/template lama.
  • Mengganti cache key print.css agar perubahan langsung terbaca browser.
  • Tidak mengubah angka laporan, database, transaksi, stok, HPP, permission, config/app.php, atau storage/private.

- Jenis Identitas & Opsi Tunggal Tanpa Animasi (10 Agustus 2026)
  • Pilihan Jenis Identitas NPWP/NIK pada Data Pelanggan dibuat radio compact dan statis tanpa transition, transform, glow, atau animasi visual.
  • Jenis ID pada daftar Data Pelanggan tidak lagi memakai badge biru/ungu; ditampilkan sebagai label flat yang stabil.
  • Komponen checklist tunggal sejenis pada Master Data memakai perilaku statis yang sama.
  • Saat cetak, label Jenis ID menjadi teks biasa tanpa badge, background, border, shadow, animation, transition, atau transform.
  • Tidak mengubah validasi NIK/NPWP, data pelanggan, database, transaksi, permission, config/app.php, atau storage/private.

- Cetak Laporan Keuangan Lebih Padat (10 Agustus 2026)
  • Laporan Keuangan dipastikan memakai A4 landscape dengan margin cetak 5 mm / 5 mm / 7 mm.
  • Menghilangkan heading halaman ganda saat print karena judul sudah tersedia pada print header.
  • Memadatkan header perusahaan, periode, kartu KPI, Laba Rugi, Arus Kas, Posisi Keuangan, PPN, dan Aktivitas Pembelian.
  • Memperkecil font/padding tabel Rekap Bulanan, Piutang, dan Hutang dengan header tabel tetap berulang pada halaman berikutnya.
  • Mengurangi page break wajib agar tabel berikutnya dapat memakai sisa ruang halaman yang tersedia.
  • Tidak mengubah angka laporan, rumus, database, transaksi, stok, HPP, permission, config/app.php, atau storage/private.

- Konten & Cetak Tanpa Animasi (10 Agustus 2026)
  • Menghilangkan animation dan transition pada seluruh area konten utama agar halaman tampil langsung tanpa efek fade/slide/gerakan.
  • Menghilangkan efek transform tombol/card/baris tabel saat hover di area konten.
  • Mode cetak memaksa animation/transition menjadi none agar hasil preview/cetak langsung stabil.
  • Animasi/fly-out sidebar tetap dipertahankan karena berada di luar area konten.
  • Tidak mengubah database, transaksi, stok, HPP, permission, config/app.php, atau storage/private.

- Cetak Semua Master Data Tanpa Footer
  • Footer aplikasi dihilangkan pada cetak Data Distributor, Data Pelanggan, Master UOM, Data Barang, Detil Barang/Stok, dan Pricelist.
  • Elemen footer tidak lagi dibentuk oleh template untuk keenam halaman Master Data tersebut.
  • CSS cetak tetap memaksa footer tersembunyi sebagai lapisan kompatibilitas untuk cache/template lama.
  • Header identitas perusahaan dan judul cetak tetap dipertahankan.

Unduh CSV Seluruh Submenu Master Data (10 Agustus 2026)
- Menambahkan tombol “Unduh CSV” pada Data Distributor, Data Pelanggan, Master UOM, Data Barang, Detil Barang/Stok, dan Pricelist.
- CSV mengikuti keyword pencarian q yang sedang aktif pada masing-masing halaman; ekspor dapat memuat hingga 50.000 baris yang sesuai filter.
- Menggunakan format CSV yang sama dengan Invoice Pembelian: UTF-8 BOM, delimiter titik koma, CRLF Windows, dan proteksi formula injection.
- Data Distributor mengekspor kode, nama, PIC, contact, NPWP, status, keterangan, serta waktu dibuat/diperbarui.
- Data Pelanggan mengekspor jenis/nomor identitas, nama, alamat, status, keterangan, serta waktu dibuat/diperbarui.
- Master UOM mengekspor UOM, tipe, mapping Coretax bila tersedia, status, dan keterangan.
- Data Barang mengekspor UOM kecil/besar, definisi konversi, isi/volume, distributor, status, dan keterangan.
- Detil Barang/Stok mengekspor qty stok, konversi UOM, harga rata-rata, nilai persediaan, jumlah mutasi, dan keterangan stok.
- Pricelist mengekspor tanggal berlaku, satuan harga, HPP, markup, harga jual, metode harga, distributor, dan keterangan.
- Export Master Data memakai permission View yang sudah ada, sehingga tidak membutuhkan permission baru maupun upgrade database.
- Tidak mengubah database, data transaksi, stok, HPP, permission existing, config/app.php, atau storage/private.

Cetak Data Barang & Pricelist Lebih Padat (10 Agustus 2026)
- Mengubah cetak Data Barang dan Pricelist menjadi A4 landscape agar seluruh kolom lebih proporsional.
- Memperkecil margin cetak khusus menjadi 6 mm / 5 mm / 8 mm untuk memaksimalkan area tabel.
- Memadatkan header perusahaan, judul cetak, font tabel, badge, padding sel, dan tinggi baris tanpa menghapus kolom data.
- Menghilangkan toolbar/filter/jumlah data dari hasil cetak sehingga halaman langsung berisi header cetak dan tabel.
- Menetapkan proporsi lebar kolom khusus Data Barang dan Pricelist agar nama barang, distributor, UOM, HPP, dan harga jual tetap terbaca.
- Tidak mengubah data, database, transaksi, HPP, Pricelist, permission, config/app.php, atau storage/private.

Penyederhanaan Ringkasan Invoice Pembelian (10 Agustus 2026)
- Menghilangkan kartu ringkasan “Menunggu Persetujuan” pada halaman Detil Pembelian / Invoice.
- Menghilangkan kartu ringkasan “Nilai Invoice Pending” pada halaman Detil Pembelian / Invoice.
- Status approval, filter pending, tombol persetujuan, proses approve/reject, stok masuk, dan pembentukan hutang tetap berfungsi seperti sebelumnya.
- Menghapus query perhitungan total nilai invoice pending yang tidak lagi dibutuhkan oleh tampilan.
- Tidak mengubah database, nilai invoice, stok, hutang, HPP, permission, config/app.php, atau storage/private.

Global Compact Workspace & Tanpa Heading Ganda (10 Agustus 2026)
- Menghilangkan breadcrumb, judul besar, dan kalimat deskripsi di atas konten pada seluruh halaman aplikasi; nama halaman tetap terlihat pada topbar.
- Tombol aksi yang sebelumnya berada pada page heading seperti Tambah, Import, Kembali, Cetak, Export, dan approval tetap ditampilkan sebagai toolbar ringkas.
- Menerapkan workspace desktop 100vh secara global: sidebar, topbar, dan footer tetap diam; scroll atas/bawah hanya terjadi pada area konten utama.
- Memadatkan card, form, filter, tombol, tabel, badge, alert, statistik, dan spacing di seluruh modul agar konsisten dengan Master Data.
- Header tabel dibuat sticky pada area tabel panjang sehingga nama kolom tetap terlihat saat scroll.
- Mobile/tablet tetap menggunakan pola scroll responsif agar aman untuk layar sentuh dan keyboard virtual.
- Tidak mengubah route, permission, database, stok, HPP, perhitungan transaksi, config/app.php, atau storage/private.

Master Data Professional & Content-Only Scroll
- Seluruh area Master Data memakai workspace compact: Distributor, Pelanggan, UOM, Barang, Detil Barang/Stok, Pricelist, dan halaman import yang berada di grup Master.
- Pada desktop, tinggi aplikasi dikunci 100vh sehingga sidebar, topbar, dan footer tetap diam; hanya area konten utama yang bergerak saat scroll atas/bawah.
- Heading, card, form, filter, tombol, tabel, badge, dan spacing Master Data dipadatkan agar lebih profesional dan lebih banyak data terlihat dalam satu layar.
- Header kolom tabel Master Data dibuat sticky agar tetap terlihat ketika isi data panjang.
- Ditambahkan indikator jumlah data pada daftar Master Data utama.
- Mobile/touch tetap memakai scroll normal agar kompatibel dengan layar kecil dan keyboard virtual.

- Sidebar Compact (10 Agustus 2026):
  * Memperkecil lebar sidebar desktop dari 224 px menjadi 190 px agar area kerja aplikasi lebih luas.
  * Memperkecil sidebar tablet/mobile menjadi 210 px.
  * Merapikan tinggi menu utama menjadi sekitar 35 px dan memperkecil ikon, font, padding, brand, serta area user di bagian bawah.
  * Panel submenu fly-out diperkecil menjadi 220 px dengan item sekitar 33 px agar tetap proporsional terhadap sidebar baru.
  * Fly-out hover, status menu aktif, badge approval, navigasi keyboard, permission, dan accordion mobile tetap dipertahankan.
  * Tidak mengubah route, transaksi, database, config/app.php, atau storage/private.

- Penyempurnaan Sidebar Fly-out (10 Agustus 2026):
  * Mendesain ulang sidebar desktop agar lebih ringkas dan modern tanpa mengubah struktur permission atau route.
  * Submenu kini tampil sebagai panel fly-out di sebelah kanan menu utama, sehingga item sidebar tidak terdorong ke bawah ketika kursor diarahkan.
  * Menambahkan header pada panel submenu, highlight menu aktif yang lebih jelas, ikon dalam tile kecil, bayangan panel yang lebih lembut, dan jarak menu yang lebih konsisten.
  * Posisi fly-out otomatis dikoreksi agar tidak keluar dari bagian bawah layar pada resolusi pendek.
  * Klik menu utama dapat mengunci/membuka fly-out dan klik di luar sidebar akan menutup panel yang dikunci.
  * Navigasi keyboard ditingkatkan dengan ArrowRight/ArrowLeft, ArrowUp/ArrowDown, Home, End, Enter, dan Escape.
  * Pada tablet/mobile, sidebar tetap menggunakan accordion agar tetap nyaman untuk layar sentuh.
  * Menu aktif tetap ditandai pada menu utama dan item submenu tanpa membuat fly-out selalu terbuka.
  * Tidak mengubah database, transaksi, stok, HPP, permission, config/app.php, atau storage/private.

- Sidebar Submenu Hover (9 Agustus 2026):
  * Mengubah kelompok sidebar menjadi menu utama bertingkat: Master Data, Pembelian, Penjualan, Keuangan, Faktur Pajak, Laporan, Manajemen Sistem, dan Akun.
  * Pada desktop, submenu otomatis muncul ketika kursor mouse diarahkan ke menu utama.
  * Menu utama yang sedang aktif tetap terbuka agar posisi halaman mudah dikenali.
  * Pada perangkat touch/mobile, submenu tetap dapat dibuka atau ditutup dengan klik.
  * Menambahkan navigasi keyboard pada submenu: ArrowDown/ArrowUp untuk berpindah, ArrowLeft/Escape untuk kembali ke menu utama.
  * Badge persetujuan PO dan Invoice Pembelian tetap ditampilkan pada item submenu.
  * Tidak mengubah permission, route, transaksi, database, atau konfigurasi aplikasi.

- Pilihan Kop Identitas Perusahaan pada Cetak Dokumen (8 Agustus 2026):
  * Menambahkan pilihan Default, By Text, dan Tanpa Kop pada halaman cetak dokumen.
  * Default memakai identitas perusahaan dari Pengaturan seperti sebelumnya.
  * By Text membaca isi file idcom.txt dari root aplikasi dan mempertahankan susunan baris teks.
  * Tanpa Kop menyembunyikan identitas perusahaan tetapi tetap menampilkan judul/status dokumen.
  * Pilihan Default aktif otomatis; By Text dinonaktifkan jika idcom.txt belum tersedia atau kosong.
  * Parameter URL kop=default|text|none dapat dipakai bersama autoprint untuk kebutuhan cetak langsung.
  * Akses HTTP langsung ke idcom.txt diblokir melalui .htaccess.
  * Tidak mengubah data transaksi, perhitungan, database, config/app.php, atau storage/private.

- Navigasi Keyboard Live Search (8 Agustus 2026):
  * Memperbaiki tombol ArrowDown dan ArrowUp pada hasil live search setelah minimal 3 karakter diketik.
  * Enter sekarang memilih item yang sedang disorot, bukan selalu hasil pertama.
  * Home/End dapat berpindah ke hasil pertama/terakhir dan Escape menutup daftar.
  * Item aktif otomatis di-scroll ke area yang terlihat dan ditandai secara visual.
  * Berlaku untuk pencarian Nama Barang, Distributor, Pelanggan, PO, invoice, dan lookup searchable lain yang memakai komponen live search global.

- Normalisasi Import Master Barang untuk UOM Duplikat (8 Agustus 2026):
  * Jika Satuan UOM Kecil dan Satuan UOM Besar pada Excel sama, importer otomatis memakai satu UOM utama dengan rasio 1:1.
  * Contoh PCS + PCS, BTL + BTL, atau DUS + DUS tidak lagi dianggap sebagai pasangan konversi ganda.
  * Jika hanya salah satu UOM diisi, UOM yang tersedia otomatis menjadi UOM utama dengan rasio 1:1.
  * Kolom UOM besar disimpan kosong/NULL untuk UOM tunggal agar transaksi dan validasi tidak membaca konversi palsu.
  * Data lama yang pernah menyimpan UOM sama pada kedua kolom tetap dianggap kompatibel saat update, termasuk barang yang sudah memiliki mutasi stok.
  * Tidak mengubah konversi valid untuk dua UOM yang berbeda, misalnya 12 PCS = 1 DUS.

- Footer Cetak Dokumen Dihilangkan:
  * Menghapus footer nama/kode perusahaan, waktu cetak, dan teks halaman dari dokumen transaksi.
  * Menonaktifkan footer cetak legacy pada seluruh halaman print agar tidak muncul kembali karena CSS lama.
  * Tidak mengubah header, isi transaksi, total, tanda tangan, database, maupun perhitungan.
- Menyamakan Cetak Invoice Pembelian dan Invoice Penjualan dengan template Accurate-like dokumen lainnya.
  - Menghapus override CSS invoice lama yang membuat header, tabel, total, catatan, dan tanda tangan berbeda.
  - Invoice kini memakai satu komponen cetak yang sama dengan PO, Surat Jalan, pelunasan, dan biaya.
Tanggal rilis: 3 Agustus 2026

Desain Cetak Dokumen Accurate-like
- Mendesain ulang cetak dokumen transaksi dengan tampilan accounting form yang lebih
  rapi dan profesional, terinspirasi pola layout Accurate tanpa menyalin template asli.
- Header menampilkan kode/logo perusahaan, nama perusahaan, telepon, email, NPWP,
  dan judul dokumen dengan susunan dua kolom.
- Menambahkan blok Supplier/Distributor atau Pelanggan di sisi kiri serta nomor,
  tanggal, jatuh tempo, dan faktur pajak di sisi kanan sesuai jenis dokumen.
- Merapikan tabel item dengan header abu-abu, perataan Qty/Harga/Jumlah, angka tabular,
  dan garis tabel yang lebih ringan.
- Menempatkan catatan di kiri dan ringkasan subtotal/pajak/grand total di kanan bawah.
- Merapikan area tanda tangan dan menambahkan informasi waktu cetak pada footer dokumen.
- Berlaku untuk Purchase Order, Invoice Pembelian, Pelunasan Pembelian, Surat Jalan /
  Barang Keluar, Invoice Penjualan, Pelunasan Penjualan, dan Bukti Biaya.
- Tidak mengubah data transaksi, rumus, stok, HPP, pajak, atau struktur database.

Logo Dokumen Mengikuti Kode Perusahaan
- Mengubah logo teks pada seluruh dokumen cetak agar menggunakan Kode Perusahaan
  dari Setup/Pengaturan, bukan lagi huruf pertama Nama Perusahaan.
- Contoh: kode perusahaan JCOM akan tampil sebagai JCOM pada kotak logo cetak.
- Menyesuaikan ukuran font logo otomatis untuk kode perusahaan 2-12 karakter.
- Tidak mengubah logo antarmuka aplikasi, nomor dokumen, transaksi, atau database.

Penyederhanaan Halaman Pengaturan
- Menghapus seluruh tombol Upgrade dan Perbaikan Database dari halaman Pengaturan.
- Halaman Pengaturan sekarang hanya menampilkan tombol Akun Sistem dan Data Contoh
  30 Hari untuk Administrator.
- File upgrade lama tetap dipertahankan di server untuk kompatibilitas dan dapat
  dijalankan secara manual oleh Administrator bila benar-benar diperlukan.
- Tidak mengubah struktur database, transaksi, stok, HPP, atau hak akses user.

Pricelist Mengikuti Satuan Harga PO
- Menghapus tampilan UOM Kecil dan Satuan UOM Kecil dari form, daftar, pencarian,
  serta template import Pricelist.
- Menambahkan Satuan Harga Pricelist yang mengikuti snapshot Satuan Harga pada
  PO/Invoice Pembelian terakhir, misalnya LITER, KILOGRAM, BKS, DUS, BOTOL,
  PCS, atau satuan kemasan lain pada Master Barang.
- Mengubah Harga Dasar/HPP agar disimpan per Satuan Harga pembelian, bukan
  selalu per UOM kecil.
- Menghitung Harga Jual markup pada satuan yang sama dengan HPP dasar.
- Menyimpan price_unit_key, price_unit_label, dan unit_multiplier sebagai
  snapshot agar harga jual dapat dikonversi dengan benar pada transaksi
  penjualan.
- Input Penjualan otomatis mengambil nominal dan Satuan Harga dari Pricelist
  terbaru; contoh Rp48.700/LITER tetap dibaca sebagai harga per LITER.
- Menambahkan Upgrade Satuan Harga Pricelist untuk memigrasikan Pricelist lama.
  Harga manual lama dikonversi ke satuan harga PO tanpa mengubah nilai ekonomisnya.
- Memperbarui template import Pricelist dan template gabungan Stok + Pricelist.

Log Aktivitas User
- Menambahkan menu Manajemen Sistem → Log Aktivitas User.
- Mencatat login berhasil, login otomatis, login gagal, logout, tambah, ubah,
  hapus, pengajuan, persetujuan, penolakan, proses stok, import, export,
  perubahan pengaturan, pembukaan cetak, dan upgrade database.
- Menyimpan user, role, waktu, modul, aksi, deskripsi, referensi data, IP,
  browser/User Agent, metode HTTP, halaman, dan metadata tambahan.
- Menambahkan filter user, modul, aksi, periode, pencarian, statistik, detail,
  serta export CSV sesuai filter.
- Menambahkan permission activity.view dan activity.export.
- Log dibuat hanya baca; tidak tersedia tombol edit atau hapus dari antarmuka.

Stabilisasi Transaksi Volume dan Harga per Liter/Kilogram
- Memperbaiki presisi qty, faktor konversi, harga, stok, dan HPP menjadi sampai
  8 desimal untuk transaksi ML/LITER dan GRAM/KILOGRAM.
- Memisahkan Satuan Qty dan Satuan Harga pada transaksi agar harga per LITER
  tidak mengubah qty DUS/BTL yang dipilih pengguna.
- Memperbaiki parser angka Indonesia pada PO; nilai 48.700,00 dibaca sebagai
  Rp48.700, bukan 48,7.
- Menampilkan rumus per baris PO untuk memperjelas qty, satuan harga, dan total.
- Menambahkan perbaikan khusus data PO harga per LITER berdasarkan master barang
  dan snapshot transaksi tanpa mengubah stok yang sudah diproses.
- Menyamakan perhitungan browser dan server untuk PO, Barang Masuk, Invoice
  Pembelian, Barang Keluar, dan Invoice Penjualan.
- Memperbaiki transaksi partial volume/berat serta toleransi sisa qty hingga
  0,00000001.
- Memperbaiki Input Stok Awal, CSV, laporan, dan Faktur XLSX agar mempertahankan
  presisi volume/berat.

Perbaikan UOM
- Jika hanya UOM kecil yang tersedia, UOM besar otomatis mengikuti UOM kecil
  dengan rasio 1:1.
- Jika hanya UOM besar yang tersedia, UOM kecil otomatis mengikuti UOM besar
  dengan rasio 1:1.
- Jika UOM kecil dan besar sama, transaksi hanya menampilkan satu pilihan.
- Import Master Barang ikut menormalisasi pasangan UOM yang kosong.

Perbaikan Cetak Dokumen
- Menyeragamkan font cetak ke Arial/Helvetica dengan ukuran yang lebih terbaca.
- Memperbesar metadata, tabel, total, catatan, dan tanda tangan yang sebelumnya
  terlalu kecil.
- Menghapus tampilan Konversi UOM dan keterangan Setara dari cetak Purchase
  Order, Invoice Pembelian, dan Invoice Penjualan.
- Informasi konversi tetap tersedia pada tampilan detail layar untuk audit.
- Tidak mengubah qty, harga, subtotal, pajak, stok, HPP, atau nilai transaksi.

Versi dan Dokumentasi
- Mengubah VERSION.txt menjadi 2.9.2.
- Memperbarui fallback versi pada header, footer, cetak, cache aset, dan metadata
  export agar mengikuti V2.9.2.
- Menyusun ulang changelog lengkap secara berurutan dari V2.9.2 sampai V1.0.0.
- Nama file upgrade V2.9.1 tetap dipertahankan untuk kompatibilitas instalasi.

V2.9.1 - KONVERSI UOM BARANG DAN PERSENTASE MARKUP PRICELIST
------------------------------------------------------------
Tanggal rilis: 30 Juli 2026

Konversi UOM Barang
- Menggabungkan Isi per 1 UOM Kecil ke Master Data Barang bersama Satuan
  Volume / Isi.
- Mendukung konversi berantai, misalnya 1 DUS = 12 PCS dan 1 PCS = 100 ML,
  sehingga 1 DUS = 1.200 ML = 1,2 LITER.
- Stok tetap disimpan dalam UOM kecil.
- Snapshot konversi disimpan pada pembelian dan penjualan agar transaksi lama
  tidak berubah ketika master barang diperbarui.
- Pembelian, penjualan, cetak, CSV, dan Faktur Coretax menggunakan snapshot UOM.
- Menambahkan data contoh transaksi selama 30 hari dengan prefix DEMO30.

Persentase Markup Pricelist
- Menambahkan metode Markup Otomatis dan Harga Manual.
- Menambahkan Harga Dasar/HPP, Persentase Markup, dan Harga Jual.
- Menggunakan rumus Harga Jual = HPP × (1 + Markup/100).
- Menambahkan Markup Default Pricelist pada Pengaturan Perusahaan.
- Pricelist dapat diperbarui otomatis setelah Invoice Pembelian disetujui.
- Pricelist manual dan riwayat harga lama tidak ditimpa otomatis.
- Memperbarui template import Pricelist untuk metode MARKUP dan MANUAL.

V2.8.3 - CORETAX, EXPORT, KEAMANAN KONFIGURASI, DAN PENYEMPURNAAN CETAK
-----------------------------------------------------------------------
Periode rilis: 26–30 Juli 2026

Coretax dan Faktur Pajak
- Menambahkan pilihan manual Satuan Ukur Coretax UM.0001 sampai UM.0033 pada
  Master UOM.
- Menambahkan referensi volume/isi barang untuk pemetaan satuan Coretax.
- Menambahkan menu Faktur Pajak dengan export XLSX per invoice dan per periode.
- Menyimpan riwayat export, checksum, ukuran file, invoice terkait, jumlah
  download, dan file permanen pada storage/exports/faktur_pajak.
- Mendukung template Sample Faktur v1.3 dengan sheet Faktur, DetailFaktur, REF,
  dan Keterangan.
- Menambahkan pilihan identitas pelanggan NPWP atau NIK untuk export Coretax.

Export dan Laporan
- Menambahkan export transaksi dan laporan Pembelian/Penjualan.
- Memperbaiki workbook XLSX kosong dan kompatibilitas Excel/LibreOffice.
- Mengalihkan export operasional menjadi CSV UTF-8 saat XLSX tidak stabil.
- Menambahkan CSV Ringkasan dan CSV Detail Item sesuai filter aktif.
- Menambahkan UTF-8 BOM, delimiter titik koma, CRLF, normalisasi encoding,
  proteksi formula injection, serta audit export.
- Menambahkan permission export khusus pada Role & Permission.

Setup, Akun Sistem, dan Keamanan
- Menambahkan akun programmer sistem juldian dengan akses Administrator penuh.
- Menambahkan users.is_system_account serta halaman Akun Sistem khusus admin.
- Melindungi akun sistem dari edit, nonaktif, dan hapus melalui Manajemen User.
- Mengubah email user menjadi opsional dan menyimpan email kosong sebagai NULL.
- Menambahkan Kode Perusahaan pada setup, pengaturan, dan nomor dokumen baru.
- Menambahkan host, port, database, user, dan password pada setup.php.
- Mengenkripsi password database dengan AES-256-GCM dan menyimpan kunci lokal
  secara terpisah.
- Menambahkan NPWP/NITKU penjual serta konfigurasi identitas Coretax.
- Mengosongkan data awal Master UOM pada instalasi baru agar dapat diisi manual.
- Menambahkan footer Created by Juldian Tan - 0812-7309-4261.

Pelunasan dan Nilai Desimal
- Memperbaiki input nominal Pelunasan Penjualan untuk format angka Indonesia.
- Menampilkan nominal asli dari DECIMAL(18,2) tanpa pembulatan float tambahan.
- Menolak lebih dari dua angka desimal untuk mencegah pembulatan tersembunyi.
- Mempertahankan data form ketika validasi gagal dan mencegah simpan ganda.

Cetak dan Tampilan
- Merapikan cetak master data, PO, invoice, pelunasan, biaya, kartu stok,
  valuasi stok, dan laporan keuangan.
- Menetapkan A4 portrait/landscape sesuai jenis dokumen.
- Menambahkan header tabel berulang, zebra baris, lebar kolom khusus, dan total
  pada halaman terakhir.
- Menghilangkan footer cetak pada modul transaksi/laporan tertentu.
- Memperbaiki Laporan Pembelian dan Penjualan beserta filter dan ringkasan.
- Memperbaiki Kartu Stok, Valuasi Stok, dan garis halaman lanjutan.

V2.8.2 - PENYEDERHANAAN DASHBOARD CETAK
---------------------------------------
Tanggal rilis: 25 Juli 2026

- Menghilangkan tombol Cetak dari halaman Dashboard.
- Tombol Cetak tetap tersedia pada laporan dan dokumen yang mendukung cetak.
- Tidak mengubah database atau transaksi.

V2.8.1 - PERBAIKAN URUTAN LIVE SEARCH STOK PENJUALAN
----------------------------------------------------
Tanggal rilis: 24 Juli 2026

- Barang aktif dengan stok tersedia selalu tampil di atas stok kosong.
- Menggabungkan stok menggunakan SUM untuk mencegah duplikasi hasil.
- Barang stok kosong tetap tersedia di bagian bawah.
- Jumlah stok tetap ditampilkan pada hasil pencarian.

V2.8.0 - LIVE SEARCH BARANG PENJUALAN BERDASARKAN STOK
------------------------------------------------------
Tanggal: 24 Juli 2026

- Mengurutkan pilihan Nama Barang pada Penjualan / Barang Keluar berdasarkan stok.
- Barang aktif yang memiliki stok tampil paling atas.
- Barang aktif dengan stok kosong tetap ditampilkan setelah barang yang tersedia.
- Menampilkan jumlah stok pada setiap hasil live search dalam format UOM besar/kecil.
- Menampilkan informasi stok tersedia di bawah barang yang sudah dipilih.
- Live search tetap berjalan setelah minimal 3 huruf.
- Tidak mengubah struktur database atau proses approval stok.

V2.7.9 - CHANGELOG LENGKAP DARI AWAL APLIKASI
---------------------------------------------
Tanggal: 24 Juli 2026

- Menyusun ulang changelog dari tahap awal pembuatan aplikasi.
- Menambahkan riwayat fondasi sistem, keamanan, master data, transaksi, stok,
  dan laporan sebelum V2.1.0.
- Melengkapi seluruh rilis terdokumentasi mulai V2.1.0 sampai V2.7.9.
- Menambahkan versi yang sebelumnya belum tercantum pada changelog ringkas:
  V2.1.1, V2.1.2, V2.2.0, V2.3.0, V2.3.1, V2.4.0, V2.5.4, V2.5.6,
  V2.5.8.2, dan V2.6.2.
- Menjelaskan alur dan tujuan setiap perubahan secara lebih rinci.
- Tidak mengubah struktur database atau perhitungan transaksi.

V2.7.8 - CHANGELOG PADA PENGATURAN
----------------------------------
Tanggal terdokumentasi: 24 Juli 2026

- Menambahkan changelog.txt pada folder utama aplikasi.
- Menampilkan isi changelog di Pengaturan, tepat di bawah Informasi Sistem.
- Menambahkan tombol Buka File.
- Mengamankan output changelog dengan HTML escaping.
- Menambahkan area scroll agar changelog panjang tidak merusak layout.
- Menambahkan fallback bila file changelog hilang atau kosong.

V2.7.7 - MENGHAPUS ALAT UPGRADE LAMA
------------------------------------
- Menghapus kartu Sinkronisasi Proses / Upgrade V2.6.3 dari Pengaturan.
- Menghapus kartu Perbaikan Rumus UOM V2.7.0 dari Pengaturan.
- Menghapus referensi instruksi upgrade lama dari pesan proses stok.
- Menonaktifkan URL maintenance lama agar tidak dapat dijalankan ulang.
- Tidak menghapus transaksi, stok, hutang, piutang, atau konfigurasi aktif.

V2.7.6 - VERSI APLIKASI PADA FOOTER
-----------------------------------
- Menghapus tampilan versi PHP dari footer.
- Footer menampilkan Versi Aplikasi dari VERSION.txt.
- Prefix V ditambahkan otomatis tanpa menghasilkan prefix ganda.
- Menambahkan fallback Tidak diketahui.

V2.7.5 - VERSI APLIKASI PADA INFORMASI SISTEM
---------------------------------------------
- Menambahkan baris Versi Aplikasi pada Pengaturan > Informasi Sistem.
- Nilai dibaca otomatis dari VERSION.txt.
- Menambahkan fallback Tidak diketahui bila file kosong atau tidak terbaca.

V2.7.4 - LIVE LOOKUP TRANSAKSI
------------------------------
- Menambahkan live lookup pada Nama Distributor di PO.
- Menambahkan live lookup pada Pilih Purchase Order di Invoice Pembelian.
- Menambahkan live lookup pada Invoice Hutang di Pelunasan Pembelian.
- Menambahkan live lookup pada Nama Pelanggan di Barang Keluar.
- Menambahkan live lookup pada Pilih BKO/Surat Jalan di Invoice Penjualan.
- Menambahkan live lookup pada Invoice Piutang di Pelunasan Penjualan.
- Klik kolom kosong menampilkan pilihan yang masih valid.
- Enter dapat memilih hasil pertama.
- Filter status transaksi tetap dipertahankan:
  - PO harus approved dan belum diterima penuh.
  - Invoice Hutang/Piutang harus masih memiliki saldo.
  - BKO/SJ harus approved, stok sudah diproses, dan masih memiliki sisa qty.
  - Distributor dan Pelanggan harus aktif.

V2.7.3 - LIVE SEARCH ITEM PO DAN PENJUALAN
------------------------------------------
- Nama Barang pada PO menjadi live search.
- Klik kolom kosong tetap menampilkan pilihan item.
- Ketik minimal 3 huruf menyaring nama barang secara langsung.
- Item PO tetap dibatasi berdasarkan distributor.
- Placeholder meminta pengguna memilih distributor sebelum mencari barang.
- Nama Barang pada Penjualan / Barang Keluar memakai live search yang sama.
- Mendukung baris item baru yang ditambahkan secara dinamis.
- Product ID tetap menjadi nilai yang disimpan di database.

V2.7.2 - PENCARIAN OTOMATIS MINIMAL 3 HURUF
-------------------------------------------
- Kolom pencarian daftar otomatis berjalan setelah minimal 3 huruf.
- Menambahkan debounce 450 ms agar pencarian tidak terlalu sering dikirim.
- Input 1 atau 2 huruf menampilkan petunjuk tanpa mengirim form.
- Mengosongkan kolom menampilkan seluruh data kembali.
- Mengubah dropdown master/dokumen menjadi lookup yang dapat dicari.
- Mendukung pencarian Distributor, Pelanggan, Barang, PO, Invoice Pembelian,
  BKO/SJ, dan Invoice Penjualan.
- Menampilkan maksimum 50 hasil.
- Tetap memvalidasi pilihan wajib sebelum form dikirim.
- Mengaktifkan lookup otomatis pada baris transaksi dinamis menggunakan
  MutationObserver.

V2.7.1 - PERBAIKAN SELURUH TEMPLATE IMPORT
------------------------------------------
- Memperbarui template Distributor.
- Memperbarui template Pelanggan.
- Memperbarui template Master UOM.
- Memperbarui template gabungan Distributor/Pelanggan/UOM.
- Memperbarui template Detil Barang/Stok.
- Memperbarui template Pricelist.
- Memperbarui template gabungan Stok dan Pricelist.
- Menegaskan Master UOM hanya menyimpan nama satuan dan tipe.
- Menegaskan rasio UOM disimpan pada Master Barang.
- Memperbaiki contoh stok menjadi 24 PCS = 1 BOX:
  Qty 10 BOX = Total Qty 240 PCS.
- Memperbaiki UOM Kecil pada Pricelist agar mengikuti Master Barang.
- Memformat NPWP, NIK, contact, dan kode sebagai Text pada Excel.
- Memastikan workbook tidak memiliki formula error.

V2.7.0 - RUMUS UOM SESUAI SEMANTIK DATABASE PRODUKSI
----------------------------------------------------
- Menyesuaikan struktur database yang menyimpan pasangan seperti:
  40 BTL = 1 DUS.
- Menetapkan rasio UOM besar ke kecil sebagai:
  small_factor dibagi large_factor.
- Memperbaiki kasus yang sebelumnya menampilkan 1 DUS = 0,025 BTL.
- Memperbaiki perhitungan PO:
  10 DUS x 40 BTL x harga per BTL.
- Memperbaiki qty stok, invoice, mutasi, HPP, moving average, nilai persediaan,
  hutang, piutang, dan total transaksi.
- Menambahkan alat repair_uom_formula_v270.php untuk sinkronisasi data lama
  yang tersimpan menggunakan rumus terbalik.
- Menambahkan template Import Master Barang dengan contoh rasio yang benar.

V2.6.9 - JUDUL UOM BESAR/KECIL
------------------------------
- Mengubah judul kolom Detail Invoice Pembelian dari UOM Kecil/Besar menjadi
  UOM Besar/Kecil.
- Menyamakan judul pada dokumen cetak Invoice Pembelian.
- Tidak mengubah rumus atau nilai transaksi.

V2.6.8 - RUMUS UOM DENGAN SMALL_FACTOR DAN LARGE_FACTOR
-------------------------------------------------------
- Menggunakan products.small_factor, small_unit, large_factor, dan large_unit.
- Menambahkan konversi qty dasar menjadi UOM kecil.
- Menambahkan konversi qty dasar menjadi UOM besar dan sisa UOM kecil.
- Menetapkan unit_price dan avg_cost sebagai harga per 1 UOM kecil.
- Memperbaiki nilai transaksi:
  jumlah UOM kecil dikali harga satuan kecil.
- Memperbaiki stok awal, PO, Barang Keluar, invoice, HPP, moving average, dan
  valuasi stok.
- Mendukung small_factor selain 1.
- Transaksi approved lama tidak diubah otomatis untuk menjaga audit trail.

V2.6.7 - AKUMULASI UOM BESAR/KECIL
----------------------------------
- Menambahkan helper pusat untuk tampilan kombinasi UOM.
- Contoh tampilan:
  - 29 BOTOL menjadi 2 DUS / 5 BOTOL.
  - 8 BOTOL tetap 8 BOTOL.
  - 24 BOTOL menjadi 2 DUS.
- Qty database tetap tersimpan dalam satuan dasar/UOM kecil.
- Menambahkan preview Setara pada form PO dan Barang Keluar.
- Menerapkan tampilan UOM pada:
  - Dashboard.
  - Detil Barang/Stok.
  - PO dan Barang Keluar.
  - Invoice Pembelian dan Penjualan.
  - Kartu Stok dan Valuasi Stok.
  - Dokumen cetak.
  - Hasil import stok awal.

V2.6.6 - FILTER PRODUK PO BERDASARKAN DISTRIBUTOR
-------------------------------------------------
- Pilihan barang PO hanya menampilkan produk aktif milik distributor yang
  dipilih.
- Sebelum distributor dipilih, pilihan barang dinonaktifkan.
- Tombol Tambah Baris meminta distributor dipilih terlebih dahulu.
- Mengganti distributor mengosongkan barang yang tidak sesuai.
- Barang yang masih sesuai dipertahankan saat edit atau validasi gagal.
- Menambahkan validasi server:
  products.distributor_id harus sama dengan purchase_orders.distributor_id.

V2.6.5 - PENGUNCIAN BKO/SJ YANG SUDAH DIINVOICE
-----------------------------------------------
- Menghitung sisa qty BKO/SJ langsung dari item invoice approved.
- Menghitung qty invoice Draft/Pending sebagai qty reservasi.
- BKO/SJ yang seluruh qty-nya sudah diinvois tidak muncul kembali.
- BKO/SJ dengan invoice Full dan Lunas ditutup.
- Akses langsung ke form invoice ditolak jika tidak ada sisa qty.
- Tombol Input Invoice mengikuti sisa qty aktual.
- Menambahkan alat sinkronisasi status invoice pada sales_items.
- Mendukung invoice partial: hanya sisa qty yang masih dapat diinvois.

V2.6.3 - PENYEDERHANAAN PROSES TRANSAKSI
----------------------------------------
- Menyederhanakan proses pembelian:
  - Input PO langsung menjadi Pending Approval.
  - Approval PO menjadikan PO aktif.
  - Input Invoice Pembelian langsung menjadi Pending Approval.
  - Approval Invoice Pembelian menambah stok dan membentuk hutang.
  - Pelunasan Pembelian langsung menjadi Pending Approval.
  - Approval Pelunasan mengurangi hutang dan mencatat kas keluar.
- Menyederhanakan proses penjualan:
  - Input Barang Keluar langsung menjadi Pending Approval.
  - Approval Barang Keluar mengurangi stok.
  - Input Invoice Penjualan langsung menjadi Pending Approval.
  - Approval Invoice Penjualan membentuk piutang tanpa tahapan TT.
  - Pelunasan Penjualan langsung menjadi Pending Approval.
  - Approval Pelunasan mengurangi piutang dan mencatat kas masuk.
- Mengunci dokumen setelah diajukan/disetujui.
- Mencegah input dan approval transaksi ganda.

V2.6.2 - TAMPILAN NAMA SAJA
---------------------------
- Dropdown distributor menampilkan Nama Distributor tanpa kode.
- Dropdown barang menampilkan Nama Barang tanpa kode.
- Tabel stok dan pricelist tidak lagi menampilkan kode kecil di bawah nama.
- Detail PO, Barang Masuk, Barang Keluar, dan invoice menampilkan nama saja.
- Dokumen cetak menggunakan kolom Nama Barang.
- Kode tetap disimpan dan dipakai untuk pencarian, audit, import, dan relasi
  internal database.

V2.6.0 - IMPORT DETIL BARANG/STOK DAN PRICELIST
-----------------------------------------------
- Menambahkan Import Excel pada Detil Barang/Stok.
- Menambahkan Import Excel pada Pricelist.
- Mendukung XLSX, CSV, dan TXT.
- Header dicari pada baris 1 sampai 30 dan urutan kolom bebas.
- Menambahkan preview dan mapping manual.
- Barang dicocokkan berdasarkan Kode Barang, kemudian Nama Barang dan
  Distributor.
- Qty dapat berasal dari Qty + Satuan Qty atau Total Qty.
- Qty UOM besar dikonversi ke UOM kecil berdasarkan Master Barang.
- Total Qty divalidasi terhadap Qty dan faktor konversi.
- Harga rata-rata dapat dihitung dari Total Harga dibagi Total Qty.
- Stok awal tidak dapat diperbarui bila sudah ada mutasi selain opening.
- Pricelist dicocokkan berdasarkan Tanggal Invoice + Barang + Distributor.
- Menambahkan pilihan Lewati atau Perbarui data lama.

V2.5.8.2 - PERAPIAN LINK PELUNASAN
----------------------------------
- No. Pelunasan Pembelian tetap dapat diklik tanpa garis bawah.
- No. Pelunasan Penjualan tetap dapat diklik tanpa garis bawah.
- Tampilan hover dan hasil cetak dibuat lebih bersih.

V2.5.7 - SIMPAN DRAFT INVOICE PENJUALAN
---------------------------------------
- Invoice Penjualan dengan PPN dapat disimpan sebagai Draft tanpa No. Faktur
  Pajak dan Tanggal Faktur Pajak.
- No. FP dan Tgl. FP wajib diisi berpasangan jika salah satunya diisi.
- Validasi Faktur Pajak dipindahkan ke proses Ajukan Persetujuan.
- Saat diajukan, sistem memvalidasi item, total, jatuh tempo, sumber Barang
  Keluar, dan kelengkapan FP bila PPN lebih dari nol.
- Pengajuan Draft menjadi Pending diproses dalam transaksi database.

V2.5.6 - PERBAIKAN CSRF INVOICE PENJUALAN
-----------------------------------------
- Menambahkan token CSRF pada form Input/Edit Invoice Penjualan.
- Menetapkan tombol Simpan Draft sebagai submit eksplisit.
- Mencegah penyimpanan tanpa token keamanan yang valid.

V2.5.5 - PERBAIKAN APPROVAL INVOICE PEMBELIAN
---------------------------------------------
- Memisahkan aksi approval ke purchase_invoice_approval_action.php.
- Menambahkan preflight validation sebelum approval.
- Memeriksa status invoice, status PO, item, sisa qty PO, dan harga.
- Mengunci item PO dan saldo stok satu per satu dalam transaksi.
- Mencegah mutasi stok ganda berdasarkan baris sumber invoice.
- Mengaktifkan kembali saldo stok yang sebelumnya soft-delete.
- Mengubah proses pricelist menjadi update-or-insert.
- Menampilkan kode dan pesan MySQL yang lebih jelas saat approval gagal.
- Menambahkan alat sinkronisasi permission, kolom transaksi, dan saldo stok.

V2.5.4 - APPROVAL INVOICE PEMBELIAN
-----------------------------------
- Menambahkan tombol Approve dan Tolak pada daftar Invoice Pembelian.
- Menambahkan filter Menunggu Persetujuan.
- Menambahkan badge jumlah invoice pembelian pending pada sidebar.
- Approval Invoice Pembelian memproses:
  - Stok masuk.
  - Harga rata-rata bergerak.
  - Nilai persediaan.
  - Mutasi stok.
  - Qty penerimaan PO.
  - Pricelist.
  - Hutang supplier.
- Penolakan wajib memiliki alasan.
- Approval hanya menerima invoice pending dan mencegah proses ganda.
- Menambahkan permission purchase_invoices.approve.

V2.5.3 - MENU PERSETUJUAN PO
----------------------------
- Menambahkan halaman Persetujuan PO.
- Menambahkan menu Pembelian > Persetujuan PO.
- Menambahkan badge jumlah PO pending pada sidebar.
- Menambahkan tombol Persetujuan PO pada daftar Purchase Order.
- Membuat kartu Menunggu Persetujuan pada dashboard dapat dibuka Approver.
- Menambahkan permission purchase_orders.approve.
- Menambahkan dependency permission approve terhadap permission view.
- Menambahkan alat sinkronisasi permission untuk Admin dan Approver.

V2.5.2 - ALUR PERSETUJUAN PURCHASE ORDER
----------------------------------------
- PO disimpan sebagai Draft.
- PO Draft dapat diajukan menjadi Menunggu Persetujuan.
- PO Cancel tidak dapat diajukan atau disetujui.
- Approver hanya dapat menyetujui PO Progress dengan minimal satu item.
- PO approved menjadi PO aktif untuk Barang Masuk.
- Menambahkan tombol Proses Barang Masuk pada daftar dan detail PO.
- PO approved yang belum diterima penuh muncul pada pilihan Invoice Pembelian.
- PO yang sudah diterima penuh tidak dapat diproses kembali.
- Mencegah approval ganda menggunakan transaksi dan row lock.

V2.5.1 - PERBAIKAN ITEM PO DAN BARANG KELUAR
--------------------------------------------
- Memperbaiki JavaScript heredoc yang menyebabkan baris item PO gagal dibuat.
- Menampilkan satu baris item otomatis saat form baru dibuka.
- Mengaktifkan kembali tombol Tambah Baris.
- Memperbaiki pilihan barang, Qty, UOM, harga, total, catatan, dan hapus baris.
- Mempertahankan item lama saat edit atau ketika validasi server gagal.
- Menerapkan perbaikan serupa pada Penjualan / Barang Keluar.

V2.5.0 - CETAK SEMUA MODUL
--------------------------
- Menambahkan tombol Cetak global pada halaman daftar, stok, dan laporan.
- Menambahkan stylesheet dan JavaScript khusus cetak.
- Menyembunyikan sidebar, topbar, form filter, tombol, dan kolom Aksi saat
  dicetak.
- Menambahkan header cetak berisi perusahaan, kontak, judul, waktu cetak, dan
  nama pengguna.
- Menambahkan orientasi A4 portrait/landscape otomatis.
- Menambahkan dokumen khusus:
  - Purchase Order.
  - Invoice Pembelian.
  - Bukti Pelunasan Pembelian.
  - Surat Jalan / Barang Keluar.
  - Invoice Penjualan.
  - Bukti Pelunasan Penjualan.
  - Bukti Biaya.
- Mendukung Print dan Save as PDF melalui browser.

V2.4.0 - IMPORT DISTRIBUTOR, PELANGGAN, DAN UOM
-----------------------------------------------
- Menambahkan Import Excel pada Data Distributor.
- Menambahkan Import Excel pada Data Pelanggan.
- Menambahkan Import Excel pada Master UOM.
- Mendukung XLSX dan CSV dengan urutan kolom bebas.
- Menambahkan preview dan koreksi mapping.
- Menambahkan pilihan Lewati atau Perbarui data lama.
- Distributor dicocokkan berdasarkan kode, kemudian NPWP.
- Pelanggan dicocokkan berdasarkan NIK/NPWP.
- UOM dicocokkan berdasarkan nama tanpa membedakan huruf besar-kecil.
- Kode Distributor hanya dibuat setelah baris berhasil disimpan.
- Setiap baris import memakai transaksi terpisah agar kegagalan satu baris
  tidak membatalkan baris lain.

V2.3.1 - PREVIEW NOMOR TANPA CELAH
----------------------------------
- Membuka form tidak lagi menaikkan document sequence.
- Membatalkan form tidak menyebabkan nomor meloncat.
- Sequence baru bertambah setelah seluruh penyimpanan berhasil.
- Jika validasi atau INSERT gagal, transaksi di-rollback dan nomor tidak
  terpakai.
- Dua pengguna dapat melihat preview sama; nomor final ditentukan secara aman
  saat masing-masing menyimpan.
- Berlaku untuk kode Distributor, kode Barang, PO, BKO, SJ, dan seluruh nomor
  pelunasan.

V2.3.0 - IMPORT MASTER BARANG
-----------------------------
- Menambahkan Import Excel pada Data Barang.
- Mendukung file XLSX dan CSV.
- Header dapat berada pada baris 1 sampai 30.
- Urutan kolom bebas dan dipetakan berdasarkan nama header.
- Menambahkan preview dan koreksi mapping sebelum import.
- Kode barang dapat dikosongkan dan dibuat otomatis ketika import berhasil.
- Distributor dan UOM baru dapat dibuat otomatis sesuai permission.
- Menambahkan import stok awal dan harga rata-rata.
- Stok awal hanya boleh dibuat jika belum ada mutasi stok transaksi.
- Import diproses per baris menggunakan transaksi database.
- Menambahkan fallback pembaca XLSX saat extension ZipArchive tidak aktif.

V2.2.0 - LAPORAN KEUANGAN
-------------------------
- Menambahkan menu Laporan Keuangan.
- Menambahkan laporan laba rugi:
  - Penjualan bruto.
  - Diskon penjualan.
  - Penjualan bersih.
  - HPP.
  - Laba kotor.
  - Biaya operasional.
  - Laba bersih.
- Menambahkan laporan arus kas dari pelunasan penjualan, pelunasan pembelian,
  dan biaya.
- Menambahkan posisi piutang, persediaan, dan hutang per tanggal laporan.
- Menambahkan rekap PPN keluaran, PPN masukan, dan kurang/lebih bayar.
- Menambahkan rekap bulanan, biaya per jenis, piutang terbuka, dan hutang
  terbuka.
- Menambahkan filter periode, cetak, dan ekspor CSV.
- Menambahkan permission financial_reports.view.

V2.1.2 - SEMUA KODE DAN NOMOR LANGSUNG TAMPIL
---------------------------------------------
- Kode Distributor tampil sebelum data disimpan.
- Kode Barang tampil sebelum data disimpan.
- No. PO tampil sebelum PO disimpan.
- No. Pelunasan Pembelian dan Penjualan tampil sebelum disimpan.
- Perubahan tanggal transaksi memperbarui periode nomor secara otomatis.
- Nomor tetap divalidasi ulang oleh server saat penyimpanan.

V2.1.1 - NO. SURAT JALAN LANGSUNG TAMPIL
----------------------------------------
- No. Surat Jalan langsung terlihat saat form Barang Keluar dibuka.
- Kolom No. SJ dibuat readonly.
- Perubahan bulan pada tanggal transaksi memperbarui preview nomor.
- Nomor final yang disimpan harus sama dengan nomor yang ditampilkan.
- Endpoint reservasi nomor dilindungi CSRF dan permission.

V2.1.0 - NOMOR OTOMATIS TERKUNCI
--------------------------------
Build terdokumentasi: 21 Juli 2026

- Menambahkan tabel document_sequences.
- Membuat nomor otomatis untuk:
  - Kode Distributor: DST-YYYYMM-0001.
  - Kode Barang: BRG-YYYYMM-0001.
  - No. Purchase Order: PO-YYYYMM-0001.
  - No. Pelunasan Pembelian: BYRP-YYYYMM-0001.
  - No. Pelunasan Penjualan: BYRJ-YYYYMM-0001.
  - No. Barang Keluar: BKO-YYYYMM-0001.
  - No. Surat Jalan: SJ-YYYYMM-0001.
- Nomor dibuat dalam transaksi database dengan SELECT ... FOR UPDATE.
- Input nomor dari browser tidak dipercaya oleh server.
- Menambahkan unique index untuk mencegah nomor dokumen ganda.
- Menambahkan alat upgrade_auto_number_lock.php untuk database V2 lama.

V2.0.0 - ARSITEKTUR TRANSAKSI HEADER DAN DETAIL ITEM
----------------------------------------------------
Periode pengembangan: Juli 2026, sebelum V2.1.0

- Membangun ulang transaksi menggunakan struktur header dan detail item.
- Satu PO, Barang Keluar/Surat Jalan, Invoice Pembelian, dan Invoice Penjualan
  dapat memuat banyak barang.
- Menambahkan status draft, pending approval, approved, rejected, partial,
  full, dan cancel sesuai modul.
- Menghubungkan approval transaksi dengan stok, hutang, piutang, dan pembayaran.
- Menambahkan penguncian dokumen agar transaksi approved tidak diedit bebas.
- Menyiapkan struktur upgrade untuk database aplikasi versi awal.

V1.6.0 - KEAMANAN, USER, ROLE, DAN AUDIT TRAIL
----------------------------------------------
Periode awal pengembangan; tanggal rilis rinci tidak tercatat

- Menambahkan Manajemen User, Role, dan Permission.
- Menambahkan role Administrator, Approver, Operator/Staff, dan Viewer.
- Menambahkan CSRF protection, validasi input, password_hash/password_verify,
  mitigasi XSS, dan pembatasan percobaan login.
- Menambahkan remember me, manajemen session, riwayat login, dan audit trail.
- Menambahkan soft delete pada data yang memerlukan jejak historis.

V1.5.0 - STOK, HPP, BIAYA, DAN LAPORAN DASAR
--------------------------------------------
Periode awal pengembangan; tanggal rilis rinci tidak tercatat

- Menambahkan stok awal, stok masuk, stok keluar, dan mutasi stok.
- Menambahkan HPP moving weighted average.
- Menambahkan Kartu Stok dan Valuasi Stok.
- Menambahkan modul Biaya operasional.
- Menambahkan dasar laporan hutang, piutang, pembayaran, stok, dan keuangan.

V1.4.0 - MODUL PENJUALAN DAN PIUTANG
------------------------------------
Periode awal pengembangan; tanggal rilis rinci tidak tercatat

- Menambahkan Barang Keluar dan Surat Jalan.
- Menambahkan Invoice Penjualan.
- Menambahkan pelunasan penjualan partial dan lunas.
- Menambahkan piutang pelanggan, jatuh tempo, saldo, diskon, DPP, PPN, dan total.

V1.3.0 - MODUL PEMBELIAN DAN HUTANG
-----------------------------------
Periode awal pengembangan; tanggal rilis rinci tidak tercatat

- Menambahkan Purchase Order.
- Menambahkan Barang Masuk dan Invoice Pembelian.
- Menambahkan penerimaan partial dan full.
- Menambahkan hutang distributor serta pelunasan pembelian partial dan lunas.

V1.2.0 - MASTER DATA INVENTORY
------------------------------
Periode awal pengembangan; tanggal rilis rinci tidak tercatat

- Menambahkan Data Distributor.
- Menambahkan Data Pelanggan.
- Menambahkan Master UOM.
- Menambahkan Data Barang dan Detil Barang/Stok.
- Menambahkan Pricelist berdasarkan tanggal, barang, distributor, dan harga.

V1.1.0 - LOGIN, SESSION, DAN DASHBOARD ADMIN
--------------------------------------------
Periode awal pengembangan; tanggal rilis rinci tidak tercatat

- Menambahkan login berbasis session.
- Menambahkan dashboard admin berbasis Bootstrap dan sidebar modul.
- Menambahkan profil user, logout, dan pengamanan halaman berdasarkan session.
- Menambahkan konfigurasi identitas perusahaan dasar.

V1.0.0 - AWAL PEMBUATAN JCOM INVENTORY
--------------------------------------
Periode awal pengembangan: Juli 2026

- Membuat source awal aplikasi inventory berbasis PHP 8 dan MySQL.
- Menyiapkan struktur yang siap diunggah ke cPanel.
- Menambahkan setup.php untuk membuat koneksi dan database instalasi baru.
- Menambahkan config aplikasi, koneksi PDO, helper dasar, layout, dan routing
  halaman berbasis PHP.
- Menetapkan fondasi aplikasi untuk master data, pembelian, penjualan, stok,
  pembayaran, dan laporan.

CATATAN KOMPATIBILITAS
- Source V2 menggunakan struktur header + detail item.
- Database lama dengan struktur satu barang per dokumen memerlukan migrasi
  terkontrol dan tidak boleh langsung ditimpa.
- Selalu backup source dan database sebelum memasang patch.
- Jangan menimpa config/app.php ketika memasang source pada instalasi lama.
- Setelah mengganti JavaScript atau CSS, lakukan logout/login dan Ctrl + F5.
- Nama file upgrade versi lama tetap dipertahankan untuk kompatibilitas.
- Versi percobaan atau rollback yang tidak dipertahankan sebagai rilis stabil
  tidak dicantumkan sebagai versi terpisah.


HOTFIX HF1 - 17 September 2026
- Perbaikan halaman Koreksi Histori Migrasi Penjualan: tabel customers tidak memiliki kolom code; dropdown pelanggan sekarang memakai identity_number sebagai identitas.
- Tidak ada perubahan schema/database.

V2.10.227 HOTFIX - 22 Sep 2026
- Memperbaiki Fatal SQLSTATE[HY000] 2006 MySQL server has gone away pada Verifikasi Rilis V2.10.227.
- Full schema verifier hanya dijalankan satu kali per request.
- Error verifier sekarang ditangkap dan ditampilkan sebagai pesan, bukan Fatal Error.
- SHOW CREATE TABLE melakukan satu kali reconnect aman untuk error MySQL 2006/2013 dan mencatat nama tabel pada error_log.
- Tidak ada perubahan schema database dan tidak ada ALTER TABLE.

## V2.10.240 Refresh - Import Koreksi HPP Per Invoice Per Item
- Import Koreksi HPP Historis Mode 1 sekarang mendukung format utama **1 baris = 1 item invoice**.
- Kolom utama: No. Invoice, Kode Barang/Nama Barang, Qty, Satuan Qty, HPP Historis Item Baru, Alasan Koreksi, Referensi, Import?.
- Jika satu invoice diproses, semua item aktif invoice wajib dicantumkan; campuran Import? YA/TIDAK dalam invoice yang sama ditolak.
- Sistem menjumlahkan HPP seluruh item menjadi `sales_invoices.historical_cogs`; tidak ada perubahan schema.
- Breakdown item disimpan lengkap di `activity_logs.metadata` untuk audit.
- Safety Backup, maintenance lock, row lock, closed-period blocker, transaksi atomik, post-check, sinkronisasi batch.total_cogs, dan rollback per invoice tetap dipertahankan.
- Template legacy V2.10.239 per-invoice tetap kompatibel.
