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