plugin-financials/repositories/BankReconciliationRepository.js
2025-11-03 13:51:33 +02:00

113 lines
3.6 KiB
JavaScript

const BaseFinancialRepository = require('./BaseFinancialRepository');
/**
* Bank Reconciliation Repository
*
* Manages bank reconciliation records and calculations.
*/
class BankReconciliationRepository extends BaseFinancialRepository {
constructor() {
super('pg_fn_bank_reconciliation_records');
}
/**
* Find reconciliations by bank account
* @param {string} bankAccountId - Bank account ID
* @returns {Promise<Array>} Array of reconciliation records
*/
async findByBankAccountId(bankAccountId) {
try {
return await this.findAll({ bank_account_id: bankAccountId });
} catch (error) {
throw error;
}
}
/**
* Create reconciliation record
* @param {Object} reconciliationData - Reconciliation data
* @returns {Promise<Object>} Created reconciliation
*/
async createReconciliation(reconciliationData) {
try {
return await this.create(reconciliationData);
} catch (error) {
throw error;
}
}
/**
* Calculate reconciliation metrics
* @param {string} bankAccountId - Bank account ID
* @param {string} asOfDate - Date as of
* @returns {Promise<Object>} Reconciliation metrics
*/
async calculateReconciliationMetrics(bankAccountId, asOfDate) {
try {
const { bankAccountRepository, bankStatementRepository, transactionRepository, transactionLineRepository } = require('./index');
const { chartOfAccountsRepository } = require('./index');
// Get bank account with ledger account
const bankAccount = await bankAccountRepository.findByIdWithLedger(bankAccountId);
if (!bankAccount) {
throw new Error('Bank account not found');
}
// Get ledger balance from transactions
let ledgerBalance = 0;
if (bankAccount.ledger_account_id) {
const balance = await transactionLineRepository.findAll({
account_id: bankAccount.ledger_account_id
});
for (const line of balance) {
const transaction = await transactionRepository.findById(line.transaction_id);
if (transaction && transaction.transaction_date <= asOfDate) {
ledgerBalance += parseFloat(line.debit_amount || 0) - parseFloat(line.credit_amount || 0);
}
}
}
// Get bank balance
const bankBalance = parseFloat(bankAccount.current_balance || 0);
// Calculate outstanding items
const outstandingDeposits = 0; // TODO: Calculate from unreconciled deposits
const outstandingWithdrawals = 0; // TODO: Calculate from unreconciled withdrawals
const reconciledBalance = bankBalance + outstandingDeposits - outstandingWithdrawals;
return {
ledger_balance: ledgerBalance,
bank_balance: bankBalance,
outstanding_deposits: outstandingDeposits,
outstanding_withdrawals: outstandingWithdrawals,
reconciled_balance: reconciledBalance,
variance: Math.abs(ledgerBalance - reconciledBalance)
};
} catch (error) {
throw new Error(`Failed to calculate reconciliation metrics: ${error.message}`);
}
}
/**
* Approve reconciliation
* @param {string} reconciliationId - Reconciliation ID
* @param {string} userId - User ID who approved
* @returns {Promise<Object>} Updated reconciliation
*/
async approveReconciliation(reconciliationId, userId) {
try {
return await this.updateById(reconciliationId, {
approved_by: userId,
approved_at: new Date(),
updated_at: new Date()
});
} catch (error) {
throw error;
}
}
}
module.exports = BankReconciliationRepository;