@sixtyninecommerce/admin 0.8.0 → 0.10.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 (179) hide show
  1. package/README.md +2739 -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 +650 -0
  28. package/dist/catalog/products.js +458 -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 +324 -0
  34. package/dist/catalog/variants.js +288 -0
  35. package/dist/catalog/visibility.d.ts +57 -0
  36. package/dist/catalog/visibility.js +59 -0
  37. package/dist/client.d.ts +192 -3
  38. package/dist/client.js +87 -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 +437 -0
  66. package/dist/fulfillments/index.js +534 -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 +95 -9
  74. package/dist/index.js +21 -1
  75. package/dist/integrations/index.d.ts +14 -0
  76. package/dist/integrations/index.js +9 -0
  77. package/dist/integrations/pipelines.d.ts +113 -0
  78. package/dist/integrations/pipelines.js +62 -0
  79. package/dist/integrations/types.d.ts +176 -0
  80. package/dist/integrations/types.js +8 -0
  81. package/dist/jobs/bulk-action-run.d.ts +74 -0
  82. package/dist/jobs/bulk-action-run.js +69 -0
  83. package/dist/locations/index.d.ts +6 -2
  84. package/dist/meta/index.d.ts +32 -0
  85. package/dist/orders/bulk.d.ts +75 -0
  86. package/dist/orders/bulk.js +150 -0
  87. package/dist/orders/commit-edit.d.ts +123 -0
  88. package/dist/orders/commit-edit.js +142 -0
  89. package/dist/orders/deposit-policy.d.ts +103 -0
  90. package/dist/orders/deposit-policy.js +202 -0
  91. package/dist/orders/get.d.ts +722 -0
  92. package/dist/orders/get.js +530 -0
  93. package/dist/orders/index.d.ts +186 -21
  94. package/dist/orders/index.js +57 -0
  95. package/dist/orders/line-price-preview.d.ts +297 -0
  96. package/dist/orders/line-price-preview.js +50 -0
  97. package/dist/orders/manual-discounts.d.ts +141 -0
  98. package/dist/orders/manual-discounts.js +97 -0
  99. package/dist/orders/manual-pricing.d.ts +192 -0
  100. package/dist/orders/manual-pricing.js +72 -0
  101. package/dist/orders/order-entry.d.ts +566 -0
  102. package/dist/orders/order-entry.js +129 -0
  103. package/dist/orders/parcel-charge.d.ts +45 -0
  104. package/dist/orders/parcel-charge.js +55 -0
  105. package/dist/orders/plan-edit.d.ts +489 -0
  106. package/dist/orders/plan-edit.js +93 -0
  107. package/dist/orders/status.d.ts +235 -0
  108. package/dist/orders/status.js +96 -0
  109. package/dist/orders/surcharges.d.ts +75 -2
  110. package/dist/orders/surcharges.js +110 -4
  111. package/dist/payments/account-credit.d.ts +171 -0
  112. package/dist/payments/account-credit.js +107 -0
  113. package/dist/payments/index.d.ts +241 -9
  114. package/dist/payments/index.js +92 -0
  115. package/dist/payments/methods.d.ts +37 -0
  116. package/dist/payments/methods.js +33 -0
  117. package/dist/platform/catalog.d.ts +148 -0
  118. package/dist/platform/catalog.js +74 -0
  119. package/dist/platform/entitlements.d.ts +111 -0
  120. package/dist/platform/entitlements.js +86 -0
  121. package/dist/platform/legal-entities.d.ts +139 -0
  122. package/dist/platform/legal-entities.js +126 -0
  123. package/dist/platform/legal-entity-numbering.d.ts +103 -0
  124. package/dist/platform/legal-entity-numbering.js +101 -0
  125. package/dist/platform/organization-membership.d.ts +80 -0
  126. package/dist/platform/organization-membership.js +71 -0
  127. package/dist/platform/organization-settings.d.ts +33 -0
  128. package/dist/platform/organization-settings.js +42 -0
  129. package/dist/platform/organization-sharing.d.ts +172 -0
  130. package/dist/platform/organization-sharing.js +120 -0
  131. package/dist/platform/organizations.d.ts +205 -0
  132. package/dist/platform/organizations.js +180 -0
  133. package/dist/platform/provision-store.d.ts +88 -8
  134. package/dist/platform/provision-store.js +12 -0
  135. package/dist/platform/reports.d.ts +46 -0
  136. package/dist/platform/reports.js +31 -0
  137. package/dist/platform/server-metrics.d.ts +58 -0
  138. package/dist/platform/server-metrics.js +11 -0
  139. package/dist/pos/index.d.ts +567 -0
  140. package/dist/pos/index.js +205 -0
  141. package/dist/pricing/index.d.ts +408 -0
  142. package/dist/pricing/index.js +353 -0
  143. package/dist/pricing/vouchers.d.ts +103 -0
  144. package/dist/pricing/vouchers.js +69 -0
  145. package/dist/provenance/index.d.ts +93 -0
  146. package/dist/provenance/index.js +53 -0
  147. package/dist/reports/index.d.ts +199 -0
  148. package/dist/reports/index.js +154 -0
  149. package/dist/returns/index.d.ts +225 -0
  150. package/dist/returns/index.js +160 -0
  151. package/dist/search/index.d.ts +99 -0
  152. package/dist/search/index.js +62 -0
  153. package/dist/shipping/parcel-count-suggestion.d.ts +52 -0
  154. package/dist/shipping/parcel-count-suggestion.js +73 -0
  155. package/dist/shipping/parcel-rule.d.ts +48 -0
  156. package/dist/shipping/parcel-rule.js +91 -0
  157. package/dist/stock/index.d.ts +166 -0
  158. package/dist/stock/index.js +115 -0
  159. package/dist/stock/transfers.d.ts +520 -0
  160. package/dist/stock/transfers.js +437 -0
  161. package/dist/stored-value/index.d.ts +154 -0
  162. package/dist/stored-value/index.js +130 -0
  163. package/dist/tenant/capabilities.d.ts +10 -0
  164. package/dist/tenant/entitlements.d.ts +35 -0
  165. package/dist/tenant/entitlements.js +15 -0
  166. package/dist/tenant/field-groups.d.ts +64 -0
  167. package/dist/tenant/field-groups.js +34 -0
  168. package/dist/tenant/legal-entity.d.ts +32 -0
  169. package/dist/tenant/legal-entity.js +41 -0
  170. package/dist/tenant/notifications.d.ts +148 -0
  171. package/dist/tenant/notifications.js +79 -0
  172. package/dist/tenant/retention.d.ts +10 -4
  173. package/dist/tenant/settings-sources.d.ts +103 -0
  174. package/dist/tenant/settings-sources.js +92 -0
  175. package/dist/types.d.ts +86 -11
  176. package/dist/uploads/index.d.ts +11 -7
  177. package/dist/users/index.d.ts +104 -0
  178. package/dist/users/index.js +80 -0
  179. package/package.json +3 -2
