@sixtyninecommerce/admin 0.7.0 → 0.9.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 (161) hide show
  1. package/README.md +2445 -17
  2. package/dist/api-tokens/index.d.ts +15 -5
  3. package/dist/api-tokens/index.js +1 -0
  4. package/dist/apps/event-subscription.d.ts +59 -0
  5. package/dist/apps/event-subscription.js +32 -0
  6. package/dist/apps/hook-secret.d.ts +22 -0
  7. package/dist/apps/hook-secret.js +36 -0
  8. package/dist/apps/index.d.ts +54 -3
  9. package/dist/apps/index.js +17 -0
  10. package/dist/audit/index.d.ts +7 -0
  11. package/dist/auth/queries.d.ts +5 -1
  12. package/dist/auth/queries.js +6 -0
  13. package/dist/bulk/index.d.ts +323 -0
  14. package/dist/bulk/index.js +162 -0
  15. package/dist/catalog/assets.d.ts +147 -0
  16. package/dist/catalog/assets.js +164 -0
  17. package/dist/catalog/collections.d.ts +109 -0
  18. package/dist/catalog/collections.js +91 -0
  19. package/dist/catalog/facets.d.ts +103 -0
  20. package/dist/catalog/facets.js +100 -0
  21. package/dist/catalog/index.d.ts +115 -0
  22. package/dist/catalog/index.js +21 -0
  23. package/dist/catalog/options.d.ts +89 -0
  24. package/dist/catalog/options.js +88 -0
  25. package/dist/catalog/products-bulk.d.ts +21 -0
  26. package/dist/catalog/products-bulk.js +58 -0
  27. package/dist/catalog/products.d.ts +489 -0
  28. package/dist/catalog/products.js +365 -0
  29. package/dist/catalog/properties.d.ts +234 -0
  30. package/dist/catalog/properties.js +158 -0
  31. package/dist/catalog/types.d.ts +174 -0
  32. package/dist/catalog/types.js +141 -0
  33. package/dist/catalog/variants.d.ts +274 -0
  34. package/dist/catalog/variants.js +258 -0
  35. package/dist/catalog/visibility.d.ts +57 -0
  36. package/dist/catalog/visibility.js +59 -0
  37. package/dist/client.d.ts +171 -3
  38. package/dist/client.js +81 -12
  39. package/dist/compliance/index.d.ts +88 -0
  40. package/dist/compliance/index.js +88 -0
  41. package/dist/customer-data-redaction.d.ts +14 -0
  42. package/dist/customer-data-redaction.js +22 -0
  43. package/dist/customers/index.d.ts +428 -17
  44. package/dist/customers/index.js +322 -15
  45. package/dist/documents/index.d.ts +513 -16
  46. package/dist/documents/index.js +229 -3
  47. package/dist/events/index.d.ts +259 -0
  48. package/dist/events/index.js +147 -0
  49. package/dist/feeds/ai.d.ts +46 -0
  50. package/dist/feeds/ai.js +43 -0
  51. package/dist/feeds/categories.d.ts +50 -0
  52. package/dist/feeds/categories.js +56 -0
  53. package/dist/feeds/configs.d.ts +54 -0
  54. package/dist/feeds/configs.js +85 -0
  55. package/dist/feeds/identifier-fields.d.ts +25 -0
  56. package/dist/feeds/identifier-fields.js +29 -0
  57. package/dist/feeds/index.d.ts +54 -0
  58. package/dist/feeds/index.js +46 -0
  59. package/dist/feeds/preserve.d.ts +38 -0
  60. package/dist/feeds/preserve.js +74 -0
  61. package/dist/feeds/rules.d.ts +42 -0
  62. package/dist/feeds/rules.js +56 -0
  63. package/dist/feeds/types.d.ts +654 -0
  64. package/dist/feeds/types.js +135 -0
  65. package/dist/fulfillments/index.d.ts +360 -0
  66. package/dist/fulfillments/index.js +425 -0
  67. package/dist/heads/index.d.ts +60 -0
  68. package/dist/heads/index.js +45 -0
  69. package/dist/hooks/assignments.d.ts +90 -0
  70. package/dist/hooks/assignments.js +53 -0
  71. package/dist/hooks/index.d.ts +97 -0
  72. package/dist/hooks/index.js +76 -0
  73. package/dist/index.d.ts +84 -9
  74. package/dist/index.js +16 -1
  75. package/dist/jobs/bulk-action-run.d.ts +65 -0
  76. package/dist/jobs/bulk-action-run.js +70 -0
  77. package/dist/locations/index.d.ts +6 -2
  78. package/dist/meta/index.d.ts +32 -0
  79. package/dist/orders/commit-edit.d.ts +123 -0
  80. package/dist/orders/commit-edit.js +142 -0
  81. package/dist/orders/get.d.ts +722 -0
  82. package/dist/orders/get.js +530 -0
  83. package/dist/orders/index.d.ts +105 -20
  84. package/dist/orders/index.js +44 -0
  85. package/dist/orders/line-price-preview.d.ts +297 -0
  86. package/dist/orders/line-price-preview.js +50 -0
  87. package/dist/orders/manual-discounts.d.ts +132 -0
  88. package/dist/orders/manual-discounts.js +95 -0
  89. package/dist/orders/manual-pricing.d.ts +192 -0
  90. package/dist/orders/manual-pricing.js +72 -0
  91. package/dist/orders/order-entry.d.ts +566 -0
  92. package/dist/orders/order-entry.js +129 -0
  93. package/dist/orders/parcel-charge.d.ts +45 -0
  94. package/dist/orders/parcel-charge.js +55 -0
  95. package/dist/orders/plan-edit.d.ts +489 -0
  96. package/dist/orders/plan-edit.js +93 -0
  97. package/dist/orders/status.d.ts +235 -0
  98. package/dist/orders/status.js +96 -0
  99. package/dist/orders/surcharges.d.ts +75 -2
  100. package/dist/orders/surcharges.js +110 -4
  101. package/dist/payments/account-credit.d.ts +171 -0
  102. package/dist/payments/account-credit.js +107 -0
  103. package/dist/payments/index.d.ts +368 -2
  104. package/dist/payments/index.js +138 -0
  105. package/dist/platform/catalog.d.ts +148 -0
  106. package/dist/platform/catalog.js +74 -0
  107. package/dist/platform/entitlements.d.ts +111 -0
  108. package/dist/platform/entitlements.js +86 -0
  109. package/dist/platform/legal-entities.d.ts +139 -0
  110. package/dist/platform/legal-entities.js +126 -0
  111. package/dist/platform/legal-entity-numbering.d.ts +103 -0
  112. package/dist/platform/legal-entity-numbering.js +101 -0
  113. package/dist/platform/organization-membership.d.ts +80 -0
  114. package/dist/platform/organization-membership.js +71 -0
  115. package/dist/platform/organization-settings.d.ts +33 -0
  116. package/dist/platform/organization-settings.js +42 -0
  117. package/dist/platform/organization-sharing.d.ts +172 -0
  118. package/dist/platform/organization-sharing.js +120 -0
  119. package/dist/platform/organizations.d.ts +205 -0
  120. package/dist/platform/organizations.js +180 -0
  121. package/dist/platform/provision-store.d.ts +88 -8
  122. package/dist/platform/provision-store.js +12 -0
  123. package/dist/platform/reports.d.ts +46 -0
  124. package/dist/platform/reports.js +31 -0
  125. package/dist/platform/server-metrics.d.ts +58 -0
  126. package/dist/platform/server-metrics.js +11 -0
  127. package/dist/pos/index.d.ts +567 -0
  128. package/dist/pos/index.js +205 -0
  129. package/dist/pricing/index.d.ts +405 -0
  130. package/dist/pricing/index.js +351 -0
  131. package/dist/provenance/index.d.ts +93 -0
  132. package/dist/provenance/index.js +53 -0
  133. package/dist/reports/index.d.ts +199 -0
  134. package/dist/reports/index.js +154 -0
  135. package/dist/shipping/parcel-count-suggestion.d.ts +52 -0
  136. package/dist/shipping/parcel-count-suggestion.js +73 -0
  137. package/dist/shipping/parcel-rule.d.ts +48 -0
  138. package/dist/shipping/parcel-rule.js +91 -0
  139. package/dist/stock/index.d.ts +166 -0
  140. package/dist/stock/index.js +115 -0
  141. package/dist/stock/transfers.d.ts +520 -0
  142. package/dist/stock/transfers.js +437 -0
  143. package/dist/stored-value/index.d.ts +154 -0
  144. package/dist/stored-value/index.js +130 -0
  145. package/dist/tenant/capabilities.d.ts +10 -0
  146. package/dist/tenant/entitlements.d.ts +35 -0
  147. package/dist/tenant/entitlements.js +15 -0
  148. package/dist/tenant/field-groups.d.ts +64 -0
  149. package/dist/tenant/field-groups.js +34 -0
  150. package/dist/tenant/legal-entity.d.ts +32 -0
  151. package/dist/tenant/legal-entity.js +41 -0
  152. package/dist/tenant/notifications.d.ts +148 -0
  153. package/dist/tenant/notifications.js +79 -0
  154. package/dist/tenant/retention.d.ts +10 -4
  155. package/dist/tenant/settings-sources.d.ts +103 -0
  156. package/dist/tenant/settings-sources.js +92 -0
  157. package/dist/types.d.ts +86 -11
  158. package/dist/uploads/index.d.ts +11 -7
  159. package/dist/users/index.d.ts +104 -0
  160. package/dist/users/index.js +80 -0
  161. package/package.json +3 -2
