@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
package/dist/index.mjs CHANGED
@@ -1,16 +1,15 @@
1
- import { n as createJournalEntrySchema, r as createAccountSchema, t as createFiscalPeriodSchema } from "./fiscal-period.schema-CbALaaKl.mjs";
2
- import { a as isValidJournalType, i as getJournalTypeCodes, n as JOURNAL_TYPES, t as JOURNAL_CODES } from "./journals-CI3Wb4EF.mjs";
3
- import { a as generateIncomeStatement, c as calculateTotal, d as generateTrialBalance, f as buildItemFilters, i as generateGeneralLedger, l as computeEndingBalance, m as getFiscalYearStart, n as reopenFiscalPeriod, o as generateBalanceSheet, p as getDateRange, r as generateCashFlow, s as buildAccountTypeMap, t as closeFiscalPeriod, u as isVirtualTaxAccount } from "./fiscal-close-DuXDgVvb.mjs";
4
- import { n as Errors, t as AccountingError } from "./errors-CeqRahE-.mjs";
5
- import { n as finalizeSession, r as defaultLogger, t as acquireSession } from "./session-Dh0s6zG4.mjs";
6
- import { c as getNormalBalance, d as isValidCategory, l as isBalanceSheet, n as CATEGORY_KEYS, t as CATEGORIES, u as isIncomeStatement } from "./categories-BNJBd4ze.mjs";
1
+ import { a as createAccountSchema, i as createJournalEntrySchema, n as createBudgetSchema, r as createFiscalPeriodSchema, t as createReconciliationSchema } from "./reconciliation.schema-BuetvZTd.mjs";
2
+ import { a as isValidJournalType, i as getJournalTypeCodes, n as JOURNAL_TYPES, t as JOURNAL_CODES } from "./journals-oH-FK3g8.mjs";
3
+ import { C as getDateRange, S as buildItemFilters, _ as buildAccountTypeMap, a as defaultLogger, b as isVirtualTaxAccount, c as computeRevaluation, d as DEFAULT_BUCKETS, f as generateAgedBalance, g as generateBalanceSheet, h as generateIncomeStatement, i as finalizeSession, l as generateBudgetVsActual, m as generateGeneralLedger, n as reopenFiscalPeriod, o as generateRevaluation, p as generateCashFlow, r as acquireSession, s as buildRevaluationEntry, t as closeFiscalPeriod, u as generateDimensionBreakdown, v as calculateTotal, w as getFiscalYearStart, x as generateTrialBalance, y as computeEndingBalance } from "./fiscal-close-B6LhQ10f.mjs";
4
+ import { n as Errors, t as AccountingError } from "./errors-B7yC-Jfw.mjs";
5
+ import { c as getNormalBalance, d as isValidCategory, l as isBalanceSheet, n as CATEGORY_KEYS, t as CATEGORIES, u as isIncomeStatement } from "./categories-CclX7Q94.mjs";
6
+ import { n as wireJournalEntryMethods, r as wireReconciliationMethods, t as wireAccountMethods } from "./account.repository-BpkSd6q3.mjs";
7
7
  import { Money, add, allocate, format, formatPlain, fromDecimal, multiply, parseCents, percentage, splitTaxExclusive, splitTaxInclusive, subtract, toDecimal } from "./money.mjs";
8
- import { n as wireJournalEntryMethods, t as wireAccountMethods } from "./account.repository-Crf5DGO4.mjs";
9
- import { n as fiscalLockPlugin, r as doubleEntryPlugin, t as idempotencyPlugin } from "./idempotency.plugin-C6r8RI8d.mjs";
10
- import { i as isValidCurrency, n as getCurrency, r as getMinorUnit, t as CURRENCIES } from "./currencies-BBk3NwXn.mjs";
8
+ import { i as doubleEntryPlugin, n as idempotencyPlugin, r as fiscalLockPlugin, t as dateLockPlugin } from "./date-lock.plugin-eYAJ9h_u.mjs";
9
+ import { i as isValidCurrency, n as getCurrency, r as getMinorUnit, t as CURRENCIES } from "./currencies-W8kQAkm0.mjs";
11
10
  import { defineCountryPack } from "./country/index.mjs";
