@classytic/ledger 0.7.0 → 0.8.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 +221 -115
- package/dist/constants/index.d.mts +1 -1
- package/dist/country/index.d.mts +1 -1
- package/dist/exports/index.d.mts +1 -1
- package/dist/exports/index.mjs +1 -1
- package/dist/{fx-realization.plugin-CfYy1tB6.mjs → fx-realization.plugin-DDVK-oYO.mjs} +43 -0
- package/dist/{index-Bl0_ak5w.d.mts → index-BSsvrf3m.d.mts} +1 -1
- package/dist/{index-BX8miYdu.d.mts → index-RNZsX0Yo.d.mts} +12 -1
- package/dist/index.d.mts +125 -8
- package/dist/index.mjs +161 -18
- package/dist/{journals-C50E9mpo.d.mts → journals-Dd4A9TN3.d.mts} +1 -1
- package/dist/opening-balance-DPXmAIzN.mjs +60 -0
- package/dist/plugins/index.d.mts +1 -1
- package/dist/plugins/index.mjs +1 -1
- package/dist/reports/index.d.mts +1 -1
- package/dist/sync/index.d.mts +313 -0
- package/dist/sync/index.mjs +527 -0
- package/dist/sync-CnuVf441.d.mts +152 -0
- package/dist/{trial-balance-DTc8kzTD.d.mts → trial-balance-DTj-c21f.d.mts} +2 -2
- package/docs/country-packs.md +71 -47
- package/docs/engine.md +3 -2
- package/docs/subledger-integration.md +29 -8
- package/docs/sync.md +330 -0
- package/package.json +26 -14
- /package/dist/{core-BkGjuVZj.d.mts → core-MpgjCqK0.d.mts} +0 -0
- /package/dist/{exports-BP-0Ni5W.mjs → exports-B3whucXe.mjs} +0 -0
- /package/dist/{index-D1ZjgVxn.d.mts → index-bCEeSzdO.d.mts} +0 -0
package/dist/index.d.mts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { _ as TaxMetadata, a as Cents, c as DateRange, d as JournalType, f as MainType, g as TaxDetail, h as StatementType, i as CategoryKey, l as EntryState, m as ObjectId, n as CashFlowCategory, o as Currency, p as NormalBalance, s as DateOption, t as AccountType, u as JournalItem, v as TotalAccountOp } from "./core-
|
|
2
|
-
import { S as isValidCategory, a as getJournalTypeCodes, b as isBalanceSheet, c as CURRENCIES, d as isValidCurrency, f as CATEGORIES, i as getJournalType, l as getCurrency, n as JOURNAL_TYPES, o as isValidJournalType, p as CATEGORY_KEYS, r as getCustomJournalTypes, s as registerJournalType, t as JOURNAL_CODES, u as getMinorUnit, x as isIncomeStatement, y as getNormalBalance } from "./journals-
|
|
3
|
-
import { i as defineCountryPack, n as CountryPackInput, r as JournalTemplate, t as CountryPack } from "./index-
|
|
4
|
-
import { _ as PopulatedJournalEntry, a as exportToCsv, h as FlatJournalRow, i as quickbooksFieldMap, m as ExportFieldMap, p as ExportField, r as universalFieldMap, t as flattenJournalEntries } from "./index-
|
|
1
|
+
import { _ as TaxMetadata, a as Cents, c as DateRange, d as JournalType, f as MainType, g as TaxDetail, h as StatementType, i as CategoryKey, l as EntryState, m as ObjectId, n as CashFlowCategory, o as Currency, p as NormalBalance, s as DateOption, t as AccountType, u as JournalItem, v as TotalAccountOp } from "./core-MpgjCqK0.mjs";
|
|
2
|
+
import { S as isValidCategory, a as getJournalTypeCodes, b as isBalanceSheet, c as CURRENCIES, d as isValidCurrency, f as CATEGORIES, i as getJournalType, l as getCurrency, n as JOURNAL_TYPES, o as isValidJournalType, p as CATEGORY_KEYS, r as getCustomJournalTypes, s as registerJournalType, t as JOURNAL_CODES, u as getMinorUnit, x as isIncomeStatement, y as getNormalBalance } from "./journals-Dd4A9TN3.mjs";
|
|
3
|
+
import { i as defineCountryPack, n as CountryPackInput, r as JournalTemplate, t as CountryPack } from "./index-RNZsX0Yo.mjs";
|
|
4
|
+
import { _ as PopulatedJournalEntry, a as exportToCsv, h as FlatJournalRow, i as quickbooksFieldMap, m as ExportFieldMap, p as ExportField, r as universalFieldMap, t as flattenJournalEntries } from "./index-bCEeSzdO.mjs";
|
|
5
5
|
import { Money, abs, add, allocate, equals, format, formatPlain, fromDecimal, isNegative, isPositive, isValid, isZero, max, min, multiply, negate, parseCents, percentage, round, splitTaxExclusive, splitTaxInclusive, subtract, toDecimal } from "./money.mjs";
|
|
6
|
-
import { $ as AgedBalanceParams, A as generateDimensionBreakdown, B as BalanceSheetReport, D as DimensionBreakdownParams, E as DimensionBreakdownOptions, F as BudgetVsActualReport, G as IncomeStatementReport, H as CashFlowSection, I as BudgetVsActualRow, J as ReportCategory, K as LedgerEntry, L as generateBudgetVsActual, M as generateCashFlow, N as BudgetVsActualOptions, O as DimensionBreakdownReport, P as BudgetVsActualParams, Q as AgedBalanceOptions, T as reopenFiscalPeriod, U as GeneralLedgerAccount, V as CashFlowReport, W as GeneralLedgerReport, X as TrialBalanceReport, Y as ReportGroup, Z as TrialBalanceRow, a as RevaluationReport, at as Logger, b as generateGeneralLedger, c as RevaluationRate, d as computeRevaluation, et as AgedBalanceReport, f as PartnerLedgerLine, g as generatePartnerLedger, h as PartnerLedgerReport, i as RevaluationParams, it as generateAgedBalance, k as DimensionBreakdownRow, l as RevaluationResult, m as PartnerLedgerParams, n as generateTrialBalance, nt as AgedBucketConfig, o as generateRevaluation, ot as defaultLogger, p as PartnerLedgerOptions, q as ReportAccount, r as RevaluationOptions, rt as DEFAULT_BUCKETS, s as AccountForeignBalance, tt as AgedBalanceRow, u as buildRevaluationEntry, v as generateIncomeStatement, w as closeFiscalPeriod, z as generateBalanceSheet } from "./trial-balance-
|
|
7
|
-
import { A as OpenItem, C as AccountRepository, D as JournalItemRef, E as JournalEntryRepository, F as SeedOptions, I as SeedResult, M as ReconciliationRepository, N as ReverseOptions, O as JournalRepository, P as ReverseResult, S as creditLimitPlugin, T as BulkCreateResult, _ as FxRealizationPluginOptions, a as dailyLockPlugin, b as doubleEntryPlugin, c as periodResolver, d as LockAccountSelector, f as LockHit, g as idempotencyPlugin, i as FiscalLockPluginOptions, j as PostOptions, k as MatchInput, 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, w as BulkCreateInput, x as CreditLimitPluginOptions } from "./index-
|
|
6
|
+
import { $ as AgedBalanceParams, A as generateDimensionBreakdown, B as BalanceSheetReport, D as DimensionBreakdownParams, E as DimensionBreakdownOptions, F as BudgetVsActualReport, G as IncomeStatementReport, H as CashFlowSection, I as BudgetVsActualRow, J as ReportCategory, K as LedgerEntry, L as generateBudgetVsActual, M as generateCashFlow, N as BudgetVsActualOptions, O as DimensionBreakdownReport, P as BudgetVsActualParams, Q as AgedBalanceOptions, T as reopenFiscalPeriod, U as GeneralLedgerAccount, V as CashFlowReport, W as GeneralLedgerReport, X as TrialBalanceReport, Y as ReportGroup, Z as TrialBalanceRow, a as RevaluationReport, at as Logger, b as generateGeneralLedger, c as RevaluationRate, d as computeRevaluation, et as AgedBalanceReport, f as PartnerLedgerLine, g as generatePartnerLedger, h as PartnerLedgerReport, i as RevaluationParams, it as generateAgedBalance, k as DimensionBreakdownRow, l as RevaluationResult, m as PartnerLedgerParams, n as generateTrialBalance, nt as AgedBucketConfig, o as generateRevaluation, ot as defaultLogger, p as PartnerLedgerOptions, q as ReportAccount, r as RevaluationOptions, rt as DEFAULT_BUCKETS, s as AccountForeignBalance, tt as AgedBalanceRow, u as buildRevaluationEntry, v as generateIncomeStatement, w as closeFiscalPeriod, z as generateBalanceSheet } from "./trial-balance-DTj-c21f.mjs";
|
|
7
|
+
import { A as OpenItem, C as AccountRepository, D as JournalItemRef, E as JournalEntryRepository, F as SeedOptions, I as SeedResult, M as ReconciliationRepository, N as ReverseOptions, O as JournalRepository, P as ReverseResult, S as creditLimitPlugin, T as BulkCreateResult, _ as FxRealizationPluginOptions, a as dailyLockPlugin, b as doubleEntryPlugin, c as periodResolver, d as LockAccountSelector, f as LockHit, g as idempotencyPlugin, i as FiscalLockPluginOptions, j as PostOptions, k as MatchInput, 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, w as BulkCreateInput, x as CreditLimitPluginOptions } from "./index-BSsvrf3m.mjs";
|
|
8
|
+
import { PaginationConfig, PluginType, QueryParser, QueryParserOptions, Repository } from "@classytic/mongokit";
|
|
8
9
|
import { ClientSession, Connection, Model } from "mongoose";
|
|
9
|
-
import { PaginationConfig, PluginType, Repository } from "@classytic/mongokit";
|
|
10
10
|
|
|
11
11
|
//#region src/types/engine.d.ts
|
|
12
12
|
/** Mongokit plugins to install per repository (composes with engine built-ins). */
|
|
@@ -381,6 +381,28 @@ interface RecordAdjustmentInput {
|
|
|
381
381
|
readonly dimensions?: Record<string, unknown>;
|
|
382
382
|
readonly journalType?: string;
|
|
383
383
|
}
|
|
384
|
+
interface RecordOpeningBalanceInput {
|
|
385
|
+
/** Cutover date — typically start of fiscal year. */
|
|
386
|
+
readonly cutoverDate: Date;
|
|
387
|
+
/**
|
|
388
|
+
* Account balances in integer cents, signed:
|
|
389
|
+
* - Positive = normal debit balance (assets)
|
|
390
|
+
* - Negative = normal credit balance (liabilities, equity)
|
|
391
|
+
*
|
|
392
|
+
* Should only contain balance sheet accounts. P&L cumulative effect
|
|
393
|
+
* belongs in retained earnings (the equity account).
|
|
394
|
+
*/
|
|
395
|
+
readonly balances: ReadonlyArray<{
|
|
396
|
+
readonly account: AccountCode;
|
|
397
|
+
readonly balance: Cents$1;
|
|
398
|
+
}>;
|
|
399
|
+
/**
|
|
400
|
+
* Equity contra account code. Defaults to the country pack's
|
|
401
|
+
* `retainedEarningsAccountCode` (e.g. '3600' for CA, '3310' for BD).
|
|
402
|
+
*/
|
|
403
|
+
readonly equityAccount?: AccountCode;
|
|
404
|
+
readonly label?: string;
|
|
405
|
+
}
|
|
384
406
|
interface RecordAPI {
|
|
385
407
|
/**
|
|
386
408
|
* Record a sale. Debits cash/AR, credits revenue. Tax lines — if needed —
|
|
@@ -418,6 +440,31 @@ interface RecordAPI {
|
|
|
418
440
|
* the other verbs. Amounts must balance (debits = credits).
|
|
419
441
|
*/
|
|
420
442
|
adjustment(organizationId: unknown, input: RecordAdjustmentInput, options?: RecordOptions): Promise<unknown>;
|
|
443
|
+
/**
|
|
444
|
+
* Record opening balances for a cutover migration. Creates a single
|
|
445
|
+
* multi-line journal entry with each account's balance, contra'd against
|
|
446
|
+
* an equity account (retained earnings by default).
|
|
447
|
+
*
|
|
448
|
+
* Follows the Odoo convention: regular JE, not a special type. Only
|
|
449
|
+
* balance sheet accounts should be passed — P&L cumulative effect belongs
|
|
450
|
+
* in the equity contra account.
|
|
451
|
+
*
|
|
452
|
+
* Idempotent: uses `_externalId: 'opening-balance:{date}'` so re-calling
|
|
453
|
+
* with the same cutover date fails cleanly (duplicate key error).
|
|
454
|
+
*
|
|
455
|
+
* @example
|
|
456
|
+
* ```typescript
|
|
457
|
+
* await engine.record.openingBalance(orgId, {
|
|
458
|
+
* cutoverDate: new Date('2025-01-01'),
|
|
459
|
+
* balances: [
|
|
460
|
+
* { account: '1000', balance: 5000000 }, // $50k cash
|
|
461
|
+
* { account: '2620', balance: -1875000 }, // $18.75k AP
|
|
462
|
+
* { account: '3600', balance: -3125000 }, // $31.25k RE
|
|
463
|
+
* ],
|
|
464
|
+
* });
|
|
465
|
+
* ```
|
|
466
|
+
*/
|
|
467
|
+
openingBalance(organizationId: unknown, input: RecordOpeningBalanceInput, options?: RecordOptions): Promise<unknown>;
|
|
421
468
|
}
|
|
422
469
|
//#endregion
|
|
423
470
|
//#region src/engine.d.ts
|
|
@@ -540,10 +587,80 @@ declare class AccountingEngine {
|
|
|
540
587
|
isValidAccountType(code: string): boolean;
|
|
541
588
|
/** Get account type definition by code */
|
|
542
589
|
getAccountType(code: string): AccountType | undefined;
|
|
590
|
+
/**
|
|
591
|
+
* Create a pre-configured QueryParser for URL-driven queries against
|
|
592
|
+
* ledger repositories. Returns a mongokit QueryParser with the correct
|
|
593
|
+
* schema and pagination limits for the specified model.
|
|
594
|
+
*
|
|
595
|
+
* @param model - Which ledger model to parse queries for
|
|
596
|
+
* @param overrides - Additional QueryParserOptions to merge
|
|
597
|
+
*
|
|
598
|
+
* @example
|
|
599
|
+
* ```typescript
|
|
600
|
+
* const parser = engine.createQueryParser('journalEntry');
|
|
601
|
+
* const parsed = parser.parse(req.query);
|
|
602
|
+
* const result = await engine.repositories.journalEntries.getAll({
|
|
603
|
+
* ...parsed,
|
|
604
|
+
* filters: { ...parsed.filters, organizationId },
|
|
605
|
+
* });
|
|
606
|
+
* ```
|
|
607
|
+
*/
|
|
608
|
+
createQueryParser(model: 'account' | 'journalEntry' | 'fiscalPeriod' | 'budget' | 'reconciliation' | 'journal', overrides?: Partial<QueryParserOptions>): QueryParser;
|
|
543
609
|
private _buildReports;
|
|
544
610
|
}
|
|
545
611
|
declare function createAccountingEngine(config: AccountingEngineConfig): AccountingEngine;
|
|
546
612
|
//#endregion
|
|
613
|
+
//#region src/repositories/reconciliation.repository.d.ts
|
|
614
|
+
interface MatchHookItem {
|
|
615
|
+
entry: unknown;
|
|
616
|
+
itemIndex: number;
|
|
617
|
+
debit: number;
|
|
618
|
+
credit: number;
|
|
619
|
+
amountCurrency: number | null;
|
|
620
|
+
exchangeRate: number | null;
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Context passed to `before:match` and `after:match` hooks.
|
|
624
|
+
*
|
|
625
|
+
* - `before:match`: fired after validation but before the matchingNumber is
|
|
626
|
+
* stamped and the reconciliation doc is created. Throw to abort.
|
|
627
|
+
* - `after:match`: fired after the reconciliation doc is persisted. Used by
|
|
628
|
+
* fxRealizationPlugin, and can be used by invoice packages to update
|
|
629
|
+
* payment state.
|
|
630
|
+
*/
|
|
631
|
+
interface MatchHookContext {
|
|
632
|
+
/** The input that was passed to match(). */
|
|
633
|
+
input: MatchInput;
|
|
634
|
+
/** Validated + enriched item snapshots with debit/credit/currency info. */
|
|
635
|
+
items: MatchHookItem[];
|
|
636
|
+
/** Shared currency across all items, or null if mixed. */
|
|
637
|
+
sharedCurrency: string | null;
|
|
638
|
+
/** The matching number (auto-generated or caller-provided). */
|
|
639
|
+
matchingNumber: string;
|
|
640
|
+
/** Totals for the matched set. */
|
|
641
|
+
debitTotal: number;
|
|
642
|
+
creditTotal: number;
|
|
643
|
+
isFullReconcile: boolean;
|
|
644
|
+
/** The created reconciliation document (only in after:match). */
|
|
645
|
+
reconciliation?: unknown;
|
|
646
|
+
session: ClientSession | null;
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Context passed to `before:unmatch` and `after:unmatch` hooks.
|
|
650
|
+
*/
|
|
651
|
+
interface UnmatchHookContext {
|
|
652
|
+
matchingNumber: string;
|
|
653
|
+
/** The reconciliation document being removed. */
|
|
654
|
+
reconciliation: Record<string, unknown>;
|
|
655
|
+
/** The items that will be / were unmatched. */
|
|
656
|
+
items: Array<{
|
|
657
|
+
entry: unknown;
|
|
658
|
+
itemIndex: number;
|
|
659
|
+
}>;
|
|
660
|
+
organizationId?: unknown;
|
|
661
|
+
session: ClientSession | null;
|
|
662
|
+
}
|
|
663
|
+
//#endregion
|
|
547
664
|
//#region src/utils/account-helpers.d.ts
|
|
548
665
|
/**
|
|
549
666
|
* Check if an account type is a virtual tax sub-account.
|
|
@@ -764,4 +881,4 @@ interface PostingResult {
|
|
|
764
881
|
idempotencyKeys?: string[];
|
|
765
882
|
}
|
|
766
883
|
//#endregion
|
|
767
|
-
export { type AccountCode, type AccountForeignBalance, type AccountRepository, type AccountSummary, type AccountType, AccountingEngine, type AccountingEngineConfig, AccountingError, type ActorContext, type AgedBalanceOptions, type AgedBalanceParams, type AgedBalanceReport, type AgedBalanceRow, type AgedBucketConfig, type AuditConfig, type BalanceSheetReport, type BudgetVsActualOptions, type BudgetVsActualParams, type BudgetVsActualReport, type BudgetVsActualRow, type BulkCreateInput, type BulkCreateResult, CATEGORIES, CATEGORY_KEYS, CURRENCIES, type CashFlowCategory, type CashFlowReport, type CashFlowSection, type CategoryKey, type Cents, type CountryPack, type CountryPackInput, type CreateLockPluginOptions, type CreditLimitPluginOptions, type Currency, DEFAULT_BUCKETS, type DailyLockPluginOptions, type DateOption, type DateRange, type DimensionBreakdownOptions, type DimensionBreakdownParams, type DimensionBreakdownReport, type DimensionBreakdownRow, type DimensionDefinition, type EntryState, Errors, type ExportField, type ExportFieldMap, type FieldError, type FiscalLockPluginOptions, type FiscalPeriodSummary, type FlatJournalRow, type FxRealizationPluginOptions, type GeneralLedgerAccount, type GeneralLedgerReport, type IncomeStatementReport, type IntrospectAPI, JOURNAL_CODES, JOURNAL_TYPES, type JournalEntryRepository, type JournalItem, type JournalItemRef, type JournalRepository, type JournalSchemaOptions, type JournalTemplate, type JournalType, type LedgerEntry, type LedgerModels, type LedgerPaginationConfig, type LedgerRepositories, type LedgerRepositoryPlugins, type LockAccountSelector, type LockHit, type LockResolver, type LockResolverContext, type Logger, type MainType, type MatchInput, type ModelNames, Money, type MultiCurrencyConfig, type MultiTenantConfig, type NormalBalance, type OpenItem, type PartnerLedgerLine, type PartnerLedgerOptions, type PartnerLedgerParams, type PartnerLedgerReport, type PeriodResolverOptions, type PopulatedJournalEntry, type PostOptions, type PostingContract, type PostingResult, type ReconciliationRepository, type RecordAPI, type RecordAdjustmentInput, type RecordAdjustmentLine, type RecordExpenseInput, type RecordOptions, type RecordPaymentInput, type RecordSaleInput, type RecordTransferInput, type ReportAccount, type ReportCategory, type ReportDescriptor, type ReportGroup, type ResolvedModelNames, type RevaluationOptions, type RevaluationParams, type RevaluationRate, type RevaluationReport, type RevaluationResult, type ReverseOptions, type ReverseResult, type SchemaOptions, type SeedOptions, type SeedResult, type Cents$1 as SemanticCents, type SessionResult, type StatementType, type StrictnessConfig, type SubledgerJournalItem, type SubledgerPostingInput, type TaxDetail, type TaxMetadata, type TotalAccountOp, type TrialBalanceReport, type TrialBalanceRow, type WatermarkResolverOptions, acquireSession, add, allocate, buildAccountTypeMap, buildDimensionFields, buildDimensionIndexes, buildItemFilters, buildRevaluationEntry, calculateTotal, closeFiscalPeriod, computeEndingBalance, computeRevaluation, createAccountingEngine, createLockPlugin, createModels, createRepositories, creditLimitPlugin, dailyLockPlugin, defaultLogger, defineCountryPack, doubleEntryPlugin, exportToCsv, finalizeSession, fiscalLockPlugin, flattenJournalEntries, format, formatPlain, fromDecimal, fxRealizationPlugin, generateAgedBalance, generateBalanceSheet, generateBudgetVsActual, generateCashFlow, generateDimensionBreakdown, generateGeneralLedger, generateIncomeStatement, generatePartnerLedger, generateRevaluation, generateTrialBalance, getCurrency, getCustomJournalTypes, getDateRange, getFiscalYearStart, getJournalType, getJournalTypeCodes, getMinorUnit, getNormalBalance, idempotencyPlugin, isBalanceSheet, isIncomeStatement, isValidCategory, isValidCurrency, isValidJournalType, isVirtualTaxAccount, multiply, parseCents, percentage, periodResolver, quickbooksFieldMap, registerJournalType, reopenFiscalPeriod, resolveModelNames, splitTaxExclusive, splitTaxInclusive, subtract, toDecimal, universalFieldMap, watermarkResolver };
|
|
884
|
+
export { type AccountCode, type AccountForeignBalance, type AccountRepository, type AccountSummary, type AccountType, AccountingEngine, type AccountingEngineConfig, AccountingError, type ActorContext, type AgedBalanceOptions, type AgedBalanceParams, type AgedBalanceReport, type AgedBalanceRow, type AgedBucketConfig, type AuditConfig, type BalanceSheetReport, type BudgetVsActualOptions, type BudgetVsActualParams, type BudgetVsActualReport, type BudgetVsActualRow, type BulkCreateInput, type BulkCreateResult, CATEGORIES, CATEGORY_KEYS, CURRENCIES, type CashFlowCategory, type CashFlowReport, type CashFlowSection, type CategoryKey, type Cents, type CountryPack, type CountryPackInput, type CreateLockPluginOptions, type CreditLimitPluginOptions, type Currency, DEFAULT_BUCKETS, type DailyLockPluginOptions, type DateOption, type DateRange, type DimensionBreakdownOptions, type DimensionBreakdownParams, type DimensionBreakdownReport, type DimensionBreakdownRow, type DimensionDefinition, type EntryState, Errors, type ExportField, type ExportFieldMap, type FieldError, type FiscalLockPluginOptions, type FiscalPeriodSummary, type FlatJournalRow, type FxRealizationPluginOptions, type GeneralLedgerAccount, type GeneralLedgerReport, type IncomeStatementReport, type IntrospectAPI, JOURNAL_CODES, JOURNAL_TYPES, type JournalEntryRepository, type JournalItem, type JournalItemRef, type JournalRepository, type JournalSchemaOptions, type JournalTemplate, type JournalType, type LedgerEntry, type LedgerModels, type LedgerPaginationConfig, type LedgerRepositories, type LedgerRepositoryPlugins, type LockAccountSelector, type LockHit, type LockResolver, type LockResolverContext, type Logger, type MainType, type MatchHookContext, type MatchHookItem, type MatchInput, type ModelNames, Money, type MultiCurrencyConfig, type MultiTenantConfig, type NormalBalance, type OpenItem, type PartnerLedgerLine, type PartnerLedgerOptions, type PartnerLedgerParams, type PartnerLedgerReport, type PeriodResolverOptions, type PopulatedJournalEntry, type PostOptions, type PostingContract, type PostingResult, type ReconciliationRepository, type RecordAPI, type RecordAdjustmentInput, type RecordAdjustmentLine, type RecordExpenseInput, type RecordOptions, type RecordPaymentInput, type RecordSaleInput, type RecordTransferInput, type ReportAccount, type ReportCategory, type ReportDescriptor, type ReportGroup, type ResolvedModelNames, type RevaluationOptions, type RevaluationParams, type RevaluationRate, type RevaluationReport, type RevaluationResult, type ReverseOptions, type ReverseResult, type SchemaOptions, type SeedOptions, type SeedResult, type Cents$1 as SemanticCents, type SessionResult, type StatementType, type StrictnessConfig, type SubledgerJournalItem, type SubledgerPostingInput, type TaxDetail, type TaxMetadata, type TotalAccountOp, type TrialBalanceReport, type TrialBalanceRow, type UnmatchHookContext, type WatermarkResolverOptions, acquireSession, add, allocate, buildAccountTypeMap, buildDimensionFields, buildDimensionIndexes, buildItemFilters, buildRevaluationEntry, calculateTotal, closeFiscalPeriod, computeEndingBalance, computeRevaluation, createAccountingEngine, createLockPlugin, createModels, createRepositories, creditLimitPlugin, dailyLockPlugin, defaultLogger, defineCountryPack, doubleEntryPlugin, exportToCsv, finalizeSession, fiscalLockPlugin, flattenJournalEntries, format, formatPlain, fromDecimal, fxRealizationPlugin, generateAgedBalance, generateBalanceSheet, generateBudgetVsActual, generateCashFlow, generateDimensionBreakdown, generateGeneralLedger, generateIncomeStatement, generatePartnerLedger, generateRevaluation, generateTrialBalance, getCurrency, getCustomJournalTypes, getDateRange, getFiscalYearStart, getJournalType, getJournalTypeCodes, getMinorUnit, getNormalBalance, idempotencyPlugin, isBalanceSheet, isIncomeStatement, isValidCategory, isValidCurrency, isValidJournalType, isVirtualTaxAccount, multiply, parseCents, percentage, periodResolver, quickbooksFieldMap, registerJournalType, reopenFiscalPeriod, resolveModelNames, splitTaxExclusive, splitTaxInclusive, subtract, toDecimal, universalFieldMap, watermarkResolver };
|
package/dist/index.mjs
CHANGED
|
@@ -3,11 +3,12 @@ import { Money, add, allocate, format, formatPlain, fromDecimal, multiply, parse
|
|
|
3
3
|
import { n as Errors, t as AccountingError } from "./errors-CSDQPNyt.mjs";
|
|
4
4
|
import { C as isVirtualTaxAccount, E as requireOrgScope, S as computeEndingBalance, T as generateAgedBalance, _ as buildItemFilters, a as finalizeSession, b as buildAccountTypeMap, c as generateRevaluation, d as generateIncomeStatement, f as generateGeneralLedger, g as generateBalanceSheet, h as generateBudgetVsActual, i as acquireSession, l as buildRevaluationEntry, m as generateCashFlow, n as closeFiscalPeriod, o as defaultLogger, p as generateDimensionBreakdown, r as reopenFiscalPeriod, s as generateTrialBalance, t as generatePartnerLedger, u as computeRevaluation, v as getDateRange, w as DEFAULT_BUCKETS, x as calculateTotal, y as getFiscalYearStart } from "./partner-ledger-D9H5hegI.mjs";
|
|
5
5
|
import { c as getNormalBalance, d as isValidCategory, l as isBalanceSheet, n as CATEGORY_KEYS, t as CATEGORIES, u as isIncomeStatement } from "./categories-BkKdv16V.mjs";
|
|
6
|
-
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-
|
|
6
|
+
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-DDVK-oYO.mjs";
|
|
7
|
+
import { t as buildOpeningBalanceEntry } from "./opening-balance-DPXmAIzN.mjs";
|
|
7
8
|
import { defineCountryPack } from "./country/index.mjs";
|
|
8
|
-
import { a as exportToCsv, i as quickbooksFieldMap, r as universalFieldMap, t as flattenJournalEntries } from "./exports-
|
|
9
|
+
import { a as exportToCsv, i as quickbooksFieldMap, r as universalFieldMap, t as flattenJournalEntries } from "./exports-B3whucXe.mjs";
|
|
10
|
+
import { QueryParser, Repository } from "@classytic/mongokit";
|
|
9
11
|
import mongoose, { Schema } from "mongoose";
|
|
10
|
-
import { Repository } from "@classytic/mongokit";
|
|
11
12
|
//#region src/schemas/currency-field.ts
|
|
12
13
|
/**
|
|
13
14
|
* Build the Mongoose currency field definition.
|
|
@@ -919,11 +920,10 @@ function createModels(connection, config) {
|
|
|
919
920
|
* onto an existing mongokit Repository.
|
|
920
921
|
*
|
|
921
922
|
* @param repository - A mongokit Repository instance (already created)
|
|
922
|
-
* @param AccountModel - The Mongoose model for accounts
|
|
923
923
|
* @param country - The CountryPack for account type lookups
|
|
924
924
|
* @param orgField - The multi-tenant field name (e.g. 'business')
|
|
925
925
|
*/
|
|
926
|
-
function wireAccountMethods(repository,
|
|
926
|
+
function wireAccountMethods(repository, country, orgField) {
|
|
927
927
|
repository.on("before:create", (ctx) => {
|
|
928
928
|
const code = ctx.data?.accountTypeCode;
|
|
929
929
|
if (code && !country.isPostingAccount(code)) throw Errors.validation(`Cannot create account with type "${code}" — it is a structural group or calculated total, not a posting account.`);
|
|
@@ -936,7 +936,10 @@ function wireAccountMethods(repository, AccountModel, country, orgField) {
|
|
|
936
936
|
const postingTypes = country.getPostingAccountTypes();
|
|
937
937
|
const filter = {};
|
|
938
938
|
if (orgField && orgId != null) filter[orgField] = orgId;
|
|
939
|
-
const existing = await
|
|
939
|
+
const existing = await repository.findAll(filter, {
|
|
940
|
+
select: { accountNumber: 1 },
|
|
941
|
+
lean: true
|
|
942
|
+
});
|
|
940
943
|
const existingNumbers = new Set(existing.map((a) => a.accountNumber));
|
|
941
944
|
const toCreate = postingTypes.filter((at) => !existingNumbers.has(at.code)).map((at) => {
|
|
942
945
|
const doc = {
|
|
@@ -953,7 +956,7 @@ function wireAccountMethods(repository, AccountModel, country, orgField) {
|
|
|
953
956
|
};
|
|
954
957
|
try {
|
|
955
958
|
return {
|
|
956
|
-
created: (await
|
|
959
|
+
created: (await repository.createMany(toCreate, {
|
|
957
960
|
session: options.session ?? void 0,
|
|
958
961
|
ordered: false
|
|
959
962
|
})).length,
|
|
@@ -1034,7 +1037,10 @@ function wireAccountMethods(repository, AccountModel, country, orgField) {
|
|
|
1034
1037
|
};
|
|
1035
1038
|
const existsFilter = { accountNumber: { $in: validAccounts.map((a) => a.accountNumber) } };
|
|
1036
1039
|
if (orgField && orgId != null) existsFilter[orgField] = orgId;
|
|
1037
|
-
const existingDocs = await
|
|
1040
|
+
const existingDocs = await repository.findAll(existsFilter, {
|
|
1041
|
+
select: { accountNumber: 1 },
|
|
1042
|
+
lean: true
|
|
1043
|
+
});
|
|
1038
1044
|
const existingNumbers = new Set(existingDocs.map((d) => d.accountNumber));
|
|
1039
1045
|
const toCreate = [];
|
|
1040
1046
|
for (const item of validAccounts) if (existingNumbers.has(item.accountNumber)) results.skipped.push({
|
|
@@ -1056,7 +1062,7 @@ function wireAccountMethods(repository, AccountModel, country, orgField) {
|
|
|
1056
1062
|
return doc;
|
|
1057
1063
|
});
|
|
1058
1064
|
try {
|
|
1059
|
-
const inserted = await
|
|
1065
|
+
const inserted = await repository.createMany(docs, { ordered: false });
|
|
1060
1066
|
results.created = toCreate.map((item, idx) => ({
|
|
1061
1067
|
accountTypeCode: item.accountTypeCode,
|
|
1062
1068
|
active: item.active,
|
|
@@ -1541,6 +1547,7 @@ function wireReconciliationMethods(repository, ReconciliationModel, JournalEntry
|
|
|
1541
1547
|
const create = repository.create.bind(repository);
|
|
1542
1548
|
const deleteById = repository.delete.bind(repository);
|
|
1543
1549
|
const repoInstance = repository;
|
|
1550
|
+
const emitHook = repoInstance.emitAsync.bind(repoInstance);
|
|
1544
1551
|
repository.match = async (input) => {
|
|
1545
1552
|
const { account, items, note, reconciledBy, organizationId, session = null } = input;
|
|
1546
1553
|
let { matchingNumber } = input;
|
|
@@ -1585,6 +1592,17 @@ function wireReconciliationMethods(repository, ReconciliationModel, JournalEntry
|
|
|
1585
1592
|
const isFullReconcile = difference === 0;
|
|
1586
1593
|
const sharedCurrency = currencies.size === 1 ? Array.from(currencies)[0] : null;
|
|
1587
1594
|
if (!matchingNumber) matchingNumber = await nextMatchingNumber(ReconciliationModel, orgField, organizationId, session);
|
|
1595
|
+
const hookCtx = {
|
|
1596
|
+
input,
|
|
1597
|
+
items: itemSnapshots,
|
|
1598
|
+
sharedCurrency,
|
|
1599
|
+
matchingNumber,
|
|
1600
|
+
debitTotal,
|
|
1601
|
+
creditTotal,
|
|
1602
|
+
isFullReconcile,
|
|
1603
|
+
session
|
|
1604
|
+
};
|
|
1605
|
+
await emitHook("before:match", hookCtx);
|
|
1588
1606
|
const bulkOps = itemSnapshots.map((snap) => ({ updateOne: {
|
|
1589
1607
|
filter: { _id: snap.entry },
|
|
1590
1608
|
update: { $set: { [`journalItems.${snap.itemIndex}.matchingNumber`]: matchingNumber } }
|
|
@@ -1612,12 +1630,9 @@ function wireReconciliationMethods(repository, ReconciliationModel, JournalEntry
|
|
|
1612
1630
|
};
|
|
1613
1631
|
if (orgField && organizationId != null) reconciliationData[orgField] = organizationId;
|
|
1614
1632
|
const record = await create(reconciliationData);
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
reconciliation: record
|
|
1618
|
-
items: itemSnapshots,
|
|
1619
|
-
sharedCurrency,
|
|
1620
|
-
session
|
|
1633
|
+
await emitHook("after:match", {
|
|
1634
|
+
...hookCtx,
|
|
1635
|
+
reconciliation: record
|
|
1621
1636
|
});
|
|
1622
1637
|
return record;
|
|
1623
1638
|
};
|
|
@@ -1628,13 +1643,23 @@ function wireReconciliationMethods(repository, ReconciliationModel, JournalEntry
|
|
|
1628
1643
|
if (orgField && organizationId != null) query[orgField] = organizationId;
|
|
1629
1644
|
const existing = await ReconciliationModel.findOne(query).session(session).lean();
|
|
1630
1645
|
if (!existing) throw Errors.notFound(`Reconciliation ${matchingNumber} not found`);
|
|
1631
|
-
const
|
|
1646
|
+
const items = existing.items ?? [];
|
|
1647
|
+
const unmatchCtx = {
|
|
1648
|
+
matchingNumber,
|
|
1649
|
+
reconciliation: existing,
|
|
1650
|
+
items,
|
|
1651
|
+
organizationId,
|
|
1652
|
+
session
|
|
1653
|
+
};
|
|
1654
|
+
await emitHook("before:unmatch", unmatchCtx);
|
|
1655
|
+
const bulkOps = items.map((it) => ({ updateOne: {
|
|
1632
1656
|
filter: { _id: it.entry },
|
|
1633
1657
|
update: { $set: { [`journalItems.${it.itemIndex}.matchingNumber`]: null } }
|
|
1634
1658
|
} }));
|
|
1635
1659
|
if (bulkOps.length > 0) await JournalEntryModel.bulkWrite(bulkOps, { session: session ?? void 0 });
|
|
1636
1660
|
const result = await deleteById(String(existing._id));
|
|
1637
1661
|
if (!result.success) throw Errors.notFound("Failed to delete reconciliation record");
|
|
1662
|
+
await emitHook("after:unmatch", unmatchCtx);
|
|
1638
1663
|
return result;
|
|
1639
1664
|
};
|
|
1640
1665
|
repository.getOpenItems = async (params) => {
|
|
@@ -1727,7 +1752,7 @@ function createRepositories(models, config, plugins = {}, pagination = {}) {
|
|
|
1727
1752
|
const fpPagination = pagination.fiscalPeriod ?? {};
|
|
1728
1753
|
const budgetPagination = pagination.budget ?? {};
|
|
1729
1754
|
const reconPagination = pagination.reconciliation ?? {};
|
|
1730
|
-
const accounts = wireAccountMethods(new Repository(models.Account, plugins.account ?? [], accountPagination),
|
|
1755
|
+
const accounts = wireAccountMethods(new Repository(models.Account, plugins.account ?? [], accountPagination), country, orgField);
|
|
1731
1756
|
const jePlugins = [
|
|
1732
1757
|
...plugins.journalEntry ?? [],
|
|
1733
1758
|
doubleEntryPlugin({
|
|
@@ -2255,16 +2280,80 @@ function buildRecordAPI({ models, repositories, config }) {
|
|
|
2255
2280
|
journalItems: items
|
|
2256
2281
|
}, options);
|
|
2257
2282
|
};
|
|
2283
|
+
const openingBalance = async (organizationId, input, options) => {
|
|
2284
|
+
if (!input.balances || input.balances.length === 0) throw Errors.validation("Opening balance requires at least one account balance.", [{
|
|
2285
|
+
path: "balances",
|
|
2286
|
+
issue: "must contain at least 1 entry",
|
|
2287
|
+
value: 0
|
|
2288
|
+
}]);
|
|
2289
|
+
const equityCode = input.equityAccount ?? config.country?.retainedEarningsAccountCode;
|
|
2290
|
+
if (!equityCode) throw Errors.validation("Equity contra account code is required. Pass equityAccount or configure retainedEarningsAccountCode in the country pack.", [{
|
|
2291
|
+
path: "equityAccount",
|
|
2292
|
+
issue: "required",
|
|
2293
|
+
value: void 0
|
|
2294
|
+
}]);
|
|
2295
|
+
const result = buildOpeningBalanceEntry({
|
|
2296
|
+
cutoverDate: input.cutoverDate,
|
|
2297
|
+
balances: input.balances.map((b) => ({
|
|
2298
|
+
accountCode: b.account,
|
|
2299
|
+
balance: b.balance
|
|
2300
|
+
})),
|
|
2301
|
+
equityAccountCode: equityCode,
|
|
2302
|
+
label: input.label
|
|
2303
|
+
});
|
|
2304
|
+
const acctMap = await resolveAccounts(organizationId, result.entry.journalItems.map((item) => item.account), "balances", options?.session ?? null);
|
|
2305
|
+
const items = result.entry.journalItems.map((item) => buildItem(acctMap.get(item.account), item.debit, item.credit, item.label));
|
|
2306
|
+
return postEntry(organizationId, {
|
|
2307
|
+
journalType: result.entry.journalType ?? "GENERAL",
|
|
2308
|
+
date: result.entry.date,
|
|
2309
|
+
label: result.entry.label,
|
|
2310
|
+
journalItems: items,
|
|
2311
|
+
...result.entry.extra
|
|
2312
|
+
}, options);
|
|
2313
|
+
};
|
|
2258
2314
|
return {
|
|
2259
2315
|
sale,
|
|
2260
2316
|
expense,
|
|
2261
2317
|
transfer,
|
|
2262
2318
|
payment,
|
|
2263
|
-
adjustment
|
|
2319
|
+
adjustment,
|
|
2320
|
+
openingBalance
|
|
2264
2321
|
};
|
|
2265
2322
|
}
|
|
2266
2323
|
//#endregion
|
|
2267
2324
|
//#region src/engine.ts
|
|
2325
|
+
/**
|
|
2326
|
+
* AccountingEngine — The main entry point for @classytic/ledger.
|
|
2327
|
+
*
|
|
2328
|
+
* The engine owns all models, repositories, and reports. Matches the
|
|
2329
|
+
* @classytic/flow and @classytic/promo pattern: pass a mongoose connection
|
|
2330
|
+
* in config, and everything is auto-wired.
|
|
2331
|
+
*
|
|
2332
|
+
* @example
|
|
2333
|
+
* ```typescript
|
|
2334
|
+
* import mongoose from 'mongoose';
|
|
2335
|
+
* import { createAccountingEngine } from '@classytic/ledger';
|
|
2336
|
+
* import { canadaPack } from '@classytic/ledger-ca';
|
|
2337
|
+
*
|
|
2338
|
+
* const engine = createAccountingEngine({
|
|
2339
|
+
* mongoose: mongoose.connection,
|
|
2340
|
+
* country: canadaPack,
|
|
2341
|
+
* currency: 'CAD',
|
|
2342
|
+
* multiTenant: { orgField: 'organizationId', orgRef: 'Organization' },
|
|
2343
|
+
* });
|
|
2344
|
+
*
|
|
2345
|
+
* // Models — auto-created Mongoose models
|
|
2346
|
+
* engine.models.Account
|
|
2347
|
+
* engine.models.JournalEntry
|
|
2348
|
+
*
|
|
2349
|
+
* // Repositories — plugins + domain methods pre-wired
|
|
2350
|
+
* await engine.repositories.accounts.seedAccounts(orgId);
|
|
2351
|
+
* await engine.repositories.journalEntries.post(entryId, orgId);
|
|
2352
|
+
*
|
|
2353
|
+
* // Reports — bound to owned models
|
|
2354
|
+
* const bs = await engine.reports.balanceSheet({ organizationId: orgId, dateOption: 'year', dateValue: 2025 });
|
|
2355
|
+
* ```
|
|
2356
|
+
*/
|
|
2268
2357
|
var AccountingEngine = class {
|
|
2269
2358
|
config;
|
|
2270
2359
|
country;
|
|
@@ -2313,6 +2402,60 @@ var AccountingEngine = class {
|
|
|
2313
2402
|
getAccountType(code) {
|
|
2314
2403
|
return this.country.getAccountType(code);
|
|
2315
2404
|
}
|
|
2405
|
+
/**
|
|
2406
|
+
* Create a pre-configured QueryParser for URL-driven queries against
|
|
2407
|
+
* ledger repositories. Returns a mongokit QueryParser with the correct
|
|
2408
|
+
* schema and pagination limits for the specified model.
|
|
2409
|
+
*
|
|
2410
|
+
* @param model - Which ledger model to parse queries for
|
|
2411
|
+
* @param overrides - Additional QueryParserOptions to merge
|
|
2412
|
+
*
|
|
2413
|
+
* @example
|
|
2414
|
+
* ```typescript
|
|
2415
|
+
* const parser = engine.createQueryParser('journalEntry');
|
|
2416
|
+
* const parsed = parser.parse(req.query);
|
|
2417
|
+
* const result = await engine.repositories.journalEntries.getAll({
|
|
2418
|
+
* ...parsed,
|
|
2419
|
+
* filters: { ...parsed.filters, organizationId },
|
|
2420
|
+
* });
|
|
2421
|
+
* ```
|
|
2422
|
+
*/
|
|
2423
|
+
createQueryParser(model, overrides) {
|
|
2424
|
+
const paginationConfig = this.config.pagination ?? {};
|
|
2425
|
+
const entry = {
|
|
2426
|
+
account: {
|
|
2427
|
+
model: this.models.Account,
|
|
2428
|
+
pagination: paginationConfig.account
|
|
2429
|
+
},
|
|
2430
|
+
journalEntry: {
|
|
2431
|
+
model: this.models.JournalEntry,
|
|
2432
|
+
pagination: paginationConfig.journalEntry
|
|
2433
|
+
},
|
|
2434
|
+
fiscalPeriod: {
|
|
2435
|
+
model: this.models.FiscalPeriod,
|
|
2436
|
+
pagination: paginationConfig.fiscalPeriod
|
|
2437
|
+
},
|
|
2438
|
+
budget: {
|
|
2439
|
+
model: this.models.Budget,
|
|
2440
|
+
pagination: paginationConfig.budget
|
|
2441
|
+
},
|
|
2442
|
+
reconciliation: {
|
|
2443
|
+
model: this.models.Reconciliation,
|
|
2444
|
+
pagination: paginationConfig.reconciliation
|
|
2445
|
+
},
|
|
2446
|
+
journal: {
|
|
2447
|
+
model: this.models.Journal,
|
|
2448
|
+
pagination: paginationConfig.journal
|
|
2449
|
+
}
|
|
2450
|
+
}[model];
|
|
2451
|
+
if (!entry) throw new Error(`createQueryParser: unknown model "${model}"`);
|
|
2452
|
+
return new QueryParser({
|
|
2453
|
+
schema: entry.model.schema,
|
|
2454
|
+
maxLimit: entry.pagination?.maxLimit ?? 100,
|
|
2455
|
+
searchMode: "regex",
|
|
2456
|
+
...overrides
|
|
2457
|
+
});
|
|
2458
|
+
}
|
|
2316
2459
|
_buildReports() {
|
|
2317
2460
|
const AccountModel = this.models.Account;
|
|
2318
2461
|
const JournalEntryModel = this.models.JournalEntry;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as JournalType, f as MainType, h as StatementType, i as CategoryKey, o as Currency, r as Category } from "./core-
|
|
1
|
+
import { d as JournalType, f as MainType, h as StatementType, i as CategoryKey, o as Currency, r as Category } from "./core-MpgjCqK0.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/constants/categories.d.ts
|
|
4
4
|
/** All valid categories */
|
|
@@ -0,0 +1,60 @@
|
|
|
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 };
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -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-
|
|
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-BSsvrf3m.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 };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -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-
|
|
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-DDVK-oYO.mjs";
|
|
2
2
|
export { createLockPlugin, creditLimitPlugin, dailyLockPlugin, doubleEntryPlugin, fiscalLockPlugin, fxRealizationPlugin, idempotencyPlugin, periodResolver, watermarkResolver };
|
package/dist/reports/index.d.mts
CHANGED
|
@@ -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-
|
|
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-DTj-c21f.mjs";
|
|
2
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 };
|