@classytic/ledger 0.5.0 → 0.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/README.md +2 -0
- package/dist/country/index.d.mts +2 -2
- package/dist/{errors-BmRjW38t.mjs → errors-CSDQPNyt.mjs} +1 -1
- package/dist/fx-realization.plugin-CgQFDGv2.mjs +459 -0
- package/dist/index-BthGypsI.d.mts +228 -0
- package/dist/index.d.mts +50 -105
- package/dist/index.mjs +644 -124
- package/dist/{fiscal-close-Dk3yRT9i.mjs → partner-ledger-D9H5hegI.mjs} +143 -6
- package/dist/plugins/index.d.mts +2 -24
- package/dist/plugins/index.mjs +2 -2
- package/dist/reports/index.d.mts +2 -2
- package/dist/reports/index.mjs +2 -2
- package/dist/tax-hooks-BnVenul5.d.mts +513 -0
- package/dist/{trial-balance-BZ7yOOFD.d.mts → trial-balance-s92GEvRR.d.mts} +75 -2
- package/package.json +6 -5
- package/dist/date-lock.plugin-B2Jy0ukX.mjs +0 -253
- package/dist/idempotency.plugin-CK7LHnBn.d.mts +0 -60
- package/dist/index-GmfEFxVn.d.mts +0 -119
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as Errors } from "./errors-
|
|
1
|
+
import { n as Errors } from "./errors-CSDQPNyt.mjs";
|
|
2
2
|
import { i as extractMainType } from "./categories-BkKdv16V.mjs";
|
|
3
3
|
import mongoose from "mongoose";
|
|
4
4
|
//#region src/utils/tenant-guard.ts
|
|
@@ -1519,7 +1519,7 @@ async function closeFiscalPeriod(opts, params) {
|
|
|
1519
1519
|
if (orgField && organizationId) periodQuery[orgField] = organizationId;
|
|
1520
1520
|
const period = await FiscalPeriodModel.findOne(periodQuery, null, queryOpts).lean();
|
|
1521
1521
|
if (!period) throw Errors.notFound("Fiscal period not found");
|
|
1522
|
-
if (period.closed) throw Errors.
|
|
1522
|
+
if (period.closed) throw Errors.locked("fiscal", "Fiscal period is already closed");
|
|
1523
1523
|
const startDate = period.startDate;
|
|
1524
1524
|
const endDate = period.endDate;
|
|
1525
1525
|
const accountQuery = { active: true };
|
|
@@ -1538,7 +1538,7 @@ async function closeFiscalPeriod(opts, params) {
|
|
|
1538
1538
|
isIncome: at.category === "Income Statement-Income"
|
|
1539
1539
|
});
|
|
1540
1540
|
}
|
|
1541
|
-
if (!retainedEarningsId) throw Errors.fiscal
|
|
1541
|
+
if (!retainedEarningsId) throw Errors.locked("fiscal", `Retained earnings account (code: ${retainedEarningsAccountCode}) not found. Create this account before closing the fiscal period.`);
|
|
1542
1542
|
const baseMatch = {
|
|
1543
1543
|
state: "posted",
|
|
1544
1544
|
date: {
|
|
@@ -1630,13 +1630,13 @@ async function reopenFiscalPeriod(opts, params) {
|
|
|
1630
1630
|
if (orgField && organizationId) periodQuery[orgField] = organizationId;
|
|
1631
1631
|
const period = await FiscalPeriodModel.findOne(periodQuery, null, queryOpts).lean();
|
|
1632
1632
|
if (!period) throw Errors.notFound("Fiscal period not found");
|
|
1633
|
-
if (!period.closed) throw Errors.
|
|
1633
|
+
if (!period.closed) throw Errors.locked("fiscal", "Fiscal period is not closed");
|
|
1634
1634
|
const laterQuery = {
|
|
1635
1635
|
closed: true,
|
|
1636
1636
|
startDate: { $gt: period.endDate }
|
|
1637
1637
|
};
|
|
1638
1638
|
if (orgField && organizationId) laterQuery[orgField] = organizationId;
|
|
1639
|
-
if (await FiscalPeriodModel.findOne(laterQuery, null, queryOpts).lean()) throw Errors.
|
|
1639
|
+
if (await FiscalPeriodModel.findOne(laterQuery, null, queryOpts).lean()) throw Errors.locked("fiscal", "Cannot reopen: a later fiscal period is already closed. Reopen later periods first.");
|
|
1640
1640
|
const closingEntryId = period.closingEntryId ?? null;
|
|
1641
1641
|
if (closingEntryId) await JournalEntryModel.findByIdAndDelete(closingEntryId, queryOpts);
|
|
1642
1642
|
const reopenedAt = /* @__PURE__ */ new Date();
|
|
@@ -1660,4 +1660,141 @@ async function reopenFiscalPeriod(opts, params) {
|
|
|
1660
1660
|
}
|
|
1661
1661
|
}
|
|
1662
1662
|
//#endregion
|
|
1663
|
-
|
|
1663
|
+
//#region src/reports/partner-ledger.ts
|
|
1664
|
+
async function generatePartnerLedger(opts, params) {
|
|
1665
|
+
const { AccountModel, JournalEntryModel, orgField } = opts;
|
|
1666
|
+
const { controlAccountId, partnerField = "partnerId", partnerId, startDate, endDate, includeMatched = true, buckets = DEFAULT_BUCKETS } = params;
|
|
1667
|
+
requireOrgScope(orgField, params.organizationId);
|
|
1668
|
+
const accountDoc = await AccountModel.findById(controlAccountId).lean();
|
|
1669
|
+
const openingMatch = {
|
|
1670
|
+
state: "posted",
|
|
1671
|
+
date: { $lt: startDate }
|
|
1672
|
+
};
|
|
1673
|
+
if (orgField && params.organizationId) openingMatch[orgField] = params.organizationId;
|
|
1674
|
+
const openingPipeline = [
|
|
1675
|
+
{ $match: openingMatch },
|
|
1676
|
+
{ $unwind: "$journalItems" },
|
|
1677
|
+
{ $match: {
|
|
1678
|
+
"journalItems.account": controlAccountId,
|
|
1679
|
+
[`journalItems.${partnerField}`]: partnerId
|
|
1680
|
+
} },
|
|
1681
|
+
{ $group: {
|
|
1682
|
+
_id: null,
|
|
1683
|
+
debit: { $sum: { $ifNull: ["$journalItems.debit", 0] } },
|
|
1684
|
+
credit: { $sum: { $ifNull: ["$journalItems.credit", 0] } }
|
|
1685
|
+
} }
|
|
1686
|
+
];
|
|
1687
|
+
const openingResult = await JournalEntryModel.aggregate(openingPipeline);
|
|
1688
|
+
const openingBalance = (openingResult[0]?.debit ?? 0) - (openingResult[0]?.credit ?? 0);
|
|
1689
|
+
const periodMatch = {
|
|
1690
|
+
state: "posted",
|
|
1691
|
+
date: {
|
|
1692
|
+
$gte: startDate,
|
|
1693
|
+
$lte: endDate
|
|
1694
|
+
}
|
|
1695
|
+
};
|
|
1696
|
+
if (orgField && params.organizationId) periodMatch[orgField] = params.organizationId;
|
|
1697
|
+
const itemMatch = {
|
|
1698
|
+
"journalItems.account": controlAccountId,
|
|
1699
|
+
[`journalItems.${partnerField}`]: partnerId
|
|
1700
|
+
};
|
|
1701
|
+
if (!includeMatched) itemMatch.$or = [{ "journalItems.matchingNumber": null }, { "journalItems.matchingNumber": { $exists: false } }];
|
|
1702
|
+
const linePipeline = [
|
|
1703
|
+
{ $match: periodMatch },
|
|
1704
|
+
{ $addFields: { journalItems: { $map: {
|
|
1705
|
+
input: { $range: [0, { $size: "$journalItems" }] },
|
|
1706
|
+
as: "idx",
|
|
1707
|
+
in: { $mergeObjects: [{ $arrayElemAt: ["$journalItems", "$$idx"] }, { _itemIndex: "$$idx" }] }
|
|
1708
|
+
} } } },
|
|
1709
|
+
{ $unwind: "$journalItems" },
|
|
1710
|
+
{ $match: itemMatch },
|
|
1711
|
+
{ $project: {
|
|
1712
|
+
_id: 0,
|
|
1713
|
+
entry: "$_id",
|
|
1714
|
+
itemIndex: "$journalItems._itemIndex",
|
|
1715
|
+
date: { $ifNull: ["$journalItems.date", "$date"] },
|
|
1716
|
+
referenceNumber: 1,
|
|
1717
|
+
label: "$journalItems.label",
|
|
1718
|
+
debit: { $ifNull: ["$journalItems.debit", 0] },
|
|
1719
|
+
credit: { $ifNull: ["$journalItems.credit", 0] },
|
|
1720
|
+
signedDelta: { $subtract: [{ $ifNull: ["$journalItems.debit", 0] }, { $ifNull: ["$journalItems.credit", 0] }] },
|
|
1721
|
+
matchingNumber: "$journalItems.matchingNumber",
|
|
1722
|
+
maturityDate: "$journalItems.maturityDate"
|
|
1723
|
+
} },
|
|
1724
|
+
{ $sort: {
|
|
1725
|
+
date: 1,
|
|
1726
|
+
entry: 1,
|
|
1727
|
+
itemIndex: 1
|
|
1728
|
+
} },
|
|
1729
|
+
{ $setWindowFields: {
|
|
1730
|
+
sortBy: {
|
|
1731
|
+
date: 1,
|
|
1732
|
+
entry: 1,
|
|
1733
|
+
itemIndex: 1
|
|
1734
|
+
},
|
|
1735
|
+
output: { runningDelta: {
|
|
1736
|
+
$sum: "$signedDelta",
|
|
1737
|
+
window: { documents: ["unbounded", "current"] }
|
|
1738
|
+
} }
|
|
1739
|
+
} }
|
|
1740
|
+
];
|
|
1741
|
+
const rawLines = await JournalEntryModel.aggregate(linePipeline);
|
|
1742
|
+
const endMs = endDate.getTime();
|
|
1743
|
+
const lines = rawLines.map((r) => {
|
|
1744
|
+
const matchingNumber = r.matchingNumber ?? null;
|
|
1745
|
+
const maturityDate = r.maturityDate ?? null;
|
|
1746
|
+
const daysPastDue = maturityDate ? Math.max(0, Math.floor((endMs - new Date(maturityDate).getTime()) / 864e5)) : null;
|
|
1747
|
+
return {
|
|
1748
|
+
date: r.date,
|
|
1749
|
+
entry: r.entry,
|
|
1750
|
+
itemIndex: r.itemIndex,
|
|
1751
|
+
referenceNumber: r.referenceNumber,
|
|
1752
|
+
label: r.label,
|
|
1753
|
+
debit: r.debit,
|
|
1754
|
+
credit: r.credit,
|
|
1755
|
+
balance: openingBalance + r.runningDelta,
|
|
1756
|
+
matchingNumber,
|
|
1757
|
+
maturityDate,
|
|
1758
|
+
daysPastDue,
|
|
1759
|
+
isMatched: matchingNumber != null
|
|
1760
|
+
};
|
|
1761
|
+
});
|
|
1762
|
+
const closingBalance = lines.length > 0 ? lines[lines.length - 1].balance : openingBalance;
|
|
1763
|
+
let openItemsTotal = 0;
|
|
1764
|
+
let matchedTotal = 0;
|
|
1765
|
+
for (const l of lines) {
|
|
1766
|
+
const delta = l.debit - l.credit;
|
|
1767
|
+
if (l.isMatched) matchedTotal += delta;
|
|
1768
|
+
else openItemsTotal += delta;
|
|
1769
|
+
}
|
|
1770
|
+
const agedBuckets = Object.fromEntries(buckets.map((b) => [b.label, 0]));
|
|
1771
|
+
for (const l of lines) {
|
|
1772
|
+
if (l.isMatched) continue;
|
|
1773
|
+
const days = l.daysPastDue ?? 0;
|
|
1774
|
+
const bucket = buckets.find((b) => days >= b.minDays && days < b.maxDays);
|
|
1775
|
+
if (bucket) agedBuckets[bucket.label] += l.debit - l.credit;
|
|
1776
|
+
}
|
|
1777
|
+
return {
|
|
1778
|
+
metadata: {
|
|
1779
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1780
|
+
partnerId,
|
|
1781
|
+
controlAccount: {
|
|
1782
|
+
id: controlAccountId,
|
|
1783
|
+
name: accountDoc?.name,
|
|
1784
|
+
code: accountDoc?.accountNumber
|
|
1785
|
+
},
|
|
1786
|
+
period: {
|
|
1787
|
+
startDate: startDate.toISOString().split("T")[0],
|
|
1788
|
+
endDate: endDate.toISOString().split("T")[0]
|
|
1789
|
+
}
|
|
1790
|
+
},
|
|
1791
|
+
openingBalance,
|
|
1792
|
+
closingBalance,
|
|
1793
|
+
openItemsTotal,
|
|
1794
|
+
matchedTotal,
|
|
1795
|
+
lines,
|
|
1796
|
+
agedBuckets
|
|
1797
|
+
};
|
|
1798
|
+
}
|
|
1799
|
+
//#endregion
|
|
1800
|
+
export { isVirtualTaxAccount as C, requireOrgScope as E, computeEndingBalance as S, generateAgedBalance as T, buildItemFilters as _, finalizeSession as a, buildAccountTypeMap as b, generateRevaluation as c, generateIncomeStatement as d, generateGeneralLedger as f, generateBalanceSheet as g, generateBudgetVsActual as h, acquireSession as i, buildRevaluationEntry as l, generateCashFlow as m, closeFiscalPeriod as n, defaultLogger as o, generateDimensionBreakdown as p, reopenFiscalPeriod as r, generateTrialBalance as s, generatePartnerLedger as t, computeRevaluation as u, getDateRange as v, DEFAULT_BUCKETS as w, calculateTotal as x, getFiscalYearStart as y };
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -1,28 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { C as DoubleEntryPluginOptions, E as creditLimitPlugin, S as fxRealizationPlugin, T as CreditLimitPluginOptions, _ as LockResolver, a as DailyLockPluginOptions, b as idempotencyPlugin, c as dailyLockPlugin, d as PeriodResolverOptions, f as periodResolver, g as LockHit, h as LockAccountSelector, i as watermarkResolver, l as fiscalLockPlugin, m as CreateLockPluginOptions, o as FiscalLockPluginOptions, p as createLockPlugin, r as WatermarkResolverOptions, s as TaxLockPluginOptions, t as TaxLineGenerator, u as taxLockPlugin, v as LockResolverContext, w as doubleEntryPlugin, x as FxRealizationPluginOptions, y as IdempotencyPluginOptions } from "../tax-hooks-BnVenul5.mjs";
|
|
2
2
|
import { RepositoryInstance } from "@classytic/mongokit";
|
|
3
3
|
|
|
4
|
-
//#region src/utils/tax-hooks.d.ts
|
|
5
|
-
interface TaxLineInput {
|
|
6
|
-
account: unknown;
|
|
7
|
-
amount: number;
|
|
8
|
-
side: 'debit' | 'credit';
|
|
9
|
-
taxCode?: string;
|
|
10
|
-
extraFields?: Record<string, unknown>;
|
|
11
|
-
}
|
|
12
|
-
interface GeneratedTaxLine {
|
|
13
|
-
account: unknown;
|
|
14
|
-
debit: number;
|
|
15
|
-
credit: number;
|
|
16
|
-
label?: string;
|
|
17
|
-
taxDetails?: Array<{
|
|
18
|
-
taxCode: string;
|
|
19
|
-
taxName?: string;
|
|
20
|
-
}>;
|
|
21
|
-
}
|
|
22
|
-
interface TaxLineGenerator {
|
|
23
|
-
generateTaxLines(input: TaxLineInput): GeneratedTaxLine[];
|
|
24
|
-
}
|
|
25
|
-
//#endregion
|
|
26
4
|
//#region src/plugins/tax-hook.plugin.d.ts
|
|
27
5
|
interface TaxHookPluginOptions {
|
|
28
6
|
/** Tax line generator — implements the tax calculation logic */
|
|
@@ -35,4 +13,4 @@ declare function taxHookPlugin(options: TaxHookPluginOptions): {
|
|
|
35
13
|
apply(repo: RepositoryInstance): void;
|
|
36
14
|
};
|
|
37
15
|
//#endregion
|
|
38
|
-
export { type
|
|
16
|
+
export { type CreateLockPluginOptions, type CreditLimitPluginOptions, type DailyLockPluginOptions, type DoubleEntryPluginOptions, type FiscalLockPluginOptions, type FxRealizationPluginOptions, type IdempotencyPluginOptions, type LockAccountSelector, type LockHit, type LockResolver, type LockResolverContext, type PeriodResolverOptions, type TaxHookPluginOptions, type TaxLockPluginOptions, type WatermarkResolverOptions, createLockPlugin, creditLimitPlugin, dailyLockPlugin, doubleEntryPlugin, fiscalLockPlugin, fxRealizationPlugin, idempotencyPlugin, periodResolver, taxHookPlugin, taxLockPlugin, watermarkResolver };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as
|
|
1
|
+
import { a as taxLockPlugin, c as createLockPlugin, i as fiscalLockPlugin, l as idempotencyPlugin, n as creditLimitPlugin, o as watermarkResolver, r as dailyLockPlugin, s as periodResolver, t as fxRealizationPlugin, u as doubleEntryPlugin } from "../fx-realization.plugin-CgQFDGv2.mjs";
|
|
2
2
|
//#region src/utils/tax-hooks.ts
|
|
3
3
|
/**
|
|
4
4
|
* Apply a tax hook to journal items.
|
|
@@ -54,4 +54,4 @@ function taxHookPlugin(options) {
|
|
|
54
54
|
};
|
|
55
55
|
}
|
|
56
56
|
//#endregion
|
|
57
|
-
export {
|
|
57
|
+
export { createLockPlugin, creditLimitPlugin, dailyLockPlugin, doubleEntryPlugin, fiscalLockPlugin, fxRealizationPlugin, idempotencyPlugin, periodResolver, taxHookPlugin, taxLockPlugin, watermarkResolver };
|
package/dist/reports/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { type AgedBalanceOptions, type AgedBalanceParams, type AgedBalanceReport, type AgedBalanceRow, type AgedBucketConfig, type BalanceSheetOptions, type BudgetVsActualOptions, type BudgetVsActualParams, type BudgetVsActualReport, type BudgetVsActualRow, type CashFlowOptions, DEFAULT_BUCKETS, type DimensionBreakdownOptions, type DimensionBreakdownParams, type DimensionBreakdownReport, type DimensionBreakdownRow, type FiscalCloseOptions, type FiscalCloseResult, type FiscalReopenResult, type GeneralLedgerOptions, type IncomeStatementOptions, type RevaluationOptions, type RevaluationParams, type RevaluationReport, type TrialBalanceOptions, closeFiscalPeriod, generateAgedBalance, generateBalanceSheet, generateBudgetVsActual, generateCashFlow, generateDimensionBreakdown, generateGeneralLedger, generateIncomeStatement, generateRevaluation, generateTrialBalance, reopenFiscalPeriod };
|
|
1
|
+
import { A as generateDimensionBreakdown, C as FiscalReopenResult, D as DimensionBreakdownParams, E as DimensionBreakdownOptions, F as BudgetVsActualReport, I as BudgetVsActualRow, L as generateBudgetVsActual, M as generateCashFlow, N as BudgetVsActualOptions, O as DimensionBreakdownReport, P as BudgetVsActualParams, R as BalanceSheetOptions, S as FiscalCloseResult, T as reopenFiscalPeriod, _ as IncomeStatementOptions, a as RevaluationReport, at as DEFAULT_BUCKETS, b as generateGeneralLedger, et as AgedBalanceOptions, f as PartnerLedgerLine, g as generatePartnerLedger, h as PartnerLedgerReport, i as RevaluationParams, it as AgedBucketConfig, j as CashFlowOptions, k as DimensionBreakdownRow, m as PartnerLedgerParams, n as generateTrialBalance, nt as AgedBalanceReport, o as generateRevaluation, ot as generateAgedBalance, p as PartnerLedgerOptions, r as RevaluationOptions, rt as AgedBalanceRow, t as TrialBalanceOptions, tt as AgedBalanceParams, v as generateIncomeStatement, w as closeFiscalPeriod, x as FiscalCloseOptions, y as GeneralLedgerOptions, z as generateBalanceSheet } from "../trial-balance-s92GEvRR.mjs";
|
|
2
|
+
export { type AgedBalanceOptions, type AgedBalanceParams, type AgedBalanceReport, type AgedBalanceRow, type AgedBucketConfig, type BalanceSheetOptions, type BudgetVsActualOptions, type BudgetVsActualParams, type BudgetVsActualReport, type BudgetVsActualRow, type CashFlowOptions, DEFAULT_BUCKETS, type DimensionBreakdownOptions, type DimensionBreakdownParams, type DimensionBreakdownReport, type DimensionBreakdownRow, type FiscalCloseOptions, type FiscalCloseResult, type FiscalReopenResult, type GeneralLedgerOptions, type IncomeStatementOptions, type PartnerLedgerLine, type PartnerLedgerOptions, type PartnerLedgerParams, type PartnerLedgerReport, type RevaluationOptions, type RevaluationParams, type RevaluationReport, type TrialBalanceOptions, closeFiscalPeriod, generateAgedBalance, generateBalanceSheet, generateBudgetVsActual, generateCashFlow, generateDimensionBreakdown, generateGeneralLedger, generateIncomeStatement, generatePartnerLedger, generateRevaluation, generateTrialBalance, reopenFiscalPeriod };
|
package/dist/reports/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { DEFAULT_BUCKETS, closeFiscalPeriod, generateAgedBalance, generateBalanceSheet, generateBudgetVsActual, generateCashFlow, generateDimensionBreakdown, generateGeneralLedger, generateIncomeStatement, generateRevaluation, generateTrialBalance, reopenFiscalPeriod };
|
|
1
|
+
import { T as generateAgedBalance, c as generateRevaluation, d as generateIncomeStatement, f as generateGeneralLedger, g as generateBalanceSheet, h as generateBudgetVsActual, m as generateCashFlow, n as closeFiscalPeriod, p as generateDimensionBreakdown, r as reopenFiscalPeriod, s as generateTrialBalance, t as generatePartnerLedger, w as DEFAULT_BUCKETS } from "../partner-ledger-D9H5hegI.mjs";
|
|
2
|
+
export { DEFAULT_BUCKETS, closeFiscalPeriod, generateAgedBalance, generateBalanceSheet, generateBudgetVsActual, generateCashFlow, generateDimensionBreakdown, generateGeneralLedger, generateIncomeStatement, generatePartnerLedger, generateRevaluation, generateTrialBalance, reopenFiscalPeriod };
|