@sixtyninecommerce/admin 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/README.md +4598 -128
  2. package/dist/catalog/assets.d.ts +120 -8
  3. package/dist/catalog/assets.js +98 -12
  4. package/dist/catalog/collections.d.ts +279 -14
  5. package/dist/catalog/collections.js +246 -15
  6. package/dist/catalog/index.d.ts +9 -2
  7. package/dist/catalog/index.js +4 -0
  8. package/dist/catalog/products.d.ts +318 -17
  9. package/dist/catalog/products.js +182 -14
  10. package/dist/catalog/properties.d.ts +102 -14
  11. package/dist/catalog/properties.js +13 -0
  12. package/dist/catalog/recommendations.d.ts +261 -0
  13. package/dist/catalog/recommendations.js +145 -0
  14. package/dist/catalog/reviews.d.ts +368 -0
  15. package/dist/catalog/reviews.js +318 -0
  16. package/dist/catalog/types.d.ts +17 -1
  17. package/dist/catalog/types.js +10 -0
  18. package/dist/catalog/variant-find.d.ts +136 -0
  19. package/dist/catalog/variant-find.js +239 -0
  20. package/dist/catalog/variants.d.ts +282 -25
  21. package/dist/catalog/variants.js +173 -25
  22. package/dist/catalog/visibility.d.ts +20 -5
  23. package/dist/catalog/visibility.js +19 -1
  24. package/dist/client.d.ts +116 -9
  25. package/dist/client.js +41 -7
  26. package/dist/content/assets.d.ts +286 -0
  27. package/dist/content/assets.js +181 -0
  28. package/dist/content/items.d.ts +269 -0
  29. package/dist/content/items.js +170 -0
  30. package/dist/content/types.d.ts +282 -0
  31. package/dist/content/types.js +100 -0
  32. package/dist/customers/age-verification.d.ts +66 -0
  33. package/dist/customers/age-verification.js +79 -0
  34. package/dist/customers/credit.d.ts +263 -0
  35. package/dist/customers/credit.js +244 -0
  36. package/dist/customers/delivery-preferences.d.ts +120 -0
  37. package/dist/customers/delivery-preferences.js +97 -0
  38. package/dist/customers/groups.d.ts +207 -0
  39. package/dist/customers/groups.js +438 -0
  40. package/dist/customers/index.d.ts +447 -37
  41. package/dist/customers/index.js +313 -40
  42. package/dist/customers/invitation-status.d.ts +57 -0
  43. package/dist/customers/invitation-status.js +21 -0
  44. package/dist/customers/notes.d.ts +67 -0
  45. package/dist/customers/notes.js +51 -0
  46. package/dist/customers/notification-recipients.d.ts +97 -0
  47. package/dist/customers/notification-recipients.js +84 -0
  48. package/dist/customers/saved-lists.d.ts +42 -0
  49. package/dist/customers/saved-lists.js +61 -0
  50. package/dist/customers/vat.d.ts +83 -0
  51. package/dist/customers/vat.js +46 -0
  52. package/dist/customers/wire.d.ts +20 -0
  53. package/dist/customers/wire.js +35 -0
  54. package/dist/documents/ar.d.ts +307 -0
  55. package/dist/documents/ar.js +254 -0
  56. package/dist/documents/index.d.ts +731 -21
  57. package/dist/documents/index.js +436 -24
  58. package/dist/documents/pdf.d.ts +2 -0
  59. package/dist/documents/pdf.js +11 -0
  60. package/dist/fulfillments/create.d.ts +167 -0
  61. package/dist/fulfillments/create.js +216 -0
  62. package/dist/fulfillments/index.d.ts +121 -10
  63. package/dist/fulfillments/index.js +120 -2
  64. package/dist/fulfillments/payment-policy.d.ts +64 -0
  65. package/dist/fulfillments/payment-policy.js +140 -0
  66. package/dist/fulfillments/warehouse.d.ts +724 -0
  67. package/dist/fulfillments/warehouse.js +914 -0
  68. package/dist/geo/index.d.ts +119 -0
  69. package/dist/geo/index.js +107 -0
  70. package/dist/index.d.ts +129 -30
  71. package/dist/index.js +47 -9
  72. package/dist/integrations/afas-actions.d.ts +234 -0
  73. package/dist/integrations/afas-actions.js +310 -0
  74. package/dist/integrations/afas-types.d.ts +483 -0
  75. package/dist/integrations/afas-types.js +5 -0
  76. package/dist/integrations/afas.d.ts +234 -0
  77. package/dist/integrations/afas.js +290 -0
  78. package/dist/integrations/connections.d.ts +103 -0
  79. package/dist/integrations/connections.js +55 -0
  80. package/dist/integrations/esp.d.ts +313 -0
  81. package/dist/integrations/esp.js +169 -0
  82. package/dist/integrations/exact-online-types.d.ts +423 -0
  83. package/dist/integrations/exact-online-types.js +6 -0
  84. package/dist/integrations/exact-online.d.ts +248 -0
  85. package/dist/integrations/exact-online.js +376 -0
  86. package/dist/integrations/index.d.ts +40 -0
  87. package/dist/integrations/index.js +24 -0
  88. package/dist/integrations/pipeline-keys.d.ts +13 -0
  89. package/dist/integrations/pipeline-keys.js +22 -0
  90. package/dist/integrations/pipelines.d.ts +114 -0
  91. package/dist/integrations/pipelines.js +46 -0
  92. package/dist/integrations/types.d.ts +322 -0
  93. package/dist/integrations/types.js +8 -0
  94. package/dist/jobs/bulk-action-run.d.ts +11 -2
  95. package/dist/jobs/bulk-action-run.js +4 -5
  96. package/dist/locations/index.d.ts +66 -0
  97. package/dist/locations/index.js +31 -0
  98. package/dist/meta/index.d.ts +162 -0
  99. package/dist/orders/bulk.d.ts +75 -0
  100. package/dist/orders/bulk.js +150 -0
  101. package/dist/orders/cancel-with-money.d.ts +227 -0
  102. package/dist/orders/cancel-with-money.js +153 -0
  103. package/dist/orders/commit-edit.d.ts +7 -1
  104. package/dist/orders/commit-edit.js +5 -1
  105. package/dist/orders/deposit-policy.d.ts +103 -0
  106. package/dist/orders/deposit-policy.js +202 -0
  107. package/dist/orders/drafts.d.ts +800 -0
  108. package/dist/orders/drafts.js +771 -0
  109. package/dist/orders/fields.d.ts +245 -0
  110. package/dist/orders/fields.js +188 -0
  111. package/dist/orders/get.d.ts +29 -19
  112. package/dist/orders/get.js +17 -8
  113. package/dist/orders/index.d.ts +125 -5
  114. package/dist/orders/index.js +35 -2
  115. package/dist/orders/lifecycle.d.ts +128 -0
  116. package/dist/orders/lifecycle.js +158 -0
  117. package/dist/orders/line-price-preview.d.ts +7 -2
  118. package/dist/orders/list.d.ts +222 -0
  119. package/dist/orders/list.js +377 -0
  120. package/dist/orders/manual-discounts.d.ts +11 -2
  121. package/dist/orders/manual-discounts.js +2 -0
  122. package/dist/orders/manual-pricing.d.ts +5 -0
  123. package/dist/orders/order-entry.d.ts +20 -7
  124. package/dist/orders/plan-edit.d.ts +1 -1
  125. package/dist/orders/plan-edit.js +4 -1
  126. package/dist/orders/settings.d.ts +201 -0
  127. package/dist/orders/settings.js +325 -0
  128. package/dist/orders/status.d.ts +159 -13
  129. package/dist/orders/status.js +21 -0
  130. package/dist/orders/surcharges.d.ts +8 -1
  131. package/dist/orders/surcharges.js +3 -2
  132. package/dist/payments/account-credit.d.ts +30 -0
  133. package/dist/payments/account-credit.js +19 -0
  134. package/dist/payments/ar.d.ts +292 -0
  135. package/dist/payments/ar.js +223 -0
  136. package/dist/payments/connected-account.d.ts +47 -0
  137. package/dist/payments/connected-account.js +61 -0
  138. package/dist/payments/credit-noted-fields.d.ts +12 -0
  139. package/dist/payments/credit-noted-fields.js +37 -0
  140. package/dist/payments/index.d.ts +263 -10
  141. package/dist/payments/index.js +133 -1
  142. package/dist/payments/methods.d.ts +332 -0
  143. package/dist/payments/methods.js +363 -0
  144. package/dist/payments/mollie-methods.d.ts +159 -0
  145. package/dist/payments/mollie-methods.js +141 -0
  146. package/dist/payments/payment-links.d.ts +180 -0
  147. package/dist/payments/payment-links.js +97 -0
  148. package/dist/payments/provider-keys.d.ts +150 -0
  149. package/dist/payments/provider-keys.js +118 -0
  150. package/dist/payments/providers.d.ts +86 -11
  151. package/dist/payments/providers.js +29 -0
  152. package/dist/payments/requests.d.ts +144 -0
  153. package/dist/payments/requests.js +92 -0
  154. package/dist/payments/store-credit-fields.d.ts +15 -0
  155. package/dist/payments/store-credit-fields.js +51 -0
  156. package/dist/pickups/index.d.ts +104 -0
  157. package/dist/pickups/index.js +105 -0
  158. package/dist/platform/channels.d.ts +132 -0
  159. package/dist/platform/channels.js +128 -0
  160. package/dist/platform/geo.d.ts +123 -0
  161. package/dist/platform/geo.js +144 -0
  162. package/dist/platform/tax.d.ts +154 -0
  163. package/dist/platform/tax.js +139 -0
  164. package/dist/pos/anomalies.d.ts +158 -0
  165. package/dist/pos/anomalies.js +64 -0
  166. package/dist/pos/assisted-selling.d.ts +79 -0
  167. package/dist/pos/assisted-selling.js +38 -0
  168. package/dist/pos/exchanges.d.ts +103 -0
  169. package/dist/pos/exchanges.js +22 -0
  170. package/dist/pos/gift-cards.d.ts +135 -0
  171. package/dist/pos/gift-cards.js +47 -0
  172. package/dist/pos/index.d.ts +2125 -32
  173. package/dist/pos/index.js +742 -4
  174. package/dist/pos/no-receipt.d.ts +94 -0
  175. package/dist/pos/no-receipt.js +25 -0
  176. package/dist/pos/offline-sales.d.ts +187 -0
  177. package/dist/pos/offline-sales.js +116 -0
  178. package/dist/pos/pay-by-link.d.ts +143 -0
  179. package/dist/pos/pay-by-link.js +57 -0
  180. package/dist/pos/quick-keys.d.ts +103 -0
  181. package/dist/pos/quick-keys.js +45 -0
  182. package/dist/pos/reports.d.ts +360 -0
  183. package/dist/pos/reports.js +62 -0
  184. package/dist/pos/returns.d.ts +217 -0
  185. package/dist/pos/returns.js +53 -0
  186. package/dist/pricing/bulk-coupons.d.ts +139 -0
  187. package/dist/pricing/bulk-coupons.js +112 -0
  188. package/dist/pricing/index.d.ts +177 -4
  189. package/dist/pricing/index.js +176 -1
  190. package/dist/pricing/price-lists.d.ts +604 -0
  191. package/dist/pricing/price-lists.js +600 -0
  192. package/dist/pricing/vouchers.d.ts +103 -0
  193. package/dist/pricing/vouchers.js +69 -0
  194. package/dist/purchasing/alerts.d.ts +89 -0
  195. package/dist/purchasing/alerts.js +62 -0
  196. package/dist/purchasing/cost.d.ts +110 -0
  197. package/dist/purchasing/cost.js +86 -0
  198. package/dist/purchasing/index.d.ts +36 -0
  199. package/dist/purchasing/index.js +16 -0
  200. package/dist/purchasing/purchase-orders.d.ts +548 -0
  201. package/dist/purchasing/purchase-orders.js +491 -0
  202. package/dist/purchasing/replenishment.d.ts +281 -0
  203. package/dist/purchasing/replenishment.js +240 -0
  204. package/dist/purchasing/settings.d.ts +152 -0
  205. package/dist/purchasing/settings.js +181 -0
  206. package/dist/purchasing/suppliers.d.ts +476 -0
  207. package/dist/purchasing/suppliers.js +438 -0
  208. package/dist/quotes/index.d.ts +501 -0
  209. package/dist/quotes/index.js +439 -0
  210. package/dist/reports/index.d.ts +71 -8
  211. package/dist/reports/index.js +74 -11
  212. package/dist/returns/index.d.ts +818 -0
  213. package/dist/returns/index.js +844 -0
  214. package/dist/search/index.d.ts +174 -0
  215. package/dist/search/index.js +125 -0
  216. package/dist/shipping/definitions.d.ts +29 -0
  217. package/dist/shipping/definitions.js +47 -0
  218. package/dist/shipping/fulfillment-profiles.d.ts +174 -0
  219. package/dist/shipping/fulfillment-profiles.js +104 -0
  220. package/dist/shipping/hendriks.d.ts +97 -0
  221. package/dist/shipping/hendriks.js +50 -0
  222. package/dist/shipping/index.d.ts +48 -0
  223. package/dist/shipping/index.js +25 -0
  224. package/dist/shipping/methods.d.ts +198 -0
  225. package/dist/shipping/methods.js +240 -0
  226. package/dist/shipping/myparcel.d.ts +254 -0
  227. package/dist/shipping/myparcel.js +178 -0
  228. package/dist/shipping/parcel-count-suggestion.d.ts +2 -0
  229. package/dist/shipping/parcel-rule.d.ts +6 -5
  230. package/dist/shipping/parcel-rule.js +21 -23
  231. package/dist/shipping/rate-tables.d.ts +179 -0
  232. package/dist/shipping/rate-tables.js +184 -0
  233. package/dist/stock/index.d.ts +10 -3
  234. package/dist/stock/index.js +3 -0
  235. package/dist/stock/locations.d.ts +144 -0
  236. package/dist/stock/locations.js +168 -0
  237. package/dist/stock/transfers.d.ts +216 -43
  238. package/dist/stock/transfers.js +140 -13
  239. package/dist/stored-value/index.d.ts +214 -4
  240. package/dist/stored-value/index.js +152 -0
  241. package/dist/subscriptions/index.d.ts +682 -0
  242. package/dist/subscriptions/index.js +815 -0
  243. package/dist/tax/index.d.ts +76 -1
  244. package/dist/tax/index.js +50 -0
  245. package/dist/tenant/email-style.d.ts +102 -0
  246. package/dist/tenant/email-style.js +72 -0
  247. package/dist/tenant/email-templates.d.ts +66 -0
  248. package/dist/tenant/email-templates.js +54 -0
  249. package/dist/tenant/notifications.d.ts +23 -17
  250. package/dist/tenant/settings-sources.d.ts +1 -1
  251. package/dist/tenant/time-zone.d.ts +17 -0
  252. package/dist/tenant/time-zone.js +11 -0
  253. package/dist/types.d.ts +51 -4
  254. package/dist/users/index.d.ts +3 -0
  255. package/dist/users/index.js +2 -0
  256. package/dist/users/warehouses.d.ts +50 -0
  257. package/dist/users/warehouses.js +51 -0
  258. package/package.json +2 -2