@@ -0,0 +1,171 @@
1
+ import type { Transport } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ /**
4
+ * Unapplied cash: money a customer paid on an order OVER what the order bills,
5
+ * moved to their account and held there until it pays an invoice or is paid
6
+ * back. Never a credit note: nothing that was billed is credited.
7
+ *
8
+ * Every amount is in minor units of `currencyCode`, and
9
+ * `amount = applied + refunded + remaining`.
10
+ */
11
+ export interface UnappliedCash {
12
+ id: string;
13
+ customerId: string;
14
+ /** The currency of the payment the money came from: its order's. */
15
+ currencyCode: string;
16
+ /** What was moved to the account. */
17
+ amount: number;
18
+ /** What of it has paid invoices. */
19
+ applied: number;
20
+ /** What of it was paid back to the customer. */
21
+ refunded: number;
22
+ /** What is still on the account, applied to nothing. */
23
+ remaining: number;
24
+ /** The order the money was paid on. */
25
+ orderId: string;
26
+ /** The payment of that order it was taken from. */
27
+ paymentId: string;
28
+ /** Date only (`YYYY-MM-DD`). */
29
+ receivedOn: string;
30
+ reference: string | null;
31
+ /** The reason given when the money was moved. */
32
+ notes: string | null;
33
+ /** ISO-8601 with offset. */
34
+ createdAt: string;
35
+ }
36
+ export interface CreditOverpaymentInput {
37
+ orderId: string;
38
+ /**
39
+ * Minor units of the order's currency. Omit it to move everything the order
40
+ * holds over what it bills.
41
+ */
42
+ amount?: number;
43
+ /** Why, in your own words: shown on the receipt and in the order's history. */
44
+ reason?: string;
45
+ }
46
+ export interface ApplyUnappliedCashInput {
47
+ unappliedCashId: string;
48
+ /** The AR invoice to pay. Give exactly one of `invoiceId` and `orderId`. */
49
+ invoiceId?: string;
50
+ /** An order, paid through the live AR invoice that bills it. */
51
+ orderId?: string;
52
+ /**
53
+ * Minor units. Omit it to apply as much as fits: the lesser of what the cash
54
+ * still holds and what the invoice still owes.
55
+ */
56
+ amount?: number;
57
+ }
58
+ export interface RefundUnappliedCashInput {
59
+ unappliedCashId: string;
60
+ /** Minor units. Omit it to pay back everything the cash still holds. */
61
+ amount?: number;
62
+ /** Free text stored on the refund. Shown to nobody automatically. */
63
+ reason?: string;
64
+ }
65
+ /** A payout's refund, as this surface projects it. */
66
+ export interface UnappliedCashRefund {
67
+ id: string;
68
+ /** Minor units. */
69
+ total: number;
70
+ /** `Pending`, `Settled` or `Failed`. */
71
+ state: string;
72
+ method: string | null;
73
+ transactionId: string | null;
74
+ reason: string | null;
75
+ }
76
+ /** What of an order's money is on its customer's account now. */
77
+ export interface OrderMoneyOnAccount {
78
+ /** The order's currency. Every amount here is in its minor units. */
79
+ currencyCode: string;
80
+ /**
81
+ * Money that left the order for the customer's account and was not paid back
82
+ * since. Already taken off the order's `refundable` and `overpaid`.
83
+ */
84
+ creditedToAccount: number;
85
+ /** The same figure per payment of the order, newest first. */
86
+ perPayment: Array<{
87
+ paymentId: string;
88
+ creditedToAccount: number;
89
+ }>;
90
+ }
91
+ /**
92
+ * An order's overpayment on the customer's account (`admin.payments.accountCredit`).
93
+ *
94
+ * For a store that keeps its own accounts-receivable ledger and a customer with
95
+ * a credit account in it. Anywhere else an overpayment is refunded: the calls
96
+ * here are refused `AR_LEDGER_NOT_ENABLED`, `AR_ACCOUNT_REQUIRED` or
97
+ * `AR_ACCOUNT_IN_ERP`. The last one covers every customer of a store whose ERP
98
+ * integration is on, and any ERP-linked account: balances are kept in the ERP
99
+ * there, where a credit recorded here would not show.
100
+ *
101
+ * Needs `UpdateOrder` to write, `ReadOrder` to read. Every write honours
102
+ * `options.idempotencyKey`: a repeat under the same key answers the first
103
+ * call's result instead of running again.
104
+ */
105
+ export interface AccountCreditModule {
106
+ /**
107
+ * Move money a customer paid on an order over what it bills onto their
108
+ * account. Answers one {@link UnappliedCash} per payment the money came from,
109
+ * newest payment first.
110
+ *
111
+ * Only money a settled payment still holds can move, net of every refund and
112
+ * of what was moved before, and at most what the order holds over its
113
+ * billable total. From then on that money is no longer the order's:
114
+ * `payments.refundPosition` takes it off `refundable` and `payments.position`
115
+ * no longer reports it as `overpaid` (read it with {@link onOrder}).
116
+ *
117
+ * An order that is already on a live AR invoice is refused
118
+ * `AR_ORDER_ALREADY_INVOICED`: refund its overpayment with `payments.refund`.
119
+ *
120
+ * Other refusals: `ACCOUNT_CREDIT_NOTHING_OVERPAID`,
121
+ * `ACCOUNT_CREDIT_EXCEEDS_OVERPAYMENT`, `ACCOUNT_CREDIT_AMOUNT_INVALID`,
122
+ * `ACCOUNT_CREDIT_NO_CUSTOMER`, `ACCOUNT_CREDIT_ORDER_NOT_FOUND`, and the three
123
+ * account refusals above.
124
+ */
125
+ creditOverpayment(input: CreditOverpaymentInput, options?: Call): Promise<UnappliedCash[]>;
126
+ /** A customer's unapplied cash in this store, oldest first. */
127
+ list(customerId: string, options?: Call): Promise<UnappliedCash[]>;
128
+ /**
129
+ * Pay an AR invoice with unapplied cash. The customer's balance does not
130
+ * move: the cash was already theirs.
131
+ *
132
+ * The invoice must be the same customer's, in the same currency, live and
133
+ * still owing. Refusals: `AR_INVOICE_NOT_FOUND`, `AR_CURRENCY_MISMATCH`,
134
+ * `AR_INVOICE_NOT_OPEN`, `AR_ORDER_NOT_INVOICED` (an order with no live
135
+ * invoice: invoice it first), `UNAPPLIED_CASH_EXCEEDED`,
136
+ * `UNAPPLIED_CASH_NOT_FOUND`, `UNAPPLIED_CASH_REFUND_UNRECONCILED` (a payout
137
+ * of the same cash has an unknown outcome), `AR_LEDGER_NOT_ENABLED`.
138
+ */
139
+ apply(input: ApplyUnappliedCashInput, options?: Call): Promise<UnappliedCash>;
140
+ /**
141
+ * Pay unapplied cash back to the customer: a refund of the payment it was
142
+ * taken from, with `payments.refund`'s rules and refusals. When one refuses,
143
+ * nothing has changed.
144
+ *
145
+ * At most what the cash still holds, and at most what the customer's account
146
+ * is in credit by in that currency (`UNAPPLIED_CASH_EXCEEDED`): cash is
147
+ * applied to what a customer owes before it is paid out.
148
+ *
149
+ * **`IDEMPOTENCY_OUTCOME_UNKNOWN`** means the payment provider was asked and
150
+ * never confirmed. The cash STAYS on the account and is frozen
151
+ * (`UNAPPLIED_CASH_REFUND_UNRECONCILED`). Find the attempt with
152
+ * `payments.unreconciledRefunds(orderId)`, check the provider, and record its
153
+ * answer with `payments.reconcileRefund(...)`: `MADE` takes the cash off the
154
+ * account then, `NOT_MADE` unfreezes it. Never pay out again on the
155
+ * assumption that nothing happened.
156
+ */
157
+ refund(input: RefundUnappliedCashInput, options?: Call): Promise<UnappliedCashRefund>;
158
+ /** What of an order's money is on its customer's account now. Needs `ReadOrder`. */
159
+ onOrder(orderId: string, options?: Call): Promise<OrderMoneyOnAccount>;
160
+ }
161
+ export declare const CREDIT_ORDER_OVERPAYMENT_MUTATION = "\n mutation CreditOrderOverpaymentToAccount(\n $input: CreditOrderOverpaymentInput!\n $idempotencyKey: String\n ) {\n creditOrderOverpaymentToAccount(input: $input, idempotencyKey: $idempotencyKey) {\n \n id\n customerId\n currencyCode\n amount\n applied\n refunded\n remaining\n orderId\n paymentId\n receivedOn\n reference\n notes\n createdAt\n\n }\n }\n";
162
+ export declare const UNAPPLIED_CASH_QUERY = "\n query ArUnappliedCash($customerId: ID!) {\n arUnappliedCash(customerId: $customerId) {\n \n id\n customerId\n currencyCode\n amount\n applied\n refunded\n remaining\n orderId\n paymentId\n receivedOn\n reference\n notes\n createdAt\n\n }\n }\n";
163
+ export declare const APPLY_UNAPPLIED_CASH_MUTATION = "\n mutation ApplyArUnappliedCash($input: ApplyArUnappliedCashInput!, $idempotencyKey: String) {\n applyArUnappliedCash(input: $input, idempotencyKey: $idempotencyKey) {\n \n id\n customerId\n currencyCode\n amount\n applied\n refunded\n remaining\n orderId\n paymentId\n receivedOn\n reference\n notes\n createdAt\n\n }\n }\n";
164
+ export declare const REFUND_UNAPPLIED_CASH_MUTATION = "\n mutation RefundArUnappliedCash($input: RefundArUnappliedCashInput!, $idempotencyKey: String) {\n refundArUnappliedCash(input: $input, idempotencyKey: $idempotencyKey) {\n id\n total\n state\n method\n transactionId\n reason\n }\n }\n";
165
+ /**
166
+ * Its own query, never a field added to `payments.refundPosition`'s: an SDK
167
+ * released ahead of a server without `creditedToAccount` must not break that
168
+ * read.
169
+ */
170
+ export declare const ORDER_MONEY_ON_ACCOUNT_QUERY = "\n query OrderMoneyOnAccount($orderId: ID!) {\n orderRefundPosition(orderId: $orderId) {\n currencyCode\n creditedToAccount\n perPayment {\n paymentId\n creditedToAccount\n }\n }\n }\n";
171
+ export declare function createAccountCreditModule(transport: Transport): AccountCreditModule;
@@ -0,0 +1,107 @@
1
+ const UNAPPLIED_CASH_FIELDS = /* GraphQL */ `
2
+ id
3
+ customerId
4
+ currencyCode
5
+ amount
6
+ applied
7
+ refunded
8
+ remaining
9
+ orderId
10
+ paymentId
11
+ receivedOn
12
+ reference
13
+ notes
14
+ createdAt
15
+ `;
16
+ export const CREDIT_ORDER_OVERPAYMENT_MUTATION = /* GraphQL */ `
17
+ mutation CreditOrderOverpaymentToAccount(
18
+ $input: CreditOrderOverpaymentInput!
19
+ $idempotencyKey: String
20
+ ) {
21
+ creditOrderOverpaymentToAccount(input: $input, idempotencyKey: $idempotencyKey) {
22
+ ${UNAPPLIED_CASH_FIELDS}
23
+ }
24
+ }
25
+ `;
26
+ export const UNAPPLIED_CASH_QUERY = /* GraphQL */ `
27
+ query ArUnappliedCash($customerId: ID!) {
28
+ arUnappliedCash(customerId: $customerId) {
29
+ ${UNAPPLIED_CASH_FIELDS}
30
+ }
31
+ }
32
+ `;
33
+ export const APPLY_UNAPPLIED_CASH_MUTATION = /* GraphQL */ `
34
+ mutation ApplyArUnappliedCash($input: ApplyArUnappliedCashInput!, $idempotencyKey: String) {
35
+ applyArUnappliedCash(input: $input, idempotencyKey: $idempotencyKey) {
36
+ ${UNAPPLIED_CASH_FIELDS}
37
+ }
38
+ }
39
+ `;
40
+ export const REFUND_UNAPPLIED_CASH_MUTATION = /* GraphQL */ `
41
+ mutation RefundArUnappliedCash($input: RefundArUnappliedCashInput!, $idempotencyKey: String) {
42
+ refundArUnappliedCash(input: $input, idempotencyKey: $idempotencyKey) {
43
+ id
44
+ total
45
+ state
46
+ method
47
+ transactionId
48
+ reason
49
+ }
50
+ }
51
+ `;
52
+ /**
53
+ * Its own query, never a field added to `payments.refundPosition`'s: an SDK
54
+ * released ahead of a server without `creditedToAccount` must not break that
55
+ * read.
56
+ */
57
+ export const ORDER_MONEY_ON_ACCOUNT_QUERY = /* GraphQL */ `
58
+ query OrderMoneyOnAccount($orderId: ID!) {
59
+ orderRefundPosition(orderId: $orderId) {
60
+ currencyCode
61
+ creditedToAccount
62
+ perPayment {
63
+ paymentId
64
+ creditedToAccount
65
+ }
66
+ }
67
+ }
68
+ `;
69
+ export function createAccountCreditModule(transport) {
70
+ return {
71
+ async creditOverpayment(input, options) {
72
+ const data = await transport.graphql({
73
+ api: 'admin',
74
+ query: CREDIT_ORDER_OVERPAYMENT_MUTATION,
75
+ // A variable, not a header: the Admin API takes the key as an argument.
76
+ // `undefined`, never an explicit null: `JSON.stringify` drops it, so an
77
+ // omitted key stays off the wire entirely.
78
+ variables: { input, idempotencyKey: options?.idempotencyKey },
79
+ }, options);
80
+ return data.creditOrderOverpaymentToAccount;
81
+ },
82
+ async list(customerId, options) {
83
+ const data = await transport.graphql({ api: 'admin', query: UNAPPLIED_CASH_QUERY, variables: { customerId } }, options);
84
+ return data.arUnappliedCash;
85
+ },
86
+ async apply(input, options) {
87
+ const data = await transport.graphql({
88
+ api: 'admin',
89
+ query: APPLY_UNAPPLIED_CASH_MUTATION,
90
+ variables: { input, idempotencyKey: options?.idempotencyKey },
91
+ }, options);
92
+ return data.applyArUnappliedCash;
93
+ },
94
+ async refund(input, options) {
95
+ const data = await transport.graphql({
96
+ api: 'admin',
97
+ query: REFUND_UNAPPLIED_CASH_MUTATION,
98
+ variables: { input, idempotencyKey: options?.idempotencyKey },
99
+ }, options);
100
+ return data.refundArUnappliedCash;
101
+ },
102
+ async onOrder(orderId, options) {
103
+ const data = await transport.graphql({ api: 'admin', query: ORDER_MONEY_ON_ACCOUNT_QUERY, variables: { orderId } }, options);
104
+ return data.orderRefundPosition;
105
+ },
106
+ };
107
+ }
@@ -1,5 +1,7 @@
1
1
  import type { Transport } from '@sixtyninecommerce/core';
