@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.
Files changed (247) hide show
  1. package/README.md +4347 -171
  2. package/dist/catalog/assets.d.ts +120 -8
  3. package/dist/catalog/assets.js +98 -12
  4. package/dist/catalog/collections.d.ts +279 -14
  5. package/dist/catalog/collections.js +246 -15
  6. package/dist/catalog/index.d.ts +9 -2
  7. package/dist/catalog/index.js +4 -0
  8. package/dist/catalog/products.d.ts +159 -19
  9. package/dist/catalog/products.js +88 -13
  10. package/dist/catalog/properties.d.ts +102 -14
  11. package/dist/catalog/properties.js +13 -0
  12. package/dist/catalog/recommendations.d.ts +261 -0
  13. package/dist/catalog/recommendations.js +145 -0
  14. package/dist/catalog/reviews.d.ts +368 -0
  15. package/dist/catalog/reviews.js +318 -0
  16. package/dist/catalog/types.d.ts +17 -1
  17. package/dist/catalog/types.js +10 -0
  18. package/dist/catalog/variant-find.d.ts +136 -0
  19. package/dist/catalog/variant-find.js +239 -0
  20. package/dist/catalog/variants.d.ts +233 -26
  21. package/dist/catalog/variants.js +125 -7
  22. package/dist/catalog/visibility.d.ts +20 -5
  23. package/dist/catalog/visibility.js +19 -1
  24. package/dist/client.d.ts +95 -9
  25. package/dist/client.js +35 -7
  26. package/dist/content/assets.d.ts +286 -0
  27. package/dist/content/assets.js +181 -0
  28. package/dist/content/items.d.ts +269 -0
  29. package/dist/content/items.js +170 -0
  30. package/dist/content/types.d.ts +282 -0
  31. package/dist/content/types.js +100 -0
  32. package/dist/customers/age-verification.d.ts +66 -0
  33. package/dist/customers/age-verification.js +79 -0
  34. package/dist/customers/credit.d.ts +263 -0
  35. package/dist/customers/credit.js +244 -0
  36. package/dist/customers/delivery-preferences.d.ts +120 -0
  37. package/dist/customers/delivery-preferences.js +97 -0
  38. package/dist/customers/groups.d.ts +207 -0
  39. package/dist/customers/groups.js +438 -0
  40. package/dist/customers/index.d.ts +447 -37
  41. package/dist/customers/index.js +313 -40
  42. package/dist/customers/invitation-status.d.ts +57 -0
  43. package/dist/customers/invitation-status.js +21 -0
  44. package/dist/customers/notes.d.ts +67 -0
  45. package/dist/customers/notes.js +51 -0
  46. package/dist/customers/notification-recipients.d.ts +97 -0
  47. package/dist/customers/notification-recipients.js +84 -0
  48. package/dist/customers/saved-lists.d.ts +42 -0
  49. package/dist/customers/saved-lists.js +61 -0
  50. package/dist/customers/vat.d.ts +83 -0
  51. package/dist/customers/vat.js +46 -0
  52. package/dist/customers/wire.d.ts +20 -0
  53. package/dist/customers/wire.js +35 -0
  54. package/dist/documents/ar.d.ts +307 -0
  55. package/dist/documents/ar.js +254 -0
  56. package/dist/documents/index.d.ts +731 -21
  57. package/dist/documents/index.js +436 -24
  58. package/dist/documents/pdf.d.ts +2 -0
  59. package/dist/documents/pdf.js +11 -0
  60. package/dist/fulfillments/create.d.ts +167 -0
  61. package/dist/fulfillments/create.js +216 -0
  62. package/dist/fulfillments/index.d.ts +44 -10
  63. package/dist/fulfillments/index.js +11 -2
  64. package/dist/fulfillments/payment-policy.d.ts +64 -0
  65. package/dist/fulfillments/payment-policy.js +140 -0
  66. package/dist/fulfillments/warehouse.d.ts +724 -0
  67. package/dist/fulfillments/warehouse.js +914 -0
  68. package/dist/geo/index.d.ts +119 -0
  69. package/dist/geo/index.js +107 -0
  70. package/dist/index.d.ts +123 -35
  71. package/dist/index.js +45 -12
  72. package/dist/integrations/afas-actions.d.ts +234 -0
  73. package/dist/integrations/afas-actions.js +310 -0
  74. package/dist/integrations/afas-types.d.ts +483 -0
  75. package/dist/integrations/afas-types.js +5 -0
  76. package/dist/integrations/afas.d.ts +234 -0
  77. package/dist/integrations/afas.js +290 -0
  78. package/dist/integrations/connections.d.ts +103 -0
  79. package/dist/integrations/connections.js +55 -0
  80. package/dist/integrations/esp.d.ts +313 -0
  81. package/dist/integrations/esp.js +169 -0
  82. package/dist/integrations/exact-online-types.d.ts +423 -0
  83. package/dist/integrations/exact-online-types.js +6 -0
  84. package/dist/integrations/exact-online.d.ts +248 -0
  85. package/dist/integrations/exact-online.js +376 -0
  86. package/dist/integrations/index.d.ts +29 -3
  87. package/dist/integrations/index.js +18 -3
  88. package/dist/integrations/pipeline-keys.d.ts +13 -0
  89. package/dist/integrations/pipeline-keys.js +22 -0
  90. package/dist/integrations/pipelines.d.ts +15 -14
  91. package/dist/integrations/pipelines.js +6 -22
  92. package/dist/integrations/types.d.ts +146 -0
  93. package/dist/locations/index.d.ts +66 -0
  94. package/dist/locations/index.js +31 -0
  95. package/dist/meta/index.d.ts +162 -0
  96. package/dist/orders/cancel-with-money.d.ts +227 -0
  97. package/dist/orders/cancel-with-money.js +153 -0
  98. package/dist/orders/commit-edit.d.ts +7 -1
  99. package/dist/orders/commit-edit.js +5 -1
  100. package/dist/orders/drafts.d.ts +800 -0
  101. package/dist/orders/drafts.js +771 -0
  102. package/dist/orders/fields.d.ts +245 -0
  103. package/dist/orders/fields.js +188 -0
  104. package/dist/orders/get.d.ts +29 -19
  105. package/dist/orders/get.js +17 -8
  106. package/dist/orders/index.d.ts +49 -9
  107. package/dist/orders/index.js +22 -2
  108. package/dist/orders/lifecycle.d.ts +128 -0
  109. package/dist/orders/lifecycle.js +158 -0
  110. package/dist/orders/line-price-preview.d.ts +7 -2
  111. package/dist/orders/list.d.ts +222 -0
  112. package/dist/orders/list.js +377 -0
  113. package/dist/orders/manual-pricing.d.ts +5 -0
  114. package/dist/orders/order-entry.d.ts +20 -7
  115. package/dist/orders/plan-edit.d.ts +1 -1
  116. package/dist/orders/plan-edit.js +4 -1
  117. package/dist/orders/settings.d.ts +201 -0
  118. package/dist/orders/settings.js +325 -0
  119. package/dist/orders/status.d.ts +159 -13
  120. package/dist/orders/status.js +21 -0
  121. package/dist/orders/surcharges.d.ts +8 -1
  122. package/dist/orders/surcharges.js +3 -2
  123. package/dist/payments/account-credit.d.ts +30 -0
  124. package/dist/payments/account-credit.js +19 -0
  125. package/dist/payments/ar.d.ts +292 -0
  126. package/dist/payments/ar.js +223 -0
  127. package/dist/payments/connected-account.d.ts +47 -0
  128. package/dist/payments/connected-account.js +61 -0
  129. package/dist/payments/credit-noted-fields.d.ts +12 -0
  130. package/dist/payments/credit-noted-fields.js +37 -0
  131. package/dist/payments/index.d.ts +257 -11
  132. package/dist/payments/index.js +131 -1
  133. package/dist/payments/methods.d.ts +303 -8
  134. package/dist/payments/methods.js +337 -7
  135. package/dist/payments/mollie-methods.d.ts +159 -0
  136. package/dist/payments/mollie-methods.js +141 -0
  137. package/dist/payments/payment-links.d.ts +180 -0
  138. package/dist/payments/payment-links.js +97 -0
  139. package/dist/payments/provider-keys.d.ts +150 -0
  140. package/dist/payments/provider-keys.js +118 -0
  141. package/dist/payments/providers.d.ts +86 -11
  142. package/dist/payments/providers.js +29 -0
  143. package/dist/payments/requests.d.ts +144 -0
  144. package/dist/payments/requests.js +92 -0
  145. package/dist/payments/store-credit-fields.d.ts +15 -0
  146. package/dist/payments/store-credit-fields.js +51 -0
  147. package/dist/pickups/index.d.ts +104 -0
  148. package/dist/pickups/index.js +105 -0
  149. package/dist/platform/channels.d.ts +132 -0
  150. package/dist/platform/channels.js +128 -0
  151. package/dist/platform/geo.d.ts +123 -0
  152. package/dist/platform/geo.js +144 -0
  153. package/dist/platform/tax.d.ts +154 -0
  154. package/dist/platform/tax.js +139 -0
  155. package/dist/pos/anomalies.d.ts +158 -0
  156. package/dist/pos/anomalies.js +64 -0
  157. package/dist/pos/assisted-selling.d.ts +79 -0
  158. package/dist/pos/assisted-selling.js +38 -0
  159. package/dist/pos/exchanges.d.ts +103 -0
  160. package/dist/pos/exchanges.js +22 -0
  161. package/dist/pos/gift-cards.d.ts +135 -0
  162. package/dist/pos/gift-cards.js +47 -0
  163. package/dist/pos/index.d.ts +2125 -32
  164. package/dist/pos/index.js +742 -4
  165. package/dist/pos/no-receipt.d.ts +94 -0
  166. package/dist/pos/no-receipt.js +25 -0
  167. package/dist/pos/offline-sales.d.ts +187 -0
  168. package/dist/pos/offline-sales.js +116 -0
  169. package/dist/pos/pay-by-link.d.ts +143 -0
  170. package/dist/pos/pay-by-link.js +57 -0
  171. package/dist/pos/quick-keys.d.ts +103 -0
  172. package/dist/pos/quick-keys.js +45 -0
  173. package/dist/pos/reports.d.ts +360 -0
  174. package/dist/pos/reports.js +62 -0
  175. package/dist/pos/returns.d.ts +217 -0
  176. package/dist/pos/returns.js +53 -0
  177. package/dist/pricing/bulk-coupons.d.ts +139 -0
  178. package/dist/pricing/bulk-coupons.js +112 -0
  179. package/dist/pricing/index.d.ts +174 -4
  180. package/dist/pricing/index.js +174 -1
  181. package/dist/pricing/price-lists.d.ts +604 -0
  182. package/dist/pricing/price-lists.js +600 -0
  183. package/dist/purchasing/alerts.d.ts +89 -0
  184. package/dist/purchasing/alerts.js +62 -0
  185. package/dist/purchasing/cost.d.ts +110 -0
  186. package/dist/purchasing/cost.js +86 -0
  187. package/dist/purchasing/index.d.ts +36 -0
  188. package/dist/purchasing/index.js +16 -0
  189. package/dist/purchasing/purchase-orders.d.ts +548 -0
  190. package/dist/purchasing/purchase-orders.js +491 -0
  191. package/dist/purchasing/replenishment.d.ts +281 -0
  192. package/dist/purchasing/replenishment.js +240 -0
  193. package/dist/purchasing/settings.d.ts +152 -0
  194. package/dist/purchasing/settings.js +181 -0
  195. package/dist/purchasing/suppliers.d.ts +476 -0
  196. package/dist/purchasing/suppliers.js +438 -0
  197. package/dist/quotes/index.d.ts +501 -0
  198. package/dist/quotes/index.js +439 -0
  199. package/dist/reports/index.d.ts +71 -8
  200. package/dist/reports/index.js +74 -11
  201. package/dist/returns/index.d.ts +614 -21
  202. package/dist/returns/index.js +695 -11
  203. package/dist/search/index.d.ts +76 -1
  204. package/dist/search/index.js +63 -0
  205. package/dist/shipping/definitions.d.ts +29 -0
  206. package/dist/shipping/definitions.js +47 -0
  207. package/dist/shipping/fulfillment-profiles.d.ts +174 -0
  208. package/dist/shipping/fulfillment-profiles.js +104 -0
  209. package/dist/shipping/hendriks.d.ts +97 -0
  210. package/dist/shipping/hendriks.js +50 -0
  211. package/dist/shipping/index.d.ts +48 -0
  212. package/dist/shipping/index.js +25 -0
  213. package/dist/shipping/methods.d.ts +198 -0
  214. package/dist/shipping/methods.js +240 -0
  215. package/dist/shipping/myparcel.d.ts +254 -0
  216. package/dist/shipping/myparcel.js +178 -0
  217. package/dist/shipping/parcel-count-suggestion.d.ts +2 -0
  218. package/dist/shipping/parcel-rule.d.ts +6 -5
  219. package/dist/shipping/parcel-rule.js +21 -23
  220. package/dist/shipping/rate-tables.d.ts +179 -0
  221. package/dist/shipping/rate-tables.js +184 -0
  222. package/dist/stock/index.d.ts +10 -3
  223. package/dist/stock/index.js +3 -0
  224. package/dist/stock/locations.d.ts +144 -0
  225. package/dist/stock/locations.js +168 -0
  226. package/dist/stock/transfers.d.ts +216 -43
  227. package/dist/stock/transfers.js +140 -13
  228. package/dist/stored-value/index.d.ts +214 -4
  229. package/dist/stored-value/index.js +152 -0
  230. package/dist/subscriptions/index.d.ts +682 -0
  231. package/dist/subscriptions/index.js +815 -0
  232. package/dist/tax/index.d.ts +76 -1
  233. package/dist/tax/index.js +50 -0
  234. package/dist/tenant/email-style.d.ts +102 -0
  235. package/dist/tenant/email-style.js +72 -0
  236. package/dist/tenant/email-templates.d.ts +66 -0
  237. package/dist/tenant/email-templates.js +54 -0
  238. package/dist/tenant/notifications.d.ts +23 -17
  239. package/dist/tenant/settings-sources.d.ts +1 -1
  240. package/dist/tenant/time-zone.d.ts +17 -0
  241. package/dist/tenant/time-zone.js +11 -0
  242. package/dist/types.d.ts +50 -3
  243. package/dist/users/index.d.ts +3 -0
  244. package/dist/users/index.js +2 -0
  245. package/dist/users/warehouses.d.ts +50 -0
  246. package/dist/users/warehouses.js +51 -0
  247. package/package.json +2 -2
