Conversation
source/schemas/shopping/order.json
Outdated
| "properties": { | ||
| "id": { | ||
| "type": "string", | ||
| "description": "Checkout session identifier." |
There was a problem hiding this comment.
| "description": "Checkout session identifier." | |
| "description": ""Unique identifier of the checkout session." |
To be consistent with checkout docs / schema desc
| "type": "string", | ||
| "format": "date-time", | ||
| "description": "RFC 3339 timestamp when this checkout session was created." | ||
| } |
There was a problem hiding this comment.
is the purpose of created_at to identify the sequential order of multiple checkouts? If so, do we need to include updated_at as well?
There was a problem hiding this comment.
Or is the purpose here just to distinguish the original checkout and edit/exchange checkouts ?
There was a problem hiding this comment.
created_at is there so the sequence is clear. Checkouts are frozen after creation - they are never updated - so updated_at is not needed here.
| "totals": { | ||
| "type": "array", | ||
| "items": { | ||
| "$ref": "total.json" |
There was a problem hiding this comment.
I don't think the current total and amount schema allows negative - should update them as part of this PR?
There was a problem hiding this comment.
Good catch. Removed minimum: 0 from amount.json so negative values are allowed for signed adjustment totals.
| **Line Items** — what was purchased at checkout: | ||
|
|
||
| * Includes current quantity counts (total, fulfilled) | ||
| * Can change post-order (e.g. order edits, exchanges) |
There was a problem hiding this comment.
With order edits now in the picture, can we add a guideline around what line_items SHOULD include post these changes, is it:
- A comprehensive list of all the items that once existed in the order, even if they were altered/removed via an edit?
OR - Only contain remaining items that are present after the latest edit?
My hunch is that 1) is more comprehensive from a data/audit perspective given there may have been adjustments that reference back to these altered products?
There was a problem hiding this comment.
Option 1 - comprehensive list. Line items should include all items that ever existed on the order, even if altered/removed via an edit. This is why quantity.original exists on line items - it preserves what was originally ordered at checkout, even when quantity.total changes to 0 after an edit. Adjustments can then always reference back to these items.
|
|
||
| * Item details (product, price, quantity ordered) | ||
| * Quantity counts and status are derived | ||
| * Quantity counts and fulfillment status |
There was a problem hiding this comment.
Can you clarify what this change mean here given I think status of the line_item is still derived based on it's relationship with quantity.total and quantity.fulfilled?
There was a problem hiding this comment.
The change here is removing the claim that quantities are "derived from events" - merchants may not send events, so we cannot say that is where the values come from, even though that may be the case the majority of the time. Status is still derived from the quantity fields, and that logic is still documented in the Status Derivation section below.
| * Include amount when relevant | ||
| * Quantities and amounts are signed—negative for reductions (returns, refunds), | ||
| positive for additions (exchanges) | ||
| * Include totals breakdown when relevant |
There was a problem hiding this comment.
Trying to visualize how totals can be used here:
- For a full refund, I can see this would be very similar to the
totalsconstruct in checkout. - However, for things like partial refund or any credit/price adjustment (i.e. resulting in an arbitrary money movement), I fail to fully understand what should be returned in the array here - if we have
type: TOTALfor these scenarios here, then it "violates"/"invalidates" our general rule of howtotalshould be calculated that currently is present intotals.json.
Alternatively, we can consider adding another categorization into totals.type for adjustment?
There was a problem hiding this comment.
totals on an adjustment is scoped to that adjustment, not the order. A partial refund of $5 would just be [{ "type": "total", "amount": -500 }]. If the business wants to break it down further (e.g. the subtotal and tax portions of the refund separately), they can, but a single total entry works fine for simple cases. The calculation rules in totals.json apply to order-level and checkout-level totals, not adjustment-level.
| "type": "object", | ||
| "required": ["total", "fulfilled"], | ||
| "properties": { | ||
| "original": { |
There was a problem hiding this comment.
It's not super clear about the use case we have in-mind for this field (especially given other quantity fields are used for deriving status).
Tied with a comment below, I think maybe one use case is to use it along with quantity.total to under if status should be in cancelled state?
There was a problem hiding this comment.
Primary use case is what we discussed above - line items are a comprehensive list that includes items removed via edits. quantity.original lets platforms see what was originally ordered without fetching the Checkout record. For example, an item edited down to 0 would have original: 2, total: 0, fulfilled: 0 - the platform can see it was a real item that got removed, not a phantom entry.
docs/specification/order.md
Outdated
| ```json | ||
| { | ||
| "total": 3, // Current total quantity | ||
| "original": 3, // Quantity at checkout |
There was a problem hiding this comment.
nit: Maybe we should clarify a bit further that this is the checkout with the oldest created_at timestamp (and not just any checkout)?
There was a problem hiding this comment.
Good point. This refers to the original checkout (the one with the earliest created_at). Updated the description to clarify.
| "partial", | ||
| "fulfilled" | ||
| ], | ||
| "description": "Derived status: fulfilled if quantity.fulfilled == quantity.total, partial if quantity.fulfilled > 0, otherwise processing." |
There was a problem hiding this comment.
I think we will need some more status or at least add some more conditions to this described logic to cover the following 2 scenarios:
- If order is cancelled prior to fulfillment, then by this logic today, item-level status will be stuck in
processing. We should probably add some terminal state to catchcancelled. - If an item is fulfilled, then edited from an exchange, then I'd imagine the old item that got exchanged would have
totals = 0butfulfilled > 0, in that case, what status should it be in (maybe we should havefulfilled if quantity.fulfilled >= quantity.totalinstead)?
There was a problem hiding this comment.
Good observations. The status derivation documented here covers the common case - it is not meant to be exhaustive. The spec treats status as an open string, so businesses can use additional values like cancelled or exchanged for these scenarios. We will keep the derivation simple for now and can expand the documented examples in a follow-up if needed. Does that sound good?
b3b2218 to
6039caf
Compare
Description
Collection of updates to the Order capability to make the spec more flexible, robust, and clear.
checkoutsarray (order edits create new sessions)quantity.originalon line itemsamounttototalsfor consistency with Order and OrderLineItemType of change
functionality to not work as expected, including removal of schema files
or fields)
Is this a Breaking Change or Removal?
!to my PR title (e.g.,feat!: remove field).Breaking Changes / Removal Justification
checkout_id(string) replaced withcheckouts(array of{ id, created_at }objects) — orders can reference multiple checkout sessions via edits and exchangesamounton Adjustment replaced withtotals(array of Total objects) — aligns with the pattern used by Order and OrderLineItemminimum: 1removed from adjustment line item quantities — signed values needed for returns and exchangesminimum: 0removed fromamount.json— amounts can be negative for refunds, credits, and adjustment totals across all capabilitiesChecklist