Skip to content

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.

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.
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_LB is read;
  • current derived state observed in source compares non-zero difference for Weight Review;
  • source/leftover ledger weight matching uses a 1.0 lb 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_STATUS only;
  • 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.


The user/process owner should approve or revise:

  1. separate review versus adjustment authority;
  2. semantic capabilities and target roles;
  3. weight-required policy dimension;
  4. exact tolerance/UOM/rounding;
  5. reason stored only on successful Confirm;
  6. Reopen history/current metadata semantics;
  7. eligibility-derived Pending during MySQL coexistence;
  8. conditional update/no-FOR UPDATE concurrency;
  9. partial-success Bulk with no mutation on excluded rows;
  10. Reopen before adjustment and no automatic Confirm;
  11. user-facing menu label and Wiki page structure;
  12. review cadence/SLA/escalation;
  13. 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.