platform-types 1.10.765 → 1.10.766

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.NotificationTypeEnum = void 0;
3
+ exports.WEB_NOTIFICATIONS_MAX_LIMIT = exports.CUSTOMER_NOTIFICATION_TYPES = exports.NotificationTypeEnum = void 0;
4
4
  // Canonical notification taxonomy and keys for legacy/type × channel preferences.
5
5
  // Indexed producers resolve candidates through `getNotificationSubscribers`:
6
6
  // legacy opt-ins and explicit channel maps remain source data on USER rows.
@@ -200,3 +200,11 @@ var NotificationTypeEnum;
200
200
  */
201
201
  NotificationTypeEnum["PAYMENT_ATTEMPT_RESOLUTION"] = "PAYMENT_ATTEMPT_RESOLUTION";
202
202
  })(NotificationTypeEnum || (exports.NotificationTypeEnum = NotificationTypeEnum = {}));
203
+ /**
204
+ * The notification types a CUSTOMER bell can carry today; each links through
205
+ * `orderId`. Adding one means a new {@link CustomerNotification} member with its
206
+ * own link field — the storefront maps type → route from this list.
207
+ */
208
+ exports.CUSTOMER_NOTIFICATION_TYPES = [NotificationTypeEnum.ORDER];
209
+ /** Web `GET /notifications` page ceiling and default (`?Limit=`). */
210
+ exports.WEB_NOTIFICATIONS_MAX_LIMIT = 500;
package/dist/cjs/order.js CHANGED
@@ -372,12 +372,26 @@ exports.orderFulfilmentProgress = orderFulfilmentProgress;
372
372
  * Storefront checkout carries `data: {}` and refuses before the cart read.
373
373
  *
374
374
  * Storefront checkout business refusals. None allocates an order
375
- * id, redeems a coupon or writes an order; none is logged as an error:
375
+ * id, redeems a coupon or writes an order; none is logged as an error —
376
+ * except `CART_CHANGED_SINCE_CONFIRM` refused at commit, as its entry says:
376
377
  * - `DELIVERY_METHOD_NOT_FOUND` · 400 — `deliveryMethod` is not in the store's
377
378
  * delivery catalogue, including an absent/empty catalogue. `data: {}`;
378
379
  * refused before reading the cart.
379
380
  * - `ORDER_INVALID_CART` · 400 — the normalized cart has no finite numeric
380
381
  * `totals.grandTotal`. `data: {}`; refused before repricing/allocation.
382
+ * - `CART_CHANGED_SINCE_CONFIRM` · 409 — the body sent `expectedCartId` /
383
+ * `expectedCartVersion` and the stored cart is not the cart the shopper
384
+ * confirmed (gone, replaced by another `cartId`, or at another `version`);
385
+ * `data` is `CartChangedSinceConfirmData` and carries no cart. Distinct from
386
+ * `ORDER_INVALID_CART` (a non-finite total) and from the operator's
387
+ * `CART_REVISION_STALE` / `CART_VERSION_*` (whose `data.basket` keeps
388
+ * `cost`). Decided at TWO points: right after the server's cart read, with
389
+ * nothing written and nothing logged; and at the commit, when the cart moved
390
+ * between the read and the write — then no order committed, but the order id
391
+ * allocated before the commit is consumed, a coupon redeemed before the
392
+ * commit is not released, and an ERROR row is logged.
393
+ * Re-read the cart and confirm again under a new `Idempotency-Key`; on
394
+ * `currentCartVersion: null` check the shopper's orders first.
381
395
  * - `ORDER_BELOW_MINIMUM_PURCHASE` · 400 — after repricing has confirmed the
382
396
  * cart, its grand total is below a finite positive `Number(customer.minBuy)`.
383
397
  * Equality passes. `data: OrderBelowMinimumPurchaseData` carries minBuy,
