@sixtyninecommerce/admin 0.11.0 → 0.13.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 (153) hide show
  1. package/README.md +1509 -28
  2. package/dist/auth/index.d.ts +7 -1
  3. package/dist/auth/index.js +8 -1
  4. package/dist/catalog/documents.d.ts +142 -0
  5. package/dist/catalog/documents.js +114 -0
  6. package/dist/catalog/index.d.ts +48 -7
  7. package/dist/catalog/index.js +6 -1
  8. package/dist/catalog/metadata.d.ts +244 -0
  9. package/dist/catalog/metadata.js +220 -0
  10. package/dist/catalog/properties.d.ts +38 -0
  11. package/dist/catalog/properties.js +52 -1
  12. package/dist/catalog/recommendations.d.ts +33 -6
  13. package/dist/catalog/recommendations.js +94 -2
  14. package/dist/catalog/reviews.d.ts +17 -4
  15. package/dist/catalog/reviews.js +7 -0
  16. package/dist/catalog/variants.d.ts +60 -0
  17. package/dist/catalog/variants.js +39 -0
  18. package/dist/catalog/visibility.d.ts +18 -2
  19. package/dist/client.d.ts +29 -3
  20. package/dist/client.js +19 -8
  21. package/dist/content/assets.d.ts +3 -4
  22. package/dist/content/forms.d.ts +332 -1
  23. package/dist/content/forms.js +140 -4
  24. package/dist/content/items.d.ts +31 -8
  25. package/dist/content/items.js +1 -1
  26. package/dist/content/menus.d.ts +254 -0
  27. package/dist/content/menus.js +70 -0
  28. package/dist/content/strings.d.ts +137 -0
  29. package/dist/content/strings.js +82 -0
  30. package/dist/customers/delivery-terms.d.ts +44 -0
  31. package/dist/customers/delivery-terms.js +32 -0
  32. package/dist/customers/groups.d.ts +16 -5
  33. package/dist/customers/groups.js +6 -2
  34. package/dist/customers/index.d.ts +15 -0
  35. package/dist/customers/index.js +4 -0
  36. package/dist/documents/emails.d.ts +154 -0
  37. package/dist/documents/emails.js +220 -0
  38. package/dist/documents/index.d.ts +13 -0
  39. package/dist/documents/index.js +2 -0
  40. package/dist/fulfillments/create.d.ts +1 -1
  41. package/dist/fulfillments/create.js +5 -2
  42. package/dist/fulfillments/index.d.ts +119 -1
  43. package/dist/fulfillments/index.js +124 -4
  44. package/dist/fulfillments/warehouse.d.ts +29 -17
  45. package/dist/fulfillments/warehouse.js +32 -1
  46. package/dist/index.d.ts +43 -23
  47. package/dist/index.js +11 -5
  48. package/dist/integrations/exact-online-types.d.ts +542 -0
  49. package/dist/integrations/exact-online.d.ts +541 -5
  50. package/dist/integrations/exact-online.js +714 -1
  51. package/dist/integrations/index.d.ts +23 -8
  52. package/dist/integrations/index.js +9 -4
  53. package/dist/integrations/pipeline-discoveries.d.ts +65 -0
  54. package/dist/integrations/pipeline-discoveries.js +65 -0
  55. package/dist/integrations/pipeline-runs.d.ts +119 -0
  56. package/dist/integrations/pipeline-runs.js +87 -0
  57. package/dist/integrations/pipelines.d.ts +73 -2
  58. package/dist/integrations/pipelines.js +36 -1
  59. package/dist/integrations/price-import.d.ts +223 -0
  60. package/dist/integrations/price-import.js +124 -0
  61. package/dist/integrations/types.d.ts +221 -3
  62. package/dist/integrations/types.js +4 -3
  63. package/dist/meta/index.d.ts +10 -0
  64. package/dist/metafields/index.d.ts +8 -1
  65. package/dist/metafields/index.js +10 -0
  66. package/dist/orders/cancel-with-money.d.ts +10 -0
  67. package/dist/orders/cancel-with-money.js +2 -0
  68. package/dist/orders/commit-edit.d.ts +16 -0
  69. package/dist/orders/commit-edit.js +14 -1
  70. package/dist/orders/deposit-policy.d.ts +3 -1
  71. package/dist/orders/index.d.ts +22 -11
  72. package/dist/orders/index.js +5 -2
  73. package/dist/orders/list.d.ts +26 -5
  74. package/dist/orders/list.js +123 -13
  75. package/dist/orders/manual-discounts.d.ts +13 -5
  76. package/dist/orders/money-view.d.ts +149 -0
  77. package/dist/orders/money-view.js +99 -0
  78. package/dist/orders/plan-edit.d.ts +34 -2
  79. package/dist/orders/plan-edit.js +110 -12
  80. package/dist/orders/surcharges.d.ts +12 -0
  81. package/dist/orders/surcharges.js +34 -9
  82. package/dist/payments/account-credit.d.ts +17 -1
  83. package/dist/payments/account-credit.js +25 -2
  84. package/dist/payments/credit-noted-fields.d.ts +8 -1
  85. package/dist/payments/credit-noted-fields.js +34 -2
  86. package/dist/payments/customer-consent.d.ts +30 -0
  87. package/dist/payments/customer-consent.js +49 -0
  88. package/dist/payments/index.d.ts +89 -14
  89. package/dist/payments/index.js +22 -2
  90. package/dist/payments/requests.d.ts +6 -3
  91. package/dist/payments/requests.js +1 -0
  92. package/dist/pickups/index.d.ts +5 -3
  93. package/dist/pickups/index.js +5 -2
  94. package/dist/platform/email-gateways.d.ts +165 -0
  95. package/dist/platform/email-gateways.js +78 -0
  96. package/dist/platform/tax.d.ts +11 -3
  97. package/dist/platform/tax.js +30 -0
  98. package/dist/pos/exchanges.d.ts +6 -1
  99. package/dist/pos/index.d.ts +229 -10
  100. package/dist/pos/index.js +113 -4
  101. package/dist/pos/offline-sales.d.ts +44 -3
  102. package/dist/pos/offline-sales.js +57 -3
  103. package/dist/pos/returns.d.ts +28 -1
  104. package/dist/pos/returns.js +36 -6
  105. package/dist/pricing/price-lists.d.ts +3 -1
  106. package/dist/purchasing/alerts.d.ts +19 -4
  107. package/dist/purchasing/alerts.js +29 -3
  108. package/dist/purchasing/backorders.d.ts +61 -0
  109. package/dist/purchasing/backorders.js +92 -0
  110. package/dist/purchasing/index.d.ts +21 -3
  111. package/dist/purchasing/index.js +8 -0
  112. package/dist/purchasing/links.d.ts +263 -0
  113. package/dist/purchasing/links.js +192 -0
  114. package/dist/purchasing/purchase-orders.d.ts +4 -1
  115. package/dist/purchasing/receipts.d.ts +396 -0
  116. package/dist/purchasing/receipts.js +287 -0
  117. package/dist/purchasing/returns.d.ts +273 -0
  118. package/dist/purchasing/returns.js +229 -0
  119. package/dist/quotes/index.d.ts +20 -3
  120. package/dist/returns/index.d.ts +62 -1
  121. package/dist/returns/index.js +61 -0
  122. package/dist/seo/config.d.ts +128 -0
  123. package/dist/seo/config.js +95 -0
  124. package/dist/seo/redirects.d.ts +125 -0
  125. package/dist/seo/redirects.js +60 -1
  126. package/dist/seo/settings.d.ts +147 -0
  127. package/dist/seo/settings.js +209 -0
  128. package/dist/shipping/index.d.ts +6 -0
  129. package/dist/shipping/index.js +2 -0
  130. package/dist/shipping/methods.d.ts +8 -1
  131. package/dist/shipping/myparcel.d.ts +415 -1
  132. package/dist/shipping/myparcel.js +291 -3
  133. package/dist/shipping/rate-tables.d.ts +149 -4
  134. package/dist/shipping/rate-tables.js +229 -23
  135. package/dist/shipping/ship-to-countries.d.ts +75 -0
  136. package/dist/shipping/ship-to-countries.js +47 -0
  137. package/dist/stock/by-location.d.ts +86 -0
  138. package/dist/stock/by-location.js +94 -0
  139. package/dist/stock/index.d.ts +8 -1
  140. package/dist/stock/index.js +4 -0
  141. package/dist/stock/settings.d.ts +106 -0
  142. package/dist/stock/settings.js +103 -0
  143. package/dist/stock/transfers.d.ts +171 -10
  144. package/dist/stock/transfers.js +82 -4
  145. package/dist/stored-value/index.d.ts +98 -7
  146. package/dist/stored-value/index.js +71 -4
  147. package/dist/tax/display-policy.d.ts +105 -0
  148. package/dist/tax/display-policy.js +84 -0
  149. package/dist/tax/index.d.ts +3 -0
  150. package/dist/tax/index.js +2 -0
  151. package/dist/tenant/email-templates.d.ts +222 -1
  152. package/dist/tenant/email-templates.js +227 -10
  153. package/package.json +2 -2
