Skip to content

Commit

Permalink
test(StockExitFormHelper): add unit tests
Browse files Browse the repository at this point in the history
Adds unit tests for the description rendering of the
StockExitFormHelper.  Note the testing $translate is a little finicky,
but this could be improved later.
  • Loading branch information
jniles committed Mar 4, 2022
1 parent 6e4688f commit 698c24f
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 131 deletions.
3 changes: 1 addition & 2 deletions client/src/i18n/en/stock.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,7 @@
"EXIT_INDIVIDUAL" : "Exit to Individual",
"EXIT_LOSS" : "Loss",
"EXIT_PATIENT" : "Distribution to a patient",
"EXIT_PATIENT_ADVANCED" : "Distribution to the patient {{patient}} from depot {{depot}}",
"EXIT_PATIENT_ADVANCED_WITH_INVOICE" : "Distribution to the patient {{patient}} invoiced by ({{invoice}}) from the depot {{depot}}",
"EXIT_PATIENT_WITH_INVOICE" : "Distribution to the patient {{patient}} invoiced by ({{invoice}}) from the depot {{depot}}",
"EXIT_SERVICE" : "Distribution to a service",
"EXIT_SERVICE_ADVANCED" : "Distribution to the service {{service}} from {{depot}}",
"EXPIRATION" : "Expiration",
Expand Down
3 changes: 1 addition & 2 deletions client/src/i18n/fr/stock.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,7 @@
"EXIT_INDIVIDUAL" : "Distribution aux individus",
"EXIT_LOSS" : "Perte",
"EXIT_PATIENT" : "Distribution vers un patient",
"EXIT_PATIENT_ADVANCED" : "Distribution vers le patient {{patient}} à partir du dépôt {{depot}}",
"EXIT_PATIENT_ADVANCED_WITH_INVOICE" : "Distribution vers le patient {{patient}} sur la facture ({{invoice}}) à partir du dépôt {{depot}}",
"EXIT_PATIENT_WITH_INVOICE" : "Distribution vers le patient {{patient}} sur la facture ({{invoice}}) à partir du dépôt {{depot}}",
"EXIT_SERVICE" : "Distribution vers un service",
"EXIT_SERVICE_ADVANCED" : "Distribution vers le service {{service}} à partir du dépôt {{depot}}",
"EXPIRATION" : "Expiration",
Expand Down
81 changes: 7 additions & 74 deletions client/src/modules/stock/StockExitForm.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ angular.module('bhima.services')

StockExitFormService.$inject = [
'Store', 'AppCache', 'SessionService', '$timeout', 'bhConstants',
'moment', 'DepotService', '$q', 'Pool', 'LotItemService',
'DepotService', 'Pool', 'LotItemService', 'StockExitFormHelperService',
];