2
2
  import type { Call } from '../types.js';
3
+ import { type AccountCreditModule } from './account-credit.js';
4
+ import { type PaymentMethodsModule } from './methods.js';
3
5
  import { type ProvidersModule } from './providers.js';
4
6
  /**
5
7
  * What an order has actually been paid, in minor units of its own currency.
@@ -16,13 +18,20 @@ export interface OrderPaymentPosition {
16
18
  settled: number;
17
19
  /** Money a payment handler may take and has not. */
18
20
  authorized: number;
21
+ /**
22
+ * Refunds recorded against the order's payments. Money moved to the
23
+ * customer's account (`payments.accountCredit`) is NOT a refund and is not
24
+ * counted here, though it is taken off `settled` like one.
25
+ */
19
26
  refunded: number;
20
27
  /** `total - covered`, floored at zero. */
21
28
  outstanding: number;
22
29
  /**
23
30
  * `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.
31
+ * this is non-zero only for imported history, rows predating the guard, a
32
+ * refund that landed after a second payment, or an edit that lowered the
33
+ * total of a paid order. Money moved to the customer's account
34
+ * (`payments.accountCredit.creditOverpayment`) no longer counts here.
26
35
  */
27
36
  overpaid: number;
28
37
  /** What a further payment may take. */
@@ -62,9 +71,18 @@ export interface RefundablePayment {
62
71
  method: string | null;
63
72
  /** Gross amount taken, minor units. */
64
73
  amount: number;
65
- /** Non-failed refunds already recorded against it. A failed refund never left. */
74
+ /**
75
+ * Refunds already recorded against it that did not fail, plus failed ones
76
+ * whose outcome is unknown — reserved until the provider's answer is recorded
77
+ * (see {@link PaymentsModule.unreconciledRefunds}). A plainly failed refund
78
+ * never left.
79
+ */
66
80
  refunded: number;
67
- /** `amount - refunded` when this payment took money, floored at zero; else zero. */
81
+ /**
82
+ * `amount - refunded`, less what of this payment is on the customer's account
83
+ * (`payments.accountCredit.onOrder`), when this payment took money; floored
84
+ * at zero, else zero.
85
+ */
68
86
  refundable: number;
69
87
  /**
70
88
  * Whether this payment took money at all.
@@ -96,11 +114,49 @@ export interface OrderRefundPosition {
96
114
  * There is deliberately no credit-note deduction. A credit note that moved
97
115
  * money already has its refund on the payment; one that moved none has
98
116
  * nothing to deduct.
117
+ *
118
+ * Money moved to the customer's account as unapplied cash IS deducted: it is
119
+ * paid back from the account (`payments.accountCredit.refund`), never from
120
+ * the order a second time.
99
121
  */
100
122
  refundable: number;
101
123
  /** Every payment on the order, NEWEST FIRST, with its own headroom. */
102
124
  perPayment: RefundablePayment[];
103
125
  }