@@ -1,5 +1,6 @@
1
1
  import type { Transport } from '@sixtyninecommerce/core';
2
2
  import type { Call } from '../types.js';
3
+ import { type AccountCreditModule } from './account-credit.js';
3
4
  import { type ProvidersModule } from './providers.js';
4
5
  /**
5
6
  * What an order has actually been paid, in minor units of its own currency.
@@ -16,13 +17,20 @@ export interface OrderPaymentPosition {
16
17
  settled: number;
17
18
  /** Money a payment handler may take and has not. */
18
19
  authorized: number;
20
+ /**
21
+ * Refunds recorded against the order's payments. Money moved to the
22
+ * customer's account (`payments.accountCredit`) is NOT a refund and is not
23
+ * counted here, though it is taken off `settled` like one.
24
+ */
19
25
  refunded: number;
20
26
  /** `total - covered`, floored at zero. */
21
27
  outstanding: number;
22
28
  /**
23
29
  * `covered - total`, floored at zero. Over-payment is refused at the door, so
24
- * this is non-zero only for imported history, rows predating the guard, or a
25
- * refund that landed after a second payment.
30
+ * this is non-zero only for imported history, rows predating the guard, a
31
+ * refund that landed after a second payment, or an edit that lowered the
32
+ * total of a paid order. Money moved to the customer's account
33
+ * (`payments.accountCredit.creditOverpayment`) no longer counts here.
26
34
  */
