@classytic/ledger 0.10.2 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/bridges/index.d.mts +1 -1
  2. package/dist/constants/index.d.mts +1 -1
  3. package/dist/constants/index.mjs +2 -2
  4. package/dist/{core-DwjkrRkJ.d.mts → core-B7uVjqGS.d.mts} +25 -0
  5. package/dist/country/index.d.mts +1 -1
  6. package/dist/events/index.d.mts +1 -1
  7. package/dist/exports/index.d.mts +1 -1
  8. package/dist/exports/index.mjs +1 -1
  9. package/dist/{fx-realization.plugin-Dzqzi3u0.mjs → fx-realization.plugin-DY3pPxIi.mjs} +70 -1
  10. package/dist/{index-ClLwzNRF.d.mts → index-BFPFihTF.d.mts} +8 -0
  11. package/dist/{index-08IpHhrU.d.mts → index-Dd7HknPP.d.mts} +1 -1
  12. package/dist/index.d.mts +120 -24
  13. package/dist/index.mjs +375 -165
  14. package/dist/{journals-DUpWwFt1.d.mts → journals-CTrAuzdk.d.mts} +1 -1
  15. package/dist/{partner-ledger-CR0geilx.mjs → partner-ledger-B0eym6Ss.mjs} +951 -213
  16. package/dist/plugins/index.d.mts +1 -1
  17. package/dist/plugins/index.mjs +1 -1
  18. package/dist/reports/index.d.mts +2 -2
  19. package/dist/reports/index.mjs +2 -2
  20. package/dist/{trial-balance-DyNm5bFu.d.mts → trial-balance-UXV2PN6x.d.mts} +280 -75
  21. package/package.json +8 -20
  22. package/dist/opening-balance-1cixYh6Y.mjs +0 -60
  23. package/dist/sync/index.d.mts +0 -324
  24. package/dist/sync/index.mjs +0 -530
  25. package/dist/sync-JvchM3FO.d.mts +0 -152
  26. /package/dist/{categories-FJlrvzcl.mjs → categories-CclX7Q94.mjs} +0 -0
  27. /package/dist/{currencies-Jo5oaM_4.mjs → currencies-OuPHPyS2.mjs} +0 -0
  28. /package/dist/{exports-C30yRapf.mjs → exports-B3whucXe.mjs} +0 -0
  29. /package/dist/{index-Bl0gP9lD.d.mts → index-DygMrab0.d.mts} +0 -0
  30. /package/dist/{index-J-XIbXH-.d.mts → index-pRW5cZhF.d.mts} +0 -0
  31. /package/dist/{outbox-store-BcCiHMPw.d.mts → outbox-store-CPLeocPg.d.mts} +0 -0
@@ -1,2 +1,2 @@
1
- import { S as creditLimitPlugin, _ as FxRealizationPluginOptions, a as dailyLockPlugin, b as doubleEntryPlugin, c as periodResolver, d as LockAccountSelector, f as LockHit, g as idempotencyPlugin, h as IdempotencyPluginOptions, i as FiscalLockPluginOptions, l as createLockPlugin, m as LockResolverContext, n as watermarkResolver, o as fiscalLockPlugin, p as LockResolver, r as DailyLockPluginOptions, s as PeriodResolverOptions, t as WatermarkResolverOptions, u as CreateLockPluginOptions, v as fxRealizationPlugin, x as CreditLimitPluginOptions, y as DoubleEntryPluginOptions } from "../index-ClLwzNRF.mjs";
1
+ import { S as creditLimitPlugin, _ as FxRealizationPluginOptions, a as dailyLockPlugin, b as doubleEntryPlugin, c as periodResolver, d as LockAccountSelector, f as LockHit, g as idempotencyPlugin, h as IdempotencyPluginOptions, i as FiscalLockPluginOptions, l as createLockPlugin, m as LockResolverContext, n as watermarkResolver, o as fiscalLockPlugin, p as LockResolver, r as DailyLockPluginOptions, s as PeriodResolverOptions, t as WatermarkResolverOptions, u as CreateLockPluginOptions, v as fxRealizationPlugin, x as CreditLimitPluginOptions, y as DoubleEntryPluginOptions } from "../index-BFPFihTF.mjs";
2
2
  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 WatermarkResolverOptions, createLockPlugin, creditLimitPlugin, dailyLockPlugin, doubleEntryPlugin, fiscalLockPlugin, fxRealizationPlugin, idempotencyPlugin, periodResolver, watermarkResolver };
