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

173 lines
4.8 KiB
JavaScript

const BaseFinancialRepository = require('./BaseFinancialRepository');
const logger = require('../../../src/utils/logger');
/**
* Unit Balance Repository
*
* Manages unit balance tracking for HOA financial management.
* This is CRITICAL for the frontend - the useUnitBalance hook depends on this.
*/
class UnitBalanceRepository extends BaseFinancialRepository {
constructor() {
super('pg_fn_unit_balances');
}
/**
* Find balance for a specific unit
* @param {string} unitId - Unit ID
* @param {string} siteId - Site ID
* @returns {Promise<Object|null>} Unit balance or null
*/
async findByUnitId(unitId, siteId) {
try {
return await this.findOne({ unit_id: unitId, site_id: siteId });
} catch (error) {
logger.error('Error finding unit balance:', error);
throw error;
}
}
/**
* Find balances for multiple units (batch lookup)
* @param {Array<string>} unitIds - Array of unit IDs
* @param {string} siteId - Site ID
* @returns {Promise<Object>} Object with unitId as key and balance as value
*/
async findByMultipleUnitIds(unitIds, siteId) {
try {
const balances = {};
const results = await this.findWhere({
unit_id: { in: unitIds },
site_id: { eq: siteId }
});
// Convert array to object for easy lookup
results.forEach(balance => {
balances[balance.unit_id] = balance;
});
return balances;
} catch (error) {
logger.error('Error finding multiple unit balances:', error);
throw error;
}
}
/**
* Create or update unit balance
* @param {Object} balanceData - Balance data
* @returns {Promise<Object>} Created or updated balance
*/
async createOrUpdateUnitBalance(balanceData) {
try {
const { unit_id, site_id } = balanceData;
const existing = await this.findByUnitId(unit_id, site_id);
if (existing) {
// Update existing balance
return await this.updateById(existing.id, {
...balanceData,
last_updated: new Date().toISOString()
});
} else {
// Create new balance
const balance = {
...balanceData,
created_at: new Date().toISOString()
};
return await this.create(balance);
}
} catch (error) {
logger.error('Error creating/updating unit balance:', error);
throw error;
}
}
/**
* Update current balance for a unit
* @param {string} unitId - Unit ID
* @param {string} siteId - Site ID
* @param {number} newBalance - New balance amount
* @returns {Promise<Object>} Updated balance
*/
async updateCurrentBalance(unitId, siteId, newBalance) {
try {
const existing = await this.findByUnitId(unitId, siteId);
if (!existing) {
throw new Error('Unit balance not found');
}
return await this.updateById(existing.id, {
current_balance: newBalance,
last_updated: new Date().toISOString()
});
} catch (error) {
logger.error('Error updating current balance:', error);
throw error;
}
}
/**
* Calculate unit balance from invoices and payments
* This will be called by the balances route to get REAL balance
* @param {string} unitId - Unit ID
* @param {string} siteId - Site ID
* @returns {Promise<Object>} Balance breakdown
*/
async calculateUnitBalance(unitId, siteId) {
try {
const balanceRecord = await this.findByUnitId(unitId, siteId);
// Balance is now calculated from transactions, not stored
const currentBalance = balanceRecord ? parseFloat(balanceRecord.current_balance) : 0;
return {
unitId,
siteId,
currentBalance,
lastUpdated: balanceRecord ? balanceRecord.last_updated : null
};
} catch (error) {
logger.error('Error calculating unit balance:', error);
throw error;
}
}
/**
* Get all balances for a site
* @param {string} siteId - Site ID
* @returns {Promise<Array>} Array of unit balances
*/
async findBySiteId(siteId) {
try {
return await this.findAll({ site_id: siteId }, { orderBy: 'last_updated', orderDirection: 'desc' });
} catch (error) {
logger.error('Error finding balances by site:', error);
throw error;
}
}
/**
* Reset unit balance
* @param {string} unitId - Unit ID
* @param {string} siteId - Site ID
* @returns {Promise<Object>} Reset balance
*/
async resetBalance(unitId, siteId) {
try {
return await this.createOrUpdateUnitBalance({
unit_id: unitId,
site_id: siteId,
current_balance: 0,
created_by: 'system' // Will be set by route
});
} catch (error) {
logger.error('Error resetting balance:', error);
throw error;
}
}
}
module.exports = UnitBalanceRepository;