ForgeFlow-ERP/docs/superpowers/plans/2026-06-02-semi-finished-measure-basis.md
2026-06-12 16:00:56 +08:00

4.6 KiB

Semi-Finished Measure Basis Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Make semi-finished inventory use one locked measure basis per semi-finished item-operation in a warehouse: by piece or by weight.

Architecture: Do not add a database column unless tests prove derivation is insufficient. Derive the measure basis from semi-finished stock lots: remaining_qty/inbound_qty means by piece, remaining_weight_kg/inbound_weight_kg means by weight, both means legacy mixed. Backend enforces exactly one inbound basis and blocks mismatched new inbound for existing semi-finished stock; frontend presents only the correct input and availability wording.

Tech Stack: FastAPI, SQLAlchemy, pytest, Vue 3, Vite, Node assertion script.


Task 1: Backend Measure Basis Enforcement

Files:

  • Modify: backend/app/api/routes/inventory.py

  • Modify: backend/tests/test_semi_finished_operation_inventory.py

  • Step 1: Write failing backend tests

Add tests that prove:

  • semi-finished inbound rejects filling both quantity and weight;

  • semi-finished inbound rejects filling neither quantity nor weight;

  • once a semi-finished item-operation has by-piece stock, later by-weight inbound is rejected;

  • once a semi-finished item-operation has by-weight stock, later by-piece inbound is rejected.

  • Step 2: Run red tests

Run: .venv/bin/python -m pytest tests/test_semi_finished_operation_inventory.py -q

Expected before implementation: at least the mismatch/both-filled tests fail because current backend accepts both fields and does not enforce existing basis.

  • Step 3: Implement minimal backend helper

Add helper logic in create_warehouse_inbound:

  • determine requested basis: PIECE when inbound_qty > 0 and inbound_weight == 0, WEIGHT when inbound_weight > 0 and inbound_qty == 0;

  • reject both-filled and neither-filled for WIP_IN / OUTSOURCING_IN;

  • query existing semi-finished lots for same item_id, warehouse_id, source_line_id with remaining quantity or weight;

  • derive existing basis; if it is MIXED, reject with a Chinese message asking to clean historical stock first;

  • if existing basis exists and differs from requested basis, reject with a Chinese message that the semi-finished item must follow existing measure basis.

  • Step 4: Run backend tests

Run: .venv/bin/python -m pytest tests/test_semi_finished_operation_inventory.py -q

Expected: all semi-finished tests pass.

Task 2: Frontend Semi-Finished UI Basis

Files:

  • Modify: frontend/src/views/InventoryLedgerView.vue

  • Modify: frontend/src/utils/inventoryOperationOptions.js

  • Modify: frontend/scripts/test-inventory-ledger-options.mjs

  • Step 1: Write/update frontend assertions

Assert the source contains:

  • user-facing label 半成品 instead of semi warehouse 产品工序;

  • 入库类型, 按件入库, 按重入库;

  • helper logic that formats semi availability by basis instead of always formatWeight(...);

  • payload sends only inbound_qty for piece basis and only inbound_weight_kg for weight basis.

  • Step 2: Run red frontend assertion

Run: node scripts/test-inventory-ledger-options.mjs

Expected before implementation: fails on missing measure-basis UI or payload logic.

  • Step 3: Implement frontend UI

In InventoryLedgerView.vue:

  • rename semi item field labels from 产品工序 to 半成品;
  • add genericForm.measure_basis;
  • when semi inbound item changes, derive existing basis from semiFinishedBalances and auto-fill/lock measure_basis;
  • show only 入库数量 for PIECE, only 入库重量(kg) for WEIGHT;
  • for semi outbound, derive basis from selected semi option and show only the matching outbound input;
  • display - for irrelevant quantity/weight values in semi balances and lots.

In inventoryOperationOptions.js:

  • carry measure_basis through semi outbound options.

  • Step 4: Run frontend checks

Run: node scripts/test-inventory-ledger-options.mjs

Expected: assertion script passes.

Run: npm run build

Expected: Vite build completes successfully.

Task 3: Final Verification

Files:

  • Verify only.

  • Step 1: Run backend full test suite

Run: .venv/bin/python -m pytest tests -q

Expected: all backend tests pass.

  • Step 2: Browser smoke

Run frontend dev server and open http://127.0.0.1:5173/ in the in-app browser.

Expected: page loads with title 嘉恒智能五金 ERP and no console errors.