@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
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import { errorFromErrorResult, isErrorResult, NotFoundError, ValidationError, } from '@sixtyninecommerce/core';
|
|
2
|
+
// Mirrors, pinned by `__tests__/order-settings.spec.ts`: the engine's `VALID_TARGET_STATES` /
|
|
3
|
+
// `VALID_CONDITION_TYPES` (`order-constraints/order-status-rules-process.ts`) and the shared
|
|
4
|
+
// `ORDER_STATUS_RULE_*` the meta catalog publishes; `ORDER_CODE_DIGITS_MIN/MAX` in
|
|
5
|
+
// `order-code/channel-aware-order-code-strategy.ts`. Change both sides together.
|
|
6
|
+
/** The states an order status rule may move a placed order to. */
|
|
7
|
+
export const ORDER_STATUS_RULE_TARGET_STATES = [
|
|
8
|
+
'AwaitingApproval',
|
|
9
|
+
'PaymentAuthorized',
|
|
10
|
+
'PaymentSettled',
|
|
11
|
+
];
|
|
12
|
+
/** What an order status rule matches on. */
|
|
13
|
+
export const ORDER_STATUS_RULE_CONDITION_TYPES = [
|
|
14
|
+
'product',
|
|
15
|
+
'coupon',
|
|
16
|
+
'collection',
|
|
17
|
+
'facet_value',
|
|
18
|
+
];
|
|
19
|
+
/** The fewest zero-padded digits of a sequential order number. */
|
|
20
|
+
export const ORDER_CODE_DIGITS_MIN = 4;
|
|
21
|
+
/** The most zero-padded digits of a sequential order number. */
|
|
22
|
+
export const ORDER_CODE_DIGITS_MAX = 8;
|
|
23
|
+
/**
|
|
24
|
+
* The longest order-number prefix. The engine stores more, but every order code is
|
|
25
|
+
* `NAMESPACE-PREFIX00001` in a 255-character column: a long prefix fails EVERY order placement.
|
|
26
|
+
*/
|
|
27
|
+
export const ORDER_CODE_PREFIX_MAX_LENGTH = 20;
|
|
28
|
+
/** The youngest minimum purchase age (the engine checks no age below 1: `minimumAge > 0`). */
|
|
29
|
+
export const MINIMUM_AGE_MIN = 1;
|
|
30
|
+
/** The oldest minimum purchase age the platform accepts. */
|
|
31
|
+
export const MINIMUM_AGE_MAX = 99;
|
|
32
|
+
/**
|
|
33
|
+
* The largest amount (minor units) the minimum and the thresholds hold: the columns are Vendure
|
|
34
|
+
* `int` custom fields, GraphQL `Int` (32 bits). ₩30,000,000 is 3,000,000,000 hundredths, past it.
|
|
35
|
+
*/
|
|
36
|
+
export const ORDER_SETTINGS_AMOUNT_MAX = 2_147_483_647;
|
|
37
|
+
/** The settings group `minimumAge` belongs to (multi-region spec §5.3). */
|
|
38
|
+
const AGE_GROUP = 'settings.age_verification';
|
|
39
|
+
const CHANNEL_FIELDS = /* GraphQL */ `
|
|
40
|
+
id
|
|
41
|
+
code
|
|
42
|
+
defaultCurrencyCode
|
|
43
|
+
customFields {
|
|
44
|
+
minOrderAmount
|
|
45
|
+
exemptCustomerGroupIds
|
|
46
|
+
exemptCollectionIds
|
|
47
|
+
orderCodeNamespace
|
|
48
|
+
orderCodePrefix
|
|
49
|
+
orderCodeDigits
|
|
50
|
+
orderCodeEnabled
|
|
51
|
+
minimumAge
|
|
52
|
+
orderStatusRules
|
|
53
|
+
outstandingBalanceWarningThreshold
|
|
54
|
+
outstandingBalanceCriticalThreshold
|
|
55
|
+
}
|
|
56
|
+
`;
|
|
57
|
+
export const ORDER_SETTINGS_QUERY = /* GraphQL */ `
|
|
58
|
+
query OrderSettings {
|
|
59
|
+
activeChannel { ${CHANNEL_FIELDS} }
|
|
60
|
+
channelSettingsSources { group source locked overridden inheritable values }
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
63
|
+
export const UPDATE_ORDER_SETTINGS_MUTATION = /* GraphQL */ `
|
|
64
|
+
mutation UpdateOrderSettings($input: UpdateChannelInput!) {
|
|
65
|
+
updateChannel(input: $input) {
|
|
66
|
+
... on Channel { ${CHANNEL_FIELDS} }
|
|
67
|
+
... on ErrorResult { errorCode message }
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
`;
|
|
71
|
+
const INVALID = 'ORDER_SETTINGS_INVALID';
|
|
72
|
+
const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
73
|
+
const isWhole = (value) => typeof value === 'number' && Number.isSafeInteger(value);
|
|
74
|
+
const numberOrNull = (value) => typeof value === 'number' && Number.isFinite(value) ? value : null;
|
|
75
|
+
const stringOrNull = (value) => (typeof value === 'string' ? value : null);
|
|
76
|
+
/** The non-empty strings of `value`, when it is an array; otherwise none. */
|
|
77
|
+
function strings(value) {
|
|
78
|
+
return Array.isArray(value)
|
|
79
|
+
? value.filter((item) => typeof item === 'string' && item.length > 0)
|
|
80
|
+
: [];
|
|
81
|
+
}
|
|
82
|
+
function parsedJson(raw) {
|
|
83
|
+
if (typeof raw !== 'string' || raw === '')
|
|
84
|
+
return null;
|
|
85
|
+
try {
|
|
86
|
+
return JSON.parse(raw);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* An exemption list as the order-minimum checker reads it: the column's non-empty string ids,
|
|
94
|
+
* once each; anything unreadable is no exemption.
|
|
95
|
+
*/
|
|
96
|
+
function readIdList(raw) {
|
|
97
|
+
return [...new Set(strings(parsedJson(raw)))];
|
|
98
|
+
}
|
|
99
|
+
const LIST_OF = {
|
|
100
|
+
product: 'productVariantIds',
|
|
101
|
+
coupon: 'couponCodes',
|
|
102
|
+
collection: 'collectionIds',
|
|
103
|
+
facet_value: 'facetValueIds',
|
|
104
|
+
};
|
|
105
|
+
const TARGET_STATES = new Set(ORDER_STATUS_RULE_TARGET_STATES);
|
|
106
|
+
const CONDITION_TYPES = new Set(ORDER_STATUS_RULE_CONDITION_TYPES);
|
|
107
|
+
/**
|
|
108
|
+
* The column as the engine's `parseRules` keeps it: an entry with a string `id`, a known
|
|
109
|
+
* `targetState` and a known `conditionType`. A rule the engine keeps is never dropped here (a
|
|
110
|
+
* stricter reader would erase it on the next save, turning off the transition it performs), so
|
|
111
|
+
* a missing `name` reads `''` and `enabled` reads as the engine takes it (truthy fires). Only the
|
|
112
|
+
* rule's own keys come back, so the list can be sent back as the engine's schema wants it.
|
|
113
|
+
*/
|
|
114
|
+
export function readOrderStatusRules(raw) {
|
|
115
|
+
const parsed = parsedJson(raw);
|
|
116
|
+
if (!Array.isArray(parsed))
|
|
117
|
+
return [];
|
|
118
|
+
const rules = [];
|
|
119
|
+
for (const entry of parsed) {
|
|
120
|
+
if (!isRecord(entry))
|
|
121
|
+
continue;
|
|
122
|
+
const { id, targetState, conditionType } = entry;
|
|
123
|
+
if (typeof id !== 'string' || !TARGET_STATES.has(targetState))
|
|
124
|
+
continue;
|
|
125
|
+
if (!CONDITION_TYPES.has(conditionType))
|
|
126
|
+
continue;
|
|
127
|
+
const rule = {
|
|
128
|
+
id,
|
|
129
|
+
name: typeof entry.name === 'string' ? entry.name : '',
|
|
130
|
+
targetState: targetState,
|
|
131
|
+
conditionType: conditionType,
|
|
132
|
+
enabled: Boolean(entry.enabled),
|
|
133
|
+
};
|
|
134
|
+
for (const list of Object.values(LIST_OF)) {
|
|
135
|
+
if (Array.isArray(entry[list]))
|
|
136
|
+
rule[list] = strings(entry[list]);
|
|
137
|
+
}
|
|
138
|
+
rules.push(rule);
|
|
139
|
+
}
|
|
140
|
+
return rules;
|
|
141
|
+
}
|
|
142
|
+
/** An age the engine checks (`minimumAge > 0`), else none. */
|
|
143
|
+
const checkedAge = (age) => (age !== null && age > 0 ? age : null);
|
|
144
|
+
function sourceOf(sources, own) {
|
|
145
|
+
const group = sources.find((item) => item.group === AGE_GROUP);
|
|
146
|
+
if (!group) {
|
|
147
|
+
return {
|
|
148
|
+
source: 'channel',
|
|
149
|
+
locked: false,
|
|
150
|
+
inheritable: false,
|
|
151
|
+
overridden: false,
|
|
152
|
+
effective: checkedAge(own),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
// The store's own value when its own applies: after `set` the sources are the ones read BEFORE
|
|
156
|
+
// the write, so their values would answer the old age. The organization's values otherwise.
|
|
157
|
+
const applied = group.source !== 'channel' && group.values ? numberOrNull(group.values.minimumAge) : own;
|
|
158
|
+
return {
|
|
159
|
+
source: group.source,
|
|
160
|
+
locked: group.locked,
|
|
161
|
+
inheritable: group.inheritable,
|
|
162
|
+
overridden: group.overridden,
|
|
163
|
+
effective: checkedAge(applied),
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
function settingsOf(channel, sources) {
|
|
167
|
+
const fields = channel.customFields ?? {};
|
|
168
|
+
const minimumAge = numberOrNull(fields.minimumAge);
|
|
169
|
+
return {
|
|
170
|
+
channelId: channel.id,
|
|
171
|
+
currencyCode: channel.defaultCurrencyCode,
|
|
172
|
+
minOrderAmount: numberOrNull(fields.minOrderAmount),
|
|
173
|
+
exemptCustomerGroupIds: readIdList(fields.exemptCustomerGroupIds),
|
|
174
|
+
exemptCollectionIds: readIdList(fields.exemptCollectionIds),
|
|
175
|
+
orderCodeEnabled: fields.orderCodeEnabled === true,
|
|
176
|
+
orderCodeNamespace: stringOrNull(fields.orderCodeNamespace) || null,
|
|
177
|
+
orderCodePrefix: stringOrNull(fields.orderCodePrefix),
|
|
178
|
+
orderCodeDigits: numberOrNull(fields.orderCodeDigits),
|
|
179
|
+
minimumAge,
|
|
180
|
+
minimumAgeSource: sourceOf(sources, minimumAge),
|
|
181
|
+
orderStatusRules: readOrderStatusRules(fields.orderStatusRules),
|
|
182
|
+
outstandingBalanceWarningThreshold: numberOrNull(fields.outstandingBalanceWarningThreshold),
|
|
183
|
+
outstandingBalanceCriticalThreshold: numberOrNull(fields.outstandingBalanceCriticalThreshold),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
const PATCH_KEYS = [
|
|
187
|
+
'minOrderAmount',
|
|
188
|
+
'exemptCustomerGroupIds',
|
|
189
|
+
'exemptCollectionIds',
|
|
190
|
+
'orderCodeEnabled',
|
|
191
|
+
'orderCodePrefix',
|
|
192
|
+
'orderCodeDigits',
|
|
193
|
+
'minimumAge',
|
|
194
|
+
'orderStatusRules',
|
|
195
|
+
'outstandingBalanceWarningThreshold',
|
|
196
|
+
'outstandingBalanceCriticalThreshold',
|
|
197
|
+
];
|
|
198
|
+
const KNOWN_KEYS = new Set(PATCH_KEYS);
|
|
199
|
+
const AMOUNT_KEYS = [
|
|
200
|
+
'minOrderAmount',
|
|
201
|
+
'outstandingBalanceWarningThreshold',
|
|
202
|
+
'outstandingBalanceCriticalThreshold',
|
|
203
|
+
];
|
|
204
|
+
const LIST_KEYS = ['exemptCustomerGroupIds', 'exemptCollectionIds', 'orderStatusRules'];
|
|
205
|
+
/** Every way `patch` breaks the input's shape, one entry per key. */
|
|
206
|
+
function problemsOf(patch) {
|
|
207
|
+
const problems = [];
|
|
208
|
+
const add = (field, message) => problems.push({ field, code: INVALID, message });
|
|
209
|
+
if (!isRecord(patch)) {
|
|
210
|
+
add('patch', 'Pass the settings to change as an object, e.g. { minOrderAmount: 5000 }.');
|
|
211
|
+
return problems;
|
|
212
|
+
}
|
|
213
|
+
const named = Object.keys(patch).filter((key) => patch[key] !== undefined);
|
|
214
|
+
if (named.length === 0) {
|
|
215
|
+
add('patch', `Name at least one setting to change: ${PATCH_KEYS.join(', ')}.`);
|
|
216
|
+
}
|
|
217
|
+
for (const key of named) {
|
|
218
|
+
if (KNOWN_KEYS.has(key))
|
|
219
|
+
continue;
|
|
220
|
+
add(key, key === 'orderCodeNamespace'
|
|
221
|
+
? 'orderCodeNamespace is set by the platform from the store code, never by a caller: switch orderCodeEnabled on and it is set for you.'
|
|
222
|
+
: `${key} is not an order setting; the settings are ${PATCH_KEYS.join(', ')}.`);
|
|
223
|
+
}
|
|
224
|
+
for (const key of AMOUNT_KEYS) {
|
|
225
|
+
const value = patch[key];
|
|
226
|
+
if (value === undefined || value === null)
|
|
227
|
+
continue;
|
|
228
|
+
if (!(isWhole(value) && value >= 0 && value <= ORDER_SETTINGS_AMOUNT_MAX)) {
|
|
229
|
+
add(key, `${key} must be a whole number of minor units from 0 to ${String(ORDER_SETTINGS_AMOUNT_MAX)}, or null to clear it.`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
for (const key of LIST_KEYS) {
|
|
233
|
+
const value = patch[key];
|
|
234
|
+
if (value !== undefined && !Array.isArray(value)) {
|
|
235
|
+
add(key, `${key} must be an array (the whole list); send [] for none.`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (patch.orderCodeEnabled !== undefined && typeof patch.orderCodeEnabled !== 'boolean') {
|
|
239
|
+
add('orderCodeEnabled', 'orderCodeEnabled must be true or false.');
|
|
240
|
+
}
|
|
241
|
+
const prefix = patch.orderCodePrefix;
|
|
242
|
+
if (prefix !== undefined &&
|
|
243
|
+
prefix !== null &&
|
|
244
|
+
!(typeof prefix === 'string' && prefix.length <= ORDER_CODE_PREFIX_MAX_LENGTH)) {
|
|
245
|
+
add('orderCodePrefix', `orderCodePrefix must be text of at most ${String(ORDER_CODE_PREFIX_MAX_LENGTH)} characters, or null for none.`);
|
|
246
|
+
}
|
|
247
|
+
const digits = patch.orderCodeDigits;
|
|
248
|
+
if (digits !== undefined &&
|
|
249
|
+
digits !== null &&
|
|
250
|
+
!(isWhole(digits) && digits >= ORDER_CODE_DIGITS_MIN && digits <= ORDER_CODE_DIGITS_MAX)) {
|
|
251
|
+
add('orderCodeDigits', `orderCodeDigits must be a whole number from ${String(ORDER_CODE_DIGITS_MIN)} to ${String(ORDER_CODE_DIGITS_MAX)}, or null for the default.`);
|
|
252
|
+
}
|
|
253
|
+
const age = patch.minimumAge;
|
|
254
|
+
if (age !== undefined &&
|
|
255
|
+
age !== null &&
|
|
256
|
+
!(isWhole(age) && age >= MINIMUM_AGE_MIN && age <= MINIMUM_AGE_MAX)) {
|
|
257
|
+
add('minimumAge', `minimumAge must be a whole number of years from ${String(MINIMUM_AGE_MIN)} to ${String(MINIMUM_AGE_MAX)}, or null for no age check.`);
|
|
258
|
+
}
|
|
259
|
+
return problems;
|
|
260
|
+
}
|
|
261
|
+
/** A list column as the engine stores it: JSON text, or null for an empty list. */
|
|
262
|
+
const listColumn = (list) => list.length > 0 ? JSON.stringify(list) : null;
|
|
263
|
+
/** The custom fields `patch` writes; `before` is the store as read just before. */
|
|
264
|
+
function customFieldsOf(patch, before) {
|
|
265
|
+
const fields = {};
|
|
266
|
+
for (const key of PATCH_KEYS) {
|
|
267
|
+
const value = patch[key];
|
|
268
|
+
if (value === undefined)
|
|
269
|
+
continue;
|
|
270
|
+
fields[key] = Array.isArray(value) ? listColumn(value) : value;
|
|
271
|
+
}
|
|
272
|
+
// Ruling G125: the namespace is the platform's, never the caller's. A store switching
|
|
273
|
+
// sequential numbers on for the first time gets its code in capitals, which is what
|
|
274
|
+
// provisioning gives a new store (`provision-store.saga.ts`) and is unique because codes are.
|
|
275
|
+
const namespace = stringOrNull(before.customFields?.orderCodeNamespace);
|
|
276
|
+
if (patch.orderCodeEnabled === true && !namespace) {
|
|
277
|
+
fields.orderCodeNamespace = before.code.toUpperCase();
|
|
278
|
+
}
|
|
279
|
+
return fields;
|
|
280
|
+
}
|
|
281
|
+
export function createOrderSettingsModule(transport) {
|
|
282
|
+
const read = async (options) => {
|
|
283
|
+
const data = await transport.graphql({ api: 'admin', query: ORDER_SETTINGS_QUERY }, options);
|
|
284
|
+
if (!data.activeChannel) {
|
|
285
|
+
throw new NotFoundError({
|
|
286
|
+
code: 'CHANNEL_NOT_FOUND',
|
|
287
|
+
message: 'No store is active for this session, so it has no order settings to read.',
|
|
288
|
+
status: 404,
|
|
289
|
+
service: 'vendure',
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
return { channel: data.activeChannel, sources: data.channelSettingsSources ?? [] };
|
|
293
|
+
};
|
|
294
|
+
return {
|
|
295
|
+
async get(options) {
|
|
296
|
+
const { channel, sources } = await read(options);
|
|
297
|
+
return settingsOf(channel, sources);
|
|
298
|
+
},
|
|
299
|
+
async set(patch, options) {
|
|
300
|
+
const problems = problemsOf(patch);
|
|
301
|
+
if (problems.length > 0) {
|
|
302
|
+
throw new ValidationError({
|
|
303
|
+
code: INVALID,
|
|
304
|
+
message: problems.map((problem) => problem.message).join(' '),
|
|
305
|
+
status: 400,
|
|
306
|
+
service: 'vendure',
|
|
307
|
+
details: problems,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
// The id `updateChannel` needs and the namespace rule's "before", read with the SAME call
|
|
311
|
+
// options, so a per-call tenant writes its own store rather than the client's.
|
|
312
|
+
const { channel, sources } = await read(options);
|
|
313
|
+
const data = await transport.graphql({
|
|
314
|
+
api: 'admin',
|
|
315
|
+
query: UPDATE_ORDER_SETTINGS_MUTATION,
|
|
316
|
+
variables: { input: { id: channel.id, customFields: customFieldsOf(patch, channel) } },
|
|
317
|
+
}, options);
|
|
318
|
+
if (isErrorResult(data.updateChannel))
|
|
319
|
+
throw errorFromErrorResult(data.updateChannel);
|
|
320
|
+
// An order settings write never changes where the age comes from, so the sources read
|
|
321
|
+
// just before still hold; `sourceOf` takes the new own value when the store's applies.
|
|
322
|
+
return settingsOf(data.updateChannel, sources);
|
|
323
|
+
},
|
|
324
|
+
};
|
|
325
|
+
}
|
package/dist/orders/status.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export type OrderAllocationBadge = (typeof ORDER_ALLOCATION_BADGES)[number];
|
|
|
34
34
|
export declare const ORDER_EDIT_BLOCK_CODES: readonly ["INVOICE_LOCKED", "COMPLETED", "CANCELLED"];
|
|
35
35
|
export type OrderEditBlockCode = (typeof ORDER_EDIT_BLOCK_CODES)[number];
|
|
36
36
|
/** The actions the engine answers for, in the order it lists them. */
|
|
37
|
-
export declare const ORDER_STATUS_ACTIONS: readonly ["MODIFY", "DELETE", "RELEASE_ALLOCATION", "CORRECT_FULFILLMENT", "CANCEL", "TRANSITION", "MARK_COMPLETED", "REOPEN"];
|
|
37
|
+
export declare const ORDER_STATUS_ACTIONS: readonly ["MODIFY", "DELETE", "RELEASE_ALLOCATION", "CORRECT_FULFILLMENT", "CANCEL", "TRANSITION", "MARK_COMPLETED", "REOPEN", "SET_PAYMENT_NOT_REQUIRED", "SET_FULFILLMENT_HOLD", "SET_GOODWILL_ROUNDING", "SET_BILLING_FIELDS", "APPLY_GOODWILL_ROUNDING", "SET_PRICING_FIELDS"];
|
|
38
38
|
/**
|
|
39
39
|
* One thing that can be done to an order, with the engine write behind it and
|
|
40
40
|
* what `allowed` asks of the caller:
|
|
@@ -56,14 +56,76 @@ export declare const ORDER_STATUS_ACTIONS: readonly ["MODIFY", "DELETE", "RELEAS
|
|
|
56
56
|
* locations (an API token or app installation with `locationIds`) must also
|
|
57
57
|
* hold every location the order's reservation sits at; otherwise the release
|
|
58
58
|
* answers `LOCATION_NOT_ALLOWED` and this action `PERMISSION`.
|
|
59
|
-
* - `CANCEL`: `cancelOrder` for the whole order. Needs `UpdateOrder`.
|
|
59
|
+
* - `CANCEL`: `cancelOrder` for the whole order. Needs `UpdateOrder`. A credential
|
|
60
|
+
* restricted to stock locations must also hold every location the order's
|
|
61
|
+
* reservation sits at (a cancel releases it there); otherwise the cancel answers
|
|
62
|
+
* `LOCATION_OUT_OF_SCOPE` and this action `PERMISSION`.
|
|
60
63
|
* - `TRANSITION`: `transitionOrderToState` into one of `nextStates`. Needs
|
|
61
64
|
* `UpdateOrder`.
|
|
62
|
-
* - `MARK_COMPLETED`: `
|
|
63
|
-
* - `REOPEN`: `
|
|
65
|
+
* - `MARK_COMPLETED`: `orders.markCompleted`. Needs `UpdateOrder`.
|
|
66
|
+
* - `REOPEN`: `orders.reopen`. Needs `UpdateOrder`.
|
|
67
|
+
* - `SET_PAYMENT_NOT_REQUIRED`: `orders.setPaymentNotRequired`, in the direction it would go
|
|
68
|
+
* next: lifting the waiver while the order carries one (`lifecycle.payment` then reads
|
|
69
|
+
* `not_required`), waiving it otherwise. A cancelled order changes neither way (`CANCELLED`);
|
|
70
|
+
* an order whose payment reads `not_required` without a waiver (a total of 0) has nothing to
|
|
71
|
+
* waive or lift (`STATE`); a waiver waits while an invoice still bills the order
|
|
72
|
+
* (`CREDIT_NOTE_REQUIRED`). The write refuses the `CANCELLED` and `CREDIT_NOTE_REQUIRED`
|
|
73
|
+
* cases, `ORDER_PAYMENT_WAIVER_REFUSED`; it takes a waiver on a zero-total order, which this
|
|
74
|
+
* action does not offer. Needs `UpdateOrder`.
|
|
75
|
+
* - `SET_FULFILLMENT_HOLD`: `orders.setFulfillmentHold`, in the direction it would go next: a
|
|
76
|
+
* release while `lifecycle.fulfillment` is `on_hold` (any order but a live cart), a new hold
|
|
77
|
+
* only on an open order (`STATE` otherwise). Needs `UpdateOrder`.
|
|
78
|
+
* - `SET_GOODWILL_ROUNDING`: `orders.setGoodwillRounding`, either way (apply or clear). Closed
|
|
79
|
+
* once the order's total no longer moves: an invoice bills it (`INVOICE_LOCKED`), it is
|
|
80
|
+
* completed or cancelled (`COMPLETED`, `CANCELLED`), or it is settled or invoiced in the
|
|
81
|
+
* store's ERP (`ERP_LOCKED`); the write then refuses `GOODWILL_ROUNDING_LOCKED`. Whether
|
|
82
|
+
* there is anything to round (one VAT rate, a total that is not whole) is not answered here:
|
|
83
|
+
* applying to such an order is refused `GOODWILL_ROUNDING_NOT_APPLICABLE`. Needs
|
|
84
|
+
* `UpdateOrder`. Whether APPLYING one is open is `APPLY_GOODWILL_ROUNDING`.
|
|
85
|
+
* - `APPLY_GOODWILL_ROUNDING`: `orders.setGoodwillRounding` with `apply: true`. The same lock as
|
|
86
|
+
* `SET_GOODWILL_ROUNDING` first, then `LEAVES_MONEY_OVER`: the order is paid, and its payments
|
|
87
|
+
* would hold more than the rounded total; the write then refuses
|
|
88
|
+
* `GOODWILL_ROUNDING_LEAVES_MONEY_OVER`, because the rounding refunds nothing. Clearing a
|
|
89
|
+
* rounding stays `SET_GOODWILL_ROUNDING` alone. Needs `UpdateOrder`.
|
|
90
|
+
* - `SET_BILLING_FIELDS`: a change of `customFields.removeTax`, `paymentTermsDays` or
|
|
91
|
+
* `paymentConditionCode`, the order's fields that decide what it BILLS, through the engine's
|
|
92
|
+
* `setOrderCustomFields` or `setOrderRemoveTax`. Closed while a live invoice bills the order
|
|
93
|
+
* (`INVOICE_LOCKED`): its standard invoice not voided, or an accounts-receivable invoice
|
|
94
|
+
* neither voided nor superseded. The write then refuses `ORDER_INVOICE_LOCKED` (422), with
|
|
95
|
+
* the field in `details[].field` (a pointer into the arguments) and a sentence naming the
|
|
96
|
+
* invoice and its ledger in `details[].message`; what the order bills is changed through that
|
|
97
|
+
* invoice's correction (`documents.commitCorrection`). A value equal to the stored one is
|
|
98
|
+
* never refused, and notes and the order's reference (`orders.setPurchaseOrderNumber`) are
|
|
99
|
+
* not part of it. It answers those two writes only, and they store the value without
|
|
100
|
+
* recalculating the order. Applying it to the order's amounts (the order edit:
|
|
101
|
+
* `orders.planEdit`, `orders.commitEdit`), and changing a line's `unitPriceOverride` or
|
|
102
|
+
* `unitPriceImported`, which this lock refuses too, are also closed while `MODIFY` answers
|
|
103
|
+
* `INVOICE_LOCKED`, and that outlives the void of a retail invoice. The void opens the payment
|
|
104
|
+
* terms again, not `removeTax`: `SET_PRICING_FIELDS` answers that. Needs `UpdateOrder`.
|
|
105
|
+
* - `SET_PRICING_FIELDS`: a change of `customFields.removeTax`, or of a line's
|
|
106
|
+
* `unitPriceOverride` or `unitPriceImported`, the fields that decide the order's AMOUNTS, at
|
|
107
|
+
* the engine's custom-field writes (`setOrderCustomFields`, `setOrderRemoveTax`,
|
|
108
|
+
* `modifyOrder`, the draft line writes). Closed (`INVOICE_LOCKED`) while a live invoice bills
|
|
109
|
+
* the order, and while its content stays locked with none: after its retail invoice was
|
|
110
|
+
* voided, and on an order the platform it was imported from invoiced. Nothing recalculates
|
|
111
|
+
* such an order, so its tax and prices stay as invoiced. The write refuses
|
|
112
|
+
* `ORDER_INVOICE_LOCKED` (422) with the field in `details[].field` and the reason in
|
|
113
|
+
* `details[].message`. A value equal to the stored one is never refused; the payment terms
|
|
114
|
+
* are not part of it. Needs `UpdateOrder`.
|
|
115
|
+
*
|
|
116
|
+
* The two toggles are answered by engines from W10-25 on, the rounding from W10-26 on, and
|
|
117
|
+
* `SET_BILLING_FIELDS` and `SET_PRICING_FIELDS` from the engines that enforce them on; an older
|
|
118
|
+
* engine leaves them out of `actions`. For the first three that reads as "not available"; an
|
|
119
|
+
* engine that does not answer `SET_BILLING_FIELDS` does not lock those fields either, and one
|
|
120
|
+
* that does not answer `SET_PRICING_FIELDS` locks them only as `SET_BILLING_FIELDS` says. `APPLY_GOODWILL_ROUNDING` is answered
|
|
121
|
+
* by the engine that refuses a rounding on a paid order; an older one leaves it out and does not
|
|
122
|
+
* refuse it, so read a missing answer as "not available" (never offer the rounding on a guess).
|
|
64
123
|
* - `CORRECT_FULFILLMENT`: one of TWO writes, with different gates.
|
|
65
|
-
* - `updateFulfillmentLineQuantities`
|
|
66
|
-
* fulfillment of the order on any store.
|
|
124
|
+
* - `updateFulfillmentLineQuantities` (`orders.correctFulfillmentQuantities`) needs
|
|
125
|
+
* `UpdateOrder`, and corrects any fulfillment of the order on any store. A credential
|
|
126
|
+
* restricted to stock locations (an API token or app installation with `locationIds`)
|
|
127
|
+
* corrects only a fulfillment that ships from one of them (`LOCATION_OUT_OF_SCOPE`
|
|
128
|
+
* otherwise).
|
|
67
129
|
* - `correctFulfillmentQuantities` needs `UpdateFulfillment` or
|
|
68
130
|
* `UpdateOrder`, and works only on a store with the warehouse workspace
|
|
69
131
|
* (`WAREHOUSE_NOT_ENABLED` otherwise). For a caller without `UpdateOrder`
|
|
@@ -73,7 +135,8 @@ export declare const ORDER_STATUS_ACTIONS: readonly ["MODIFY", "DELETE", "RELEAS
|
|
|
73
135
|
* quantity (`OFFICE_ONLY`).
|
|
74
136
|
*
|
|
75
137
|
* So `allowed` is true for a caller with `UpdateOrder` whenever the order is
|
|
76
|
-
* eligible
|
|
138
|
+
* eligible, except a credential restricted to stock locations, for which it is true only
|
|
139
|
+
* while one of THIS order's fulfillments ships from one of its locations. For a caller holding `UpdateFulfillment` without `UpdateOrder`
|
|
77
140
|
* it is true only on a store with the warehouse workspace, and only while
|
|
78
141
|
* at least one of THIS order's fulfillments ships from one of the caller's
|
|
79
142
|
* warehouses. That caller must call `correctFulfillmentQuantities`: the
|
|
@@ -86,7 +149,7 @@ export declare const ORDER_STATUS_ACTIONS: readonly ["MODIFY", "DELETE", "RELEAS
|
|
|
86
149
|
*/
|
|
87
150
|
export type OrderStatusActionName = (typeof ORDER_STATUS_ACTIONS)[number];
|
|
88
151
|
/** Why an action is not allowed, in the order the engine lists them. */
|
|
89
|
-
export declare const ORDER_STATUS_REASON_CODES: readonly ["INVOICE_LOCKED", "COMPLETED", "CANCELLED", "STATE", "NOTHING_ALLOCATED", "HAS_RECORDS", "NOTHING_TO_CANCEL", "SHOPPER_CART", "UNITS_SHIPPED", "ACTIVE_FULFILLMENT", "PERMISSION"];
|
|
152
|
+
export declare const ORDER_STATUS_REASON_CODES: readonly ["INVOICE_LOCKED", "COMPLETED", "CANCELLED", "STATE", "NOTHING_ALLOCATED", "HAS_RECORDS", "NOTHING_TO_CANCEL", "SHOPPER_CART", "UNITS_SHIPPED", "ACTIVE_FULFILLMENT", "CREDIT_NOTE_REQUIRED", "HOLDS_MONEY", "ERP_LOCKED", "LEAVES_MONEY_OVER", "PERMISSION"];
|
|
90
153
|
/**
|
|
91
154
|
* - `INVOICE_LOCKED`, `COMPLETED`, `CANCELLED`: the edit block.
|
|
92
155
|
* - `STATE`: the order's state does not allow it.
|
|
@@ -104,6 +167,31 @@ export declare const ORDER_STATUS_REASON_CODES: readonly ["INVOICE_LOCKED", "COM
|
|
|
104
167
|
* units come back through a return.
|
|
105
168
|
* - `ACTIVE_FULFILLMENT`: a fulfillment not yet shipped holds a line. Detach
|
|
106
169
|
* the order from it or correct its quantities first.
|
|
170
|
+
* - `CREDIT_NOTE_REQUIRED` (`CANCEL` and `SET_PAYMENT_NOT_REQUIRED`): an invoice
|
|
171
|
+
* still bills the order, paid or not. For `SET_PAYMENT_NOT_REQUIRED`, correct
|
|
172
|
+
* the invoice first. For `CANCEL`, cancelling (whole or by lines) would leave
|
|
173
|
+
* the invoice standing. Do what {@link OrderStatusView.cancelCreditNote}'s `remedy`
|
|
174
|
+
* says first, then cancel: `CORRECT_INVOICE`, correct the invoice it names
|
|
175
|
+
* (`documents.commitCorrection` on its ledger: credit it in full, with a
|
|
176
|
+
* refund on a retail invoice); `REFUND_PAYMENT`, refund the order's settled
|
|
177
|
+
* payment (`payments.refund`), whose AR credit note corrects the invoice,
|
|
178
|
+
* and do NOT correct it as well (that credits the customer twice). Both cancel
|
|
179
|
+
* doors (`cancelOrder` and `orders.cancelWithMoney`) refuse
|
|
180
|
+
* `ORDER_CANCEL_CREDIT_NOTE_CONFLICT` (409) meanwhile. Named before
|
|
181
|
+
* `HOLDS_MONEY`.
|
|
182
|
+
* - `HOLDS_MONEY`: `CANCEL` only. The order has been placed or parked and
|
|
183
|
+
* still holds money, which a plain cancel would leave on it (the Admin
|
|
184
|
+
* `cancelOrder` refuses it `ORDER_HOLDS_MONEY`). Cancel it with
|
|
185
|
+
* `orders.cancelWithMoney`, or give its money back first: refund settled
|
|
186
|
+
* payments, cancel card holds (a hold released at the payment provider
|
|
187
|
+
* first where its payment method cannot). The value of spent gift cards
|
|
188
|
+
* sold on it is never given back: only `orders.cancelWithMoney`'s
|
|
189
|
+
* `retain` keeps it.
|
|
190
|
+
* - `ERP_LOCKED`: `SET_GOODWILL_ROUNDING` and `APPLY_GOODWILL_ROUNDING` only. The order is
|
|
191
|
+
* settled or invoiced in the store's ERP, which holds its total: correct it there.
|
|
192
|
+
* - `LEAVES_MONEY_OVER`: `APPLY_GOODWILL_ROUNDING` only. The order is paid: rounding its total
|
|
193
|
+
* down would leave the customer's money over the rounded total, which nothing pays back.
|
|
194
|
+
* Refund the customer instead.
|
|
107
195
|
* - `PERMISSION`: the order allows it and this caller may not. The only
|
|
108
196
|
* reason about the caller.
|
|
109
197
|
*/
|
|
@@ -147,13 +235,18 @@ export interface OrderStatusView {
|
|
|
147
235
|
locked: boolean;
|
|
148
236
|
reason: OrderLockReason | (string & {});
|
|
149
237
|
/**
|
|
150
|
-
* Set only when the reason is `INVOICE`: the live standard invoice,
|
|
151
|
-
*
|
|
238
|
+
* Set only when the reason is `INVOICE`: the live standard retail invoice,
|
|
239
|
+
* else the live accounts-receivable invoice billing the order, else a voided
|
|
240
|
+
* standard retail one (voiding a retail invoice does not unlock the order;
|
|
241
|
+
* an AR invoice locks only while it is live, so it is never voided here).
|
|
242
|
+
* `ledger` is `RETAIL` or `AR`: the ledger to correct it on
|
|
243
|
+
* (`documents.planCorrection`).
|
|
152
244
|
*/
|
|
153
245
|
lockingInvoice: {
|
|
154
246
|
id: string;
|
|
155
247
|
number: string;
|
|
156
248
|
voided: boolean;
|
|
249
|
+
ledger: 'RETAIL' | 'AR' | (string & {});
|
|
157
250
|
} | null;
|
|
158
251
|
};
|
|
159
252
|
/** Null when the order's content may change; the message is the one every edit is refused with. */
|
|
@@ -192,6 +285,12 @@ export interface OrderStatusView {
|
|
|
192
285
|
* fulfillment provider, and the store blocks shipping it again.
|
|
193
286
|
*/
|
|
194
287
|
sourceFulfilled: boolean;
|
|
288
|
+
/**
|
|
289
|
+
* Why `sourceFulfilled` is true, in words for staff (the source platform and its order
|
|
290
|
+
* number), the same sentence the warehouse demand carries; null when it is false. Show it as
|
|
291
|
+
* sent rather than composing one.
|
|
292
|
+
*/
|
|
293
|
+
sourceFulfilledReason: string | null;
|
|
195
294
|
/** Set while the order is parked. */
|
|
196
295
|
park: {
|
|
197
296
|
reason: string | null;
|
|
@@ -207,6 +306,13 @@ export interface OrderStatusView {
|
|
|
207
306
|
} | null;
|
|
208
307
|
/** Empty when the order runs on every provider the store assigned. */
|
|
209
308
|
providerFallbacks: OrderStatusProviderFallback[];
|
|
309
|
+
/**
|
|
310
|
+
* Set while a cancel (whole or by lines) waits for a credit note (`CANCEL` answers
|
|
311
|
+
* `CREDIT_NOTE_REQUIRED`, unless a more fundamental reason comes first).
|
|
312
|
+
* This SDK's document selects it, so against an engine older than the field
|
|
313
|
+
* `status` fails validation: deploy the engine first.
|
|
314
|
+
*/
|
|
315
|
+
cancelCreditNote: OrderStatusCancelCreditNote | null;
|
|
210
316
|
/**
|
|
211
317
|
* The states a change-status menu lists, in the engine's order: without
|
|
212
318
|
* `Cancelled` and `Modifying` (their own actions), without the cart phase,
|
|
@@ -216,7 +322,41 @@ export interface OrderStatusView {
|
|
|
216
322
|
nextStates: string[];
|
|
217
323
|
actions: OrderStatusAction[];
|
|
218
324
|
}
|
|
219
|
-
|
|
325
|
+
/**
|
|
326
|
+
* Why a cancel (whole or by lines) waits for a credit note: an invoice still
|
|
327
|
+
* bills the order, paid or not (cancelling would leave the invoice
|
|
328
|
+
* standing for revenue the order no longer has).
|
|
329
|
+
*/
|
|
330
|
+
export interface OrderStatusCancelCreditNote {
|
|
331
|
+
/** The `InvoiceCorrectionLedger` to correct the invoice on: `RETAIL` or `AR`. */
|
|
332
|
+
ledger: 'RETAIL' | 'AR' | (string & {});
|
|
333
|
+
/**
|
|
334
|
+
* What to do first. `CORRECT_INVOICE`: correct this invoice (credited in
|
|
335
|
+
* full; a `RETAIL` correction refunds along). `REFUND_PAYMENT`: refund the
|
|
336
|
+
* order's settled payment first (`payments.refund`): on an AR-invoiced
|
|
337
|
+
* order the refund issues the AR credit note that corrects the invoice, and
|
|
338
|
+
* correcting the invoice as well would credit the customer twice.
|
|
339
|
+
*/
|
|
340
|
+
remedy: 'CORRECT_INVOICE' | 'REFUND_PAYMENT' | (string & {});
|
|
341
|
+
invoiceId: string;
|
|
342
|
+
invoiceNumber: string;
|
|
343
|
+
/**
|
|
344
|
+
* What the invoice still bills the order for, in minor units of
|
|
345
|
+
* `currencyCode`: its total (on `AR`, the order's share) less its credit
|
|
346
|
+
* notes.
|
|
347
|
+
*/
|
|
348
|
+
uncredited: number;
|
|
349
|
+
/**
|
|
350
|
+
* What the order still holds, in minor units of `currencyCode`: its settled
|
|
351
|
+
* payments less what went back, or the receipts on its live
|
|
352
|
+
* accounts-receivable invoices, whichever is larger (a collected direct
|
|
353
|
+
* debit records the same money on both).
|
|
354
|
+
*/
|
|
355
|
+
held: number;
|
|
356
|
+
/** The order's currency. */
|
|
357
|
+
currencyCode: string;
|
|
358
|
+
}
|
|
359
|
+
export declare const ORDER_STATUS_QUERY = "\n query OrderStatus($orderId: ID!) {\n orderStatus(orderId: $orderId) {\n orderId\n state\n lifecycle {\n status\n payment\n fulfillment\n return\n }\n lock {\n locked\n reason\n lockingInvoice {\n id\n number\n voided\n ledger\n }\n }\n editBlock {\n code\n message\n }\n modifiable\n deletable\n releasableUnits\n releaseAllowed\n allocationBadge\n fulfillmentCorrection {\n blocked\n code\n }\n sourceFulfilled\n sourceFulfilledReason\n park {\n reason\n }\n hold {\n forReview\n byApp\n }\n providerFallbacks {\n kind\n installationId\n reason\n since\n }\n cancelCreditNote {\n ledger\n remedy\n invoiceId\n invoiceNumber\n uncredited\n held\n currencyCode\n }\n nextStates\n actions {\n action\n eligible\n allowed\n reasonCode\n }\n }\n }\n";
|
|
220
360
|
export interface OrderStatusModule {
|
|
221
361
|
/**
|
|
222
362
|
* Why the order is the way it is, and the actions open to this caller.
|
|
@@ -227,8 +367,14 @@ export interface OrderStatusModule {
|
|
|
227
367
|
* the ORDER allows it (`eligible`) and whether THIS caller may take it now
|
|
228
368
|
* (`allowed`), so a head can show an action greyed out with its reason.
|
|
229
369
|
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
370
|
+
* An order a live accounts-receivable invoice bills is invoice-locked like a
|
|
371
|
+
* retail-invoiced one (`INVOICE_LOCKED`, `lock.lockingInvoice.ledger: 'AR'`).
|
|
372
|
+
*
|
|
373
|
+
* Needs an engine that serves `orderStatus` with `cancelCreditNote`,
|
|
374
|
+
* `lock.lockingInvoice.ledger` and `sourceFulfilledReason`; against an older
|
|
375
|
+
* one this call fails validation and nothing else does.
|
|
376
|
+
*
|
|
377
|
+
* @effect read
|
|
232
378
|
*/
|
|
233
379
|
status(orderId: string, options?: Call): Promise<OrderStatusView>;
|
|
234
380
|
}
|
package/dist/orders/status.js
CHANGED
|
@@ -14,6 +14,12 @@ export const ORDER_STATUS_ACTIONS = [
|
|
|
14
14
|
'TRANSITION',
|
|
15
15
|
'MARK_COMPLETED',
|
|
16
16
|
'REOPEN',
|
|
17
|
+
'SET_PAYMENT_NOT_REQUIRED',
|
|
18
|
+
'SET_FULFILLMENT_HOLD',
|
|
19
|
+
'SET_GOODWILL_ROUNDING',
|
|
20
|
+
'SET_BILLING_FIELDS',
|
|
21
|
+
'APPLY_GOODWILL_ROUNDING',
|
|
22
|
+
'SET_PRICING_FIELDS',
|
|
17
23
|
];
|
|
18
24
|
/** Why an action is not allowed, in the order the engine lists them. */
|
|
19
25
|
export const ORDER_STATUS_REASON_CODES = [
|
|
@@ -27,6 +33,10 @@ export const ORDER_STATUS_REASON_CODES = [
|
|
|
27
33
|
'SHOPPER_CART',
|
|
28
34
|
'UNITS_SHIPPED',
|
|
29
35
|
'ACTIVE_FULFILLMENT',
|
|
36
|
+
'CREDIT_NOTE_REQUIRED',
|
|
37
|
+
'HOLDS_MONEY',
|
|
38
|
+
'ERP_LOCKED',
|
|
39
|
+
'LEAVES_MONEY_OVER',
|
|
30
40
|
'PERMISSION',
|
|
31
41
|
];
|
|
32
42
|
export const ORDER_STATUS_QUERY = /* GraphQL */ `
|
|
@@ -47,6 +57,7 @@ export const ORDER_STATUS_QUERY = /* GraphQL */ `
|
|
|
47
57
|
id
|
|
48
58
|
number
|
|
49
59
|
voided
|
|
60
|
+
ledger
|
|
50
61
|
}
|
|
51
62
|
}
|
|
52
63
|
editBlock {
|
|
@@ -63,6 +74,7 @@ export const ORDER_STATUS_QUERY = /* GraphQL */ `
|
|
|
63
74
|
code
|
|
64
75
|
}
|
|
65
76
|
sourceFulfilled
|
|
77
|
+
sourceFulfilledReason
|
|
66
78
|
park {
|
|
67
79
|
reason
|
|
68
80
|
}
|
|
@@ -76,6 +88,15 @@ export const ORDER_STATUS_QUERY = /* GraphQL */ `
|
|
|
76
88
|
reason
|
|
77
89
|
since
|
|
78
90
|
}
|
|
91
|
+
cancelCreditNote {
|
|
92
|
+
ledger
|
|
93
|
+
remedy
|
|
94
|
+
invoiceId
|
|
95
|
+
invoiceNumber
|
|
96
|
+
uncredited
|
|
97
|
+
held
|
|
98
|
+
currencyCode
|
|
99
|
+
}
|
|
79
100
|
nextStates
|
|
80
101
|
actions {
|
|
81
102
|
action
|