Ocean Booking — Traditional Development Specification¶
- Process ID:
process.transport.ocean-booking - Current review basis:
c853c62146730717af72f0395c8bd4687e8248c2, 2026-09-12; repository source only - Scope: Client ID 1 Legacy; Client ID 2
reference/mkmetalplus New-System - Current work/evidence: NS4-017; unresolved decisions below are not approved by source observation
- Detailed native design/data/interface: Transportation
- Screen and acceptance/RTM: Page, TEST_MATRIX
- Manual/Wiki: Client ID 2 only, derived after specification review; no new manual/runtime acceptance in this review
SRS: Purpose, Actors And Boundaries¶
Booking records a carrier reservation, schedule, intended equipment quantity, company references and document context. Saving it does not itself receive inventory, complete loading, dispatch equipment, post an invoice or deliver a document. Client-specific source behavior is reconstructed below; source existence is not approval of every business rule.
| Requirement / concern | Client ID 1: Legacy basis | Client ID 2: reference + native basis | Acceptance / unresolved decision |
|---|---|---|---|
| Create/read/edit a Booking | Office entry via booking-list; numeric compatibility API, tenant-scoped record |
reference Booking list/form; native UUID Booking workspace | persist and reread exactly the intended tenant/record; real-world initiation/role policy remains an explicit business decision |
| Identify reservation and carrier | Legacy create/update requires Booking number, SSL (≤10), Shipper and Booking type | reference form explicitly marks Booking number required; native requires number/type/SSL but accepts empty Shippers | preserve the source distinction; do not invent a C2 Shipper requirement or remove the C1 requirement in prose |
| Schedule and equipment intent | five size quantities; ERD/SI cutoff/cutoff datetime, ETD/ETA dates | reference one SIZE/QUANTITY and DATE fields; native five quantities and datetime/date mapping | quantities represent reservation intent, not actual loaded/used equipment |
| Company meaning | billing customer, Shipper list, pickup/return terminals | reference SHIPPER_COMPANY_ID is labelled Supplier; AGENCY_COMPANY_ID is Shipper; CONSIGNEE_COMPANY_ID is Consignee/Customer context | same spelling does not prove the same role; migration/default-company correspondence needs explicit evidence |
| Commercial/execution context | PO_NUMBER is text; optional compatibility extension is separately configured | reference ORDER_ID and many T_SALES rows; native T_LOAD.BOOKING_ID on outbound execution, read-only Booking salesOrderUuid | no assertion that one Booking must have exactly one Sales execution; distinguish commercial agreement from execution order |
| Documents | independent Packing/Confirmation/email actions and submission/invoiced flags | reference Packing/Confirmation and SI/BL/AR dates; native Packing source/preview plus source-rate editing | preview is not issuance; submitted/invoiced flags are not dispatch/accounting acceptance |
| Clone | current explicit clone route creates 1–9 headers; separate from ordinary create | native request UUID + 1–9 new UUIDs, atomic batch and replay receipt | no downstream row copy; reference has no independently traced clone contract here |
| Correction and conflicting edits | full normalized payload, resource lock; no expectedVersion CAS in this writer | sparse top-level PATCH with complete supplied groups and version CAS | C1 lock is not stale-edit detection; native conflict must not overwrite newer state |
| Access and tenant isolation | server tms.booking module decision; clone/assign-out-refs additionally declare role IDs 1–6 |
native session → tenant/actor → uuidBookingAccess; Packing also checks Booking menu exposure |
do not copy reference's single-system ID lookup or introduce a new role matrix; actual role acceptance remains NOT_RUN |
| Reliability / NFR | transaction and explicit related effects, known write vs unknown response distinguished | UUID replay/CAS and read-before-retry; eight-second HTTP deadline is not DB cancellation | no invented latency SLA, retention period or availability target; source/mock proof is not runtime proof |
Approved cross-cutting constraints are shared module ownership, tenant isolation, UUID-native public contracts and separation of DB commit from external effects. Observed Legacy/reference exceptions are comparison facts, not permission to weaken those constraints or automatically rewrite the Product.
Source Baseline And SAD — Three Distinct Systems¶
| Basis | Actual sources and responsibility | Evidence ceiling |
|---|---|---|
| C1 Legacy | app/systems/TMS/booking/{api_routes,post_helper,query_helper,profile_extension}.php; public/assets/js/modules/shared/booking-editor.js; current C1 page binding |
source at review SHA; server field rules and transaction path, not current Production role/data acceptance |
| C2 reference | reference/mkmetal/public/js/kjtable.js, controller/Ajax.php, view/{packingList,bookingConfirmation}.php, mk.sql DDL |
preserved source-system behavior and dump schema, not live runtime; customer rows/secrets are not reproduced |
| New-System | BookingWorkspace/hook → semanticBookingRoutes → BookingDataAccess → MysqlCompanyBookingData; separate Packing/File/AI owners |
native current source; applies by effective profile, not hardcoded client-owned packages |
| Physical schema | root .agents/rules/DB_SCHEMA.md, historical .agents/reference/schema.sql, migrations and adapter SQL |
source/snapshot only here; deployed constraints require named-environment metadata |
C1 is described from Legacy, with native differences shown separately. C2 is reconstructed from its own reference and native implementation, not from C1's Legacy screens. Reference source IDs are external identifiers; they must not be treated as current numeric IDs or native UUIDs. Historical source registry hashes remain historical. This review SHA applies only to the named source paths, not every assertion or old runtime record in this document.
Legacy Sequence — Client ID 1 Basis¶
sequenceDiagram
participant UI as Legacy Booking editor
participant API as tmsBookingWriteWithOutRefs
participant Owner as booking_post_handle
participant DB as MySQL transaction
UI->>API: POST / PATCH numeric ID + normalized form
API->>DB: begin
API->>Owner: CREATE or UPDATE with server tenant
Owner->>DB: validate and write T_BOOKING
opt Configured extension or explicitly supplied related input
Owner->>DB: Sales execution pointer / Consignee
API->>DB: OUT_REFS when present
end
Owner-->>API: ID and BOOKING_RATE task
API->>DB: syncTaskFlush on same connection
API->>DB: commit
API-->>UI: value.ID
UI->>API: exact detail readback
Note over UI,DB: No response does not prove rollback; check identity before retry
Current update additionally refreshes BMS setup occurrences when Pier Pass/clean-truck-fee/billing company
changes, and inspection occurrences when inspection ID changes. These calls are inside the same outer
transaction; inspect their owning BMS code when changing these fields. BOOKING_RATE dispatch goes through
SyncTaskRegistry/OrderSyncService before commit, not an assumed durable asynchronous worker.
Current Legacy clone route calls delivery_post_handle_clone_booking → clone_booking inside
tmsBookingWrite. It removes identity/audit/generated columns, filters extension columns by policy,
allocates suffixes and inserts headers. The route currently returns an empty value and no sync tasks,
not a list of created IDs. When enabled, source pointer columns are not explicitly cleared by
clone_booking_clean_template. Do not carry the older “clears link and returns IDs” claim forward.
Reference Sequence And State — Client ID 2 Origin¶
sequenceDiagram
participant UI as reference kjtable Booking form
participant Ajax as controller/Ajax.php
participant DB as reference MySQL
UI->>Ajax: action insert, type BOOKING, form data
Ajax->>DB: begin + INSERT T_BOOKING
Ajax->>DB: commit
Ajax-->>UI: lastInsertId
UI->>Ajax: table BOOKING / report query
Ajax->>DB: Booking + Sales/company/commodity projection
Ajax-->>UI: used count and derived status
Note over UI,DB: Generic update uses selected numeric keys; no native UUID/CAS receipt contract
The reference generic insert explicitly begins/commits; the generic update executes by selected keys. No rollback/unknown-result protocol is established by those branches. Reference behavior is not a safe implementation template for new native code.
| Representation | Actual values / derivation | Native correspondence |
|---|---|---|
Reference stored T_BOOKING.STATUS |
enum Active / Closed, default Active in mk.sql |
no same field in BookingData; do not equate automatically with active |
Reference list alias STATUS |
AR_DATE present → COMPLETED; else BL_DATE → AR-PENDING; else SI_DATE → SI-PENDING; otherwise PENDING | display formula, separate from stored STATUS; native does not expose these dates as writable Booking input |
| Reference container grouping | T_SALES.INGATE_TIME zero → schedule; populated → return; drag/drop writes Sales INGATE_TIME | not a Booking lifecycle transition; native execution/equipment writer must be traced separately |
Native active |
inverse of NOT_IN_USE | independent from soft deletion, document submission and invoiced flag |
| Native submission/invoiced | booleans in Booking flags | not automatic mappings of SI_DATE/BL_DATE/AR_DATE |
| Native editor recovery | CONFLICT, UNRESOLVED, RETRY_ALLOWED, RECOVERED | UI/write certainty states, never business Booking status |
The reference does have states; “Booking has no status” is only valid for the specific native contract, not for every Client/source. No new DRAFT→CONFIRMED→COMPLETED state machine is approved here.
Data Relationships And Change Impact¶
Client source data dictionary¶
This table compares historical DDL and source meaning, not deployed schemas. C1 snapshot is
.agents/reference/schema.sql T_BOOKING; C2 reference is reference/mkmetal/mk.sql T_BOOKING DDL
and public/js/kjtable.js Booking form. The native request dictionary and SQL mapping are in
Root/current migrations and named-environment metadata take precedence for physical deployment facts.
| Data meaning | C1 Legacy snapshot / current writer | C2 reference snapshot / form | Difference to resolve |
|---|---|---|---|
| Identity/scope | ID integer, CLIENT_ID integer; current tenant enforced by server |
BOOKING_ID integer primary key; no tenant column in this table |
reference ID is not current identity; native UUID + tenant + version mapping separate |
| Reservation | BOOKING_NUMBER varchar50; nonempty writer validation |
varchar20, default empty; global unique index; only explicit required form field | native max50/tenant uniqueness is not reference global uniqueness |
| BOL / offer / order | BOL varchar20 in snapshot; optional extension; PO text, separate Sales pointer | BOL_NUMBER, OFFER_NUMBER varchar20; ORDER_ID int default-1 |
native ordinary input does not expose BOL/offer/order pointer; PO is not an execution ID |
| Carrier/vessel | SSL varchar10, vessel varchar50 | SSL varchar10, vessel varchar50 | native vessel max100 requires actual schema-capacity proof |
| Schedule | ERD/SI_CUTOFF/CUTOFF nullable datetime; ETD/ETA nullable date | ERD/DOC_CUTOFF/CUTOFF/ETD/ETA NOT NULL date default zero-date | name, precision and absence representation differ; no automatic zero-date→native timestamp rule assumed |
| Equipment plan | five QUANTITY_* smallint default0 |
SIZE enum40H/40S/40F/45H/20S default40F, QUANTITY smallint0 | UI choices omit45H although DDL allows it; native five quantities need explicit transformation |
| Commodity | COMMODITY_NAME varchar20, COMMODITY_RATE decimal(10,4) | COMMODITY_ID int-1, COMMODITY_RATE decimal(10,3) | master identity vs text; header rate vs native execution-line invoice rate |
| Terminals | pickup/return Company numeric references, default-1 | RETURN_TERMINAL varchar20 text | free terminal text cannot be treated as native Company UUID |
| Company roles | BILLING_COMPANY_ID, SHIPPER_COMPANY_ID and varchar100 Shipper list | SHIPPER_COMPANY_ID=Supplier; AGENCY_COMPANY_ID=Shipper; CONSIGNEE_COMPANY_ID=Consignee; IDs default-1 | roles require semantic mapping, not column-name equality |
| Weights | MINIMUM/MAXIMUM_WEIGHT integer default0 | no corresponding T_BOOKING columns in this reference DDL | reference Confirmation has editable weight text; that is not evidence of persisted Booking weights |
| Commercial/document references | PO_NUMBER and INVOICE_NUMBER varchar50 | INVOICE_NUMBER varchar50 | native max100 differs from both snapshots; neither is a financial posting |
| Document progress | SI_DATE/BL_DATE/AR_DATE nullable date; separate submitted/invoiced tinyint flags | SI_DATE/BL_DATE/AR_DATE zero-date; STATUS enum Active/Closed | reference date-derived list state and stored state are separate as specified above |
| Notes/instructions | REMARK varchar255; SPECIAL_INSTRUCTION text | REMARK varchar255 | native permits5000; live capacity unknown |
| Operational flags | IS_PIERPASS, IS_CLEAN_TRUCK_FEE, IS_BOLT_SEAL tinyint0 | no equivalent columns in reference T_BOOKING DDL | current native independent flags must not be attributed to reference requirements |
| Seal/label/destination | enums in snapshot; LABEL_MESSAGE varchar100 | not in reference T_BOOKING DDL | native parser permits strings100/5000; enum compatibility remains a schema/policy question |
| Inspection/email | INSPECTOR_ID int-1; INSPECTION_ID varchar40; INSPECTION_EMAIL varchar100; EMAIL_TO/CC varchar200 | not in reference T_BOOKING DDL | native inspector remains numeric; email/inspection fields are not provider acceptance |
| Native concurrency/audit | historical snapshot is incomplete for UUID/lifecycle migrations | reference table has no native ROW_VERSION/receipt fields | use current adapter/migrations; neither dump proves current CAS or soft-delete constraints |
Reference list USED counts linked T_SALES; it is derived, not a stored reservation quantity.
Reference Confirmation textareas can carry print-only values absent from its T_BOOKING DDL. No field
should be declared persisted solely because it appears on that form. Decimal rounding/currency/unit,
retention and field-level privacy classification need explicit business/schema evidence; this review
does not invent them or reproduce production customer rows.
These are logical source relationships, not assertions of deployed foreign-key constraints.
flowchart LR
RB["reference T_BOOKING.BOOKING_ID"] --> RS["reference T_SALES.BOOKING_ID (many)"]
RB --> RC["reference Company / Commodity IDs"]
NB["native T_BOOKING UUID + tenant"] --> NL["T_LOAD.BOOKING_ID (outbound executions)"]
NL --> NI["T_LOAD_ITEM: commodity / rate / quantity"]
NL --> EL["T_EQUIPMENT_LOAD.OUTBOUND_ORDER_ID"]
NB --> EQ["T_EQUIPMENT return/pickup Booking references"]
EQ --> EL
EL --> PE["NS_PACKING_SOURCE_EDIT: scoped row + version"]
NB --> BF["Booking file relations → file object"]
- C1 current equipment-load ownership is resolved via Equipment return/pickup Booking references; do not assume an EQL.BOOKING_ID from an older helper defines the current source authority.
- Native ordinary Booking save writes its header and, on a submission transition, an operation event. It does not create/relink outbound orders, allocate inventory, assign Out Refs or run Legacy rate sync.
- Native Fulfillment's existing create/update/multi-edit writer owns
T_LOAD.BOOKING_ID. It resolves a same-tenant Booking and can represent several outbound rows for one Booking. Booking's historicalSALES_ORDER_ID/UUIDpointer is a separate compatibility read, not proof of a native one-to-one invariant. - Native Packing's OUTBOUND_SALES policy selects execution equipment and commodity lines through T_LOAD/EQL; the other policy selects the latest non-delivery equipment-load per equipment.
- Invoice-rate editing calls
trade/fulfillment-write.ts:updateFulfillmentItemRatesin the Packing transaction. The amount source is not the Booking header rate or a financial posting. - Company, schedule, flags and execution/source edits can affect lists, packing, printed documents and billing projections. Changing a query/result must review these consumers, not just the header form.
Exceptions, Recovery And Related Effects¶
The native save/unknown-result sequence and full error table are owned by the Transportation contract. The following boundaries are part of the business specification, not optional implementation notes.
| Operation | Failure and expected handling | Separate evidence required |
|---|---|---|
| Native header create/update | invalid/duplicate/ref failure is not success; conflict reloads explicitly; unknown response GETs the same UUID and compares submitted fields/version | actual MySQL concurrency and mounted editor/network |
| Native clone | same request receipt replays; changed payload or preexisting child IDs without receipt conflict; batch and receipt commit together | real DB replay/concurrency; Legacy clone has a different response contract |
| Packing source edit/batch | Booking revision + row source fingerprint + edit version checked; conflict rolls back batch; commit/readback uncertainty returns WRITE_RESULT_UNKNOWN | exact persisted row/overlay readback, not just rendered text |
| Packing Restore | sets source-following representation and advances version; does not undo separate equipment metadata or financial writes | demonstrate intended original source, not a blanket “undo all” |
| Invoice rate | selected UUID group and source/order versions required; same final rates can be read-confirmed; failed proof requires refresh | T_LOAD_ITEM rate readback and amount recalculation |
| Document preview | PREVIEW/RENDER_ONLY result; render failure does not undo Booking save | preview/print layout and any separately requested delivery |
| File attach/delete | object storage and relation transaction are separate; uncertain attach retains object for reconciliation; delete tracks cleanup/references | object/provider and relation readback |
| AI instruction | PDF/source parsing and allowlisted suggestions; Apply edits the draft, not persisted Booking | real provider output and explicit later Save |
| Legacy email/rate effects | email is explicit provider action; rate flush belongs to Legacy transaction | provider failure is not Booking rollback; native save does not inherit email/rate effects |
Specification Gaps And Decision Ownership¶
| Gap | Evidence and consequence | Existing owner / next proof |
|---|---|---|
| C2 reference state mapping | stored Active/Closed and date-derived status differ from native flags | Product/Transportation decision in NS4-017; do not populate target states from inference |
| Company-role mapping | reference Supplier/Shipper/Consignee names do not align by column spelling | Master Data + import mapping owner; check exact mapping before claiming migration parity |
| Source-link cardinality | historical dual pointer differs from native multiple outbound execution references | Fulfillment/Transportation; source linkage reconstruction retains its historical scope, no new dedicated bridge assumed |
| Legacy clone claims drifted | current route returns empty value; old narrative promised IDs/link clearing | corrected current description here; exact consumer/response recovery test still needed |
| Parser versus physical schema | native text maxima exceed some historical SQL widths; weight/unit and enum differences | DB adapter/migration owner; named-environment metadata required, not a reason to alter rules silently |
| Full role/trigger/retention policy | source does not establish business approval, all users or SLA | Product/Identity/operations decision; unresolved does not become unrestricted access |
| Runtime/source equivalence | this review is source-bound | current Task retains per-test and NOT_RUN boundaries; no manual or Production acceptance |
Traceability, Maintenance And Completion¶
Existing IDs remain: process.transport.ocean-booking, process.fulfillment.booking-linkage,
Booking command/query/data IDs and Page SCN IDs. See TEST_MATRIX
for requirement → source → test/expected outcome → actual evidence. Catalog entries must distinguish
native header response from Legacy compound detail and source effects.
A change to the named Legacy/reference/native writer, public input, schema mapping or policy invalidates the affected current description for review, not its historical evidence. Update the owning specification first, then affected guide/runbook/C2 manual. Source-change detection itself is still a separate L10 deliverable; this statement does not claim it is automated.
This specification records current source and explicit unresolved decisions. Runtime, live DB, external effects and end-user acceptance are not established by a Markdown table or a passing fixture.
Historical Reconstruction — Original NS0-003 Evidence¶
The original record below keeps its own revision and unresolved target decisions. Its “current” wording means that recorded revision; it must not override the current Client-specific specification above.
Original reconstruction and evidence boundaries
# Ocean Booking Process — Source-Reconciled Current Contract - Process ID: `process.transport.ocean-booking` - Status: `SOURCE_RECONCILED / TARGET APPROVAL BLOCKED` - Task: `NS0-003` - Current-source revision: `36655f639ee34e9bb371eb2c1ad893d0da2d09d4` - Candidate target owner: `transportation` - Current Runtime module: `tms.booking` with a CTC page-binding exception - Evidence level: repository source/schema/migration/test review - Operational verification: `NOT_RUN` - Current page contract: `booking-workspace/README.md` - User procedure: `Booking User Manual` - Focused source regression: `booking-profiles.test.ts` ## Reading boundary — native implementation versus historical reconstruction The source revision, Legacy commands, target blockers and operational `NOT_RUN` below belong to the recorded NS0-003 reconstruction. They are retained evidence, not a declaration that the later native implementation is still at Stage A. For current developer work start at the Transportation contract and linked Page/test matrix. Native POST/PATCH use `booking-data.ts` and `MysqlCompanyBookingData`; they do not automatically perform this historical document's conditional Sales Order/Out Ref/rate-sync sequence. Native unknown-result recovery is by UUID and submitted data/version, not a Booking-number search. Resolve actual policy gaps separately; source implementation alone does not approve every open business decision. Manual/Wiki expansion is currently Client ID 2 only; Client ID 1 is undecided. ## 1. Process Meaning An Ocean Booking records a tenant-scoped carrier booking commitment and the schedule, terminal, port and equipment-intent facts used by later execution and document work. It is not, by itself:a Sales Order
a Fulfillment request
an Inventory allocation
a Shipment dispatch
a Container return
a completed document set
a billing/settlement completion
identity:
ID / UUID / CLIENT_ID / BOOKING_NUMBER
carrier and schedule:
SHIPPING_LINE / VESSEL_NAME
ERD / SI_CUTOFF / CUTOFF / ETD / ETA
route:
PICKUP_TERMINAL_ID / RETURN_TERMINAL_ID
PORT_OF_LOADING / PORT_OF_DISCHARGE
equipment intent:
QUANTITY_20S / QUANTITY_40F / QUANTITY_40S
QUANTITY_40H / QUANTITY_45H
commercial/service context:
PO_NUMBER
optional SALES_ORDER_ID / SALES_ORDER_UUID
BILLING_COMPANY_ID
SHIPPER_COMPANY_ID / SHIPPER_COMPANY_ID_LIST
COMMODITY_NAME / COMMODITY_RATE
MINIMUM_WEIGHT / MAXIMUM_WEIGHT
documents and operational indicators:
INVOICE_NUMBER
IS_PACKINGLIST_SUBMITTED / IS_INVOICED
IS_PIERPASS / IS_CLEAN_TRUCK_FEE / NOT_IN_USE
seal / destination / label / inspection / instruction fields
lifecycle:
CREATED_AT / UPDATED_AT / DELETED_AT
record exists / soft-deleted
schedule dates present or absent
Sales Order linked or unlinked
containers linked or absent
Packing List submitted flag
invoiced flag
not-in-use flag
provider/document effects pending or complete
Booking saved != Booking confirmed
Booking saved != Fulfillment created
Sales Order linked != Inventory allocated
Container linked != Container loaded
Packing List submitted != Shipment dispatched
Invoiced != Settlement reconciled
Not In Use != Cancelled target state
input
-> normalize
-> validate
-> tenant-scoped insert
-> optional invoice number generation under lock
-> optional Sales Order/T_LOAD synchronization
-> optional Out Ref save
-> queue Booking rate synchronization
-> commit
-> return ID
-> exact detail readback in browser
tenant-scoped current-row read
-> normalize
-> validate
-> update Booking
-> optional explicit Sales Order relink/unlink
-> optional consignee synchronization
-> optional Out Ref save
-> queue Booking rate synchronization
-> commit
-> exact detail readback
read source Booking
-> remove identity/audit fields
-> clear SALES_ORDER_ID / SALES_ORDER_UUID because one Sales Order has one Booking owner
-> apply allowlisted overrides
-> generate unique Booking number suffix when needed
-> create one to nine new Bookings
-> return created Booking IDs and queue Booking-rate synchronization
-> reopen each created Booking by returned ID for authoritative readback
no response
-> result unknown
-> search/read Booking number before replay
write response includes ID
-> GET exact detail
-> verify ID
-> then report success and refresh parent list
shared Ocean Booking authority
+ explicit source reference
+ independent downstream states
+ compact Compatibility surfaces
+ additive Booking Workspace
+ one writer per command
+ authoritative readback
CreateOceanBooking
UpdateOceanBooking
CloneOceanBooking
LinkBookingSource
UnlinkBookingSource
CorrectOceanBooking
RetireOceanBooking or CancelOceanBooking OPEN
current source = SOURCE_RECONCILED
target Process = PROPOSED / BLOCKED
Runtime = NOT CHANGED
DB = NOT READ OR CHANGED
operator acceptance = NOT_RUN
---¶
Source:
new-system/docs/processes/OCEAN_BOOKING_SOURCE_RECONCILED.md— ctc repository · This page is an English translation of the source document. Identifiers, file paths and code symbols are unchanged.