Skip to content

Commit

Permalink
feat(cash): CashForm.configure() and open barcode
Browse files Browse the repository at this point in the history
This commit implements a convience method that allows the CashForm to be
configured from a generic object.  It also toggles a checkbox to open
the barcode automatically when the payment has succeeded.

Finally, debtor invoices on the cash payment page is now it's own state.
  • Loading branch information
Jonathan Niles authored and sfount committed Jan 14, 2017
1 parent 7a23ac8 commit 37079f3
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 80 deletions.
1 change: 1 addition & 0 deletions client/src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
"READ_ERROR" : "Unreadable Barcode! Please enter the barcode manually."
},
"SCAN_BARCODE" : "Scan Invoice Barcode",
"OPEN_BARCODE_MODAL" : "Scan another barcode on successful payment.",
"DEBTOR_INVOICES" : "Debtor Invoices",
"RECEIPTS_TITLE" : "Cash Payment Receipt",
"REPORT" : "Report",
Expand Down
1 change: 1 addition & 0 deletions client/src/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@
"READ_SUCCESS" : "Facture Trouvée",
"READ_ERROR" : "Code à barres illisible! Entrez le code à barres manuellement."
},
"OPEN_BARCODE_MODAL" : "Numériser un autre code à barres lors d'un paiement réussi.",
"DEBTOR_INVOICES" : "Factures des débiteurs",
"REPORT" : "Rapport",
"RECEIPTS_TITLE" : "Reçu de paiement des factures",
Expand Down
34 changes: 0 additions & 34 deletions client/src/js/services/ModalService.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ function ModalService(Modal) {
service.alert = alert;
service.confirm = confirm;
service.openSelectCashbox = openSelectCashbox;
service.openDebtorInvoices = openDebtorInvoices;
service.openTransfer = openTransfer;
service.openUploadDocument = openUploadDocument;
// modal for reporting
service.openReports = openReports;
Expand Down Expand Up @@ -126,38 +124,6 @@ function ModalService(Modal) {
return Modal.open(params).result;
}

/**
* Debtor invoices Modal
*/
function openDebtorInvoices(request) {
var params = angular.extend(modalParameters, {
templateUrl : 'partials/cash/modals/invoices.modal.html',
controller : 'CashInvoiceModalController as CashInvoiceModalCtrl',
resolve : {
debtorId : function debtorIdProvider() { return request.debtorUuid; },
invoices : function invoicesProvider() { return request.invoices; }
}
});

var instance = Modal.open(params);
return instance.result;
}

/**
* Transfer Modal
*/
function openTransfer(request) {
var params = angular.extend(modalParameters, {
templateUrl : 'partials/cash/modals/transfer.modal.html',
controller : 'CashTransferModalController as CashTransferModalCtrl',
resolve : {
cashBox: function transferProvider() { return request.cashbox; }
}
});

var instance = Modal.open(params);
}

/**
* upload document Modal
*/
Expand Down
41 changes: 29 additions & 12 deletions client/src/partials/cash/CashForm.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,23 +89,17 @@ function CashFormService(AppCache, Session, Patients, Exchange) {
* This method takes in a patient and sets the form's debtor_uuid as needed.
* It also looks up to confirm if the patient has a caution to alert the user.
*/
CashForm.prototype.setPatient = function setPatient(patient, searchByUuid) {
CashForm.prototype.setPatient = function setPatient(patient) {
var self = this;

this.patient = patient;
this.details.debtor_uuid = patient.debtor_uuid;

if (this.patientApi && searchByUuid) {
this.patientApi.searchByUuid(patient.uuid);
}

return Patients.balance(patient.debtor_uuid)
.then(function (balance) {

var patientAccountBalance = balance * -1;

console.log('Patients.balance', balance, patientAccountBalance);

self.messages.hasPositiveAccountBalance = patientAccountBalance > 0;
self.messages.patientAccountBalance = patientAccountBalance;

Expand All @@ -114,14 +108,37 @@ function CashFormService(AppCache, Session, Patients, Exchange) {
};

/**
* @method bindPatientApi
* @method configure
*
* @description
* This binds the bhFindPatient's API to re-search for a patient.
* @todo -- this feels really strictly tied ... can we do better?
* This is a convenience method for setting the form properties from an
* object passed into the form.
*/
CashForm.prototype.bindPatientApi = function bindPatientApi(api) {
this.patientApi = api;
CashForm.prototype.configure = function configure(config) {

if (config.patient) {
this.setPatient(config.invoices);
}

if (config.description) {
this.details.description = config.description;
}

if (config.cashbox) {
this.setCashbox(config.cashbox);
}

if (config.currency_id) {
this.setCurrency(config.currency_id);
}

if (config.is_caution) {
this.setCautionType(config.is_caution);
}

if (config.invoices) {
this.setInvoices(config.invoices);
}
};

/**
Expand Down
6 changes: 6 additions & 0 deletions client/src/partials/cash/cash.html
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,12 @@

<div class="form-group text-right">

<div class="checkbox" style="display : inline-block; padding-right:5px;">
<label>
<input type="checkbox" ng-model="CashCtrl.openBarcodeModalOnSuccess"> <span translate>CASH.VOUCHER.OPEN_BARCODE_MODAL</span>
</label>
</div>

<button type="button" class="btn btn-default" ng-click="CashCtrl.clear(CashVoucherForm)" data-method="clear">
<span translate>FORM.BUTTONS.CLEAR</span>
</button>
Expand Down
48 changes: 26 additions & 22 deletions client/src/partials/cash/cash.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ function CashController(Cash, Cashboxes, AppCache, Currencies, Session, Modals,
vm.Payment = new CashForm(cacheKey);

vm.timestamp = new Date();

vm.enterprise = Session.enterprise;

// this toggles whether the form should re-enter the checkbox state
var DEFAULT_BARCODE_CHECKBOX_STATE = (cache.openBarcodeModalOnSuccess || true);

// bind methods
vm.submit = submit;
vm.clear = clear;
Expand All @@ -53,11 +55,12 @@ function CashController(Cash, Cashboxes, AppCache, Currencies, Session, Modals,
// fired when the bhFindPatient API becomes available
function onRegisterApiCallback(api) {
vm.bhFindPatient = api;
vm.Payment.bindPatientApi(api);
}

// fired on controller start or form refresh
function startup() {
vm.openBarcodeModalOnSuccess = (cache.openBarcodeModalOnSuccess || DEFAULT_BARCODE_CHECKBOX_STATE);

Currencies.read()
.then(function (currencies) {
vm.currencies = currencies;
Expand Down Expand Up @@ -86,24 +89,19 @@ function CashController(Cash, Cashboxes, AppCache, Currencies, Session, Modals,
vm.cashbox = cashbox;
cache.cashbox = cashbox;
vm.disabledCurrencyIds = Cash.calculateDisabledIds(vm.cashbox, vm.currencies);

vm.Payment.setCashbox(cashbox);
}

/* Debtor Invoices Modal */
function openInvoicesModal() {

// only retrieve the invoice UUIDs
var invoices = vm.Payment.details.invoices
.map(function (invoice) {
return invoice.uuid;
});

// open the invoices modal selection controller
Modals.openDebtorInvoices({ debtorUuid: vm.Payment.details.debtor_uuid, invoices: invoices })
.then(function (invoices) {
vm.Payment.setInvoices(invoices);
});
$state.go('cash.debtors', {
id : vm.cashbox.id,
debtor_uuid : vm.Payment.details.debtor_uuid,
invoices: vm.Payment.details.invoices
.map(function (invoice) {
return invoice.uuid;
})
});
}

// submits the form to the server
Expand All @@ -113,6 +111,8 @@ function CashController(Cash, Cashboxes, AppCache, Currencies, Session, Modals,
// be sure the cashbox is set
vm.Payment.setCashbox(vm.cashbox);

vm.openBarcodeModalOnSuccess = cache.openBarcodeModalOnSuccess;

// patient invoices are covered by caution
var hasCaution = vm.Payment.messages.hasPositiveAccountBalance;
var isCaution = vm.Payment.isCaution();
Expand Down Expand Up @@ -157,12 +157,15 @@ function CashController(Cash, Cashboxes, AppCache, Currencies, Session, Modals,

// clear and refresh the form
clear(form);

if (vm.openBarcodeModalOnSuccess) {
$state.go('^.scan', { id : vm.cashbox.id });
}
})
.catch(Notify.handleError);
}

function clear(form) {

vm.Payment.setup();

// clear the patient selection
Expand All @@ -172,13 +175,14 @@ function CashController(Cash, Cashboxes, AppCache, Currencies, Session, Modals,
form.$setPristine();
}

function configureCashPaymentsForm(event, data) {
vm.Payment.setInvoices(data.invoices);
vm.Payment.details.description = data.description;
vm.Payment.setPatient(data.patient, true);
}
RS.$on('cash:configure', function (event, data) {
vm.Payment.configure(data);

RS.$on('cash:configure', configureCashPaymentsForm);
// if the patient UUID is provided, search by that patient
if (data.patient) {
vm.bhFindPatient.searchByUuid(data.patient.uuid);
}
});

// start up the module
startup();
Expand Down
27 changes: 25 additions & 2 deletions client/src/partials/cash/cash.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ angular.module('bhima.routes')
onExit : ['$uibModalStack', closeModal]
})

.state('cash.debtors', {
url : '/:id',
params : {
id : { squash: true, value: null },
debtor_uuid: { value: undefined },
invoices: { value : [] }
},
onEnter :['$state', '$uibModal', debtorInvoicesModal],
onExit : ['$uibModalStack', closeModal]
})

.state('cash.scan', {
url : '/:id/scan',
params : { id : { squash: true, value: null } },
Expand Down Expand Up @@ -70,8 +81,20 @@ function scanBarcodeModal($state, Modal) {
size : 'lg',
backdrop: 'static',
keyboard: true
}).result.catch(function () {
$state.go('^.window', $state.params);
}).result.finally(function () {
$state.go('^.window', { id : $state.params.id });
});
}

function debtorInvoicesModal($state, Modal) {
Modal.open({
templateUrl : 'partials/cash/modals/invoices.modal.html',
controller : 'CashInvoiceModalController as CashInvoiceModalCtrl',
backdrop: 'static',
animation : false,
keyboard: true
}).result.finally(function () {
$state.go('^.window', { id : $state.params.id });
});
}

Expand Down
4 changes: 4 additions & 0 deletions client/src/partials/cash/modals/invoices.modal.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
<i class="fa fa-warning"></i> {{ ::"FORM.ERRORS.MISSING_DEBTOR_ID" | translate }}
</p>

<pre>
{{ CashInvoiceModalCtrl.$params | json }}
</pre>

<!-- ui-grid to select debtor invoices -->
<div ng-if="!CashInvoiceModalCtrl.missingId">
<div ui-grid="CashInvoiceModalCtrl.gridOptions" ui-grid-selection class="modal-grid" id="debtorInvoicesGrid">
Expand Down
29 changes: 20 additions & 9 deletions client/src/partials/cash/modals/invoices.modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ angular.module('bhima.controllers')
.controller('CashInvoiceModalController', CashInvoiceModalController);

CashInvoiceModalController.$inject = [
'DebtorService', 'debtorId', 'invoices', '$uibModalInstance', 'SessionService',
'$timeout', 'NotifyService'
'DebtorService', 'SessionService', '$timeout', 'NotifyService', '$state',
'$rootScope'
];

/**
Expand All @@ -13,19 +13,20 @@ CashInvoiceModalController.$inject = [
* This controller is responsible for retrieving a list of debtor invoices
* from the server, and allowing selection of any number of invoices.
*/
function CashInvoiceModalController(Debtors, debtorId, invoices, ModalInstance, Session, $timeout, Notify) {
function CashInvoiceModalController(Debtors, Session, $timeout, Notify, $state, $rootScope) {
var vm = this;

// we start in a neutral state
vm.loading = false;
vm.hasError = false;
var debtorId = $state.params.debtor_uuid;
var invoices = $state.params.invoices;

vm.$params = $state.params;

// defaults to value
vm.missingId = !debtorId ;
vm.missingId = !angular.isDefined(debtorId);

// bind methods
vm.cancel = ModalInstance.dismiss;
vm.submit = submit;
vm.cancel = dismiss;

vm.gridOptions = {
appScopeProvider : vm,
Expand Down Expand Up @@ -107,10 +108,20 @@ function CashInvoiceModalController(Debtors, debtorId, invoices, ModalInstance,
// resolve the modal with the selected invoices to add to the cash payment bills
function submit() {

// we start in a neutral state
vm.loading = false;
vm.hasError = false;

// retrieve the outstanding patient invoices from the ui grid
var invoices = vm.getSelectedRows();

ModalInstance.close(invoices);
$rootScope.$broadcast('cash:configure', { invoices : invoices });

$state.go('^.window', $state.params);
}

function dismiss() {
$state.go('^.window', $state.params);
}

// start up the module
Expand Down
4 changes: 3 additions & 1 deletion client/src/partials/cash/modals/scanBarcode.modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ function CashBarController($state, Cashboxes, Notify, Barcodes, Patients, bhCons

// TODO(@jniles) potentially this should tell you if you are trying to read a
// cash payment instead of an invoice
// TODO(@jniles) potentially this should clear the input when the barcode is greater in length than 10.
// TODO(@jniles) potentially this should clear the input when the barcode
// is greater in length than 10.
// TODO(@jniles) this should be a component
function triggerBarcodeRead() {
if (isValidBarcode(vm.barcode)) {
searchForBarcode(vm.barcode);
Expand Down
4 changes: 4 additions & 0 deletions test/end-to-end/cash/cash.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ describe('Cash Payments', function () {
});

it('should make a payment against previous invoices', function () {

// @fixme - why is this better?
browser.refresh();

var gridId = 'debtorInvoicesGrid';

// select the proper patient
Expand Down

0 comments on commit 37079f3

Please sign in to comment.