@sixtyninecommerce/admin 0.10.0 → 0.11.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.
- package/README.md +4347 -171
- package/dist/catalog/assets.d.ts +120 -8
- package/dist/catalog/assets.js +98 -12
- package/dist/catalog/collections.d.ts +279 -14
- package/dist/catalog/collections.js +246 -15
- package/dist/catalog/index.d.ts +9 -2
- package/dist/catalog/index.js +4 -0
- package/dist/catalog/products.d.ts +159 -19
- package/dist/catalog/products.js +88 -13
- package/dist/catalog/properties.d.ts +102 -14
- package/dist/catalog/properties.js +13 -0
- package/dist/catalog/recommendations.d.ts +261 -0
- package/dist/catalog/recommendations.js +145 -0
- package/dist/catalog/reviews.d.ts +368 -0
- package/dist/catalog/reviews.js +318 -0
- package/dist/catalog/types.d.ts +17 -1
- package/dist/catalog/types.js +10 -0
- package/dist/catalog/variant-find.d.ts +136 -0
- package/dist/catalog/variant-find.js +239 -0
- package/dist/catalog/variants.d.ts +233 -26
- package/dist/catalog/variants.js +125 -7
- package/dist/catalog/visibility.d.ts +20 -5
- package/dist/catalog/visibility.js +19 -1
- package/dist/client.d.ts +95 -9
- package/dist/client.js +35 -7
- package/dist/content/assets.d.ts +286 -0
- package/dist/content/assets.js +181 -0
- package/dist/content/items.d.ts +269 -0
- package/dist/content/items.js +170 -0
- package/dist/content/types.d.ts +282 -0
- package/dist/content/types.js +100 -0
- package/dist/customers/age-verification.d.ts +66 -0
- package/dist/customers/age-verification.js +79 -0
- package/dist/customers/credit.d.ts +263 -0
- package/dist/customers/credit.js +244 -0
- package/dist/customers/delivery-preferences.d.ts +120 -0
- package/dist/customers/delivery-preferences.js +97 -0
- package/dist/customers/groups.d.ts +207 -0
- package/dist/customers/groups.js +438 -0
- package/dist/customers/index.d.ts +447 -37
- package/dist/customers/index.js +313 -40
- package/dist/customers/invitation-status.d.ts +57 -0
- package/dist/customers/invitation-status.js +21 -0
- package/dist/customers/notes.d.ts +67 -0
- package/dist/customers/notes.js +51 -0
- package/dist/customers/notification-recipients.d.ts +97 -0
- package/dist/customers/notification-recipients.js +84 -0
- package/dist/customers/saved-lists.d.ts +42 -0
- package/dist/customers/saved-lists.js +61 -0
- package/dist/customers/vat.d.ts +83 -0
- package/dist/customers/vat.js +46 -0
- package/dist/customers/wire.d.ts +20 -0
- package/dist/customers/wire.js +35 -0
- package/dist/documents/ar.d.ts +307 -0
- package/dist/documents/ar.js +254 -0
- package/dist/documents/index.d.ts +731 -21
- package/dist/documents/index.js +436 -24
- package/dist/documents/pdf.d.ts +2 -0
- package/dist/documents/pdf.js +11 -0
- package/dist/fulfillments/create.d.ts +167 -0
- package/dist/fulfillments/create.js +216 -0
- package/dist/fulfillments/index.d.ts +44 -10
- package/dist/fulfillments/index.js +11 -2
- package/dist/fulfillments/payment-policy.d.ts +64 -0
- package/dist/fulfillments/payment-policy.js +140 -0
- package/dist/fulfillments/warehouse.d.ts +724 -0
- package/dist/fulfillments/warehouse.js +914 -0
- package/dist/geo/index.d.ts +119 -0
- package/dist/geo/index.js +107 -0
- package/dist/index.d.ts +123 -35
- package/dist/index.js +45 -12
- package/dist/integrations/afas-actions.d.ts +234 -0
- package/dist/integrations/afas-actions.js +310 -0
- package/dist/integrations/afas-types.d.ts +483 -0
- package/dist/integrations/afas-types.js +5 -0
- package/dist/integrations/afas.d.ts +234 -0
- package/dist/integrations/afas.js +290 -0
- package/dist/integrations/connections.d.ts +103 -0
- package/dist/integrations/connections.js +55 -0
- package/dist/integrations/esp.d.ts +313 -0
- package/dist/integrations/esp.js +169 -0
- package/dist/integrations/exact-online-types.d.ts +423 -0
- package/dist/integrations/exact-online-types.js +6 -0
- package/dist/integrations/exact-online.d.ts +248 -0
- package/dist/integrations/exact-online.js +376 -0
- package/dist/integrations/index.d.ts +29 -3
- package/dist/integrations/index.js +18 -3
- package/dist/integrations/pipeline-keys.d.ts +13 -0
- package/dist/integrations/pipeline-keys.js +22 -0
- package/dist/integrations/pipelines.d.ts +15 -14
- package/dist/integrations/pipelines.js +6 -22
- package/dist/integrations/types.d.ts +146 -0
- package/dist/locations/index.d.ts +66 -0
- package/dist/locations/index.js +31 -0
- package/dist/meta/index.d.ts +162 -0
- package/dist/orders/cancel-with-money.d.ts +227 -0
- package/dist/orders/cancel-with-money.js +153 -0
- package/dist/orders/commit-edit.d.ts +7 -1
- package/dist/orders/commit-edit.js +5 -1
- package/dist/orders/drafts.d.ts +800 -0
- package/dist/orders/drafts.js +771 -0
- package/dist/orders/fields.d.ts +245 -0
- package/dist/orders/fields.js +188 -0
- package/dist/orders/get.d.ts +29 -19
- package/dist/orders/get.js +17 -8
- package/dist/orders/index.d.ts +49 -9
- package/dist/orders/index.js +22 -2
- package/dist/orders/lifecycle.d.ts +128 -0
- package/dist/orders/lifecycle.js +158 -0
- package/dist/orders/line-price-preview.d.ts +7 -2
- package/dist/orders/list.d.ts +222 -0
- package/dist/orders/list.js +377 -0
- package/dist/orders/manual-pricing.d.ts +5 -0
- package/dist/orders/order-entry.d.ts +20 -7
- package/dist/orders/plan-edit.d.ts +1 -1
- package/dist/orders/plan-edit.js +4 -1
- package/dist/orders/settings.d.ts +201 -0
- package/dist/orders/settings.js +325 -0
- package/dist/orders/status.d.ts +159 -13
- package/dist/orders/status.js +21 -0
- package/dist/orders/surcharges.d.ts +8 -1
- package/dist/orders/surcharges.js +3 -2
- package/dist/payments/account-credit.d.ts +30 -0
- package/dist/payments/account-credit.js +19 -0
- package/dist/payments/ar.d.ts +292 -0
- package/dist/payments/ar.js +223 -0
- package/dist/payments/connected-account.d.ts +47 -0
- package/dist/payments/connected-account.js +61 -0
- package/dist/payments/credit-noted-fields.d.ts +12 -0
- package/dist/payments/credit-noted-fields.js +37 -0
- package/dist/payments/index.d.ts +257 -11
- package/dist/payments/index.js +131 -1
- package/dist/payments/methods.d.ts +303 -8
- package/dist/payments/methods.js +337 -7
- package/dist/payments/mollie-methods.d.ts +159 -0
- package/dist/payments/mollie-methods.js +141 -0
- package/dist/payments/payment-links.d.ts +180 -0
- package/dist/payments/payment-links.js +97 -0
- package/dist/payments/provider-keys.d.ts +150 -0
- package/dist/payments/provider-keys.js +118 -0
- package/dist/payments/providers.d.ts +86 -11
- package/dist/payments/providers.js +29 -0
- package/dist/payments/requests.d.ts +144 -0
- package/dist/payments/requests.js +92 -0
- package/dist/payments/store-credit-fields.d.ts +15 -0
- package/dist/payments/store-credit-fields.js +51 -0
- package/dist/pickups/index.d.ts +104 -0
- package/dist/pickups/index.js +105 -0
- package/dist/platform/channels.d.ts +132 -0
- package/dist/platform/channels.js +128 -0
- package/dist/platform/geo.d.ts +123 -0
- package/dist/platform/geo.js +144 -0
- package/dist/platform/tax.d.ts +154 -0
- package/dist/platform/tax.js +139 -0
- package/dist/pos/anomalies.d.ts +158 -0
- package/dist/pos/anomalies.js +64 -0
- package/dist/pos/assisted-selling.d.ts +79 -0
- package/dist/pos/assisted-selling.js +38 -0
- package/dist/pos/exchanges.d.ts +103 -0
- package/dist/pos/exchanges.js +22 -0
- package/dist/pos/gift-cards.d.ts +135 -0
- package/dist/pos/gift-cards.js +47 -0
- package/dist/pos/index.d.ts +2125 -32
- package/dist/pos/index.js +742 -4
- package/dist/pos/no-receipt.d.ts +94 -0
- package/dist/pos/no-receipt.js +25 -0
- package/dist/pos/offline-sales.d.ts +187 -0
- package/dist/pos/offline-sales.js +116 -0
- package/dist/pos/pay-by-link.d.ts +143 -0
- package/dist/pos/pay-by-link.js +57 -0
- package/dist/pos/quick-keys.d.ts +103 -0
- package/dist/pos/quick-keys.js +45 -0
- package/dist/pos/reports.d.ts +360 -0
- package/dist/pos/reports.js +62 -0
- package/dist/pos/returns.d.ts +217 -0
- package/dist/pos/returns.js +53 -0
- package/dist/pricing/bulk-coupons.d.ts +139 -0
- package/dist/pricing/bulk-coupons.js +112 -0
- package/dist/pricing/index.d.ts +174 -4
- package/dist/pricing/index.js +174 -1
- package/dist/pricing/price-lists.d.ts +604 -0
- package/dist/pricing/price-lists.js +600 -0
- package/dist/purchasing/alerts.d.ts +89 -0
- package/dist/purchasing/alerts.js +62 -0
- package/dist/purchasing/cost.d.ts +110 -0
- package/dist/purchasing/cost.js +86 -0
- package/dist/purchasing/index.d.ts +36 -0
- package/dist/purchasing/index.js +16 -0
- package/dist/purchasing/purchase-orders.d.ts +548 -0
- package/dist/purchasing/purchase-orders.js +491 -0
- package/dist/purchasing/replenishment.d.ts +281 -0
- package/dist/purchasing/replenishment.js +240 -0
- package/dist/purchasing/settings.d.ts +152 -0
- package/dist/purchasing/settings.js +181 -0
- package/dist/purchasing/suppliers.d.ts +476 -0
- package/dist/purchasing/suppliers.js +438 -0
- package/dist/quotes/index.d.ts +501 -0
- package/dist/quotes/index.js +439 -0
- package/dist/reports/index.d.ts +71 -8
- package/dist/reports/index.js +74 -11
- package/dist/returns/index.d.ts +614 -21
- package/dist/returns/index.js +695 -11
- package/dist/search/index.d.ts +76 -1
- package/dist/search/index.js +63 -0
- package/dist/shipping/definitions.d.ts +29 -0
- package/dist/shipping/definitions.js +47 -0
- package/dist/shipping/fulfillment-profiles.d.ts +174 -0
- package/dist/shipping/fulfillment-profiles.js +104 -0
- package/dist/shipping/hendriks.d.ts +97 -0
- package/dist/shipping/hendriks.js +50 -0
- package/dist/shipping/index.d.ts +48 -0
- package/dist/shipping/index.js +25 -0
- package/dist/shipping/methods.d.ts +198 -0
- package/dist/shipping/methods.js +240 -0
- package/dist/shipping/myparcel.d.ts +254 -0
- package/dist/shipping/myparcel.js +178 -0
- package/dist/shipping/parcel-count-suggestion.d.ts +2 -0
- package/dist/shipping/parcel-rule.d.ts +6 -5
- package/dist/shipping/parcel-rule.js +21 -23
- package/dist/shipping/rate-tables.d.ts +179 -0
- package/dist/shipping/rate-tables.js +184 -0
- package/dist/stock/index.d.ts +10 -3
- package/dist/stock/index.js +3 -0
- package/dist/stock/locations.d.ts +144 -0
- package/dist/stock/locations.js +168 -0
- package/dist/stock/transfers.d.ts +216 -43
- package/dist/stock/transfers.js +140 -13
- package/dist/stored-value/index.d.ts +214 -4
- package/dist/stored-value/index.js +152 -0
- package/dist/subscriptions/index.d.ts +682 -0
- package/dist/subscriptions/index.js +815 -0
- package/dist/tax/index.d.ts +76 -1
- package/dist/tax/index.js +50 -0
- package/dist/tenant/email-style.d.ts +102 -0
- package/dist/tenant/email-style.js +72 -0
- package/dist/tenant/email-templates.d.ts +66 -0
- package/dist/tenant/email-templates.js +54 -0
- package/dist/tenant/notifications.d.ts +23 -17
- package/dist/tenant/settings-sources.d.ts +1 -1
- package/dist/tenant/time-zone.d.ts +17 -0
- package/dist/tenant/time-zone.js +11 -0
- package/dist/types.d.ts +50 -3
- package/dist/users/index.d.ts +3 -0
- package/dist/users/index.js +2 -0
- package/dist/users/warehouses.d.ts +50 -0
- package/dist/users/warehouses.js +51 -0
- package/package.json +2 -2
|
@@ -0,0 +1,771 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `admin.orders.drafts`: staff build an order by hand, one step at a time (headless spec §9.2
|
|
3
|
+
* `orders` "draft-order editing"; plan W10-21).
|
|
4
|
+
*
|
|
5
|
+
* A draft is an order in the `Draft` state that only staff can see. Each method here changes
|
|
6
|
+
* one thing about it and answers the draft as it then stands; `cloneFrom` fills it from an
|
|
7
|
+
* earlier order, and `place` turns it into a placed order with its payment recorded.
|
|
8
|
+
*
|
|
9
|
+
* `orders.createOrRecover` is the other way to make an order: ONE keyed call that composes a
|
|
10
|
+
* whole order an external system already decided (its reference, its lines, its prices). This
|
|
11
|
+
* module is the builder a person drives: a line can carry a manual price with a reason, a variant
|
|
12
|
+
* can be on two lines, and the customer, shipping and minimum are settled step by step.
|
|
13
|
+
*
|
|
14
|
+
* **Only drafts.** Every write refuses an order that is not a `Draft` with `ORDER_NOT_DRAFT`
|
|
15
|
+
* (`BusinessRuleError`, 422): a shopper's cart, a till sale or a placed order is changed through
|
|
16
|
+
* its own door (`orders.planEdit` / `orders.commitEdit` for a placed one). A till's held sale is
|
|
17
|
+
* refused `POS_CART_HELD`. An order of another store, or none, is core's `ENTITY_NOT_FOUND`
|
|
18
|
+
* (`NotFoundError`, 404).
|
|
19
|
+
*
|
|
20
|
+
* **Only `place` records money.** A draft bills nobody, so the editing methods take no
|
|
21
|
+
* idempotency key and repeating one repeats the edit (adding a line twice adds it twice). Three
|
|
22
|
+
* methods are keyed: `place` (it records the order's payment), `cloneFrom` (it replaces the
|
|
23
|
+
* draft's contents) and `saveAddresses` (it can add an entry to the customer's address book). A
|
|
24
|
+
* repeat of one of them under the same key answers the first call's result.
|
|
25
|
+
*/
|
|
26
|
+
import { BusinessRuleError, errorFromErrorResult, isErrorResult, idempotencyKey as mintIdempotencyKey, UpstreamError, ValidationError, } from '@sixtyninecommerce/core';
|
|
27
|
+
import { assertDeleted, fieldOf } from '../catalog/types.js';
|
|
28
|
+
import { redactionWatcher } from '../customer-data-redaction.js';
|
|
29
|
+
/**
|
|
30
|
+
* How long `cloneFrom` waits for its answer. The engine copies an order in ONE call and one
|
|
31
|
+
* transaction, adding its lines one by one, so the call lasts as long as the whole copy; the
|
|
32
|
+
* default 15 s aborted the copy of a large order the engine went on to finish. Measured on a dev
|
|
33
|
+
* stack under heavy load (5-minute load average 34): 164 lines copied in 47 s, about 0.3 s a
|
|
34
|
+
* line, so the default ran out past some 50 lines and this covers some 300. Well under the
|
|
35
|
+
* engine's five-minute idempotency claim, so a repeat under the same key after this runs out
|
|
36
|
+
* meets the first attempt's claim (`IDEMPOTENCY_IN_PROGRESS`) instead of starting a second copy.
|
|
37
|
+
*/
|
|
38
|
+
export const DRAFT_CLONE_TIMEOUT_MS = 90_000;
|
|
39
|
+
/**
|
|
40
|
+
* `addLine` and `adjustLine` asked for more than the stock allows. The engine took what it could
|
|
41
|
+
* and answers the draft as it now stands, so this is a partial success to show, not a refusal to
|
|
42
|
+
* retry: `INSUFFICIENT_STOCK` (`BusinessRuleError`, 422). Read the line's quantity off `order`.
|
|
43
|
+
*/
|
|
44
|
+
export class DraftInsufficientStockError extends BusinessRuleError {
|
|
45
|
+
/**
|
|
46
|
+
* The engine's own figure, which means a different thing per method:
|
|
47
|
+
* - `addLine`: how many units the add could TAKE. When the add merged into a line the draft
|
|
48
|
+
* already had, the line holds its old quantity plus this. `0` means nothing was added.
|
|
49
|
+
* - `adjustLine`: the quantity the line holds now.
|
|
50
|
+
*/
|
|
51
|
+
quantityAvailable;
|
|
52
|
+
/** The draft as the engine left it. */
|
|
53
|
+
order;
|
|
54
|
+
constructor(init, quantityAvailable, order) {
|
|
55
|
+
super({ ...init, status: 422 });
|
|
56
|
+
this.quantityAvailable = quantityAvailable;
|
|
57
|
+
this.order = order;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const ORDER_ADDRESS_FIELDS = /* GraphQL */ `
|
|
61
|
+
fullName
|
|
62
|
+
company
|
|
63
|
+
streetLine1
|
|
64
|
+
streetLine2
|
|
65
|
+
city
|
|
66
|
+
province
|
|
67
|
+
postalCode
|
|
68
|
+
country
|
|
69
|
+
countryCode
|
|
70
|
+
phoneNumber
|
|
71
|
+
`;
|
|
72
|
+
export const DRAFT_ORDER_FIELDS = /* GraphQL */ `
|
|
73
|
+
id
|
|
74
|
+
code
|
|
75
|
+
state
|
|
76
|
+
currencyCode
|
|
77
|
+
subTotal
|
|
78
|
+
subTotalWithTax
|
|
79
|
+
shipping
|
|
80
|
+
shippingWithTax
|
|
81
|
+
total
|
|
82
|
+
totalWithTax
|
|
83
|
+
customer {
|
|
84
|
+
id
|
|
85
|
+
firstName
|
|
86
|
+
lastName
|
|
87
|
+
emailAddress
|
|
88
|
+
}
|
|
89
|
+
lines {
|
|
90
|
+
id
|
|
91
|
+
quantity
|
|
92
|
+
unitPrice
|
|
93
|
+
unitPriceWithTax
|
|
94
|
+
listPriceIncludesTax
|
|
95
|
+
linePrice
|
|
96
|
+
linePriceWithTax
|
|
97
|
+
productVariant {
|
|
98
|
+
id
|
|
99
|
+
name
|
|
100
|
+
sku
|
|
101
|
+
}
|
|
102
|
+
customFields {
|
|
103
|
+
unitPriceOverride
|
|
104
|
+
priceOverrideReason
|
|
105
|
+
unitPriceImported
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
shippingLines {
|
|
109
|
+
id
|
|
110
|
+
price
|
|
111
|
+
priceWithTax
|
|
112
|
+
shippingMethod {
|
|
113
|
+
id
|
|
114
|
+
code
|
|
115
|
+
name
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
couponCodes
|
|
119
|
+
shippingAddress {
|
|
120
|
+
${ORDER_ADDRESS_FIELDS}
|
|
121
|
+
}
|
|
122
|
+
billingAddress {
|
|
123
|
+
${ORDER_ADDRESS_FIELDS}
|
|
124
|
+
}
|
|
125
|
+
customFields {
|
|
126
|
+
paymentConditionCode
|
|
127
|
+
paymentTermsDays
|
|
128
|
+
poNumber
|
|
129
|
+
orderNotes
|
|
130
|
+
requestedDeliveryDate
|
|
131
|
+
customerShippingAddressId
|
|
132
|
+
customerBillingAddressId
|
|
133
|
+
shippingAddressIsTemporary
|
|
134
|
+
billingAddressIsTemporary
|
|
135
|
+
}
|
|
136
|
+
`;
|
|
137
|
+
/** The refusals a line door answers, each with the field that carries its reason. */
|
|
138
|
+
const LINE_REFUSALS = /* GraphQL */ `
|
|
139
|
+
... on OrderInterceptorError {
|
|
140
|
+
interceptorError
|
|
141
|
+
}
|
|
142
|
+
... on InsufficientStockError {
|
|
143
|
+
quantityAvailable
|
|
144
|
+
order {
|
|
145
|
+
${DRAFT_ORDER_FIELDS}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
... on ErrorResult {
|
|
149
|
+
errorCode
|
|
150
|
+
message
|
|
151
|
+
}
|
|
152
|
+
`;
|
|
153
|
+
export const CREATE_DRAFT_ORDER_MUTATION = /* GraphQL */ `
|
|
154
|
+
mutation DraftsCreate {
|
|
155
|
+
createDraftOrder {
|
|
156
|
+
${DRAFT_ORDER_FIELDS}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
`;
|
|
160
|
+
export const DELETE_DRAFT_ORDER_MUTATION = /* GraphQL */ `
|
|
161
|
+
mutation DraftsDelete($orderId: ID!) {
|
|
162
|
+
deleteDraftOrder(orderId: $orderId) {
|
|
163
|
+
result
|
|
164
|
+
message
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
`;
|
|
168
|
+
export const SET_DRAFT_CUSTOMER_MUTATION = /* GraphQL */ `
|
|
169
|
+
mutation DraftsSetCustomer($orderId: ID!, $customerId: ID!) {
|
|
170
|
+
setCustomerForDraftOrder(orderId: $orderId, customerId: $customerId) {
|
|
171
|
+
... on Order {
|
|
172
|
+
${DRAFT_ORDER_FIELDS}
|
|
173
|
+
}
|
|
174
|
+
... on ErrorResult {
|
|
175
|
+
errorCode
|
|
176
|
+
message
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
`;
|
|
181
|
+
export const ADD_DRAFT_LINE_MUTATION = /* GraphQL */ `
|
|
182
|
+
mutation DraftsAddLine($orderId: ID!, $input: AddItemToDraftOrderInput!) {
|
|
183
|
+
addItemToDraftOrder(orderId: $orderId, input: $input) {
|
|
184
|
+
... on Order {
|
|
185
|
+
${DRAFT_ORDER_FIELDS}
|
|
186
|
+
}
|
|
187
|
+
${LINE_REFUSALS}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
`;
|
|
191
|
+
export const ADJUST_DRAFT_LINE_MUTATION = /* GraphQL */ `
|
|
192
|
+
mutation DraftsAdjustLine($orderId: ID!, $input: AdjustDraftOrderLineInput!) {
|
|
193
|
+
adjustDraftOrderLine(orderId: $orderId, input: $input) {
|
|
194
|
+
... on Order {
|
|
195
|
+
${DRAFT_ORDER_FIELDS}
|
|
196
|
+
}
|
|
197
|
+
${LINE_REFUSALS}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
`;
|
|
201
|
+
export const REMOVE_DRAFT_LINE_MUTATION = /* GraphQL */ `
|
|
202
|
+
mutation DraftsRemoveLine($orderId: ID!, $orderLineId: ID!) {
|
|
203
|
+
removeDraftOrderLine(orderId: $orderId, orderLineId: $orderLineId) {
|
|
204
|
+
... on Order {
|
|
205
|
+
${DRAFT_ORDER_FIELDS}
|
|
206
|
+
}
|
|
207
|
+
... on OrderInterceptorError {
|
|
208
|
+
interceptorError
|
|
209
|
+
}
|
|
210
|
+
... on ErrorResult {
|
|
211
|
+
errorCode
|
|
212
|
+
message
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
`;
|
|
217
|
+
export const SET_DRAFT_FIELDS_MUTATION = /* GraphQL */ `
|
|
218
|
+
mutation DraftsSetFields($orderId: ID!, $input: UpdateOrderInput!) {
|
|
219
|
+
setDraftOrderCustomFields(orderId: $orderId, input: $input) {
|
|
220
|
+
${DRAFT_ORDER_FIELDS}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
`;
|
|
224
|
+
const ADDRESS_DEFAULT_FIELDS = /* GraphQL */ `
|
|
225
|
+
source
|
|
226
|
+
customerAddressId
|
|
227
|
+
address {
|
|
228
|
+
fullName
|
|
229
|
+
company
|
|
230
|
+
streetLine1
|
|
231
|
+
streetLine2
|
|
232
|
+
city
|
|
233
|
+
province
|
|
234
|
+
postalCode
|
|
235
|
+
countryCode
|
|
236
|
+
phoneNumber
|
|
237
|
+
}
|
|
238
|
+
temporary
|
|
239
|
+
temporaryInferred
|
|
240
|
+
`;
|
|
241
|
+
export const DRAFT_ADDRESS_DEFAULTS_QUERY = /* GraphQL */ `
|
|
242
|
+
query DraftsAddressDefaults($orderId: ID!) {
|
|
243
|
+
draftOrderAddressDefaults(orderId: $orderId) {
|
|
244
|
+
shipping {
|
|
245
|
+
${ADDRESS_DEFAULT_FIELDS}
|
|
246
|
+
}
|
|
247
|
+
billing {
|
|
248
|
+
${ADDRESS_DEFAULT_FIELDS}
|
|
249
|
+
}
|
|
250
|
+
billingSameAsShipping
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
`;
|
|
254
|
+
export const SAVE_DRAFT_ADDRESSES_MUTATION = /* GraphQL */ `
|
|
255
|
+
mutation DraftsSaveAddresses(
|
|
256
|
+
$orderId: ID!
|
|
257
|
+
$input: SaveDraftOrderAddressesInput!
|
|
258
|
+
$idempotencyKey: String
|
|
259
|
+
) {
|
|
260
|
+
saveDraftOrderAddresses(orderId: $orderId, input: $input, idempotencyKey: $idempotencyKey) {
|
|
261
|
+
order {
|
|
262
|
+
${DRAFT_ORDER_FIELDS}
|
|
263
|
+
}
|
|
264
|
+
createdAddressIds
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
`;
|
|
268
|
+
export const SET_DRAFT_SHIPPING_ADDRESS_MUTATION = /* GraphQL */ `
|
|
269
|
+
mutation DraftsSetShippingAddress($orderId: ID!, $input: CreateAddressInput!) {
|
|
270
|
+
setDraftOrderShippingAddress(orderId: $orderId, input: $input) {
|
|
271
|
+
${DRAFT_ORDER_FIELDS}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
`;
|
|
275
|
+
export const SET_DRAFT_BILLING_ADDRESS_MUTATION = /* GraphQL */ `
|
|
276
|
+
mutation DraftsSetBillingAddress($orderId: ID!, $input: CreateAddressInput!) {
|
|
277
|
+
setDraftOrderBillingAddress(orderId: $orderId, input: $input) {
|
|
278
|
+
${DRAFT_ORDER_FIELDS}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
`;
|
|
282
|
+
export const UNSET_DRAFT_SHIPPING_ADDRESS_MUTATION = /* GraphQL */ `
|
|
283
|
+
mutation DraftsUnsetShippingAddress($orderId: ID!) {
|
|
284
|
+
unsetDraftOrderShippingAddress(orderId: $orderId) {
|
|
285
|
+
${DRAFT_ORDER_FIELDS}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
`;
|
|
289
|
+
export const UNSET_DRAFT_BILLING_ADDRESS_MUTATION = /* GraphQL */ `
|
|
290
|
+
mutation DraftsUnsetBillingAddress($orderId: ID!) {
|
|
291
|
+
unsetDraftOrderBillingAddress(orderId: $orderId) {
|
|
292
|
+
${DRAFT_ORDER_FIELDS}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
`;
|
|
296
|
+
export const DRAFT_SHIPPING_QUOTES_QUERY = /* GraphQL */ `
|
|
297
|
+
query DraftsShippingQuotes($orderId: ID!) {
|
|
298
|
+
eligibleShippingMethodsForDraftOrder(orderId: $orderId) {
|
|
299
|
+
id
|
|
300
|
+
code
|
|
301
|
+
name
|
|
302
|
+
description
|
|
303
|
+
price
|
|
304
|
+
priceWithTax
|
|
305
|
+
metadata
|
|
306
|
+
isPreferred
|
|
307
|
+
isDeliveryTermsEligible
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
`;
|
|
311
|
+
const SHIPPING_RESULT = /* GraphQL */ `
|
|
312
|
+
... on Order {
|
|
313
|
+
${DRAFT_ORDER_FIELDS}
|
|
314
|
+
}
|
|
315
|
+
... on ErrorResult {
|
|
316
|
+
errorCode
|
|
317
|
+
message
|
|
318
|
+
}
|
|
319
|
+
`;
|
|
320
|
+
export const SELECT_DRAFT_DELIVERY_MUTATION = /* GraphQL */ `
|
|
321
|
+
mutation DraftsSelectDelivery($orderId: ID!, $shippingMethodId: ID!) {
|
|
322
|
+
selectDraftOrderDeliveryMethod(orderId: $orderId, shippingMethodId: $shippingMethodId) {
|
|
323
|
+
${SHIPPING_RESULT}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
`;
|
|
327
|
+
export const APPLY_PREFERRED_DRAFT_DELIVERY_MUTATION = /* GraphQL */ `
|
|
328
|
+
mutation DraftsApplyPreferredDelivery($orderId: ID!) {
|
|
329
|
+
applyPreferredDeliveryMethodToDraftOrder(orderId: $orderId) {
|
|
330
|
+
${SHIPPING_RESULT}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
`;
|
|
334
|
+
export const SET_DRAFT_SHIPPING_METHOD_MUTATION = /* GraphQL */ `
|
|
335
|
+
mutation DraftsSetShippingMethod($orderId: ID!, $shippingMethodId: ID!) {
|
|
336
|
+
setDraftOrderShippingMethod(orderId: $orderId, shippingMethodId: $shippingMethodId) {
|
|
337
|
+
${SHIPPING_RESULT}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
`;
|
|
341
|
+
export const REPRICE_DRAFT_MUTATION = /* GraphQL */ `
|
|
342
|
+
mutation DraftsReprice($orderId: ID!) {
|
|
343
|
+
repriceDraftOrder(orderId: $orderId) {
|
|
344
|
+
success
|
|
345
|
+
changed
|
|
346
|
+
linesRepriced
|
|
347
|
+
error
|
|
348
|
+
errorCode
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
`;
|
|
352
|
+
/**
|
|
353
|
+
* The same mutation as an engine released before 2026-10-10 serves it, with no `errorCode`.
|
|
354
|
+
* Used only when that engine refuses the current document at validation.
|
|
355
|
+
*/
|
|
356
|
+
export const REPRICE_DRAFT_LEGACY_MUTATION = /* GraphQL */ `
|
|
357
|
+
mutation DraftsRepriceLegacy($orderId: ID!) {
|
|
358
|
+
repriceDraftOrder(orderId: $orderId) {
|
|
359
|
+
success
|
|
360
|
+
changed
|
|
361
|
+
linesRepriced
|
|
362
|
+
error
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
`;
|
|
366
|
+
export const DRAFT_MINIMUM_STATUS_QUERY = /* GraphQL */ `
|
|
367
|
+
query DraftsMinimumStatus($orderId: ID!) {
|
|
368
|
+
draftOrderMinimumStatus(orderId: $orderId) {
|
|
369
|
+
belowMinimum
|
|
370
|
+
message
|
|
371
|
+
overridden
|
|
372
|
+
overriddenAt
|
|
373
|
+
overriddenBy
|
|
374
|
+
reason
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
`;
|
|
378
|
+
export const OVERRIDE_DRAFT_MINIMUM_MUTATION = /* GraphQL */ `
|
|
379
|
+
mutation DraftsMinimumOverride($orderId: ID!, $reason: String) {
|
|
380
|
+
overrideDraftOrderMinimum(orderId: $orderId, reason: $reason) {
|
|
381
|
+
id
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
`;
|
|
385
|
+
export const CLEAR_DRAFT_MINIMUM_MUTATION = /* GraphQL */ `
|
|
386
|
+
mutation DraftsMinimumClear($orderId: ID!) {
|
|
387
|
+
clearDraftOrderMinimumOverride(orderId: $orderId) {
|
|
388
|
+
id
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
`;
|
|
392
|
+
export const APPLY_DRAFT_COUPON_MUTATION = /* GraphQL */ `
|
|
393
|
+
mutation DraftsApplyCoupon($orderId: ID!, $couponCode: String!) {
|
|
394
|
+
applyCouponCodeToDraftOrder(orderId: $orderId, couponCode: $couponCode) {
|
|
395
|
+
... on Order {
|
|
396
|
+
${DRAFT_ORDER_FIELDS}
|
|
397
|
+
}
|
|
398
|
+
... on ErrorResult {
|
|
399
|
+
errorCode
|
|
400
|
+
message
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
`;
|
|
405
|
+
export const REMOVE_DRAFT_COUPON_MUTATION = /* GraphQL */ `
|
|
406
|
+
mutation DraftsRemoveCoupon($orderId: ID!, $couponCode: String!) {
|
|
407
|
+
removeCouponCodeFromDraftOrder(orderId: $orderId, couponCode: $couponCode) {
|
|
408
|
+
${DRAFT_ORDER_FIELDS}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
`;
|
|
412
|
+
export const PLACE_DRAFT_MUTATION = /* GraphQL */ `
|
|
413
|
+
mutation DraftsPlace($input: PlaceDraftOrderInput!, $idempotencyKey: String!) {
|
|
414
|
+
placeDraftOrder(input: $input, idempotencyKey: $idempotencyKey) {
|
|
415
|
+
id
|
|
416
|
+
code
|
|
417
|
+
state
|
|
418
|
+
currencyCode
|
|
419
|
+
totalWithTax
|
|
420
|
+
payments {
|
|
421
|
+
id
|
|
422
|
+
state
|
|
423
|
+
method
|
|
424
|
+
amount
|
|
425
|
+
transactionId
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
`;
|
|
430
|
+
export const CLONE_DRAFT_MUTATION = /* GraphQL */ `
|
|
431
|
+
mutation DraftsCloneFrom(
|
|
432
|
+
$orderId: ID!
|
|
433
|
+
$sourceOrderId: ID!
|
|
434
|
+
$reasonCode: String
|
|
435
|
+
$idempotencyKey: String!
|
|
436
|
+
) {
|
|
437
|
+
cloneOrderToDraftOrder(
|
|
438
|
+
orderId: $orderId
|
|
439
|
+
sourceOrderId: $sourceOrderId
|
|
440
|
+
reasonCode: $reasonCode
|
|
441
|
+
idempotencyKey: $idempotencyKey
|
|
442
|
+
) {
|
|
443
|
+
order {
|
|
444
|
+
${DRAFT_ORDER_FIELDS}
|
|
445
|
+
}
|
|
446
|
+
skipped {
|
|
447
|
+
sourceLineId
|
|
448
|
+
reason
|
|
449
|
+
message
|
|
450
|
+
}
|
|
451
|
+
clamped {
|
|
452
|
+
sourceLineId
|
|
453
|
+
quantityAdded
|
|
454
|
+
}
|
|
455
|
+
shippingMethodApplied
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
`;
|
|
459
|
+
/**
|
|
460
|
+
* The draft, or the refusal as its error. An interceptor's `message` is core's template ("An
|
|
461
|
+
* error occurred"); its reason is in `interceptorError`. A stock clamp keeps the line, so it
|
|
462
|
+
* carries the quantity and the draft.
|
|
463
|
+
*/
|
|
464
|
+
function draftOrThrow(answer, field) {
|
|
465
|
+
if (answer == null)
|
|
466
|
+
throw unexpected(field);
|
|
467
|
+
if (!isErrorResult(answer))
|
|
468
|
+
return answer;
|
|
469
|
+
if (answer.errorCode === 'INSUFFICIENT_STOCK_ERROR' && answer.order) {
|
|
470
|
+
// Core's own sentence: its figure is the units an add could take, or an adjusted line's new
|
|
471
|
+
// quantity, so a sentence composed here would misstate one of the two.
|
|
472
|
+
throw new DraftInsufficientStockError({
|
|
473
|
+
code: 'INSUFFICIENT_STOCK',
|
|
474
|
+
message: answer.message,
|
|
475
|
+
service: 'vendure',
|
|
476
|
+
details: [{ field: 'quantity', code: 'INSUFFICIENT_STOCK', message: answer.message }],
|
|
477
|
+
}, answer.quantityAvailable ?? 0, answer.order);
|
|
478
|
+
}
|
|
479
|
+
const reason = typeof answer.interceptorError === 'string' ? answer.interceptorError.trim() : '';
|
|
480
|
+
throw errorFromErrorResult(reason === '' ? answer : { ...answer, message: reason });
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* A request the engine refused before running anything: Apollo answers a document that fails
|
|
484
|
+
* validation with HTTP 400, which `@sixtyninecommerce/core` reads as `ValidationError`
|
|
485
|
+
* `BAD_REQUEST` (it reads the GraphQL error document only on a 5xx); an answer at 200 would carry
|
|
486
|
+
* `GRAPHQL_VALIDATION_FAILED`. An error a resolver threw never carries either code.
|
|
487
|
+
*/
|
|
488
|
+
function rejectedBeforeRunning(error) {
|
|
489
|
+
return (error instanceof ValidationError &&
|
|
490
|
+
(error.code === 'BAD_REQUEST' || error.code === 'GRAPHQL_VALIDATION_FAILED'));
|
|
491
|
+
}
|
|
492
|
+
function unexpected(field) {
|
|
493
|
+
return new UpstreamError({
|
|
494
|
+
code: 'UNEXPECTED_RESPONSE',
|
|
495
|
+
message: `The engine answered without "${field}".`,
|
|
496
|
+
status: 502,
|
|
497
|
+
service: 'vendure',
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
/** The key a caller retries under, on an error of a call whose key it did not choose. */
|
|
501
|
+
function withAttemptKey(error, key) {
|
|
502
|
+
if (error !== null && typeof error === 'object' && !('idempotencyKey' in error)) {
|
|
503
|
+
Object.defineProperty(error, 'idempotencyKey', { value: key, enumerable: true });
|
|
504
|
+
}
|
|
505
|
+
return error;
|
|
506
|
+
}
|
|
507
|
+
/** Line custom fields, from the three-state inputs: an absent key stays absent. */
|
|
508
|
+
function lineCustomFields(input) {
|
|
509
|
+
const fields = {};
|
|
510
|
+
for (const key of ['unitPriceOverride', 'priceOverrideReason', 'unitPriceImported']) {
|
|
511
|
+
if (input[key] !== undefined)
|
|
512
|
+
fields[key] = input[key];
|
|
513
|
+
}
|
|
514
|
+
return Object.keys(fields).length > 0 ? fields : undefined;
|
|
515
|
+
}
|
|
516
|
+
const ADDRESS_INPUT_FIELDS = [
|
|
517
|
+
'fullName',
|
|
518
|
+
'company',
|
|
519
|
+
'streetLine1',
|
|
520
|
+
'streetLine2',
|
|
521
|
+
'city',
|
|
522
|
+
'province',
|
|
523
|
+
'postalCode',
|
|
524
|
+
'countryCode',
|
|
525
|
+
'phoneNumber',
|
|
526
|
+
];
|
|
527
|
+
/** The typed address as the engine takes it: its own nine fields, an unset one left out. */
|
|
528
|
+
function addressInput(address) {
|
|
529
|
+
const input = {};
|
|
530
|
+
for (const key of ADDRESS_INPUT_FIELDS) {
|
|
531
|
+
const value = address[key];
|
|
532
|
+
if (value != null)
|
|
533
|
+
input[key] = value;
|
|
534
|
+
}
|
|
535
|
+
return input;
|
|
536
|
+
}
|
|
537
|
+
/** One side as the engine takes it: the saved address's id, or the typed address. */
|
|
538
|
+
function addressSide(side) {
|
|
539
|
+
if ('customerAddressId' in side)
|
|
540
|
+
return { customerAddressId: side.customerAddressId };
|
|
541
|
+
return {
|
|
542
|
+
address: addressInput(side.address),
|
|
543
|
+
...(side.temporary === true ? { temporary: true } : {}),
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
function lineInput(input, base) {
|
|
547
|
+
const customFields = lineCustomFields(input);
|
|
548
|
+
return {
|
|
549
|
+
...base,
|
|
550
|
+
...(customFields ? { customFields } : {}),
|
|
551
|
+
// Only when chosen: an engine without the discount-reason layer refuses the field.
|
|
552
|
+
...(input.reasonCode ? { reasonCode: input.reasonCode } : {}),
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
export function createOrderDraftsModule(transport, getModule) {
|
|
556
|
+
/** One draft-answering call: the redaction stamp, and the union read through `draftOrThrow`. */
|
|
557
|
+
async function draftCall(document, field, variables, options) {
|
|
558
|
+
const redaction = redactionWatcher();
|
|
559
|
+
const data = await transport.graphql({ api: 'admin', query: document, variables, onExtensions: redaction.onExtensions }, options);
|
|
560
|
+
try {
|
|
561
|
+
return redaction.mark(draftOrThrow(data?.[field], field));
|
|
562
|
+
}
|
|
563
|
+
catch (error) {
|
|
564
|
+
if (error instanceof DraftInsufficientStockError)
|
|
565
|
+
redaction.mark(error.order);
|
|
566
|
+
throw error;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
const minimum = {
|
|
570
|
+
async status(orderId, options) {
|
|
571
|
+
return fieldOf(transport, DRAFT_MINIMUM_STATUS_QUERY, 'draftOrderMinimumStatus', { orderId }, options);
|
|
572
|
+
},
|
|
573
|
+
async override(orderId, options) {
|
|
574
|
+
const reason = options?.reason?.trim();
|
|
575
|
+
await fieldOf(transport, OVERRIDE_DRAFT_MINIMUM_MUTATION, 'overrideDraftOrderMinimum', { orderId, reason: reason ? reason : null }, options);
|
|
576
|
+
},
|
|
577
|
+
async clear(orderId, options) {
|
|
578
|
+
await fieldOf(transport, CLEAR_DRAFT_MINIMUM_MUTATION, 'clearDraftOrderMinimumOverride', { orderId }, options);
|
|
579
|
+
},
|
|
580
|
+
};
|
|
581
|
+
const coupons = {
|
|
582
|
+
apply(orderId, couponCode, options) {
|
|
583
|
+
return draftCall(APPLY_DRAFT_COUPON_MUTATION, 'applyCouponCodeToDraftOrder', { orderId, couponCode }, options);
|
|
584
|
+
},
|
|
585
|
+
remove(orderId, couponCode, options) {
|
|
586
|
+
return draftCall(REMOVE_DRAFT_COUPON_MUTATION, 'removeCouponCodeFromDraftOrder', { orderId, couponCode }, options);
|
|
587
|
+
},
|
|
588
|
+
};
|
|
589
|
+
return {
|
|
590
|
+
create(options) {
|
|
591
|
+
return draftCall(CREATE_DRAFT_ORDER_MUTATION, 'createDraftOrder', {}, options);
|
|
592
|
+
},
|
|
593
|
+
get: getModule.get,
|
|
594
|
+
async delete(orderId, options) {
|
|
595
|
+
assertDeleted('ORDER_NOT_DELETED', [
|
|
596
|
+
await fieldOf(transport, DELETE_DRAFT_ORDER_MUTATION, 'deleteDraftOrder', { orderId }, options),
|
|
597
|
+
]);
|
|
598
|
+
},
|
|
599
|
+
setCustomer(orderId, customerId, options) {
|
|
600
|
+
return draftCall(SET_DRAFT_CUSTOMER_MUTATION, 'setCustomerForDraftOrder', { orderId, customerId }, options);
|
|
601
|
+
},
|
|
602
|
+
addLine(orderId, input, options) {
|
|
603
|
+
return draftCall(ADD_DRAFT_LINE_MUTATION, 'addItemToDraftOrder', {
|
|
604
|
+
orderId,
|
|
605
|
+
input: lineInput(input, {
|
|
606
|
+
productVariantId: input.productVariantId,
|
|
607
|
+
quantity: input.quantity,
|
|
608
|
+
}),
|
|
609
|
+
}, options);
|
|
610
|
+
},
|
|
611
|
+
adjustLine(orderId, lineId, input, options) {
|
|
612
|
+
return draftCall(ADJUST_DRAFT_LINE_MUTATION, 'adjustDraftOrderLine', { orderId, input: lineInput(input, { orderLineId: lineId, quantity: input.quantity }) }, options);
|
|
613
|
+
},
|
|
614
|
+
removeLine(orderId, lineId, options) {
|
|
615
|
+
return draftCall(REMOVE_DRAFT_LINE_MUTATION, 'removeDraftOrderLine', { orderId, orderLineId: lineId }, options);
|
|
616
|
+
},
|
|
617
|
+
setFields(orderId, fields, options) {
|
|
618
|
+
const customFields = {};
|
|
619
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
620
|
+
if (value !== undefined)
|
|
621
|
+
customFields[key] = value;
|
|
622
|
+
}
|
|
623
|
+
return draftCall(SET_DRAFT_FIELDS_MUTATION, 'setDraftOrderCustomFields',
|
|
624
|
+
// `UpdateOrderInput.id` is required by the schema even though the door names the order.
|
|
625
|
+
{ orderId, input: { id: orderId, customFields } }, options);
|
|
626
|
+
},
|
|
627
|
+
async addressDefaults(orderId, options) {
|
|
628
|
+
const redaction = redactionWatcher();
|
|
629
|
+
const data = await transport.graphql({
|
|
630
|
+
api: 'admin',
|
|
631
|
+
query: DRAFT_ADDRESS_DEFAULTS_QUERY,
|
|
632
|
+
variables: { orderId },
|
|
633
|
+
onExtensions: redaction.onExtensions,
|
|
634
|
+
}, options);
|
|
635
|
+
if (data?.draftOrderAddressDefaults == null)
|
|
636
|
+
throw unexpected('draftOrderAddressDefaults');
|
|
637
|
+
return redaction.mark(data.draftOrderAddressDefaults);
|
|
638
|
+
},
|
|
639
|
+
async saveAddresses(orderId, input, options) {
|
|
640
|
+
const redaction = redactionWatcher();
|
|
641
|
+
const data = await transport.graphql({
|
|
642
|
+
api: 'admin',
|
|
643
|
+
query: SAVE_DRAFT_ADDRESSES_MUTATION,
|
|
644
|
+
variables: {
|
|
645
|
+
orderId,
|
|
646
|
+
input: {
|
|
647
|
+
shipping: addressSide(input.shipping),
|
|
648
|
+
...('billing' in input
|
|
649
|
+
? { billing: addressSide(input.billing) }
|
|
650
|
+
: { billingSameAsShipping: true }),
|
|
651
|
+
},
|
|
652
|
+
idempotencyKey: options?.idempotencyKey,
|
|
653
|
+
},
|
|
654
|
+
onExtensions: redaction.onExtensions,
|
|
655
|
+
}, options);
|
|
656
|
+
const saved = data?.saveDraftOrderAddresses;
|
|
657
|
+
if (saved?.order == null)
|
|
658
|
+
throw unexpected('saveDraftOrderAddresses');
|
|
659
|
+
redaction.mark(saved.order);
|
|
660
|
+
return saved;
|
|
661
|
+
},
|
|
662
|
+
setShippingAddress(orderId, address, options) {
|
|
663
|
+
return draftCall(SET_DRAFT_SHIPPING_ADDRESS_MUTATION, 'setDraftOrderShippingAddress', { orderId, input: addressInput(address) }, options);
|
|
664
|
+
},
|
|
665
|
+
setBillingAddress(orderId, address, options) {
|
|
666
|
+
return draftCall(SET_DRAFT_BILLING_ADDRESS_MUTATION, 'setDraftOrderBillingAddress', { orderId, input: addressInput(address) }, options);
|
|
667
|
+
},
|
|
668
|
+
unsetShippingAddress(orderId, options) {
|
|
669
|
+
return draftCall(UNSET_DRAFT_SHIPPING_ADDRESS_MUTATION, 'unsetDraftOrderShippingAddress', { orderId }, options);
|
|
670
|
+
},
|
|
671
|
+
unsetBillingAddress(orderId, options) {
|
|
672
|
+
return draftCall(UNSET_DRAFT_BILLING_ADDRESS_MUTATION, 'unsetDraftOrderBillingAddress', { orderId }, options);
|
|
673
|
+
},
|
|
674
|
+
async shippingQuotes(orderId, options) {
|
|
675
|
+
return fieldOf(transport, DRAFT_SHIPPING_QUOTES_QUERY, 'eligibleShippingMethodsForDraftOrder', { orderId }, options);
|
|
676
|
+
},
|
|
677
|
+
selectDelivery(orderId, shippingMethodId, options) {
|
|
678
|
+
return draftCall(SELECT_DRAFT_DELIVERY_MUTATION, 'selectDraftOrderDeliveryMethod', { orderId, shippingMethodId }, options);
|
|
679
|
+
},
|
|
680
|
+
applyPreferredDelivery(orderId, options) {
|
|
681
|
+
return draftCall(APPLY_PREFERRED_DRAFT_DELIVERY_MUTATION, 'applyPreferredDeliveryMethodToDraftOrder', { orderId }, options);
|
|
682
|
+
},
|
|
683
|
+
setShippingMethod(orderId, shippingMethodId, options) {
|
|
684
|
+
return draftCall(SET_DRAFT_SHIPPING_METHOD_MUTATION, 'setDraftOrderShippingMethod', { orderId, shippingMethodId }, options);
|
|
685
|
+
},
|
|
686
|
+
async reprice(orderId, options) {
|
|
687
|
+
let answer;
|
|
688
|
+
try {
|
|
689
|
+
answer = await fieldOf(transport, REPRICE_DRAFT_MUTATION, 'repriceDraftOrder', { orderId }, options);
|
|
690
|
+
}
|
|
691
|
+
catch (error) {
|
|
692
|
+
// An engine before `errorCode` refuses the whole document at validation, before the
|
|
693
|
+
// resolver runs, so asking again with the older document cannot re-price twice. A
|
|
694
|
+
// dashboard deployed ahead of its engine would otherwise fail every draft it opens.
|
|
695
|
+
if (!rejectedBeforeRunning(error))
|
|
696
|
+
throw error;
|
|
697
|
+
answer = await fieldOf(transport, REPRICE_DRAFT_LEGACY_MUTATION, 'repriceDraftOrder', { orderId }, options);
|
|
698
|
+
}
|
|
699
|
+
if (!answer.success) {
|
|
700
|
+
throw errorFromErrorResult({
|
|
701
|
+
errorCode: answer.errorCode ?? 'DRAFT_REPRICE_REFUSED',
|
|
702
|
+
message: answer.error ?? 'The draft could not be re-priced.',
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
return { changed: answer.changed, linesRepriced: answer.linesRepriced };
|
|
706
|
+
},
|
|
707
|
+
async cloneFrom(orderId, sourceOrderId, options) {
|
|
708
|
+
const key = options?.idempotencyKey ?? mintIdempotencyKey();
|
|
709
|
+
const reasonCode = options?.reasonCode?.trim();
|
|
710
|
+
const redaction = redactionWatcher();
|
|
711
|
+
try {
|
|
712
|
+
const data = await transport.graphql({
|
|
713
|
+
api: 'admin',
|
|
714
|
+
query: CLONE_DRAFT_MUTATION,
|
|
715
|
+
variables: {
|
|
716
|
+
orderId,
|
|
717
|
+
sourceOrderId,
|
|
718
|
+
// Only when chosen: a blank reason is none.
|
|
719
|
+
reasonCode: reasonCode ? reasonCode : null,
|
|
720
|
+
idempotencyKey: key,
|
|
721
|
+
},
|
|
722
|
+
onExtensions: redaction.onExtensions,
|
|
723
|
+
}, { timeoutMs: DRAFT_CLONE_TIMEOUT_MS, ...options, idempotencyKey: key });
|
|
724
|
+
const cloned = data?.cloneOrderToDraftOrder;
|
|
725
|
+
if (cloned?.order == null)
|
|
726
|
+
throw unexpected('cloneOrderToDraftOrder');
|
|
727
|
+
redaction.mark(cloned.order);
|
|
728
|
+
return { ...cloned, idempotencyKey: key };
|
|
729
|
+
}
|
|
730
|
+
catch (error) {
|
|
731
|
+
throw withAttemptKey(error, key);
|
|
732
|
+
}
|
|
733
|
+
},
|
|
734
|
+
async place(input, options) {
|
|
735
|
+
const key = options?.idempotencyKey ?? mintIdempotencyKey();
|
|
736
|
+
const { payment } = input;
|
|
737
|
+
try {
|
|
738
|
+
const data = await transport.graphql({
|
|
739
|
+
api: 'admin',
|
|
740
|
+
query: PLACE_DRAFT_MUTATION,
|
|
741
|
+
variables: {
|
|
742
|
+
input: {
|
|
743
|
+
orderId: input.orderId,
|
|
744
|
+
// Three states: left out keeps the draft's terms, `null` clears the override.
|
|
745
|
+
...(input.paymentConditionCode !== undefined
|
|
746
|
+
? { paymentConditionCode: input.paymentConditionCode }
|
|
747
|
+
: {}),
|
|
748
|
+
payment: {
|
|
749
|
+
methodCode: payment.methodCode,
|
|
750
|
+
received: payment.received,
|
|
751
|
+
...(payment.transactionId != null
|
|
752
|
+
? { transactionId: payment.transactionId }
|
|
753
|
+
: {}),
|
|
754
|
+
...(payment.metadata != null ? { metadata: payment.metadata } : {}),
|
|
755
|
+
},
|
|
756
|
+
},
|
|
757
|
+
idempotencyKey: key,
|
|
758
|
+
},
|
|
759
|
+
}, { ...options, idempotencyKey: key });
|
|
760
|
+
if (data?.placeDraftOrder == null)
|
|
761
|
+
throw unexpected('placeDraftOrder');
|
|
762
|
+
return { ...data.placeDraftOrder, idempotencyKey: key };
|
|
763
|
+
}
|
|
764
|
+
catch (error) {
|
|
765
|
+
throw withAttemptKey(error, key);
|
|
766
|
+
}
|
|
767
|
+
},
|
|
768
|
+
minimum,
|
|
769
|
+
coupons,
|
|
770
|
+
};
|
|
771
|
+
}
|