@@ -1,2 +1,2 @@
1
- import { a as watermarkResolver, c as idempotencyPlugin, i as fiscalLockPlugin, l as doubleEntryPlugin, n as creditLimitPlugin, o as periodResolver, r as dailyLockPlugin, s as createLockPlugin, t as fxRealizationPlugin } from "../fx-realization.plugin-Dzqzi3u0.mjs";
1
+ import { a as watermarkResolver, c as idempotencyPlugin, i as fiscalLockPlugin, l as doubleEntryPlugin, n as creditLimitPlugin, o as periodResolver, r as dailyLockPlugin, s as createLockPlugin, t as fxRealizationPlugin } from "../fx-realization.plugin-DY3pPxIi.mjs";
2
2
  export { createLockPlugin, creditLimitPlugin, dailyLockPlugin, doubleEntryPlugin, fiscalLockPlugin, fxRealizationPlugin, idempotencyPlugin, periodResolver, watermarkResolver };
@@ -1,2 +1,2 @@
1
- import { $ as AgedBalanceParams, 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, Q as AgedBalanceOptions, R as BalanceSheetOptions, S as FiscalCloseResult, T as reopenFiscalPeriod, _ as IncomeStatementOptions, a as RevaluationReport, b as generateGeneralLedger, et as AgedBalanceReport, f as PartnerLedgerLine, g as generatePartnerLedger, h as PartnerLedgerReport, i as RevaluationParams, it as generateAgedBalance, j as CashFlowOptions, k as DimensionBreakdownRow, m as PartnerLedgerParams, n as generateTrialBalance, nt as AgedBucketConfig, o as generateRevaluation, p as PartnerLedgerOptions, r as RevaluationOptions, rt as DEFAULT_BUCKETS, t as TrialBalanceOptions, tt as AgedBalanceRow, v as generateIncomeStatement, w as closeFiscalPeriod, x as FiscalCloseOptions, y as GeneralLedgerOptions, z as generateBalanceSheet } from "../trial-balance-DyNm5bFu.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 };
1
+ import { A as generateDimensionBreakdown, B as AgedBalanceOptions, C as FiscalReopenResult, D as DimensionBreakdownParams, E as DimensionBreakdownOptions, F as BudgetVsActualReport, G as DEFAULT_BUCKETS, H as AgedBalanceReport, I as BudgetVsActualRow, K as generateAgedBalance, L as generateBudgetVsActual, M as generateCashFlow, N as BudgetVsActualOptions, O as DimensionBreakdownReport, P as BudgetVsActualParams, R as BalanceSheetOptions, S as FiscalCloseResult, T as reopenFiscalPeriod, U as AgedBalanceRow, V as AgedBalanceParams, W as AgedBucketConfig, _ as IncomeStatementOptions, _t as DaybookOptions, a as RevaluationReport, b as generateGeneralLedger, bt as generateDaybook, f as PartnerLedgerLine, g as generatePartnerLedger, gt as DaybookLine, h as PartnerLedgerReport, i as RevaluationParams, j as CashFlowOptions, k as DimensionBreakdownRow, m as PartnerLedgerParams, n as generateTrialBalance, o as generateRevaluation, p as PartnerLedgerOptions, r as RevaluationOptions, t as TrialBalanceOptions, v as generateIncomeStatement, vt as DaybookParams, w as closeFiscalPeriod, x as FiscalCloseOptions, y as GeneralLedgerOptions, yt as DaybookReport, z as generateBalanceSheet } from "../trial-balance-UXV2PN6x.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 DaybookLine, type DaybookOptions, type DaybookParams, type DaybookReport, 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, generateDaybook, generateDimensionBreakdown, generateGeneralLedger, generateIncomeStatement, generatePartnerLedger, generateRevaluation, generateTrialBalance, reopenFiscalPeriod };
@@ -1,2 +1,2 @@
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-CR0geilx.mjs";
2
- export { DEFAULT_BUCKETS, closeFiscalPeriod, generateAgedBalance, generateBalanceSheet, generateBudgetVsActual, generateCashFlow, generateDimensionBreakdown, generateGeneralLedger, generateIncomeStatement, generatePartnerLedger, generateRevaluation, generateTrialBalance, reopenFiscalPeriod };
1
+ import { E as generateAgedBalance, T as DEFAULT_BUCKETS, _ as generateBalanceSheet, c as generateRevaluation, d as generateIncomeStatement, f as generateGeneralLedger, g as generateBudgetVsActual, h as generateCashFlow, m as generateDaybook, n as closeFiscalPeriod, p as generateDimensionBreakdown, r as reopenFiscalPeriod, s as generateTrialBalance, t as generatePartnerLedger } from "../partner-ledger-B0eym6Ss.mjs";
2
+ export { DEFAULT_BUCKETS, closeFiscalPeriod, generateAgedBalance, generateBalanceSheet, generateBudgetVsActual, generateCashFlow, generateDaybook, generateDimensionBreakdown, generateGeneralLedger, generateIncomeStatement, generatePartnerLedger, generateRevaluation, generateTrialBalance, reopenFiscalPeriod };
@@ -1,7 +1,72 @@
1
- import { c as DateRange } from "./core-DwjkrRkJ.mjs";
2
- import { t as CountryPack } from "./index-08IpHhrU.mjs";
1
+ import { c as DateRange } from "./core-B7uVjqGS.mjs";
2
+ import { t as CountryPack } from "./index-Dd7HknPP.mjs";
3
3
  import { ClientSession, Model } from "mongoose";
