765 lines
22 KiB
JavaScript
765 lines
22 KiB
JavaScript
// node_api/jobs/depreciationDatabase.js
|
|
const { Pool } = require('pg');
|
|
const { logger } = require('../utils/logger');
|
|
|
|
class DepreciationDatabase {
|
|
constructor() {
|
|
this.pool = new Pool({
|
|
host: process.env.DB_HOST || 'localhost',
|
|
port: process.env.DB_PORT || 5432,
|
|
database: process.env.DB_DATABASE || 'directus',
|
|
user: process.env.DB_USERNAME || 'directus',
|
|
password: process.env.DB_PASSWORD || 'directus',
|
|
max: 10,
|
|
idleTimeoutMillis: 30000,
|
|
connectionTimeoutMillis: 2000,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get all assets eligible for depreciation
|
|
*/
|
|
async getAssetsForDepreciation(calculationDate = new Date()) {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
const query = `
|
|
SELECT
|
|
a.id,
|
|
a.name,
|
|
a.acquisition_cost,
|
|
a.acquisition_date,
|
|
a.depreciation_method,
|
|
a.depreciation_percentage_rate,
|
|
a.expected_useful_life_months,
|
|
a.salvage_value,
|
|
a.total_accumulated_depreciation,
|
|
a.net_book_value,
|
|
a.status,
|
|
a.expected_total_units,
|
|
a.current_month_units,
|
|
a.organization_id,
|
|
a.date_created,
|
|
a.date_updated
|
|
FROM assets a
|
|
WHERE
|
|
a.status = 'active'
|
|
AND a.acquisition_cost > 0
|
|
AND a.acquisition_date IS NOT NULL
|
|
AND a.acquisition_date <= $1
|
|
AND a.depreciation_method IS NOT NULL
|
|
AND (
|
|
a.total_accumulated_depreciation IS NULL
|
|
OR a.total_accumulated_depreciation < (a.acquisition_cost - COALESCE(a.salvage_value, 0))
|
|
)
|
|
ORDER BY a.acquisition_date ASC
|
|
`;
|
|
|
|
const result = await client.query(query, [calculationDate]);
|
|
|
|
logger.depreciation(`Found ${result.rows.length} assets eligible for depreciation`, {
|
|
calculationDate,
|
|
assetCount: result.rows.length
|
|
});
|
|
|
|
return result.rows;
|
|
} catch (error) {
|
|
logger.error('Error fetching assets for depreciation:', error);
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the last depreciation record for an asset
|
|
*/
|
|
async getLastDepreciationRecord(assetId) {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
const query = `
|
|
SELECT *
|
|
FROM asset_depreciation_records
|
|
WHERE asset_id = $1
|
|
ORDER BY depreciation_date DESC
|
|
LIMIT 1
|
|
`;
|
|
|
|
const result = await client.query(query, [assetId]);
|
|
return result.rows[0] || null;
|
|
} catch (error) {
|
|
logger.error(`Error fetching last depreciation record for asset ${assetId}:`, error);
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if depreciation record exists for asset and date
|
|
*/
|
|
async depreciationRecordExists(assetId, depreciationDate) {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
const query = `
|
|
SELECT COUNT(*) as count
|
|
FROM asset_depreciation_records
|
|
WHERE asset_id = $1
|
|
AND DATE_TRUNC('month', depreciation_date) = DATE_TRUNC('month', $2)
|
|
`;
|
|
|
|
const result = await client.query(query, [assetId, depreciationDate]);
|
|
return parseInt(result.rows[0].count) > 0;
|
|
} catch (error) {
|
|
logger.error(`Error checking depreciation record existence:`, error);
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a new depreciation record
|
|
*/
|
|
async createDepreciationRecord(depreciationData) {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
await client.query('BEGIN');
|
|
|
|
const {
|
|
asset_id,
|
|
depreciation_date,
|
|
depreciation_method,
|
|
monthly_depreciation,
|
|
accumulated_depreciation_before,
|
|
accumulated_depreciation_after,
|
|
net_book_value_before,
|
|
net_book_value_after,
|
|
calculation_details
|
|
} = depreciationData;
|
|
|
|
// Insert depreciation record
|
|
const insertQuery = `
|
|
INSERT INTO asset_depreciation_records (
|
|
id,
|
|
asset_id,
|
|
depreciation_date,
|
|
depreciation_method,
|
|
monthly_depreciation,
|
|
accumulated_depreciation_before,
|
|
accumulated_depreciation_after,
|
|
net_book_value_before,
|
|
net_book_value_after,
|
|
calculation_details,
|
|
date_created,
|
|
date_updated
|
|
) VALUES (
|
|
gen_random_uuid(),
|
|
$1, $2, $3, $4, $5, $6, $7, $8, $9, NOW(), NOW()
|
|
)
|
|
RETURNING id
|
|
`;
|
|
|
|
const insertResult = await client.query(insertQuery, [
|
|
asset_id,
|
|
depreciation_date,
|
|
depreciation_method,
|
|
monthly_depreciation,
|
|
accumulated_depreciation_before,
|
|
accumulated_depreciation_after,
|
|
net_book_value_before,
|
|
net_book_value_after,
|
|
JSON.stringify(calculation_details)
|
|
]);
|
|
|
|
// Update asset's accumulated depreciation and net book value
|
|
const updateAssetQuery = `
|
|
UPDATE assets
|
|
SET
|
|
total_accumulated_depreciation = $1,
|
|
net_book_value = $2,
|
|
date_updated = NOW()
|
|
WHERE id = $3
|
|
`;
|
|
|
|
await client.query(updateAssetQuery, [
|
|
accumulated_depreciation_after,
|
|
net_book_value_after,
|
|
asset_id
|
|
]);
|
|
|
|
await client.query('COMMIT');
|
|
|
|
logger.depreciation(`Created depreciation record for asset ${asset_id}`, {
|
|
recordId: insertResult.rows[0].id,
|
|
assetId: asset_id,
|
|
monthlyDepreciation: monthly_depreciation,
|
|
accumulatedDepreciation: accumulated_depreciation_after
|
|
});
|
|
|
|
return insertResult.rows[0].id;
|
|
} catch (error) {
|
|
await client.query('ROLLBACK');
|
|
logger.error(`Error creating depreciation record:`, error);
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get depreciation summary for a specific period
|
|
*/
|
|
async getDepreciationSummary(startDate, endDate) {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
const query = `
|
|
SELECT
|
|
COUNT(*) as total_assets,
|
|
SUM(monthly_depreciation) as total_monthly_depreciation,
|
|
AVG(monthly_depreciation) as avg_monthly_depreciation,
|
|
MIN(monthly_depreciation) as min_monthly_depreciation,
|
|
MAX(monthly_depreciation) as max_monthly_depreciation,
|
|
depreciation_method,
|
|
COUNT(*) as method_count
|
|
FROM asset_depreciation_records
|
|
WHERE depreciation_date BETWEEN $1 AND $2
|
|
GROUP BY depreciation_method
|
|
ORDER BY method_count DESC
|
|
`;
|
|
|
|
const result = await client.query(query, [startDate, endDate]);
|
|
|
|
const overallQuery = `
|
|
SELECT
|
|
COUNT(*) as total_assets,
|
|
SUM(monthly_depreciation) as total_monthly_depreciation,
|
|
AVG(monthly_depreciation) as avg_monthly_depreciation
|
|
FROM asset_depreciation_records
|
|
WHERE depreciation_date BETWEEN $1 AND $2
|
|
`;
|
|
|
|
const overallResult = await client.query(overallQuery, [startDate, endDate]);
|
|
|
|
return {
|
|
overall: overallResult.rows[0],
|
|
byMethod: result.rows
|
|
};
|
|
} catch (error) {
|
|
logger.error('Error getting depreciation summary:', error);
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get assets with depreciation issues
|
|
*/
|
|
async getDepreciationIssues() {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
const query = `
|
|
SELECT
|
|
a.id,
|
|
a.name,
|
|
a.acquisition_cost,
|
|
a.total_accumulated_depreciation,
|
|
a.net_book_value,
|
|
a.depreciation_method,
|
|
CASE
|
|
WHEN a.total_accumulated_depreciation > a.acquisition_cost THEN 'over_depreciated'
|
|
WHEN a.net_book_value < 0 THEN 'negative_book_value'
|
|
WHEN a.net_book_value != (a.acquisition_cost - COALESCE(a.total_accumulated_depreciation, 0)) THEN 'calculation_mismatch'
|
|
ELSE 'unknown'
|
|
END as issue_type
|
|
FROM assets a
|
|
WHERE
|
|
a.status = 'active'
|
|
AND (
|
|
a.total_accumulated_depreciation > a.acquisition_cost
|
|
OR a.net_book_value < 0
|
|
OR a.net_book_value != (a.acquisition_cost - COALESCE(a.total_accumulated_depreciation, 0))
|
|
)
|
|
ORDER BY a.name
|
|
`;
|
|
|
|
const result = await client.query(query);
|
|
return result.rows;
|
|
} catch (error) {
|
|
logger.error('Error getting depreciation issues:', error);
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fix calculation mismatches
|
|
*/
|
|
async fixCalculationMismatches() {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
await client.query('BEGIN');
|
|
|
|
const updateQuery = `
|
|
UPDATE assets
|
|
SET
|
|
net_book_value = acquisition_cost - COALESCE(total_accumulated_depreciation, 0),
|
|
date_updated = NOW()
|
|
WHERE
|
|
status = 'active'
|
|
AND net_book_value != (acquisition_cost - COALESCE(total_accumulated_depreciation, 0))
|
|
`;
|
|
|
|
const result = await client.query(updateQuery);
|
|
|
|
await client.query('COMMIT');
|
|
|
|
logger.depreciation(`Fixed calculation mismatches for ${result.rowCount} assets`);
|
|
|
|
return result.rowCount;
|
|
} catch (error) {
|
|
await client.query('ROLLBACK');
|
|
logger.error('Error fixing calculation mismatches:', error);
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get monthly depreciation report
|
|
*/
|
|
async getMonthlyDepreciationReport(year, month) {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
const query = `
|
|
SELECT
|
|
a.id,
|
|
a.name,
|
|
a.acquisition_cost,
|
|
dr.monthly_depreciation,
|
|
dr.accumulated_depreciation_before,
|
|
dr.accumulated_depreciation_after,
|
|
dr.net_book_value_before,
|
|
dr.net_book_value_after,
|
|
dr.depreciation_method,
|
|
dr.depreciation_date,
|
|
c.name as category_name,
|
|
l.name as location_name
|
|
FROM asset_depreciation_records dr
|
|
JOIN assets a ON dr.asset_id = a.id
|
|
LEFT JOIN categories c ON a.category_id = c.id
|
|
LEFT JOIN locations l ON a.location_id = l.id
|
|
WHERE
|
|
EXTRACT(YEAR FROM dr.depreciation_date) = $1
|
|
AND EXTRACT(MONTH FROM dr.depreciation_date) = $2
|
|
ORDER BY dr.monthly_depreciation DESC
|
|
`;
|
|
|
|
const result = await client.query(query, [year, month]);
|
|
return result.rows;
|
|
} catch (error) {
|
|
logger.error('Error getting monthly depreciation report:', error);
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get all asset components eligible for depreciation
|
|
*/
|
|
async getAssetComponentsForDepreciation(calculationDate = new Date()) {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
const query = `
|
|
SELECT
|
|
ac.id,
|
|
ac.name,
|
|
ac.component_identifier,
|
|
ac.parent_asset_id,
|
|
ac.acquisition_cost,
|
|
ac.acquisition_date,
|
|
ac.depreciation_method,
|
|
ac.depreciation_percentage_rate,
|
|
ac.expected_useful_life_months,
|
|
ac.salvage_value,
|
|
ac.total_accumulated_depreciation,
|
|
ac.net_book_value,
|
|
ac.status,
|
|
ac.expected_total_units,
|
|
ac.current_month_units,
|
|
ac.organization_id,
|
|
ac.date_created,
|
|
ac.date_updated,
|
|
a.name as parent_asset_name,
|
|
a.asset_identifier as parent_asset_identifier
|
|
FROM asset_components ac
|
|
JOIN assets a ON ac.parent_asset_id = a.id
|
|
WHERE
|
|
ac.status = 'active'
|
|
AND ac.acquisition_cost > 0
|
|
AND ac.acquisition_date IS NOT NULL
|
|
AND ac.acquisition_date <= $1
|
|
AND ac.depreciation_method IS NOT NULL
|
|
AND (
|
|
ac.total_accumulated_depreciation IS NULL
|
|
OR ac.total_accumulated_depreciation < (ac.acquisition_cost - COALESCE(ac.salvage_value, 0))
|
|
)
|
|
ORDER BY ac.acquisition_date ASC
|
|
`;
|
|
|
|
const result = await client.query(query, [calculationDate]);
|
|
|
|
logger.depreciation(`Found ${result.rows.length} asset components eligible for depreciation`, {
|
|
calculationDate,
|
|
componentCount: result.rows.length
|
|
});
|
|
|
|
return result.rows;
|
|
} catch (error) {
|
|
logger.error('Error fetching asset components for depreciation:', error);
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the last depreciation record for an asset component
|
|
*/
|
|
async getLastComponentDepreciationRecord(componentId) {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
const query = `
|
|
SELECT *
|
|
FROM asset_component_depreciation_records
|
|
WHERE component_id = $1
|
|
ORDER BY depreciation_date DESC
|
|
LIMIT 1
|
|
`;
|
|
|
|
const result = await client.query(query, [componentId]);
|
|
return result.rows[0] || null;
|
|
} catch (error) {
|
|
logger.error(`Error fetching last depreciation record for component ${componentId}:`, error);
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if depreciation record exists for component and date
|
|
*/
|
|
async componentDepreciationRecordExists(componentId, depreciationDate) {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
const query = `
|
|
SELECT COUNT(*) as count
|
|
FROM asset_component_depreciation_records
|
|
WHERE component_id = $1
|
|
AND DATE_TRUNC('month', depreciation_date) = DATE_TRUNC('month', $2)
|
|
`;
|
|
|
|
const result = await client.query(query, [componentId, depreciationDate]);
|
|
return parseInt(result.rows[0].count) > 0;
|
|
} catch (error) {
|
|
logger.error(`Error checking component depreciation record existence:`, error);
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a new asset component depreciation record
|
|
*/
|
|
async createComponentDepreciationRecord(depreciationData) {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
await client.query('BEGIN');
|
|
|
|
const {
|
|
component_id,
|
|
asset_id,
|
|
depreciation_date,
|
|
depreciation_method,
|
|
monthly_depreciation,
|
|
accumulated_depreciation_before,
|
|
accumulated_depreciation_after,
|
|
net_book_value_before,
|
|
net_book_value_after,
|
|
calculation_details
|
|
} = depreciationData;
|
|
|
|
// Insert component depreciation record
|
|
const insertQuery = `
|
|
INSERT INTO asset_component_depreciation_records (
|
|
id,
|
|
component_id,
|
|
asset_id,
|
|
depreciation_date,
|
|
depreciation_method,
|
|
monthly_depreciation,
|
|
accumulated_depreciation_before,
|
|
accumulated_depreciation_after,
|
|
net_book_value_before,
|
|
net_book_value_after,
|
|
calculation_details,
|
|
date_created,
|
|
date_updated
|
|
) VALUES (
|
|
gen_random_uuid(),
|
|
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, NOW(), NOW()
|
|
)
|
|
RETURNING id
|
|
`;
|
|
|
|
const insertResult = await client.query(insertQuery, [
|
|
component_id,
|
|
asset_id,
|
|
depreciation_date,
|
|
depreciation_method,
|
|
monthly_depreciation,
|
|
accumulated_depreciation_before,
|
|
accumulated_depreciation_after,
|
|
net_book_value_before,
|
|
net_book_value_after,
|
|
JSON.stringify(calculation_details)
|
|
]);
|
|
|
|
// Update component's accumulated depreciation and net book value
|
|
const updateComponentQuery = `
|
|
UPDATE asset_components
|
|
SET
|
|
total_accumulated_depreciation = $1,
|
|
net_book_value = $2,
|
|
date_updated = NOW()
|
|
WHERE id = $3
|
|
`;
|
|
|
|
await client.query(updateComponentQuery, [
|
|
accumulated_depreciation_after,
|
|
net_book_value_after,
|
|
component_id
|
|
]);
|
|
|
|
await client.query('COMMIT');
|
|
|
|
logger.depreciation(`Created component depreciation record for component ${component_id}`, {
|
|
recordId: insertResult.rows[0].id,
|
|
componentId: component_id,
|
|
assetId: asset_id,
|
|
monthlyDepreciation: monthly_depreciation,
|
|
accumulatedDepreciation: accumulated_depreciation_after
|
|
});
|
|
|
|
return insertResult.rows[0].id;
|
|
} catch (error) {
|
|
await client.query('ROLLBACK');
|
|
logger.error(`Error creating component depreciation record:`, error);
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get asset components with depreciation issues
|
|
*/
|
|
async getComponentDepreciationIssues() {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
const query = `
|
|
SELECT
|
|
ac.id,
|
|
ac.name,
|
|
ac.component_identifier,
|
|
ac.parent_asset_id,
|
|
a.name as parent_asset_name,
|
|
a.asset_identifier as parent_asset_identifier,
|
|
ac.acquisition_cost,
|
|
ac.total_accumulated_depreciation,
|
|
ac.net_book_value,
|
|
ac.depreciation_method,
|
|
CASE
|
|
WHEN ac.total_accumulated_depreciation > ac.acquisition_cost THEN 'over_depreciated'
|
|
WHEN ac.net_book_value < 0 THEN 'negative_book_value'
|
|
WHEN ac.net_book_value != (ac.acquisition_cost - COALESCE(ac.total_accumulated_depreciation, 0)) THEN 'calculation_mismatch'
|
|
ELSE 'unknown'
|
|
END as issue_type
|
|
FROM asset_components ac
|
|
JOIN assets a ON ac.parent_asset_id = a.id
|
|
WHERE
|
|
ac.status = 'active'
|
|
AND (
|
|
ac.total_accumulated_depreciation > ac.acquisition_cost
|
|
OR ac.net_book_value < 0
|
|
OR ac.net_book_value != (ac.acquisition_cost - COALESCE(ac.total_accumulated_depreciation, 0))
|
|
)
|
|
ORDER BY ac.name
|
|
`;
|
|
|
|
const result = await client.query(query);
|
|
return result.rows;
|
|
} catch (error) {
|
|
logger.error('Error getting component depreciation issues:', error);
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fix component calculation mismatches
|
|
*/
|
|
async fixComponentCalculationMismatches() {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
await client.query('BEGIN');
|
|
|
|
const updateQuery = `
|
|
UPDATE asset_components
|
|
SET
|
|
net_book_value = acquisition_cost - COALESCE(total_accumulated_depreciation, 0),
|
|
date_updated = NOW()
|
|
WHERE
|
|
status = 'active'
|
|
AND net_book_value != (acquisition_cost - COALESCE(total_accumulated_depreciation, 0))
|
|
`;
|
|
|
|
const result = await client.query(updateQuery);
|
|
|
|
await client.query('COMMIT');
|
|
|
|
logger.depreciation(`Fixed component calculation mismatches for ${result.rowCount} components`);
|
|
|
|
return result.rowCount;
|
|
} catch (error) {
|
|
await client.query('ROLLBACK');
|
|
logger.error('Error fixing component calculation mismatches:', error);
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get monthly component depreciation report
|
|
*/
|
|
async getMonthlyComponentDepreciationReport(year, month) {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
const query = `
|
|
SELECT
|
|
ac.id,
|
|
ac.name,
|
|
ac.component_identifier,
|
|
ac.parent_asset_id,
|
|
a.name as parent_asset_name,
|
|
a.asset_identifier as parent_asset_identifier,
|
|
ac.acquisition_cost,
|
|
dr.monthly_depreciation,
|
|
dr.accumulated_depreciation_before,
|
|
dr.accumulated_depreciation_after,
|
|
dr.net_book_value_before,
|
|
dr.net_book_value_after,
|
|
dr.depreciation_method,
|
|
dr.depreciation_date,
|
|
c.name as category_name,
|
|
l.name as location_name
|
|
FROM asset_component_depreciation_records dr
|
|
JOIN asset_components ac ON dr.component_id = ac.id
|
|
JOIN assets a ON dr.asset_id = a.id
|
|
LEFT JOIN asset_categories c ON a.category_id = c.id
|
|
LEFT JOIN locations l ON a.location_id = l.id
|
|
WHERE
|
|
EXTRACT(YEAR FROM dr.depreciation_date) = $1
|
|
AND EXTRACT(MONTH FROM dr.depreciation_date) = $2
|
|
ORDER BY dr.monthly_depreciation DESC
|
|
`;
|
|
|
|
const result = await client.query(query, [year, month]);
|
|
return result.rows;
|
|
} catch (error) {
|
|
logger.error('Error getting monthly component depreciation report:', error);
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get component depreciation summary for a period
|
|
*/
|
|
async getComponentDepreciationSummary(startDate, endDate) {
|
|
const client = await this.pool.connect();
|
|
|
|
try {
|
|
const query = `
|
|
SELECT
|
|
COUNT(*) as total_components,
|
|
SUM(monthly_depreciation) as total_monthly_depreciation,
|
|
AVG(monthly_depreciation) as avg_monthly_depreciation,
|
|
MIN(monthly_depreciation) as min_monthly_depreciation,
|
|
MAX(monthly_depreciation) as max_monthly_depreciation,
|
|
depreciation_method,
|
|
COUNT(*) as method_count
|
|
FROM asset_component_depreciation_records
|
|
WHERE depreciation_date BETWEEN $1 AND $2
|
|
GROUP BY depreciation_method
|
|
ORDER BY method_count DESC
|
|
`;
|
|
|
|
const result = await client.query(query, [startDate, endDate]);
|
|
|
|
const overallQuery = `
|
|
SELECT
|
|
COUNT(*) as total_components,
|
|
SUM(monthly_depreciation) as total_monthly_depreciation,
|
|
AVG(monthly_depreciation) as avg_monthly_depreciation
|
|
FROM asset_component_depreciation_records
|
|
WHERE depreciation_date BETWEEN $1 AND $2
|
|
`;
|
|
|
|
const overallResult = await client.query(overallQuery, [startDate, endDate]);
|
|
|
|
return {
|
|
overall: overallResult.rows[0],
|
|
byMethod: result.rows
|
|
};
|
|
} catch (error) {
|
|
logger.error('Error getting component depreciation summary:', error);
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Close database connection pool
|
|
*/
|
|
async close() {
|
|
await this.pool.end();
|
|
logger.info('Database connection pool closed');
|
|
}
|
|
}
|
|
|
|
module.exports = { DepreciationDatabase }; |