@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,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
|
+
}
|