offinance-shared-core 0.1.0-alpha.3 → 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.
- package/dist/OffinanceCore.d.ts +5 -0
- package/dist/contracts/AuditTrailContract.d.ts +27 -0
- package/dist/contracts/CashMovementContract.d.ts +7 -0
- package/dist/contracts/FiscalContract.d.ts +1 -0
- package/dist/contracts/ReconciliationContract.d.ts +11 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.esm.js +2 -2
- package/dist/index.js +2 -2
- package/dist/services/DbAdapterOffinanceService.d.ts +3 -0
- package/dist/services/OffinanceEnvelopeService.d.ts +7 -0
- package/package.json +2 -2
package/dist/OffinanceCore.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { FinanceJournalEntry, JournalDraftInput } from './contracts/Journal
|
|
|
3
3
|
import type { FinanceOpenItemAgingQuery, FinanceOpenItemAgingSummary, FinanceOpenItemPosition, FinanceOpenItemScope } from './contracts/OpenItemContract.js';
|
|
4
4
|
import type { FinanceOpenItemReconciliationInput, FinanceOpenItemReconciliationSummary } from './contracts/ReconciliationContract.js';
|
|
5
5
|
import type { FinanceCashBankMovementEntry, FinanceCashBankMovementScope, FinanceCashBankMovementSummary } from './contracts/CashMovementContract.js';
|
|
6
|
+
import type { FinanceAuditTrailEntry, FinanceAuditTrailScope } from './contracts/AuditTrailContract.js';
|
|
6
7
|
import type { FiscalPeriod, TrialBalanceRow, FinanceLedgerScope } from './contracts/FiscalContract.js';
|
|
7
8
|
import type { RapbPlan, CreateRapbInput, RapbVariance } from './contracts/BudgetContract.js';
|
|
8
9
|
interface LedgerAccumulator {
|
|
@@ -15,6 +16,7 @@ export interface OffinanceCoreState {
|
|
|
15
16
|
journals: Map<string, FinanceJournalEntry>;
|
|
16
17
|
balances: Map<string, LedgerAccumulator>;
|
|
17
18
|
rapbPlans: Map<string, RapbPlan>;
|
|
19
|
+
auditTrail: FinanceAuditTrailEntry[];
|
|
18
20
|
}
|
|
19
21
|
export declare class OffinanceCore {
|
|
20
22
|
private readonly state;
|
|
@@ -35,6 +37,7 @@ export declare class OffinanceCore {
|
|
|
35
37
|
reconcileOpenItems(input: FinanceOpenItemReconciliationInput): FinanceOpenItemReconciliationSummary;
|
|
36
38
|
listCashBankMovements(scope: FinanceCashBankMovementScope): FinanceCashBankMovementEntry[];
|
|
37
39
|
summarizeCashBankMovements(scope: FinanceCashBankMovementScope): FinanceCashBankMovementSummary;
|
|
40
|
+
listFinancialAuditTrail(scope?: FinanceAuditTrailScope): FinanceAuditTrailEntry[];
|
|
38
41
|
private assertJournalLinesKnownAccounts;
|
|
39
42
|
private assertJournalPeriodOpen;
|
|
40
43
|
private findPeriodByDate;
|
|
@@ -48,5 +51,7 @@ export declare class OffinanceCore {
|
|
|
48
51
|
approvedBy: string;
|
|
49
52
|
}): RapbPlan;
|
|
50
53
|
evaluateVariance(rapbId: string): RapbVariance;
|
|
54
|
+
private recordAuditTrail;
|
|
55
|
+
private matchesAuditScope;
|
|
51
56
|
}
|
|
52
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
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { ResponseEnvelope } from 'ofcore';
|
|
2
2
|
import type { FinanceLedgerScope } from './FiscalContract.js';
|
|
3
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';
|
|
4
6
|
export interface FinanceCashBankMovementScope extends FinanceLedgerScope {
|
|
5
7
|
trackedAccountIds: string[];
|
|
6
8
|
}
|
|
@@ -15,7 +17,11 @@ export interface FinanceCashBankMovementEntry {
|
|
|
15
17
|
evidenceRef?: string;
|
|
16
18
|
accountId: string;
|
|
17
19
|
direction: FinanceCashBankMovementDirection;
|
|
20
|
+
movementKind: FinanceCashBankMovementKind;
|
|
21
|
+
lifecycleStatus: FinanceCashBankMovementLifecycleStatus;
|
|
18
22
|
amount: number;
|
|
23
|
+
signedAmount: number;
|
|
24
|
+
sourceJournalId?: string;
|
|
19
25
|
counterpartAccountIds: string[];
|
|
20
26
|
trackedAccountIdsInJournal: string[];
|
|
21
27
|
}
|
|
@@ -25,6 +31,7 @@ export interface FinanceCashBankMovementSummary {
|
|
|
25
31
|
totalTransferIn: number;
|
|
26
32
|
totalTransferOut: number;
|
|
27
33
|
netExternalMovement: number;
|
|
34
|
+
netByTrackedAccountId: Record<string, number>;
|
|
28
35
|
entries: FinanceCashBankMovementEntry[];
|
|
29
36
|
}
|
|
30
37
|
export interface FinanceCashBankMovementServiceContractV2 {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { ResponseEnvelope, ScopeRef } from 'ofcore';
|
|
2
2
|
import type { FinanceOpenItemScope, FinanceOpenItemType } from './OpenItemContract.js';
|
|
3
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';
|
|
4
6
|
export interface FinanceObservedSettlementItem {
|
|
5
7
|
openItemId: string;
|
|
6
8
|
openItemType?: FinanceOpenItemType;
|
|
@@ -13,6 +15,8 @@ export interface FinanceObservedSettlementItem {
|
|
|
13
15
|
export interface FinanceOpenItemReconciliationInput extends FinanceOpenItemScope {
|
|
14
16
|
observations: FinanceObservedSettlementItem[];
|
|
15
17
|
toleranceAmount?: number;
|
|
18
|
+
asOf?: string;
|
|
19
|
+
writeOffPastDueDays?: number;
|
|
16
20
|
}
|
|
17
21
|
export interface FinanceOpenItemReconciliationRow extends ScopeRef {
|
|
18
22
|
financeDomainId?: string;
|
|
@@ -27,7 +31,10 @@ export interface FinanceOpenItemReconciliationRow extends ScopeRef {
|
|
|
27
31
|
observedAmount: number;
|
|
28
32
|
varianceAmount: number;
|
|
29
33
|
status: FinanceReconciliationStatus;
|
|
34
|
+
lifecycleStatus: FinanceReconciliationLifecycleStatus;
|
|
35
|
+
suggestedAction: FinanceReconciliationSuggestedAction;
|
|
30
36
|
reason?: string;
|
|
37
|
+
pastDueDays?: number;
|
|
31
38
|
observedReferences: string[];
|
|
32
39
|
}
|
|
33
40
|
export interface FinanceOpenItemReconciliationSummary {
|
|
@@ -35,6 +42,10 @@ export interface FinanceOpenItemReconciliationSummary {
|
|
|
35
42
|
totalExpectedAmount: number;
|
|
36
43
|
totalObservedAmount: number;
|
|
37
44
|
totalVarianceAmount: number;
|
|
45
|
+
resolvedCount: number;
|
|
46
|
+
unresolvedCount: number;
|
|
47
|
+
exceptionCount: number;
|
|
48
|
+
writeoffCandidateCount: number;
|
|
38
49
|
rows: FinanceOpenItemReconciliationRow[];
|
|
39
50
|
}
|
|
40
51
|
export interface FinanceReconciliationServiceContractV2 {
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export * from './contracts/OpenItemContract.js';
|
|
|
9
9
|
export * from './contracts/ReconciliationContract.js';
|
|
10
10
|
export * from './contracts/ComplianceExportContract.js';
|
|
11
11
|
export * from './contracts/CashMovementContract.js';
|
|
12
|
+
export * from './contracts/AuditTrailContract.js';
|
|
12
13
|
export * from './contracts/FiscalContract.js';
|
|
13
14
|
export * from './contracts/BudgetContract.js';
|
|
14
15
|
export * from './contracts/AdapterContract.js';
|
package/dist/index.esm.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
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 ue=[{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 le(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 me(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 O(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=le(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 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:ue).map(a=>({...a,amount:0,itemCount:0})),r=0;for(let a of n){if(a.outstandingAmount<=0)continue;r+=a.outstandingAmount;let o=me(e.asOf,a.dueAt),i=t.find(c=>{let s=c.minDaysPastDue??Number.NEGATIVE_INFINITY,p=c.maxDaysPastDue??Number.POSITIVE_INFINITY;return o>=s&&o<=p});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 fe(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 ge(n,e){let t=new Map;for(let r of n){fe(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){let r=n.outstandingAmount,a=e?.observedAmount??0,o=a-r;if(!e)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:r,observedAmount:a,varianceAmount:o,status:"missing",reason:"FINANCE_RECONCILIATION_OBSERVATION_MISSING",observedReferences:[]};let i=e.counterpartyRef&&n.counterpartyRef&&e.counterpartyRef!==n.counterpartyRef||e.documentRef&&n.documentRef&&e.documentRef!==n.documentRef,c="matched",s;return i?(c="mismatch",s="FINANCE_RECONCILIATION_METADATA_MISMATCH"):Math.abs(o)<=t?c="matched":o<0?(c="under",s="FINANCE_RECONCILIATION_OBSERVED_UNDER"):o>0&&(c="over",s="FINANCE_RECONCILIATION_OBSERVED_OVER"),{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:r,observedAmount:a,varianceAmount:o,status:c,reason:s,observedReferences:[...e.references]}}function Ae(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",reason:"FINANCE_RECONCILIATION_EXPECTED_ITEM_NOT_FOUND",observedReferences:[...n.references]}}function w(n,e){let t=e.toleranceAmount??0;if(!Number.isFinite(t)||t<0)throw new Error("FINANCE_RECONCILIATION_TOLERANCE_INVALID");let r=ge(e.observations,e.openItemType),a=[];for(let s of n){let p=H(s.openItemId,s.openItemType),f=r.get(p);a.push(ye(s,f,t)),r.delete(p)}for(let s of r.values())a.push(Ae(s,e));a.sort((s,p)=>(s.financeDomainId??"")!==(p.financeDomainId??"")?(s.financeDomainId??"").localeCompare(p.financeDomainId??""):(s.ledgerProfileId??"")!==(p.ledgerProfileId??"")?(s.ledgerProfileId??"").localeCompare(p.ledgerProfileId??""):s.openItemId.localeCompare(p.openItemId));let o=a.reduce((s,p)=>s+p.expectedAmount,0),i=a.reduce((s,p)=>s+p.observedAmount,0),c=a.reduce((s,p)=>s+p.varianceAmount,0);return{openItemType:e.openItemType,totalExpectedAmount:o,totalObservedAmount:i,totalVarianceAmount:c,rows:a}}function be(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 he(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 _(n,e){let t=be(e),r=[];for(let a of n){if(a.status!=="posted"||!he(a,e))continue;let o=a.lines.filter(l=>t.has(l.accountId)&&(l.debit>0||l.credit>0));if(o.length===0)continue;let i=Array.from(new Set(o.map(l=>l.accountId))).sort(),c=Array.from(new Set(a.lines.filter(l=>!t.has(l.accountId)&&(l.debit>0||l.credit>0)).map(l=>l.accountId))).sort(),s=o.some(l=>l.debit>0),p=o.some(l=>l.credit>0),f=i.length>1&&s&&p;for(let l of o)l.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:l.accountId,direction:f?"transfer_in":"in",amount:l.debit,counterpartAccountIds:c,trackedAccountIdsInJournal:i}),l.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:l.accountId,direction:f?"transfer_out":"out",amount:l.credit,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 T(n){let e=0,t=0,r=0,a=0;for(let o of n)o.direction==="in"&&(e+=o.amount),o.direction==="out"&&(t+=o.amount),o.direction==="transfer_in"&&(r+=o.amount),o.direction==="transfer_out"&&(a+=o.amount);return{totalInflow:e,totalOutflow:t,totalTransferIn:r,totalTransferOut:a,netExternalMovement:e-t,entries:n.map(o=>({...o,counterpartAccountIds:[...o.counterpartAccountIds],trackedAccountIdsInJournal:[...o.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}}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),{...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),{...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),O(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),{...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(o=>({...o}))};this.applyLinesToBalance(r.lines);let a={...r,status:"posted",postedAt:t};return this.state.journals.set(e,a),{...a,lines:a.lines.map(o=>({...o}))}}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(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})),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});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(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 w(this.listOpenItems(e),e)}listCashBankMovements(e){return _(this.listJournals(e),e)}summarizeCashBankMovements(e){return T(this.listCashBankMovements(e))}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),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),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(u=>[u.accountId,u])),o=0,i=0,c=0,s=0,p=t.lines.map(u=>{let C=a.get(u.accountId),g=C?.debit??0,y=C?.credit??0,E=g-y;return u.accountType==="revenue"?(o+=u.budgetedCredit-u.budgetedDebit,i+=y-g):u.accountType==="expense"&&(c+=u.budgetedDebit-u.budgetedCredit,s+=g-y),{accountId:u.accountId,accountCode:u.accountCode,accountName:u.accountName,accountType:u.accountType,budgetedDebit:u.budgetedDebit,budgetedCredit:u.budgetedCredit,budgetedNet:u.budgetedNet,actualDebit:g,actualCredit:y,actualNet:E,varianceDebit:g-u.budgetedDebit,varianceCredit:y-u.budgetedCredit,varianceNet:E-u.budgetedNet}}),f=o-c,l=i-s;return{rapbId:e,periodCode:t.periodCode,evaluatedAt:new Date().toISOString(),lines:p,totalBudgetedRevenue:o,totalActualRevenue:i,totalBudgetedExpense:c,totalActualExpense:s,budgetedNetIncome:f,actualNetIncome:l,netVariance:l-f}}};import{CoreRuntime as Re}from"ofcore";import{InMemoryDbAdapter as Pe}from"ofcore";import{asReadonlyStore as Oe,createStore as Fe}from"ofcore";var d={accounts:"ofinance_accounts",periods:"ofinance_periods",journals:"ofinance_journals",journalLines:"ofinance_journal_lines",rapbPlans:"ofinance_rapb_plans",rapbLines:"ofinance_rapb_lines",histories:"ofinance_histories"},Se=[{name:d.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:d.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:d.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:d.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:d.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:d.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:d.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 Se.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 Ce={logInfo(){},logWarn(){},logError(){}};async function L(n,e=Ce){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 m(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 m(await this.legacy.accountService.createAccount(t))}catch(r){return I(r)}},listAccounts:async()=>{try{return m(await this.legacy.accountService.listAccounts())}catch(t){return I(t)}}},this.journalService={createJournalDraft:async t=>{try{return m(await this.legacy.journalService.createJournalDraft(t))}catch(r){return I(r)}},postJournal:async(t,r)=>{try{return m(await this.legacy.journalService.postJournal(t,r))}catch(a){return I(a)}},reverseJournal:async(t,r)=>{try{return m(await this.legacy.journalService.reverseJournal(t,r))}catch(a){return I(a)}},listJournals:async t=>{try{return m(await this.legacy.journalService.listJournals(t))}catch(r){return I(r)}}},this.fiscalService={openFiscalPeriod:async t=>{try{return m(await this.legacy.fiscalService.openFiscalPeriod(t))}catch(r){return I(r)}},closeFiscalPeriod:async t=>{try{return m(await this.legacy.fiscalService.closeFiscalPeriod(t))}catch(r){return I(r)}},listFiscalPeriods:async()=>{try{return m(await this.legacy.fiscalService.listFiscalPeriods())}catch(t){return I(t)}},getTrialBalance:async()=>{try{return m(await this.legacy.fiscalService.getTrialBalance())}catch(t){return I(t)}},getTrialBalanceByScope:async t=>{try{return m(await this.legacy.fiscalService.getTrialBalanceByScope(t))}catch(r){return I(r)}}},this.rapbService={createRapb:async t=>{try{return m(await this.legacy.rapbService.createRapb(t))}catch(r){return I(r)}},getRapb:async t=>{try{return m(await this.legacy.rapbService.getRapb(t))}catch(r){return I(r)}},listRapb:async t=>{try{return m(await this.legacy.rapbService.listRapb(t))}catch(r){return I(r)}},approveRapb:async(t,r)=>{try{return m(await this.legacy.rapbService.approveRapb(t,r))}catch(a){return I(a)}},evaluateVariance:async t=>{try{return m(await this.legacy.rapbService.evaluateVariance(t))}catch(r){return I(r)}}},this.openItemService={listOpenItems:async t=>{try{return m(await this.legacy.openItemService.listOpenItems(t))}catch(r){return I(r)}},getOpenItemAging:async t=>{try{return m(await this.legacy.openItemService.getOpenItemAging(t))}catch(r){return I(r)}}},this.reconciliationService={reconcileOpenItems:async t=>{try{return m(await this.legacy.reconciliationService.reconcileOpenItems(t))}catch(r){return I(r)}}},this.cashMovementService={listCashBankMovements:async t=>{try{return m(await this.legacy.cashMovementService.listCashBankMovements(t))}catch(r){return I(r)}},summarizeCashBankMovements:async t=>{try{return m(await this.legacy.cashMovementService.summarizeCashBankMovements(t))}catch(r){return I(r)}}}}};function $(n){return new J({accountService:n,journalService:n,fiscalService:n,rapbService:n,openItemService:n,reconciliationService:n,cashMovementService:n})}function b(n){return JSON.parse(JSON.stringify(n))}function A(){return new Date().toISOString()}function Ee(n,e){return`${n}:${e}:${Date.now()}:${Math.random().toString(36).slice(2,8)}`}function ve(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}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(d.accounts,e.id);if(t&&!t.deleted)throw new Error("FINANCE_ACCOUNT_ALREADY_EXISTS");if((await this.dbAdapter.query(d.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=A(),o={...b(e),lastModified:a,deleted:!1};return t?await this.dbAdapter.update(d.accounts,e.id,o):await this.dbAdapter.create(d.accounts,o),await this.writeHistory("accounts",e.id,"UPSERT",o),b(e)}async listAccounts(){return(await this.dbAdapter.query(d.accounts,{filters:{field:"deleted",value:!1}})).map(({lastModified:t,deleted:r,...a})=>b(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(d.journals,e.id);if(t&&!t.deleted)throw new Error("JOURNAL_ALREADY_EXISTS");await this.assertJournalLinesKnownAccounts(e.lines),await this.assertJournalPeriodOpen(e),O(e.lines);let r=P(e.lines);if(!r.ok)throw new Error(r.reason??"JOURNAL_INVALID");let a=A(),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(d.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(d.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=A()){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:A()};return await this.dbAdapter.update(d.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(d.journals,{filters:{field:"deleted",value:!1}})).filter(o=>ve(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 w(await this.listOpenItems(e),e)}async listCashBankMovements(e){return _(await this.listJournals(e),e)}async summarizeCashBankMovements(e){return T(await this.listCashBankMovements(e))}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(d.periods,e.id);if(t&&!t.deleted)throw new Error("FISCAL_PERIOD_ALREADY_EXISTS");let r=A(),a={...b(e),status:"open",lastModified:r,deleted:!1};return t?await this.dbAdapter.update(d.periods,e.id,a):await this.dbAdapter.create(d.periods,a),await this.writeHistory("periods",e.id,"UPSERT",a),this.toPeriod(a)}async closeFiscalPeriod(e){let t=await this.dbAdapter.get(d.periods,e);if(!t||t.deleted)throw new Error("FISCAL_PERIOD_NOT_FOUND");let r={...t,status:"closed",lastModified:A()};return await this.dbAdapter.update(d.periods,e,r),await this.writeHistory("periods",e,"UPSERT",r),this.toPeriod(r)}async listFiscalPeriods(){return(await this.dbAdapter.query(d.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(d.rapbPlans,e.id);if(t&&!t.deleted)throw new Error("RAPB_ALREADY_EXISTS");let r=A(),a=[];for(let i=0;i<e.lines.length;i+=1){let c=e.lines[i],s=await this.dbAdapter.get(d.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(d.rapbPlans,o),await this.writeHistory("rapb_plans",e.id,"UPSERT",o);for(let i of a)await this.dbAdapter.create(d.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(d.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(d.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(d.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:A(),approvedBy:a,lastModified:A()};await this.dbAdapter.update(d.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(u=>[u.accountId,u])),o=0,i=0,c=0,s=0,p=t.lines.map(u=>{let C=a.get(u.accountId),g=C?.debit??0,y=C?.credit??0,E=g-y;return u.accountType==="revenue"?(o+=u.budgetedCredit-u.budgetedDebit,i+=y-g):u.accountType==="expense"&&(c+=u.budgetedDebit-u.budgetedCredit,s+=g-y),{accountId:u.accountId,accountCode:u.accountCode,accountName:u.accountName,accountType:u.accountType,budgetedDebit:u.budgetedDebit,budgetedCredit:u.budgetedCredit,budgetedNet:u.budgetedNet,actualDebit:g,actualCredit:y,actualNet:E,varianceDebit:g-u.budgetedDebit,varianceCredit:y-u.budgetedCredit,varianceNet:E-u.budgetedNet}}),f=o-c,l=i-s;return{rapbId:e,periodCode:t.periodCode,evaluatedAt:A(),lines:p,totalBudgetedRevenue:o,totalActualRevenue:i,totalBudgetedExpense:c,totalActualExpense:s,budgetedNetIncome:f,actualNetIncome:l,netVariance:l-f}}async assertJournalLinesKnownAccounts(e){for(let t of e){let r=await this.dbAdapter.get(d.accounts,t.accountId);if(!r||r.deleted)throw new Error("JOURNAL_ACCOUNT_NOT_FOUND")}}async assertJournalPeriodOpen(e){let t=await this.dbAdapter.query(d.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(d.journals,e);if(!t||t.deleted)throw new Error("JOURNAL_NOT_FOUND");return t}async listJournalLines(e){return(await this.dbAdapter.query(d.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(d.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{...b(o),lines:t.map(i=>b(i))}}toPeriod(e){let{lastModified:t,deleted:r,...a}=e;return b(a)}toRapbPlan(e,t){let{lastModified:r,deleted:a,...o}=e;return{...b(o),lines:t.map(({id:i,rapbId:c,lastModified:s,deleted:p,...f})=>b(f))}}async writeHistory(e,t,r,a){let o=a,i={id:Ee(e,t),tableName:e,recordId:t,action:r,changes:b(o),timestamp:A(),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(d.histories,i)}};async function G(n){await L(n);let e=new x(n);return{financeService:$({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)})}}var k=class{constructor(e,t){this.runtime=e;this.runtimeStateStore=t;this.runtimeStore=Oe(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=Re.builder();this.runtimeHooks={};this.runtimeBuilder.withDbAdapter(()=>new Pe)}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=Fe({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 k(r,e)}};function Y(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 h(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 S(n,e){if(!Number.isFinite(n)||n<=0)throw new Error(e)}function z(n,e){S(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(...Y({memoPrefix:"POS sale tax",components:[{accountId:e.taxPayableAccountId,amount:r,direction:"payable",memo:"POS sale tax payable"}]}))}return h(n,i)}function W(n,e){return S(e.principalAmount,"COOP_LOAN_INVALID_PRINCIPAL"),h(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 X(n,e){return S(e.amount,"COOP_SAVING_INVALID_AMOUNT"),h(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 K(n,e){return S(e.amount,"COOP_SAVING_WITHDRAWAL_INVALID_AMOUNT"),h(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 Z(n,e){S(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"}),h(n,o)}function vn(n,e){if(S(e.amount,"COOP_SHU_PARTICIPATION_INVALID_AMOUNT"),!n.evidenceRef?.trim())throw new Error("COOP_SHU_PARTICIPATION_EVIDENCE_REQUIRED");return h(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 ee(n,e){return e?{...n,...e}:{...n}}function v(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 ee(ee(n.scopedMapping.default,e),r)}function ne(n){return v(n)}function te(n){return v(n)}function re(n){return v(n)}function ae(n){return v(n)}function oe(n){return v(n)}function Dn(n,e){let{scopedAccountMapping:t,...r}=e,a=ne({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return z(n,{...r,...a})}function wn(n,e){let{scopedAccountMapping:t,...r}=e,a=te({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return W(n,{...r,...a})}function _n(n,e){let{scopedAccountMapping:t,...r}=e,a=ae({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return X(n,{...r,...a})}function Tn(n,e){let{scopedAccountMapping:t,...r}=e,a=oe({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return K(n,{...r,...a})}function Nn(n,e){let{scopedAccountMapping:t,...r}=e,a=re({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return Z(n,{...r,...a})}function M(n){return!!(n&&typeof n=="object"&&n.error)}function U(n){return n.startsWith("ofinance_")?`offinance_${n.slice(9)}`:n}async function De(n,e,t){let r=await n.accountService.listAccounts();if(M(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(M(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(d.accounts),type:"CREATE",data:o})}}async function ie(n,e,t){return n.query(e,{filters:{and:t}})}async function we(n,e,t){if(!t)return;let r=await ie(n,d.journals,[{field:"id",value:e.id}]),a=await ie(n,d.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(d.journals),type:"CREATE",data:o});for(let o of a)await t({changeId:`offinance:journal-line:${o.id}`,entity:"FinanceJournalLine",table:U(d.journalLines),type:"CREATE",data:o})}function Mn(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 De(t,n.requiredAccounts,a);let o=n.buildJournalDraft(e,r),i=await t.journalService.createJournalDraft(o);if(M(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(M(c))throw new Error(c.error.message||c.error.code||"FINANCE_JOURNAL_POST_FAILED");await we(n.dbAdapter,c.data,a)}}function _e(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+_e(r),0)}function Jn(n){let e=R(n,"revenue"),t=R(n,"expense");return{revenue:e,expense:t,netIncome:e-t}}function kn(n){return{assets:R(n,"asset"),liabilities:R(n,"liability"),equity:R(n,"equity")}}function ce(n){return n.accountType==="revenue"?n.credit-n.debit:n.accountType==="expense"?n.debit-n.credit:0}function Un(n){let e=n.filter(r=>r.accountType==="revenue").reduce((r,a)=>r+Math.max(0,ce(a)),0),t=n.filter(r=>r.accountType==="expense").reduce((r,a)=>r+Math.max(0,ce(a)),0);return{operatingInflow:e,operatingOutflow:t,netOperatingCashflow:e-t}}function Vn(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 Te(n){return Array.isArray(n)?n.length:n&&typeof n=="object"?1:n===null||typeof n>"u"?0:1}function Ne(n){return n==="json"?"application/json":"text/csv"}function Le(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
|
|
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};
|
|
3
3
|
/*! For license information please see index.esm.js.LEGAL.txt */
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";var U=Object.defineProperty;var ye=Object.getOwnPropertyDescriptor;var Ae=Object.getOwnPropertyNames;var be=Object.prototype.hasOwnProperty;var he=(n,e)=>{for(var t in e)U(n,t,{get:e[t],enumerable:!0})},Se=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of Ae(e))!be.call(n,a)&&a!==t&&U(n,a,{get:()=>e[a],enumerable:!(r=ye(e,a))||r.enumerable});return n};var Ce=n=>Se(U({},"__esModule",{value:!0}),n);var mn={};he(mn,{CANONICAL_COA_TEMPLATES:()=>fe,COOP_COA_TEMPLATES:()=>ge,OFINANCE_TABLES:()=>d,OffinanceCore:()=>T,OffinanceEnvelopeService:()=>x,OfinanceRuntimeCore:()=>B,OfinanceRuntimeCoreBuilder:()=>J,applyFinanceDomainEvent:()=>Ie,applyPendingMigrations:()=>N,buildBalanceSheet:()=>ze,buildBudgetVsRealization:()=>sn,buildCashflowBaseline:()=>We,buildClosingJournalDraft:()=>Xe,buildFinanceComplianceExportBundle:()=>ae,buildFinanceExportEnvelope:()=>an,buildFinanceOpenItemAging:()=>F,buildFinanceOperationalComplianceBundle:()=>on,buildFinanceTaxPostingLines:()=>$,buildIncomeStatement:()=>Ye,buildJournalFromCoopLoanDisbursement:()=>Y,buildJournalFromCoopLoanRepayment:()=>X,buildJournalFromCoopSavingDeposit:()=>z,buildJournalFromCoopSavingWithdrawal:()=>W,buildJournalFromCoopShuParticipationManualRecap:()=>Je,buildJournalFromPosSale:()=>G,buildJournalFromScopedCoopLoanDisbursement:()=>je,buildJournalFromScopedCoopLoanRepayment:()=>He,buildJournalFromScopedCoopSavingDeposit:()=>Ue,buildJournalFromScopedCoopSavingWithdrawal:()=>Ve,buildJournalFromScopedPosSale:()=>ke,createCanonicalCoA:()=>un,createCoopCoA:()=>pn,createDbAdapterOfinanceServices:()=>q,createFinanceProjectionSink:()=>$e,createOffinanceEnvelopeService:()=>Q,mapOffinanceErrorToEnvelope:()=>I,projectFinanceCashBankMovements:()=>w,projectFinanceOpenItems:()=>O,reconcileFinanceOpenItems:()=>D,replayFinanceDomainEvents:()=>dn,resolveCoopLoanDisbursementAccountMapping:()=>Z,resolveCoopLoanRepaymentAccountMapping:()=>ee,resolveCoopSavingDepositAccountMapping:()=>ne,resolveCoopSavingWithdrawalAccountMapping:()=>te,resolvePosSaleAccountMapping:()=>K,resolveScopedAccountMapping:()=>C,summarizeFinanceCashBankMovements:()=>_,toOffinanceFailureEnvelope:()=>H,toOffinanceSuccessEnvelope:()=>m,validateCoaIntegrity:()=>ln,validateJournalBalance:()=>R,validateOpenItemLineMetadata:()=>P});module.exports=Ce(mn);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 ve(n,e,t){return n==="receivable"?e-t:t-e}function Re(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 Pe(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 Oe(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 O(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=Re(r,a),i=ve(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=>Oe(r,e)).sort((r,a)=>r.originatedAt!==a.originatedAt?r.originatedAt.localeCompare(a.originatedAt):r.openItemId.localeCompare(a.openItemId))}function F(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=Pe(e.asOf,a.dueAt),i=t.find(c=>{let s=c.minDaysPastDue??Number.NEGATIVE_INFINITY,p=c.maxDaysPastDue??Number.POSITIVE_INFINITY;return o>=s&&o<=p});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 ie(n,e){return`${e??""}::${n}`}function Fe(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 De(n,e){let t=new Map;for(let r of n){Fe(r);let a=r.openItemType??e,o=ie(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 we(n,e,t){let r=n.outstandingAmount,a=e?.observedAmount??0,o=a-r;if(!e)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:r,observedAmount:a,varianceAmount:o,status:"missing",reason:"FINANCE_RECONCILIATION_OBSERVATION_MISSING",observedReferences:[]};let i=e.counterpartyRef&&n.counterpartyRef&&e.counterpartyRef!==n.counterpartyRef||e.documentRef&&n.documentRef&&e.documentRef!==n.documentRef,c="matched",s;return i?(c="mismatch",s="FINANCE_RECONCILIATION_METADATA_MISMATCH"):Math.abs(o)<=t?c="matched":o<0?(c="under",s="FINANCE_RECONCILIATION_OBSERVED_UNDER"):o>0&&(c="over",s="FINANCE_RECONCILIATION_OBSERVED_OVER"),{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:r,observedAmount:a,varianceAmount:o,status:c,reason:s,observedReferences:[...e.references]}}function _e(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",reason:"FINANCE_RECONCILIATION_EXPECTED_ITEM_NOT_FOUND",observedReferences:[...n.references]}}function D(n,e){let t=e.toleranceAmount??0;if(!Number.isFinite(t)||t<0)throw new Error("FINANCE_RECONCILIATION_TOLERANCE_INVALID");let r=De(e.observations,e.openItemType),a=[];for(let s of n){let p=ie(s.openItemId,s.openItemType),f=r.get(p);a.push(we(s,f,t)),r.delete(p)}for(let s of r.values())a.push(_e(s,e));a.sort((s,p)=>(s.financeDomainId??"")!==(p.financeDomainId??"")?(s.financeDomainId??"").localeCompare(p.financeDomainId??""):(s.ledgerProfileId??"")!==(p.ledgerProfileId??"")?(s.ledgerProfileId??"").localeCompare(p.ledgerProfileId??""):s.openItemId.localeCompare(p.openItemId));let o=a.reduce((s,p)=>s+p.expectedAmount,0),i=a.reduce((s,p)=>s+p.observedAmount,0),c=a.reduce((s,p)=>s+p.varianceAmount,0);return{openItemType:e.openItemType,totalExpectedAmount:o,totalObservedAmount:i,totalVarianceAmount:c,rows:a}}function Te(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 Ne(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 w(n,e){let t=Te(e),r=[];for(let a of n){if(a.status!=="posted"||!Ne(a,e))continue;let o=a.lines.filter(l=>t.has(l.accountId)&&(l.debit>0||l.credit>0));if(o.length===0)continue;let i=Array.from(new Set(o.map(l=>l.accountId))).sort(),c=Array.from(new Set(a.lines.filter(l=>!t.has(l.accountId)&&(l.debit>0||l.credit>0)).map(l=>l.accountId))).sort(),s=o.some(l=>l.debit>0),p=o.some(l=>l.credit>0),f=i.length>1&&s&&p;for(let l of o)l.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:l.accountId,direction:f?"transfer_in":"in",amount:l.debit,counterpartAccountIds:c,trackedAccountIdsInJournal:i}),l.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:l.accountId,direction:f?"transfer_out":"out",amount:l.credit,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;for(let o of n)o.direction==="in"&&(e+=o.amount),o.direction==="out"&&(t+=o.amount),o.direction==="transfer_in"&&(r+=o.amount),o.direction==="transfer_out"&&(a+=o.amount);return{totalInflow:e,totalOutflow:t,totalTransferIn:r,totalTransferOut:a,netExternalMovement:e-t,entries:n.map(o=>({...o,counterpartAccountIds:[...o.counterpartAccountIds],trackedAccountIdsInJournal:[...o.trackedAccountIdsInJournal]}))}}var T=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(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),{...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),{...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),{...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(o=>({...o}))};this.applyLinesToBalance(r.lines);let a={...r,status:"posted",postedAt:t};return this.state.journals.set(e,a),{...a,lines:a.lines.map(o=>({...o}))}}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(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})),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});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(r=>({...r}))})).sort((t,r)=>t.occurredAt.localeCompare(r.occurredAt))}listOpenItems(e){return O(this.listJournals(e),e)}getOpenItemAging(e){return F(this.listOpenItems(e),e)}reconcileOpenItems(e){return D(this.listOpenItems(e),e)}listCashBankMovements(e){return w(this.listJournals(e),e)}summarizeCashBankMovements(e){return _(this.listCashBankMovements(e))}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),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),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(u=>[u.accountId,u])),o=0,i=0,c=0,s=0,p=t.lines.map(u=>{let E=a.get(u.accountId),g=E?.debit??0,y=E?.credit??0,v=g-y;return u.accountType==="revenue"?(o+=u.budgetedCredit-u.budgetedDebit,i+=y-g):u.accountType==="expense"&&(c+=u.budgetedDebit-u.budgetedCredit,s+=g-y),{accountId:u.accountId,accountCode:u.accountCode,accountName:u.accountName,accountType:u.accountType,budgetedDebit:u.budgetedDebit,budgetedCredit:u.budgetedCredit,budgetedNet:u.budgetedNet,actualDebit:g,actualCredit:y,actualNet:v,varianceDebit:g-u.budgetedDebit,varianceCredit:y-u.budgetedCredit,varianceNet:v-u.budgetedNet}}),f=o-c,l=i-s;return{rapbId:e,periodCode:t.periodCode,evaluatedAt:new Date().toISOString(),lines:p,totalBudgetedRevenue:o,totalActualRevenue:i,totalBudgetedExpense:c,totalActualExpense:s,budgetedNetIncome:f,actualNetIncome:l,netVariance:l-f}}};var se=require("ofcore"),de=require("ofcore"),k=require("ofcore");var d={accounts:"ofinance_accounts",periods:"ofinance_periods",journals:"ofinance_journals",journalLines:"ofinance_journal_lines",rapbPlans:"ofinance_rapb_plans",rapbLines:"ofinance_rapb_lines",histories:"ofinance_histories"},Le=[{name:d.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:d.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:d.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:d.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:d.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:d.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:d.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 Le.map(n=>({...n,columns:n.columns.map(e=>({...e}))}))}var ce=[{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 xe={logInfo(){},logWarn(){},logError(){}};async function N(n,e=xe){e.logInfo("[offinance] starting database migration process");let t=[...ce].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 H(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?H(e,n.message||t):H(e,t)}var x=class{constructor(e){this.legacy=e;this.accountService={createAccount:async t=>{try{return m(await this.legacy.accountService.createAccount(t))}catch(r){return I(r)}},listAccounts:async()=>{try{return m(await this.legacy.accountService.listAccounts())}catch(t){return I(t)}}},this.journalService={createJournalDraft:async t=>{try{return m(await this.legacy.journalService.createJournalDraft(t))}catch(r){return I(r)}},postJournal:async(t,r)=>{try{return m(await this.legacy.journalService.postJournal(t,r))}catch(a){return I(a)}},reverseJournal:async(t,r)=>{try{return m(await this.legacy.journalService.reverseJournal(t,r))}catch(a){return I(a)}},listJournals:async t=>{try{return m(await this.legacy.journalService.listJournals(t))}catch(r){return I(r)}}},this.fiscalService={openFiscalPeriod:async t=>{try{return m(await this.legacy.fiscalService.openFiscalPeriod(t))}catch(r){return I(r)}},closeFiscalPeriod:async t=>{try{return m(await this.legacy.fiscalService.closeFiscalPeriod(t))}catch(r){return I(r)}},listFiscalPeriods:async()=>{try{return m(await this.legacy.fiscalService.listFiscalPeriods())}catch(t){return I(t)}},getTrialBalance:async()=>{try{return m(await this.legacy.fiscalService.getTrialBalance())}catch(t){return I(t)}},getTrialBalanceByScope:async t=>{try{return m(await this.legacy.fiscalService.getTrialBalanceByScope(t))}catch(r){return I(r)}}},this.rapbService={createRapb:async t=>{try{return m(await this.legacy.rapbService.createRapb(t))}catch(r){return I(r)}},getRapb:async t=>{try{return m(await this.legacy.rapbService.getRapb(t))}catch(r){return I(r)}},listRapb:async t=>{try{return m(await this.legacy.rapbService.listRapb(t))}catch(r){return I(r)}},approveRapb:async(t,r)=>{try{return m(await this.legacy.rapbService.approveRapb(t,r))}catch(a){return I(a)}},evaluateVariance:async t=>{try{return m(await this.legacy.rapbService.evaluateVariance(t))}catch(r){return I(r)}}},this.openItemService={listOpenItems:async t=>{try{return m(await this.legacy.openItemService.listOpenItems(t))}catch(r){return I(r)}},getOpenItemAging:async t=>{try{return m(await this.legacy.openItemService.getOpenItemAging(t))}catch(r){return I(r)}}},this.reconciliationService={reconcileOpenItems:async t=>{try{return m(await this.legacy.reconciliationService.reconcileOpenItems(t))}catch(r){return I(r)}}},this.cashMovementService={listCashBankMovements:async t=>{try{return m(await this.legacy.cashMovementService.listCashBankMovements(t))}catch(r){return I(r)}},summarizeCashBankMovements:async t=>{try{return m(await this.legacy.cashMovementService.summarizeCashBankMovements(t))}catch(r){return I(r)}}}}};function Q(n){return new x({accountService:n,journalService:n,fiscalService:n,rapbService:n,openItemService:n,reconciliationService:n,cashMovementService:n})}function b(n){return JSON.parse(JSON.stringify(n))}function A(){return new Date().toISOString()}function Me(n,e){return`${n}:${e}:${Date.now()}:${Math.random().toString(36).slice(2,8)}`}function Be(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}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(d.accounts,e.id);if(t&&!t.deleted)throw new Error("FINANCE_ACCOUNT_ALREADY_EXISTS");if((await this.dbAdapter.query(d.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=A(),o={...b(e),lastModified:a,deleted:!1};return t?await this.dbAdapter.update(d.accounts,e.id,o):await this.dbAdapter.create(d.accounts,o),await this.writeHistory("accounts",e.id,"UPSERT",o),b(e)}async listAccounts(){return(await this.dbAdapter.query(d.accounts,{filters:{field:"deleted",value:!1}})).map(({lastModified:t,deleted:r,...a})=>b(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(d.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=A(),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(d.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(d.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=A()){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:A()};return await this.dbAdapter.update(d.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(d.journals,{filters:{field:"deleted",value:!1}})).filter(o=>Be(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 O(await this.listJournals(e),e)}async getOpenItemAging(e){return F(await this.listOpenItems(e),e)}async reconcileOpenItems(e){return D(await this.listOpenItems(e),e)}async listCashBankMovements(e){return w(await this.listJournals(e),e)}async summarizeCashBankMovements(e){return _(await this.listCashBankMovements(e))}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(d.periods,e.id);if(t&&!t.deleted)throw new Error("FISCAL_PERIOD_ALREADY_EXISTS");let r=A(),a={...b(e),status:"open",lastModified:r,deleted:!1};return t?await this.dbAdapter.update(d.periods,e.id,a):await this.dbAdapter.create(d.periods,a),await this.writeHistory("periods",e.id,"UPSERT",a),this.toPeriod(a)}async closeFiscalPeriod(e){let t=await this.dbAdapter.get(d.periods,e);if(!t||t.deleted)throw new Error("FISCAL_PERIOD_NOT_FOUND");let r={...t,status:"closed",lastModified:A()};return await this.dbAdapter.update(d.periods,e,r),await this.writeHistory("periods",e,"UPSERT",r),this.toPeriod(r)}async listFiscalPeriods(){return(await this.dbAdapter.query(d.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(d.rapbPlans,e.id);if(t&&!t.deleted)throw new Error("RAPB_ALREADY_EXISTS");let r=A(),a=[];for(let i=0;i<e.lines.length;i+=1){let c=e.lines[i],s=await this.dbAdapter.get(d.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(d.rapbPlans,o),await this.writeHistory("rapb_plans",e.id,"UPSERT",o);for(let i of a)await this.dbAdapter.create(d.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(d.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(d.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(d.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:A(),approvedBy:a,lastModified:A()};await this.dbAdapter.update(d.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(u=>[u.accountId,u])),o=0,i=0,c=0,s=0,p=t.lines.map(u=>{let E=a.get(u.accountId),g=E?.debit??0,y=E?.credit??0,v=g-y;return u.accountType==="revenue"?(o+=u.budgetedCredit-u.budgetedDebit,i+=y-g):u.accountType==="expense"&&(c+=u.budgetedDebit-u.budgetedCredit,s+=g-y),{accountId:u.accountId,accountCode:u.accountCode,accountName:u.accountName,accountType:u.accountType,budgetedDebit:u.budgetedDebit,budgetedCredit:u.budgetedCredit,budgetedNet:u.budgetedNet,actualDebit:g,actualCredit:y,actualNet:v,varianceDebit:g-u.budgetedDebit,varianceCredit:y-u.budgetedCredit,varianceNet:v-u.budgetedNet}}),f=o-c,l=i-s;return{rapbId:e,periodCode:t.periodCode,evaluatedAt:A(),lines:p,totalBudgetedRevenue:o,totalActualRevenue:i,totalBudgetedExpense:c,totalActualExpense:s,budgetedNetIncome:f,actualNetIncome:l,netVariance:l-f}}async assertJournalLinesKnownAccounts(e){for(let t of e){let r=await this.dbAdapter.get(d.accounts,t.accountId);if(!r||r.deleted)throw new Error("JOURNAL_ACCOUNT_NOT_FOUND")}}async assertJournalPeriodOpen(e){let t=await this.dbAdapter.query(d.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(d.journals,e);if(!t||t.deleted)throw new Error("JOURNAL_NOT_FOUND");return t}async listJournalLines(e){return(await this.dbAdapter.query(d.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(d.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{...b(o),lines:t.map(i=>b(i))}}toPeriod(e){let{lastModified:t,deleted:r,...a}=e;return b(a)}toRapbPlan(e,t){let{lastModified:r,deleted:a,...o}=e;return{...b(o),lines:t.map(({id:i,rapbId:c,lastModified:s,deleted:p,...f})=>b(f))}}async writeHistory(e,t,r,a){let o=a,i={id:Me(e,t),tableName:e,recordId:t,action:r,changes:b(o),timestamp:A(),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(d.histories,i)}};async function q(n){await N(n);let e=new M(n);return{financeService:Q({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)})}}var B=class{constructor(e,t){this.runtime=e;this.runtimeStateStore=t;this.runtimeStore=(0,k.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 de.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,k.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 $(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 h(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 S(n,e){if(!Number.isFinite(n)||n<=0)throw new Error(e)}function G(n,e){S(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(...$({memoPrefix:"POS sale tax",components:[{accountId:e.taxPayableAccountId,amount:r,direction:"payable",memo:"POS sale tax payable"}]}))}return h(n,i)}function Y(n,e){return S(e.principalAmount,"COOP_LOAN_INVALID_PRINCIPAL"),h(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 z(n,e){return S(e.amount,"COOP_SAVING_INVALID_AMOUNT"),h(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 W(n,e){return S(e.amount,"COOP_SAVING_WITHDRAWAL_INVALID_AMOUNT"),h(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){S(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"}),h(n,o)}function Je(n,e){if(S(e.amount,"COOP_SHU_PARTICIPATION_INVALID_AMOUNT"),!n.evidenceRef?.trim())throw new Error("COOP_SHU_PARTICIPATION_EVIDENCE_REQUIRED");return h(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 ue(n,e){return e?{...n,...e}:{...n}}function C(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 ue(ue(n.scopedMapping.default,e),r)}function K(n){return C(n)}function Z(n){return C(n)}function ee(n){return C(n)}function ne(n){return C(n)}function te(n){return C(n)}function ke(n,e){let{scopedAccountMapping:t,...r}=e,a=K({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return G(n,{...r,...a})}function je(n,e){let{scopedAccountMapping:t,...r}=e,a=Z({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return Y(n,{...r,...a})}function Ue(n,e){let{scopedAccountMapping:t,...r}=e,a=ne({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return z(n,{...r,...a})}function Ve(n,e){let{scopedAccountMapping:t,...r}=e,a=te({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return W(n,{...r,...a})}function He(n,e){let{scopedAccountMapping:t,...r}=e,a=ee({tenantId:n.tenantId,branchId:n.branchId,scopedMapping:t});return X(n,{...r,...a})}function j(n){return!!(n&&typeof n=="object"&&n.error)}function re(n){return n.startsWith("ofinance_")?`offinance_${n.slice(9)}`:n}async function Qe(n,e,t){let r=await n.accountService.listAccounts();if(j(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(j(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(d.accounts),type:"CREATE",data:o})}}async function pe(n,e,t){return n.query(e,{filters:{and:t}})}async function qe(n,e,t){if(!t)return;let r=await pe(n,d.journals,[{field:"id",value:e.id}]),a=await pe(n,d.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(d.journals),type:"CREATE",data:o});for(let o of a)await t({changeId:`offinance:journal-line:${o.id}`,entity:"FinanceJournalLine",table:re(d.journalLines),type:"CREATE",data:o})}function $e(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 Qe(t,n.requiredAccounts,a);let o=n.buildJournalDraft(e,r),i=await t.journalService.createJournalDraft(o);if(j(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(j(c))throw new Error(c.error.message||c.error.code||"FINANCE_JOURNAL_POST_FAILED");await qe(n.dbAdapter,c.data,a)}}function Ge(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+Ge(r),0)}function Ye(n){let e=L(n,"revenue"),t=L(n,"expense");return{revenue:e,expense:t,netIncome:e-t}}function ze(n){return{assets:L(n,"asset"),liabilities:L(n,"liability"),equity:L(n,"equity")}}function le(n){return n.accountType==="revenue"?n.credit-n.debit:n.accountType==="expense"?n.debit-n.credit:0}function We(n){let e=n.filter(r=>r.accountType==="revenue").reduce((r,a)=>r+Math.max(0,le(a)),0),t=n.filter(r=>r.accountType==="expense").reduce((r,a)=>r+Math.max(0,le(a)),0);return{operatingInflow:e,operatingOutflow:t,netOperatingCashflow:e-t}}function Xe(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 Ke(n){return Array.isArray(n)?n.length:n&&typeof n=="object"?1:n===null||typeof n>"u"?0:1}function Ze(n){return n==="json"?"application/json":"text/csv"}function en(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
|
|
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}}
|
|
3
3
|
/*! For license information please see index.js.LEGAL.txt */
|
|
@@ -6,6 +6,7 @@ import type { FinanceJournalEntry, JournalDraftInput } from '../contracts/Journa
|
|
|
6
6
|
import type { FinanceOpenItemAgingQuery, FinanceOpenItemAgingSummary, FinanceOpenItemPosition, FinanceOpenItemScope } from '../contracts/OpenItemContract.js';
|
|
7
7
|
import type { FinanceOpenItemReconciliationInput, FinanceOpenItemReconciliationSummary } from '../contracts/ReconciliationContract.js';
|
|
8
8
|
import type { FinanceCashBankMovementEntry, FinanceCashBankMovementScope, FinanceCashBankMovementSummary } from '../contracts/CashMovementContract.js';
|
|
9
|
+
import type { FinanceAuditTrailEntry, FinanceAuditTrailScope } from '../contracts/AuditTrailContract.js';
|
|
9
10
|
export declare class DbAdapterOffinanceService {
|
|
10
11
|
private readonly dbAdapter;
|
|
11
12
|
constructor(dbAdapter: DbAdapter);
|
|
@@ -20,6 +21,7 @@ export declare class DbAdapterOffinanceService {
|
|
|
20
21
|
reconcileOpenItems(input: FinanceOpenItemReconciliationInput): Promise<FinanceOpenItemReconciliationSummary>;
|
|
21
22
|
listCashBankMovements(scope: FinanceCashBankMovementScope): Promise<FinanceCashBankMovementEntry[]>;
|
|
22
23
|
summarizeCashBankMovements(scope: FinanceCashBankMovementScope): Promise<FinanceCashBankMovementSummary>;
|
|
24
|
+
listFinancialAuditTrail(scope?: FinanceAuditTrailScope): Promise<FinanceAuditTrailEntry[]>;
|
|
23
25
|
openFiscalPeriod(period: FiscalPeriod): Promise<FiscalPeriod>;
|
|
24
26
|
closeFiscalPeriod(periodId: string): Promise<FiscalPeriod>;
|
|
25
27
|
listFiscalPeriods(): Promise<FiscalPeriod[]>;
|
|
@@ -41,4 +43,5 @@ export declare class DbAdapterOffinanceService {
|
|
|
41
43
|
private toPeriod;
|
|
42
44
|
private toRapbPlan;
|
|
43
45
|
private writeHistory;
|
|
46
|
+
private toAuditTrailEntry;
|
|
44
47
|
}
|
|
@@ -5,6 +5,7 @@ import type { FinanceJournalServiceContractV2, JournalDraftInput } from '../cont
|
|
|
5
5
|
import type { FinanceOpenItemAgingQuery, FinanceOpenItemServiceContractV2, FinanceOpenItemScope } from '../contracts/OpenItemContract.js';
|
|
6
6
|
import type { FinanceOpenItemReconciliationInput, FinanceReconciliationServiceContractV2 } from '../contracts/ReconciliationContract.js';
|
|
7
7
|
import type { FinanceCashBankMovementScope, FinanceCashBankMovementServiceContractV2 } from '../contracts/CashMovementContract.js';
|
|
8
|
+
import type { FinanceAuditTrailScope, FinanceAuditTrailServiceContractV2 } from '../contracts/AuditTrailContract.js';
|
|
8
9
|
export interface OffinanceLegacyServices {
|
|
9
10
|
accountService: {
|
|
10
11
|
createAccount(account: FinanceAccount): FinanceAccount | Promise<FinanceAccount>;
|
|
@@ -43,6 +44,9 @@ export interface OffinanceLegacyServices {
|
|
|
43
44
|
listCashBankMovements(scope: FinanceCashBankMovementScope): any[] | Promise<any[]>;
|
|
44
45
|
summarizeCashBankMovements(scope: FinanceCashBankMovementScope): any | Promise<any>;
|
|
45
46
|
};
|
|
47
|
+
auditTrailService: {
|
|
48
|
+
listFinancialAuditTrail(scope?: FinanceAuditTrailScope): any[] | Promise<any[]>;
|
|
49
|
+
};
|
|
46
50
|
}
|
|
47
51
|
export interface OffinanceEnvelopeServices {
|
|
48
52
|
accountService: FinanceAccountServiceContractV2;
|
|
@@ -52,6 +56,7 @@ export interface OffinanceEnvelopeServices {
|
|
|
52
56
|
openItemService: FinanceOpenItemServiceContractV2;
|
|
53
57
|
reconciliationService: FinanceReconciliationServiceContractV2;
|
|
54
58
|
cashMovementService: FinanceCashBankMovementServiceContractV2;
|
|
59
|
+
auditTrailService: FinanceAuditTrailServiceContractV2;
|
|
55
60
|
}
|
|
56
61
|
export declare class OffinanceEnvelopeService implements OffinanceEnvelopeServices {
|
|
57
62
|
private readonly legacy;
|
|
@@ -62,6 +67,7 @@ export declare class OffinanceEnvelopeService implements OffinanceEnvelopeServic
|
|
|
62
67
|
readonly openItemService: FinanceOpenItemServiceContractV2;
|
|
63
68
|
readonly reconciliationService: FinanceReconciliationServiceContractV2;
|
|
64
69
|
readonly cashMovementService: FinanceCashBankMovementServiceContractV2;
|
|
70
|
+
readonly auditTrailService: FinanceAuditTrailServiceContractV2;
|
|
65
71
|
constructor(legacy: OffinanceLegacyServices);
|
|
66
72
|
}
|
|
67
73
|
export declare function createOffinanceEnvelopeService(legacyService: {
|
|
@@ -88,4 +94,5 @@ export declare function createOffinanceEnvelopeService(legacyService: {
|
|
|
88
94
|
reconcileOpenItems(input: FinanceOpenItemReconciliationInput): any | Promise<any>;
|
|
89
95
|
listCashBankMovements(scope: FinanceCashBankMovementScope): any[] | Promise<any[]>;
|
|
90
96
|
summarizeCashBankMovements(scope: FinanceCashBankMovementScope): any | Promise<any>;
|
|
97
|
+
listFinancialAuditTrail(scope?: FinanceAuditTrailScope): any[] | Promise<any[]>;
|
|
91
98
|
}): OffinanceEnvelopeServices;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "offinance-shared-core",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
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.
|
|
44
|
+
"ofcore": "0.2.0-alpha.2"
|
|
45
45
|
},
|
|
46
46
|
"repository": {
|
|
47
47
|
"type": "git",
|