@@ -638,6 +652,8 @@ exports.ORDER_ERROR_CODES = [
638
652
  'DELIVERY_METHOD_NOT_FOUND',
639
653
  'ORDER_BELOW_MINIMUM_PURCHASE',
640
654
  'ORDER_INVALID_CART',
655
+ // The storefront's confirmed-cart pin (`StorefrontOrderCreateRequest.expectedCartId` / `expectedCartVersion`).
656
+ 'CART_CHANGED_SINCE_CONFIRM',
641
657
  'EMAIL_VERIFICATION_REQUIRED',
642
658
  'ACCOUNT_DISABLED',
643
659
  'CUSTOMER_ACCESS_PENDING',
@@ -179,6 +179,14 @@ export declare enum NotificationTypeEnum {
179
179
  */
180
180
  PAYMENT_ATTEMPT_RESOLUTION = "PAYMENT_ATTEMPT_RESOLUTION"
181
181
  }
182
+ /**
183
+ * The notification types a CUSTOMER bell can carry today; each links through
184
+ * `orderId`. Adding one means a new {@link CustomerNotification} member with its
185
+ * own link field — the storefront maps type → route from this list.
186
+ */
187
+ export declare const CUSTOMER_NOTIFICATION_TYPES: readonly [NotificationTypeEnum.ORDER];
188
+ /** Web `GET /notifications` page ceiling and default (`?Limit=`). */
189
+ export declare const WEB_NOTIFICATIONS_MAX_LIMIT = 500;
182
190
  declare global {
183
191
  type CustomerNotificationPreferences = Partial<Record<'reminder-scheduled' | 'appointment-reminder', {
184
192
  email: boolean;
@@ -241,6 +249,7 @@ declare global {
241
249
  createdAt: number;
242
250
  type: NotificationTypeEnum;
243
251
  title: string;
252
+ /** `ORDER` links through `orderId` on both audiences (operator and customer). */
244
253
  orderId?: string;
245
254
  productId?: string;
246
255
  lotId?: string;
@@ -305,7 +314,8 @@ declare global {
305
314
  };
306
315
  /**
307
316
  * `GET /notifications` body on the operator host — the caller's own
308
- * notifications, newest first, projected through an allow-list.
317
+ * notifications, newest first, projected through an allow-list. Operator
318
+ * host only; the web leg is {@link WebGetNotificationsResponse}.
309
319
  *
310
320
  * ⚠️ There is no `hasMore` on this leg: the ABSENCE of `LastEvaluatedKey` is
311
321
  * the end of the list. A client that waits for a `hasMore: false` never stops
@@ -337,6 +347,52 @@ declare global {
337
347
  hasMore: boolean;
338
348
  };
339
349
  }
350
+ type CustomerNotificationType = (typeof CUSTOMER_NOTIFICATION_TYPES)[number];
351
+ /**
352
+ * The customer projection: what web `GET`/`POST /notifications` and the
353
+ * customer socket carry — the stored row minus the operator-only pointers.
354
+ * A union keyed on `type`; `ORDER` is its only member today.
355
+ */
356
+ type CustomerNotification = Omit<NotificationInterface, 'cartRef' | 'pendingCustomerRef' | 'TableName' | 'type' | 'orderId'> & {
357
+ type: NotificationTypeEnum.ORDER;
358
+ /** Set on every customer row: the order the bell is about. */
359
+ orderId: string;
360
+ };
361
+ /**
362
+ * Web `GET /notifications`: the caller's own rows, newest first by
363
+ * `createdAt`. An `offSet` outside the caller's own key range is
364
+ * `400 INVALID_CURSOR`; one inside it resumes from that position, whether
365
+ * or not a row with that id still exists.
366
+ */
367
+ interface WebGetNotificationsResponse {
368
+ message: string;
369
+ data: CustomerNotification[];
370
+ /** The last row's `notificationId`; send it back as `?offSet=`. Absent = end of list. */
371
+ LastEvaluatedKey?: string;
372
+ }
373
+ /** Web `POST /notifications` (single, or `all: true`). */
374
+ interface WebPostNotificationsResponse {
375
+ message: string;
376
+ data: CustomerNotification[];
377
+ /** `all: true` only. */
378
+ updatedCount?: number;
379
+ /** `all: true` only — `true` means call again. */
380
+ hasMore?: boolean;
381
+ }
382
+ /**
383
+ * Customer socket frames, action `notifications`: one row as it is now
384
+ * stored (its `read` is the stored value, so a mark-unread reads `false`), or
385
+ * the mark-all summary.
386
+ */
387
+ type CustomerNotificationFrame = CustomerNotification | {
388
+ storeId: string;
389
+ customerId: string;
390
+ bulkRead: true;
391
+ updatedCount: number;
392
+ hasMore: boolean;
393
+ /** Every row this call marked read (their `notificationId`); patch these, no refetch needed. */
394
+ notificationIds: string[];
395
+ };
340
396
  /**
341
397
  * What the outbound seam (`notify()`) knew about one call the moment its
342
398
  * transport returned. It is never a delivery receipt: `enqueued` and
@@ -197,3 +197,11 @@ export var NotificationTypeEnum;
197
197
  */
198
198
  NotificationTypeEnum["PAYMENT_ATTEMPT_RESOLUTION"] = "PAYMENT_ATTEMPT_RESOLUTION";
199
199
  })(NotificationTypeEnum || (NotificationTypeEnum = {}));
200
+ /**
201
+ * The notification types a CUSTOMER bell can carry today; each links through
202
+ * `orderId`. Adding one means a new {@link CustomerNotification} member with its
203
+ * own link field — the storefront maps type → route from this list.
204
+ */
205
+ export const CUSTOMER_NOTIFICATION_TYPES = [NotificationTypeEnum.ORDER];
206
+ /** Web `GET /notifications` page ceiling and default (`?Limit=`). */
207
+ export const WEB_NOTIFICATIONS_MAX_LIMIT = 500;
package/dist/order.d.ts CHANGED
@@ -2137,6 +2137,24 @@ declare global {
2137
2137
  */
2138
2138
  basket: Cart | null;
2139
2139
  }
2140
+ /**
2141
+ * `data` of the storefront's `409 CART_CHANGED_SINCE_CONFIRM` — a web
2142
+ * `POST /orders` that sent {@link StorefrontOrderCreateRequest.expectedCartId}
2143
+ * or {@link StorefrontOrderCreateRequest.expectedCartVersion} against a cart
2144
+ * that is no longer the one the shopper confirmed. It carries no cart: re-read
2145
+ * it (`GET /basket`) and confirm again under a NEW `Idempotency-Key`.
2146
+ */
2147
+ interface CartChangedSinceConfirmData {
2148
+ /**
2149
+ * The confirmed cart's stored `version` as the server now reads it — a
2150
+ * row with no stored `version` reads as `0`. `null` when the confirmed cart
2151
+ * is no longer the stored cart: it is gone, or a different cart replaced
2152
+ * it. ⚠️ On `null` the order may already exist (the confirmed cart is
2153
+ * deleted by its own checkout), so check the shopper's orders before
2154
+ * letting them retry.
2155
+ */
2156
+ currentCartVersion: number | null;
2157
+ }
2140
2158
  /**
2141
2159
  * `data` of `409 CART_CUSTOMER_MISMATCH` — a create that sent
2142
2160
  * {@link CreateOrderRequest.expectedCartVersion} for a cart that carries a
@@ -2358,6 +2376,25 @@ declare global {
2358
2376
  };
2359
2377
  /** Persist `deliveryAddress` as the customer's default. Directive only, never stored. */
2360
2378
  saveAsDefault?: boolean;
2379
+ /**
2380
+ * The `cartId` of the cart the shopper confirmed (`CART` + 6-10 digits).
2381
+ * Omit it ONLY when that cart had none (a legacy cart). ⚠️ Compared
2382
+ * together with {@link expectedCartVersion} as ONE cart identity: a body
2383
+ * sending the version without this field means "the cart I confirmed had
2384
+ * no `cartId`", so a stored cart that has one is refused. A checkout
2385
+ * deletes its cart and the next add mints a NEW `cartId` at `version: 1`,
2386
+ * so a version alone does not identify a cart — always send this when the
2387
+ * rendered cart has one. A mismatch is `409 CART_CHANGED_SINCE_CONFIRM`.
2388
+ */
2389
+ expectedCartId?: string;
2390
+ /**
2391
+ * The `version` of the cart the shopper confirmed, an integer ≥ 1. Omit it
2392
+ * when that cart had none. Refused `409 CART_CHANGED_SINCE_CONFIRM` when
2393
+ * the stored cart's version (absent reads as `0`) differs, and re-asserted
2394
+ * at the commit, so a write between the server's read and the order
2395
+ * transaction refuses too.
2396
+ */
2397
+ expectedCartVersion?: number;
2361
2398
  }
2362
2399
  interface ZebraTag {
2363
2400
  orderId: string;
@@ -2730,12 +2767,26 @@ export declare const orderFulfilmentProgress: (order: OrderFulfilmentProgressInp
2730
2767
  * Storefront checkout carries `data: {}` and refuses before the cart read.
2731
2768
  *
2732
2769
  * Storefront checkout business refusals. None allocates an order
2733
- * id, redeems a coupon or writes an order; none is logged as an error:
2770
+ * id, redeems a coupon or writes an order; none is logged as an error —
2771
+ * except `CART_CHANGED_SINCE_CONFIRM` refused at commit, as its entry says:
2734
2772
  * - `DELIVERY_METHOD_NOT_FOUND` · 400 — `deliveryMethod` is not in the store's
2735
2773
  * delivery catalogue, including an absent/empty catalogue. `data: {}`;
2736
2774
  * refused before reading the cart.
2737
2775
  * - `ORDER_INVALID_CART` · 400 — the normalized cart has no finite numeric
2738
2776
  * `totals.grandTotal`. `data: {}`; refused before repricing/allocation.
2777
+ * - `CART_CHANGED_SINCE_CONFIRM` · 409 — the body sent `expectedCartId` /
2778
+ * `expectedCartVersion` and the stored cart is not the cart the shopper
2779
+ * confirmed (gone, replaced by another `cartId`, or at another `version`);
2780
+ * `data` is `CartChangedSinceConfirmData` and carries no cart. Distinct from
2781
+ * `ORDER_INVALID_CART` (a non-finite total) and from the operator's
2782
+ * `CART_REVISION_STALE` / `CART_VERSION_*` (whose `data.basket` keeps
2783
+ * `cost`). Decided at TWO points: right after the server's cart read, with
2784
+ * nothing written and nothing logged; and at the commit, when the cart moved
2785
+ * between the read and the write — then no order committed, but the order id
2786
+ * allocated before the commit is consumed, a coupon redeemed before the
2787
+ * commit is not released, and an ERROR row is logged.
2788
+ * Re-read the cart and confirm again under a new `Idempotency-Key`; on
2789
+ * `currentCartVersion: null` check the shopper's orders first.
2739
2790
  * - `ORDER_BELOW_MINIMUM_PURCHASE` · 400 — after repricing has confirmed the
2740
2791
  * cart, its grand total is below a finite positive `Number(customer.minBuy)`.
2741
2792
  * Equality passes. `data: OrderBelowMinimumPurchaseData` carries minBuy,
@@ -2873,6 +2924,6 @@ export declare const orderFulfilmentProgress: (order: OrderFulfilmentProgressInp
2873
2924
  * `SUBSCRIPTION_READONLY`) sit on the order CREATE leg only: an edit is not a new
2874
2925
  * order, so `bareOrderPostHandler` routes past `requireMetered` entirely.
2875
2926
  */
2876
- export declare const ORDER_ERROR_CODES: readonly ["ORDER_COST_DENOMINATION_UNKNOWN", "SERVICE_ORDER_DELIVERY_MANAGED", "ORDER_NOT_FOUND", "ORDER_LOCKED", "ORDER_NOT_READY", "ORDER_DELIVERED_ANOTHER_DAY", "ORDER_DELIVERY_STATE_UNCHANGED", "ORDER_ILLEGAL_TRANSITION", "ORDER_VERSION_CONFLICT", "CUSTOMER_NOT_FOUND", "CUSTOMER_MERGED", "ORDER_HAS_NO_CUSTOMER", "CUSTOMER_ANONYMIZED", "FX_CONVERSION_UNAVAILABLE", "ROLE_FORBIDDEN", "ORDER_CANCELLED", "PAYMENT_SETTLED_ON_ANOTHER_ORDER", "ORDER_HAS_SHIPMENTS", "ORDER_HAS_RETURNS", "SHIPMENT_QUANTITY_EXCEEDED", "SHIPMENT_LINE_MISMATCH", "SHIPMENT_NOT_FOUND", "SHIPMENT_LIMIT_REACHED", "SHIPMENT_TOO_LARGE", "ORDER_FULFILMENT_EXTERNAL", "SHIPMENT_FAILED", "ADMIN_REQUIRED", "IDEMPOTENCY_KEY_REQUIRED", "INVALID_IDEMPOTENCY_KEY", "IDEMPOTENCY_KEY_REUSE", "IDEMPOTENCY_IN_PROGRESS", "IDEMPOTENCY_LOCK_CONTENTION", "IDEMPOTENCY_KEY_FAILED", "IDEMPOTENT_RESPONSE_NOT_CACHED", "ORDER_CANCELLATION_NOT_PROTECTED", "ORDER_CANCELLATION_COMMITTED", "ORDER_CANCELLATION_LOCKED", "ORDER_CANCELLATION_TOO_LARGE", "ORDER_CANCELLATION_FAILED", "SALE_LEDGER_RETRACTION_REFUSED", "SALE_LEDGER_ROW_NOT_OWNED", "PRODUCT_NOT_FOUND", "PRODUCT_SALE_LIMIT_EXCEEDED", "PRODUCT_SALE_LIMIT_INVALID", "DEPOSIT_SOURCE_NOT_ALLOWED", "DEPOSIT_CURRENCY_MISMATCH", "DEPOSIT_EXCEEDS_TOTAL", "DEPOSIT_FREEZE_REQUIRES_INVOICE", "DEPOSIT_FREEZE_INVOICE_PENDING", "DEPOSIT_CHARACTERIZATION_CONFLICT", "DEPOSIT_FREEZE_INVOICE_NOT_QUALIFYING", "DEPOSIT_INVOICED_ORDER_MUST_FREEZE", "DEPOSIT_FROZEN_ORDER_MUST_FREEZE", "DEPOSIT_REFERENCE_IS_LINKED_PAYMENT", "DEPOSIT_DUPLICATE_REFERENCE", "TILL_TENDER_REQUIRES_DEPOSIT", "PAYMENT_REFERENCED_BY_DEPOSIT", "ORDER_HAS_UNREFUNDED_DEPOSIT", "ORDER_PRICE_FROZEN", "DEPOSIT_NOT_FOUND", "DEPOSIT_ALREADY_REFUNDED", "UNIT_QUANTITY_NOT_WHOLE", "UNIT_REVISION_STALE", "UNIT_QUANTITY_UNREPRESENTABLE", "KIT_RECIPE_CHANGED", "CART_PROMOTION_UNAVAILABLE", "ORDER_HAS_KIT_LINES", "ORDER_TARGET_REQUIRED", "ORDER_SOURCE_CONFLICT", "ORDER_CUSTOMER_REQUIRED", "BASKET_EMPTY", "BASKET_CHANGED_DURING_CHECKOUT", "CART_VERSION_CREATE_ONLY", "CART_VERSION_REQUIRES_CART_ID", "CART_REVISION_STALE", "CART_CUSTOMER_MISMATCH", "COUNTER_SALE_CREATE_ONLY", "SOLD_AT_CREATE_ONLY", "SOLD_AT_IN_FUTURE", "ORDER_TENDER_CREATE_ONLY", "CREDIT_OVERRIDE_CREATE_ONLY", "ON_ACCOUNT_CREATE_ONLY", "ON_ACCOUNT_WITH_TENDERS", "TENDERS_REQUIRE_COUNTER_SALE", "LINES_REQUIRE_COUNTER_SALE", "PRODUCT_COST_UNKNOWN", "PRICE_CHANGE_DISABLED", "LINE_DISCOUNT_EXCEEDS_MAX", "CUSTOMER_DISABLED", "SHIFT_NOT_AVAILABLE", "SOLD_AT_OUTSIDE_SHIFT", "ORDER_CURRENCY_NOT_SUBSCRIBED", "PAYMENT_METHODS_NOT_CONFIGURED", "PAYMENT_METHOD_NOT_FOUND", "PAYMENT_METHOD_UNAVAILABLE", "CART_PRICES_CHANGED", "ORDER_ID_COLLISION", "DELIVERY_METHOD_NOT_FOUND", "ORDER_BELOW_MINIMUM_PURCHASE", "ORDER_INVALID_CART", "EMAIL_VERIFICATION_REQUIRED", "ACCOUNT_DISABLED", "CUSTOMER_ACCESS_PENDING", "CUSTOMER_ACCESS_REJECTED", "CURRENCY_MISMATCH", "SHIFT_NOT_OPEN", "ORDER_DISCOUNT_AFTER_INVOICE", "ORDER_DISCOUNT_ON_SERVICE_ORDER", "ORDER_DISCOUNT_ON_MARKETPLACE_ORDER", "ORDER_INVOICE_METHOD_OUTSTANDING_FACTURA", "ORDER_SERVICE_PERIOD_AFTER_INVOICE", "ORDER_ATTEMPT_COMMITTED", "ORDER_ATTEMPT_ABANDONED", "ORDER_ATTEMPT_KEY_EXPIRED", "ORDER_ATTEMPT_KEY_SCOPE_MISMATCH", "ORDER_COMPLETION_ATTEMPT_COMMITTED", "ORDER_COMPLETION_ATTEMPT_ABANDONED"];
2927
+ export declare const ORDER_ERROR_CODES: readonly ["ORDER_COST_DENOMINATION_UNKNOWN", "SERVICE_ORDER_DELIVERY_MANAGED", "ORDER_NOT_FOUND", "ORDER_LOCKED", "ORDER_NOT_READY", "ORDER_DELIVERED_ANOTHER_DAY", "ORDER_DELIVERY_STATE_UNCHANGED", "ORDER_ILLEGAL_TRANSITION", "ORDER_VERSION_CONFLICT", "CUSTOMER_NOT_FOUND", "CUSTOMER_MERGED", "ORDER_HAS_NO_CUSTOMER", "CUSTOMER_ANONYMIZED", "FX_CONVERSION_UNAVAILABLE", "ROLE_FORBIDDEN", "ORDER_CANCELLED", "PAYMENT_SETTLED_ON_ANOTHER_ORDER", "ORDER_HAS_SHIPMENTS", "ORDER_HAS_RETURNS", "SHIPMENT_QUANTITY_EXCEEDED", "SHIPMENT_LINE_MISMATCH", "SHIPMENT_NOT_FOUND", "SHIPMENT_LIMIT_REACHED", "SHIPMENT_TOO_LARGE", "ORDER_FULFILMENT_EXTERNAL", "SHIPMENT_FAILED", "ADMIN_REQUIRED", "IDEMPOTENCY_KEY_REQUIRED", "INVALID_IDEMPOTENCY_KEY", "IDEMPOTENCY_KEY_REUSE", "IDEMPOTENCY_IN_PROGRESS", "IDEMPOTENCY_LOCK_CONTENTION", "IDEMPOTENCY_KEY_FAILED", "IDEMPOTENT_RESPONSE_NOT_CACHED", "ORDER_CANCELLATION_NOT_PROTECTED", "ORDER_CANCELLATION_COMMITTED", "ORDER_CANCELLATION_LOCKED", "ORDER_CANCELLATION_TOO_LARGE", "ORDER_CANCELLATION_FAILED", "SALE_LEDGER_RETRACTION_REFUSED", "SALE_LEDGER_ROW_NOT_OWNED", "PRODUCT_NOT_FOUND", "PRODUCT_SALE_LIMIT_EXCEEDED", "PRODUCT_SALE_LIMIT_INVALID", "DEPOSIT_SOURCE_NOT_ALLOWED", "DEPOSIT_CURRENCY_MISMATCH", "DEPOSIT_EXCEEDS_TOTAL", "DEPOSIT_FREEZE_REQUIRES_INVOICE", "DEPOSIT_FREEZE_INVOICE_PENDING", "DEPOSIT_CHARACTERIZATION_CONFLICT", "DEPOSIT_FREEZE_INVOICE_NOT_QUALIFYING", "DEPOSIT_INVOICED_ORDER_MUST_FREEZE", "DEPOSIT_FROZEN_ORDER_MUST_FREEZE", "DEPOSIT_REFERENCE_IS_LINKED_PAYMENT", "DEPOSIT_DUPLICATE_REFERENCE", "TILL_TENDER_REQUIRES_DEPOSIT", "PAYMENT_REFERENCED_BY_DEPOSIT", "ORDER_HAS_UNREFUNDED_DEPOSIT", "ORDER_PRICE_FROZEN", "DEPOSIT_NOT_FOUND", "DEPOSIT_ALREADY_REFUNDED", "UNIT_QUANTITY_NOT_WHOLE", "UNIT_REVISION_STALE", "UNIT_QUANTITY_UNREPRESENTABLE", "KIT_RECIPE_CHANGED", "CART_PROMOTION_UNAVAILABLE", "ORDER_HAS_KIT_LINES", "ORDER_TARGET_REQUIRED", "ORDER_SOURCE_CONFLICT", "ORDER_CUSTOMER_REQUIRED", "BASKET_EMPTY", "BASKET_CHANGED_DURING_CHECKOUT", "CART_VERSION_CREATE_ONLY", "CART_VERSION_REQUIRES_CART_ID", "CART_REVISION_STALE", "CART_CUSTOMER_MISMATCH", "COUNTER_SALE_CREATE_ONLY", "SOLD_AT_CREATE_ONLY", "SOLD_AT_IN_FUTURE", "ORDER_TENDER_CREATE_ONLY", "CREDIT_OVERRIDE_CREATE_ONLY", "ON_ACCOUNT_CREATE_ONLY", "ON_ACCOUNT_WITH_TENDERS", "TENDERS_REQUIRE_COUNTER_SALE", "LINES_REQUIRE_COUNTER_SALE", "PRODUCT_COST_UNKNOWN", "PRICE_CHANGE_DISABLED", "LINE_DISCOUNT_EXCEEDS_MAX", "CUSTOMER_DISABLED", "SHIFT_NOT_AVAILABLE", "SOLD_AT_OUTSIDE_SHIFT", "ORDER_CURRENCY_NOT_SUBSCRIBED", "PAYMENT_METHODS_NOT_CONFIGURED", "PAYMENT_METHOD_NOT_FOUND", "PAYMENT_METHOD_UNAVAILABLE", "CART_PRICES_CHANGED", "ORDER_ID_COLLISION", "DELIVERY_METHOD_NOT_FOUND", "ORDER_BELOW_MINIMUM_PURCHASE", "ORDER_INVALID_CART", "CART_CHANGED_SINCE_CONFIRM", "EMAIL_VERIFICATION_REQUIRED", "ACCOUNT_DISABLED", "CUSTOMER_ACCESS_PENDING", "CUSTOMER_ACCESS_REJECTED", "CURRENCY_MISMATCH", "SHIFT_NOT_OPEN", "ORDER_DISCOUNT_AFTER_INVOICE", "ORDER_DISCOUNT_ON_SERVICE_ORDER", "ORDER_DISCOUNT_ON_MARKETPLACE_ORDER", "ORDER_INVOICE_METHOD_OUTSTANDING_FACTURA", "ORDER_SERVICE_PERIOD_AFTER_INVOICE", "ORDER_ATTEMPT_COMMITTED", "ORDER_ATTEMPT_ABANDONED", "ORDER_ATTEMPT_KEY_EXPIRED", "ORDER_ATTEMPT_KEY_SCOPE_MISMATCH", "ORDER_COMPLETION_ATTEMPT_COMMITTED", "ORDER_COMPLETION_ATTEMPT_ABANDONED"];
2877
2928
  export type OrderErrorCode = (typeof ORDER_ERROR_CODES)[number];
2878
2929
  export {};
package/dist/order.js CHANGED
@@ -365,12 +365,26 @@ export const orderFulfilmentProgress = (order) => {
365
365
  * Storefront checkout carries `data: {}` and refuses before the cart read.
366
366
  *
367
367
  * Storefront checkout business refusals. None allocates an order
368
- * id, redeems a coupon or writes an order; none is logged as an error:
368
+ * id, redeems a coupon or writes an order; none is logged as an error —
369
+ * except `CART_CHANGED_SINCE_CONFIRM` refused at commit, as its entry says:
369
370
  * - `DELIVERY_METHOD_NOT_FOUND` · 400 — `deliveryMethod` is not in the store's
370
371
  * delivery catalogue, including an absent/empty catalogue. `data: {}`;
371
372
  * refused before reading the cart.
372
373
  * - `ORDER_INVALID_CART` · 400 — the normalized cart has no finite numeric
373
374
  * `totals.grandTotal`. `data: {}`; refused before repricing/allocation.
375
+ * - `CART_CHANGED_SINCE_CONFIRM` · 409 — the body sent `expectedCartId` /
376
+ * `expectedCartVersion` and the stored cart is not the cart the shopper
377
+ * confirmed (gone, replaced by another `cartId`, or at another `version`);
378
+ * `data` is `CartChangedSinceConfirmData` and carries no cart. Distinct from
379
+ * `ORDER_INVALID_CART` (a non-finite total) and from the operator's
380
+ * `CART_REVISION_STALE` / `CART_VERSION_*` (whose `data.basket` keeps
381
+ * `cost`). Decided at TWO points: right after the server's cart read, with
382
+ * nothing written and nothing logged; and at the commit, when the cart moved
383
+ * between the read and the write — then no order committed, but the order id
384
+ * allocated before the commit is consumed, a coupon redeemed before the
385
+ * commit is not released, and an ERROR row is logged.
386
+ * Re-read the cart and confirm again under a new `Idempotency-Key`; on
387
+ * `currentCartVersion: null` check the shopper's orders first.
374
388
  * - `ORDER_BELOW_MINIMUM_PURCHASE` · 400 — after repricing has confirmed the
375
389
  * cart, its grand total is below a finite positive `Number(customer.minBuy)`.
376
390
  * Equality passes. `data: OrderBelowMinimumPurchaseData` carries minBuy,
@@ -631,6 +645,8 @@ export const ORDER_ERROR_CODES = [
631
645
  'DELIVERY_METHOD_NOT_FOUND',
632
646
  'ORDER_BELOW_MINIMUM_PURCHASE',
633
647
  'ORDER_INVALID_CART',
648
+ // The storefront's confirmed-cart pin (`StorefrontOrderCreateRequest.expectedCartId` / `expectedCartVersion`).
649
+ 'CART_CHANGED_SINCE_CONFIRM',
634
650
  'EMAIL_VERIFICATION_REQUIRED',
635
651
  'ACCOUNT_DISABLED',
636
652
  'CUSTOMER_ACCESS_PENDING',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "platform-types",
3
- "version": "1.10.765",
3
+ "version": "1.10.766",
4
4
  "description": "Shared wire and entity contracts for the platform.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",