forked from Third-Culture-Software/bhima
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(account): report opening balances
This commit builds a new feature for accounts that can discern their opening balance (from the General Ledger) given a date and account id. The major changes have been added in an "AccountExtra" file that should be merged into accounts/index.js as soon as the major refactoring is finished. This PR consists of two parts: the updated account report that now contains an opening balance and the utility to find the opening balance give a particular date and account_id. Closes Third-Culture-Software#1611. Closes Third-Culture-Software#1636.
- Loading branch information
Showing
7 changed files
with
250 additions
and
90 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,42 +1,41 @@ | ||
{"REPORT":{"ACCOUNT":"Report of Account", | ||
"BALANCE":"Balance Report", | ||
"DOWNLOAD":"Download", | ||
"DELETE":"Delete Report", | ||
"AGED_DEBTORS":{"TITLE":"Aged Debtors"}, | ||
"ZERO_TO_THIRTY_DAYS":"Less Than 30 Days", | ||
"THIRTY_TO_SIXTY_DAYS":"30 to 60 Days", | ||
"SIXTY_TO_NINETY_DAYS":"60 to 90 Days", | ||
"OVER_NINETY_DAYS":"Over 90 Days", | ||
"AGED_CREDITORS":"Aged Debts", | ||
"OPEN_DEBTORS":{"TITLE":"Debtors with Unpaid Debts", | ||
"TREE":"Open Debtors"}, | ||
"CASH_EXPENSE":"Expenses", | ||
"CASH_INCOME":"Incomes", | ||
"CASHFLOW":"Cashflow", | ||
"CASHFLOW_BY_SERVICE":"Cashflow By Service", | ||
"CHART_OF_ACCOUNTS":"Chart of Accounts", | ||
"CLIENTS_REPORT":"Clients Report", | ||
"CLOSING_BALANCE":"Closing Balance", | ||
"CONFIGURATION":"Report Configuration", | ||
"GENERATED":"Generated Report", | ||
"MONTHLY_BALANCE":"Monthly Balance", | ||
"OPENNING_BALANCE":"Opening Balance", | ||
"PERIOD_START":"Start", | ||
"PERIOD_STOP":"Stop", | ||
"PRODUCED_BY":"Produced by", | ||
"PRODUCED_DATE":"Production Date", | ||
"PRODUCED_ON":"Produced on", | ||
"REPORT_ACCOUNTS":"Report accounts", | ||
"INCOME_REPORT":"Incomes Report", | ||
"EXPENSE_REPORT":"Expenses Report", | ||
"INCOME_EXPENSE": "Income Expense Report", | ||
"VIEW_CREDIT_NOTE": "View Credit Note", | ||
"VIEW_INVOICE":"View Invoices", | ||
"VIEW_PATIENT":"View Patient", | ||
"SINCE":"Since", | ||
"VIEW_RECEIPT":"View Receipt", | ||
"VIEW_CREDIT_NOTE":"View Credit Note", | ||
"CLIENTS_REPORT":"Clients Report", | ||
"VIEW_PAYMENTS":"View Cash Payments", | ||
"VIEW_RECEIPT":"View Receipt", | ||
"INCOME_EXPENSE":"Income Expense Report"}} | ||
{ | ||
"REPORT":{ | ||
"ACCOUNT":"Report of Account", | ||
"AGED_CREDITORS":"Aged Debts", | ||
"AGED_DEBTORS":{"TITLE":"Aged Debtors"}, | ||
"BALANCE":"Balance Report", | ||
"CASH_EXPENSE":"Expenses", | ||
"CASHFLOW_BY_SERVICE":"Cashflow By Service", | ||
"CASHFLOW":"Cashflow", | ||
"CASH_INCOME":"Incomes", | ||
"CHART_OF_ACCOUNTS":"Chart of Accounts", | ||
"CLIENTS_REPORT":{"TITLE":"Clients Report", "CURRENT_MVT":"Current Movement", "PREVIOUS_MVT":"Previous Movement"}, | ||
"CLOSING_BALANCE":"Closing Balance", | ||
"CONFIGURATION":"Report Configuration", | ||
"DELETE":"Delete Report", | ||
"DOWNLOAD":"Download", | ||
"EXPENSE_REPORT":"Expenses Report", | ||
"GENERATED":"Generated Report", | ||
"INCOME_EXPENSE": "Income Expense Report", | ||
"INCOME_REPORT":"Incomes Report", | ||
"MONTHLY_BALANCE":"Monthly Balance", | ||
"OPEN_DEBTORS":{ "TITLE":"Debtors with Unpaid Debts", "TREE":"Open Debtors" }, | ||
"OPENING_BALANCE":"Opening Balance", | ||
"OVER_NINETY_DAYS":"Over 90 Days", | ||
"PERIOD_START":"Start", | ||
"PERIOD_STOP":"Stop", | ||
"PRODUCED_BY":"Produced by", | ||
"PRODUCED_DATE":"Production Date", | ||
"PRODUCED_ON":"Produced on", | ||
"REPORT_ACCOUNTS":"Report accounts", | ||
"SINCE":"Since", | ||
"SIXTY_TO_NINETY_DAYS":"60 to 90 Days", | ||
"THIRTY_TO_SIXTY_DAYS":"30 to 60 Days", | ||
"VIEW_CREDIT_NOTE":"View Credit Note", | ||
"VIEW_INVOICE":"View Invoices", | ||
"VIEW_PATIENT":"View Patient", | ||
"VIEW_PAYMENTS":"View Cash Payments", | ||
"VIEW_RECEIPT":"View Receipt", | ||
"ZERO_TO_THIRTY_DAYS":"Less Than 30 Days" | ||
} | ||
} |
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 |
---|---|---|
@@ -1,42 +1,42 @@ | ||
{"REPORT":{"ACCOUNT":"Rapport du Compte", | ||
"BALANCE":"Rapport de la Balance", | ||
"AGED_DEBTORS":{"TITLE":"Balance agée des clients"}, | ||
"ZERO_TO_THIRTY_DAYS":"Moins de 30 jours", | ||
"THIRTY_TO_SIXTY_DAYS":"30 a 60 jours", | ||
"SIXTY_TO_NINETY_DAYS":"60 a 90 jours", | ||
"OVER_NINETY_DAYS":"Plus de 90 jours", | ||
"AGED_CREDITORS":"Balance agée des Créances", | ||
"OPEN_DEBTORS":{"TITLE":"Debiteurs Avec Dettes", | ||
"TREE":"Debiteurs Avec Dettes"}, | ||
"CASH_EXPENSE":"Depenses", | ||
"CASH_INCOME":"Recettes", | ||
"CASHFLOW":"Cashflow", | ||
"CASHFLOW_BY_SERVICE":"Cashflow par Service", | ||
"CHART_OF_ACCOUNTS":"Plan Comptable", | ||
"CLIENTS_REPORT":{"TITLE":"Rapport Clients", | ||
"CURRENT_MVT":"Mouvement Courant", | ||
"PREVIOUS_MVT":"Mouvement Precedent"}, | ||
"CLOSING_BALANCE":"Balance à la cloture", | ||
"CONFIGURATION":"Configuration rapport", | ||
"DELETE":"Supprimer un rapport", | ||
"DOWNLOAD":"Télécharger", | ||
"GENERATED":"Rapport généré", | ||
"INCOME_EXPENSE":"Rapport des recettes et des dépenses", | ||
"MONTHLY_BALANCE":"Balance mensuelle", | ||
"OPENNING_BALANCE":"Balance d'ouverture", | ||
"PERIOD_START":"Debut", | ||
"PERIOD_STOP":"Fin", | ||
"PRODUCED_BY":"Produit par", | ||
"PRODUCED_DATE":"Date de generation", | ||
"PRODUCED_ON":"Produit le", | ||
"REPORT_ACCOUNTS":"Rapport de comptes", | ||
"INCOME_REPORT":"Rapport des recettes", | ||
"EXPENSE_REPORT":"Rapport des dépenses", | ||
"SINCE":"Depuis", | ||
"VIEW_CREDIT_NOTE":"Voir la note de credit", | ||
"VIEW_INVOICE":"Voir les factures", | ||
"VIEW_PATIENT":"Voir le Patient", | ||
"VIEW_RECEIPT":"Voir le document", | ||
"VIEW_PAYMENTS":"Voir les payments", | ||
"VIEW_RECEIPT":"Voir le document", | ||
"VIEW_CREDIT_NOTE":"Voir la note de credit"}} | ||
{ | ||
"REPORT":{ | ||
"ACCOUNT":"Rapport du Compte", | ||
"AGED_CREDITORS":"Balance agée des Créances", | ||
"AGED_DEBTORS":{"TITLE":"Balance agée des clients"}, | ||
"BALANCE":"Rapport de la Balance", | ||
"CASH_EXPENSE":"Depenses", | ||
"CASHFLOW_BY_SERVICE":"Cashflow par Service", | ||
"CASHFLOW":"Cashflow", | ||
"CASH_INCOME":"Recettes", | ||
"CHART_OF_ACCOUNTS":"Plan Comptable", | ||
"CLIENTS_REPORT":{"TITLE":"Rapport Clients", "CURRENT_MVT":"Mouvement Courant", "PREVIOUS_MVT":"Mouvement Precedent"}, | ||
"CLOSING_BALANCE":"Balance à la cloture", | ||
"CONFIGURATION":"Configuration rapport", | ||
"DELETE":"Supprimer un rapport", | ||
"DOWNLOAD":"Télécharger", | ||
"EXPENSE_REPORT":"Rapport des dépenses", | ||
"GENERATED":"Rapport généré", | ||
"INCOME_EXPENSE":"Rapport des recettes et des dépenses", | ||
"INCOME_REPORT":"Rapport des recettes", | ||
"MONTHLY_BALANCE":"Balance mensuelle", | ||
"OPEN_DEBTORS":{"TITLE":"Debiteurs Avec Dettes", "TREE":"Debiteurs Avec Dettes"}, | ||
"OPENING_BALANCE":"Balance d'ouverture", | ||
"OVER_NINETY_DAYS":"Plus de 90 jours", | ||
"PERIOD_START":"Debut", | ||
"PERIOD_STOP":"Fin", | ||
"PRODUCED_BY":"Produit par", | ||
"PRODUCED_DATE":"Date de generation", | ||
"PRODUCED_ON":"Produit le", | ||
"REPORT_ACCOUNTS":"Rapport de comptes", | ||
"SINCE":"Depuis", | ||
"SIXTY_TO_NINETY_DAYS":"60 a 90 jours", | ||
"THIRTY_TO_SIXTY_DAYS":"30 a 60 jours", | ||
"VIEW_CREDIT_NOTE":"Voir la note de credit", | ||
"VIEW_INVOICE":"Voir les factures", | ||
"VIEW_PATIENT":"Voir le Patient", | ||
"VIEW_PAYMENTS":"Voir les payments", | ||
"VIEW_RECEIPT":"Voir le document", | ||
"VIEW_RECEIPT":"Voir le document", | ||
"ZERO_TO_THIRTY_DAYS":"Moins de 30 jours" | ||
} | ||
} |
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,127 @@ | ||
/** | ||
* @overview AccountExtras | ||
* | ||
* @description | ||
* Temporary file to avoid conflicts with changes in accounts/index.js. This will be merged into accounts/index.js. | ||
* It should only be used in the account report. | ||
*/ | ||
|
||
const db = require('../../../lib/db'); | ||
|
||
/** | ||
* @function getFiscalYearForDate | ||
* @private | ||
* | ||
* @description | ||
* Helper method to return the fiscal year associated with a provided date. | ||
* | ||
* @param {Date} date - the sought after JS date | ||
* @returns Promise - promise wrapping an integer fiscalYearId | ||
*/ | ||
function getFiscalYearForDate(date) { | ||
const sql = ` | ||
SELECT id FROM fiscal_year WHERE start_date <= DATE(?) AND end_date >= DATE(?); | ||
`; | ||
|
||
return db.one(sql, [date, date]) | ||
.then(data => data.id); | ||
} | ||
|
||
|
||
/** | ||
* @function getPeriodForDate | ||
* @private | ||
* | ||
* @description | ||
* Helper method to return the period id associated with a given date. | ||
* | ||
* @param {Date} date - the sought after date | ||
* @returns Promise - promise wrapping an integer periodId | ||
*/ | ||
function getPeriodForDate(date) { | ||
const sql = ` | ||
SELECT id FROM period WHERE start_date <= DATE(?) AND end_date >= DATE(?); | ||
`; | ||
|
||
return db.one(sql, [date, date]) | ||
.then(data => data.id); | ||
} | ||
|
||
/** | ||
* @function getPeriodAccountBalanceUntilDate | ||
* @private | ||
* | ||
* @description | ||
* Sums the balance of an account up to just before the given date's period. For example, if the date was provided as | ||
* May 19, 2016, this function would return the account balance at the end of April 30, 2016. This is useful for | ||
* computing opening balances of the period given a date. | ||
* | ||
* @param {Number} accountId - the account_id for the period_total table | ||
* @param {Date} date - the upper limit of the period | ||
* @param {Number} fiscalYearId - the fiscal_year_id for the period_total table | ||
* | ||
* @returns Promise - promise wrapping the balance object | ||
*/ | ||
function getPeriodAccountBalanceUntilDate(accountId, date, fiscalYearId) { | ||
const sql = ` | ||
SELECT SUM(debit - credit) AS balance | ||
FROM period_total JOIN period ON period.id = period_total.period_id | ||
WHERE period_total.account_id = ? | ||
AND period.end_date <= DATE(?) | ||
AND period.fiscal_year_id = ?; | ||
`; | ||
|
||
return db.one(sql, [accountId, date, fiscalYearId]) | ||
.then(data => data.balance); | ||
} | ||
|
||
/** | ||
* @function getComputedAccountBalanceUntilDate | ||
* @private | ||
* | ||
* @description | ||
* Sums general ledger lines hitting an account during a period, up to (and including) the provided date. | ||
*/ | ||
function getComputedAccountBalanceUntilDate(accountId, date, periodId) { | ||
const sql = ` | ||
SELECT SUM(debit_equiv - credit_equiv) AS balance FROM general_ledger | ||
WHERE account_id = ? | ||
AND trans_date <= DATE(?) | ||
AND period_id = ?; | ||
`; | ||
|
||
return db.one(sql, [accountId, date, periodId]) | ||
.then(data => data.balance); | ||
} | ||
|
||
|
||
/** | ||
* @method getOpeningBalanceForDate | ||
* @public | ||
* | ||
* @description | ||
* Query the database for an account's balance as of a start date. Note that the date should be escaped (via new | ||
* Date()) prior to calling this function - this method is expected to does not do any escaping. | ||
* | ||
* @param {Number} accountId - the identifier for the account | ||
* @param {Date} date - the date that the opening balance should be computed through | ||
* @returns {Promise} - promise wrapping the balance of the account | ||
*/ | ||
function getOpeningBalanceForDate(accountId, date) { | ||
let balance = 0; | ||
|
||
return getFiscalYearForDate(date) | ||
.then(fiscalYearId => | ||
getPeriodAccountBalanceUntilDate(accountId, date, fiscalYearId) | ||
) | ||
.then((previousPeriodClosingBalance) => { | ||
balance += previousPeriodClosingBalance; | ||
return getPeriodForDate(date); | ||
}) | ||
.then(periodId => | ||
getComputedAccountBalanceUntilDate(accountId, date, periodId) | ||
) | ||
.then(runningPeriodBalance => (balance + runningPeriodBalance).toFixed(4)); | ||
} | ||
|
||
exports.getOpeningBalanceForDate = getOpeningBalanceForDate; |
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
Oops, something went wrong.