126
+ /**
127
+ * A refund whose outcome is unknown: it reached its payment provider and was
128
+ * never confirmed (a timeout, a dropped connection, a server error), so the
129
+ * platform cannot say whether the money moved. Its amount is reserved — counted
130
+ * in the refund position's `refunded` — until
131
+ * {@link PaymentsModule.reconcileRefund} records the provider's answer.
132
+ */
133
+ export interface UnreconciledRefund {
134
+ /** The refund to pass to `reconcileRefund`. */
135
+ refundId: string;
136
+ paymentId: string;
137
+ /** Minor units of the order's currency. */
138
+ amount: number;
139
+ /** ISO-8601 with offset. */
140
+ createdAt: string | null;
141
+ }
142
+ /** What the payment provider says happened to a refund whose outcome was unknown. */
143
+ export type RefundProviderOutcome = 'MADE' | 'NOT_MADE';
144
+ /** The provider's answer for a refund whose outcome is unknown. */
145
+ export interface ReconcileRefundInput {
146
+ refundId: string;
147
+ /**
148
+ * `MADE`: the money went back. `NOT_MADE`: nothing moved. Checked with the
149
+ * provider — never guessed.
150
+ */
151
+ outcome: RefundProviderOutcome;
152
+ /**
153
+ * The provider's reference for its answer: its refund id when it made one, or
154
+ * where the answer was checked. Required, at most 200 characters.
155
+ */
156
+ providerReference: string;
157
+ /** Optional context for the order's history, at most 1000 characters. */
158
+ note?: string;
159
+ }
104
160
  /** Money handed back to a customer. */
