-
Notifications
You must be signed in to change notification settings - Fork 99
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Patients): implement financial activity
This commit implements the patient financial activity bar on the patient edit page. The financial activity gives at a glance the amount of time a patient has been a client of the hospital and their activity over time. It also indicates whether the patient has an outstanding debt or any financial irregularities.
- Loading branch information
Showing
15 changed files
with
498 additions
and
175 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,39 @@ | ||
{"PATIENT_RECORDS":{"TITLE":"Patients", | ||
"UPDATE_PICTURE":"Update Patient Photo", | ||
"UPLOAD_PICTURE":"Upload Patient Photo", | ||
"NOT_FOUND":"Unable to find patient with that ID. Please check with your system administrator.", | ||
"DOB_NOT_SPECIFIED":"Only a year of birth was specified during patient registration. This is an approximate date.", | ||
"CHECK_IN":{"TITLE":"Check In", | ||
"SUBMIT":"Check Patient In", | ||
"NOT_RECENT":"This patient has not recently been checked in, check the patient in to track this hospital visit.", | ||
"ORIGINAL":"This patient has never been checked in.", | ||
"RECENT":"Recent Visits", | ||
"ITEM":"Checked in", | ||
"BY":"by", | ||
"REPORT_TITLE":"Patient Checkin Report", | ||
"SUCCESS":"Patient has been checked in"}, | ||
"VISITS":{"TITLE":"Patient Visits", | ||
"ADMIT":"Admit Patient", | ||
"ADMISSION_DIAGNOSIS":"Admission Diagnosis", | ||
"ADMISSION":"Admission", | ||
"DISCHARGE":"Discharge Patient", | ||
"ORIGINAL":"This patient has no logged visits.", | ||
"RECENT":"Recent Visits", | ||
"IN_PROGRESS":"In Progress", | ||
"SEARCH_INFO":"The input will search for diagnosis after 3 characters have been typed."}, | ||
"FINANCIAL_ACTIVITY":{"ACCOUNT":"Account Number", | ||
"DEBTOR_GROUP":"Debtor Group", | ||
"REPORT_TITLE":"Patient Financial Activity"}, | ||
"STAT_TOTAL_PATIENT":"Total Patients", | ||
"STAT_TOTAL_VISIT":"Total Visits", | ||
"IS_COVERED_BY":"is covered by", | ||
"INVOICE_COVERED_BY":"Invoice covered by", | ||
"STAT_TOTAL_NEW":"New Patients"}} | ||
{ | ||
"PATIENT_RECORDS":{ | ||
"TITLE":"Patients", | ||
"UPDATE_PICTURE":"Update Patient Photo", | ||
"UPLOAD_PICTURE":"Upload Patient Photo", | ||
"NOT_FOUND":"Unable to find patient with that ID. Please check with your system administrator.", | ||
"DOB_NOT_SPECIFIED":"Only a year of birth was specified during patient registration. This is an approximate date.", | ||
"CHECK_IN":{"TITLE":"Check In", | ||
"SUBMIT":"Check Patient In", | ||
"NOT_RECENT":"This patient has not recently been checked in, check the patient in to track this hospital visit.", | ||
"ORIGINAL":"This patient has never been checked in.", | ||
"RECENT":"Recent Visits", | ||
"ITEM":"Checked in", | ||
"BY":"by", | ||
"REPORT_TITLE":"Patient Checkin Report", | ||
"SUCCESS":"Patient has been checked in"}, | ||
"VISITS":{ | ||
"TITLE":"Patient Visits", | ||
"ADMIT":"Admit Patient", | ||
"ADMISSION_DIAGNOSIS":"Admission Diagnosis", | ||
"ADMISSION":"Admission", | ||
"DISCHARGE":"Discharge Patient", | ||
"ORIGINAL":"This patient has no logged visits.", | ||
"RECENT":"Recent Visits", | ||
"IN_PROGRESS":"In Progress", | ||
"SEARCH_INFO":"The input will search for diagnosis after 3 characters have been typed." | ||
}, | ||
"FINANCIAL_ACTIVITY":{ | ||
"ACCOUNT":"Account Number", | ||
"DEBTOR_GROUP":"Debtor Group", | ||
"REPORT_TITLE":"Patient Financial Activity" | ||
}, | ||
"STAT_TOTAL_PATIENT":"Total Patients", | ||
"STAT_TOTAL_VISIT":"Total Visits", | ||
"IS_COVERED_BY":"is covered by", | ||
"INVOICE_COVERED_BY":"Invoice covered by", | ||
"STAT_TOTAL_NEW":"New Patients" | ||
} | ||
} |
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,14 @@ | ||
const bhPanelOverlayTemplate = ` | ||
<div class="panel-overlay"> | ||
<div class="panel-overlay-container"> | ||
<span class="panel-overlay-text" ng-transclude> | ||
</span> | ||
</div> | ||
</div> | ||
`; | ||
|
||
angular.module('bhima.components') | ||
.component('bhPanelOverlay', { | ||
transclude : true, | ||
template : bhPanelOverlayTemplate, | ||
}); |
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,119 @@ | ||
angular.module('bhima.components') | ||
.component('bhPatientFinancialActivity', { | ||
controller : PatientFinancialActivityCtrl, | ||
templateUrl : 'modules/patients/record/bh-patient-financial-activity.html', | ||
bindings : { | ||
patientUuid : '<', | ||
}, | ||
}); | ||
|
||
PatientFinancialActivityCtrl.$inject = [ | ||
'PatientService', 'moment', 'SessionService', 'bhConstants', | ||
]; | ||
|
||
/** | ||
* @function PatientFinancialActivityCtrl | ||
* | ||
* @description | ||
* This component is responsible for giving an overview of the patient's | ||
* financial situation. | ||
*/ | ||
function PatientFinancialActivityCtrl(Patients, moment, Session, Constants) { | ||
const $ctrl = this; | ||
|
||
// TODO(@jniles) - add the ability for users to change this | ||
const EXCESSIVE_DEBT_LIMIT = 250000; // FC (enterprise currency) | ||
const OLD_DEBT_LIMIT = 30; // days | ||
|
||
this.$onInit = () => { | ||
$ctrl.enterpriseCurrencyId = Session.enterprise.currency_id; | ||
angular.merge($ctrl, { EXCESSIVE_DEBT_LIMIT, OLD_DEBT_LIMIT }); | ||
|
||
$ctrl.DATE_FORMAT = Constants.dates.format; | ||
|
||
$ctrl.loading = true; | ||
|
||
Patients.getFinancialActivity($ctrl.patientUuid) | ||
.then(data => { | ||
$ctrl.data = data; | ||
|
||
// indicate that the patient does not have a financial history | ||
$ctrl.noFinancialHistory = data.transactions.length === 0; | ||
|
||
$ctrl.status = calculateFinancialStatus(data.transactions, data.aggregates); | ||
$ctrl.groups = groupFinancialRecords(data.transactions); | ||
|
||
$ctrl.hasWarnings = ( | ||
$ctrl.status.hasExcessiveDebt || | ||
$ctrl.status.hasCreditorBalance || | ||
$ctrl.status.hasOldDebt | ||
); | ||
}) | ||
.finally(() => { | ||
$ctrl.loading = false; | ||
}); | ||
}; | ||
|
||
|
||
/** | ||
* @function calculateFinancialStatus | ||
* | ||
* @description | ||
* | ||
*/ | ||
function calculateFinancialStatus(transactions, totals) { | ||
const hasExcessiveDebt = (totals.balance >= EXCESSIVE_DEBT_LIMIT); | ||
const hasDebtorBalance = (totals.balance > 0); | ||
const hasCreditorBalance = (totals.balance < 0); | ||
|
||
// hasOldDebt checks if there is debt and it is too old | ||
const isOldDebt = (date) => (moment().diff(date, 'days') >= OLD_DEBT_LIMIT); | ||
const hasOldDebt = hasDebtorBalance && isOldDebt(totals.until); | ||
|
||
const isInGoodStanding = !(hasExcessiveDebt || hasOldDebt); | ||
|
||
return { | ||
hasExcessiveDebt, | ||
hasCreditorBalance, | ||
hasOldDebt, | ||
isInGoodStanding, | ||
}; | ||
} | ||
|
||
// returns IV, CP, VO by parsing on the document id | ||
const ident = (record) => record.document.slice(0, 2); | ||
|
||
// make a record object for tracking records | ||
const mkRecord = () => ({ | ||
count : 0, | ||
lastDate : null, | ||
lastUuid : null, | ||
lastAmount : 0, | ||
totalAmount : 0, | ||
}); | ||
|
||
function groupFinancialRecords(transactions) { | ||
// summary of all the types of financial records | ||
const records = { | ||
VO : mkRecord(), | ||
IV : mkRecord(), | ||
CP : mkRecord(), | ||
}; | ||
|
||
transactions.forEach(record => { | ||
const summary = records[ident(record)]; | ||
summary.count++; | ||
summary.lastDate = record.trans_date; | ||
summary.lastUuid = record.record_uuid; | ||
summary.lastAmount = Math.abs(record.balance); | ||
summary.totalAmount += record.balance; | ||
}); | ||
|
||
const isCreditBalance = balance => balance < 0; | ||
records.VO.isCreditBalance = isCreditBalance(records.VO.totalAmount); | ||
records.IV.isCreditBalance = isCreditBalance(records.IV.totalAmount); | ||
records.CP.isCreditBalance = isCreditBalance(records.CP.totalAmount); | ||
|
||
return records; | ||
} | ||
} |
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.