-
Notifications
You must be signed in to change notification settings - Fork 105
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(reports): bare-bones aged debtor report
This commit adds the SQL and handlebars template for a bare-bones aged debtor report. It is very plain. The next steps are: 1. Make a report partial with the enterprise header information. This should be readily available to be used in any report. 2. Make a report partials with a "no data" message for tables that do not have any data. 3. Move styles into a central reports.css location.
- Loading branch information
Jonathan Niles
committed
Aug 17, 2016
1 parent
6f34210
commit 9d77b39
Showing
9 changed files
with
239 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
103 changes: 103 additions & 0 deletions
103
server/controllers/finance/reports/agedDebtor.handlebars
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
<head> | ||
<title>{{translate "REPORT.AGED_DEBTORS.TITLE"}}</title> | ||
<link href="{{absolutePath}}/css/bhima-bootstrap.css" rel="stylesheet"> | ||
<link href="{{absolutePath}}/vendor/components-font-awesome/css/font-awesome.css" rel="stylesheet"> | ||
<meta charset="utf-8" /> | ||
<style> | ||
.table-report { | ||
font-size: 0.8em; | ||
} | ||
.table-report > thead > th { | ||
font-size: 1.2em; | ||
} | ||
.table-report > tbody > tr > td, | ||
.table-report > tbody > tr > th, | ||
.table-report > tfoot > tr > td, | ||
.table-report > tfoot > tr > th, | ||
.table-report > thead > tr > th { | ||
padding : 2px; | ||
} | ||
.table-report { | ||
margin-bottom : 0; | ||
} | ||
.table-report > tbody > tr > td, | ||
.table-report > tbody > tr > th { | ||
border: 1px solid #ddd; | ||
} | ||
.table-report > tbody > tr:last-child > td, | ||
.table-report > tbody > tr:last-child > th { | ||
border-bottom:none; | ||
} | ||
.table-report > thead > tr > th { | ||
border-bottom : 1px solid #000; | ||
} | ||
.table-report > tfoot > tr > th { | ||
border-top: 1px solid #000; | ||
} | ||
.clear-borders { | ||
border: none !important; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<main class="container"> | ||
<h4 class="text-center">{{translate "REPORT.AGED_DEBTORS.TITLE"}}</h4> | ||
|
||
<!-- margin is the cell size --> | ||
<section style="margin-right: 120px;"> | ||
<table class="table table-condensed table-report"> | ||
<thead> | ||
<tr class="text-capitalize"> | ||
<th class="text-center">{{translate "TABLE.COLUMNS.NAME"}}</th> | ||
<th class="text-center" style="width:15%">{{translate "FORM.LABELS.ACCOUNT_NUMBER"}}</th> | ||
<th class="text-center">{{translate "REPORT.AGED_DEBTORS.THIRTY_DAYS"}}</th> | ||
<th class="text-center">{{translate "REPORT.AGED_DEBTORS.SIXTY_DAYS"}}</th> | ||
<th class="text-center">{{translate "REPORT.AGED_DEBTORS.NINETY_DAYS"}}</th> | ||
<th class="text-center">{{translate "REPORT.AGED_DEBTORS.OVER_NINETY_DAYS"}}</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
|
||
<!-- print a row for each debtor --> | ||
{{#each debtors}} | ||
<tr> | ||
<th>{{this.name}}</th> | ||
<td class="text-left">{{this.number}}</td> | ||
<td class="text-right">{{currency this.thirty ../metadata.currency_id}}</td> | ||
<td class="text-right">{{currency this.sixty ../metadata.currency_id}}</td> | ||
<td class="text-right">{{currency this.ninety ../metadata.currency_id}}</td> | ||
<td class="text-right">{{currency this.excess ../metadata.currency_id}}</td> | ||
</tr> | ||
{{else}} | ||
<tr> | ||
<td colspan="6" class="text-center clear-borders"> | ||
<i class="fa fa-warning"></i> {{translate "TABLE.COLUMNS.EMPTY"}} | ||
</td> | ||
</tr> | ||
{{/each}} | ||
</tbody> | ||
{{#if aggregates}} | ||
<tfoot> | ||
<tr> | ||
<th colspan="2">{{translate "TABLE.COLUMNS.TOTAL"}}</th> | ||
<th class="text-right">{{currency aggregates.thirty metadata.currency_id}}</th> | ||
<th class="text-right">{{currency aggregates.sixty metadata.currency_id}}</th> | ||
<th class="text-right">{{currency aggregates.ninety metadata.currency_id}}</th> | ||
<th class="text-right">{{currency aggregates.excess metadata.currency_id}}</th> | ||
</tr> | ||
</tfoot> | ||
{{/if}} | ||
</table> | ||
</section> | ||
</main> | ||
</body> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
/** | ||
* @overview agedDebtor | ||
* | ||
* @description | ||
* This report displays the amounts owed by debtor groups broken down by age of | ||
* their debt. The report highlights clients who have long overdue debts, so | ||
* that the administration can send out a recovery service to try and recover | ||
* the owed debt. | ||
* | ||
* The typical age categories are 0-30 days, 30-60 days, 60-90 days, and > 90 | ||
* days. | ||
* | ||
* As usual, the reports are created with a handlebars template and shipped to | ||
* the client as either JSON, HTML, or PDF, depending on the renderer specified | ||
* in the HTTP query string. | ||
*/ | ||
|
||
'use strict'; | ||
|
||
const _ = require('lodash'); | ||
const path = require('path'); | ||
|
||
const db = require('../../../lib/db'); | ||
const BadRequest = require('../../../lib/errors/BadRequest'); | ||
|
||
// group supported renderers | ||
const renderers = { | ||
'json': require('../../../lib/renderers/json'), | ||
'html': require('../../../lib/renderers/html'), | ||
'pdf': require('../../../lib/renderers/pdf'), | ||
}; | ||
|
||
// default rendering parameters | ||
const defaults = { | ||
pageSize: 'A4', | ||
renderer: 'pdf' | ||
}; | ||
|
||
// path to the template to render | ||
const template = path.normalize('./server/controllers/finance/reports/agedDebtor.handlebars'); | ||
|
||
/** | ||
* @method agedDebtorReport | ||
* | ||
* @description | ||
* The HTTP interface which actually creates the report. | ||
*/ | ||
module.exports = function agedDebtorReport(req, res, next) { | ||
|
||
const qs = req.query; | ||
|
||
// choose the renderer | ||
const renderer = renderers[qs.renderer || defaults.renderer]; | ||
if (_.isUndefined(renderer)) { | ||
return next(new BadRequest(`The application does not support rendering ${qs.renderer}.`)); | ||
} | ||
|
||
// data to be passed to the report | ||
const data = { | ||
metadata : { | ||
timestamp : new Date(), | ||
currency_id : req.session.enterprise.currency_id | ||
} | ||
}; | ||
|
||
// make sure the language is set appropriately | ||
const context = { lang : qs.lang }; | ||
_.defaults(context, defaults); | ||
|
||
// makes the | ||
const havingNonZeroValues = ' HAVING thirty + sixty + ninety + excess > 0 '; | ||
const includeZeroes = Boolean(Number(qs.zeroes)); | ||
|
||
// selects into columns of 30, 60, 90, and >90 | ||
const debtorSql = ` | ||
SELECT BUID(dg.uuid) AS id, dg.name, a.number, | ||
SUM(IF(DATEDIFF(CURRENT_TIMESTAMP(), gl.trans_date) BETWEEN 0 AND 30, gl.debit_equiv - gl.credit_equiv, 0)) AS thirty, | ||
SUM(IF(DATEDIFF(CURRENT_TIMESTAMP(), gl.trans_date) BETWEEN 30 AND 60, gl.debit_equiv - gl.credit_equiv, 0)) AS sixty, | ||
SUM(IF(DATEDIFF(CURRENT_TIMESTAMP(), gl.trans_date) BETWEEN 60 AND 90, gl.debit_equiv - gl.credit_equiv, 0)) AS ninety, | ||
SUM(IF(DATEDIFF(CURRENT_TIMESTAMP(), gl.trans_date) > 90, gl.debit_equiv - gl.credit_equiv, 0)) AS excess | ||
FROM debtor_group AS dg JOIN debtor AS d ON dg.uuid = d.group_uuid | ||
LEFT JOIN general_ledger AS gl ON gl.entity_uuid = d.uuid | ||
JOIN account AS a ON a.id = dg.account_id | ||
GROUP BY dg.uuid | ||
${includeZeroes ? '' : havingNonZeroValues} | ||
ORDER BY dg.name; | ||
`; | ||
|
||
// aggregates the data above as totals into columns of 30, 60, 90, and >90 | ||
const aggregateSql = ` | ||
SELECT | ||
SUM(IF(DATEDIFF(CURRENT_TIMESTAMP(), gl.trans_date) BETWEEN 0 AND 30, gl.debit_equiv - gl.credit_equiv, 0)) AS thirty, | ||
SUM(IF(DATEDIFF(CURRENT_TIMESTAMP(), gl.trans_date) BETWEEN 30 AND 60, gl.debit_equiv - gl.credit_equiv, 0)) AS sixty, | ||
SUM(IF(DATEDIFF(CURRENT_TIMESTAMP(), gl.trans_date) BETWEEN 60 AND 90, gl.debit_equiv - gl.credit_equiv, 0)) AS ninety, | ||
SUM(IF(DATEDIFF(CURRENT_TIMESTAMP(), gl.trans_date) > 90, gl.debit_equiv - gl.credit_equiv, 0)) AS excess | ||
FROM debtor_group AS dg JOIN debtor AS d ON dg.uuid = d.group_uuid | ||
LEFT JOIN general_ledger AS gl ON gl.entity_uuid = d.uuid | ||
${includeZeroes ? '' : havingNonZeroValues} | ||
`; | ||
|
||
// fire the SQL for the report | ||
db.exec(debtorSql) | ||
.then(function (debtors) { | ||
data.debtors = debtors; | ||
return db.exec(aggregateSql); | ||
}) | ||
.then(aggregates => { | ||
data.aggregates = aggregates[0]; | ||
return renderer.render(data, template, context); | ||
}) | ||
.then(result => { | ||
res.set(renderer.headers).send(result); | ||
}) | ||
.catch(next) | ||
.done(); | ||
|
||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -54,8 +54,6 @@ | |
{{/each}} | ||
</tbody> | ||
</table> | ||
|
||
</div> | ||
</div> | ||
|
||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters