@sixtyninecommerce/admin 0.8.0 → 0.10.0

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.
Files changed (179) hide show
  1. package/README.md +2739 -17
  2. package/dist/api-tokens/index.d.ts +15 -5
  3. package/dist/api-tokens/index.js +1 -0
  4. package/dist/apps/event-subscription.d.ts +59 -0
  5. package/dist/apps/event-subscription.js +32 -0
  6. package/dist/apps/hook-secret.d.ts +22 -0
  7. package/dist/apps/hook-secret.js +36 -0
  8. package/dist/apps/index.d.ts +54 -3
  9. package/dist/apps/index.js +17 -0
  10. package/dist/audit/index.d.ts +7 -0
  11. package/dist/auth/queries.d.ts +5 -1
  12. package/dist/auth/queries.js +6 -0
  13. package/dist/bulk/index.d.ts +323 -0
  14. package/dist/bulk/index.js +162 -0
  15. package/dist/catalog/assets.d.ts +147 -0
  16. package/dist/catalog/assets.js +164 -0
  17. package/dist/catalog/collections.d.ts +109 -0
  18. package/dist/catalog/collections.js +91 -0
  19. package/dist/catalog/facets.d.ts +103 -0
  20. package/dist/catalog/facets.js +100 -0
  21. package/dist/catalog/index.d.ts +115 -0
  22. package/dist/catalog/index.js +21 -0
  23. package/dist/catalog/options.d.ts +89 -0
  24. package/dist/catalog/options.js +88 -0
  25. package/dist/catalog/products-bulk.d.ts +21 -0
  26. package/dist/catalog/products-bulk.js +58 -0
  27. package/dist/catalog/products.d.ts +650 -0
  28. package/dist/catalog/products.js +458 -0
  29. package/dist/catalog/properties.d.ts +234 -0
  30. package/dist/catalog/properties.js +158 -0
  31. package/dist/catalog/types.d.ts +174 -0
  32. package/dist/catalog/types.js +141 -0
  33. package/dist/catalog/variants.d.ts +324 -0
  34. package/dist/catalog/variants.js +288 -0
  35. package/dist/catalog/visibility.d.ts +57 -0
  36. package/dist/catalog/visibility.js +59 -0
  37. package/dist/client.d.ts +192 -3
  38. package/dist/client.js +87 -12
  39. package/dist/compliance/index.d.ts +88 -0
  40. package/dist/compliance/index.js +88 -0
  41. package/dist/customer-data-redaction.d.ts +14 -0
  42. package/dist/customer-data-redaction.js +22 -0
  43. package/dist/customers/index.d.ts +428 -17
  44. package/dist/customers/index.js +322 -15
  45. package/dist/documents/index.d.ts +513 -16
  46. package/dist/documents/index.js +229 -3
  47. package/dist/events/index.d.ts +259 -0
  48. package/dist/events/index.js +147 -0
  49. package/dist/feeds/ai.d.ts +46 -0
  50. package/dist/feeds/ai.js +43 -0
  51. package/dist/feeds/categories.d.ts +50 -0
  52. package/dist/feeds/categories.js +56 -0
  53. package/dist/feeds/configs.d.ts +54 -0
  54. package/dist/feeds/configs.js +85 -0
  55. package/dist/feeds/identifier-fields.d.ts +25 -0
  56. package/dist/feeds/identifier-fields.js +29 -0
  57. package/dist/feeds/index.d.ts +54 -0
  58. package/dist/feeds/index.js +46 -0
  59. package/dist/feeds/preserve.d.ts +38 -0
  60. package/dist/feeds/preserve.js +74 -0
  61. package/dist/feeds/rules.d.ts +42 -0
  62. package/dist/feeds/rules.js +56 -0
  63. package/dist/feeds/types.d.ts +654 -0
  64. package/dist/feeds/types.js +135 -0
  65. package/dist/fulfillments/index.d.ts +437 -0
  66. package/dist/fulfillments/index.js +534 -0
  67. package/dist/heads/index.d.ts +60 -0
  68. package/dist/heads/index.js +45 -0
  69. package/dist/hooks/assignments.d.ts +90 -0
  70. package/dist/hooks/assignments.js +53 -0
  71. package/dist/hooks/index.d.ts +97 -0
  72. package/dist/hooks/index.js +76 -0
  73. package/dist/index.d.ts +95 -9
  74. package/dist/index.js +21 -1
  75. package/dist/integrations/index.d.ts +14 -0
  76. package/dist/integrations/index.js +9 -0
  77. package/dist/integrations/pipelines.d.ts +113 -0
  78. package/dist/integrations/pipelines.js +62 -0
  79. package/dist/integrations/types.d.ts +176 -0
  80. package/dist/integrations/types.js +8 -0
  81. package/dist/jobs/bulk-action-run.d.ts +74 -0
  82. package/dist/jobs/bulk-action-run.js +69 -0
  83. package/dist/locations/index.d.ts +6 -2
  84. package/dist/meta/index.d.ts +32 -0
  85. package/dist/orders/bulk.d.ts +75 -0
  86. package/dist/orders/bulk.js +150 -0
  87. package/dist/orders/commit-edit.d.ts +123 -0
  88. package/dist/orders/commit-edit.js +142 -0
  89. package/dist/orders/deposit-policy.d.ts +103 -0
  90. package/dist/orders/deposit-policy.js +202 -0
  91. package/dist/orders/get.d.ts +722 -0
  92. package/dist/orders/get.js +530 -0
  93. package/dist/orders/index.d.ts +186 -21
  94. package/dist/orders/index.js +57 -0
  95. package/dist/orders/line-price-preview.d.ts +297 -0
  96. package/dist/orders/line-price-preview.js +50 -0
  97. package/dist/orders/manual-discounts.d.ts +141 -0
  98. package/dist/orders/manual-discounts.js +97 -0
  99. package/dist/orders/manual-pricing.d.ts +192 -0
  100. package/dist/orders/manual-pricing.js +72 -0
  101. package/dist/orders/order-entry.d.ts +566 -0
  102. package/dist/orders/order-entry.js +129 -0
  103. package/dist/orders/parcel-charge.d.ts +45 -0
  104. package/dist/orders/parcel-charge.js +55 -0
  105. package/dist/orders/plan-edit.d.ts +489 -0
  106. package/dist/orders/plan-edit.js +93 -0
  107. package/dist/orders/status.d.ts +235 -0
  108. package/dist/orders/status.js +96 -0
  109. package/dist/orders/surcharges.d.ts +75 -2
  110. package/dist/orders/surcharges.js +110 -4
  111. package/dist/payments/account-credit.d.ts +171 -0
  112. package/dist/payments/account-credit.js +107 -0
  113. package/dist/payments/index.d.ts +241 -9
  114. package/dist/payments/index.js +92 -0
  115. package/dist/payments/methods.d.ts +37 -0
  116. package/dist/payments/methods.js +33 -0
  117. package/dist/platform/catalog.d.ts +148 -0
  118. package/dist/platform/catalog.js +74 -0
  119. package/dist/platform/entitlements.d.ts +111 -0
  120. package/dist/platform/entitlements.js +86 -0
  121. package/dist/platform/legal-entities.d.ts +139 -0
  122. package/dist/platform/legal-entities.js +126 -0
  123. package/dist/platform/legal-entity-numbering.d.ts +103 -0
  124. package/dist/platform/legal-entity-numbering.js +101 -0
  125. package/dist/platform/organization-membership.d.ts +80 -0
  126. package/dist/platform/organization-membership.js +71 -0
  127. package/dist/platform/organization-settings.d.ts +33 -0
  128. package/dist/platform/organization-settings.js +42 -0
  129. package/dist/platform/organization-sharing.d.ts +172 -0
  130. package/dist/platform/organization-sharing.js +120 -0
  131. package/dist/platform/organizations.d.ts +205 -0
  132. package/dist/platform/organizations.js +180 -0
  133. package/dist/platform/provision-store.d.ts +88 -8
  134. package/dist/platform/provision-store.js +12 -0
  135. package/dist/platform/reports.d.ts +46 -0
  136. package/dist/platform/reports.js +31 -0
  137. package/dist/platform/server-metrics.d.ts +58 -0
  138. package/dist/platform/server-metrics.js +11 -0
  139. package/dist/pos/index.d.ts +567 -0
  140. package/dist/pos/index.js +205 -0
  141. package/dist/pricing/index.d.ts +408 -0
  142. package/dist/pricing/index.js +353 -0
  143. package/dist/pricing/vouchers.d.ts +103 -0
  144. package/dist/pricing/vouchers.js +69 -0
  145. package/dist/provenance/index.d.ts +93 -0
  146. package/dist/provenance/index.js +53 -0
  147. package/dist/reports/index.d.ts +199 -0
  148. package/dist/reports/index.js +154 -0
  149. package/dist/returns/index.d.ts +225 -0
  150. package/dist/returns/index.js +160 -0
  151. package/dist/search/index.d.ts +99 -0
  152. package/dist/search/index.js +62 -0
  153. package/dist/shipping/parcel-count-suggestion.d.ts +52 -0
  154. package/dist/shipping/parcel-count-suggestion.js +73 -0
  155. package/dist/shipping/parcel-rule.d.ts +48 -0
  156. package/dist/shipping/parcel-rule.js +91 -0
  157. package/dist/stock/index.d.ts +166 -0
  158. package/dist/stock/index.js +115 -0
  159. package/dist/stock/transfers.d.ts +520 -0
  160. package/dist/stock/transfers.js +437 -0
  161. package/dist/stored-value/index.d.ts +154 -0
  162. package/dist/stored-value/index.js +130 -0
  163. package/dist/tenant/capabilities.d.ts +10 -0
  164. package/dist/tenant/entitlements.d.ts +35 -0
  165. package/dist/tenant/entitlements.js +15 -0
  166. package/dist/tenant/field-groups.d.ts +64 -0
  167. package/dist/tenant/field-groups.js +34 -0
  168. package/dist/tenant/legal-entity.d.ts +32 -0
  169. package/dist/tenant/legal-entity.js +41 -0
  170. package/dist/tenant/notifications.d.ts +148 -0
  171. package/dist/tenant/notifications.js +79 -0
  172. package/dist/tenant/retention.d.ts +10 -4
  173. package/dist/tenant/settings-sources.d.ts +103 -0
  174. package/dist/tenant/settings-sources.js +92 -0
  175. package/dist/types.d.ts +86 -11
  176. package/dist/uploads/index.d.ts +11 -7
  177. package/dist/users/index.d.ts +104 -0
  178. package/dist/users/index.js +80 -0
  179. package/package.json +3 -2
@@ -0,0 +1,235 @@
1
+ /**
2
+ * `admin.orders.status(orderId)`: why an order is the way it is, and what can
3
+ * be done to it (headless spec §7 `orders.status`, plan W9-8).
4
+ *
5
+ * One derived read, so a head does not re-derive the lock, the edit block,
6
+ * the allocation badge or the status menu from the order's fields. It is the
7
+ * engine's root `orderStatus` query, never a field on an order list.
8
+ *
9
+ * The four lists below are the engine's own, pinned to it by
10
+ * `__tests__/orders-status.spec.ts`. The engine adds to them over time, so
11
+ * every field that carries one also accepts a string this version does not
12
+ * name: treat an unknown value as "not available".
13
+ */
14
+ import type { Transport } from '@sixtyninecommerce/core';
15
+ import type { Call } from '../types.js';
16
+ /** Which of the lock's two writers locked the order. */
17
+ export declare const ORDER_LOCK_REASONS: readonly ["NONE", "INVOICE", "IMPORTED", "UNKNOWN"];
18
+ /**
19
+ * `NONE`: not locked. `INVOICE`: an invoice was issued for it on this
20
+ * platform. `IMPORTED`: the source platform had already invoiced it, and this
21
+ * platform holds no invoice for it. `UNKNOWN`: locked, cause not established.
22
+ */
23
+ export type OrderLockReason = (typeof ORDER_LOCK_REASONS)[number];
24
+ /** What to show for the order's stock-reservation expiry. */
25
+ export declare const ORDER_ALLOCATION_BADGES: readonly ["HIDDEN", "RESERVED", "EXPIRED"];
26
+ /**
27
+ * `EXPIRED` means the allocation sweeper WILL cancel the order. An order it
28
+ * leaves alone (placed, holding money, parked, held by a fulfillment) is never
29
+ * `EXPIRED`. `RESERVED`: the expiry is ahead, or the order is parked and keeps
30
+ * its stock. `HIDDEN`: no expiry applies.
31
+ */
32
+ export type OrderAllocationBadge = (typeof ORDER_ALLOCATION_BADGES)[number];
33
+ /** Why an order's content may not change. */
34
+ export declare const ORDER_EDIT_BLOCK_CODES: readonly ["INVOICE_LOCKED", "COMPLETED", "CANCELLED"];
35
+ export type OrderEditBlockCode = (typeof ORDER_EDIT_BLOCK_CODES)[number];
36
+ /** The actions the engine answers for, in the order it lists them. */
37
+ export declare const ORDER_STATUS_ACTIONS: readonly ["MODIFY", "DELETE", "RELEASE_ALLOCATION", "CORRECT_FULFILLMENT", "CANCEL", "TRANSITION", "MARK_COMPLETED", "REOPEN"];
38
+ /**
39
+ * One thing that can be done to an order, with the engine write behind it and
40
+ * what `allowed` asks of the caller:
41
+ *
42
+ * - `MODIFY`: the Edit Order flow, whose write is `modifyOrder`. That write
43
+ * runs only while the order is in the `Modifying` state, so the flow first
44
+ * moves the order there (`transitionOrderToState`; `Modifying` is never in
45
+ * `nextStates`), calls `modifyOrder`, and moves the order out again.
46
+ * `eligible` says the flow can OPEN from the order's present state, so an
47
+ * order already in `Modifying` answers `STATE`. Needs `UpdateOrder`.
48
+ * - `DELETE`: `deleteOrder`. Needs `DeleteOrder`. The write refuses what this
49
+ * action reports: an invoiced order (`INVOICE_LOCKED` here,
50
+ * `ORDER_INVOICE_LOCKED` from the write, for every caller) and an order a
51
+ * payment or a stock movement is recorded on (`HAS_RECORDS` here,
52
+ * `ORDER_HAS_RECORDS` from the write).
53
+ * - `RELEASE_ALLOCATION`: `releaseOrderAllocation`. Needs `UpdateOrder`. The
54
+ * write refuses an invoiced order for every caller (`INVOICE_LOCKED` here,
55
+ * `ORDER_INVOICE_LOCKED` from the write). A credential restricted to stock
56
+ * locations (an API token or app installation with `locationIds`) must also
57
+ * hold every location the order's reservation sits at; otherwise the release
58
+ * answers `LOCATION_NOT_ALLOWED` and this action `PERMISSION`.
59
+ * - `CANCEL`: `cancelOrder` for the whole order. Needs `UpdateOrder`.
60
+ * - `TRANSITION`: `transitionOrderToState` into one of `nextStates`. Needs
61
+ * `UpdateOrder`.
62
+ * - `MARK_COMPLETED`: `markOrderCompleted`. Needs `UpdateOrder`.
63
+ * - `REOPEN`: `reopenOrder`. Needs `UpdateOrder`.
64
+ * - `CORRECT_FULFILLMENT`: one of TWO writes, with different gates.
65
+ * - `updateFulfillmentLineQuantities` needs `UpdateOrder`, and corrects any
66
+ * fulfillment of the order on any store.
67
+ * - `correctFulfillmentQuantities` needs `UpdateFulfillment` or
68
+ * `UpdateOrder`, and works only on a store with the warehouse workspace
69
+ * (`WAREHOUSE_NOT_ENABLED` otherwise). For a caller without `UpdateOrder`
70
+ * it corrects only a fulfillment that ships from a warehouse the caller is
71
+ * assigned to (any other answers `LOCATION_OUT_OF_SCOPE`, a fulfillment
72
+ * with no recorded warehouse included), and it cannot lower the ordered
73
+ * quantity (`OFFICE_ONLY`).
74
+ *
75
+ * So `allowed` is true for a caller with `UpdateOrder` whenever the order is
76
+ * eligible. For a caller holding `UpdateFulfillment` without `UpdateOrder`
77
+ * it is true only on a store with the warehouse workspace, and only while
78
+ * at least one of THIS order's fulfillments ships from one of the caller's
79
+ * warehouses. That caller must call `correctFulfillmentQuantities`: the
80
+ * other write answers `FORBIDDEN`. An order with no fulfillment gives such a
81
+ * caller `PERMISSION`.
82
+ *
83
+ * It is an order-level answer. Whether a given fulfillment can still be
84
+ * corrected (Pending or Picking, or Packed with no carrier booking) is that
85
+ * fulfillment's own state, and is not answered here.
86
+ */
87
+ export type OrderStatusActionName = (typeof ORDER_STATUS_ACTIONS)[number];
88
+ /** Why an action is not allowed, in the order the engine lists them. */
89
+ export declare const ORDER_STATUS_REASON_CODES: readonly ["INVOICE_LOCKED", "COMPLETED", "CANCELLED", "STATE", "NOTHING_ALLOCATED", "HAS_RECORDS", "NOTHING_TO_CANCEL", "SHOPPER_CART", "UNITS_SHIPPED", "ACTIVE_FULFILLMENT", "PERMISSION"];
90
+ /**
91
+ * - `INVOICE_LOCKED`, `COMPLETED`, `CANCELLED`: the edit block.
92
+ * - `STATE`: the order's state does not allow it.
93
+ * - `NOTHING_ALLOCATED`: no line holds stock to release.
94
+ * - `HAS_RECORDS`: the order carries a payment or a stock movement, which a
95
+ * delete cannot remove. A draft, or a shopper's live cart, is cancelled
96
+ * instead: `CANCEL` is open on it.
97
+ * - `NOTHING_TO_CANCEL`: the order's lines hold no unit. Delete an empty
98
+ * draft instead.
99
+ * - `SHOPPER_CART`: a live cart, a shopper's or a till's open sale in the cart
100
+ * state. Its status is not moved, completed or reopened. `CANCEL` answers it
101
+ * too on a cart with no payment and no stock movement (delete it instead)
102
+ * and on a till's open sale (ended at the till).
103
+ * - `UNITS_SHIPPED`: a shipped or delivered fulfillment holds a line. Those
104
+ * units come back through a return.
105
+ * - `ACTIVE_FULFILLMENT`: a fulfillment not yet shipped holds a line. Detach
106
+ * the order from it or correct its quantities first.
107
+ * - `PERMISSION`: the order allows it and this caller may not. The only
108
+ * reason about the caller.
109
+ */
110
+ export type OrderStatusReasonCode = (typeof ORDER_STATUS_REASON_CODES)[number];
111
+ /** One thing that can be done to the order: see {@link OrderStatusActionName}. */
112
+ export interface OrderStatusAction {
113
+ action: OrderStatusActionName | (string & {});
114
+ /** The ORDER allows it, whoever asks. */
115
+ eligible: boolean;
116
+ /** This caller may do it now: eligible, and the caller may take a write that does it. */
117
+ allowed: boolean;
118
+ /** Null exactly when `allowed`. Otherwise why not: see {@link OrderStatusReasonCode}. */
119
+ reasonCode: OrderStatusReasonCode | (string & {}) | null;
120
+ }
121
+ /** An app provider the order runs without (see `admin.orders.providerFallbacks`). */
122
+ export interface OrderStatusProviderFallback {
123
+ /** `shipping.rates`, `tax.calculate`, and others over time. */
124
+ kind: string;
125
+ installationId: string;
126
+ reason: string;
127
+ /** ISO-8601 with offset. */
128
+ since: string;
129
+ }
130
+ export interface OrderStatusView {
131
+ orderId: string;
132
+ /** The engine state. */
133
+ state: string;
134
+ /**
135
+ * The four projected dimensions. `status` is `draft`, `open`, `completed` or
136
+ * `cancelled`. Each is null on an order that predates them, and for a moment
137
+ * on an order just created or changed: the engine writes them after the
138
+ * change that causes them.
139
+ */
140
+ lifecycle: {
141
+ status: string | null;
142
+ payment: string | null;
143
+ fulfillment: string | null;
144
+ return: string | null;
145
+ };
146
+ lock: {
147
+ locked: boolean;
148
+ reason: OrderLockReason | (string & {});
149
+ /**
150
+ * Set only when the reason is `INVOICE`: the live standard invoice, else a
151
+ * voided standard one (voiding does not unlock the order).
152
+ */
153
+ lockingInvoice: {
154
+ id: string;
155
+ number: string;
156
+ voided: boolean;
157
+ } | null;
158
+ };
159
+ /** Null when the order's content may change; the message is the one every edit is refused with. */
160
+ editBlock: {
161
+ code: OrderEditBlockCode | (string & {});
162
+ message: string;
163
+ } | null;
164
+ /** The Edit Order flow opens for this order. It may still be refused by `editBlock`. */
165
+ modifiable: boolean;
166
+ /** A deletable state on an order no invoice locks, carrying no payment and no stock movement. */
167
+ deletable: boolean;
168
+ /**
169
+ * The units `releaseOrderAllocation` would free now: the sum of the net
170
+ * reservations of the lines that still hold stock. Never negative. A line
171
+ * whose ledger nets below zero releases nothing and cancels nothing out, so
172
+ * this can be above zero while the lines' total is not.
173
+ */
174
+ releasableUnits: number;
175
+ /**
176
+ * A releasable state, no invoice lock, and `releasableUnits` above zero.
177
+ * The order's answer: the `RELEASE_ALLOCATION` action adds whether this
178
+ * caller may.
179
+ */
180
+ releaseAllowed: boolean;
181
+ allocationBadge: OrderAllocationBadge | (string & {});
182
+ /**
183
+ * The edit block on correcting a fulfillment's quantities. The
184
+ * `CORRECT_FULFILLMENT` action adds whether this caller may.
185
+ */
186
+ fulfillmentCorrection: {
187
+ blocked: boolean;
188
+ code: OrderEditBlockCode | (string & {}) | null;
189
+ };
190
+ /**
191
+ * The source platform already handed this imported order to its own
192
+ * fulfillment provider, and the store blocks shipping it again.
193
+ */
194
+ sourceFulfilled: boolean;
195
+ /** Set while the order is parked. */
196
+ park: {
197
+ reason: string | null;
198
+ } | null;
199
+ /**
200
+ * Set while a paid order is held for review: the code of the first refusal
201
+ * the order met after the buyer paid, and the slug of the app that refused
202
+ * it when an app did.
203
+ */
204
+ hold: {
205
+ forReview: string | null;
206
+ byApp: string | null;
207
+ } | null;
208
+ /** Empty when the order runs on every provider the store assigned. */
209
+ providerFallbacks: OrderStatusProviderFallback[];
210
+ /**
211
+ * The states a change-status menu lists, in the engine's order: without
212
+ * `Cancelled` and `Modifying` (their own actions), without the cart phase,
213
+ * and without the fulfillment states while the order has no fulfillment.
214
+ * Empty on a live cart.
215
+ */
216
+ nextStates: string[];
217
+ actions: OrderStatusAction[];
218
+ }
219
+ export declare const ORDER_STATUS_QUERY = "\n query OrderStatus($orderId: ID!) {\n orderStatus(orderId: $orderId) {\n orderId\n state\n lifecycle {\n status\n payment\n fulfillment\n return\n }\n lock {\n locked\n reason\n lockingInvoice {\n id\n number\n voided\n }\n }\n editBlock {\n code\n message\n }\n modifiable\n deletable\n releasableUnits\n releaseAllowed\n allocationBadge\n fulfillmentCorrection {\n blocked\n code\n }\n sourceFulfilled\n park {\n reason\n }\n hold {\n forReview\n byApp\n }\n providerFallbacks {\n kind\n installationId\n reason\n since\n }\n nextStates\n actions {\n action\n eligible\n allowed\n reasonCode\n }\n }\n }\n";
220
+ export interface OrderStatusModule {
221
+ /**
222
+ * Why the order is the way it is, and the actions open to this caller.
223
+ * Needs `ReadOrder`.
224
+ *
225
+ * An order this store does not hold is a `NotFoundError`
226
+ * (`ENTITY_NOT_FOUND`), the same as a missing id. Each action says whether
227
+ * the ORDER allows it (`eligible`) and whether THIS caller may take it now
228
+ * (`allowed`), so a head can show an action greyed out with its reason.
229
+ *
230
+ * Needs an engine that serves `orderStatus`; against an older one this call
231
+ * fails validation and nothing else does.
232
+ */
233
+ status(orderId: string, options?: Call): Promise<OrderStatusView>;
234
+ }
235
+ export declare function createOrderStatusModule(transport: Transport): OrderStatusModule;
@@ -0,0 +1,96 @@
1
+ /** Which of the lock's two writers locked the order. */
2
+ export const ORDER_LOCK_REASONS = ['NONE', 'INVOICE', 'IMPORTED', 'UNKNOWN'];
3
+ /** What to show for the order's stock-reservation expiry. */
4
+ export const ORDER_ALLOCATION_BADGES = ['HIDDEN', 'RESERVED', 'EXPIRED'];
5
+ /** Why an order's content may not change. */
6
+ export const ORDER_EDIT_BLOCK_CODES = ['INVOICE_LOCKED', 'COMPLETED', 'CANCELLED'];
7
+ /** The actions the engine answers for, in the order it lists them. */
8
+ export const ORDER_STATUS_ACTIONS = [
9
+ 'MODIFY',
10
+ 'DELETE',
11
+ 'RELEASE_ALLOCATION',
12
+ 'CORRECT_FULFILLMENT',
13
+ 'CANCEL',
14
+ 'TRANSITION',
15
+ 'MARK_COMPLETED',
16
+ 'REOPEN',
17
+ ];
18
+ /** Why an action is not allowed, in the order the engine lists them. */
19
+ export const ORDER_STATUS_REASON_CODES = [
20
+ 'INVOICE_LOCKED',
21
+ 'COMPLETED',
22
+ 'CANCELLED',
23
+ 'STATE',
24
+ 'NOTHING_ALLOCATED',
25
+ 'HAS_RECORDS',
26
+ 'NOTHING_TO_CANCEL',
27
+ 'SHOPPER_CART',
28
+ 'UNITS_SHIPPED',
29
+ 'ACTIVE_FULFILLMENT',
30
+ 'PERMISSION',
31
+ ];
32
+ export const ORDER_STATUS_QUERY = /* GraphQL */ `
33
+ query OrderStatus($orderId: ID!) {
34
+ orderStatus(orderId: $orderId) {
35
+ orderId
36
+ state
37
+ lifecycle {
38
+ status
39
+ payment
40
+ fulfillment
41
+ return
42
+ }
43
+ lock {
44
+ locked
45
+ reason
46
+ lockingInvoice {
47
+ id
48
+ number
49
+ voided
50
+ }
51
+ }
52
+ editBlock {
53
+ code
54
+ message
55
+ }
56
+ modifiable
57
+ deletable
58
+ releasableUnits
59
+ releaseAllowed
60
+ allocationBadge
61
+ fulfillmentCorrection {
62
+ blocked
63
+ code
64
+ }
65
+ sourceFulfilled
66
+ park {
67
+ reason
68
+ }
69
+ hold {
70
+ forReview
71
+ byApp
72
+ }
73
+ providerFallbacks {
74
+ kind
75
+ installationId
76
+ reason
77
+ since
78
+ }
79
+ nextStates
80
+ actions {
81
+ action
82
+ eligible
83
+ allowed
84
+ reasonCode
85
+ }
86
+ }
87
+ }
88
+ `;
89
+ export function createOrderStatusModule(transport) {
90
+ return {
91
+ async status(orderId, options) {
92
+ const data = await transport.graphql({ api: 'admin', query: ORDER_STATUS_QUERY, variables: { orderId } }, options);
93
+ return data.orderStatus;
94
+ },
95
+ };
96
+ }
@@ -29,8 +29,33 @@ export interface SurchargeInput {
29
29
  */
30
30
  taxDescription?: string | null;
31
31
  }
32
+ /**
33
+ * How money a change owes a PAID order's customer back is settled: `REFUND`
34
+ * to their payment, or `ACCOUNT_CREDIT` to their account as unapplied cash
35
+ * (`payments.accountCredit`).
36
+ */
37
+ export type OrderOverpaymentChoice = 'REFUND' | 'ACCOUNT_CREDIT';
38
+ /** Options for a surcharge removal. */
39
+ export interface SurchargeRemoveCall extends Call {
40
+ /**
41
+ * On an order the customer has PAID, how the money a lowered or removed
42
+ * charge owes them back is settled. Without it such a change is refused
43
+ * `ORDER_EDIT_OVERPAYMENT_CHOICE_REQUIRED` (→ `BusinessRuleError`), nothing
44
+ * written: ask the merchant (`preview` names the amount and which options
45
+ * are open), then send it again. Ignored when nothing is owed back.
46
+ *
47
+ * `REFUND` is refused `REFUND_EXCEEDS_PAYMENT` when no single payment can
48
+ * carry the amount, `ORDER_OVERPAYMENT_REFUND_ORDER_STATE` on an order
49
+ * in a state core does not refund, and `REFUND_METHOD_UNAVAILABLE`
50
+ * when that payment's method can no longer be reached; `ACCOUNT_CREDIT` by the account's own refusal
51
+ * (`AR_ACCOUNT_REQUIRED`, `AR_ACCOUNT_IN_ERP`, `AR_ORDER_ALREADY_INVOICED`,
52
+ * `AR_LEDGER_NOT_ENABLED`). A refund of unknown outcome on the order refuses
53
+ * either (`ORDER_OVERPAYMENT_REFUND_UNRECONCILED`) until it is reconciled.
54
+ */
55
+ overpayment?: OrderOverpaymentChoice;
56
+ }
32
57
  /** Options for a surcharge write. */
33
- export interface SurchargeCall extends Call {
58
+ export interface SurchargeCall extends SurchargeRemoveCall {
34
59
  /**
35
60
  * Price the surcharge from one of the store's tax classes (spec §8.6)
36
61
  * instead of from an explicit `taxRate`.
@@ -89,6 +114,43 @@ export interface SurchargedOrder {
89
114
  taxRate: number;
90
115
  }>;
91
116
  }
117
+ /** One surcharge change to preview: an add, an update, or a removal. */
118
+ export type SurchargeChange = {
119
+ input: SurchargeInput;
120
+ surchargeId?: never;
121
+ remove?: never;
122
+ } | {
123
+ surchargeId: string;
124
+ input: SurchargeInput;
125
+ remove?: never;
126
+ } | {
127
+ surchargeId: string;
128
+ remove: true;
129
+ input?: never;
130
+ };
131
+ /** Whether one way of settling an overpayment is open; when not, the refusal it would answer. */
132
+ export interface OverpaymentOption {
133
+ available: boolean;
134
+ code: string | null;
135
+ message: string | null;
136
+ }
137
+ /** What a surcharge change would do to an order's money. Nothing was saved. */
138
+ export interface SurchargeChangePreview {
139
+ currencyCode: string;
140
+ /** The order's billable total with tax, minor units, before and after the change. */
141
+ totalBefore: number;
142
+ totalAfter: number;
143
+ /**
144
+ * On a paid order: what the change would owe the customer back, and the
145
+ * ways to settle it. Null when it owes nothing.
146
+ */
147
+ overpayment: {
148
+ amount: number;
149
+ currencyCode: string;
150
+ refund: OverpaymentOption;
151
+ accountCredit: OverpaymentOption;
152
+ } | null;
153
+ }
92
154
  /**
93
155
  * Surcharges on a placed order.
94
156
  *
@@ -113,9 +175,20 @@ export interface SurchargesModule {
113
175
  */
114
176
  update(orderId: string, surchargeId: string, input: SurchargeInput, options?: SurchargeCall): Promise<SurchargedOrder>;
115
177
  /** Remove a surcharge entirely and re-total the order. */
116
- remove(orderId: string, surchargeId: string, options?: Call): Promise<SurchargedOrder>;
178
+ remove(orderId: string, surchargeId: string, options?: SurchargeRemoveCall): Promise<SurchargedOrder>;
179
+ /**
180
+ * What one change would do, before it is saved: run in a transaction the
181
+ * engine always rolls back, so nothing is written or announced. On a paid
182
+ * order it names what the customer would be owed back and which choices are
183
+ * open. Needs `UpdateOrder`, as the change itself does.
184
+ */
185
+ preview(orderId: string, change: SurchargeChange, options?: Pick<SurchargeCall, 'taxClass'> & Call): Promise<SurchargeChangePreview>;
117
186
  }
118
187
  export declare const ADD_ORDER_SURCHARGE_MUTATION = "\n mutation AddOrderSurcharge(\n $orderId: ID!\n $input: SurchargeInput!\n $taxClass: String\n $idempotencyKey: String\n ) {\n addOrderSurcharge(\n orderId: $orderId\n input: $input\n taxClass: $taxClass\n idempotencyKey: $idempotencyKey\n ) {\n \n id\n code\n currencyCode\n total\n totalWithTax\n surcharges {\n id\n description\n sku\n price\n priceWithTax\n taxRate\n }\n\n }\n }\n";
188
+ export declare const ADD_ORDER_SURCHARGE_WITH_OVERPAYMENT_MUTATION = "\n mutation AddOrderSurchargeWithOverpayment(\n $orderId: ID!\n $input: SurchargeInput!\n $taxClass: String\n $idempotencyKey: String\n $overpayment: OrderOverpaymentChoice\n ) {\n addOrderSurcharge(\n orderId: $orderId\n input: $input\n taxClass: $taxClass\n idempotencyKey: $idempotencyKey\n overpayment: $overpayment\n ) {\n \n id\n code\n currencyCode\n total\n totalWithTax\n surcharges {\n id\n description\n sku\n price\n priceWithTax\n taxRate\n }\n\n }\n }\n";
119
189
  export declare const UPDATE_ORDER_SURCHARGE_MUTATION = "\n mutation UpdateOrderSurcharge(\n $orderId: ID!\n $surchargeId: ID!\n $input: SurchargeInput!\n $taxClass: String\n $idempotencyKey: String\n ) {\n updateOrderSurcharge(\n orderId: $orderId\n surchargeId: $surchargeId\n input: $input\n taxClass: $taxClass\n idempotencyKey: $idempotencyKey\n ) {\n \n id\n code\n currencyCode\n total\n totalWithTax\n surcharges {\n id\n description\n sku\n price\n priceWithTax\n taxRate\n }\n\n }\n }\n";
190
+ export declare const UPDATE_ORDER_SURCHARGE_WITH_OVERPAYMENT_MUTATION = "\n mutation UpdateOrderSurchargeWithOverpayment(\n $orderId: ID!\n $surchargeId: ID!\n $input: SurchargeInput!\n $taxClass: String\n $idempotencyKey: String\n $overpayment: OrderOverpaymentChoice\n ) {\n updateOrderSurcharge(\n orderId: $orderId\n surchargeId: $surchargeId\n input: $input\n taxClass: $taxClass\n idempotencyKey: $idempotencyKey\n overpayment: $overpayment\n ) {\n \n id\n code\n currencyCode\n total\n totalWithTax\n surcharges {\n id\n description\n sku\n price\n priceWithTax\n taxRate\n }\n\n }\n }\n";
120
191
  export declare const REMOVE_ORDER_SURCHARGE_MUTATION = "\n mutation RemoveOrderSurcharge($orderId: ID!, $surchargeId: ID!, $idempotencyKey: String) {\n removeOrderSurcharge(\n orderId: $orderId\n surchargeId: $surchargeId\n idempotencyKey: $idempotencyKey\n ) {\n \n id\n code\n currencyCode\n total\n totalWithTax\n surcharges {\n id\n description\n sku\n price\n priceWithTax\n taxRate\n }\n\n }\n }\n";
192
+ export declare const REMOVE_ORDER_SURCHARGE_WITH_OVERPAYMENT_MUTATION = "\n mutation RemoveOrderSurchargeWithOverpayment(\n $orderId: ID!\n $surchargeId: ID!\n $idempotencyKey: String\n $overpayment: OrderOverpaymentChoice\n ) {\n removeOrderSurcharge(\n orderId: $orderId\n surchargeId: $surchargeId\n idempotencyKey: $idempotencyKey\n overpayment: $overpayment\n ) {\n \n id\n code\n currencyCode\n total\n totalWithTax\n surcharges {\n id\n description\n sku\n price\n priceWithTax\n taxRate\n }\n\n }\n }\n";
193
+ export declare const PREVIEW_ORDER_SURCHARGE_CHANGE_QUERY = "\n query PreviewOrderSurchargeChange($orderId: ID!, $change: OrderSurchargeChangeInput!) {\n previewOrderSurchargeChange(orderId: $orderId, change: $change) {\n currencyCode\n totalBefore\n totalAfter\n overpayment {\n amount\n currencyCode\n refund { available code message }\n accountCredit { available code message }\n }\n }\n }\n";
121
194
  export declare function createSurchargesModule(transport: Transport): SurchargesModule;
@@ -13,6 +13,9 @@ const SURCHARGED_ORDER_FIELDS = /* GraphQL */ `
13
13
  taxRate
14
14
  }
15
15
  `;
16
+ // Each write has two documents: without `overpayment` (as it always was), and with it. The
17
+ // variable is declared, and the argument named, only on a call that sends a choice, so an older
18
+ // engine without the argument still accepts every call that does not use it.
16
19
  export const ADD_ORDER_SURCHARGE_MUTATION = /* GraphQL */ `
17
20
  mutation AddOrderSurcharge(
18
21
  $orderId: ID!
@@ -30,6 +33,25 @@ export const ADD_ORDER_SURCHARGE_MUTATION = /* GraphQL */ `
30
33
  }