@@ -1,9 +1,16 @@
1
1
  import { errorFromErrorResult, isErrorResult, NotFoundError, ValidationError, } from '@sixtyninecommerce/core';
2
+ import { storeCreditAware } from '../payments/store-credit-fields.js';
3
+ import { createFulfillmentCreateMethods } from './create.js';
4
+ import { createFulfillmentPaymentPolicyModule, } from './payment-policy.js';
5
+ import { createWarehouseFulfillmentsModule, } from './warehouse.js';
6
+ /** The longest override reason the engine stores. */
7
+ export const FULFILLMENT_COVERAGE_REASON_MAX_LENGTH = 500;
2
8
  /** Every field of `OrderOverpaymentOption`. */
3
9
  const OVERPAYMENT_OPTION_FIELDS = /* GraphQL */ `
4
10
  available
5
11
  code
6
12
  message
13
+ book
7
14
  `;
8
15
  /**
9
16
  * Its own document, like every call here: on an engine without the query this call alone fails
@@ -46,10 +53,86 @@ export const CANCEL_FULFILLMENT_MUTATION = /* GraphQL */ `
46
53
  amount
47
54
  currencyCode
48
55
  choice
56
+ book
49
57
  }
50
58
  }
51
59
  }
52
60
  `;
61
+ /** Every field of `OrderFulfillmentCoverageOverride`. */
62
+ const COVERAGE_OVERRIDE_FIELDS = /* GraphQL */ `
63
+ id
64
+ orderId
65
+ reason
66
+ actorKind
67
+ actorId
68
+ outstandingAtGrant
69
+ currencyCode
70
+ createdAt
71
+ active
72
+ `;
73
+ /** Its own document: on an engine without the query this call alone fails validation. */
74
+ export const ORDER_FULFILLMENT_COVERAGE_QUERY = /* GraphQL */ `
75
+ query OrderFulfillmentCoverage($orderId: ID!) {
76
+ orderFulfillmentCoverage(orderId: $orderId) {
77
+ orderId
78
+ orderCode
79
+ currencyCode
80
+ policyActive
81
+ covered
82
+ outstanding
83
+ exempt
84
+ exemptReason
85
+ allowed
86
+ override { ${COVERAGE_OVERRIDE_FIELDS} }
87
+ }
88
+ }
89
+ `;
90
+ /** `$idempotencyKey` is optional and left out of the variables when not given. */
91
+ export const ALLOW_UNCOVERED_FULFILLMENT_MUTATION = /* GraphQL */ `
92
+ mutation AllowUncoveredFulfillment($orderId: ID!, $reason: String!, $idempotencyKey: String) {
93
+ allowUncoveredFulfillment(orderId: $orderId, reason: $reason, idempotencyKey: $idempotencyKey) {
94
+ ${COVERAGE_OVERRIDE_FIELDS}
95
+ }
96
+ }
97
+ `;
98
+ function invalidCoverage(field, message) {
99
+ return new ValidationError({
100
+ code: 'FULFILLMENT_COVERAGE_OVERRIDE_INVALID',
101
+ message,
102
+ status: 400,
103
+ service: 'vendure',
104
+ details: [{ field, code: 'FULFILLMENT_COVERAGE_OVERRIDE_INVALID', message }],
105
+ });
106
+ }
107
+ function assertOrderId(orderId) {
108
+ if (typeof orderId !== 'string' || orderId.trim() === '') {
109
+ throw invalidCoverage('orderId', 'An order id is required.');
110
+ }
111
+ }
112
+ /** Refused before any request: the engine would refuse it the same way. */
113
+ function assertOverrideReason(reason) {
114
+ const text = typeof reason === 'string' ? reason.trim() : '';
115
+ if (text === '') {
116
+ throw invalidCoverage('reason', 'Say why this order may be handed over before it is paid: a reason is required.');
117
+ }
118
+ if (text.length > FULFILLMENT_COVERAGE_REASON_MAX_LENGTH) {
119
+ throw invalidCoverage('reason', `The reason is at most ${FULFILLMENT_COVERAGE_REASON_MAX_LENGTH} characters.`);
120
+ }
121
+ return text;
122
+ }
123
+ function toCoverageOverride(raw) {
124
+ return {
125
+ id: raw.id,
126
+ orderId: raw.orderId,
127
+ reason: raw.reason,
128
+ actorKind: raw.actorKind,
129
+ actorId: raw.actorId,
130
+ outstandingAtGrant: raw.outstandingAtGrant,
131
+ currencyCode: raw.currencyCode,
132
+ createdAt: raw.createdAt,
133
+ active: raw.active,
134
+ };
135
+ }
53
136
  const OVERPAYMENT_CHOICES = new Set([
54
137
  'REFUND',
55
138
  'ACCOUNT_CREDIT',
@@ -283,6 +366,9 @@ function assertLabelRequest(fulfillmentId, format) {
283
366
  }
284
367
  export function createFulfillmentsModule(transport) {
285
368
  return {
369
+ ...createFulfillmentCreateMethods(transport),
370
+ paymentPolicy: createFulfillmentPaymentPolicyModule(transport),
371
+ warehouse: createWarehouseFulfillmentsModule(transport),
286
372
  async parcelsOfOrder(orderId, options) {
287
373
  const data = await transport.graphql({ api: 'admin', query: ORDER_FULFILLMENT_PARCELS_QUERY, variables: { id: orderId } }, options);
288
374
  if (!data.order)
@@ -365,7 +451,7 @@ export function createFulfillmentsModule(transport) {
365
451
  if (typeof fulfillmentId !== 'string' || fulfillmentId.trim() === '') {
366
452
  throw invalidCancel('fulfillmentId', 'A fulfillment id is required.');
367
453
  }
368
- const data = await transport.graphql({ api: 'admin', query: FULFILLMENT_CANCEL_PREVIEW_QUERY, variables: { fulfillmentId } }, options);
454
+ const data = await storeCreditAware(transport).graphql({ api: 'admin', query: FULFILLMENT_CANCEL_PREVIEW_QUERY, variables: { fulfillmentId } }, options);
369
455
  const preview = data.fulfillmentCancelPreview;
370
456
  return {
371
457
  fulfillmentId: preview.fulfillmentId,
@@ -382,7 +468,7 @@ export function createFulfillmentsModule(transport) {
382
468
  async cancel(fulfillmentId, input = {}, options) {
383
469
  assertCancelRequest(fulfillmentId, input);
384
470
  const overpayment = input.overpayment ?? [];
385
- const data = await transport.graphql({
471
+ const data = await storeCreditAware(transport).graphql({
386
472
  api: 'admin',
387
473
  query: CANCEL_FULFILLMENT_MUTATION,
388
474
  // A variable, not a header: the Admin API takes the key as an argument.
@@ -406,6 +492,38 @@ export function createFulfillmentsModule(transport) {
406
492
  })),
407
493
  };
408
494
  },
495
+ async coverage(orderId, options) {
496
+ assertOrderId(orderId);
497
+ const data = await transport.graphql({ api: 'admin', query: ORDER_FULFILLMENT_COVERAGE_QUERY, variables: { orderId } }, options);
498
+ const coverage = data.orderFulfillmentCoverage;
499
+ return {
500
+ orderId: coverage.orderId,
501
+ orderCode: coverage.orderCode,
502
+ currencyCode: coverage.currencyCode,
503
+ policyActive: coverage.policyActive,
504
+ covered: coverage.covered,
505
+ outstanding: coverage.outstanding,
506
+ exempt: coverage.exempt,
507
+ exemptReason: coverage.exemptReason ?? null,
508
+ allowed: coverage.allowed,
509
+ override: coverage.override ? toCoverageOverride(coverage.override) : null,
510
+ };
511
+ },
512
+ async allowUncovered(orderId, reason, options) {
513
+ assertOrderId(orderId);
514
+ const text = assertOverrideReason(reason);
515
+ const data = await transport.graphql({
516
+ api: 'admin',
517
+ query: ALLOW_UNCOVERED_FULFILLMENT_MUTATION,
518
+ // A variable, not a header: the Admin API takes the key as an argument.
519
+ variables: {
520
+ orderId,
521
+ reason: text,
522
+ ...(options?.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {}),
523
+ },
524
+ }, options);
525
+ return toCoverageOverride(data.allowUncoveredFulfillment);
526
+ },
409
527
  async reportAppFulfillment(fulfillmentId, input, options) {
410
528
  const data = await transport.graphql({
411
529
  api: 'admin',
@@ -0,0 +1,64 @@
1
+ import { type Transport } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ /** The most payment method codes `exemptMethodCodes` may name. */
4
+ export declare const FULFILLMENT_PAYMENT_POLICY_EXEMPT_METHODS_MAX = 50;
5
+ /** The longest payment method code the list accepts (`PaymentMethod.code` is a varchar(255)). */
6
+ export declare const FULFILLMENT_PAYMENT_POLICY_METHOD_CODE_MAX_LENGTH = 255;
7
+ /**
8
+ * The store's fulfilment payment policy (`Channel.customFields.fulfillmentPaymentPolicy`):
9
+ * whether goods are handed over before an order is paid in full. Every field present: this is
10
+ * what the engine APPLIES, absent and malformed fields read as their defaults (OFF).
11
+ */
12
+ export interface FulfillmentPaymentPolicy {
13
+ /**
14
+ * On: a fulfilment is created, extended or shipped only once the money COLLECTED for the
15
+ * order (settled, or held by a payment provider) covers what it bills, unless the order is
16
+ * exempt or an override was recorded (`fulfillments.allowUncovered`). Otherwise refused
17
+ * `ORDER_NOT_COVERED`.
18
+ */
19
+ requireFullPayment: boolean;
20
+ /**
21
+ * Payment method CODES whose orders are handed over unpaid as a matter of course (cash on
22
+ * delivery, a bank transfer the store ships against), judged on the order's latest live
23
+ * payment. Read as the engine compares them: trimmed, lower-cased, once each.
24
+ */
25
+ exemptMethodCodes: string[];
26
+ }
27
+ /** The policy of a store that never set one, and of a column that cannot be read: off. */
28
+ export declare const DEFAULT_FULFILLMENT_PAYMENT_POLICY: Readonly<FulfillmentPaymentPolicy>;
29
+ /**
30
+ * The ACTIVE store's fulfilment payment policy (`admin.fulfillments.paymentPolicy`), stored as a
31
+ * Channel custom field and written through core `updateChannel`.
32
+ *
33
+ * Reading needs an authenticated administrator on the store; writing needs `UpdateChannel`.
34
+ */
35
+ export interface FulfillmentPaymentPolicyModule {
36
+ /**
37
+ * The policy the engine applies, read as tolerantly as the engine reads it
38
+ * (`resolveFulfillmentPaymentPolicy`): a store that never set one, a malformed column and a
39
+ * field of the wrong type all answer OFF ({@link DEFAULT_FULFILLMENT_PAYMENT_POLICY}); the
40
+ * exempt codes are the non-blank ones, trimmed, lower-cased and once each.
41
+ */
42
+ get(options?: Call): Promise<FulfillmentPaymentPolicy>;
43
+ /**
44
+ * Replace the whole policy, and answer it as the engine now applies it.
45
+ *
46
+ * Both fields are required: read it with {@link get}, change what you mean to, and send it
47
+ * back. Only the schema's fields are stored, the codes trimmed.
48
+ *
49
+ * Refused before any request with `FULFILLMENT_PAYMENT_POLICY_INVALID` ({@link ValidationError},
50
+ * one `details[]` entry per failing field): a non-boolean switch, an exempt list that is not a
51
+ * list, holds a blank or over-long code, names one code twice in any case, or more than 50.
52
+ * The engine's own write validator refuses the same values (a `ValidationError` too, carrying
53
+ * its sentence), so a value that slips past this check is still never stored.
54
+ *
55
+ * Absent and "set to the defaults" mean the same thing to the engine, and a store's column is
56
+ * never backfilled: write the policy when a merchant changed it.
57
+ */
58
+ set(policy: FulfillmentPaymentPolicy, options?: Call): Promise<FulfillmentPaymentPolicy>;
59
+ }
60
+ export declare const FULFILLMENT_PAYMENT_POLICY_QUERY = "\n query FulfillmentPaymentPolicy {\n activeChannel { \n id\n customFields {\n fulfillmentPaymentPolicy\n }\n }\n }\n";
61
+ export declare const SET_FULFILLMENT_PAYMENT_POLICY_MUTATION = "\n mutation SetFulfillmentPaymentPolicy($input: UpdateChannelInput!) {\n updateChannel(input: $input) {\n ... on Channel { \n id\n customFields {\n fulfillmentPaymentPolicy\n }\n }\n ... on ErrorResult { errorCode message }\n }\n }\n";
62
+ /** A payment method code as the engine compares it (`normalizeMethodCode`). */
63
+ export declare function normalizeFulfillmentPolicyMethodCode(code: string): string;
64
+ export declare function createFulfillmentPaymentPolicyModule(transport: Transport): FulfillmentPaymentPolicyModule;
@@ -0,0 +1,140 @@
1
+ import { errorFromErrorResult, isErrorResult, ValidationError, } from '@sixtyninecommerce/core';
2
+ // The bounds of the meta catalog's `fulfillment_payment_policy` schema
3
+ // (`packages/shared/src/meta-catalog/settings-schemas.ts`), which the spec reads
4
+ // back from that schema, and of the engine's write validator
5
+ // (`validateFulfillmentPaymentPolicyValue`), which refuses the same values.
6
+ /** The most payment method codes `exemptMethodCodes` may name. */
7
+ export const FULFILLMENT_PAYMENT_POLICY_EXEMPT_METHODS_MAX = 50;
8
+ /** The longest payment method code the list accepts (`PaymentMethod.code` is a varchar(255)). */
9
+ export const FULFILLMENT_PAYMENT_POLICY_METHOD_CODE_MAX_LENGTH = 255;
10
+ /** The policy of a store that never set one, and of a column that cannot be read: off. */
11
+ export const DEFAULT_FULFILLMENT_PAYMENT_POLICY = Object.freeze({
12
+ requireFullPayment: false,
13
+ exemptMethodCodes: [],
14
+ });
15
+ const POLICY_FIELDS = /* GraphQL */ `
16
+ id
17
+ customFields {
18
+ fulfillmentPaymentPolicy
19
+ }
20
+ `;
21
+ export const FULFILLMENT_PAYMENT_POLICY_QUERY = /* GraphQL */ `
22
+ query FulfillmentPaymentPolicy {
23
+ activeChannel { ${POLICY_FIELDS} }
24
+ }
25
+ `;
26
+ export const SET_FULFILLMENT_PAYMENT_POLICY_MUTATION = /* GraphQL */ `
27
+ mutation SetFulfillmentPaymentPolicy($input: UpdateChannelInput!) {
28
+ updateChannel(input: $input) {
29
+ ... on Channel { ${POLICY_FIELDS} }
30
+ ... on ErrorResult { errorCode message }
31
+ }
32
+ }
33
+ `;
34
+ function isRecord(value) {
35
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
36
+ }
37
+ /** A payment method code as the engine compares it (`normalizeMethodCode`). */
38
+ export function normalizeFulfillmentPolicyMethodCode(code) {
39
+ return code.trim().toLowerCase();
40
+ }
41
+ /** The column, read as the engine reads it: anything unreadable is OFF. */
42
+ function readFulfillmentPaymentPolicy(raw) {
43
+ let parsed = raw;
44
+ if (typeof raw === 'string') {
45
+ try {
46
+ parsed = JSON.parse(raw);
47
+ }
48
+ catch {
49
+ parsed = null;
50
+ }
51
+ }
52
+ if (!isRecord(parsed))
53
+ return { requireFullPayment: false, exemptMethodCodes: [] };
54
+ const codes = Array.isArray(parsed.exemptMethodCodes)
55
+ ? [
56
+ ...new Set(parsed.exemptMethodCodes
57
+ .filter((code) => typeof code === 'string' && code.trim() !== '')
58
+ .map(normalizeFulfillmentPolicyMethodCode)),
59
+ ].slice(0, FULFILLMENT_PAYMENT_POLICY_EXEMPT_METHODS_MAX)
60
+ : [];
61
+ return { requireFullPayment: parsed.requireFullPayment === true, exemptMethodCodes: codes };
62
+ }
63
+ /** Every way `policy` breaks the schema, one entry per field. */
64
+ function problemsOf(policy) {
65
+ const problems = [];
66
+ const add = (field, message) => problems.push({ field, code: 'FULFILLMENT_PAYMENT_POLICY_INVALID', message });
67
+ if (!isRecord(policy)) {
68
+ add('policy', 'Pass the whole policy as an object: read it with get(), change it, send it back.');
69
+ return problems;
70
+ }
71
+ if (typeof policy.requireFullPayment !== 'boolean') {
72
+ add('requireFullPayment', 'requireFullPayment must be true or false.');
73
+ }
74
+ const codes = policy.exemptMethodCodes;
75
+ if (!Array.isArray(codes)) {
76
+ add('exemptMethodCodes', 'exemptMethodCodes must be a list of payment method codes.');
77
+ }
78
+ else if (codes.some((code) => typeof code !== 'string' || code.trim() === '')) {
79
+ add('exemptMethodCodes', 'exemptMethodCodes may hold only non-blank payment method codes.');
80
+ }
81
+ else if (codes.some((code) => code.trim().length > FULFILLMENT_PAYMENT_POLICY_METHOD_CODE_MAX_LENGTH)) {
82
+ add('exemptMethodCodes', `A payment method code is at most ${String(FULFILLMENT_PAYMENT_POLICY_METHOD_CODE_MAX_LENGTH)} characters.`);
83
+ }
84
+ else if (new Set(codes.map((code) => normalizeFulfillmentPolicyMethodCode(code))).size !==
85
+ codes.length) {
86
+ add('exemptMethodCodes', 'exemptMethodCodes names a payment method code more than once (codes are compared ignoring case).');
87
+ }
88
+ else if (codes.length > FULFILLMENT_PAYMENT_POLICY_EXEMPT_METHODS_MAX) {
89
+ add('exemptMethodCodes', `exemptMethodCodes may name at most ${String(FULFILLMENT_PAYMENT_POLICY_EXEMPT_METHODS_MAX)} payment methods.`);
90
+ }
91
+ return problems;
92
+ }
93
+ /** Exactly the schema's fields, in its order, codes trimmed: what the column stores. */
94
+ function storedOf(policy) {
95
+ return {
96
+ requireFullPayment: policy.requireFullPayment,
97
+ exemptMethodCodes: policy.exemptMethodCodes.map((code) => code.trim()),
98
+ };
99
+ }
100
+ export function createFulfillmentPaymentPolicyModule(transport) {
101
+ const read = async (options) => {
102
+ const data = await transport.graphql({ api: 'admin', query: FULFILLMENT_PAYMENT_POLICY_QUERY }, options);
103
+ return data.activeChannel;
104
+ };
105
+ return {
106
+ async get(options) {
107
+ const channel = await read(options);
108
+ return readFulfillmentPaymentPolicy(channel.customFields?.fulfillmentPaymentPolicy ?? null);
109
+ },
110
+ async set(policy, options) {
111
+ const problems = problemsOf(policy);
112
+ if (problems.length > 0) {
113
+ throw new ValidationError({
114
+ code: 'FULFILLMENT_PAYMENT_POLICY_INVALID',
115
+ message: problems.map((problem) => problem.message).join(' '),
116
+ status: 400,
117
+ service: 'vendure',
118
+ details: problems,
119
+ });
120
+ }
121
+ // `updateChannel` needs the id, and the active channel is the one the client is scoped
122
+ // to: read it with the SAME call options, so a per-call tenant writes its own channel.
123
+ const { id } = await read(options);
124
+ const data = await transport.graphql({
125
+ api: 'admin',
126
+ query: SET_FULFILLMENT_PAYMENT_POLICY_MUTATION,
127
+ variables: {
128
+ // The column is `text` holding JSON, so it is sent as a string.
129
+ input: {
130
+ id,
131
+ customFields: { fulfillmentPaymentPolicy: JSON.stringify(storedOf(policy)) },
132
+ },
133
+ },
134
+ }, options);
135
+ if (isErrorResult(data.updateChannel))
136
+ throw errorFromErrorResult(data.updateChannel);
137
+ return readFulfillmentPaymentPolicy(data.updateChannel.customFields?.fulfillmentPaymentPolicy ?? null);
138
+ },
139
+ };
140
+ }