Skip to content

Booking Source Linkage — Source-Reconciled Current Contract

  • Process ID: process.fulfillment.booking-linkage
  • Status: SOURCE_RECONCILED CURRENT ADAPTER / TARGET OWNER OPEN
  • Task: NS0-003
  • Current-source revision: 98b3a59d76ce66c3e69788c93aac7e3e08e6edff
  • Profiles: mk-order; CTC PO/reference behavior mapped separately
  • Evidence level: repository source/schema/migration/test review
  • Live DB/browser/operator verification: NOT_RUN

1. Meaning

Current MK Booking linkage connects:

T_BOOKING
<-> one outbound SALES T_LOAD execution order

It does not connect Booking directly to T_COMMERCIAL_ORDER.

Current field names:

T_BOOKING.SALES_ORDER_ID
T_BOOKING.SALES_ORDER_UUID
T_LOAD.BOOKING_ID

The term Sales Order in this adapter means the current outbound execution order stored in T_LOAD.

2. Current Identity Resolution

A requested Sales execution can be resolved by:

T_LOAD.ID
T_LOAD.UUID
T_LOAD.ORDER_NUMBER

with these predicates:

same CLIENT_ID
active T_LOAD
ORDER_CLASS = SALES
ORDER_DIRECTION = OUTBOUND

Legacy PO-number input can be accepted as a compatibility order-number lookup during selected create paths.

3. Current Cardinality

3.1 Booking side

T_BOOKING stores one Sales execution pointer, so one active Booking can point to at most one current Sales execution through this column set.

3.2 Sales execution side

T_LOAD stores one BOOKING_ID.

Linking checks:

existing T_LOAD.BOOKING_ID > 0
and existing Booking differs
-> reject: Sales order already linked to another Booking

3.3 Database enforcement boundary

No evidence reviewed in this packet proves a unique index on T_BOOKING.SALES_ORDER_ID or SALES_ORDER_UUID.

Therefore current one-to-one behavior is application-enforced across selected writers, not proven as a complete database invariant.

4. Current Writer Paths

4.1 Booking writer

Booking create/update can:

write T_BOOKING fields
-> set/clear SALES_ORDER_ID and SALES_ORDER_UUID
-> set/clear T_LOAD.BOOKING_ID
-> optionally update T_LOAD.CONSIGNEE_COMPANY_ID

These changes occur inside the Booking API transaction.

4.2 Sales execution writer

Sales execution create/update can:

resolve Booking reference
-> write T_LOAD.BOOKING_ID
-> clear prior T_BOOKING pointers for that execution
-> set T_BOOKING.SALES_ORDER_ID / UUID on the selected Booking

4.3 Consequence

There are multiple current entry points that can synchronize the same relationship.

Booking save path
+ Sales execution save path
= compatibility multi-entry relationship writer

The characterized paths run inside their owning transactions and apply relation guards, but the target must select one semantic command owner.

Current Booking-side link flow:

lock active previous/new Sales execution rows
-> validate new execution exists
-> reject if it points to another Booking
-> clear old T_LOAD.BOOKING_ID when changed
-> set new T_LOAD.BOOKING_ID
-> persist Booking pointer

When explicit empty Sales-order input is provided, the update can clear the pointer and reverse link.

6. Hidden Consignee Effect

When the Booking payload contains CONSIGNEE_COMPANY_ID, the Booking save path can also update:

T_LOAD.CONSIGNEE_COMPANY_ID

for the linked Sales execution.

This is a separate Commercial/Fulfillment fact and must not remain an undocumented side effect in the target command.

Target options:

LinkBookingSource includes one explicit accepted source snapshot
or
UpdateSalesExecutionConsignee is a separate named command

The business owner must decide.

7. CTC Difference

Current CTC Booking commonly uses:

PO_NUMBER

as text/reference context. Current source does not prove it is a relational link to an active Commercial or Fulfillment aggregate.

Therefore:

CTC PO_NUMBER
!= MK T_LOAD Sales execution pointer

The target can present one common Source area while preserving different typed source references.

8. Fulfillment Boundary

