UNPKG

@pingleware/bestbooks-reports

Version:

Reports module for BestBooks Accounting Application Framework

150 lines (127 loc) 5.8 kB
"use strict" const BaseReport = require('./report'); const {format, array2xml} = require('./formatReport'); const os = require('os'); const fs = require('fs'); const path = require('path'); class IncomeStatement extends BaseReport { constructor() { super(); } saveReport(name, contents, type="xml",callback=null){ const filePath = path.join(os.homedir(),`.bestbooks/${name}.${type}`); // the xslt-processor does not support the XSLT syntax xsl:for-each-group, // so the XML generated is returned, // using a free tool like https://xslttest.appspot.com/, // to copy the .bestbooks/balance-sheet.xslt and .bestbooks/balance-sheet.xml // to render a HTML // TODO: implement xsl:for-each-group. callback(format("balanceSheet",formattedData)); fs.writeFileSync(filePath, contents); callback(filePath) } async saveReportSync(name, html, type) { return new Promise((resolve,reject) => { try { this.saveReport(name, html, type, function(filePath){ resolve(filePath); }) } catch(error) { reject(error); } }) } async formatHtml(template,formattedData) { return format(template,formattedData); } async formatXml(template,contents) { return array2xml(template,contents); } async formatArray(data,notes) { var _data = { date: new Date().toDateString(), lineItems: [], geographies: [], totalIncome: 0, totalExpense: 0, netIncome: 0 }; let totalIncome = 0; let totalExpense = 0; var lineItems = []; var geographies = []; let totalLineItems = 0; data.forEach(function(lineItem){ lineItem.code = lineItem.account_code; lineItem.name = lineItem.account_name; switch(lineItem.type) { case 'Expense': lineItem.balance = lineItem.total_expense; lineItems.push(lineItem); totalExpense += Number(lineItem.total_expense); totalLineItems++; if (lineItem.region) { if (typeof geographies[lineItem.region] === "undefined") { geographies[lineItem.region] = {}; // Initialize as an object } if (typeof geographies[lineItem.region][lineItem.location] === "undefined") { geographies[lineItem.region][lineItem.location] = 0; } geographies[lineItem.region][lineItem.location]++; } break; case 'Income': lineItem.balance = lineItem.total_revenue; lineItems.push(lineItem); totalIncome += Number(lineItem.total_revenue); totalLineItems++; if (lineItem.region) { if (typeof geographies[lineItem.region] === "undefined") { geographies[lineItem.region] = {}; // Initialize as an object } if (typeof geographies[lineItem.region][lineItem.location] === "undefined") { geographies[lineItem.region][lineItem.location] = 0; } geographies[lineItem.region][lineItem.location]++; } break; case 'Revenue': lineItem.type = "Income"; lineItem.balance = lineItem.total_revenue; lineItems.push(lineItem); totalIncome += Number(lineItem.total_revenue); totalLineItems++; if (lineItem.region) { if (typeof geographies[lineItem.region] === "undefined") { geographies[lineItem.region] = {}; // Initialize as an object } if (typeof geographies[lineItem.region][lineItem.location] === "undefined") { geographies[lineItem.region][lineItem.location] = 0; } geographies[lineItem.region][lineItem.location]++; } break; } }); for (const region in geographies) { for (const location in geographies[region]) { const percent = (Number(geographies[region][location] / totalLineItems) * 100).toFixed(0); geographies[region][location] = Number(percent); } } let netIncome = Number(totalIncome - totalExpense).toFixed(2); _data.lineItems = { lineitem: lineItems }; _data.geographies = geographies; _data.totalIncome = totalIncome.toFixed(2); _data.totalExpense = totalExpense.toFixed(2); _data.netIncome = netIncome; _data.notes = notes; return _data; } retrieveReportData(startDate,endDate,callback,geographic=false) { callback(this.retrieveReportDataSync(startDate,endDate,geographic)); } async retrieveReportDataSync(startDate,endDate,geographic) { return await this.incomeStatementSync(startDate, endDate, geographic); } } module.exports = IncomeStatement;