@classytic/revenue 2.5.0 → 2.7.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 +50 -0
- package/dist/{audit-Ba2XB2C4.mjs → audit-C5c4LAf6.mjs} +1 -1
- package/dist/{audit-DRKuLBFO.d.mts → audit-Cug6g_31.d.mts} +3 -2
- package/dist/{bank-feed-ClxNob_I.mjs → bank-feed-yxrt4YpT.mjs} +1 -1
- package/dist/core/state-machines.mjs +2 -2
- package/dist/{engine-types-F3f1lWNG.d.mts → engine-types-D6ijamqA.d.mts} +29 -1
- package/dist/enums/index.mjs +1 -1
- package/dist/{errors-Bt5NRVMq.mjs → errors-8P5tRgV7.mjs} +11 -1
- package/dist/{escrow.schema-o4qhjOca.d.mts → escrow.schema-DSx7EywJ.d.mts} +18 -18
- package/dist/{escrow.schema-BcKdzrJ7.mjs → escrow.schema-gksK8F-W.mjs} +5 -4
- package/dist/events/index.d.mts +1 -1
- package/dist/events/index.mjs +2 -2
- package/dist/index.d.mts +13 -5
- package/dist/index.mjs +10 -10
- package/dist/providers/index.mjs +1 -1
- 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/{revenue-event-catalog-B9aZmNpL.mjs → revenue-event-catalog-DQXCuS-l.mjs} +3 -2
- package/dist/{settlement.repository-BDrJQc27.mjs → settlement.repository-KDKH2jcq.mjs} +104 -44
- package/dist/shared/index.d.mts +2 -2
- package/dist/shared/index.mjs +3 -3
- package/dist/{splits-CNfQj92L.mjs → splits-rs6mkdGN.mjs} +22 -7
- package/dist/validators/index.d.mts +1 -1
- package/dist/validators/index.mjs +5 -4
- package/package.json +8 -7
- /package/dist/{event-constants-DM_-A57b.mjs → event-constants-CPmh2sIt.mjs} +0 -0
- /package/dist/{subscription.enums-95othr0i.mjs → subscription.enums-olW5dyly.mjs} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { t as REVENUE_EVENTS } from "./event-constants-
|
|
1
|
+
import { t as REVENUE_EVENTS } from "./event-constants-CPmh2sIt.mjs";
|
|
2
2
|
import { PAYMENT_METHOD_KIND } from "@classytic/primitives/payment-method-kind";
|
|
3
3
|
import { createEvent, matchEventPattern } from "@classytic/primitives/events";
|
|
4
|
+
import { CURRENCY_PATTERN } from "@classytic/primitives/currency";
|
|
4
5
|
import { z } from "zod";
|
|
5
6
|
|
|
6
7
|
//#region src/events/in-process-bus.ts
|
|
@@ -91,7 +92,7 @@ function defineRevenueEvent(input) {
|
|
|
91
92
|
}
|
|
92
93
|
const money = z.object({
|
|
93
94
|
amount: z.number().nonnegative(),
|
|
94
|
-
currency: z.string().
|
|
95
|
+
currency: z.string().regex(CURRENCY_PATTERN, "ISO 4217 (3 uppercase letters)")
|
|
95
96
|
});
|
|
96
97
|
const transactionRef = z.object({
|
|
97
98
|
_id: z.union([z.string(), z.any()]).optional(),
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { _ as TRANSACTION_STATUS, a as TRANSACTION_KIND, s as initialStatusFor } from "./bank-feed.enums-ByS3mjX0.mjs";
|
|
2
|
-
import { n as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { _ as ValidationError, g as UnmanagedSessionError, h as TransactionNotFoundError, m as SubscriptionNotFoundError, n as BankFeedImportError, o as MethodKindLockedError, p as SettlementNotFoundError, v as WrongTransactionKindError } from "./errors-8P5tRgV7.mjs";
|
|
3
|
+
import { n as createEvent, t as REVENUE_EVENTS } from "./event-constants-CPmh2sIt.mjs";
|
|
4
|
+
import { g as SETTLEMENT_STATUS, r as SUBSCRIPTION_STATUS, w as HOLD_STATUS } from "./subscription.enums-olW5dyly.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-rs6mkdGN.mjs";
|
|
7
7
|
import { Repository, repoOptionsFromCtx, withTransaction } from "@classytic/mongokit";
|
|
8
|
+
import { addDays, addMonths, addYears } from "@classytic/primitives/calendar";
|
|
8
9
|
|
|
9
10
|
//#region src/repositories/base.repository.ts
|
|
10
11
|
/**
|
|
@@ -139,12 +140,14 @@ var RevenueRepositoryBase = class extends Repository {
|
|
|
139
140
|
* @param ctx - The same context that produced the business write.
|
|
140
141
|
*/
|
|
141
142
|
async dispatch(event, ctx = {}) {
|
|
143
|
+
if (ctx.session && !this.deps.outbox) throw new UnmanagedSessionError();
|
|
142
144
|
if (this.deps.outbox) try {
|
|
143
145
|
await this.deps.outbox.save(event, ctx.session !== void 0 ? { session: ctx.session } : {});
|
|
144
146
|
} catch (err) {
|
|
145
147
|
this.deps.logger?.error("[revenue] outbox.save failed for", event.type, err);
|
|
146
148
|
throw err;
|
|
147
149
|
}
|
|
150
|
+
if (ctx.session) return;
|
|
148
151
|
try {
|
|
149
152
|
await this.deps.events.publish(event);
|
|
150
153
|
} catch (err) {
|
|
@@ -1303,11 +1306,7 @@ var SubscriptionRepository = class extends RevenueRepositoryBase {
|
|
|
1303
1306
|
if (!sub) throw new SubscriptionNotFoundError(subscriptionId);
|
|
1304
1307
|
SUBSCRIPTION_STATE_MACHINE.validate(sub.status, SUBSCRIPTION_STATUS.ACTIVE, subscriptionId);
|
|
1305
1308
|
const now = options.timestamp ?? /* @__PURE__ */ new Date();
|
|
1306
|
-
const endDate =
|
|
1307
|
-
if (sub.planKey === "monthly") endDate.setMonth(endDate.getMonth() + 1);
|
|
1308
|
-
else if (sub.planKey === "quarterly") endDate.setMonth(endDate.getMonth() + 3);
|
|
1309
|
-
else if (sub.planKey === "yearly") endDate.setFullYear(endDate.getFullYear() + 1);
|
|
1310
|
-
else endDate.setDate(endDate.getDate() + 30);
|
|
1309
|
+
const endDate = sub.planKey === "monthly" ? addMonths(now, 1) : sub.planKey === "quarterly" ? addMonths(now, 3) : sub.planKey === "yearly" ? addYears(now, 1) : addDays(now, 30);
|
|
1311
1310
|
const updated = await this.update(subscriptionId, {
|
|
1312
1311
|
status: SUBSCRIPTION_STATUS.ACTIVE,
|
|
1313
1312
|
isActive: true,
|
|
@@ -1402,6 +1401,38 @@ var SubscriptionRepository = class extends RevenueRepositoryBase {
|
|
|
1402
1401
|
|
|
1403
1402
|
//#endregion
|
|
1404
1403
|
//#region src/repositories/settlement.repository.ts
|
|
1404
|
+
function emptySettlementSummary() {
|
|
1405
|
+
return {
|
|
1406
|
+
currency: null,
|
|
1407
|
+
pending: 0,
|
|
1408
|
+
held: 0,
|
|
1409
|
+
available: 0,
|
|
1410
|
+
processing: 0,
|
|
1411
|
+
paidOut: 0,
|
|
1412
|
+
failed: 0,
|
|
1413
|
+
lifetime: 0
|
|
1414
|
+
};
|
|
1415
|
+
}
|
|
1416
|
+
/** Bucket one aggregated (status, due, total) row into a running summary. */
|
|
1417
|
+
function foldSettlementStatus(s, status, due, total) {
|
|
1418
|
+
switch (status) {
|
|
1419
|
+
case SETTLEMENT_STATUS.PENDING:
|
|
1420
|
+
s.pending += total;
|
|
1421
|
+
if (due) s.available += total;
|
|
1422
|
+
else s.held += total;
|
|
1423
|
+
break;
|
|
1424
|
+
case SETTLEMENT_STATUS.PROCESSING:
|
|
1425
|
+
s.processing += total;
|
|
1426
|
+
break;
|
|
1427
|
+
case SETTLEMENT_STATUS.COMPLETED:
|
|
1428
|
+
s.paidOut += total;
|
|
1429
|
+
break;
|
|
1430
|
+
case SETTLEMENT_STATUS.FAILED:
|
|
1431
|
+
s.failed += total;
|
|
1432
|
+
break;
|
|
1433
|
+
default: break;
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1405
1436
|
/**
|
|
1406
1437
|
* SettlementRepository — payouts to recipients (organizations, vendors,
|
|
1407
1438
|
* affiliates).
|
|
@@ -1563,12 +1594,16 @@ var SettlementRepository = class extends RevenueRepositoryBase {
|
|
|
1563
1594
|
}), ctx);
|
|
1564
1595
|
return updated;
|
|
1565
1596
|
}
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1597
|
+
/**
|
|
1598
|
+
* Settlement money-state for an ARBITRARY filter — a recipient, an org, or
|
|
1599
|
+
* the whole platform (pass `_bypassTenant` in ctx to span every org). One
|
|
1600
|
+
* tenant-scoped `aggregatePipeline` (the `{ recipientId, status }` index backs
|
|
1601
|
+
* the `$match`), never a raw `Model.aggregate`. The reusable rollup behind
|
|
1602
|
+
* `recipientBalance`, platform reconciliation, and cross-org earnings.
|
|
1603
|
+
*/
|
|
1604
|
+
async summary(filter = {}, ctx = {}) {
|
|
1570
1605
|
const now = /* @__PURE__ */ new Date();
|
|
1571
|
-
const rows = await this.aggregatePipeline([{ $match:
|
|
1606
|
+
const rows = await this.aggregatePipeline([{ $match: filter }, { $group: {
|
|
1572
1607
|
_id: {
|
|
1573
1608
|
status: "$status",
|
|
1574
1609
|
due: { $lte: ["$scheduledAt", now] }
|
|
@@ -1576,39 +1611,64 @@ var SettlementRepository = class extends RevenueRepositoryBase {
|
|
|
1576
1611
|
total: { $sum: "$amount" },
|
|
1577
1612
|
currency: { $first: "$currency" }
|
|
1578
1613
|
} }], 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
|
-
};
|
|
1614
|
+
const out = emptySettlementSummary();
|
|
1590
1615
|
for (const row of rows) {
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1616
|
+
foldSettlementStatus(out, row._id.status, row._id.due, row.total);
|
|
1617
|
+
if (row.currency && !out.currency) out.currency = row.currency;
|
|
1618
|
+
}
|
|
1619
|
+
out.lifetime = out.pending + out.processing + out.paidOut;
|
|
1620
|
+
return out;
|
|
1621
|
+
}
|
|
1622
|
+
/**
|
|
1623
|
+
* Per-recipient settlement rollup — one {@link RecipientBreakdown} per
|
|
1624
|
+
* distinct (recipientId, recipientType) matching `filter`. The reusable list
|
|
1625
|
+
* behind a platform "who is owed what" view; pass `_bypassTenant` to span all
|
|
1626
|
+
* orgs.
|
|
1627
|
+
*/
|
|
1628
|
+
async breakdownByRecipient(filter = {}, ctx = {}) {
|
|
1629
|
+
const now = /* @__PURE__ */ new Date();
|
|
1630
|
+
const rows = await this.aggregatePipeline([{ $match: filter }, { $group: {
|
|
1631
|
+
_id: {
|
|
1632
|
+
recipientId: "$recipientId",
|
|
1633
|
+
recipientType: "$recipientType",
|
|
1634
|
+
status: "$status",
|
|
1635
|
+
due: { $lte: ["$scheduledAt", now] }
|
|
1636
|
+
},
|
|
1637
|
+
total: { $sum: "$amount" },
|
|
1638
|
+
currency: { $first: "$currency" },
|
|
1639
|
+
role: { $first: "$metadata.role" }
|
|
1640
|
+
} }], this.optsFromCtx(ctx));
|
|
1641
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
1642
|
+
for (const row of rows) {
|
|
1643
|
+
const key = `${row._id.recipientType}:${row._id.recipientId}`;
|
|
1644
|
+
let r = byKey.get(key);
|
|
1645
|
+
if (!r) {
|
|
1646
|
+
r = {
|
|
1647
|
+
recipientId: row._id.recipientId,
|
|
1648
|
+
recipientType: row._id.recipientType,
|
|
1649
|
+
role: row.role ?? null,
|
|
1650
|
+
...emptySettlementSummary()
|
|
1651
|
+
};
|
|
1652
|
+
byKey.set(key, r);
|
|
1607
1653
|
}
|
|
1608
|
-
|
|
1654
|
+
foldSettlementStatus(r, row._id.status, row._id.due, row.total);
|
|
1655
|
+
if (row.role && !r.role) r.role = row.role;
|
|
1656
|
+
if (row.currency && !r.currency) r.currency = row.currency;
|
|
1609
1657
|
}
|
|
1610
|
-
|
|
1611
|
-
return
|
|
1658
|
+
for (const r of byKey.values()) r.lifetime = r.pending + r.processing + r.paidOut;
|
|
1659
|
+
return [...byKey.values()];
|
|
1660
|
+
}
|
|
1661
|
+
/** One recipient's wallet — a thin `summary` over `{ recipientId, … }`. */
|
|
1662
|
+
async recipientBalance(recipientId, options = {}, ctx = {}) {
|
|
1663
|
+
const filter = { recipientId };
|
|
1664
|
+
if (options.recipientType !== void 0) filter.recipientType = options.recipientType;
|
|
1665
|
+
if (options.currency !== void 0) filter.currency = options.currency;
|
|
1666
|
+
const s = await this.summary(filter, ctx);
|
|
1667
|
+
return {
|
|
1668
|
+
recipientId,
|
|
1669
|
+
...s,
|
|
1670
|
+
currency: options.currency ?? s.currency
|
|
1671
|
+
};
|
|
1612
1672
|
}
|
|
1613
1673
|
};
|
|
1614
1674
|
|
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-Cug6g_31.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
|
|
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-
|
|
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-rs6mkdGN.mjs";
|
|
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-C5c4LAf6.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 { _ as ValidationError } from "./errors-8P5tRgV7.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
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { n as BANK_FEED_SOURCE_VALUES, o as TRANSACTION_KIND_VALUES } from "../bank-feed.enums-ByS3mjX0.mjs";
|
|
2
|
-
import { _ as transactionListFilterSchema, a as paymentVerifySchema, c as settlementCreateSchema, d as subscriptionBaseSchema, f as subscriptionCreateSchema, g as transactionCreateSchema, h as transactionBaseSchema, i as paymentIntentSchema, l as settlementListFilterSchema, m as subscriptionUpdateSchema, n as escrowReleaseSchema, o as refundSchema, p as subscriptionListFilterSchema, r as splitRuleSchema, s as settlementBaseSchema, t as escrowHoldSchema, u as settlementUpdateSchema, v as transactionUpdateSchema } from "../escrow.schema-
|
|
2
|
+
import { _ as transactionListFilterSchema, a as paymentVerifySchema, c as settlementCreateSchema, d as subscriptionBaseSchema, f as subscriptionCreateSchema, g as transactionCreateSchema, h as transactionBaseSchema, i as paymentIntentSchema, l as settlementListFilterSchema, m as subscriptionUpdateSchema, n as escrowReleaseSchema, o as refundSchema, p as subscriptionListFilterSchema, r as splitRuleSchema, s as settlementBaseSchema, t as escrowHoldSchema, u as settlementUpdateSchema, v as transactionUpdateSchema } from "../escrow.schema-gksK8F-W.mjs";
|
|
3
|
+
import { CURRENCY_PATTERN } from "@classytic/primitives/currency";
|
|
3
4
|
import { z } from "zod";
|
|
4
5
|
|
|
5
6
|
//#region src/validators/bank-feed.schema.ts
|
|
@@ -12,7 +13,7 @@ import { z } from "zod";
|
|
|
12
13
|
*/
|
|
13
14
|
const moneySchema = z.object({
|
|
14
15
|
amount: z.number().int(),
|
|
15
|
-
currency: z.string().
|
|
16
|
+
currency: z.string().regex(CURRENCY_PATTERN, "ISO 4217 (3 uppercase letters)")
|
|
16
17
|
});
|
|
17
18
|
const counterpartySchema = z.object({
|
|
18
19
|
name: z.string().optional(),
|
|
@@ -66,7 +67,7 @@ const unmatchBodySchema = z.object({ unmatchedBy: z.string().optional() });
|
|
|
66
67
|
const manualEntrySchema = z.object({
|
|
67
68
|
kind: z.literal("manual").default("manual"),
|
|
68
69
|
amount: z.number().nonnegative(),
|
|
69
|
-
currency: z.string().
|
|
70
|
+
currency: z.string().regex(CURRENCY_PATTERN, "ISO 4217 (3 uppercase letters)"),
|
|
70
71
|
flow: z.enum(["inflow", "outflow"]),
|
|
71
72
|
type: z.string().min(1),
|
|
72
73
|
description: z.string().optional(),
|
|
@@ -79,7 +80,7 @@ const manualEntrySchema = z.object({
|
|
|
79
80
|
});
|
|
80
81
|
const findMatchCandidatesQuerySchema = z.object({
|
|
81
82
|
amount: z.coerce.number().nonnegative(),
|
|
82
|
-
currency: z.string().
|
|
83
|
+
currency: z.string().regex(CURRENCY_PATTERN, "ISO 4217 (3 uppercase letters)").optional(),
|
|
83
84
|
postedDate: z.coerce.date(),
|
|
84
85
|
toleranceDays: z.coerce.number().int().min(0).max(30).optional(),
|
|
85
86
|
amountTolerancePct: z.coerce.number().min(0).max(.5).optional(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@classytic/revenue",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.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,
|
|
@@ -100,9 +100,9 @@
|
|
|
100
100
|
"LICENSE"
|
|
101
101
|
],
|
|
102
102
|
"peerDependencies": {
|
|
103
|
-
"@classytic/mongokit": ">=3.
|
|
104
|
-
"@classytic/primitives": ">=0.
|
|
105
|
-
"@classytic/repo-core": ">=0.
|
|
103
|
+
"@classytic/mongokit": ">=3.18.0",
|
|
104
|
+
"@classytic/primitives": ">=0.9.1",
|
|
105
|
+
"@classytic/repo-core": ">=0.7.0",
|
|
106
106
|
"mongoose": ">=9.4.1",
|
|
107
107
|
"zod": ">=4.0.0"
|
|
108
108
|
},
|
|
@@ -110,9 +110,10 @@
|
|
|
110
110
|
"node": ">=18.0.0"
|
|
111
111
|
},
|
|
112
112
|
"devDependencies": {
|
|
113
|
-
"@classytic/
|
|
114
|
-
"@classytic/
|
|
115
|
-
"@classytic/
|
|
113
|
+
"@classytic/dev-tools": "^0.2.0",
|
|
114
|
+
"@classytic/mongokit": "^3.18.0",
|
|
115
|
+
"@classytic/primitives": "^0.9.0",
|
|
116
|
+
"@classytic/repo-core": "^0.7.0",
|
|
116
117
|
"@types/node": "^22.8.7",
|
|
117
118
|
"mongoose": "^9.4.1",
|
|
118
119
|
"tsdown": "^0.20.3",
|
|
File without changes
|
|
File without changes
|