108 lines
4.4 KiB
JavaScript
108 lines
4.4 KiB
JavaScript
const PDFDocument = require('pdfkit');
|
|
const { all, one, parseJson } = require('../db');
|
|
const { annualSchedule, money, monthlyFromAnnual } = require('../depreciation');
|
|
const { assetExportRows, assetFromRow } = require('./assets');
|
|
|
|
function activeRuleSet() {
|
|
const row = one('SELECT * FROM tax_rule_sets WHERE active = 1 ORDER BY effective_date DESC, id DESC LIMIT 1');
|
|
return row ? parseJson(row.rules_json, {}) : {};
|
|
}
|
|
|
|
function depreciationReport(year, bookType) {
|
|
const rules = activeRuleSet();
|
|
const rows = all(`
|
|
SELECT a.*, b.book_type, b.active, b.cost, b.depreciation_method, b.convention, b.useful_life_months AS book_life,
|
|
b.section_179_amount, b.bonus_percent, b.business_use_percent AS book_business_use_percent,
|
|
b.investment_use_percent AS book_investment_use_percent, b.manual_depreciation, e.name AS entity_name
|
|
FROM assets a
|
|
JOIN asset_books b ON b.asset_id = a.id
|
|
LEFT JOIN entities e ON e.id = a.entity_id
|
|
WHERE b.active = 1 AND b.book_type = ?
|
|
ORDER BY a.asset_id
|
|
`, [bookType]);
|
|
|
|
const reportRows = rows.map((row) => {
|
|
const asset = assetFromRow(row);
|
|
const book = {
|
|
...row,
|
|
useful_life_months: row.book_life,
|
|
business_use_percent: row.book_business_use_percent,
|
|
investment_use_percent: row.book_investment_use_percent
|
|
};
|
|
const schedule = annualSchedule(asset, book, rules, { startYear: year, endYear: year })[0] || {};
|
|
return {
|
|
asset_id: row.asset_id,
|
|
description: row.description,
|
|
entity_name: row.entity_name,
|
|
category: row.category,
|
|
book: bookType,
|
|
method: row.depreciation_method,
|
|
methodLabel: schedule.methodLabel || row.depreciation_method,
|
|
cost: money(row.cost ?? row.acquisition_cost),
|
|
depreciation: money(schedule.depreciation || 0),
|
|
accumulated: money(schedule.accumulated || 0),
|
|
net_book_value: money(schedule.netBookValue ?? row.acquisition_cost)
|
|
};
|
|
});
|
|
|
|
return {
|
|
year,
|
|
book: bookType,
|
|
totals: {
|
|
cost: money(reportRows.reduce((sum, row) => sum + row.cost, 0)),
|
|
depreciation: money(reportRows.reduce((sum, row) => sum + row.depreciation, 0)),
|
|
accumulated: money(reportRows.reduce((sum, row) => sum + row.accumulated, 0)),
|
|
netBookValue: money(reportRows.reduce((sum, row) => sum + row.net_book_value, 0))
|
|
},
|
|
rows: reportRows
|
|
};
|
|
}
|
|
|
|
function monthlyDepreciationReport(year, bookType) {
|
|
const rules = activeRuleSet();
|
|
const assets = all('SELECT * FROM assets ORDER BY asset_id').map(assetFromRow);
|
|
const rows = assets.flatMap((asset) => {
|
|
const book = one('SELECT * FROM asset_books WHERE asset_id = ? AND book_type = ? AND active = 1', [asset.id, bookType]);
|
|
if (!book) return [];
|
|
return annualSchedule(asset, book, rules, { startYear: year, endYear: year }).flatMap(monthlyFromAnnual);
|
|
});
|
|
const months = Array.from({ length: 12 }, (_, index) => {
|
|
const month = index + 1;
|
|
return {
|
|
month,
|
|
depreciation: money(rows.filter((row) => row.month === month).reduce((sum, row) => sum + row.depreciation, 0))
|
|
};
|
|
});
|
|
return { year, book: bookType, months };
|
|
}
|
|
|
|
function writeDepreciationPdf(res, year, book) {
|
|
const rows = assetExportRows();
|
|
const doc = new PDFDocument({ margin: 36, size: 'LETTER' });
|
|
res.setHeader('Content-Type', 'application/pdf');
|
|
res.setHeader('Content-Disposition', `attachment; filename="mixedassets-${book}-${year}.pdf"`);
|
|
doc.pipe(res);
|
|
doc.fontSize(18).text('MixedAssets Depreciation Report');
|
|
doc.fontSize(10).text(`Book: ${book} Year: ${year} Generated: ${new Date().toLocaleString()}`);
|
|
doc.moveDown();
|
|
doc.fontSize(9).text('Asset ID', 36, doc.y, { continued: true, width: 80 });
|
|
doc.text('Description', 100, doc.y, { continued: true, width: 210 });
|
|
doc.text('Category', 300, doc.y, { continued: true, width: 110 });
|
|
doc.text('Cost', 430, doc.y, { align: 'right' });
|
|
doc.moveDown(0.5);
|
|
rows.slice(0, 80).forEach((row) => {
|
|
doc.text(row.asset_id, 36, doc.y, { continued: true, width: 80 });
|
|
doc.text(String(row.description).slice(0, 36), 100, doc.y, { continued: true, width: 210 });
|
|
doc.text(String(row.category).slice(0, 20), 300, doc.y, { continued: true, width: 110 });
|
|
doc.text(money(row.acquisition_cost).toLocaleString(), 430, doc.y, { align: 'right' });
|
|
});
|
|
doc.end();
|
|
}
|
|
|
|
module.exports = {
|
|
activeRuleSet,
|
|
depreciationReport,
|
|
monthlyDepreciationReport,
|
|
writeDepreciationPdf
|
|
};
|