MK Inventory Allocation Capability Rebuild Packet¶
- Packet status:
DETAILED SOURCE-RECONCILED REBUILD INPUT / POLICY, TARGET-ROLE AND RUNTIME REVIEW REQUIRED - Capability: inventory-lot allocation to an existing MK outbound shipment
- Process owner:
PROC-OMS-INVENTORY-TO-OUTBOUND-ALLOCATION-MK - Operating profile:
mk-order - Current module:
oms.allocation - Current primary records:
T_INVENTORY_LOT,T_LOAD_ALLOCATION,T_LOAD,T_LOAD_ITEM - Related source records:
T_TRANSLOAD, source inboundT_LOAD/T_LOAD_ITEM - Related target bridge:
T_EQUIPMENT,T_EQUIPMENT_LOAD - Target stack: React + Next.js + framework-independent TypeScript application/domain/repository contracts + MySQL first
- Worker requirement: none for the core local allocation transaction; use a worker only for separately approved asynchronous effects
- Later database target: PostgreSQL after accepted React + Next.js + TypeScript + MySQL stabilization
- Current Process contract:
MK_SCHEDULE_ALLOCATION_WORKFLOW.md - Current source authority:
MK_INVENTORY_ALLOCATION_SOURCE_AUTHORITY.md - Important boundary: this packet assembles current behavior, target contracts and migration requirements. It does not approve open allocation, reversal, UOM, quantity/weight or role policy.
1. Capability Outcome¶
1.1 Business problem¶
MK receiving creates inventory lots, while outbound Sales records requested shipment demand. Allocation must establish an explicit, tenant-scoped relation between eligible received inventory and an existing outbound shipment without making Inbound or Outbound CRUD itself the allocation authority.
The capability must preserve these distinctions:
Inbound receipt
!= Inventory Lot eligibility
!= Allocation commitment
!= Outbound demand completion
!= Scale / Packing / Delivery completion
1.2 Required user-visible result¶
An authorized inventory/allocation operator can:
- enter the Allocation Workbench through the assigned MK menu;
- search eligible source lots and understand the exact inbound source identity;
- add intended source lots to a basket;
- select one existing outbound shipment with an active container/equipment bridge;
- preview quantity, weight, UOM, rate and target identity before commit;
- apply the basket once;
- reread the exact created outbound item, allocation relation and source-lot balance;
- distinguish allocation completion from physical shipment completion;
- recover from stale balance, duplicate, timeout or unknown result without replaying the complete basket blindly;
- correct or reverse an allocation only through an explicitly approved owner command;
- retain stable Wiki topics when the current PHP page later moves to React + Next.js.
1.3 Explicit non-goals¶
This packet does not approve:
- one universal MK order or inventory status;
- allocation as a side effect of ordinary Inbound or Outbound Save;
- hidden allocation inside Booking Save;
- a generic table/column mutation API;
- automatic conversion between arbitrary UOM values;
- silent over-allocation or negative remaining balances;
- blind replay after a missing response;
- hard deletion as the target reversal model;
- a universal unallocate path before downstream-lock policy is accepted;
- a new asynchronous worker for the core local transaction;
- route-by-route copying of current PHP into TypeScript;
- PostgreSQL conversion in the first React/Next.js write wave.
2. Current Truth Table¶
| Statement | Current source-reconciled truth |
|---|---|
| Workbench selects an existing outbound shipment | Yes |
| Workbench creates a new target shipment | No |
| One basket row represents one source lot/source order item pair | Yes |
| Current UI allocates the full displayed remaining lot | Yes |
| Current UI supports partial-lot quantity/weight entry | No |
| Current Apply creates a new outbound item for every basket source | Yes |
Current Apply creates one T_LOAD_ALLOCATION row per new outbound item |
Yes |
| The whole basket is one local DB transaction | Yes |
| A later row failure rolls back earlier rows in the request | Yes, under the current request transaction |
Immediate lot update decrements REMAIN_NET_WEIGHT |
Yes |
Immediate lot update decrements REMAIN_QUANTITY |
No |
Current write validates LOT_STATUS='OPEN' again |
Not proven in the write helper |
| Current write validates the complete source item/transload eligibility again | Not proven |
| Current write validates UOM compatibility or conversion | No approved validation found |
| Current request has a durable idempotency token | No |
| Current general unallocate/reversal command exists | Not source-confirmed |
| Outbound item delete is blocked when an active allocation exists | Yes |
| Outbound allocated-item update fully reconciles allocation and lot balance | No |
| Booking compatibility can affect lot/allocation state | Yes, separately documented |
| React + Next.js allocation implementation exists | No |
Every downstream document must classify statements as:
CURRENT SOURCE-RECONCILED
CURRENT RUNTIME-VERIFIED
USER-APPROVED FUTURE PLAN
TARGET MIGRATION DESIGN
OPEN POLICY / UNKNOWN
3. Capability Boundary¶
3.1 Allocation owns¶
- selection of eligible source lot(s);
- selection of one eligible existing outbound shipment;
- accepted source-to-target allocation relation;
- allocation quantity, weight, rate, UOM and remark snapshot;
- target outbound item created for the allocation under current parity behavior;
- conditional source balance consumption;
- exact post-commit source/target/allocation readback;
- duplicate, stale, unknown-result and reversal reconciliation;
- allocation audit and correction reason in the target model.
3.2 Allocation does not own¶
- receipt or lot materialization;
- arbitrary lot quantity/weight correction;
- general Outbound header/item CRUD;
- Booking lifecycle;
- Scale, Packing, Delivery or Cost completion;
- Commercial fulfillment;
- Yard/Warehouse physical movement;
- cross-tenant or customer-specific policy;
- hidden cleanup initiated from another module.
3.3 Cross-owner handoff¶
Inbound receipt owner
-> exact Inventory Lot
-> Allocation owner
-> exact T_LOAD_ALLOCATION + target Outbound Item
-> Outbound/Scale/Packing/Delivery owners
A child owner must reread its own authoritative data. No child may infer completion from a success toast or another child’s label.
4. Actors And Capabilities¶
4.1 Actors¶
| Actor | Normal responsibility | Must not do |
|---|---|---|
| Inventory/Allocation operator | review source lots, basket and target; apply; reread; escalate conflicts | edit DB rows, assume an unallocate path, replay unknown requests |
| Receiving operator | establish and correct received source evidence through Inbound/Inventory owner | change allocation rows from Inbound editor |
| Shipping operator | establish outbound shipment and review allocated demand | allocate through ordinary Outbound Save |
| Manager/Administrator | review conflict, correction or reversal; authorize bounded recovery | use generic mutation as a universal recovery |
| Support/Migration operator | inspect exact IDs, request identity, callers and parity | invent business policy or modify Production without authorization |
4.2 Target semantic capabilities¶
oms.allocation.view
oms.allocation.preview
oms.allocation.apply
oms.allocation.correct
oms.allocation.reverse
oms.allocation.reconcile
oms.allocation.support
Target authorization is evaluated from authenticated actor, tenant, profile, semantic capability, record scope and current state. Numeric role IDs and CLIENT_ID === 2 are compatibility inputs only.
4.3 Record-scope rules¶
- source lot, source order/item/transload and target order/item must belong to the effective tenant;
- target order must be an active MK Outbound Sales order;
- source lot must be active and eligible under accepted lot policy;
- actor must not infer access from a visible row alone;
- direct IDs must be revalidated server-side;
- correction/reversal requires stronger capability and downstream-state review than ordinary Apply.
5. Current Entry And Interaction Model¶
5.1 Current entry¶
Operations > Orders > Allocation Workbench
slug: mk-allocation-workbench
module: oms.allocation
5.2 Current page model¶
The page exposes:
- source mode/filter/search;
- eligible source-lot list;
- client-side basket;
- existing target-shipment selector;
- selected target summary;
- Apply to Existing Shipment action.
Client-side state and localStorage are convenience state only. They are not allocation authority or durable intent.
5.3 Current basket identity¶
INVENTORY_LOT_ID : SOURCE_ORDER_ITEM_ID
The UI copies the displayed full REMAIN_QUANTITY and REMAIN_NET_WEIGHT into the Apply payload. It does not present a partial-allocation input.
5.4 Current target behavior¶
The Workbench requires an existing target order with:
- active Outbound Sales classification;
- active equipment-load/equipment bridge;
- nonempty container number;
- nonempty size;
- equipment-load status not
RETURNEDorBROKEN.
It does not create a new outbound shipment.
6. State Model¶
These are semantic state families. They are not automatic schema changes.
6.1 Inventory Lot eligibility projection¶
ELIGIBLE
PARTIALLY_AVAILABLE
EXHAUSTED
HELD
CLOSED
CONFLICT
Current source-list evidence commonly treats an active OPEN lot with positive REMAIN_NET_WEIGHT as eligible. The target policy must also define quantity, UOM, source status, hold/close and correction rules.
6.2 Outbound demand allocation projection¶
UNALLOCATED
PARTIALLY_ALLOCATED
ALLOCATED
OVERALLOCATED_CONFLICT
NOT_APPLICABLE
Current Workbench creates new target items per source lot rather than allocating against a preexisting demand line. The target must preserve this for parity initially or explicitly approve a different demand-line model.
6.3 Allocation relation state¶
ACTIVE
CORRECTED
REVERSED
CONFLICT
Current source primarily represents active versus soft-deleted allocation rows. The target should preserve immutable correction/reversal evidence rather than hard-delete financial/inventory history.
6.4 Basket state¶
DRAFT_CLIENT_ONLY
PREVIEWED
COMMITTED
CONFLICT
UNKNOWN
Current basket is client-only until Apply. A target preview/request identity may be durable or idempotently reconstructable; the exact persistence design remains a P5/P6/P12 decision.
7. Authoritative Data And Identity¶
7.1 Entity relationship¶
erDiagram
T_LOAD ||--o{ T_LOAD_ITEM : contains
T_INVENTORY_LOT ||--o{ T_LOAD_ALLOCATION : supplies
T_LOAD_ITEM ||--o{ T_LOAD_ALLOCATION : receives
T_LOAD ||--o{ T_LOAD_ALLOCATION : target_order
T_LOAD_ITEM ||--o{ T_INVENTORY_LOT : source_item
T_TRANSLOAD ||--o{ T_INVENTORY_LOT : source_receipt
T_EQUIPMENT_LOAD }o--|| T_LOAD : bridges_target
T_EQUIPMENT ||--o{ T_EQUIPMENT_LOAD : identifies_container
7.2 Stable current identities¶
| Identity | Purpose |
|---|---|
T_INVENTORY_LOT.ID/UUID |
source inventory identity |
SOURCE_ORDER_ID |
source Inbound Purchase header |
SOURCE_ORDER_ITEM_ID |
exact source line |
SOURCE_TRANSLOAD_ID |
exact receipt/execution bridge |
target T_LOAD.ID/UUID |
existing Outbound Sales shipment |
created target T_LOAD_ITEM.ID |
target line created by current Apply |
T_LOAD_ALLOCATION.ID |
authoritative source-to-target relation |
| request token, target design | duplicate/unknown-result reconciliation |
| correction/reversal identity, target design | immutable adjustment chain |
7.3 T_INVENTORY_LOT field dictionary¶
| Field | Meaning / rule |
|---|---|
ID, UUID |
stable lot identity; never use list position |
CLIENT_ID |
tenant scope |
SOURCE_ORDER_ID |
originating Inbound order |
SOURCE_ORDER_ITEM_ID |
originating line |
SOURCE_TRANSLOAD_ID |
originating receipt/transload |
LOT_STATUS |
current lot lifecycle label; accepted eligibility criteria remain policy-owned |
INBOUND_QUANTITY |
source received quantity snapshot |
INBOUND_NET_WEIGHT |
source received net-weight snapshot |
REMAIN_QUANTITY |
remaining quantity projection/persisted value; current Apply does not immediately decrement it |
REMAIN_NET_WEIGHT |
remaining net-weight value; current Apply conditionally decrements it |
UOM |
lot UOM; target must validate compatibility/conversion explicitly |
COMMODITY_ID/NAME |
lot commodity evidence |
UNIT_RATE |
current source rate snapshot/proposal for target line |
OWNER_COMPANY_ID |
inventory owner/counterparty context |
WAREHOUSE_LOCATION |
physical-location projection; does not itself prove allocation eligibility |
DELETED_AT |
soft-delete boundary |
7.4 Target T_LOAD / T_LOAD_ITEM¶
| Field group | Meaning |
|---|---|
target T_LOAD.ID/UUID |
existing Outbound Sales order |
| order direction/class | must remain active Sales/Outbound |
| Booking/container/equipment references | target operational bridge; separate owner |
target T_LOAD_ITEM.ID |
current Apply-created line for one source lot |
QUANTITY |
allocated/requested quantity snapshot; current helper inserts integer-normalized quantity |
NET_WEIGHT or equivalent |
target allocated weight snapshot |
UOM |
target line UOM |
| commodity/rate/remark | source snapshot or operator-approved values |
7.5 T_LOAD_ALLOCATION¶
| Field | Target semantic meaning |
|---|---|
ID |
stable allocation relation identity |
CLIENT_ID |
tenant scope |
OUTBOUND_ORDER_ID |
target shipment |
OUTBOUND_ORDER_ITEM_ID |
exact target line |
INVENTORY_LOT_ID |
exact source lot |
ALLOCATED_QUANTITY |
accepted allocated quantity |
ALLOCATED_NET_WEIGHT |
accepted allocated net weight |
ALLOCATED_RATE |
rate snapshot when applicable |
REMARK |
bounded operator/business note, not hidden state |
DELETED_AT |
current soft-delete compatibility; target reversal should retain reason/history |
7.6 Target request identity¶
The target Apply command requires a stable request identity, for example:
allocationRequestToken
+ tenant
+ targetOrderId
+ normalized ordered source rows
+ preview/freshness fingerprint
The final storage location is not selected here. The identity must allow exact duplicate and timeout reconciliation without reapplying lot consumption.
8. Current Quantity, Weight And UOM Asymmetry¶
8.1 Current immediate write¶
For each basket row the current helper:
- creates a target Outbound item;
- creates a
T_LOAD_ALLOCATIONrow with quantity and weight; - conditionally decrements only
T_INVENTORY_LOT.REMAIN_NET_WEIGHT; - leaves
REMAIN_QUANTITYunchanged in that immediate command.
8.2 Why this matters¶
The system can show:
allocated quantity recorded
+ allocated weight recorded
+ remaining weight reduced
+ remaining quantity unchanged until another reconciliation path
This is not automatically wrong if quantity is informational for certain UOMs, but no universal approved policy was found. A migration must not silently copy the asymmetry without documenting the rule.
8.3 Target decision required¶
For every supported UOM define:
- authoritative consumption dimension: quantity, weight or both;
- allowed precision and rounding;
- conversion source and version;
- zero handling;
- lower-bound check;
- remaining-value update;
- conflict/reconciliation behavior.
No implicit conversion is allowed.
9. Semantic Query Contracts¶
9.1 GetEligibleInventoryLots¶
Input:
tenant context
source mode
optional inbound order
search text
page/limit
Returns:
- lot and exact source identities;
- commodity, UOM, inbound and remaining quantity/weight;
- lot/source/receipt state;
- warehouse/source-mode projection;
- allocation summary;
- eligibility result and blocking reasons;
- freshness/version marker.
No mutation.
9.2 GetAllocationTargets¶
Returns existing eligible Outbound Sales shipments with:
- order/Booking/reference;
- container/equipment/size;
- active bridge state;
- current allocated quantity/weight summary;
- target freshness marker;
- blocking reason.
9.3 GetAllocationPreview¶
Input:
target order identity
ordered source lot rows
requested quantity/weight/UOM per source
Returns:
- exact normalized rows;
- source and target freshness;
- projected target lines;
- projected source balances;
- UOM/precision warnings;
- duplicate/conflict detection;
- basket atomicity statement;
- request fingerprint.
No mutation.
9.4 GetOutboundAllocationState¶
Returns target order, target items, active allocations, source lots and independently owned downstream blockers.
9.5 GetInventoryLotBalanceAndAllocationHistory¶
Returns source receipt, original values, active allocations, corrections/reversals, current remaining values and any conflict.
9.6 GetAllocationResultByRequestToken¶
Returns:
NOT_FOUND
COMMITTED
CONFLICT
UNKNOWN_NEEDS_RECONCILIATION
with exact target item/allocation IDs and source before/after values.
10. Semantic Command Contracts¶
10.1 AllocateInventoryBasket¶
Purpose: parity command for the current all-or-nothing basket.
Input:
{
"requestToken": "uuid",
"targetOrderId": 123,
"targetVersion": "...",
"rows": [
{
"inventoryLotId": 45,
"sourceOrderId": 10,
"sourceOrderItemId": 11,
"sourceTransloadId": 12,
"quantity": "10.000",
"netWeight": "20000.000",
"uom": "LB",
"rate": "0.1200",
"remark": ""
}
]
}
Required server behavior:
- authenticate tenant/actor/capability;
- normalize and validate unique ordered rows;
- check request-token duplicate;
- reread target order/equipment bridge;
- reread every source lot and exact source relation;
- validate status, balance, commodity, UOM and freshness;
- begin one local transaction;
- conditionally consume accepted source balances;
- create target item and allocation relation per row under the accepted parity model;
- write audit/correction metadata;
- commit all rows or none;
- reread target items, allocations and source balances;
- return exact IDs and before/after values.
No provider call and no worker are required.
10.2 AllocateInventoryToOutbound¶
Single-row semantic variant. It may share the same application command internally but must preserve the same idempotency and readback contract.
10.3 CorrectAllocation¶
Allowed only after accepted policy defines:
- editable fields;
- source balance correction;
- target item correction;
- downstream locks;
- reason/audit;
- whether correction creates a new immutable adjustment relation.
10.4 ReverseAllocation¶
Target recommendation:
original allocation remains
+ reversal record/reason/actor/time
+ source balance restored conditionally
+ target item disposition explicit
+ downstream blockers reread
Do not hard-delete evidence as the primary target model.
10.5 ReconcileAllocationUnknownResult¶
Input: request token and strongest source/target identities.
Result:
FOUND_AND_READ_BACK
CONFIRMED_ABSENT_RETRY_ALLOWED
PARTIAL_OR_CONFLICT_MANUAL_REVIEW
UNKNOWN_MANUAL_REVIEW
10.6 No generic mutation command¶
The target must not expose:
POST table=T_LOAD_ALLOCATION
PATCH T_INVENTORY_LOT.REMAIN_NET_WEIGHT
as the business contract.
11. Stable Error Catalog¶
| Code | Meaning / operator action |
|---|---|
ALLOCATION_UNAUTHENTICATED |
sign in through assigned account |
ALLOCATION_FORBIDDEN |
actor lacks capability or record scope |
ALLOCATION_PROFILE_NOT_APPLICABLE |
tenant/profile does not support this flow |
ALLOCATION_SOURCE_NOT_FOUND |
reread source lot/filter |
ALLOCATION_SOURCE_NOT_ELIGIBLE |
source state/hold/close blocks allocation |
ALLOCATION_TARGET_NOT_FOUND |
target shipment absent/foreign/deleted |
ALLOCATION_TARGET_NOT_READY |
target lacks accepted container/size/bridge state |
ALLOCATION_UOM_MISMATCH |
stop; use approved conversion/correction policy |
ALLOCATION_QUANTITY_INVALID |
quantity zero/negative/precision invalid |
ALLOCATION_WEIGHT_INVALID |
weight zero/negative/precision invalid |
ALLOCATION_INSUFFICIENT_QUANTITY |
requested quantity exceeds accepted balance |
ALLOCATION_INSUFFICIENT_WEIGHT |
requested weight exceeds accepted balance |
ALLOCATION_STALE_BALANCE |
source changed after preview; refresh |
ALLOCATION_STALE_TARGET |
target changed after preview; refresh |
ALLOCATION_DUPLICATE_REQUEST |
return prior committed result; do not reapply |
ALLOCATION_DUPLICATE_RELATION |
equivalent active source-target allocation exists |
ALLOCATION_BASKET_CONFLICT |
one or more rows fail; no commit under all-or-nothing policy |
ALLOCATION_DOWNSTREAM_LOCKED |
Scale/Packing/Delivery/other accepted child blocks correction/reversal |
ALLOCATION_REVERSE_CONFLICT |
reversal cannot restore safely |
ALLOCATION_RESULT_UNKNOWN |
reread by request/source/target before retry |
ALLOCATION_DATA_CONFLICT |
persisted rows/balances disagree; manual review |
ALLOCATION_SCHEMA_NOT_READY |
required schema/index/precision unavailable |
UNEXPECTED_ERROR |
safe generic message plus correlation ID |
Internal SQL and raw data/provider details are logged safely and not exposed as validation text.
12. Transaction, Concurrency And Idempotency¶
12.1 Current transaction¶
Current Apply executes one request-level local DB transaction. A later basket-row error rolls back earlier row inserts and balance updates.
12.2 Required target serialization¶
The target must serialize competing consumption of the same source lot without relying on application memory.
Acceptable mechanisms may include:
- conditional atomic balance update with affected-row verification;
- repository-level optimistic version/fingerprint;
- a bounded database lock strategy approved for the target DB/runtime.
The exact mechanism is selected by P5/P11/P12. The invariant is:
one accepted source balance
cannot be consumed twice
12.3 Idempotency¶
The same request token and normalized payload:
- returns the original committed result;
- does not create another target item;
- does not insert another allocation;
- does not decrement the lot again.
A reused token with a different payload returns a conflict.
12.4 Basket atomicity¶
Recommended initial migration parity:
all rows committed
or
no row committed
If Product later wants partial basket success, it requires an explicit policy, per-row request identity, UI and recovery redesign. It must not emerge accidentally from implementation.
13. Exception And Recovery Matrix¶
| ID | Detection | Required reread | Safe recovery | Must not repeat blindly |
|---|---|---|---|---|
ALLOC-EXC-010 |
source disappeared from list | lot + source item/transload | select another eligible source or escalate | stale basket Apply |
ALLOC-EXC-020 |
target no longer eligible | target order/equipment bridge | choose corrected target after owner review | same Apply |
ALLOC-EXC-030 |
stale/insufficient balance | lot + active allocations | refresh preview; submit adjusted request once | old quantity/weight |
ALLOC-EXC-040 |
two operators apply same lot | request result + lot/allocation history | accept winning commit; loser refreshes | second full basket |
ALLOC-EXC-050 |
Apply response missing | request token, target items, allocation rows, lot balances | use committed result or retry only when absence confirmed | full Apply button |
ALLOC-EXC-060 |
later basket row fails | transaction/result + all source/target rows | under current parity expect no rows; reconcile if evidence disagrees | individual assumptions |
ALLOC-EXC-070 |
quantity/weight remaining disagree | lot original values + active allocations | stop and reconcile through Allocation/Inventory owner | manual field overwrite |
ALLOC-EXC-080 |
outbound item edited after allocation | item + allocation + lot | use approved correction/reversal | ordinary Outbound Save |
ALLOC-EXC-090 |
inbound lot/source edited after allocation | source item/transload/lot/allocation/ledger | use approved Inventory/Allocation correction | source-row overwrite |
ALLOC-EXC-100 |
Booking compatibility changed/deleted allocation | Booking, order/item, lot, allocation and logs | stop dependent work; reconcile exact children | another Booking Save |
ALLOC-EXC-110 |
unallocate requested | allocation + all downstream children | follow approved reversal policy or escalate | delete row/manual balance add |
ALLOC-EXC-120 |
foreign/denied direct ID | tenant/actor/record scope | return through assigned menu/account | alternate direct route |
Universal rule:
Do not repeat Apply, source correction, target edit or Booking Save
until lot + target item + allocation + request identity are reread.
14. Current Caller And Consumer Map¶
Current writers¶
- Allocation Workbench Apply route;
oms.allocation/post_handler.php;mk_sales_order_post_handle(... APPLY_WORKBENCH ...);mk_sales_order_insert_allocated_item();- current Booking compatibility behavior can separately update/delete allocation-related rows;
- current Inbound lot reconciliation recalculates remaining balances from active allocations.
Current readers/consumers¶
- Allocation Workbench source and target queries;
- Outbound order detail/readiness;
- Inbound/lot detail and inventory reports;
- Scale, Packing, Export Brokerage and Trade/Cost projections where they consume target/source rows;
- Wiki/operator procedures and support investigation.
Current compatibility risks¶
- source query eligibility is stronger than parts of the write revalidation;
- role/tenant context is legacy on current routes;
- outbound item updates can diverge from allocation balances;
- no general reversal owner is source-confirmed;
- Booking compatibility can mutate the same records;
- no durable request token prevents replay after response loss.
15. Target Component Map¶
flowchart TB
React[React Allocation Workspace]
Next[Next.js Server Components / Route Handlers]
App[TypeScript Allocation Application]
Policy[Allocation Policy / UOM / Eligibility]
Repo[Allocation + Lot + Outbound Repository]
DB[(MySQL)]
Audit[Audit / Reconciliation Read Model]
React --> Next
Next --> App
App --> Policy
App --> Repo
Repo --> DB
App --> Audit
React owns¶
- source/target search and selection;
- basket/preview presentation;
- loading, empty, denied, stale, conflict, unknown and success states;
- exact result IDs and balance changes;
- accessible/mobile interaction;
- no-blind-retry guidance.
React does not own eligibility, balance arithmetic, transaction or reversal policy.
Next.js owns¶
- session/tenant/actor adapter;
- server read composition;
- Route Handler transport;
- runtime payload validation;
- safe error mapping and correlation ID;
- no business SQL or hidden allocation mutation.
TypeScript application/domain owns¶
- source and target eligibility;
- quantity/weight/UOM policy;
- request idempotency;
- basket atomicity;
- transaction orchestration;
- correction/reversal;
- exact readback and reconciliation.
Repository owns¶
- tenant-scoped reads;
- conditional balance write;
- target item/allocation persistence;
- immutable correction/reversal evidence;
- MySQL and later PostgreSQL implementation.
Worker¶
Not required for the core local allocation. Introduce a worker only for separately approved asynchronous child effects; it must not delay or own the local allocation commit.
16. UI State Contract¶
The target workspace must implement:
Loading sources
No eligible sources
Loading targets
No eligible targets
Denied
Validation error
Stale source
Stale target
UOM conflict
Basket preview
Submitting
Committed with exact rows
Unknown result — reread in progress
Data conflict — stop and escalate
Correction/reversal blocked
Success presentation includes:
- target order identity;
- created target item IDs;
- allocation IDs;
- each source lot before/after quantity and weight;
- UOM/rate snapshot;
- next owner/action;
- statement that Scale/Packing/Delivery are not complete.
The UI must not clear the basket and show success unless authoritative readback is available. If the response is lost, it must switch to reconciliation rather than invite another Apply.
17. Policy Decision Summary¶
Open decisions are owned in MK_INVENTORY_ALLOCATION_POLICY_DECISION_MATRIX.md.
Critical decisions before write migration:
- full-lot-only versus partial allocation;
- quantity, weight or dual consumption authority by UOM;
- UOM conversion and rounding;
- target line per source lot versus allocation to an existing demand line;
- all-or-nothing basket versus explicit partial batch;
- request idempotency storage;
- source eligibility revalidation;
- duplicate relation uniqueness;
- correction/unallocate/reversal model;
- downstream locks;
- role/capability mapping;
- Booking compatibility retirement;
- optimistic concurrency/versioning;
- PostgreSQL precision, constraints and index design.
18. Migration Plan¶
ALLOC-W0 Characterization¶
- exact branch/schema/index/precision;
- active callers/readers;
- target-role page/API/record matrix;
- current basket transaction and failure behavior;
- response-loss/duplicate behavior;
- quantity/weight drift fixtures;
- Booking compatibility impact;
- current Wiki content.
ALLOC-W1 Typed read model¶
Build TypeScript repositories and queries against MySQL; compare source/target/balance results with current PHP.
ALLOC-W2 React + Next.js read-only workspace¶
Use current PHP as writer. Validate target-role source/target/preview presentation.
ALLOC-W3 Shadow preview and reconciliation¶
Compute target eligibility, normalization and projected balances without writing. Compare with current Apply inputs/results.
ALLOC-W4 One-writer parity Apply¶
Activate AllocateInventoryBasket for a bounded cohort. Preserve current full-lot, one-target, one-line-per-source and all-or-nothing behavior initially unless policies are changed explicitly.
ALLOC-W5 Idempotency and unknown-result recovery¶
Require request token, exact duplicate result and support reconciliation.
ALLOC-W6 Correction and reversal¶
Activate only after policy, downstream locks, audit and source-balance restoration are accepted.
ALLOC-W7 Target-role stabilization¶
Normal, denied, stale, concurrent, duplicate, unknown and recovery evidence plus field observation.
ALLOC-W8 PHP caller-zero¶
Prove old Apply and internal helper callers are zero before removal. Remove compatibility only after user acceptance.
ALLOC-W9 PostgreSQL later¶
Preserve decimal precision, conditional lower-bound constraints, relation identity, idempotency and reversal history after React + Next.js + MySQL stabilization.
19. Rollback¶
Rollback from the new writer means:
- stop routing new Apply commands to TypeScript;
- preserve every committed allocation, target item and lot balance;
- reconcile in-flight/unknown request tokens;
- restore PHP writer for new requests only;
- keep new read/audit evidence available;
- do not replay baskets;
- do not delete/recreate allocation history;
- verify source/target balance parity before resuming.
Rollback does not mean:
hard-delete target items
hard-delete allocation rows
manually add lot weight
run both writers
replay unknown requests
20. PostgreSQL Preservation¶
The later repository must preserve:
- exact decimal precision for quantity, weight and rate;
- explicit UOM values and conversion version when used;
- conditional nonnegative balance enforcement;
- tenant-scoped foreign keys/indexes;
- stable allocation/request/reversal identity;
- uniqueness/idempotency rules;
- immutable audit/reversal chain;
- current soft-delete semantics until an approved replacement exists;
- transaction isolation/concurrency behavior proven by scenarios.
Do not rely on MySQL implicit casts, integer truncation or case-insensitive comparison without an explicit compatibility decision.
21. Stable Verification Scenarios¶
Current capability¶
ALLOC-SCN-010 Single eligible lot -> existing target
ALLOC-SCN-020 Multiple lots -> same target, all rows commit
ALLOC-SCN-030 Later basket row fails -> complete rollback
ALLOC-SCN-040 Same lot concurrently submitted by two operators
ALLOC-SCN-050 Apply response lost after commit
ALLOC-SCN-060 Same request token replay
ALLOC-SCN-070 Source lot closed/deleted/empty after preview
ALLOC-SCN-080 Target missing container/size or invalid bridge state
ALLOC-SCN-090 UOM mismatch or unsupported conversion
ALLOC-SCN-100 Quantity/weight remaining-value divergence
ALLOC-SCN-110 Outbound item edited after allocation
ALLOC-SCN-120 Inbound source/lot edited after allocation
ALLOC-SCN-130 Correction/unallocate/reversal allowed or blocked
ALLOC-SCN-140 Foreign tenant, denied role and direct-ID access
ALLOC-SCN-150 Booking compatibility modifies allocation/lot
ALLOC-SCN-160 Source list eligibility differs from write eligibility
Migration¶
ALLOC-MIG-SCN-010 PHP/TypeScript source-list parity
ALLOC-MIG-SCN-020 Target-list and preview parity
ALLOC-MIG-SCN-030 One-writer parity Apply
ALLOC-MIG-SCN-040 Request-token duplicate and timeout reconciliation
ALLOC-MIG-SCN-050 Concurrent lower-bound protection
ALLOC-MIG-SCN-060 Rollback to PHP without replay
ALLOC-MIG-SCN-070 PHP caller-zero
ALLOC-MIG-SCN-080 PostgreSQL balance/idempotency parity
Evidence records:
- exact revision/environment/schema;
- actor/tenant/profile;
- before/after rows and IDs;
- request token;
- transaction/result;
- cleanup or retained conflict fixture;
- screenshots/API/DB evidence where authorized;
- limitations and next owner.
22. Definition Of Ready For Implementation¶
- [ ] Product accepts full/partial lot behavior.
- [ ] Quantity/weight/UOM authority is accepted.
- [ ] Basket atomicity is accepted.
- [ ] Target-line model is accepted.
- [ ] Request idempotency/version strategy is accepted.
- [ ] Correction/reversal/downstream-lock policy is accepted or explicitly out of first wave.
- [ ] Role/page/API/record matrix is available.
- [ ] Current schema/index/caller inventory is pinned.
- [ ] Booking compatibility interaction is characterized.
- [ ] Runbook and current Wiki content are reviewed.
- [ ] One-writer selector and rollback are approved.
- [ ] Stable scenarios and fixtures are ready.
23. Definition Of Complete¶
A migration wave is complete only when:
- intended role enters the normal React workspace;
- source/target/preview parity is accepted;
- exactly one writer owns Apply;
- duplicate/timeout cannot consume twice;
- quantity/weight/UOM and source balances remain correct;
- correction/reversal behavior is explicit;
- operator can recover without blind replay;
- old PHP callers are zero before removal;
- Wiki/current route/runbook are aligned;
- rollback is rehearsed;
- user accepts the visible result;
- stabilization observation is complete.
Documentation alone does not establish completion.
---¶
Source:
docs/reconstruction/MK_INVENTORY_ALLOCATION_CAPABILITY_REBUILD_PACKET.md— ctc repository · This page is an English translation of the source document. Identifiers, file paths and code symbols are unchanged.