105
161
  export interface RefundPaymentInput {
106
162
  orderId: string;
@@ -146,6 +202,65 @@ export interface PaidOrder {
146
202
  total: number;
147
203
  totalWithTax: number;
148
204
  }
205
+ /** What a payment app reports happened to a payment it took (`reportAppPayment`). */
206
+ export type AppPaymentReportState = 'Authorized' | 'Settled' | 'Declined' | 'Cancelled';
207
+ /** An app's report on one of its payments. */
208
+ export interface ReportAppPaymentInput {
209
+ /**
210
+ * What the provider did. An authorized payment can be reported `Settled`,
211
+ * `Declined` or `Cancelled`; a payment whose outcome is unknown (see
212
+ * {@link AppPayment}) only `Settled` or `Declined` — the provider knows
213
+ * whether it took the money.
214
+ *
215
+ * `Authorized` is for ONE case: you answered `create` `Authorized` with a
216
+ * `redirect_url`, and the buyer finished your hosted page with the money
217
+ * authorized, to be captured later (pay later, capture at shipment). Until
218
+ * you report, the order stays the buyer's unplaced cart; this report places
219
+ * it (`PaymentAuthorized`) when the payment covers it. A later `Settled`
220
+ * report, or the store capturing it (your `capture` hook), settles it. Any
221
+ * other payment reported `Authorized` is `PAYMENT_STATE_NOT_REPORTABLE`.
222
+ */
223
+ state: AppPaymentReportState;
224
+ /**
225
+ * The provider's reference for the payment, at most 255 characters. When the
226
+ * app answered `create` with one, it must be that one.
227
+ */
228
+ providerReference: string;
229
+ /** Minor units of the order's currency. Must equal the payment's amount. */
230
+ amount: number;
231
+ }
232
+ /** A payment an app took, as the installation that took it reads it. */
233
+ export interface AppPayment {
234
+ id: string;
235
+ orderId: string;
236
+ orderCode: string;
237
+ /** Vendure's payment state: `Authorized`, `Settled`, `Declined`, `Error`, `Cancelled`. */
238
+ state: string;
239
+ /** Minor units. */
240
+ amount: number;
241
+ currencyCode: string;
242
+ /** The provider's reference — the payment's `transactionId` — once the app gave one. */
243
+ providerReference: string | null;
244
+ methodCode: string;
245
+ /**
246
+ * The platform asked the app (create, or capture) and never heard back, so
247
+ * whether the money moved is unknown. The platform does NOT ask again (a
248
+ * second request could be a second charge): report the outcome with
249
+ * {@link PaymentsModule.reportAppPayment}.
250
+ */
251
+ outcomeUnknown: boolean;
252
+ /** ISO-8601 with offset. */
253
+ createdAt: string;
254
+ }
255
+ /** The payment as it stands after an app's report. */
256
+ export interface ReportedAppPayment {
257
+ id: string;
258
+ state: string;
259
+ /** Minor units. */
260
+ amount: number;
261
+ method: string;
262
+ transactionId: string | null;
263
+ }
149
264
  /**
150
265
  * Payments: money against an order (spec §8.2), and the provider accounts
151
266
  * it runs through (spec §8.9).
@@ -165,6 +280,16 @@ export interface PaidOrder {
165
280
  export interface PaymentsModule {
166
281
  /** Provider onboarding, terminals and readiness (spec §8.9). */
167
282
  providers: ProvidersModule;
283
+ /**
284
+ * An order's overpayment on the customer's account: move it there, apply it
285
+ * to an invoice, pay it back.
286
+ */
287
+ accountCredit: AccountCreditModule;
288
+ /**
289
+ * The store's payment methods, as staff choose one: the `method` code
290
+ * {@link PaymentsModule.record} takes, and the codes a deposit policy names.
291
+ */
292
+ methods: PaymentMethodsModule;
168
293
  /**
169
294
  * Record part (or all) of what an order owes, and return the order.
170
295
  *
@@ -196,15 +321,38 @@ export interface PaymentsModule {
196
321
  * argument — so a retry under the same key returns the FIRST call's refund
197
322
  * instead of raising a second one. Use a fresh key per intended refund.
198
323
  *
199
- * **`IDEMPOTENCY_OUTCOME_UNKNOWN` is neither success nor refusal.** The engine
200
- * calls the payment gateway from inside the transaction that writes the refund
324
+ * **`error.outcomeUnknown` has two causes here, and they recover differently.**
325
+ *
326
+ * 1. **No answer came back** (a timeout, your own signal aborting the call
327
+ * after it was sent, a dropped connection, a proxy's 502/504). The first
328
+ * call may still be running on the server and its key is NOT spent, so
329
+ * repeat the call under the SAME key, never a new one. The
330
+ * platform then answers with the first call's refund, with
331
+ * `IDEMPOTENCY_IN_PROGRESS` (wait, then repeat again under that key), or
332
+ * with `IDEMPOTENCY_OUTCOME_UNKNOWN` (case 2). A NEW key here can refund
333
+ * twice: the second request waits on the order lock until the first one
334
+ * commits, and then both fit under the ceiling. A call made without a key
335
+ * has no safe repeat: once the first call can have finished, read
336
+ * `payments.refundPosition(orderId)` and reconcile against the gateway.
337
+ * 2. **`IDEMPOTENCY_OUTCOME_UNKNOWN`** is neither success nor refusal. It
338
+ * arrives as a `ConflictError` (409) because the key is spent, but the class
339
+ * is not the message: branch on the code, or on `error.outcomeUnknown`. The
340
+ * engine calls the payment gateway from inside the transaction that writes the refund
201
341
  * row, so a failure after that call leaves an outcome nobody can read off the
202
342
  * database: the money may be on its way back with no row to show for it. You
203
343
  * get this code on the FIRST call when that happens, and on every repeat under
204
344
  * 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.
345
+ * runs again. Do NOT treat it as `REFUND_REFUSED`: the attempt is recorded as
346
+ * a refund whose outcome is unknown, and its amount stays RESERVED in the
347
+ * position — this call, the till, credit notes, returns and core's own
348
+ * `refundOrder` mutation (the dashboard's Refund button) no longer refund
349
+ * the order or that payment past what they took. The reservation does NOT
350
+ * stop a new request for the same
351
+ * partial amount while headroom remains, so never retry under a new key
352
+ * blindly. Find the attempt with `payments.unreconciledRefunds(orderId)`,
353
+ * check the gateway, and record the answer with `payments.reconcileRefund(...)`.
354
+ * After `MADE` the spent key replays that refund; after `NOT_MADE` it may run
355
+ * again, and the amount is refundable again.
208
356
  *
209
357
  * (The server also attaches the position to that error, but `PlatformError`
210
358
  * carries only `code`, `message`, `details` and `traceId`, so an SDK caller
@@ -235,10 +383,94 @@ export interface PaymentsModule {
235
383
  refund(input: RefundPaymentInput, options?: Call): Promise<IssuedRefund>;
236
384
  /** Read what an order may still hand back. */
237
385
  refundPosition(orderId: string, options?: Call): Promise<OrderRefundPosition>;
386
+ /**
387
+ * The order's refunds whose outcome is unknown, oldest first — the ones
388
+ * {@link reconcileRefund} resolves. Each one's amount is already reserved in
389
+ * {@link refundPosition}.
390
+ *
391
+ * A refund lands here when its payment provider was asked and never
392
+ * confirmed: `refund` answered `IDEMPOTENCY_OUTCOME_UNKNOWN`, or a till card
393
+ * refund, a credit note or a return settlement did. Needs `ReadOrder`.
394
+ */
395
+ unreconciledRefunds(orderId: string, options?: Call): Promise<UnreconciledRefund[]>;
396
+ /**
397
+ * Record the payment provider's answer for a refund whose outcome is unknown.
398
+ * Needs `UpdateOrder` — the permission refunds take.
399
+ *
400
+ * - `MADE`: the money went back. The refund becomes `Settled` as if the
401
+ * provider had confirmed it at the time: it counts as returned, a return
402
+ * parked on it completes its settlement, and `payment.refunded` is
403
+ * announced. The key that spent itself on the attempt now replays it.
404
+ * - `NOT_MADE`: nothing moved. The refund stays `Failed`, its reservation is
405
+ * released and a retry is allowed — the spent key, a till refund, the credit
406
+ * note, or settling the parked return again.
407
+ *
408
+ * The outcome is kept on the refund's metadata, which the Shop API serves, so
409
+ * nothing else goes there: `providerReference`, `note` and who recorded it go
410
+ * to a private order note and the audit trail.
411
+ *
412
+ * Refusals: `REFUND_NOT_FOUND`, `REFUND_OUTCOME_NOT_UNKNOWN` (the outcome is
413
+ * already known — never unknown, or reconciled already),
414
+ * `REFUND_RECONCILIATION_INVALID` (a blank or oversized `providerReference`,
415
+ * an oversized `note`), and `REFUND_EXCEEDS_PAYMENT` when `MADE` would have
416
+ * the payment return more than it took (another refund on record against it
417
+ * cannot be right).
418
+ *
419
+ * `options.idempotencyKey` is honoured: a repeat under the same key returns
420
+ * the first call's refund.
421
+ */
422
+ reconcileRefund(input: ReconcileRefundInput, options?: Call): Promise<IssuedRefund>;
423
+ /**
424
+ * **For a payment app, with its installation token.** Report what happened to
425
+ * a payment your app took (spec §8.14 `payment.provider`): the asynchronous
426
+ * pattern — you answered `create` `Authorized`, and the money lands later —
427
+ * and the reconciliation of a payment whose outcome is unknown (you were
428
+ * asked and the platform never received your answer; it will not ask again).
429
+ *
430
+ * The platform moves the payment through its own payment processes, exactly
431
+ * as for any provider callback: a covered order is settled and placed, money
432
+ * for a held (parked) order lands where the order stands, and
433
+ * `payment.settled` is published with your installation as its actor. A
434
+ * hosted page that only authorized is reported `Authorized` (see
435
+ * {@link ReportAppPaymentInput.state}): the order is placed on it.
436
+ *
437
+ * `options.idempotencyKey` is REQUIRED: a repeat of the same report under it
438
+ * answers the payment as it now is, for as long as the payment exists; a
439
+ * DIFFERENT report under it is refused `IDEMPOTENCY_CONFLICT` (409). Use one
440
+ * key per event you received from your provider.
441
+ *
442
+ * Refusals: `PAYMENT_NOT_OWNED_BY_INSTALLATION` (a `PermissionDeniedError`,
443
+ * 403: not a payment this installation took on this store — one answer
444
+ * whatever the reason),
445
+ * `PAYMENT_AMOUNT_MISMATCH`, `PAYMENT_STATE_NOT_REPORTABLE` (the payment
446
+ * cannot move to that state from where it is, `extensions.details.state`),
447
+ * `APP_PAYMENT_REPORT_INVALID` (a malformed report, or a reference other than
448
+ * the one `create` answered), `APP_PAYMENT_METHOD_DISABLED` (the store took
449
+ * your app off as its payment provider; a decline is still recorded),
450
+ * `IDEMPOTENCY_KEY_INVALID`.
451
+ */
452
+ reportAppPayment(paymentId: string, input: ReportAppPaymentInput, options: Call & {
453
+ idempotencyKey: string;
454
+ }): Promise<ReportedAppPayment>;
455
+ /**
456
+ * **For a payment app, with its installation token.** Your installation's
457
+ * payments on one order of this store, oldest first: how you find a
458
+ * payment's id, which the `create` call cannot carry because the payment
459
+ * does not exist until you answer. Match on `providerReference`. An order the
460
+ * store does not have answers `[]`; any caller but an installation is refused
461
+ * `PAYMENT_NOT_OWNED_BY_INSTALLATION`.
462
+ */
463
+ appPayments(orderId: string, options?: Call): Promise<AppPayment[]>;
238
464
  }
239
465
  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
466
  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
467
  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
468
  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";
469
+ 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";
470
+ 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";
471
+ 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";
472
+ 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";
243
473
  export declare function createPaymentsModule(transport: Transport): PaymentsModule;
474
+ export type { AccountCreditModule, ApplyUnappliedCashInput, CreditOverpaymentInput, OrderMoneyOnAccount, RefundUnappliedCashInput, UnappliedCash, UnappliedCashRefund, } from './account-credit.js';
475
+ export type { PaymentMethod, PaymentMethodsModule } from './methods.js';
244
476
  export type { ProviderConnection, ProviderCredentialPath, ProviderOnboardingStart, ProviderReadiness, ProvidersModule, ProviderTerminal, ProviderTerminalsModule, ProvisionTerminalInput, ReadinessOptions, } from './providers.js';