@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.
Files changed (302) hide show
  1. package/README.md +5772 -118
  2. package/dist/auth/index.d.ts +7 -1
  3. package/dist/auth/index.js +8 -1
  4. package/dist/catalog/assets.d.ts +120 -8
  5. package/dist/catalog/assets.js +98 -12
  6. package/dist/catalog/collections.d.ts +279 -14
  7. package/dist/catalog/collections.js +246 -15
  8. package/dist/catalog/documents.d.ts +142 -0
  9. package/dist/catalog/documents.js +114 -0
  10. package/dist/catalog/index.d.ts +54 -6
  11. package/dist/catalog/index.js +10 -1
  12. package/dist/catalog/metadata.d.ts +244 -0
  13. package/dist/catalog/metadata.js +220 -0
  14. package/dist/catalog/products.d.ts +159 -19
  15. package/dist/catalog/products.js +88 -13
  16. package/dist/catalog/properties.d.ts +140 -14
  17. package/dist/catalog/properties.js +65 -1
  18. package/dist/catalog/recommendations.d.ts +288 -0
  19. package/dist/catalog/recommendations.js +237 -0
  20. package/dist/catalog/reviews.d.ts +381 -0
  21. package/dist/catalog/reviews.js +325 -0
  22. package/dist/catalog/types.d.ts +17 -1
  23. package/dist/catalog/types.js +10 -0
  24. package/dist/catalog/variant-find.d.ts +136 -0
  25. package/dist/catalog/variant-find.js +239 -0
  26. package/dist/catalog/variants.d.ts +293 -26
  27. package/dist/catalog/variants.js +164 -7
  28. package/dist/catalog/visibility.d.ts +38 -7
  29. package/dist/catalog/visibility.js +19 -1
  30. package/dist/client.d.ts +121 -9
  31. package/dist/client.js +53 -14
  32. package/dist/content/assets.d.ts +285 -0
  33. package/dist/content/assets.js +181 -0
  34. package/dist/content/forms.d.ts +332 -1
  35. package/dist/content/forms.js +140 -4
  36. package/dist/content/items.d.ts +292 -0
  37. package/dist/content/items.js +170 -0
  38. package/dist/content/menus.d.ts +254 -0
  39. package/dist/content/menus.js +70 -0
  40. package/dist/content/strings.d.ts +137 -0
  41. package/dist/content/strings.js +82 -0
  42. package/dist/content/types.d.ts +282 -0
  43. package/dist/content/types.js +100 -0
  44. package/dist/customers/age-verification.d.ts +66 -0
  45. package/dist/customers/age-verification.js +79 -0
  46. package/dist/customers/credit.d.ts +263 -0
  47. package/dist/customers/credit.js +244 -0
  48. package/dist/customers/delivery-preferences.d.ts +120 -0
  49. package/dist/customers/delivery-preferences.js +97 -0
  50. package/dist/customers/delivery-terms.d.ts +44 -0
  51. package/dist/customers/delivery-terms.js +32 -0
  52. package/dist/customers/groups.d.ts +207 -0
  53. package/dist/customers/groups.js +438 -0
  54. package/dist/customers/index.d.ts +462 -37
  55. package/dist/customers/index.js +317 -40
  56. package/dist/customers/invitation-status.d.ts +57 -0
  57. package/dist/customers/invitation-status.js +21 -0
  58. package/dist/customers/notes.d.ts +67 -0
  59. package/dist/customers/notes.js +51 -0
  60. package/dist/customers/notification-recipients.d.ts +97 -0
  61. package/dist/customers/notification-recipients.js +84 -0
  62. package/dist/customers/saved-lists.d.ts +42 -0
  63. package/dist/customers/saved-lists.js +61 -0
  64. package/dist/customers/vat.d.ts +83 -0
  65. package/dist/customers/vat.js +46 -0
  66. package/dist/customers/wire.d.ts +20 -0
  67. package/dist/customers/wire.js +35 -0
  68. package/dist/documents/ar.d.ts +307 -0
  69. package/dist/documents/ar.js +254 -0
  70. package/dist/documents/emails.d.ts +150 -0
  71. package/dist/documents/emails.js +220 -0
  72. package/dist/documents/index.d.ts +744 -21
  73. package/dist/documents/index.js +438 -24
  74. package/dist/documents/pdf.d.ts +2 -0
  75. package/dist/documents/pdf.js +11 -0
  76. package/dist/fulfillments/create.d.ts +167 -0
  77. package/dist/fulfillments/create.js +216 -0
  78. package/dist/fulfillments/index.d.ts +163 -11
  79. package/dist/fulfillments/index.js +135 -6
  80. package/dist/fulfillments/payment-policy.d.ts +64 -0
  81. package/dist/fulfillments/payment-policy.js +140 -0
  82. package/dist/fulfillments/warehouse.d.ts +724 -0
  83. package/dist/fulfillments/warehouse.js +914 -0
  84. package/dist/geo/index.d.ts +119 -0
  85. package/dist/geo/index.js +107 -0
  86. package/dist/index.d.ts +147 -39
  87. package/dist/index.js +51 -12
  88. package/dist/integrations/afas-actions.d.ts +234 -0
  89. package/dist/integrations/afas-actions.js +310 -0
  90. package/dist/integrations/afas-types.d.ts +483 -0
  91. package/dist/integrations/afas-types.js +5 -0
  92. package/dist/integrations/afas.d.ts +234 -0
  93. package/dist/integrations/afas.js +290 -0
  94. package/dist/integrations/connections.d.ts +103 -0
  95. package/dist/integrations/connections.js +55 -0
  96. package/dist/integrations/esp.d.ts +313 -0
  97. package/dist/integrations/esp.js +169 -0
  98. package/dist/integrations/exact-online-types.d.ts +965 -0
  99. package/dist/integrations/exact-online-types.js +6 -0
  100. package/dist/integrations/exact-online.d.ts +784 -0
  101. package/dist/integrations/exact-online.js +1089 -0
  102. package/dist/integrations/index.d.ts +44 -3
  103. package/dist/integrations/index.js +23 -3
  104. package/dist/integrations/pipeline-discoveries.d.ts +65 -0
  105. package/dist/integrations/pipeline-discoveries.js +65 -0
  106. package/dist/integrations/pipeline-keys.d.ts +13 -0
  107. package/dist/integrations/pipeline-keys.js +22 -0
  108. package/dist/integrations/pipeline-runs.d.ts +119 -0
  109. package/dist/integrations/pipeline-runs.js +87 -0
  110. package/dist/integrations/pipelines.d.ts +87 -15
  111. package/dist/integrations/pipelines.js +41 -22
  112. package/dist/integrations/price-import.d.ts +223 -0
  113. package/dist/integrations/price-import.js +124 -0
  114. package/dist/integrations/types.d.ts +367 -3
  115. package/dist/integrations/types.js +4 -3
  116. package/dist/locations/index.d.ts +66 -0
  117. package/dist/locations/index.js +31 -0
  118. package/dist/meta/index.d.ts +172 -0
  119. package/dist/metafields/index.d.ts +8 -1
  120. package/dist/metafields/index.js +10 -0
  121. package/dist/orders/cancel-with-money.d.ts +237 -0
  122. package/dist/orders/cancel-with-money.js +155 -0
  123. package/dist/orders/commit-edit.d.ts +23 -1
  124. package/dist/orders/commit-edit.js +19 -2
  125. package/dist/orders/deposit-policy.d.ts +3 -1
  126. package/dist/orders/drafts.d.ts +800 -0
  127. package/dist/orders/drafts.js +771 -0
  128. package/dist/orders/fields.d.ts +245 -0
  129. package/dist/orders/fields.js +188 -0
  130. package/dist/orders/get.d.ts +29 -19
  131. package/dist/orders/get.js +17 -8
  132. package/dist/orders/index.d.ts +66 -15
  133. package/dist/orders/index.js +25 -2
  134. package/dist/orders/lifecycle.d.ts +128 -0
  135. package/dist/orders/lifecycle.js +158 -0
  136. package/dist/orders/line-price-preview.d.ts +7 -2
  137. package/dist/orders/list.d.ts +243 -0
  138. package/dist/orders/list.js +487 -0
  139. package/dist/orders/manual-discounts.d.ts +13 -5
  140. package/dist/orders/manual-pricing.d.ts +5 -0
  141. package/dist/orders/money-view.d.ts +149 -0
  142. package/dist/orders/money-view.js +99 -0
  143. package/dist/orders/order-entry.d.ts +20 -7
  144. package/dist/orders/plan-edit.d.ts +34 -2
  145. package/dist/orders/plan-edit.js +112 -11
  146. package/dist/orders/settings.d.ts +201 -0
  147. package/dist/orders/settings.js +325 -0
  148. package/dist/orders/status.d.ts +159 -13
  149. package/dist/orders/status.js +21 -0
  150. package/dist/orders/surcharges.d.ts +20 -1
  151. package/dist/orders/surcharges.js +37 -11
  152. package/dist/payments/account-credit.d.ts +46 -0
  153. package/dist/payments/account-credit.js +42 -0
  154. package/dist/payments/ar.d.ts +292 -0
  155. package/dist/payments/ar.js +223 -0
  156. package/dist/payments/connected-account.d.ts +47 -0
  157. package/dist/payments/connected-account.js +61 -0
  158. package/dist/payments/credit-noted-fields.d.ts +19 -0
  159. package/dist/payments/credit-noted-fields.js +69 -0
  160. package/dist/payments/customer-consent.d.ts +30 -0
  161. package/dist/payments/customer-consent.js +49 -0
  162. package/dist/payments/index.d.ts +340 -19
  163. package/dist/payments/index.js +151 -1
  164. package/dist/payments/methods.d.ts +303 -8
  165. package/dist/payments/methods.js +337 -7
  166. package/dist/payments/mollie-methods.d.ts +159 -0
  167. package/dist/payments/mollie-methods.js +141 -0
  168. package/dist/payments/payment-links.d.ts +180 -0
  169. package/dist/payments/payment-links.js +97 -0
  170. package/dist/payments/provider-keys.d.ts +150 -0
  171. package/dist/payments/provider-keys.js +118 -0
  172. package/dist/payments/providers.d.ts +86 -11
  173. package/dist/payments/providers.js +29 -0
  174. package/dist/payments/requests.d.ts +147 -0
  175. package/dist/payments/requests.js +93 -0
  176. package/dist/payments/store-credit-fields.d.ts +15 -0
  177. package/dist/payments/store-credit-fields.js +51 -0
  178. package/dist/pickups/index.d.ts +106 -0
  179. package/dist/pickups/index.js +108 -0
  180. package/dist/platform/channels.d.ts +132 -0
  181. package/dist/platform/channels.js +128 -0
  182. package/dist/platform/email-gateways.d.ts +165 -0
  183. package/dist/platform/email-gateways.js +78 -0
  184. package/dist/platform/geo.d.ts +123 -0
  185. package/dist/platform/geo.js +144 -0
  186. package/dist/platform/tax.d.ts +162 -0
  187. package/dist/platform/tax.js +169 -0
  188. package/dist/pos/anomalies.d.ts +158 -0
  189. package/dist/pos/anomalies.js +64 -0
  190. package/dist/pos/assisted-selling.d.ts +79 -0
  191. package/dist/pos/assisted-selling.js +38 -0
  192. package/dist/pos/exchanges.d.ts +108 -0
  193. package/dist/pos/exchanges.js +22 -0
  194. package/dist/pos/gift-cards.d.ts +135 -0
  195. package/dist/pos/gift-cards.js +47 -0
  196. package/dist/pos/index.d.ts +2370 -58
  197. package/dist/pos/index.js +854 -7
  198. package/dist/pos/no-receipt.d.ts +94 -0
  199. package/dist/pos/no-receipt.js +25 -0
  200. package/dist/pos/offline-sales.d.ts +228 -0
  201. package/dist/pos/offline-sales.js +170 -0
  202. package/dist/pos/pay-by-link.d.ts +143 -0
  203. package/dist/pos/pay-by-link.js +57 -0
  204. package/dist/pos/quick-keys.d.ts +103 -0
  205. package/dist/pos/quick-keys.js +45 -0
  206. package/dist/pos/reports.d.ts +360 -0
  207. package/dist/pos/reports.js +62 -0
  208. package/dist/pos/returns.d.ts +244 -0
  209. package/dist/pos/returns.js +83 -0
  210. package/dist/pricing/bulk-coupons.d.ts +139 -0
  211. package/dist/pricing/bulk-coupons.js +112 -0
  212. package/dist/pricing/index.d.ts +174 -4
  213. package/dist/pricing/index.js +174 -1
  214. package/dist/pricing/price-lists.d.ts +606 -0
  215. package/dist/pricing/price-lists.js +600 -0
  216. package/dist/purchasing/alerts.d.ts +104 -0
  217. package/dist/purchasing/alerts.js +88 -0
  218. package/dist/purchasing/backorders.d.ts +61 -0
  219. package/dist/purchasing/backorders.js +92 -0
  220. package/dist/purchasing/cost.d.ts +110 -0
  221. package/dist/purchasing/cost.js +86 -0
  222. package/dist/purchasing/index.d.ts +54 -0
  223. package/dist/purchasing/index.js +24 -0
  224. package/dist/purchasing/links.d.ts +263 -0
  225. package/dist/purchasing/links.js +192 -0
  226. package/dist/purchasing/purchase-orders.d.ts +551 -0
  227. package/dist/purchasing/purchase-orders.js +491 -0
  228. package/dist/purchasing/receipts.d.ts +396 -0
  229. package/dist/purchasing/receipts.js +287 -0
  230. package/dist/purchasing/replenishment.d.ts +281 -0
  231. package/dist/purchasing/replenishment.js +240 -0
  232. package/dist/purchasing/returns.d.ts +273 -0
  233. package/dist/purchasing/returns.js +229 -0
  234. package/dist/purchasing/settings.d.ts +152 -0
  235. package/dist/purchasing/settings.js +181 -0
  236. package/dist/purchasing/suppliers.d.ts +476 -0
  237. package/dist/purchasing/suppliers.js +438 -0
  238. package/dist/quotes/index.d.ts +518 -0
  239. package/dist/quotes/index.js +439 -0
  240. package/dist/reports/index.d.ts +71 -8
  241. package/dist/reports/index.js +74 -11
  242. package/dist/returns/index.d.ts +675 -21
  243. package/dist/returns/index.js +756 -11
  244. package/dist/search/index.d.ts +76 -1
  245. package/dist/search/index.js +63 -0
  246. package/dist/seo/config.d.ts +128 -0
  247. package/dist/seo/config.js +95 -0
  248. package/dist/seo/redirects.d.ts +125 -0
  249. package/dist/seo/redirects.js +60 -1
  250. package/dist/seo/settings.d.ts +147 -0
  251. package/dist/seo/settings.js +209 -0
  252. package/dist/shipping/definitions.d.ts +29 -0
  253. package/dist/shipping/definitions.js +47 -0
  254. package/dist/shipping/fulfillment-profiles.d.ts +174 -0
  255. package/dist/shipping/fulfillment-profiles.js +104 -0
  256. package/dist/shipping/hendriks.d.ts +97 -0
  257. package/dist/shipping/hendriks.js +50 -0
  258. package/dist/shipping/index.d.ts +54 -0
  259. package/dist/shipping/index.js +27 -0
  260. package/dist/shipping/methods.d.ts +205 -0
  261. package/dist/shipping/methods.js +240 -0
  262. package/dist/shipping/myparcel.d.ts +668 -0
  263. package/dist/shipping/myparcel.js +466 -0
  264. package/dist/shipping/parcel-count-suggestion.d.ts +2 -0
  265. package/dist/shipping/parcel-rule.d.ts +6 -5
  266. package/dist/shipping/parcel-rule.js +21 -23
  267. package/dist/shipping/rate-tables.d.ts +324 -0
  268. package/dist/shipping/rate-tables.js +390 -0
  269. package/dist/shipping/ship-to-countries.d.ts +75 -0
  270. package/dist/shipping/ship-to-countries.js +47 -0
  271. package/dist/stock/by-location.d.ts +86 -0
  272. package/dist/stock/by-location.js +94 -0
  273. package/dist/stock/index.d.ts +18 -4
  274. package/dist/stock/index.js +7 -0
  275. package/dist/stock/locations.d.ts +144 -0
  276. package/dist/stock/locations.js +168 -0
  277. package/dist/stock/settings.d.ts +106 -0
  278. package/dist/stock/settings.js +103 -0
  279. package/dist/stock/transfers.d.ts +386 -52
  280. package/dist/stock/transfers.js +222 -17
  281. package/dist/stored-value/index.d.ts +312 -11
  282. package/dist/stored-value/index.js +223 -4
  283. package/dist/subscriptions/index.d.ts +682 -0
  284. package/dist/subscriptions/index.js +815 -0
  285. package/dist/tax/display-policy.d.ts +105 -0
  286. package/dist/tax/display-policy.js +84 -0
  287. package/dist/tax/index.d.ts +79 -1
  288. package/dist/tax/index.js +52 -0
  289. package/dist/tenant/email-style.d.ts +102 -0
  290. package/dist/tenant/email-style.js +72 -0
  291. package/dist/tenant/email-templates.d.ts +287 -0
  292. package/dist/tenant/email-templates.js +271 -0
  293. package/dist/tenant/notifications.d.ts +23 -17
  294. package/dist/tenant/settings-sources.d.ts +1 -1
  295. package/dist/tenant/time-zone.d.ts +17 -0
  296. package/dist/tenant/time-zone.js +11 -0
  297. package/dist/types.d.ts +50 -3
  298. package/dist/users/index.d.ts +3 -0
  299. package/dist/users/index.js +2 -0
  300. package/dist/users/warehouses.d.ts +50 -0
  301. package/dist/users/warehouses.js +51 -0
  302. 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
+ }
@@ -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`: `markOrderCompleted`. Needs `UpdateOrder`.
63
- * - `REOPEN`: `reopenOrder`. Needs `UpdateOrder`.
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` needs `UpdateOrder`, and corrects any
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. For a caller holding `UpdateFulfillment` without `UpdateOrder`
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, else a
151
- * voided standard one (voiding does not unlock the order).
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
- 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 }\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 park {\n reason\n }\n hold {\n forReview\n byApp\n }\n providerFallbacks {\n kind\n installationId\n reason\n since\n }\n nextStates\n actions {\n action\n eligible\n allowed\n reasonCode\n }\n }\n }\n";
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
- * Needs an engine that serves `orderStatus`; against an older one this call
231
- * fails validation and nothing else does.
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
  }
@@ -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