27
35
  overpaid: number;
28
36
  /** What a further payment may take. */
@@ -51,6 +59,139 @@ export interface RecordPaymentInput {
51
59
  */
52
60
  metadata?: Record<string, unknown>;
53
61
  }
62
+ /**
63
+ * One payment's contribution to an order's refund position.
64
+ */
65
+ export interface RefundablePayment {
66
+ paymentId: string;
67
+ /** Vendure's payment state. */
68
+ state: string;
69
+ /** The payment method code, or null when the payment carries no label. */
70
+ method: string | null;
71
+ /** Gross amount taken, minor units. */
72
+ amount: number;
73
+ /**
74
+ * Refunds already recorded against it that did not fail, plus failed ones
75
+ * whose outcome is unknown — reserved until the provider's answer is recorded
76
+ * (see {@link PaymentsModule.unreconciledRefunds}). A plainly failed refund
77
+ * never left.
78
+ */
79
+ refunded: number;
80
+ /**
81
+ * `amount - refunded`, less what of this payment is on the customer's account
82
+ * (`payments.accountCredit.onOrder`), when this payment took money; floored
83
+ * at zero, else zero.
84
+ */
85
+ refundable: number;
86
+ /**
87
+ * Whether this payment took money at all.
88
+ *
89
+ * True for a settled payment and for an authorized one on a real gateway — a
90
+ * card sale at a terminal rests authorized until the webhook settles it, and
91
+ * that hold is real money. False for an authorized payment on an offline or
92
+ * net-terms method, where authorized means the money has NOT arrived.
93
+ */
94
+ tookMoney: boolean;
95
+ }
96
+ /**
97
+ * What an order may still hand back, in minor units of its own currency.
98
+ *
99
+ * A different question from {@link OrderPaymentPosition}, and the two disagree
100
+ * on purpose: that one nets refunds against every authorization because it
101
+ * answers "what is this order covered for", while this one counts only money
102
+ * that was actually TAKEN, because that is all a refund can return.
103
+ */
104
+ export interface OrderRefundPosition {
105
+ /** The order's currency. Every amount here is in its minor units. */
106
+ currencyCode: string;
107
+ /** Money already given back out of money that was taken. */
108
+ refunded: number;
109
+ /**
110
+ * What may still be handed back for this order: the sum of every payment's
111
+ * own remaining headroom, each floored at zero.
112
+ *
113
+ * There is deliberately no credit-note deduction. A credit note that moved
114
+ * money already has its refund on the payment; one that moved none has
115
+ * nothing to deduct.
116
+ *
117
+ * Money moved to the customer's account as unapplied cash IS deducted: it is
118
+ * paid back from the account (`payments.accountCredit.refund`), never from
119
+ * the order a second time.
120
+ */
121
+ refundable: number;
122
+ /** Every payment on the order, NEWEST FIRST, with its own headroom. */
123
+ perPayment: RefundablePayment[];
124
+ }
125
+ /**
126
+ * A refund whose outcome is unknown: it reached its payment provider and was
127
+ * never confirmed (a timeout, a dropped connection, a server error), so the
128
+ * platform cannot say whether the money moved. Its amount is reserved — counted
129
+ * in the refund position's `refunded` — until
130
+ * {@link PaymentsModule.reconcileRefund} records the provider's answer.
131
+ */
132
+ export interface UnreconciledRefund {
133
+ /** The refund to pass to `reconcileRefund`. */
134
+ refundId: string;
135
+ paymentId: string;
136
+ /** Minor units of the order's currency. */
137
+ amount: number;
138
+ /** ISO-8601 with offset. */
139
+ createdAt: string | null;
140
+ }
141
+ /** What the payment provider says happened to a refund whose outcome was unknown. */
142
+ export type RefundProviderOutcome = 'MADE' | 'NOT_MADE';
143
+ /** The provider's answer for a refund whose outcome is unknown. */
144
+ export interface ReconcileRefundInput {
145
+ refundId: string;
146
+ /**
147
+ * `MADE`: the money went back. `NOT_MADE`: nothing moved. Checked with the
148
+ * provider — never guessed.
149
+ */
150
+ outcome: RefundProviderOutcome;
151
+ /**
152
+ * The provider's reference for its answer: its refund id when it made one, or
153
+ * where the answer was checked. Required, at most 200 characters.
154
+ */
155
+ providerReference: string;
156
+ /** Optional context for the order's history, at most 1000 characters. */
157
+ note?: string;
158
+ }
159
+ /** Money handed back to a customer. */
160
+ export interface RefundPaymentInput {
161
+ orderId: string;
162
+ /** Minor units of the order's currency. Greater than zero. */
163
+ amount: number;
164
+ /**
165
+ * The payment to return the money to.
166
+ *
167
+ * Omit it and the platform allocates across the order's paying payments
168
+ * NEWEST FIRST: it picks the most recent one whose remaining headroom can
169
+ * carry the WHOLE amount. A part-paid order settles its remainder last, so
170
+ * that is the money a merchant means by "give some of it back".
171
+ *
172
+ * **One call refunds against ONE payment.** When the order can return the
173
+ * amount but no single payment can, the call is refused with
174
+ * `REFUND_EXCEEDS_PAYMENT` and `perPayment` shows exactly how to split it —
175
+ * rather than the platform spilling silently onto a payment you did not name,
176
+ * which is what the engine would do.
177
+ */
178
+ paymentId?: string;
179
+ /** Free text stored on the refund. Shown to nobody automatically. */
180
+ reason?: string;
181
+ }
182
+ /** A refund, as this surface projects it. */
183
+ export interface IssuedRefund {
184
+ id: string;
185
+ /** Minor units. */
186
+ total: number;
187
+ /** `Pending`, `Settled` or `Failed`. */
188
+ state: string;
189
+ /** The payment method the refund was booked against. */
190
+ method: string | null;
191
+ /** The gateway's own receipt, when it gave one. */
192
+ transactionId: string | null;
193
+ reason: string | null;
194
+ }
54
195
  /** The order, as much of it as this surface projects. */