4
4
 
5
+ //#region src/reports/daybook.d.ts
6
+ interface DaybookOptions {
7
+ JournalEntryModel: Model<unknown>;
8
+ orgField?: string;
9
+ }
10
+ interface DaybookParams {
11
+ organizationId?: unknown;
12
+ startDate: Date;
13
+ endDate: Date;
14
+ /** Default `'posted'`. Pass `'draft'` or `'all'` to widen. */
15
+ state?: 'posted' | 'draft' | 'all';
16
+ /** Filter to one specific account (renders that account's daybook slice). */
17
+ accountId?: unknown;
18
+ /** Filter to one journal type (e.g. `'SALES'`, `'PURCHASES'`). */
19
+ journalType?: string;
20
+ /** Filter to one partner (item-level field). */
21
+ partnerId?: unknown;
22
+ /** Field name on each item that holds the partner reference. Default `partnerId`. */
23
+ partnerField?: string;
24
+ /** Hard cap on rows. Default 5000 — prevents accidental full-table dumps. */
25
+ limit?: number;
26
+ }
27
+ interface DaybookLine {
28
+ date: Date;
29
+ entryId: unknown;
30
+ itemIndex: number;
31
+ referenceNumber?: string;
32
+ journalType?: string;
33
+ entryLabel?: string;
34
+ itemLabel?: string;
35
+ state?: string;
36
+ accountId: unknown;
37
+ /** Item-level debit in minor units (paisa). */
38
+ debit: number;
39
+ /** Item-level credit in minor units (paisa). */
40
+ credit: number;
41
+ partnerId?: unknown;
42
+ matchingNumber?: string | null;
43
+ }
44
+ interface DaybookReport {
45
+ metadata: {
46
+ generatedAt: string;
47
+ period: {
48
+ startDate: string;
49
+ endDate: string;
50
+ };
51
+ state: string;
52
+ filters: {
53
+ accountId?: unknown;
54
+ journalType?: string;
55
+ partnerId?: unknown;
56
+ };
57
+ truncated: boolean;
58
+ rowCount: number;
59
+ };
60
+ lines: DaybookLine[];
61
+ /** Sum of debits across the returned slice (minor units). */
62
+ totalDebit: number;
63
+ /** Sum of credits across the returned slice (minor units). */
64
+ totalCredit: number;
65
+ /** Net = totalDebit − totalCredit. Posted-only slices should net to 0. */
66
+ netDelta: number;
67
+ }
68
+ declare function generateDaybook(opts: DaybookOptions, params: DaybookParams): Promise<DaybookReport>;
69
+ //#endregion
5
70
  //#region src/utils/logger.d.ts
6
71
  /**
7
72
  * Minimal logger interface for the accounting package.
@@ -15,49 +80,6 @@ interface Logger {
15
80
  /** Default console-based implementation */
16
81
  declare const defaultLogger: Logger;
17
82
  //#endregion
18
- //#region src/reports/aged-balance.d.ts
19
- interface AgedBucketConfig {
20
- label: string;
21
- minDays: number;
22
- maxDays: number;
23
- }
24
- declare const DEFAULT_BUCKETS: AgedBucketConfig[];
25
- interface AgedBalanceOptions {
26
- AccountModel: Model<unknown>;
27
- JournalEntryModel: Model<unknown>;
28
- country: CountryPack;
29
- orgField?: string;
30
- }
31
- interface AgedBalanceParams {
32
- organizationId?: unknown;
33
- asOfDate?: Date;
34
- type: 'receivable' | 'payable';
35
- accountIds?: unknown[];
36
- dueDateField?: string;
37
- contactField?: string;
38
- buckets?: AgedBucketConfig[];
39
- }
40
- interface AgedBalanceRow {
41
- accountId: unknown;
42
- accountName: string;
43
- accountCode: string;
44
- contactId?: unknown;
45
- total: number;
46
- buckets: Record<string, number>;
47
- }
48
- interface AgedBalanceReport {
49
- metadata: {
50
- generatedAt: string;
51
- asOfDate: string;
52
- type: string;
53
- };
54
- bucketLabels: string[];
55
- rows: AgedBalanceRow[];
56
- totals: Record<string, number>;
57
- grandTotal: number;
58
- }
59
- declare function generateAgedBalance(opts: AgedBalanceOptions, params: AgedBalanceParams): Promise<AgedBalanceReport>;
60
- //#endregion
61
83
  //#region src/types/report.d.ts
