173 lines
4.8 KiB
JavaScript
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;
|
|
|
|
|