offinance-shared-core 0.1.0-alpha.2 → 0.1.0-alpha.4

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.
@@ -1,5 +1,9 @@
1
1
  import type { FinanceAccount } from './contracts/AccountContract.js';
2
2
  import type { FinanceJournalEntry, JournalDraftInput } from './contracts/JournalContract.js';
3
+ import type { FinanceOpenItemAgingQuery, FinanceOpenItemAgingSummary, FinanceOpenItemPosition, FinanceOpenItemScope } from './contracts/OpenItemContract.js';
4
+ import type { FinanceOpenItemReconciliationInput, FinanceOpenItemReconciliationSummary } from './contracts/ReconciliationContract.js';
5
+ import type { FinanceCashBankMovementEntry, FinanceCashBankMovementScope, FinanceCashBankMovementSummary } from './contracts/CashMovementContract.js';
6
+ import type { FinanceAuditTrailEntry, FinanceAuditTrailScope } from './contracts/AuditTrailContract.js';
3
7
  import type { FiscalPeriod, TrialBalanceRow, FinanceLedgerScope } from './contracts/FiscalContract.js';
4
8
  import type { RapbPlan, CreateRapbInput, RapbVariance } from './contracts/BudgetContract.js';
5
9
  interface LedgerAccumulator {
@@ -12,6 +16,7 @@ export interface OffinanceCoreState {
12
16
  journals: Map<string, FinanceJournalEntry>;
13
17
  balances: Map<string, LedgerAccumulator>;
14
18
  rapbPlans: Map<string, RapbPlan>;
19
+ auditTrail: FinanceAuditTrailEntry[];
15
20
  }
16
21
  export declare class OffinanceCore {
17
22
  private readonly state;
@@ -27,6 +32,12 @@ export declare class OffinanceCore {
27
32
  getTrialBalance(): TrialBalanceRow[];
28
33
  getTrialBalanceByScope(scope?: FinanceLedgerScope): TrialBalanceRow[];
29
34
  listJournals(scope?: FinanceLedgerScope): FinanceJournalEntry[];
35
+ listOpenItems(scope?: FinanceOpenItemScope): FinanceOpenItemPosition[];
36
+ getOpenItemAging(query: FinanceOpenItemAgingQuery): FinanceOpenItemAgingSummary;
37
+ reconcileOpenItems(input: FinanceOpenItemReconciliationInput): FinanceOpenItemReconciliationSummary;
38
+ listCashBankMovements(scope: FinanceCashBankMovementScope): FinanceCashBankMovementEntry[];
39
+ summarizeCashBankMovements(scope: FinanceCashBankMovementScope): FinanceCashBankMovementSummary;
40
+ listFinancialAuditTrail(scope?: FinanceAuditTrailScope): FinanceAuditTrailEntry[];
30
41
  private assertJournalLinesKnownAccounts;
31
42
  private assertJournalPeriodOpen;
32
43
  private findPeriodByDate;
@@ -40,5 +51,7 @@ export declare class OffinanceCore {
40
51
  approvedBy: string;
41
52
  }): RapbPlan;
42
53
  evaluateVariance(rapbId: string): RapbVariance;
54
+ private recordAuditTrail;
55
+ private matchesAuditScope;
43
56
  }
44
57
  export {};
@@ -0,0 +1,27 @@
1
+ import type { ResponseEnvelope, ScopeRef } from 'ofcore';
2
+ import type { FinanceLedgerScope } from './FiscalContract.js';
3
+ export type FinanceAuditTrailEventType = 'journal_drafted' | 'journal_posted' | 'journal_reversal_posted' | 'fiscal_period_opened' | 'fiscal_period_closed' | 'rapb_created' | 'rapb_approved';
4
+ export type FinanceAuditTrailRecordType = 'journal' | 'fiscal_period' | 'rapb_plan';
5
+ export interface FinanceAuditTrailScope extends FinanceLedgerScope {
6
+ recordId?: string;
7
+ journalId?: string;
8
+ eventTypes?: FinanceAuditTrailEventType[];
9
+ }
10
+ export interface FinanceAuditTrailEntry extends ScopeRef {
11
+ id: string;
12
+ financeDomainId?: string;
13
+ ledgerProfileId?: string;
14
+ occurredAt: string;
15
+ eventType: FinanceAuditTrailEventType;
16
+ recordType: FinanceAuditTrailRecordType;
17
+ recordId: string;
18
+ journalId?: string;
19
+ sourceJournalId?: string;
20
+ reference?: string;
21
+ evidenceRef?: string;
22
+ summary: string;
23
+ metadata?: Record<string, unknown>;
24
+ }
25
+ export interface FinanceAuditTrailServiceContractV2 {
26
+ listFinancialAuditTrail(scope?: FinanceAuditTrailScope): Promise<ResponseEnvelope<FinanceAuditTrailEntry[]>>;
27
+ }
@@ -0,0 +1,40 @@
1
+ import type { ResponseEnvelope } from 'ofcore';
2
+ import type { FinanceLedgerScope } from './FiscalContract.js';
3
+ export type FinanceCashBankMovementDirection = 'in' | 'out' | 'transfer_in' | 'transfer_out';
4
+ export type FinanceCashBankMovementKind = 'external' | 'internal_transfer' | 'reversal';
5
+ export type FinanceCashBankMovementLifecycleStatus = 'posted' | 'reversal_posted';
6
+ export interface FinanceCashBankMovementScope extends FinanceLedgerScope {
7
+ trackedAccountIds: string[];
8
+ }
9
+ export interface FinanceCashBankMovementEntry {
10
+ journalId: string;
11
+ tenantId?: string;
12
+ branchId?: string;
13
+ financeDomainId?: string;
14
+ ledgerProfileId?: string;
15
+ occurredAt: string;
16
+ reference?: string;
17
+ evidenceRef?: string;
18
+ accountId: string;
19
+ direction: FinanceCashBankMovementDirection;
20
+ movementKind: FinanceCashBankMovementKind;
21
+ lifecycleStatus: FinanceCashBankMovementLifecycleStatus;
22
+ amount: number;
23
+ signedAmount: number;
24
+ sourceJournalId?: string;
25
+ counterpartAccountIds: string[];
26
+ trackedAccountIdsInJournal: string[];
27
+ }
28
+ export interface FinanceCashBankMovementSummary {
29
+ totalInflow: number;
30
+ totalOutflow: number;
31
+ totalTransferIn: number;
32
+ totalTransferOut: number;
33
+ netExternalMovement: number;
34
+ netByTrackedAccountId: Record<string, number>;
35
+ entries: FinanceCashBankMovementEntry[];
36
+ }
37
+ export interface FinanceCashBankMovementServiceContractV2 {
38
+ listCashBankMovements(scope: FinanceCashBankMovementScope): Promise<ResponseEnvelope<FinanceCashBankMovementEntry[]>>;
39
+ summarizeCashBankMovements(scope: FinanceCashBankMovementScope): Promise<ResponseEnvelope<FinanceCashBankMovementSummary>>;
40
+ }
@@ -0,0 +1,44 @@
1
+ import type { ScopeRef } from 'ofcore';
2
+ export type FinanceComplianceExportDatasetFormat = 'json' | 'csv';
3
+ export type FinanceComplianceExportDatasetSemantic = 'trial_balance' | 'income_statement' | 'balance_sheet' | 'open_items' | 'aging_summary' | 'reconciliation' | 'cash_movements' | 'tax_lines' | 'custom';
4
+ export interface FinanceComplianceExportPeriod {
5
+ from: string | null;
6
+ to: string | null;
7
+ label: string | null;
8
+ }
9
+ export interface FinanceComplianceExportDatasetInput {
10
+ key: string;
11
+ fileName: string;
12
+ format: FinanceComplianceExportDatasetFormat;
13
+ semantic?: FinanceComplianceExportDatasetSemantic;
14
+ contentType?: string;
15
+ payload: unknown;
16
+ }
17
+ export interface FinanceComplianceExportDatasetDescriptor {
18
+ key: string;
19
+ fileName: string;
20
+ format: FinanceComplianceExportDatasetFormat;
21
+ semantic: FinanceComplianceExportDatasetSemantic;
22
+ contentType: string;
23
+ recordCount: number;
24
+ checksum: string;
25
+ }
26
+ export interface FinanceComplianceExportContract extends ScopeRef {
27
+ contractVersion: 'fcx-v1';
28
+ financeDomainId?: string;
29
+ ledgerProfileId?: string;
30
+ generatedAt: string;
31
+ period: FinanceComplianceExportPeriod;
32
+ currency: {
33
+ baseCurrencyCode: string;
34
+ };
35
+ datasets: FinanceComplianceExportDatasetDescriptor[];
36
+ summary: {
37
+ datasetCount: number;
38
+ totalRecordCount: number;
39
+ };
40
+ }
41
+ export interface FinanceComplianceExportBundle {
42
+ contract: FinanceComplianceExportContract;
43
+ files: Record<string, string>;
44
+ }
@@ -3,6 +3,7 @@ import type { FinanceAccountType } from './AccountContract.js';
3
3
  export interface FiscalPeriod extends ScopeRef {
4
4
  id: string;
5
5
  financeDomainId?: string;
6
+ ledgerProfileId?: string;
6
7
  code: string;
7
8
  startDate: string;
8
9
  endDate: string;
@@ -1,10 +1,16 @@
1
1
  import type { ResponseEnvelope, ScopeRef } from 'ofcore';
2
2
  import type { FinanceLedgerScope } from './FiscalContract.js';
3
+ import type { FinanceOpenItemType } from './OpenItemContract.js';
3
4
  export interface JournalLineInput {
4
5
  accountId: string;
5
6
  debit: number;
6
7
  credit: number;
7
8
  memo?: string;
9
+ openItemId?: string;
10
+ openItemType?: FinanceOpenItemType;
11
+ counterpartyRef?: string;
12
+ documentRef?: string;
13
+ dueAt?: string;
8
14
  }
9
15
  export interface JournalDraftInput extends ScopeRef {
10
16
  id: string;
@@ -0,0 +1,48 @@
1
+ import type { ResponseEnvelope, ScopeRef } from 'ofcore';
2
+ import type { FinanceLedgerScope } from './FiscalContract.js';
3
+ export type FinanceOpenItemType = 'receivable' | 'payable';
4
+ export interface FinanceOpenItemScope extends FinanceLedgerScope {
5
+ openItemType?: FinanceOpenItemType;
6
+ counterpartyRef?: string;
7
+ includeSettled?: boolean;
8
+ }
9
+ export interface FinanceOpenItemPosition extends ScopeRef {
10
+ financeDomainId?: string;
11
+ ledgerProfileId: string;
12
+ openItemId: string;
13
+ openItemType: FinanceOpenItemType;
14
+ accountId: string;
15
+ counterpartyRef?: string;
16
+ documentRef?: string;
17
+ dueAt?: string;
18
+ originatedAt: string;
19
+ lastActivityAt: string;
20
+ originalAmount: number;
21
+ settledAmount: number;
22
+ outstandingAmount: number;
23
+ status: 'open' | 'settled' | 'overpaid';
24
+ }
25
+ export interface FinanceOpenItemAgingBucket {
26
+ key: string;
27
+ label: string;
28
+ minDaysPastDue?: number;
29
+ maxDaysPastDue?: number;
30
+ }
31
+ export interface FinanceOpenItemAgingQuery extends FinanceOpenItemScope {
32
+ asOf: string;
33
+ buckets?: FinanceOpenItemAgingBucket[];
34
+ }
35
+ export interface FinanceOpenItemAgingBucketResult extends FinanceOpenItemAgingBucket {
36
+ amount: number;
37
+ itemCount: number;
38
+ }
39
+ export interface FinanceOpenItemAgingSummary {
40
+ asOf: string;
41
+ openItemType?: FinanceOpenItemType;
42
+ totalOutstanding: number;
43
+ buckets: FinanceOpenItemAgingBucketResult[];
44
+ }
45
+ export interface FinanceOpenItemServiceContractV2 {
46
+ listOpenItems(scope?: FinanceOpenItemScope): Promise<ResponseEnvelope<FinanceOpenItemPosition[]>>;
47
+ getOpenItemAging(query: FinanceOpenItemAgingQuery): Promise<ResponseEnvelope<FinanceOpenItemAgingSummary>>;
48
+ }
@@ -0,0 +1,53 @@
1
+ import type { ResponseEnvelope, ScopeRef } from 'ofcore';
2
+ import type { FinanceOpenItemScope, FinanceOpenItemType } from './OpenItemContract.js';
3
+ export type FinanceReconciliationStatus = 'matched' | 'missing' | 'under' | 'over' | 'mismatch';
4
+ export type FinanceReconciliationLifecycleStatus = 'resolved' | 'unresolved' | 'exception' | 'writeoff_candidate';
5
+ export type FinanceReconciliationSuggestedAction = 'none' | 'collect_follow_up' | 'investigate' | 'refund_or_apply_credit' | 'write_off_review';
6
+ export interface FinanceObservedSettlementItem {
7
+ openItemId: string;
8
+ openItemType?: FinanceOpenItemType;
9
+ observedAmount: number;
10
+ observedAt?: string;
11
+ reference?: string;
12
+ counterpartyRef?: string;
13
+ documentRef?: string;
14
+ }
15
+ export interface FinanceOpenItemReconciliationInput extends FinanceOpenItemScope {
16
+ observations: FinanceObservedSettlementItem[];
17
+ toleranceAmount?: number;
18
+ asOf?: string;
19
+ writeOffPastDueDays?: number;
20
+ }
21
+ export interface FinanceOpenItemReconciliationRow extends ScopeRef {
22
+ financeDomainId?: string;
23
+ ledgerProfileId?: string;
24
+ openItemId: string;
25
+ openItemType?: FinanceOpenItemType;
26
+ accountId?: string;
27
+ counterpartyRef?: string;
28
+ documentRef?: string;
29
+ dueAt?: string;
30
+ expectedAmount: number;
31
+ observedAmount: number;
32
+ varianceAmount: number;
33
+ status: FinanceReconciliationStatus;
34
+ lifecycleStatus: FinanceReconciliationLifecycleStatus;
35
+ suggestedAction: FinanceReconciliationSuggestedAction;
36
+ reason?: string;
37
+ pastDueDays?: number;
38
+ observedReferences: string[];
39
+ }
40
+ export interface FinanceOpenItemReconciliationSummary {
41
+ openItemType?: FinanceOpenItemType;
42
+ totalExpectedAmount: number;
43
+ totalObservedAmount: number;
44
+ totalVarianceAmount: number;
45
+ resolvedCount: number;
46
+ unresolvedCount: number;
47
+ exceptionCount: number;
48
+ writeoffCandidateCount: number;
49
+ rows: FinanceOpenItemReconciliationRow[];
50
+ }
51
+ export interface FinanceReconciliationServiceContractV2 {
52
+ reconcileOpenItems(input: FinanceOpenItemReconciliationInput): Promise<ResponseEnvelope<FinanceOpenItemReconciliationSummary>>;
53
+ }
@@ -0,0 +1,14 @@
1
+ import type { JournalLineInput } from './JournalContract.js';
2
+ export type FinanceTaxPostingDirection = 'payable' | 'receivable';
3
+ export interface FinanceTaxComponentInput {
4
+ taxCode?: string;
5
+ amount: number;
6
+ accountId: string;
7
+ direction: FinanceTaxPostingDirection;
8
+ memo?: string;
9
+ }
10
+ export interface FinanceTaxPostingInput {
11
+ components: FinanceTaxComponentInput[];
12
+ memoPrefix?: string;
13
+ }
14
+ export declare function buildFinanceTaxPostingLines(input: FinanceTaxPostingInput): JournalLineInput[];
package/dist/index.d.ts CHANGED
@@ -5,9 +5,15 @@ export * from './services/OffinanceEnvelopeService.js';
5
5
  export * from './services/responseEnvelope.js';
6
6
  export * from './contracts/AccountContract.js';
7
7
  export * from './contracts/JournalContract.js';
8
+ export * from './contracts/OpenItemContract.js';
9
+ export * from './contracts/ReconciliationContract.js';
10
+ export * from './contracts/ComplianceExportContract.js';
11
+ export * from './contracts/CashMovementContract.js';
12
+ export * from './contracts/AuditTrailContract.js';
8
13
  export * from './contracts/FiscalContract.js';
9
14
  export * from './contracts/BudgetContract.js';
10
15
  export * from './contracts/AdapterContract.js';
16
+ export * from './contracts/TaxContract.js';
11
17
  export * from './adapters/builders.js';
12
18
  export * from './adapters/accountMapping.js';
13
19
  export * from './adapters/scopedBuilders.js';
@@ -16,6 +22,10 @@ export * from './reporting/financialStatements.js';
16
22
  export * from './reporting/closing.js';
17
23
  export * from './reporting/exporters.js';
18
24
  export * from './reporting/budget.js';
25
+ export * from './reporting/openItems.js';
26
+ export * from './reporting/reconciliation.js';
27
+ export * from './reporting/complianceExport.js';
28
+ export * from './reporting/cashMovements.js';
19
29
  export * from './events/catalog.js';
20
30
  export * from './events/replay.js';
21
31
  export * from './domain/chartOfAccounts.js';
package/dist/index.esm.js CHANGED
@@ -1,2 +1,3 @@
1
- function D(r){if(!Array.isArray(r)||r.length===0)return{ok:!1,totalDebit:0,totalCredit:0,reason:"JOURNAL_LINES_EMPTY"};let e=0,t=0;for(let n of r){if(!n||!n.accountId)return{ok:!1,totalDebit:e,totalCredit:t,reason:"JOURNAL_ACCOUNT_REQUIRED"};if(n.debit<0||n.credit<0)return{ok:!1,totalDebit:e,totalCredit:t,reason:"JOURNAL_NEGATIVE_AMOUNT"};e+=n.debit,t+=n.credit}return Math.abs(e-t)>1e-6?{ok:!1,totalDebit:e,totalCredit:t,reason:"JOURNAL_NOT_BALANCED"}:{ok:!0,totalDebit:e,totalCredit:t}}var R=class{constructor(e){this.state={accounts:e?.accounts??new Map,periods:e?.periods??new Map,journals:e?.journals??new Map,balances:e?.balances??new Map,rapbPlans:e?.rapbPlans??new Map}}createAccount(e){if(!e.id||!e.code||!e.name)throw new Error("FINANCE_ACCOUNT_REQUIRED_FIELDS");if(this.state.accounts.has(e.id))throw new Error("FINANCE_ACCOUNT_ALREADY_EXISTS");if(Array.from(this.state.accounts.values()).some(n=>n.code===e.code))throw new Error("FINANCE_ACCOUNT_CODE_DUPLICATE");return this.state.accounts.set(e.id,{...e}),{...e}}listAccounts(){return Array.from(this.state.accounts.values()).map(e=>({...e})).sort((e,t)=>e.code.localeCompare(t.code))}openFiscalPeriod(e){if(!e.id||!e.tenantId||!e.code||!e.startDate||!e.endDate)throw new Error("FISCAL_PERIOD_REQUIRED_FIELDS");if(this.state.periods.has(e.id))throw new Error("FISCAL_PERIOD_ALREADY_EXISTS");if(Date.parse(e.startDate)>Date.parse(e.endDate))throw new Error("FISCAL_PERIOD_INVALID_RANGE");let t={...e,status:"open"};return this.state.periods.set(t.id,t),{...t}}closeFiscalPeriod(e){let t=this.state.periods.get(e);if(!t)throw new Error("FISCAL_PERIOD_NOT_FOUND");let n={...t,status:"closed"};return this.state.periods.set(e,n),{...n}}listFiscalPeriods(){return Array.from(this.state.periods.values()).map(e=>({...e})).sort((e,t)=>e.startDate.localeCompare(t.startDate))}createJournalDraft(e){if(!e.id||!e.tenantId||!e.occurredAt)throw new Error("JOURNAL_REQUIRED_FIELDS");if(this.state.journals.has(e.id))throw new Error("JOURNAL_ALREADY_EXISTS");this.assertJournalLinesKnownAccounts(e.lines),this.assertJournalPeriodOpen(e.occurredAt);let t=D(e.lines);if(!t.ok)throw new Error(t.reason??"JOURNAL_INVALID");let n={id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,occurredAt:e.occurredAt,reference:e.reference,lines:e.lines.map(a=>({...a})),status:"draft"};return this.state.journals.set(n.id,n),{...n,lines:n.lines.map(a=>({...a}))}}postJournal(e,t=new Date().toISOString()){let n=this.state.journals.get(e);if(!n)throw new Error("JOURNAL_NOT_FOUND");if(n.status==="posted"||n.status==="reversed")return{...n,lines:n.lines.map(o=>({...o}))};this.applyLinesToBalance(n.lines);let a={...n,status:"posted",postedAt:t};return this.state.journals.set(e,a),{...a,lines:a.lines.map(o=>({...o}))}}reverseJournal(e,t){let n=this.state.journals.get(e);if(!n)throw new Error("JOURNAL_NOT_FOUND");if(n.status!=="posted")throw new Error("JOURNAL_NOT_POSTED");if(this.state.journals.has(t))throw new Error("JOURNAL_ALREADY_EXISTS");let a=n.lines.map(i=>({accountId:i.accountId,debit:i.credit,credit:i.debit,memo:i.memo})),o=this.createJournalDraft({id:t,tenantId:n.tenantId,branchId:n.branchId,financeDomainId:n.financeDomainId,ledgerProfileId:n.ledgerProfileId,occurredAt:n.occurredAt,reference:`reversal:${n.id}`,lines:a});return this.postJournal(o.id)}getTrialBalance(){return this.getTrialBalanceByScope()}getTrialBalanceByScope(e){let t=this.computeScopedBalances(e);return this.listAccounts().map(a=>{let o=t.get(a.id)??{debit:0,credit:0};return{accountId:a.id,accountCode:a.code,accountName:a.name,accountType:a.type,debit:o.debit,credit:o.credit,net:o.debit-o.credit}})}listJournals(e){return Array.from(this.state.journals.values()).filter(t=>this.matchesScope(t,e)).map(t=>({...t,lines:t.lines.map(n=>({...n}))})).sort((t,n)=>t.occurredAt.localeCompare(n.occurredAt))}assertJournalLinesKnownAccounts(e){for(let t of e)if(!this.state.accounts.has(t.accountId))throw new Error("JOURNAL_ACCOUNT_NOT_FOUND")}assertJournalPeriodOpen(e){if(this.state.periods.size===0)return;let t=this.findPeriodByDate(e);if(!t)throw new Error("FISCAL_PERIOD_NOT_FOUND_FOR_DATE");if(t.status!=="open")throw new Error("FISCAL_PERIOD_CLOSED")}findPeriodByDate(e){let t=Date.parse(e);for(let n of this.state.periods.values()){let a=Date.parse(n.startDate),o=Date.parse(n.endDate);if(t>=a&&t<=o)return n}return null}applyLinesToBalance(e){for(let t of e){let n=this.state.balances.get(t.accountId)??{debit:0,credit:0};n.debit+=t.debit,n.credit+=t.credit,this.state.balances.set(t.accountId,n)}}computeScopedBalances(e){if(!e||!e.tenantId&&!e.branchId&&!e.financeDomainId&&!e.ledgerProfileId&&!e.occurredFrom&&!e.occurredTo)return this.state.balances;let t=new Map;for(let n of this.state.journals.values())if(n.status==="posted"&&this.matchesScope(n,e))for(let a of n.lines){let o=t.get(a.accountId)??{debit:0,credit:0};o.debit+=a.debit,o.credit+=a.credit,t.set(a.accountId,o)}return t}matchesScope(e,t){return t?!(t.tenantId&&e.tenantId!==t.tenantId||t.branchId&&e.branchId!==t.branchId||t.financeDomainId&&e.financeDomainId!==t.financeDomainId||t.ledgerProfileId&&e.ledgerProfileId!==t.ledgerProfileId||t.occurredFrom&&e.occurredAt<t.occurredFrom||t.occurredTo&&e.occurredAt>t.occurredTo):!0}createRapb(e){if(!e.id||!e.tenantId||!e.periodCode||!e.title)throw new Error("RAPB_REQUIRED_FIELDS");if(!e.lines||e.lines.length===0)throw new Error("RAPB_LINES_REQUIRED");if(this.state.rapbPlans.has(e.id))throw new Error("RAPB_ALREADY_EXISTS");if(e.lines.some(a=>a.budgetedDebit<0||a.budgetedCredit<0))throw new Error("RAPB_NEGATIVE_AMOUNT");let t=e.lines.map(a=>{let o=this.state.accounts.get(a.accountId);if(!o)throw new Error(`RAPB_ACCOUNT_NOT_FOUND:${a.accountId}`);let i=a.budgetedDebit-a.budgetedCredit;return{accountId:a.accountId,accountCode:o.code,accountName:o.name,accountType:o.type,budgetedDebit:a.budgetedDebit,budgetedCredit:a.budgetedCredit,budgetedNet:i}}),n={id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,periodCode:e.periodCode,title:e.title,status:"draft",lines:t,notes:e.notes,createdAt:new Date().toISOString()};return this.state.rapbPlans.set(n.id,n),n}getRapb(e){return this.state.rapbPlans.get(e)??null}listRapb(e){let t=Array.from(this.state.rapbPlans.values());return e&&(e.tenantId&&(t=t.filter(n=>n.tenantId===e.tenantId)),e.periodCode&&(t=t.filter(n=>n.periodCode===e.periodCode)),e.branchId&&(t=t.filter(n=>n.branchId===e.branchId)),e.financeDomainId&&(t=t.filter(n=>n.financeDomainId===e.financeDomainId)),e.ledgerProfileId&&(t=t.filter(n=>n.ledgerProfileId===e.ledgerProfileId))),t}approveRapb(e,t){let n=this.state.rapbPlans.get(e);if(!n)throw new Error("RAPB_NOT_FOUND");let a=typeof t=="string"?t:t.approvedBy;if(n.status==="approved")throw new Error("RAPB_ALREADY_APPROVED");let o={...n,status:"approved",approvedAt:new Date().toISOString(),approvedBy:a};return this.state.rapbPlans.set(e,o),o}evaluateVariance(e){let t=this.state.rapbPlans.get(e);if(!t)throw new Error("RAPB_NOT_FOUND");let n=this.getTrialBalance(),a=new Map(n.map(d=>[d.accountId,d])),o=0,i=0,s=0,u=0,I=t.lines.map(d=>{let P=a.get(d.accountId),m=P?.debit??0,f=P?.credit??0,v=m-f;return d.accountType==="revenue"?(o+=d.budgetedCredit-d.budgetedDebit,i+=f-m):d.accountType==="expense"&&(s+=d.budgetedDebit-d.budgetedCredit,u+=m-f),{accountId:d.accountId,accountCode:d.accountCode,accountName:d.accountName,accountType:d.accountType,budgetedDebit:d.budgetedDebit,budgetedCredit:d.budgetedCredit,budgetedNet:d.budgetedNet,actualDebit:m,actualCredit:f,actualNet:v,varianceDebit:m-d.budgetedDebit,varianceCredit:f-d.budgetedCredit,varianceNet:v-d.budgetedNet}}),A=o-s,S=i-u;return{rapbId:e,periodCode:t.periodCode,evaluatedAt:new Date().toISOString(),lines:I,totalBudgetedRevenue:o,totalActualRevenue:i,totalBudgetedExpense:s,totalActualExpense:u,budgetedNetIncome:A,actualNetIncome:S,netVariance:S-A}}};import{CoreRuntime as ae}from"ofcore";import{InMemoryDbAdapter as oe}from"ofcore";import{asReadonlyStore as ie,createStore as ce}from"ofcore";var c={accounts:"ofinance_accounts",periods:"ofinance_periods",journals:"ofinance_journals",journalLines:"ofinance_journal_lines",rapbPlans:"ofinance_rapb_plans",rapbLines:"ofinance_rapb_lines",histories:"ofinance_histories"},ee=[{name:c.accounts,columns:[{name:"id",type:"string"},{name:"code",type:"string",isIndexed:!0},{name:"name",type:"string"},{name:"type",type:"string",isIndexed:!0},{name:"currency",type:"string"},{name:"isActive",type:"boolean",isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:c.periods,columns:[{name:"id",type:"string"},{name:"tenantId",type:"string",isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"code",type:"string",isIndexed:!0},{name:"startDate",type:"string",isIndexed:!0},{name:"endDate",type:"string",isIndexed:!0},{name:"status",type:"string",isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:c.journals,columns:[{name:"id",type:"string"},{name:"tenantId",type:"string",isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"occurredAt",type:"string",isIndexed:!0},{name:"reference",type:"string",isOptional:!0,isIndexed:!0},{name:"evidenceRef",type:"string",isOptional:!0,isIndexed:!0},{name:"status",type:"string",isIndexed:!0},{name:"postedAt",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:c.journalLines,columns:[{name:"id",type:"string"},{name:"journalId",type:"string",isIndexed:!0},{name:"accountId",type:"string",isIndexed:!0},{name:"debit",type:"number"},{name:"credit",type:"number"},{name:"memo",type:"string",isOptional:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:c.rapbPlans,columns:[{name:"id",type:"string"},{name:"tenantId",type:"string",isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"periodCode",type:"string",isIndexed:!0},{name:"title",type:"string",isIndexed:!0},{name:"status",type:"string",isIndexed:!0},{name:"notes",type:"string",isOptional:!0},{name:"createdAt",type:"string",isIndexed:!0},{name:"approvedAt",type:"string",isOptional:!0,isIndexed:!0},{name:"approvedBy",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:c.rapbLines,columns:[{name:"id",type:"string"},{name:"rapbId",type:"string",isIndexed:!0},{name:"accountId",type:"string",isIndexed:!0},{name:"accountCode",type:"string",isIndexed:!0},{name:"accountName",type:"string"},{name:"accountType",type:"string",isIndexed:!0},{name:"budgetedDebit",type:"number"},{name:"budgetedCredit",type:"number"},{name:"budgetedNet",type:"number"},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:c.histories,columns:[{name:"id",type:"string"},{name:"tableName",type:"string",isIndexed:!0},{name:"recordId",type:"string",isIndexed:!0},{name:"action",type:"string",isIndexed:!0},{name:"changes",type:"json",isOptional:!0},{name:"timestamp",type:"string",isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0}]}];function _(){return ee.map(r=>({...r,columns:r.columns.map(e=>({...e}))}))}var J=[{toVersion:1,up:async r=>{let e=_();for(let t of e)try{await r.addTable(t)}catch{}}},{toVersion:2,up:async r=>{let e=_().filter(t=>t.name==="ofinance_rapb_plans"||t.name==="ofinance_rapb_lines");for(let t of e)try{await r.addTable(t)}catch{}}},{toVersion:3,up:async r=>{try{await r.addColumn("ofinance_journals",{name:"evidenceRef",type:"string",isOptional:!0,isIndexed:!0})}catch{}}}];var te={logInfo(){},logWarn(){},logError(){}};async function w(r,e=te){e.logInfo("[offinance] starting database migration process");let t=[...J].sort((o,i)=>o.toVersion-i.toVersion),n=t.length>0?t[t.length-1].toVersion:0,a=await r.getSchemaVersion();if((a==null||a<0)&&(a=0),a>=n){e.logInfo(`[offinance] database already up-to-date at v${a}`);return}for(let o of t)o.toVersion>a&&(e.logInfo(`[offinance] applying migration v${o.toVersion}`),await o.up(r),await r.setSchemaVersion(o.toVersion),a=o.toVersion);e.logInfo(`[offinance] migration completed at v${a}`)}function l(r,e){return{data:r,meta:{request_id:e??null,timestamp:new Date().toISOString()}}}function M(r,e,t={}){return{error:{code:r,message:e,details:t.details,retryable:t.retryable,correlationId:t.correlationId,timestamp:new Date().toISOString()},meta:{request_id:t.requestId??null,timestamp:new Date().toISOString()}}}function p(r,e="FINANCE_NOT_IMPLEMENTED",t="Unhandled offinance error."){return r instanceof Error?M(e,r.message||t):M(e,t)}var T=class{constructor(e){this.legacy=e;this.accountService={createAccount:async t=>{try{return l(await this.legacy.accountService.createAccount(t))}catch(n){return p(n)}},listAccounts:async()=>{try{return l(await this.legacy.accountService.listAccounts())}catch(t){return p(t)}}},this.journalService={createJournalDraft:async t=>{try{return l(await this.legacy.journalService.createJournalDraft(t))}catch(n){return p(n)}},postJournal:async(t,n)=>{try{return l(await this.legacy.journalService.postJournal(t,n))}catch(a){return p(a)}},reverseJournal:async(t,n)=>{try{return l(await this.legacy.journalService.reverseJournal(t,n))}catch(a){return p(a)}},listJournals:async t=>{try{return l(await this.legacy.journalService.listJournals(t))}catch(n){return p(n)}}},this.fiscalService={openFiscalPeriod:async t=>{try{return l(await this.legacy.fiscalService.openFiscalPeriod(t))}catch(n){return p(n)}},closeFiscalPeriod:async t=>{try{return l(await this.legacy.fiscalService.closeFiscalPeriod(t))}catch(n){return p(n)}},listFiscalPeriods:async()=>{try{return l(await this.legacy.fiscalService.listFiscalPeriods())}catch(t){return p(t)}},getTrialBalance:async()=>{try{return l(await this.legacy.fiscalService.getTrialBalance())}catch(t){return p(t)}},getTrialBalanceByScope:async t=>{try{return l(await this.legacy.fiscalService.getTrialBalanceByScope(t))}catch(n){return p(n)}}},this.rapbService={createRapb:async t=>{try{return l(await this.legacy.rapbService.createRapb(t))}catch(n){return p(n)}},getRapb:async t=>{try{return l(await this.legacy.rapbService.getRapb(t))}catch(n){return p(n)}},listRapb:async t=>{try{return l(await this.legacy.rapbService.listRapb(t))}catch(n){return p(n)}},approveRapb:async(t,n)=>{try{return l(await this.legacy.rapbService.approveRapb(t,n))}catch(a){return p(a)}},evaluateVariance:async t=>{try{return l(await this.legacy.rapbService.evaluateVariance(t))}catch(n){return p(n)}}}}};function B(r){return new T({accountService:r,journalService:r,fiscalService:r,rapbService:r})}function b(r){return JSON.parse(JSON.stringify(r))}function g(){return new Date().toISOString()}function ne(r,e){return`${r}:${e}:${Date.now()}:${Math.random().toString(36).slice(2,8)}`}function re(r,e){return!r||r.deleted?!1:e?!(e.tenantId&&r.tenantId!==e.tenantId||e.branchId&&r.branchId!==e.branchId||e.financeDomainId&&r.financeDomainId!==e.financeDomainId||e.ledgerProfileId&&r.ledgerProfileId!==e.ledgerProfileId||e.occurredFrom&&r.occurredAt&&r.occurredAt<e.occurredFrom||e.occurredTo&&r.occurredAt&&r.occurredAt>e.occurredTo):!0}var F=class{constructor(e){this.dbAdapter=e}async createAccount(e){if(!e.id||!e.code||!e.name)throw new Error("FINANCE_ACCOUNT_REQUIRED_FIELDS");let t=await this.dbAdapter.get(c.accounts,e.id);if(t&&!t.deleted)throw new Error("FINANCE_ACCOUNT_ALREADY_EXISTS");if((await this.dbAdapter.query(c.accounts,{filters:{and:[{field:"code",value:e.code},{field:"deleted",value:!1}]}})).some(i=>i.id!==e.id))throw new Error("FINANCE_ACCOUNT_CODE_DUPLICATE");let a=g(),o={...b(e),lastModified:a,deleted:!1};return t?await this.dbAdapter.update(c.accounts,e.id,o):await this.dbAdapter.create(c.accounts,o),await this.writeHistory("accounts",e.id,"UPSERT",o),b(e)}async listAccounts(){return(await this.dbAdapter.query(c.accounts,{filters:{field:"deleted",value:!1}})).map(({lastModified:t,deleted:n,...a})=>b(a)).sort((t,n)=>t.code.localeCompare(n.code))}async createJournalDraft(e){if(!e.id||!e.tenantId||!e.occurredAt)throw new Error("JOURNAL_REQUIRED_FIELDS");if(!e.ledgerProfileId)throw new Error("JOURNAL_REQUIRED_FIELDS");let t=await this.dbAdapter.get(c.journals,e.id);if(t&&!t.deleted)throw new Error("JOURNAL_ALREADY_EXISTS");await this.assertJournalLinesKnownAccounts(e.lines),await this.assertJournalPeriodOpen(e);let n=D(e.lines);if(!n.ok)throw new Error(n.reason??"JOURNAL_INVALID");let a=g(),o={id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,occurredAt:e.occurredAt,reference:e.reference,evidenceRef:e.evidenceRef,status:"draft",postedAt:void 0,lastModified:a,deleted:!1};await this.dbAdapter.create(c.journals,o);for(let i=0;i<e.lines.length;i+=1){let s=e.lines[i],u={id:`${e.id}:line:${i}`,journalId:e.id,accountId:s.accountId,debit:s.debit,credit:s.credit,memo:s.memo,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,lastModified:a,deleted:!1};await this.dbAdapter.create(c.journalLines,u),await this.writeHistory("journal_lines",u.id,"UPSERT",u)}return await this.writeHistory("journals",e.id,"UPSERT",o),this.toJournalEntry(o,e.lines)}async postJournal(e,t=g()){let n=await this.requireJournal(e),a=await this.listJournalLines(e);if(n.status==="posted"||n.status==="reversed")return this.toJournalEntry(n,a);let o={...n,status:"posted",postedAt:t,lastModified:g()};return await this.dbAdapter.update(c.journals,e,o),await this.writeHistory("journals",e,"UPSERT",o),this.toJournalEntry(o,a)}async reverseJournal(e,t){let n=await this.requireJournal(e);if(n.status!=="posted")throw new Error("JOURNAL_NOT_POSTED");let a=await this.listJournalLines(e),o=await this.createJournalDraft({id:t,tenantId:n.tenantId,branchId:n.branchId,financeDomainId:n.financeDomainId,ledgerProfileId:n.ledgerProfileId,occurredAt:n.occurredAt,reference:`reversal:${n.id}`,evidenceRef:n.evidenceRef,lines:a.map(i=>({accountId:i.accountId,debit:i.credit,credit:i.debit,memo:i.memo}))});return this.postJournal(o.id)}async listJournals(e){let n=(await this.dbAdapter.query(c.journals,{filters:{field:"deleted",value:!1}})).filter(o=>re(o,e)).sort((o,i)=>o.occurredAt.localeCompare(i.occurredAt)),a=[];for(let o of n){let i=await this.listJournalLines(o.id);a.push(this.toJournalEntry(o,i))}return a}async openFiscalPeriod(e){if(!e.id||!e.tenantId||!e.code||!e.startDate||!e.endDate)throw new Error("FISCAL_PERIOD_REQUIRED_FIELDS");if(Date.parse(e.startDate)>Date.parse(e.endDate))throw new Error("FISCAL_PERIOD_INVALID_RANGE");let t=await this.dbAdapter.get(c.periods,e.id);if(t&&!t.deleted)throw new Error("FISCAL_PERIOD_ALREADY_EXISTS");let n=g(),a={...b(e),status:"open",lastModified:n,deleted:!1};return t?await this.dbAdapter.update(c.periods,e.id,a):await this.dbAdapter.create(c.periods,a),await this.writeHistory("periods",e.id,"UPSERT",a),this.toPeriod(a)}async closeFiscalPeriod(e){let t=await this.dbAdapter.get(c.periods,e);if(!t||t.deleted)throw new Error("FISCAL_PERIOD_NOT_FOUND");let n={...t,status:"closed",lastModified:g()};return await this.dbAdapter.update(c.periods,e,n),await this.writeHistory("periods",e,"UPSERT",n),this.toPeriod(n)}async listFiscalPeriods(){return(await this.dbAdapter.query(c.periods,{filters:{field:"deleted",value:!1}})).map(t=>this.toPeriod(t)).sort((t,n)=>t.startDate.localeCompare(n.startDate))}async getTrialBalance(){return this.getTrialBalanceByScope()}async getTrialBalanceByScope(e){let t=await this.listAccounts(),a=(await this.listJournals(e)).filter(i=>i.status==="posted"),o=new Map;for(let i of a)for(let s of i.lines){let u=o.get(s.accountId)??{debit:0,credit:0};u.debit+=Number(s.debit||0),u.credit+=Number(s.credit||0),o.set(s.accountId,u)}return t.map(i=>{let s=o.get(i.id)??{debit:0,credit:0};return{accountId:i.id,accountCode:i.code,accountName:i.name,accountType:i.type,debit:s.debit,credit:s.credit,net:s.debit-s.credit}})}async createRapb(e){if(!e.id||!e.tenantId||!e.periodCode||!e.title)throw new Error("RAPB_REQUIRED_FIELDS");if(!e.lines||e.lines.length===0)throw new Error("RAPB_LINES_REQUIRED");if(e.lines.some(i=>i.budgetedDebit<0||i.budgetedCredit<0))throw new Error("RAPB_NEGATIVE_AMOUNT");let t=await this.dbAdapter.get(c.rapbPlans,e.id);if(t&&!t.deleted)throw new Error("RAPB_ALREADY_EXISTS");let n=g(),a=[];for(let i=0;i<e.lines.length;i+=1){let s=e.lines[i],u=await this.dbAdapter.get(c.accounts,s.accountId);if(!u||u.deleted)throw new Error(`RAPB_ACCOUNT_NOT_FOUND:${s.accountId}`);a.push({id:`${e.id}:line:${i}`,rapbId:e.id,accountId:s.accountId,accountCode:u.code,accountName:u.name,accountType:u.type,budgetedDebit:s.budgetedDebit,budgetedCredit:s.budgetedCredit,budgetedNet:s.budgetedDebit-s.budgetedCredit,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,lastModified:n,deleted:!1})}let o={id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,periodCode:e.periodCode,title:e.title,status:"draft",notes:e.notes,createdAt:n,approvedAt:void 0,approvedBy:void 0,lastModified:n,deleted:!1};await this.dbAdapter.create(c.rapbPlans,o),await this.writeHistory("rapb_plans",e.id,"UPSERT",o);for(let i of a)await this.dbAdapter.create(c.rapbLines,i),await this.writeHistory("rapb_lines",i.id,"UPSERT",i);return this.toRapbPlan(o,a)}async getRapb(e){let t=await this.dbAdapter.get(c.rapbPlans,e);if(!t||t.deleted)return null;let n=await this.listRapbLines(e);return this.toRapbPlan(t,n)}async listRapb(e){let n=await this.dbAdapter.query(c.rapbPlans,{filters:{field:"deleted",value:!1}});e&&(e.tenantId&&(n=n.filter(o=>o.tenantId===e.tenantId)),e.periodCode&&(n=n.filter(o=>o.periodCode===e.periodCode)),e.branchId&&(n=n.filter(o=>o.branchId===e.branchId)),e.financeDomainId&&(n=n.filter(o=>o.financeDomainId===e.financeDomainId)),e.ledgerProfileId&&(n=n.filter(o=>o.ledgerProfileId===e.ledgerProfileId)));let a=[];for(let o of n.sort((i,s)=>i.createdAt.localeCompare(s.createdAt))){let i=await this.listRapbLines(o.id);a.push(this.toRapbPlan(o,i))}return a}async approveRapb(e,t){let n=await this.dbAdapter.get(c.rapbPlans,e);if(!n||n.deleted)throw new Error("RAPB_NOT_FOUND");if(n.status==="approved")throw new Error("RAPB_ALREADY_APPROVED");let a=typeof t=="string"?t:t.approvedBy,o={...n,status:"approved",approvedAt:g(),approvedBy:a,lastModified:g()};await this.dbAdapter.update(c.rapbPlans,e,o),await this.writeHistory("rapb_plans",e,"UPSERT",o);let i=await this.listRapbLines(e);return this.toRapbPlan(o,i)}async evaluateVariance(e){let t=await this.getRapb(e);if(!t)throw new Error("RAPB_NOT_FOUND");let n=await this.getTrialBalanceByScope({tenantId:t.tenantId,branchId:t.branchId,financeDomainId:t.financeDomainId,ledgerProfileId:t.ledgerProfileId}),a=new Map(n.map(d=>[d.accountId,d])),o=0,i=0,s=0,u=0,I=t.lines.map(d=>{let P=a.get(d.accountId),m=P?.debit??0,f=P?.credit??0,v=m-f;return d.accountType==="revenue"?(o+=d.budgetedCredit-d.budgetedDebit,i+=f-m):d.accountType==="expense"&&(s+=d.budgetedDebit-d.budgetedCredit,u+=m-f),{accountId:d.accountId,accountCode:d.accountCode,accountName:d.accountName,accountType:d.accountType,budgetedDebit:d.budgetedDebit,budgetedCredit:d.budgetedCredit,budgetedNet:d.budgetedNet,actualDebit:m,actualCredit:f,actualNet:v,varianceDebit:m-d.budgetedDebit,varianceCredit:f-d.budgetedCredit,varianceNet:v-d.budgetedNet}}),A=o-s,S=i-u;return{rapbId:e,periodCode:t.periodCode,evaluatedAt:g(),lines:I,totalBudgetedRevenue:o,totalActualRevenue:i,totalBudgetedExpense:s,totalActualExpense:u,budgetedNetIncome:A,actualNetIncome:S,netVariance:S-A}}async assertJournalLinesKnownAccounts(e){for(let t of e){let n=await this.dbAdapter.get(c.accounts,t.accountId);if(!n||n.deleted)throw new Error("JOURNAL_ACCOUNT_NOT_FOUND")}}async assertJournalPeriodOpen(e){let t=await this.dbAdapter.query(c.periods,{filters:{field:"deleted",value:!1}});if(t.length===0)return;let n=t.find(a=>!(a.tenantId!==e.tenantId||Date.parse(a.startDate)>Date.parse(e.occurredAt)||Date.parse(a.endDate)<Date.parse(e.occurredAt)||e.ledgerProfileId&&a.ledgerProfileId&&a.ledgerProfileId!==e.ledgerProfileId||e.financeDomainId&&a.financeDomainId&&a.financeDomainId!==e.financeDomainId));if(!n)throw new Error("FISCAL_PERIOD_NOT_FOUND_FOR_DATE");if(n.status!=="open")throw new Error("FISCAL_PERIOD_CLOSED")}async requireJournal(e){let t=await this.dbAdapter.get(c.journals,e);if(!t||t.deleted)throw new Error("JOURNAL_NOT_FOUND");return t}async listJournalLines(e){return(await this.dbAdapter.query(c.journalLines,{filters:{and:[{field:"journalId",value:e},{field:"deleted",value:!1}]}})).sort((n,a)=>n.id.localeCompare(a.id))}async listRapbLines(e){return(await this.dbAdapter.query(c.rapbLines,{filters:{and:[{field:"rapbId",value:e},{field:"deleted",value:!1}]}})).sort((n,a)=>n.id.localeCompare(a.id))}toJournalEntry(e,t){let{lastModified:n,deleted:a,...o}=e;return{...b(o),lines:t.map(i=>b(i))}}toPeriod(e){let{lastModified:t,deleted:n,...a}=e;return b(a)}toRapbPlan(e,t){let{lastModified:n,deleted:a,...o}=e;return{...b(o),lines:t.map(({id:i,rapbId:s,lastModified:u,deleted:I,...A})=>b(A))}}async writeHistory(e,t,n,a){let o=a,i={id:ne(e,t),tableName:e,recordId:t,action:n,changes:b(o),timestamp:g(),tenantId:typeof o.tenantId=="string"?o.tenantId:void 0,branchId:typeof o.branchId=="string"?o.branchId:void 0,financeDomainId:typeof o.financeDomainId=="string"?o.financeDomainId:void 0,ledgerProfileId:typeof o.ledgerProfileId=="string"?o.ledgerProfileId:void 0};await this.dbAdapter.create(c.histories,i)}};async function U(r){await w(r);let e=new F(r);return{financeService:B({createAccount:e.createAccount.bind(e),listAccounts:e.listAccounts.bind(e),createJournalDraft:e.createJournalDraft.bind(e),postJournal:e.postJournal.bind(e),reverseJournal:e.reverseJournal.bind(e),listJournals:e.listJournals.bind(e),openFiscalPeriod:e.openFiscalPeriod.bind(e),closeFiscalPeriod:e.closeFiscalPeriod.bind(e),listFiscalPeriods:e.listFiscalPeriods.bind(e),getTrialBalance:e.getTrialBalance.bind(e),getTrialBalanceByScope:e.getTrialBalanceByScope.bind(e),createRapb:e.createRapb.bind(e),getRapb:e.getRapb.bind(e),listRapb:e.listRapb.bind(e),approveRapb:e.approveRapb.bind(e),evaluateVariance:e.evaluateVariance.bind(e)})}}var L=class{constructor(e,t){this.runtime=e;this.runtimeStateStore=t;this.runtimeStore=ie(this.runtimeStateStore)}static builder(){return new N}get registry(){return this.runtime.registry}async start(e={}){this.runtimeStateStore.setState({phase:"starting",started:!1,lastError:null,lastTransitionAt:new Date().toISOString(),startCount:this.runtimeStateStore.getState().startCount,stopCount:this.runtimeStateStore.getState().stopCount});try{await this.runtime.start(e),this.domainServices=this.runtime.domainServices,this.runtimeStateStore.setState(t=>({...t,phase:"started",started:!0,startCount:t.startCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(t){throw this.runtimeStateStore.setState(n=>({...n,phase:"error",started:!1,lastError:t instanceof Error?t.message:String(t),lastTransitionAt:new Date().toISOString()})),t}}async stop(){this.runtimeStateStore.setState(e=>({...e,phase:"stopping",started:this.runtime.isStarted(),lastError:null,lastTransitionAt:new Date().toISOString()}));try{await this.runtime.stop(),this.runtimeStateStore.setState(e=>({...e,phase:"stopped",started:!1,stopCount:e.stopCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(e){throw this.runtimeStateStore.setState(t=>({...t,phase:"error",started:this.runtime.isStarted(),lastError:e instanceof Error?e.message:String(e),lastTransitionAt:new Date().toISOString()})),e}}isStarted(){return this.runtime.isStarted()}},N=class{constructor(){this.runtimeBuilder=ae.builder();this.runtimeHooks={};this.runtimeBuilder.withDbAdapter(()=>new oe)}withPlatformAdapter(e){return this.runtimeBuilder.withPlatformAdapter(e),this}withDbAdapter(e){return this.runtimeBuilder.withDbAdapter(e),this}withHttpAdapter(e){return this.runtimeBuilder.withHttpAdapter(e),this}withSocketAdapter(e){return this.runtimeBuilder.withSocketAdapter(e),this}withLoggerAdapter(e){return this.runtimeBuilder.withLoggerAdapter(e),this}withActivitySink(e){return this.runtimeBuilder.withActivitySink(e),this}withExtension(e,t){return this.runtimeBuilder.withExtension(e,t),this}withDomainServicesFactory(e){return this.domainServicesFactory=e,this}withRuntimeHooks(e){return this.runtimeHooks={...this.runtimeHooks,...e},this}build(){let e=ce({phase:"idle",started:!1,startCount:0,stopCount:0,lastError:null,lastTransitionAt:new Date().toISOString()}),t={runMigrations:async a=>{let o=a.registry?.dbAdapter;if(!o)throw new Error("OFINANCE_DB_ADAPTER_REQUIRED");await w(o,a.registry?.loggerAdapter),this.runtimeHooks.runMigrations&&await this.runtimeHooks.runMigrations(a)},...this.runtimeHooks,createDomainServices:async a=>{if(this.domainServicesFactory)return this.domainServicesFactory();let o=a.registry?.dbAdapter;if(!o)throw new Error("OFINANCE_DB_ADAPTER_REQUIRED");return U(o)}};this.runtimeBuilder.withHooks(t);let n=this.runtimeBuilder.build();return new L(n,e)}};function y(r,e,t){return{id:r.journalId,tenantId:r.tenantId,branchId:r.branchId,financeDomainId:r.financeDomainId,ledgerProfileId:r.ledgerProfileId,occurredAt:r.occurredAt,reference:t?`${r.reference??""}${t}`:r.reference,evidenceRef:r.evidenceRef,lines:e}}function h(r,e){if(!Number.isFinite(r)||r<=0)throw new Error(e)}function j(r,e){h(e.grossAmount,"POS_SALE_INVALID_GROSS_AMOUNT");let t=e.discountAmount??0,n=e.taxAmount??0;if(t<0||n<0)throw new Error("POS_SALE_NEGATIVE_COMPONENT");let a=e.grossAmount,o=a-t+n,i=[{accountId:e.paymentAccountId,debit:o,credit:0,memo:"POS sale payment"},{accountId:e.revenueAccountId,debit:0,credit:a,memo:"POS sale revenue"}];if(t>0){if(!e.discountAccountId)throw new Error("POS_SALE_DISCOUNT_ACCOUNT_REQUIRED");i.push({accountId:e.discountAccountId,debit:t,credit:0,memo:"POS sale discount"})}if(n>0){if(!e.taxPayableAccountId)throw new Error("POS_SALE_TAX_ACCOUNT_REQUIRED");i.push({accountId:e.taxPayableAccountId,debit:0,credit:n,memo:"POS sale tax payable"})}return y(r,i)}function V(r,e){return h(e.principalAmount,"COOP_LOAN_INVALID_PRINCIPAL"),y(r,[{accountId:e.receivableAccountId,debit:e.principalAmount,credit:0,memo:"Loan receivable principal"},{accountId:e.cashAccountId,debit:0,credit:e.principalAmount,memo:"Loan cash out"}])}function k(r,e){return h(e.amount,"COOP_SAVING_INVALID_AMOUNT"),y(r,[{accountId:e.cashAccountId,debit:e.amount,credit:0,memo:"Saving deposit cash in"},{accountId:e.savingLiabilityAccountId,debit:0,credit:e.amount,memo:"Saving liability increase"}])}function H(r,e){return h(e.amount,"COOP_SAVING_WITHDRAWAL_INVALID_AMOUNT"),y(r,[{accountId:e.savingLiabilityAccountId,debit:e.amount,credit:0,memo:"Saving liability decrease"},{accountId:e.cashAccountId,debit:0,credit:e.amount,memo:"Saving withdrawal cash out"}])}function q(r,e){h(e.principalAmount,"COOP_LOAN_REPAYMENT_INVALID_PRINCIPAL");let t=e.serviceAmount??0,n=e.penaltyAmount??0;if(t<0||n<0)throw new Error("COOP_LOAN_REPAYMENT_NEGATIVE_COMPONENT");if(t>0&&!e.serviceRevenueAccountId)throw new Error("COOP_LOAN_REPAYMENT_SERVICE_ACCOUNT_REQUIRED");if(n>0&&!e.penaltyRevenueAccountId)throw new Error("COOP_LOAN_REPAYMENT_PENALTY_ACCOUNT_REQUIRED");let a=e.principalAmount+t+n,o=[{accountId:e.cashAccountId,debit:a,credit:0,memo:"Loan repayment cash in"},{accountId:e.receivableAccountId,debit:0,credit:e.principalAmount,memo:"Loan receivable principal repayment"}];return t>0&&o.push({accountId:e.serviceRevenueAccountId,debit:0,credit:t,memo:"Loan service revenue"}),n>0&&o.push({accountId:e.penaltyRevenueAccountId,debit:0,credit:n,memo:"Loan penalty revenue"}),y(r,o)}function Ue(r,e){if(h(e.amount,"COOP_SHU_PARTICIPATION_INVALID_AMOUNT"),!r.evidenceRef?.trim())throw new Error("COOP_SHU_PARTICIPATION_EVIDENCE_REQUIRED");return y(r,[{accountId:e.debitAccountId,debit:e.amount,credit:0,memo:e.memo??"Coop SHU participation manual recap debit"},{accountId:e.creditAccountId,debit:0,credit:e.amount,memo:e.memo??"Coop SHU participation manual recap credit"}])}function $(r,e){return e?{...r,...e}:{...r}}function C(r){let e=r.tenantId?r.scopedMapping.byTenant?.[r.tenantId]:void 0,t=r.tenantId&&r.branchId?`${r.tenantId}:${r.branchId}`:"",n=t?r.scopedMapping.byBranch?.[t]:void 0;return $($(r.scopedMapping.default,e),n)}function Q(r){return C(r)}function W(r){return C(r)}function Y(r){return C(r)}function G(r){return C(r)}function X(r){return C(r)}function qe(r,e){let{scopedAccountMapping:t,...n}=e,a=Q({tenantId:r.tenantId,branchId:r.branchId,scopedMapping:t});return j(r,{...n,...a})}function $e(r,e){let{scopedAccountMapping:t,...n}=e,a=W({tenantId:r.tenantId,branchId:r.branchId,scopedMapping:t});return V(r,{...n,...a})}function Qe(r,e){let{scopedAccountMapping:t,...n}=e,a=G({tenantId:r.tenantId,branchId:r.branchId,scopedMapping:t});return k(r,{...n,...a})}function We(r,e){let{scopedAccountMapping:t,...n}=e,a=X({tenantId:r.tenantId,branchId:r.branchId,scopedMapping:t});return H(r,{...n,...a})}function Ye(r,e){let{scopedAccountMapping:t,...n}=e,a=Y({tenantId:r.tenantId,branchId:r.branchId,scopedMapping:t});return q(r,{...n,...a})}function O(r){return!!(r&&typeof r=="object"&&r.error)}function x(r){return r.startsWith("ofinance_")?`offinance_${r.slice(9)}`:r}async function se(r,e,t){let n=await r.accountService.listAccounts();if(O(n))throw new Error(n.error.message||n.error.code||"FINANCE_ACCOUNT_LIST_FAILED");let a=new Set((n.data||[]).map(o=>o.id));for(let o of e){if(a.has(o.id))continue;let i=await r.accountService.createAccount(o);if(O(i))throw new Error(i.error.message||i.error.code||"FINANCE_ACCOUNT_CREATE_FAILED");await t?.({changeId:`offinance:account:${o.id}`,entity:"FinanceAccount",table:x(c.accounts),type:"CREATE",data:o})}}async function K(r,e,t){return r.query(e,{filters:{and:t}})}async function de(r,e,t){if(!t)return;let n=await K(r,c.journals,[{field:"id",value:e.id}]),a=await K(r,c.journalLines,[{field:"journalId",value:e.id}]);n.length===0&&(n=[{id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,occurredAt:e.occurredAt,reference:e.reference,status:e.status,postedAt:e.postedAt,lastModified:e.postedAt||e.occurredAt,deleted:!1}]),a.length===0&&(a=e.lines.map((o,i)=>({id:`${e.id}:line:${i}`,journalId:e.id,accountId:o.accountId,debit:o.debit,credit:o.credit,memo:o.memo,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,lastModified:e.postedAt||e.occurredAt,deleted:!1})));for(let o of n)await t({changeId:`offinance:journal:${o.id}`,entity:"FinanceJournalEntry",table:x(c.journals),type:"CREATE",data:o});for(let o of a)await t({changeId:`offinance:journal-line:${o.id}`,entity:"FinanceJournalLine",table:x(c.journalLines),type:"CREATE",data:o})}function Ke(r){return async e=>{let t=r.resolveFinanceServices();if(!t)throw new Error(r.missingServicesErrorCode||"FINANCE_SERVICES_UNAVAILABLE");let n=r.resolveLedgerProfileId().trim();if(!n)throw new Error(r.missingLedgerProfileErrorCode||"FINANCE_LEDGER_PROFILE_REQUIRED");let a=r.resolveSyncEnqueuer?.()??null;await se(t,r.requiredAccounts,a);let o=r.buildJournalDraft(e,n),i=await t.journalService.createJournalDraft(o);if(O(i)&&i.error.code!=="JOURNAL_ALREADY_EXISTS")throw new Error(i.error.message||i.error.code||"FINANCE_JOURNAL_CREATE_FAILED");let s=await t.journalService.postJournal(o.id,o.occurredAt);if(O(s))throw new Error(s.error.message||s.error.code||"FINANCE_JOURNAL_POST_FAILED");await de(r.dbAdapter,s.data,a)}}function ue(r){switch(r.accountType){case"asset":case"expense":return r.debit-r.credit;case"liability":case"equity":case"revenue":return r.credit-r.debit;default:return 0}}function E(r,e){return r.filter(t=>t.accountType===e).reduce((t,n)=>t+ue(n),0)}function Ze(r){let e=E(r,"revenue"),t=E(r,"expense");return{revenue:e,expense:t,netIncome:e-t}}function et(r){return{assets:E(r,"asset"),liabilities:E(r,"liability"),equity:E(r,"equity")}}function z(r){return r.accountType==="revenue"?r.credit-r.debit:r.accountType==="expense"?r.debit-r.credit:0}function nt(r){let e=r.filter(n=>n.accountType==="revenue").reduce((n,a)=>n+Math.max(0,z(a)),0),t=r.filter(n=>n.accountType==="expense").reduce((n,a)=>n+Math.max(0,z(a)),0);return{operatingInflow:e,operatingOutflow:t,netOperatingCashflow:e-t}}function rt(r,e){let t=[],n=0;for(let a of e){if(a.accountType==="revenue"){let o=a.credit-a.debit;o>0&&(t.push({accountId:a.accountId,debit:o,credit:0,memo:"Close revenue account"}),n+=o)}if(a.accountType==="expense"){let o=a.debit-a.credit;o>0&&(t.push({accountId:a.accountId,debit:0,credit:o,memo:"Close expense account"}),n-=o)}}return n>0?t.push({accountId:r.retainedEarningsAccountId,debit:0,credit:n,memo:"Retained earnings from period close"}):n<0&&t.push({accountId:r.retainedEarningsAccountId,debit:Math.abs(n),credit:0,memo:"Retained earnings from period close"}),{id:r.journalId,tenantId:r.tenantId,branchId:r.branchId,financeDomainId:r.financeDomainId,ledgerProfileId:r.ledgerProfileId,occurredAt:r.occurredAt,reference:r.reference,lines:t}}function ot(r){return{version:"v1",generatedAt:r.generatedAt??new Date().toISOString(),payload:{trialBalance:r.trialBalance.map(e=>({...e})),incomeStatement:{...r.incomeStatement},balanceSheet:{...r.balanceSheet}}}}function le(r){return r.accountType==="revenue"?r.credit-r.debit:r.accountType==="expense"?r.debit-r.credit:0}function Z(r,e){return e===0?r===0?1:0:Number((r/e).toFixed(4))}function ct(r,e){let t=e.map(a=>{let s=((a.accountCodes?.length?r.filter(I=>a.accountCodes?.includes(I.accountCode)):null)??r.filter(I=>a.accountType?I.accountType===a.accountType:!1)).reduce((I,A)=>I+le(A),0),u=s-a.plannedAmount;return{id:a.id,label:a.label,plannedAmount:a.plannedAmount,actualAmount:s,varianceAmount:u,achievementRatio:Z(s,a.plannedAmount)}}),n=t.reduce((a,o)=>(a.plannedAmount+=o.plannedAmount,a.actualAmount+=o.actualAmount,a.varianceAmount+=o.varianceAmount,a),{plannedAmount:0,actualAmount:0,varianceAmount:0});return{rows:t,totals:{...n,achievementRatio:Z(n.actualAmount,n.plannedAmount)}}}function pe(r,e){switch(e.type){case"finance.account.created":r.createAccount(e.payload);return;case"finance.period.opened":r.openFiscalPeriod(e.payload);return;case"finance.period.closed":r.closeFiscalPeriod(e.payload.periodId);return;case"finance.journal.drafted":r.createJournalDraft(e.payload);return;case"finance.journal.posted":r.postJournal(e.payload.journalId,e.payload.postedAt);return;case"finance.journal.reversed":r.reverseJournal(e.payload.journalId,e.payload.reversalId);return;default:throw new Error("FINANCE_EVENT_UNSUPPORTED")}}function ut(r){let e=new R;for(let t of r)pe(e,t);return e}var me=[{id:"coa-cash",code:"1101",name:"Kas",type:"asset"},{id:"coa-bank",code:"1102",name:"Bank",type:"asset"},{id:"coa-ar",code:"1201",name:"Piutang Usaha",type:"asset"},{id:"coa-ap",code:"2101",name:"Utang Usaha",type:"liability"},{id:"coa-retained",code:"3201",name:"Laba Ditahan",type:"equity"},{id:"coa-revenue",code:"4101",name:"Pendapatan Operasional",type:"revenue"},{id:"coa-expense",code:"5101",name:"Biaya Operasional",type:"expense"}];function pt(r="IDR"){return me.map(e=>({id:e.id,code:e.code,name:e.name,type:e.type,currency:r,isActive:!0}))}var fe=[{id:"coop-coa-cash",code:"1101",name:"Kas",type:"asset"},{id:"coop-coa-bank",code:"1102",name:"Bank",type:"asset"},{id:"coop-coa-loan-ar",code:"1201",name:"Piutang Pinjaman Anggota",type:"asset"},{id:"coop-coa-other-ar",code:"1202",name:"Piutang Lain-lain",type:"asset"},{id:"coop-coa-prepaid",code:"1301",name:"Biaya Dibayar Dimuka",type:"asset"},{id:"coop-coa-fixed-asset",code:"1401",name:"Aset Tetap",type:"asset"},{id:"coop-coa-accum-depr",code:"1402",name:"Akumulasi Penyusutan",type:"asset"},{id:"coop-coa-simp-pokok",code:"2101",name:"Simpanan Pokok",type:"liability"},{id:"coop-coa-simp-wajib",code:"2102",name:"Simpanan Wajib",type:"liability"},{id:"coop-coa-simp-sukarela",code:"2103",name:"Simpanan Sukarela",type:"liability"},{id:"coop-coa-simp-berjangka",code:"2104",name:"Simpanan Berjangka",type:"liability"},{id:"coop-coa-ap",code:"2201",name:"Utang Usaha",type:"liability"},{id:"coop-coa-ext-loan",code:"2301",name:"Pinjaman Luar",type:"liability"},{id:"coop-coa-tax-payable",code:"2401",name:"Utang Pajak",type:"liability"},{id:"coop-coa-modal-awal",code:"3101",name:"Modal Awal",type:"equity"},{id:"coop-coa-cadangan-umum",code:"3201",name:"Dana Cadangan Umum",type:"equity"},{id:"coop-coa-cadangan-tujuan",code:"3202",name:"Dana Cadangan Tujuan",type:"equity"},{id:"coop-coa-shu-prior",code:"3301",name:"SHU Tahun Lalu",type:"equity"},{id:"coop-coa-shu-current",code:"3302",name:"SHU Berjalan",type:"equity"},{id:"coop-coa-shu-reserve",code:"3303",name:"Dana SHU Belum Dibagi",type:"equity"},{id:"coop-coa-jasa-pinjaman",code:"4101",name:"Pendapatan Jasa Pinjaman",type:"revenue"},{id:"coop-coa-provisi",code:"4102",name:"Pendapatan Provisi",type:"revenue"},{id:"coop-coa-rev-other",code:"4103",name:"Pendapatan Lain-lain",type:"revenue"},{id:"coop-coa-beban-bunga",code:"5101",name:"Beban Bunga Simpanan",type:"expense"},{id:"coop-coa-beban-ops",code:"5102",name:"Beban Operasional",type:"expense"},{id:"coop-coa-beban-gaji",code:"5103",name:"Beban Gaji dan Tunjangan",type:"expense"},{id:"coop-coa-beban-admin",code:"5104",name:"Beban Administrasi",type:"expense"},{id:"coop-coa-beban-depr",code:"5105",name:"Beban Penyusutan",type:"expense"},{id:"coop-coa-prov-kredit",code:"5106",name:"Cadangan Kerugian Piutang",type:"expense"}];function mt(r="IDR"){return fe.map(e=>({id:e.id,code:e.code,name:e.name,type:e.type,currency:r,isActive:!0}))}function ft(r){let e=new Set,t=new Set;for(let n of r){if(!n.id||!n.code||!n.name)return{ok:!1,reason:"COA_REQUIRED_FIELDS"};if(e.has(n.id))return{ok:!1,reason:"COA_DUPLICATE_ID"};if(t.has(n.code))return{ok:!1,reason:"COA_DUPLICATE_CODE"};e.add(n.id),t.add(n.code)}return{ok:!0}}export{me as CANONICAL_COA_TEMPLATES,fe as COOP_COA_TEMPLATES,c as OFINANCE_TABLES,R as OffinanceCore,T as OffinanceEnvelopeService,L as OfinanceRuntimeCore,N as OfinanceRuntimeCoreBuilder,pe as applyFinanceDomainEvent,w as applyPendingMigrations,et as buildBalanceSheet,ct as buildBudgetVsRealization,nt as buildCashflowBaseline,rt as buildClosingJournalDraft,ot as buildFinanceExportEnvelope,Ze as buildIncomeStatement,V as buildJournalFromCoopLoanDisbursement,q as buildJournalFromCoopLoanRepayment,k as buildJournalFromCoopSavingDeposit,H as buildJournalFromCoopSavingWithdrawal,Ue as buildJournalFromCoopShuParticipationManualRecap,j as buildJournalFromPosSale,$e as buildJournalFromScopedCoopLoanDisbursement,Ye as buildJournalFromScopedCoopLoanRepayment,Qe as buildJournalFromScopedCoopSavingDeposit,We as buildJournalFromScopedCoopSavingWithdrawal,qe as buildJournalFromScopedPosSale,pt as createCanonicalCoA,mt as createCoopCoA,U as createDbAdapterOfinanceServices,Ke as createFinanceProjectionSink,B as createOffinanceEnvelopeService,p as mapOffinanceErrorToEnvelope,ut as replayFinanceDomainEvents,W as resolveCoopLoanDisbursementAccountMapping,Y as resolveCoopLoanRepaymentAccountMapping,G as resolveCoopSavingDepositAccountMapping,X as resolveCoopSavingWithdrawalAccountMapping,Q as resolvePosSaleAccountMapping,C as resolveScopedAccountMapping,M as toOffinanceFailureEnvelope,l as toOffinanceSuccessEnvelope,ft as validateCoaIntegrity,D as validateJournalBalance};
1
+ function P(n){if(!Array.isArray(n)||n.length===0)return{ok:!1,totalDebit:0,totalCredit:0,reason:"JOURNAL_LINES_EMPTY"};let e=0,t=0;for(let r of n){if(!r||!r.accountId)return{ok:!1,totalDebit:e,totalCredit:t,reason:"JOURNAL_ACCOUNT_REQUIRED"};if(r.debit<0||r.credit<0)return{ok:!1,totalDebit:e,totalCredit:t,reason:"JOURNAL_NEGATIVE_AMOUNT"};e+=r.debit,t+=r.credit}return Math.abs(e-t)>1e-6?{ok:!1,totalDebit:e,totalCredit:t,reason:"JOURNAL_NOT_BALANCED"}:{ok:!0,totalDebit:e,totalCredit:t}}var le=[{key:"current",label:"Current",maxDaysPastDue:0},{key:"1-30",label:"1-30 days",minDaysPastDue:1,maxDaysPastDue:30},{key:"31-60",label:"31-60 days",minDaysPastDue:31,maxDaysPastDue:60},{key:"61-90",label:"61-90 days",minDaysPastDue:61,maxDaysPastDue:90},{key:"90+",label:"90+ days",minDaysPastDue:91}];function pe(n,e,t){return n==="receivable"?e-t:t-e}function me(n,e){return[n.tenantId??"",n.branchId??"",n.financeDomainId??"",n.ledgerProfileId??"",e.accountId,e.openItemType??"",e.openItemId??""].join("::")}function V(n){return n<0?"overpaid":Math.abs(n)<1e-6?"settled":"open"}function fe(n,e){if(!e)return 0;let t=Date.parse(n)-Date.parse(e);return!Number.isFinite(t)||t<=0?0:Math.floor(t/864e5)}function Ie(n,e){return e?!(e.tenantId&&n.tenantId!==e.tenantId||e.branchId&&n.branchId!==e.branchId||e.financeDomainId&&n.financeDomainId!==e.financeDomainId||e.ledgerProfileId&&n.ledgerProfileId!==e.ledgerProfileId||e.openItemType&&n.openItemType!==e.openItemType||e.counterpartyRef&&n.counterpartyRef!==e.counterpartyRef||!e.includeSettled&&n.status==="settled"):!0}function F(n){for(let e of n){let t=!!(e.openItemId||e.openItemType),r=!!(e.counterpartyRef||e.documentRef||e.dueAt);if(!(!t&&!r)){if(!e.openItemId)throw new Error("JOURNAL_OPEN_ITEM_ID_REQUIRED");if(!e.openItemType)throw new Error("JOURNAL_OPEN_ITEM_TYPE_REQUIRED");if(e.openItemType!=="receivable"&&e.openItemType!=="payable")throw new Error("JOURNAL_OPEN_ITEM_TYPE_INVALID");if(e.dueAt&&Number.isNaN(Date.parse(e.dueAt)))throw new Error("JOURNAL_OPEN_ITEM_DUE_AT_INVALID")}}}function D(n,e){let t=new Map;for(let r of n)if(r.status==="posted")for(let a of r.lines){if(!a.openItemId||!a.openItemType)continue;let o=me(r,a),i=pe(a.openItemType,a.debit,a.credit),c=t.get(o);if(!c){let s={tenantId:r.tenantId,branchId:r.branchId,financeDomainId:r.financeDomainId,ledgerProfileId:r.ledgerProfileId,openItemId:a.openItemId,openItemType:a.openItemType,accountId:a.accountId,counterpartyRef:a.counterpartyRef,documentRef:a.documentRef,dueAt:a.dueAt,originatedAt:r.occurredAt,lastActivityAt:r.occurredAt,originalAmount:i>0?i:0,settledAmount:i<0?Math.abs(i):0,outstandingAmount:i,status:V(i)};t.set(o,{item:s});continue}c.item.originatedAt=c.item.originatedAt<r.occurredAt?c.item.originatedAt:r.occurredAt,c.item.lastActivityAt=c.item.lastActivityAt>r.occurredAt?c.item.lastActivityAt:r.occurredAt,c.item.counterpartyRef=a.counterpartyRef??c.item.counterpartyRef,c.item.documentRef=a.documentRef??c.item.documentRef,c.item.dueAt=a.dueAt??c.item.dueAt,i>0?c.item.originalAmount+=i:i<0&&(c.item.settledAmount+=Math.abs(i)),c.item.outstandingAmount+=i,c.item.status=V(c.item.outstandingAmount)}return Array.from(t.values()).map(({item:r})=>({...r})).filter(r=>Ie(r,e)).sort((r,a)=>r.originatedAt!==a.originatedAt?r.originatedAt.localeCompare(a.originatedAt):r.openItemId.localeCompare(a.openItemId))}function O(n,e){if(Number.isNaN(Date.parse(e.asOf)))throw new Error("FINANCE_OPEN_ITEM_AGING_AS_OF_INVALID");let t=(e.buckets?.length?e.buckets:le).map(a=>({...a,amount:0,itemCount:0})),r=0;for(let a of n){if(a.outstandingAmount<=0)continue;r+=a.outstandingAmount;let o=fe(e.asOf,a.dueAt),i=t.find(c=>{let s=c.minDaysPastDue??Number.NEGATIVE_INFINITY,m=c.maxDaysPastDue??Number.POSITIVE_INFINITY;return o>=s&&o<=m});if(!i)throw new Error("FINANCE_OPEN_ITEM_AGING_BUCKET_UNRESOLVED");i.amount+=a.outstandingAmount,i.itemCount+=1}return{asOf:e.asOf,openItemType:e.openItemType,totalOutstanding:r,buckets:t}}function H(n,e){return`${e??""}::${n}`}function ge(n){if(!n.openItemId?.trim())throw new Error("FINANCE_RECONCILIATION_OPEN_ITEM_ID_REQUIRED");if(!Number.isFinite(n.observedAmount)||n.observedAmount<0)throw new Error("FINANCE_RECONCILIATION_OBSERVED_AMOUNT_INVALID");if(n.openItemType&&n.openItemType!=="receivable"&&n.openItemType!=="payable")throw new Error("FINANCE_RECONCILIATION_OPEN_ITEM_TYPE_INVALID")}function Ae(n,e){let t=new Map;for(let r of n){ge(r);let a=r.openItemType??e,o=H(r.openItemId,a),i=t.get(o);if(!i){t.set(o,{openItemId:r.openItemId,openItemType:a,observedAmount:r.observedAmount,counterpartyRef:r.counterpartyRef,documentRef:r.documentRef,references:r.reference?[r.reference]:[]});continue}i.observedAmount+=r.observedAmount,i.counterpartyRef=r.counterpartyRef??i.counterpartyRef,i.documentRef=r.documentRef??i.documentRef,r.reference&&i.references.push(r.reference)}return t}function ye(n,e,t,r,a){let o=n.outstandingAmount,i=e?.observedAmount??0,c=i-o,s=he(n.dueAt,r);if(!e){let A=$("missing",s,a);return{tenantId:n.tenantId,branchId:n.branchId,financeDomainId:n.financeDomainId,ledgerProfileId:n.ledgerProfileId,openItemId:n.openItemId,openItemType:n.openItemType,accountId:n.accountId,counterpartyRef:n.counterpartyRef,documentRef:n.documentRef,dueAt:n.dueAt,expectedAmount:o,observedAmount:i,varianceAmount:c,status:"missing",lifecycleStatus:A.lifecycleStatus,suggestedAction:A.suggestedAction,reason:"FINANCE_RECONCILIATION_OBSERVATION_MISSING",pastDueDays:s,observedReferences:[]}}let m=e.counterpartyRef&&n.counterpartyRef&&e.counterpartyRef!==n.counterpartyRef||e.documentRef&&n.documentRef&&e.documentRef!==n.documentRef,p="matched",g="resolved",d="none",u;if(m)p="mismatch",g="exception",d="investigate",u="FINANCE_RECONCILIATION_METADATA_MISMATCH";else if(Math.abs(c)<=t)p="matched";else if(c<0){p="under";let A=$("under",s,a);g=A.lifecycleStatus,d=A.suggestedAction,u="FINANCE_RECONCILIATION_OBSERVED_UNDER"}else c>0&&(p="over",g="unresolved",d="refund_or_apply_credit",u="FINANCE_RECONCILIATION_OBSERVED_OVER");return{tenantId:n.tenantId,branchId:n.branchId,financeDomainId:n.financeDomainId,ledgerProfileId:n.ledgerProfileId,openItemId:n.openItemId,openItemType:n.openItemType,accountId:n.accountId,counterpartyRef:n.counterpartyRef,documentRef:n.documentRef,dueAt:n.dueAt,expectedAmount:o,observedAmount:i,varianceAmount:c,status:p,lifecycleStatus:g,suggestedAction:d,reason:u,pastDueDays:s,observedReferences:[...e.references]}}function be(n,e){return{tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,openItemId:n.openItemId,openItemType:n.openItemType??e.openItemType,counterpartyRef:n.counterpartyRef,documentRef:n.documentRef,expectedAmount:0,observedAmount:n.observedAmount,varianceAmount:n.observedAmount,status:"mismatch",lifecycleStatus:"exception",suggestedAction:"investigate",reason:"FINANCE_RECONCILIATION_EXPECTED_ITEM_NOT_FOUND",observedReferences:[...n.references]}}function he(n,e){if(!n||!e)return;let t=Date.parse(n),r=Date.parse(e);if(!Number.isFinite(t)||!Number.isFinite(r))throw new Error("FINANCE_RECONCILIATION_AS_OF_INVALID");let a=r-t;return a<=0?0:Math.floor(a/864e5)}function $(n,e,t){return typeof t=="number"&&typeof e=="number"&&e>=t?{lifecycleStatus:"writeoff_candidate",suggestedAction:"write_off_review"}:{lifecycleStatus:"unresolved",suggestedAction:n==="missing"||n==="under"?"collect_follow_up":"investigate"}}function T(n,e){let t=e.toleranceAmount??0;if(!Number.isFinite(t)||t<0)throw new Error("FINANCE_RECONCILIATION_TOLERANCE_INVALID");if(e.asOf&&!Number.isFinite(Date.parse(e.asOf)))throw new Error("FINANCE_RECONCILIATION_AS_OF_INVALID");if(typeof e.writeOffPastDueDays=="number"&&(!Number.isFinite(e.writeOffPastDueDays)||e.writeOffPastDueDays<0))throw new Error("FINANCE_RECONCILIATION_WRITE_OFF_DAYS_INVALID");let r=Ae(e.observations,e.openItemType),a=[];for(let d of n){let u=H(d.openItemId,d.openItemType),A=r.get(u);a.push(ye(d,A,t,e.asOf,e.writeOffPastDueDays)),r.delete(u)}for(let d of r.values())a.push(be(d,e));a.sort((d,u)=>(d.financeDomainId??"")!==(u.financeDomainId??"")?(d.financeDomainId??"").localeCompare(u.financeDomainId??""):(d.ledgerProfileId??"")!==(u.ledgerProfileId??"")?(d.ledgerProfileId??"").localeCompare(u.ledgerProfileId??""):d.openItemId.localeCompare(u.openItemId));let o=a.reduce((d,u)=>d+u.expectedAmount,0),i=a.reduce((d,u)=>d+u.observedAmount,0),c=a.reduce((d,u)=>d+u.varianceAmount,0),s=a.filter(d=>d.lifecycleStatus==="resolved").length,m=a.filter(d=>d.lifecycleStatus==="unresolved").length,p=a.filter(d=>d.lifecycleStatus==="exception").length,g=a.filter(d=>d.lifecycleStatus==="writeoff_candidate").length;return{openItemType:e.openItemType,totalExpectedAmount:o,totalObservedAmount:i,totalVarianceAmount:c,resolvedCount:s,unresolvedCount:m,exceptionCount:p,writeoffCandidateCount:g,rows:a}}function Se(n){if(!Array.isArray(n.trackedAccountIds)||n.trackedAccountIds.length===0)throw new Error("FINANCE_CASH_MOVEMENT_TRACKED_ACCOUNTS_REQUIRED");let e=new Set(n.trackedAccountIds.map(t=>t.trim()).filter(Boolean));if(e.size===0)throw new Error("FINANCE_CASH_MOVEMENT_TRACKED_ACCOUNTS_REQUIRED");return e}function Ce(n,e){return!(e.tenantId&&n.tenantId!==e.tenantId||e.branchId&&n.branchId!==e.branchId||e.financeDomainId&&n.financeDomainId!==e.financeDomainId||e.ledgerProfileId&&n.ledgerProfileId!==e.ledgerProfileId||e.occurredFrom&&n.occurredAt<e.occurredFrom||e.occurredTo&&n.occurredAt>e.occurredTo)}function ve(n){return n?.startsWith("reversal:")&&n.slice(9).trim()||void 0}function _(n,e){let t=Se(e),r=[];for(let a of n){if(a.status!=="posted"||!Ce(a,e))continue;let o=a.lines.filter(u=>t.has(u.accountId)&&(u.debit>0||u.credit>0));if(o.length===0)continue;let i=Array.from(new Set(o.map(u=>u.accountId))).sort(),c=Array.from(new Set(a.lines.filter(u=>!t.has(u.accountId)&&(u.debit>0||u.credit>0)).map(u=>u.accountId))).sort(),s=o.some(u=>u.debit>0),m=o.some(u=>u.credit>0),p=ve(a.reference),g=!!p,d=i.length>1&&s&&m&&c.length===0;if(i.length>1&&c.length>0)throw new Error("FINANCE_CASH_MOVEMENT_MIXED_TRACKED_JOURNAL_UNSUPPORTED");if(d){let u=o.reduce((y,S)=>y+S.debit,0),A=o.reduce((y,S)=>y+S.credit,0);if(Math.abs(u-A)>1e-6)throw new Error("FINANCE_CASH_MOVEMENT_TRANSFER_IMBALANCED")}for(let u of o)u.debit>0&&r.push({journalId:a.id,tenantId:a.tenantId,branchId:a.branchId,financeDomainId:a.financeDomainId,ledgerProfileId:a.ledgerProfileId,occurredAt:a.occurredAt,reference:a.reference,evidenceRef:a.evidenceRef,accountId:u.accountId,direction:d?"transfer_in":"in",movementKind:g?"reversal":d?"internal_transfer":"external",lifecycleStatus:g?"reversal_posted":"posted",amount:u.debit,signedAmount:u.debit,sourceJournalId:p,counterpartAccountIds:c,trackedAccountIdsInJournal:i}),u.credit>0&&r.push({journalId:a.id,tenantId:a.tenantId,branchId:a.branchId,financeDomainId:a.financeDomainId,ledgerProfileId:a.ledgerProfileId,occurredAt:a.occurredAt,reference:a.reference,evidenceRef:a.evidenceRef,accountId:u.accountId,direction:d?"transfer_out":"out",movementKind:g?"reversal":d?"internal_transfer":"external",lifecycleStatus:g?"reversal_posted":"posted",amount:u.credit,signedAmount:-u.credit,sourceJournalId:p,counterpartAccountIds:c,trackedAccountIdsInJournal:i})}return r.sort((a,o)=>a.occurredAt!==o.occurredAt?a.occurredAt.localeCompare(o.occurredAt):a.journalId!==o.journalId?a.journalId.localeCompare(o.journalId):a.accountId.localeCompare(o.accountId))}function w(n){let e=0,t=0,r=0,a=0,o=new Map;for(let i of n)i.direction==="in"&&(e+=i.amount),i.direction==="out"&&(t+=i.amount),i.direction==="transfer_in"&&(r+=i.amount),i.direction==="transfer_out"&&(a+=i.amount),o.set(i.accountId,(o.get(i.accountId)??0)+i.signedAmount);return{totalInflow:e,totalOutflow:t,totalTransferIn:r,totalTransferOut:a,netExternalMovement:e-t,netByTrackedAccountId:Object.fromEntries(Array.from(o.entries()).sort(([i],[c])=>i.localeCompare(c))),entries:n.map(i=>({...i,counterpartAccountIds:[...i.counterpartAccountIds],trackedAccountIdsInJournal:[...i.trackedAccountIdsInJournal]}))}}var N=class{constructor(e){this.state={accounts:e?.accounts??new Map,periods:e?.periods??new Map,journals:e?.journals??new Map,balances:e?.balances??new Map,rapbPlans:e?.rapbPlans??new Map,auditTrail:e?.auditTrail?.map(t=>({...t}))??[]}}createAccount(e){if(!e.id||!e.code||!e.name)throw new Error("FINANCE_ACCOUNT_REQUIRED_FIELDS");if(this.state.accounts.has(e.id))throw new Error("FINANCE_ACCOUNT_ALREADY_EXISTS");if(Array.from(this.state.accounts.values()).some(r=>r.code===e.code))throw new Error("FINANCE_ACCOUNT_CODE_DUPLICATE");return this.state.accounts.set(e.id,{...e}),{...e}}listAccounts(){return Array.from(this.state.accounts.values()).map(e=>({...e})).sort((e,t)=>e.code.localeCompare(t.code))}openFiscalPeriod(e){if(!e.id||!e.tenantId||!e.code||!e.startDate||!e.endDate)throw new Error("FISCAL_PERIOD_REQUIRED_FIELDS");if(this.state.periods.has(e.id))throw new Error("FISCAL_PERIOD_ALREADY_EXISTS");if(Date.parse(e.startDate)>Date.parse(e.endDate))throw new Error("FISCAL_PERIOD_INVALID_RANGE");let t={...e,status:"open"};return this.state.periods.set(t.id,t),this.recordAuditTrail({eventType:"fiscal_period_opened",recordType:"fiscal_period",recordId:t.id,tenantId:t.tenantId,branchId:t.branchId,financeDomainId:t.financeDomainId,ledgerProfileId:t.ledgerProfileId,occurredAt:new Date().toISOString(),summary:`Fiscal period ${t.code} opened`,metadata:{code:t.code,startDate:t.startDate,endDate:t.endDate}}),{...t}}closeFiscalPeriod(e){let t=this.state.periods.get(e);if(!t)throw new Error("FISCAL_PERIOD_NOT_FOUND");let r={...t,status:"closed"};return this.state.periods.set(e,r),this.recordAuditTrail({eventType:"fiscal_period_closed",recordType:"fiscal_period",recordId:r.id,tenantId:r.tenantId,branchId:r.branchId,financeDomainId:r.financeDomainId,ledgerProfileId:r.ledgerProfileId,occurredAt:new Date().toISOString(),summary:`Fiscal period ${r.code} closed`,metadata:{code:r.code}}),{...r}}listFiscalPeriods(){return Array.from(this.state.periods.values()).map(e=>({...e})).sort((e,t)=>e.startDate.localeCompare(t.startDate))}createJournalDraft(e){if(!e.id||!e.tenantId||!e.occurredAt)throw new Error("JOURNAL_REQUIRED_FIELDS");if(this.state.journals.has(e.id))throw new Error("JOURNAL_ALREADY_EXISTS");this.assertJournalLinesKnownAccounts(e.lines),this.assertJournalPeriodOpen(e.occurredAt),F(e.lines);let t=P(e.lines);if(!t.ok)throw new Error(t.reason??"JOURNAL_INVALID");let r={id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,occurredAt:e.occurredAt,reference:e.reference,evidenceRef:e.evidenceRef,lines:e.lines.map(a=>({...a})),status:"draft"};return this.state.journals.set(r.id,r),this.recordAuditTrail({eventType:"journal_drafted",recordType:"journal",recordId:r.id,journalId:r.id,tenantId:r.tenantId,branchId:r.branchId,financeDomainId:r.financeDomainId,ledgerProfileId:r.ledgerProfileId,occurredAt:new Date().toISOString(),reference:r.reference,evidenceRef:r.evidenceRef,summary:`Journal ${r.id} drafted`,metadata:{journalOccurredAt:r.occurredAt,status:r.status}}),{...r,lines:r.lines.map(a=>({...a}))}}postJournal(e,t=new Date().toISOString()){let r=this.state.journals.get(e);if(!r)throw new Error("JOURNAL_NOT_FOUND");if(r.status==="posted"||r.status==="reversed")return{...r,lines:r.lines.map(i=>({...i}))};this.applyLinesToBalance(r.lines);let a={...r,status:"posted",postedAt:t};this.state.journals.set(e,a);let o=new Date().toISOString();return this.recordAuditTrail({eventType:"journal_posted",recordType:"journal",recordId:a.id,journalId:a.id,tenantId:a.tenantId,branchId:a.branchId,financeDomainId:a.financeDomainId,ledgerProfileId:a.ledgerProfileId,occurredAt:o,reference:a.reference,evidenceRef:a.evidenceRef,summary:`Journal ${a.id} posted`,metadata:{journalOccurredAt:a.occurredAt,postedAt:t,status:a.status}}),{...a,lines:a.lines.map(i=>({...i}))}}reverseJournal(e,t){let r=this.state.journals.get(e);if(!r)throw new Error("JOURNAL_NOT_FOUND");if(r.status!=="posted")throw new Error("JOURNAL_NOT_POSTED");if(this.state.journals.has(t))throw new Error("JOURNAL_ALREADY_EXISTS");let a=r.lines.map(s=>({accountId:s.accountId,debit:s.credit,credit:s.debit,memo:s.memo,openItemId:s.openItemId,openItemType:s.openItemType,counterpartyRef:s.counterpartyRef,documentRef:s.documentRef,dueAt:s.dueAt})),o=this.createJournalDraft({id:t,tenantId:r.tenantId,branchId:r.branchId,financeDomainId:r.financeDomainId,ledgerProfileId:r.ledgerProfileId,occurredAt:r.occurredAt,reference:`reversal:${r.id}`,evidenceRef:r.evidenceRef,lines:a}),i=this.postJournal(o.id),c=new Date().toISOString();return this.recordAuditTrail({eventType:"journal_reversal_posted",recordType:"journal",recordId:i.id,journalId:i.id,sourceJournalId:r.id,tenantId:i.tenantId,branchId:i.branchId,financeDomainId:i.financeDomainId,ledgerProfileId:i.ledgerProfileId,occurredAt:c,reference:i.reference,evidenceRef:i.evidenceRef,summary:`Reversal journal ${i.id} posted for ${r.id}`,metadata:{journalOccurredAt:i.occurredAt,postedAt:i.postedAt,status:i.status}}),i}getTrialBalance(){return this.getTrialBalanceByScope()}getTrialBalanceByScope(e){let t=this.computeScopedBalances(e);return this.listAccounts().map(a=>{let o=t.get(a.id)??{debit:0,credit:0};return{accountId:a.id,accountCode:a.code,accountName:a.name,accountType:a.type,debit:o.debit,credit:o.credit,net:o.debit-o.credit}})}listJournals(e){return Array.from(this.state.journals.values()).filter(t=>this.matchesScope(t,e)).map(t=>({...t,lines:t.lines.map(r=>({...r}))})).sort((t,r)=>t.occurredAt.localeCompare(r.occurredAt))}listOpenItems(e){return D(this.listJournals(e),e)}getOpenItemAging(e){return O(this.listOpenItems(e),e)}reconcileOpenItems(e){return T(this.listOpenItems(e),e)}listCashBankMovements(e){return _(this.listJournals(e),e)}summarizeCashBankMovements(e){return w(this.listCashBankMovements(e))}listFinancialAuditTrail(e){return this.state.auditTrail.filter(t=>this.matchesAuditScope(t,e)).sort((t,r)=>t.occurredAt!==r.occurredAt?t.occurredAt.localeCompare(r.occurredAt):t.id.localeCompare(r.id)).map(t=>({...t,metadata:t.metadata?{...t.metadata}:void 0}))}assertJournalLinesKnownAccounts(e){for(let t of e)if(!this.state.accounts.has(t.accountId))throw new Error("JOURNAL_ACCOUNT_NOT_FOUND")}assertJournalPeriodOpen(e){if(this.state.periods.size===0)return;let t=this.findPeriodByDate(e);if(!t)throw new Error("FISCAL_PERIOD_NOT_FOUND_FOR_DATE");if(t.status!=="open")throw new Error("FISCAL_PERIOD_CLOSED")}findPeriodByDate(e){let t=Date.parse(e);for(let r of this.state.periods.values()){let a=Date.parse(r.startDate),o=Date.parse(r.endDate);if(t>=a&&t<=o)return r}return null}applyLinesToBalance(e){for(let t of e){let r=this.state.balances.get(t.accountId)??{debit:0,credit:0};r.debit+=t.debit,r.credit+=t.credit,this.state.balances.set(t.accountId,r)}}computeScopedBalances(e){if(!e||!e.tenantId&&!e.branchId&&!e.financeDomainId&&!e.ledgerProfileId&&!e.occurredFrom&&!e.occurredTo)return this.state.balances;let t=new Map;for(let r of this.state.journals.values())if(r.status==="posted"&&this.matchesScope(r,e))for(let a of r.lines){let o=t.get(a.accountId)??{debit:0,credit:0};o.debit+=a.debit,o.credit+=a.credit,t.set(a.accountId,o)}return t}matchesScope(e,t){return t?!(t.tenantId&&e.tenantId!==t.tenantId||t.branchId&&e.branchId!==t.branchId||t.financeDomainId&&e.financeDomainId!==t.financeDomainId||t.ledgerProfileId&&e.ledgerProfileId!==t.ledgerProfileId||t.occurredFrom&&e.occurredAt<t.occurredFrom||t.occurredTo&&e.occurredAt>t.occurredTo):!0}createRapb(e){if(!e.id||!e.tenantId||!e.periodCode||!e.title)throw new Error("RAPB_REQUIRED_FIELDS");if(!e.lines||e.lines.length===0)throw new Error("RAPB_LINES_REQUIRED");if(this.state.rapbPlans.has(e.id))throw new Error("RAPB_ALREADY_EXISTS");if(e.lines.some(a=>a.budgetedDebit<0||a.budgetedCredit<0))throw new Error("RAPB_NEGATIVE_AMOUNT");let t=e.lines.map(a=>{let o=this.state.accounts.get(a.accountId);if(!o)throw new Error(`RAPB_ACCOUNT_NOT_FOUND:${a.accountId}`);let i=a.budgetedDebit-a.budgetedCredit;return{accountId:a.accountId,accountCode:o.code,accountName:o.name,accountType:o.type,budgetedDebit:a.budgetedDebit,budgetedCredit:a.budgetedCredit,budgetedNet:i}}),r={id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,periodCode:e.periodCode,title:e.title,status:"draft",lines:t,notes:e.notes,createdAt:new Date().toISOString()};return this.state.rapbPlans.set(r.id,r),this.recordAuditTrail({eventType:"rapb_created",recordType:"rapb_plan",recordId:r.id,tenantId:r.tenantId,branchId:r.branchId,financeDomainId:r.financeDomainId,ledgerProfileId:r.ledgerProfileId,occurredAt:r.createdAt,summary:`RAPB ${r.title} created`,metadata:{periodCode:r.periodCode,status:r.status}}),r}getRapb(e){return this.state.rapbPlans.get(e)??null}listRapb(e){let t=Array.from(this.state.rapbPlans.values());return e&&(e.tenantId&&(t=t.filter(r=>r.tenantId===e.tenantId)),e.periodCode&&(t=t.filter(r=>r.periodCode===e.periodCode)),e.branchId&&(t=t.filter(r=>r.branchId===e.branchId)),e.financeDomainId&&(t=t.filter(r=>r.financeDomainId===e.financeDomainId)),e.ledgerProfileId&&(t=t.filter(r=>r.ledgerProfileId===e.ledgerProfileId))),t}approveRapb(e,t){let r=this.state.rapbPlans.get(e);if(!r)throw new Error("RAPB_NOT_FOUND");let a=typeof t=="string"?t:t.approvedBy;if(r.status==="approved")throw new Error("RAPB_ALREADY_APPROVED");let o={...r,status:"approved",approvedAt:new Date().toISOString(),approvedBy:a};return this.state.rapbPlans.set(e,o),this.recordAuditTrail({eventType:"rapb_approved",recordType:"rapb_plan",recordId:o.id,tenantId:o.tenantId,branchId:o.branchId,financeDomainId:o.financeDomainId,ledgerProfileId:o.ledgerProfileId,occurredAt:o.approvedAt??new Date().toISOString(),summary:`RAPB ${o.title} approved`,metadata:{periodCode:o.periodCode,approvedBy:a,status:o.status}}),o}evaluateVariance(e){let t=this.state.rapbPlans.get(e);if(!t)throw new Error("RAPB_NOT_FOUND");let r=this.getTrialBalance(),a=new Map(r.map(d=>[d.accountId,d])),o=0,i=0,c=0,s=0,m=t.lines.map(d=>{let u=a.get(d.accountId),A=u?.debit??0,y=u?.credit??0,S=A-y;return d.accountType==="revenue"?(o+=d.budgetedCredit-d.budgetedDebit,i+=y-A):d.accountType==="expense"&&(c+=d.budgetedDebit-d.budgetedCredit,s+=A-y),{accountId:d.accountId,accountCode:d.accountCode,accountName:d.accountName,accountType:d.accountType,budgetedDebit:d.budgetedDebit,budgetedCredit:d.budgetedCredit,budgetedNet:d.budgetedNet,actualDebit:A,actualCredit:y,actualNet:S,varianceDebit:A-d.budgetedDebit,varianceCredit:y-d.budgetedCredit,varianceNet:S-d.budgetedNet}}),p=o-c,g=i-s;return{rapbId:e,periodCode:t.periodCode,evaluatedAt:new Date().toISOString(),lines:m,totalBudgetedRevenue:o,totalActualRevenue:i,totalBudgetedExpense:c,totalActualExpense:s,budgetedNetIncome:p,actualNetIncome:g,netVariance:g-p}}recordAuditTrail(e){this.state.auditTrail.push({id:`audit:${this.state.auditTrail.length+1}:${Date.now()}`,...e,metadata:e.metadata?{...e.metadata}:void 0})}matchesAuditScope(e,t){return t?!(t.tenantId&&e.tenantId!==t.tenantId||t.branchId&&e.branchId!==t.branchId||t.financeDomainId&&e.financeDomainId!==t.financeDomainId||t.ledgerProfileId&&e.ledgerProfileId!==t.ledgerProfileId||t.occurredFrom&&e.occurredAt<t.occurredFrom||t.occurredTo&&e.occurredAt>t.occurredTo||t.recordId&&e.recordId!==t.recordId||t.journalId&&e.journalId!==t.journalId||t.eventTypes&&t.eventTypes.length>0&&!t.eventTypes.includes(e.eventType)):!0}};import{CoreRuntime as Te}from"ofcore";import{InMemoryDbAdapter as _e}from"ofcore";import{asReadonlyStore as we,createStore as Ne}from"ofcore";var l={accounts:"ofinance_accounts",periods:"ofinance_periods",journals:"ofinance_journals",journalLines:"ofinance_journal_lines",rapbPlans:"ofinance_rapb_plans",rapbLines:"ofinance_rapb_lines",histories:"ofinance_histories"},Ee=[{name:l.accounts,columns:[{name:"id",type:"string"},{name:"code",type:"string",isIndexed:!0},{name:"name",type:"string"},{name:"type",type:"string",isIndexed:!0},{name:"currency",type:"string"},{name:"isActive",type:"boolean",isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:l.periods,columns:[{name:"id",type:"string"},{name:"tenantId",type:"string",isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"code",type:"string",isIndexed:!0},{name:"startDate",type:"string",isIndexed:!0},{name:"endDate",type:"string",isIndexed:!0},{name:"status",type:"string",isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:l.journals,columns:[{name:"id",type:"string"},{name:"tenantId",type:"string",isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"occurredAt",type:"string",isIndexed:!0},{name:"reference",type:"string",isOptional:!0,isIndexed:!0},{name:"evidenceRef",type:"string",isOptional:!0,isIndexed:!0},{name:"status",type:"string",isIndexed:!0},{name:"postedAt",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:l.journalLines,columns:[{name:"id",type:"string"},{name:"journalId",type:"string",isIndexed:!0},{name:"accountId",type:"string",isIndexed:!0},{name:"debit",type:"number"},{name:"credit",type:"number"},{name:"memo",type:"string",isOptional:!0},{name:"openItemId",type:"string",isOptional:!0,isIndexed:!0},{name:"openItemType",type:"string",isOptional:!0,isIndexed:!0},{name:"counterpartyRef",type:"string",isOptional:!0,isIndexed:!0},{name:"documentRef",type:"string",isOptional:!0,isIndexed:!0},{name:"dueAt",type:"string",isOptional:!0,isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:l.rapbPlans,columns:[{name:"id",type:"string"},{name:"tenantId",type:"string",isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"periodCode",type:"string",isIndexed:!0},{name:"title",type:"string",isIndexed:!0},{name:"status",type:"string",isIndexed:!0},{name:"notes",type:"string",isOptional:!0},{name:"createdAt",type:"string",isIndexed:!0},{name:"approvedAt",type:"string",isOptional:!0,isIndexed:!0},{name:"approvedBy",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:l.rapbLines,columns:[{name:"id",type:"string"},{name:"rapbId",type:"string",isIndexed:!0},{name:"accountId",type:"string",isIndexed:!0},{name:"accountCode",type:"string",isIndexed:!0},{name:"accountName",type:"string"},{name:"accountType",type:"string",isIndexed:!0},{name:"budgetedDebit",type:"number"},{name:"budgetedCredit",type:"number"},{name:"budgetedNet",type:"number"},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:l.histories,columns:[{name:"id",type:"string"},{name:"tableName",type:"string",isIndexed:!0},{name:"recordId",type:"string",isIndexed:!0},{name:"action",type:"string",isIndexed:!0},{name:"changes",type:"json",isOptional:!0},{name:"timestamp",type:"string",isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0}]}];function B(){return Ee.map(n=>({...n,columns:n.columns.map(e=>({...e}))}))}var Q=[{toVersion:1,up:async n=>{let e=B();for(let t of e)try{await n.addTable(t)}catch{}}},{toVersion:2,up:async n=>{let e=B().filter(t=>t.name==="ofinance_rapb_plans"||t.name==="ofinance_rapb_lines");for(let t of e)try{await n.addTable(t)}catch{}}},{toVersion:3,up:async n=>{try{await n.addColumn("ofinance_journals",{name:"evidenceRef",type:"string",isOptional:!0,isIndexed:!0})}catch{}}},{toVersion:4,up:async n=>{let e=[{name:"openItemId",type:"string",isOptional:!0,isIndexed:!0},{name:"openItemType",type:"string",isOptional:!0,isIndexed:!0},{name:"counterpartyRef",type:"string",isOptional:!0,isIndexed:!0},{name:"documentRef",type:"string",isOptional:!0,isIndexed:!0},{name:"dueAt",type:"string",isOptional:!0,isIndexed:!0}];for(let t of e)try{await n.addColumn("ofinance_journal_lines",t)}catch{}}}];var Re={logInfo(){},logWarn(){},logError(){}};async function L(n,e=Re){e.logInfo("[offinance] starting database migration process");let t=[...Q].sort((o,i)=>o.toVersion-i.toVersion),r=t.length>0?t[t.length-1].toVersion:0,a=await n.getSchemaVersion();if((a==null||a<0)&&(a=0),a>=r){e.logInfo(`[offinance] database already up-to-date at v${a}`);return}for(let o of t)o.toVersion>a&&(e.logInfo(`[offinance] applying migration v${o.toVersion}`),await o.up(n),await n.setSchemaVersion(o.toVersion),a=o.toVersion);e.logInfo(`[offinance] migration completed at v${a}`)}function f(n,e){return{data:n,meta:{request_id:e??null,timestamp:new Date().toISOString()}}}function q(n,e,t={}){return{error:{code:n,message:e,details:t.details,retryable:t.retryable,correlationId:t.correlationId,timestamp:new Date().toISOString()},meta:{request_id:t.requestId??null,timestamp:new Date().toISOString()}}}function I(n,e="FINANCE_NOT_IMPLEMENTED",t="Unhandled offinance error."){return n instanceof Error?q(e,n.message||t):q(e,t)}var J=class{constructor(e){this.legacy=e;this.accountService={createAccount:async t=>{try{return f(await this.legacy.accountService.createAccount(t))}catch(r){return I(r)}},listAccounts:async()=>{try{return f(await this.legacy.accountService.listAccounts())}catch(t){return I(t)}}},this.journalService={createJournalDraft:async t=>{try{return f(await this.legacy.journalService.createJournalDraft(t))}catch(r){return I(r)}},postJournal:async(t,r)=>{try{return f(await this.legacy.journalService.postJournal(t,r))}catch(a){return I(a)}},reverseJournal:async(t,r)=>{try{return f(await this.legacy.journalService.reverseJournal(t,r))}catch(a){return I(a)}},listJournals:async t=>{try{return f(await this.legacy.journalService.listJournals(t))}catch(r){return I(r)}}},this.fiscalService={openFiscalPeriod:async t=>{try{return f(await this.legacy.fiscalService.openFiscalPeriod(t))}catch(r){return I(r)}},closeFiscalPeriod:async t=>{try{return f(await this.legacy.fiscalService.closeFiscalPeriod(t))}catch(r){return I(r)}},listFiscalPeriods:async()=>{try{return f(await this.legacy.fiscalService.listFiscalPeriods())}catch(t){return I(t)}},getTrialBalance:async()=>{try{return f(await this.legacy.fiscalService.getTrialBalance())}catch(t){return I(t)}},getTrialBalanceByScope:async t=>{try{return f(await this.legacy.fiscalService.getTrialBalanceByScope(t))}catch(r){return I(r)}}},this.rapbService={createRapb:async t=>{try{return f(await this.legacy.rapbService.createRapb(t))}catch(r){return I(r)}},getRapb:async t=>{try{return f(await this.legacy.rapbService.getRapb(t))}catch(r){return I(r)}},listRapb:async t=>{try{return f(await this.legacy.rapbService.listRapb(t))}catch(r){return I(r)}},approveRapb:async(t,r)=>{try{return f(await this.legacy.rapbService.approveRapb(t,r))}catch(a){return I(a)}},evaluateVariance:async t=>{try{return f(await this.legacy.rapbService.evaluateVariance(t))}catch(r){return I(r)}}},this.openItemService={listOpenItems:async t=>{try{return f(await this.legacy.openItemService.listOpenItems(t))}catch(r){return I(r)}},getOpenItemAging:async t=>{try{return f(await this.legacy.openItemService.getOpenItemAging(t))}catch(r){return I(r)}}},this.reconciliationService={reconcileOpenItems:async t=>{try{return f(await this.legacy.reconciliationService.reconcileOpenItems(t))}catch(r){return I(r)}}},this.cashMovementService={listCashBankMovements:async t=>{try{return f(await this.legacy.cashMovementService.listCashBankMovements(t))}catch(r){return I(r)}},summarizeCashBankMovements:async t=>{try{return f(await this.legacy.cashMovementService.summarizeCashBankMovements(t))}catch(r){return I(r)}}},this.auditTrailService={listFinancialAuditTrail:async t=>{try{return f(await this.legacy.auditTrailService.listFinancialAuditTrail(t))}catch(r){return I(r)}}}}};function Y(n){return new J({accountService:n,journalService:n,fiscalService:n,rapbService:n,openItemService:n,reconciliationService:n,cashMovementService:n,auditTrailService:n})}function h(n){return JSON.parse(JSON.stringify(n))}function b(){return new Date().toISOString()}function Pe(n,e){return`${n}:${e}:${Date.now()}:${Math.random().toString(36).slice(2,8)}`}function Fe(n,e){return!n||n.deleted?!1:e?!(e.tenantId&&n.tenantId!==e.tenantId||e.branchId&&n.branchId!==e.branchId||e.financeDomainId&&n.financeDomainId!==e.financeDomainId||e.ledgerProfileId&&n.ledgerProfileId!==e.ledgerProfileId||e.occurredFrom&&n.occurredAt&&n.occurredAt<e.occurredFrom||e.occurredTo&&n.occurredAt&&n.occurredAt>e.occurredTo):!0}function De(n,e){return e?!(e.tenantId&&n.tenantId!==e.tenantId||e.branchId&&n.branchId!==e.branchId||e.financeDomainId&&n.financeDomainId!==e.financeDomainId||e.ledgerProfileId&&n.ledgerProfileId!==e.ledgerProfileId||e.occurredFrom&&n.occurredAt<e.occurredFrom||e.occurredTo&&n.occurredAt>e.occurredTo||e.recordId&&n.recordId!==e.recordId||e.journalId&&n.journalId!==e.journalId||e.eventTypes&&e.eventTypes.length>0&&!e.eventTypes.includes(n.eventType)):!0}function Oe(n){return typeof n!="string"||!n.startsWith("reversal:")?void 0:n.slice(9).trim()||void 0}var M=class{constructor(e){this.dbAdapter=e}async createAccount(e){if(!e.id||!e.code||!e.name)throw new Error("FINANCE_ACCOUNT_REQUIRED_FIELDS");let t=await this.dbAdapter.get(l.accounts,e.id);if(t&&!t.deleted)throw new Error("FINANCE_ACCOUNT_ALREADY_EXISTS");if((await this.dbAdapter.query(l.accounts,{filters:{and:[{field:"code",value:e.code},{field:"deleted",value:!1}]}})).some(i=>i.id!==e.id))throw new Error("FINANCE_ACCOUNT_CODE_DUPLICATE");let a=b(),o={...h(e),lastModified:a,deleted:!1};return t?await this.dbAdapter.update(l.accounts,e.id,o):await this.dbAdapter.create(l.accounts,o),await this.writeHistory("accounts",e.id,"UPSERT",o),h(e)}async listAccounts(){return(await this.dbAdapter.query(l.accounts,{filters:{field:"deleted",value:!1}})).map(({lastModified:t,deleted:r,...a})=>h(a)).sort((t,r)=>t.code.localeCompare(r.code))}async createJournalDraft(e){if(!e.id||!e.tenantId||!e.occurredAt)throw new Error("JOURNAL_REQUIRED_FIELDS");if(!e.ledgerProfileId)throw new Error("JOURNAL_REQUIRED_FIELDS");let t=await this.dbAdapter.get(l.journals,e.id);if(t&&!t.deleted)throw new Error("JOURNAL_ALREADY_EXISTS");await this.assertJournalLinesKnownAccounts(e.lines),await this.assertJournalPeriodOpen(e),F(e.lines);let r=P(e.lines);if(!r.ok)throw new Error(r.reason??"JOURNAL_INVALID");let a=b(),o={id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,occurredAt:e.occurredAt,reference:e.reference,evidenceRef:e.evidenceRef,status:"draft",postedAt:void 0,lastModified:a,deleted:!1};await this.dbAdapter.create(l.journals,o);for(let i=0;i<e.lines.length;i+=1){let c=e.lines[i],s={id:`${e.id}:line:${i}`,journalId:e.id,accountId:c.accountId,debit:c.debit,credit:c.credit,memo:c.memo,openItemId:c.openItemId,openItemType:c.openItemType,counterpartyRef:c.counterpartyRef,documentRef:c.documentRef,dueAt:c.dueAt,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,lastModified:a,deleted:!1};await this.dbAdapter.create(l.journalLines,s),await this.writeHistory("journal_lines",s.id,"UPSERT",s)}return await this.writeHistory("journals",e.id,"UPSERT",o),this.toJournalEntry(o,e.lines)}async postJournal(e,t=b()){let r=await this.requireJournal(e),a=await this.listJournalLines(e);if(r.status==="posted"||r.status==="reversed")return this.toJournalEntry(r,a);let o={...r,status:"posted",postedAt:t,lastModified:b()};return await this.dbAdapter.update(l.journals,e,o),await this.writeHistory("journals",e,"UPSERT",o),this.toJournalEntry(o,a)}async reverseJournal(e,t){let r=await this.requireJournal(e);if(r.status!=="posted")throw new Error("JOURNAL_NOT_POSTED");let a=await this.listJournalLines(e),o=await this.createJournalDraft({id:t,tenantId:r.tenantId,branchId:r.branchId,financeDomainId:r.financeDomainId,ledgerProfileId:r.ledgerProfileId,occurredAt:r.occurredAt,reference:`reversal:${r.id}`,evidenceRef:r.evidenceRef,lines:a.map(i=>({accountId:i.accountId,debit:i.credit,credit:i.debit,memo:i.memo,openItemId:i.openItemId,openItemType:i.openItemType,counterpartyRef:i.counterpartyRef,documentRef:i.documentRef,dueAt:i.dueAt}))});return this.postJournal(o.id)}async listJournals(e){let r=(await this.dbAdapter.query(l.journals,{filters:{field:"deleted",value:!1}})).filter(o=>Fe(o,e)).sort((o,i)=>o.occurredAt.localeCompare(i.occurredAt)),a=[];for(let o of r){let i=await this.listJournalLines(o.id);a.push(this.toJournalEntry(o,i))}return a}async listOpenItems(e){return D(await this.listJournals(e),e)}async getOpenItemAging(e){return O(await this.listOpenItems(e),e)}async reconcileOpenItems(e){return T(await this.listOpenItems(e),e)}async listCashBankMovements(e){return _(await this.listJournals(e),e)}async summarizeCashBankMovements(e){return w(await this.listCashBankMovements(e))}async listFinancialAuditTrail(e){return(await this.dbAdapter.query(l.histories,{})).map(r=>this.toAuditTrailEntry(r)).filter(r=>r!==null).filter(r=>De(r,e)).sort((r,a)=>r.occurredAt!==a.occurredAt?r.occurredAt.localeCompare(a.occurredAt):r.id.localeCompare(a.id))}async openFiscalPeriod(e){if(!e.id||!e.tenantId||!e.code||!e.startDate||!e.endDate)throw new Error("FISCAL_PERIOD_REQUIRED_FIELDS");if(Date.parse(e.startDate)>Date.parse(e.endDate))throw new Error("FISCAL_PERIOD_INVALID_RANGE");let t=await this.dbAdapter.get(l.periods,e.id);if(t&&!t.deleted)throw new Error("FISCAL_PERIOD_ALREADY_EXISTS");let r=b(),a={...h(e),status:"open",lastModified:r,deleted:!1};return t?await this.dbAdapter.update(l.periods,e.id,a):await this.dbAdapter.create(l.periods,a),await this.writeHistory("periods",e.id,"UPSERT",a),this.toPeriod(a)}async closeFiscalPeriod(e){let t=await this.dbAdapter.get(l.periods,e);if(!t||t.deleted)throw new Error("FISCAL_PERIOD_NOT_FOUND");let r={...t,status:"closed",lastModified:b()};return await this.dbAdapter.update(l.periods,e,r),await this.writeHistory("periods",e,"UPSERT",r),this.toPeriod(r)}async listFiscalPeriods(){return(await this.dbAdapter.query(l.periods,{filters:{field:"deleted",value:!1}})).map(t=>this.toPeriod(t)).sort((t,r)=>t.startDate.localeCompare(r.startDate))}async getTrialBalance(){return this.getTrialBalanceByScope()}async getTrialBalanceByScope(e){let t=await this.listAccounts(),a=(await this.listJournals(e)).filter(i=>i.status==="posted"),o=new Map;for(let i of a)for(let c of i.lines){let s=o.get(c.accountId)??{debit:0,credit:0};s.debit+=Number(c.debit||0),s.credit+=Number(c.credit||0),o.set(c.accountId,s)}return t.map(i=>{let c=o.get(i.id)??{debit:0,credit:0};return{accountId:i.id,accountCode:i.code,accountName:i.name,accountType:i.type,debit:c.debit,credit:c.credit,net:c.debit-c.credit}})}async createRapb(e){if(!e.id||!e.tenantId||!e.periodCode||!e.title)throw new Error("RAPB_REQUIRED_FIELDS");if(!e.lines||e.lines.length===0)throw new Error("RAPB_LINES_REQUIRED");if(e.lines.some(i=>i.budgetedDebit<0||i.budgetedCredit<0))throw new Error("RAPB_NEGATIVE_AMOUNT");let t=await this.dbAdapter.get(l.rapbPlans,e.id);if(t&&!t.deleted)throw new Error("RAPB_ALREADY_EXISTS");let r=b(),a=[];for(let i=0;i<e.lines.length;i+=1){let c=e.lines[i],s=await this.dbAdapter.get(l.accounts,c.accountId);if(!s||s.deleted)throw new Error(`RAPB_ACCOUNT_NOT_FOUND:${c.accountId}`);a.push({id:`${e.id}:line:${i}`,rapbId:e.id,accountId:c.accountId,accountCode:s.code,accountName:s.name,accountType:s.type,budgetedDebit:c.budgetedDebit,budgetedCredit:c.budgetedCredit,budgetedNet:c.budgetedDebit-c.budgetedCredit,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,lastModified:r,deleted:!1})}let o={id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,periodCode:e.periodCode,title:e.title,status:"draft",notes:e.notes,createdAt:r,approvedAt:void 0,approvedBy:void 0,lastModified:r,deleted:!1};await this.dbAdapter.create(l.rapbPlans,o),await this.writeHistory("rapb_plans",e.id,"UPSERT",o);for(let i of a)await this.dbAdapter.create(l.rapbLines,i),await this.writeHistory("rapb_lines",i.id,"UPSERT",i);return this.toRapbPlan(o,a)}async getRapb(e){let t=await this.dbAdapter.get(l.rapbPlans,e);if(!t||t.deleted)return null;let r=await this.listRapbLines(e);return this.toRapbPlan(t,r)}async listRapb(e){let r=await this.dbAdapter.query(l.rapbPlans,{filters:{field:"deleted",value:!1}});e&&(e.tenantId&&(r=r.filter(o=>o.tenantId===e.tenantId)),e.periodCode&&(r=r.filter(o=>o.periodCode===e.periodCode)),e.branchId&&(r=r.filter(o=>o.branchId===e.branchId)),e.financeDomainId&&(r=r.filter(o=>o.financeDomainId===e.financeDomainId)),e.ledgerProfileId&&(r=r.filter(o=>o.ledgerProfileId===e.ledgerProfileId)));let a=[];for(let o of r.sort((i,c)=>i.createdAt.localeCompare(c.createdAt))){let i=await this.listRapbLines(o.id);a.push(this.toRapbPlan(o,i))}return a}async approveRapb(e,t){let r=await this.dbAdapter.get(l.rapbPlans,e);if(!r||r.deleted)throw new Error("RAPB_NOT_FOUND");if(r.status==="approved")throw new Error("RAPB_ALREADY_APPROVED");let a=typeof t=="string"?t:t.approvedBy,o={...r,status:"approved",approvedAt:b(),approvedBy:a,lastModified:b()};await this.dbAdapter.update(l.rapbPlans,e,o),await this.writeHistory("rapb_plans",e,"UPSERT",o);let i=await this.listRapbLines(e);return this.toRapbPlan(o,i)}async evaluateVariance(e){let t=await this.getRapb(e);if(!t)throw new Error("RAPB_NOT_FOUND");let r=await this.getTrialBalanceByScope({tenantId:t.tenantId,branchId:t.branchId,financeDomainId:t.financeDomainId,ledgerProfileId:t.ledgerProfileId}),a=new Map(r.map(d=>[d.accountId,d])),o=0,i=0,c=0,s=0,m=t.lines.map(d=>{let u=a.get(d.accountId),A=u?.debit??0,y=u?.credit??0,S=A-y;return d.accountType==="revenue"?(o+=d.budgetedCredit-d.budgetedDebit,i+=y-A):d.accountType==="expense"&&(c+=d.budgetedDebit-d.budgetedCredit,s+=A-y),{accountId:d.accountId,accountCode:d.accountCode,accountName:d.accountName,accountType:d.accountType,budgetedDebit:d.budgetedDebit,budgetedCredit:d.budgetedCredit,budgetedNet:d.budgetedNet,actualDebit:A,actualCredit:y,actualNet:S,varianceDebit:A-d.budgetedDebit,varianceCredit:y-d.budgetedCredit,varianceNet:S-d.budgetedNet}}),p=o-c,g=i-s;return{rapbId:e,periodCode:t.periodCode,evaluatedAt:b(),lines:m,totalBudgetedRevenue:o,totalActualRevenue:i,totalBudgetedExpense:c,totalActualExpense:s,budgetedNetIncome:p,actualNetIncome:g,netVariance:g-p}}async assertJournalLinesKnownAccounts(e){for(let t of e){let r=await this.dbAdapter.get(l.accounts,t.accountId);if(!r||r.deleted)throw new Error("JOURNAL_ACCOUNT_NOT_FOUND")}}async assertJournalPeriodOpen(e){let t=await this.dbAdapter.query(l.periods,{filters:{field:"deleted",value:!1}});if(t.length===0)return;let r=t.find(a=>!(a.tenantId!==e.tenantId||Date.parse(a.startDate)>Date.parse(e.occurredAt)||Date.parse(a.endDate)<Date.parse(e.occurredAt)||e.ledgerProfileId&&a.ledgerProfileId&&a.ledgerProfileId!==e.ledgerProfileId||e.financeDomainId&&a.financeDomainId&&a.financeDomainId!==e.financeDomainId));if(!r)throw new Error("FISCAL_PERIOD_NOT_FOUND_FOR_DATE");if(r.status!=="open")throw new Error("FISCAL_PERIOD_CLOSED")}async requireJournal(e){let t=await this.dbAdapter.get(l.journals,e);if(!t||t.deleted)throw new Error("JOURNAL_NOT_FOUND");return t}async listJournalLines(e){return(await this.dbAdapter.query(l.journalLines,{filters:{and:[{field:"journalId",value:e},{field:"deleted",value:!1}]}})).sort((r,a)=>r.id.localeCompare(a.id))}async listRapbLines(e){return(await this.dbAdapter.query(l.rapbLines,{filters:{and:[{field:"rapbId",value:e},{field:"deleted",value:!1}]}})).sort((r,a)=>r.id.localeCompare(a.id))}toJournalEntry(e,t){let{lastModified:r,deleted:a,...o}=e;return{...h(o),lines:t.map(i=>h(i))}}toPeriod(e){let{lastModified:t,deleted:r,...a}=e;return h(a)}toRapbPlan(e,t){let{lastModified:r,deleted:a,...o}=e;return{...h(o),lines:t.map(({id:i,rapbId:c,lastModified:s,deleted:m,...p})=>h(p))}}async writeHistory(e,t,r,a){let o=a,i={id:Pe(e,t),tableName:e,recordId:t,action:r,changes:h(o),timestamp:b(),tenantId:typeof o.tenantId=="string"?o.tenantId:void 0,branchId:typeof o.branchId=="string"?o.branchId:void 0,financeDomainId:typeof o.financeDomainId=="string"?o.financeDomainId:void 0,ledgerProfileId:typeof o.ledgerProfileId=="string"?o.ledgerProfileId:void 0};await this.dbAdapter.create(l.histories,i)}toAuditTrailEntry(e){let t=e.changes??{},r=typeof t.tenantId=="string"?t.tenantId:e.tenantId,a=typeof t.branchId=="string"?t.branchId:e.branchId,o=typeof t.financeDomainId=="string"?t.financeDomainId:e.financeDomainId,i=typeof t.ledgerProfileId=="string"?t.ledgerProfileId:e.ledgerProfileId;if(e.tableName==="journals"){let c=typeof t.reference=="string"?t.reference:void 0,s=typeof t.evidenceRef=="string"?t.evidenceRef:void 0,m=typeof t.status=="string"?t.status:void 0,p=Oe(c),g=m==="draft"?"journal_drafted":m==="posted"&&p?"journal_reversal_posted":m==="posted"?"journal_posted":null;return g?{id:e.id,occurredAt:e.timestamp,eventType:g,recordType:"journal",recordId:e.recordId,journalId:e.recordId,sourceJournalId:p,tenantId:r,branchId:a,financeDomainId:o,ledgerProfileId:i,reference:c,evidenceRef:s,summary:g==="journal_reversal_posted"?`Reversal journal ${e.recordId} posted for ${p}`:`Journal ${e.recordId} ${g==="journal_drafted"?"drafted":"posted"}`,metadata:{journalOccurredAt:t.occurredAt,status:m}}:null}if(e.tableName==="periods"){let c=typeof t.status=="string"?t.status:void 0;return c!=="open"&&c!=="closed"?null:{id:e.id,occurredAt:e.timestamp,eventType:c==="open"?"fiscal_period_opened":"fiscal_period_closed",recordType:"fiscal_period",recordId:e.recordId,tenantId:r,branchId:a,financeDomainId:o,ledgerProfileId:i,summary:`Fiscal period ${String(t.code??e.recordId)} ${c}`,metadata:{code:t.code,status:c,startDate:t.startDate,endDate:t.endDate}}}if(e.tableName==="rapb_plans"){let c=typeof t.status=="string"?t.status:void 0,s=c==="draft"?"rapb_created":c==="approved"?"rapb_approved":null;return s?{id:e.id,occurredAt:e.timestamp,eventType:s,recordType:"rapb_plan",recordId:e.recordId,tenantId:r,branchId:a,financeDomainId:o,ledgerProfileId:i,summary:s==="rapb_created"?`RAPB ${String(t.title??e.recordId)} created`:`RAPB ${String(t.title??e.recordId)} approved`,metadata:{title:t.title,status:c,periodCode:t.periodCode,approvedBy:t.approvedBy}}:null}return null}};async function G(n){await L(n);let e=new M(n);return{financeService:Y({createAccount:e.createAccount.bind(e),listAccounts:e.listAccounts.bind(e),createJournalDraft:e.createJournalDraft.bind(e),postJournal:e.postJournal.bind(e),reverseJournal:e.reverseJournal.bind(e),listJournals:e.listJournals.bind(e),openFiscalPeriod:e.openFiscalPeriod.bind(e),closeFiscalPeriod:e.closeFiscalPeriod.bind(e),listFiscalPeriods:e.listFiscalPeriods.bind(e),getTrialBalance:e.getTrialBalance.bind(e),getTrialBalanceByScope:e.getTrialBalanceByScope.bind(e),createRapb:e.createRapb.bind(e),getRapb:e.getRapb.bind(e),listRapb:e.listRapb.bind(e),approveRapb:e.approveRapb.bind(e),evaluateVariance:e.evaluateVariance.bind(e),listOpenItems:e.listOpenItems.bind(e),getOpenItemAging:e.getOpenItemAging.bind(e),reconcileOpenItems:e.reconcileOpenItems.bind(e),listCashBankMovements:e.listCashBankMovements.bind(e),summarizeCashBankMovements:e.summarizeCashBankMovements.bind(e),listFinancialAuditTrail:e.listFinancialAuditTrail.bind(e)})}}var j=class{constructor(e,t){this.runtime=e;this.runtimeStateStore=t;this.runtimeStore=we(this.runtimeStateStore)}static builder(){return new k}get registry(){return this.runtime.registry}async start(e={}){this.runtimeStateStore.setState({phase:"starting",started:!1,lastError:null,lastTransitionAt:new Date().toISOString(),startCount:this.runtimeStateStore.getState().startCount,stopCount:this.runtimeStateStore.getState().stopCount});try{await this.runtime.start(e),this.domainServices=this.runtime.domainServices,this.runtimeStateStore.setState(t=>({...t,phase:"started",started:!0,startCount:t.startCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(t){throw this.runtimeStateStore.setState(r=>({...r,phase:"error",started:!1,lastError:t instanceof Error?t.message:String(t),lastTransitionAt:new Date().toISOString()})),t}}async stop(){this.runtimeStateStore.setState(e=>({...e,phase:"stopping",started:this.runtime.isStarted(),lastError:null,lastTransitionAt:new Date().toISOString()}));try{await this.runtime.stop(),this.runtimeStateStore.setState(e=>({...e,phase:"stopped",started:!1,stopCount:e.stopCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(e){throw this.runtimeStateStore.setState(t=>({...t,phase:"error",started:this.runtime.isStarted(),lastError:e instanceof Error?e.message:String(e),lastTransitionAt:new Date().toISOString()})),e}}isStarted(){return this.runtime.isStarted()}},k=class{constructor(){this.runtimeBuilder=Te.builder();this.runtimeHooks={};this.runtimeBuilder.withDbAdapter(()=>new _e)}withPlatformAdapter(e){return this.runtimeBuilder.withPlatformAdapter(e),this}withDbAdapter(e){return this.runtimeBuilder.withDbAdapter(e),this}withHttpAdapter(e){return this.runtimeBuilder.withHttpAdapter(e),this}withSocketAdapter(e){return this.runtimeBuilder.withSocketAdapter(e),this}withLoggerAdapter(e){return this.runtimeBuilder.withLoggerAdapter(e),this}withActivitySink(e){return this.runtimeBuilder.withActivitySink(e),this}withExtension(e,t){return this.runtimeBuilder.withExtension(e,t),this}withDomainServicesFactory(e){return this.domainServicesFactory=e,this}withRuntimeHooks(e){return this.runtimeHooks={...this.runtimeHooks,...e},this}build(){let e=Ne({phase:"idle",started:!1,startCount:0,stopCount:0,lastError:null,lastTransitionAt:new Date().toISOString()}),t={runMigrations:async a=>{let o=a.registry?.dbAdapter;if(!o)throw new Error("OFINANCE_DB_ADAPTER_REQUIRED");await L(o,a.registry?.loggerAdapter),this.runtimeHooks.runMigrations&&await this.runtimeHooks.runMigrations(a)},...this.runtimeHooks,createDomainServices:async a=>{if(this.domainServicesFactory)return this.domainServicesFactory();let o=a.registry?.dbAdapter;if(!o)throw new Error("OFINANCE_DB_ADAPTER_REQUIRED");return G(o)}};this.runtimeBuilder.withHooks(t);let r=this.runtimeBuilder.build();return new j(r,e)}};function W(n){return!Array.isArray(n.components)||n.components.length===0?[]:n.components.map(e=>{if(!e.accountId?.trim())throw new Error("FINANCE_TAX_ACCOUNT_REQUIRED");if(!Number.isFinite(e.amount)||e.amount<=0)throw new Error("FINANCE_TAX_AMOUNT_INVALID");if(e.direction!=="payable"&&e.direction!=="receivable")throw new Error("FINANCE_TAX_DIRECTION_INVALID");let t=`${n.memoPrefix??"Finance tax"} ${e.direction}`;return{accountId:e.accountId,debit:e.direction==="receivable"?e.amount:0,credit:e.direction==="payable"?e.amount:0,memo:e.memo??t}})}function C(n,e,t){return{id:n.journalId,tenantId:n.tenantId,branchId:n.branchId,financeDomainId:n.financeDomainId,ledgerProfileId:n.ledgerProfileId,occurredAt:n.occurredAt,reference:t?`${n.reference??""}${t}`:n.reference,evidenceRef:n.evidenceRef,lines:e}}function v(n,e){if(!Number.isFinite(n)||n<=0)throw new Error(e)}function z(n,e){v(e.grossAmount,"POS_SALE_INVALID_GROSS_AMOUNT");let t=e.discountAmount??0,r=e.taxAmount??0;if(t<0||r<0)throw new Error("POS_SALE_NEGATIVE_COMPONENT");let a=e.grossAmount,o=a-t+r,i=[{accountId:e.paymentAccountId,debit:o,credit:0,memo:"POS sale payment"},{accountId:e.revenueAccountId,debit:0,credit:a,memo:"POS sale revenue"}];if(t>0){if(!e.discountAccountId)throw new Error("POS_SALE_DISCOUNT_ACCOUNT_REQUIRED");i.push({accountId:e.discountAccountId,debit:t,credit:0,memo:"POS sale discount"})}if(r>0){if(!e.taxPayableAccountId)throw new Error("POS_SALE_TAX_ACCOUNT_REQUIRED");i.push(...W({memoPrefix:"POS sale tax",components:[{accountId:e.taxPayableAccountId,amount:r,direction:"payable",memo:"POS sale tax payable"}]}))}return C(n,i)}function X(n,e){return v(e.principalAmount,"COOP_LOAN_INVALID_PRINCIPAL"),C(n,[{accountId:e.receivableAccountId,debit:e.principalAmount,credit:0,memo:"Loan receivable principal"},{accountId:e.cashAccountId,debit:0,credit:e.principalAmount,memo:"Loan cash out"}])}function K(n,e){return v(e.amount,"COOP_SAVING_INVALID_AMOUNT"),C(n,[{accountId:e.cashAccountId,debit:e.amount,credit:0,memo:"Saving deposit cash in"},{accountId:e.savingLiabilityAccountId,debit:0,credit:e.amount,memo:"Saving liability increase"}])}function Z(n,e){return v(e.amount,"COOP_SAVING_WITHDRAWAL_INVALID_AMOUNT"),C(n,[{accountId:e.savingLiabilityAccountId,debit:e.amount,credit:0,memo:"Saving liability decrease"},{accountId:e.cashAccountId,debit:0,credit:e.amount,memo:"Saving withdrawal cash out"}])}function ee(n,e){v(e.principalAmount,"COOP_LOAN_REPAYMENT_INVALID_PRINCIPAL");let t=e.serviceAmount??0,r=e.penaltyAmount??0;if(t<0||r<0)throw new Error("COOP_LOAN_REPAYMENT_NEGATIVE_COMPONENT");if(t>0&&!e.serviceRevenueAccountId)throw new Error("COOP_LOAN_REPAYMENT_SERVICE_ACCOUNT_REQUIRED");if(r>0&&!e.penaltyRevenueAccountId)throw new Error("COOP_LOAN_REPAYMENT_PENALTY_ACCOUNT_REQUIRED");let a=e.principalAmount+t+r,o=[{accountId:e.cashAccountId,debit:a,credit:0,memo:"Loan repayment cash in"},{accountId:e.receivableAccountId,debit:0,credit:e.principalAmount,memo:"Loan receivable principal repayment"}];return t>0&&o.push({accountId:e.serviceRevenueAccountId,debit:0,credit:t,memo:"Loan service revenue"}),r>0&&o.push({accountId:e.penaltyRevenueAccountId,debit:0,credit:r,memo:"Loan penalty revenue"}),C(n,o)}function Dt(n,e){if(v(e.amount,"COOP_SHU_PARTICIPATION_INVALID_AMOUNT"),!n.evidenceRef?.trim())throw new Error("COOP_SHU_PARTICIPATION_EVIDENCE_REQUIRED");return C(n,[{accountId:e.debitAccountId,debit:e.amount,credit:0,memo:e.memo??"Coop SHU participation manual recap debit"},{accountId:e.creditAccountId,debit:0,credit:e.amount,memo:e.memo??"Coop SHU participation manual recap credit"}])}function te(n,e){return e?{...n,...e}:{...n}}function E(n){let e=n.tenantId?n.scopedMapping.byTenant?.[n.tenantId]:void 0,t=n.tenantId&&n.branchId?`${n.tenantId}:${n.branchId}`:"",r=t?n.scopedMapping.byBranch?.[t]:void 0;return te(te(n.scopedMapping.default,e),r)}function ne(n){return E(n)}function re(n){return E(n)}function ae(n){return E(n)}function oe(n){return E(n)}function ie(n){return E(n)}function Nt(n,e){let{scopedAccountMapping:t,...r}=e,a=ne({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return z(n,{...r,...a})}function Lt(n,e){let{scopedAccountMapping:t,...r}=e,a=re({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return X(n,{...r,...a})}function Mt(n,e){let{scopedAccountMapping:t,...r}=e,a=oe({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return K(n,{...r,...a})}function xt(n,e){let{scopedAccountMapping:t,...r}=e,a=ie({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return Z(n,{...r,...a})}function Bt(n,e){let{scopedAccountMapping:t,...r}=e,a=ae({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return ee(n,{...r,...a})}function x(n){return!!(n&&typeof n=="object"&&n.error)}function U(n){return n.startsWith("ofinance_")?`offinance_${n.slice(9)}`:n}async function Le(n,e,t){let r=await n.accountService.listAccounts();if(x(r))throw new Error(r.error.message||r.error.code||"FINANCE_ACCOUNT_LIST_FAILED");let a=new Set((r.data||[]).map(o=>o.id));for(let o of e){if(a.has(o.id))continue;let i=await n.accountService.createAccount(o);if(x(i))throw new Error(i.error.message||i.error.code||"FINANCE_ACCOUNT_CREATE_FAILED");await t?.({changeId:`offinance:account:${o.id}`,entity:"FinanceAccount",table:U(l.accounts),type:"CREATE",data:o})}}async function ce(n,e,t){return n.query(e,{filters:{and:t}})}async function Me(n,e,t){if(!t)return;let r=await ce(n,l.journals,[{field:"id",value:e.id}]),a=await ce(n,l.journalLines,[{field:"journalId",value:e.id}]);r.length===0&&(r=[{id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,occurredAt:e.occurredAt,reference:e.reference,status:e.status,postedAt:e.postedAt,lastModified:e.postedAt||e.occurredAt,deleted:!1}]),a.length===0&&(a=e.lines.map((o,i)=>({id:`${e.id}:line:${i}`,journalId:e.id,accountId:o.accountId,debit:o.debit,credit:o.credit,memo:o.memo,openItemId:o.openItemId,openItemType:o.openItemType,counterpartyRef:o.counterpartyRef,documentRef:o.documentRef,dueAt:o.dueAt,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,lastModified:e.postedAt||e.occurredAt,deleted:!1})));for(let o of r)await t({changeId:`offinance:journal:${o.id}`,entity:"FinanceJournalEntry",table:U(l.journals),type:"CREATE",data:o});for(let o of a)await t({changeId:`offinance:journal-line:${o.id}`,entity:"FinanceJournalLine",table:U(l.journalLines),type:"CREATE",data:o})}function kt(n){return async e=>{let t=n.resolveFinanceServices();if(!t)throw new Error(n.missingServicesErrorCode||"FINANCE_SERVICES_UNAVAILABLE");let r=n.resolveLedgerProfileId().trim();if(!r)throw new Error(n.missingLedgerProfileErrorCode||"FINANCE_LEDGER_PROFILE_REQUIRED");let a=n.resolveSyncEnqueuer?.()??null;await Le(t,n.requiredAccounts,a);let o=n.buildJournalDraft(e,r),i=await t.journalService.createJournalDraft(o);if(x(i)&&i.error.code!=="JOURNAL_ALREADY_EXISTS")throw new Error(i.error.message||i.error.code||"FINANCE_JOURNAL_CREATE_FAILED");let c=await t.journalService.postJournal(o.id,o.occurredAt);if(x(c))throw new Error(c.error.message||c.error.code||"FINANCE_JOURNAL_POST_FAILED");await Me(n.dbAdapter,c.data,a)}}function xe(n){switch(n.accountType){case"asset":case"expense":return n.debit-n.credit;case"liability":case"equity":case"revenue":return n.credit-n.debit;default:return 0}}function R(n,e){return n.filter(t=>t.accountType===e).reduce((t,r)=>t+xe(r),0)}function Vt(n){let e=R(n,"revenue"),t=R(n,"expense");return{revenue:e,expense:t,netIncome:e-t}}function $t(n){return{assets:R(n,"asset"),liabilities:R(n,"liability"),equity:R(n,"equity")}}function de(n){return n.accountType==="revenue"?n.credit-n.debit:n.accountType==="expense"?n.debit-n.credit:0}function Qt(n){let e=n.filter(r=>r.accountType==="revenue").reduce((r,a)=>r+Math.max(0,de(a)),0),t=n.filter(r=>r.accountType==="expense").reduce((r,a)=>r+Math.max(0,de(a)),0);return{operatingInflow:e,operatingOutflow:t,netOperatingCashflow:e-t}}function qt(n,e){let t=[],r=0;for(let a of e){if(a.accountType==="revenue"){let o=a.credit-a.debit;o>0&&(t.push({accountId:a.accountId,debit:o,credit:0,memo:"Close revenue account"}),r+=o)}if(a.accountType==="expense"){let o=a.debit-a.credit;o>0&&(t.push({accountId:a.accountId,debit:0,credit:o,memo:"Close expense account"}),r-=o)}}return r>0?t.push({accountId:n.retainedEarningsAccountId,debit:0,credit:r,memo:"Retained earnings from period close"}):r<0&&t.push({accountId:n.retainedEarningsAccountId,debit:Math.abs(r),credit:0,memo:"Retained earnings from period close"}),{id:n.journalId,tenantId:n.tenantId,branchId:n.branchId,financeDomainId:n.financeDomainId,ledgerProfileId:n.ledgerProfileId,occurredAt:n.occurredAt,reference:n.reference,lines:t}}function Be(n){return Array.isArray(n)?n.length:n&&typeof n=="object"?1:n===null||typeof n>"u"?0:1}function Je(n){return n==="json"?"application/json":"text/csv"}function je(n,e){if(n==="json")return`${JSON.stringify(e,null,2)}
2
+ `;if(typeof e!="string")throw new Error("FINANCE_COMPLIANCE_EXPORT_CSV_PAYLOAD_STRING_REQUIRED");return e}function ke(n){let e=2166136261;for(let t=0;t<n.length;t+=1)e^=n.charCodeAt(t),e=Math.imul(e,16777619);return`fnv1a32-${(e>>>0).toString(16).padStart(8,"0")}`}function Ue(n){if(!n.key?.trim())throw new Error("FINANCE_COMPLIANCE_EXPORT_DATASET_KEY_REQUIRED");if(!n.fileName?.trim())throw new Error("FINANCE_COMPLIANCE_EXPORT_FILE_NAME_REQUIRED");if(n.format!=="json"&&n.format!=="csv")throw new Error("FINANCE_COMPLIANCE_EXPORT_FORMAT_INVALID")}function Ve(n){return n??"custom"}function se(n){if(!Array.isArray(n.datasets)||n.datasets.length===0)throw new Error("FINANCE_COMPLIANCE_EXPORT_DATASETS_REQUIRED");let e=new Set,t={},r=[];for(let o of n.datasets){if(Ue(o),e.has(o.key))throw new Error("FINANCE_COMPLIANCE_EXPORT_DATASET_KEY_DUPLICATE");e.add(o.key);let i=je(o.format,o.payload);t[o.fileName]=i,r.push({key:o.key,fileName:o.fileName,format:o.format,semantic:Ve(o.semantic),contentType:o.contentType??Je(o.format),recordCount:Be(o.payload),checksum:ke(i)})}return{contract:{contractVersion:"fcx-v1",tenantId:n.tenantId,branchId:n.branchId,financeDomainId:n.financeDomainId,ledgerProfileId:n.ledgerProfileId,generatedAt:n.generatedAt??new Date().toISOString(),period:{from:n.period?.from??null,to:n.period?.to??null,label:n.period?.label??null},currency:{baseCurrencyCode:n.baseCurrencyCode??"IDR"},datasets:r,summary:{datasetCount:r.length,totalRecordCount:r.reduce((o,i)=>o+i.recordCount,0)}},files:t}}function zt(n){return{version:"v1",generatedAt:n.generatedAt??new Date().toISOString(),payload:{trialBalance:n.trialBalance.map(e=>({...e})),incomeStatement:{...n.incomeStatement},balanceSheet:{...n.balanceSheet}}}}function Xt(n){let e=[{key:"trial-balance",fileName:"trial_balance.json",format:"json",semantic:"trial_balance",payload:n.trialBalance},{key:"income-statement",fileName:"income_statement.json",format:"json",semantic:"income_statement",payload:n.incomeStatement},{key:"balance-sheet",fileName:"balance_sheet.json",format:"json",semantic:"balance_sheet",payload:n.balanceSheet}];return typeof n.openItems<"u"&&e.push({key:"open-items",fileName:"open_items.json",format:"json",semantic:"open_items",payload:n.openItems}),typeof n.agingSummary<"u"&&e.push({key:"aging-summary",fileName:"aging_summary.json",format:"json",semantic:"aging_summary",payload:n.agingSummary}),typeof n.reconciliationSummary<"u"&&e.push({key:"reconciliation-summary",fileName:"reconciliation_summary.json",format:"json",semantic:"reconciliation",payload:n.reconciliationSummary}),typeof n.cashMovements<"u"&&e.push({key:"cash-movements",fileName:"cash_movements.json",format:"json",semantic:"cash_movements",payload:n.cashMovements}),se({tenantId:n.tenantId,branchId:n.branchId,financeDomainId:n.financeDomainId,ledgerProfileId:n.ledgerProfileId,generatedAt:n.generatedAt,period:n.period,baseCurrencyCode:n.baseCurrencyCode,datasets:e})}function $e(n){return n.accountType==="revenue"?n.credit-n.debit:n.accountType==="expense"?n.debit-n.credit:0}function ue(n,e){return e===0?n===0?1:0:Number((n/e).toFixed(4))}function Zt(n,e){let t=e.map(a=>{let c=((a.accountCodes?.length?n.filter(m=>a.accountCodes?.includes(m.accountCode)):null)??n.filter(m=>a.accountType?m.accountType===a.accountType:!1)).reduce((m,p)=>m+$e(p),0),s=c-a.plannedAmount;return{id:a.id,label:a.label,plannedAmount:a.plannedAmount,actualAmount:c,varianceAmount:s,achievementRatio:ue(c,a.plannedAmount)}}),r=t.reduce((a,o)=>(a.plannedAmount+=o.plannedAmount,a.actualAmount+=o.actualAmount,a.varianceAmount+=o.varianceAmount,a),{plannedAmount:0,actualAmount:0,varianceAmount:0});return{rows:t,totals:{...r,achievementRatio:ue(r.actualAmount,r.plannedAmount)}}}function He(n,e){switch(e.type){case"finance.account.created":n.createAccount(e.payload);return;case"finance.period.opened":n.openFiscalPeriod(e.payload);return;case"finance.period.closed":n.closeFiscalPeriod(e.payload.periodId);return;case"finance.journal.drafted":n.createJournalDraft(e.payload);return;case"finance.journal.posted":n.postJournal(e.payload.journalId,e.payload.postedAt);return;case"finance.journal.reversed":n.reverseJournal(e.payload.journalId,e.payload.reversalId);return;default:throw new Error("FINANCE_EVENT_UNSUPPORTED")}}function nn(n){let e=new N;for(let t of n)He(e,t);return e}var Qe=[{id:"coa-cash",code:"1101",name:"Kas",type:"asset"},{id:"coa-bank",code:"1102",name:"Bank",type:"asset"},{id:"coa-ar",code:"1201",name:"Piutang Usaha",type:"asset"},{id:"coa-ap",code:"2101",name:"Utang Usaha",type:"liability"},{id:"coa-retained",code:"3201",name:"Laba Ditahan",type:"equity"},{id:"coa-revenue",code:"4101",name:"Pendapatan Operasional",type:"revenue"},{id:"coa-expense",code:"5101",name:"Biaya Operasional",type:"expense"}];function an(n="IDR"){return Qe.map(e=>({id:e.id,code:e.code,name:e.name,type:e.type,currency:n,isActive:!0}))}var qe=[{id:"coop-coa-cash",code:"1101",name:"Kas",type:"asset"},{id:"coop-coa-bank",code:"1102",name:"Bank",type:"asset"},{id:"coop-coa-loan-ar",code:"1201",name:"Piutang Pinjaman Anggota",type:"asset"},{id:"coop-coa-other-ar",code:"1202",name:"Piutang Lain-lain",type:"asset"},{id:"coop-coa-prepaid",code:"1301",name:"Biaya Dibayar Dimuka",type:"asset"},{id:"coop-coa-fixed-asset",code:"1401",name:"Aset Tetap",type:"asset"},{id:"coop-coa-accum-depr",code:"1402",name:"Akumulasi Penyusutan",type:"asset"},{id:"coop-coa-simp-pokok",code:"2101",name:"Simpanan Pokok",type:"liability"},{id:"coop-coa-simp-wajib",code:"2102",name:"Simpanan Wajib",type:"liability"},{id:"coop-coa-simp-sukarela",code:"2103",name:"Simpanan Sukarela",type:"liability"},{id:"coop-coa-simp-berjangka",code:"2104",name:"Simpanan Berjangka",type:"liability"},{id:"coop-coa-ap",code:"2201",name:"Utang Usaha",type:"liability"},{id:"coop-coa-ext-loan",code:"2301",name:"Pinjaman Luar",type:"liability"},{id:"coop-coa-tax-payable",code:"2401",name:"Utang Pajak",type:"liability"},{id:"coop-coa-modal-awal",code:"3101",name:"Modal Awal",type:"equity"},{id:"coop-coa-cadangan-umum",code:"3201",name:"Dana Cadangan Umum",type:"equity"},{id:"coop-coa-cadangan-tujuan",code:"3202",name:"Dana Cadangan Tujuan",type:"equity"},{id:"coop-coa-shu-prior",code:"3301",name:"SHU Tahun Lalu",type:"equity"},{id:"coop-coa-shu-current",code:"3302",name:"SHU Berjalan",type:"equity"},{id:"coop-coa-shu-reserve",code:"3303",name:"Dana SHU Belum Dibagi",type:"equity"},{id:"coop-coa-jasa-pinjaman",code:"4101",name:"Pendapatan Jasa Pinjaman",type:"revenue"},{id:"coop-coa-provisi",code:"4102",name:"Pendapatan Provisi",type:"revenue"},{id:"coop-coa-rev-other",code:"4103",name:"Pendapatan Lain-lain",type:"revenue"},{id:"coop-coa-beban-bunga",code:"5101",name:"Beban Bunga Simpanan",type:"expense"},{id:"coop-coa-beban-ops",code:"5102",name:"Beban Operasional",type:"expense"},{id:"coop-coa-beban-gaji",code:"5103",name:"Beban Gaji dan Tunjangan",type:"expense"},{id:"coop-coa-beban-admin",code:"5104",name:"Beban Administrasi",type:"expense"},{id:"coop-coa-beban-depr",code:"5105",name:"Beban Penyusutan",type:"expense"},{id:"coop-coa-prov-kredit",code:"5106",name:"Cadangan Kerugian Piutang",type:"expense"}];function on(n="IDR"){return qe.map(e=>({id:e.id,code:e.code,name:e.name,type:e.type,currency:n,isActive:!0}))}function cn(n){let e=new Set,t=new Set;for(let r of n){if(!r.id||!r.code||!r.name)return{ok:!1,reason:"COA_REQUIRED_FIELDS"};if(e.has(r.id))return{ok:!1,reason:"COA_DUPLICATE_ID"};if(t.has(r.code))return{ok:!1,reason:"COA_DUPLICATE_CODE"};e.add(r.id),t.add(r.code)}return{ok:!0}}export{Qe as CANONICAL_COA_TEMPLATES,qe as COOP_COA_TEMPLATES,l as OFINANCE_TABLES,N as OffinanceCore,J as OffinanceEnvelopeService,j as OfinanceRuntimeCore,k as OfinanceRuntimeCoreBuilder,He as applyFinanceDomainEvent,L as applyPendingMigrations,$t as buildBalanceSheet,Zt as buildBudgetVsRealization,Qt as buildCashflowBaseline,qt as buildClosingJournalDraft,se as buildFinanceComplianceExportBundle,zt as buildFinanceExportEnvelope,O as buildFinanceOpenItemAging,Xt as buildFinanceOperationalComplianceBundle,W as buildFinanceTaxPostingLines,Vt as buildIncomeStatement,X as buildJournalFromCoopLoanDisbursement,ee as buildJournalFromCoopLoanRepayment,K as buildJournalFromCoopSavingDeposit,Z as buildJournalFromCoopSavingWithdrawal,Dt as buildJournalFromCoopShuParticipationManualRecap,z as buildJournalFromPosSale,Lt as buildJournalFromScopedCoopLoanDisbursement,Bt as buildJournalFromScopedCoopLoanRepayment,Mt as buildJournalFromScopedCoopSavingDeposit,xt as buildJournalFromScopedCoopSavingWithdrawal,Nt as buildJournalFromScopedPosSale,an as createCanonicalCoA,on as createCoopCoA,G as createDbAdapterOfinanceServices,kt as createFinanceProjectionSink,Y as createOffinanceEnvelopeService,I as mapOffinanceErrorToEnvelope,_ as projectFinanceCashBankMovements,D as projectFinanceOpenItems,T as reconcileFinanceOpenItems,nn as replayFinanceDomainEvents,re as resolveCoopLoanDisbursementAccountMapping,ae as resolveCoopLoanRepaymentAccountMapping,oe as resolveCoopSavingDepositAccountMapping,ie as resolveCoopSavingWithdrawalAccountMapping,ne as resolvePosSaleAccountMapping,E as resolveScopedAccountMapping,w as summarizeFinanceCashBankMovements,q as toOffinanceFailureEnvelope,f as toOffinanceSuccessEnvelope,cn as validateCoaIntegrity,P as validateJournalBalance,F as validateOpenItemLineMetadata};
2
3
  /*! For license information please see index.esm.js.LEGAL.txt */
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
- "use strict";var x=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var se=Object.getOwnPropertyNames;var de=Object.prototype.hasOwnProperty;var ue=(r,e)=>{for(var t in e)x(r,t,{get:e[t],enumerable:!0})},le=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of se(e))!de.call(r,a)&&a!==t&&x(r,a,{get:()=>e[a],enumerable:!(n=ce(e,a))||n.enumerable});return r};var pe=r=>le(x({},"__esModule",{value:!0}),r);var Be={};ue(Be,{CANONICAL_COA_TEMPLATES:()=>oe,COOP_COA_TEMPLATES:()=>ie,OFINANCE_TABLES:()=>c,OffinanceCore:()=>D,OffinanceEnvelopeService:()=>F,OfinanceRuntimeCore:()=>_,OfinanceRuntimeCoreBuilder:()=>T,applyFinanceDomainEvent:()=>ae,applyPendingMigrations:()=>R,buildBalanceSheet:()=>we,buildBudgetVsRealization:()=>Le,buildCashflowBaseline:()=>Fe,buildClosingJournalDraft:()=>Oe,buildFinanceExportEnvelope:()=>_e,buildIncomeStatement:()=>Re,buildJournalFromCoopLoanDisbursement:()=>V,buildJournalFromCoopLoanRepayment:()=>q,buildJournalFromCoopSavingDeposit:()=>k,buildJournalFromCoopSavingWithdrawal:()=>H,buildJournalFromCoopShuParticipationManualRecap:()=>be,buildJournalFromPosSale:()=>j,buildJournalFromScopedCoopLoanDisbursement:()=>ye,buildJournalFromScopedCoopLoanRepayment:()=>Pe,buildJournalFromScopedCoopSavingDeposit:()=>he,buildJournalFromScopedCoopSavingWithdrawal:()=>Se,buildJournalFromScopedPosSale:()=>Ae,createCanonicalCoA:()=>xe,createCoopCoA:()=>Je,createDbAdapterOfinanceServices:()=>U,createFinanceProjectionSink:()=>Ee,createOffinanceEnvelopeService:()=>B,mapOffinanceErrorToEnvelope:()=>p,replayFinanceDomainEvents:()=>Ne,resolveCoopLoanDisbursementAccountMapping:()=>Q,resolveCoopLoanRepaymentAccountMapping:()=>W,resolveCoopSavingDepositAccountMapping:()=>Y,resolveCoopSavingWithdrawalAccountMapping:()=>G,resolvePosSaleAccountMapping:()=>$,resolveScopedAccountMapping:()=>S,toOffinanceFailureEnvelope:()=>M,toOffinanceSuccessEnvelope:()=>l,validateCoaIntegrity:()=>Me,validateJournalBalance:()=>E});module.exports=pe(Be);function E(r){if(!Array.isArray(r)||r.length===0)return{ok:!1,totalDebit:0,totalCredit:0,reason:"JOURNAL_LINES_EMPTY"};let e=0,t=0;for(let n of r){if(!n||!n.accountId)return{ok:!1,totalDebit:e,totalCredit:t,reason:"JOURNAL_ACCOUNT_REQUIRED"};if(n.debit<0||n.credit<0)return{ok:!1,totalDebit:e,totalCredit:t,reason:"JOURNAL_NEGATIVE_AMOUNT"};e+=n.debit,t+=n.credit}return Math.abs(e-t)>1e-6?{ok:!1,totalDebit:e,totalCredit:t,reason:"JOURNAL_NOT_BALANCED"}:{ok:!0,totalDebit:e,totalCredit:t}}var D=class{constructor(e){this.state={accounts:e?.accounts??new Map,periods:e?.periods??new Map,journals:e?.journals??new Map,balances:e?.balances??new Map,rapbPlans:e?.rapbPlans??new Map}}createAccount(e){if(!e.id||!e.code||!e.name)throw new Error("FINANCE_ACCOUNT_REQUIRED_FIELDS");if(this.state.accounts.has(e.id))throw new Error("FINANCE_ACCOUNT_ALREADY_EXISTS");if(Array.from(this.state.accounts.values()).some(n=>n.code===e.code))throw new Error("FINANCE_ACCOUNT_CODE_DUPLICATE");return this.state.accounts.set(e.id,{...e}),{...e}}listAccounts(){return Array.from(this.state.accounts.values()).map(e=>({...e})).sort((e,t)=>e.code.localeCompare(t.code))}openFiscalPeriod(e){if(!e.id||!e.tenantId||!e.code||!e.startDate||!e.endDate)throw new Error("FISCAL_PERIOD_REQUIRED_FIELDS");if(this.state.periods.has(e.id))throw new Error("FISCAL_PERIOD_ALREADY_EXISTS");if(Date.parse(e.startDate)>Date.parse(e.endDate))throw new Error("FISCAL_PERIOD_INVALID_RANGE");let t={...e,status:"open"};return this.state.periods.set(t.id,t),{...t}}closeFiscalPeriod(e){let t=this.state.periods.get(e);if(!t)throw new Error("FISCAL_PERIOD_NOT_FOUND");let n={...t,status:"closed"};return this.state.periods.set(e,n),{...n}}listFiscalPeriods(){return Array.from(this.state.periods.values()).map(e=>({...e})).sort((e,t)=>e.startDate.localeCompare(t.startDate))}createJournalDraft(e){if(!e.id||!e.tenantId||!e.occurredAt)throw new Error("JOURNAL_REQUIRED_FIELDS");if(this.state.journals.has(e.id))throw new Error("JOURNAL_ALREADY_EXISTS");this.assertJournalLinesKnownAccounts(e.lines),this.assertJournalPeriodOpen(e.occurredAt);let t=E(e.lines);if(!t.ok)throw new Error(t.reason??"JOURNAL_INVALID");let n={id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,occurredAt:e.occurredAt,reference:e.reference,lines:e.lines.map(a=>({...a})),status:"draft"};return this.state.journals.set(n.id,n),{...n,lines:n.lines.map(a=>({...a}))}}postJournal(e,t=new Date().toISOString()){let n=this.state.journals.get(e);if(!n)throw new Error("JOURNAL_NOT_FOUND");if(n.status==="posted"||n.status==="reversed")return{...n,lines:n.lines.map(o=>({...o}))};this.applyLinesToBalance(n.lines);let a={...n,status:"posted",postedAt:t};return this.state.journals.set(e,a),{...a,lines:a.lines.map(o=>({...o}))}}reverseJournal(e,t){let n=this.state.journals.get(e);if(!n)throw new Error("JOURNAL_NOT_FOUND");if(n.status!=="posted")throw new Error("JOURNAL_NOT_POSTED");if(this.state.journals.has(t))throw new Error("JOURNAL_ALREADY_EXISTS");let a=n.lines.map(i=>({accountId:i.accountId,debit:i.credit,credit:i.debit,memo:i.memo})),o=this.createJournalDraft({id:t,tenantId:n.tenantId,branchId:n.branchId,financeDomainId:n.financeDomainId,ledgerProfileId:n.ledgerProfileId,occurredAt:n.occurredAt,reference:`reversal:${n.id}`,lines:a});return this.postJournal(o.id)}getTrialBalance(){return this.getTrialBalanceByScope()}getTrialBalanceByScope(e){let t=this.computeScopedBalances(e);return this.listAccounts().map(a=>{let o=t.get(a.id)??{debit:0,credit:0};return{accountId:a.id,accountCode:a.code,accountName:a.name,accountType:a.type,debit:o.debit,credit:o.credit,net:o.debit-o.credit}})}listJournals(e){return Array.from(this.state.journals.values()).filter(t=>this.matchesScope(t,e)).map(t=>({...t,lines:t.lines.map(n=>({...n}))})).sort((t,n)=>t.occurredAt.localeCompare(n.occurredAt))}assertJournalLinesKnownAccounts(e){for(let t of e)if(!this.state.accounts.has(t.accountId))throw new Error("JOURNAL_ACCOUNT_NOT_FOUND")}assertJournalPeriodOpen(e){if(this.state.periods.size===0)return;let t=this.findPeriodByDate(e);if(!t)throw new Error("FISCAL_PERIOD_NOT_FOUND_FOR_DATE");if(t.status!=="open")throw new Error("FISCAL_PERIOD_CLOSED")}findPeriodByDate(e){let t=Date.parse(e);for(let n of this.state.periods.values()){let a=Date.parse(n.startDate),o=Date.parse(n.endDate);if(t>=a&&t<=o)return n}return null}applyLinesToBalance(e){for(let t of e){let n=this.state.balances.get(t.accountId)??{debit:0,credit:0};n.debit+=t.debit,n.credit+=t.credit,this.state.balances.set(t.accountId,n)}}computeScopedBalances(e){if(!e||!e.tenantId&&!e.branchId&&!e.financeDomainId&&!e.ledgerProfileId&&!e.occurredFrom&&!e.occurredTo)return this.state.balances;let t=new Map;for(let n of this.state.journals.values())if(n.status==="posted"&&this.matchesScope(n,e))for(let a of n.lines){let o=t.get(a.accountId)??{debit:0,credit:0};o.debit+=a.debit,o.credit+=a.credit,t.set(a.accountId,o)}return t}matchesScope(e,t){return t?!(t.tenantId&&e.tenantId!==t.tenantId||t.branchId&&e.branchId!==t.branchId||t.financeDomainId&&e.financeDomainId!==t.financeDomainId||t.ledgerProfileId&&e.ledgerProfileId!==t.ledgerProfileId||t.occurredFrom&&e.occurredAt<t.occurredFrom||t.occurredTo&&e.occurredAt>t.occurredTo):!0}createRapb(e){if(!e.id||!e.tenantId||!e.periodCode||!e.title)throw new Error("RAPB_REQUIRED_FIELDS");if(!e.lines||e.lines.length===0)throw new Error("RAPB_LINES_REQUIRED");if(this.state.rapbPlans.has(e.id))throw new Error("RAPB_ALREADY_EXISTS");if(e.lines.some(a=>a.budgetedDebit<0||a.budgetedCredit<0))throw new Error("RAPB_NEGATIVE_AMOUNT");let t=e.lines.map(a=>{let o=this.state.accounts.get(a.accountId);if(!o)throw new Error(`RAPB_ACCOUNT_NOT_FOUND:${a.accountId}`);let i=a.budgetedDebit-a.budgetedCredit;return{accountId:a.accountId,accountCode:o.code,accountName:o.name,accountType:o.type,budgetedDebit:a.budgetedDebit,budgetedCredit:a.budgetedCredit,budgetedNet:i}}),n={id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,periodCode:e.periodCode,title:e.title,status:"draft",lines:t,notes:e.notes,createdAt:new Date().toISOString()};return this.state.rapbPlans.set(n.id,n),n}getRapb(e){return this.state.rapbPlans.get(e)??null}listRapb(e){let t=Array.from(this.state.rapbPlans.values());return e&&(e.tenantId&&(t=t.filter(n=>n.tenantId===e.tenantId)),e.periodCode&&(t=t.filter(n=>n.periodCode===e.periodCode)),e.branchId&&(t=t.filter(n=>n.branchId===e.branchId)),e.financeDomainId&&(t=t.filter(n=>n.financeDomainId===e.financeDomainId)),e.ledgerProfileId&&(t=t.filter(n=>n.ledgerProfileId===e.ledgerProfileId))),t}approveRapb(e,t){let n=this.state.rapbPlans.get(e);if(!n)throw new Error("RAPB_NOT_FOUND");let a=typeof t=="string"?t:t.approvedBy;if(n.status==="approved")throw new Error("RAPB_ALREADY_APPROVED");let o={...n,status:"approved",approvedAt:new Date().toISOString(),approvedBy:a};return this.state.rapbPlans.set(e,o),o}evaluateVariance(e){let t=this.state.rapbPlans.get(e);if(!t)throw new Error("RAPB_NOT_FOUND");let n=this.getTrialBalance(),a=new Map(n.map(d=>[d.accountId,d])),o=0,i=0,s=0,u=0,I=t.lines.map(d=>{let v=a.get(d.accountId),m=v?.debit??0,f=v?.credit??0,C=m-f;return d.accountType==="revenue"?(o+=d.budgetedCredit-d.budgetedDebit,i+=f-m):d.accountType==="expense"&&(s+=d.budgetedDebit-d.budgetedCredit,u+=m-f),{accountId:d.accountId,accountCode:d.accountCode,accountName:d.accountName,accountType:d.accountType,budgetedDebit:d.budgetedDebit,budgetedCredit:d.budgetedCredit,budgetedNet:d.budgetedNet,actualDebit:m,actualCredit:f,actualNet:C,varianceDebit:m-d.budgetedDebit,varianceCredit:f-d.budgetedCredit,varianceNet:C-d.budgetedNet}}),A=o-s,P=i-u;return{rapbId:e,periodCode:t.periodCode,evaluatedAt:new Date().toISOString(),lines:I,totalBudgetedRevenue:o,totalActualRevenue:i,totalBudgetedExpense:s,totalActualExpense:u,budgetedNetIncome:A,actualNetIncome:P,netVariance:P-A}}};var z=require("ofcore"),Z=require("ofcore"),L=require("ofcore");var c={accounts:"ofinance_accounts",periods:"ofinance_periods",journals:"ofinance_journals",journalLines:"ofinance_journal_lines",rapbPlans:"ofinance_rapb_plans",rapbLines:"ofinance_rapb_lines",histories:"ofinance_histories"},me=[{name:c.accounts,columns:[{name:"id",type:"string"},{name:"code",type:"string",isIndexed:!0},{name:"name",type:"string"},{name:"type",type:"string",isIndexed:!0},{name:"currency",type:"string"},{name:"isActive",type:"boolean",isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:c.periods,columns:[{name:"id",type:"string"},{name:"tenantId",type:"string",isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"code",type:"string",isIndexed:!0},{name:"startDate",type:"string",isIndexed:!0},{name:"endDate",type:"string",isIndexed:!0},{name:"status",type:"string",isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:c.journals,columns:[{name:"id",type:"string"},{name:"tenantId",type:"string",isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"occurredAt",type:"string",isIndexed:!0},{name:"reference",type:"string",isOptional:!0,isIndexed:!0},{name:"evidenceRef",type:"string",isOptional:!0,isIndexed:!0},{name:"status",type:"string",isIndexed:!0},{name:"postedAt",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:c.journalLines,columns:[{name:"id",type:"string"},{name:"journalId",type:"string",isIndexed:!0},{name:"accountId",type:"string",isIndexed:!0},{name:"debit",type:"number"},{name:"credit",type:"number"},{name:"memo",type:"string",isOptional:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:c.rapbPlans,columns:[{name:"id",type:"string"},{name:"tenantId",type:"string",isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"periodCode",type:"string",isIndexed:!0},{name:"title",type:"string",isIndexed:!0},{name:"status",type:"string",isIndexed:!0},{name:"notes",type:"string",isOptional:!0},{name:"createdAt",type:"string",isIndexed:!0},{name:"approvedAt",type:"string",isOptional:!0,isIndexed:!0},{name:"approvedBy",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:c.rapbLines,columns:[{name:"id",type:"string"},{name:"rapbId",type:"string",isIndexed:!0},{name:"accountId",type:"string",isIndexed:!0},{name:"accountCode",type:"string",isIndexed:!0},{name:"accountName",type:"string"},{name:"accountType",type:"string",isIndexed:!0},{name:"budgetedDebit",type:"number"},{name:"budgetedCredit",type:"number"},{name:"budgetedNet",type:"number"},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:c.histories,columns:[{name:"id",type:"string"},{name:"tableName",type:"string",isIndexed:!0},{name:"recordId",type:"string",isIndexed:!0},{name:"action",type:"string",isIndexed:!0},{name:"changes",type:"json",isOptional:!0},{name:"timestamp",type:"string",isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0}]}];function J(){return me.map(r=>({...r,columns:r.columns.map(e=>({...e}))}))}var K=[{toVersion:1,up:async r=>{let e=J();for(let t of e)try{await r.addTable(t)}catch{}}},{toVersion:2,up:async r=>{let e=J().filter(t=>t.name==="ofinance_rapb_plans"||t.name==="ofinance_rapb_lines");for(let t of e)try{await r.addTable(t)}catch{}}},{toVersion:3,up:async r=>{try{await r.addColumn("ofinance_journals",{name:"evidenceRef",type:"string",isOptional:!0,isIndexed:!0})}catch{}}}];var fe={logInfo(){},logWarn(){},logError(){}};async function R(r,e=fe){e.logInfo("[offinance] starting database migration process");let t=[...K].sort((o,i)=>o.toVersion-i.toVersion),n=t.length>0?t[t.length-1].toVersion:0,a=await r.getSchemaVersion();if((a==null||a<0)&&(a=0),a>=n){e.logInfo(`[offinance] database already up-to-date at v${a}`);return}for(let o of t)o.toVersion>a&&(e.logInfo(`[offinance] applying migration v${o.toVersion}`),await o.up(r),await r.setSchemaVersion(o.toVersion),a=o.toVersion);e.logInfo(`[offinance] migration completed at v${a}`)}function l(r,e){return{data:r,meta:{request_id:e??null,timestamp:new Date().toISOString()}}}function M(r,e,t={}){return{error:{code:r,message:e,details:t.details,retryable:t.retryable,correlationId:t.correlationId,timestamp:new Date().toISOString()},meta:{request_id:t.requestId??null,timestamp:new Date().toISOString()}}}function p(r,e="FINANCE_NOT_IMPLEMENTED",t="Unhandled offinance error."){return r instanceof Error?M(e,r.message||t):M(e,t)}var F=class{constructor(e){this.legacy=e;this.accountService={createAccount:async t=>{try{return l(await this.legacy.accountService.createAccount(t))}catch(n){return p(n)}},listAccounts:async()=>{try{return l(await this.legacy.accountService.listAccounts())}catch(t){return p(t)}}},this.journalService={createJournalDraft:async t=>{try{return l(await this.legacy.journalService.createJournalDraft(t))}catch(n){return p(n)}},postJournal:async(t,n)=>{try{return l(await this.legacy.journalService.postJournal(t,n))}catch(a){return p(a)}},reverseJournal:async(t,n)=>{try{return l(await this.legacy.journalService.reverseJournal(t,n))}catch(a){return p(a)}},listJournals:async t=>{try{return l(await this.legacy.journalService.listJournals(t))}catch(n){return p(n)}}},this.fiscalService={openFiscalPeriod:async t=>{try{return l(await this.legacy.fiscalService.openFiscalPeriod(t))}catch(n){return p(n)}},closeFiscalPeriod:async t=>{try{return l(await this.legacy.fiscalService.closeFiscalPeriod(t))}catch(n){return p(n)}},listFiscalPeriods:async()=>{try{return l(await this.legacy.fiscalService.listFiscalPeriods())}catch(t){return p(t)}},getTrialBalance:async()=>{try{return l(await this.legacy.fiscalService.getTrialBalance())}catch(t){return p(t)}},getTrialBalanceByScope:async t=>{try{return l(await this.legacy.fiscalService.getTrialBalanceByScope(t))}catch(n){return p(n)}}},this.rapbService={createRapb:async t=>{try{return l(await this.legacy.rapbService.createRapb(t))}catch(n){return p(n)}},getRapb:async t=>{try{return l(await this.legacy.rapbService.getRapb(t))}catch(n){return p(n)}},listRapb:async t=>{try{return l(await this.legacy.rapbService.listRapb(t))}catch(n){return p(n)}},approveRapb:async(t,n)=>{try{return l(await this.legacy.rapbService.approveRapb(t,n))}catch(a){return p(a)}},evaluateVariance:async t=>{try{return l(await this.legacy.rapbService.evaluateVariance(t))}catch(n){return p(n)}}}}};function B(r){return new F({accountService:r,journalService:r,fiscalService:r,rapbService:r})}function b(r){return JSON.parse(JSON.stringify(r))}function g(){return new Date().toISOString()}function ge(r,e){return`${r}:${e}:${Date.now()}:${Math.random().toString(36).slice(2,8)}`}function Ie(r,e){return!r||r.deleted?!1:e?!(e.tenantId&&r.tenantId!==e.tenantId||e.branchId&&r.branchId!==e.branchId||e.financeDomainId&&r.financeDomainId!==e.financeDomainId||e.ledgerProfileId&&r.ledgerProfileId!==e.ledgerProfileId||e.occurredFrom&&r.occurredAt&&r.occurredAt<e.occurredFrom||e.occurredTo&&r.occurredAt&&r.occurredAt>e.occurredTo):!0}var O=class{constructor(e){this.dbAdapter=e}async createAccount(e){if(!e.id||!e.code||!e.name)throw new Error("FINANCE_ACCOUNT_REQUIRED_FIELDS");let t=await this.dbAdapter.get(c.accounts,e.id);if(t&&!t.deleted)throw new Error("FINANCE_ACCOUNT_ALREADY_EXISTS");if((await this.dbAdapter.query(c.accounts,{filters:{and:[{field:"code",value:e.code},{field:"deleted",value:!1}]}})).some(i=>i.id!==e.id))throw new Error("FINANCE_ACCOUNT_CODE_DUPLICATE");let a=g(),o={...b(e),lastModified:a,deleted:!1};return t?await this.dbAdapter.update(c.accounts,e.id,o):await this.dbAdapter.create(c.accounts,o),await this.writeHistory("accounts",e.id,"UPSERT",o),b(e)}async listAccounts(){return(await this.dbAdapter.query(c.accounts,{filters:{field:"deleted",value:!1}})).map(({lastModified:t,deleted:n,...a})=>b(a)).sort((t,n)=>t.code.localeCompare(n.code))}async createJournalDraft(e){if(!e.id||!e.tenantId||!e.occurredAt)throw new Error("JOURNAL_REQUIRED_FIELDS");if(!e.ledgerProfileId)throw new Error("JOURNAL_REQUIRED_FIELDS");let t=await this.dbAdapter.get(c.journals,e.id);if(t&&!t.deleted)throw new Error("JOURNAL_ALREADY_EXISTS");await this.assertJournalLinesKnownAccounts(e.lines),await this.assertJournalPeriodOpen(e);let n=E(e.lines);if(!n.ok)throw new Error(n.reason??"JOURNAL_INVALID");let a=g(),o={id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,occurredAt:e.occurredAt,reference:e.reference,evidenceRef:e.evidenceRef,status:"draft",postedAt:void 0,lastModified:a,deleted:!1};await this.dbAdapter.create(c.journals,o);for(let i=0;i<e.lines.length;i+=1){let s=e.lines[i],u={id:`${e.id}:line:${i}`,journalId:e.id,accountId:s.accountId,debit:s.debit,credit:s.credit,memo:s.memo,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,lastModified:a,deleted:!1};await this.dbAdapter.create(c.journalLines,u),await this.writeHistory("journal_lines",u.id,"UPSERT",u)}return await this.writeHistory("journals",e.id,"UPSERT",o),this.toJournalEntry(o,e.lines)}async postJournal(e,t=g()){let n=await this.requireJournal(e),a=await this.listJournalLines(e);if(n.status==="posted"||n.status==="reversed")return this.toJournalEntry(n,a);let o={...n,status:"posted",postedAt:t,lastModified:g()};return await this.dbAdapter.update(c.journals,e,o),await this.writeHistory("journals",e,"UPSERT",o),this.toJournalEntry(o,a)}async reverseJournal(e,t){let n=await this.requireJournal(e);if(n.status!=="posted")throw new Error("JOURNAL_NOT_POSTED");let a=await this.listJournalLines(e),o=await this.createJournalDraft({id:t,tenantId:n.tenantId,branchId:n.branchId,financeDomainId:n.financeDomainId,ledgerProfileId:n.ledgerProfileId,occurredAt:n.occurredAt,reference:`reversal:${n.id}`,evidenceRef:n.evidenceRef,lines:a.map(i=>({accountId:i.accountId,debit:i.credit,credit:i.debit,memo:i.memo}))});return this.postJournal(o.id)}async listJournals(e){let n=(await this.dbAdapter.query(c.journals,{filters:{field:"deleted",value:!1}})).filter(o=>Ie(o,e)).sort((o,i)=>o.occurredAt.localeCompare(i.occurredAt)),a=[];for(let o of n){let i=await this.listJournalLines(o.id);a.push(this.toJournalEntry(o,i))}return a}async openFiscalPeriod(e){if(!e.id||!e.tenantId||!e.code||!e.startDate||!e.endDate)throw new Error("FISCAL_PERIOD_REQUIRED_FIELDS");if(Date.parse(e.startDate)>Date.parse(e.endDate))throw new Error("FISCAL_PERIOD_INVALID_RANGE");let t=await this.dbAdapter.get(c.periods,e.id);if(t&&!t.deleted)throw new Error("FISCAL_PERIOD_ALREADY_EXISTS");let n=g(),a={...b(e),status:"open",lastModified:n,deleted:!1};return t?await this.dbAdapter.update(c.periods,e.id,a):await this.dbAdapter.create(c.periods,a),await this.writeHistory("periods",e.id,"UPSERT",a),this.toPeriod(a)}async closeFiscalPeriod(e){let t=await this.dbAdapter.get(c.periods,e);if(!t||t.deleted)throw new Error("FISCAL_PERIOD_NOT_FOUND");let n={...t,status:"closed",lastModified:g()};return await this.dbAdapter.update(c.periods,e,n),await this.writeHistory("periods",e,"UPSERT",n),this.toPeriod(n)}async listFiscalPeriods(){return(await this.dbAdapter.query(c.periods,{filters:{field:"deleted",value:!1}})).map(t=>this.toPeriod(t)).sort((t,n)=>t.startDate.localeCompare(n.startDate))}async getTrialBalance(){return this.getTrialBalanceByScope()}async getTrialBalanceByScope(e){let t=await this.listAccounts(),a=(await this.listJournals(e)).filter(i=>i.status==="posted"),o=new Map;for(let i of a)for(let s of i.lines){let u=o.get(s.accountId)??{debit:0,credit:0};u.debit+=Number(s.debit||0),u.credit+=Number(s.credit||0),o.set(s.accountId,u)}return t.map(i=>{let s=o.get(i.id)??{debit:0,credit:0};return{accountId:i.id,accountCode:i.code,accountName:i.name,accountType:i.type,debit:s.debit,credit:s.credit,net:s.debit-s.credit}})}async createRapb(e){if(!e.id||!e.tenantId||!e.periodCode||!e.title)throw new Error("RAPB_REQUIRED_FIELDS");if(!e.lines||e.lines.length===0)throw new Error("RAPB_LINES_REQUIRED");if(e.lines.some(i=>i.budgetedDebit<0||i.budgetedCredit<0))throw new Error("RAPB_NEGATIVE_AMOUNT");let t=await this.dbAdapter.get(c.rapbPlans,e.id);if(t&&!t.deleted)throw new Error("RAPB_ALREADY_EXISTS");let n=g(),a=[];for(let i=0;i<e.lines.length;i+=1){let s=e.lines[i],u=await this.dbAdapter.get(c.accounts,s.accountId);if(!u||u.deleted)throw new Error(`RAPB_ACCOUNT_NOT_FOUND:${s.accountId}`);a.push({id:`${e.id}:line:${i}`,rapbId:e.id,accountId:s.accountId,accountCode:u.code,accountName:u.name,accountType:u.type,budgetedDebit:s.budgetedDebit,budgetedCredit:s.budgetedCredit,budgetedNet:s.budgetedDebit-s.budgetedCredit,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,lastModified:n,deleted:!1})}let o={id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,periodCode:e.periodCode,title:e.title,status:"draft",notes:e.notes,createdAt:n,approvedAt:void 0,approvedBy:void 0,lastModified:n,deleted:!1};await this.dbAdapter.create(c.rapbPlans,o),await this.writeHistory("rapb_plans",e.id,"UPSERT",o);for(let i of a)await this.dbAdapter.create(c.rapbLines,i),await this.writeHistory("rapb_lines",i.id,"UPSERT",i);return this.toRapbPlan(o,a)}async getRapb(e){let t=await this.dbAdapter.get(c.rapbPlans,e);if(!t||t.deleted)return null;let n=await this.listRapbLines(e);return this.toRapbPlan(t,n)}async listRapb(e){let n=await this.dbAdapter.query(c.rapbPlans,{filters:{field:"deleted",value:!1}});e&&(e.tenantId&&(n=n.filter(o=>o.tenantId===e.tenantId)),e.periodCode&&(n=n.filter(o=>o.periodCode===e.periodCode)),e.branchId&&(n=n.filter(o=>o.branchId===e.branchId)),e.financeDomainId&&(n=n.filter(o=>o.financeDomainId===e.financeDomainId)),e.ledgerProfileId&&(n=n.filter(o=>o.ledgerProfileId===e.ledgerProfileId)));let a=[];for(let o of n.sort((i,s)=>i.createdAt.localeCompare(s.createdAt))){let i=await this.listRapbLines(o.id);a.push(this.toRapbPlan(o,i))}return a}async approveRapb(e,t){let n=await this.dbAdapter.get(c.rapbPlans,e);if(!n||n.deleted)throw new Error("RAPB_NOT_FOUND");if(n.status==="approved")throw new Error("RAPB_ALREADY_APPROVED");let a=typeof t=="string"?t:t.approvedBy,o={...n,status:"approved",approvedAt:g(),approvedBy:a,lastModified:g()};await this.dbAdapter.update(c.rapbPlans,e,o),await this.writeHistory("rapb_plans",e,"UPSERT",o);let i=await this.listRapbLines(e);return this.toRapbPlan(o,i)}async evaluateVariance(e){let t=await this.getRapb(e);if(!t)throw new Error("RAPB_NOT_FOUND");let n=await this.getTrialBalanceByScope({tenantId:t.tenantId,branchId:t.branchId,financeDomainId:t.financeDomainId,ledgerProfileId:t.ledgerProfileId}),a=new Map(n.map(d=>[d.accountId,d])),o=0,i=0,s=0,u=0,I=t.lines.map(d=>{let v=a.get(d.accountId),m=v?.debit??0,f=v?.credit??0,C=m-f;return d.accountType==="revenue"?(o+=d.budgetedCredit-d.budgetedDebit,i+=f-m):d.accountType==="expense"&&(s+=d.budgetedDebit-d.budgetedCredit,u+=m-f),{accountId:d.accountId,accountCode:d.accountCode,accountName:d.accountName,accountType:d.accountType,budgetedDebit:d.budgetedDebit,budgetedCredit:d.budgetedCredit,budgetedNet:d.budgetedNet,actualDebit:m,actualCredit:f,actualNet:C,varianceDebit:m-d.budgetedDebit,varianceCredit:f-d.budgetedCredit,varianceNet:C-d.budgetedNet}}),A=o-s,P=i-u;return{rapbId:e,periodCode:t.periodCode,evaluatedAt:g(),lines:I,totalBudgetedRevenue:o,totalActualRevenue:i,totalBudgetedExpense:s,totalActualExpense:u,budgetedNetIncome:A,actualNetIncome:P,netVariance:P-A}}async assertJournalLinesKnownAccounts(e){for(let t of e){let n=await this.dbAdapter.get(c.accounts,t.accountId);if(!n||n.deleted)throw new Error("JOURNAL_ACCOUNT_NOT_FOUND")}}async assertJournalPeriodOpen(e){let t=await this.dbAdapter.query(c.periods,{filters:{field:"deleted",value:!1}});if(t.length===0)return;let n=t.find(a=>!(a.tenantId!==e.tenantId||Date.parse(a.startDate)>Date.parse(e.occurredAt)||Date.parse(a.endDate)<Date.parse(e.occurredAt)||e.ledgerProfileId&&a.ledgerProfileId&&a.ledgerProfileId!==e.ledgerProfileId||e.financeDomainId&&a.financeDomainId&&a.financeDomainId!==e.financeDomainId));if(!n)throw new Error("FISCAL_PERIOD_NOT_FOUND_FOR_DATE");if(n.status!=="open")throw new Error("FISCAL_PERIOD_CLOSED")}async requireJournal(e){let t=await this.dbAdapter.get(c.journals,e);if(!t||t.deleted)throw new Error("JOURNAL_NOT_FOUND");return t}async listJournalLines(e){return(await this.dbAdapter.query(c.journalLines,{filters:{and:[{field:"journalId",value:e},{field:"deleted",value:!1}]}})).sort((n,a)=>n.id.localeCompare(a.id))}async listRapbLines(e){return(await this.dbAdapter.query(c.rapbLines,{filters:{and:[{field:"rapbId",value:e},{field:"deleted",value:!1}]}})).sort((n,a)=>n.id.localeCompare(a.id))}toJournalEntry(e,t){let{lastModified:n,deleted:a,...o}=e;return{...b(o),lines:t.map(i=>b(i))}}toPeriod(e){let{lastModified:t,deleted:n,...a}=e;return b(a)}toRapbPlan(e,t){let{lastModified:n,deleted:a,...o}=e;return{...b(o),lines:t.map(({id:i,rapbId:s,lastModified:u,deleted:I,...A})=>b(A))}}async writeHistory(e,t,n,a){let o=a,i={id:ge(e,t),tableName:e,recordId:t,action:n,changes:b(o),timestamp:g(),tenantId:typeof o.tenantId=="string"?o.tenantId:void 0,branchId:typeof o.branchId=="string"?o.branchId:void 0,financeDomainId:typeof o.financeDomainId=="string"?o.financeDomainId:void 0,ledgerProfileId:typeof o.ledgerProfileId=="string"?o.ledgerProfileId:void 0};await this.dbAdapter.create(c.histories,i)}};async function U(r){await R(r);let e=new O(r);return{financeService:B({createAccount:e.createAccount.bind(e),listAccounts:e.listAccounts.bind(e),createJournalDraft:e.createJournalDraft.bind(e),postJournal:e.postJournal.bind(e),reverseJournal:e.reverseJournal.bind(e),listJournals:e.listJournals.bind(e),openFiscalPeriod:e.openFiscalPeriod.bind(e),closeFiscalPeriod:e.closeFiscalPeriod.bind(e),listFiscalPeriods:e.listFiscalPeriods.bind(e),getTrialBalance:e.getTrialBalance.bind(e),getTrialBalanceByScope:e.getTrialBalanceByScope.bind(e),createRapb:e.createRapb.bind(e),getRapb:e.getRapb.bind(e),listRapb:e.listRapb.bind(e),approveRapb:e.approveRapb.bind(e),evaluateVariance:e.evaluateVariance.bind(e)})}}var _=class{constructor(e,t){this.runtime=e;this.runtimeStateStore=t;this.runtimeStore=(0,L.asReadonlyStore)(this.runtimeStateStore)}static builder(){return new T}get registry(){return this.runtime.registry}async start(e={}){this.runtimeStateStore.setState({phase:"starting",started:!1,lastError:null,lastTransitionAt:new Date().toISOString(),startCount:this.runtimeStateStore.getState().startCount,stopCount:this.runtimeStateStore.getState().stopCount});try{await this.runtime.start(e),this.domainServices=this.runtime.domainServices,this.runtimeStateStore.setState(t=>({...t,phase:"started",started:!0,startCount:t.startCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(t){throw this.runtimeStateStore.setState(n=>({...n,phase:"error",started:!1,lastError:t instanceof Error?t.message:String(t),lastTransitionAt:new Date().toISOString()})),t}}async stop(){this.runtimeStateStore.setState(e=>({...e,phase:"stopping",started:this.runtime.isStarted(),lastError:null,lastTransitionAt:new Date().toISOString()}));try{await this.runtime.stop(),this.runtimeStateStore.setState(e=>({...e,phase:"stopped",started:!1,stopCount:e.stopCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(e){throw this.runtimeStateStore.setState(t=>({...t,phase:"error",started:this.runtime.isStarted(),lastError:e instanceof Error?e.message:String(e),lastTransitionAt:new Date().toISOString()})),e}}isStarted(){return this.runtime.isStarted()}},T=class{constructor(){this.runtimeBuilder=z.CoreRuntime.builder();this.runtimeHooks={};this.runtimeBuilder.withDbAdapter(()=>new Z.InMemoryDbAdapter)}withPlatformAdapter(e){return this.runtimeBuilder.withPlatformAdapter(e),this}withDbAdapter(e){return this.runtimeBuilder.withDbAdapter(e),this}withHttpAdapter(e){return this.runtimeBuilder.withHttpAdapter(e),this}withSocketAdapter(e){return this.runtimeBuilder.withSocketAdapter(e),this}withLoggerAdapter(e){return this.runtimeBuilder.withLoggerAdapter(e),this}withActivitySink(e){return this.runtimeBuilder.withActivitySink(e),this}withExtension(e,t){return this.runtimeBuilder.withExtension(e,t),this}withDomainServicesFactory(e){return this.domainServicesFactory=e,this}withRuntimeHooks(e){return this.runtimeHooks={...this.runtimeHooks,...e},this}build(){let e=(0,L.createStore)({phase:"idle",started:!1,startCount:0,stopCount:0,lastError:null,lastTransitionAt:new Date().toISOString()}),t={runMigrations:async a=>{let o=a.registry?.dbAdapter;if(!o)throw new Error("OFINANCE_DB_ADAPTER_REQUIRED");await R(o,a.registry?.loggerAdapter),this.runtimeHooks.runMigrations&&await this.runtimeHooks.runMigrations(a)},...this.runtimeHooks,createDomainServices:async a=>{if(this.domainServicesFactory)return this.domainServicesFactory();let o=a.registry?.dbAdapter;if(!o)throw new Error("OFINANCE_DB_ADAPTER_REQUIRED");return U(o)}};this.runtimeBuilder.withHooks(t);let n=this.runtimeBuilder.build();return new _(n,e)}};function y(r,e,t){return{id:r.journalId,tenantId:r.tenantId,branchId:r.branchId,financeDomainId:r.financeDomainId,ledgerProfileId:r.ledgerProfileId,occurredAt:r.occurredAt,reference:t?`${r.reference??""}${t}`:r.reference,evidenceRef:r.evidenceRef,lines:e}}function h(r,e){if(!Number.isFinite(r)||r<=0)throw new Error(e)}function j(r,e){h(e.grossAmount,"POS_SALE_INVALID_GROSS_AMOUNT");let t=e.discountAmount??0,n=e.taxAmount??0;if(t<0||n<0)throw new Error("POS_SALE_NEGATIVE_COMPONENT");let a=e.grossAmount,o=a-t+n,i=[{accountId:e.paymentAccountId,debit:o,credit:0,memo:"POS sale payment"},{accountId:e.revenueAccountId,debit:0,credit:a,memo:"POS sale revenue"}];if(t>0){if(!e.discountAccountId)throw new Error("POS_SALE_DISCOUNT_ACCOUNT_REQUIRED");i.push({accountId:e.discountAccountId,debit:t,credit:0,memo:"POS sale discount"})}if(n>0){if(!e.taxPayableAccountId)throw new Error("POS_SALE_TAX_ACCOUNT_REQUIRED");i.push({accountId:e.taxPayableAccountId,debit:0,credit:n,memo:"POS sale tax payable"})}return y(r,i)}function V(r,e){return h(e.principalAmount,"COOP_LOAN_INVALID_PRINCIPAL"),y(r,[{accountId:e.receivableAccountId,debit:e.principalAmount,credit:0,memo:"Loan receivable principal"},{accountId:e.cashAccountId,debit:0,credit:e.principalAmount,memo:"Loan cash out"}])}function k(r,e){return h(e.amount,"COOP_SAVING_INVALID_AMOUNT"),y(r,[{accountId:e.cashAccountId,debit:e.amount,credit:0,memo:"Saving deposit cash in"},{accountId:e.savingLiabilityAccountId,debit:0,credit:e.amount,memo:"Saving liability increase"}])}function H(r,e){return h(e.amount,"COOP_SAVING_WITHDRAWAL_INVALID_AMOUNT"),y(r,[{accountId:e.savingLiabilityAccountId,debit:e.amount,credit:0,memo:"Saving liability decrease"},{accountId:e.cashAccountId,debit:0,credit:e.amount,memo:"Saving withdrawal cash out"}])}function q(r,e){h(e.principalAmount,"COOP_LOAN_REPAYMENT_INVALID_PRINCIPAL");let t=e.serviceAmount??0,n=e.penaltyAmount??0;if(t<0||n<0)throw new Error("COOP_LOAN_REPAYMENT_NEGATIVE_COMPONENT");if(t>0&&!e.serviceRevenueAccountId)throw new Error("COOP_LOAN_REPAYMENT_SERVICE_ACCOUNT_REQUIRED");if(n>0&&!e.penaltyRevenueAccountId)throw new Error("COOP_LOAN_REPAYMENT_PENALTY_ACCOUNT_REQUIRED");let a=e.principalAmount+t+n,o=[{accountId:e.cashAccountId,debit:a,credit:0,memo:"Loan repayment cash in"},{accountId:e.receivableAccountId,debit:0,credit:e.principalAmount,memo:"Loan receivable principal repayment"}];return t>0&&o.push({accountId:e.serviceRevenueAccountId,debit:0,credit:t,memo:"Loan service revenue"}),n>0&&o.push({accountId:e.penaltyRevenueAccountId,debit:0,credit:n,memo:"Loan penalty revenue"}),y(r,o)}function be(r,e){if(h(e.amount,"COOP_SHU_PARTICIPATION_INVALID_AMOUNT"),!r.evidenceRef?.trim())throw new Error("COOP_SHU_PARTICIPATION_EVIDENCE_REQUIRED");return y(r,[{accountId:e.debitAccountId,debit:e.amount,credit:0,memo:e.memo??"Coop SHU participation manual recap debit"},{accountId:e.creditAccountId,debit:0,credit:e.amount,memo:e.memo??"Coop SHU participation manual recap credit"}])}function ee(r,e){return e?{...r,...e}:{...r}}function S(r){let e=r.tenantId?r.scopedMapping.byTenant?.[r.tenantId]:void 0,t=r.tenantId&&r.branchId?`${r.tenantId}:${r.branchId}`:"",n=t?r.scopedMapping.byBranch?.[t]:void 0;return ee(ee(r.scopedMapping.default,e),n)}function $(r){return S(r)}function Q(r){return S(r)}function W(r){return S(r)}function Y(r){return S(r)}function G(r){return S(r)}function Ae(r,e){let{scopedAccountMapping:t,...n}=e,a=$({tenantId:r.tenantId,branchId:r.branchId,scopedMapping:t});return j(r,{...n,...a})}function ye(r,e){let{scopedAccountMapping:t,...n}=e,a=Q({tenantId:r.tenantId,branchId:r.branchId,scopedMapping:t});return V(r,{...n,...a})}function he(r,e){let{scopedAccountMapping:t,...n}=e,a=Y({tenantId:r.tenantId,branchId:r.branchId,scopedMapping:t});return k(r,{...n,...a})}function Se(r,e){let{scopedAccountMapping:t,...n}=e,a=G({tenantId:r.tenantId,branchId:r.branchId,scopedMapping:t});return H(r,{...n,...a})}function Pe(r,e){let{scopedAccountMapping:t,...n}=e,a=W({tenantId:r.tenantId,branchId:r.branchId,scopedMapping:t});return q(r,{...n,...a})}function N(r){return!!(r&&typeof r=="object"&&r.error)}function X(r){return r.startsWith("ofinance_")?`offinance_${r.slice(9)}`:r}async function ve(r,e,t){let n=await r.accountService.listAccounts();if(N(n))throw new Error(n.error.message||n.error.code||"FINANCE_ACCOUNT_LIST_FAILED");let a=new Set((n.data||[]).map(o=>o.id));for(let o of e){if(a.has(o.id))continue;let i=await r.accountService.createAccount(o);if(N(i))throw new Error(i.error.message||i.error.code||"FINANCE_ACCOUNT_CREATE_FAILED");await t?.({changeId:`offinance:account:${o.id}`,entity:"FinanceAccount",table:X(c.accounts),type:"CREATE",data:o})}}async function te(r,e,t){return r.query(e,{filters:{and:t}})}async function Ce(r,e,t){if(!t)return;let n=await te(r,c.journals,[{field:"id",value:e.id}]),a=await te(r,c.journalLines,[{field:"journalId",value:e.id}]);n.length===0&&(n=[{id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,occurredAt:e.occurredAt,reference:e.reference,status:e.status,postedAt:e.postedAt,lastModified:e.postedAt||e.occurredAt,deleted:!1}]),a.length===0&&(a=e.lines.map((o,i)=>({id:`${e.id}:line:${i}`,journalId:e.id,accountId:o.accountId,debit:o.debit,credit:o.credit,memo:o.memo,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,lastModified:e.postedAt||e.occurredAt,deleted:!1})));for(let o of n)await t({changeId:`offinance:journal:${o.id}`,entity:"FinanceJournalEntry",table:X(c.journals),type:"CREATE",data:o});for(let o of a)await t({changeId:`offinance:journal-line:${o.id}`,entity:"FinanceJournalLine",table:X(c.journalLines),type:"CREATE",data:o})}function Ee(r){return async e=>{let t=r.resolveFinanceServices();if(!t)throw new Error(r.missingServicesErrorCode||"FINANCE_SERVICES_UNAVAILABLE");let n=r.resolveLedgerProfileId().trim();if(!n)throw new Error(r.missingLedgerProfileErrorCode||"FINANCE_LEDGER_PROFILE_REQUIRED");let a=r.resolveSyncEnqueuer?.()??null;await ve(t,r.requiredAccounts,a);let o=r.buildJournalDraft(e,n),i=await t.journalService.createJournalDraft(o);if(N(i)&&i.error.code!=="JOURNAL_ALREADY_EXISTS")throw new Error(i.error.message||i.error.code||"FINANCE_JOURNAL_CREATE_FAILED");let s=await t.journalService.postJournal(o.id,o.occurredAt);if(N(s))throw new Error(s.error.message||s.error.code||"FINANCE_JOURNAL_POST_FAILED");await Ce(r.dbAdapter,s.data,a)}}function De(r){switch(r.accountType){case"asset":case"expense":return r.debit-r.credit;case"liability":case"equity":case"revenue":return r.credit-r.debit;default:return 0}}function w(r,e){return r.filter(t=>t.accountType===e).reduce((t,n)=>t+De(n),0)}function Re(r){let e=w(r,"revenue"),t=w(r,"expense");return{revenue:e,expense:t,netIncome:e-t}}function we(r){return{assets:w(r,"asset"),liabilities:w(r,"liability"),equity:w(r,"equity")}}function ne(r){return r.accountType==="revenue"?r.credit-r.debit:r.accountType==="expense"?r.debit-r.credit:0}function Fe(r){let e=r.filter(n=>n.accountType==="revenue").reduce((n,a)=>n+Math.max(0,ne(a)),0),t=r.filter(n=>n.accountType==="expense").reduce((n,a)=>n+Math.max(0,ne(a)),0);return{operatingInflow:e,operatingOutflow:t,netOperatingCashflow:e-t}}function Oe(r,e){let t=[],n=0;for(let a of e){if(a.accountType==="revenue"){let o=a.credit-a.debit;o>0&&(t.push({accountId:a.accountId,debit:o,credit:0,memo:"Close revenue account"}),n+=o)}if(a.accountType==="expense"){let o=a.debit-a.credit;o>0&&(t.push({accountId:a.accountId,debit:0,credit:o,memo:"Close expense account"}),n-=o)}}return n>0?t.push({accountId:r.retainedEarningsAccountId,debit:0,credit:n,memo:"Retained earnings from period close"}):n<0&&t.push({accountId:r.retainedEarningsAccountId,debit:Math.abs(n),credit:0,memo:"Retained earnings from period close"}),{id:r.journalId,tenantId:r.tenantId,branchId:r.branchId,financeDomainId:r.financeDomainId,ledgerProfileId:r.ledgerProfileId,occurredAt:r.occurredAt,reference:r.reference,lines:t}}function _e(r){return{version:"v1",generatedAt:r.generatedAt??new Date().toISOString(),payload:{trialBalance:r.trialBalance.map(e=>({...e})),incomeStatement:{...r.incomeStatement},balanceSheet:{...r.balanceSheet}}}}function Te(r){return r.accountType==="revenue"?r.credit-r.debit:r.accountType==="expense"?r.debit-r.credit:0}function re(r,e){return e===0?r===0?1:0:Number((r/e).toFixed(4))}function Le(r,e){let t=e.map(a=>{let s=((a.accountCodes?.length?r.filter(I=>a.accountCodes?.includes(I.accountCode)):null)??r.filter(I=>a.accountType?I.accountType===a.accountType:!1)).reduce((I,A)=>I+Te(A),0),u=s-a.plannedAmount;return{id:a.id,label:a.label,plannedAmount:a.plannedAmount,actualAmount:s,varianceAmount:u,achievementRatio:re(s,a.plannedAmount)}}),n=t.reduce((a,o)=>(a.plannedAmount+=o.plannedAmount,a.actualAmount+=o.actualAmount,a.varianceAmount+=o.varianceAmount,a),{plannedAmount:0,actualAmount:0,varianceAmount:0});return{rows:t,totals:{...n,achievementRatio:re(n.actualAmount,n.plannedAmount)}}}function ae(r,e){switch(e.type){case"finance.account.created":r.createAccount(e.payload);return;case"finance.period.opened":r.openFiscalPeriod(e.payload);return;case"finance.period.closed":r.closeFiscalPeriod(e.payload.periodId);return;case"finance.journal.drafted":r.createJournalDraft(e.payload);return;case"finance.journal.posted":r.postJournal(e.payload.journalId,e.payload.postedAt);return;case"finance.journal.reversed":r.reverseJournal(e.payload.journalId,e.payload.reversalId);return;default:throw new Error("FINANCE_EVENT_UNSUPPORTED")}}function Ne(r){let e=new D;for(let t of r)ae(e,t);return e}var oe=[{id:"coa-cash",code:"1101",name:"Kas",type:"asset"},{id:"coa-bank",code:"1102",name:"Bank",type:"asset"},{id:"coa-ar",code:"1201",name:"Piutang Usaha",type:"asset"},{id:"coa-ap",code:"2101",name:"Utang Usaha",type:"liability"},{id:"coa-retained",code:"3201",name:"Laba Ditahan",type:"equity"},{id:"coa-revenue",code:"4101",name:"Pendapatan Operasional",type:"revenue"},{id:"coa-expense",code:"5101",name:"Biaya Operasional",type:"expense"}];function xe(r="IDR"){return oe.map(e=>({id:e.id,code:e.code,name:e.name,type:e.type,currency:r,isActive:!0}))}var ie=[{id:"coop-coa-cash",code:"1101",name:"Kas",type:"asset"},{id:"coop-coa-bank",code:"1102",name:"Bank",type:"asset"},{id:"coop-coa-loan-ar",code:"1201",name:"Piutang Pinjaman Anggota",type:"asset"},{id:"coop-coa-other-ar",code:"1202",name:"Piutang Lain-lain",type:"asset"},{id:"coop-coa-prepaid",code:"1301",name:"Biaya Dibayar Dimuka",type:"asset"},{id:"coop-coa-fixed-asset",code:"1401",name:"Aset Tetap",type:"asset"},{id:"coop-coa-accum-depr",code:"1402",name:"Akumulasi Penyusutan",type:"asset"},{id:"coop-coa-simp-pokok",code:"2101",name:"Simpanan Pokok",type:"liability"},{id:"coop-coa-simp-wajib",code:"2102",name:"Simpanan Wajib",type:"liability"},{id:"coop-coa-simp-sukarela",code:"2103",name:"Simpanan Sukarela",type:"liability"},{id:"coop-coa-simp-berjangka",code:"2104",name:"Simpanan Berjangka",type:"liability"},{id:"coop-coa-ap",code:"2201",name:"Utang Usaha",type:"liability"},{id:"coop-coa-ext-loan",code:"2301",name:"Pinjaman Luar",type:"liability"},{id:"coop-coa-tax-payable",code:"2401",name:"Utang Pajak",type:"liability"},{id:"coop-coa-modal-awal",code:"3101",name:"Modal Awal",type:"equity"},{id:"coop-coa-cadangan-umum",code:"3201",name:"Dana Cadangan Umum",type:"equity"},{id:"coop-coa-cadangan-tujuan",code:"3202",name:"Dana Cadangan Tujuan",type:"equity"},{id:"coop-coa-shu-prior",code:"3301",name:"SHU Tahun Lalu",type:"equity"},{id:"coop-coa-shu-current",code:"3302",name:"SHU Berjalan",type:"equity"},{id:"coop-coa-shu-reserve",code:"3303",name:"Dana SHU Belum Dibagi",type:"equity"},{id:"coop-coa-jasa-pinjaman",code:"4101",name:"Pendapatan Jasa Pinjaman",type:"revenue"},{id:"coop-coa-provisi",code:"4102",name:"Pendapatan Provisi",type:"revenue"},{id:"coop-coa-rev-other",code:"4103",name:"Pendapatan Lain-lain",type:"revenue"},{id:"coop-coa-beban-bunga",code:"5101",name:"Beban Bunga Simpanan",type:"expense"},{id:"coop-coa-beban-ops",code:"5102",name:"Beban Operasional",type:"expense"},{id:"coop-coa-beban-gaji",code:"5103",name:"Beban Gaji dan Tunjangan",type:"expense"},{id:"coop-coa-beban-admin",code:"5104",name:"Beban Administrasi",type:"expense"},{id:"coop-coa-beban-depr",code:"5105",name:"Beban Penyusutan",type:"expense"},{id:"coop-coa-prov-kredit",code:"5106",name:"Cadangan Kerugian Piutang",type:"expense"}];function Je(r="IDR"){return ie.map(e=>({id:e.id,code:e.code,name:e.name,type:e.type,currency:r,isActive:!0}))}function Me(r){let e=new Set,t=new Set;for(let n of r){if(!n.id||!n.code||!n.name)return{ok:!1,reason:"COA_REQUIRED_FIELDS"};if(e.has(n.id))return{ok:!1,reason:"COA_DUPLICATE_ID"};if(t.has(n.code))return{ok:!1,reason:"COA_DUPLICATE_CODE"};e.add(n.id),t.add(n.code)}return{ok:!0}}
1
+ "use strict";var U=Object.defineProperty;var ye=Object.getOwnPropertyDescriptor;var be=Object.getOwnPropertyNames;var he=Object.prototype.hasOwnProperty;var Se=(n,e)=>{for(var t in e)U(n,t,{get:e[t],enumerable:!0})},Ce=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of be(e))!he.call(n,a)&&a!==t&&U(n,a,{get:()=>e[a],enumerable:!(r=ye(e,a))||r.enumerable});return n};var ve=n=>Ce(U({},"__esModule",{value:!0}),n);var At={};Se(At,{CANONICAL_COA_TEMPLATES:()=>ge,COOP_COA_TEMPLATES:()=>Ae,OFINANCE_TABLES:()=>l,OffinanceCore:()=>w,OffinanceEnvelopeService:()=>M,OfinanceRuntimeCore:()=>B,OfinanceRuntimeCoreBuilder:()=>J,applyFinanceDomainEvent:()=>Ie,applyPendingMigrations:()=>N,buildBalanceSheet:()=>et,buildBudgetVsRealization:()=>pt,buildCashflowBaseline:()=>tt,buildClosingJournalDraft:()=>nt,buildFinanceComplianceExportBundle:()=>ae,buildFinanceExportEnvelope:()=>st,buildFinanceOpenItemAging:()=>D,buildFinanceOperationalComplianceBundle:()=>ut,buildFinanceTaxPostingLines:()=>q,buildIncomeStatement:()=>Ze,buildJournalFromCoopLoanDisbursement:()=>G,buildJournalFromCoopLoanRepayment:()=>X,buildJournalFromCoopSavingDeposit:()=>W,buildJournalFromCoopSavingWithdrawal:()=>z,buildJournalFromCoopShuParticipationManualRecap:()=>$e,buildJournalFromPosSale:()=>Y,buildJournalFromScopedCoopLoanDisbursement:()=>Qe,buildJournalFromScopedCoopLoanRepayment:()=>Ge,buildJournalFromScopedCoopSavingDeposit:()=>qe,buildJournalFromScopedCoopSavingWithdrawal:()=>Ye,buildJournalFromScopedPosSale:()=>He,createCanonicalCoA:()=>ft,createCoopCoA:()=>It,createDbAdapterOfinanceServices:()=>Q,createFinanceProjectionSink:()=>Xe,createOffinanceEnvelopeService:()=>H,mapOffinanceErrorToEnvelope:()=>f,projectFinanceCashBankMovements:()=>T,projectFinanceOpenItems:()=>F,reconcileFinanceOpenItems:()=>O,replayFinanceDomainEvents:()=>mt,resolveCoopLoanDisbursementAccountMapping:()=>Z,resolveCoopLoanRepaymentAccountMapping:()=>ee,resolveCoopSavingDepositAccountMapping:()=>te,resolveCoopSavingWithdrawalAccountMapping:()=>ne,resolvePosSaleAccountMapping:()=>K,resolveScopedAccountMapping:()=>E,summarizeFinanceCashBankMovements:()=>_,toOffinanceFailureEnvelope:()=>$,toOffinanceSuccessEnvelope:()=>m,validateCoaIntegrity:()=>gt,validateJournalBalance:()=>R,validateOpenItemLineMetadata:()=>P});module.exports=ve(At);function R(n){if(!Array.isArray(n)||n.length===0)return{ok:!1,totalDebit:0,totalCredit:0,reason:"JOURNAL_LINES_EMPTY"};let e=0,t=0;for(let r of n){if(!r||!r.accountId)return{ok:!1,totalDebit:e,totalCredit:t,reason:"JOURNAL_ACCOUNT_REQUIRED"};if(r.debit<0||r.credit<0)return{ok:!1,totalDebit:e,totalCredit:t,reason:"JOURNAL_NEGATIVE_AMOUNT"};e+=r.debit,t+=r.credit}return Math.abs(e-t)>1e-6?{ok:!1,totalDebit:e,totalCredit:t,reason:"JOURNAL_NOT_BALANCED"}:{ok:!0,totalDebit:e,totalCredit:t}}var Ee=[{key:"current",label:"Current",maxDaysPastDue:0},{key:"1-30",label:"1-30 days",minDaysPastDue:1,maxDaysPastDue:30},{key:"31-60",label:"31-60 days",minDaysPastDue:31,maxDaysPastDue:60},{key:"61-90",label:"61-90 days",minDaysPastDue:61,maxDaysPastDue:90},{key:"90+",label:"90+ days",minDaysPastDue:91}];function Re(n,e,t){return n==="receivable"?e-t:t-e}function Pe(n,e){return[n.tenantId??"",n.branchId??"",n.financeDomainId??"",n.ledgerProfileId??"",e.accountId,e.openItemType??"",e.openItemId??""].join("::")}function oe(n){return n<0?"overpaid":Math.abs(n)<1e-6?"settled":"open"}function Fe(n,e){if(!e)return 0;let t=Date.parse(n)-Date.parse(e);return!Number.isFinite(t)||t<=0?0:Math.floor(t/864e5)}function De(n,e){return e?!(e.tenantId&&n.tenantId!==e.tenantId||e.branchId&&n.branchId!==e.branchId||e.financeDomainId&&n.financeDomainId!==e.financeDomainId||e.ledgerProfileId&&n.ledgerProfileId!==e.ledgerProfileId||e.openItemType&&n.openItemType!==e.openItemType||e.counterpartyRef&&n.counterpartyRef!==e.counterpartyRef||!e.includeSettled&&n.status==="settled"):!0}function P(n){for(let e of n){let t=!!(e.openItemId||e.openItemType),r=!!(e.counterpartyRef||e.documentRef||e.dueAt);if(!(!t&&!r)){if(!e.openItemId)throw new Error("JOURNAL_OPEN_ITEM_ID_REQUIRED");if(!e.openItemType)throw new Error("JOURNAL_OPEN_ITEM_TYPE_REQUIRED");if(e.openItemType!=="receivable"&&e.openItemType!=="payable")throw new Error("JOURNAL_OPEN_ITEM_TYPE_INVALID");if(e.dueAt&&Number.isNaN(Date.parse(e.dueAt)))throw new Error("JOURNAL_OPEN_ITEM_DUE_AT_INVALID")}}}function F(n,e){let t=new Map;for(let r of n)if(r.status==="posted")for(let a of r.lines){if(!a.openItemId||!a.openItemType)continue;let o=Pe(r,a),i=Re(a.openItemType,a.debit,a.credit),c=t.get(o);if(!c){let s={tenantId:r.tenantId,branchId:r.branchId,financeDomainId:r.financeDomainId,ledgerProfileId:r.ledgerProfileId,openItemId:a.openItemId,openItemType:a.openItemType,accountId:a.accountId,counterpartyRef:a.counterpartyRef,documentRef:a.documentRef,dueAt:a.dueAt,originatedAt:r.occurredAt,lastActivityAt:r.occurredAt,originalAmount:i>0?i:0,settledAmount:i<0?Math.abs(i):0,outstandingAmount:i,status:oe(i)};t.set(o,{item:s});continue}c.item.originatedAt=c.item.originatedAt<r.occurredAt?c.item.originatedAt:r.occurredAt,c.item.lastActivityAt=c.item.lastActivityAt>r.occurredAt?c.item.lastActivityAt:r.occurredAt,c.item.counterpartyRef=a.counterpartyRef??c.item.counterpartyRef,c.item.documentRef=a.documentRef??c.item.documentRef,c.item.dueAt=a.dueAt??c.item.dueAt,i>0?c.item.originalAmount+=i:i<0&&(c.item.settledAmount+=Math.abs(i)),c.item.outstandingAmount+=i,c.item.status=oe(c.item.outstandingAmount)}return Array.from(t.values()).map(({item:r})=>({...r})).filter(r=>De(r,e)).sort((r,a)=>r.originatedAt!==a.originatedAt?r.originatedAt.localeCompare(a.originatedAt):r.openItemId.localeCompare(a.openItemId))}function D(n,e){if(Number.isNaN(Date.parse(e.asOf)))throw new Error("FINANCE_OPEN_ITEM_AGING_AS_OF_INVALID");let t=(e.buckets?.length?e.buckets:Ee).map(a=>({...a,amount:0,itemCount:0})),r=0;for(let a of n){if(a.outstandingAmount<=0)continue;r+=a.outstandingAmount;let o=Fe(e.asOf,a.dueAt),i=t.find(c=>{let s=c.minDaysPastDue??Number.NEGATIVE_INFINITY,I=c.maxDaysPastDue??Number.POSITIVE_INFINITY;return o>=s&&o<=I});if(!i)throw new Error("FINANCE_OPEN_ITEM_AGING_BUCKET_UNRESOLVED");i.amount+=a.outstandingAmount,i.itemCount+=1}return{asOf:e.asOf,openItemType:e.openItemType,totalOutstanding:r,buckets:t}}function ce(n,e){return`${e??""}::${n}`}function Oe(n){if(!n.openItemId?.trim())throw new Error("FINANCE_RECONCILIATION_OPEN_ITEM_ID_REQUIRED");if(!Number.isFinite(n.observedAmount)||n.observedAmount<0)throw new Error("FINANCE_RECONCILIATION_OBSERVED_AMOUNT_INVALID");if(n.openItemType&&n.openItemType!=="receivable"&&n.openItemType!=="payable")throw new Error("FINANCE_RECONCILIATION_OPEN_ITEM_TYPE_INVALID")}function Te(n,e){let t=new Map;for(let r of n){Oe(r);let a=r.openItemType??e,o=ce(r.openItemId,a),i=t.get(o);if(!i){t.set(o,{openItemId:r.openItemId,openItemType:a,observedAmount:r.observedAmount,counterpartyRef:r.counterpartyRef,documentRef:r.documentRef,references:r.reference?[r.reference]:[]});continue}i.observedAmount+=r.observedAmount,i.counterpartyRef=r.counterpartyRef??i.counterpartyRef,i.documentRef=r.documentRef??i.documentRef,r.reference&&i.references.push(r.reference)}return t}function _e(n,e,t,r,a){let o=n.outstandingAmount,i=e?.observedAmount??0,c=i-o,s=Ne(n.dueAt,r);if(!e){let A=ie("missing",s,a);return{tenantId:n.tenantId,branchId:n.branchId,financeDomainId:n.financeDomainId,ledgerProfileId:n.ledgerProfileId,openItemId:n.openItemId,openItemType:n.openItemType,accountId:n.accountId,counterpartyRef:n.counterpartyRef,documentRef:n.documentRef,dueAt:n.dueAt,expectedAmount:o,observedAmount:i,varianceAmount:c,status:"missing",lifecycleStatus:A.lifecycleStatus,suggestedAction:A.suggestedAction,reason:"FINANCE_RECONCILIATION_OBSERVATION_MISSING",pastDueDays:s,observedReferences:[]}}let I=e.counterpartyRef&&n.counterpartyRef&&e.counterpartyRef!==n.counterpartyRef||e.documentRef&&n.documentRef&&e.documentRef!==n.documentRef,p="matched",g="resolved",d="none",u;if(I)p="mismatch",g="exception",d="investigate",u="FINANCE_RECONCILIATION_METADATA_MISMATCH";else if(Math.abs(c)<=t)p="matched";else if(c<0){p="under";let A=ie("under",s,a);g=A.lifecycleStatus,d=A.suggestedAction,u="FINANCE_RECONCILIATION_OBSERVED_UNDER"}else c>0&&(p="over",g="unresolved",d="refund_or_apply_credit",u="FINANCE_RECONCILIATION_OBSERVED_OVER");return{tenantId:n.tenantId,branchId:n.branchId,financeDomainId:n.financeDomainId,ledgerProfileId:n.ledgerProfileId,openItemId:n.openItemId,openItemType:n.openItemType,accountId:n.accountId,counterpartyRef:n.counterpartyRef,documentRef:n.documentRef,dueAt:n.dueAt,expectedAmount:o,observedAmount:i,varianceAmount:c,status:p,lifecycleStatus:g,suggestedAction:d,reason:u,pastDueDays:s,observedReferences:[...e.references]}}function we(n,e){return{tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,openItemId:n.openItemId,openItemType:n.openItemType??e.openItemType,counterpartyRef:n.counterpartyRef,documentRef:n.documentRef,expectedAmount:0,observedAmount:n.observedAmount,varianceAmount:n.observedAmount,status:"mismatch",lifecycleStatus:"exception",suggestedAction:"investigate",reason:"FINANCE_RECONCILIATION_EXPECTED_ITEM_NOT_FOUND",observedReferences:[...n.references]}}function Ne(n,e){if(!n||!e)return;let t=Date.parse(n),r=Date.parse(e);if(!Number.isFinite(t)||!Number.isFinite(r))throw new Error("FINANCE_RECONCILIATION_AS_OF_INVALID");let a=r-t;return a<=0?0:Math.floor(a/864e5)}function ie(n,e,t){return typeof t=="number"&&typeof e=="number"&&e>=t?{lifecycleStatus:"writeoff_candidate",suggestedAction:"write_off_review"}:{lifecycleStatus:"unresolved",suggestedAction:n==="missing"||n==="under"?"collect_follow_up":"investigate"}}function O(n,e){let t=e.toleranceAmount??0;if(!Number.isFinite(t)||t<0)throw new Error("FINANCE_RECONCILIATION_TOLERANCE_INVALID");if(e.asOf&&!Number.isFinite(Date.parse(e.asOf)))throw new Error("FINANCE_RECONCILIATION_AS_OF_INVALID");if(typeof e.writeOffPastDueDays=="number"&&(!Number.isFinite(e.writeOffPastDueDays)||e.writeOffPastDueDays<0))throw new Error("FINANCE_RECONCILIATION_WRITE_OFF_DAYS_INVALID");let r=Te(e.observations,e.openItemType),a=[];for(let d of n){let u=ce(d.openItemId,d.openItemType),A=r.get(u);a.push(_e(d,A,t,e.asOf,e.writeOffPastDueDays)),r.delete(u)}for(let d of r.values())a.push(we(d,e));a.sort((d,u)=>(d.financeDomainId??"")!==(u.financeDomainId??"")?(d.financeDomainId??"").localeCompare(u.financeDomainId??""):(d.ledgerProfileId??"")!==(u.ledgerProfileId??"")?(d.ledgerProfileId??"").localeCompare(u.ledgerProfileId??""):d.openItemId.localeCompare(u.openItemId));let o=a.reduce((d,u)=>d+u.expectedAmount,0),i=a.reduce((d,u)=>d+u.observedAmount,0),c=a.reduce((d,u)=>d+u.varianceAmount,0),s=a.filter(d=>d.lifecycleStatus==="resolved").length,I=a.filter(d=>d.lifecycleStatus==="unresolved").length,p=a.filter(d=>d.lifecycleStatus==="exception").length,g=a.filter(d=>d.lifecycleStatus==="writeoff_candidate").length;return{openItemType:e.openItemType,totalExpectedAmount:o,totalObservedAmount:i,totalVarianceAmount:c,resolvedCount:s,unresolvedCount:I,exceptionCount:p,writeoffCandidateCount:g,rows:a}}function Le(n){if(!Array.isArray(n.trackedAccountIds)||n.trackedAccountIds.length===0)throw new Error("FINANCE_CASH_MOVEMENT_TRACKED_ACCOUNTS_REQUIRED");let e=new Set(n.trackedAccountIds.map(t=>t.trim()).filter(Boolean));if(e.size===0)throw new Error("FINANCE_CASH_MOVEMENT_TRACKED_ACCOUNTS_REQUIRED");return e}function Me(n,e){return!(e.tenantId&&n.tenantId!==e.tenantId||e.branchId&&n.branchId!==e.branchId||e.financeDomainId&&n.financeDomainId!==e.financeDomainId||e.ledgerProfileId&&n.ledgerProfileId!==e.ledgerProfileId||e.occurredFrom&&n.occurredAt<e.occurredFrom||e.occurredTo&&n.occurredAt>e.occurredTo)}function xe(n){return n?.startsWith("reversal:")&&n.slice(9).trim()||void 0}function T(n,e){let t=Le(e),r=[];for(let a of n){if(a.status!=="posted"||!Me(a,e))continue;let o=a.lines.filter(u=>t.has(u.accountId)&&(u.debit>0||u.credit>0));if(o.length===0)continue;let i=Array.from(new Set(o.map(u=>u.accountId))).sort(),c=Array.from(new Set(a.lines.filter(u=>!t.has(u.accountId)&&(u.debit>0||u.credit>0)).map(u=>u.accountId))).sort(),s=o.some(u=>u.debit>0),I=o.some(u=>u.credit>0),p=xe(a.reference),g=!!p,d=i.length>1&&s&&I&&c.length===0;if(i.length>1&&c.length>0)throw new Error("FINANCE_CASH_MOVEMENT_MIXED_TRACKED_JOURNAL_UNSUPPORTED");if(d){let u=o.reduce((y,S)=>y+S.debit,0),A=o.reduce((y,S)=>y+S.credit,0);if(Math.abs(u-A)>1e-6)throw new Error("FINANCE_CASH_MOVEMENT_TRANSFER_IMBALANCED")}for(let u of o)u.debit>0&&r.push({journalId:a.id,tenantId:a.tenantId,branchId:a.branchId,financeDomainId:a.financeDomainId,ledgerProfileId:a.ledgerProfileId,occurredAt:a.occurredAt,reference:a.reference,evidenceRef:a.evidenceRef,accountId:u.accountId,direction:d?"transfer_in":"in",movementKind:g?"reversal":d?"internal_transfer":"external",lifecycleStatus:g?"reversal_posted":"posted",amount:u.debit,signedAmount:u.debit,sourceJournalId:p,counterpartAccountIds:c,trackedAccountIdsInJournal:i}),u.credit>0&&r.push({journalId:a.id,tenantId:a.tenantId,branchId:a.branchId,financeDomainId:a.financeDomainId,ledgerProfileId:a.ledgerProfileId,occurredAt:a.occurredAt,reference:a.reference,evidenceRef:a.evidenceRef,accountId:u.accountId,direction:d?"transfer_out":"out",movementKind:g?"reversal":d?"internal_transfer":"external",lifecycleStatus:g?"reversal_posted":"posted",amount:u.credit,signedAmount:-u.credit,sourceJournalId:p,counterpartAccountIds:c,trackedAccountIdsInJournal:i})}return r.sort((a,o)=>a.occurredAt!==o.occurredAt?a.occurredAt.localeCompare(o.occurredAt):a.journalId!==o.journalId?a.journalId.localeCompare(o.journalId):a.accountId.localeCompare(o.accountId))}function _(n){let e=0,t=0,r=0,a=0,o=new Map;for(let i of n)i.direction==="in"&&(e+=i.amount),i.direction==="out"&&(t+=i.amount),i.direction==="transfer_in"&&(r+=i.amount),i.direction==="transfer_out"&&(a+=i.amount),o.set(i.accountId,(o.get(i.accountId)??0)+i.signedAmount);return{totalInflow:e,totalOutflow:t,totalTransferIn:r,totalTransferOut:a,netExternalMovement:e-t,netByTrackedAccountId:Object.fromEntries(Array.from(o.entries()).sort(([i],[c])=>i.localeCompare(c))),entries:n.map(i=>({...i,counterpartAccountIds:[...i.counterpartAccountIds],trackedAccountIdsInJournal:[...i.trackedAccountIdsInJournal]}))}}var w=class{constructor(e){this.state={accounts:e?.accounts??new Map,periods:e?.periods??new Map,journals:e?.journals??new Map,balances:e?.balances??new Map,rapbPlans:e?.rapbPlans??new Map,auditTrail:e?.auditTrail?.map(t=>({...t}))??[]}}createAccount(e){if(!e.id||!e.code||!e.name)throw new Error("FINANCE_ACCOUNT_REQUIRED_FIELDS");if(this.state.accounts.has(e.id))throw new Error("FINANCE_ACCOUNT_ALREADY_EXISTS");if(Array.from(this.state.accounts.values()).some(r=>r.code===e.code))throw new Error("FINANCE_ACCOUNT_CODE_DUPLICATE");return this.state.accounts.set(e.id,{...e}),{...e}}listAccounts(){return Array.from(this.state.accounts.values()).map(e=>({...e})).sort((e,t)=>e.code.localeCompare(t.code))}openFiscalPeriod(e){if(!e.id||!e.tenantId||!e.code||!e.startDate||!e.endDate)throw new Error("FISCAL_PERIOD_REQUIRED_FIELDS");if(this.state.periods.has(e.id))throw new Error("FISCAL_PERIOD_ALREADY_EXISTS");if(Date.parse(e.startDate)>Date.parse(e.endDate))throw new Error("FISCAL_PERIOD_INVALID_RANGE");let t={...e,status:"open"};return this.state.periods.set(t.id,t),this.recordAuditTrail({eventType:"fiscal_period_opened",recordType:"fiscal_period",recordId:t.id,tenantId:t.tenantId,branchId:t.branchId,financeDomainId:t.financeDomainId,ledgerProfileId:t.ledgerProfileId,occurredAt:new Date().toISOString(),summary:`Fiscal period ${t.code} opened`,metadata:{code:t.code,startDate:t.startDate,endDate:t.endDate}}),{...t}}closeFiscalPeriod(e){let t=this.state.periods.get(e);if(!t)throw new Error("FISCAL_PERIOD_NOT_FOUND");let r={...t,status:"closed"};return this.state.periods.set(e,r),this.recordAuditTrail({eventType:"fiscal_period_closed",recordType:"fiscal_period",recordId:r.id,tenantId:r.tenantId,branchId:r.branchId,financeDomainId:r.financeDomainId,ledgerProfileId:r.ledgerProfileId,occurredAt:new Date().toISOString(),summary:`Fiscal period ${r.code} closed`,metadata:{code:r.code}}),{...r}}listFiscalPeriods(){return Array.from(this.state.periods.values()).map(e=>({...e})).sort((e,t)=>e.startDate.localeCompare(t.startDate))}createJournalDraft(e){if(!e.id||!e.tenantId||!e.occurredAt)throw new Error("JOURNAL_REQUIRED_FIELDS");if(this.state.journals.has(e.id))throw new Error("JOURNAL_ALREADY_EXISTS");this.assertJournalLinesKnownAccounts(e.lines),this.assertJournalPeriodOpen(e.occurredAt),P(e.lines);let t=R(e.lines);if(!t.ok)throw new Error(t.reason??"JOURNAL_INVALID");let r={id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,occurredAt:e.occurredAt,reference:e.reference,evidenceRef:e.evidenceRef,lines:e.lines.map(a=>({...a})),status:"draft"};return this.state.journals.set(r.id,r),this.recordAuditTrail({eventType:"journal_drafted",recordType:"journal",recordId:r.id,journalId:r.id,tenantId:r.tenantId,branchId:r.branchId,financeDomainId:r.financeDomainId,ledgerProfileId:r.ledgerProfileId,occurredAt:new Date().toISOString(),reference:r.reference,evidenceRef:r.evidenceRef,summary:`Journal ${r.id} drafted`,metadata:{journalOccurredAt:r.occurredAt,status:r.status}}),{...r,lines:r.lines.map(a=>({...a}))}}postJournal(e,t=new Date().toISOString()){let r=this.state.journals.get(e);if(!r)throw new Error("JOURNAL_NOT_FOUND");if(r.status==="posted"||r.status==="reversed")return{...r,lines:r.lines.map(i=>({...i}))};this.applyLinesToBalance(r.lines);let a={...r,status:"posted",postedAt:t};this.state.journals.set(e,a);let o=new Date().toISOString();return this.recordAuditTrail({eventType:"journal_posted",recordType:"journal",recordId:a.id,journalId:a.id,tenantId:a.tenantId,branchId:a.branchId,financeDomainId:a.financeDomainId,ledgerProfileId:a.ledgerProfileId,occurredAt:o,reference:a.reference,evidenceRef:a.evidenceRef,summary:`Journal ${a.id} posted`,metadata:{journalOccurredAt:a.occurredAt,postedAt:t,status:a.status}}),{...a,lines:a.lines.map(i=>({...i}))}}reverseJournal(e,t){let r=this.state.journals.get(e);if(!r)throw new Error("JOURNAL_NOT_FOUND");if(r.status!=="posted")throw new Error("JOURNAL_NOT_POSTED");if(this.state.journals.has(t))throw new Error("JOURNAL_ALREADY_EXISTS");let a=r.lines.map(s=>({accountId:s.accountId,debit:s.credit,credit:s.debit,memo:s.memo,openItemId:s.openItemId,openItemType:s.openItemType,counterpartyRef:s.counterpartyRef,documentRef:s.documentRef,dueAt:s.dueAt})),o=this.createJournalDraft({id:t,tenantId:r.tenantId,branchId:r.branchId,financeDomainId:r.financeDomainId,ledgerProfileId:r.ledgerProfileId,occurredAt:r.occurredAt,reference:`reversal:${r.id}`,evidenceRef:r.evidenceRef,lines:a}),i=this.postJournal(o.id),c=new Date().toISOString();return this.recordAuditTrail({eventType:"journal_reversal_posted",recordType:"journal",recordId:i.id,journalId:i.id,sourceJournalId:r.id,tenantId:i.tenantId,branchId:i.branchId,financeDomainId:i.financeDomainId,ledgerProfileId:i.ledgerProfileId,occurredAt:c,reference:i.reference,evidenceRef:i.evidenceRef,summary:`Reversal journal ${i.id} posted for ${r.id}`,metadata:{journalOccurredAt:i.occurredAt,postedAt:i.postedAt,status:i.status}}),i}getTrialBalance(){return this.getTrialBalanceByScope()}getTrialBalanceByScope(e){let t=this.computeScopedBalances(e);return this.listAccounts().map(a=>{let o=t.get(a.id)??{debit:0,credit:0};return{accountId:a.id,accountCode:a.code,accountName:a.name,accountType:a.type,debit:o.debit,credit:o.credit,net:o.debit-o.credit}})}listJournals(e){return Array.from(this.state.journals.values()).filter(t=>this.matchesScope(t,e)).map(t=>({...t,lines:t.lines.map(r=>({...r}))})).sort((t,r)=>t.occurredAt.localeCompare(r.occurredAt))}listOpenItems(e){return F(this.listJournals(e),e)}getOpenItemAging(e){return D(this.listOpenItems(e),e)}reconcileOpenItems(e){return O(this.listOpenItems(e),e)}listCashBankMovements(e){return T(this.listJournals(e),e)}summarizeCashBankMovements(e){return _(this.listCashBankMovements(e))}listFinancialAuditTrail(e){return this.state.auditTrail.filter(t=>this.matchesAuditScope(t,e)).sort((t,r)=>t.occurredAt!==r.occurredAt?t.occurredAt.localeCompare(r.occurredAt):t.id.localeCompare(r.id)).map(t=>({...t,metadata:t.metadata?{...t.metadata}:void 0}))}assertJournalLinesKnownAccounts(e){for(let t of e)if(!this.state.accounts.has(t.accountId))throw new Error("JOURNAL_ACCOUNT_NOT_FOUND")}assertJournalPeriodOpen(e){if(this.state.periods.size===0)return;let t=this.findPeriodByDate(e);if(!t)throw new Error("FISCAL_PERIOD_NOT_FOUND_FOR_DATE");if(t.status!=="open")throw new Error("FISCAL_PERIOD_CLOSED")}findPeriodByDate(e){let t=Date.parse(e);for(let r of this.state.periods.values()){let a=Date.parse(r.startDate),o=Date.parse(r.endDate);if(t>=a&&t<=o)return r}return null}applyLinesToBalance(e){for(let t of e){let r=this.state.balances.get(t.accountId)??{debit:0,credit:0};r.debit+=t.debit,r.credit+=t.credit,this.state.balances.set(t.accountId,r)}}computeScopedBalances(e){if(!e||!e.tenantId&&!e.branchId&&!e.financeDomainId&&!e.ledgerProfileId&&!e.occurredFrom&&!e.occurredTo)return this.state.balances;let t=new Map;for(let r of this.state.journals.values())if(r.status==="posted"&&this.matchesScope(r,e))for(let a of r.lines){let o=t.get(a.accountId)??{debit:0,credit:0};o.debit+=a.debit,o.credit+=a.credit,t.set(a.accountId,o)}return t}matchesScope(e,t){return t?!(t.tenantId&&e.tenantId!==t.tenantId||t.branchId&&e.branchId!==t.branchId||t.financeDomainId&&e.financeDomainId!==t.financeDomainId||t.ledgerProfileId&&e.ledgerProfileId!==t.ledgerProfileId||t.occurredFrom&&e.occurredAt<t.occurredFrom||t.occurredTo&&e.occurredAt>t.occurredTo):!0}createRapb(e){if(!e.id||!e.tenantId||!e.periodCode||!e.title)throw new Error("RAPB_REQUIRED_FIELDS");if(!e.lines||e.lines.length===0)throw new Error("RAPB_LINES_REQUIRED");if(this.state.rapbPlans.has(e.id))throw new Error("RAPB_ALREADY_EXISTS");if(e.lines.some(a=>a.budgetedDebit<0||a.budgetedCredit<0))throw new Error("RAPB_NEGATIVE_AMOUNT");let t=e.lines.map(a=>{let o=this.state.accounts.get(a.accountId);if(!o)throw new Error(`RAPB_ACCOUNT_NOT_FOUND:${a.accountId}`);let i=a.budgetedDebit-a.budgetedCredit;return{accountId:a.accountId,accountCode:o.code,accountName:o.name,accountType:o.type,budgetedDebit:a.budgetedDebit,budgetedCredit:a.budgetedCredit,budgetedNet:i}}),r={id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,periodCode:e.periodCode,title:e.title,status:"draft",lines:t,notes:e.notes,createdAt:new Date().toISOString()};return this.state.rapbPlans.set(r.id,r),this.recordAuditTrail({eventType:"rapb_created",recordType:"rapb_plan",recordId:r.id,tenantId:r.tenantId,branchId:r.branchId,financeDomainId:r.financeDomainId,ledgerProfileId:r.ledgerProfileId,occurredAt:r.createdAt,summary:`RAPB ${r.title} created`,metadata:{periodCode:r.periodCode,status:r.status}}),r}getRapb(e){return this.state.rapbPlans.get(e)??null}listRapb(e){let t=Array.from(this.state.rapbPlans.values());return e&&(e.tenantId&&(t=t.filter(r=>r.tenantId===e.tenantId)),e.periodCode&&(t=t.filter(r=>r.periodCode===e.periodCode)),e.branchId&&(t=t.filter(r=>r.branchId===e.branchId)),e.financeDomainId&&(t=t.filter(r=>r.financeDomainId===e.financeDomainId)),e.ledgerProfileId&&(t=t.filter(r=>r.ledgerProfileId===e.ledgerProfileId))),t}approveRapb(e,t){let r=this.state.rapbPlans.get(e);if(!r)throw new Error("RAPB_NOT_FOUND");let a=typeof t=="string"?t:t.approvedBy;if(r.status==="approved")throw new Error("RAPB_ALREADY_APPROVED");let o={...r,status:"approved",approvedAt:new Date().toISOString(),approvedBy:a};return this.state.rapbPlans.set(e,o),this.recordAuditTrail({eventType:"rapb_approved",recordType:"rapb_plan",recordId:o.id,tenantId:o.tenantId,branchId:o.branchId,financeDomainId:o.financeDomainId,ledgerProfileId:o.ledgerProfileId,occurredAt:o.approvedAt??new Date().toISOString(),summary:`RAPB ${o.title} approved`,metadata:{periodCode:o.periodCode,approvedBy:a,status:o.status}}),o}evaluateVariance(e){let t=this.state.rapbPlans.get(e);if(!t)throw new Error("RAPB_NOT_FOUND");let r=this.getTrialBalance(),a=new Map(r.map(d=>[d.accountId,d])),o=0,i=0,c=0,s=0,I=t.lines.map(d=>{let u=a.get(d.accountId),A=u?.debit??0,y=u?.credit??0,S=A-y;return d.accountType==="revenue"?(o+=d.budgetedCredit-d.budgetedDebit,i+=y-A):d.accountType==="expense"&&(c+=d.budgetedDebit-d.budgetedCredit,s+=A-y),{accountId:d.accountId,accountCode:d.accountCode,accountName:d.accountName,accountType:d.accountType,budgetedDebit:d.budgetedDebit,budgetedCredit:d.budgetedCredit,budgetedNet:d.budgetedNet,actualDebit:A,actualCredit:y,actualNet:S,varianceDebit:A-d.budgetedDebit,varianceCredit:y-d.budgetedCredit,varianceNet:S-d.budgetedNet}}),p=o-c,g=i-s;return{rapbId:e,periodCode:t.periodCode,evaluatedAt:new Date().toISOString(),lines:I,totalBudgetedRevenue:o,totalActualRevenue:i,totalBudgetedExpense:c,totalActualExpense:s,budgetedNetIncome:p,actualNetIncome:g,netVariance:g-p}}recordAuditTrail(e){this.state.auditTrail.push({id:`audit:${this.state.auditTrail.length+1}:${Date.now()}`,...e,metadata:e.metadata?{...e.metadata}:void 0})}matchesAuditScope(e,t){return t?!(t.tenantId&&e.tenantId!==t.tenantId||t.branchId&&e.branchId!==t.branchId||t.financeDomainId&&e.financeDomainId!==t.financeDomainId||t.ledgerProfileId&&e.ledgerProfileId!==t.ledgerProfileId||t.occurredFrom&&e.occurredAt<t.occurredFrom||t.occurredTo&&e.occurredAt>t.occurredTo||t.recordId&&e.recordId!==t.recordId||t.journalId&&e.journalId!==t.journalId||t.eventTypes&&t.eventTypes.length>0&&!t.eventTypes.includes(e.eventType)):!0}};var se=require("ofcore"),ue=require("ofcore"),j=require("ofcore");var l={accounts:"ofinance_accounts",periods:"ofinance_periods",journals:"ofinance_journals",journalLines:"ofinance_journal_lines",rapbPlans:"ofinance_rapb_plans",rapbLines:"ofinance_rapb_lines",histories:"ofinance_histories"},Be=[{name:l.accounts,columns:[{name:"id",type:"string"},{name:"code",type:"string",isIndexed:!0},{name:"name",type:"string"},{name:"type",type:"string",isIndexed:!0},{name:"currency",type:"string"},{name:"isActive",type:"boolean",isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:l.periods,columns:[{name:"id",type:"string"},{name:"tenantId",type:"string",isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"code",type:"string",isIndexed:!0},{name:"startDate",type:"string",isIndexed:!0},{name:"endDate",type:"string",isIndexed:!0},{name:"status",type:"string",isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:l.journals,columns:[{name:"id",type:"string"},{name:"tenantId",type:"string",isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"occurredAt",type:"string",isIndexed:!0},{name:"reference",type:"string",isOptional:!0,isIndexed:!0},{name:"evidenceRef",type:"string",isOptional:!0,isIndexed:!0},{name:"status",type:"string",isIndexed:!0},{name:"postedAt",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:l.journalLines,columns:[{name:"id",type:"string"},{name:"journalId",type:"string",isIndexed:!0},{name:"accountId",type:"string",isIndexed:!0},{name:"debit",type:"number"},{name:"credit",type:"number"},{name:"memo",type:"string",isOptional:!0},{name:"openItemId",type:"string",isOptional:!0,isIndexed:!0},{name:"openItemType",type:"string",isOptional:!0,isIndexed:!0},{name:"counterpartyRef",type:"string",isOptional:!0,isIndexed:!0},{name:"documentRef",type:"string",isOptional:!0,isIndexed:!0},{name:"dueAt",type:"string",isOptional:!0,isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:l.rapbPlans,columns:[{name:"id",type:"string"},{name:"tenantId",type:"string",isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"periodCode",type:"string",isIndexed:!0},{name:"title",type:"string",isIndexed:!0},{name:"status",type:"string",isIndexed:!0},{name:"notes",type:"string",isOptional:!0},{name:"createdAt",type:"string",isIndexed:!0},{name:"approvedAt",type:"string",isOptional:!0,isIndexed:!0},{name:"approvedBy",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:l.rapbLines,columns:[{name:"id",type:"string"},{name:"rapbId",type:"string",isIndexed:!0},{name:"accountId",type:"string",isIndexed:!0},{name:"accountCode",type:"string",isIndexed:!0},{name:"accountName",type:"string"},{name:"accountType",type:"string",isIndexed:!0},{name:"budgetedDebit",type:"number"},{name:"budgetedCredit",type:"number"},{name:"budgetedNet",type:"number"},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0},{name:"lastModified",type:"string"},{name:"deleted",type:"boolean",isIndexed:!0}]},{name:l.histories,columns:[{name:"id",type:"string"},{name:"tableName",type:"string",isIndexed:!0},{name:"recordId",type:"string",isIndexed:!0},{name:"action",type:"string",isIndexed:!0},{name:"changes",type:"json",isOptional:!0},{name:"timestamp",type:"string",isIndexed:!0},{name:"tenantId",type:"string",isOptional:!0,isIndexed:!0},{name:"branchId",type:"string",isOptional:!0,isIndexed:!0},{name:"financeDomainId",type:"string",isOptional:!0,isIndexed:!0},{name:"ledgerProfileId",type:"string",isOptional:!0,isIndexed:!0}]}];function V(){return Be.map(n=>({...n,columns:n.columns.map(e=>({...e}))}))}var de=[{toVersion:1,up:async n=>{let e=V();for(let t of e)try{await n.addTable(t)}catch{}}},{toVersion:2,up:async n=>{let e=V().filter(t=>t.name==="ofinance_rapb_plans"||t.name==="ofinance_rapb_lines");for(let t of e)try{await n.addTable(t)}catch{}}},{toVersion:3,up:async n=>{try{await n.addColumn("ofinance_journals",{name:"evidenceRef",type:"string",isOptional:!0,isIndexed:!0})}catch{}}},{toVersion:4,up:async n=>{let e=[{name:"openItemId",type:"string",isOptional:!0,isIndexed:!0},{name:"openItemType",type:"string",isOptional:!0,isIndexed:!0},{name:"counterpartyRef",type:"string",isOptional:!0,isIndexed:!0},{name:"documentRef",type:"string",isOptional:!0,isIndexed:!0},{name:"dueAt",type:"string",isOptional:!0,isIndexed:!0}];for(let t of e)try{await n.addColumn("ofinance_journal_lines",t)}catch{}}}];var Je={logInfo(){},logWarn(){},logError(){}};async function N(n,e=Je){e.logInfo("[offinance] starting database migration process");let t=[...de].sort((o,i)=>o.toVersion-i.toVersion),r=t.length>0?t[t.length-1].toVersion:0,a=await n.getSchemaVersion();if((a==null||a<0)&&(a=0),a>=r){e.logInfo(`[offinance] database already up-to-date at v${a}`);return}for(let o of t)o.toVersion>a&&(e.logInfo(`[offinance] applying migration v${o.toVersion}`),await o.up(n),await n.setSchemaVersion(o.toVersion),a=o.toVersion);e.logInfo(`[offinance] migration completed at v${a}`)}function m(n,e){return{data:n,meta:{request_id:e??null,timestamp:new Date().toISOString()}}}function $(n,e,t={}){return{error:{code:n,message:e,details:t.details,retryable:t.retryable,correlationId:t.correlationId,timestamp:new Date().toISOString()},meta:{request_id:t.requestId??null,timestamp:new Date().toISOString()}}}function f(n,e="FINANCE_NOT_IMPLEMENTED",t="Unhandled offinance error."){return n instanceof Error?$(e,n.message||t):$(e,t)}var M=class{constructor(e){this.legacy=e;this.accountService={createAccount:async t=>{try{return m(await this.legacy.accountService.createAccount(t))}catch(r){return f(r)}},listAccounts:async()=>{try{return m(await this.legacy.accountService.listAccounts())}catch(t){return f(t)}}},this.journalService={createJournalDraft:async t=>{try{return m(await this.legacy.journalService.createJournalDraft(t))}catch(r){return f(r)}},postJournal:async(t,r)=>{try{return m(await this.legacy.journalService.postJournal(t,r))}catch(a){return f(a)}},reverseJournal:async(t,r)=>{try{return m(await this.legacy.journalService.reverseJournal(t,r))}catch(a){return f(a)}},listJournals:async t=>{try{return m(await this.legacy.journalService.listJournals(t))}catch(r){return f(r)}}},this.fiscalService={openFiscalPeriod:async t=>{try{return m(await this.legacy.fiscalService.openFiscalPeriod(t))}catch(r){return f(r)}},closeFiscalPeriod:async t=>{try{return m(await this.legacy.fiscalService.closeFiscalPeriod(t))}catch(r){return f(r)}},listFiscalPeriods:async()=>{try{return m(await this.legacy.fiscalService.listFiscalPeriods())}catch(t){return f(t)}},getTrialBalance:async()=>{try{return m(await this.legacy.fiscalService.getTrialBalance())}catch(t){return f(t)}},getTrialBalanceByScope:async t=>{try{return m(await this.legacy.fiscalService.getTrialBalanceByScope(t))}catch(r){return f(r)}}},this.rapbService={createRapb:async t=>{try{return m(await this.legacy.rapbService.createRapb(t))}catch(r){return f(r)}},getRapb:async t=>{try{return m(await this.legacy.rapbService.getRapb(t))}catch(r){return f(r)}},listRapb:async t=>{try{return m(await this.legacy.rapbService.listRapb(t))}catch(r){return f(r)}},approveRapb:async(t,r)=>{try{return m(await this.legacy.rapbService.approveRapb(t,r))}catch(a){return f(a)}},evaluateVariance:async t=>{try{return m(await this.legacy.rapbService.evaluateVariance(t))}catch(r){return f(r)}}},this.openItemService={listOpenItems:async t=>{try{return m(await this.legacy.openItemService.listOpenItems(t))}catch(r){return f(r)}},getOpenItemAging:async t=>{try{return m(await this.legacy.openItemService.getOpenItemAging(t))}catch(r){return f(r)}}},this.reconciliationService={reconcileOpenItems:async t=>{try{return m(await this.legacy.reconciliationService.reconcileOpenItems(t))}catch(r){return f(r)}}},this.cashMovementService={listCashBankMovements:async t=>{try{return m(await this.legacy.cashMovementService.listCashBankMovements(t))}catch(r){return f(r)}},summarizeCashBankMovements:async t=>{try{return m(await this.legacy.cashMovementService.summarizeCashBankMovements(t))}catch(r){return f(r)}}},this.auditTrailService={listFinancialAuditTrail:async t=>{try{return m(await this.legacy.auditTrailService.listFinancialAuditTrail(t))}catch(r){return f(r)}}}}};function H(n){return new M({accountService:n,journalService:n,fiscalService:n,rapbService:n,openItemService:n,reconciliationService:n,cashMovementService:n,auditTrailService:n})}function h(n){return JSON.parse(JSON.stringify(n))}function b(){return new Date().toISOString()}function je(n,e){return`${n}:${e}:${Date.now()}:${Math.random().toString(36).slice(2,8)}`}function ke(n,e){return!n||n.deleted?!1:e?!(e.tenantId&&n.tenantId!==e.tenantId||e.branchId&&n.branchId!==e.branchId||e.financeDomainId&&n.financeDomainId!==e.financeDomainId||e.ledgerProfileId&&n.ledgerProfileId!==e.ledgerProfileId||e.occurredFrom&&n.occurredAt&&n.occurredAt<e.occurredFrom||e.occurredTo&&n.occurredAt&&n.occurredAt>e.occurredTo):!0}function Ue(n,e){return e?!(e.tenantId&&n.tenantId!==e.tenantId||e.branchId&&n.branchId!==e.branchId||e.financeDomainId&&n.financeDomainId!==e.financeDomainId||e.ledgerProfileId&&n.ledgerProfileId!==e.ledgerProfileId||e.occurredFrom&&n.occurredAt<e.occurredFrom||e.occurredTo&&n.occurredAt>e.occurredTo||e.recordId&&n.recordId!==e.recordId||e.journalId&&n.journalId!==e.journalId||e.eventTypes&&e.eventTypes.length>0&&!e.eventTypes.includes(n.eventType)):!0}function Ve(n){return typeof n!="string"||!n.startsWith("reversal:")?void 0:n.slice(9).trim()||void 0}var x=class{constructor(e){this.dbAdapter=e}async createAccount(e){if(!e.id||!e.code||!e.name)throw new Error("FINANCE_ACCOUNT_REQUIRED_FIELDS");let t=await this.dbAdapter.get(l.accounts,e.id);if(t&&!t.deleted)throw new Error("FINANCE_ACCOUNT_ALREADY_EXISTS");if((await this.dbAdapter.query(l.accounts,{filters:{and:[{field:"code",value:e.code},{field:"deleted",value:!1}]}})).some(i=>i.id!==e.id))throw new Error("FINANCE_ACCOUNT_CODE_DUPLICATE");let a=b(),o={...h(e),lastModified:a,deleted:!1};return t?await this.dbAdapter.update(l.accounts,e.id,o):await this.dbAdapter.create(l.accounts,o),await this.writeHistory("accounts",e.id,"UPSERT",o),h(e)}async listAccounts(){return(await this.dbAdapter.query(l.accounts,{filters:{field:"deleted",value:!1}})).map(({lastModified:t,deleted:r,...a})=>h(a)).sort((t,r)=>t.code.localeCompare(r.code))}async createJournalDraft(e){if(!e.id||!e.tenantId||!e.occurredAt)throw new Error("JOURNAL_REQUIRED_FIELDS");if(!e.ledgerProfileId)throw new Error("JOURNAL_REQUIRED_FIELDS");let t=await this.dbAdapter.get(l.journals,e.id);if(t&&!t.deleted)throw new Error("JOURNAL_ALREADY_EXISTS");await this.assertJournalLinesKnownAccounts(e.lines),await this.assertJournalPeriodOpen(e),P(e.lines);let r=R(e.lines);if(!r.ok)throw new Error(r.reason??"JOURNAL_INVALID");let a=b(),o={id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,occurredAt:e.occurredAt,reference:e.reference,evidenceRef:e.evidenceRef,status:"draft",postedAt:void 0,lastModified:a,deleted:!1};await this.dbAdapter.create(l.journals,o);for(let i=0;i<e.lines.length;i+=1){let c=e.lines[i],s={id:`${e.id}:line:${i}`,journalId:e.id,accountId:c.accountId,debit:c.debit,credit:c.credit,memo:c.memo,openItemId:c.openItemId,openItemType:c.openItemType,counterpartyRef:c.counterpartyRef,documentRef:c.documentRef,dueAt:c.dueAt,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,lastModified:a,deleted:!1};await this.dbAdapter.create(l.journalLines,s),await this.writeHistory("journal_lines",s.id,"UPSERT",s)}return await this.writeHistory("journals",e.id,"UPSERT",o),this.toJournalEntry(o,e.lines)}async postJournal(e,t=b()){let r=await this.requireJournal(e),a=await this.listJournalLines(e);if(r.status==="posted"||r.status==="reversed")return this.toJournalEntry(r,a);let o={...r,status:"posted",postedAt:t,lastModified:b()};return await this.dbAdapter.update(l.journals,e,o),await this.writeHistory("journals",e,"UPSERT",o),this.toJournalEntry(o,a)}async reverseJournal(e,t){let r=await this.requireJournal(e);if(r.status!=="posted")throw new Error("JOURNAL_NOT_POSTED");let a=await this.listJournalLines(e),o=await this.createJournalDraft({id:t,tenantId:r.tenantId,branchId:r.branchId,financeDomainId:r.financeDomainId,ledgerProfileId:r.ledgerProfileId,occurredAt:r.occurredAt,reference:`reversal:${r.id}`,evidenceRef:r.evidenceRef,lines:a.map(i=>({accountId:i.accountId,debit:i.credit,credit:i.debit,memo:i.memo,openItemId:i.openItemId,openItemType:i.openItemType,counterpartyRef:i.counterpartyRef,documentRef:i.documentRef,dueAt:i.dueAt}))});return this.postJournal(o.id)}async listJournals(e){let r=(await this.dbAdapter.query(l.journals,{filters:{field:"deleted",value:!1}})).filter(o=>ke(o,e)).sort((o,i)=>o.occurredAt.localeCompare(i.occurredAt)),a=[];for(let o of r){let i=await this.listJournalLines(o.id);a.push(this.toJournalEntry(o,i))}return a}async listOpenItems(e){return F(await this.listJournals(e),e)}async getOpenItemAging(e){return D(await this.listOpenItems(e),e)}async reconcileOpenItems(e){return O(await this.listOpenItems(e),e)}async listCashBankMovements(e){return T(await this.listJournals(e),e)}async summarizeCashBankMovements(e){return _(await this.listCashBankMovements(e))}async listFinancialAuditTrail(e){return(await this.dbAdapter.query(l.histories,{})).map(r=>this.toAuditTrailEntry(r)).filter(r=>r!==null).filter(r=>Ue(r,e)).sort((r,a)=>r.occurredAt!==a.occurredAt?r.occurredAt.localeCompare(a.occurredAt):r.id.localeCompare(a.id))}async openFiscalPeriod(e){if(!e.id||!e.tenantId||!e.code||!e.startDate||!e.endDate)throw new Error("FISCAL_PERIOD_REQUIRED_FIELDS");if(Date.parse(e.startDate)>Date.parse(e.endDate))throw new Error("FISCAL_PERIOD_INVALID_RANGE");let t=await this.dbAdapter.get(l.periods,e.id);if(t&&!t.deleted)throw new Error("FISCAL_PERIOD_ALREADY_EXISTS");let r=b(),a={...h(e),status:"open",lastModified:r,deleted:!1};return t?await this.dbAdapter.update(l.periods,e.id,a):await this.dbAdapter.create(l.periods,a),await this.writeHistory("periods",e.id,"UPSERT",a),this.toPeriod(a)}async closeFiscalPeriod(e){let t=await this.dbAdapter.get(l.periods,e);if(!t||t.deleted)throw new Error("FISCAL_PERIOD_NOT_FOUND");let r={...t,status:"closed",lastModified:b()};return await this.dbAdapter.update(l.periods,e,r),await this.writeHistory("periods",e,"UPSERT",r),this.toPeriod(r)}async listFiscalPeriods(){return(await this.dbAdapter.query(l.periods,{filters:{field:"deleted",value:!1}})).map(t=>this.toPeriod(t)).sort((t,r)=>t.startDate.localeCompare(r.startDate))}async getTrialBalance(){return this.getTrialBalanceByScope()}async getTrialBalanceByScope(e){let t=await this.listAccounts(),a=(await this.listJournals(e)).filter(i=>i.status==="posted"),o=new Map;for(let i of a)for(let c of i.lines){let s=o.get(c.accountId)??{debit:0,credit:0};s.debit+=Number(c.debit||0),s.credit+=Number(c.credit||0),o.set(c.accountId,s)}return t.map(i=>{let c=o.get(i.id)??{debit:0,credit:0};return{accountId:i.id,accountCode:i.code,accountName:i.name,accountType:i.type,debit:c.debit,credit:c.credit,net:c.debit-c.credit}})}async createRapb(e){if(!e.id||!e.tenantId||!e.periodCode||!e.title)throw new Error("RAPB_REQUIRED_FIELDS");if(!e.lines||e.lines.length===0)throw new Error("RAPB_LINES_REQUIRED");if(e.lines.some(i=>i.budgetedDebit<0||i.budgetedCredit<0))throw new Error("RAPB_NEGATIVE_AMOUNT");let t=await this.dbAdapter.get(l.rapbPlans,e.id);if(t&&!t.deleted)throw new Error("RAPB_ALREADY_EXISTS");let r=b(),a=[];for(let i=0;i<e.lines.length;i+=1){let c=e.lines[i],s=await this.dbAdapter.get(l.accounts,c.accountId);if(!s||s.deleted)throw new Error(`RAPB_ACCOUNT_NOT_FOUND:${c.accountId}`);a.push({id:`${e.id}:line:${i}`,rapbId:e.id,accountId:c.accountId,accountCode:s.code,accountName:s.name,accountType:s.type,budgetedDebit:c.budgetedDebit,budgetedCredit:c.budgetedCredit,budgetedNet:c.budgetedDebit-c.budgetedCredit,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,lastModified:r,deleted:!1})}let o={id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,periodCode:e.periodCode,title:e.title,status:"draft",notes:e.notes,createdAt:r,approvedAt:void 0,approvedBy:void 0,lastModified:r,deleted:!1};await this.dbAdapter.create(l.rapbPlans,o),await this.writeHistory("rapb_plans",e.id,"UPSERT",o);for(let i of a)await this.dbAdapter.create(l.rapbLines,i),await this.writeHistory("rapb_lines",i.id,"UPSERT",i);return this.toRapbPlan(o,a)}async getRapb(e){let t=await this.dbAdapter.get(l.rapbPlans,e);if(!t||t.deleted)return null;let r=await this.listRapbLines(e);return this.toRapbPlan(t,r)}async listRapb(e){let r=await this.dbAdapter.query(l.rapbPlans,{filters:{field:"deleted",value:!1}});e&&(e.tenantId&&(r=r.filter(o=>o.tenantId===e.tenantId)),e.periodCode&&(r=r.filter(o=>o.periodCode===e.periodCode)),e.branchId&&(r=r.filter(o=>o.branchId===e.branchId)),e.financeDomainId&&(r=r.filter(o=>o.financeDomainId===e.financeDomainId)),e.ledgerProfileId&&(r=r.filter(o=>o.ledgerProfileId===e.ledgerProfileId)));let a=[];for(let o of r.sort((i,c)=>i.createdAt.localeCompare(c.createdAt))){let i=await this.listRapbLines(o.id);a.push(this.toRapbPlan(o,i))}return a}async approveRapb(e,t){let r=await this.dbAdapter.get(l.rapbPlans,e);if(!r||r.deleted)throw new Error("RAPB_NOT_FOUND");if(r.status==="approved")throw new Error("RAPB_ALREADY_APPROVED");let a=typeof t=="string"?t:t.approvedBy,o={...r,status:"approved",approvedAt:b(),approvedBy:a,lastModified:b()};await this.dbAdapter.update(l.rapbPlans,e,o),await this.writeHistory("rapb_plans",e,"UPSERT",o);let i=await this.listRapbLines(e);return this.toRapbPlan(o,i)}async evaluateVariance(e){let t=await this.getRapb(e);if(!t)throw new Error("RAPB_NOT_FOUND");let r=await this.getTrialBalanceByScope({tenantId:t.tenantId,branchId:t.branchId,financeDomainId:t.financeDomainId,ledgerProfileId:t.ledgerProfileId}),a=new Map(r.map(d=>[d.accountId,d])),o=0,i=0,c=0,s=0,I=t.lines.map(d=>{let u=a.get(d.accountId),A=u?.debit??0,y=u?.credit??0,S=A-y;return d.accountType==="revenue"?(o+=d.budgetedCredit-d.budgetedDebit,i+=y-A):d.accountType==="expense"&&(c+=d.budgetedDebit-d.budgetedCredit,s+=A-y),{accountId:d.accountId,accountCode:d.accountCode,accountName:d.accountName,accountType:d.accountType,budgetedDebit:d.budgetedDebit,budgetedCredit:d.budgetedCredit,budgetedNet:d.budgetedNet,actualDebit:A,actualCredit:y,actualNet:S,varianceDebit:A-d.budgetedDebit,varianceCredit:y-d.budgetedCredit,varianceNet:S-d.budgetedNet}}),p=o-c,g=i-s;return{rapbId:e,periodCode:t.periodCode,evaluatedAt:b(),lines:I,totalBudgetedRevenue:o,totalActualRevenue:i,totalBudgetedExpense:c,totalActualExpense:s,budgetedNetIncome:p,actualNetIncome:g,netVariance:g-p}}async assertJournalLinesKnownAccounts(e){for(let t of e){let r=await this.dbAdapter.get(l.accounts,t.accountId);if(!r||r.deleted)throw new Error("JOURNAL_ACCOUNT_NOT_FOUND")}}async assertJournalPeriodOpen(e){let t=await this.dbAdapter.query(l.periods,{filters:{field:"deleted",value:!1}});if(t.length===0)return;let r=t.find(a=>!(a.tenantId!==e.tenantId||Date.parse(a.startDate)>Date.parse(e.occurredAt)||Date.parse(a.endDate)<Date.parse(e.occurredAt)||e.ledgerProfileId&&a.ledgerProfileId&&a.ledgerProfileId!==e.ledgerProfileId||e.financeDomainId&&a.financeDomainId&&a.financeDomainId!==e.financeDomainId));if(!r)throw new Error("FISCAL_PERIOD_NOT_FOUND_FOR_DATE");if(r.status!=="open")throw new Error("FISCAL_PERIOD_CLOSED")}async requireJournal(e){let t=await this.dbAdapter.get(l.journals,e);if(!t||t.deleted)throw new Error("JOURNAL_NOT_FOUND");return t}async listJournalLines(e){return(await this.dbAdapter.query(l.journalLines,{filters:{and:[{field:"journalId",value:e},{field:"deleted",value:!1}]}})).sort((r,a)=>r.id.localeCompare(a.id))}async listRapbLines(e){return(await this.dbAdapter.query(l.rapbLines,{filters:{and:[{field:"rapbId",value:e},{field:"deleted",value:!1}]}})).sort((r,a)=>r.id.localeCompare(a.id))}toJournalEntry(e,t){let{lastModified:r,deleted:a,...o}=e;return{...h(o),lines:t.map(i=>h(i))}}toPeriod(e){let{lastModified:t,deleted:r,...a}=e;return h(a)}toRapbPlan(e,t){let{lastModified:r,deleted:a,...o}=e;return{...h(o),lines:t.map(({id:i,rapbId:c,lastModified:s,deleted:I,...p})=>h(p))}}async writeHistory(e,t,r,a){let o=a,i={id:je(e,t),tableName:e,recordId:t,action:r,changes:h(o),timestamp:b(),tenantId:typeof o.tenantId=="string"?o.tenantId:void 0,branchId:typeof o.branchId=="string"?o.branchId:void 0,financeDomainId:typeof o.financeDomainId=="string"?o.financeDomainId:void 0,ledgerProfileId:typeof o.ledgerProfileId=="string"?o.ledgerProfileId:void 0};await this.dbAdapter.create(l.histories,i)}toAuditTrailEntry(e){let t=e.changes??{},r=typeof t.tenantId=="string"?t.tenantId:e.tenantId,a=typeof t.branchId=="string"?t.branchId:e.branchId,o=typeof t.financeDomainId=="string"?t.financeDomainId:e.financeDomainId,i=typeof t.ledgerProfileId=="string"?t.ledgerProfileId:e.ledgerProfileId;if(e.tableName==="journals"){let c=typeof t.reference=="string"?t.reference:void 0,s=typeof t.evidenceRef=="string"?t.evidenceRef:void 0,I=typeof t.status=="string"?t.status:void 0,p=Ve(c),g=I==="draft"?"journal_drafted":I==="posted"&&p?"journal_reversal_posted":I==="posted"?"journal_posted":null;return g?{id:e.id,occurredAt:e.timestamp,eventType:g,recordType:"journal",recordId:e.recordId,journalId:e.recordId,sourceJournalId:p,tenantId:r,branchId:a,financeDomainId:o,ledgerProfileId:i,reference:c,evidenceRef:s,summary:g==="journal_reversal_posted"?`Reversal journal ${e.recordId} posted for ${p}`:`Journal ${e.recordId} ${g==="journal_drafted"?"drafted":"posted"}`,metadata:{journalOccurredAt:t.occurredAt,status:I}}:null}if(e.tableName==="periods"){let c=typeof t.status=="string"?t.status:void 0;return c!=="open"&&c!=="closed"?null:{id:e.id,occurredAt:e.timestamp,eventType:c==="open"?"fiscal_period_opened":"fiscal_period_closed",recordType:"fiscal_period",recordId:e.recordId,tenantId:r,branchId:a,financeDomainId:o,ledgerProfileId:i,summary:`Fiscal period ${String(t.code??e.recordId)} ${c}`,metadata:{code:t.code,status:c,startDate:t.startDate,endDate:t.endDate}}}if(e.tableName==="rapb_plans"){let c=typeof t.status=="string"?t.status:void 0,s=c==="draft"?"rapb_created":c==="approved"?"rapb_approved":null;return s?{id:e.id,occurredAt:e.timestamp,eventType:s,recordType:"rapb_plan",recordId:e.recordId,tenantId:r,branchId:a,financeDomainId:o,ledgerProfileId:i,summary:s==="rapb_created"?`RAPB ${String(t.title??e.recordId)} created`:`RAPB ${String(t.title??e.recordId)} approved`,metadata:{title:t.title,status:c,periodCode:t.periodCode,approvedBy:t.approvedBy}}:null}return null}};async function Q(n){await N(n);let e=new x(n);return{financeService:H({createAccount:e.createAccount.bind(e),listAccounts:e.listAccounts.bind(e),createJournalDraft:e.createJournalDraft.bind(e),postJournal:e.postJournal.bind(e),reverseJournal:e.reverseJournal.bind(e),listJournals:e.listJournals.bind(e),openFiscalPeriod:e.openFiscalPeriod.bind(e),closeFiscalPeriod:e.closeFiscalPeriod.bind(e),listFiscalPeriods:e.listFiscalPeriods.bind(e),getTrialBalance:e.getTrialBalance.bind(e),getTrialBalanceByScope:e.getTrialBalanceByScope.bind(e),createRapb:e.createRapb.bind(e),getRapb:e.getRapb.bind(e),listRapb:e.listRapb.bind(e),approveRapb:e.approveRapb.bind(e),evaluateVariance:e.evaluateVariance.bind(e),listOpenItems:e.listOpenItems.bind(e),getOpenItemAging:e.getOpenItemAging.bind(e),reconcileOpenItems:e.reconcileOpenItems.bind(e),listCashBankMovements:e.listCashBankMovements.bind(e),summarizeCashBankMovements:e.summarizeCashBankMovements.bind(e),listFinancialAuditTrail:e.listFinancialAuditTrail.bind(e)})}}var B=class{constructor(e,t){this.runtime=e;this.runtimeStateStore=t;this.runtimeStore=(0,j.asReadonlyStore)(this.runtimeStateStore)}static builder(){return new J}get registry(){return this.runtime.registry}async start(e={}){this.runtimeStateStore.setState({phase:"starting",started:!1,lastError:null,lastTransitionAt:new Date().toISOString(),startCount:this.runtimeStateStore.getState().startCount,stopCount:this.runtimeStateStore.getState().stopCount});try{await this.runtime.start(e),this.domainServices=this.runtime.domainServices,this.runtimeStateStore.setState(t=>({...t,phase:"started",started:!0,startCount:t.startCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(t){throw this.runtimeStateStore.setState(r=>({...r,phase:"error",started:!1,lastError:t instanceof Error?t.message:String(t),lastTransitionAt:new Date().toISOString()})),t}}async stop(){this.runtimeStateStore.setState(e=>({...e,phase:"stopping",started:this.runtime.isStarted(),lastError:null,lastTransitionAt:new Date().toISOString()}));try{await this.runtime.stop(),this.runtimeStateStore.setState(e=>({...e,phase:"stopped",started:!1,stopCount:e.stopCount+1,lastError:null,lastTransitionAt:new Date().toISOString()}))}catch(e){throw this.runtimeStateStore.setState(t=>({...t,phase:"error",started:this.runtime.isStarted(),lastError:e instanceof Error?e.message:String(e),lastTransitionAt:new Date().toISOString()})),e}}isStarted(){return this.runtime.isStarted()}},J=class{constructor(){this.runtimeBuilder=se.CoreRuntime.builder();this.runtimeHooks={};this.runtimeBuilder.withDbAdapter(()=>new ue.InMemoryDbAdapter)}withPlatformAdapter(e){return this.runtimeBuilder.withPlatformAdapter(e),this}withDbAdapter(e){return this.runtimeBuilder.withDbAdapter(e),this}withHttpAdapter(e){return this.runtimeBuilder.withHttpAdapter(e),this}withSocketAdapter(e){return this.runtimeBuilder.withSocketAdapter(e),this}withLoggerAdapter(e){return this.runtimeBuilder.withLoggerAdapter(e),this}withActivitySink(e){return this.runtimeBuilder.withActivitySink(e),this}withExtension(e,t){return this.runtimeBuilder.withExtension(e,t),this}withDomainServicesFactory(e){return this.domainServicesFactory=e,this}withRuntimeHooks(e){return this.runtimeHooks={...this.runtimeHooks,...e},this}build(){let e=(0,j.createStore)({phase:"idle",started:!1,startCount:0,stopCount:0,lastError:null,lastTransitionAt:new Date().toISOString()}),t={runMigrations:async a=>{let o=a.registry?.dbAdapter;if(!o)throw new Error("OFINANCE_DB_ADAPTER_REQUIRED");await N(o,a.registry?.loggerAdapter),this.runtimeHooks.runMigrations&&await this.runtimeHooks.runMigrations(a)},...this.runtimeHooks,createDomainServices:async a=>{if(this.domainServicesFactory)return this.domainServicesFactory();let o=a.registry?.dbAdapter;if(!o)throw new Error("OFINANCE_DB_ADAPTER_REQUIRED");return Q(o)}};this.runtimeBuilder.withHooks(t);let r=this.runtimeBuilder.build();return new B(r,e)}};function q(n){return!Array.isArray(n.components)||n.components.length===0?[]:n.components.map(e=>{if(!e.accountId?.trim())throw new Error("FINANCE_TAX_ACCOUNT_REQUIRED");if(!Number.isFinite(e.amount)||e.amount<=0)throw new Error("FINANCE_TAX_AMOUNT_INVALID");if(e.direction!=="payable"&&e.direction!=="receivable")throw new Error("FINANCE_TAX_DIRECTION_INVALID");let t=`${n.memoPrefix??"Finance tax"} ${e.direction}`;return{accountId:e.accountId,debit:e.direction==="receivable"?e.amount:0,credit:e.direction==="payable"?e.amount:0,memo:e.memo??t}})}function C(n,e,t){return{id:n.journalId,tenantId:n.tenantId,branchId:n.branchId,financeDomainId:n.financeDomainId,ledgerProfileId:n.ledgerProfileId,occurredAt:n.occurredAt,reference:t?`${n.reference??""}${t}`:n.reference,evidenceRef:n.evidenceRef,lines:e}}function v(n,e){if(!Number.isFinite(n)||n<=0)throw new Error(e)}function Y(n,e){v(e.grossAmount,"POS_SALE_INVALID_GROSS_AMOUNT");let t=e.discountAmount??0,r=e.taxAmount??0;if(t<0||r<0)throw new Error("POS_SALE_NEGATIVE_COMPONENT");let a=e.grossAmount,o=a-t+r,i=[{accountId:e.paymentAccountId,debit:o,credit:0,memo:"POS sale payment"},{accountId:e.revenueAccountId,debit:0,credit:a,memo:"POS sale revenue"}];if(t>0){if(!e.discountAccountId)throw new Error("POS_SALE_DISCOUNT_ACCOUNT_REQUIRED");i.push({accountId:e.discountAccountId,debit:t,credit:0,memo:"POS sale discount"})}if(r>0){if(!e.taxPayableAccountId)throw new Error("POS_SALE_TAX_ACCOUNT_REQUIRED");i.push(...q({memoPrefix:"POS sale tax",components:[{accountId:e.taxPayableAccountId,amount:r,direction:"payable",memo:"POS sale tax payable"}]}))}return C(n,i)}function G(n,e){return v(e.principalAmount,"COOP_LOAN_INVALID_PRINCIPAL"),C(n,[{accountId:e.receivableAccountId,debit:e.principalAmount,credit:0,memo:"Loan receivable principal"},{accountId:e.cashAccountId,debit:0,credit:e.principalAmount,memo:"Loan cash out"}])}function W(n,e){return v(e.amount,"COOP_SAVING_INVALID_AMOUNT"),C(n,[{accountId:e.cashAccountId,debit:e.amount,credit:0,memo:"Saving deposit cash in"},{accountId:e.savingLiabilityAccountId,debit:0,credit:e.amount,memo:"Saving liability increase"}])}function z(n,e){return v(e.amount,"COOP_SAVING_WITHDRAWAL_INVALID_AMOUNT"),C(n,[{accountId:e.savingLiabilityAccountId,debit:e.amount,credit:0,memo:"Saving liability decrease"},{accountId:e.cashAccountId,debit:0,credit:e.amount,memo:"Saving withdrawal cash out"}])}function X(n,e){v(e.principalAmount,"COOP_LOAN_REPAYMENT_INVALID_PRINCIPAL");let t=e.serviceAmount??0,r=e.penaltyAmount??0;if(t<0||r<0)throw new Error("COOP_LOAN_REPAYMENT_NEGATIVE_COMPONENT");if(t>0&&!e.serviceRevenueAccountId)throw new Error("COOP_LOAN_REPAYMENT_SERVICE_ACCOUNT_REQUIRED");if(r>0&&!e.penaltyRevenueAccountId)throw new Error("COOP_LOAN_REPAYMENT_PENALTY_ACCOUNT_REQUIRED");let a=e.principalAmount+t+r,o=[{accountId:e.cashAccountId,debit:a,credit:0,memo:"Loan repayment cash in"},{accountId:e.receivableAccountId,debit:0,credit:e.principalAmount,memo:"Loan receivable principal repayment"}];return t>0&&o.push({accountId:e.serviceRevenueAccountId,debit:0,credit:t,memo:"Loan service revenue"}),r>0&&o.push({accountId:e.penaltyRevenueAccountId,debit:0,credit:r,memo:"Loan penalty revenue"}),C(n,o)}function $e(n,e){if(v(e.amount,"COOP_SHU_PARTICIPATION_INVALID_AMOUNT"),!n.evidenceRef?.trim())throw new Error("COOP_SHU_PARTICIPATION_EVIDENCE_REQUIRED");return C(n,[{accountId:e.debitAccountId,debit:e.amount,credit:0,memo:e.memo??"Coop SHU participation manual recap debit"},{accountId:e.creditAccountId,debit:0,credit:e.amount,memo:e.memo??"Coop SHU participation manual recap credit"}])}function le(n,e){return e?{...n,...e}:{...n}}function E(n){let e=n.tenantId?n.scopedMapping.byTenant?.[n.tenantId]:void 0,t=n.tenantId&&n.branchId?`${n.tenantId}:${n.branchId}`:"",r=t?n.scopedMapping.byBranch?.[t]:void 0;return le(le(n.scopedMapping.default,e),r)}function K(n){return E(n)}function Z(n){return E(n)}function ee(n){return E(n)}function te(n){return E(n)}function ne(n){return E(n)}function He(n,e){let{scopedAccountMapping:t,...r}=e,a=K({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return Y(n,{...r,...a})}function Qe(n,e){let{scopedAccountMapping:t,...r}=e,a=Z({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return G(n,{...r,...a})}function qe(n,e){let{scopedAccountMapping:t,...r}=e,a=te({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return W(n,{...r,...a})}function Ye(n,e){let{scopedAccountMapping:t,...r}=e,a=ne({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return z(n,{...r,...a})}function Ge(n,e){let{scopedAccountMapping:t,...r}=e,a=ee({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return X(n,{...r,...a})}function k(n){return!!(n&&typeof n=="object"&&n.error)}function re(n){return n.startsWith("ofinance_")?`offinance_${n.slice(9)}`:n}async function We(n,e,t){let r=await n.accountService.listAccounts();if(k(r))throw new Error(r.error.message||r.error.code||"FINANCE_ACCOUNT_LIST_FAILED");let a=new Set((r.data||[]).map(o=>o.id));for(let o of e){if(a.has(o.id))continue;let i=await n.accountService.createAccount(o);if(k(i))throw new Error(i.error.message||i.error.code||"FINANCE_ACCOUNT_CREATE_FAILED");await t?.({changeId:`offinance:account:${o.id}`,entity:"FinanceAccount",table:re(l.accounts),type:"CREATE",data:o})}}async function pe(n,e,t){return n.query(e,{filters:{and:t}})}async function ze(n,e,t){if(!t)return;let r=await pe(n,l.journals,[{field:"id",value:e.id}]),a=await pe(n,l.journalLines,[{field:"journalId",value:e.id}]);r.length===0&&(r=[{id:e.id,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,occurredAt:e.occurredAt,reference:e.reference,status:e.status,postedAt:e.postedAt,lastModified:e.postedAt||e.occurredAt,deleted:!1}]),a.length===0&&(a=e.lines.map((o,i)=>({id:`${e.id}:line:${i}`,journalId:e.id,accountId:o.accountId,debit:o.debit,credit:o.credit,memo:o.memo,openItemId:o.openItemId,openItemType:o.openItemType,counterpartyRef:o.counterpartyRef,documentRef:o.documentRef,dueAt:o.dueAt,tenantId:e.tenantId,branchId:e.branchId,financeDomainId:e.financeDomainId,ledgerProfileId:e.ledgerProfileId,lastModified:e.postedAt||e.occurredAt,deleted:!1})));for(let o of r)await t({changeId:`offinance:journal:${o.id}`,entity:"FinanceJournalEntry",table:re(l.journals),type:"CREATE",data:o});for(let o of a)await t({changeId:`offinance:journal-line:${o.id}`,entity:"FinanceJournalLine",table:re(l.journalLines),type:"CREATE",data:o})}function Xe(n){return async e=>{let t=n.resolveFinanceServices();if(!t)throw new Error(n.missingServicesErrorCode||"FINANCE_SERVICES_UNAVAILABLE");let r=n.resolveLedgerProfileId().trim();if(!r)throw new Error(n.missingLedgerProfileErrorCode||"FINANCE_LEDGER_PROFILE_REQUIRED");let a=n.resolveSyncEnqueuer?.()??null;await We(t,n.requiredAccounts,a);let o=n.buildJournalDraft(e,r),i=await t.journalService.createJournalDraft(o);if(k(i)&&i.error.code!=="JOURNAL_ALREADY_EXISTS")throw new Error(i.error.message||i.error.code||"FINANCE_JOURNAL_CREATE_FAILED");let c=await t.journalService.postJournal(o.id,o.occurredAt);if(k(c))throw new Error(c.error.message||c.error.code||"FINANCE_JOURNAL_POST_FAILED");await ze(n.dbAdapter,c.data,a)}}function Ke(n){switch(n.accountType){case"asset":case"expense":return n.debit-n.credit;case"liability":case"equity":case"revenue":return n.credit-n.debit;default:return 0}}function L(n,e){return n.filter(t=>t.accountType===e).reduce((t,r)=>t+Ke(r),0)}function Ze(n){let e=L(n,"revenue"),t=L(n,"expense");return{revenue:e,expense:t,netIncome:e-t}}function et(n){return{assets:L(n,"asset"),liabilities:L(n,"liability"),equity:L(n,"equity")}}function me(n){return n.accountType==="revenue"?n.credit-n.debit:n.accountType==="expense"?n.debit-n.credit:0}function tt(n){let e=n.filter(r=>r.accountType==="revenue").reduce((r,a)=>r+Math.max(0,me(a)),0),t=n.filter(r=>r.accountType==="expense").reduce((r,a)=>r+Math.max(0,me(a)),0);return{operatingInflow:e,operatingOutflow:t,netOperatingCashflow:e-t}}function nt(n,e){let t=[],r=0;for(let a of e){if(a.accountType==="revenue"){let o=a.credit-a.debit;o>0&&(t.push({accountId:a.accountId,debit:o,credit:0,memo:"Close revenue account"}),r+=o)}if(a.accountType==="expense"){let o=a.debit-a.credit;o>0&&(t.push({accountId:a.accountId,debit:0,credit:o,memo:"Close expense account"}),r-=o)}}return r>0?t.push({accountId:n.retainedEarningsAccountId,debit:0,credit:r,memo:"Retained earnings from period close"}):r<0&&t.push({accountId:n.retainedEarningsAccountId,debit:Math.abs(r),credit:0,memo:"Retained earnings from period close"}),{id:n.journalId,tenantId:n.tenantId,branchId:n.branchId,financeDomainId:n.financeDomainId,ledgerProfileId:n.ledgerProfileId,occurredAt:n.occurredAt,reference:n.reference,lines:t}}function rt(n){return Array.isArray(n)?n.length:n&&typeof n=="object"?1:n===null||typeof n>"u"?0:1}function at(n){return n==="json"?"application/json":"text/csv"}function ot(n,e){if(n==="json")return`${JSON.stringify(e,null,2)}
2
+ `;if(typeof e!="string")throw new Error("FINANCE_COMPLIANCE_EXPORT_CSV_PAYLOAD_STRING_REQUIRED");return e}function it(n){let e=2166136261;for(let t=0;t<n.length;t+=1)e^=n.charCodeAt(t),e=Math.imul(e,16777619);return`fnv1a32-${(e>>>0).toString(16).padStart(8,"0")}`}function ct(n){if(!n.key?.trim())throw new Error("FINANCE_COMPLIANCE_EXPORT_DATASET_KEY_REQUIRED");if(!n.fileName?.trim())throw new Error("FINANCE_COMPLIANCE_EXPORT_FILE_NAME_REQUIRED");if(n.format!=="json"&&n.format!=="csv")throw new Error("FINANCE_COMPLIANCE_EXPORT_FORMAT_INVALID")}function dt(n){return n??"custom"}function ae(n){if(!Array.isArray(n.datasets)||n.datasets.length===0)throw new Error("FINANCE_COMPLIANCE_EXPORT_DATASETS_REQUIRED");let e=new Set,t={},r=[];for(let o of n.datasets){if(ct(o),e.has(o.key))throw new Error("FINANCE_COMPLIANCE_EXPORT_DATASET_KEY_DUPLICATE");e.add(o.key);let i=ot(o.format,o.payload);t[o.fileName]=i,r.push({key:o.key,fileName:o.fileName,format:o.format,semantic:dt(o.semantic),contentType:o.contentType??at(o.format),recordCount:rt(o.payload),checksum:it(i)})}return{contract:{contractVersion:"fcx-v1",tenantId:n.tenantId,branchId:n.branchId,financeDomainId:n.financeDomainId,ledgerProfileId:n.ledgerProfileId,generatedAt:n.generatedAt??new Date().toISOString(),period:{from:n.period?.from??null,to:n.period?.to??null,label:n.period?.label??null},currency:{baseCurrencyCode:n.baseCurrencyCode??"IDR"},datasets:r,summary:{datasetCount:r.length,totalRecordCount:r.reduce((o,i)=>o+i.recordCount,0)}},files:t}}function st(n){return{version:"v1",generatedAt:n.generatedAt??new Date().toISOString(),payload:{trialBalance:n.trialBalance.map(e=>({...e})),incomeStatement:{...n.incomeStatement},balanceSheet:{...n.balanceSheet}}}}function ut(n){let e=[{key:"trial-balance",fileName:"trial_balance.json",format:"json",semantic:"trial_balance",payload:n.trialBalance},{key:"income-statement",fileName:"income_statement.json",format:"json",semantic:"income_statement",payload:n.incomeStatement},{key:"balance-sheet",fileName:"balance_sheet.json",format:"json",semantic:"balance_sheet",payload:n.balanceSheet}];return typeof n.openItems<"u"&&e.push({key:"open-items",fileName:"open_items.json",format:"json",semantic:"open_items",payload:n.openItems}),typeof n.agingSummary<"u"&&e.push({key:"aging-summary",fileName:"aging_summary.json",format:"json",semantic:"aging_summary",payload:n.agingSummary}),typeof n.reconciliationSummary<"u"&&e.push({key:"reconciliation-summary",fileName:"reconciliation_summary.json",format:"json",semantic:"reconciliation",payload:n.reconciliationSummary}),typeof n.cashMovements<"u"&&e.push({key:"cash-movements",fileName:"cash_movements.json",format:"json",semantic:"cash_movements",payload:n.cashMovements}),ae({tenantId:n.tenantId,branchId:n.branchId,financeDomainId:n.financeDomainId,ledgerProfileId:n.ledgerProfileId,generatedAt:n.generatedAt,period:n.period,baseCurrencyCode:n.baseCurrencyCode,datasets:e})}function lt(n){return n.accountType==="revenue"?n.credit-n.debit:n.accountType==="expense"?n.debit-n.credit:0}function fe(n,e){return e===0?n===0?1:0:Number((n/e).toFixed(4))}function pt(n,e){let t=e.map(a=>{let c=((a.accountCodes?.length?n.filter(I=>a.accountCodes?.includes(I.accountCode)):null)??n.filter(I=>a.accountType?I.accountType===a.accountType:!1)).reduce((I,p)=>I+lt(p),0),s=c-a.plannedAmount;return{id:a.id,label:a.label,plannedAmount:a.plannedAmount,actualAmount:c,varianceAmount:s,achievementRatio:fe(c,a.plannedAmount)}}),r=t.reduce((a,o)=>(a.plannedAmount+=o.plannedAmount,a.actualAmount+=o.actualAmount,a.varianceAmount+=o.varianceAmount,a),{plannedAmount:0,actualAmount:0,varianceAmount:0});return{rows:t,totals:{...r,achievementRatio:fe(r.actualAmount,r.plannedAmount)}}}function Ie(n,e){switch(e.type){case"finance.account.created":n.createAccount(e.payload);return;case"finance.period.opened":n.openFiscalPeriod(e.payload);return;case"finance.period.closed":n.closeFiscalPeriod(e.payload.periodId);return;case"finance.journal.drafted":n.createJournalDraft(e.payload);return;case"finance.journal.posted":n.postJournal(e.payload.journalId,e.payload.postedAt);return;case"finance.journal.reversed":n.reverseJournal(e.payload.journalId,e.payload.reversalId);return;default:throw new Error("FINANCE_EVENT_UNSUPPORTED")}}function mt(n){let e=new w;for(let t of n)Ie(e,t);return e}var ge=[{id:"coa-cash",code:"1101",name:"Kas",type:"asset"},{id:"coa-bank",code:"1102",name:"Bank",type:"asset"},{id:"coa-ar",code:"1201",name:"Piutang Usaha",type:"asset"},{id:"coa-ap",code:"2101",name:"Utang Usaha",type:"liability"},{id:"coa-retained",code:"3201",name:"Laba Ditahan",type:"equity"},{id:"coa-revenue",code:"4101",name:"Pendapatan Operasional",type:"revenue"},{id:"coa-expense",code:"5101",name:"Biaya Operasional",type:"expense"}];function ft(n="IDR"){return ge.map(e=>({id:e.id,code:e.code,name:e.name,type:e.type,currency:n,isActive:!0}))}var Ae=[{id:"coop-coa-cash",code:"1101",name:"Kas",type:"asset"},{id:"coop-coa-bank",code:"1102",name:"Bank",type:"asset"},{id:"coop-coa-loan-ar",code:"1201",name:"Piutang Pinjaman Anggota",type:"asset"},{id:"coop-coa-other-ar",code:"1202",name:"Piutang Lain-lain",type:"asset"},{id:"coop-coa-prepaid",code:"1301",name:"Biaya Dibayar Dimuka",type:"asset"},{id:"coop-coa-fixed-asset",code:"1401",name:"Aset Tetap",type:"asset"},{id:"coop-coa-accum-depr",code:"1402",name:"Akumulasi Penyusutan",type:"asset"},{id:"coop-coa-simp-pokok",code:"2101",name:"Simpanan Pokok",type:"liability"},{id:"coop-coa-simp-wajib",code:"2102",name:"Simpanan Wajib",type:"liability"},{id:"coop-coa-simp-sukarela",code:"2103",name:"Simpanan Sukarela",type:"liability"},{id:"coop-coa-simp-berjangka",code:"2104",name:"Simpanan Berjangka",type:"liability"},{id:"coop-coa-ap",code:"2201",name:"Utang Usaha",type:"liability"},{id:"coop-coa-ext-loan",code:"2301",name:"Pinjaman Luar",type:"liability"},{id:"coop-coa-tax-payable",code:"2401",name:"Utang Pajak",type:"liability"},{id:"coop-coa-modal-awal",code:"3101",name:"Modal Awal",type:"equity"},{id:"coop-coa-cadangan-umum",code:"3201",name:"Dana Cadangan Umum",type:"equity"},{id:"coop-coa-cadangan-tujuan",code:"3202",name:"Dana Cadangan Tujuan",type:"equity"},{id:"coop-coa-shu-prior",code:"3301",name:"SHU Tahun Lalu",type:"equity"},{id:"coop-coa-shu-current",code:"3302",name:"SHU Berjalan",type:"equity"},{id:"coop-coa-shu-reserve",code:"3303",name:"Dana SHU Belum Dibagi",type:"equity"},{id:"coop-coa-jasa-pinjaman",code:"4101",name:"Pendapatan Jasa Pinjaman",type:"revenue"},{id:"coop-coa-provisi",code:"4102",name:"Pendapatan Provisi",type:"revenue"},{id:"coop-coa-rev-other",code:"4103",name:"Pendapatan Lain-lain",type:"revenue"},{id:"coop-coa-beban-bunga",code:"5101",name:"Beban Bunga Simpanan",type:"expense"},{id:"coop-coa-beban-ops",code:"5102",name:"Beban Operasional",type:"expense"},{id:"coop-coa-beban-gaji",code:"5103",name:"Beban Gaji dan Tunjangan",type:"expense"},{id:"coop-coa-beban-admin",code:"5104",name:"Beban Administrasi",type:"expense"},{id:"coop-coa-beban-depr",code:"5105",name:"Beban Penyusutan",type:"expense"},{id:"coop-coa-prov-kredit",code:"5106",name:"Cadangan Kerugian Piutang",type:"expense"}];function It(n="IDR"){return Ae.map(e=>({id:e.id,code:e.code,name:e.name,type:e.type,currency:n,isActive:!0}))}function gt(n){let e=new Set,t=new Set;for(let r of n){if(!r.id||!r.code||!r.name)return{ok:!1,reason:"COA_REQUIRED_FIELDS"};if(e.has(r.id))return{ok:!1,reason:"COA_DUPLICATE_ID"};if(t.has(r.code))return{ok:!1,reason:"COA_DUPLICATE_CODE"};e.add(r.id),t.add(r.code)}return{ok:!0}}
2
3
  /*! For license information please see index.js.LEGAL.txt */
@@ -0,0 +1,4 @@
1
+ import type { FinanceJournalEntry } from '../contracts/JournalContract.js';
2
+ import type { FinanceCashBankMovementEntry, FinanceCashBankMovementScope, FinanceCashBankMovementSummary } from '../contracts/CashMovementContract.js';
3
+ export declare function projectFinanceCashBankMovements(journals: FinanceJournalEntry[], scope: FinanceCashBankMovementScope): FinanceCashBankMovementEntry[];
4
+ export declare function summarizeFinanceCashBankMovements(entries: FinanceCashBankMovementEntry[]): FinanceCashBankMovementSummary;
@@ -0,0 +1,11 @@
1
+ import type { FinanceComplianceExportBundle, FinanceComplianceExportDatasetInput, FinanceComplianceExportPeriod } from '../contracts/ComplianceExportContract.js';
2
+ export declare function buildFinanceComplianceExportBundle(params: {
3
+ tenantId?: string;
4
+ branchId?: string;
5
+ financeDomainId?: string;
6
+ ledgerProfileId?: string;
7
+ generatedAt?: string;
8
+ period?: Partial<FinanceComplianceExportPeriod>;
9
+ baseCurrencyCode?: string;
10
+ datasets: FinanceComplianceExportDatasetInput[];
11
+ }): FinanceComplianceExportBundle;
@@ -1,5 +1,6 @@
1
1
  import type { BalanceSheet, IncomeStatement } from './financialStatements.js';
2
2
  import type { TrialBalanceRow } from '../contracts/FiscalContract.js';
3
+ import { buildFinanceComplianceExportBundle } from './complianceExport.js';
3
4
  export interface FinanceExportEnvelope {
4
5
  version: 'v1';
5
6
  generatedAt: string;
@@ -15,3 +16,23 @@ export declare function buildFinanceExportEnvelope(params: {
15
16
  balanceSheet: BalanceSheet;
16
17
  generatedAt?: string;
17
18
  }): FinanceExportEnvelope;
19
+ export declare function buildFinanceOperationalComplianceBundle(params: {
20
+ tenantId?: string;
21
+ branchId?: string;
22
+ financeDomainId?: string;
23
+ ledgerProfileId?: string;
24
+ generatedAt?: string;
25
+ period?: {
26
+ from?: string | null;
27
+ to?: string | null;
28
+ label?: string | null;
29
+ };
30
+ baseCurrencyCode?: string;
31
+ trialBalance: TrialBalanceRow[];
32
+ incomeStatement: IncomeStatement;
33
+ balanceSheet: BalanceSheet;
34
+ openItems?: unknown[];
35
+ agingSummary?: unknown;
36
+ reconciliationSummary?: unknown;
37
+ cashMovements?: unknown[];
38
+ }): ReturnType<typeof buildFinanceComplianceExportBundle>;
@@ -0,0 +1,10 @@
1
+ import type { FinanceJournalEntry } from '../contracts/JournalContract.js';
2
+ import type { FinanceOpenItemAgingBucketResult, FinanceOpenItemAgingQuery, FinanceOpenItemPosition, FinanceOpenItemScope, FinanceOpenItemType } from '../contracts/OpenItemContract.js';
3
+ export declare function validateOpenItemLineMetadata(lines: FinanceJournalEntry['lines']): void;
4
+ export declare function projectFinanceOpenItems(journals: FinanceJournalEntry[], scope?: FinanceOpenItemScope): FinanceOpenItemPosition[];
5
+ export declare function buildFinanceOpenItemAging(items: FinanceOpenItemPosition[], query: FinanceOpenItemAgingQuery): {
6
+ asOf: string;
7
+ openItemType?: FinanceOpenItemType;
8
+ totalOutstanding: number;
9
+ buckets: FinanceOpenItemAgingBucketResult[];
10
+ };
@@ -0,0 +1,3 @@
1
+ import type { FinanceOpenItemReconciliationInput, FinanceOpenItemReconciliationSummary } from '../contracts/ReconciliationContract.js';
2
+ import type { FinanceOpenItemPosition } from '../contracts/OpenItemContract.js';
3
+ export declare function reconcileFinanceOpenItems(expectedItems: FinanceOpenItemPosition[], input: FinanceOpenItemReconciliationInput): FinanceOpenItemReconciliationSummary;
@@ -3,6 +3,10 @@ import type { FinanceAccount } from '../contracts/AccountContract.js';
3
3
  import type { CreateRapbInput, RapbPlan, RapbVariance } from '../contracts/BudgetContract.js';
4
4
  import type { FinanceLedgerScope, FiscalPeriod, TrialBalanceRow } from '../contracts/FiscalContract.js';
5
5
  import type { FinanceJournalEntry, JournalDraftInput } from '../contracts/JournalContract.js';
6
+ import type { FinanceOpenItemAgingQuery, FinanceOpenItemAgingSummary, FinanceOpenItemPosition, FinanceOpenItemScope } from '../contracts/OpenItemContract.js';
7
+ import type { FinanceOpenItemReconciliationInput, FinanceOpenItemReconciliationSummary } from '../contracts/ReconciliationContract.js';
8
+ import type { FinanceCashBankMovementEntry, FinanceCashBankMovementScope, FinanceCashBankMovementSummary } from '../contracts/CashMovementContract.js';
9
+ import type { FinanceAuditTrailEntry, FinanceAuditTrailScope } from '../contracts/AuditTrailContract.js';
6
10
  export declare class DbAdapterOffinanceService {
7
11
  private readonly dbAdapter;
8
12
  constructor(dbAdapter: DbAdapter);
@@ -12,6 +16,12 @@ export declare class DbAdapterOffinanceService {
12
16
  postJournal(journalId: string, postedAt?: string): Promise<FinanceJournalEntry>;
13
17
  reverseJournal(journalId: string, reversalId: string): Promise<FinanceJournalEntry>;
14
18
  listJournals(scope?: FinanceLedgerScope): Promise<FinanceJournalEntry[]>;
19
+ listOpenItems(scope?: FinanceOpenItemScope): Promise<FinanceOpenItemPosition[]>;
20
+ getOpenItemAging(query: FinanceOpenItemAgingQuery): Promise<FinanceOpenItemAgingSummary>;
21
+ reconcileOpenItems(input: FinanceOpenItemReconciliationInput): Promise<FinanceOpenItemReconciliationSummary>;
22
+ listCashBankMovements(scope: FinanceCashBankMovementScope): Promise<FinanceCashBankMovementEntry[]>;
23
+ summarizeCashBankMovements(scope: FinanceCashBankMovementScope): Promise<FinanceCashBankMovementSummary>;
24
+ listFinancialAuditTrail(scope?: FinanceAuditTrailScope): Promise<FinanceAuditTrailEntry[]>;
15
25
  openFiscalPeriod(period: FiscalPeriod): Promise<FiscalPeriod>;
16
26
  closeFiscalPeriod(periodId: string): Promise<FiscalPeriod>;
17
27
  listFiscalPeriods(): Promise<FiscalPeriod[]>;
@@ -33,4 +43,5 @@ export declare class DbAdapterOffinanceService {
33
43
  private toPeriod;
34
44
  private toRapbPlan;
35
45
  private writeHistory;
46
+ private toAuditTrailEntry;
36
47
  }
@@ -2,6 +2,10 @@ import type { FinanceAccount, FinanceAccountServiceContractV2 } from '../contrac
2
2
  import type { RapbServiceContractV2 } from '../contracts/BudgetContract.js';
3
3
  import type { FinanceLedgerScope, FiscalPeriod, FiscalPeriodServiceContractV2 } from '../contracts/FiscalContract.js';
4
4
  import type { FinanceJournalServiceContractV2, JournalDraftInput } from '../contracts/JournalContract.js';
5
+ import type { FinanceOpenItemAgingQuery, FinanceOpenItemServiceContractV2, FinanceOpenItemScope } from '../contracts/OpenItemContract.js';
6
+ import type { FinanceOpenItemReconciliationInput, FinanceReconciliationServiceContractV2 } from '../contracts/ReconciliationContract.js';
7
+ import type { FinanceCashBankMovementScope, FinanceCashBankMovementServiceContractV2 } from '../contracts/CashMovementContract.js';
8
+ import type { FinanceAuditTrailScope, FinanceAuditTrailServiceContractV2 } from '../contracts/AuditTrailContract.js';
5
9
  export interface OffinanceLegacyServices {
6
10
  accountService: {
7
11
  createAccount(account: FinanceAccount): FinanceAccount | Promise<FinanceAccount>;
@@ -29,12 +33,30 @@ export interface OffinanceLegacyServices {
29
33
  }): any | Promise<any>;
30
34
  evaluateVariance(rapbId: string): any | Promise<any>;
31
35
  };
36
+ openItemService: {
37
+ listOpenItems(scope?: FinanceOpenItemScope): any[] | Promise<any[]>;
38
+ getOpenItemAging(query: FinanceOpenItemAgingQuery): any | Promise<any>;
39
+ };
40
+ reconciliationService: {
41
+ reconcileOpenItems(input: FinanceOpenItemReconciliationInput): any | Promise<any>;
42
+ };
43
+ cashMovementService: {
44
+ listCashBankMovements(scope: FinanceCashBankMovementScope): any[] | Promise<any[]>;
45
+ summarizeCashBankMovements(scope: FinanceCashBankMovementScope): any | Promise<any>;
46
+ };
47
+ auditTrailService: {
48
+ listFinancialAuditTrail(scope?: FinanceAuditTrailScope): any[] | Promise<any[]>;
49
+ };
32
50
  }
33
51
  export interface OffinanceEnvelopeServices {
34
52
  accountService: FinanceAccountServiceContractV2;
35
53
  journalService: FinanceJournalServiceContractV2;
36
54
  fiscalService: FiscalPeriodServiceContractV2;
37
55
  rapbService: RapbServiceContractV2;
56
+ openItemService: FinanceOpenItemServiceContractV2;
57
+ reconciliationService: FinanceReconciliationServiceContractV2;
58
+ cashMovementService: FinanceCashBankMovementServiceContractV2;
59
+ auditTrailService: FinanceAuditTrailServiceContractV2;
38
60
  }
39
61
  export declare class OffinanceEnvelopeService implements OffinanceEnvelopeServices {
40
62
  private readonly legacy;
@@ -42,6 +64,10 @@ export declare class OffinanceEnvelopeService implements OffinanceEnvelopeServic
42
64
  readonly journalService: FinanceJournalServiceContractV2;
43
65
  readonly fiscalService: FiscalPeriodServiceContractV2;
44
66
  readonly rapbService: RapbServiceContractV2;
67
+ readonly openItemService: FinanceOpenItemServiceContractV2;
68
+ readonly reconciliationService: FinanceReconciliationServiceContractV2;
69
+ readonly cashMovementService: FinanceCashBankMovementServiceContractV2;
70
+ readonly auditTrailService: FinanceAuditTrailServiceContractV2;
45
71
  constructor(legacy: OffinanceLegacyServices);
46
72
  }
47
73
  export declare function createOffinanceEnvelopeService(legacyService: {
@@ -63,4 +89,10 @@ export declare function createOffinanceEnvelopeService(legacyService: {
63
89
  approvedBy: string;
64
90
  }): any | Promise<any>;
65
91
  evaluateVariance(rapbId: string): any | Promise<any>;
92
+ listOpenItems(scope?: FinanceOpenItemScope): any[] | Promise<any[]>;
93
+ getOpenItemAging(query: FinanceOpenItemAgingQuery): any | Promise<any>;
94
+ reconcileOpenItems(input: FinanceOpenItemReconciliationInput): any | Promise<any>;
95
+ listCashBankMovements(scope: FinanceCashBankMovementScope): any[] | Promise<any[]>;
96
+ summarizeCashBankMovements(scope: FinanceCashBankMovementScope): any | Promise<any>;
97
+ listFinancialAuditTrail(scope?: FinanceAuditTrailScope): any[] | Promise<any[]>;
66
98
  }): OffinanceEnvelopeServices;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "offinance-shared-core",
3
- "version": "0.1.0-alpha.2",
3
+ "version": "0.1.0-alpha.4",
4
4
  "private": false,
5
5
  "description": "Offline-first platform-agnostic db-agnostic finance shared core",
6
6
  "author": {
@@ -41,7 +41,7 @@
41
41
  "vitest": "^1.6.1"
42
42
  },
43
43
  "dependencies": {
44
- "ofcore": "0.2.0-alpha.1"
44
+ "ofcore": "0.2.0-alpha.2"
45
45
  },
46
46
  "repository": {
47
47
  "type": "git",