@fantastic.dev/better-stripe 0.20.1 → 0.21.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 (60) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +11 -1
  3. package/dist/client/connect/payoutReceipt.d.ts +53 -0
  4. package/dist/client/connect/payoutReceipt.d.ts.map +1 -0
  5. package/dist/client/connect/payoutReceipt.js +185 -0
  6. package/dist/client/connect/payoutReceipt.js.map +1 -0
  7. package/dist/client/connect/payoutReconciliation.d.ts +38 -0
  8. package/dist/client/connect/payoutReconciliation.d.ts.map +1 -0
  9. package/dist/client/connect/payoutReconciliation.js +110 -0
  10. package/dist/client/connect/payoutReconciliation.js.map +1 -0
  11. package/dist/client/payoutPolicy.d.ts +6 -0
  12. package/dist/client/payoutPolicy.d.ts.map +1 -1
  13. package/dist/client/payoutPolicy.js +8 -0
  14. package/dist/client/payoutPolicy.js.map +1 -1
  15. package/dist/component/_generated/component.d.ts +39 -0
  16. package/dist/component/_generated/component.d.ts.map +1 -1
  17. package/dist/component/earnings/triggers.d.ts +50 -2
  18. package/dist/component/earnings/triggers.d.ts.map +1 -1
  19. package/dist/component/payoutRelease/allocation.d.ts +1 -0
  20. package/dist/component/payoutRelease/allocation.d.ts.map +1 -1
  21. package/dist/component/payoutRelease/allocation.js +3 -0
  22. package/dist/component/payoutRelease/allocation.js.map +1 -1
  23. package/dist/component/payoutRelease/fees.d.ts +22 -0
  24. package/dist/component/payoutRelease/fees.d.ts.map +1 -0
  25. package/dist/component/payoutRelease/fees.js +73 -0
  26. package/dist/component/payoutRelease/fees.js.map +1 -0
  27. package/dist/component/payoutRelease/helpers.d.ts +4 -0
  28. package/dist/component/payoutRelease/helpers.d.ts.map +1 -1
  29. package/dist/component/payoutRelease/mutations.d.ts +23 -0
  30. package/dist/component/payoutRelease/mutations.d.ts.map +1 -1
  31. package/dist/component/payoutRelease/mutations.js +17 -0
  32. package/dist/component/payoutRelease/mutations.js.map +1 -1
  33. package/dist/component/payoutRelease/queries.d.ts +16 -0
  34. package/dist/component/payoutRelease/queries.d.ts.map +1 -1
  35. package/dist/component/payoutRelease/queries.js +10 -0
  36. package/dist/component/payoutRelease/queries.js.map +1 -1
  37. package/dist/component/payoutRelease/schema.d.ts +38 -2
  38. package/dist/component/payoutRelease/schema.d.ts.map +1 -1
  39. package/dist/component/payoutRelease/schema.js +11 -0
  40. package/dist/component/payoutRelease/schema.js.map +1 -1
  41. package/dist/component/schema.d.ts +25 -1
  42. package/dist/component/schema.js +2 -1
  43. package/dist/component/schema.js.map +1 -1
  44. package/docs/settlement.md +74 -3
  45. package/package.json +1 -1
  46. package/src/client/connect/payoutAllocation.test.ts +36 -3
  47. package/src/client/connect/payoutReceipt.test.ts +312 -0
  48. package/src/client/connect/payoutReceipt.ts +287 -0
  49. package/src/client/connect/payoutReconciliation.test.ts +385 -0
  50. package/src/client/connect/payoutReconciliation.ts +174 -0
  51. package/src/client/payoutPolicy.ts +16 -0
  52. package/src/component/_generated/api.ts +2 -0
  53. package/src/component/_generated/component.ts +38 -0
  54. package/src/component/payout-fees.test.ts +224 -0
  55. package/src/component/payoutRelease/allocation.ts +6 -0
  56. package/src/component/payoutRelease/fees.ts +93 -0
  57. package/src/component/payoutRelease/mutations.ts +17 -0
  58. package/src/component/payoutRelease/queries.ts +11 -0
  59. package/src/component/payoutRelease/schema.ts +12 -0
  60. package/src/component/schema.ts +2 -0
