15 KiB
Stock Consolidation Operations Guide
This guide explains how to use the warehouse consolidation commands to fix misplaced PAKAN/OVK stocks and migrate them to the correct farm-level warehouses.
Overview
The stock consolidation system handles two main scenarios:
| Case | Scenario | Root Cause | Solution |
|---|---|---|---|
| Case B | Invalid kandang references | Purchases pointed to warehouses with location mismatch | Move unused stocks to correct farm-level warehouse |
| Case A | General kandang cleanup | Any kandang-level warehouse with unused PAKAN/OVK stocks | Consolidate to farm-level warehouse |
Recommended Execution Order
For a complete stock consolidation operation, follow this sequence:
1. find-wrong-warehouse-records ← Diagnose issues
2. repoint-wrong-warehouse-relations ← Fix Case B (invalid references)
3. consolidate-kandang-to-farm-stocks ← Fix Case A (general cleanup)
4. verify-stock-consolidation ← Audit and verify results
Command Reference
1. find-wrong-warehouse-records — Diagnostic Tool
Purpose: Identify problematic warehouses and their associated stocks before making any changes.
Applies to: Both Case A and Case B scenarios
What it does:
- Lists warehouses with location mismatches (Case B)
- Shows stock allocations that reference wrong warehouses
- Helps identify scope of work needed
Usage:
# Report 1: Find warehouses with location mismatches (Case B issues)
./find-wrong-warehouse-records --report=warehouses
# Report 2: Find stock allocations in wrong warehouses (Case B impact)
./find-wrong-warehouse-records --report=usage
# Filter by area
./find-wrong-warehouse-records --report=warehouses --area-name "East Region"
# Filter by kandang location
./find-wrong-warehouse-records --report=usage --kandang-location-name "Location 1"
# Filter by product type
./find-wrong-warehouse-records --report=usage --usable-type=RECORDING_STOCK
# JSON output for analysis
./find-wrong-warehouse-records --report=usage --output=json > analysis.json
Output Columns (Warehouses Report):
- AREA: Geographic area
- KANDANG_LOCATION: Kandang's intended location
- KANDANG: Kandang name
- WRONG_LOCATION: Where the warehouse actually is
- WRONG_WAREHOUSE: Problematic warehouse name
- CORRECT_WAREHOUSE: Where stocks should be
Output Columns (Usage Report):
- USABLE_TYPE: RECORDING_STOCK or MARKETING_DELIVERY
- PRODUCTS: Which products are affected
- QTY_FROM_WRONG_STOCK: How much stock is misplaced
- SOURCE_PURCHASES: Which purchase orders are affected
When to use:
- Before starting any consolidation
- To understand the scope of issues
- To get metrics on how much stock needs moving
- To identify which areas are most affected
2. repoint-wrong-warehouse-relations — Fix Case B (Invalid References)
Purpose: Fix purchases pointed to invalid kandang warehouses (location mismatch).
Applies to: Case B only
Cases it handles:
- ✅ Warehouses with
location_id ≠ kandang.location_id(location mismatch) - ✅ Only PAKAN/OVK products
- ✅ Only unused/leftover stocks (no active allocations)
- ✅ Moves to farm-level warehouse at correct location
What it does:
- Finds product_warehouses in wrong locations
- Consolidates duplicates into survivor warehouses
- Updates all references across the system
- Recalculates FIFO stocks if needed
- Optionally soft-deletes the wrong warehouse
Usage:
# Dry-run: See what would be moved (always run first!)
./repoint-wrong-warehouse-relations
# Dry-run with specific filters
./repoint-wrong-warehouse-relations --area-name "East Region"
./repoint-wrong-warehouse-relations --kandang-location-name "Location 1"
# Actually apply the migration
./repoint-wrong-warehouse-relations --apply
# Apply but keep the wrong warehouses (for audit trail)
./repoint-wrong-warehouse-relations --apply --delete-wrong-warehouses=false
# JSON output for automation/logging
./repoint-wrong-warehouse-relations --apply --output=json > migration.json
Flags:
--apply: Apply changes (omit for dry-run)--output:table(default) orjson--area-name: Filter by exact area name--kandang-location-name: Filter by exact location name--delete-wrong-warehouses: Soft-delete wrong warehouses (default: true)--db-sslmode: PostgreSQL SSL mode override (e.g.,require)
Output:
Table mode shows:
- AREA, LOCATION, KANDANG: Where the issue is
- WRONG_WAREHOUSE: Source (will be deleted)
- TARGET_WAREHOUSE: Destination (farm-level)
- PRODUCT: What's being moved
- SURVIVOR_PW / ABSORBED_PW: Consolidation details
- NEEDS_REFLOW: Whether FIFO recalculation is needed
Summary shows:
Summary: plan_rows=15 wrong_warehouses=3 survivor_pws=12 absorbed_pws=5
needs_reflow_pws=3 deleted_product_warehouses=5 soft_deleted_warehouses=3
Updated product_warehouse refs:
fifo_stock_v2_operation_log.product_warehouse_id=8
fifo_stock_v2_reflow_checkpoints.product_warehouse_id=3
purchase_items.warehouse_id=12
Updated warehouse refs:
purchase_items.warehouse_id=12
Safety Features:
- Dry-run first: Always preview before applying
- Prechecks: Verifies no blocked references or FIFO conflicts
- Atomic transactions: All-or-nothing database updates
- Reference verification: Confirms all references were updated
- Stock log recalculation: Ensures FIFO accuracy after moves
3. consolidate-kandang-to-farm-stocks — Fix Case A (General Cleanup)
Purpose: Consolidate ALL kandang-level PAKAN/OVK stocks to farm-level warehouse.
Applies to: Case A only
Cases it handles:
- ✅ ALL kandang-level warehouses (type ≠ 'LOKASI')
- ✅ Only PAKAN/OVK products
- ✅ Only unused/leftover stocks (no active allocations)
- ✅ Moves to farm-level warehouse regardless of warehouse validity
- ✅ No location validation (processes all kandang warehouses)
What it does:
- Finds all kandang-level warehouses with unused stocks
- Consolidates duplicates into survivor warehouses
- Updates all references across the system
- Recalculates FIFO stocks if needed
- Optionally soft-deletes the kandang warehouse
Usage:
# Dry-run: See what would be consolidated
./consolidate-kandang-to-farm-stocks
# Dry-run with filters
./consolidate-kandang-to-farm-stocks --area-name "East Region"
./consolidate-kandang-to-farm-stocks --kandang-location-name "Location 1"
# Actually apply the consolidation
./consolidate-kandang-to-farm-stocks --apply
# Apply but keep kandang warehouses
./consolidate-kandang-to-farm-stocks --apply --delete-kandang-warehouses=false
# JSON output for logging
./consolidate-kandang-to-farm-stocks --apply --output=json > consolidation.json
Flags:
--apply: Apply changes (omit for dry-run)--output:table(default) orjson--area-name: Filter by exact area name--kandang-location-name: Filter by exact location name--delete-kandang-warehouses: Soft-delete kandang warehouses (default: true)--db-sslmode: PostgreSQL SSL mode override
Output Format:
Similar to Case B, shows:
- Source kandang warehouse → Destination farm warehouse
- Product and quantity details
- Consolidation and FIFO reflow information
Key Differences from Case B:
| Aspect | Case B | Case A |
|---|---|---|
| Scope | Wrong-location warehouses only | ALL kandang-level warehouses |
| Validation | Checks location mismatch | No validation checks |
| When to use | After finding mismatches | General cleanup/consolidation |
| Risk level | Lower (targeted fix) | Higher (broader scope) |
4. verify-stock-consolidation — Audit and Verify
Purpose: Verify that stock consolidations were successful and no stocks were lost.
Applies to: Both Case A and Case B (post-migration verification)
What it checks:
✅ Source Warehouse Verification
Ensures deleted warehouses are clean:
- CLEAN: No remaining stock or purchase references
- DIRTY: Still has orphaned data (migration incomplete)
✅ Destination Warehouse Verification
Ensures farm-level warehouses received stocks correctly:
- MATCHED: Quantity in product_warehouse matches stock_logs
- DISCREPANCY: Quantity mismatch (data integrity issue!)
- EMPTY: No stocks (correct if nothing was supposed to move)
✅ Orphaned Reference Detection
Finds any remaining references to deleted warehouses in:
purchase_items.warehouse_idstock_transfers.from/to_warehouse_idfifo_stock_v2_operation_log.warehouse_id
Usage:
# Verify all consolidations (Case A + B together)
./verify-stock-consolidation
# Verify only Case B results
./verify-stock-consolidation --verify-case=B
# Verify only Case A results
./verify-stock-consolidation --verify-case=A
# Filter by area
./verify-stock-consolidation --area-name "East Region"
# Filter by location
./verify-stock-consolidation --kandang-location-name "Location 1"
# JSON output for reporting
./verify-stock-consolidation --output=json > verification_report.json
Flags:
--verify-case:A,B, orall(default)--output:table(default) orjson--area-name: Filter by exact area name--kandang-location-name: Filter by exact location name--db-sslmode: PostgreSQL SSL mode override
Output Sections:
1. Source Warehouses
AREA LOKASI KANDANG WAREHOUSE CASE DELETED_AT STOCK PURCHASES STATUS
Area A Location 1 Kandang A KWH-A-01 A 2026-04-23 0.000 0 CLEAN
Area A Location 1 Kandang B WH-WRONG-001 B 2026-04-23 2.500 1 DIRTY ❌
2. Destination Warehouses
AREA LOKASI FARM_WAREHOUSE PRODUCT QTY LOGS_TOTAL LOGS STATUS
Area A Location 1 FWH-LOC-001 PAKAN A 2.500 2.500 3 MATCHED ✅
Area A Location 1 FWH-LOC-001 OVK B 5.000 4.999 5 DISCREPANCY ❌
3. Orphaned References (if any)
TABLE COLUMN COUNT WAREHOUSE_IDS
purchase_items warehouse_id 3 1001, 1002, 1003
stock_transfers from_warehouse_id 1 1001
4. Summary
Source Warehouses: 10 total, 8 clean, 2 dirty
Destination Warehouses: 15 total, 14 matching, 1 discrepancy
Orphaned References: 4
Overall Status: FAIL ❌
Interpreting Results:
| Scenario | Meaning | Action |
|---|---|---|
| ✅ Overall Status: PASS | All migrations successful | No action needed |
| ❌ Dirty Source Warehouses | Stocks not fully moved | Re-run repoint/consolidate |
| ❌ Discrepancy Destinations | Quantity mismatch | Investigate data integrity |
| ❌ Orphaned References | Broken references remain | Manual cleanup needed |
Complete Workflow Example
Scenario: Consolidate East Region stocks
# Step 1: Understand the scope (Case B issues)
./find-wrong-warehouse-records --report=warehouses --area-name "East Region"
./find-wrong-warehouse-records --report=usage --area-name "East Region"
# Review the output to understand:
# - How many wrong warehouses
# - How much stock needs moving
# - Which products are affected
# Step 2: Fix Case B (invalid kandang references)
./repoint-wrong-warehouse-relations --area-name "East Region"
# Review dry-run output
./repoint-wrong-warehouse-relations --apply --area-name "East Region"
# Watch for summary - should show successful updates
# Step 3: Fix Case A (general kandang cleanup)
./consolidate-kandang-to-farm-stocks --area-name "East Region"
# Review dry-run output
./consolidate-kandang-to-farm-stocks --apply --area-name "East Region"
# Watch for summary - should show consolidation complete
# Step 4: Verify everything worked
./verify-stock-consolidation --area-name "East Region"
# Should show:
# - All source warehouses: CLEAN
# - All destination warehouses: MATCHED
# - Orphaned references: 0
# - Overall Status: PASS ✅
Flags Reference
Common Flags (All Commands)
| Flag | Description | Example |
|---|---|---|
--output |
Output format | --output=json |
--area-name |
Filter by area | --area-name "East Region" |
--kandang-location-name |
Filter by location | --kandang-location-name "Location 1" |
--db-sslmode |
PostgreSQL SSL mode | --db-sslmode=require |
Migration-Specific Flags
| Command | Flag | Description |
|---|---|---|
repoint-wrong-warehouse-relations |
--apply |
Apply changes |
repoint-wrong-warehouse-relations |
--delete-wrong-warehouses |
Delete wrong warehouses (default: true) |
consolidate-kandang-to-farm-stocks |
--apply |
Apply changes |
consolidate-kandang-to-farm-stocks |
--delete-kandang-warehouses |
Delete kandang warehouses (default: true) |
verify-stock-consolidation |
--verify-case |
Verify specific case (A, B, or all) |
Best Practices
Before Running Any Command
- Back up the database — These operations modify stock data
- Run in dry-run mode first — Always preview changes before applying
- Check during low-traffic periods — Avoid peak hours
- Have a rollback plan — Know how to restore from backup if needed
When Running Migrations
- Start small — Use
--area-nameto test on one area first - Check the summary — Verify numbers make sense
- Watch for errors — Stop if you see unexpected error messages
- Run verification immediately after — Don't wait to verify
Red Flags (Stop and Investigate)
- ❌ More rows affected than expected
- ❌ Negative quantities or zero counts where expecting data
- ❌ Errors about blocked references
- ❌ FIFO conflicts or in-flight artifacts
- ❌ Very large numbers in NEEDS_REFLOW
JSON Output for Automation
All commands support --output=json for:
- Piping to other tools
- Parsing in scripts
- Generating reports
- Integration with monitoring systems
# Example: Extract all affected warehouses to CSV
./find-wrong-warehouse-records --report=warehouses --output=json \
| jq -r '.rows[] | [.area_name, .kandang_name, .wrong_warehouse_name] | @csv' \
> affected_warehouses.csv
Troubleshooting
Issue: "No wrong warehouse relations found"
- Cause: No matching Case B issues in the filter scope
- Solution: Remove filters or use different criteria
Issue: "found X rows still point to wrong warehouses"
- Cause: References not fully migrated
- Solution: Check for blocked references, re-run command
Issue: "discrepancy_destinations > 0" in verification
- Cause: Quantity mismatch in farm warehouse
- Solution: Investigate manually or rollback and retry
Issue: "DIRTY source warehouses" in verification
- Cause: Deleted warehouses still have stock/references
- Solution: May need manual cleanup or re-run migrations
Performance Notes
- Commands use efficient SQL queries with proper filtering
- Large operations (100K+ rows) may take a few minutes
- Use area/location filters to reduce scope for testing
- Dry-runs don't modify database and complete quickly
Support
For issues or questions:
- Review the relevant section of this guide
- Check the command output for specific error messages
- Run verification to diagnose state issues
- Contact the development team with JSON outputs from failed operations