12
- import { a as exportToCsv, n as quickbooksFieldMap, r as flattenJournalEntries, t as universalFieldMap } from "./universal-CMfrZ2hG.mjs";
13
-
11
+ import { a as exportToCsv, n as quickbooksFieldMap, r as flattenJournalEntries, t as universalFieldMap } from "./exports-I5Xkq-9_.mjs";
12
+ import { Schema } from "mongoose";
14
13
  //#region src/engine.ts
15
14
  var AccountingEngine = class {
16
15
  config;
@@ -31,12 +30,19 @@ var AccountingEngine = class {
31
30
  createFiscalPeriodSchema(options) {
32
31
  return createFiscalPeriodSchema(this.config, options);
33
32
  }
33
+ createBudgetSchema(options) {
34
+ return createBudgetSchema(this.config, options);
35
+ }
36
+ createReconciliationSchema(accountModelName, journalEntryModelName, options) {
37
+ return createReconciliationSchema(this.config, accountModelName, journalEntryModelName, options);
38
+ }
34
39
  createReports(models) {
35
- const { Account: AccountModel, JournalEntry: JournalEntryModel } = models;
40
+ const { Account: AccountModel, JournalEntry: JournalEntryModel, Budget: BudgetModel } = models;
36
41
  const { country, config } = this;
37
42
  const orgField = config.multiTenant?.orgField;
38
43
  const fiscalYearStartMonth = config.fiscalYearStartMonth ?? 1;
39
- const retainedEarningsCode = config.retainedEarningsCode;
44
+ const retainedEarningsAccountCode = config.retainedEarningsAccountCode;
45
+ const retainedEarningsDisplayCode = config.retainedEarningsDisplayCode;
40
46
  const currentYearEarningsCode = config.currentYearEarningsCode;
41
47
  return {
42
48
  trialBalance: (params) => generateTrialBalance({
@@ -52,7 +58,8 @@ var AccountingEngine = class {
52
58
  country,
53
59
  orgField,
54
60
  fiscalYearStartMonth,
55
- retainedEarningsCode,
61
+ retainedEarningsAccountCode,
62
+ retainedEarningsDisplayCode,
56
63
  currentYearEarningsCode
57
64
  }, params),
58
65
  incomeStatement: (params) => generateIncomeStatement({
@@ -73,6 +80,35 @@ var AccountingEngine = class {
73
80
  JournalEntryModel,
74
81
  country,
75
82
  orgField
83
+ }, params),
84
+ agedBalance: (params) => generateAgedBalance({
85
+ AccountModel,
86
+ JournalEntryModel,
87
+ country,
88
+ orgField
89
+ }, params),
90
+ dimensionBreakdown: (params) => generateDimensionBreakdown({
91
+ AccountModel,
92
+ JournalEntryModel,
93
+ country,
94
+ orgField
95
+ }, params),
96
+ budgetVsActual: (params) => {
97
+ if (!BudgetModel) throw new Error("Budget model required — pass Budget to createReports()");
98
+ return generateBudgetVsActual({
99
+ AccountModel,
100
+ JournalEntryModel,
101
+ BudgetModel,
102
+ country,
103
+ orgField
104
+ }, params);
105
+ },
106
+ revaluation: (params) => generateRevaluation({
107
+ AccountModel,
108
+ JournalEntryModel,
109
+ country,
110
+ orgField,
111
+ baseCurrency: this.currency
76
112
  }, params)
77
113
  };
78
114
  }
@@ -111,23 +147,22 @@ var AccountingEngine = class {
111
147
  createJournalEntryRepository(createRepository, models, additionalPlugins = []) {
112
148
  const orgField = this.config.multiTenant?.orgField;
113
149
  const { JournalEntryModel, AccountModel, FiscalPeriodModel } = models;
150
+ const jeModel = JournalEntryModel;
114
151
  const plugins = [...additionalPlugins, doubleEntryPlugin({
115
- JournalEntryModel,
152
+ JournalEntryModel: jeModel,
116
153
  AccountModel,
117
154
  orgField
118
155
  })];
119
156
  if (FiscalPeriodModel) plugins.push(fiscalLockPlugin({
120
157
  FiscalPeriodModel,
121
- JournalEntryModel,
158
+ JournalEntryModel: jeModel,
122
159
  orgField
123
160
  }));
124
161
  if (this.config.idempotency) plugins.push(idempotencyPlugin({
125
- JournalEntryModel,
162
+ JournalEntryModel: jeModel,
126
163
  orgField
127
164
  }));
128
- const repository = createRepository(JournalEntryModel, plugins);
129
- wireJournalEntryMethods(repository, JournalEntryModel, orgField, this.config.strictness);
130
- return repository;
165
+ return wireJournalEntryMethods(createRepository(JournalEntryModel, plugins), JournalEntryModel, orgField, this.config.strictness);
131
166
  }
132
167
  /**
133
168
  * Wire post/reverse domain methods onto a mongokit Repository
@@ -144,8 +179,7 @@ var AccountingEngine = class {
144
179
  */
145
180
  wireJournalEntryRepository(repository, JournalEntryModel) {
146
181
  const orgField = this.config.multiTenant?.orgField;
147
- wireJournalEntryMethods(repository, JournalEntryModel, orgField, this.config.strictness);
148
- return repository;
182
+ return wireJournalEntryMethods(repository, JournalEntryModel, orgField, this.config.strictness);
149
183
  }
150
184
  /**
151
185
  * Wire seedAccounts/bulkCreate and posting-account validation onto a
@@ -158,14 +192,77 @@ var AccountingEngine = class {
158
192
  */
159
193
  wireAccountRepository(repository, AccountModel) {
160
194
  const orgField = this.config.multiTenant?.orgField;
161
- wireAccountMethods(repository, AccountModel, this.country, orgField);
162
- return repository;
195
+ return wireAccountMethods(repository, AccountModel, this.country, orgField);
196
+ }
197
+ /**
198
+ * Wire reconcile/unreconcile/getUnreconciled methods onto a mongokit Repository.
199
+ */
200
+ wireReconciliationRepository(repository, ReconciliationModel, JournalEntryModel) {
201
+ const orgField = this.config.multiTenant?.orgField;
202
+ return wireReconciliationMethods(repository, ReconciliationModel, JournalEntryModel, orgField);
163
203
  }
164
204
  };
165
205
  function createAccountingEngine(config) {
166
206
  return new AccountingEngine(config);
167
207
  }
168
-
169
208
  //#endregion
170
- export { AccountingEngine, AccountingError, CATEGORIES, CATEGORY_KEYS, CURRENCIES, Errors, JOURNAL_CODES, JOURNAL_TYPES, Money, acquireSession, add, allocate, buildAccountTypeMap, buildItemFilters, calculateTotal, closeFiscalPeriod, computeEndingBalance, createAccountSchema, createAccountingEngine, createFiscalPeriodSchema, createJournalEntrySchema, defaultLogger, defineCountryPack, doubleEntryPlugin, exportToCsv, finalizeSession, fiscalLockPlugin, flattenJournalEntries, format, formatPlain, fromDecimal, generateBalanceSheet, generateCashFlow, generateGeneralLedger, generateIncomeStatement, generateTrialBalance, getCurrency, getDateRange, getFiscalYearStart, getJournalTypeCodes, getMinorUnit, getNormalBalance, idempotencyPlugin, isBalanceSheet, isIncomeStatement, isValidCategory, isValidCurrency, isValidJournalType, isVirtualTaxAccount, multiply, parseCents, percentage, quickbooksFieldMap, reopenFiscalPeriod, splitTaxExclusive, splitTaxInclusive, subtract, toDecimal, universalFieldMap, wireAccountMethods, wireJournalEntryMethods };
171
- //# sourceMappingURL=index.mjs.map
209
+ //#region src/utils/dimensions.ts
210
+ /**
211
+ * Analytic Dimensions — Helpers for defining analytic dimensions
212
+ * (department, project, cost center) on journal items.
213
+ *
214
+ * Generates Mongoose schema fields and indexes for dimension queries.
215
+ */
216
+ /**
217
+ * Build extraItemFields schema definition for a set of dimensions.
218
+ *
219
+ * Returns a Mongoose schema-compatible object suitable for spreading into
220
+ * `extraItemFields` in JournalSchemaOptions.
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * const fields = buildDimensionFields([
225
+ * { field: 'departmentId', label: 'Department', ref: 'Department' },
226
+ * { field: 'projectId', label: 'Project', ref: 'Project' },
227
+ * ]);
228
+ * // => { departmentId: { type: Schema.Types.ObjectId, ref: 'Department', required: false, default: null }, ... }
229
+ * ```
230
+ */
231
+ function buildDimensionFields(dimensions) {
232
+ const fields = {};
233
+ for (const dim of dimensions) {
234
+ const fieldDef = {
235
+ type: Schema.Types.ObjectId,
236
+ required: dim.required ?? false,
237
+ default: null
238
+ };
239
+ if (dim.ref) fieldDef.ref = dim.ref;
240
+ fields[dim.field] = fieldDef;
241
+ }
242
+ return fields;
243
+ }
244
+ /**
245
+ * Build extra indexes for dimension queries.
246
+ *
247
+ * Each dimension gets a compound index on `journalItems.{field}` + `date`
248
+ * for efficient filtered reporting. When `orgField` is provided, it is
249
+ * prepended to each index for multi-tenant scoping.
250
+ *
251
+ * @param dimensions - Array of dimension definitions
252
+ * @param orgField - Optional org-scoping field name (e.g. 'business')
253
+ * @returns Array of index specifications compatible with `extraIndexes` in JournalSchemaOptions
254
+ */
255
+ function buildDimensionIndexes(dimensions, orgField) {
256
+ return dimensions.map((dim) => {
257
+ const fields = {};
258
+ if (orgField) fields[orgField] = 1;
259
+ fields[`journalItems.${dim.field}`] = 1;
260
+ fields.date = -1;
261
+ return {
262
+ fields,
263
+ options: {}
264
+ };
265
+ });
266
+ }
267
+ //#endregion
268
+ export { AccountingEngine, AccountingError, CATEGORIES, CATEGORY_KEYS, CURRENCIES, DEFAULT_BUCKETS, Errors, JOURNAL_CODES, JOURNAL_TYPES, Money, acquireSession, add, allocate, buildAccountTypeMap, buildDimensionFields, buildDimensionIndexes, buildItemFilters, buildRevaluationEntry, calculateTotal, closeFiscalPeriod, computeEndingBalance, computeRevaluation, createAccountSchema, createAccountingEngine, createFiscalPeriodSchema, createJournalEntrySchema, dateLockPlugin, defaultLogger, defineCountryPack, doubleEntryPlugin, exportToCsv, finalizeSession, fiscalLockPlugin, flattenJournalEntries, format, formatPlain, fromDecimal, generateAgedBalance, generateBalanceSheet, generateCashFlow, generateDimensionBreakdown, generateGeneralLedger, generateIncomeStatement, generateRevaluation, generateTrialBalance, getCurrency, getDateRange, getFiscalYearStart, getJournalTypeCodes, getMinorUnit, getNormalBalance, idempotencyPlugin, isBalanceSheet, isIncomeStatement, isValidCategory, isValidCurrency, isValidJournalType, isVirtualTaxAccount, multiply, parseCents, percentage, quickbooksFieldMap, reopenFiscalPeriod, splitTaxExclusive, splitTaxInclusive, subtract, toDecimal, universalFieldMap, wireAccountMethods, wireJournalEntryMethods, wireReconciliationMethods };
@@ -86,7 +86,5 @@ function isValidJournalType(code) {
86
86
  function getJournalType(code) {
87
87
  return JOURNAL_TYPES[code] ?? null;
88
88
  }
89
-
90
89
  //#endregion
91
90
  export { isValidJournalType as a, getJournalTypeCodes as i, JOURNAL_TYPES as n, getJournalType as r, JOURNAL_CODES as t };
92
- //# sourceMappingURL=journals-CI3Wb4EF.mjs.map
@@ -11,5 +11,4 @@ interface Logger {
11
11
  /** Default console-based implementation */
12
12
  declare const defaultLogger: Logger;
13
13
  //#endregion
14
- export { defaultLogger as n, Logger as t };
15
- //# sourceMappingURL=logger-Cv6VVc4r.d.mts.map
14
+ export { defaultLogger as n, Logger as t };
package/dist/money.d.mts CHANGED
@@ -125,5 +125,4 @@ declare const Money: {
125
125
  readonly parseCents: typeof parseCents;
126
126
  };
127
127
  //#endregion
128
- export { Money, abs, add, allocate, equals, format, formatPlain, fromDecimal, isNegative, isPositive, isValid, isZero, max, min, multiply, negate, parseCents, percentage, round, splitTaxExclusive, splitTaxInclusive, subtract, toDecimal };
129
- //# sourceMappingURL=money.d.mts.map
128
+ export { Money, abs, add, allocate, equals, format, formatPlain, fromDecimal, isNegative, isPositive, isValid, isZero, max, min, multiply, negate, parseCents, percentage, round, splitTaxExclusive, splitTaxInclusive, subtract, toDecimal };
package/dist/money.mjs CHANGED
@@ -30,7 +30,9 @@ function round(amount) {
30
30
  /** Convert a decimal dollar amount to integer cents: 10.50 → 1050 */
31
31
  function fromDecimal(dollars, minorUnit = 2) {
32
32
  const factor = 10 ** minorUnit;
33
- return Math.round(dollars * factor);
33
+ const cents = Math.round(dollars * factor);
34
+ if (!Number.isSafeInteger(cents)) throw new Error(`Amount ${dollars} exceeds safe integer limit when converted to minor units. Max safe amount: ${Number.MAX_SAFE_INTEGER / factor}`);
35
+ return cents;
34
36
  }
35
37
  /** Convert integer cents to a decimal dollar amount: 1050 → 10.50 */
36
38
  function toDecimal(cents, minorUnit = 2) {
@@ -191,7 +193,5 @@ const Money = {
191
193
  isValid,
192
194
  parseCents
193
195
  };
194
-
195
196
  //#endregion
196
197
  export { Money, abs, add, allocate, equals, format, formatPlain, fromDecimal, isNegative, isPositive, isValid, isZero, max, min, multiply, negate, parseCents, percentage, round, splitTaxExclusive, splitTaxInclusive, subtract, toDecimal };
197
- //# sourceMappingURL=money.mjs.map
@@ -1,2 +1,38 @@
1
- import { a as DoubleEntryPluginOptions, i as fiscalLockPlugin, n as idempotencyPlugin, o as doubleEntryPlugin, r as FiscalLockPluginOptions, t as IdempotencyPluginOptions } from "../idempotency.plugin-BESs9YPD.mjs";
2
- export { type DoubleEntryPluginOptions, type FiscalLockPluginOptions, type IdempotencyPluginOptions, doubleEntryPlugin, fiscalLockPlugin, idempotencyPlugin };
1
+ import { a as DoubleEntryPluginOptions, c as dateLockPlugin, i as fiscalLockPlugin, n as idempotencyPlugin, o as doubleEntryPlugin, r as FiscalLockPluginOptions, s as DateLockPluginOptions, t as IdempotencyPluginOptions } from "../idempotency.plugin-B_CNsInz.mjs";
2
+ import { RepositoryInstance } from "@classytic/mongokit";
3
+
4
+ //#region src/utils/tax-hooks.d.ts
5
+ interface TaxLineInput {
6
+ account: unknown;
7
+ amount: number;
8
+ side: 'debit' | 'credit';
9
+ taxCode?: string;
10
+ extraFields?: Record<string, unknown>;
11
+ }
12
+ interface GeneratedTaxLine {
13
+ account: unknown;
14
+ debit: number;
15
+ credit: number;
16
+ label?: string;
17
+ taxDetails?: Array<{
18
+ taxCode: string;
19
+ taxName?: string;
20
+ }>;
21
+ }
22
+ interface TaxLineGenerator {
23
+ generateTaxLines(input: TaxLineInput): GeneratedTaxLine[];
24
+ }
25
+ //#endregion
26
+ //#region src/plugins/tax-hook.plugin.d.ts
27
+ interface TaxHookPluginOptions {
28
+ /** Tax line generator — implements the tax calculation logic */
29
+ generator: TaxLineGenerator;
30
+ /** Only apply tax hooks on posted entries (default: true) */
31
+ onlyOnPost?: boolean;
32
+ }
33
+ declare function taxHookPlugin(options: TaxHookPluginOptions): {
34
+ name: string;
35
+ apply(repo: RepositoryInstance): void;
36
+ };
37
+ //#endregion
38
+ export { type DateLockPluginOptions, type DoubleEntryPluginOptions, type FiscalLockPluginOptions, type IdempotencyPluginOptions, type TaxHookPluginOptions, dateLockPlugin, doubleEntryPlugin, fiscalLockPlugin, idempotencyPlugin, taxHookPlugin };
@@ -1,3 +1,57 @@
1
- import { n as fiscalLockPlugin, r as doubleEntryPlugin, t as idempotencyPlugin } from "../idempotency.plugin-C6r8RI8d.mjs";
2
-
3
- export { doubleEntryPlugin, fiscalLockPlugin, idempotencyPlugin };
1
+ import { i as doubleEntryPlugin, n as idempotencyPlugin, r as fiscalLockPlugin, t as dateLockPlugin } from "../date-lock.plugin-eYAJ9h_u.mjs";
2
+ //#region src/utils/tax-hooks.ts
3
+ /**
4
+ * Apply a tax hook to journal items.
5
+ *
6
+ * Iterates each item that has a taxCode in taxDetails, calls
7
+ * `generator.generateTaxLines` for each, and appends the generated
8
+ * tax lines as new journal items.
9
+ *
10
+ * @returns The original items + generated tax items
11
+ */
12
+ function applyTaxHook(items, generator) {
13
+ const taxLines = [];
14
+ for (const item of items) {
15
+ const taxDetails = item.taxDetails;
16
+ if (!taxDetails || taxDetails.length === 0) continue;
17
+ const taxCode = taxDetails.find((td) => td.taxCode != null)?.taxCode;
18
+ if (!taxCode) continue;
19
+ const side = item.debit > 0 ? "debit" : "credit";
20
+ const amount = item.debit > 0 ? item.debit : item.credit;
21
+ const input = {
22
+ account: item.account,
23
+ amount,
24
+ side,
25
+ taxCode
26
+ };
27
+ const generated = generator.generateTaxLines(input);
28
+ for (const line of generated) taxLines.push({
29
+ account: line.account,
30
+ debit: line.debit,
31
+ credit: line.credit,
32
+ label: line.label,
33
+ taxDetails: line.taxDetails
34
+ });
35
+ }
36
+ return [...items, ...taxLines];
37
+ }
38
+ //#endregion
39
+ //#region src/plugins/tax-hook.plugin.ts
40
+ function taxHookPlugin(options) {
41
+ const { generator, onlyOnPost = true } = options;
42
+ return {
43
+ name: "accounting:tax-hook",
44
+ apply(repo) {
45
+ repo.on("before:create", (context) => {
46
+ const data = context.data;
47
+ if (!data) return;
48
+ if (onlyOnPost && data.state !== "posted") return;
49
+ const items = data.journalItems;
50
+ if (!items || items.length === 0) return;
51
+ data.journalItems = applyTaxHook(items, generator);
52
+ });
53
+ }
54
+ };
55
+ }
56
+ //#endregion
57
+ export { dateLockPlugin, doubleEntryPlugin, fiscalLockPlugin, idempotencyPlugin, taxHookPlugin };
@@ -0,0 +1,135 @@
1
+ import { t as CountryPack } from "./index-CxZqRaOU.mjs";
2
+ import { s as StrictnessConfig } from "./engine-Cn-9yerQ.mjs";
3
+ import { ClientSession, Model } from "mongoose";
4
+ import { Repository } from "@classytic/mongokit";
5
+
6
+ //#region src/types/repositories.d.ts
7
+ interface PostOptions {
8
+ session?: ClientSession | null;
9
+ /** Actor performing this operation (required when strictness.requireActor is enabled) */
10
+ actorId?: unknown;
11
+ }
12
+ interface ReverseOptions extends PostOptions {
13
+ /** Date for the reversal entry (defaults to now) */
14
+ reversalDate?: Date;
15
+ }
16
+ interface SeedOptions {
17
+ session?: ClientSession | null;
18
+ }
19
+ interface SeedResult {
20
+ created: number;
21
+ skipped: number;
22
+ }
23
+ interface BulkCreateInput {
24
+ accountTypeCode?: string;
25
+ accountNumber?: string;
26
+ name?: string;
27
+ active?: boolean;
28
+ isCashAccount?: boolean;
29
+ }
30
+ interface BulkCreateResult {
31
+ summary: {
32
+ total: number;
33
+ created: number;
34
+ skipped: number;
35
+ errors: number;
36
+ };
37
+ created: Array<Record<string, unknown>>;
38
+ skipped: Array<Record<string, unknown>>;
39
+ errors: Array<Record<string, unknown>>;
40
+ }
41
+ interface ReverseResult {
42
+ original: Record<string, unknown>;
43
+ reversal: Record<string, unknown>;
44
+ }
45
+ interface ReconcileParams {
46
+ accountId: unknown;
47
+ journalEntryIds: unknown[];
48
+ organizationId?: unknown;
49
+ note?: string;
50
+ session?: ClientSession;
51
+ }
52
+ /**
53
+ * Journal Entry Repository — extends mongokit Repository with accounting domain methods.
54
+ *
55
+ * Inherits ALL Repository<TDoc> methods: create, getById, getAll, update,
56
+ * delete, count, exists, distinct, aggregate, withTransaction, etc.
57
+ */
58
+ interface JournalEntryRepository<TDoc = unknown> extends Repository<TDoc> {
59
+ /** Post an entry (draft → posted). Validates items, balance, and accounts. */
60
+ post(id: unknown, orgId?: unknown, options?: PostOptions): Promise<Record<string, unknown>>;
61
+ /** Unpost an entry (posted → draft). Resets state for re-editing. */
62
+ unpost(id: unknown, orgId?: unknown, options?: PostOptions): Promise<Record<string, unknown>>;
63
+ /** Archive a draft entry (draft → archived). Preserves audit trail. */
64
+ archive(id: unknown, orgId?: unknown, options?: PostOptions): Promise<Record<string, unknown>>;
65
+ /** Duplicate an entry as a new draft. Copies items, type, and label. */
66
+ duplicate(id: unknown, orgId?: unknown, options?: PostOptions): Promise<Record<string, unknown>>;
67
+ /** Reverse a posted entry. Creates mirror entry with flipped debits/credits. */
68
+ reverse(id: unknown, orgId?: unknown, options?: ReverseOptions): Promise<ReverseResult>;
69
+ }
70
+ /**
71
+ * Account Repository — extends mongokit Repository with seed and bulk operations.
72
+ */
73
+ interface AccountRepository<TDoc = unknown> extends Repository<TDoc> {
74
+ /** Seed standard posting accounts for an org from the country pack. */
75
+ seedAccounts(orgId: unknown, options?: SeedOptions): Promise<SeedResult>;
76
+ /** Bulk create accounts with validation and skip-if-exists logic. */
77
+ bulkCreate(accounts: BulkCreateInput[], orgId: unknown): Promise<BulkCreateResult>;
78
+ }
79
+ /**
80
+ * Reconciliation Repository — extends mongokit Repository with bank reconciliation methods.
81
+ */
82
+ interface ReconciliationRepository<TDoc = unknown> extends Repository<TDoc> {
83
+ /** Reconcile journal entries for a specific account. */
84
+ reconcile(params: ReconcileParams): Promise<Record<string, unknown>>;
85
+ /** Remove a reconciliation record. */
86
+ unreconcile(params: {
87
+ reconciliationId: unknown;
88
+ organizationId?: unknown;
89
+ }): Promise<{
90
+ success: boolean;
91
+ }>;
92
+ /** Get unreconciled journal entries for an account. */
93
+ getUnreconciled(params: {
94
+ accountId: unknown;
95
+ organizationId?: unknown;
96
+ }): Promise<Record<string, unknown>[]>;
97
+ }
98
+ //#endregion
99
+ //#region src/repositories/journal-entry.repository.d.ts
100
+ /**
101
+ * Wire post/reverse onto an existing mongokit Repository.
102
+ *
103
+ * All reads use `repository.getByQuery()` so registered plugins
104
+ * (multi-tenant, audit, cache) fire on every operation.
105
+ *
106
+ * @param repository - A mongokit Repository instance (already created)
107
+ * @param _JournalEntryModel - (Deprecated) The Mongoose model — no longer used internally; kept for API compat
108
+ * @param orgField - The multi-tenant field name (e.g. 'business')
109
+ * @param strictness - Strictness rules (immutable, requireActor, requireApproval)
110
+ */
111
+ declare function wireJournalEntryMethods<TDoc = unknown>(repository: Repository<TDoc>, _JournalEntryModel: unknown, orgField?: string, strictness?: StrictnessConfig): JournalEntryRepository<TDoc>;
112
+ //#endregion
113
+ //#region src/repositories/account.repository.d.ts
114
+ /**
115
+ * Wire seedAccounts, bulkCreate and posting-account validation
116
+ * onto an existing mongokit Repository.
117
+ *
118
+ * @param repository - A mongokit Repository instance (already created)
119
+ * @param AccountModel - The Mongoose model for accounts
120
+ * @param country - The CountryPack for account type lookups
121
+ * @param orgField - The multi-tenant field name (e.g. 'business')
122
+ */
123
+ declare function wireAccountMethods<TDoc = unknown>(repository: Repository<TDoc>, AccountModel: Model<unknown>, country: CountryPack, orgField?: string): AccountRepository<TDoc>;
124
+ //#endregion
125
+ //#region src/repositories/reconciliation.repository.d.ts
126
+ /**
127
+ * Wire reconciliation methods onto an existing mongokit Repository.
128
+ *
129
+ * - reconcile() uses repository.create() so hooks (multi-tenant, audit) fire
130
+ * - unreconcile() uses repository.delete() so hooks fire
131
+ * - Cross-repo reads (JournalEntryModel) use direct Model access (acceptable)
132
+ */
133
+ declare function wireReconciliationMethods<TDoc = unknown>(repository: Repository<TDoc>, _ReconciliationModel: Model<unknown>, JournalEntryModel: Model<unknown>, orgField?: string): ReconciliationRepository<TDoc>;
134
+ //#endregion
135
+ export { BulkCreateInput as a, PostOptions as c, ReverseOptions as d, ReverseResult as f, AccountRepository as i, ReconcileParams as l, SeedResult as m, wireAccountMethods as n, BulkCreateResult as o, SeedOptions as p, wireJournalEntryMethods as r, JournalEntryRepository as s, wireReconciliationMethods as t, ReconciliationRepository as u };