Current T_LOAD combines order/execution facts and connects to equipment, scale, allocation and transload. The target should not rename the entire current row to Fulfillment without a field/state ownership map.

Candidate target boundary:

Commercial Agreement or Service Request
-> Fulfillment Request
-> optional Ocean Booking link
-> Shipment/Equipment/Operations

Current adapter migration may temporarily map a Fulfillment source reference to T_LOAD, but the target aggregate meaning must be approved independently.

9. Transaction And Recovery

Current Booking API:

begin transaction
-> write Booking
-> synchronize Sales execution pointer/consignee
-> save Out Refs when present
-> flush sync tasks
-> commit
-> return Booking ID

Current shared UI then rereads the exact Booking detail and verifies the ID.

Unknown response rule:

no server response
-> result UNKNOWN
-> search/reread by Booking identity
-> retry only if absent

This read-before-retry behavior should be preserved.

10. Concurrency

Current link helper locks the active previous and requested Sales execution rows before changing the relation. It also rejects a Sales execution already linked to another Booking.

Open concurrency questions:

  • whether every non-Booking writer uses the same lock helper;
  • whether stale Booking edit can overwrite a newer link;
  • whether missing database uniqueness allows an unlisted writer to create duplicate pointers;
  • exact behavior when one side is soft-deleted concurrently.

11. Target Command Candidates

LinkBookingSource
UnlinkBookingSource
CorrectBookingSourceLink
GetBookingSourceLink
ReconcileBookingSourceLink

Candidate command result:

Booking identity/revision
Source identity/type/revision
previous link
current link
transaction outcome
authoritative readback
correlation/audit evidence

No target command is approved by this document.

12. Target Owner Decision

Candidate owners:

Option Description Risk
Fulfillment Fulfillment owns source association and exposes it to Booking requires approved Fulfillment aggregate
Transportation/Booking Ocean Booking owns one typed source reference can overreach into commercial/execution authority
Dedicated bridge application bridge command coordinates repositories without owning either aggregate requires clear transaction and correction owner

Current recommendation for further decision:

dedicated application command
with Fulfillment as candidate semantic owner

This remains OPEN_DECISION.

13. Current Gaps

ID Gap Consequence
LINK-GAP-010 Sales Order name resolves to T_LOAD, not T_COMMERCIAL_ORDER terminology and API confusion
LINK-GAP-020 multiple entry paths synchronize the relation target one-writer owner is unresolved
LINK-GAP-030 no reviewed unique DB constraint cardinality depends on characterized writers
LINK-GAP-040 Booking save can change Consignee on T_LOAD hidden cross-aggregate mutation
LINK-GAP-050 CTC PO text and MK relational source differ one generic source field would lose type
LINK-GAP-060 Fulfillment target meaning is not approved target record mapping remains blocked
LINK-GAP-070 correction/history lineage is not persisted as a first-class link record audit/reconciliation are weak
LINK-GAP-080 live representative mismatches were not sampled current data consistency is unverified

14. Lifecycle Result

current application linkage behavior
= SOURCE_RECONCILED

current application cardinality
= ONE-TO-ONE INTENT / DB ENFORCEMENT NOT PROVEN

target command owner
= OPEN_DECISION

target Fulfillment aggregate
= CANDIDATE

live data parity
= NOT_RUN

NS2 Booking implementation
= BLOCKED

15. Evidence Sources

app/systems/TMS/booking/profile_extension.php
app/systems/TMS/booking/post_helper.php
app/systems/TMS/booking/api_routes.php
app/systems/OMS/inbound-order/order_reference_helper.php
app/systems/OMS/inbound-order/sales_order_write_helper.php
app/systems/OMS/shared/order_runtime_helper.php
scripts/migrations/2026-05-28_task-638_booking_sales_order_pointer.sql
tests/booking_sales_order_mapping_contract.test.mjs
tests/p5_booking_profile_extension_contract.test.mjs

---

Source: new-system/docs/reconstruction/BOOKING_SOURCE_LINKAGE_SOURCE_RECONCILED.md — ctc repository · This page is an English translation of the source document. Identifiers, file paths and code symbols are unchanged.