113 lines
3.6 KiB
JavaScript
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;
|
|
|