@fantastic.dev/better-stripe 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/README.md +267 -2
- package/dist/client/billing/balanceFunding.d.ts +36 -0
- package/dist/client/billing/balanceFunding.d.ts.map +1 -0
- package/dist/client/billing/balanceFunding.js +107 -0
- package/dist/client/billing/balanceFunding.js.map +1 -0
- package/dist/client/billing/invoicePreview.d.ts +28 -0
- package/dist/client/billing/invoicePreview.d.ts.map +1 -0
- package/dist/client/billing/invoicePreview.js +56 -0
- package/dist/client/billing/invoicePreview.js.map +1 -0
- package/dist/client/charge-currency-format.d.ts +3 -0
- package/dist/client/charge-currency-format.d.ts.map +1 -0
- package/dist/client/charge-currency-format.js +22 -0
- package/dist/client/charge-currency-format.js.map +1 -0
- package/dist/client/charge-currency.d.ts +14 -0
- package/dist/client/charge-currency.d.ts.map +1 -0
- package/dist/client/charge-currency.js +85 -0
- package/dist/client/charge-currency.js.map +1 -0
- package/dist/client/costRecovery-invoices.d.ts +38 -0
- package/dist/client/costRecovery-invoices.d.ts.map +1 -0
- package/dist/client/costRecovery-invoices.js +105 -0
- package/dist/client/costRecovery-invoices.js.map +1 -0
- package/dist/client/costRecovery.d.ts +156 -0
- package/dist/client/costRecovery.d.ts.map +1 -0
- package/dist/client/costRecovery.js +117 -0
- package/dist/client/costRecovery.js.map +1 -0
- package/dist/client/index.d.ts +28 -66
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +25 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/products/prices.d.ts +3 -2
- package/dist/client/products/prices.d.ts.map +1 -1
- package/dist/client/products/prices.js +0 -3
- package/dist/client/products/prices.js.map +1 -1
- package/dist/client/products/products.d.ts +3 -2
- package/dist/client/products/products.d.ts.map +1 -1
- package/dist/client/products/products.js +0 -3
- package/dist/client/products/products.js.map +1 -1
- package/dist/client/settlement/processingCosts.d.ts +56 -0
- package/dist/client/settlement/processingCosts.d.ts.map +1 -0
- package/dist/client/settlement/processingCosts.js +173 -0
- package/dist/client/settlement/processingCosts.js.map +1 -0
- package/dist/client/utils/webhookEndpoints.d.ts +1 -1
- package/dist/client/utils/webhookEndpoints.d.ts.map +1 -1
- package/dist/client/utils/webhookEndpoints.js +1 -0
- package/dist/client/utils/webhookEndpoints.js.map +1 -1
- package/dist/client/webhooks/processors.d.ts.map +1 -1
- package/dist/client/webhooks/processors.js +1 -0
- package/dist/client/webhooks/processors.js.map +1 -1
- package/dist/component/_generated/component.d.ts +322 -0
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/costRecovery/claims.d.ts +68 -0
- package/dist/component/costRecovery/claims.d.ts.map +1 -0
- package/dist/component/costRecovery/claims.js +92 -0
- package/dist/component/costRecovery/claims.js.map +1 -0
- package/dist/component/costRecovery/completion.d.ts +39 -0
- package/dist/component/costRecovery/completion.d.ts.map +1 -0
- package/dist/component/costRecovery/completion.js +69 -0
- package/dist/component/costRecovery/completion.js.map +1 -0
- package/dist/component/costRecovery/helpers.d.ts +68 -0
- package/dist/component/costRecovery/helpers.d.ts.map +1 -0
- package/dist/component/costRecovery/helpers.js +71 -0
- package/dist/component/costRecovery/helpers.js.map +1 -0
- package/dist/component/costRecovery/mutations.d.ts +210 -0
- package/dist/component/costRecovery/mutations.d.ts.map +1 -0
- package/dist/component/costRecovery/mutations.js +93 -0
- package/dist/component/costRecovery/mutations.js.map +1 -0
- package/dist/component/costRecovery/queries.d.ts +108 -0
- package/dist/component/costRecovery/queries.d.ts.map +1 -0
- package/dist/component/costRecovery/queries.js +73 -0
- package/dist/component/costRecovery/queries.js.map +1 -0
- package/dist/component/costRecovery/reservations.d.ts +95 -0
- package/dist/component/costRecovery/reservations.d.ts.map +1 -0
- package/dist/component/costRecovery/reservations.js +134 -0
- package/dist/component/costRecovery/reservations.js.map +1 -0
- package/dist/component/costRecovery/schema.d.ts +382 -0
- package/dist/component/costRecovery/schema.d.ts.map +1 -0
- package/dist/component/costRecovery/schema.js +115 -0
- package/dist/component/costRecovery/schema.js.map +1 -0
- package/dist/component/schema.d.ts +135 -0
- package/dist/component/schema.js +5 -0
- package/dist/component/schema.js.map +1 -1
- package/dist/react/components/PriceCard.d.ts +3 -1
- package/dist/react/components/PriceCard.d.ts.map +1 -1
- package/dist/react/components/PriceCard.js +2 -2
- package/dist/react/components/PriceCard.js.map +1 -1
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +1 -0
- package/dist/react/index.js.map +1 -1
- package/dist/react/lib/price-helpers.d.ts +4 -6
- package/dist/react/lib/price-helpers.d.ts.map +1 -1
- package/dist/react/lib/price-helpers.js +16 -9
- package/dist/react/lib/price-helpers.js.map +1 -1
- package/dist/react/workflows/Collections.d.ts.map +1 -1
- package/dist/react/workflows/Collections.js +2 -1
- package/dist/react/workflows/Collections.js.map +1 -1
- package/dist/react/workflows/PlanPricingEditor.d.ts +4 -0
- package/dist/react/workflows/PlanPricingEditor.d.ts.map +1 -1
- package/dist/react/workflows/PlanPricingEditor.js +12 -9
- package/dist/react/workflows/PlanPricingEditor.js.map +1 -1
- package/dist/react/workflows/Refunds.d.ts +14 -3
- package/dist/react/workflows/Refunds.d.ts.map +1 -1
- package/dist/react/workflows/Refunds.js +58 -16
- package/dist/react/workflows/Refunds.js.map +1 -1
- package/dist/react/workflows/index.d.ts +3 -1
- package/dist/react/workflows/index.d.ts.map +1 -1
- package/dist/react/workflows/index.js +2 -1
- package/dist/react/workflows/index.js.map +1 -1
- package/dist/react/workflows/refund-preview.d.ts +16 -0
- package/dist/react/workflows/refund-preview.d.ts.map +1 -0
- package/dist/react/workflows/refund-preview.js +38 -0
- package/dist/react/workflows/refund-preview.js.map +1 -0
- package/docs/react-workflows.md +167 -1
- package/package.json +2 -2
- package/src/client/billing/balanceFunding.test.ts +257 -0
- package/src/client/billing/balanceFunding.ts +183 -0
- package/src/client/billing/balanceFundingTransport.test.ts +89 -0
- package/src/client/billing/invoicePreview.test.ts +123 -0
- package/src/client/billing/invoicePreview.ts +94 -0
- package/src/client/billing/invoicePreviewTransport.test.ts +70 -0
- package/src/client/charge-currency-format.ts +29 -0
- package/src/client/charge-currency.test.ts +113 -0
- package/src/client/charge-currency.ts +119 -0
- package/src/client/costRecovery-invoices.test.ts +401 -0
- package/src/client/costRecovery-invoices.transport.test.ts +107 -0
- package/src/client/costRecovery-invoices.ts +144 -0
- package/src/client/costRecovery.test.ts +76 -0
- package/src/client/costRecovery.ts +254 -0
- package/src/client/index.ts +76 -75
- package/src/client/products/prices.ts +13 -11
- package/src/client/products/products.ts +10 -10
- package/src/client/settlement/processingCosts.test.ts +349 -0
- package/src/client/settlement/processingCosts.ts +315 -0
- package/src/client/settlement/processingCostsTransport.test.ts +135 -0
- package/src/client/utils/webhookEndpoints.test.ts +5 -0
- package/src/client/utils/webhookEndpoints.ts +1 -0
- package/src/client/webhooks/hooks.test.ts +9 -0
- package/src/client/webhooks/payout-canceled.integration.test.ts +192 -0
- package/src/client/webhooks/processors.ts +1 -0
- package/src/component/_generated/api.ts +12 -0
- package/src/component/_generated/component.ts +407 -0
- package/src/component/cost-recovery.test.ts +344 -0
- package/src/component/costRecovery/claims.ts +119 -0
- package/src/component/costRecovery/completion.ts +92 -0
- package/src/component/costRecovery/helpers.ts +83 -0
- package/src/component/costRecovery/mutations.ts +115 -0
- package/src/component/costRecovery/queries.ts +88 -0
- package/src/component/costRecovery/reservations.ts +164 -0
- package/src/component/costRecovery/schema.ts +135 -0
- package/src/component/schema.ts +10 -0
- package/src/react/components/PayoutSchedule.render.test.tsx +15 -0
- package/src/react/components/PriceCard.render.test.tsx +37 -0
- package/src/react/components/PriceCard.tsx +9 -1
- package/src/react/index.test.ts +5 -0
- package/src/react/index.ts +7 -0
- package/src/react/lib/price-helpers.test.ts +15 -2
- package/src/react/lib/price-helpers.ts +25 -8
- package/src/react/workflows/Billing.test.tsx +1 -1
- package/src/react/workflows/Collections.test.tsx +36 -0
- package/src/react/workflows/Collections.tsx +3 -1
- package/src/react/workflows/PlanPricingEditor.currency.test.tsx +164 -0
- package/src/react/workflows/PlanPricingEditor.tsx +26 -10
- package/src/react/workflows/Refunds.currency.test.tsx +290 -0
- package/src/react/workflows/Refunds.tsx +115 -25
- package/src/react/workflows/index.ts +8 -1
- package/src/react/workflows/refund-preview.test.ts +65 -0
- package/src/react/workflows/refund-preview.ts +56 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { v } from "convex/values";
|
|
2
|
+
import { observationFields, rollbackArgs } from "./schema.js";
|
|
3
|
+
import { adjustTotals, getGroup, integer, sign, validateScope, } from "./helpers.js";
|
|
4
|
+
const _observation = v.object(observationFields);
|
|
5
|
+
export async function recordClaim(ctx, args) {
|
|
6
|
+
validateScope(args);
|
|
7
|
+
[
|
|
8
|
+
args.amountDue,
|
|
9
|
+
args.sourceGross,
|
|
10
|
+
args.sourceProcessingFee,
|
|
11
|
+
args.revision,
|
|
12
|
+
].forEach(integer);
|
|
13
|
+
if (!args.claimKey ||
|
|
14
|
+
!args.sourceChargeId ||
|
|
15
|
+
args.sourceGross <= 0 ||
|
|
16
|
+
args.sourceProcessingFee < 0 ||
|
|
17
|
+
args.revision < 0)
|
|
18
|
+
throw new Error("Invalid recovery claim observation.");
|
|
19
|
+
const existing = await ctx.db
|
|
20
|
+
.query("recoveryClaims")
|
|
21
|
+
.withIndex("by_key", (q) => q.eq("claimKey", args.claimKey))
|
|
22
|
+
.unique();
|
|
23
|
+
if (existing) {
|
|
24
|
+
for (const key of [
|
|
25
|
+
"accountId",
|
|
26
|
+
"scopeKey",
|
|
27
|
+
"currency",
|
|
28
|
+
"sourceChargeId",
|
|
29
|
+
"sourceGross",
|
|
30
|
+
"sourceProcessingFee",
|
|
31
|
+
])
|
|
32
|
+
if (existing[key] !== args[key])
|
|
33
|
+
throw new Error("Recovery claim source identity cannot change.");
|
|
34
|
+
if (args.revision < existing.revision)
|
|
35
|
+
return existing;
|
|
36
|
+
if (args.revision === existing.revision) {
|
|
37
|
+
if (args.amountDue !== existing.amountDue)
|
|
38
|
+
throw new Error("Recovery revision cannot be reused with a different amount.");
|
|
39
|
+
return existing;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const delta = integer(args.amountDue - (existing?.amountDue ?? 0));
|
|
43
|
+
const collectedAmount = existing?.collectedAmount ?? 0, reservedAmount = existing?.reservedAmount ?? 0;
|
|
44
|
+
const outstanding = integer(args.amountDue - collectedAmount - reservedAmount);
|
|
45
|
+
const fields = {
|
|
46
|
+
...args,
|
|
47
|
+
collectedAmount,
|
|
48
|
+
reservedAmount,
|
|
49
|
+
outstanding,
|
|
50
|
+
sign: sign(outstanding),
|
|
51
|
+
};
|
|
52
|
+
let id = existing?._id;
|
|
53
|
+
if (id)
|
|
54
|
+
await ctx.db.patch("recoveryClaims", id, fields);
|
|
55
|
+
else
|
|
56
|
+
id = await ctx.db.insert("recoveryClaims", fields);
|
|
57
|
+
await adjustTotals(ctx, args, { amountDue: delta, outstanding: delta });
|
|
58
|
+
return (await ctx.db.get("recoveryClaims", id));
|
|
59
|
+
}
|
|
60
|
+
const _rollbackArgs = v.object(rollbackArgs);
|
|
61
|
+
export async function rollbackClaim(ctx, args) {
|
|
62
|
+
integer(args.returnedPrincipal);
|
|
63
|
+
integer(args.revision);
|
|
64
|
+
const group = await getGroup(ctx, args.groupKey);
|
|
65
|
+
if (group.status !== "collected" ||
|
|
66
|
+
(group.sourceKind === "settlement"
|
|
67
|
+
? !group.sourceGross
|
|
68
|
+
: !group.invoiceFunding))
|
|
69
|
+
throw new Error("Rollback requires a collected group with original funding economics.");
|
|
70
|
+
const funding = group.sourceKind === "settlement"
|
|
71
|
+
? {
|
|
72
|
+
sourceChargeId: group.sourceId,
|
|
73
|
+
sourceGross: group.sourceGross,
|
|
74
|
+
sourceProcessingFee: group.sourceProcessingFee,
|
|
75
|
+
}
|
|
76
|
+
: group.invoiceFunding;
|
|
77
|
+
if (args.returnedPrincipal < 0 ||
|
|
78
|
+
args.returnedPrincipal > funding.sourceGross)
|
|
79
|
+
throw new Error("Returned principal exceeds the original funding sale.");
|
|
80
|
+
const abs = BigInt(Math.abs(group.amount)), gross = BigInt(funding.sourceGross), principal = BigInt(args.returnedPrincipal);
|
|
81
|
+
const rounded = Number((abs * principal + gross / 2n) / gross);
|
|
82
|
+
return recordClaim(ctx, {
|
|
83
|
+
accountId: group.accountId,
|
|
84
|
+
scopeKey: group.scopeKey,
|
|
85
|
+
currency: group.currency,
|
|
86
|
+
claimKey: `rollback:${group.groupKey}`,
|
|
87
|
+
...funding,
|
|
88
|
+
amountDue: group.amount < 0 ? -rounded : rounded,
|
|
89
|
+
revision: args.revision,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=claims.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claims.js","sourceRoot":"","sources":["../../../src/component/costRecovery/claims.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { MutationCtx } from "../_generated/server.js";
|
|
2
|
+
import type { Infer } from "convex/values";
|
|
3
|
+
declare const _finishArgs: import("convex/values").VObject<{
|
|
4
|
+
groupKey: string;
|
|
5
|
+
limit?: number | undefined;
|
|
6
|
+
outcome: "collect" | "release";
|
|
7
|
+
}, {
|
|
8
|
+
groupKey: import("convex/values").VString<string, "required">;
|
|
9
|
+
outcome: import("convex/values").VUnion<"collect" | "release", [import("convex/values").VLiteral<"collect", "required">, import("convex/values").VLiteral<"release", "required">], "required", never>;
|
|
10
|
+
limit: import("convex/values").VFloat64<number | undefined, "optional">;
|
|
11
|
+
}, "required", "groupKey" | "limit" | "outcome">;
|
|
12
|
+
export declare function finishGroup(ctx: MutationCtx, args: Infer<typeof _finishArgs>): Promise<{
|
|
13
|
+
group: {
|
|
14
|
+
_creationTime: number;
|
|
15
|
+
_id: import("convex/values").GenericId<"recoveryGroups">;
|
|
16
|
+
accountId: string;
|
|
17
|
+
amount: number;
|
|
18
|
+
currency: string;
|
|
19
|
+
groupKey: string;
|
|
20
|
+
invoiceFunding?: {
|
|
21
|
+
sourceChargeId: string;
|
|
22
|
+
sourceGross: number;
|
|
23
|
+
sourceProcessingFee: number;
|
|
24
|
+
} | undefined;
|
|
25
|
+
invoiceItemId?: string | undefined;
|
|
26
|
+
maxCredit: number;
|
|
27
|
+
maxDebit: number;
|
|
28
|
+
pendingOperations: number;
|
|
29
|
+
scopeKey: string;
|
|
30
|
+
sourceGross?: number | undefined;
|
|
31
|
+
sourceId: string;
|
|
32
|
+
sourceKind: "invoice" | "settlement";
|
|
33
|
+
sourceProcessingFee?: number | undefined;
|
|
34
|
+
status: "collected" | "collecting" | "open" | "released" | "releasing" | "sealed";
|
|
35
|
+
};
|
|
36
|
+
isDone: boolean;
|
|
37
|
+
}>;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=completion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../../src/component/costRecovery/completion.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAW3D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,QAAA,MAAM,WAAW;;;;;;;;gDAAuB,CAAC;AACzC,wBAAsB,WAAW,CAC/B,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;GA2EhC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { v } from "convex/values";
|
|
2
|
+
import { finishArgs } from "./schema.js";
|
|
3
|
+
import { adjustTotals, balance, batchLimit, getGroup, integer, sign, } from "./helpers.js";
|
|
4
|
+
const _finishArgs = v.object(finishArgs);
|
|
5
|
+
export async function finishGroup(ctx, args) {
|
|
6
|
+
const limit = args.limit ?? 10;
|
|
7
|
+
batchLimit(limit, 10);
|
|
8
|
+
const group = await getGroup(ctx, args.groupKey);
|
|
9
|
+
const collect = args.outcome === "collect", terminal = collect ? "collected" : "released", progress = collect ? "collecting" : "releasing";
|
|
10
|
+
if (group.status === terminal)
|
|
11
|
+
return { group, isDone: true };
|
|
12
|
+
if ((collect && ["released", "releasing"].includes(group.status)) ||
|
|
13
|
+
(!collect && ["collected", "collecting"].includes(group.status)))
|
|
14
|
+
throw new Error("Recovery outcome cannot change.");
|
|
15
|
+
if (collect && group.status === "open")
|
|
16
|
+
throw new Error("Seal recovery before confirming provider collection.");
|
|
17
|
+
const operations = await ctx.db
|
|
18
|
+
.query("recoveryReservations")
|
|
19
|
+
.withIndex("by_group_status", (q) => q.eq("groupKey", group.groupKey).eq("status", "reserved"))
|
|
20
|
+
.take(limit);
|
|
21
|
+
let amount = 0;
|
|
22
|
+
for (const operation of operations) {
|
|
23
|
+
for (const allocation of operation.allocations) {
|
|
24
|
+
const claim = await ctx.db.get("recoveryClaims", allocation.claimId);
|
|
25
|
+
if (!claim ||
|
|
26
|
+
claim.accountId !== group.accountId ||
|
|
27
|
+
claim.scopeKey !== group.scopeKey ||
|
|
28
|
+
claim.currency !== group.currency)
|
|
29
|
+
throw new Error("Recovery allocation identity does not match.");
|
|
30
|
+
const reservedAmount = integer(claim.reservedAmount - allocation.amount);
|
|
31
|
+
const collectedAmount = integer(claim.collectedAmount + (collect ? allocation.amount : 0));
|
|
32
|
+
const outstanding = integer(claim.amountDue - collectedAmount - reservedAmount);
|
|
33
|
+
await ctx.db.patch("recoveryClaims", claim._id, {
|
|
34
|
+
reservedAmount,
|
|
35
|
+
collectedAmount,
|
|
36
|
+
outstanding,
|
|
37
|
+
sign: sign(outstanding),
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
await ctx.db.patch("recoveryReservations", operation._id, {
|
|
41
|
+
status: terminal,
|
|
42
|
+
});
|
|
43
|
+
amount = integer(amount + operation.amount);
|
|
44
|
+
}
|
|
45
|
+
await adjustTotals(ctx, group, {
|
|
46
|
+
reservedAmount: -amount,
|
|
47
|
+
collectedAmount: collect ? amount : 0,
|
|
48
|
+
outstanding: collect ? 0 : amount,
|
|
49
|
+
});
|
|
50
|
+
const pendingOperations = group.pendingOperations - operations.length;
|
|
51
|
+
if (pendingOperations < 0)
|
|
52
|
+
throw new Error("Recovery operation count does not reconcile.");
|
|
53
|
+
await ctx.db.patch("recoveryGroups", group._id, {
|
|
54
|
+
pendingOperations,
|
|
55
|
+
status: pendingOperations ? progress : terminal,
|
|
56
|
+
});
|
|
57
|
+
if (!pendingOperations) {
|
|
58
|
+
const ledger = await balance(ctx, group);
|
|
59
|
+
if (ledger.activeGroupKey === group.groupKey)
|
|
60
|
+
await ctx.db.patch("recoveryBalances", ledger._id, {
|
|
61
|
+
activeGroupKey: undefined,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
group: (await ctx.db.get("recoveryGroups", group._id)),
|
|
66
|
+
isDone: pendingOperations === 0,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=completion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completion.js","sourceRoot":"","sources":["../../../src/component/costRecovery/completion.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { MutationCtx, QueryCtx } from "../_generated/server.js";
|
|
2
|
+
import type { Doc } from "../_generated/dataModel.js";
|
|
3
|
+
export type Scope = {
|
|
4
|
+
accountId: string;
|
|
5
|
+
scopeKey: string;
|
|
6
|
+
currency: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function integer(value: number): number;
|
|
9
|
+
export declare function validateScope(scope: Scope): void;
|
|
10
|
+
export declare const sign: (value: number) => "negative" | "positive" | "zero";
|
|
11
|
+
export declare const scopeOnly: (scope: Scope) => Scope;
|
|
12
|
+
export declare const zeroTotals: {
|
|
13
|
+
amountDue: number;
|
|
14
|
+
collectedAmount: number;
|
|
15
|
+
reservedAmount: number;
|
|
16
|
+
outstanding: number;
|
|
17
|
+
};
|
|
18
|
+
export declare function readBalance(ctx: QueryCtx | MutationCtx, scope: Scope): Promise<{
|
|
19
|
+
_creationTime: number;
|
|
20
|
+
_id: import("convex/values").GenericId<"recoveryBalances">;
|
|
21
|
+
accountId: string;
|
|
22
|
+
activeGroupKey?: string | undefined;
|
|
23
|
+
amountDue: number;
|
|
24
|
+
collectedAmount: number;
|
|
25
|
+
currency: string;
|
|
26
|
+
outstanding: number;
|
|
27
|
+
reservedAmount: number;
|
|
28
|
+
scopeKey: string;
|
|
29
|
+
} | null>;
|
|
30
|
+
export declare function balance(ctx: MutationCtx, scope: Scope): Promise<{
|
|
31
|
+
_creationTime: number;
|
|
32
|
+
_id: import("convex/values").GenericId<"recoveryBalances">;
|
|
33
|
+
accountId: string;
|
|
34
|
+
activeGroupKey?: string | undefined;
|
|
35
|
+
amountDue: number;
|
|
36
|
+
collectedAmount: number;
|
|
37
|
+
currency: string;
|
|
38
|
+
outstanding: number;
|
|
39
|
+
reservedAmount: number;
|
|
40
|
+
scopeKey: string;
|
|
41
|
+
}>;
|
|
42
|
+
export declare function adjustTotals(ctx: MutationCtx, scope: Scope, delta: Partial<typeof zeroTotals>): Promise<void>;
|
|
43
|
+
export declare function groupTarget(group: Doc<"recoveryGroups">, outstanding: number): number;
|
|
44
|
+
export declare function getGroup(ctx: MutationCtx, key: string): Promise<{
|
|
45
|
+
_creationTime: number;
|
|
46
|
+
_id: import("convex/values").GenericId<"recoveryGroups">;
|
|
47
|
+
accountId: string;
|
|
48
|
+
amount: number;
|
|
49
|
+
currency: string;
|
|
50
|
+
groupKey: string;
|
|
51
|
+
invoiceFunding?: {
|
|
52
|
+
sourceChargeId: string;
|
|
53
|
+
sourceGross: number;
|
|
54
|
+
sourceProcessingFee: number;
|
|
55
|
+
} | undefined;
|
|
56
|
+
invoiceItemId?: string | undefined;
|
|
57
|
+
maxCredit: number;
|
|
58
|
+
maxDebit: number;
|
|
59
|
+
pendingOperations: number;
|
|
60
|
+
scopeKey: string;
|
|
61
|
+
sourceGross?: number | undefined;
|
|
62
|
+
sourceId: string;
|
|
63
|
+
sourceKind: "invoice" | "settlement";
|
|
64
|
+
sourceProcessingFee?: number | undefined;
|
|
65
|
+
status: "collected" | "collecting" | "open" | "released" | "releasing" | "sealed";
|
|
66
|
+
}>;
|
|
67
|
+
export declare function batchLimit(limit: number, max?: number): void;
|
|
68
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/component/costRecovery/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,4BAA4B,CAAC;AACtD,MAAM,MAAM,KAAK,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAC9E,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,UAIpC;AACD,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,QAGzC;AACD,eAAO,MAAM,IAAI,UAAW,MAAM,qCAKT,CAAC;AAC1B,eAAO,MAAM,SAAS,UAAW,KAAK,KAAG,KAIvC,CAAC;AACH,eAAO,MAAM,UAAU;IACrB,SAAS;IACT,eAAe;IACf,cAAc;IACd,WAAW;CACZ,CAAC;AACF,wBAAgB,WAAW,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW,EAAE,KAAK,EAAE,KAAK;;;;;;;;;;;UAUpE;AACD,wBAAsB,OAAO,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK;;;;;;;;;;;GAQ3D;AACD,wBAAsB,YAAY,CAChC,GAAG,EAAE,WAAW,EAChB,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,OAAO,CAAC,OAAO,UAAU,CAAC,iBAYlC;AACD,wBAAgB,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,gBAAgB,CAAC,EAAE,WAAW,EAAE,MAAM,UAK5E;AACD,wBAAsB,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;GAO3D;AACD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAM,QAGlD"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export function integer(value) {
|
|
2
|
+
if (!Number.isSafeInteger(value))
|
|
3
|
+
throw new Error("Recovery amounts must be safe integers.");
|
|
4
|
+
return value;
|
|
5
|
+
}
|
|
6
|
+
export function validateScope(scope) {
|
|
7
|
+
if (!scope.accountId || !scope.scopeKey || !/^[a-z]{3}$/.test(scope.currency))
|
|
8
|
+
throw new Error("Recovery account, scope and currency are required.");
|
|
9
|
+
}
|
|
10
|
+
export const sign = (value) => value > 0
|
|
11
|
+
? "positive"
|
|
12
|
+
: value < 0
|
|
13
|
+
? "negative"
|
|
14
|
+
: "zero";
|
|
15
|
+
export const scopeOnly = (scope) => ({
|
|
16
|
+
accountId: scope.accountId,
|
|
17
|
+
scopeKey: scope.scopeKey,
|
|
18
|
+
currency: scope.currency,
|
|
19
|
+
});
|
|
20
|
+
export const zeroTotals = {
|
|
21
|
+
amountDue: 0,
|
|
22
|
+
collectedAmount: 0,
|
|
23
|
+
reservedAmount: 0,
|
|
24
|
+
outstanding: 0,
|
|
25
|
+
};
|
|
26
|
+
export function readBalance(ctx, scope) {
|
|
27
|
+
return ctx.db
|
|
28
|
+
.query("recoveryBalances")
|
|
29
|
+
.withIndex("by_scope", (q) => q
|
|
30
|
+
.eq("accountId", scope.accountId)
|
|
31
|
+
.eq("scopeKey", scope.scopeKey)
|
|
32
|
+
.eq("currency", scope.currency))
|
|
33
|
+
.unique();
|
|
34
|
+
}
|
|
35
|
+
export async function balance(ctx, scope) {
|
|
36
|
+
const found = await readBalance(ctx, scope);
|
|
37
|
+
if (found)
|
|
38
|
+
return found;
|
|
39
|
+
const id = await ctx.db.insert("recoveryBalances", {
|
|
40
|
+
...scopeOnly(scope),
|
|
41
|
+
...zeroTotals,
|
|
42
|
+
});
|
|
43
|
+
return (await ctx.db.get("recoveryBalances", id));
|
|
44
|
+
}
|
|
45
|
+
export async function adjustTotals(ctx, scope, delta) {
|
|
46
|
+
const stored = await balance(ctx, scope);
|
|
47
|
+
const next = { ...zeroTotals };
|
|
48
|
+
for (const key of Object.keys(zeroTotals))
|
|
49
|
+
next[key] = integer(stored[key] + (delta[key] ?? 0));
|
|
50
|
+
if (next.outstanding !==
|
|
51
|
+
integer(next.amountDue - next.collectedAmount - next.reservedAmount))
|
|
52
|
+
throw new Error("Recovery totals do not reconcile.");
|
|
53
|
+
await ctx.db.patch("recoveryBalances", stored._id, next);
|
|
54
|
+
}
|
|
55
|
+
export function groupTarget(group, outstanding) {
|
|
56
|
+
return Math.max(-group.maxCredit, Math.min(group.maxDebit, integer(outstanding + group.amount)));
|
|
57
|
+
}
|
|
58
|
+
export async function getGroup(ctx, key) {
|
|
59
|
+
const group = await ctx.db
|
|
60
|
+
.query("recoveryGroups")
|
|
61
|
+
.withIndex("by_key", (q) => q.eq("groupKey", key))
|
|
62
|
+
.unique();
|
|
63
|
+
if (!group)
|
|
64
|
+
throw new Error("Recovery group is missing.");
|
|
65
|
+
return group;
|
|
66
|
+
}
|
|
67
|
+
export function batchLimit(limit, max = 100) {
|
|
68
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > max)
|
|
69
|
+
throw new Error(`Recovery batch limit must be between 1 and ${max}.`);
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/component/costRecovery/helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
export declare const record: import("convex/server").RegisteredMutation<"public", {
|
|
2
|
+
accountId: string;
|
|
3
|
+
amountDue: number;
|
|
4
|
+
claimKey: string;
|
|
5
|
+
currency: string;
|
|
6
|
+
revision: number;
|
|
7
|
+
scopeKey: string;
|
|
8
|
+
sourceChargeId: string;
|
|
9
|
+
sourceGross: number;
|
|
10
|
+
sourceProcessingFee: number;
|
|
11
|
+
}, Promise<{
|
|
12
|
+
_creationTime: number;
|
|
13
|
+
_id: import("convex/values").GenericId<"recoveryClaims">;
|
|
14
|
+
accountId: string;
|
|
15
|
+
amountDue: number;
|
|
16
|
+
claimKey: string;
|
|
17
|
+
collectedAmount: number;
|
|
18
|
+
currency: string;
|
|
19
|
+
outstanding: number;
|
|
20
|
+
reservedAmount: number;
|
|
21
|
+
revision: number;
|
|
22
|
+
scopeKey: string;
|
|
23
|
+
sign: "negative" | "positive" | "zero";
|
|
24
|
+
sourceChargeId: string;
|
|
25
|
+
sourceGross: number;
|
|
26
|
+
sourceProcessingFee: number;
|
|
27
|
+
}>>;
|
|
28
|
+
export declare const rollback: import("convex/server").RegisteredMutation<"public", {
|
|
29
|
+
groupKey: string;
|
|
30
|
+
returnedPrincipal: number;
|
|
31
|
+
revision: number;
|
|
32
|
+
}, Promise<{
|
|
33
|
+
_creationTime: number;
|
|
34
|
+
_id: import("convex/values").GenericId<"recoveryClaims">;
|
|
35
|
+
accountId: string;
|
|
36
|
+
amountDue: number;
|
|
37
|
+
claimKey: string;
|
|
38
|
+
collectedAmount: number;
|
|
39
|
+
currency: string;
|
|
40
|
+
outstanding: number;
|
|
41
|
+
reservedAmount: number;
|
|
42
|
+
revision: number;
|
|
43
|
+
scopeKey: string;
|
|
44
|
+
sign: "negative" | "positive" | "zero";
|
|
45
|
+
sourceChargeId: string;
|
|
46
|
+
sourceGross: number;
|
|
47
|
+
sourceProcessingFee: number;
|
|
48
|
+
}>>;
|
|
49
|
+
export declare const reserve: import("convex/server").RegisteredMutation<"public", {
|
|
50
|
+
accountId: string;
|
|
51
|
+
currency: string;
|
|
52
|
+
groupKey: string;
|
|
53
|
+
limit?: number | undefined;
|
|
54
|
+
maxCredit: number;
|
|
55
|
+
maxDebit: number;
|
|
56
|
+
operationKey: string;
|
|
57
|
+
scopeKey: string;
|
|
58
|
+
sourceGross?: number | undefined;
|
|
59
|
+
sourceId: string;
|
|
60
|
+
sourceKind: "invoice" | "settlement";
|
|
61
|
+
sourceProcessingFee?: number | undefined;
|
|
62
|
+
}, Promise<{
|
|
63
|
+
reservation: {
|
|
64
|
+
_creationTime: number;
|
|
65
|
+
_id: import("convex/values").GenericId<"recoveryReservations">;
|
|
66
|
+
allocations: {
|
|
67
|
+
amount: number;
|
|
68
|
+
claimId: import("convex/values").GenericId<"recoveryClaims">;
|
|
69
|
+
claimKey: string;
|
|
70
|
+
}[];
|
|
71
|
+
amount: number;
|
|
72
|
+
groupKey: string;
|
|
73
|
+
limit: number;
|
|
74
|
+
operationKey: string;
|
|
75
|
+
status: "collected" | "empty" | "released" | "reserved";
|
|
76
|
+
};
|
|
77
|
+
group: {
|
|
78
|
+
_creationTime: number;
|
|
79
|
+
_id: import("convex/values").GenericId<"recoveryGroups">;
|
|
80
|
+
accountId: string;
|
|
81
|
+
amount: number;
|
|
82
|
+
currency: string;
|
|
83
|
+
groupKey: string;
|
|
84
|
+
invoiceFunding?: {
|
|
85
|
+
sourceChargeId: string;
|
|
86
|
+
sourceGross: number;
|
|
87
|
+
sourceProcessingFee: number;
|
|
88
|
+
} | undefined;
|
|
89
|
+
invoiceItemId?: string | undefined;
|
|
90
|
+
maxCredit: number;
|
|
91
|
+
maxDebit: number;
|
|
92
|
+
pendingOperations: number;
|
|
93
|
+
scopeKey: string;
|
|
94
|
+
sourceGross?: number | undefined;
|
|
95
|
+
sourceId: string;
|
|
96
|
+
sourceKind: "invoice" | "settlement";
|
|
97
|
+
sourceProcessingFee?: number | undefined;
|
|
98
|
+
status: "collected" | "collecting" | "open" | "released" | "releasing" | "sealed";
|
|
99
|
+
};
|
|
100
|
+
}>>;
|
|
101
|
+
export declare const seal: import("convex/server").RegisteredMutation<"public", {
|
|
102
|
+
groupKey: string;
|
|
103
|
+
}, Promise<{
|
|
104
|
+
_creationTime: number;
|
|
105
|
+
_id: import("convex/values").GenericId<"recoveryGroups">;
|
|
106
|
+
accountId: string;
|
|
107
|
+
amount: number;
|
|
108
|
+
currency: string;
|
|
109
|
+
groupKey: string;
|
|
110
|
+
invoiceFunding?: {
|
|
111
|
+
sourceChargeId: string;
|
|
112
|
+
sourceGross: number;
|
|
113
|
+
sourceProcessingFee: number;
|
|
114
|
+
} | undefined;
|
|
115
|
+
invoiceItemId?: string | undefined;
|
|
116
|
+
maxCredit: number;
|
|
117
|
+
maxDebit: number;
|
|
118
|
+
pendingOperations: number;
|
|
119
|
+
scopeKey: string;
|
|
120
|
+
sourceGross?: number | undefined;
|
|
121
|
+
sourceId: string;
|
|
122
|
+
sourceKind: "invoice" | "settlement";
|
|
123
|
+
sourceProcessingFee?: number | undefined;
|
|
124
|
+
status: "collected" | "collecting" | "open" | "released" | "releasing" | "sealed";
|
|
125
|
+
}>>;
|
|
126
|
+
export declare const finish: import("convex/server").RegisteredMutation<"public", {
|
|
127
|
+
groupKey: string;
|
|
128
|
+
limit?: number | undefined;
|
|
129
|
+
outcome: "collect" | "release";
|
|
130
|
+
}, Promise<{
|
|
131
|
+
group: {
|
|
132
|
+
_creationTime: number;
|
|
133
|
+
_id: import("convex/values").GenericId<"recoveryGroups">;
|
|
134
|
+
accountId: string;
|
|
135
|
+
amount: number;
|
|
136
|
+
currency: string;
|
|
137
|
+
groupKey: string;
|
|
138
|
+
invoiceFunding?: {
|
|
139
|
+
sourceChargeId: string;
|
|
140
|
+
sourceGross: number;
|
|
141
|
+
sourceProcessingFee: number;
|
|
142
|
+
} | undefined;
|
|
143
|
+
invoiceItemId?: string | undefined;
|
|
144
|
+
maxCredit: number;
|
|
145
|
+
maxDebit: number;
|
|
146
|
+
pendingOperations: number;
|
|
147
|
+
scopeKey: string;
|
|
148
|
+
sourceGross?: number | undefined;
|
|
149
|
+
sourceId: string;
|
|
150
|
+
sourceKind: "invoice" | "settlement";
|
|
151
|
+
sourceProcessingFee?: number | undefined;
|
|
152
|
+
status: "collected" | "collecting" | "open" | "released" | "releasing" | "sealed";
|
|
153
|
+
};
|
|
154
|
+
isDone: boolean;
|
|
155
|
+
}>>;
|
|
156
|
+
export declare const bindInvoiceItem: import("convex/server").RegisteredMutation<"public", {
|
|
157
|
+
groupKey: string;
|
|
158
|
+
invoiceItemId: string;
|
|
159
|
+
}, Promise<{
|
|
160
|
+
_creationTime: number;
|
|
161
|
+
_id: import("convex/values").GenericId<"recoveryGroups">;
|
|
162
|
+
accountId: string;
|
|
163
|
+
amount: number;
|
|
164
|
+
currency: string;
|
|
165
|
+
groupKey: string;
|
|
166
|
+
invoiceFunding?: {
|
|
167
|
+
sourceChargeId: string;
|
|
168
|
+
sourceGross: number;
|
|
169
|
+
sourceProcessingFee: number;
|
|
170
|
+
} | undefined;
|
|
171
|
+
invoiceItemId?: string | undefined;
|
|
172
|
+
maxCredit: number;
|
|
173
|
+
maxDebit: number;
|
|
174
|
+
pendingOperations: number;
|
|
175
|
+
scopeKey: string;
|
|
176
|
+
sourceGross?: number | undefined;
|
|
177
|
+
sourceId: string;
|
|
178
|
+
sourceKind: "invoice" | "settlement";
|
|
179
|
+
sourceProcessingFee?: number | undefined;
|
|
180
|
+
status: "collected" | "collecting" | "open" | "released" | "releasing" | "sealed";
|
|
181
|
+
}>>;
|
|
182
|
+
export declare const bindInvoiceFunding: import("convex/server").RegisteredMutation<"public", {
|
|
183
|
+
groupKey: string;
|
|
184
|
+
sourceChargeId: string;
|
|
185
|
+
sourceGross: number;
|
|
186
|
+
sourceProcessingFee: number;
|
|
187
|
+
}, Promise<{
|
|
188
|
+
_creationTime: number;
|
|
189
|
+
_id: import("convex/values").GenericId<"recoveryGroups">;
|
|
190
|
+
accountId: string;
|
|
191
|
+
amount: number;
|
|
192
|
+
currency: string;
|
|
193
|
+
groupKey: string;
|
|
194
|
+
invoiceFunding?: {
|
|
195
|
+
sourceChargeId: string;
|
|
196
|
+
sourceGross: number;
|
|
197
|
+
sourceProcessingFee: number;
|
|
198
|
+
} | undefined;
|
|
199
|
+
invoiceItemId?: string | undefined;
|
|
200
|
+
maxCredit: number;
|
|
201
|
+
maxDebit: number;
|
|
202
|
+
pendingOperations: number;
|
|
203
|
+
scopeKey: string;
|
|
204
|
+
sourceGross?: number | undefined;
|
|
205
|
+
sourceId: string;
|
|
206
|
+
sourceKind: "invoice" | "settlement";
|
|
207
|
+
sourceProcessingFee?: number | undefined;
|
|
208
|
+
status: "collected" | "collecting" | "open" | "released" | "releasing" | "sealed";
|
|
209
|
+
}>>;
|
|
210
|
+
//# sourceMappingURL=mutations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutations.d.ts","sourceRoot":"","sources":["../../../src/component/costRecovery/mutations.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;GAQjB,CAAC;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;GAInB,CAAC;AACH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAIlB,CAAC;AACH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;GAIf,CAAC;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAIjB,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;GA0B1B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyC7B,CAAC"}
|