-- Legacy Egg Cutover Verification Checklist -- Usage: -- 1. Replace the values below before executing. -- 2. Run section BEFORE before --apply. -- 3. Run section AFTER after --apply. -- 4. Run rollback checks if needed. -- ===================================================================== -- PARAMETERS -- ===================================================================== -- Replace manually before running. -- Example: -- location_name = Jamali -- cutover_date = 2026-04-07 -- run_id = egg-cutover-20260407T130344.220407000Z -- ===================================================================== -- BEFORE APPLY -- ===================================================================== -- [BEFORE-01] Identify target location and farm warehouse SELECT l.id AS location_id, l.name AS location_name, fw.id AS farm_warehouse_id, fw.name AS farm_warehouse_name FROM locations l LEFT JOIN warehouses fw ON fw.location_id = l.id AND fw.type = 'LOKASI' AND fw.deleted_at IS NULL WHERE LOWER(l.name) = LOWER('') ORDER BY fw.id ASC; -- Expectation: -- - exactly one target location -- - at least one farm warehouse exists -- [BEFORE-02] Verify location timing status (must be CLEAN_CUTOVER for phase 1) WITH timing AS ( SELECT pf.location_id AS location_id, l.name AS location_name, MIN(CASE WHEN w.type = 'KANDANG' THEN DATE(r.record_datetime) END) AS first_kandang_date, MAX(CASE WHEN w.type = 'KANDANG' THEN DATE(r.record_datetime) END) AS last_kandang_date, MIN(CASE WHEN w.type = 'LOKASI' THEN DATE(r.record_datetime) END) AS first_farm_date, MAX(CASE WHEN w.type = 'LOKASI' THEN DATE(r.record_datetime) END) AS last_farm_date FROM recording_eggs re JOIN recordings r ON r.id = re.recording_id JOIN project_flock_kandangs pk ON pk.id = COALESCE(re.project_flock_kandang_id, r.project_flock_kandangs_id) JOIN project_flocks pf ON pf.id = pk.project_flock_id JOIN locations l ON l.id = pf.location_id JOIN product_warehouses pw ON pw.id = re.product_warehouse_id JOIN warehouses w ON w.id = pw.warehouse_id WHERE LOWER(l.name) = LOWER('') GROUP BY pf.location_id, l.name ) SELECT location_id, location_name, first_kandang_date, last_kandang_date, first_farm_date, last_farm_date, CASE WHEN first_farm_date IS NULL THEN 'KANDANG_ONLY' WHEN last_kandang_date IS NULL OR first_farm_date > last_kandang_date THEN 'CLEAN_CUTOVER' ELSE 'OVERLAP' END AS location_status FROM timing; -- Expectation: -- - phase 1 location must be CLEAN_CUTOVER -- [BEFORE-03] Candidate source rows that should be migrated WITH first_farm AS ( SELECT location_id, MIN(id) AS farm_warehouse_id FROM warehouses WHERE type = 'LOKASI' AND deleted_at IS NULL GROUP BY location_id ) SELECT l.id AS location_id, l.name AS location_name, kw.id AS source_warehouse_id, kw.name AS source_warehouse_name, fw.id AS farm_warehouse_id, fw.name AS farm_warehouse_name, pw.id AS product_warehouse_id, p.id AS product_id, p.name AS product_name, COALESCE(pw.qty, 0) AS on_hand_qty FROM product_warehouses pw JOIN warehouses kw ON kw.id = pw.warehouse_id AND kw.type = 'KANDANG' AND kw.deleted_at IS NULL JOIN locations l ON l.id = kw.location_id JOIN products p ON p.id = pw.product_id LEFT JOIN product_categories pc ON pc.id = p.product_category_id LEFT JOIN first_farm ff ON ff.location_id = kw.location_id LEFT JOIN warehouses fw ON fw.id = ff.farm_warehouse_id WHERE LOWER(l.name) = LOWER('') AND EXISTS ( SELECT 1 FROM recording_eggs re WHERE re.product_warehouse_id = pw.id ) AND ( EXISTS ( SELECT 1 FROM flags f WHERE f.flagable_type = 'products' AND f.flagable_id = p.id AND (UPPER(f.name) = 'TELUR' OR UPPER(f.name) LIKE 'TELUR-%') ) OR ( NOT EXISTS ( SELECT 1 FROM flags f_any WHERE f_any.flagable_type = 'products' AND f_any.flagable_id = p.id ) AND UPPER(COALESCE(pc.code, '')) = 'EGG' ) ) AND COALESCE(pw.qty, 0) > 0 ORDER BY kw.name, p.name; -- Expectation: -- - every row here should match dry-run eligible rows -- [BEFORE-04] Totals per source warehouse and product WITH candidates AS ( SELECT kw.name AS source_warehouse_name, p.name AS product_name, COALESCE(pw.qty, 0) AS on_hand_qty FROM product_warehouses pw JOIN warehouses kw ON kw.id = pw.warehouse_id AND kw.type = 'KANDANG' AND kw.deleted_at IS NULL JOIN locations l ON l.id = kw.location_id JOIN products p ON p.id = pw.product_id LEFT JOIN product_categories pc ON pc.id = p.product_category_id WHERE LOWER(l.name) = LOWER('') AND EXISTS ( SELECT 1 FROM recording_eggs re WHERE re.product_warehouse_id = pw.id ) AND ( EXISTS ( SELECT 1 FROM flags f WHERE f.flagable_type = 'products' AND f.flagable_id = p.id AND (UPPER(f.name) = 'TELUR' OR UPPER(f.name) LIKE 'TELUR-%') ) OR ( NOT EXISTS ( SELECT 1 FROM flags f_any WHERE f_any.flagable_type = 'products' AND f_any.flagable_id = p.id ) AND UPPER(COALESCE(pc.code, '')) = 'EGG' ) ) AND COALESCE(pw.qty, 0) > 0 ) SELECT source_warehouse_name, product_name, SUM(on_hand_qty) AS total_qty FROM candidates GROUP BY source_warehouse_name, product_name ORDER BY source_warehouse_name, product_name; -- [BEFORE-05] Current farm egg stock before cutover SELECT fw.name AS farm_warehouse_name, p.name AS product_name, COALESCE(pw.qty, 0) AS farm_on_hand_qty FROM warehouses fw JOIN locations l ON l.id = fw.location_id JOIN product_warehouses pw ON pw.warehouse_id = fw.id JOIN products p ON p.id = pw.product_id LEFT JOIN product_categories pc ON pc.id = p.product_category_id WHERE LOWER(l.name) = LOWER('') AND fw.type = 'LOKASI' AND fw.deleted_at IS NULL AND ( EXISTS ( SELECT 1 FROM flags f WHERE f.flagable_type = 'products' AND f.flagable_id = p.id AND (UPPER(f.name) = 'TELUR' OR UPPER(f.name) LIKE 'TELUR-%') ) OR ( NOT EXISTS ( SELECT 1 FROM flags f_any WHERE f_any.flagable_type = 'products' AND f_any.flagable_id = p.id ) AND UPPER(COALESCE(pc.code, '')) = 'EGG' ) ) ORDER BY p.name; -- [BEFORE-06] Existing cutover transfers for this location SELECT st.id, st.movement_number, st.transfer_date, st.reason, ws.name AS source_warehouse_name, wd.name AS farm_warehouse_name, st.deleted_at FROM stock_transfers st JOIN warehouses ws ON ws.id = st.from_warehouse_id JOIN warehouses wd ON wd.id = st.to_warehouse_id LEFT JOIN locations l ON l.id = COALESCE(ws.location_id, wd.location_id) WHERE LOWER(COALESCE(l.name, '')) = LOWER('') AND st.reason LIKE 'EGG_FARM_CUTOVER|%' ORDER BY st.id DESC; -- Expectation: -- - no unexpected older active cutover transfers for the same location -- ===================================================================== -- AFTER APPLY -- ===================================================================== -- [AFTER-01] Transfer headers created by run_id SELECT st.id, st.movement_number, st.transfer_date, st.reason, ws.name AS source_warehouse_name, wd.name AS farm_warehouse_name, st.deleted_at FROM stock_transfers st JOIN warehouses ws ON ws.id = st.from_warehouse_id JOIN warehouses wd ON wd.id = st.to_warehouse_id WHERE st.reason LIKE 'EGG_FARM_CUTOVER|run_id=|%' ORDER BY st.id ASC; -- [AFTER-02] Transfer detail rows created by run_id SELECT st.id AS transfer_id, st.movement_number, ws.name AS source_warehouse_name, wd.name AS farm_warehouse_name, p.name AS product_name, COALESCE(std.total_qty, std.usage_qty, 0) AS moved_qty, std.source_product_warehouse_id, std.dest_product_warehouse_id FROM stock_transfers st JOIN stock_transfer_details std ON std.stock_transfer_id = st.id AND std.deleted_at IS NULL JOIN products p ON p.id = std.product_id JOIN warehouses ws ON ws.id = st.from_warehouse_id JOIN warehouses wd ON wd.id = st.to_warehouse_id WHERE st.deleted_at IS NULL AND st.reason LIKE 'EGG_FARM_CUTOVER|run_id=|%' ORDER BY st.id, p.name; -- [AFTER-03] Stock logs created by run_id transfer details SELECT st.id AS transfer_id, st.movement_number, p.name AS product_name, sl.product_warehouse_id, sl.increase, sl.decrease, sl.stock, sl.created_at FROM stock_transfers st JOIN stock_transfer_details std ON std.stock_transfer_id = st.id AND std.deleted_at IS NULL JOIN products p ON p.id = std.product_id JOIN stock_logs sl ON sl.loggable_type = 'TRANSFER' AND sl.loggable_id = std.id WHERE st.deleted_at IS NULL AND st.reason LIKE 'EGG_FARM_CUTOVER|run_id=|%' ORDER BY st.id, p.name, sl.id; -- Expectation: -- - every detail has one stock log decrease from source and one stock log increase to destination -- [AFTER-04] Source rows after cutover SELECT kw.name AS source_warehouse_name, p.name AS product_name, COALESCE(pw.qty, 0) AS source_qty_after FROM product_warehouses pw JOIN warehouses kw ON kw.id = pw.warehouse_id JOIN locations l ON l.id = kw.location_id JOIN products p ON p.id = pw.product_id WHERE LOWER(l.name) = LOWER('') AND kw.type = 'KANDANG' AND EXISTS ( SELECT 1 FROM recording_eggs re WHERE re.product_warehouse_id = pw.id ) ORDER BY kw.name, p.name; -- Expectation: -- - rows that were transferred should now be 0 or no longer available for use -- [AFTER-05] Farm rows after cutover SELECT fw.name AS farm_warehouse_name, p.name AS product_name, COALESCE(pw.qty, 0) AS farm_qty_after FROM product_warehouses pw JOIN warehouses fw ON fw.id = pw.warehouse_id JOIN locations l ON l.id = fw.location_id JOIN products p ON p.id = pw.product_id WHERE LOWER(l.name) = LOWER('') AND fw.type = 'LOKASI' ORDER BY fw.name, p.name; -- Expectation: -- - farm qty increases by the moved amount -- [AFTER-06] Reconciliation: total moved by run SELECT p.name AS product_name, SUM(COALESCE(std.total_qty, std.usage_qty, 0)) AS total_moved_qty FROM stock_transfers st JOIN stock_transfer_details std ON std.stock_transfer_id = st.id AND std.deleted_at IS NULL JOIN products p ON p.id = std.product_id WHERE st.deleted_at IS NULL AND st.reason LIKE 'EGG_FARM_CUTOVER|run_id=|%' GROUP BY p.name ORDER BY p.name; -- [AFTER-07] Farm stock available for SO after cutover SELECT fw.name AS farm_warehouse_name, p.name AS product_name, COALESCE(pw.qty, 0) AS available_qty FROM product_warehouses pw JOIN warehouses fw ON fw.id = pw.warehouse_id JOIN locations l ON l.id = fw.location_id JOIN products p ON p.id = pw.product_id WHERE LOWER(l.name) = LOWER('') AND fw.type = 'LOKASI' AND COALESCE(pw.qty, 0) > 0 ORDER BY p.name; -- ===================================================================== -- ROLLBACK CHECKS -- ===================================================================== -- [ROLLBACK-01] Check downstream consumption guard before rollback SELECT st.id AS transfer_id, st.movement_number, p.name AS product_name, sa.usable_type, sa.usable_id, sa.qty, sa.function_code, sa.flag_group_code FROM stock_transfers st JOIN stock_transfer_details std ON std.stock_transfer_id = st.id AND std.deleted_at IS NULL JOIN products p ON p.id = std.product_id JOIN stock_allocations sa ON sa.stockable_type = 'STOCK_TRANSFER_IN' AND sa.stockable_id = std.id AND sa.status = 'ACTIVE' AND sa.allocation_purpose = 'CONSUME' AND sa.deleted_at IS NULL WHERE st.deleted_at IS NULL AND st.reason LIKE 'EGG_FARM_CUTOVER|run_id=|%' ORDER BY st.id, p.name, sa.usable_type, sa.usable_id; -- Expectation: -- - rollback only safe if this query returns 0 rows -- [ROLLBACK-02] Verify run is fully rolled back SELECT st.id, st.movement_number, st.deleted_at FROM stock_transfers st WHERE st.reason LIKE 'EGG_FARM_CUTOVER|run_id=|%' ORDER BY st.id; -- Expectation: -- - after rollback, deleted_at should be filled for all transfers in the run