31
34
  }
32
35
  `;
36
+ export const ADD_ORDER_SURCHARGE_WITH_OVERPAYMENT_MUTATION = /* GraphQL */ `
37
+ mutation AddOrderSurchargeWithOverpayment(
38
+ $orderId: ID!
39
+ $input: SurchargeInput!
40
+ $taxClass: String
41
+ $idempotencyKey: String
42
+ $overpayment: OrderOverpaymentChoice
43
+ ) {
44
+ addOrderSurcharge(
45
+ orderId: $orderId
46
+ input: $input
47
+ taxClass: $taxClass
48
+ idempotencyKey: $idempotencyKey
49
+ overpayment: $overpayment
50
+ ) {
51
+ ${SURCHARGED_ORDER_FIELDS}
52
+ }
53
+ }
54
+ `;
33
55
  export const UPDATE_ORDER_SURCHARGE_MUTATION = /* GraphQL */ `
34
56
  mutation UpdateOrderSurcharge(
35
57
  $orderId: ID!
@@ -49,6 +71,27 @@ export const UPDATE_ORDER_SURCHARGE_MUTATION = /* GraphQL */ `
49
71
  }
50
72
  }
51
73
  `;
74
+ export const UPDATE_ORDER_SURCHARGE_WITH_OVERPAYMENT_MUTATION = /* GraphQL */ `
75
+ mutation UpdateOrderSurchargeWithOverpayment(
76
+ $orderId: ID!
77
+ $surchargeId: ID!
78
+ $input: SurchargeInput!
79
+ $taxClass: String
80
+ $idempotencyKey: String
81
+ $overpayment: OrderOverpaymentChoice
82
+ ) {
83
+ updateOrderSurcharge(
84
+ orderId: $orderId
85
+ surchargeId: $surchargeId
86
+ input: $input
87
+ taxClass: $taxClass
88
+ idempotencyKey: $idempotencyKey
89
+ overpayment: $overpayment
90
+ ) {
91
+ ${SURCHARGED_ORDER_FIELDS}
92
+ }
93
+ }
94
+ `;
52
95
  export const REMOVE_ORDER_SURCHARGE_MUTATION = /* GraphQL */ `
53
96
  mutation RemoveOrderSurcharge($orderId: ID!, $surchargeId: ID!, $idempotencyKey: String) {
54
97
  removeOrderSurcharge(
@@ -60,6 +103,44 @@ export const REMOVE_ORDER_SURCHARGE_MUTATION = /* GraphQL */ `
60
103
  }