@@ -73,6 +73,10 @@ export declare const claimFields: {
73
73
  attemptedAt: import("convex/values").VFloat64<number | undefined, "optional">;
74
74
  stripePayoutId: import("convex/values").VString<string | undefined, "optional">;
75
75
  returnTransactionId: import("convex/values").VString<string | undefined, "optional">;
76
+ feeRevision: import("convex/values").VFloat64<number | undefined, "optional">;
77
+ debitTransactionId: import("convex/values").VString<string | undefined, "optional">;
78
+ debitFee: import("convex/values").VFloat64<number | undefined, "optional">;
79
+ providerFee: import("convex/values").VFloat64<number | undefined, "optional">;
76
80
  rejection: import("convex/values").VObject<{
77
81
  code: "amount_too_small" | "balance_insufficient";
78
82
  requestId: string;
@@ -93,7 +97,10 @@ export declare const claimDoc: import("convex/values").VObject<{
93
97
  amount: number;
94
98
  attemptedAt?: number | undefined;
95
99
  currency: string;
100
+ debitFee?: number | undefined;
101
+ debitTransactionId?: string | undefined;
96
102
  expectedRevision: number;
103
+ feeRevision?: number | undefined;
97
104
  observations: {
98
105
  currency: string;
99
106
  ledgerFingerprint: string;
@@ -105,6 +112,7 @@ export declare const claimDoc: import("convex/values").VObject<{
105
112
  }[];
106
113
  operationKey: string;
107
114
  ownerKey: string;
115
+ providerFee?: number | undefined;
108
116
  rejection?: {
109
117
  code: "amount_too_small" | "balance_insufficient";
110
118
  requestId: string;
@@ -161,6 +169,10 @@ export declare const claimDoc: import("convex/values").VObject<{
161
169
  attemptedAt: import("convex/values").VFloat64<number | undefined, "optional">;
162
170
  stripePayoutId: import("convex/values").VString<string | undefined, "optional">;
163
171
  returnTransactionId: import("convex/values").VString<string | undefined, "optional">;
172
+ feeRevision: import("convex/values").VFloat64<number | undefined, "optional">;
173
+ debitTransactionId: import("convex/values").VString<string | undefined, "optional">;
174
+ debitFee: import("convex/values").VFloat64<number | undefined, "optional">;
175
+ providerFee: import("convex/values").VFloat64<number | undefined, "optional">;
164
176
  rejection: import("convex/values").VObject<{
165
177
  code: "amount_too_small" | "balance_insufficient";
166
178
  requestId: string;
@@ -170,7 +182,7 @@ export declare const claimDoc: import("convex/values").VObject<{
170
182
  }, "optional", "code" | "requestId">;
171
183
  _id: import("convex/values").VId<import("convex/values").GenericId<"payoutReleaseClaims">, "required">;
172
184
  _creationTime: import("convex/values").VFloat64<number, "required">;
173
- }, "required", "_creationTime" | "_id" | "accountId" | "allocations" | "amount" | "attemptedAt" | "currency" | "expectedRevision" | "observations" | "operationKey" | "ownerKey" | "rejection" | "rejection.code" | "rejection.requestId" | "returnTransactionId" | "status" | "stripePayoutId">;
185
+ }, "required", "_creationTime" | "_id" | "accountId" | "allocations" | "amount" | "attemptedAt" | "currency" | "debitFee" | "debitTransactionId" | "expectedRevision" | "feeRevision" | "observations" | "operationKey" | "ownerKey" | "providerFee" | "rejection" | "rejection.code" | "rejection.requestId" | "returnTransactionId" | "status" | "stripePayoutId">;
174
186
  export declare const claimsTable: import("convex/server").TableDefinition<import("convex/values").VObject<{
175
187
  accountId: string;
176
188
  allocations: {
@@ -181,7 +193,10 @@ export declare const claimsTable: import("convex/server").TableDefinition<import
181
193
  amount: number;
182
194
  attemptedAt?: number | undefined;
183
195
  currency: string;
196
+ debitFee?: number | undefined;
197
+ debitTransactionId?: string | undefined;
184
198
  expectedRevision: number;
199
+ feeRevision?: number | undefined;
185
200
  observations: {
186
201
  currency: string;
187
202
  ledgerFingerprint: string;
@@ -193,6 +208,7 @@ export declare const claimsTable: import("convex/server").TableDefinition<import
193
208
  }[];
194
209
  operationKey: string;
195
210
  ownerKey: string;
211
+ providerFee?: number | undefined;
196
212
  rejection?: {
197
213
  code: "amount_too_small" | "balance_insufficient";
198
214
  requestId: string;
@@ -249,6 +265,10 @@ export declare const claimsTable: import("convex/server").TableDefinition<import
249
265
  attemptedAt: import("convex/values").VFloat64<number | undefined, "optional">;
250
266
  stripePayoutId: import("convex/values").VString<string | undefined, "optional">;
251
267
  returnTransactionId: import("convex/values").VString<string | undefined, "optional">;
268
+ feeRevision: import("convex/values").VFloat64<number | undefined, "optional">;
269
+ debitTransactionId: import("convex/values").VString<string | undefined, "optional">;
270
+ debitFee: import("convex/values").VFloat64<number | undefined, "optional">;
271
+ providerFee: import("convex/values").VFloat64<number | undefined, "optional">;
252
272
  rejection: import("convex/values").VObject<{
253
273
  code: "amount_too_small" | "balance_insufficient";
254
274
  requestId: string;
@@ -256,8 +276,9 @@ export declare const claimsTable: import("convex/server").TableDefinition<import
256
276
  requestId: import("convex/values").VString<string, "required">;
257
277
  code: import("convex/values").VUnion<"amount_too_small" | "balance_insufficient", [import("convex/values").VLiteral<"balance_insufficient", "required">, import("convex/values").VLiteral<"amount_too_small", "required">], "required", never>;
258
278
  }, "optional", "code" | "requestId">;
259
- }, "required", "accountId" | "allocations" | "amount" | "attemptedAt" | "currency" | "expectedRevision" | "observations" | "operationKey" | "ownerKey" | "rejection" | "rejection.code" | "rejection.requestId" | "returnTransactionId" | "status" | "stripePayoutId">, {
279
+ }, "required", "accountId" | "allocations" | "amount" | "attemptedAt" | "currency" | "debitFee" | "debitTransactionId" | "expectedRevision" | "feeRevision" | "observations" | "operationKey" | "ownerKey" | "providerFee" | "rejection" | "rejection.code" | "rejection.requestId" | "returnTransactionId" | "status" | "stripePayoutId">, {
260
280
  by_account_status: ["accountId", "status", "_creationTime"];
281
+ by_debit_receipt: ["debitTransactionId", "_creationTime"];
261
282
  by_operation: ["operationKey", "_creationTime"];
262
283
  by_provider_payout: ["stripePayoutId", "_creationTime"];
263
284
  by_rejection_request: ["rejection.requestId", "_creationTime"];
@@ -286,4 +307,19 @@ export declare const identity: {
286
307
  ownerKey: import("convex/values").VString<string, "required">;
287
308
  operationKey: import("convex/values").VString<string, "required">;
288
309
  };
310
+ export declare const feeBalancesTable: import("convex/server").TableDefinition<import("convex/values").VObject<{
311
+ accountId: string;
312
+ amount: number;
313
+ currency: string;
314
+ ownerKey: string;
315
+ revision: number;
316
+ }, {
317
+ accountId: import("convex/values").VString<string, "required">;
318
+ ownerKey: import("convex/values").VString<string, "required">;
319
+ currency: import("convex/values").VString<string, "required">;
320
+ amount: import("convex/values").VFloat64<number, "required">;
321
+ revision: import("convex/values").VFloat64<number, "required">;
322
+ }, "required", "accountId" | "amount" | "currency" | "ownerKey" | "revision">, {
323
+ by_account_currency: ["accountId", "currency", "_creationTime"];
324
+ }, {}, {}>;
289
325
  //# sourceMappingURL=schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/component/payoutRelease/schema.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;wIAQtB,CAAC;AACH,eAAO,MAAM,UAAU;;;;;;;;sDAMrB,CAAC;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BvB,CAAC;AACF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gSAInB,CAAC;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAKiC,CAAC;AAC1D,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;UAQY,CAAC;AACtC,eAAO,MAAM,QAAQ;;;;CAA+C,CAAC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/component/payoutRelease/schema.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;wIAQtB,CAAC;AACH,eAAO,MAAM,UAAU;;;;;;;;sDAMrB,CAAC;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCvB,CAAC;AACF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oWAInB,CAAC;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAMiC,CAAC;AAC1D,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;UAQY,CAAC;AACtC,eAAO,MAAM,QAAQ;;;;CAA+C,CAAC;AAErE,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;UAK6B,CAAC"}
@@ -27,6 +27,10 @@ export const claimFields = {
27
27
  attemptedAt: v.optional(v.number()),
28
28
  stripePayoutId: v.optional(v.string()),
29
29
  returnTransactionId: v.optional(v.string()),
30
+ feeRevision: v.optional(v.number()),
31
+ debitTransactionId: v.optional(v.string()),
32
+ debitFee: v.optional(v.number()),
33
+ providerFee: v.optional(v.number()),
30
34
  rejection: v.optional(v.object({
31
35
  requestId: v.string(),
32
36
  code: v.union(v.literal("balance_insufficient"), v.literal("amount_too_small")),
@@ -41,6 +45,7 @@ export const claimsTable = defineTable(claimFields)
41
45
  .index("by_operation", ["operationKey"])
42
46
  .index("by_account_status", ["accountId", "status"])
43
47
  .index("by_provider_payout", ["stripePayoutId"])
48
+ .index("by_debit_receipt", ["debitTransactionId"])
44
49
  .index("by_return_receipt", ["returnTransactionId"])
45
50
  .index("by_rejection_request", ["rejection.requestId"]);
46
51
  export const sourcesTable = defineTable({
@@ -53,4 +58,10 @@ export const sourcesTable = defineTable({
53
58
  .index("by_transfer", ["stripeTransferId"])
54
59
  .index("by_account", ["accountId"]);
55
60
  export const identity = { ...scopeFields, operationKey: v.string() };
61
+ export const feeBalancesTable = defineTable({
62
+ ...scopeFields,
63
+ currency: v.string(),
64
+ amount: v.number(),
65
+ revision: v.number(),
66
+ }).index("by_account_currency", ["accountId", "currency"]);
56
67
  //# sourceMappingURL=schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/component/payoutRelease/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/component/payoutRelease/schema.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,19 @@
1
1
  declare const _default: import("convex/server").SchemaDefinition<{
2
+ payoutFeeBalances: import("convex/server").TableDefinition<import("convex/values").VObject<{
3
+ accountId: string;
4
+ amount: number;
5
+ currency: string;
6
+ ownerKey: string;
7
+ revision: number;
8
+ }, {
9
+ accountId: import("convex/values").VString<string, "required">;
10
+ ownerKey: import("convex/values").VString<string, "required">;
11
+ currency: import("convex/values").VString<string, "required">;
12
+ amount: import("convex/values").VFloat64<number, "required">;
13
+ revision: import("convex/values").VFloat64<number, "required">;
14
+ }, "required", "accountId" | "amount" | "currency" | "ownerKey" | "revision">, {
15
+ by_account_currency: ["accountId", "currency", "_creationTime"];
16
+ }, {}, {}>;
2
17
  payoutReleaseClaims: import("convex/server").TableDefinition<import("convex/values").VObject<{
3
18
  accountId: string;
4
19
  allocations: {
@@ -9,7 +24,10 @@ declare const _default: import("convex/server").SchemaDefinition<{
9
24
  amount: number;
10
25
  attemptedAt?: number | undefined;
11
26
  currency: string;
27
+ debitFee?: number | undefined;
28
+ debitTransactionId?: string | undefined;
12
29
  expectedRevision: number;
30
+ feeRevision?: number | undefined;
13
31
  observations: {
14
32
  currency: string;
15
33
  ledgerFingerprint: string;
@@ -21,6 +39,7 @@ declare const _default: import("convex/server").SchemaDefinition<{
21
39
  }[];
22
40
  operationKey: string;
23
41
  ownerKey: string;
42
+ providerFee?: number | undefined;
24
43
  rejection?: {
25
44
  code: "amount_too_small" | "balance_insufficient";
26
45
  requestId: string;
@@ -77,6 +96,10 @@ declare const _default: import("convex/server").SchemaDefinition<{
77
96
  attemptedAt: import("convex/values").VFloat64<number | undefined, "optional">;
78
97
  stripePayoutId: import("convex/values").VString<string | undefined, "optional">;
79
98
  returnTransactionId: import("convex/values").VString<string | undefined, "optional">;
99
+ feeRevision: import("convex/values").VFloat64<number | undefined, "optional">;
100
+ debitTransactionId: import("convex/values").VString<string | undefined, "optional">;
101
+ debitFee: import("convex/values").VFloat64<number | undefined, "optional">;
102
+ providerFee: import("convex/values").VFloat64<number | undefined, "optional">;
80
103
  rejection: import("convex/values").VObject<{
81
104
  code: "amount_too_small" | "balance_insufficient";
82
105
  requestId: string;
@@ -84,8 +107,9 @@ declare const _default: import("convex/server").SchemaDefinition<{
84
107
  requestId: import("convex/values").VString<string, "required">;
85
108
  code: import("convex/values").VUnion<"amount_too_small" | "balance_insufficient", [import("convex/values").VLiteral<"balance_insufficient", "required">, import("convex/values").VLiteral<"amount_too_small", "required">], "required", never>;
86
109
  }, "optional", "code" | "requestId">;
87
- }, "required", "accountId" | "allocations" | "amount" | "attemptedAt" | "currency" | "expectedRevision" | "observations" | "operationKey" | "ownerKey" | "rejection" | "rejection.code" | "rejection.requestId" | "returnTransactionId" | "status" | "stripePayoutId">, {
110
+ }, "required", "accountId" | "allocations" | "amount" | "attemptedAt" | "currency" | "debitFee" | "debitTransactionId" | "expectedRevision" | "feeRevision" | "observations" | "operationKey" | "ownerKey" | "providerFee" | "rejection" | "rejection.code" | "rejection.requestId" | "returnTransactionId" | "status" | "stripePayoutId">, {
88
111
  by_account_status: ["accountId", "status", "_creationTime"];
112
+ by_debit_receipt: ["debitTransactionId", "_creationTime"];
89
113
  by_operation: ["operationKey", "_creationTime"];
90
114
  by_provider_payout: ["stripePayoutId", "_creationTime"];
91
115
  by_rejection_request: ["rejection.requestId", "_creationTime"];
@@ -1,4 +1,4 @@
1
- import { claimsTable as payoutReleaseClaimsTable, sourcesTable as payoutSourceAllocationsTable, } from "./payoutRelease/schema.js";
1
+ import { feeBalancesTable as payoutFeeBalancesTable, claimsTable as payoutReleaseClaimsTable, sourcesTable as payoutSourceAllocationsTable, } from "./payoutRelease/schema.js";
2
2
  import { policiesTable, operationsTable } from "./payoutPolicy/schema.js";
3
3
  import { currencyTotalsTable } from "./earnings/schema.js";
4
4
  import { claimsTable, balancesTable, groupsTable, reservationsTable, } from "./costRecovery/schema";
@@ -10,6 +10,7 @@ import { accountsTable } from "./core/schema";
10
10
  import { pricesTable, productsTable } from "./products/schema";
11
11
  import { webhookEventsTable } from "./webhooks/schema";
12
12
  export default defineSchema({
13
+ payoutFeeBalances: payoutFeeBalancesTable,
13
14
  payoutReleaseClaims: payoutReleaseClaimsTable,
14
15
  payoutSourceAllocations: payoutSourceAllocationsTable,
15
16
  payoutPolicies: policiesTable,
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/component/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,IAAI,wBAAwB,EACvC,YAAY,IAAI,4BAA4B,GAC7C,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EACL,WAAW,EACX,aAAa,EACb,WAAW,EACX,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,aAAa,EACb,aAAa,EACb,YAAY,EACZ,sBAAsB,EACtB,YAAY,EACZ,wBAAwB,EACxB,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,eAAe,YAAY,CAAC;IAC1B,mBAAmB,EAAE,wBAAwB;IAC7C,uBAAuB,EAAE,4BAA4B;IACrD,cAAc,EAAE,aAAa;IAC7B,sBAAsB,EAAE,eAAe;IACvC,cAAc,EAAE,mBAAmB;IACnC,cAAc,EAAE,WAAW;IAC3B,gBAAgB,EAAE,aAAa;IAC/B,cAAc,EAAE,WAAW;IAC3B,oBAAoB,EAAE,iBAAiB;IACvC,qBAAqB,EAAE,gBAAgB;IACvC,eAAe,EAAE,oBAAoB;IACrC,mBAAmB,EAAE,wBAAwB;IAC7C,OAAO;IACP,QAAQ,EAAE,aAAa;IAEvB,WAAW;IACX,QAAQ,EAAE,aAAa;IACvB,MAAM,EAAE,WAAW;IAEnB,UAAU;IACV,aAAa,EAAE,kBAAkB;IACjC,gBAAgB,EAAE,qBAAqB;IACvC,QAAQ,EAAE,aAAa;IAEvB,UAAU;IACV,QAAQ,EAAE,aAAa;IACvB,OAAO,EAAE,YAAY;IACrB,iBAAiB,EAAE,sBAAsB;IACzC,OAAO,EAAE,YAAY;IACrB,QAAQ,EAAE,aAAa;IACvB,SAAS,EAAE,cAAc;IACzB,mBAAmB,EAAE,wBAAwB;IAE7C,WAAW;IACX,aAAa,EAAE,kBAAkB;CAClC,CAAC,CAAC"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/component/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,IAAI,sBAAsB,EAC1C,WAAW,IAAI,wBAAwB,EACvC,YAAY,IAAI,4BAA4B,GAC7C,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EACL,WAAW,EACX,aAAa,EACb,WAAW,EACX,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,aAAa,EACb,aAAa,EACb,YAAY,EACZ,sBAAsB,EACtB,YAAY,EACZ,wBAAwB,EACxB,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,eAAe,YAAY,CAAC;IAC1B,iBAAiB,EAAE,sBAAsB;IACzC,mBAAmB,EAAE,wBAAwB;IAC7C,uBAAuB,EAAE,4BAA4B;IACrD,cAAc,EAAE,aAAa;IAC7B,sBAAsB,EAAE,eAAe;IACvC,cAAc,EAAE,mBAAmB;IACnC,cAAc,EAAE,WAAW;IAC3B,gBAAgB,EAAE,aAAa;IAC/B,cAAc,EAAE,WAAW;IAC3B,oBAAoB,EAAE,iBAAiB;IACvC,qBAAqB,EAAE,gBAAgB;IACvC,eAAe,EAAE,oBAAoB;IACrC,mBAAmB,EAAE,wBAAwB;IAC7C,OAAO;IACP,QAAQ,EAAE,aAAa;IAEvB,WAAW;IACX,QAAQ,EAAE,aAAa;IACvB,MAAM,EAAE,WAAW;IAEnB,UAAU;IACV,aAAa,EAAE,kBAAkB;IACjC,gBAAgB,EAAE,qBAAqB;IACvC,QAAQ,EAAE,aAAa;IAEvB,UAAU;IACV,QAAQ,EAAE,aAAa;IACvB,OAAO,EAAE,YAAY;IACrB,iBAAiB,EAAE,sBAAsB;IACzC,OAAO,EAAE,YAAY;IACrB,QAAQ,EAAE,aAAa;IACvB,SAAS,EAAE,cAAc;IACzB,mBAAmB,EAAE,wBAAwB;IAE7C,WAAW;IACX,aAAa,EAAE,kBAAkB;CAClC,CAAC,CAAC"}
@@ -222,8 +222,8 @@ Sources: [payout schedules](https://docs.stripe.com/connect/manage-payout-schedu
222
222
  ### Transactional claim ledger implementation status
223
223
 
224
224
  The component contains `payoutRelease` claim and source-allocation tables. These
225
- are server-side building blocks for the release boundary, with no public client
226
- executor or scheduled bank-payout integration yet. Do not call the claim
225
+ are server-side building blocks for the release boundary, with no automatic
226
+ payout-creation or scheduled bank-payout integration yet. Do not call the claim
227
227
  mutation with UI totals or a transfer receipt alone. Its trusted upstream caller
228
228
  must establish complete provider history, still-unpaid ownership, adoption of
229
229
  prior payouts, independent liabilities, and live payout controls first.
@@ -245,7 +245,7 @@ held. This window stays below Stripe's [24-hour v1 idempotency retention minimum
245
245
  The current claim snapshot is deliberately bounded to 100 account transfer rows
246
246
  and 1,000 receipt IDs per source. Larger or incomplete histories reject the whole
247
247
  claim, without using partial totals. A resumable reconciliation/adoption process,
248
- provider payout creation and receipt verification, payout-fee accounting, and
248
+ provider payout creation and receipt verification, historical fee adoption, other account debit allocation, and
249
249
  recurring release/expiry integration remain required before custom payout
250
250
  minimums can be presented as an operational feature. In-memory claim tests are
251
251
  not evidence of a completed Stripe bank payout.
@@ -299,3 +299,74 @@ remains intact for retries.
299
299
  Sources: [transfer provenance](https://docs.stripe.com/api/transfers/object),
300
300
  [receipt maturity](https://docs.stripe.com/api/balance_transactions/object), and
301
301
  [history pagination and payout-filter limits](https://docs.stripe.com/api/balance_transactions/list).
302
+
303
+ ## Verified payout receipts and reconciliation
304
+
305
+ In an authorized server action, read a Connect Stripe-balance payout with:
306
+
307
+ ```ts
308
+ const receipt = await stripe.payoutPolicy.payoutReceipt({
309
+ accountId,
310
+ stripePayoutId,
311
+ });
312
+ ```
313
+
314
+ The reader retrieves the payout and its actual account-scoped balance
315
+ transactions, including a failed/canceled payout's return transaction. It checks
316
+ transaction identity, currency, exact principal, signed fees, net amounts and
317
+ maturity, then re-reads the payout to detect changes. Expanded transaction
318
+ objects are not trusted in place of scoped retrieval. Automatic and manual
319
+ history can both be inspected; a manual payout receipt does not identify the
320
+ transfers that funded it. Changed snapshots, missing debit/return receipts,
321
+ pending debits or returns, unsupported currency allocation and bank-payout reversals return
322
+ `not_ready` without partial financial totals.
323
+
324
+ A ready receipt preserves `providerStatus`, original `debit`, optional returned
325
+ `credit`, `returnedPrincipal` and `returnedNet`. A returned principal can differ
326
+ from net cash because payout fees are retained or credited separately. This data
327
+ alone does not authorize releasing a reservation, identify still-unpaid earnings,
328
+ or prove that a pending payout reached the bank. Global Payouts requires a
329
+ separate receipt and capability implementation.
330
+
331
+ To reconcile an already attempted durable claim:
332
+
333
+ ```ts
334
+ const outcome = await stripe.payoutPolicy.reconcilePayout(ctx, {
335
+ accountId,
336
+ ownerKey,
337
+ operationKey,
338
+ // stripePayoutId, // optional when the provider ID is already known
339
+ maxPages: 10,
340
+ });
341
+ ```
342
+
343
+ The host authenticates the account/owner/operation before this call. Reconciliation
344
+ requires `ctx.runMutation`. It never creates or retries a bank payout. A stored
345
+ provider ID must agree with any supplied ID. Otherwise, bounded provider history
346
+ is scanned for the exact reserved `bsPayoutClaim` marker. Discovery must finish;
347
+ partial history, duplicate matches and a changed history head stay held. The
348
+ page budget is 1 to 100, default 10. No match, including after idempotency expiry,
349
+ never proves that money did not move.
350
+
351
+ Adoption verifies the claim marker, amount, currency, creation window and
352
+ standard manual bank-payout type. Current claims use the card source balance;
353
+ other source rails return an explicit allocation limitation. A missing or
354
+ immature return keeps allocations reserved. Verified paid and returned outcomes
355
+ update source allocations and payout fees in one component transaction. Unknown
356
+ provider and persistence errors propagate so the host can retry reconciliation.
357
+ Canceled/rejected claim states are returned as terminal states, not as bank
358
+ payment confirmation.
359
+
360
+ Net non-refundable payout fees are retained per recipient/currency and deducted
361
+ from later mature unpaid entitlement. They are not deducted again from fresh
362
+ provider availability, which already reflects the debit. A newly observed fee
363
+ invalidates an unattempted claim prepared against an older fee revision. Fee
364
+ credits after a return reduce only the verified original fee; excess credits
365
+ require explicit allocation. Original debit receipts and their fees remain
366
+ immutable. Older returned claims can receive verified fee evidence without
367
+ releasing their principal again.
368
+
369
+ These APIs reconcile existing claims; full automatic qualification/creation,
370
+ historical source adoption, large-history collection, other account debit
371
+ allocation and recurring/UI integration remain separate work. Do not expose a
372
+ custom minimum as fully enforced solely because reconciliation is available.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fantastic.dev/better-stripe",
3
- "version": "0.20.1",
3
+ "version": "0.21.0",
4
4
  "description": "A Convex component for Stripe V2 Accounts API integration.",
5
5
  "keywords": [
6
6
  "stripe",
@@ -139,7 +139,7 @@ describe("combined recipient payout allocation", () => {
139
139
  expect(result).toMatchObject({
140
140
  status: "qualified",
141
141
  amount: 1300,
142
- matureUnpaid: 2000,
142
+ matureUnpaid: 1800,
143
143
  });
144
144
  expect(
145
145
  planRecipientPayout({
@@ -149,8 +149,8 @@ describe("combined recipient payout allocation", () => {
149
149
  }),
150
150
  ).toMatchObject({
151
151
  status: "held",
152
- reason: "insufficient_available",
153
- matureUnpaid: 1000,
152
+ reason: "below_threshold",
153
+ matureUnpaid: 999,
154
154
  });
155
155
  });
156
156
  it("does not subtract reservations again from an already debited provider balance", () => {
@@ -290,3 +290,36 @@ describe("combined recipient payout allocation", () => {
290
290
  function awaitInvalid(action: () => unknown) {
291
291
  expect(action).toThrow(/Invalid|Unsafe|Duplicate/);
292
292
  }
293
+ it("deducts confirmed payout fees from entitlement without deducting them twice from provider availability", () => {
294
+ expect(
295
+ planRecipientPayout({
296
+ ...options([source("tr_one", 1500)]),
297
+ providerAvailable: 1470,
298
+ confirmedFees: 30,
299
+ }),
300
+ ).toMatchObject({ status: "qualified", amount: 1470, matureUnpaid: 1470 });
301
+ expect(
302
+ planRecipientPayout({
303
+ ...options([source("tr_one", 1000)]),
304
+ providerAvailable: 5000,
305
+ confirmedFees: 30,
306
+ }),
307
+ ).toMatchObject({
308
+ status: "held",
309
+ reason: "below_threshold",
310
+ matureUnpaid: 970,
311
+ });
312
+ });
313
+ it("does not qualify the gross threshold while known independent liabilities remain", () => {
314
+ expect(
315
+ planRecipientPayout({
316
+ ...options(),
317
+ providerAvailable: 5000,
318
+ independentLiabilities: 1,
319
+ }),
320
+ ).toMatchObject({
321
+ status: "held",
322
+ reason: "below_threshold",
323
+ matureUnpaid: 999,
324
+ });
325
+ });