@classytic/revenue 2.5.0 → 2.6.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 +22 -0
- package/dist/{audit-DRKuLBFO.d.mts → audit-BkDdPSed.d.mts} +2 -1
- package/dist/{engine-types-F3f1lWNG.d.mts → engine-types-D6ijamqA.d.mts} +29 -1
- package/dist/{escrow.schema-o4qhjOca.d.mts → escrow.schema-DSx7EywJ.d.mts} +18 -18
- package/dist/events/index.d.mts +1 -1
- package/dist/index.d.mts +5 -5
- package/dist/index.mjs +2 -2
- package/dist/repositories/create-repositories.d.mts +1 -1
- package/dist/repositories/create-repositories.mjs +1 -1
- package/dist/{revenue-event-catalog-j8Fh7Yag.d.mts → revenue-event-catalog-BU_KYN2-.d.mts} +126 -126
- package/dist/{settlement.repository-BDrJQc27.mjs → settlement.repository-oypYDjKq.mjs} +97 -36
- package/dist/shared/index.d.mts +2 -2
- package/dist/shared/index.mjs +2 -2
- package/dist/{splits-CNfQj92L.mjs → splits-CEdZN6OT.mjs} +22 -7
- package/dist/validators/index.d.mts +1 -1
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ import { n as createEvent, t as REVENUE_EVENTS } from "./event-constants-DM_-A57
|
|
|
3
3
|
import { g as SETTLEMENT_STATUS, r as SUBSCRIPTION_STATUS, w as HOLD_STATUS } from "./subscription.enums-95othr0i.mjs";
|
|
4
4
|
import { _ as WrongTransactionKindError, g as ValidationError, h as TransactionNotFoundError, m as SubscriptionNotFoundError, n as BankFeedImportError, o as MethodKindLockedError, p as SettlementNotFoundError } from "./errors-Bt5NRVMq.mjs";
|
|
5
5
|
import { SETTLEMENT_STATE_MACHINE, SUBSCRIPTION_STATE_MACHINE, TRANSACTION_STATE_MACHINE, smFor } from "./core/state-machines.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import { c as calculateCommission, l as reverseCommission, n as calculateSplits, o as reverseTax, t as calculateOrganizationPayout } from "./splits-CEdZN6OT.mjs";
|
|
7
7
|
import { Repository, repoOptionsFromCtx, withTransaction } from "@classytic/mongokit";
|
|
8
8
|
|
|
9
9
|
//#region src/repositories/base.repository.ts
|
|
@@ -1402,6 +1402,38 @@ var SubscriptionRepository = class extends RevenueRepositoryBase {
|
|
|
1402
1402
|
|
|
1403
1403
|
//#endregion
|
|
1404
1404
|
//#region src/repositories/settlement.repository.ts
|
|
1405
|
+
function emptySettlementSummary() {
|
|
1406
|
+
return {
|
|
1407
|
+
currency: null,
|
|
1408
|
+
pending: 0,
|
|
1409
|
+
held: 0,
|
|
1410
|
+
available: 0,
|
|
1411
|
+
processing: 0,
|
|
1412
|
+
paidOut: 0,
|
|
1413
|
+
failed: 0,
|
|
1414
|
+
lifetime: 0
|
|
1415
|
+
};
|
|
1416
|
+
}
|
|
1417
|
+
/** Bucket one aggregated (status, due, total) row into a running summary. */
|
|
1418
|
+
function foldSettlementStatus(s, status, due, total) {
|
|
1419
|
+
switch (status) {
|
|
1420
|
+
case SETTLEMENT_STATUS.PENDING:
|
|
1421
|
+
s.pending += total;
|
|
1422
|
+
if (due) s.available += total;
|
|
1423
|
+
else s.held += total;
|
|
1424
|
+
break;
|
|
1425
|
+
case SETTLEMENT_STATUS.PROCESSING:
|
|
1426
|
+
s.processing += total;
|
|
1427
|
+
break;
|
|
1428
|
+
case SETTLEMENT_STATUS.COMPLETED:
|
|
1429
|
+
s.paidOut += total;
|
|
1430
|
+
break;
|
|
1431
|
+
case SETTLEMENT_STATUS.FAILED:
|
|
1432
|
+
s.failed += total;
|
|
1433
|
+
break;
|
|
1434
|
+
default: break;
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1405
1437
|
/**
|
|
1406
1438
|
* SettlementRepository — payouts to recipients (organizations, vendors,
|
|
1407
1439
|
* affiliates).
|
|
@@ -1563,12 +1595,16 @@ var SettlementRepository = class extends RevenueRepositoryBase {
|
|
|
1563
1595
|
}), ctx);
|
|
1564
1596
|
return updated;
|
|
1565
1597
|
}
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1598
|
+
/**
|
|
1599
|
+
* Settlement money-state for an ARBITRARY filter — a recipient, an org, or
|
|
1600
|
+
* the whole platform (pass `_bypassTenant` in ctx to span every org). One
|
|
1601
|
+
* tenant-scoped `aggregatePipeline` (the `{ recipientId, status }` index backs
|
|
1602
|
+
* the `$match`), never a raw `Model.aggregate`. The reusable rollup behind
|
|
1603
|
+
* `recipientBalance`, platform reconciliation, and cross-org earnings.
|
|
1604
|
+
*/
|
|
1605
|
+
async summary(filter = {}, ctx = {}) {
|
|
1570
1606
|
const now = /* @__PURE__ */ new Date();
|
|
1571
|
-
const rows = await this.aggregatePipeline([{ $match:
|
|
1607
|
+
const rows = await this.aggregatePipeline([{ $match: filter }, { $group: {
|
|
1572
1608
|
_id: {
|
|
1573
1609
|
status: "$status",
|
|
1574
1610
|
due: { $lte: ["$scheduledAt", now] }
|
|
@@ -1576,39 +1612,64 @@ var SettlementRepository = class extends RevenueRepositoryBase {
|
|
|
1576
1612
|
total: { $sum: "$amount" },
|
|
1577
1613
|
currency: { $first: "$currency" }
|
|
1578
1614
|
} }], this.optsFromCtx(ctx));
|
|
1579
|
-
const
|
|
1580
|
-
recipientId,
|
|
1581
|
-
currency: options.currency ?? null,
|
|
1582
|
-
pending: 0,
|
|
1583
|
-
held: 0,
|
|
1584
|
-
available: 0,
|
|
1585
|
-
processing: 0,
|
|
1586
|
-
paidOut: 0,
|
|
1587
|
-
failed: 0,
|
|
1588
|
-
lifetime: 0
|
|
1589
|
-
};
|
|
1615
|
+
const out = emptySettlementSummary();
|
|
1590
1616
|
for (const row of rows) {
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1617
|
+
foldSettlementStatus(out, row._id.status, row._id.due, row.total);
|
|
1618
|
+
if (row.currency && !out.currency) out.currency = row.currency;
|
|
1619
|
+
}
|
|
1620
|
+
out.lifetime = out.pending + out.processing + out.paidOut;
|
|
1621
|
+
return out;
|
|
1622
|
+
}
|
|
1623
|
+
/**
|
|
1624
|
+
* Per-recipient settlement rollup — one {@link RecipientBreakdown} per
|
|
1625
|
+
* distinct (recipientId, recipientType) matching `filter`. The reusable list
|
|
1626
|
+
* behind a platform "who is owed what" view; pass `_bypassTenant` to span all
|
|
1627
|
+
* orgs.
|
|
1628
|
+
*/
|
|
1629
|
+
async breakdownByRecipient(filter = {}, ctx = {}) {
|
|
1630
|
+
const now = /* @__PURE__ */ new Date();
|
|
1631
|
+
const rows = await this.aggregatePipeline([{ $match: filter }, { $group: {
|
|
1632
|
+
_id: {
|
|
1633
|
+
recipientId: "$recipientId",
|
|
1634
|
+
recipientType: "$recipientType",
|
|
1635
|
+
status: "$status",
|
|
1636
|
+
due: { $lte: ["$scheduledAt", now] }
|
|
1637
|
+
},
|
|
1638
|
+
total: { $sum: "$amount" },
|
|
1639
|
+
currency: { $first: "$currency" },
|
|
1640
|
+
role: { $first: "$metadata.role" }
|
|
1641
|
+
} }], this.optsFromCtx(ctx));
|
|
1642
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
1643
|
+
for (const row of rows) {
|
|
1644
|
+
const key = `${row._id.recipientType}:${row._id.recipientId}`;
|
|
1645
|
+
let r = byKey.get(key);
|
|
1646
|
+
if (!r) {
|
|
1647
|
+
r = {
|
|
1648
|
+
recipientId: row._id.recipientId,
|
|
1649
|
+
recipientType: row._id.recipientType,
|
|
1650
|
+
role: row.role ?? null,
|
|
1651
|
+
...emptySettlementSummary()
|
|
1652
|
+
};
|
|
1653
|
+
byKey.set(key, r);
|
|
1607
1654
|
}
|
|
1608
|
-
|
|
1655
|
+
foldSettlementStatus(r, row._id.status, row._id.due, row.total);
|
|
1656
|
+
if (row.role && !r.role) r.role = row.role;
|
|
1657
|
+
if (row.currency && !r.currency) r.currency = row.currency;
|
|
1609
1658
|
}
|
|
1610
|
-
|
|
1611
|
-
return
|
|
1659
|
+
for (const r of byKey.values()) r.lifetime = r.pending + r.processing + r.paidOut;
|
|
1660
|
+
return [...byKey.values()];
|
|
1661
|
+
}
|
|
1662
|
+
/** One recipient's wallet — a thin `summary` over `{ recipientId, … }`. */
|
|
1663
|
+
async recipientBalance(recipientId, options = {}, ctx = {}) {
|
|
1664
|
+
const filter = { recipientId };
|
|
1665
|
+
if (options.recipientType !== void 0) filter.recipientType = options.recipientType;
|
|
1666
|
+
if (options.currency !== void 0) filter.currency = options.currency;
|
|
1667
|
+
const s = await this.summary(filter, ctx);
|
|
1668
|
+
return {
|
|
1669
|
+
recipientId,
|
|
1670
|
+
...s,
|
|
1671
|
+
currency: options.currency ?? s.currency
|
|
1672
|
+
};
|
|
1612
1673
|
}
|
|
1613
1674
|
};
|
|
1614
1675
|
|
package/dist/shared/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as SplitInfo, B as
|
|
2
|
-
export { CURRENCIES, CommissionInfo, type CurrencyCode, CurrencyMismatchError, MINOR_UNIT_FACTOR, type Money, type MoneyValue, SplitInfo, SplitRule, TaxCalculation, TaxConfig, TaxType, absMoney, addMoney, appendAuditEvent, calculateCommission, calculateOrganizationPayout, calculateSplits, calculateTax, compareMoney, equalsMoney, fromMajor, fromSmallestUnit, getAuditTrail, getLastStateChange, getTaxType, isCurrencyCode, isMoney, isNegativeMoney, isPositiveMoney, isZeroMoney, minorUnitFactor, money, multiplyMoney, negateMoney, reverseCommission, reverseTax, subtractMoney, sumMoney, toCurrencyCode, toMajor, toSmallestUnit, validateTaxCalculation };
|
|
1
|
+
import { A as SplitInfo, B as reverseTax, C as multiplyMoney, D as toCurrencyCode, E as sumMoney, F as TaxCalculation, H as CommissionInfo, I as TaxConfig, L as TaxType, M as calculateOrganizationPayout, N as calculateSplits, O as toMajor, P as reverseSplits, R as calculateTax, S as money, T as subtractMoney, U as calculateCommission, V as validateTaxCalculation, W as reverseCommission, _ as isMoney, a as CurrencyCode, b as isZeroMoney, c as Money, d as addMoney, f as compareMoney, g as isCurrencyCode, h as fromSmallestUnit, i as CURRENCIES, j as SplitRule, k as toSmallestUnit, l as MoneyValue, m as fromMajor, n as getAuditTrail, o as CurrencyMismatchError, p as equalsMoney, r as getLastStateChange, s as MINOR_UNIT_FACTOR, t as appendAuditEvent, u as absMoney, v as isNegativeMoney, w as negateMoney, x as minorUnitFactor, y as isPositiveMoney, z as getTaxType } from "../audit-BkDdPSed.mjs";
|
|
2
|
+
export { CURRENCIES, CommissionInfo, type CurrencyCode, CurrencyMismatchError, MINOR_UNIT_FACTOR, type Money, type MoneyValue, SplitInfo, SplitRule, TaxCalculation, TaxConfig, TaxType, absMoney, addMoney, appendAuditEvent, calculateCommission, calculateOrganizationPayout, calculateSplits, calculateTax, compareMoney, equalsMoney, fromMajor, fromSmallestUnit, getAuditTrail, getLastStateChange, getTaxType, isCurrencyCode, isMoney, isNegativeMoney, isPositiveMoney, isZeroMoney, minorUnitFactor, money, multiplyMoney, negateMoney, reverseCommission, reverseSplits, reverseTax, subtractMoney, sumMoney, toCurrencyCode, toMajor, toSmallestUnit, validateTaxCalculation };
|
package/dist/shared/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as getTaxType, c as calculateCommission, i as calculateTax, l as reverseCommission, n as calculateSplits, o as reverseTax, r as reverseSplits, s as validateTaxCalculation, t as calculateOrganizationPayout } from "../splits-CEdZN6OT.mjs";
|
|
2
2
|
import { C as sumMoney, E as toSmallestUnit, S as subtractMoney, T as toMajor, _ as isZeroMoney, a as CurrencyMismatchError, b as multiplyMoney, c as addMoney, d as fromMajor, f as fromSmallestUnit, g as isPositiveMoney, h as isNegativeMoney, i as CURRENCIES, l as compareMoney, m as isMoney, n as getAuditTrail, o as MINOR_UNIT_FACTOR, p as isCurrencyCode, r as getLastStateChange, s as absMoney, t as appendAuditEvent, u as equalsMoney, v as minorUnitFactor, w as toCurrencyCode, x as negateMoney, y as money } from "../audit-Ba2XB2C4.mjs";
|
|
3
3
|
|
|
4
|
-
export { CURRENCIES, CurrencyMismatchError, MINOR_UNIT_FACTOR, absMoney, addMoney, appendAuditEvent, calculateCommission, calculateOrganizationPayout, calculateSplits, calculateTax, compareMoney, equalsMoney, fromMajor, fromSmallestUnit, getAuditTrail, getLastStateChange, getTaxType, isCurrencyCode, isMoney, isNegativeMoney, isPositiveMoney, isZeroMoney, minorUnitFactor, money, multiplyMoney, negateMoney, reverseCommission, reverseTax, subtractMoney, sumMoney, toCurrencyCode, toMajor, toSmallestUnit, validateTaxCalculation };
|
|
4
|
+
export { CURRENCIES, CurrencyMismatchError, MINOR_UNIT_FACTOR, absMoney, addMoney, appendAuditEvent, calculateCommission, calculateOrganizationPayout, calculateSplits, calculateTax, compareMoney, equalsMoney, fromMajor, fromSmallestUnit, getAuditTrail, getLastStateChange, getTaxType, isCurrencyCode, isMoney, isNegativeMoney, isPositiveMoney, isZeroMoney, minorUnitFactor, money, multiplyMoney, negateMoney, reverseCommission, reverseSplits, reverseTax, subtractMoney, sumMoney, toCurrencyCode, toMajor, toSmallestUnit, validateTaxCalculation };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { g as ValidationError } from "./errors-Bt5NRVMq.mjs";
|
|
2
|
+
|
|
1
3
|
//#region src/shared/calculators/commission.ts
|
|
2
4
|
function calculateCommission(amount, commissionRate, gatewayFeeRate = 0) {
|
|
3
5
|
if (!commissionRate || commissionRate <= 0) return null;
|
|
@@ -17,9 +19,9 @@ function calculateCommission(amount, commissionRate, gatewayFeeRate = 0) {
|
|
|
17
19
|
}
|
|
18
20
|
function reverseCommission(originalCommission, originalAmount, refundAmount) {
|
|
19
21
|
if (!originalCommission?.netAmount) return null;
|
|
20
|
-
if (!originalAmount || originalAmount <= 0) throw new
|
|
21
|
-
if (refundAmount < 0) throw new
|
|
22
|
-
if (refundAmount > originalAmount) throw new
|
|
22
|
+
if (!originalAmount || originalAmount <= 0) throw new ValidationError("Original amount must be greater than 0");
|
|
23
|
+
if (refundAmount < 0) throw new ValidationError("Refund amount cannot be negative");
|
|
24
|
+
if (refundAmount > originalAmount) throw new ValidationError("Refund amount exceeds original amount");
|
|
23
25
|
const refundRatio = refundAmount / originalAmount;
|
|
24
26
|
return {
|
|
25
27
|
rate: originalCommission.rate,
|
|
@@ -74,9 +76,9 @@ function reverseTax(originalTax, originalAmount, refundAmount) {
|
|
|
74
76
|
totalAmount: refundAmount,
|
|
75
77
|
pricesIncludeTax: false
|
|
76
78
|
};
|
|
77
|
-
if (!originalAmount || originalAmount <= 0) throw new
|
|
78
|
-
if (refundAmount < 0) throw new
|
|
79
|
-
if (refundAmount > originalAmount) throw new
|
|
79
|
+
if (!originalAmount || originalAmount <= 0) throw new ValidationError("Original amount must be greater than 0");
|
|
80
|
+
if (refundAmount < 0) throw new ValidationError("Refund amount cannot be negative");
|
|
81
|
+
if (refundAmount > originalAmount) throw new ValidationError("Refund amount exceeds original amount");
|
|
80
82
|
const refundRatio = refundAmount / originalAmount;
|
|
81
83
|
const reversedType = originalTax.type ? originalTax.type === "collected" ? "paid" : originalTax.type === "paid" ? "collected" : "exempt" : void 0;
|
|
82
84
|
return {
|
|
@@ -118,6 +120,19 @@ function calculateSplits(amount, rules, gatewayFeeRate = 0) {
|
|
|
118
120
|
function calculateOrganizationPayout(amount, splits) {
|
|
119
121
|
return amount - splits.reduce((sum, s) => sum + s.grossAmount, 0);
|
|
120
122
|
}
|
|
123
|
+
function reverseSplits(originalSplits, originalAmount, refundAmount) {
|
|
124
|
+
if (!originalAmount || originalAmount <= 0) throw new ValidationError("Original amount must be greater than 0");
|
|
125
|
+
if (refundAmount < 0) throw new ValidationError("Refund amount cannot be negative");
|
|
126
|
+
if (refundAmount > originalAmount) throw new ValidationError("Refund amount exceeds original amount");
|
|
127
|
+
const refundRatio = refundAmount / originalAmount;
|
|
128
|
+
return originalSplits.map((s) => ({
|
|
129
|
+
...s,
|
|
130
|
+
grossAmount: Math.round(s.grossAmount * refundRatio),
|
|
131
|
+
gatewayFeeAmount: Math.round(s.gatewayFeeAmount * refundRatio),
|
|
132
|
+
netAmount: Math.round(s.netAmount * refundRatio),
|
|
133
|
+
status: "waived"
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
121
136
|
|
|
122
137
|
//#endregion
|
|
123
|
-
export {
|
|
138
|
+
export { getTaxType as a, calculateCommission as c, calculateTax as i, reverseCommission as l, calculateSplits as n, reverseTax as o, reverseSplits as r, validateTaxCalculation as s, calculateOrganizationPayout as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as transactionBaseSchema, C as subscriptionBaseSchema, D as TransactionCreateInput, E as subscriptionUpdateSchema, M as transactionListFilterSchema, N as transactionUpdateSchema, O as TransactionListFilter, S as SubscriptionUpdateInput, T as subscriptionListFilterSchema, _ as settlementCreateSchema, a as escrowReleaseSchema, b as SubscriptionCreateInput, c as PaymentVerifyInput, d as paymentVerifySchema, f as refundSchema, g as settlementBaseSchema, h as SettlementUpdateInput, i as escrowHoldSchema, j as transactionCreateSchema, k as TransactionUpdateInput, l as RefundInput, m as SettlementListFilter, n as EscrowReleaseInput, o as splitRuleSchema, p as SettlementCreateInput, r as SplitRuleInput, s as PaymentIntentInput, t as EscrowHoldInput, u as paymentIntentSchema, v as settlementListFilterSchema, w as subscriptionCreateSchema, x as SubscriptionListFilter, y as settlementUpdateSchema } from "../escrow.schema-
|
|
1
|
+
import { A as transactionBaseSchema, C as subscriptionBaseSchema, D as TransactionCreateInput, E as subscriptionUpdateSchema, M as transactionListFilterSchema, N as transactionUpdateSchema, O as TransactionListFilter, S as SubscriptionUpdateInput, T as subscriptionListFilterSchema, _ as settlementCreateSchema, a as escrowReleaseSchema, b as SubscriptionCreateInput, c as PaymentVerifyInput, d as paymentVerifySchema, f as refundSchema, g as settlementBaseSchema, h as SettlementUpdateInput, i as escrowHoldSchema, j as transactionCreateSchema, k as TransactionUpdateInput, l as RefundInput, m as SettlementListFilter, n as EscrowReleaseInput, o as splitRuleSchema, p as SettlementCreateInput, r as SplitRuleInput, s as PaymentIntentInput, t as EscrowHoldInput, u as paymentIntentSchema, v as settlementListFilterSchema, w as subscriptionCreateSchema, x as SubscriptionListFilter, y as settlementUpdateSchema } from "../escrow.schema-DSx7EywJ.mjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
|
|
4
4
|
//#region src/validators/bank-feed.schema.d.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@classytic/revenue",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "Payment lifecycle engine — transactions, subscriptions, escrow, settlements, commissions. MongoKit-powered, Arc-compatible, framework-agnostic.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|