@@ -33,7 +33,12 @@ export interface StoredValueEntry {
33
33
  id: string;
34
34
  createdAt: string;
35
35
  occurredAt: string;
36
- entryType: 'issue' | 'redeem' | 'reversal' | 'adjustment' | 'expiry' | 'forfeit';
36
+ /**
37
+ * `payout`: store credit moved from an order, paid back to the payment it came from
38
+ * (`payOut`); a payout whose refund did not happen comes back as a `reversal` with
39
+ * `sourceType: 'payout_refund'`. Treat a value you do not know as a movement you do not report.
40
+ */
41
+ entryType: 'issue' | 'redeem' | 'reversal' | 'adjustment' | 'expiry' | 'forfeit' | 'payout';
37
42
  /** Signed: credits positive, debits negative. */
38
43
  amount: number;
39
44
  balanceAfter: number;
@@ -48,6 +53,31 @@ export interface StoredValueEntry {
48
53
  onBehalfOfRef: string | null;
49
54
  deviceRef: string | null;
50
55
  reason: string | null;
56
+ /**
57
+ * Store credit moved from an order (`sourceType: 'order_credit'`): the decision that moved it,
58
+ * `return`, `correction`, `order_edit`, `surcharge`, `fulfillment_cancel`, `cancel`,
59
+ * `overpayment` or `till_return` (a value you do not know is another decision). Null otherwise,
60
+ * and on an engine before incentives sprint 8.
61
+ */
62
+ origin: string | null;
63
+ /**
64
+ * The record of that decision, when it has one: the return's id (`return`), the credit note's
65
+ * (`correction`), the surcharge's, the fulfillment's, or the till return's. Null otherwise.
66
+ */
67
+ originRef: string | null;
68
+ /**
69
+ * The lot (an `order_credit` entry's id) a `payout` pays back, or its `payout_refund` restore
70
+ * gives back to. Null otherwise, and on an engine before payouts.
71
+ */
72
+ lotId: string | null;
73
+ /**
74
+ * Store credit moved from an order: whether the customer expressly agreed to store credit
75
+ * instead of a refund to their payment (EU consumer law), as the staff member who chose it
76
+ * recorded, a till return's included (`pos.returns.create`'s `customerAgreed`). Null when nobody
77
+ * said (the door was not told, a till that did not ask, a move recorded before the field), on
78
+ * every other entry, and on an engine before it. A record, never a condition.
79
+ */
80
+ customerAgreed: boolean | null;
51
81
  }
52
82
  export interface StoredValueStatement {
53
83
  account: StoredValueAccount;
@@ -56,17 +86,34 @@ export interface StoredValueStatement {
56
86
  entries: StoredValueEntry[];
57
87
  totalItems: number;
58
88
  }
59
- /** `outstanding = issued − redeemed + reversed + adjusted − expired − forfeited`. */
89
+ /**
90
+ * `outstanding = issued − redeemed + reversed + adjusted − expired − forfeited − paidOut`, where
91
+ * `paidOut` is store credit paid back to money (`payOut`), net of the payouts whose refund did not
92
+ * happen. On an engine before incentives sprint 8 the split of `issued` and `paidOut` are null
93
+ * (it serves neither; nothing was paid out there).
94
+ */
60
95
  export interface StoredValueLiability {
61
96
  unit: string;
62
97
  kind: string;
63
98
  accounts: number;
64
99
  issued: number;
100
+ /** Of `issued`: created by staff without payment (goodwill, a staff gift card). */
101
+ issuedGoodwill: number | null;
102
+ /** Of `issued`: an order's money moved to store credit instead of a refund. */
103
+ issuedFromOrders: number | null;
104
+ /** Of `issued`: store credit for goods a till took back that no order payment paid for. */
105
+ issuedFromReturns: number | null;
65
106
  redeemed: number;
107
+ /**
108
+ * Value given back by refunds and cancelled payments. A payout's restore (a `reversal` with
109
+ * `sourceType: 'payout_refund'`) is NOT here: the engine nets it in `paidOut`.
110
+ */
66
111
  reversed: number;
67
112
  adjusted: number;
68
113
  expired: number;
69
114
  forfeited: number;
115
+ /** Paid back to money (`payOut`), net of the payouts whose refund did not happen. */
116
+ paidOut: number | null;
70
117
  outstanding: number;
71
118
  }
72
119
  export interface IssueStoredValueInput {
@@ -119,6 +166,25 @@ export interface RedeemStoredValueInput {
119
166
  /** The code of the store's payment method on the `stored-value` handler. */
120
167
  method: string;
121
168
  }
169
+ export interface PayOutStoreCreditInput {
170
+ /** The lot: an `order_credit` entry of the customer's store credit (`StoredValueEntry.id`). */
171
+ entryId: string;
172
+ /** Minor units of the store credit's currency. Omitted: everything the lot can pay back. */
173
+ amount?: number;
174
+ /** Free text, on the Refund and the order note. */
175
+ reason?: string;
176
+ }
177
+ /** The refund a payout made, of the payment the store credit came from. */
178
+ export interface StoreCreditPayoutRefund {
179
+ id: string;
180
+ /** Minor units. */
181
+ total: number;
182
+ /** `Settled`, or `Pending` while the payment provider has not confirmed it. */
183
+ state: string;
184
+ method: string;
185
+ transactionId: string | null;
186
+ reason: string | null;
187
+ }
122
188
  export interface StoredValueModule {
123
189
  accounts(filter?: {
124
190
  customerId?: string;
@@ -173,11 +239,31 @@ export interface StoredValueModule {
173
239
  unblock(id: string, reason: string, options?: Call): Promise<StoredValueAccount>;
174
240
  /**
175
241
  * Pay part (or all) of an order from an account (`redeemStoredValue`), through the platform's
176
- * payment position: the order lock, the outstanding bound and the store's deposit policy apply,
177
- * and the ledger is debited in the payment's own transaction. Requires UpdateOrder. Answers the
178
- * payment the SERVER recorded for this call; a repeat under the same key answers the same one.
242
+ * payment position: the order lock and the outstanding bound apply, and the ledger is debited in
243
+ * the payment's own transaction. Requires UpdateOrder. Answers the payment the SERVER recorded
244
+ * for this call; a repeat under the same key answers the same one.
245
+ *
246
+ * Stored value may pay PART of an order still arranging payment whatever the store's deposit
247
+ * policy (split tender, not a deposit): the order is placed only once its money covers it, so the
248
+ * rest is paid by another method, and cancelling the payment gives the part back to the account.
249
+ * On a parked or placed order a part is a deposit, refused `DEPOSITS_NOT_ENABLED` on a store
250
+ * without deposits.
179
251
  */
180
252
  redeem(input: RedeemStoredValueInput, options?: Call): Promise<StoredValueRedemption>;
253
+ /**
254
+ * Requires UpdateOrder AND ManageStoredValue (no Stored Value grant: it pays the customer's own
255
+ * money back; a blocked wallet may be paid out). Pay store credit moved from an order back to the
256
+ * payment it came from (`payOutStoreCredit`): a refund of that payment, the last step. Only an
257
+ * `order_credit` lot (`STORE_CREDIT_PAYOUT_NOT_PAYABLE`); at most what it still holds and what
258
+ * the customer can spend (`STORE_CREDIT_PAYOUT_EXCEEDED`; the thrown error's
259
+ * `extensions.storeCredit.payable` says how much may go); and
260
+ * the refund's own refusals (`REFUND_REFUSED`, …), after which the store credit is given back to
261
+ * its lot (a `reversal` of `sourceType: 'payout_refund'`). Send an
262
+ * `idempotencyKey`: a provider answer that is unknown answers `IDEMPOTENCY_OUTCOME_UNKNOWN`, the
263
+ * store credit stays paid out until `reconcileRefundOutcome`, and a repeat of the key replays the
264
+ * refund (MADE) or runs again (NOT_MADE). Needs an engine that serves it (incentives sprint 8).
265
+ */
266
+ payOut(input: PayOutStoreCreditInput, options?: Call): Promise<StoreCreditPayoutRefund>;
181
267
  /**
182
268
  * Requires ReadStoredValue. The store's refund-to-credit switch and whether it is usable now.
183
269
  * Needs an engine that serves `storeCreditSettings` (incentives sprint 8).
@@ -342,13 +428,18 @@ export interface StoredValueRedemption {
342
428
  }
343
429
  export declare const STORED_VALUE_ACCOUNTS_QUERY = "\n query StoredValueAccounts($customerId: ID, $kind: String, $take: Int, $skip: Int) {\n storedValueAccounts(customerId: $customerId, kind: $kind, take: $take, skip: $skip) {\n items { \n id\n createdAt\n updatedAt\n kind\n unit\n customerId\n codeLast4\n expiresAt\n expiresOn\n status\n balance\n spendable\n }\n totalItems\n }\n }\n";
344
430
  export declare const STORED_VALUE_ACCOUNT_QUERY = "\n query StoredValueAccount($id: ID!) {\n storedValueAccount(id: $id) { \n id\n createdAt\n updatedAt\n kind\n unit\n customerId\n codeLast4\n expiresAt\n expiresOn\n status\n balance\n spendable\n }\n }\n";
345
- export declare const STORED_VALUE_STATEMENT_QUERY = "\n query StoredValueStatement($accountId: ID!, $from: DateTime, $to: DateTime, $take: Int, $skip: Int) {\n storedValueStatement(accountId: $accountId, from: $from, to: $to, take: $take, skip: $skip) {\n account { \n id\n createdAt\n updatedAt\n kind\n unit\n customerId\n codeLast4\n expiresAt\n expiresOn\n status\n balance\n spendable\n }\n openingBalance\n closingBalance\n totalItems\n entries {\n id createdAt occurredAt entryType amount balanceAfter unit sourceType sourceId paymentId\n orderId locationId actorType actorId onBehalfOfRef deviceRef reason\n }\n }\n }\n";
346
- export declare const STORED_VALUE_LIABILITY_QUERY = "\n query StoredValueLiability($at: DateTime, $kind: String, $locationId: ID) {\n storedValueLiability(at: $at, kind: $kind, locationId: $locationId) {\n unit kind accounts issued redeemed reversed adjusted expired forfeited outstanding\n }\n }\n";
431
+ export declare const STORED_VALUE_STATEMENT_QUERY = "\n query StoredValueStatement($accountId: ID!, $from: DateTime, $to: DateTime, $take: Int, $skip: Int) {\n storedValueStatement(accountId: $accountId, from: $from, to: $to, take: $take, skip: $skip) {\n account { \n id\n createdAt\n updatedAt\n kind\n unit\n customerId\n codeLast4\n expiresAt\n expiresOn\n status\n balance\n spendable\n }\n openingBalance\n closingBalance\n totalItems\n entries {\n id createdAt occurredAt entryType amount balanceAfter unit sourceType sourceId paymentId\n orderId locationId actorType actorId onBehalfOfRef deviceRef reason origin originRef lotId\n customerAgreed\n }\n }\n }\n";
432
+ export declare const STORED_VALUE_LIABILITY_QUERY = "\n query StoredValueLiability($at: DateTime, $kind: String, $locationId: ID) {\n storedValueLiability(at: $at, kind: $kind, locationId: $locationId) {\n unit kind accounts issued issuedGoodwill issuedFromOrders issuedFromReturns redeemed\n reversed adjusted expired forfeited paidOut outstanding\n }\n }\n";
433
+ /** `document` without the fields above: what an engine before them accepts. */
434
+ export declare function withoutWalletFields(document: string): string;
435
+ /** `document` without the consent field: what an engine of sprint 8 before PR 6a accepts. */
436
+ export declare function withoutConsentField(document: string): string;
347
437
  export declare const ISSUE_STORED_VALUE_MUTATION = "\n mutation IssueStoredValue($input: IssueStoredValueInput!, $idempotencyKey: String) {\n issueStoredValue(input: $input, idempotencyKey: $idempotencyKey) { \n id\n createdAt\n updatedAt\n kind\n unit\n customerId\n codeLast4\n expiresAt\n expiresOn\n status\n balance\n spendable\n }\n }\n";
348
438
  export declare const ADJUST_STORED_VALUE_MUTATION = "\n mutation AdjustStoredValue($input: AdjustStoredValueInput!, $idempotencyKey: String) {\n adjustStoredValue(input: $input, idempotencyKey: $idempotencyKey) { \n id\n createdAt\n updatedAt\n kind\n unit\n customerId\n codeLast4\n expiresAt\n expiresOn\n status\n balance\n spendable\n }\n }\n";
349
439
  export declare const BLOCK_STORED_VALUE_MUTATION = "\n mutation BlockStoredValueAccount($id: ID!, $reason: String!) {\n blockStoredValueAccount(id: $id, reason: $reason) { \n id\n createdAt\n updatedAt\n kind\n unit\n customerId\n codeLast4\n expiresAt\n expiresOn\n status\n balance\n spendable\n }\n }\n";
350
440
  export declare const UNBLOCK_STORED_VALUE_MUTATION = "\n mutation UnblockStoredValueAccount($id: ID!, $reason: String!) {\n unblockStoredValueAccount(id: $id, reason: $reason) { \n id\n createdAt\n updatedAt\n kind\n unit\n customerId\n codeLast4\n expiresAt\n expiresOn\n status\n balance\n spendable\n }\n }\n";
351
441
  export declare const SET_STORED_VALUE_EXPIRY_MUTATION = "\n mutation SetStoredValueAccountExpiry(\n $id: ID!\n $expiresOn: String\n $reason: String!\n $idempotencyKey: String\n ) {\n setStoredValueAccountExpiry(\n id: $id\n expiresOn: $expiresOn\n reason: $reason\n idempotencyKey: $idempotencyKey\n ) { \n id\n createdAt\n updatedAt\n kind\n unit\n customerId\n codeLast4\n expiresAt\n expiresOn\n status\n balance\n spendable\n }\n }\n";
442
+ export declare const PAY_OUT_STORE_CREDIT_MUTATION = "\n mutation PayOutStoreCredit($input: PayOutStoreCreditInput!, $idempotencyKey: String) {\n payOutStoreCredit(input: $input, idempotencyKey: $idempotencyKey) {\n id\n total\n state\n method\n transactionId\n reason\n }\n }\n";
352
443
  export declare const REDEEM_STORED_VALUE_MUTATION = "\n mutation RedeemStoredValue($input: RedeemStoredValueInput!, $idempotencyKey: String) {\n redeemStoredValue(input: $input, idempotencyKey: $idempotencyKey) {\n orderId\n paymentId\n accountId\n amount\n }\n }\n";
353
444
  export declare const STORE_CREDIT_SETTINGS_QUERY = "\n query StoreCreditSettings {\n storeCreditSettings { \n refundToCredit\n book\n available\n code\n message\n }\n }\n";
354
445
  export declare const UPDATE_STORE_CREDIT_SETTINGS_MUTATION = "\n mutation UpdateStoreCreditSettings($input: UpdateStoreCreditSettingsInput!) {\n updateStoreCreditSettings(input: $input) { \n refundToCredit\n book\n available\n code\n message\n }\n }\n";
@@ -1,3 +1,4 @@
1
+ import { isUnknownFieldRejection } from '../payments/store-credit-fields.js';
1
2
  const ACCOUNT_FIELDS = `
2
3
  id
3
4
  createdAt
@@ -34,7 +35,8 @@ export const STORED_VALUE_STATEMENT_QUERY = /* GraphQL */ `
34
35
  totalItems
35
36
  entries {
36
37
  id createdAt occurredAt entryType amount balanceAfter unit sourceType sourceId paymentId
37
- orderId locationId actorType actorId onBehalfOfRef deviceRef reason
38
+ orderId locationId actorType actorId onBehalfOfRef deviceRef reason origin originRef lotId
39
+ customerAgreed
38
40
  }
39
41
  }
40
42
  }
@@ -42,10 +44,28 @@ export const STORED_VALUE_STATEMENT_QUERY = /* GraphQL */ `
42
44
  export const STORED_VALUE_LIABILITY_QUERY = /* GraphQL */ `
43
45
  query StoredValueLiability($at: DateTime, $kind: String, $locationId: ID) {
44
46
  storedValueLiability(at: $at, kind: $kind, locationId: $locationId) {
45
- unit kind accounts issued redeemed reversed adjusted expired forfeited outstanding
47
+ unit kind accounts issued issuedGoodwill issuedFromOrders issuedFromReturns redeemed
48
+ reversed adjusted expired forfeited paidOut outstanding
46
49
  }
47
50
  }
48
51
  `;
52
+ /**
53
+ * The statement's and the liability's fields from incentives sprint 8 (the wallet's origins and
54
+ * split, PR 1; the payout's `lotId` and `paidOut`, PR 5; the customer's consent, PR 6a). An engine
55
+ * before them refuses a document naming one as a whole, before it runs; the same document without
56
+ * them reads as it did then.
57
+ */
58
+ const WALLET_FIELDS = /\b(?:origin|originRef|lotId|customerAgreed|issuedGoodwill|issuedFromOrders|issuedFromReturns|paidOut)\b/g;
59
+ /** `document` without the fields above: what an engine before them accepts. */
60
+ export function withoutWalletFields(document) {
61
+ return document.replace(WALLET_FIELDS, '');
62
+ }
63
+ /** The newest of them, the customer's consent (PR 6a): an engine with the others lacks only it. */
64
+ const CONSENT_FIELD = /\bcustomerAgreed\b/g;
65
+ /** `document` without the consent field: what an engine of sprint 8 before PR 6a accepts. */
66
+ export function withoutConsentField(document) {
67
+ return document.replace(CONSENT_FIELD, '');
68
+ }
49
69
  export const ISSUE_STORED_VALUE_MUTATION = /* GraphQL */ `
50
70
  mutation IssueStoredValue($input: IssueStoredValueInput!, $idempotencyKey: String) {
51
71
  issueStoredValue(input: $input, idempotencyKey: $idempotencyKey) { ${ACCOUNT_FIELDS} }
@@ -81,6 +101,18 @@ export const SET_STORED_VALUE_EXPIRY_MUTATION = /* GraphQL */ `
81
101
  ) { ${ACCOUNT_FIELDS} }
82
102
  }
83
103
  `;
104
+ export const PAY_OUT_STORE_CREDIT_MUTATION = /* GraphQL */ `
105
+ mutation PayOutStoreCredit($input: PayOutStoreCreditInput!, $idempotencyKey: String) {
106
+ payOutStoreCredit(input: $input, idempotencyKey: $idempotencyKey) {
107
+ id
108
+ total
109
+ state
110
+ method
111
+ transactionId
112
+ reason
113
+ }
114
+ }
115
+ `;
84
116
  export const REDEEM_STORED_VALUE_MUTATION = /* GraphQL */ `
85
117
  mutation RedeemStoredValue($input: RedeemStoredValueInput!, $idempotencyKey: String) {
86
118
  redeemStoredValue(input: $input, idempotencyKey: $idempotencyKey) {
@@ -202,6 +234,21 @@ export const ISSUE_GIFT_CARD_MUTATION = /* GraphQL */ `
202
234
  `;
203
235
  export function createStoredValueModule(transport) {
204
236
  const read = async (query, variables, options) => transport.graphql({ api: 'admin', query, variables }, options);
237
+ // A read naming the sprint-8 fields, sent again to an engine that refuses one as unknown: first
238
+ // without the consent field alone (an engine with the rest of sprint 8), then without any of them.
239
+ const readWallet = async (query, variables, options) => {
240
+ const documents = [...new Set([query, withoutConsentField(query), withoutWalletFields(query)])];
241
+ for (const [index, document] of documents.entries()) {
242
+ try {
243
+ return await read(document, variables, options);
244
+ }
245
+ catch (error) {
246
+ if (index === documents.length - 1 || !isUnknownFieldRejection(error))
247
+ throw error;
248
+ }
249
+ }
250
+ throw new Error('unreachable: the last document either answers or throws');
251
+ };
205
252
  // The key is an ARGUMENT on the Admin API; `undefined` keeps an omitted key off the wire.
206
253
  const write = async (query, variables, options) => transport.graphql({ api: 'admin', query, variables: { ...variables, idempotencyKey: options?.idempotencyKey } }, options);
207
254
  return {
@@ -212,10 +259,27 @@ export function createStoredValueModule(transport) {
212
259
  return (await read(STORED_VALUE_ACCOUNT_QUERY, { id }, options)).storedValueAccount;
213
260
  },
214
261
  async statement(accountId, window = {}, options) {
215
- return (await read(STORED_VALUE_STATEMENT_QUERY, { accountId, ...window }, options)).storedValueStatement;
262
+ const statement = (await readWallet(STORED_VALUE_STATEMENT_QUERY, { accountId, ...window }, options)).storedValueStatement;
263
+ return {
264
+ ...statement,
265
+ entries: statement.entries.map((entry) => ({
266
+ ...entry,
267
+ origin: entry.origin ?? null,
268
+ originRef: entry.originRef ?? null,
269
+ lotId: entry.lotId ?? null,
270
+ customerAgreed: entry.customerAgreed ?? null,
271
+ })),
272
+ };
216
273
  },
217
274
  async liability(filter = {}, options) {
218
- return (await read(STORED_VALUE_LIABILITY_QUERY, filter, options)).storedValueLiability;
275
+ const rows = (await readWallet(STORED_VALUE_LIABILITY_QUERY, filter, options)).storedValueLiability;
276
+ return rows.map((row) => ({
277
+ ...row,
278
+ issuedGoodwill: row.issuedGoodwill ?? null,
279
+ issuedFromOrders: row.issuedFromOrders ?? null,
280
+ issuedFromReturns: row.issuedFromReturns ?? null,
281
+ paidOut: row.paidOut ?? null,
282
+ }));
219
283
  },
220
284
  async issue(input, options) {
221
285
  return (await write(ISSUE_STORED_VALUE_MUTATION, { input }, options)).issueStoredValue;
@@ -235,6 +299,9 @@ export function createStoredValueModule(transport) {
235
299
  async redeem(input, options) {
236
300
  return (await write(REDEEM_STORED_VALUE_MUTATION, { input }, options)).redeemStoredValue;
237
301
  },
302
+ async payOut(input, options) {
303
+ return (await write(PAY_OUT_STORE_CREDIT_MUTATION, { input }, options)).payOutStoreCredit;
304
+ },
238
305
  async storeCreditSettings(options) {
239
306
  return (await read(STORE_CREDIT_SETTINGS_QUERY, {}, options)).storeCreditSettings;
240
307
  },
@@ -0,0 +1,105 @@
1
+ import { type Transport } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ /** `channel` follows the store's "prices include tax"; `gross` = incl. tax; `net` = excl. tax. */
4
+ export type TaxDisplayDefault = 'channel' | 'gross' | 'net';
5
+ /** `inherit` leaves B2B and trade customers on the default. */
6
+ export type TaxDisplayB2b = 'inherit' | 'gross' | 'net';
7
+ /** What a shopper is shown: `GROSS` = incl. tax, `NET` = excl. tax (the Shop API's casing). */
8
+ export type TaxDisplayMode = 'GROSS' | 'NET';
9
+ /** The shoppers a policy is answered for, in the order a settings screen lists them. */
10
+ export type TaxDisplayAudience = 'VISITOR' | 'RETAIL_CUSTOMER' | 'B2B_CUSTOMER' | 'LISTED_COUNTRY_CUSTOMER';
11
+ /**
12
+ * A store's price-display policy: who sees prices with or without tax. Three Channel custom fields
13
+ * (`taxDisplayDefault`, `taxDisplayB2b`, `taxExclusiveCountries`), in the organization settings
14
+ * group `settings.tax_display`.
15
+ */
16
+ export interface TaxDisplayPolicy {
17
+ default: TaxDisplayDefault;
18
+ b2b: TaxDisplayB2b;
19
+ /**
20
+ * Upper-case ISO-3166 alpha-2 codes; empty turns the rule off. A customer shipping to a listed
21
+ * country always sees prices excl. tax, whatever the other two say, AND is taxed by that
22
+ * country's tax zone instead of the store's: this list changes what customers are charged, not
23
+ * only what they are shown.
24
+ */
25
+ countries: string[];
26
+ }
27
+ export interface TaxDisplayAudienceAnswer {
28
+ audience: TaxDisplayAudience;
29
+ /** The listed country the answer is judged for (`LISTED_COUNTRY_CUSTOMER` only); else null. */
30
+ countryCode: string | null;
31
+ /** What this shopper is shown, by the rule the storefront applies. Null when `dependsOnStore`. */
32
+ mode: TaxDisplayMode | null;
33
+ /**
34
+ * True only in an organization's workspace, for an answer that falls back to "prices include
35
+ * tax": each member store keeps its own, so there is no one answer.
36
+ */
37
+ dependsOnStore: boolean;
38
+ }
39
+ /** A policy and who it shows which tax figure, as the engine answers it. */
40
+ export interface TaxDisplayPolicyView extends TaxDisplayPolicy {
41
+ /** The store's own storage mode, the policy's last fallback. */
42
+ pricesIncludeTax: boolean;
43
+ /**
44
+ * Visitor, retail customer, B2B or trade customer, then a customer in the FIRST listed country
45
+ * (absent while none is listed). The same rule decides the storefront's prices and the prices an
46
+ * order's emails, receipts and invoices show its customer.
47
+ */
48
+ audiences: TaxDisplayAudienceAnswer[];
49
+ }
50
+ /**
51
+ * The ACTIVE store's price-display policy (`admin.tax.displayPolicy`). Reading needs any
52
+ * administrator permission on the store; writing needs `UpdateChannel` (the policy is stored on
53
+ * the channel and written through core `updateChannel`).
54
+ *
55
+ * The engine owns the rule: who sees what is never worked out in the client. Ask {@link preview}
56
+ * for a policy the merchant has not saved.
57
+ */
58
+ export interface TaxDisplayPolicyModule {
59
+ /**
60
+ * The policy the storefront applies and who it shows which figure. For a store that inherits
61
+ * `settings.tax_display` from its organization this is the organization's policy. An unreadable
62
+ * stored value reads as its default (`channel` / `inherit` / no countries); a stored choice is
63
+ * read trimmed and lower-cased, as the storefront reads it.
64
+ *
65
+ * @effect read
66
+ */
67
+ get(options?: Call): Promise<TaxDisplayPolicyView>;
68
+ /**
69
+ * Who `policy` WOULD show which figure on this store, without saving anything.
70
+ *
71
+ * Refused `CHANNEL_SETTINGS_INVALID` (`ValidationError`, one `details[]` entry per field named
72
+ * `customFields.<field>`) for a policy the save would refuse: a choice that is not exactly one of
73
+ * the values above, a country code that is not two letters, a country listed twice, or more than
74
+ * 300 countries.
75
+ *
76
+ * @effect read
77
+ */
78
+ preview(policy: TaxDisplayPolicy, options?: Call): Promise<TaxDisplayPolicyView>;
79
+ /**
80
+ * Replace the whole policy, and answer it as the engine now applies it.
81
+ *
82
+ * Pass all three fields: read with {@link get}, change what you mean to, send it back. An empty
83
+ * country list clears the stored list.
84
+ *
85
+ * Refused, before anything is written, `CHANNEL_SETTINGS_INVALID` (`ValidationError`) for a policy
86
+ * {@link preview} refuses. Refused by the save itself:
87
+ * - `ORGANIZATION_SETTINGS_INHERITED` (`BusinessRuleError`, 422) while the store uses its
88
+ * organization's policy: override it first (`tenant.settingsSources`), or change it in the
89
+ * organization's workspace;
90
+ * - `MANAGED_BY_ORGANIZATION` (`BusinessRuleError`, 422) if the organization manages the group;
91
+ * - `FORBIDDEN` without `UpdateChannel`.
92
+ *
93
+ * @effect write
94
+ */
95
+ set(policy: TaxDisplayPolicy, options?: Call): Promise<TaxDisplayPolicyView>;
96
+ }
97
+ export declare const TAX_DISPLAY_POLICY_QUERY = "\n query TaxDisplayPolicy {\n taxDisplayPolicy { \n default\n b2b\n countries\n pricesIncludeTax\n audiences {\n audience\n countryCode\n mode\n dependsOnStore\n }\n }\n }\n";
98
+ export declare const PREVIEW_TAX_DISPLAY_POLICY_QUERY = "\n query PreviewTaxDisplayPolicy($input: TaxDisplayPolicyInput!) {\n previewTaxDisplayPolicy(input: $input) { \n default\n b2b\n countries\n pricesIncludeTax\n audiences {\n audience\n countryCode\n mode\n dependsOnStore\n }\n }\n }\n";
99
+ /**
100
+ * The save's first step: the engine judges the policy (the preview's refusal is the save's) and
101
+ * names the channel `updateChannel` must be given, in one request with the save's call options.
102
+ */
103
+ export declare const CHECK_TAX_DISPLAY_POLICY_QUERY = "\n query CheckTaxDisplayPolicy($input: TaxDisplayPolicyInput!) {\n activeChannel { id }\n previewTaxDisplayPolicy(input: $input) { default }\n }\n";
104
+ export declare const SET_TAX_DISPLAY_POLICY_MUTATION = "\n mutation SetTaxDisplayPolicy($input: UpdateChannelInput!) {\n updateChannel(input: $input) {\n ... on Channel { id }\n ... on ErrorResult { errorCode message }\n }\n }\n";
105
+ export declare function createTaxDisplayPolicyModule(transport: Transport): TaxDisplayPolicyModule;
@@ -0,0 +1,84 @@
1
+ import { errorFromErrorResult, isErrorResult, } from '@sixtyninecommerce/core';
2
+ const VIEW_FIELDS = /* GraphQL */ `
3
+ default
4
+ b2b
5
+ countries
6
+ pricesIncludeTax
7
+ audiences {
8
+ audience
9
+ countryCode
10
+ mode
11
+ dependsOnStore
12
+ }
13
+ `;
14
+ export const TAX_DISPLAY_POLICY_QUERY = /* GraphQL */ `
15
+ query TaxDisplayPolicy {
16
+ taxDisplayPolicy { ${VIEW_FIELDS} }
17
+ }
18
+ `;
19
+ export const PREVIEW_TAX_DISPLAY_POLICY_QUERY = /* GraphQL */ `
20
+ query PreviewTaxDisplayPolicy($input: TaxDisplayPolicyInput!) {
21
+ previewTaxDisplayPolicy(input: $input) { ${VIEW_FIELDS} }
22
+ }
23
+ `;
24
+ /**
25
+ * The save's first step: the engine judges the policy (the preview's refusal is the save's) and
26
+ * names the channel `updateChannel` must be given, in one request with the save's call options.
27
+ */
28
+ export const CHECK_TAX_DISPLAY_POLICY_QUERY = /* GraphQL */ `
29
+ query CheckTaxDisplayPolicy($input: TaxDisplayPolicyInput!) {
30
+ activeChannel { id }
31
+ previewTaxDisplayPolicy(input: $input) { default }
32
+ }
33
+ `;
34
+ export const SET_TAX_DISPLAY_POLICY_MUTATION = /* GraphQL */ `
35
+ mutation SetTaxDisplayPolicy($input: UpdateChannelInput!) {
36
+ updateChannel(input: $input) {
37
+ ... on Channel { id }
38
+ ... on ErrorResult { errorCode message }
39
+ }
40
+ }
41
+ `;
42
+ /** Exactly the input the engine takes: no extra keys travel. */
43
+ function inputOf(policy) {
44
+ return { default: policy.default, b2b: policy.b2b, countries: [...policy.countries] };
45
+ }
46
+ export function createTaxDisplayPolicyModule(transport) {
47
+ const get = async (options) => {
48
+ const data = await transport.graphql({ api: 'admin', query: TAX_DISPLAY_POLICY_QUERY }, options);
49
+ return data.taxDisplayPolicy;
50
+ };
51
+ return {
52
+ get,
53
+ async preview(policy, options) {
54
+ const data = await transport.graphql({
55
+ api: 'admin',
56
+ query: PREVIEW_TAX_DISPLAY_POLICY_QUERY,
57
+ variables: { input: inputOf(policy) },
58
+ }, options);
59
+ return data.previewTaxDisplayPolicy;
60
+ },
61
+ async set(policy, options) {
62
+ const input = inputOf(policy);
63
+ const checked = await transport.graphql({ api: 'admin', query: CHECK_TAX_DISPLAY_POLICY_QUERY, variables: { input } }, options);
64
+ const data = await transport.graphql({
65
+ api: 'admin',
66
+ query: SET_TAX_DISPLAY_POLICY_MUTATION,
67
+ variables: {
68
+ input: {
69
+ id: checked.activeChannel.id,
70
+ customFields: {
71
+ taxDisplayDefault: input.default,
72
+ taxDisplayB2b: input.b2b,
73
+ // `null` is the column's "off", and the only value that clears a stored list.
74
+ taxExclusiveCountries: input.countries.length === 0 ? null : JSON.stringify(input.countries),
75
+ },
76
+ },
77
+ },
78
+ }, options);
79
+ if (isErrorResult(data.updateChannel))
80
+ throw errorFromErrorResult(data.updateChannel);
81
+ return get(options);
82
+ },
83
+ };
84
+ }
@@ -1,5 +1,6 @@
1
1
  import { type Page, type Transport } from '@sixtyninecommerce/core';
2
2
  import type { Call, ListOptions } from '../types.js';
3
+ import { type TaxDisplayPolicyModule } from './display-policy.js';
3
4
  /**
4
5
  * The mapping used when no mapping names the country the money is taxed in.
5
6
  *
@@ -187,6 +188,8 @@ export interface TaxModule {
187
188
  categories: TaxCategoriesModule;
188
189
  /** The platform-wide tax rates every store shares. */
189
190
  rates: TaxRatesModule;
191
+ /** Who the store shows prices with or without tax, saved or previewed. */
192
+ displayPolicy: TaxDisplayPolicyModule;
190
193
  }
191
194
  /** A {@link TaxCategory} as every read and write answers it (`platform.tax` reuses it). */
192
195
  export declare const TAX_CATEGORY_FIELDS = "\n id\n name\n isDefault\n createdAt\n updatedAt\n";
package/dist/tax/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { createPage } from '@sixtyninecommerce/core';
2
2
  import { vendureListPage } from '../catalog/types.js';
3
+ import { createTaxDisplayPolicyModule } from './display-policy.js';
3
4
  /**
4
5
  * The mapping used when no mapping names the country the money is taxed in.
5
6
  *
@@ -100,6 +101,7 @@ export const REMOVE_TAX_CLASS_MAPPING_MUTATION = /* GraphQL */ `
100
101
  `;
101
102
  export function createTaxModule(transport) {
102
103
  return {
104
+ displayPolicy: createTaxDisplayPolicyModule(transport),
103
105
  classes: {
104
106
  async list(options) {
105
107
  const data = await transport.graphql({ api: 'admin', query: TAX_CLASSES_QUERY }, options);