55
196
  export interface PaidOrder {
56
197
  id: string;
@@ -60,6 +201,65 @@ export interface PaidOrder {
60
201
  total: number;
61
202
  totalWithTax: number;
62
203
  }
204
+ /** What a payment app reports happened to a payment it took (`reportAppPayment`). */
205
+ export type AppPaymentReportState = 'Authorized' | 'Settled' | 'Declined' | 'Cancelled';
206
+ /** An app's report on one of its payments. */
207
+ export interface ReportAppPaymentInput {
208
+ /**
209
+ * What the provider did. An authorized payment can be reported `Settled`,
210
+ * `Declined` or `Cancelled`; a payment whose outcome is unknown (see
211
+ * {@link AppPayment}) only `Settled` or `Declined` — the provider knows
212
+ * whether it took the money.
213
+ *
214
+ * `Authorized` is for ONE case: you answered `create` `Authorized` with a
215
+ * `redirect_url`, and the buyer finished your hosted page with the money
216
+ * authorized, to be captured later (pay later, capture at shipment). Until
217
+ * you report, the order stays the buyer's unplaced cart; this report places
218
+ * it (`PaymentAuthorized`) when the payment covers it. A later `Settled`
219
+ * report, or the store capturing it (your `capture` hook), settles it. Any
220
+ * other payment reported `Authorized` is `PAYMENT_STATE_NOT_REPORTABLE`.
221
+ */
222
+ state: AppPaymentReportState;
223
+ /**
224
+ * The provider's reference for the payment, at most 255 characters. When the
225
+ * app answered `create` with one, it must be that one.
226
+ */
227
+ providerReference: string;
228
+ /** Minor units of the order's currency. Must equal the payment's amount. */
229
+ amount: number;
230
+ }
231
+ /** A payment an app took, as the installation that took it reads it. */
232
+ export interface AppPayment {
233
+ id: string;
234
+ orderId: string;
235
+ orderCode: string;
236
+ /** Vendure's payment state: `Authorized`, `Settled`, `Declined`, `Error`, `Cancelled`. */
237
+ state: string;
238
+ /** Minor units. */
239
+ amount: number;
240
+ currencyCode: string;
241
+ /** The provider's reference — the payment's `transactionId` — once the app gave one. */
242
+ providerReference: string | null;
243
+ methodCode: string;
244
+ /**
245
+ * The platform asked the app (create, or capture) and never heard back, so
246
+ * whether the money moved is unknown. The platform does NOT ask again (a
247
+ * second request could be a second charge): report the outcome with
248
+ * {@link PaymentsModule.reportAppPayment}.
249
+ */
250
+ outcomeUnknown: boolean;
251
+ /** ISO-8601 with offset. */
252
+ createdAt: string;
253
+ }
254
+ /** The payment as it stands after an app's report. */
255
+ export interface ReportedAppPayment {
256
+ id: string;
257
+ state: string;
258
+ /** Minor units. */
259
+ amount: number;
260
+ method: string;
261
+ transactionId: string | null;
262
+ }
63
263
  /**
64
264
  * Payments: money against an order (spec §8.2), and the provider accounts
65
265
  * it runs through (spec §8.9).
@@ -79,6 +279,11 @@ export interface PaidOrder {
79
279
  export interface PaymentsModule {
80
280
  /** Provider onboarding, terminals and readiness (spec §8.9). */
81
281
  providers: ProvidersModule;
282
+ /**
283
+ * An order's overpayment on the customer's account: move it there, apply it
284
+ * to an invoice, pay it back.
285
+ */
286
+ accountCredit: AccountCreditModule;
82
287
  /**
83
288
  * Record part (or all) of what an order owes, and return the order.
84
289
  *
@@ -96,8 +301,169 @@ export interface PaymentsModule {
96
301
  record(orderId: string, input: RecordPaymentInput, options?: Call): Promise<PaidOrder>;
97
302
  /** Read an order's payment position. */
98
303
  position(orderId: string, options?: Call): Promise<OrderPaymentPosition>;
304
+ /**
305
+ * Hand money back to a customer, never more than the order took.
306
+ *
307
+ * The platform's own refund ceiling, and the one the four surfaces that issue
308
+ * refunds — returns settlement, credit notes, the till and the order importer
309
+ * — are measured against. Refuses `REFUND_EXCEEDS_SETTLED` when the amount is
310
+ * more than the whole ORDER can return, which is the check no per-payment
311
+ * arithmetic can make: another surface may have refunded the rest of it ten
312
+ * seconds ago.
313
+ *
314
+ * `options.idempotencyKey` is honoured — the Admin API takes it as a mutation
315
+ * argument — so a retry under the same key returns the FIRST call's refund
316
+ * instead of raising a second one. Use a fresh key per intended refund.
317
+ *
318
+ * **`error.outcomeUnknown` has two causes here, and they recover differently.**
319
+ *
320
+ * 1. **No answer came back** (a timeout, your own signal aborting the call
321
+ * after it was sent, a dropped connection, a proxy's 502/504). The first
322
+ * call may still be running on the server and its key is NOT spent, so
323
+ * repeat the call under the SAME key, never a new one. The
324
+ * platform then answers with the first call's refund, with
325
+ * `IDEMPOTENCY_IN_PROGRESS` (wait, then repeat again under that key), or
326
+ * with `IDEMPOTENCY_OUTCOME_UNKNOWN` (case 2). A NEW key here can refund
327
+ * twice: the second request waits on the order lock until the first one
328
+ * commits, and then both fit under the ceiling. A call made without a key
329
+ * has no safe repeat: once the first call can have finished, read
330
+ * `payments.refundPosition(orderId)` and reconcile against the gateway.
331
+ * 2. **`IDEMPOTENCY_OUTCOME_UNKNOWN`** is neither success nor refusal. It
332
+ * arrives as a `ConflictError` (409) because the key is spent, but the class
333
+ * is not the message: branch on the code, or on `error.outcomeUnknown`. The
334
+ * engine calls the payment gateway from inside the transaction that writes the refund
335
+ * row, so a failure after that call leaves an outcome nobody can read off the
336
+ * database: the money may be on its way back with no row to show for it. You
337
+ * get this code on the FIRST call when that happens, and on every repeat under
338
+ * the same key — the key is spent rather than released, so the refund never
339
+ * runs again. Do NOT treat it as `REFUND_REFUSED`: the attempt is recorded as
340
+ * a refund whose outcome is unknown, and its amount stays RESERVED in the
341
+ * position — this call, the till, credit notes, returns and core's own
342
+ * `refundOrder` mutation (the dashboard's Refund button) no longer refund
343
+ * the order or that payment past what they took. The reservation does NOT
344
+ * stop a new request for the same
345
+ * partial amount while headroom remains, so never retry under a new key
346
+ * blindly. Find the attempt with `payments.unreconciledRefunds(orderId)`,
347
+ * check the gateway, and record the answer with `payments.reconcileRefund(...)`.
348
+ * After `MADE` the spent key replays that refund; after `NOT_MADE` it may run
349
+ * again, and the amount is refundable again.
350
+ *
351
+ * (The server also attaches the position to that error, but `PlatformError`
352
+ * carries only `code`, `message`, `details` and `traceId`, so an SDK caller
353
+ * reads it with `refundPosition(orderId)` rather than off the error.)
354
+ *
355
+ * Only money that was TAKEN can come back: a settled payment, or an
356
+ * authorized one on a real gateway. An offline or net-terms authorization
357
+ * took nothing and is refused with `REFUND_PAYMENT_HOLDS_NO_MONEY`.
358
+ *
359
+ * **The refund you get back is one that moved money.** On an OFFLINE method —
360
+ * bank transfer, invoice, cash, an imported order's historical tender — it
361
+ * comes back `Settled`, because there the money moves by hand and recording
362
+ * it is the settlement. On a live gateway it comes back `Pending` and settles
363
+ * when the gateway calls back. A method whose handler cannot be resolved at
364
+ * all, because it is disabled or no longer on this store, is refused
365
+ * `REFUND_METHOD_UNAVAILABLE` before anything is created, with the payment and
366
+ * the method in `extensions.details`.
367
+ *
368
+ * Other refusals: `REFUND_EXCEEDS_PAYMENT` (the order can return this much,
369
+ * but no single payment can — split it, using `perPayment`),
370
+ * `REFUND_PAYMENT_NOT_FOUND`, `REFUND_AMOUNT_NOT_POSITIVE`,
371
+ * `REFUND_ORDER_NOT_FOUND`, and `REFUND_REFUSED` when the money was there and
372
+ * the engine or the gateway said no anyway. Every refusal raised once the
373
+ * order has been read carries that order's position in
374
+ * `extensions.refundPosition`, so a till can correct itself without a second
375
+ * round trip.
376
+ */
377
+ refund(input: RefundPaymentInput, options?: Call): Promise<IssuedRefund>;
378
+ /** Read what an order may still hand back. */
379
+ refundPosition(orderId: string, options?: Call): Promise<OrderRefundPosition>;
380
+ /**
381
+ * The order's refunds whose outcome is unknown, oldest first — the ones
382
+ * {@link reconcileRefund} resolves. Each one's amount is already reserved in
383
+ * {@link refundPosition}.
384
+ *
385
+ * A refund lands here when its payment provider was asked and never
386
+ * confirmed: `refund` answered `IDEMPOTENCY_OUTCOME_UNKNOWN`, or a till card
387
+ * refund, a credit note or a return settlement did. Needs `ReadOrder`.
388
+ */
389
+ unreconciledRefunds(orderId: string, options?: Call): Promise<UnreconciledRefund[]>;
390
+ /**
391
+ * Record the payment provider's answer for a refund whose outcome is unknown.
392
+ * Needs `UpdateOrder` — the permission refunds take.
393
+ *
394
+ * - `MADE`: the money went back. The refund becomes `Settled` as if the
395
+ * provider had confirmed it at the time: it counts as returned, a return
396
+ * parked on it completes its settlement, and `payment.refunded` is
397
+ * announced. The key that spent itself on the attempt now replays it.
398
+ * - `NOT_MADE`: nothing moved. The refund stays `Failed`, its reservation is
399
+ * released and a retry is allowed — the spent key, a till refund, the credit
400
+ * note, or settling the parked return again.
401
+ *
402
+ * The outcome is kept on the refund's metadata, which the Shop API serves, so
403
+ * nothing else goes there: `providerReference`, `note` and who recorded it go
404
+ * to a private order note and the audit trail.
405
+ *
406
+ * Refusals: `REFUND_NOT_FOUND`, `REFUND_OUTCOME_NOT_UNKNOWN` (the outcome is
407
+ * already known — never unknown, or reconciled already),
408
+ * `REFUND_RECONCILIATION_INVALID` (a blank or oversized `providerReference`,
409
+ * an oversized `note`), and `REFUND_EXCEEDS_PAYMENT` when `MADE` would have
410
+ * the payment return more than it took (another refund on record against it
411
+ * cannot be right).
412
+ *
413
+ * `options.idempotencyKey` is honoured: a repeat under the same key returns
414
+ * the first call's refund.
415
+ */
416
+ reconcileRefund(input: ReconcileRefundInput, options?: Call): Promise<IssuedRefund>;
417
+ /**
418
+ * **For a payment app, with its installation token.** Report what happened to
419
+ * a payment your app took (spec §8.14 `payment.provider`): the asynchronous
420
+ * pattern — you answered `create` `Authorized`, and the money lands later —
421
+ * and the reconciliation of a payment whose outcome is unknown (you were
422
+ * asked and the platform never received your answer; it will not ask again).
423
+ *
424
+ * The platform moves the payment through its own payment processes, exactly
425
+ * as for any provider callback: a covered order is settled and placed, money
426
+ * for a held (parked) order lands where the order stands, and
427
+ * `payment.settled` is published with your installation as its actor. A
428
+ * hosted page that only authorized is reported `Authorized` (see
429
+ * {@link ReportAppPaymentInput.state}): the order is placed on it.
430
+ *
431
+ * `options.idempotencyKey` is REQUIRED: a repeat of the same report under it
432
+ * answers the payment as it now is, for as long as the payment exists; a
433
+ * DIFFERENT report under it is refused `IDEMPOTENCY_CONFLICT` (409). Use one
434
+ * key per event you received from your provider.
435
+ *
436
+ * Refusals: `PAYMENT_NOT_OWNED_BY_INSTALLATION` (a `PermissionDeniedError`,
437
+ * 403: not a payment this installation took on this store — one answer
438
+ * whatever the reason),
439
+ * `PAYMENT_AMOUNT_MISMATCH`, `PAYMENT_STATE_NOT_REPORTABLE` (the payment
440
+ * cannot move to that state from where it is, `extensions.details.state`),
441
+ * `APP_PAYMENT_REPORT_INVALID` (a malformed report, or a reference other than
442
+ * the one `create` answered), `APP_PAYMENT_METHOD_DISABLED` (the store took
443
+ * your app off as its payment provider; a decline is still recorded),
444
+ * `IDEMPOTENCY_KEY_INVALID`.
445
+ */
446
+ reportAppPayment(paymentId: string, input: ReportAppPaymentInput, options: Call & {
447
+ idempotencyKey: string;
448
+ }): Promise<ReportedAppPayment>;
449
+ /**
450
+ * **For a payment app, with its installation token.** Your installation's
451
+ * payments on one order of this store, oldest first: how you find a
452
+ * payment's id, which the `create` call cannot carry because the payment
453
+ * does not exist until you answer. Match on `providerReference`. An order the
454
+ * store does not have answers `[]`; any caller but an installation is refused
455
+ * `PAYMENT_NOT_OWNED_BY_INSTALLATION`.
456
+ */
457
+ appPayments(orderId: string, options?: Call): Promise<AppPayment[]>;
99
458
  }