62
84
  interface ReportMetadata {
63
85
  businessName?: string;
@@ -82,6 +104,39 @@ interface ReportCategory {
82
104
  total: number;
83
105
  groups: ReportGroup[];
84
106
  }
107
+ type ComparativeMode = 'monthly' | 'quarterly' | null;
108
+ interface PeriodColumn {
109
+ /** Stable column key (e.g. '2026-01', '2026-Q2', 'total', '31-60'). */
110
+ key: string;
111
+ /** Human label shown in the column header (e.g. 'Jan 2026', 'Q2 2026'). */
112
+ label: string;
113
+ /**
114
+ * Column start boundary — ISO yyyy-mm-dd. Empty string for age buckets
115
+ * (`isAgeBucket: true`), since aging buckets represent age windows
116
+ * relative to `asOfDate`, not absolute date ranges.
117
+ */
118
+ startDate: string;
119
+ /**
120
+ * Column end boundary — ISO yyyy-mm-dd. Empty string for age buckets.
121
+ * Consumers should drive UI rendering off `isAgeBucket` + `label`, not
122
+ * `startDate`/`endDate`, when displaying aging columns.
123
+ */
124
+ endDate: string;
125
+ /** True for aggregate columns appended after detail columns. */
126
+ isTotal?: boolean;
127
+ /** True when the column is an aging bucket rather than a date period. */
128
+ isAgeBucket?: boolean;
129
+ }
130
+ interface ReportLine<TSource = Record<string, unknown>> {
131
+ label: string;
132
+ code: string;
133
+ amounts: Record<string, number>;
134
+ source: TSource;
135
+ }
136
+ interface ReportSection<TSource = Record<string, unknown>> {
137
+ totals: Record<string, number>;
138
+ lines: Array<ReportLine<TSource>>;
139
+ }
85
140
  interface TrialBalanceRow {
86
141
  account: unknown;
87
142
  initial: {
@@ -97,45 +152,109 @@ interface TrialBalanceRow {
97
152
  credit: number;
98
153
  };
99
154
  }
155
+ interface TrialBalanceColumnRow {
156
+ account: unknown;
157
+ initial: {
158
+ debit: Record<string, number>;
159
+ credit: Record<string, number>;
160
+ };
161
+ current: {
162
+ debit: Record<string, number>;
163
+ credit: Record<string, number>;
164
+ };
165
+ ending: {
166
+ debit: Record<string, number>;
167
+ credit: Record<string, number>;
168
+ };
169
+ }
100
170
  interface TrialBalanceReport {
101
171
  metadata?: ReportMetadata & {
102
172
  periodStart: string;
103
173
  periodEnd: string;
104
174
  displayPeriod: string;
175
+ comparative?: ComparativeMode;
105
176
  };
106
- rows: TrialBalanceRow[];
107
177
  period: DateRange;
178
+ periods: PeriodColumn[];
179
+ columnarRows: TrialBalanceColumnRow[];
108
180
  }
109
181
  interface BalanceSheetReport {
110
182
  metadata: ReportMetadata & {
111
183
  asOfDate: string;
112
184
  displayDate: string;
185
+ comparative?: ComparativeMode;
186
+ /**
187
+ * Display labels sourced from the country pack's `reportLabels`. FE
188
+ * renders section headers from these so the same engine output can
189
+ * power "Stockholders' Equity" (US) or "Owners' Equity" (UK) without
190
+ * a fork. Defaults: assets='Assets', liabilities='Liabilities', equity='Equity'.
191
+ */
192
+ labels?: {
193
+ assets?: string;
194
+ liabilities?: string;
195
+ equity?: string;
196
+ };
113
197
  };
114
- assets: ReportCategory;
115
- liabilities: ReportCategory;
116
- equity: ReportCategory;
117
- summary: {
118
- totalAssets: number;
119
- totalLiabilities: number;
120
- totalEquity: number;
121
- liabilitiesAndEquity: number;
122
- difference: number;
123
- isBalanced: boolean;
198
+ periods: PeriodColumn[];
199
+ summaryByPeriod: {
200
+ totalAssets: Record<string, number>;
201
+ totalLiabilities: Record<string, number>;
202
+ totalEquity: Record<string, number>;
203
+ liabilitiesAndEquity: Record<string, number>;
204
+ difference: Record<string, number>;
205
+ isBalanced: Record<string, boolean>;
124
206
  };
125
- }
207
+ assetsSection: BalanceSheetSection;
208
+ liabilitiesSection: BalanceSheetSection;
209
+ equitySection: BalanceSheetSection;
210
+ }
211
+ type BalanceSheetLineSource = {
212
+ kind: 'account';
213
+ accountId: string;
214
+ group: string;
215
+ section: 'assets' | 'liabilities' | 'equity';
216
+ } | {
217
+ kind: 'calculated';
218
+ accountId: string;
219
+ group: string;
220
+ section: 'equity';
221
+ };
222
+ type BalanceSheetSection = ReportSection<BalanceSheetLineSource>;
126
223
  interface IncomeStatementReport {
127
224
  metadata: ReportMetadata & {
128
225
  periodStart: string;
129
226
  periodEnd: string;
130
227
  displayPeriod: string;
228
+ comparative?: ComparativeMode;
229
+ /**
230
+ * Display labels sourced from the country pack's `reportLabels`. Same
231
+ * shape as `BalanceSheetReport.metadata.labels`; powers section
232
+ * headers like "Net Revenue" (US) vs "Revenue" (default).
233
+ */
234
+ labels?: {
235
+ revenue?: string;
236
+ expenses?: string;
237
+ };
131
238
  };
132
- revenue: ReportCategory;
133
- costOfSales: number;
134
- grossProfit: number;
135
- expenses: ReportCategory;
136
- operatingIncome: number;
137
- netIncome: number;
138
- }
239
+ periods: PeriodColumn[];
240
+ revenueSection: IncomeStatementSection;
241
+ expensesSection: IncomeStatementSection;
242
+ summarySection: IncomeStatementSection;
243
+ costOfSalesByPeriod: Record<string, number>;
244
+ grossProfitByPeriod: Record<string, number>;
245
+ operatingIncomeByPeriod: Record<string, number>;
246
+ netIncomeByPeriod: Record<string, number>;
247
+ }
248
+ type IncomeStatementLineSource = {
249
+ kind: 'account';
250
+ accountId: string;
251
+ group: string;
252
+ statementType: 'revenue' | 'expense';
253
+ } | {
254
+ kind: 'aggregate';
255
+ name: 'costOfSales' | 'grossProfit' | 'operatingIncome' | 'netIncome';
256
+ };
257
+ type IncomeStatementSection = ReportSection<IncomeStatementLineSource>;
139
258
  interface LedgerEntry {
140
259
  date: Date;
141
260
  referenceNumber: string;
@@ -159,25 +278,106 @@ interface GeneralLedgerReport {
159
278
  accounts: GeneralLedgerAccount[];
160
279
  period: DateRange;
161
280
  }
162
- interface CashFlowSection {
163
- total: number;
164
- accounts: Array<{
165
- name: string;
166
- code: string;
167
- amount: number;
168
- }>;
281
+ /** Discriminator on each CashFlowLine — drives UI drill-down + section logic. */
282
+ type CashFlowLineSource = {
283
+ kind: 'netIncome';
284
+ } | {
285
+ kind: 'nonCashAdjustment';
286
+ tag: string;
287
+ } | {
288
+ kind: 'workingCapital';
289
+ accountId: string;
290
+ } | {
291
+ kind: 'directMovement';
292
+ accountId: string;
293
+ } | {
294
+ kind: 'fxEffect';
295
+ };
296
+ /**
297
+ * One column of a comparative CFS — also used for single-period reports
298
+ * (in which case `periods` has a single entry with key `'total'`).
299
+ */
300
+ type CashFlowPeriodColumn = PeriodColumn;
301
+ type CashFlowSection = ReportSection<CashFlowLineSource>;
302
+ /**
303
+ * Per-column reconciliation. `tieOutOk: false` means the algorithm has
304
+ * drifted from reality — fail-loud QA signal. Mirrors ERPNext's
305
+ * opening/closing balance reconciliation (cash_flow.py:282-308).
306
+ */
307
+ interface CashFlowColumnReconciliation {
308
+ openingCash: number;
309
+ closingCash: number;
310
+ /** `openingCash + netCashFlow` — what closingCash should be. */
311
+ calculated: number;
312
+ /** `true` when |closingCash − calculated| ≤ 1 cent. */
313
+ tieOutOk: boolean;
169
314
  }
170
315
  interface CashFlowReport {
171
316
  metadata: ReportMetadata & {
172
317
  periodStart: string;
173
318
  periodEnd: string;
174
- displayPeriod: string;
319
+ displayPeriod: string; /** Currency the report is denominated in. */
320
+ currency?: string; /** Comparative mode used to build the columns ('monthly' | 'quarterly' | null). */
321
+ comparative?: ComparativeMode;
175
322
  };
323
+ /** Column definitions in display order. Always at least one entry. */
324
+ periods: CashFlowPeriodColumn[];
325
+ /** Operating: Net Income + non-cash adjustments + ΔWorking Capital. */
176
326
  operating: CashFlowSection;
327
+ /** Investing: direct movements on fixed/non-current asset accounts. */
177
328
  investing: CashFlowSection;
329
+ /** Financing: direct movements on equity (excl. retained earnings) + non-current liabilities. */
178
330
  financing: CashFlowSection;
179
- netCashFlow: number;
331
+ /** FX cash effect (IAS 7 §28 / ASC 230) per column. Zero for single-currency hosts. */
332
+ fxEffect: Record<string, number>;
333
+ /** Net change in cash per column = operating + investing + financing + fxEffect. */
334
+ netCashFlow: Record<string, number>;
335
+ /** Per-column tie-out against actual cash account balance deltas. */
336
+ cashReconciliation: Record<string, CashFlowColumnReconciliation>;
337
+ }
338
+ //#endregion
339
+ //#region src/reports/aged-balance.d.ts
340
+ interface AgedBucketConfig {
341
+ label: string;
342
+ minDays: number;
343
+ maxDays: number;
344
+ }
345
+ declare const DEFAULT_BUCKETS: AgedBucketConfig[];
346
+ interface AgedBalanceOptions {
347
+ AccountModel: Model<unknown>;
348
+ JournalEntryModel: Model<unknown>;
349
+ country: CountryPack;
350
+ orgField?: string;
180
351
  }
352
+ interface AgedBalanceParams {
353
+ organizationId?: unknown;
354
+ asOfDate?: Date;
355
+ type: 'receivable' | 'payable';
356
+ accountIds?: unknown[];
357
+ dueDateField?: string;
358
+ contactField?: string;
359
+ buckets?: AgedBucketConfig[];
360
+ }
361
+ interface AgedBalanceRow {
362
+ accountId: unknown;
363
+ accountName: string;
364
+ accountCode: string;
365
+ contactId?: unknown;
366
+ total: number;
367
+ amounts: Record<string, number>;
368
+ }
369
+ interface AgedBalanceReport {
370
+ metadata: {
371
+ generatedAt: string;
372
+ asOfDate: string;
373
+ type: string;
374
+ };
375
+ periods: PeriodColumn[];
376
+ rows: AgedBalanceRow[];
377
+ totals: Record<string, number>;
378
+ grandTotal: number;
379
+ }
380
+ declare function generateAgedBalance(opts: AgedBalanceOptions, params: AgedBalanceParams): Promise<AgedBalanceReport>;
181
381
  //#endregion
182
382
  //#region src/reports/balance-sheet.d.ts
183
383
  interface BalanceSheetOptions {
@@ -201,6 +401,7 @@ declare function generateBalanceSheet(opts: BalanceSheetOptions, params: {
201
401
  organizationId?: unknown;
202
402
  dateOption: 'month' | 'quarter' | 'year' | 'custom';
203
403
  dateValue: unknown;
404
+ comparative?: 'monthly' | 'quarterly' | null;
204
405
  businessName?: string;
205
406
  filters?: Record<string, unknown>;
206
407
  }): Promise<BalanceSheetReport>;
@@ -255,9 +456,11 @@ interface CashFlowOptions {
255
456
  declare function generateCashFlow(opts: CashFlowOptions, params: {
256
457
  organizationId?: unknown;
257
458
  dateOption: 'month' | 'quarter' | 'year' | 'custom';
258
- dateValue: unknown;
459
+ dateValue: unknown; /** Expand the outer range into per-month or per-quarter columns + a YTD total. */
460
+ comparative?: 'monthly' | 'quarterly' | null;
259
461
  businessName?: string;
260
462
  filters?: Record<string, unknown>;
463
+ currency?: string;
261
464
  }): Promise<CashFlowReport>;
262
465
  //#endregion
263
466
  //#region src/reports/dimension-breakdown.d.ts
@@ -368,6 +571,7 @@ declare function generateIncomeStatement(opts: IncomeStatementOptions, params: {
368
571
  organizationId?: unknown;
369
572
  dateOption: 'month' | 'quarter' | 'year' | 'custom';
370
573
  dateValue: unknown;
574
+ comparative?: 'monthly' | 'quarterly' | null;
371
575
  businessName?: string;
372
576
  filters?: Record<string, unknown>;
373
577
  }): Promise<IncomeStatementReport>;
@@ -577,8 +781,9 @@ declare function generateTrialBalance(opts: TrialBalanceOptions, params: {
577
781
  dateOption: 'month' | 'quarter' | 'year' | 'custom';
578
782
  dateValue: unknown;
579
783
  accountId?: string;
784
+ comparative?: 'monthly' | 'quarterly' | null;
580
785
  businessName?: string;
581
786
  filters?: Record<string, unknown>;
582
787
  }): Promise<TrialBalanceReport>;
583
788
  //#endregion
584
- export { AgedBalanceParams as $, generateDimensionBreakdown as A, BalanceSheetReport as B, FiscalReopenResult as C, DimensionBreakdownParams as D, DimensionBreakdownOptions as E, BudgetVsActualReport as F, IncomeStatementReport as G, CashFlowSection as H, BudgetVsActualRow as I, ReportCategory as J, LedgerEntry as K, generateBudgetVsActual as L, generateCashFlow as M, BudgetVsActualOptions as N, DimensionBreakdownReport as O, BudgetVsActualParams as P, AgedBalanceOptions as Q, BalanceSheetOptions as R, FiscalCloseResult as S, reopenFiscalPeriod as T, GeneralLedgerAccount as U, CashFlowReport as V, GeneralLedgerReport as W, TrialBalanceReport as X, ReportGroup as Y, TrialBalanceRow as Z, IncomeStatementOptions as _, RevaluationReport as a, Logger as at, generateGeneralLedger as b, RevaluationRate as c, computeRevaluation as d, AgedBalanceReport as et, PartnerLedgerLine as f, generatePartnerLedger as g, PartnerLedgerReport as h, RevaluationParams as i, generateAgedBalance as it, CashFlowOptions as j, DimensionBreakdownRow as k, RevaluationResult as l, PartnerLedgerParams as m, generateTrialBalance as n, AgedBucketConfig as nt, generateRevaluation as o, defaultLogger as ot, PartnerLedgerOptions as p, ReportAccount as q, RevaluationOptions as r, DEFAULT_BUCKETS as rt, AccountForeignBalance as s, TrialBalanceOptions as t, AgedBalanceRow as tt, buildRevaluationEntry as u, generateIncomeStatement as v, closeFiscalPeriod as w, FiscalCloseOptions as x, GeneralLedgerOptions as y, generateBalanceSheet as z };
789
+ export { GeneralLedgerAccount as $, generateDimensionBreakdown as A, AgedBalanceOptions as B, FiscalReopenResult as C, DimensionBreakdownParams as D, DimensionBreakdownOptions as E, BudgetVsActualReport as F, DEFAULT_BUCKETS as G, AgedBalanceReport as H, BudgetVsActualRow as I, BalanceSheetReport as J, generateAgedBalance as K, generateBudgetVsActual as L, generateCashFlow as M, BudgetVsActualOptions as N, DimensionBreakdownReport as O, BudgetVsActualParams as P, ComparativeMode as Q, BalanceSheetOptions as R, FiscalCloseResult as S, reopenFiscalPeriod as T, AgedBalanceRow as U, AgedBalanceParams as V, AgedBucketConfig as W, CashFlowReport as X, BalanceSheetSection as Y, CashFlowSection as Z, IncomeStatementOptions as _, DaybookOptions as _t, RevaluationReport as a, PeriodColumn as at, generateGeneralLedger as b, generateDaybook as bt, RevaluationRate as c, ReportGroup as ct, computeRevaluation as d, TrialBalanceColumnRow as dt, GeneralLedgerReport as et, PartnerLedgerLine as f, TrialBalanceReport as ft, generatePartnerLedger as g, DaybookLine as gt, PartnerLedgerReport as h, defaultLogger as ht, RevaluationParams as i, LedgerEntry as it, CashFlowOptions as j, DimensionBreakdownRow as k, RevaluationResult as l, ReportLine as lt, PartnerLedgerParams as m, Logger as mt, generateTrialBalance as n, IncomeStatementReport as nt, generateRevaluation as o, ReportAccount as ot, PartnerLedgerOptions as p, TrialBalanceRow as pt, BalanceSheetLineSource as q, RevaluationOptions as r, IncomeStatementSection as rt, AccountForeignBalance as s, ReportCategory as st, TrialBalanceOptions as t, IncomeStatementLineSource as tt, buildRevaluationEntry as u, ReportSection as ut, generateIncomeStatement as v, DaybookParams as vt, closeFiscalPeriod as w, FiscalCloseOptions as x, GeneralLedgerOptions as y, DaybookReport as yt, generateBalanceSheet as z };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@classytic/ledger",
3
- "version": "0.10.2",
4
- "description": "Production-grade double-entry accounting engine for MongoDB schemas, reports, tax, multi-tenant",
3
+ "version": "0.11.0",
4
+ "description": "Production-grade double-entry accounting engine for MongoDB — schemas, reports, tax, multi-tenant",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "main": "./dist/index.mjs",
@@ -43,11 +43,6 @@
43
43
  "import": "./dist/exports/index.mjs",
44
44
  "default": "./dist/exports/index.mjs"
45
45
  },
46
- "./sync": {
47
- "types": "./dist/sync/index.d.mts",
48
- "import": "./dist/sync/index.mjs",
49
- "default": "./dist/sync/index.mjs"
50
- },
51
46
  "./events": {
52
47
  "types": "./dist/events/index.d.mts",
53
48
  "import": "./dist/events/index.mjs",
@@ -93,25 +88,18 @@
93
88
  "url": "git+https://github.com/classytic/ledger.git"
94
89
  },
95
90
  "peerDependencies": {
96
- "@classytic/fin-io": ">=0.1.0",
97
- "@classytic/mongokit": ">=3.11.0",
98
- "@classytic/primitives": ">=0.1.0",
99
- "@classytic/repo-core": ">=0.2.0",
91
+ "@classytic/mongokit": ">=3.13.0",
92
+ "@classytic/primitives": ">=0.5.0",
93
+ "@classytic/repo-core": ">=0.4.0",
100
94
  "mongoose": ">=9.4.1",
101
95
  "zod": ">=4.0.0"
102
96
  },
103
- "peerDependenciesMeta": {
104
- "@classytic/fin-io": {
105
- "optional": true
106
- }
107
- },
108
97
  "devDependencies": {
109
98
  "@biomejs/biome": "^2.4.12",
110
99
  "@classytic/dev-tools": "^0.2.0",
111
- "@classytic/fin-io": ">=0.1.0",
112
- "@classytic/mongokit": ">=3.11.0",
113
- "@classytic/primitives": ">=0.1.0",
114
- "@classytic/repo-core": ">=0.2.0",
100
+ "@classytic/mongokit": ">=3.13.0",
101
+ "@classytic/primitives": ">=0.5.0",
102
+ "@classytic/repo-core": ">=0.4.0",
115
103
  "@types/node": "^25.5.0",
116
104
  "@vitest/coverage-v8": "^4.1.4",
117
105
  "knip": "^6.4.1",
@@ -1,60 +0,0 @@
1
- //#region src/sync/builders/opening-balance.ts
2
- function buildOpeningBalanceEntry(input) {
3
- const { cutoverDate, balances, equityAccountCode } = input;
4
- const dateStr = cutoverDate.toISOString().split("T")[0];
5
- const label = input.label ?? `Opening Balance — Cutover ${dateStr}`;
6
- const items = [];
7
- let totalDebit = 0;
8
- let totalCredit = 0;
9
- for (const { accountCode, balance } of balances) {
10
- if (balance === 0) continue;
11
- if (balance > 0) {
12
- items.push({
13
- account: accountCode,
14
- debit: balance,
15
- credit: 0,
16
- label: "Opening balance"
17
- });
18
- totalDebit += balance;
19
- } else {
20
- const absBalance = Math.abs(balance);
21
- items.push({
22
- account: accountCode,
23
- debit: 0,
24
- credit: absBalance,
25
- label: "Opening balance"
26
- });
27
- totalCredit += absBalance;
28
- }
29
- }
30
- const residual = totalDebit - totalCredit;
31
- const lineCount = items.length;
32
- if (residual > 0) items.push({
33
- account: equityAccountCode,
34
- debit: 0,
35
- credit: residual,
36
- label: "Opening balance equity (contra)"
37
- });
38
- else if (residual < 0) items.push({
39
- account: equityAccountCode,
40
- debit: Math.abs(residual),
41
- credit: 0,
42
- label: "Opening balance equity (contra)"
43
- });
44
- return {
45
- entry: {
46
- date: cutoverDate,
47
- label,
48
- journalType: "GENERAL",
49
- journalItems: items,
50
- extra: {
51
- _externalId: `opening-balance:${dateStr}`,
52
- _importSource: "opening-balance"
53
- }
54
- },
55
- residual,
56
- lineCount
57
- };
58
- }
59
- //#endregion
60
- export { buildOpeningBalanceEntry as t };