Skip to content

Commit

Permalink
fix(patientInvoice): recover service from cache
Browse files Browse the repository at this point in the history
This commit allows services to be recovered from the cache of the
PatientInvoiceForm.  It also moves the services loading out of the
patient invoice controller and into the service.

Closes #1024.
  • Loading branch information
Jonathan Niles authored and sfount committed Mar 17, 2017
1 parent 594d9d2 commit 5d9b7bd
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 103 deletions.
13 changes: 7 additions & 6 deletions client/src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,7 @@
"MISSING_SALES_ACCOUNT" : "The record contains an inventory item missing a sales account. You cannot make an invoice without a sales account.",
"NOT_CONFIGURED" : "The record is missing an inventory item. Please put in an inventory item or remove the row."
},
"DESCRIPTION" : "Invoice to patient {{ patientName }} ({{ patientReference }} for {{ numItems }} items from service {{ serviceName }}.",
"INVALID_DETAILS" : "This invoice contains invalid details",
"INVALID_ITEMS" : "This invoice contains invalid items",
"PAGE_TITLE" : "Patient Invoice",
Expand Down Expand Up @@ -1603,9 +1604,9 @@
"CREATE_SUCCESS" : "Successfully posted",
"CREATE_ERROR" : "An error occurred when post",
"CREDITOR" : "Creditor (C)",
"DEBTOR" : "Debitor (D)",
"DEBTOR" : "Debtor (D)",
"DEB_CRED" : "Debtor/Creditor",
"DESCRIPTION" : "This Module allows you to make advanced journal transactions manually",
"DESCRIPTION" : "This module allows you to make advanced journal transactions manually",
"ENTITY" : "Entity (Debtor/Creditor)",
"ERROR_ACCOUNT" : "Selected accounts are invalid",
"ERROR_AMOUNT" : "Amount's values are invalid",
Expand Down Expand Up @@ -1662,10 +1663,10 @@
"SINGLE_ROW_TRANSACTION" : "This transaction only has a single row, but two rows are required. Please add one or more lines."
},
"GRAPHS" : {
"PATIENT_REGISTRATIONS" : "Patient Registrations",
"PATIENT_INVOICES" : "Patient Invoices",
"PATIENT_REGISTRATIONS" : "Patient Registrations",
"PATIENT_INVOICES" : "Patient Invoices",
"MEDICINE_DISTRIBUTIONS" : "Medicine Distributions",
"LOGINS" : "Logins",
"PURCHASES" : "Purchases"
"LOGINS" : "Logins",
"PURCHASES" : "Purchases"
}
}
114 changes: 78 additions & 36 deletions client/src/js/services/PatientInvoiceForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ angular.module('bhima.services')

PatientInvoiceFormService.$inject = [
'PatientService', 'PriceListService', 'InventoryService', 'AppCache', 'Store',
'Pool', 'PatientInvoiceItemService', 'bhConstants'
'Pool', 'PatientInvoiceItemService', 'bhConstants', 'ServiceService', '$q',
];

/**
Expand All @@ -18,9 +18,9 @@ PatientInvoiceFormService.$inject = [
* @todo (required) billing services and subsidies should be ignored for
* specific debtors.
*/
function PatientInvoiceFormService(Patients, PriceLists, Inventory, AppCache, Store, Pool, PatientInvoiceItem, Constants) {

function PatientInvoiceFormService(Patients, PriceLists, Inventory, AppCache, Store, Pool, PatientInvoiceItem, Constants, Services, $q) {
var ROW_ERROR_FLAG = Constants.grid.ROW_ERROR_FLAG;
var DEFAULT_SERVICE_IDX = 0;

// Reduce method - assigns the current billing services charge to the billing
// service and adds to the running total
Expand Down Expand Up @@ -59,6 +59,13 @@ function PatientInvoiceFormService(Patients, PriceLists, Inventory, AppCache, St
}, 0);
}

function setDefaultService() {
var hasServices = angular.isDefined(this.services) && this.services.length;

if (hasServices) {
this.setService(this.services[DEFAULT_SERVICE_IDX]);
}
}