100
459
  export declare const RECORD_ORDER_PAYMENT_MUTATION = "\n mutation RecordOrderPayment($orderId: ID!, $input: RecordPaymentInput!, $idempotencyKey: String) {\n recordOrderPayment(orderId: $orderId, input: $input, idempotencyKey: $idempotencyKey) {\n \n id\n code\n state\n currencyCode\n total\n totalWithTax\n\n }\n }\n";
101
460
  export declare const ORDER_PAYMENT_POSITION_QUERY = "\n query OrderPaymentPosition($orderId: ID!) {\n orderPaymentPosition(orderId: $orderId) {\n \n total\n covered\n settled\n authorized\n refunded\n outstanding\n overpaid\n availableToCharge\n\n }\n }\n";
461
+ export declare const ORDER_REFUND_POSITION_QUERY = "\n query OrderRefundPosition($orderId: ID!) {\n orderRefundPosition(orderId: $orderId) {\n \n currencyCode\n refunded\n refundable\n perPayment {\n paymentId\n state\n method\n amount\n refunded\n refundable\n tookMoney\n }\n\n }\n }\n";
462
+ export declare const REFUND_ORDER_PAYMENT_MUTATION = "\n mutation RefundOrderPayment($input: RefundPaymentInput!, $idempotencyKey: String) {\n refundOrderPayment(input: $input, idempotencyKey: $idempotencyKey) {\n id\n total\n state\n method\n transactionId\n reason\n }\n }\n";
463
+ export declare const UNRECONCILED_REFUNDS_QUERY = "\n query UnreconciledRefunds($orderId: ID!) {\n orderRefundPosition(orderId: $orderId) {\n unreconciled {\n refundId\n paymentId\n amount\n createdAt\n }\n }\n }\n";
464
+ export declare const RECONCILE_REFUND_OUTCOME_MUTATION = "\n mutation ReconcileRefundOutcome($input: ReconcileRefundOutcomeInput!, $idempotencyKey: String) {\n reconcileRefundOutcome(input: $input, idempotencyKey: $idempotencyKey) {\n id\n total\n state\n method\n transactionId\n reason\n }\n }\n";
465
+ export declare const REPORT_APP_PAYMENT_MUTATION = "\n mutation ReportAppPayment(\n $paymentId: ID!\n $input: ReportAppPaymentInput!\n $idempotencyKey: String!\n ) {\n reportAppPayment(paymentId: $paymentId, input: $input, idempotencyKey: $idempotencyKey) {\n id\n state\n amount\n method\n transactionId\n }\n }\n";
466
+ export declare const APP_PAYMENTS_QUERY = "\n query AppPayments($orderId: ID!) {\n appPayments(orderId: $orderId) {\n id\n orderId\n orderCode\n state\n amount\n currencyCode\n providerReference\n methodCode\n outcomeUnknown\n createdAt\n }\n }\n";
102
467
  export declare function createPaymentsModule(transport: Transport): PaymentsModule;
