This is an internal working record, not an everyday instruction. It was written while the system was being rebuilt, for whoever maintains it. If you are here to do today's work, use the everyday documents instead: Procedures · Processes · Runbooks · The working day, step by step
Final Loading Review Policy Decision Matrix¶
- Status:
P6-007 DECISION INPUT / RECOMMENDATIONS NOT YET USER-APPROVED - Process:
PROC-WMS-FINAL-LOADING-REVIEW-CTC - Migration packet:
FINAL_LOADING_REVIEW_MIGRATION_PACKET.md - Source baseline:
4fc2f5a893765fbb95e0a2bdcb971322b0ec9fc0 - Owners: Product/Operations decide business policy; P2 validates access; P5/P12 implement accepted application/runtime contract
- Effect boundary: documentation only; no Runtime, DB, role/config, Wiki or deployment change
1. Purpose¶
Source reconciliation identified several behaviors that cannot be copied into React/Next.js/TypeScript without an explicit decision.
This matrix separates:
current source fact
-> business question
-> available choices
-> recommended target
-> compatibility and migration impact
A recommendation is not an approved business rule. Unknowns remain blockers for M4, not reasons to invent defaults in code.
2. Decision Summary¶
| ID | Topic | Current source fact | Recommended target | Required decision owner | M4 impact |
|---|---|---|---|---|---|
| FLR-POL-001 | Process owner | review and adjustment share one page but have different state/commands | separate Final Review and Bale Adjustment authorities | Product/Operations | blocking if merged again |
| FLR-POL-002 | Roles/capabilities | menu roles 1,2; write helper roles 1,2,3 only for Client 1 |
semantic capabilities, page/API parity, no role IDs in domain policy | P2/Product | blocking |
| FLR-POL-003 | Tenant/profile applicability | tenant-scoped source plus Client-ID-specific behavior | ctc-execution process policy selected through profile/capability |
Product/P4/P2 | blocking |
| FLR-POL-004 | Weight required | customer display name TGI makes weight optional |
explicit customer/profile review policy, never display-name branch | Product/Operations | blocking |
| FLR-POL-005 | Weight tolerance | config exists but current derived state appears to require review for any non-zero difference | explicit tolerance + UOM + rounding; reason required only outside tolerance | Product/Operations | blocking |
| FLR-POL-006 | Weight reason | Confirm may persist reason before final Confirm succeeds | persist reason only as part of successful Confirm, unless a separate draft contract is approved | Product/P5 | blocking |
| FLR-POL-007 | Reopen metadata | Reopen sets Pending but retains actor/time/reason | preserve immutable history separately; Pending projection must not present old metadata as current confirmation | Product/P6/P5 | blocking |
| FLR-POL-008 | Review intent | schema default makes eligible rows Pending; no explicit create command | keep eligibility-derived Pending during MySQL coexistence; do not add a speculative review table | Product/P5 | non-blocking if documented |
| FLR-POL-009 | Confirm concurrency | conditional Pending update; stale conflict; no row lock | conditional compare/update + exact reread; no Runtime FOR UPDATE |
P5/DB | blocking for implementation |
| FLR-POL-010 | Bulk semantics | mixed confirmed IDs/exclusions; one outer transaction; excluded row may retain prior reason write | explicit partial-success batch of independent row commands; no state change on excluded row | Product/P5 | blocking |
| FLR-POL-011 | Adjustment relationship | Source/Leftover/void are separate commands | Reopen before confirmed correction; adjustment never auto-confirms | Product/P6 | blocking |
| FLR-POL-012 | Menu/URL | route/menu says Inventory Adjustment; page says Final Loading Review | preserve legacy URL as alias; user-facing label reflects Final Loading Review; Bale Inventory remains related procedure | Product/P7/P8 | not blocking for source parity |
| FLR-POL-013 | Cadence/SLA | date-based queue; no approved review SLA | define same-shift/day or next-business-day expectation and escalation | Operations | required before value/KPI |
| FLR-POL-014 | Wiki structure | likely ctc-labels-reports; content not read |
dedicated page when role/recovery volume warrants it, otherwise clearly separated section | P8/Product | required before M3/field acceptance |
| FLR-POL-015 | Migration order | page mixes review and adjustment | read-only review -> individual Confirm -> Reopen/weight -> Bulk -> compatibility guard; adjustment migrates separately | P12/P5/P7 | blocking for wave plan |
3. Process And Command Authority¶
Current conflict¶
One PHP page currently presents:
- Final Loading Review state and commands;
- Source and Leftover adjustment actions;
- BAL TRK/lot evidence.
The current UI boundary is not the business authority boundary.
Recommended authority model¶
FinalLoadingReview
├─ List / Get / Evaluate
├─ Confirm
├─ Reopen
├─ UseInboundWeight
├─ BulkConfirm
└─ AssertReviewMutable
BaleInventoryAdjustment
├─ SearchEligibleSource
├─ ApplySource
├─ CreateLeftover
├─ CountCheck
└─ VoidOrReverse
Decision¶
Accept separate process authorities. A future React page may compose both, but application commands and audit remain distinct.
4. Roles And Capabilities¶
Current facts¶
Client-1 menu migration: role IDs 1,2
review write helper: role IDs 1,2,3 only when Client ID == 1
non-Client-1 helper path: no equivalent role list in this function
module gate: wms.inventory
Problem¶
- menu visibility and command authority disagree;
- role IDs are deployment data, not stable Product semantics;
- Client ID selects policy;
- page visibility can be mistaken for API permission.
Recommended capability set¶
wms.final-loading-review.view
wms.final-loading-review.confirm
wms.final-loading-review.reopen
wms.final-loading-review.resolve-weight
wms.final-loading-review.bulk-confirm
wms.bale-inventory.view
wms.bale-inventory.apply-source
wms.bale-inventory.create-leftover
wms.bale-inventory.count-check
wms.bale-inventory.void-reversal
A role/profile maps to capabilities. Domain/application code consumes capability decisions and never checks numeric role IDs.
Required acceptance¶
For every affected role/profile:
- menu expected visible/hidden;
- page expected allowed/denied;
- each API action expected allowed/denied;
- direct API negative;
- same-tenant/foreign-tenant negative;
- exact no-mutation evidence on denial.
P2-007 owns this matrix.
5. Weight Requirement Policy¶
Current fact¶
Weight is treated as optional when uppercased BILLING_COMPANY_NAME equals TGI.
Problems¶
- customer display text selects a core invariant;
- rename or data variation changes process behavior;
- the browser/API contract does not expose why weight is optional;
- future tenant/customer onboarding encourages more name branches.
Options¶
A. Tenant/profile-wide policy¶
finalLoadingReview.weightRequired = true/false
Suitable when every customer under one profile follows the same rule.
B. Customer/account policy¶
customerPolicy.finalLoadingReview.weightRequired
Suitable when contractual operation differs by customer. Must use stable customer identity/config, not name.
C. Work-type policy¶
loadingTypePolicy[RELOAD|TRANSLOAD].weightRequired
Suitable when physical workflow, not customer, determines requirement.
Recommendation¶
Use an explicit resolved FinalLoadingReviewPolicy capable of composing stable profile, customer and work-type inputs. Start with the smallest proven dimension; do not build speculative rule engines.
policy.weightRequired
policy.weightTolerance
policy.weightUnit
policy.reasonRequiredOutsideTolerance
The resolved policy is returned in the page/API field contract so the operator can understand the rule.
6. Weight Difference, Tolerance And Rounding¶
Current facts¶
- inbound/initial weight supplies expected baseline;
- final weight supplies outbound result;
- tenant config
BALE_REVIEW_WEIGHT_VARIANCE_LBis read; - current derived state observed in source compares non-zero difference for Weight Review;
- source/leftover ledger weight matching uses a
1.0lb comparison tolerance; - weight optional may zero both expected and final values.
Required policy fields¶
canonicalUnit
inputUnit
comparisonUnit
precision
roundingMode
absoluteTolerance
relativeTolerance if needed
reasonRequiredThreshold
zero/missing distinction
Recommendation¶
For the current CTC process, use one explicit absolute tolerance in lb unless Operations proves another requirement.
abs(finalWeight - expectedWeight) <= tolerance
-> no weight exception
abs(diff) > tolerance
-> reason or correction required
Do not treat missing weight as zero. Do not silently convert units without provenance.
Required Product decision¶
- exact tolerance;
- whether tolerance differs by work/customer;
- rounding before or after comparison;
- whether equal quantity plus weight difference may be confirmed with reason;
- whether extreme variance requires a hard block/escalation rather than reason.
7. Weight Reason Semantics¶
Current behavior¶
Confirm can write BALE_REVIEW_WEIGHT_REASON before final readiness/conditional Confirm. If later validation fails and the exception is handled inside Bulk, the reason may remain on a Pending/excluded row when the surrounding transaction commits successful rows.
Options¶
A. Successful-confirm evidence only¶
- reason is input to Confirm;
- validation occurs first;
- reason and Confirmed transition commit together;
- failed/excluded row has no new persisted reason.
B. Pending draft reason¶
- separate draft command and explicit pending-draft field/version;
- user can save before Confirm;
- UI distinguishes draft from confirmed evidence.
C. Last-entered mutable note¶
- reason may persist independently of Confirm;
- weakest audit semantics and easiest to misunderstand.
Recommendation¶
Use A unless operators explicitly require saved drafts. Do not preserve current partial-write behavior as an accidental contract.
If draft support is approved later, implement B as a separate use case rather than ordering writes inside Confirm.
8. Confirm And Concurrency¶
Current useful behavior¶
- named identity is tenant + transload;
- Confirm requires Pending and Ready;
- final update is conditional on Pending;
- stale/duplicate Confirm becomes conflict;
- exact reread proves completion.
Target command¶
ConfirmFinalLoadingReview(
reviewIdentity,
expectedReviewVersionOrState,
optionalAcceptedWeightReason,
actorContext
)
Recommendation¶
- retain conditional update/compare semantics;
- use application transaction and exact readback;
- no
FOR UPDATE; - optionally add a revision/version only if it solves a proven concurrent-edit problem;
- idempotent duplicate should return existing Confirmed state only when the command identity and accepted semantics permit it; otherwise return conflict.
Unknown-result recovery¶
request timeout / response loss
-> GetFinalLoadingReview by stable ID
-> if Confirmed, do not retry
-> if Pending and unchanged, retry with explicit user action
-> if changed, show refreshed blocker
9. Reopen And Audit Metadata¶
Current behavior¶
Reopen changes BALE_REVIEW_STATUS to Pending and retains prior confirmation actor/time/reason fields.
Interpretations¶
A. Current-confirmation metadata¶
If fields mean the current Confirmed state, they should be cleared on Reopen.
B. Last-confirmed metadata¶
If fields mean historical last confirmation, names and UI must say LAST_CONFIRMED_*; Pending must not display them as current confirmation.
C. Immutable transition audit¶
Store Confirm/Reopen events with actor/time/reason/correlation while current row stores only current state/projection.
Recommendation¶
Target C, with current MySQL coexistence using a minimally disruptive interpretation:
- treat existing actor/time as last-confirmed metadata;
- do not use them to determine current state;
- show current state from
BALE_REVIEW_STATUSonly; - add immutable transition audit when P5/P6/P12 selects the approved audit owner;
- do not add a new review table merely to make the model look cleaner.
Before M4, Product must explicitly approve whether existing fields are retained/renamed/cleared during migration.
10. Review Intent And Historical Rows¶
Current fact¶
Adding the review columns with default Pending makes existing eligible rows appear Pending based on current query criteria. There is no explicit review-create event.
Options¶
A. Eligibility-derived review¶
Every eligible current row is a Pending review until confirmed.
B. Explicit review intent¶
Operational completion creates a review instance/event.
C. Hybrid¶
Historical/current compatibility is derived; new target writes explicit intent/audit.
Recommendation¶
Use A during PHP/MySQL and first React/Next.js migration to avoid unnecessary schema expansion. Consider C only if an explicit review audit or SLA requires a durable start event.
Historical migration must define date/status scope so old completed work does not unexpectedly flood current queues.
11. Bulk Confirm Semantics¶
Current behavior¶
- one API request starts an outer transaction;
- each row calls individual Confirm;
- exceptions are caught per row and returned as exclusions;
- successful row writes commit together when the outer transaction commits;
- excluded rows can still retain a prior reason write made before their failure.
Options¶
A. All-or-nothing batch¶
One blocked row rejects all rows.
B. Explicit partial-success batch¶
Each row is an independent conditional command. Response returns durable success/conflict/error for every row.
C. Best-effort without exact per-row readback¶
Not acceptable.
Recommendation¶
Use B because the current UI/business concept already exposes exclusions and Office review rows are independent.
Target requirements:
- independent row transaction or equivalent durable per-row command result;
- no state/reason mutation for excluded row;
- stable input ID order and result for every requested ID;
- exact reread of all success and conflict rows;
- successful row is not repeated after response loss;
- request-level failure distinguishes “no row attempted” from “some rows may have committed.”
Bulk is an orchestrator, not a new business state.
12. Source/Leftover And Reopen Relationship¶
Required rule¶
Pending review
-> adjustment may change Source/Leftover evidence
-> review recalculates readiness
Confirmed review
-> adjustment is blocked
-> Reopen required
-> adjustment through owning command
-> review exact reread
-> reconfirm
Recommendation¶
Keep separate commands and audits. Never make Source/Leftover apply automatically Confirm the review, and never make Reopen automatically reverse inventory.
13. Menu, Page And URL¶
Current mismatch¶
- route/menu identity:
inventory-adjustment/ Inventory Adjustment; - page heading and dominant workflow: Final Loading Review;
- related actions include Bale Inventory Adjustment.
Options¶
A. Keep current menu label¶
Lowest rollout risk but hides primary workflow.
B. Rename menu to Final Loading Review, preserve URL¶
Clear operator purpose; lowest technical migration risk.
C. New page/URL immediately¶
Potentially cleaner but creates unnecessary compatibility and menu churn during current PHP operation.
Recommendation¶
Use B after role/menu and Wiki review:
menu label: Final Loading Review
legacy route: inventory-adjustment preserved
related link: Bale Inventory / Adjustment
future React route: descriptive path with legacy alias
Do not split the current Runtime page solely for documentation cleanliness before P7/P12.
14. Cadence, SLA And Escalation¶
Current fact¶
The queue is filtered by LA business date. No accepted SLA or escalation timer is documented.
Decisions required¶
- review by end of same shift, same business day or next business day;
- who owns Pending rows after Loader completion;
- backup owner;
- what state requires immediate stop/escalation;
- handling of late corrections and reopened historical reviews;
- overdue indicator and metric definition;
- whether unresolved review blocks billing, shipment or daily close.
Recommendation¶
Do not hard-block unrelated daily operation solely because a review is Pending unless a named downstream integrity rule requires it.
Initial operating policy should expose:
current pending count
age since eligible completion
blocking reason
current owner
next action
P6-003 can measure cycle time only after these boundaries are approved.
15. Wiki Information Architecture¶
Current likely owner¶
ctc-labels-reports, but actual content is not read.
Options¶
A. Shared page with separated sections¶
Use when one role commonly performs labels, reports, Final Review and Bale adjustment.
B. Dedicated Final Loading Review page¶
Use when the workflow has distinct role, frequency, status/recovery complexity or onboarding need.
Recommendation¶
Prefer B for long-term clarity because Final Review has:
- independent state and commands;
- detailed exception/recovery;
- separate adjustment handoff;
- future migration packet.
Before creating a slug, P8 must read current content and confirm menu/findability. Until then, keep ctc-labels-reports as the mapped current owner and prepare a dedicated-page proposal only.
16. Migration Wave Decision¶
Recommended order:
Wave 0: policy decisions + current role/source characterization
Wave 1: TypeScript read query shadow
Wave 2: React/Next.js read-only page
Wave 3: individual Confirm one-writer cutover
Wave 4: Reopen and Use Inbound Weight
Wave 5: Bulk Confirm
Wave 6: public mutable-policy adapter for TMS/BMS callers
Wave 7: PHP review caller-zero and retirement
Bale Inventory Adjustment migrates in its own packet. It may be composed into the same React page after both application contracts are stable.
17. Recommended Decision Package For User Review¶
The user/process owner should approve or revise:
- separate review versus adjustment authority;
- semantic capabilities and target roles;
- weight-required policy dimension;
- exact tolerance/UOM/rounding;
- reason stored only on successful Confirm;
- Reopen history/current metadata semantics;
- eligibility-derived Pending during MySQL coexistence;
- conditional update/no-
FOR UPDATEconcurrency; - partial-success Bulk with no mutation on excluded rows;
- Reopen before adjustment and no automatic Confirm;
- user-facing menu label and Wiki page structure;
- review cadence/SLA/escalation;
- migration wave order.
Until accepted, source behavior remains documented compatibility rather than target Product policy.
---¶
Source:
docs/processes/FINAL_LOADING_REVIEW_POLICY_DECISION_MATRIX.md— ctc repository · This page is an English translation of the source document. Identifiers, file paths and code symbols are unchanged.