Originally posted in: https://github.com/commerce-operations-foundation/mcp-reference-server/pull/24
shippingRequestedDate is flagged as ambiguous. The author proposes splitting into two concepts: requested_ship_date / ship_not_before_date (outbound timing), and desired_receipt_date (DRDT, consistent with EDI 850 usage). These are operationally distinct and relevant for pre-orders and new product launches. The reviewer noted this is a terminology question that warrants group consensus.
What the existing schema tells us:
- No existing date fields at order header level are visible in the diff beyond the proposed shippingRequestedDate
- The schema uses ISO 8601 strings for date values throughout
- The PR adds shippingRequestedDate as a single flat string, which the reviewer flagged as ambiguous and the author proposed splitting
The operational reality - There are actually four distinct date concepts in cross-border and pre-order fulfilment, not two. Collapsing them creates downstream ambiguity at the WMS and carrier booking layer:
- When the seller commits to ship by (outbound SLA)
- The earliest the shipment can leave the warehouse (embargo / pre-order release gate)
- When the customer wants to receive it (demand signal)
- The latest acceptable delivery date before the order is considered failed (customer expectation ceiling)
EDI 850 uses separate qualifier codes for each: 037 (Ship Not Before), 038 (Ship Not After), 002 (Delivery Requested), 007 (Cancel After / Do Not Deliver After). Mapping a single shippingRequestedDate to any of these requires the WMS to guess, which it will get wrong on pre-orders and embargoed launches.
"fulfillmentWindow": {
"type": "object",
"description": "Date constraints governing outbound shipment timing and customer delivery expectations. All dates in ISO 8601 format (YYYY-MM-DD). Maps to EDI 850 date qualifier codes for downstream WMS and TMS consumption. All fields optional; populate only those relevant to the order type.",
"properties": {
"requestedShipDate": {
"description": "Date the seller commits or the buyer requests the order to ship. EDI 850 qualifier 010 (Requested Ship). Used as the primary outbound target date by the WMS pick/pack scheduler.",
"type": "string",
"format": "date"
},
"shipNotBeforeDate": {
"description": "Earliest date the order may leave the warehouse. EDI 850 qualifier 037 (Ship Not Before). Set for embargoed product launches, pre-orders, or date-sensitive promotions. WMS must hold the order until this date regardless of pick completion.",
"type": "string",
"format": "date"
},
"shipNotAfterDate": {
"description": "Latest date the order may ship to remain viable for delivery. EDI 850 qualifier 038 (Ship Not After). Beyond this date the order should be cancelled or escalated. Prevents late shipment of time-critical goods.",
"type": "string",
"format": "date"
},
"requestedDeliveryDate": {
"description": "Date the customer expects to receive the order. EDI 850 qualifier 002 (Delivery Requested). Passed to the carrier as the desired delivery date. Informs carrier service level selection where the TMS is choosing between options.",
"type": "string",
"format": "date"
},
"doNotDeliverAfterDate": {
"description": "Latest acceptable delivery date. EDI 850 qualifier 007 (Cancel After). Order should be returned or refused by the carrier if delivery cannot be completed by this date. Common for perishables, event merchandise, and seasonal goods.",
"type": "string",
"format": "date"
}
},
"additionalProperties": false
}
fulfillmentWindow as the node name rather than a shipping-prefixed name because this data serves both the WMS (shipment release decisions) and the carrier booking layer (delivery promise), not just the shipping process. A WMS reads shipNotBeforeDate to hold a pre-order. The TMS reads requestedDeliveryDate to select a service level. Naming it shippingDates would imply it belongs only to the carrier leg.
format: "date" enforces ISO 8601 date-only strings (YYYY-MM-DD) rather than datetime, which is the correct precision for these fields. Shipment release and delivery windows are calendar-day constraints, not timestamp constraints. Using datetime would introduce timezone ambiguity across the WMS-to-carrier handoff.
EDI 850 qualifier codes in the descriptions are not schema enforcement, they are translation keys for the adapter layer. Any WMS or TMS that speaks EDI can map these fields directly without maintaining a separate lookup table.
shipNotAfterDate is the addition that the author's proposal omitted. The window between shipNotBeforeDate and shipNotAfterDate defines the valid shipping corridor. Without the upper bound, the WMS has no automated signal to cancel or escalate an order that missed its launch window.
doNotDeliverAfterDate is similarly absent from the author's proposal. For time-sensitive shipments this is the field that prevents a carrier from delivering a Christmas gift on 27 December or a concert ticket after the event date. Without it the WMS has no basis to instruct the carrier to return rather than deliver late.
Interaction with existing and proposed fields:
order (header)
├── shippingCarrier ← existing flat field
├── shippingMethod ← existing flat field
├── incoterms ← existing flat field
├── reasonForExport ← proposed enum
├── crossBorderParties ← party identity and regulatory IDs
├── crossBorderCharges ← taxes and duties collected at checkout
├── shippingCharges ← shipping financials for customs valuation
├── carrierBilling ← carrier account and billing responsibility
└── fulfillmentWindow ← date constraints for WMS and carrier
├── requestedShipDate
├── shipNotBeforeDate
├── shipNotAfterDate
├── requestedDeliveryDate
└── doNotDeliverAfterDate
Notes:
Whether requestedShipDate and shipNotBeforeDate can coexist without conflict. For a standard order requestedShipDate is the target. For a pre-order shipNotBeforeDate is the constraint and requestedShipDate may be absent or equal to shipNotBeforeDate. The schema allows both to be populated simultaneously, which is valid: a pre-order might have a release gate of 1 July and a committed ship date of 3 July. The WMS needs both. >>> a validation note in the description clarifying that requestedShipDate must not precede shipNotBeforeDate where both are present.
Datetime versus date format. If any fulfilment operation requires hour-level precision, such as same-day cut-offs or time-definite carrier bookings, the format: "date" constraint will need to become format: "date-time". This is worth confirming with WMS adapter maintainers before the field type is locked, as changing it later is a breaking schema change.
Originally posted in: https://github.com/commerce-operations-foundation/mcp-reference-server/pull/24
What the existing schema tells us:
The operational reality - There are actually four distinct date concepts in cross-border and pre-order fulfilment, not two. Collapsing them creates downstream ambiguity at the WMS and carrier booking layer:
EDI 850 uses separate qualifier codes for each: 037 (Ship Not Before), 038 (Ship Not After), 002 (Delivery Requested), 007 (Cancel After / Do Not Deliver After). Mapping a single shippingRequestedDate to any of these requires the WMS to guess, which it will get wrong on pre-orders and embargoed launches.
fulfillmentWindow as the node name rather than a shipping-prefixed name because this data serves both the WMS (shipment release decisions) and the carrier booking layer (delivery promise), not just the shipping process. A WMS reads shipNotBeforeDate to hold a pre-order. The TMS reads requestedDeliveryDate to select a service level. Naming it shippingDates would imply it belongs only to the carrier leg.
format: "date" enforces ISO 8601 date-only strings (YYYY-MM-DD) rather than datetime, which is the correct precision for these fields. Shipment release and delivery windows are calendar-day constraints, not timestamp constraints. Using datetime would introduce timezone ambiguity across the WMS-to-carrier handoff.
EDI 850 qualifier codes in the descriptions are not schema enforcement, they are translation keys for the adapter layer. Any WMS or TMS that speaks EDI can map these fields directly without maintaining a separate lookup table.
shipNotAfterDate is the addition that the author's proposal omitted. The window between shipNotBeforeDate and shipNotAfterDate defines the valid shipping corridor. Without the upper bound, the WMS has no automated signal to cancel or escalate an order that missed its launch window.
doNotDeliverAfterDate is similarly absent from the author's proposal. For time-sensitive shipments this is the field that prevents a carrier from delivering a Christmas gift on 27 December or a concert ticket after the event date. Without it the WMS has no basis to instruct the carrier to return rather than deliver late.
Interaction with existing and proposed fields:
Notes:
Whether requestedShipDate and shipNotBeforeDate can coexist without conflict. For a standard order requestedShipDate is the target. For a pre-order shipNotBeforeDate is the constraint and requestedShipDate may be absent or equal to shipNotBeforeDate. The schema allows both to be populated simultaneously, which is valid: a pre-order might have a release gate of 1 July and a committed ship date of 3 July. The WMS needs both. >>> a validation note in the description clarifying that requestedShipDate must not precede shipNotBeforeDate where both are present.
Datetime versus date format. If any fulfilment operation requires hour-level precision, such as same-day cut-offs or time-definite carrier bookings, the format: "date" constraint will need to become format: "date-time". This is worth confirming with WMS adapter maintainers before the field type is locked, as changing it later is a breaking schema change.