@classytic/ledger 0.1.5 → 0.3.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 (70) hide show
  1. package/README.md +161 -64
  2. package/dist/{account.repository-Crf5DGO4.mjs → account.repository-BpkSd6q3.mjs} +190 -41
  3. package/dist/{categories-BNJBd4ze.mjs → categories-CclX7Q94.mjs} +0 -2
  4. package/dist/constants/index.d.mts +1 -1
  5. package/dist/constants/index.mjs +4 -5
  6. package/dist/{core-Cx0baosR.d.mts → core-8Xfnpn6g.d.mts} +1 -2
  7. package/dist/country/index.d.mts +2 -105
  8. package/dist/country/index.mjs +0 -2
  9. package/dist/{currencies-Bkn3FNkC.d.mts → currencies-4WAbFRlw.d.mts} +2 -3
  10. package/dist/{currencies-BBk3NwXn.mjs → currencies-W8kQAkm0.mjs} +0 -2
  11. package/dist/{idempotency.plugin-C6r8RI8d.mjs → date-lock.plugin-eYAJ9h_u.mjs} +50 -13
  12. package/dist/{engine-Cd73EOT6.d.mts → engine-Cn-9yerQ.d.mts} +38 -8
  13. package/dist/{errors-CeqRahE-.mjs → errors-B7yC-Jfw.mjs} +0 -2
  14. package/dist/exports/index.d.mts +2 -2
  15. package/dist/exports/index.mjs +2 -3
  16. package/dist/{universal-CMfrZ2hG.mjs → exports-I5Xkq-9_.mjs} +0 -7
  17. package/dist/{fiscal-close-DuXDgVvb.mjs → fiscal-close-B6LhQ10f.mjs} +742 -32
  18. package/dist/fiscal-period.schema-BMnlI9H5.d.mts +103 -0
  19. package/dist/{idempotency.plugin-BESs9YPD.d.mts → idempotency.plugin-B_CNsInz.d.mts} +19 -17
  20. package/dist/{universal-x33ZJODp.d.mts → index-BPukb3L8.d.mts} +1 -2
  21. package/dist/index-CxZqRaOU.d.mts +119 -0
  22. package/dist/index.d.mts +251 -29
  23. package/dist/index.mjs +124 -27
  24. package/dist/{journals-CI3Wb4EF.mjs → journals-oH-FK3g8.mjs} +0 -2
  25. package/dist/{logger-Cv6VVc4r.d.mts → logger-CbHWZl7v.d.mts} +1 -2
  26. package/dist/money.d.mts +1 -2
  27. package/dist/money.mjs +3 -3
  28. package/dist/plugins/index.d.mts +38 -2
  29. package/dist/plugins/index.mjs +57 -3
  30. package/dist/reconciliation.repository-CW4-8q90.d.mts +135 -0
  31. package/dist/{fiscal-period.schema-CbALaaKl.mjs → reconciliation.schema-BuetvZTd.mjs} +218 -30
  32. package/dist/reports/index.d.mts +2 -2
  33. package/dist/reports/index.mjs +2 -3
  34. package/dist/repositories/index.d.mts +2 -2
  35. package/dist/repositories/index.mjs +2 -3
  36. package/dist/revaluation-D9x0NE8w.d.mts +530 -0
  37. package/dist/schemas/index.d.mts +71 -2
  38. package/dist/schemas/index.mjs +2 -3
  39. package/dist/tenant-guard-Fm6AID_6.mjs +13 -0
  40. package/docs/reports.md +1 -1
  41. package/package.json +3 -3
  42. package/dist/account.repository-1C2sZvB2.d.mts +0 -29
  43. package/dist/account.repository-1C2sZvB2.d.mts.map +0 -1
  44. package/dist/account.repository-Crf5DGO4.mjs.map +0 -1
  45. package/dist/categories-BNJBd4ze.mjs.map +0 -1
  46. package/dist/core-Cx0baosR.d.mts.map +0 -1
  47. package/dist/country/index.d.mts.map +0 -1
  48. package/dist/country/index.mjs.map +0 -1
  49. package/dist/currencies-BBk3NwXn.mjs.map +0 -1
  50. package/dist/currencies-Bkn3FNkC.d.mts.map +0 -1
  51. package/dist/engine-Cd73EOT6.d.mts.map +0 -1
  52. package/dist/errors-CeqRahE-.mjs.map +0 -1
  53. package/dist/fiscal-close-CzUzpnMg.d.mts +0 -270
  54. package/dist/fiscal-close-CzUzpnMg.d.mts.map +0 -1
  55. package/dist/fiscal-close-DuXDgVvb.mjs.map +0 -1
  56. package/dist/fiscal-period.schema-CbALaaKl.mjs.map +0 -1
  57. package/dist/fiscal-period.schema-DI2scngu.d.mts +0 -38
  58. package/dist/fiscal-period.schema-DI2scngu.d.mts.map +0 -1
  59. package/dist/idempotency.plugin-BESs9YPD.d.mts.map +0 -1
  60. package/dist/idempotency.plugin-C6r8RI8d.mjs.map +0 -1
  61. package/dist/index.d.mts.map +0 -1
  62. package/dist/index.mjs.map +0 -1
  63. package/dist/journals-CI3Wb4EF.mjs.map +0 -1
  64. package/dist/logger-Cv6VVc4r.d.mts.map +0 -1
  65. package/dist/money.d.mts.map +0 -1
  66. package/dist/money.mjs.map +0 -1
  67. package/dist/session-Dh0s6zG4.mjs +0 -87
  68. package/dist/session-Dh0s6zG4.mjs.map +0 -1
  69. package/dist/universal-CMfrZ2hG.mjs.map +0 -1
  70. package/dist/universal-x33ZJODp.d.mts.map +0 -1