/**
* @constructor
Expand All @@ -82,10 +89,19 @@ function PatientInvoiceFormService(Patients, PriceLists, Inventory, AppCache, St

// set up the inventory
// this will be referred to as PatientInvoiceForm.inventory.available.data
this.inventory = new Pool({ identifier: 'uuid', data : [] });
this.inventory = new Pool({ identifier: 'uuid', data: [] });

// set up the services
Services.read()
.then(function (services) {
this.services = services;

// compute the default service once
setDefaultService.call(this);
}.bind(this));

// set up the inventory
Inventory.read(null, { detailed : 1 })
Inventory.read(null, { detailed: 1 })
.then(function (data) {

// make sure both the label and code is searchable
Expand All @@ -98,23 +114,22 @@ function PatientInvoiceFormService(Patients, PriceLists, Inventory, AppCache, St

// setup the rows of the grid as a store
// this will be referred to as PatientInvoiceForm.store.data
this.store = new Store({ identifier : 'uuid', data: [] });
this.store = new Store({ identifier: 'uuid', data: [] });

this.setup();
}

// initial setup and clearing of the invoice
PatientInvoiceForm.prototype.setup = function setup() {

// the invoice details
this.details = {
date : new Date(),
cost : 0,
description : null
date : new Date(),
cost : 0,
description : null,
};

// tracks the price list of the inventory items
this.prices = new Store({ identifier : 'inventory_uuid' });
this.prices = new Store({ identifier: 'inventory_uuid' });

// the recipient is null
this.recipient = null;
Expand All @@ -126,17 +141,16 @@ function PatientInvoiceFormService(Patients, PriceLists, Inventory, AppCache, St
// this object holds the totals for the invoice.
this.totals = {
billingServices : 0,
subsidies : 0,
rows : 0,
grandTotal : 0
subsidies : 0,
rows : 0,
grandTotal : 0,
};

// remove all items from the store as needed
this.clear();

this._valid = false ;
this._valid = false;
this._invalid = true;

// trigger a totals digest
this.digest();
};
Expand Down Expand Up @@ -189,28 +203,36 @@ function PatientInvoiceFormService(Patients, PriceLists, Inventory, AppCache, St
*/
PatientInvoiceForm.prototype.setPatient = function setPatient(patient) {
var invoice = this;
var promises = [];

var billingServicePromise;
var subsidyPromise;
var priceListPromise;

// load the billing services and bind to the invoice
Patients.billingServices(patient.uuid)
.then(function (billingServices) {
invoice.billingServices = billingServices;
invoice.digest();
});
billingServicePromise = Patients.billingServices(patient.uuid)
.then(function (billingServices) {
invoice.billingServices = billingServices;
});

promises.push(billingServicePromise);

// load the subsidies and bind to the invoice
Patients.subsidies(patient.uuid)
.then(function (subsidies) {
invoice.subsidies = subsidies;
invoice.digest();
});
subsidyPromise = Patients.subsidies(patient.uuid)
.then(function (subsidies) {
invoice.subsidies = subsidies;
});

promises.push(subsidyPromise);

// the patient's price list when complete
if (patient.price_list_uuid) {
PriceLists.read(patient.price_list_uuid)
.then(function (priceList) {
invoice.setPriceList(priceList);
invoice.digest();
});
priceListPromise = PriceLists.read(patient.price_list_uuid)
.then(function (priceList) {
invoice.setPriceList(priceList);
});

promises.push(priceListPromise);
}

invoice.recipient = patient;
Expand All @@ -219,6 +241,12 @@ function PatientInvoiceFormService(Patients, PriceLists, Inventory, AppCache, St
// add a single item to the invoice to begin
invoice.addItem();

// once all HTTP requests have returned, re-digest the invoice.
$q.all(promises)
.finally(function () {
invoice.digest();
});

// run validation and calculation
invoice.digest();
};
Expand Down Expand Up @@ -249,6 +277,17 @@ function PatientInvoiceFormService(Patients, PriceLists, Inventory, AppCache, St
this.details.service_id = service.id;
};

/**
* @method updateDescription
*
* @description
* This method updates the description based on the currently selected service
*
*/
PatientInvoiceForm.prototype.updateDescription = function updateDescription() {
// TODO(@jniles)
};


/**
* @method digest
Expand Down Expand Up @@ -313,7 +352,6 @@ function PatientInvoiceFormService(Patients, PriceLists, Inventory, AppCache, St
* configured with inventory items.
*/
PatientInvoiceForm.prototype.addItem = function addItem() {

// we cannot insert more rows than our max inventory size
var maxRows = this.inventory.size();
if (this.store.data.length >= maxRows) {
Expand Down Expand Up @@ -357,15 +395,15 @@ function PatientInvoiceFormService(Patients, PriceLists, Inventory, AppCache, St
* @param {Object} item - the item/row to be configured
*/
PatientInvoiceForm.prototype.configureItem = function configureItem(item) {

// remove the item from the pool
var inventoryItem = this.inventory.use(item.inventory_uuid);
var price;

// configure the PatientPatientInvoiceFormItem with the inventory values
item.configure(inventoryItem);

// apply the price list, if it exists
var price = this.prices.get(item.inventory_uuid);
price = this.prices.get(item.inventory_uuid);
if (angular.isDefined(price)) {
item.applyPriceList(price);
}
Expand All @@ -387,7 +425,6 @@ function PatientInvoiceFormService(Patients, PriceLists, Inventory, AppCache, St
* perform validation and computer totals.
*/
PatientInvoiceForm.prototype.readCache = function readCache() {

// copy the cache temporarily
var cp = angular.copy(this.cache);

Expand All @@ -398,6 +435,9 @@ function PatientInvoiceFormService(Patients, PriceLists, Inventory, AppCache, St
// set the patient
this.setPatient(cp.recipient);

// set the service
this.setService(cp.service);

// setPatient() adds an item. Remove it before configuring data
this.clear();

Expand Down Expand Up @@ -428,6 +468,7 @@ function PatientInvoiceFormService(Patients, PriceLists, Inventory, AppCache, St
PatientInvoiceForm.prototype.writeCache = function writeCache() {
this.cache.details = this.details;
this.cache.recipient = this.recipient;
this.cache.service = this.service;
this.cache.items = angular.copy(this.store.data);
};

Expand All @@ -441,6 +482,7 @@ function PatientInvoiceFormService(Patients, PriceLists, Inventory, AppCache, St
delete this.cache.details;
delete this.cache.recipient;
delete this.cache.items;
delete this.cache.service;
};

/**
Expand All @@ -449,7 +491,7 @@ function PatientInvoiceFormService(Patients, PriceLists, Inventory, AppCache, St
* @description
* Checks to see if the invoice has cached items to recover.
*/
PatientInvoiceForm.prototype.hasCacheAvailable = function hasCacheAvailable() {
PatientInvoiceForm.prototype.hasCacheAvailable = function hasCacheAvailable() {
return Object.keys(this.cache).length > 0;
};

Expand Down
7 changes: 3 additions & 4 deletions client/src/partials/patient_invoice/patientInvoice.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,15 @@
</bh-find-patient>
</div>

<div
class="form-group"
<div class="form-group"
ng-class="{'has-error' : detailsForm.$submitted && detailsForm.service.$invalid }">
<label class="control-label" translate>FORM.LABELS.SERVICE</label>
<select
class="form-control"
name="service"
ng-model="PatientInvoiceCtrl.Invoice.service"
ng-options="service as service.name for service in PatientInvoiceCtrl.services"
ng-change="PatientInvoiceCtrl.handleServiceChange()"
ng-options="service as service.name for service in PatientInvoiceCtrl.Invoice.services"
ng-change="PatientInvoiceCtrl.Invoice.setService(PatientInvoiceCtrl.Invoice.service)"
required>
<option disabled="disabled" value="" translate>FORM.LABELS.SERVICE</option>
</select>
Expand Down
Loading

0 comments on commit 5d9b7bd

Please sign in to comment.