@sixtyninecommerce/admin 0.10.0 → 0.12.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 +5772 -118
- package/dist/auth/index.d.ts +7 -1
- package/dist/auth/index.js +8 -1
- 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/documents.d.ts +142 -0
- package/dist/catalog/documents.js +114 -0
- package/dist/catalog/index.d.ts +54 -6
- package/dist/catalog/index.js +10 -1
- package/dist/catalog/metadata.d.ts +244 -0
- package/dist/catalog/metadata.js +220 -0
- package/dist/catalog/products.d.ts +159 -19
- package/dist/catalog/products.js +88 -13
- package/dist/catalog/properties.d.ts +140 -14
- package/dist/catalog/properties.js +65 -1
- package/dist/catalog/recommendations.d.ts +288 -0
- package/dist/catalog/recommendations.js +237 -0
- package/dist/catalog/reviews.d.ts +381 -0
- package/dist/catalog/reviews.js +325 -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 +293 -26
- package/dist/catalog/variants.js +164 -7
- package/dist/catalog/visibility.d.ts +38 -7
- package/dist/catalog/visibility.js +19 -1
- package/dist/client.d.ts +121 -9
- package/dist/client.js +53 -14
- package/dist/content/assets.d.ts +285 -0
- package/dist/content/assets.js +181 -0
- package/dist/content/forms.d.ts +332 -1
- package/dist/content/forms.js +140 -4
- package/dist/content/items.d.ts +292 -0
- package/dist/content/items.js +170 -0
- package/dist/content/menus.d.ts +254 -0
- package/dist/content/menus.js +70 -0
- package/dist/content/strings.d.ts +137 -0
- package/dist/content/strings.js +82 -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/delivery-terms.d.ts +44 -0
- package/dist/customers/delivery-terms.js +32 -0
- package/dist/customers/groups.d.ts +207 -0
- package/dist/customers/groups.js +438 -0
- package/dist/customers/index.d.ts +462 -37
- package/dist/customers/index.js +317 -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/emails.d.ts +150 -0
- package/dist/documents/emails.js +220 -0
- package/dist/documents/index.d.ts +744 -21
- package/dist/documents/index.js +438 -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 +163 -11
- package/dist/fulfillments/index.js +135 -6
- 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 +147 -39
- package/dist/index.js +51 -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 +965 -0
- package/dist/integrations/exact-online-types.js +6 -0
- package/dist/integrations/exact-online.d.ts +784 -0
- package/dist/integrations/exact-online.js +1089 -0
- package/dist/integrations/index.d.ts +44 -3
- package/dist/integrations/index.js +23 -3
- package/dist/integrations/pipeline-discoveries.d.ts +65 -0
- package/dist/integrations/pipeline-discoveries.js +65 -0
- package/dist/integrations/pipeline-keys.d.ts +13 -0
- package/dist/integrations/pipeline-keys.js +22 -0
- package/dist/integrations/pipeline-runs.d.ts +119 -0
- package/dist/integrations/pipeline-runs.js +87 -0
- package/dist/integrations/pipelines.d.ts +87 -15
- package/dist/integrations/pipelines.js +41 -22
- package/dist/integrations/price-import.d.ts +223 -0
- package/dist/integrations/price-import.js +124 -0
- package/dist/integrations/types.d.ts +367 -3
- package/dist/integrations/types.js +4 -3
- package/dist/locations/index.d.ts +66 -0
- package/dist/locations/index.js +31 -0
- package/dist/meta/index.d.ts +172 -0
- package/dist/metafields/index.d.ts +8 -1
- package/dist/metafields/index.js +10 -0
- package/dist/orders/cancel-with-money.d.ts +237 -0
- package/dist/orders/cancel-with-money.js +155 -0
- package/dist/orders/commit-edit.d.ts +23 -1
- package/dist/orders/commit-edit.js +19 -2
- package/dist/orders/deposit-policy.d.ts +3 -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 +66 -15
- package/dist/orders/index.js +25 -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 +243 -0
- package/dist/orders/list.js +487 -0
- package/dist/orders/manual-discounts.d.ts +13 -5
- package/dist/orders/manual-pricing.d.ts +5 -0
- package/dist/orders/money-view.d.ts +149 -0
- package/dist/orders/money-view.js +99 -0
- package/dist/orders/order-entry.d.ts +20 -7
- package/dist/orders/plan-edit.d.ts +34 -2
- package/dist/orders/plan-edit.js +112 -11
- 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 +20 -1
- package/dist/orders/surcharges.js +37 -11
- package/dist/payments/account-credit.d.ts +46 -0
- package/dist/payments/account-credit.js +42 -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 +19 -0
- package/dist/payments/credit-noted-fields.js +69 -0
- package/dist/payments/customer-consent.d.ts +30 -0
- package/dist/payments/customer-consent.js +49 -0
- package/dist/payments/index.d.ts +340 -19
- package/dist/payments/index.js +151 -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 +147 -0
- package/dist/payments/requests.js +93 -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 +106 -0
- package/dist/pickups/index.js +108 -0
- package/dist/platform/channels.d.ts +132 -0
- package/dist/platform/channels.js +128 -0
- package/dist/platform/email-gateways.d.ts +165 -0
- package/dist/platform/email-gateways.js +78 -0
- package/dist/platform/geo.d.ts +123 -0
- package/dist/platform/geo.js +144 -0
- package/dist/platform/tax.d.ts +162 -0
- package/dist/platform/tax.js +169 -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 +108 -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 +2370 -58
- package/dist/pos/index.js +854 -7
- package/dist/pos/no-receipt.d.ts +94 -0
- package/dist/pos/no-receipt.js +25 -0
- package/dist/pos/offline-sales.d.ts +228 -0
- package/dist/pos/offline-sales.js +170 -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 +244 -0
- package/dist/pos/returns.js +83 -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 +606 -0
- package/dist/pricing/price-lists.js +600 -0
- package/dist/purchasing/alerts.d.ts +104 -0
- package/dist/purchasing/alerts.js +88 -0
- package/dist/purchasing/backorders.d.ts +61 -0
- package/dist/purchasing/backorders.js +92 -0
- package/dist/purchasing/cost.d.ts +110 -0
- package/dist/purchasing/cost.js +86 -0
- package/dist/purchasing/index.d.ts +54 -0
- package/dist/purchasing/index.js +24 -0
- package/dist/purchasing/links.d.ts +263 -0
- package/dist/purchasing/links.js +192 -0
- package/dist/purchasing/purchase-orders.d.ts +551 -0
- package/dist/purchasing/purchase-orders.js +491 -0
- package/dist/purchasing/receipts.d.ts +396 -0
- package/dist/purchasing/receipts.js +287 -0
- package/dist/purchasing/replenishment.d.ts +281 -0
- package/dist/purchasing/replenishment.js +240 -0
- package/dist/purchasing/returns.d.ts +273 -0
- package/dist/purchasing/returns.js +229 -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 +518 -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 +675 -21
- package/dist/returns/index.js +756 -11
- package/dist/search/index.d.ts +76 -1
- package/dist/search/index.js +63 -0
- package/dist/seo/config.d.ts +128 -0
- package/dist/seo/config.js +95 -0
- package/dist/seo/redirects.d.ts +125 -0
- package/dist/seo/redirects.js +60 -1
- package/dist/seo/settings.d.ts +147 -0
- package/dist/seo/settings.js +209 -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 +54 -0
- package/dist/shipping/index.js +27 -0
- package/dist/shipping/methods.d.ts +205 -0
- package/dist/shipping/methods.js +240 -0
- package/dist/shipping/myparcel.d.ts +668 -0
- package/dist/shipping/myparcel.js +466 -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 +324 -0
- package/dist/shipping/rate-tables.js +390 -0
- package/dist/shipping/ship-to-countries.d.ts +75 -0
- package/dist/shipping/ship-to-countries.js +47 -0
- package/dist/stock/by-location.d.ts +86 -0
- package/dist/stock/by-location.js +94 -0
- package/dist/stock/index.d.ts +18 -4
- package/dist/stock/index.js +7 -0
- package/dist/stock/locations.d.ts +144 -0
- package/dist/stock/locations.js +168 -0
- package/dist/stock/settings.d.ts +106 -0
- package/dist/stock/settings.js +103 -0
- package/dist/stock/transfers.d.ts +386 -52
- package/dist/stock/transfers.js +222 -17
- package/dist/stored-value/index.d.ts +312 -11
- package/dist/stored-value/index.js +223 -4
- package/dist/subscriptions/index.d.ts +682 -0
- package/dist/subscriptions/index.js +815 -0
- package/dist/tax/display-policy.d.ts +105 -0
- package/dist/tax/display-policy.js +84 -0
- package/dist/tax/index.d.ts +79 -1
- package/dist/tax/index.js +52 -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 +287 -0
- package/dist/tenant/email-templates.js +271 -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
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import { errorFromErrorResult, isErrorResult, NotFoundError, ValidationError, } from '@sixtyninecommerce/core';
|
|
1
|
+
import { errorForStatus, errorFromErrorResult, errorFromGraphQLErrors, isErrorResult, NotFoundError, ValidationError, } from '@sixtyninecommerce/core';
|
|
2
|
+
import { customerAgreedVariable, statedCustomerAgreed } from '../payments/customer-consent.js';
|
|
3
|
+
import { storeCreditAware } from '../payments/store-credit-fields.js';
|
|
4
|
+
import { createFulfillmentCreateMethods } from './create.js';
|
|
5
|
+
import { createFulfillmentPaymentPolicyModule, } from './payment-policy.js';
|
|
6
|
+
import { createWarehouseFulfillmentsModule, } from './warehouse.js';
|
|
2
7
|
/** The longest override reason the engine stores. */
|
|
3
8
|
export const FULFILLMENT_COVERAGE_REASON_MAX_LENGTH = 500;
|
|
4
9
|
/** Every field of `OrderOverpaymentOption`. */
|
|
@@ -6,6 +11,7 @@ const OVERPAYMENT_OPTION_FIELDS = /* GraphQL */ `
|
|
|
6
11
|
available
|
|
7
12
|
code
|
|
8
13
|
message
|
|
14
|
+
book
|
|
9
15
|
`;
|
|
10
16
|
/**
|
|
11
17
|
* Its own document, like every call here: on an engine without the query this call alone fails
|
|
@@ -48,10 +54,39 @@ export const CANCEL_FULFILLMENT_MUTATION = /* GraphQL */ `
|
|
|
48
54
|
amount
|
|
49
55
|
currencyCode
|
|
50
56
|
choice
|
|
57
|
+
book
|
|
51
58
|
}
|
|
52
59
|
}
|
|
53
60
|
}
|
|
54
61
|
`;
|
|
62
|
+
/**
|
|
63
|
+
* The refusal member is selected for its facts: `message` is core's per-code template ("Cannot
|
|
64
|
+
* transition Fulfillment from X to Y"), and the refusing step's reason is `transitionError` alone.
|
|
65
|
+
*/
|
|
66
|
+
export const TRANSITION_FULFILLMENT_MUTATION = /* GraphQL */ `
|
|
67
|
+
mutation TransitionFulfillment($id: ID!, $state: String!) {
|
|
68
|
+
transitionFulfillmentToState(id: $id, state: $state) {
|
|
69
|
+
__typename
|
|
70
|
+
... on Fulfillment {
|
|
71
|
+
id
|
|
72
|
+
state
|
|
73
|
+
nextStates
|
|
74
|
+
}
|
|
75
|
+
... on FulfillmentStateTransitionError {
|
|
76
|
+
errorCode
|
|
77
|
+
message
|
|
78
|
+
fromState
|
|
79
|
+
toState
|
|
80
|
+
transitionError
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
`;
|
|
85
|
+
export const RESEND_FULFILLMENT_LABEL_HANDOFF_MUTATION = /* GraphQL */ `
|
|
86
|
+
mutation ResendFulfillmentLabelHandoff($fulfillmentId: ID!) {
|
|
87
|
+
resendFulfillmentLabelHandoff(fulfillmentId: $fulfillmentId)
|
|
88
|
+
}
|
|
89
|
+
`;
|
|
55
90
|
/** Every field of `OrderFulfillmentCoverageOverride`. */
|
|
56
91
|
const COVERAGE_OVERRIDE_FIELDS = /* GraphQL */ `
|
|
57
92
|
id
|
|
@@ -154,15 +189,27 @@ function assertCancelRequest(fulfillmentId, input) {
|
|
|
154
189
|
if (!OVERPAYMENT_CHOICES.has(entry.choice)) {
|
|
155
190
|
throw invalidCancel(`overpayment[${String(index)}].choice`, `The choice for order ${orderId} must be REFUND or ACCOUNT_CREDIT; got ${JSON.stringify(entry.choice)}.`);
|
|
156
191
|
}
|
|
192
|
+
if (entry.customerAgreed != null &&
|
|
193
|
+
customerAgreedVariable(entry.customerAgreed) === undefined) {
|
|
194
|
+
throw invalidCancel(`overpayment[${String(index)}].customerAgreed`, `The customer's answer for order ${orderId} must be true or false; got ${JSON.stringify(entry.customerAgreed)}.`);
|
|
195
|
+
}
|
|
157
196
|
if (seen.has(orderId)) {
|
|
158
197
|
throw invalidCancel(`overpayment[${String(index)}].orderId`, `Order ${orderId} is named twice: give one choice per order.`);
|
|
159
198
|
}
|
|
160
199
|
seen.add(orderId);
|
|
161
200
|
}
|
|
162
201
|
}
|
|
163
|
-
/**
|
|
202
|
+
/**
|
|
203
|
+
* An option as the SDK types it: `code` and `message` are null when it is open; `book` (the
|
|
204
|
+
* account credit's, incentives sprint 8) null on the refund and from an engine before it.
|
|
205
|
+
*/
|
|
164
206
|
function toOption(raw) {
|
|
165
|
-
return {
|
|
207
|
+
return {
|
|
208
|
+
available: raw.available,
|
|
209
|
+
code: raw.code ?? null,
|
|
210
|
+
message: raw.message ?? null,
|
|
211
|
+
book: raw.book ?? null,
|
|
212
|
+
};
|
|
166
213
|
}
|
|
167
214
|
export const REPORT_APP_FULFILLMENT_MUTATION = /* GraphQL */ `
|
|
168
215
|
mutation ReportAppFulfillment(
|
|
@@ -358,8 +405,55 @@ function assertLabelRequest(fulfillmentId, format) {
|
|
|
358
405
|
throw invalidLabelRequest('format', `format must be 'A4' or 'A6', or left out to label every parcel still missing one; got ${JSON.stringify(format)}.`);
|
|
359
406
|
}
|
|
360
407
|
}
|
|
408
|
+
function invalidTransition(field, message) {
|
|
409
|
+
return new ValidationError({
|
|
410
|
+
code: 'FULFILLMENT_TRANSITION_INVALID',
|
|
411
|
+
message,
|
|
412
|
+
status: 400,
|
|
413
|
+
service: 'vendure',
|
|
414
|
+
details: [{ field, code: 'FULFILLMENT_TRANSITION_INVALID', message }],
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
/** The `[CODE]` a step of the fulfillment process prefixes its refusal text with. */
|
|
418
|
+
const STEP_CODE = /^\s*\[([A-Z][A-Z0-9_]*)\]\s*/;
|
|
419
|
+
/**
|
|
420
|
+
* A refused move as the coded error it is. Core carries a step's refusal only as text, so the
|
|
421
|
+
* step's own code is read off its `[CODE]` prefix and classed through the GraphQL dialect, as the
|
|
422
|
+
* warehouse API's refusals of the same codes are (`warehouseRefusalError`): one code, one class,
|
|
423
|
+
* whichever door answered it.
|
|
424
|
+
*/
|
|
425
|
+
export function fulfillmentTransitionRefusal(result) {
|
|
426
|
+
const text = typeof result.transitionError === 'string' ? result.transitionError.trim() : '';
|
|
427
|
+
const facts = {
|
|
428
|
+
errorCode: result.errorCode,
|
|
429
|
+
fromState: result.fromState ?? '',
|
|
430
|
+
toState: result.toState ?? '',
|
|
431
|
+
transitionError: text,
|
|
432
|
+
};
|
|
433
|
+
const step = STEP_CODE.exec(text);
|
|
434
|
+
const sentence = step ? text.slice(step[0].length).trim() : text;
|
|
435
|
+
// Core's `message` is a per-code template, untranslated on some engines
|
|
436
|
+
// ("errorResult.FULFILLMENT_STATE_TRANSITION_ERROR"): said only when the move is unknown too.
|
|
437
|
+
const message = sentence ||
|
|
438
|
+
(facts.fromState && facts.toState
|
|
439
|
+
? `The fulfillment cannot move from ${facts.fromState} to ${facts.toState}.`
|
|
440
|
+
: result.message);
|
|
441
|
+
if (step?.[1]) {
|
|
442
|
+
return errorFromGraphQLErrors([{ message, extensions: { ...facts, code: step[1] } }]);
|
|
443
|
+
}
|
|
444
|
+
const base = errorFromErrorResult({ errorCode: result.errorCode, message });
|
|
445
|
+
return errorForStatus(base.status, {
|
|
446
|
+
code: base.code,
|
|
447
|
+
message,
|
|
448
|
+
service: 'vendure',
|
|
449
|
+
extensions: { ...facts },
|
|
450
|
+
});
|
|
451
|
+
}
|
|
361
452
|
export function createFulfillmentsModule(transport) {
|
|
362
453
|
return {
|
|
454
|
+
...createFulfillmentCreateMethods(transport),
|
|
455
|
+
paymentPolicy: createFulfillmentPaymentPolicyModule(transport),
|
|
456
|
+
warehouse: createWarehouseFulfillmentsModule(transport),
|
|
363
457
|
async parcelsOfOrder(orderId, options) {
|
|
364
458
|
const data = await transport.graphql({ api: 'admin', query: ORDER_FULFILLMENT_PARCELS_QUERY, variables: { id: orderId } }, options);
|
|
365
459
|
if (!data.order)
|
|
@@ -442,7 +536,7 @@ export function createFulfillmentsModule(transport) {
|
|
|
442
536
|
if (typeof fulfillmentId !== 'string' || fulfillmentId.trim() === '') {
|
|
443
537
|
throw invalidCancel('fulfillmentId', 'A fulfillment id is required.');
|
|
444
538
|
}
|
|
445
|
-
const data = await transport.graphql({ api: 'admin', query: FULFILLMENT_CANCEL_PREVIEW_QUERY, variables: { fulfillmentId } }, options);
|
|
539
|
+
const data = await storeCreditAware(transport).graphql({ api: 'admin', query: FULFILLMENT_CANCEL_PREVIEW_QUERY, variables: { fulfillmentId } }, options);
|
|
446
540
|
const preview = data.fulfillmentCancelPreview;
|
|
447
541
|
return {
|
|
448
542
|
fulfillmentId: preview.fulfillmentId,
|
|
@@ -459,14 +553,21 @@ export function createFulfillmentsModule(transport) {
|
|
|
459
553
|
async cancel(fulfillmentId, input = {}, options) {
|
|
460
554
|
assertCancelRequest(fulfillmentId, input);
|
|
461
555
|
const overpayment = input.overpayment ?? [];
|
|
462
|
-
const data = await transport.graphql({
|
|
556
|
+
const data = await storeCreditAware(transport).graphql({
|
|
463
557
|
api: 'admin',
|
|
464
558
|
query: CANCEL_FULFILLMENT_MUTATION,
|
|
465
559
|
// A variable, not a header: the Admin API takes the key as an argument.
|
|
466
560
|
variables: {
|
|
467
561
|
fulfillmentId,
|
|
468
562
|
...(overpayment.length > 0
|
|
469
|
-
? {
|
|
563
|
+
? {
|
|
564
|
+
overpayment: overpayment.map(({ orderId, choice, customerAgreed }) => ({
|
|
565
|
+
orderId,
|
|
566
|
+
choice,
|
|
567
|
+
// Named only when stated: an engine before the field takes the rest.
|
|
568
|
+
...statedCustomerAgreed(customerAgreed),
|
|
569
|
+
})),
|
|
570
|
+
}
|
|
470
571
|
: {}),
|
|
471
572
|
...(options?.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {}),
|
|
472
573
|
},
|
|
@@ -480,6 +581,7 @@ export function createFulfillmentsModule(transport) {
|
|
|
480
581
|
amount: entry.amount,
|
|
481
582
|
currencyCode: entry.currencyCode,
|
|
482
583
|
choice: entry.choice,
|
|
584
|
+
book: entry.book ?? null,
|
|
483
585
|
})),
|
|
484
586
|
};
|
|
485
587
|
},
|
|
@@ -515,6 +617,33 @@ export function createFulfillmentsModule(transport) {
|
|
|
515
617
|
}, options);
|
|
516
618
|
return toCoverageOverride(data.allowUncoveredFulfillment);
|
|
517
619
|
},
|
|
620
|
+
async transition(fulfillmentId, state, options) {
|
|
621
|
+
if (typeof fulfillmentId !== 'string' || fulfillmentId.trim() === '') {
|
|
622
|
+
throw invalidTransition('fulfillmentId', 'A fulfillment id is required.');
|
|
623
|
+
}
|
|
624
|
+
if (typeof state !== 'string' || state.trim() === '') {
|
|
625
|
+
throw invalidTransition('state', 'Name the state to move the fulfillment to.');
|
|
626
|
+
}
|
|
627
|
+
const data = await transport.graphql({
|
|
628
|
+
api: 'admin',
|
|
629
|
+
query: TRANSITION_FULFILLMENT_MUTATION,
|
|
630
|
+
variables: { id: fulfillmentId, state },
|
|
631
|
+
}, options);
|
|
632
|
+
const result = data.transitionFulfillmentToState;
|
|
633
|
+
if (isErrorResult(result))
|
|
634
|
+
throw fulfillmentTransitionRefusal(result);
|
|
635
|
+
const moved = result;
|
|
636
|
+
return { id: moved.id, state: moved.state, nextStates: [...(moved.nextStates ?? [])] };
|
|
637
|
+
},
|
|
638
|
+
async resendLabelHandoff(fulfillmentId, options) {
|
|
639
|
+
assertLabelRequest(fulfillmentId, undefined);
|
|
640
|
+
const data = await transport.graphql({
|
|
641
|
+
api: 'admin',
|
|
642
|
+
query: RESEND_FULFILLMENT_LABEL_HANDOFF_MUTATION,
|
|
643
|
+
variables: { fulfillmentId },
|
|
644
|
+
}, options);
|
|
645
|
+
return data.resendFulfillmentLabelHandoff;
|
|
646
|
+
},
|
|
518
647
|
async reportAppFulfillment(fulfillmentId, input, options) {
|
|
519
648
|
const data = await transport.graphql({
|
|
520
649
|
api: 'admin',
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { type Transport } from '@sixtyninecommerce/core';
|
|
2
|
+
import type { Call } from '../types.js';
|
|
3
|
+
/** The most payment method codes `exemptMethodCodes` may name. */
|
|
4
|
+
export declare const FULFILLMENT_PAYMENT_POLICY_EXEMPT_METHODS_MAX = 50;
|
|
5
|
+
/** The longest payment method code the list accepts (`PaymentMethod.code` is a varchar(255)). */
|
|
6
|
+
export declare const FULFILLMENT_PAYMENT_POLICY_METHOD_CODE_MAX_LENGTH = 255;
|
|
7
|
+
/**
|
|
8
|
+
* The store's fulfilment payment policy (`Channel.customFields.fulfillmentPaymentPolicy`):
|
|
9
|
+
* whether goods are handed over before an order is paid in full. Every field present: this is
|
|
10
|
+
* what the engine APPLIES, absent and malformed fields read as their defaults (OFF).
|
|
11
|
+
*/
|
|
12
|
+
export interface FulfillmentPaymentPolicy {
|
|
13
|
+
/**
|
|
14
|
+
* On: a fulfilment is created, extended or shipped only once the money COLLECTED for the
|
|
15
|
+
* order (settled, or held by a payment provider) covers what it bills, unless the order is
|
|
16
|
+
* exempt or an override was recorded (`fulfillments.allowUncovered`). Otherwise refused
|
|
17
|
+
* `ORDER_NOT_COVERED`.
|
|
18
|
+
*/
|
|
19
|
+
requireFullPayment: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Payment method CODES whose orders are handed over unpaid as a matter of course (cash on
|
|
22
|
+
* delivery, a bank transfer the store ships against), judged on the order's latest live
|
|
23
|
+
* payment. Read as the engine compares them: trimmed, lower-cased, once each.
|
|
24
|
+
*/
|
|
25
|
+
exemptMethodCodes: string[];
|
|
26
|
+
}
|
|
27
|
+
/** The policy of a store that never set one, and of a column that cannot be read: off. */
|
|
28
|
+
export declare const DEFAULT_FULFILLMENT_PAYMENT_POLICY: Readonly<FulfillmentPaymentPolicy>;
|
|
29
|
+
/**
|
|
30
|
+
* The ACTIVE store's fulfilment payment policy (`admin.fulfillments.paymentPolicy`), stored as a
|
|
31
|
+
* Channel custom field and written through core `updateChannel`.
|
|
32
|
+
*
|
|
33
|
+
* Reading needs an authenticated administrator on the store; writing needs `UpdateChannel`.
|
|
34
|
+
*/
|
|
35
|
+
export interface FulfillmentPaymentPolicyModule {
|
|
36
|
+
/**
|
|
37
|
+
* The policy the engine applies, read as tolerantly as the engine reads it
|
|
38
|
+
* (`resolveFulfillmentPaymentPolicy`): a store that never set one, a malformed column and a
|
|
39
|
+
* field of the wrong type all answer OFF ({@link DEFAULT_FULFILLMENT_PAYMENT_POLICY}); the
|
|
40
|
+
* exempt codes are the non-blank ones, trimmed, lower-cased and once each.
|
|
41
|
+
*/
|
|
42
|
+
get(options?: Call): Promise<FulfillmentPaymentPolicy>;
|
|
43
|
+
/**
|
|
44
|
+
* Replace the whole policy, and answer it as the engine now applies it.
|
|
45
|
+
*
|
|
46
|
+
* Both fields are required: read it with {@link get}, change what you mean to, and send it
|
|
47
|
+
* back. Only the schema's fields are stored, the codes trimmed.
|
|
48
|
+
*
|
|
49
|
+
* Refused before any request with `FULFILLMENT_PAYMENT_POLICY_INVALID` ({@link ValidationError},
|
|
50
|
+
* one `details[]` entry per failing field): a non-boolean switch, an exempt list that is not a
|
|
51
|
+
* list, holds a blank or over-long code, names one code twice in any case, or more than 50.
|
|
52
|
+
* The engine's own write validator refuses the same values (a `ValidationError` too, carrying
|
|
53
|
+
* its sentence), so a value that slips past this check is still never stored.
|
|
54
|
+
*
|
|
55
|
+
* Absent and "set to the defaults" mean the same thing to the engine, and a store's column is
|
|
56
|
+
* never backfilled: write the policy when a merchant changed it.
|
|
57
|
+
*/
|
|
58
|
+
set(policy: FulfillmentPaymentPolicy, options?: Call): Promise<FulfillmentPaymentPolicy>;
|
|
59
|
+
}
|
|
60
|
+
export declare const FULFILLMENT_PAYMENT_POLICY_QUERY = "\n query FulfillmentPaymentPolicy {\n activeChannel { \n id\n customFields {\n fulfillmentPaymentPolicy\n }\n }\n }\n";
|
|
61
|
+
export declare const SET_FULFILLMENT_PAYMENT_POLICY_MUTATION = "\n mutation SetFulfillmentPaymentPolicy($input: UpdateChannelInput!) {\n updateChannel(input: $input) {\n ... on Channel { \n id\n customFields {\n fulfillmentPaymentPolicy\n }\n }\n ... on ErrorResult { errorCode message }\n }\n }\n";
|
|
62
|
+
/** A payment method code as the engine compares it (`normalizeMethodCode`). */
|
|
63
|
+
export declare function normalizeFulfillmentPolicyMethodCode(code: string): string;
|
|
64
|
+
export declare function createFulfillmentPaymentPolicyModule(transport: Transport): FulfillmentPaymentPolicyModule;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { errorFromErrorResult, isErrorResult, ValidationError, } from '@sixtyninecommerce/core';
|
|
2
|
+
// The bounds of the meta catalog's `fulfillment_payment_policy` schema
|
|
3
|
+
// (`packages/shared/src/meta-catalog/settings-schemas.ts`), which the spec reads
|
|
4
|
+
// back from that schema, and of the engine's write validator
|
|
5
|
+
// (`validateFulfillmentPaymentPolicyValue`), which refuses the same values.
|
|
6
|
+
/** The most payment method codes `exemptMethodCodes` may name. */
|
|
7
|
+
export const FULFILLMENT_PAYMENT_POLICY_EXEMPT_METHODS_MAX = 50;
|
|
8
|
+
/** The longest payment method code the list accepts (`PaymentMethod.code` is a varchar(255)). */
|
|
9
|
+
export const FULFILLMENT_PAYMENT_POLICY_METHOD_CODE_MAX_LENGTH = 255;
|
|
10
|
+
/** The policy of a store that never set one, and of a column that cannot be read: off. */
|
|
11
|
+
export const DEFAULT_FULFILLMENT_PAYMENT_POLICY = Object.freeze({
|
|
12
|
+
requireFullPayment: false,
|
|
13
|
+
exemptMethodCodes: [],
|
|
14
|
+
});
|
|
15
|
+
const POLICY_FIELDS = /* GraphQL */ `
|
|
16
|
+
id
|
|
17
|
+
customFields {
|
|
18
|
+
fulfillmentPaymentPolicy
|
|
19
|
+
}
|
|
20
|
+
`;
|
|
21
|
+
export const FULFILLMENT_PAYMENT_POLICY_QUERY = /* GraphQL */ `
|
|
22
|
+
query FulfillmentPaymentPolicy {
|
|
23
|
+
activeChannel { ${POLICY_FIELDS} }
|
|
24
|
+
}
|
|
25
|
+
`;
|
|
26
|
+
export const SET_FULFILLMENT_PAYMENT_POLICY_MUTATION = /* GraphQL */ `
|
|
27
|
+
mutation SetFulfillmentPaymentPolicy($input: UpdateChannelInput!) {
|
|
28
|
+
updateChannel(input: $input) {
|
|
29
|
+
... on Channel { ${POLICY_FIELDS} }
|
|
30
|
+
... on ErrorResult { errorCode message }
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
`;
|
|
34
|
+
function isRecord(value) {
|
|
35
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
36
|
+
}
|
|
37
|
+
/** A payment method code as the engine compares it (`normalizeMethodCode`). */
|
|
38
|
+
export function normalizeFulfillmentPolicyMethodCode(code) {
|
|
39
|
+
return code.trim().toLowerCase();
|
|
40
|
+
}
|
|
41
|
+
/** The column, read as the engine reads it: anything unreadable is OFF. */
|
|
42
|
+
function readFulfillmentPaymentPolicy(raw) {
|
|
43
|
+
let parsed = raw;
|
|
44
|
+
if (typeof raw === 'string') {
|
|
45
|
+
try {
|
|
46
|
+
parsed = JSON.parse(raw);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
parsed = null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (!isRecord(parsed))
|
|
53
|
+
return { requireFullPayment: false, exemptMethodCodes: [] };
|
|
54
|
+
const codes = Array.isArray(parsed.exemptMethodCodes)
|
|
55
|
+
? [
|
|
56
|
+
...new Set(parsed.exemptMethodCodes
|
|
57
|
+
.filter((code) => typeof code === 'string' && code.trim() !== '')
|
|
58
|
+
.map(normalizeFulfillmentPolicyMethodCode)),
|
|
59
|
+
].slice(0, FULFILLMENT_PAYMENT_POLICY_EXEMPT_METHODS_MAX)
|
|
60
|
+
: [];
|
|
61
|
+
return { requireFullPayment: parsed.requireFullPayment === true, exemptMethodCodes: codes };
|
|
62
|
+
}
|
|
63
|
+
/** Every way `policy` breaks the schema, one entry per field. */
|
|
64
|
+
function problemsOf(policy) {
|
|
65
|
+
const problems = [];
|
|
66
|
+
const add = (field, message) => problems.push({ field, code: 'FULFILLMENT_PAYMENT_POLICY_INVALID', message });
|
|
67
|
+
if (!isRecord(policy)) {
|
|
68
|
+
add('policy', 'Pass the whole policy as an object: read it with get(), change it, send it back.');
|
|
69
|
+
return problems;
|
|
70
|
+
}
|
|
71
|
+
if (typeof policy.requireFullPayment !== 'boolean') {
|
|
72
|
+
add('requireFullPayment', 'requireFullPayment must be true or false.');
|
|
73
|
+
}
|
|
74
|
+
const codes = policy.exemptMethodCodes;
|
|
75
|
+
if (!Array.isArray(codes)) {
|
|
76
|
+
add('exemptMethodCodes', 'exemptMethodCodes must be a list of payment method codes.');
|
|
77
|
+
}
|
|
78
|
+
else if (codes.some((code) => typeof code !== 'string' || code.trim() === '')) {
|
|
79
|
+
add('exemptMethodCodes', 'exemptMethodCodes may hold only non-blank payment method codes.');
|
|
80
|
+
}
|
|
81
|
+
else if (codes.some((code) => code.trim().length > FULFILLMENT_PAYMENT_POLICY_METHOD_CODE_MAX_LENGTH)) {
|
|
82
|
+
add('exemptMethodCodes', `A payment method code is at most ${String(FULFILLMENT_PAYMENT_POLICY_METHOD_CODE_MAX_LENGTH)} characters.`);
|
|
83
|
+
}
|
|
84
|
+
else if (new Set(codes.map((code) => normalizeFulfillmentPolicyMethodCode(code))).size !==
|
|
85
|
+
codes.length) {
|
|
86
|
+
add('exemptMethodCodes', 'exemptMethodCodes names a payment method code more than once (codes are compared ignoring case).');
|
|
87
|
+
}
|
|
88
|
+
else if (codes.length > FULFILLMENT_PAYMENT_POLICY_EXEMPT_METHODS_MAX) {
|
|
89
|
+
add('exemptMethodCodes', `exemptMethodCodes may name at most ${String(FULFILLMENT_PAYMENT_POLICY_EXEMPT_METHODS_MAX)} payment methods.`);
|
|
90
|
+
}
|
|
91
|
+
return problems;
|
|
92
|
+
}
|
|
93
|
+
/** Exactly the schema's fields, in its order, codes trimmed: what the column stores. */
|
|
94
|
+
function storedOf(policy) {
|
|
95
|
+
return {
|
|
96
|
+
requireFullPayment: policy.requireFullPayment,
|
|
97
|
+
exemptMethodCodes: policy.exemptMethodCodes.map((code) => code.trim()),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
export function createFulfillmentPaymentPolicyModule(transport) {
|
|
101
|
+
const read = async (options) => {
|
|
102
|
+
const data = await transport.graphql({ api: 'admin', query: FULFILLMENT_PAYMENT_POLICY_QUERY }, options);
|
|
103
|
+
return data.activeChannel;
|
|
104
|
+
};
|
|
105
|
+
return {
|
|
106
|
+
async get(options) {
|
|
107
|
+
const channel = await read(options);
|
|
108
|
+
return readFulfillmentPaymentPolicy(channel.customFields?.fulfillmentPaymentPolicy ?? null);
|
|
109
|
+
},
|
|
110
|
+
async set(policy, options) {
|
|
111
|
+
const problems = problemsOf(policy);
|
|
112
|
+
if (problems.length > 0) {
|
|
113
|
+
throw new ValidationError({
|
|
114
|
+
code: 'FULFILLMENT_PAYMENT_POLICY_INVALID',
|
|
115
|
+
message: problems.map((problem) => problem.message).join(' '),
|
|
116
|
+
status: 400,
|
|
117
|
+
service: 'vendure',
|
|
118
|
+
details: problems,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
// `updateChannel` needs the id, and the active channel is the one the client is scoped
|
|
122
|
+
// to: read it with the SAME call options, so a per-call tenant writes its own channel.
|
|
123
|
+
const { id } = await read(options);
|
|
124
|
+
const data = await transport.graphql({
|
|
125
|
+
api: 'admin',
|
|
126
|
+
query: SET_FULFILLMENT_PAYMENT_POLICY_MUTATION,
|
|
127
|
+
variables: {
|
|
128
|
+
// The column is `text` holding JSON, so it is sent as a string.
|
|
129
|
+
input: {
|
|
130
|
+
id,
|
|
131
|
+
customFields: { fulfillmentPaymentPolicy: JSON.stringify(storedOf(policy)) },
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
}, options);
|
|
135
|
+
if (isErrorResult(data.updateChannel))
|
|
136
|
+
throw errorFromErrorResult(data.updateChannel);
|
|
137
|
+
return readFulfillmentPaymentPolicy(data.updateChannel.customFields?.fulfillmentPaymentPolicy ?? null);
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|