@@ -0,0 +1,914 @@
1
+ /**
2
+ * `admin.fulfillments.warehouse`: the pick/pack/ship workspace (headless W10-37; spec
3
+ * `decoupling-fulfillments`, ADR `2026-09-10-warehouse-access-model`).
4
+ *
5
+ * The warehouse API is the fulfillment's own API, built for warehouse staff who have no
6
+ * `ReadOrder`: it is PRICE-FREE (no order totals, prices, payment amounts, customer e-mail or
7
+ * billing address; a payment shows as a `paid | due | not_required` badge) and LOCATION-SCOPED.
8
+ * `detachPreview` is the one exception: it names money, so it is the order API's (`ReadOrder`).
9
+ *
10
+ * **Who may act where.** Reads need `ReadFulfillment` (or `UpdateOrder`), writes
11
+ * `UpdateFulfillment` (or `UpdateOrder`), and the store needs the `warehouse` entitlement
12
+ * (`WAREHOUSE_NOT_ENABLED` otherwise). `mine`, `demand` and `handlers` also serve office staff of a
13
+ * store without the entitlement: the shared create flow reads them. A caller holding `UpdateOrder`
14
+ * is office staff and works in every warehouse of the store, plus the fulfillments with no recorded
15
+ * warehouse. Anyone else works only in the warehouses a store admin assigned to them (none
16
+ * assigned: nothing). An API token or app restricted to stock locations is held to those
17
+ * locations whatever it holds, and never sees a fulfillment with no recorded warehouse.
18
+ *
19
+ * **One refusal for "not found" and "not yours":** `LOCATION_OUT_OF_SCOPE`, for a fulfillment or a
20
+ * warehouse that does not exist, belongs to another store, or is outside the caller's warehouses.
21
+ * The API never confirms that a fulfillment exists outside the caller's scope.
22
+ *
23
+ * **The stages.** With the entitlement a fulfillment moves `Pending → Picking` (`claim`),
24
+ * `Picking → Pending` (`unclaim`: the claimer or office staff), `Picking → Packed` (`pack`),
25
+ * `Packed → Picking` (`reopen`, while no carrier booking is active), `→ Shipped` from `Packed`, or
26
+ * from `Pending` for a 3PL or a manual method (`ship`), and `→ Delivered` from `Shipped` or
27
+ * `Pending` (`deliver`). A 3PL (`mode: outsourced`) skips picking and packing: creating it was the
28
+ * handoff. A held order, addresses that diverged in a consolidated fulfillment, a carrier booking
29
+ * still missing and, on a store that requires it, an order not paid in full each refuse shipping
30
+ * (`ORDER_ON_HOLD`, `CONSOLIDATION_ADDRESS_DIVERGED`, `BOOKING_REQUIRED`, `ORDER_NOT_COVERED`).
31
+ *
32
+ * **Refusals are coded errors.** A write's `WarehouseError` union member is thrown as a
33
+ * `PlatformError` carrying its `code` (`ALREADY_CLAIMED`, `INVALID_STAGE_TRANSITION`,
34
+ * `LOCATION_OUT_OF_SCOPE`, …), classified by the same code rules as the errors the warehouse
35
+ * queries throw, so one refusal reaches you as one class whichever call answered it:
36
+ * `INVALID_INPUT` is a `ValidationError` (400), `HANDLER_NOT_FOUND` (a carrier code the engine
37
+ * does not know) a `NotFoundError` (404), and the warehouse's other codes `BusinessRuleError`
38
+ * (422). A `COMBINE_RULE_VIOLATED` names the part of the rule that broke in `details[0].field`.
39
+ * Bulk `ship` and `deliver` report each fulfillment's refusal as data and throw only for the call
40
+ * as a whole. Three refusals come from before the warehouse decides: a missing permission is
41
+ * `FORBIDDEN`, a carrier of a plugin the store does not have (`setHandler`, `book`) is
42
+ * `PLUGIN_ACCESS_DENIED` (both `PermissionDeniedError`, 403), and an id that is not a uuid is
43
+ * `ENTITY_NOT_FOUND` (`NotFoundError`).
44
+ *
45
+ * **Idempotency keys: `append` only.** Every other write is safe to repeat: the stage it needs is
46
+ * gone after the first call, so a repeat is refused (see each method), and `options.idempotencyKey`
47
+ * is sent nowhere for it. `append` takes one per attempt (made up when omitted, as
48
+ * `orders.drafts.place` does).
49
+ */
50
+ import { errorFromGraphQLErrors, idempotencyKey as mintIdempotencyKey, pageFromVendureList, readOffsetCursor, ValidationError, } from '@sixtyninecommerce/core';
51
+ /** The most fulfillments one `ship`, `deliver` or `pickList` call takes. */
52
+ export const MAX_WAREHOUSE_BULK_IDS = 100;
53
+ const ADDRESS_FIELDS = /* GraphQL */ `
54
+ fullName
55
+ company
56
+ streetLine1
57
+ streetLine2
58
+ city
59
+ province
60
+ postalCode
61
+ countryCode
62
+ `;
63
+ /**
64
+ * Every field of `WarehouseFulfillment` the workspace reads, without `lines`. A field list, never a
65
+ * named fragment: `orders-coverage.spec.ts` reads each document's root field with every
66
+ * interpolation replaced, which a fragment spread at the top level would not survive.
67
+ */
68
+ export const FULFILLMENT_FIELDS = /* GraphQL */ `
69
+ id
70
+ state
71
+ handlerCode
72
+ method
73
+ mode
74
+ trackingCode
75
+ stockLocationId
76
+ stockLocationName
77
+ createdAt
78
+ stateChangedAt
79
+ overdue
80
+ claimedBy {
81
+ id
82
+ name
83
+ }
84
+ claimedAt
85
+ packedAt
86
+ bookingStatus
87
+ bookingError
88
+ parcels {
89
+ weightGrams
90
+ lengthMm
91
+ widthMm
92
+ heightMm
93
+ }
94
+ orders {
95
+ id
96
+ code
97
+ poNumber
98
+ orderNotes
99
+ requestedDeliveryDate
100
+ deliveryDue
101
+ paymentBadge
102
+ hold {
103
+ reason
104
+ note
105
+ }
106
+ }
107
+ customer {
108
+ id
109
+ name
110
+ phone
111
+ }
112
+ shippingAddress {
113
+ ${ADDRESS_FIELDS}
114
+ }
115
+ lineCount
116
+ unitCount
117
+ `;
118
+ /** Every field of `WarehouseDemandOrder`. */
119
+ const DEMAND_ORDER_FIELDS = /* GraphQL */ `
120
+ orderId
121
+ orderCode
122
+ poNumber
123
+ orderNotes
124
+ requestedDeliveryDate
125
+ deliveryDue
126
+ orderPlacedAt
127
+ customer {
128
+ id
129
+ name
130
+ phone
131
+ }
132
+ shippingAddress {
133
+ ${ADDRESS_FIELDS}
134
+ }
135
+ consolidationKey
136
+ suggestedHandlerCode
137
+ paymentBadge
138
+ hold {
139
+ reason
140
+ note
141
+ }
142
+ queueExclusions
143
+ externalPlatform
144
+ externalOrderId
145
+ sourceFulfillmentHandedOff
146
+ sourceFulfilled
147
+ sourceFulfilledReason
148
+ chargedParcelCount
149
+ lines {
150
+ orderLineId
151
+ productVariantId
152
+ sku
153
+ name
154
+ featuredAsset {
155
+ id
156
+ preview
157
+ }
158
+ openQty
159
+ routing
160
+ routedLocationId
161
+ onHandAtLocation
162
+ }
163
+ `;
164
+ /** The `WarehouseError` member, read the same way under every union. */
165
+ const ERROR_FIELDS = /* GraphQL */ `
166
+ ... on WarehouseError {
167
+ errorCode
168
+ code
169
+ message
170
+ field
171
+ }
172
+ `;
173
+ const SINGLE_RESULT = /* GraphQL */ `
174
+ __typename
175
+ ... on WarehouseFulfillment {
176
+ ${FULFILLMENT_FIELDS}
177
+ }
178
+ ${ERROR_FIELDS}
179
+ `;
180
+ const BULK_RESULT = /* GraphQL */ `
181
+ __typename
182
+ ... on WarehouseBulkResult {
183
+ succeeded
184
+ failed
185
+ results {
186
+ fulfillmentId
187
+ fulfillment {
188
+ ${FULFILLMENT_FIELDS}
189
+ }
190
+ error {
191
+ code
192
+ message
193
+ field
194
+ }
195
+ }
196
+ }
197
+ ${ERROR_FIELDS}
198
+ `;
199
+ // Each document is spelled out, root field included, so the coverage spec can read what it
200
+ // reaches. The operation names are the dashboard's, so the audit trail reads as it always did.
201
+ export const MY_WAREHOUSES_QUERY = /* GraphQL */ `
202
+ query MyWarehouses {
203
+ myWarehouses {
204
+ id
205
+ name
206
+ }
207
+ }
208
+ `;
209
+ export const WAREHOUSE_COUNTS_QUERY = /* GraphQL */ `
210
+ query WarehouseCounts($stockLocationId: ID!) {
211
+ warehouseCounts(stockLocationId: $stockLocationId) {
212
+ toShip
213
+ toPick
214
+ picking
215
+ packed
216
+ overdue
217
+ shippedToday
218
+ outsourced
219
+ }
220
+ }
221
+ `;
222
+ export const WAREHOUSE_DEMAND_QUERY = /* GraphQL */ `
223
+ query WarehouseDemand($input: WarehouseDemandInput!) {
224
+ warehouseDemand(input: $input) {
225
+ totalItems
226
+ truncated
227
+ items {
228
+ ${DEMAND_ORDER_FIELDS}
229
+ }
230
+ }
231
+ }
232
+ `;
233
+ export const WAREHOUSE_FULFILLMENTS_QUERY = /* GraphQL */ `
234
+ query WarehouseFulfillments($input: WarehouseFulfillmentListInput) {
235
+ warehouseFulfillments(input: $input) {
236
+ totalItems
237
+ items {
238
+ ${FULFILLMENT_FIELDS}
239
+ }
240
+ }
241
+ }
242
+ `;
243
+ export const WAREHOUSE_FULFILLMENT_QUERY = /* GraphQL */ `
244
+ query WarehouseFulfillment($id: ID!) {
245
+ warehouseFulfillment(id: $id) {
246
+ ${FULFILLMENT_FIELDS}
247
+ lines {
248
+ orderLineId
249
+ orderId
250
+ orderCode
251
+ productVariantId
252
+ sku
253
+ name
254
+ featuredAsset {
255
+ id
256
+ preview
257
+ }
258
+ quantity
259
+ }
260
+ }
261
+ }
262
+ `;
263
+ export const WAREHOUSE_FULFILLMENT_HANDLERS_QUERY = /* GraphQL */ `
264
+ query WarehouseFulfillmentHandlers {
265
+ warehouseFulfillmentHandlers {
266
+ code
267
+ description
268
+ mode
269
+ argsRequiredForCreate
270
+ args {
271
+ name
272
+ type
273
+ list
274
+ required
275
+ defaultValue
276
+ label
277
+ description
278
+ ui
279
+ }
280
+ }
281
+ }
282
+ `;
283
+ export const WAREHOUSE_PICK_LIST_QUERY = /* GraphQL */ `
284
+ query WarehousePickList($fulfillmentIds: [ID!]!) {
285
+ warehousePickList(fulfillmentIds: $fulfillmentIds) {
286
+ generatedAt
287
+ timeZone
288
+ warehouseNames
289
+ lineCount
290
+ unitCount
291
+ printedBy {
292
+ id
293
+ name
294
+ }
295
+ fulfillments {
296
+ id
297
+ reference
298
+ state
299
+ orderCodes
300
+ stockLocationName
301
+ lineCount
302
+ unitCount
303
+ }
304
+ lines {
305
+ sku
306
+ name
307
+ productVariantId
308
+ quantity
309
+ fulfillments {
310
+ fulfillmentId
311
+ reference
312
+ orderCodes
313
+ quantity
314
+ }
315
+ }
316
+ }
317
+ }
318
+ `;
319
+ export const WAREHOUSE_APPEND_CANDIDATES_QUERY = /* GraphQL */ `
320
+ query WarehouseAppendCandidates($fulfillmentId: ID!) {
321
+ warehouseAppendCandidates(fulfillmentId: $fulfillmentId) {
322
+ ${DEMAND_ORDER_FIELDS}
323
+ }
324
+ }
325
+ `;
326
+ /** The order API, not the warehouse one: it names money (`ReadOrder`). */
327
+ export const FULFILLMENT_DETACH_PREVIEW_QUERY = /* GraphQL */ `
328
+ query FulfillmentDetachPreview($fulfillmentId: ID!, $orderId: ID!) {
329
+ fulfillmentDetachPreview(fulfillmentId: $fulfillmentId, orderId: $orderId) {
330
+ deliveryChargeApplies
331
+ profileName
332
+ profileMinimum
333
+ currencyCode
334
+ priceIncludesTax
335
+ currentIncludesTax
336
+ currentCharge
337
+ newCharge
338
+ orders {
339
+ orderId
340
+ code
341
+ currentCharge
342
+ newCharge
343
+ }
344
+ remainingNet
345
+ belowProfileMinimum
346
+ refusal {
347
+ code
348
+ message
349
+ }
350
+ }
351
+ }
352
+ `;
353
+ export const CLAIM_FULFILLMENT_MUTATION = /* GraphQL */ `
354
+ mutation ClaimFulfillment($id: ID!) {
355
+ claimFulfillment(id: $id) {
356
+ ${SINGLE_RESULT}
357
+ }
358
+ }
359
+ `;
360
+ export const UNCLAIM_FULFILLMENT_MUTATION = /* GraphQL */ `
361
+ mutation UnclaimFulfillment($id: ID!) {
362
+ unclaimFulfillment(id: $id) {
363
+ ${SINGLE_RESULT}
364
+ }
365
+ }
366
+ `;
367
+ export const REOPEN_FULFILLMENT_MUTATION = /* GraphQL */ `
368
+ mutation ReopenFulfillment($id: ID!) {
369
+ reopenFulfillment(id: $id) {
370
+ ${SINGLE_RESULT}
371
+ }
372
+ }
373
+ `;
374
+ export const PACK_FULFILLMENT_MUTATION = /* GraphQL */ `
375
+ mutation PackFulfillment($id: ID!, $parcels: [WarehouseParcelInput!]) {
376
+ packFulfillment(id: $id, parcels: $parcels) {
377
+ ${SINGLE_RESULT}
378
+ }
379
+ }
380
+ `;
381
+ export const BOOK_FULFILLMENT_MUTATION = /* GraphQL */ `
382
+ mutation BookFulfillment($id: ID!) {
383
+ bookFulfillment(id: $id) {
384
+ ${SINGLE_RESULT}
385
+ }
386
+ }
387
+ `;
388
+ export const UNBOOK_FULFILLMENT_MUTATION = /* GraphQL */ `
389
+ mutation UnbookFulfillment($id: ID!) {
390
+ unbookFulfillment(id: $id) {
391
+ ${SINGLE_RESULT}
392
+ }
393
+ }
394
+ `;
395
+ export const SET_FULFILLMENT_HANDLER_MUTATION = /* GraphQL */ `
396
+ mutation SetFulfillmentHandler(
397
+ $id: ID!
398
+ $handlerCode: String!
399
+ $handlerArgs: [WarehouseHandlerArgInput!]
400
+ ) {
401
+ setFulfillmentHandler(id: $id, handlerCode: $handlerCode, handlerArgs: $handlerArgs) {
402
+ ${SINGLE_RESULT}
403
+ }
404
+ }
405
+ `;
406
+ export const SET_FULFILLMENT_WAREHOUSE_MUTATION = /* GraphQL */ `
407
+ mutation SetFulfillmentWarehouse($id: ID!, $stockLocationId: ID!) {
408
+ setFulfillmentWarehouse(id: $id, stockLocationId: $stockLocationId) {
409
+ ${SINGLE_RESULT}
410
+ }
411
+ }
412
+ `;
413
+ export const CORRECT_FULFILLMENT_QUANTITIES_MUTATION = /* GraphQL */ `
414
+ mutation CorrectFulfillmentQuantities(
415
+ $fulfillmentId: ID!
416
+ $lines: [WarehouseQuantityCorrectionLineInput!]!
417
+ $disposition: FulfillmentUnitDisposition!
418
+ $reason: String
419
+ ) {
420
+ correctFulfillmentQuantities(
421
+ fulfillmentId: $fulfillmentId
422
+ lines: $lines
423
+ disposition: $disposition
424
+ reason: $reason
425
+ ) {
426
+ ${SINGLE_RESULT}
427
+ }
428
+ }
429
+ `;
430
+ export const SHIP_FULFILLMENTS_MUTATION = /* GraphQL */ `
431
+ mutation ShipFulfillments($ids: [ID!]!, $trackingCode: String) {
432
+ shipFulfillments(ids: $ids, trackingCode: $trackingCode) {
433
+ ${BULK_RESULT}
434
+ }
435
+ }
436
+ `;
437
+ export const DELIVER_FULFILLMENTS_MUTATION = /* GraphQL */ `
438
+ mutation DeliverFulfillments($ids: [ID!]!) {
439
+ deliverFulfillments(ids: $ids) {
440
+ ${BULK_RESULT}
441
+ }
442
+ }
443
+ `;
444
+ export const APPEND_TO_FULFILLMENT_MUTATION = /* GraphQL */ `
445
+ mutation AppendToFulfillment(
446
+ $id: ID!
447
+ $lines: [WarehouseFulfillmentLineInput!]!
448
+ $idempotencyKey: String
449
+ ) {
450
+ appendToFulfillment(id: $id, lines: $lines, idempotencyKey: $idempotencyKey) {
451
+ ${SINGLE_RESULT}
452
+ }
453
+ }
454
+ `;
455
+ export const DETACH_ORDER_FROM_FULFILLMENT_MUTATION = /* GraphQL */ `
456
+ mutation DetachOrderFromFulfillment($id: ID!, $orderId: ID!) {
457
+ detachOrderFromFulfillment(id: $id, orderId: $orderId) {
458
+ ${SINGLE_RESULT}
459
+ }
460
+ }
461
+ `;
462
+ // ── mapping ──────────────────────────────────────────────────────────────────
463
+ /** The key a caller retries under, on an error of a call whose key it did not choose. */
464
+ export function withAttemptKey(error, key) {
465
+ if (error !== null && typeof error === 'object' && !('idempotencyKey' in error)) {
466
+ Object.defineProperty(error, 'idempotencyKey', { value: key, enumerable: true });
467
+ }
468
+ return error;
469
+ }
470
+ export function isWarehouseErrorMember(value) {
471
+ return (typeof value === 'object' &&
472
+ value !== null &&
473
+ value.__typename === 'WarehouseError');
474
+ }
475
+ /**
476
+ * A `WarehouseError` as the error the SAME code would be if a warehouse query had thrown it: the
477
+ * queries refuse with these codes as GraphQL errors, so classifying the union member by the
478
+ * ErrorResult rules would give one refusal two classes (`INVALID_INPUT` a 400 from a query and a
479
+ * 422 from a mutation).
480
+ *
481
+ * NOTE: every SDK method over a `WarehouseError` union classifies through this function, never
482
+ * through `errorFromErrorResult` (the create door, `createWarehouseFulfillments`, included).
483
+ * `fulfillments-warehouse.spec.ts` pins the class of every `WarehouseErrorCode`, so a change to
484
+ * core's GraphQL-dialect rules cannot move one silently.
485
+ */
486
+ export function warehouseRefusalError(refusal) {
487
+ const field = typeof refusal.field === 'string' && refusal.field !== '' ? refusal.field : null;
488
+ return errorFromGraphQLErrors([
489
+ {
490
+ message: refusal.message,
491
+ extensions: {
492
+ code: refusal.code,
493
+ ...(field
494
+ ? { details: [{ path: field, message: refusal.message, keyword: refusal.code }] }
495
+ : {}),
496
+ },
497
+ },
498
+ ]);
499
+ }
500
+ export function invalid(field, message) {
501
+ return new ValidationError({
502
+ code: 'INVALID_INPUT',
503
+ message,
504
+ status: 400,
505
+ service: 'vendure',
506
+ details: [{ field, code: 'INVALID_INPUT', message }],
507
+ });
508
+ }
509
+ /** Refused before any request: an absent id would otherwise fail GraphQL validation, uncoded. */
510
+ export function assertId(value, field) {
511
+ if (typeof value !== 'string' || value.trim() === '') {
512
+ throw invalid(field, `A ${field} is required.`);
513
+ }
514
+ }
515
+ function assertIds(values, field) {
516
+ if (!Array.isArray(values) || values.length === 0) {
517
+ throw invalid(field, 'Name at least one fulfillment.');
518
+ }
519
+ for (const [index, value] of values.entries())
520
+ assertId(value, `${field}[${String(index)}]`);
521
+ }
522
+ function toAddress(raw) {
523
+ if (!raw)
524
+ return null;
525
+ return {
526
+ fullName: raw.fullName ?? null,
527
+ company: raw.company ?? null,
528
+ streetLine1: raw.streetLine1 ?? null,
529
+ streetLine2: raw.streetLine2 ?? null,
530
+ city: raw.city ?? null,
531
+ province: raw.province ?? null,
532
+ postalCode: raw.postalCode ?? null,
533
+ countryCode: raw.countryCode ?? null,
534
+ };
535
+ }
536
+ function toCustomer(raw) {
537
+ return raw ? { id: raw.id, name: raw.name ?? null, phone: raw.phone ?? null } : null;
538
+ }
539
+ function toHold(raw) {
540
+ return raw ? { reason: raw.reason ?? null, note: raw.note ?? null } : null;
541
+ }
542
+ function toAsset(raw) {
543
+ return raw ? { id: raw.id, preview: raw.preview } : null;
544
+ }
545
+ export function toFulfillment(raw) {
546
+ return {
547
+ id: raw.id,
548
+ state: raw.state,
549
+ handlerCode: raw.handlerCode,
550
+ method: raw.method ?? null,
551
+ mode: raw.mode,
552
+ trackingCode: raw.trackingCode ?? null,
553
+ stockLocationId: raw.stockLocationId ?? null,
554
+ stockLocationName: raw.stockLocationName ?? null,
555
+ createdAt: raw.createdAt,
556
+ stateChangedAt: raw.stateChangedAt ?? null,
557
+ overdue: raw.overdue,
558
+ claimedBy: raw.claimedBy ? { id: raw.claimedBy.id, name: raw.claimedBy.name ?? null } : null,
559
+ claimedAt: raw.claimedAt ?? null,
560
+ packedAt: raw.packedAt ?? null,
561
+ bookingStatus: raw.bookingStatus ?? null,
562
+ bookingError: raw.bookingError ?? null,
563
+ parcels: (raw.parcels ?? []).map((parcel) => ({
564
+ weightGrams: parcel.weightGrams,
565
+ lengthMm: parcel.lengthMm ?? null,
566
+ widthMm: parcel.widthMm ?? null,
567
+ heightMm: parcel.heightMm ?? null,
568
+ })),
569
+ orders: (raw.orders ?? []).map((order) => ({
570
+ id: order.id,
571
+ code: order.code,
572
+ poNumber: order.poNumber ?? null,
573
+ orderNotes: order.orderNotes ?? null,
574
+ requestedDeliveryDate: order.requestedDeliveryDate ?? null,
575
+ deliveryDue: order.deliveryDue ?? null,
576
+ paymentBadge: order.paymentBadge,
577
+ hold: toHold(order.hold),
578
+ })),
579
+ customer: toCustomer(raw.customer),
580
+ shippingAddress: toAddress(raw.shippingAddress),
581
+ lineCount: raw.lineCount,
582
+ unitCount: raw.unitCount,
583
+ };
584
+ }
585
+ function toDemandOrder(raw) {
586
+ return {
587
+ orderId: raw.orderId,
588
+ orderCode: raw.orderCode,
589
+ poNumber: raw.poNumber ?? null,
590
+ orderNotes: raw.orderNotes ?? null,
591
+ requestedDeliveryDate: raw.requestedDeliveryDate ?? null,
592
+ deliveryDue: raw.deliveryDue ?? null,
593
+ orderPlacedAt: raw.orderPlacedAt ?? null,
594
+ customer: toCustomer(raw.customer),
595
+ shippingAddress: toAddress(raw.shippingAddress),
596
+ consolidationKey: raw.consolidationKey ?? null,
597
+ suggestedHandlerCode: raw.suggestedHandlerCode ?? null,
598
+ paymentBadge: raw.paymentBadge,
599
+ hold: toHold(raw.hold),
600
+ queueExclusions: [...(raw.queueExclusions ?? [])],
601
+ externalPlatform: raw.externalPlatform ?? null,
602
+ externalOrderId: raw.externalOrderId ?? null,
603
+ sourceFulfillmentHandedOff: raw.sourceFulfillmentHandedOff ?? null,
604
+ sourceFulfilled: raw.sourceFulfilled === true,
605
+ sourceFulfilledReason: raw.sourceFulfilledReason ?? null,
606
+ chargedParcelCount: raw.chargedParcelCount ?? null,
607
+ lines: (raw.lines ?? []).map((line) => ({
608
+ orderLineId: line.orderLineId,
609
+ productVariantId: line.productVariantId,
610
+ sku: line.sku,
611
+ name: line.name,
612
+ featuredAsset: toAsset(line.featuredAsset),
613
+ openQty: line.openQty,
614
+ routing: line.routing,
615
+ routedLocationId: line.routedLocationId ?? null,
616
+ onHandAtLocation: line.onHandAtLocation ?? null,
617
+ })),
618
+ };
619
+ }
620
+ function toArg(raw) {
621
+ return {
622
+ name: raw.name,
623
+ type: raw.type,
624
+ list: raw.list,
625
+ required: raw.required,
626
+ defaultValue: raw.defaultValue ?? null,
627
+ label: raw.label ?? null,
628
+ description: raw.description ?? null,
629
+ ui: raw.ui ?? null,
630
+ };
631
+ }
632
+ export function toRefusal(raw) {
633
+ return raw ? { code: raw.code, message: raw.message, field: raw.field ?? null } : null;
634
+ }
635
+ /** The fulfillment a single-result write answers, or its refusal thrown coded. */
636
+ function fulfillmentOrThrow(result) {
637
+ if (isWarehouseErrorMember(result))
638
+ throw warehouseRefusalError(result);
639
+ return toFulfillment(result);
640
+ }
641
+ function bulkOrThrow(result) {
642
+ if (isWarehouseErrorMember(result))
643
+ throw warehouseRefusalError(result);
644
+ const bulk = result;
645
+ return {
646
+ succeeded: bulk.succeeded,
647
+ failed: bulk.failed,
648
+ results: bulk.results.map((item) => ({
649
+ fulfillmentId: item.fulfillmentId,
650
+ fulfillment: item.fulfillment ? toFulfillment(item.fulfillment) : null,
651
+ error: toRefusal(item.error),
652
+ })),
653
+ };
654
+ }
655
+ const DEFAULT_TAKE = 50;
656
+ export function createWarehouseFulfillmentsModule(transport) {
657
+ const single = async (query, field, variables, options) => {
658
+ const data = await transport.graphql({ api: 'admin', query, variables }, options);
659
+ return fulfillmentOrThrow(data[field]);
660
+ };
661
+ const demandPage = async (input, skip, options) => {
662
+ const take = input.take ?? DEFAULT_TAKE;
663
+ const data = await transport.graphql({
664
+ api: 'admin',
665
+ query: WAREHOUSE_DEMAND_QUERY,
666
+ variables: { input: { ...input, take, skip } },
667
+ }, options);
668
+ const page = pageFromVendureList({
669
+ items: data.warehouseDemand.items.map(toDemandOrder),
670
+ totalItems: data.warehouseDemand.totalItems,
671
+ }, skip, take, (cursor) => demandPage(input, readOffsetCursor(cursor), options));
672
+ return Object.assign(page, { truncated: data.warehouseDemand.truncated });
673
+ };
674
+ const listPage = async (input, skip, options) => {
675
+ const take = input.take ?? DEFAULT_TAKE;
676
+ const data = await transport.graphql({
677
+ api: 'admin',
678
+ query: WAREHOUSE_FULFILLMENTS_QUERY,
679
+ variables: { input: { ...input, take, skip } },
680
+ }, options);
681
+ return pageFromVendureList({
682
+ items: data.warehouseFulfillments.items.map(toFulfillment),
683
+ totalItems: data.warehouseFulfillments.totalItems,
684
+ }, skip, take, (cursor) => listPage(input, readOffsetCursor(cursor), options));
685
+ };
686
+ return {
687
+ async mine(options) {
688
+ const data = await transport.graphql({ api: 'admin', query: MY_WAREHOUSES_QUERY }, options);
689
+ return data.myWarehouses.map((location) => ({ id: location.id, name: location.name }));
690
+ },
691
+ async counts(stockLocationId, options) {
692
+ assertId(stockLocationId, 'stockLocationId');
693
+ const data = await transport.graphql({ api: 'admin', query: WAREHOUSE_COUNTS_QUERY, variables: { stockLocationId } }, options);
694
+ const counts = data.warehouseCounts;
695
+ return {
696
+ toShip: counts.toShip,
697
+ toPick: counts.toPick,
698
+ picking: counts.picking,
699
+ packed: counts.packed,
700
+ overdue: counts.overdue,
701
+ shippedToday: counts.shippedToday,
702
+ outsourced: counts.outsourced,
703
+ };
704
+ },
705
+ async demand(input, options) {
706
+ assertId(input?.stockLocationId, 'stockLocationId');
707
+ return demandPage(input, input.skip ?? 0, options);
708
+ },
709
+ async list(input = {}, options) {
710
+ return listPage(input, input.skip ?? 0, options);
711
+ },
712
+ async get(fulfillmentId, options) {
713
+ assertId(fulfillmentId, 'fulfillmentId');
714
+ const data = await transport.graphql({ api: 'admin', query: WAREHOUSE_FULFILLMENT_QUERY, variables: { id: fulfillmentId } }, options);
715
+ const raw = data.warehouseFulfillment;
716
+ return {
717
+ ...toFulfillment(raw),
718
+ lines: (raw.lines ?? []).map((line) => ({
719
+ orderLineId: line.orderLineId,
720
+ orderId: line.orderId,
721
+ orderCode: line.orderCode,
722
+ productVariantId: line.productVariantId,
723
+ sku: line.sku,
724
+ name: line.name,
725
+ featuredAsset: toAsset(line.featuredAsset),
726
+ quantity: line.quantity,
727
+ })),
728
+ };
729
+ },
730
+ async handlers(options) {
731
+ const data = await transport.graphql({ api: 'admin', query: WAREHOUSE_FULFILLMENT_HANDLERS_QUERY }, options);
732
+ return data.warehouseFulfillmentHandlers.map((handler) => ({
733
+ code: handler.code,
734
+ description: handler.description,
735
+ mode: handler.mode,
736
+ args: (handler.args ?? []).map(toArg),
737
+ argsRequiredForCreate: [...(handler.argsRequiredForCreate ?? [])],
738
+ }));
739
+ },
740
+ async pickList(fulfillmentIds, options) {
741
+ assertIds(fulfillmentIds, 'fulfillmentIds');
742
+ const data = await transport.graphql({ api: 'admin', query: WAREHOUSE_PICK_LIST_QUERY, variables: { fulfillmentIds } }, options);
743
+ const list = data.warehousePickList;
744
+ return {
745
+ generatedAt: list.generatedAt,
746
+ timeZone: list.timeZone,
747
+ warehouseNames: [...list.warehouseNames],
748
+ printedBy: list.printedBy
749
+ ? { id: list.printedBy.id, name: list.printedBy.name ?? null }
750
+ : null,
751
+ fulfillments: list.fulfillments.map((entry) => ({
752
+ id: entry.id,
753
+ reference: entry.reference,
754
+ state: entry.state,
755
+ orderCodes: [...entry.orderCodes],
756
+ stockLocationName: entry.stockLocationName ?? null,
757
+ lineCount: entry.lineCount,
758
+ unitCount: entry.unitCount,
759
+ })),
760
+ lines: list.lines.map((line) => ({
761
+ sku: line.sku,
762
+ name: line.name,
763
+ productVariantId: line.productVariantId,
764
+ quantity: line.quantity,
765
+ fulfillments: line.fulfillments.map((part) => ({
766
+ fulfillmentId: part.fulfillmentId,
767
+ reference: part.reference,
768
+ orderCodes: [...part.orderCodes],
769
+ quantity: part.quantity,
770
+ })),
771
+ })),
772
+ lineCount: list.lineCount,
773
+ unitCount: list.unitCount,
774
+ };
775
+ },
776
+ async appendCandidates(fulfillmentId, options) {
777
+ assertId(fulfillmentId, 'fulfillmentId');
778
+ const data = await transport.graphql({ api: 'admin', query: WAREHOUSE_APPEND_CANDIDATES_QUERY, variables: { fulfillmentId } }, options);
779
+ return data.warehouseAppendCandidates.map(toDemandOrder);
780
+ },
781
+ async detachPreview(fulfillmentId, orderId, options) {
782
+ assertId(fulfillmentId, 'fulfillmentId');
783
+ assertId(orderId, 'orderId');
784
+ const data = await transport.graphql({
785
+ api: 'admin',
786
+ query: FULFILLMENT_DETACH_PREVIEW_QUERY,
787
+ variables: { fulfillmentId, orderId },
788
+ }, options);
789
+ const preview = data.fulfillmentDetachPreview;
790
+ return {
791
+ deliveryChargeApplies: preview.deliveryChargeApplies,
792
+ profileName: preview.profileName ?? null,
793
+ profileMinimum: preview.profileMinimum,
794
+ currencyCode: preview.currencyCode,
795
+ priceIncludesTax: preview.priceIncludesTax,
796
+ currentIncludesTax: preview.currentIncludesTax,
797
+ currentCharge: preview.currentCharge,
798
+ newCharge: preview.newCharge,
799
+ orders: preview.orders.map((order) => ({
800
+ orderId: order.orderId,
801
+ code: order.code,
802
+ currentCharge: order.currentCharge,
803
+ newCharge: order.newCharge,
804
+ })),
805
+ remainingNet: preview.remainingNet,
806
+ belowProfileMinimum: preview.belowProfileMinimum,
807
+ refusal: preview.refusal
808
+ ? { code: preview.refusal.code, message: preview.refusal.message }
809
+ : null,
810
+ };
811
+ },
812
+ async claim(fulfillmentId, options) {
813
+ assertId(fulfillmentId, 'fulfillmentId');
814
+ return single(CLAIM_FULFILLMENT_MUTATION, 'claimFulfillment', { id: fulfillmentId }, options);
815
+ },
816
+ async unclaim(fulfillmentId, options) {
817
+ assertId(fulfillmentId, 'fulfillmentId');
818
+ return single(UNCLAIM_FULFILLMENT_MUTATION, 'unclaimFulfillment', { id: fulfillmentId }, options);
819
+ },
820
+ async reopen(fulfillmentId, options) {
821
+ assertId(fulfillmentId, 'fulfillmentId');
822
+ return single(REOPEN_FULFILLMENT_MUTATION, 'reopenFulfillment', { id: fulfillmentId }, options);
823
+ },
824
+ async pack(fulfillmentId, input = {}, options) {
825
+ assertId(fulfillmentId, 'fulfillmentId');
826
+ const parcels = input.parcels;
827
+ return single(PACK_FULFILLMENT_MUTATION, 'packFulfillment', {
828
+ id: fulfillmentId,
829
+ // Omitted is null; an empty list is sent as it is, and the engine refuses it.
830
+ parcels: parcels
831
+ ? parcels.map((parcel) => ({
832
+ weightGrams: parcel.weightGrams,
833
+ ...(parcel.lengthMm === undefined ? {} : { lengthMm: parcel.lengthMm }),
834
+ ...(parcel.widthMm === undefined ? {} : { widthMm: parcel.widthMm }),
835
+ ...(parcel.heightMm === undefined ? {} : { heightMm: parcel.heightMm }),
836
+ }))
837
+ : null,
838
+ }, options);
839
+ },
840
+ async book(fulfillmentId, options) {
841
+ assertId(fulfillmentId, 'fulfillmentId');
842
+ return single(BOOK_FULFILLMENT_MUTATION, 'bookFulfillment', { id: fulfillmentId }, options);
843
+ },
844
+ async unbook(fulfillmentId, options) {
845
+ assertId(fulfillmentId, 'fulfillmentId');
846
+ return single(UNBOOK_FULFILLMENT_MUTATION, 'unbookFulfillment', { id: fulfillmentId }, options);
847
+ },
848
+ async setHandler(fulfillmentId, handlerCode, handlerArgs = [], options) {
849
+ assertId(fulfillmentId, 'fulfillmentId');
850
+ assertId(handlerCode, 'handlerCode');
851
+ return single(SET_FULFILLMENT_HANDLER_MUTATION, 'setFulfillmentHandler', {
852
+ id: fulfillmentId,
853
+ handlerCode,
854
+ handlerArgs: handlerArgs.map(({ name, value }) => ({ name, value })),
855
+ }, options);
856
+ },
857
+ async setWarehouse(fulfillmentId, stockLocationId, options) {
858
+ assertId(fulfillmentId, 'fulfillmentId');
859
+ assertId(stockLocationId, 'stockLocationId');
860
+ return single(SET_FULFILLMENT_WAREHOUSE_MUTATION, 'setFulfillmentWarehouse', { id: fulfillmentId, stockLocationId }, options);
861
+ },
862
+ async correct(fulfillmentId, input, options) {
863
+ assertId(fulfillmentId, 'fulfillmentId');
864
+ const reason = input.reason?.trim();
865
+ return single(CORRECT_FULFILLMENT_QUANTITIES_MUTATION, 'correctFulfillmentQuantities', {
866
+ fulfillmentId,
867
+ lines: input.lines.map((line) => ({
868
+ orderLineId: line.orderLineId,
869
+ quantity: line.quantity,
870
+ ...(line.reduceOrderLine === undefined
871
+ ? {}
872
+ : { reduceOrderLine: line.reduceOrderLine }),
873
+ })),
874
+ disposition: input.disposition,
875
+ reason: reason ? reason : null,
876
+ }, options);
877
+ },
878
+ async ship(fulfillmentIds, trackingCode, options) {
879
+ assertIds(fulfillmentIds, 'fulfillmentIds');
880
+ const tracking = trackingCode?.trim();
881
+ const data = await transport.graphql({
882
+ api: 'admin',
883
+ query: SHIP_FULFILLMENTS_MUTATION,
884
+ variables: { ids: fulfillmentIds, trackingCode: tracking ? tracking : null },
885
+ }, options);
886
+ return bulkOrThrow(data.shipFulfillments);
887
+ },
888
+ async deliver(fulfillmentIds, options) {
889
+ assertIds(fulfillmentIds, 'fulfillmentIds');
890
+ const data = await transport.graphql({ api: 'admin', query: DELIVER_FULFILLMENTS_MUTATION, variables: { ids: fulfillmentIds } }, options);
891
+ return bulkOrThrow(data.deliverFulfillments);
892
+ },
893
+ async append(fulfillmentId, lines, options) {
894
+ assertId(fulfillmentId, 'fulfillmentId');
895
+ const key = options?.idempotencyKey ?? mintIdempotencyKey();
896
+ try {
897
+ const fulfillment = await single(APPEND_TO_FULFILLMENT_MUTATION, 'appendToFulfillment', {
898
+ id: fulfillmentId,
899
+ lines: lines.map(({ orderLineId, quantity }) => ({ orderLineId, quantity })),
900
+ idempotencyKey: key,
901
+ }, { ...options, idempotencyKey: key });
902
+ return { ...fulfillment, idempotencyKey: key };
903
+ }
904
+ catch (error) {
905
+ throw withAttemptKey(error, key);
906
+ }
907
+ },
908
+ async detach(fulfillmentId, orderId, options) {
909
+ assertId(fulfillmentId, 'fulfillmentId');
910
+ assertId(orderId, 'orderId');
911
+ return single(DETACH_ORDER_FROM_FULFILLMENT_MUTATION, 'detachOrderFromFulfillment', { id: fulfillmentId, orderId }, options);
912
+ },
913
+ };
914
+ }