mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-06-09 15:07:49 +00:00
Merge branch 'fix/jamali' into feat/fifo-ar
This commit is contained in:
+99
@@ -0,0 +1,99 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- Rollback dynamic via audit snapshots di schema `migration_audit.jamali_w10_*`.
|
||||||
|
-- Semua reverse dibaca dari snapshot yang dibuat oleh UP migration —
|
||||||
|
-- tidak ada IDs/qty yang hardcode. Robust terhadap data drift antara
|
||||||
|
-- dump time dan UP apply time (misalnya row baru warehouse_id=10
|
||||||
|
-- yang muncul setelah dump diambil).
|
||||||
|
--
|
||||||
|
-- LIMITASI: FK relinks di stock_logs / stock_allocations / recording_eggs /
|
||||||
|
-- marketing_products / dll. TIDAK direverse di sini (skip audit per-row
|
||||||
|
-- untuk hemat storage ~40MB). Setelah down, 9 PW W10 yang di-restore
|
||||||
|
-- akan kosong dari child rows (semua child masih pointing ke W25 PW
|
||||||
|
-- yang sebelumnya menerima merge). Untuk rollback penuh, restore DB
|
||||||
|
-- dari backup pre-migration.
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
-- Guard: pastikan audit tables ada (kalau tidak, fail-loud)
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1 FROM information_schema.tables
|
||||||
|
WHERE table_schema = 'migration_audit'
|
||||||
|
AND table_name = 'jamali_w10_pw_deleted_snapshot'
|
||||||
|
) THEN
|
||||||
|
RAISE EXCEPTION 'Audit table migration_audit.jamali_w10_* tidak ditemukan. UP migration belum dijalankan atau audit sudah di-drop. Restore dari DB backup jika perlu.';
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
-- 1. Un-soft-delete warehouse 10 (kalau memang di-softdelete oleh UP)
|
||||||
|
UPDATE warehouses w
|
||||||
|
SET deleted_at = NULL, updated_at = NOW()
|
||||||
|
FROM migration_audit.jamali_w10_warehouse_softdeleted a
|
||||||
|
WHERE w.id = a.id;
|
||||||
|
|
||||||
|
-- 2. Un-soft-delete stock_transfers self-loop yang disoft-delete UP step 7.1
|
||||||
|
UPDATE stock_transfers st
|
||||||
|
SET deleted_at = NULL, updated_at = NOW()
|
||||||
|
FROM migration_audit.jamali_w10_st_softdeleted a
|
||||||
|
WHERE st.id = a.id;
|
||||||
|
|
||||||
|
-- 3. Reverse stock_transfers redirect (CASE-based dari snapshot was_from_w10/was_to_w10)
|
||||||
|
UPDATE stock_transfers st
|
||||||
|
SET from_warehouse_id = CASE WHEN a.was_from_w10 THEN 10 ELSE st.from_warehouse_id END,
|
||||||
|
to_warehouse_id = CASE WHEN a.was_to_w10 THEN 10 ELSE st.to_warehouse_id END,
|
||||||
|
updated_at = NOW()
|
||||||
|
FROM migration_audit.jamali_w10_st_redirected a
|
||||||
|
WHERE st.id = a.id;
|
||||||
|
|
||||||
|
-- 3b. Self-loop transfers (W10<->W25 awal) juga punya from_warehouse_id=25 atau
|
||||||
|
-- to_warehouse_id=25 setelah UP step 7.2. Karena snapshot jamali_w10_st_softdeleted
|
||||||
|
-- punya kolom from_warehouse_id & to_warehouse_id asli, pakai itu untuk reverse.
|
||||||
|
UPDATE stock_transfers st
|
||||||
|
SET from_warehouse_id = 10, updated_at = NOW()
|
||||||
|
FROM migration_audit.jamali_w10_st_softdeleted a
|
||||||
|
WHERE st.id = a.id AND a.from_warehouse_id = 10;
|
||||||
|
|
||||||
|
UPDATE stock_transfers st
|
||||||
|
SET to_warehouse_id = 10, updated_at = NOW()
|
||||||
|
FROM migration_audit.jamali_w10_st_softdeleted a
|
||||||
|
WHERE st.id = a.id AND a.to_warehouse_id = 10;
|
||||||
|
|
||||||
|
-- 4. Reverse purchase_items.warehouse_id 25 -> 10
|
||||||
|
UPDATE purchase_items
|
||||||
|
SET warehouse_id = 10
|
||||||
|
WHERE id IN (SELECT id FROM migration_audit.jamali_w10_purchase_items);
|
||||||
|
|
||||||
|
-- 5. Reverse W10-only PW (warehouse_id 25 -> 10, restore pfk asli dari snapshot)
|
||||||
|
UPDATE product_warehouses pw
|
||||||
|
SET warehouse_id = 10, project_flock_kandang_id = a.original_pfk
|
||||||
|
FROM migration_audit.jamali_w10_pw_w10only_snapshot a
|
||||||
|
WHERE pw.id = a.id;
|
||||||
|
|
||||||
|
-- 6. Subtract qty dari W25 PW (reverse merge)
|
||||||
|
-- WARNING: kalau W25 qty sudah dikonsumsi pasca-UP (sales/recording/dll),
|
||||||
|
-- hasil bisa negatif. Tidak ada CHECK constraint di product_warehouses.qty,
|
||||||
|
-- jadi silent. Operator harus verifikasi manual post-down:
|
||||||
|
-- SELECT id, qty FROM product_warehouses WHERE qty < 0;
|
||||||
|
UPDATE product_warehouses pw
|
||||||
|
SET qty = pw.qty - a.merged_qty
|
||||||
|
FROM migration_audit.jamali_w10_qty_merge a
|
||||||
|
WHERE pw.id = a.target_pw_id;
|
||||||
|
|
||||||
|
-- 7. Re-INSERT 9 W10 PW rows yang di-DELETE oleh UP (PK asli + qty asli)
|
||||||
|
INSERT INTO product_warehouses (id, product_id, warehouse_id, qty, project_flock_kandang_id)
|
||||||
|
SELECT id, product_id, 10, qty, project_flock_kandang_id
|
||||||
|
FROM migration_audit.jamali_w10_pw_deleted_snapshot;
|
||||||
|
|
||||||
|
-- 8. Cleanup audit tables (drop satu per satu, tidak wildcard untuk safety)
|
||||||
|
DROP TABLE migration_audit.jamali_w10_pw_deleted_snapshot;
|
||||||
|
DROP TABLE migration_audit.jamali_w10_qty_merge;
|
||||||
|
DROP TABLE migration_audit.jamali_w10_pw_w10only_snapshot;
|
||||||
|
DROP TABLE migration_audit.jamali_w10_st_softdeleted;
|
||||||
|
DROP TABLE migration_audit.jamali_w10_st_redirected;
|
||||||
|
DROP TABLE migration_audit.jamali_w10_purchase_items;
|
||||||
|
DROP TABLE migration_audit.jamali_w10_warehouse_softdeleted;
|
||||||
|
-- Schema migration_audit dipertahankan (bisa dipakai migration lain di masa depan)
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
+241
@@ -0,0 +1,241 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- Normalisasi warehouse 10 (Jamali NON_AKTIF) -> 25 (Gudang Farm Jamali)
|
||||||
|
-- Background: Dua warehouse LOKASI di area & lokasi sama (area_id=6,
|
||||||
|
-- location_id=16). W10 sudah ditandai NON_AKTIF tapi masih punya 13
|
||||||
|
-- product_warehouses, 3,590 stock_logs, ~790K stock_allocations,
|
||||||
|
-- 332 marketing_products, 17 purchase_items, dan 14 stock_transfers.
|
||||||
|
-- Migration ini konsolidasikan semua relasi ke W25 lalu soft-delete W10.
|
||||||
|
--
|
||||||
|
-- Klasifikasi data:
|
||||||
|
-- A. 9 product_warehouses W10 overlap dengan W25 (sama product_id, pfk=NULL)
|
||||||
|
-- -> merge qty ke W25, relink semua FK ke product_warehouses.id,
|
||||||
|
-- lalu DELETE W10 PW rows.
|
||||||
|
-- B. 4 product_warehouses W10-only -> UPDATE warehouse_id=25.
|
||||||
|
-- Rows 1188/1189/1190 punya pfk=98 (anomali LOKASI, seharusnya NULL
|
||||||
|
-- per aturan di CLAUDE.md [2026-05-06]) -> normalisasi sekalian.
|
||||||
|
-- C. 17 purchase_items.warehouse_id=10 -> UPDATE 25 (no unique conflict).
|
||||||
|
-- D. 3 stock_transfers W10<->W25 (PND-LTI-00107/00109/00119) akan jadi
|
||||||
|
-- self-loop W25<->W25 setelah merge -> soft-delete.
|
||||||
|
-- E. 12 stock_transfers EGG_FARM_CUTOVER to_warehouse_id=10 -> UPDATE 25.
|
||||||
|
-- F. warehouse_id=10 sendiri -> soft-delete.
|
||||||
|
--
|
||||||
|
-- UP membuat 7 snapshot table di schema `migration_audit.jamali_w10_*`
|
||||||
|
-- sebelum mutasi. DOWN baca snapshot itu untuk reverse dynamic (tidak
|
||||||
|
-- hardcode IDs/qty), sehingga apapun yang ada di production saat UP
|
||||||
|
-- dijalankan akan ter-audit dan ter-reverse. FK relinks
|
||||||
|
-- (stock_logs/stock_allocations/dll) TIDAK di-audit (storage ~40MB)
|
||||||
|
-- — limitation: tidak bisa di-reverse DOWN, full rollback = DB backup.
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
-- STEP -1: Buat schema audit + snapshot tables (idempotent rerun via DROP IF EXISTS)
|
||||||
|
CREATE SCHEMA IF NOT EXISTS migration_audit;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS migration_audit.jamali_w10_pw_deleted_snapshot;
|
||||||
|
DROP TABLE IF EXISTS migration_audit.jamali_w10_qty_merge;
|
||||||
|
DROP TABLE IF EXISTS migration_audit.jamali_w10_pw_w10only_snapshot;
|
||||||
|
DROP TABLE IF EXISTS migration_audit.jamali_w10_st_softdeleted;
|
||||||
|
DROP TABLE IF EXISTS migration_audit.jamali_w10_st_redirected;
|
||||||
|
DROP TABLE IF EXISTS migration_audit.jamali_w10_purchase_items;
|
||||||
|
DROP TABLE IF EXISTS migration_audit.jamali_w10_warehouse_softdeleted;
|
||||||
|
|
||||||
|
-- Snapshot 9 W10 PW yang akan di-DELETE (overlap dgn W25, pfk=NULL)
|
||||||
|
CREATE TABLE migration_audit.jamali_w10_pw_deleted_snapshot AS
|
||||||
|
SELECT pw10.id, pw10.product_id, pw10.qty, pw10.project_flock_kandang_id
|
||||||
|
FROM product_warehouses pw10
|
||||||
|
JOIN product_warehouses pw25
|
||||||
|
ON pw25.product_id = pw10.product_id
|
||||||
|
AND pw25.warehouse_id = 25
|
||||||
|
AND pw25.project_flock_kandang_id IS NULL
|
||||||
|
WHERE pw10.warehouse_id = 10 AND pw10.project_flock_kandang_id IS NULL;
|
||||||
|
|
||||||
|
-- Snapshot qty delta per W25 target (untuk reverse subtract)
|
||||||
|
CREATE TABLE migration_audit.jamali_w10_qty_merge AS
|
||||||
|
SELECT pw25.id AS target_pw_id, pw10.id AS source_pw_id, pw10.qty AS merged_qty
|
||||||
|
FROM product_warehouses pw10
|
||||||
|
JOIN product_warehouses pw25
|
||||||
|
ON pw25.product_id = pw10.product_id
|
||||||
|
AND pw25.warehouse_id = 25
|
||||||
|
AND pw25.project_flock_kandang_id IS NULL
|
||||||
|
WHERE pw10.warehouse_id = 10 AND pw10.project_flock_kandang_id IS NULL;
|
||||||
|
|
||||||
|
-- Snapshot W10-only PW (yang akan di-UPDATE warehouse_id 10->25)
|
||||||
|
CREATE TABLE migration_audit.jamali_w10_pw_w10only_snapshot AS
|
||||||
|
SELECT pw10.id, pw10.project_flock_kandang_id AS original_pfk
|
||||||
|
FROM product_warehouses pw10
|
||||||
|
WHERE pw10.warehouse_id = 10
|
||||||
|
AND pw10.id NOT IN (SELECT id FROM migration_audit.jamali_w10_pw_deleted_snapshot);
|
||||||
|
|
||||||
|
-- Snapshot stock_transfers yang akan di-soft-delete (self-loop W10<->W25)
|
||||||
|
-- Simpan from/to_warehouse_id asli supaya DOWN bisa reverse direction tepat
|
||||||
|
CREATE TABLE migration_audit.jamali_w10_st_softdeleted AS
|
||||||
|
SELECT id, movement_number, from_warehouse_id, to_warehouse_id
|
||||||
|
FROM stock_transfers
|
||||||
|
WHERE deleted_at IS NULL
|
||||||
|
AND ((from_warehouse_id = 10 AND to_warehouse_id = 25)
|
||||||
|
OR (from_warehouse_id = 25 AND to_warehouse_id = 10));
|
||||||
|
|
||||||
|
-- Snapshot stock_transfers yang akan di-UPDATE (W10<->other, bukan self-loop)
|
||||||
|
CREATE TABLE migration_audit.jamali_w10_st_redirected AS
|
||||||
|
SELECT id,
|
||||||
|
(from_warehouse_id = 10) AS was_from_w10,
|
||||||
|
(to_warehouse_id = 10) AS was_to_w10
|
||||||
|
FROM stock_transfers
|
||||||
|
WHERE deleted_at IS NULL
|
||||||
|
AND (from_warehouse_id = 10 OR to_warehouse_id = 10)
|
||||||
|
AND id NOT IN (SELECT id FROM migration_audit.jamali_w10_st_softdeleted);
|
||||||
|
|
||||||
|
-- Snapshot purchase_items IDs (cheap, ~17 rows)
|
||||||
|
CREATE TABLE migration_audit.jamali_w10_purchase_items AS
|
||||||
|
SELECT id FROM purchase_items WHERE warehouse_id = 10;
|
||||||
|
|
||||||
|
-- Snapshot warehouses soft-delete flag (1 row, kalau memang masih aktif)
|
||||||
|
CREATE TABLE migration_audit.jamali_w10_warehouse_softdeleted AS
|
||||||
|
SELECT id FROM warehouses WHERE id = 10 AND deleted_at IS NULL;
|
||||||
|
|
||||||
|
-- STEP 0: Pre-check sanity (idempotent guards)
|
||||||
|
DO $$
|
||||||
|
DECLARE v_count INT;
|
||||||
|
BEGIN
|
||||||
|
SELECT COUNT(*) INTO v_count FROM warehouses
|
||||||
|
WHERE id IN (10, 25) AND type = 'LOKASI' AND area_id = 6 AND location_id = 16;
|
||||||
|
IF v_count <> 2 THEN
|
||||||
|
RAISE EXCEPTION 'Pre-check: warehouse 10/25 schema mismatch (got % rows)', v_count;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
SELECT COUNT(*) INTO v_count FROM purchase_items a
|
||||||
|
JOIN purchase_items b ON a.purchase_id = b.purchase_id
|
||||||
|
AND a.product_id = b.product_id
|
||||||
|
AND a.id <> b.id
|
||||||
|
WHERE a.warehouse_id = 10 AND b.warehouse_id = 25;
|
||||||
|
IF v_count > 0 THEN
|
||||||
|
RAISE EXCEPTION 'Pre-check: % purchase_items unique conflict (purchase_id,product_id)', v_count;
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
-- STEP 1: Merge qty W10 -> W25 untuk overlap (pfk=NULL)
|
||||||
|
UPDATE product_warehouses pw25
|
||||||
|
SET qty = pw25.qty + pw10.qty
|
||||||
|
FROM product_warehouses pw10
|
||||||
|
WHERE pw10.warehouse_id = 10 AND pw10.project_flock_kandang_id IS NULL
|
||||||
|
AND pw25.warehouse_id = 25 AND pw25.project_flock_kandang_id IS NULL
|
||||||
|
AND pw25.product_id = pw10.product_id;
|
||||||
|
|
||||||
|
-- STEP 2: Build temp mapping (W10 PW id -> W25 PW id) untuk overlap saja
|
||||||
|
CREATE TEMP TABLE _pw_map ON COMMIT DROP AS
|
||||||
|
SELECT pw10.id AS old_id, pw25.id AS new_id
|
||||||
|
FROM product_warehouses pw10
|
||||||
|
JOIN product_warehouses pw25
|
||||||
|
ON pw25.product_id = pw10.product_id
|
||||||
|
AND pw25.warehouse_id = 25
|
||||||
|
AND pw25.project_flock_kandang_id IS NULL
|
||||||
|
WHERE pw10.warehouse_id = 10 AND pw10.project_flock_kandang_id IS NULL;
|
||||||
|
|
||||||
|
CREATE INDEX ON _pw_map(old_id);
|
||||||
|
|
||||||
|
-- STEP 3: Relink semua FK ke product_warehouses.id (hanya rows di _pw_map)
|
||||||
|
UPDATE stock_logs SET product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE stock_logs.product_warehouse_id = m.old_id;
|
||||||
|
|
||||||
|
UPDATE stock_allocations SET product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE stock_allocations.product_warehouse_id = m.old_id;
|
||||||
|
|
||||||
|
UPDATE recording_eggs SET product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE recording_eggs.product_warehouse_id = m.old_id;
|
||||||
|
|
||||||
|
UPDATE recording_stocks SET product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE recording_stocks.product_warehouse_id = m.old_id;
|
||||||
|
|
||||||
|
UPDATE recording_depletions SET product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE recording_depletions.product_warehouse_id = m.old_id;
|
||||||
|
UPDATE recording_depletions SET source_product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE recording_depletions.source_product_warehouse_id = m.old_id;
|
||||||
|
|
||||||
|
UPDATE adjustment_stocks SET product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE adjustment_stocks.product_warehouse_id = m.old_id;
|
||||||
|
|
||||||
|
UPDATE marketing_products SET product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE marketing_products.product_warehouse_id = m.old_id;
|
||||||
|
|
||||||
|
UPDATE marketing_delivery_products SET product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE marketing_delivery_products.product_warehouse_id = m.old_id;
|
||||||
|
|
||||||
|
UPDATE project_chickins SET product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE project_chickins.product_warehouse_id = m.old_id;
|
||||||
|
|
||||||
|
UPDATE project_chickin_details SET product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE project_chickin_details.product_warehouse_id = m.old_id;
|
||||||
|
|
||||||
|
UPDATE project_flock_populations SET product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE project_flock_populations.product_warehouse_id = m.old_id;
|
||||||
|
|
||||||
|
UPDATE laying_transfers SET source_product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE laying_transfers.source_product_warehouse_id = m.old_id;
|
||||||
|
|
||||||
|
UPDATE laying_transfer_sources SET product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE laying_transfer_sources.product_warehouse_id = m.old_id;
|
||||||
|
|
||||||
|
UPDATE laying_transfer_targets SET product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE laying_transfer_targets.product_warehouse_id = m.old_id;
|
||||||
|
|
||||||
|
UPDATE stock_transfer_details SET source_product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE stock_transfer_details.source_product_warehouse_id = m.old_id;
|
||||||
|
UPDATE stock_transfer_details SET dest_product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE stock_transfer_details.dest_product_warehouse_id = m.old_id;
|
||||||
|
|
||||||
|
UPDATE purchase_items SET product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE purchase_items.product_warehouse_id = m.old_id;
|
||||||
|
|
||||||
|
-- FIFO v2 tables (kosong di dump 2026-05-25, defensive)
|
||||||
|
UPDATE fifo_stock_v2_operation_log SET product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE fifo_stock_v2_operation_log.product_warehouse_id = m.old_id;
|
||||||
|
UPDATE fifo_stock_v2_reflow_checkpoints SET product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE fifo_stock_v2_reflow_checkpoints.product_warehouse_id = m.old_id;
|
||||||
|
UPDATE fifo_stock_v2_shadow_allocations SET product_warehouse_id = m.new_id
|
||||||
|
FROM _pw_map m WHERE fifo_stock_v2_shadow_allocations.product_warehouse_id = m.old_id;
|
||||||
|
|
||||||
|
-- STEP 4: Hard-delete W10 PW yang sudah merged (9 rows expected)
|
||||||
|
DELETE FROM product_warehouses WHERE id IN (SELECT old_id FROM _pw_map);
|
||||||
|
|
||||||
|
-- STEP 5: Sisa W10 PW (4 rows: 1188/1189/1190/1196) -> warehouse_id=25,
|
||||||
|
-- pfk dinormalisasi ke NULL sekalian (LOKASI rule)
|
||||||
|
UPDATE product_warehouses
|
||||||
|
SET warehouse_id = 25, project_flock_kandang_id = NULL
|
||||||
|
WHERE warehouse_id = 10;
|
||||||
|
|
||||||
|
-- STEP 6: purchase_items.warehouse_id (17 rows)
|
||||||
|
UPDATE purchase_items SET warehouse_id = 25 WHERE warehouse_id = 10;
|
||||||
|
|
||||||
|
-- STEP 7: stock_transfers
|
||||||
|
-- 7.1 Soft-delete self-loop (W10<->W25 akan jadi W25<->W25)
|
||||||
|
UPDATE stock_transfers
|
||||||
|
SET deleted_at = NOW(), updated_at = NOW()
|
||||||
|
WHERE deleted_at IS NULL
|
||||||
|
AND ((from_warehouse_id = 10 AND to_warehouse_id = 25)
|
||||||
|
OR (from_warehouse_id = 25 AND to_warehouse_id = 10));
|
||||||
|
|
||||||
|
-- 7.2 Sisa W10<->other -> 25 (12 EGG_FARM_CUTOVER ke W10)
|
||||||
|
UPDATE stock_transfers SET from_warehouse_id = 25, updated_at = NOW() WHERE from_warehouse_id = 10;
|
||||||
|
UPDATE stock_transfers SET to_warehouse_id = 25, updated_at = NOW() WHERE to_warehouse_id = 10;
|
||||||
|
|
||||||
|
-- STEP 8: Soft-delete warehouse 10 sendiri
|
||||||
|
UPDATE warehouses SET deleted_at = NOW(), updated_at = NOW()
|
||||||
|
WHERE id = 10 AND deleted_at IS NULL;
|
||||||
|
|
||||||
|
-- STEP 9: Post-check (fail-fast jika ada residu)
|
||||||
|
DO $$
|
||||||
|
DECLARE v_count INT;
|
||||||
|
BEGIN
|
||||||
|
SELECT COUNT(*) INTO v_count FROM product_warehouses WHERE warehouse_id = 10;
|
||||||
|
IF v_count <> 0 THEN RAISE EXCEPTION 'product_warehouses W10 residual %', v_count; END IF;
|
||||||
|
|
||||||
|
SELECT COUNT(*) INTO v_count FROM purchase_items WHERE warehouse_id = 10;
|
||||||
|
IF v_count <> 0 THEN RAISE EXCEPTION 'purchase_items W10 residual %', v_count; END IF;
|
||||||
|
|
||||||
|
SELECT COUNT(*) INTO v_count FROM stock_transfers
|
||||||
|
WHERE deleted_at IS NULL AND (from_warehouse_id = 10 OR to_warehouse_id = 10);
|
||||||
|
IF v_count <> 0 THEN RAISE EXCEPTION 'stock_transfers W10 residual %', v_count; END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- Rollback stock_log drift fix: DELETE corrective rows yang di-insert UP.
|
||||||
|
-- IDs ditarik dari audit table `migration_audit.jamali_w10_stocklog_corrections`.
|
||||||
|
-- Setelah delete, `last_stock_log.stock` kembali ke nilai pre-fix (drift muncul lagi).
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
-- Guard: audit table harus ada
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1 FROM information_schema.tables
|
||||||
|
WHERE table_schema = 'migration_audit'
|
||||||
|
AND table_name = 'jamali_w10_stocklog_corrections'
|
||||||
|
) THEN
|
||||||
|
RAISE EXCEPTION
|
||||||
|
'Audit table migration_audit.jamali_w10_stocklog_corrections tidak ditemukan. UP belum dijalankan atau audit sudah di-drop.';
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
-- DELETE corrective stock_logs yang di-insert oleh UP
|
||||||
|
DELETE FROM stock_logs
|
||||||
|
WHERE id IN (SELECT stock_log_id FROM migration_audit.jamali_w10_stocklog_corrections);
|
||||||
|
|
||||||
|
-- Cleanup audit table
|
||||||
|
DROP TABLE migration_audit.jamali_w10_stocklog_corrections;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- Fix stock_log drift pasca-merge warehouse Jamali (NON_AKTIF) -> Gudang Farm Jamali.
|
||||||
|
-- Follow-up migration setelah 20260528121631_normalize_warehouse_jamali_10_to_25.
|
||||||
|
--
|
||||||
|
-- Setelah merge, `stock_logs.stock` (running ledger) drift dari
|
||||||
|
-- `product_warehouses.qty` karena: pre-existing drift di W10 + W25 sources,
|
||||||
|
-- plus FIFO reflow yang trigger pasca-merge (Recording-Edit) recompute
|
||||||
|
-- pw.qty tapi stock_logs tidak ikut update.
|
||||||
|
--
|
||||||
|
-- Migration ini insert 1 ADJUSTMENT stock_log corrective per PW yang drift
|
||||||
|
-- supaya `last_stock_log.stock = pw.qty`. Logic ekivalen dengan
|
||||||
|
-- `cmd/fix-stock-log-drift`.
|
||||||
|
--
|
||||||
|
-- Karakteristik dynamic:
|
||||||
|
-- - Tidak hardcode PW IDs atau drift values
|
||||||
|
-- - Iterate via merge target + W10-only kept PWs (data-driven dari snapshot)
|
||||||
|
-- - Per PW: hitung drift runtime, skip kalau negligible (< 0.001) atau no logs
|
||||||
|
-- - Track stock_log IDs yang di-insert untuk DOWN reverse
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
-- Guard: previous migration (normalisasi) audit harus ada
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1 FROM information_schema.tables
|
||||||
|
WHERE table_schema = 'migration_audit'
|
||||||
|
AND table_name = 'jamali_w10_qty_merge'
|
||||||
|
) THEN
|
||||||
|
RAISE EXCEPTION
|
||||||
|
'Migration 20260528121631 (normalize_warehouse_jamali) belum dijalankan atau audit-nya sudah di-drop. Apply UP-nya dulu sebelum migration ini.';
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
-- Audit table untuk track stock_log IDs yang di-insert (untuk DOWN reverse)
|
||||||
|
DROP TABLE IF EXISTS migration_audit.jamali_w10_stocklog_corrections;
|
||||||
|
CREATE TABLE migration_audit.jamali_w10_stocklog_corrections (
|
||||||
|
stock_log_id BIGINT NOT NULL PRIMARY KEY,
|
||||||
|
product_warehouse_id BIGINT NOT NULL,
|
||||||
|
drift NUMERIC(15,3) NOT NULL,
|
||||||
|
inserted_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Insert corrective ADJUSTMENT stock_log untuk tiap PW yang drift
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
rec RECORD;
|
||||||
|
v_last_log_stock NUMERIC(15,3);
|
||||||
|
v_drift NUMERIC(15,3);
|
||||||
|
v_new_log_id BIGINT;
|
||||||
|
v_inserts INT := 0;
|
||||||
|
BEGIN
|
||||||
|
FOR rec IN (
|
||||||
|
SELECT pw.id AS pw_id, pw.qty AS qty
|
||||||
|
FROM product_warehouses pw
|
||||||
|
WHERE pw.id IN (
|
||||||
|
-- Merge target W25 PWs (9 rows)
|
||||||
|
SELECT target_pw_id FROM migration_audit.jamali_w10_qty_merge
|
||||||
|
UNION
|
||||||
|
-- W10-only PWs yang di-update warehouse_id 10->25 (4 rows)
|
||||||
|
SELECT id FROM migration_audit.jamali_w10_pw_w10only_snapshot
|
||||||
|
)
|
||||||
|
) LOOP
|
||||||
|
-- Ambil stock akhir di stock_logs ledger
|
||||||
|
SELECT stock INTO v_last_log_stock
|
||||||
|
FROM stock_logs
|
||||||
|
WHERE product_warehouse_id = rec.pw_id
|
||||||
|
ORDER BY id DESC
|
||||||
|
LIMIT 1;
|
||||||
|
|
||||||
|
-- PW tanpa stock_logs entry (mis. 1188/1189/1190 ayam) -> skip
|
||||||
|
IF v_last_log_stock IS NULL THEN
|
||||||
|
CONTINUE;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
v_drift := rec.qty - v_last_log_stock;
|
||||||
|
|
||||||
|
-- Drift negligible -> skip
|
||||||
|
IF ABS(v_drift) < 0.001 THEN
|
||||||
|
CONTINUE;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Insert corrective ADJUSTMENT stock_log
|
||||||
|
INSERT INTO stock_logs (
|
||||||
|
product_warehouse_id, loggable_type, loggable_id,
|
||||||
|
notes, increase, decrease, stock, created_by, created_at
|
||||||
|
) VALUES (
|
||||||
|
rec.pw_id,
|
||||||
|
'ADJUSTMENT',
|
||||||
|
0,
|
||||||
|
'Koreksi stock_log drift pasca-merge warehouse Jamali (migration 20260528123243)',
|
||||||
|
CASE WHEN v_drift > 0 THEN v_drift ELSE 0 END,
|
||||||
|
CASE WHEN v_drift < 0 THEN -v_drift ELSE 0 END,
|
||||||
|
rec.qty,
|
||||||
|
1,
|
||||||
|
NOW()
|
||||||
|
) RETURNING id INTO v_new_log_id;
|
||||||
|
|
||||||
|
-- Track ke audit table untuk DOWN
|
||||||
|
INSERT INTO migration_audit.jamali_w10_stocklog_corrections (
|
||||||
|
stock_log_id, product_warehouse_id, drift
|
||||||
|
) VALUES (v_new_log_id, rec.pw_id, v_drift);
|
||||||
|
|
||||||
|
v_inserts := v_inserts + 1;
|
||||||
|
END LOOP;
|
||||||
|
|
||||||
|
RAISE NOTICE 'Inserted % corrective stock_logs to align ledger with pw.qty', v_inserts;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
Reference in New Issue
Block a user