@sixtyninecommerce/admin 0.6.0 → 0.8.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 (39) hide show
  1. package/README.md +359 -2
  2. package/dist/apps/assertion.d.ts +30 -3
  3. package/dist/apps/assertion.js +40 -3
  4. package/dist/apps/config.d.ts +39 -0
  5. package/dist/apps/config.js +22 -0
  6. package/dist/apps/credential.d.ts +5 -0
  7. package/dist/apps/credential.js +55 -4
  8. package/dist/apps/index.d.ts +11 -0
  9. package/dist/client.d.ts +54 -1
  10. package/dist/client.js +34 -1
  11. package/dist/custom-objects/index.d.ts +66 -0
  12. package/dist/custom-objects/index.js +48 -0
  13. package/dist/customers/index.d.ts +225 -0
  14. package/dist/customers/index.js +279 -0
  15. package/dist/documents/index.d.ts +432 -0
  16. package/dist/documents/index.js +289 -0
  17. package/dist/index.d.ts +34 -2
  18. package/dist/index.js +16 -1
  19. package/dist/jobs/index.d.ts +143 -0
  20. package/dist/jobs/index.js +132 -0
  21. package/dist/metafields/index.d.ts +291 -0
  22. package/dist/metafields/index.js +141 -0
  23. package/dist/orders/index.d.ts +106 -0
  24. package/dist/orders/index.js +115 -0
  25. package/dist/orders/surcharges.d.ts +121 -0
  26. package/dist/orders/surcharges.js +110 -0
  27. package/dist/payments/index.d.ts +244 -0
  28. package/dist/payments/index.js +103 -0
  29. package/dist/payments/providers.d.ts +281 -0
  30. package/dist/payments/providers.js +205 -0
  31. package/dist/platform/provision-store.d.ts +9 -26
  32. package/dist/platform/provision-store.js +8 -66
  33. package/dist/tax/index.d.ts +128 -0
  34. package/dist/tax/index.js +101 -0
  35. package/dist/tenant/capabilities.d.ts +15 -0
  36. package/dist/types.d.ts +20 -3
  37. package/dist/uploads/index.d.ts +146 -0
  38. package/dist/uploads/index.js +72 -0
  39. package/package.json +3 -3
