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 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} 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} 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} 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;