@@ -0,0 +1,530 @@
1
+ import { c as DateRange } from "./core-8Xfnpn6g.mjs";
2
+ import { t as CountryPack } from "./index-CxZqRaOU.mjs";
3
+ import { t as Logger } from "./logger-CbHWZl7v.mjs";
4
+ import { ClientSession, Model } from "mongoose";
5
+
6
+ //#region src/reports/budget-vs-actual.d.ts
7
+ interface BudgetVsActualOptions {
8
+ AccountModel: Model<unknown>;
9
+ JournalEntryModel: Model<unknown>;
10
+ BudgetModel: Model<unknown>;
11
+ country: CountryPack;
12
+ orgField?: string;
13
+ }
14
+ interface BudgetVsActualParams {
15
+ organizationId?: unknown;
16
+ dateOption: 'month' | 'quarter' | 'year' | 'custom';
17
+ dateValue: unknown;
18
+ accountIds?: unknown[];
19
+ filters?: Record<string, unknown>;
20
+ }
21
+ interface BudgetVsActualRow {
22
+ accountId: unknown;
23
+ accountName: string;
24
+ accountCode: string;
25
+ category: string;
26
+ budgetAmount: number;
27
+ actualAmount: number;
28
+ variance: number;
29
+ variancePercent: number;
30
+ }
31
+ interface BudgetVsActualReport {
32
+ metadata: {
33
+ generatedAt: string;
34
+ periodStart: string;
35
+ periodEnd: string;
36
+ };
37
+ rows: BudgetVsActualRow[];
38
+ summary: {
39
+ totalBudget: number;
40
+ totalActual: number;
41
+ totalVariance: number;
42
+ };
43
+ }
44
+ declare function generateBudgetVsActual(opts: BudgetVsActualOptions, params: BudgetVsActualParams): Promise<BudgetVsActualReport>;
45
+ //#endregion
46
+ //#region src/types/report.d.ts
47
+ interface ReportMetadata {
48
+ businessName?: string;
49
+ generatedAt: string;
50
+ }
51
+ interface ReportAccount {
52
+ id: unknown;
53
+ name: string;
54
+ code: string;
55
+ balance: number;
56
+ isTotal?: boolean;
57
+ isVirtualTotal?: boolean;
58
+ isCalculated?: boolean;
59
+ }
60
+ interface ReportGroup {
61
+ name: string;
62
+ total: number;
63
+ accounts: ReportAccount[];
64
+ }
65
+ interface ReportCategory {
66
+ name: string;
67
+ total: number;
68
+ groups: ReportGroup[];
69
+ }
70
+ interface TrialBalanceRow {
71
+ account: unknown;
72
+ initial: {
73
+ debit: number;
74
+ credit: number;
75
+ };
76
+ current: {
77
+ debit: number;
78
+ credit: number;
79
+ };
80
+ ending: {
81
+ debit: number;
82
+ credit: number;
83
+ };
84
+ }
85
+ interface TrialBalanceReport {
86
+ metadata?: ReportMetadata & {
87
+ periodStart: string;
88
+ periodEnd: string;
89
+ displayPeriod: string;
90
+ };
91
+ rows: TrialBalanceRow[];
92
+ period: DateRange;
93
+ }
94
+ interface BalanceSheetReport {
95
+ metadata: ReportMetadata & {
96
+ asOfDate: string;
97
+ displayDate: string;
98
+ };
99
+ assets: ReportCategory;
100
+ liabilities: ReportCategory;
101
+ equity: ReportCategory;
102
+ summary: {
103
+ totalAssets: number;
104
+ totalLiabilities: number;
105
+ totalEquity: number;
106
+ liabilitiesAndEquity: number;
107
+ difference: number;
108
+ isBalanced: boolean;
109
+ };
110
+ }
111
+ interface IncomeStatementReport {
112
+ metadata: ReportMetadata & {
113
+ periodStart: string;
114
+ periodEnd: string;
115
+ displayPeriod: string;
116
+ };
117
+ revenue: ReportCategory;
118
+ costOfSales: number;
119
+ grossProfit: number;
120
+ expenses: ReportCategory;
121
+ operatingIncome: number;
122
+ netIncome: number;
123
+ }
124
+ interface LedgerEntry {
125
+ date: Date;
126
+ referenceNumber: string;
127
+ label: string;
128
+ debit: number;
129
+ credit: number;
130
+ runningBalance: number;
131
+ }
132
+ interface GeneralLedgerAccount {
133
+ account: unknown;
134
+ openingBalance: number;
135
+ entries: LedgerEntry[];
136
+ closingBalance: number;
137
+ }
138
+ interface GeneralLedgerReport {
139
+ metadata?: ReportMetadata & {
140
+ periodStart: string;
141
+ periodEnd: string;
142
+ displayPeriod: string;
143
+ };
144
+ accounts: GeneralLedgerAccount[];
145
+ period: DateRange;
146
+ }
147
+ interface CashFlowSection {
148
+ total: number;
149
+ accounts: Array<{
150
+ name: string;
151
+ code: string;
152
+ amount: number;
153
+ }>;
154
+ }
155
+ interface CashFlowReport {
156
+ metadata: ReportMetadata & {
157
+ periodStart: string;
158
+ periodEnd: string;
159
+ displayPeriod: string;
160
+ };
161
+ operating: CashFlowSection;
162
+ investing: CashFlowSection;
163
+ financing: CashFlowSection;
164
+ netCashFlow: number;
165
+ }
166
+ interface TaxAccountBalance {
167
+ code: string;
168
+ name: string;
169
+ balance: number;
170
+ taxMetadata?: unknown;
171
+ }
172
+ interface TaxReturnSummary {
173
+ totalSales: number;
174
+ gstHstCollected: number;
175
+ inputTaxCredits: number;
176
+ netTax: number;
177
+ finalAmount: number;
178
+ isRefund: boolean;
179
+ refundAmount: number;
180
+ paymentAmount: number;
181
+ }
182
+ interface TaxReport {
183
+ period: {
184
+ startDate: string;
185
+ endDate: string;
186
+ province: string;
187
+ };
188
+ accountBalances: {
189
+ collected: Record<string, TaxAccountBalance>;
190
+ itc: Record<string, TaxAccountBalance>;
191
+ instalments: Record<string, TaxAccountBalance>;
192
+ };
193
+ craLines: Record<string | number, number>;
194
+ summary: TaxReturnSummary;
195
+ calculatedAt: string;
196
+ }
197
+ //#endregion
198
+ //#region src/reports/trial-balance.d.ts
199
+ interface TrialBalanceOptions {
200
+ AccountModel: Model<unknown>;
201
+ JournalEntryModel: Model<unknown>;
202
+ country: CountryPack;
203
+ orgField?: string;
204
+ fiscalYearStartMonth?: number;
205
+ }
206
+ declare function generateTrialBalance(opts: TrialBalanceOptions, params: {
207
+ organizationId?: unknown;
208
+ dateOption: 'month' | 'quarter' | 'year' | 'custom';
209
+ dateValue: unknown;
210
+ accountId?: string;
211
+ businessName?: string;
212
+ filters?: Record<string, unknown>;
213
+ }): Promise<TrialBalanceReport>;
214
+ //#endregion
215
+ //#region src/reports/balance-sheet.d.ts
216
+ interface BalanceSheetOptions {
217
+ AccountModel: Model<unknown>;
218
+ JournalEntryModel: Model<unknown>;
219
+ country: CountryPack;
220
+ orgField?: string;
221
+ fiscalYearStartMonth?: number;
222
+ /**
223
+ * The retained earnings account code (e.g. '3600' CA, '3310' BD).
224
+ * This account is excluded from normal equity grouping and its balance
225
+ * is folded into the computed Retained Earnings section.
226
+ */
227
+ retainedEarningsAccountCode?: string;
228
+ /** Display code for the "Previous Years Retained Earnings" line */
229
+ retainedEarningsDisplayCode?: string;
230
+ /** Display code for current year net income (default: '3680') */
231
+ currentYearEarningsCode?: string;
232
+ }
233
+ declare function generateBalanceSheet(opts: BalanceSheetOptions, params: {
234
+ organizationId?: unknown;
235
+ dateOption: 'month' | 'quarter' | 'year' | 'custom';
236
+ dateValue: unknown;
237
+ businessName?: string;
238
+ filters?: Record<string, unknown>;
239
+ }): Promise<BalanceSheetReport>;
240
+ //#endregion
241
+ //#region src/reports/income-statement.d.ts
242
+ interface IncomeStatementOptions {
243
+ AccountModel: Model<unknown>;
244
+ JournalEntryModel: Model<unknown>;
245
+ country: CountryPack;
246
+ orgField?: string;
247
+ }
248
+ declare function generateIncomeStatement(opts: IncomeStatementOptions, params: {
249
+ organizationId?: unknown;
250
+ dateOption: 'month' | 'quarter' | 'year' | 'custom';
251
+ dateValue: unknown;
252
+ businessName?: string;
253
+ filters?: Record<string, unknown>;
254
+ }): Promise<IncomeStatementReport>;
255
+ //#endregion
256
+ //#region src/reports/general-ledger.d.ts
257
+ interface GeneralLedgerOptions {
258
+ AccountModel: Model<unknown>;
259
+ JournalEntryModel: Model<unknown>;
260
+ country: CountryPack;
261
+ orgField?: string;
262
+ fiscalYearStartMonth?: number;
263
+ }
264
+ declare function generateGeneralLedger(opts: GeneralLedgerOptions, params: {
265
+ organizationId?: unknown;
266
+ dateOption: 'month' | 'quarter' | 'year' | 'custom';
267
+ dateValue: unknown;
268
+ accountId?: string;
269
+ businessName?: string;
270
+ filters?: Record<string, unknown>;
271
+ }): Promise<GeneralLedgerReport>;
272
+ //#endregion
273
+ //#region src/reports/cash-flow.d.ts
274
+ interface CashFlowOptions {
275
+ AccountModel: Model<unknown>;
276
+ JournalEntryModel: Model<unknown>;
277
+ country: CountryPack;
278
+ orgField?: string;
279
+ }
280
+ declare function generateCashFlow(opts: CashFlowOptions, params: {
281
+ organizationId?: unknown;
282
+ dateOption: 'month' | 'quarter' | 'year' | 'custom';
283
+ dateValue: unknown;
284
+ businessName?: string;
285
+ filters?: Record<string, unknown>;
286
+ }): Promise<CashFlowReport>;
287
+ //#endregion
288
+ //#region src/reports/fiscal-close.d.ts
289
+ interface FiscalCloseOptions {
290
+ AccountModel: Model<unknown>;
291
+ JournalEntryModel: Model<unknown>;
292
+ FiscalPeriodModel: Model<unknown>;
293
+ country: CountryPack;
294
+ orgField?: string;
295
+ /** The retained earnings account code — where year-end net income is transferred to */
296
+ retainedEarningsAccountCode?: string;
297
+ logger?: Logger;
298
+ }
299
+ interface FiscalCloseResult {
300
+ periodId: unknown;
301
+ netIncome: number;
302
+ closingEntryId: unknown | null;
303
+ accountsClosed: number;
304
+ closedAt: Date;
305
+ }
306
+ declare function closeFiscalPeriod(opts: FiscalCloseOptions, params: {
307
+ periodId: unknown;
308
+ organizationId?: unknown;
309
+ closedBy?: string;
310
+ session?: ClientSession;
311
+ }): Promise<FiscalCloseResult>;
312
+ interface FiscalReopenResult {
313
+ periodId: unknown;
314
+ deletedEntryId: unknown | null;
315
+ reopenedAt: Date;
316
+ }
317
+ declare function reopenFiscalPeriod(opts: Pick<FiscalCloseOptions, 'JournalEntryModel' | 'FiscalPeriodModel'> & {
318
+ orgField?: string;
319
+ logger?: Logger; /** Any model on the same connection — used to start sessions */
320
+ AccountModel?: Model<unknown>;
321
+ }, params: {
322
+ periodId: unknown;
323
+ organizationId?: unknown;
324
+ reopenedBy?: string;
325
+ session?: ClientSession;
326
+ }): Promise<FiscalReopenResult>;
327
+ //#endregion
328
+ //#region src/reports/dimension-breakdown.d.ts
329
+ interface DimensionBreakdownOptions {
330
+ AccountModel: Model<unknown>;
331
+ JournalEntryModel: Model<unknown>;
332
+ country: CountryPack;
333
+ orgField?: string;
334
+ }
335
+ interface DimensionBreakdownParams {
336
+ organizationId?: unknown;
337
+ dateOption: 'month' | 'quarter' | 'year' | 'custom';
338
+ dateValue: unknown;
339
+ /** Field on journalItems to group by, e.g. 'departmentId' */
340
+ dimension: string;
341
+ /** Filter accounts by category, e.g. 'Income Statement-Expense' */
342
+ accountCategory?: string;
343
+ /** Additional item-level filters */
344
+ filters?: Record<string, unknown>;
345
+ }
346
+ interface DimensionBreakdownRow {
347
+ dimensionValue: unknown;
348
+ accounts: Array<{
349
+ id: unknown;
350
+ name: string;
351
+ code: string;
352
+ balance: number;
353
+ }>;
354
+ total: number;
355
+ }
356
+ interface DimensionBreakdownReport {
357
+ metadata: {
358
+ generatedAt: string;
359
+ dimension: string;
360
+ periodStart: string;
361
+ periodEnd: string;
362
+ };
363
+ rows: DimensionBreakdownRow[];
364
+ grandTotal: number;
365
+ }
366
+ declare function generateDimensionBreakdown(opts: DimensionBreakdownOptions, params: DimensionBreakdownParams): Promise<DimensionBreakdownReport>;
367
+ //#endregion
368
+ //#region src/reports/aged-balance.d.ts
369
+ interface AgedBucketConfig {
370
+ label: string;
371
+ minDays: number;
372
+ maxDays: number;
373
+ }
374
+ declare const DEFAULT_BUCKETS: AgedBucketConfig[];
375
+ interface AgedBalanceOptions {
376
+ AccountModel: Model<unknown>;
377
+ JournalEntryModel: Model<unknown>;
378
+ country: CountryPack;
379
+ orgField?: string;
380
+ }
381
+ interface AgedBalanceParams {
382
+ organizationId?: unknown;
383
+ asOfDate?: Date;
384
+ type: 'receivable' | 'payable';
385
+ accountIds?: unknown[];
386
+ dueDateField?: string;
387
+ contactField?: string;
388
+ buckets?: AgedBucketConfig[];
389
+ }
390
+ interface AgedBalanceRow {
391
+ accountId: unknown;
392
+ accountName: string;
393
+ accountCode: string;
394
+ contactId?: unknown;
395
+ total: number;
396
+ buckets: Record<string, number>;
397
+ }
398
+ interface AgedBalanceReport {
399
+ metadata: {
400
+ generatedAt: string;
401
+ asOfDate: string;
402
+ type: string;
403
+ };
404
+ bucketLabels: string[];
405
+ rows: AgedBalanceRow[];
406
+ totals: Record<string, number>;
407
+ grandTotal: number;
408
+ }
409
+ declare function generateAgedBalance(opts: AgedBalanceOptions, params: AgedBalanceParams): Promise<AgedBalanceReport>;
410
+ //#endregion
411
+ //#region src/utils/revaluation.d.ts
412
+ /**
413
+ * Foreign Exchange Revaluation Utilities
414
+ *
415
+ * Pure functions for computing unrealized exchange gains/losses
416
+ * on foreign-currency-denominated balance sheet accounts.
417
+ *
418
+ * All monetary values are integer cents.
419
+ * Exchange rates are decimals (e.g., 1 USD = 1.37 CAD means rate = 1.37).
420
+ */
421
+ /** A new exchange rate for a foreign currency */
422
+ interface RevaluationRate {
423
+ /** ISO 4217 currency code */
424
+ currency: string;
425
+ /** New exchange rate: 1 foreign unit = rate base units (decimal, e.g. 1.37) */
426
+ rate: number;
427
+ }
428
+ /** An account's foreign-currency balance at historical rates */
429
+ interface AccountForeignBalance {
430
+ accountId: unknown;
431
+ accountName: string;
432
+ accountCode: string;
433
+ currency: string;
434
+ /** Integer cents in foreign currency */
435
+ foreignBalance: number;
436
+ /** Integer cents in base currency (at historical rates) */
437
+ baseBalance: number;
438
+ /** CategoryKey of the account */
439
+ category: string;
440
+ }
441
+ /** Result of revaluing a single account */
442
+ interface RevaluationResult {
443
+ accountId: unknown;
444
+ accountName: string;
445
+ accountCode: string;
446
+ currency: string;
447
+ foreignBalance: number;
448
+ /** Base currency amount at historical rates (integer cents) */
449
+ historicalBase: number;
450
+ /** Base currency amount at the new rate (integer cents) */
451
+ revaluedBase: number;
452
+ /** revaluedBase - historicalBase; positive = gain, negative = loss */
453
+ gainLoss: number;
454
+ }
455
+ /**
456
+ * Compute revaluation results for a set of accounts at new exchange rates.
457
+ *
458
+ * For each account, finds the matching rate by currency, computes the
459
+ * revalued base amount, and determines the gain/loss.
460
+ * Accounts with zero gain/loss are excluded from the results.
461
+ *
462
+ * @param accounts - Foreign-currency account balances at historical rates
463
+ * @param rates - New exchange rates to revalue against
464
+ * @param baseCurrency - The functional/base currency code (accounts in this currency are skipped)
465
+ */
466
+ declare function computeRevaluation(accounts: AccountForeignBalance[], rates: RevaluationRate[], baseCurrency: string): RevaluationResult[];
467
+ /**
468
+ * Build a balanced revaluation journal entry from revaluation results.
469
+ *
470
+ * For each result with a non-zero gain/loss:
471
+ * - Gain (positive gainLoss): Debit the account, Credit the unrealized gain/loss account
472
+ * - Loss (negative gainLoss): Credit the account, Debit the unrealized gain/loss account
473
+ *
474
+ * @param results - Revaluation results from computeRevaluation
475
+ * @param unrealizedGainLossAccountId - The account to book the offsetting entry against
476
+ * @param date - Date for the revaluation entry
477
+ */
478
+ declare function buildRevaluationEntry(results: RevaluationResult[], unrealizedGainLossAccountId: unknown, date: Date): {
479
+ journalItems: Array<{
480
+ account: unknown;
481
+ debit: number;
482
+ credit: number;
483
+ label: string;
484
+ originalDebit: number;
485
+ originalCredit: number;
486
+ }>;
487
+ totalDebit: number;
488
+ totalCredit: number;
489
+ label: string;
490
+ };
491
+ //#endregion
492
+ //#region src/reports/revaluation.d.ts
493
+ interface RevaluationOptions {
494
+ AccountModel: Model<unknown>;
495
+ JournalEntryModel: Model<unknown>;
496
+ country: CountryPack;
497
+ orgField?: string;
498
+ baseCurrency: string;
499
+ }
500
+ interface RevaluationParams {
501
+ organizationId?: unknown;
502
+ asOfDate: Date;
503
+ rates: RevaluationRate[];
504
+ unrealizedGainLossAccountId: unknown;
505
+ /** If true, create and save the revaluation journal entry */
506
+ generateEntry?: boolean;
507
+ }
508
+ interface RevaluationReport {
509
+ metadata: {
510
+ generatedAt: string;
511
+ asOfDate: string;
512
+ baseCurrency: string;
513
+ };
514
+ results: RevaluationResult[];
515
+ totalGainLoss: number;
516
+ /** Present only when generateEntry was true */
517
+ entryId?: unknown;
518
+ }
519
+ /**
520
+ * Generate a foreign exchange revaluation report.
521
+ *
522
+ * 1. Finds all accounts with a `currency` field (foreign-currency accounts)
523
+ * 2. Filters to balance sheet accounts only (not P&L)
524
+ * 3. Aggregates foreign-currency and base-currency balances from posted entries
525
+ * 4. Computes gain/loss at the new rates
526
+ * 5. Optionally creates and saves a balanced journal entry
527
+ */
528
+ declare function generateRevaluation(opts: RevaluationOptions, params: RevaluationParams): Promise<RevaluationReport>;
529
+ //#endregion
530
+ export { BudgetVsActualReport as $, generateGeneralLedger as A, GeneralLedgerAccount as B, FiscalCloseResult as C, CashFlowOptions as D, reopenFiscalPeriod as E, TrialBalanceOptions as F, ReportCategory as G, IncomeStatementReport as H, generateTrialBalance as I, TaxReturnSummary as J, ReportGroup as K, BalanceSheetReport as L, generateIncomeStatement as M, BalanceSheetOptions as N, generateCashFlow as O, generateBalanceSheet as P, BudgetVsActualParams as Q, CashFlowReport as R, FiscalCloseOptions as S, closeFiscalPeriod as T, LedgerEntry as U, GeneralLedgerReport as V, ReportAccount as W, TrialBalanceRow as X, TrialBalanceReport as Y, BudgetVsActualOptions as Z, DimensionBreakdownOptions as _, AccountForeignBalance as a, DimensionBreakdownRow as b, buildRevaluationEntry as c, AgedBalanceParams as d, BudgetVsActualRow as et, AgedBalanceReport as f, generateAgedBalance as g, DEFAULT_BUCKETS as h, generateRevaluation as i, IncomeStatementOptions as j, GeneralLedgerOptions as k, computeRevaluation as l, AgedBucketConfig as m, RevaluationParams as n, RevaluationRate as o, AgedBalanceRow as p, TaxReport as q, RevaluationReport as r, RevaluationResult as s, RevaluationOptions as t, generateBudgetVsActual as tt, AgedBalanceOptions as u, DimensionBreakdownParams as v, FiscalReopenResult as w, generateDimensionBreakdown as x, DimensionBreakdownReport as y, CashFlowSection as z };
@@ -1,2 +1,71 @@
1
- import { n as createJournalEntrySchema, r as createAccountSchema, t as createFiscalPeriodSchema } from "../fiscal-period.schema-DI2scngu.mjs";
2
- export { createAccountSchema, createFiscalPeriodSchema, createJournalEntrySchema };
1
+ import { o as SchemaOptions, t as AccountingEngineConfig } from "../engine-Cn-9yerQ.mjs";
2
+ import { n as createJournalEntrySchema, r as createAccountSchema, t as createFiscalPeriodSchema } from "../fiscal-period.schema-BMnlI9H5.mjs";
3
+ import mongoose from "mongoose";
4
+
5
+ //#region src/schemas/budget.schema.d.ts
6
+ declare function createBudgetSchema(config: AccountingEngineConfig, options?: SchemaOptions): mongoose.Schema<any, mongoose.Model<any, any, any, any, any, any, any>, {}, {}, {}, {}, {
7
+ timestamps: true;
8
+ }, {
9
+ [x: number]: any;
10
+ [x: string]: any;
11
+ } & mongoose.DefaultTimestampProps, mongoose.Document<unknown, {}, {
12
+ [x: number]: any;
13
+ [x: string]: any;
14
+ } & mongoose.DefaultTimestampProps, {
15
+ id: string;
16
+ }, mongoose.MergeType<mongoose.DefaultSchemaOptions, {
17
+ timestamps: true;
18
+ }>> & Omit<{
19
+ [x: number]: any;
20
+ [x: string]: any;
21
+ } & mongoose.DefaultTimestampProps & {
22
+ _id: mongoose.Types.ObjectId;
23
+ } & {
24
+ __v: number;
25
+ }, "id"> & {
26
+ id: string;
27
+ }, unknown, {
28
+ [x: number]: any;
29
+ [x: string]: any;
30
+ createdAt: NativeDate;
31
+ updatedAt: NativeDate;
32
+ } & {
33
+ _id: mongoose.Types.ObjectId;
34
+ } & {
35
+ __v: number;
36
+ }>;
37
+ //#endregion
38
+ //#region src/schemas/reconciliation.schema.d.ts
39
+ declare function createReconciliationSchema(config: AccountingEngineConfig, accountModelName: string, journalEntryModelName: string, options?: SchemaOptions): mongoose.Schema<any, mongoose.Model<any, any, any, any, any, any, any>, {}, {}, {}, {}, {
40
+ timestamps: true;
41
+ }, {
42
+ [x: number]: any;
43
+ [x: string]: any;
44
+ } & mongoose.DefaultTimestampProps, mongoose.Document<unknown, {}, {
45
+ [x: number]: any;
46
+ [x: string]: any;
47
+ } & mongoose.DefaultTimestampProps, {
48
+ id: string;
49
+ }, mongoose.MergeType<mongoose.DefaultSchemaOptions, {
50
+ timestamps: true;
51
+ }>> & Omit<{
52
+ [x: number]: any;
53
+ [x: string]: any;
54
+ } & mongoose.DefaultTimestampProps & {
55
+ _id: mongoose.Types.ObjectId;
56
+ } & {
57
+ __v: number;
58
+ }, "id"> & {
59
+ id: string;
60
+ }, unknown, {
61
+ [x: number]: any;
62
+ [x: string]: any;
63
+ createdAt: NativeDate;
64
+ updatedAt: NativeDate;
65
+ } & {
66
+ _id: mongoose.Types.ObjectId;
67
+ } & {
68
+ __v: number;
69
+ }>;
70
+ //#endregion
71
+ export { createAccountSchema, createBudgetSchema, createFiscalPeriodSchema, createJournalEntrySchema, createReconciliationSchema };
@@ -1,3 +1,2 @@
1
- import { n as createJournalEntrySchema, r as createAccountSchema, t as createFiscalPeriodSchema } from "../fiscal-period.schema-CbALaaKl.mjs";
2
-
3
- export { createAccountSchema, createFiscalPeriodSchema, createJournalEntrySchema };
1
+ import { a as createAccountSchema, i as createJournalEntrySchema, n as createBudgetSchema, r as createFiscalPeriodSchema, t as createReconciliationSchema } from "../reconciliation.schema-BuetvZTd.mjs";
2
+ export { createAccountSchema, createBudgetSchema, createFiscalPeriodSchema, createJournalEntrySchema, createReconciliationSchema };
@@ -0,0 +1,13 @@
1
+ import { n as Errors } from "./errors-B7yC-Jfw.mjs";
2
+ //#region src/utils/tenant-guard.ts
3
+ /**
4
+ * Multi-tenant scope guard.
5
+ *
6
+ * Throws when orgField is configured (multi-tenant mode active) but
7
+ * organizationId is missing — preventing unscoped cross-tenant queries.
8
+ */
9
+ function requireOrgScope(orgField, organizationId) {
10
+ if (orgField && !organizationId) throw Errors.validation("organizationId is required when multi-tenant mode is configured (orgField: \"" + orgField + "\"). Refusing to run unscoped query.");
11
+ }
12
+ //#endregion
13
+ export { requireOrgScope as t };
package/docs/reports.md CHANGED
@@ -120,7 +120,7 @@ const result = await closeFiscalPeriod(
120
120
  ```
121
121
 
122
122
  - Zeroes all income/expense account balances via a `YEAR_END` closing journal entry
123
- - Transfers net income to retained earnings (default code: `3660`, configurable via `retainedEarningsCode`)
123
+ - Transfers net income to retained earnings (configurable via `retainedEarningsAccountCode`)
124
124
  - Marks period as `closed: true`
125
125
  - Atomic by default (internal transaction)
126
126
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/ledger",
3
- "version": "0.1.5",
3
+ "version": "0.3.0",
4
4
  "description": "Production-grade double-entry accounting engine for MongoDB — schemas, reports, tax, multi-tenant",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -88,7 +88,7 @@
88
88
  "url": "git+https://github.com/classytic/accounting.git"
89
89
  },
90
90
  "peerDependencies": {
91
- "@classytic/mongokit": ">=3.3.2",
91
+ "@classytic/mongokit": ">=3.4.3",
92
92
  "mongoose": ">=9.0.0"
93
93
  },
94
94
  "engines": {
@@ -109,7 +109,7 @@
109
109
  "@vitest/coverage-v8": "^3.2.4",
110
110
  "mongodb-memory-server": "^10.2.3",
111
111
  "mongoose": "^9.3.1",
112
- "tsdown": "^0.20.3",
112
+ "tsdown": "^0.21.5",
113
113
  "typescript": "^5.7.0",
114
114
  "vitest": "^3.0.0"
115
115
  }
@@ -1,29 +0,0 @@
1
- import { CountryPack } from "./country/index.mjs";
2
- import { o as StrictnessConfig } from "./engine-Cd73EOT6.mjs";
3
- import { Model } from "mongoose";
4
-
5
- //#region src/repositories/journal-entry.repository.d.ts
6
- /**
7
- * Wire post/reverse onto an existing mongokit Repository.
8
- *
9
- * @param repository - A mongokit Repository instance (already created)
10
- * @param JournalEntryModel - The Mongoose model for journal entries
11
- * @param orgField - The multi-tenant field name (e.g. 'business')
12
- * @param strictness - Strictness rules (immutable, requireActor, requireApproval)
13
- */
14
- declare function wireJournalEntryMethods(repository: any, JournalEntryModel: Model<unknown>, orgField?: string, strictness?: StrictnessConfig): void;
15
- //#endregion
16
- //#region src/repositories/account.repository.d.ts
17
- /**
18
- * Wire seedAccounts, bulkCreate and posting-account validation
19
- * onto an existing mongokit Repository.
20
- *
21
- * @param repository - A mongokit Repository instance (already created)
22
- * @param AccountModel - The Mongoose model for accounts
23
- * @param country - The CountryPack for account type lookups
24
- * @param orgField - The multi-tenant field name (e.g. 'business')
25
- */
26
- declare function wireAccountMethods(repository: any, AccountModel: Model<unknown>, country: CountryPack, orgField?: string): void;
27
- //#endregion
28
- export { wireJournalEntryMethods as n, wireAccountMethods as t };
29
- //# sourceMappingURL=account.repository-1C2sZvB2.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"account.repository-1C2sZvB2.d.mts","names":[],"sources":["../src/repositories/journal-entry.repository.ts","../src/repositories/account.repository.ts"],"mappings":";;;;;;;;;;;;;iBAgEgB,uBAAA,CAEd,UAAA,OACA,iBAAA,EAAmB,KAAA,WACnB,QAAA,WACA,UAAA,GAAa,gBAAA;;;;;;;;;;;;iBC3CC,kBAAA,CAEd,UAAA,OACA,YAAA,EAAc,KAAA,WACd,OAAA,EAAS,WAAA,EACT,QAAA"}