@@ -0,0 +1,121 @@
1
+ import type { Transport } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ /**
4
+ * A surcharge: an adjustment on a PLACED order that is not a line — a delivery
5
+ * charge, a negotiated discount, a handling fee.
6
+ *
7
+ * Money is integer MINOR UNITS of the order's currency, and `price` is NEGATIVE
8
+ * for a discount. `priceIncludesTax` says which basis the amount is stated in;
9
+ * there is no default, because guessing it is a 21% error.
10
+ */
11
+ export interface SurchargeInput {
12
+ description: string;
13
+ sku?: string | null;
14
+ /** Minor units. Negative for a discount agreed after the order was placed. */
15
+ price: number;
16
+ /** Whether `price` is gross. Required: the engine will not guess a basis. */
17
+ priceIncludesTax: boolean;
18
+ /**
19
+ * Percentage (21 for 21%). Omit it for no tax line at all — and never send it
20
+ * together with `taxClass`, which is refused rather than silently resolved
21
+ * one way.
22
+ */
23
+ taxRate?: number | null;
24
+ /**
25
+ * Label for the tax line. Refused together with `taxClass`: a class-priced
26
+ * line is named by the store's own tax setup — including names that are a
27
+ * policy statement, like `EU Reverse Charge (0%)` — and relabelling one would
28
+ * put on an invoice something the line is not.
29
+ */
30
+ taxDescription?: string | null;
31
+ }
32
+ /** Options for a surcharge write. */
33
+ export interface SurchargeCall extends Call {
34
+ /**
35
+ * Price the surcharge from one of the store's tax classes (spec §8.6)
36
+ * instead of from an explicit `taxRate`.
37
+ *
38
+ * Resolved PER ORDER, which is the half of the platform's tax-class decision
39
+ * that is not write-time: a surcharge is money the platform composes, with no
40
+ * product variant behind it to have been priced already.
41
+ *
42
+ * **Which country, and which zone — they are two different questions.** The
43
+ * order's shipping COUNTRY picks the class's mapping (that is the store's own
44
+ * "what kind of thing is this" decision, one row per country). The order's
45
+ * tax ZONE picks the rate for the category that mapping names. The two can
46
+ * legitimately differ: a store only moves a country into its own zone by
47
+ * listing it in the tax-exclusive countries setting, so a Belgian order on a
48
+ * store that has not listed BE is still priced in the store's default zone
49
+ * while the BE mapping decides the category. Map a country and configure that
50
+ * zone's rates, or the write is refused rather than silently untaxed.
51
+ *
52
+ * **The order's own tax policy still wins.** A tax-removed order and an EU
53
+ * reverse charge override whatever the class resolved to, because the
54
+ * resolved rate is run through the same tax-line strategy the order's lines
55
+ * go through. The class chooses which rate is looked up, never what the line
56
+ * finally says. A per-line rate imported from an ERP is the one policy that
57
+ * does NOT carry over: it belongs to a line the ERP sent, never to a charge
58
+ * the merchant adds afterwards.
59
+ *
60
+ * Refusals: `TAX_CLASS_NOT_FOUND` (→ `NotFoundError`) for a key this store
61
+ * does not have; `TAX_CLASS_UNMAPPED` (→ `ValidationError`) when the class
62
+ * says nothing about the order's country and has no `*` fallback; and
63
+ * `TAX_CLASS_RATE_MISSING` (→ `ValidationError`) when it is mapped but that
64
+ * category has no rate in the order's zone. Sending it together with
65
+ * `input.taxRate` or `input.taxDescription` is refused as bad input.
66
+ */
67
+ taxClass?: string;
68
+ }
69
+ /**
70
+ * The order the mutation answers with, as much of it as this surface projects.
71
+ *
72
+ * The totals are re-derived and PERSISTED by every one of these calls, so the
73
+ * numbers here are the order's new state rather than a projection of the
74
+ * request.
75
+ */
76
+ export interface SurchargedOrder {
77
+ id: string;
78
+ code: string;
79
+ currencyCode: string;
80
+ /** Minor units. */
81
+ total: number;
82
+ totalWithTax: number;
83
+ surcharges: Array<{
84
+ id: string;
85
+ description: string;
86
+ sku: string | null;
87
+ price: number;
88
+ priceWithTax: number;
89
+ taxRate: number;
90
+ }>;
91
+ }
92
+ /**
93
+ * Surcharges on a placed order.
94
+ *
95
+ * These exist beside Vendure's `modifyOrder`, which hard-requires a refund
96
+ * input for ANY downward price delta — so it cannot express "remove this
97
+ * discount" at all on an order with no payment to refund against. Needs
98
+ * `UpdateOrder`; refused once the order's invoice has been approved.
99
+ */
100
+ export interface SurchargesModule {
101
+ /** Add a surcharge and re-total the order. */
102
+ add(orderId: string, input: SurchargeInput, options?: SurchargeCall): Promise<SurchargedOrder>;
103
+ /**
104
+ * Replace a surcharge in place and re-total the order. The surcharge keeps
105
+ * its id, so a delivery charge stays linked to the fulfillment that created
106
+ * it, and an omitted `sku` is left alone rather than cleared.
107
+ *
108
+ * TAX IS NOT LIKE `sku`: this is a whole replacement, so omitting BOTH
109
+ * `options.taxClass` and `input.taxRate` writes a surcharge with no tax line
110
+ * at all and lowers the order total. Re-send whichever of the two the
111
+ * surcharge should carry — a `taxClass` is then resolved afresh, so the rate
112
+ * that applies now is the one written.
113
+ */
114
+ update(orderId: string, surchargeId: string, input: SurchargeInput, options?: SurchargeCall): Promise<SurchargedOrder>;
115
+ /** Remove a surcharge entirely and re-total the order. */
116
+ remove(orderId: string, surchargeId: string, options?: Call): Promise<SurchargedOrder>;
117
+ }
118
+ export declare const ADD_ORDER_SURCHARGE_MUTATION = "\n mutation AddOrderSurcharge(\n $orderId: ID!\n $input: SurchargeInput!\n $taxClass: String\n $idempotencyKey: String\n ) {\n addOrderSurcharge(\n orderId: $orderId\n input: $input\n taxClass: $taxClass\n idempotencyKey: $idempotencyKey\n ) {\n \n id\n code\n currencyCode\n total\n totalWithTax\n surcharges {\n id\n description\n sku\n price\n priceWithTax\n taxRate\n }\n\n }\n }\n";
119
+ export declare const UPDATE_ORDER_SURCHARGE_MUTATION = "\n mutation UpdateOrderSurcharge(\n $orderId: ID!\n $surchargeId: ID!\n $input: SurchargeInput!\n $taxClass: String\n $idempotencyKey: String\n ) {\n updateOrderSurcharge(\n orderId: $orderId\n surchargeId: $surchargeId\n input: $input\n taxClass: $taxClass\n idempotencyKey: $idempotencyKey\n ) {\n \n id\n code\n currencyCode\n total\n totalWithTax\n surcharges {\n id\n description\n sku\n price\n priceWithTax\n taxRate\n }\n\n }\n }\n";
120
+ export declare const REMOVE_ORDER_SURCHARGE_MUTATION = "\n mutation RemoveOrderSurcharge($orderId: ID!, $surchargeId: ID!, $idempotencyKey: String) {\n removeOrderSurcharge(\n orderId: $orderId\n surchargeId: $surchargeId\n idempotencyKey: $idempotencyKey\n ) {\n \n id\n code\n currencyCode\n total\n totalWithTax\n surcharges {\n id\n description\n sku\n price\n priceWithTax\n taxRate\n }\n\n }\n }\n";
121
+ export declare function createSurchargesModule(transport: Transport): SurchargesModule;
@@ -0,0 +1,110 @@
1
+ const SURCHARGED_ORDER_FIELDS = /* GraphQL */ `
2
+ id
3
+ code
4
+ currencyCode
5
+ total
6
+ totalWithTax
7
+ surcharges {
8
+ id
9
+ description
10
+ sku
11
+ price
12
+ priceWithTax
13
+ taxRate
14
+ }
15
+ `;
16
+ export const ADD_ORDER_SURCHARGE_MUTATION = /* GraphQL */ `
17
+ mutation AddOrderSurcharge(
18
+ $orderId: ID!
19
+ $input: SurchargeInput!
20
+ $taxClass: String
21
+ $idempotencyKey: String
22
+ ) {
23
+ addOrderSurcharge(
24
+ orderId: $orderId
25
+ input: $input
26
+ taxClass: $taxClass
27
+ idempotencyKey: $idempotencyKey
28
+ ) {
29
+ ${SURCHARGED_ORDER_FIELDS}
30
+ }
31
+ }
32
+ `;
33
+ export const UPDATE_ORDER_SURCHARGE_MUTATION = /* GraphQL */ `
34
+ mutation UpdateOrderSurcharge(
35
+ $orderId: ID!
36
+ $surchargeId: ID!
37
+ $input: SurchargeInput!
38
+ $taxClass: String
39
+ $idempotencyKey: String
40
+ ) {
41
+ updateOrderSurcharge(
42
+ orderId: $orderId
43
+ surchargeId: $surchargeId
44
+ input: $input
45
+ taxClass: $taxClass
46
+ idempotencyKey: $idempotencyKey
47
+ ) {
48
+ ${SURCHARGED_ORDER_FIELDS}
49
+ }
50
+ }
51
+ `;
52
+ export const REMOVE_ORDER_SURCHARGE_MUTATION = /* GraphQL */ `
53
+ mutation RemoveOrderSurcharge($orderId: ID!, $surchargeId: ID!, $idempotencyKey: String) {
54
+ removeOrderSurcharge(
55
+ orderId: $orderId
56
+ surchargeId: $surchargeId
57
+ idempotencyKey: $idempotencyKey
58
+ ) {
59
+ ${SURCHARGED_ORDER_FIELDS}
60
+ }
61
+ }
62
+ `;
63
+ /**
64
+ * `undefined` rather than `null` for an absent tax class: a variable explicitly
65
+ * set to null is still a value the engine reads, and this argument's whole
66
+ * contract is "omit it and the legacy `taxRate` path is untouched".
67
+ */
68
+ function taxClassVariable(options) {
69
+ const value = options?.taxClass;
70
+ return typeof value === 'string' && value.trim() !== '' ? value : undefined;
71
+ }
72
+ export function createSurchargesModule(transport) {
73
+ return {
74
+ async add(orderId, input, options) {
75
+ const data = await transport.graphql({
76
+ api: 'admin',
77
+ query: ADD_ORDER_SURCHARGE_MUTATION,
78
+ variables: {
79
+ orderId,
80
+ input,
81
+ taxClass: taxClassVariable(options),
82
+ idempotencyKey: options?.idempotencyKey,
83
+ },
84
+ }, options);
85
+ return data.addOrderSurcharge;
86
+ },
87
+ async update(orderId, surchargeId, input, options) {
88
+ const data = await transport.graphql({
89
+ api: 'admin',
90
+ query: UPDATE_ORDER_SURCHARGE_MUTATION,
91
+ variables: {
92
+ orderId,
93
+ surchargeId,
94
+ input,
95
+ taxClass: taxClassVariable(options),
96
+ idempotencyKey: options?.idempotencyKey,
97
+ },
98
+ }, options);
99
+ return data.updateOrderSurcharge;
100
+ },
101
+ async remove(orderId, surchargeId, options) {
102
+ const data = await transport.graphql({
103
+ api: 'admin',
104
+ query: REMOVE_ORDER_SURCHARGE_MUTATION,
105
+ variables: { orderId, surchargeId, idempotencyKey: options?.idempotencyKey },
106
+ }, options);
107
+ return data.removeOrderSurcharge;
108
+ },
109
+ };
110
+ }
@@ -0,0 +1,244 @@
1
+ import type { Transport } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ import { type ProvidersModule } from './providers.js';
4
+ /**
5
+ * What an order has actually been paid, in minor units of its own currency.
6
+ *
7
+ * Derived from the order's payments on every read, never stored — a stored copy
8
+ * is a second source of truth that drifts the first time a refund lands.
9
+ */
10
+ export interface OrderPaymentPosition {
11
+ /** The order's own gross total, carrying the order's rounding rule. */
12
+ total: number;
13
+ /** Settled plus authorized, less refunds: what is accounted for. */
14
+ covered: number;
15
+ /** Money actually taken, less refunds. This is what `orders.settle` requires. */
16
+ settled: number;
17
+ /** Money a payment handler may take and has not. */
18
+ authorized: number;
19
+ refunded: number;
20
+ /** `total - covered`, floored at zero. */
21
+ outstanding: number;
22
+ /**
23
+ * `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.
26
+ */
27
+ overpaid: number;
28
+ /** What a further payment may take. */
29
+ availableToCharge: number;
30
+ }
31
+ /** Money the merchant HAS, recorded against an order. */
32
+ export interface RecordPaymentInput {
33
+ /**
34
+ * Minor units of the order's currency. Greater than zero, and at most the
35
+ * order's `outstanding` — an over-payment is refused rather than accepted,
36
+ * and the refusal carries the position so a till can correct itself without a
37
+ * second round trip.
38
+ */
39
+ amount: number;
40
+ /** A payment method code configured on this channel. */
41
+ method: string;
42
+ /**
43
+ * Free-form detail stored on the payment, MINUS two keys the platform writes
44
+ * itself: `attribution` (the vouched-for staff, device and register refs) and
45
+ * `isDeposit`. Sending either is refused with `METADATA_KEY_RESERVED` rather
46
+ * than merged, so no caller can invent a till or a member of staff that every
47
+ * later report would believe.
48
+ *
49
+ * Anything you put under `public` is visible to the storefront — Vendure's
50
+ * Shop API exposes `metadata.public`. The platform never writes there.
51
+ */
52
+ metadata?: Record<string, unknown>;
53
+ }
54
+ /**
55
+ * One payment's contribution to an order's refund position.
56
+ */
57
+ export interface RefundablePayment {
58
+ paymentId: string;
59
+ /** Vendure's payment state. */
60
+ state: string;
61
+ /** The payment method code, or null when the payment carries no label. */
62
+ method: string | null;
63
+ /** Gross amount taken, minor units. */
64
+ amount: number;
65
+ /** Non-failed refunds already recorded against it. A failed refund never left. */
66
+ refunded: number;
67
+ /** `amount - refunded` when this payment took money, floored at zero; else zero. */
68
+ refundable: number;
69
+ /**
70
+ * Whether this payment took money at all.
71
+ *
72
+ * True for a settled payment and for an authorized one on a real gateway — a
73
+ * card sale at a terminal rests authorized until the webhook settles it, and
74
+ * that hold is real money. False for an authorized payment on an offline or
75
+ * net-terms method, where authorized means the money has NOT arrived.
76
+ */
77
+ tookMoney: boolean;
78
+ }
79
+ /**
80
+ * What an order may still hand back, in minor units of its own currency.
81
+ *
82
+ * A different question from {@link OrderPaymentPosition}, and the two disagree
83
+ * on purpose: that one nets refunds against every authorization because it
84
+ * answers "what is this order covered for", while this one counts only money
85
+ * that was actually TAKEN, because that is all a refund can return.
86
+ */
87
+ export interface OrderRefundPosition {
88
+ /** The order's currency. Every amount here is in its minor units. */
89
+ currencyCode: string;
90
+ /** Money already given back out of money that was taken. */
91
+ refunded: number;
92
+ /**
93
+ * What may still be handed back for this order: the sum of every payment's
94
+ * own remaining headroom, each floored at zero.
95
+ *
96
+ * There is deliberately no credit-note deduction. A credit note that moved
97
+ * money already has its refund on the payment; one that moved none has
98
+ * nothing to deduct.
99
+ */
100
+ refundable: number;
101
+ /** Every payment on the order, NEWEST FIRST, with its own headroom. */
102
+ perPayment: RefundablePayment[];
103
+ }
104
+ /** Money handed back to a customer. */
105
+ export interface RefundPaymentInput {
106
+ orderId: string;
107
+ /** Minor units of the order's currency. Greater than zero. */
108
+ amount: number;
109
+ /**
110
+ * The payment to return the money to.
111
+ *
112
+ * Omit it and the platform allocates across the order's paying payments
113
+ * NEWEST FIRST: it picks the most recent one whose remaining headroom can
114
+ * carry the WHOLE amount. A part-paid order settles its remainder last, so
115
+ * that is the money a merchant means by "give some of it back".
116
+ *
117
+ * **One call refunds against ONE payment.** When the order can return the
118
+ * amount but no single payment can, the call is refused with
119
+ * `REFUND_EXCEEDS_PAYMENT` and `perPayment` shows exactly how to split it —
120
+ * rather than the platform spilling silently onto a payment you did not name,
121
+ * which is what the engine would do.
122
+ */
123
+ paymentId?: string;
124
+ /** Free text stored on the refund. Shown to nobody automatically. */
125
+ reason?: string;
126
+ }
127
+ /** A refund, as this surface projects it. */
128
+ export interface IssuedRefund {
129
+ id: string;
130
+ /** Minor units. */
131
+ total: number;
132
+ /** `Pending`, `Settled` or `Failed`. */
133
+ state: string;
134
+ /** The payment method the refund was booked against. */
135
+ method: string | null;
136
+ /** The gateway's own receipt, when it gave one. */
137
+ transactionId: string | null;
138
+ reason: string | null;
139
+ }
140
+ /** The order, as much of it as this surface projects. */
141
+ export interface PaidOrder {
142
+ id: string;
143
+ code: string;
144
+ state: string;
145
+ currencyCode: string;
146
+ total: number;
147
+ totalWithTax: number;
148
+ }
149
+ /**
150
+ * Payments: money against an order (spec §8.2), and the provider accounts
151
+ * it runs through (spec §8.9).
152
+ *
153
+ * `providers` is payment-provider onboarding, terminals and readiness. The
154
+ * rest of this namespace is the money itself.
155
+ *
156
+ * `record` writes money the merchant HAS, which lands the payment `Settled`.
157
+ * There is no payment state to choose: an AUTHORIZATION is a payment method
158
+ * handler's business — the gateway decides whether a card may be charged later
159
+ * — so one cannot be created here. Authorized payments that handlers DO create
160
+ * are counted by `position()` all the same, under `authorized`; only the write
161
+ * side is narrowed.
162
+ *
163
+ * Needs `UpdateOrder` to record, `ReadOrder` to read the position.
164
+ */
165
+ export interface PaymentsModule {
166
+ /** Provider onboarding, terminals and readiness (spec §8.9). */
167
+ providers: ProvidersModule;
168
+ /**
169
+ * Record part (or all) of what an order owes, and return the order.
170
+ *
171
+ * `options.idempotencyKey` is honoured: the Admin API takes it as a mutation
172
+ * argument, so a retry under the same key returns the first call's order
173
+ * rather than taking the money twice. Use a fresh key per intended payment.
174
+ *
175
+ * Refusals: `AMOUNT_EXCEEDS_OUTSTANDING` (over-payment, with the position
176
+ * attached), `AMOUNT_NOT_POSITIVE`, `ORDER_NOT_RECORDABLE` (the order's state
177
+ * cannot take a payment), `DEPOSITS_NOT_ENABLED` — a PARTIAL payment on a
178
+ * store that has not turned deposits on; paying the whole outstanding balance
179
+ * is not a deposit and always works — `METADATA_KEY_RESERVED`,
180
+ * `PAYMENT_METHOD_NOT_FOUND`, `ORDER_NOT_FOUND`.
181
+ */
182
+ record(orderId: string, input: RecordPaymentInput, options?: Call): Promise<PaidOrder>;
183
+ /** Read an order's payment position. */
184
+ position(orderId: string, options?: Call): Promise<OrderPaymentPosition>;
185
+ /**
186
+ * Hand money back to a customer, never more than the order took.
187
+ *
188
+ * The platform's own refund ceiling, and the one the four surfaces that issue
189
+ * refunds — returns settlement, credit notes, the till and the order importer
190
+ * — are measured against. Refuses `REFUND_EXCEEDS_SETTLED` when the amount is
191
+ * more than the whole ORDER can return, which is the check no per-payment
192
+ * arithmetic can make: another surface may have refunded the rest of it ten
193
+ * seconds ago.
194
+ *
195
+ * `options.idempotencyKey` is honoured — the Admin API takes it as a mutation
196
+ * argument — so a retry under the same key returns the FIRST call's refund
197
+ * instead of raising a second one. Use a fresh key per intended refund.
198
+ *
199
+ * **`IDEMPOTENCY_OUTCOME_UNKNOWN` is neither success nor refusal.** The engine
200
+ * calls the payment gateway from inside the transaction that writes the refund
201
+ * row, so a failure after that call leaves an outcome nobody can read off the
202
+ * database: the money may be on its way back with no row to show for it. You
203
+ * get this code on the FIRST call when that happens, and on every repeat under
204
+ * the same key — the key is spent rather than released, so the refund never
205
+ * runs again. Do NOT treat it as `REFUND_REFUSED`: read
206
+ * `payments.refundPosition(orderId)`, reconcile against the gateway, and only
207
+ * then decide. If the money did not move, issue a new request under a NEW key.
208
+ *
209
+ * (The server also attaches the position to that error, but `PlatformError`
210
+ * carries only `code`, `message`, `details` and `traceId`, so an SDK caller
211
+ * reads it with `refundPosition(orderId)` rather than off the error.)
212
+ *
213
+ * Only money that was TAKEN can come back: a settled payment, or an
214
+ * authorized one on a real gateway. An offline or net-terms authorization
215
+ * took nothing and is refused with `REFUND_PAYMENT_HOLDS_NO_MONEY`.
216
+ *
217
+ * **The refund you get back is one that moved money.** On an OFFLINE method —
218
+ * bank transfer, invoice, cash, an imported order's historical tender — it
219
+ * comes back `Settled`, because there the money moves by hand and recording
220
+ * it is the settlement. On a live gateway it comes back `Pending` and settles
221
+ * when the gateway calls back. A method whose handler cannot be resolved at
222
+ * all, because it is disabled or no longer on this store, is refused
223
+ * `REFUND_METHOD_UNAVAILABLE` before anything is created, with the payment and
224
+ * the method in `extensions.details`.
225
+ *
226
+ * Other refusals: `REFUND_EXCEEDS_PAYMENT` (the order can return this much,
227
+ * but no single payment can — split it, using `perPayment`),
228
+ * `REFUND_PAYMENT_NOT_FOUND`, `REFUND_AMOUNT_NOT_POSITIVE`,
229
+ * `REFUND_ORDER_NOT_FOUND`, and `REFUND_REFUSED` when the money was there and
230
+ * the engine or the gateway said no anyway. Every refusal raised once the
231
+ * order has been read carries that order's position in
232
+ * `extensions.refundPosition`, so a till can correct itself without a second
233
+ * round trip.
234
+ */
235
+ refund(input: RefundPaymentInput, options?: Call): Promise<IssuedRefund>;
236
+ /** Read what an order may still hand back. */
237
+ refundPosition(orderId: string, options?: Call): Promise<OrderRefundPosition>;
238
+ }
239
+ 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";
240
+ 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";
241
+ 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";
242
+ 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";
243
+ export declare function createPaymentsModule(transport: Transport): PaymentsModule;
244
+ export type { ProviderConnection, ProviderCredentialPath, ProviderOnboardingStart, ProviderReadiness, ProvidersModule, ProviderTerminal, ProviderTerminalsModule, ProvisionTerminalInput, ReadinessOptions, } from './providers.js';
@@ -0,0 +1,103 @@
1
+ import { createProvidersModule } from './providers.js';
2
+ const PAID_ORDER_FIELDS = /* GraphQL */ `
3
+ id
4
+ code
5
+ state
6
+ currencyCode
7
+ total
8
+ totalWithTax
9
+ `;
10
+ const POSITION_FIELDS = /* GraphQL */ `
11
+ total
12
+ covered
13
+ settled
14
+ authorized
15
+ refunded
16
+ outstanding
17
+ overpaid
18
+ availableToCharge
19
+ `;
20
+ export const RECORD_ORDER_PAYMENT_MUTATION = /* GraphQL */ `
21
+ mutation RecordOrderPayment($orderId: ID!, $input: RecordPaymentInput!, $idempotencyKey: String) {
22
+ recordOrderPayment(orderId: $orderId, input: $input, idempotencyKey: $idempotencyKey) {
23
+ ${PAID_ORDER_FIELDS}
24
+ }
25
+ }
26
+ `;
27
+ export const ORDER_PAYMENT_POSITION_QUERY = /* GraphQL */ `
28
+ query OrderPaymentPosition($orderId: ID!) {
29
+ orderPaymentPosition(orderId: $orderId) {
30
+ ${POSITION_FIELDS}
31
+ }
32
+ }
33
+ `;
34
+ const REFUND_POSITION_FIELDS = /* GraphQL */ `
35
+ currencyCode
36
+ refunded
37
+ refundable
38
+ perPayment {
39
+ paymentId
40
+ state
41
+ method
42
+ amount
43
+ refunded
44
+ refundable
45
+ tookMoney
46
+ }
47
+ `;
48
+ export const ORDER_REFUND_POSITION_QUERY = /* GraphQL */ `
49
+ query OrderRefundPosition($orderId: ID!) {
50
+ orderRefundPosition(orderId: $orderId) {
51
+ ${REFUND_POSITION_FIELDS}
52
+ }
53
+ }
54
+ `;
55
+ export const REFUND_ORDER_PAYMENT_MUTATION = /* GraphQL */ `
56
+ mutation RefundOrderPayment($input: RefundPaymentInput!, $idempotencyKey: String) {
57
+ refundOrderPayment(input: $input, idempotencyKey: $idempotencyKey) {
58
+ id
59
+ total
60
+ state
61
+ method
62
+ transactionId
63
+ reason
64
+ }
65
+ }
66
+ `;
67
+ export function createPaymentsModule(transport) {
68
+ return {
69
+ providers: createProvidersModule(transport),
70
+ async record(orderId, input, options) {
71
+ const data = await transport.graphql({
72
+ api: 'admin',
73
+ query: RECORD_ORDER_PAYMENT_MUTATION,
74
+ // Forwarded as a VARIABLE, not a header: the Admin API has no header
75
+ // for it, which is why the mutation takes the key as an argument.
76
+ // `undefined`, never an explicit null — `JSON.stringify` drops it, so
77
+ // an omitted key stays off the wire entirely rather than arriving as a
78
+ // value a future server could read as one.
79
+ variables: { orderId, input, idempotencyKey: options?.idempotencyKey },
80
+ }, options);
81
+ return data.recordOrderPayment;
82
+ },
83
+ async position(orderId, options) {
84
+ const data = await transport.graphql({ api: 'admin', query: ORDER_PAYMENT_POSITION_QUERY, variables: { orderId } }, options);
85
+ return data.orderPaymentPosition;
86
+ },
87
+ async refund(input, options) {
88
+ const data = await transport.graphql({
89
+ api: 'admin',
90
+ query: REFUND_ORDER_PAYMENT_MUTATION,
91
+ // Forwarded as a VARIABLE, not a header: the Admin API has no header
92
+ // for it. `undefined`, never an explicit null — `JSON.stringify` drops
93
+ // it, so an omitted key stays off the wire entirely.
94
+ variables: { input, idempotencyKey: options?.idempotencyKey },
95
+ }, options);
96
+ return data.refundOrderPayment;
97
+ },
98
+ async refundPosition(orderId, options) {
99
+ const data = await transport.graphql({ api: 'admin', query: ORDER_REFUND_POSITION_QUERY, variables: { orderId } }, options);
100
+ return data.orderRefundPosition;
101
+ },
102
+ };
103
+ }