468
+ export type { AccountCreditModule, ApplyUnappliedCashInput, CreditOverpaymentInput, OrderMoneyOnAccount, RefundUnappliedCashInput, UnappliedCash, UnappliedCashRefund, } from './account-credit.js';
103
469
  export type { ProviderConnection, ProviderCredentialPath, ProviderOnboardingStart, ProviderReadiness, ProvidersModule, ProviderTerminal, ProviderTerminalsModule, ProvisionTerminalInput, ReadinessOptions, } from './providers.js';
@@ -1,3 +1,4 @@
1
+ import { createAccountCreditModule } from './account-credit.js';
1
2
  import { createProvidersModule } from './providers.js';
2
3
  const PAID_ORDER_FIELDS = /* GraphQL */ `
3
4
  id
@@ -31,9 +32,98 @@ export const ORDER_PAYMENT_POSITION_QUERY = /* GraphQL */ `
31
32
  }
32
33
  }
33
34
  `;
35
+ const REFUND_POSITION_FIELDS = /* GraphQL */ `
36
+ currencyCode
37
+ refunded
38
+ refundable
39
+ perPayment {
40
+ paymentId
41
+ state
42
+ method
43
+ amount
44
+ refunded
45
+ refundable
46
+ tookMoney
47
+ }
48
+ `;
49
+ export const ORDER_REFUND_POSITION_QUERY = /* GraphQL */ `
50
+ query OrderRefundPosition($orderId: ID!) {
51
+ orderRefundPosition(orderId: $orderId) {
52
+ ${REFUND_POSITION_FIELDS}
53
+ }
54
+ }
55
+ `;
56
+ export const REFUND_ORDER_PAYMENT_MUTATION = /* GraphQL */ `
57
+ mutation RefundOrderPayment($input: RefundPaymentInput!, $idempotencyKey: String) {
58
+ refundOrderPayment(input: $input, idempotencyKey: $idempotencyKey) {
59
+ id
60
+ total
61
+ state
62
+ method
63
+ transactionId
64
+ reason
65
+ }
66
+ }
67
+ `;
68
+ export const UNRECONCILED_REFUNDS_QUERY = /* GraphQL */ `
69
+ query UnreconciledRefunds($orderId: ID!) {
70
+ orderRefundPosition(orderId: $orderId) {
71
+ unreconciled {
72
+ refundId
73
+ paymentId
74
+ amount
75
+ createdAt
76
+ }
77
+ }
78
+ }
79
+ `;
80
+ export const RECONCILE_REFUND_OUTCOME_MUTATION = /* GraphQL */ `
81
+ mutation ReconcileRefundOutcome($input: ReconcileRefundOutcomeInput!, $idempotencyKey: String) {
82
+ reconcileRefundOutcome(input: $input, idempotencyKey: $idempotencyKey) {
83
+ id
84
+ total
85
+ state
86
+ method
87
+ transactionId
88
+ reason
89
+ }
90
+ }
91
+ `;
92
+ export const REPORT_APP_PAYMENT_MUTATION = /* GraphQL */ `
93
+ mutation ReportAppPayment(
94
+ $paymentId: ID!
95
+ $input: ReportAppPaymentInput!
96
+ $idempotencyKey: String!
97
+ ) {
98
+ reportAppPayment(paymentId: $paymentId, input: $input, idempotencyKey: $idempotencyKey) {
99
+ id
100
+ state
101
+ amount
102
+ method
103
+ transactionId
104
+ }
105
+ }
106
+ `;
107
+ export const APP_PAYMENTS_QUERY = /* GraphQL */ `
108
+ query AppPayments($orderId: ID!) {
109
+ appPayments(orderId: $orderId) {
110
+ id
111
+ orderId
112
+ orderCode
113
+ state
114
+ amount
115
+ currencyCode
116
+ providerReference
117
+ methodCode
118
+ outcomeUnknown
119
+ createdAt
120
+ }
121
+ }
122
+ `;
34
123
  export function createPaymentsModule(transport) {
35
124
  return {
36
125
  providers: createProvidersModule(transport),
126
+ accountCredit: createAccountCreditModule(transport),
37
127
  async record(orderId, input, options) {
38
128
  const data = await transport.graphql({
39
129
  api: 'admin',
@@ -51,5 +141,53 @@ export function createPaymentsModule(transport) {
51
141
  const data = await transport.graphql({ api: 'admin', query: ORDER_PAYMENT_POSITION_QUERY, variables: { orderId } }, options);
52
142
  return data.orderPaymentPosition;
53
143
  },
144
+ async refund(input, options) {
145
+ const data = await transport.graphql({
146
+ api: 'admin',
147
+ query: REFUND_ORDER_PAYMENT_MUTATION,
148
+ // Forwarded as a VARIABLE, not a header: the Admin API has no header
149
+ // for it. `undefined`, never an explicit null — `JSON.stringify` drops
150
+ // it, so an omitted key stays off the wire entirely.
151
+ variables: { input, idempotencyKey: options?.idempotencyKey },
152
+ }, options);
153
+ return data.refundOrderPayment;
154
+ },
155
+ async refundPosition(orderId, options) {
156
+ const data = await transport.graphql({ api: 'admin', query: ORDER_REFUND_POSITION_QUERY, variables: { orderId } }, options);
157
+ return data.orderRefundPosition;
158
+ },
159
+ // Its own query rather than a field on `refundPosition`'s: an SDK released
160
+ // ahead of a server without `unreconciled` must not break that read.
161
+ async unreconciledRefunds(orderId, options) {
162
+ const data = await transport.graphql({ api: 'admin', query: UNRECONCILED_REFUNDS_QUERY, variables: { orderId } }, options);
163
+ return data.orderRefundPosition.unreconciled;
164
+ },
165
+ async reconcileRefund(input, options) {
166
+ const data = await transport.graphql({
167
+ api: 'admin',
168
+ query: RECONCILE_REFUND_OUTCOME_MUTATION,
169
+ // A variable, not a header: the Admin API takes the key as an argument.
170
+ variables: { input, idempotencyKey: options?.idempotencyKey },
171
+ }, options);
172
+ return data.reconcileRefundOutcome;
173
+ },
174
+ async reportAppPayment(paymentId, input, options) {
175
+ // Refused here rather than sent: the argument is non-null on the wire, and
176
+ // a report without a key could never be safely repeated.
177
+ if (typeof options?.idempotencyKey !== 'string' || options.idempotencyKey.trim() === '') {
178
+ throw new TypeError('reportAppPayment needs options.idempotencyKey: one key per provider event.');
179
+ }
180
+ const data = await transport.graphql({
181
+ api: 'admin',
182
+ query: REPORT_APP_PAYMENT_MUTATION,
183
+ // A variable, not a header: the Admin API takes the key as an argument.
184
+ variables: { paymentId, input, idempotencyKey: options.idempotencyKey },
185
+ }, options);
186
+ return data.reportAppPayment;
187
+ },
188
+ async appPayments(orderId, options) {
189
+ const data = await transport.graphql({ api: 'admin', query: APP_PAYMENTS_QUERY, variables: { orderId } }, options);
190
+ return data.appPayments;
191
+ },
54
192
  };
55
193
  }