61
104
  }
62
105
  `;
106
+ export const REMOVE_ORDER_SURCHARGE_WITH_OVERPAYMENT_MUTATION = /* GraphQL */ `
107
+ mutation RemoveOrderSurchargeWithOverpayment(
108
+ $orderId: ID!
109
+ $surchargeId: ID!
110
+ $idempotencyKey: String
111
+ $overpayment: OrderOverpaymentChoice
112
+ ) {
113
+ removeOrderSurcharge(
114
+ orderId: $orderId
115
+ surchargeId: $surchargeId
116
+ idempotencyKey: $idempotencyKey
117
+ overpayment: $overpayment
118
+ ) {
119
+ ${SURCHARGED_ORDER_FIELDS}
120
+ }
121
+ }
122
+ `;
123
+ const OVERPAYMENT_OPTION_FIELDS = 'available code message';
124
+ export const PREVIEW_ORDER_SURCHARGE_CHANGE_QUERY = /* GraphQL */ `
125
+ query PreviewOrderSurchargeChange($orderId: ID!, $change: OrderSurchargeChangeInput!) {
126
+ previewOrderSurchargeChange(orderId: $orderId, change: $change) {
127
+ currencyCode
128
+ totalBefore
129
+ totalAfter
130
+ overpayment {
131
+ amount
132
+ currencyCode
133
+ refund { ${OVERPAYMENT_OPTION_FIELDS} }
134
+ accountCredit { ${OVERPAYMENT_OPTION_FIELDS} }
135
+ }
136
+ }
137
+ }
138
+ `;
139
+ /** The choice as a variable, or `undefined` so it never reaches the wire as null. */
140
+ function overpaymentVariable(options) {
141
+ const value = options?.overpayment;
142
+ return value === 'REFUND' || value === 'ACCOUNT_CREDIT' ? value : undefined;
143
+ }
63
144
  /**
64
145
  * `undefined` rather than `null` for an absent tax class: a variable explicitly
65
146
  * set to null is still a value the engine reads, and this argument's whole
@@ -74,12 +155,15 @@ export function createSurchargesModule(transport) {
74
155
  async add(orderId, input, options) {
75
156
  const data = await transport.graphql({
76
157
  api: 'admin',
77
- query: ADD_ORDER_SURCHARGE_MUTATION,
158
+ query: overpaymentVariable(options) === undefined
159
+ ? ADD_ORDER_SURCHARGE_MUTATION
160
+ : ADD_ORDER_SURCHARGE_WITH_OVERPAYMENT_MUTATION,
78
161
  variables: {
79
162
  orderId,
80
163
  input,
81
164
  taxClass: taxClassVariable(options),
82
165
  idempotencyKey: options?.idempotencyKey,
166
+ overpayment: overpaymentVariable(options),
83
167
  },
84
168
  }, options);
85
169
  return data.addOrderSurcharge;
@@ -87,13 +171,16 @@ export function createSurchargesModule(transport) {
87
171
  async update(orderId, surchargeId, input, options) {
88
172
  const data = await transport.graphql({
89
173
  api: 'admin',
90
- query: UPDATE_ORDER_SURCHARGE_MUTATION,
174
+ query: overpaymentVariable(options) === undefined
175
+ ? UPDATE_ORDER_SURCHARGE_MUTATION
176
+ : UPDATE_ORDER_SURCHARGE_WITH_OVERPAYMENT_MUTATION,
91
177
  variables: {
92
178
  orderId,
93
179
  surchargeId,
94
180
  input,
95
181
  taxClass: taxClassVariable(options),
96
182
  idempotencyKey: options?.idempotencyKey,
183
+ overpayment: overpaymentVariable(options),
97
184
  },
98
185
  }, options);
99
186
  return data.updateOrderSurcharge;
@@ -101,10 +188,29 @@ export function createSurchargesModule(transport) {
101
188
  async remove(orderId, surchargeId, options) {
102
189
  const data = await transport.graphql({
103
190
  api: 'admin',
104
- query: REMOVE_ORDER_SURCHARGE_MUTATION,
105
- variables: { orderId, surchargeId, idempotencyKey: options?.idempotencyKey },
191
+ query: overpaymentVariable(options) === undefined
192
+ ? REMOVE_ORDER_SURCHARGE_MUTATION
193
+ : REMOVE_ORDER_SURCHARGE_WITH_OVERPAYMENT_MUTATION,
194
+ variables: {
195
+ orderId,
196
+ surchargeId,
197
+ idempotencyKey: options?.idempotencyKey,
198
+ overpayment: overpaymentVariable(options),
199
+ },
106
200
  }, options);
107
201
  return data.removeOrderSurcharge;
108
202
  },
203
+ async preview(orderId, change, options) {
204
+ const taxClass = taxClassVariable(options);
205
+ const data = await transport.graphql({
206
+ api: 'admin',
207
+ query: PREVIEW_ORDER_SURCHARGE_CHANGE_QUERY,
208
+ variables: {
209
+ orderId,
210
+ change: taxClass === undefined ? change : { ...change, taxClass },
211
+ },
212
+ }, options);
213
+ return data.previewOrderSurchargeChange;
214
+ },
109
215
  };
110
216
  }