/**
Expand All @@ -12,7 +12,7 @@ StockExitFormService.$inject = [
* @description
* This form powers the stock exit form in BHIMA.
*/
function StockExitFormService(Store, AppCache, Session, $timeout, bhConstants, moment, Depots, $q, Pool, Lot) {
function StockExitFormService(Store, AppCache, Session, $timeout, bhConstants, Depots, Pool, Lot, Helpers) {

const {
TO_PATIENT, TO_LOSS, TO_SERVICE, TO_OTHER_DEPOT,
Expand Down Expand Up @@ -450,53 +450,6 @@ function StockExitFormService(Store, AppCache, Session, $timeout, bhConstants, m
return hasValidLots && hasRequiredDetails;
};

/**
* @function getI18nKeys
*
* @description
* Gets the i18nKeys to render the description. Note, not all data is
* cached on the client so this function is async, looking up data from
* the server.
*
* It requires that an exit type be set before calling it.
*
* TODO(@jniles) - should this be changed?
*/
StockExitForm.prototype.getI18nKeys = function getI18nKeys() {
const keys = { depot : this.depot.text };

if (!this.details.exit_type) { return ''; }

return $q.resolve('hello', keys);

// const queries = this.details.exit_type === 'patient'
// ? [
// PatientService.read(null, { uuid : this.details.entity_uuid }),
// PatientInvoiceService.read(null, { uuid : this.details.invoice_uuid }),
// ]
// : [
// ServiceService.read(null, { uuid : this.details.entity_uuid }),
// ];

// $q.all(queries).

// if (patients && patients.length) {
// const patient = patients[0];
// i18nKeys.patient = patient.display_name.concat(` (${patient.reference})`);
// }

// if (invoices && invoices.length) {
// const invoice = invoices[0];
// i18nKeys.invoice = invoice.reference;
// }

// if (services && services.length) {
// const service = services[0];
// i18nKeys.service = service.name;
// }

};

/**
* @function getDataForSubmission
*
Expand All @@ -506,33 +459,13 @@ function StockExitFormService(Store, AppCache, Session, $timeout, bhConstants, m
StockExitForm.prototype.getDataForSubmission = function getDataForSubmission() {
const data = { ...this.details };

// how do we
Helpers.getDescription(this.depot, data)
.then(description => {
Object.assign(data, { description });
});

};
// how do we

/**
* @function formatRowsForExport
*
* @description this function will be apply to grid columns as filter for getting new columns
*
* @param {array} rows - refer to the grid data array
* @return {array} - return an array of array with value as an object in this format : { value : ... }
*/
StockExitForm.prototype.formatRowsForExport = function formatRowsForExport(rows = []) {
return rows.map(row => {
const code = row.inventory?.code;
const description = row.inventory?.text;
const lot = row.lot?.label;
const price = row.inventory?.unit_cost;
const quantity = row.quantity?.quantity;
const type = row.quantity?.unit_type;
const available = row.inventory?.quantity;
const amount = (price && quantity) ? price * quantity : 0;
const expiration = (row.lot && row.lot.expiration_date)
? moment(row.lot.expiration_date).format(bhConstants.dates.formatDB) : null;

return [code, description, lot, price, quantity, type, available, amount, expiration].map(value => ({ value }));
});
};

return StockExitForm;
Expand Down
152 changes: 152 additions & 0 deletions client/src/modules/stock/StockExitFormHelper.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
angular.module('bhima.services')
.service('StockExitFormHelperService', StockExitFormHelperService);

StockExitFormHelperService.$inject = [
'moment', '$q', '$translate', 'bhConstants',
'PatientService', 'PatientInvoiceService', 'ServiceService',
];

/**
* @class StockExitFormHelperService
*
* @description
* This form powers the stock exit form in BHIMA.
*/
function StockExitFormHelperService(moment, $q, $translate, bhConstants, Patients, Invoices, Services) {
const service = {};

const { formatDB } = bhConstants.dates;

/**
* @function getDescriptionForPatient
*
* @description
* Fetches all the components to create a proper translation
* for the stock exit to patient.
*
* @returns {Promise<String>} description
*/
function getDescriptionForPatient(details, i18nKeys) {

// load the required information for the patient description
const queries = $q.all([
Patients.read(null, { uuid : details.entity_uuid }),
Invoices.read(null, { uuid : details.invoice_uuid }),
]);

return queries
.then(([patients, invoices]) => {
const [patient] = patients;
const [invoice] = invoices;

Object.assign(i18nKeys, {
patient : patient.display_name.concat(` (${patient.reference})`),
invoice : invoice.reference,
});

return $translate.instant('STOCK.EXIT_PATIENT_WITH_INVOICE', i18nKeys);
});
}

/**
* @function getDescriptionForService
*
* @description
* Fetches all the components to create a proper translation
* for the stock exit to service.
*
* @returns {Promise<String>} description
*/
function getDescriptionForService(details, i18nKeys) {
// load the required information for the service description
Services.read(null, { uuid : details.entity_uuid })
.then(([{ name }]) => {

Object.assign(i18nKeys, {
service : name,
});

return $translate.instant('STOCK.EXIT_SERVICE_ADVANCED', i18nKeys);
});
}

// depots do not require any special translation
// TODO(@jniles) - should this say "exit from depot X to depot Y of Z items"?
function getDescriptionForDepot(details, i18nKeys) {
return $q.resolve($translate.instant('STOCK.EXIT_DEPOT', i18nKeys));
}

// losses do not require any special translation
// TODO(@jniles) - should this say "Loss of Z items from Depot Y"?
function getDescriptionForLoss(details, i18nKeys) {
return $q.resolve($translate.instant('STOCK.EXIT_LOSS', i18nKeys));
}

/**
* @function getI18nKeys
*
* @description
* Gets the i18nKeys to render the description. Note, not all data is
* cached on the client so this function is async, looking up data from
* the server.
*
* It requires that an exit type be set before calling it.
*
* @returns {Promise<String>} description
*/
service.getDescription = function getDescription(depot, details) {
const i18nKeys = { depot : depot.text };

let promise;

switch (details.exit_type) {
case 'patient':
promise = getDescriptionForPatient(details, i18nKeys);
break;
case 'service':
promise = getDescriptionForService(details, i18nKeys);
break;
case 'depot':
promise = getDescriptionForDepot(details, i18nKeys);
break;
case 'loss':
promise = getDescriptionForLoss(details, i18nKeys);
break;
default:
throw new Error('Unrecognized Exit Type');
}

return promise
.then(description => {
return description.concat(' - ', details.description);
});
};

/**
* @function formatRowsForExport
*
* @description this function will be apply to grid columns as filter for getting new columns
*
* @param {array} rows - refer to the grid data array
* @return {array} - return an array of array with value as an object in this format : { value : ... }
*/
service.formatRowsForExport = function formatRowsForExport(rows = []) {
return rows.map(row => {
const code = row.inventory?.code;
const description = row.inventory?.text;
const lot = row.lot?.label;
const price = row.inventory?.unit_cost;
const quantity = row.quantity?.quantity;
const type = row.quantity?.unit_type;
const available = row.inventory?.quantity;
const amount = (price && quantity) ? price * quantity : 0;
const expiration = (row.lot && row.lot.expiration_date)
? moment(row.lot.expiration_date).format(formatDB) : null;

return [code, description, lot, price, quantity, type, available, amount, expiration].map(value => ({ value }));
});
};

return service;

}
53 changes: 0 additions & 53 deletions client/src/modules/stock/exit/exit.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ StockExitController.$inject = [
'bhConstants', 'ReceiptModal', 'StockExitFormService', 'StockService',
'StockModalService', 'uiGridConstants', '$translate',
'GridExportService', 'Store', 'BarcodeService',
'PatientService', 'PatientInvoiceService', 'ServiceService',
];

/**
Expand All @@ -20,7 +19,6 @@ function StockExitController(
Notify, Session, util, bhConstants, ReceiptModal,
StockForm, Stock, StockModal, uiGridConstants, $translate,
GridExportService, Store, Barcode,
PatientService, PatientInvoiceService, ServiceService,
) {
const vm = this;

Expand All @@ -40,13 +38,6 @@ function StockExitController(
vm.submit = submit;
vm.getLotByBarcode = getLotByBarcode;

// const mapExit = {
// patient : { description : 'STOCK.EXIT_PATIENT', find : findPatient, submit : submitPatient },
// service : { description : 'STOCK.EXIT_SERVICE', find : findService, submit : submitService },
// depot : { description : 'STOCK.EXIT_DEPOT', find : findDepot, submit : submitDepot },
// loss : { description : 'STOCK.EXIT_LOSS', find : configureLoss, submit : submitLoss },
// };

const gridFooterTemplate = `
<div style="margin-left: 10px;">
{{ grid.appScope.gridApi.core.getVisibleRows().length }}
Expand Down Expand Up @@ -269,50 +260,6 @@ function StockExitController(
// .finally(() => { vm.$loading = false; });
}

function buildDescription(entityUuid, invoiceUuid) {
const dbPromises = [
PatientService.read(null, { uuid : entityUuid }),
ServiceService.read(null, { uuid : entityUuid }),
invoiceUuid ? PatientInvoiceService.read(null, { uuid : invoiceUuid }) : [],
];

return Promise.all(dbPromises)
.then(([patients, services, invoices]) => {
const i18nKeys = { depot : vm.stockForm.depot.text };

if (patients && patients.length) {
const patient = patients[0];
i18nKeys.patient = patient.display_name.concat(` (${patient.reference})`);
}

if (invoices && invoices.length) {
const invoice = invoices[0];
i18nKeys.invoice = invoice.reference;
}

if (services && services.length) {
const service = services[0];
i18nKeys.service = service.name;
}

let description;

if (vm.stockForm.depot.text && i18nKeys.patient) {
description = $translate.instant('STOCK.EXIT_PATIENT_ADVANCED', i18nKeys);
}

if (vm.stockForm.depot.text && i18nKeys.patient && i18nKeys.invoice) {
description = $translate.instant('STOCK.EXIT_PATIENT_ADVANCED_WITH_INVOICE', i18nKeys);
}

if (vm.stockForm.depot.text && i18nKeys.service) {
description = $translate.instant('STOCK.EXIT_SERVICE_ADVANCED', i18nKeys);
}

return description ? description.concat(' : ') : '';
});
}

// // submit patient
// function submitPatient(form) {
// const invoiceUuid = vm.movement.entity.instance.invoice && vm.movement.entity.instance.invoice
Expand Down
Loading

0 comments on commit 698c24f

Please sign in to comment.