diff --git a/README.md b/README.md index 99e8e3cb4d..1de7918a54 100644 --- a/README.md +++ b/README.md @@ -65,28 +65,42 @@ Resources to build the following docker images can be found in the [package](/pa ## Prevent Search Engines from Indexing the homepage + >⚠️ : Search Engines are able to index the Bahmni App homepage. This behaviour can be prevented by: -1. **Adding a “noindex” metatag:** - +1. **Adding a “noindex” metatag:** + The following tag should be inserted in the `` section of the homepage's HTML markup: + ``` ``` + Additionally, in order to both _de-index_ the homepage and not follow the links, use the `noindex` with the `nofollow` metatag: + ``` ``` - > The same is already done [here](https://github.com/Bahmni/openmrs-module-bahmniapps/blob/master/package/docker/index.html#L5) + > The same is already done [here](https://github.com/Bahmni/openmrs-module-bahmniapps/blob/master/package/docker/index.html#L5) + > 2. **Using an X-ROBOTS-TAG HTTP HEADER:** An `X-Robots-Tag` can be added to the HTTP response header. It has basically the same effect as a `noindex` tag, but with the additional options to specify conditions for different search engines. For more information, please see Google’s guide [here](https://developers.google.com/search/docs/advanced/robots/robots_meta_tag). Here are examples of X-Robots-Tag for specific functions: - + - To de-index a web page: + ``` Header set X-Robots-Tag "noindex, nofollow" ``` + + > The same is already done [here](https://github.com/Bahmni/openmrs-module-bahmniapps/blob/master/package/docker/httpd.conf#L32) + > + +### SNOMED Integration Support + +openmrs-module-bahmniapps also integrates with SNOMED for terminology lookup and CDSS. More details can be found in [this](https://bahmni.atlassian.net/wiki/spaces/BAH/pages/3132686337/SNOMED+FHIR+Terminology+Server+Integration+with+Bahmni) Wiki link +======= > The same is already done [here](https://github.com/Bahmni/openmrs-module-bahmniapps/blob/master/package/docker/httpd.conf#L32) diff --git a/ui/app/clinical/common/models/drugOrderViewModel.js b/ui/app/clinical/common/models/drugOrderViewModel.js index 8b10fdb50b..496ef8b1bf 100644 --- a/ui/app/clinical/common/models/drugOrderViewModel.js +++ b/ui/app/clinical/common/models/drugOrderViewModel.js @@ -707,6 +707,7 @@ Bahmni.Clinical.DrugOrderViewModel.createFromContract = function (drugOrderRespo }; } viewModel.instructions = administrationInstructions.instructions; + viewModel.audit = drugOrderResponse.audit; viewModel.additionalInstructions = administrationInstructions.additionalInstructions; viewModel.quantity = drugOrderResponse.dosingInstructions.quantity; viewModel.quantityUnit = drugOrderResponse.dosingInstructions.quantityUnits; diff --git a/ui/app/clinical/consultation/controllers/addTreatmentController.js b/ui/app/clinical/consultation/controllers/addTreatmentController.js index 56405c2481..0b63395f8d 100644 --- a/ui/app/clinical/consultation/controllers/addTreatmentController.js +++ b/ui/app/clinical/consultation/controllers/addTreatmentController.js @@ -15,6 +15,8 @@ angular.module('bahmni.clinical') $scope.addTreatment = true; $scope.canOrderSetBeAdded = true; $scope.isSearchDisabled = false; + $scope.cdssEnabled = false; + $scope.conceptSource = localStorage.getItem("conceptSource") || ""; $scope.getFilteredOrderSets = function (searchTerm) { if (searchTerm && searchTerm.length >= 3) { @@ -56,7 +58,7 @@ angular.module('bahmni.clinical') $scope.showDoseFractions = treatmentConfig.inputOptionsConfig.showDoseFractions; $scope.isDoseFractionsAvailable = function () { - return $scope.doseFractions && !_.isEmpty($scope.doseFractions) ? true : false; + return !!($scope.doseFractions && !_.isEmpty($scope.doseFractions)); }; $scope.isSelected = function (drug) { @@ -68,6 +70,24 @@ angular.module('bahmni.clinical') $scope.onSelect($scope.treatment.selectedItem); }; + $scope.auditOptions = function () { + return appService + .getAppDescriptor() + .getConfigValue('cdssDismissalOptionsToDisplay'); + }; + + $scope.submitAudit = function (index) { + var patientUuid = $scope.patient.uuid; + var message = $scope.cdssaAlerts[index].summary.replace(/"/g, ''); + var eventType = 'Dismissed: ' + $scope.treatment.audit; + $scope.cdssaAlerts.splice(index, 1); + return drugService + .cdssAudit(patientUuid, eventType, message, 'CDSS') + .then(function () { + $scope.treatment.audit = ''; + }); + }; + var markVariable = function (variable) { $scope[variable] = true; $timeout(function () { @@ -127,6 +147,12 @@ angular.module('bahmni.clinical') durationUnit: treatment.durationUnit }; }; + var getCdssEnabled = function () { + drugService.getCdssEnabled().then(function (response) { + $scope.cdssEnabled = response.data; + }); + }; + getCdssEnabled(); var isSameDrugBeingDiscontinuedAndOrdered = function () { var existingTreatment = false; @@ -188,9 +214,13 @@ angular.module('bahmni.clinical') _.each(refilledOrderGroupOrders, function (drugOrder) { _.each(orderSetMembersOfMatchedOrderSet, function (orderSetMember) { if (orderSetMember.orderTemplate.drug) { - if (orderSetMember.orderTemplate.drug.uuid === _.get(drugOrder, 'drug.uuid')) { matchedMembers.push(orderSetMember); } + if (orderSetMember.orderTemplate.drug.uuid === _.get(drugOrder, 'drug.uuid')) { + matchedMembers.push(orderSetMember); + } } else { - if (orderSetMember.concept.uuid === drugOrder.concept.uuid) { matchedMembers.push(orderSetMember); } + if (orderSetMember.concept.uuid === drugOrder.concept.uuid) { + matchedMembers.push(orderSetMember); + } } }); }); @@ -201,11 +231,11 @@ angular.module('bahmni.clinical') var baseDose = eachMember.orderTemplate.dosingInstructions.dose; var drugName = eachMember.orderTemplate.concept.name; return orderSetService.getCalculatedDose($scope.patient.uuid, drugName, baseDose, doseUnits, $scope.newOrderSet.name) - .then(function (calculatedDosage) { - refilledOrderGroupOrders[index].uniformDosingType.dose = calculatedDosage.dose; - refilledOrderGroupOrders[index].uniformDosingType.doseUnits = calculatedDosage.doseUnit; - refilledOrderGroupOrders[index].calculateQuantityAndUnit(); - }); + .then(function (calculatedDosage) { + refilledOrderGroupOrders[index].uniformDosingType.dose = calculatedDosage.dose; + refilledOrderGroupOrders[index].uniformDosingType.doseUnits = calculatedDosage.doseUnit; + refilledOrderGroupOrders[index].calculateQuantityAndUnit(); + }); } }); @@ -466,7 +496,10 @@ angular.module('bahmni.clinical') var contextChange = function () { var errorMessages = Bahmni.Clinical.Constants.errorMessages; if (isSameDrugBeingDiscontinuedAndOrdered()) { - return {allow: false, errorMessage: $translate.instant(errorMessages.discontinuingAndOrderingSameDrug)}; + return { + allow: false, + errorMessage: $translate.instant(errorMessages.discontinuingAndOrderingSameDrug) + }; } if ($scope.incompleteDrugOrders()) { $scope.formInvalid = true; @@ -482,6 +515,17 @@ angular.module('bahmni.clinical') treatment.isBeingEdited = false; }; + $scope.closeAlert = function (index) { + $scope.cdssaAlerts = $scope.cdssaAlerts.filter(function (alert, alertIndex) { + return alertIndex !== index; + }); + }; + + $scope.toggleAlertDetails = function (index) { + $scope.cdssaAlerts[index].showDetails = + !$scope.cdssaAlerts[index].showDetails; + }; + $scope.getDataResults = function (drugs) { var searchString = $scope.treatment.drugNameDisplay; var listOfDrugSynonyms = _.map(drugs, function (drug) { @@ -489,12 +533,175 @@ angular.module('bahmni.clinical') }); return _.flatten(listOfDrugSynonyms); }; + var createMedicationRequest = function (medication, patientUuid) { + return extractCodeInfo(medication).then(function (coding) { + var medicationRequest = { + resourceType: 'MedicationRequest', + id: medication.uuid, + status: 'active', + intent: 'order', + subject: { + reference: 'Patient/' + patientUuid + }, + medicationCodeableConcept: { + id: medication.drug.uuid, + coding: [ + coding + ], + text: medication.drugNameDisplay + } + }; + return { + resource: medicationRequest + }; + }); + }; + var extractCodeInfo = function (medication) { + if (!(medication.drug.drugReferenceMaps && medication.drug.drugReferenceMaps.length > 0)) { + return Promise.resolve({ + code: medication.drug.uuid, + display: medication.drug.name + }); + } else { + var drugReferenceMap = medication.drug.drugReferenceMaps[0]; + if (!$scope.conceptSource) { + return drugService.getDrugConceptSourceMapping(medication.drug.uuid).then(function (response) { + var bundle = response.data; + var code = bundle.entry && bundle.entry.length > 0 && bundle.entry[0].resource.code; + var conceptCode = code.coding.find(function (coding) { + return coding.system; + }); + if (conceptCode) { + localStorage.setItem("conceptSource", conceptCode.system); + $scope.conceptSource = conceptCode.system; + return { + system: $scope.conceptSource, + code: drugReferenceMap.conceptReferenceTerm && drugReferenceMap.conceptReferenceTerm.display && drugReferenceMap.conceptReferenceTerm.display.split(':')[1].trim(), + display: medication.drug.name + }; + } else { + return { + code: medication.drug.uuid, + display: medication.drug.name + }; + } + }); + } else { + return Promise.resolve({ + system: $scope.conceptSource, + code: drugReferenceMap.conceptReferenceTerm && drugReferenceMap.conceptReferenceTerm.display && drugReferenceMap.conceptReferenceTerm.display.split(':')[1].trim(), + display: medication.drug.name + }); + } + } + }; + + var createConditionResource = function (condition, patientUuid, isDiagnosis) { + var conceptLimitIndex = isDiagnosis ? -1 : condition.concept.uuid.lastIndexOf('/'); + var conditionStatus = condition.status || condition.certainty; + var activeConditions = ['CONFIRMED', 'PRESUMED', 'ACTIVE']; + var status = activeConditions.indexOf(conditionStatus) > -1 ? 'active' : 'inactive'; + var conditionResource = { + resourceType: 'Condition', + id: condition.uuid, + clinicalStatus: { + coding: [ + { + code: status, + display: status.charAt(0).toUpperCase() + status.slice(1), + system: 'http://terminology.hl7.org/CodeSystem/condition-clinical' + } + ] + }, + code: { + coding: [ + { + system: isDiagnosis ? condition.codedAnswer.conceptSystem : (conceptLimitIndex > -1 ? (condition.concept.uuid.substring(0, conceptLimitIndex) || '') : ''), + code: isDiagnosis ? condition.codedAnswer.uuid : (conceptLimitIndex > -1 ? condition.concept.uuid.substring(conceptLimitIndex + 1) : condition.concept.uuid), + display: isDiagnosis ? condition.codedAnswer.name : condition.concept.name + } + ], + text: isDiagnosis ? condition.codedAnswer.name : condition.concept.name + }, + subject: { + reference: 'Patient/' + patientUuid + } + }; + if (angular.isNumber(condition.onSetDate) === 'number') { + conditionResource.onsetDateTime = new Date(condition.onSetDate).toLocaleDateString('en-CA'); + } + if (!conditionResource.onsetDateTime) { + delete conditionResource.onsetDateTime; + } + return { + resource: conditionResource + }; + }; + + $scope.createFhirBundle = function (patient, conditions, medications, diagnosis) { + var encounterResource = conditions.filter(function (condition) { + return !condition.uuid; + }).map(function (condition) { + return createConditionResource(condition, patient.uuid, false); + }); + encounterResource = encounterResource.concat(diagnosis.map(function (condition) { + return createConditionResource(condition, patient.uuid, true); + })); + + return Promise.all(medications.map(function (medication) { + return createMedicationRequest(medication, patient.uuid).then(function (medicationResource) { + return medicationResource; + }); + })).then(function (medicationResources) { + return { + resourceType: 'Bundle', + type: 'collection', + entry: [].concat(encounterResource, medicationResources) + }; + }); + }; + + var createParams = function (consultationData) { + var patient = consultationData.patient; + var conditions = consultationData.conditions; + var diagnosis = consultationData.newlyAddedDiagnoses; + var medications = consultationData.draftDrug; + return { + patient: patient, + conditions: conditions, + diagnosis: diagnosis, + medications: medications + }; + }; + + function sortInteractionsByStatus (arr) { + var order = { "critical": 0, "warning": 1, "info": 2 }; + return arr.sort(function (a, b) { + return order[a.indicator] - order[b.indicator]; + }); + } (function () { var selectedItem; $scope.onSelect = function (item) { selectedItem = item; $scope.onChange(); + if ($scope.cdssEnabled) { + var consultationData = angular.copy($scope.consultation); + consultationData.patient = $scope.patient; + + consultationData.draftDrug = [$scope.treatment].concat( + consultationData.newlyAddedTabTreatments ? consultationData.newlyAddedTabTreatments.allMedicationTabConfig.treatments : [] + ); + var params = createParams(consultationData); + $scope.createFhirBundle(params.patient, params.conditions, params.medications, params.diagnosis) + .then(function (bundle) { + var cdssaAlerts = drugService.sendDiagnosisDrugBundle(bundle); + cdssaAlerts.then(function (response) { + $scope.cdssaAlerts = sortInteractionsByStatus(response.data); + }); + }); + } }; $scope.onAccept = function () { $scope.treatment.acceptedItem = $scope.treatment.drugNameDisplay; @@ -508,7 +715,8 @@ angular.module('bahmni.clinical') $scope.treatment.changeDrug({ name: selectedItem.drug.name, form: selectedItem.drug.dosageForm && selectedItem.drug.dosageForm.display, - uuid: selectedItem.drug.uuid + uuid: selectedItem.drug.uuid, + drugReferenceMaps: selectedItem.drug.drugReferenceMaps }); selectedItem = null; return; @@ -521,12 +729,14 @@ angular.module('bahmni.clinical') return; } delete $scope.treatment.drug; + $scope.cdssaAlerts = []; }; })(); $scope.clearForm = function () { $scope.treatment = newTreatment(); $scope.formInvalid = false; + $scope.cdssaAlerts = []; clearHighlights(); markVariable("startNewDrugEntry"); }; @@ -553,7 +763,7 @@ angular.module('bahmni.clinical') }; $scope.toggleDrugOrderAttribute = function (orderAttribute) { - orderAttribute.value = orderAttribute.value ? false : true; + orderAttribute.value = !orderAttribute.value; }; contextChangeHandler.add(contextChange); @@ -644,7 +854,9 @@ angular.module('bahmni.clinical') $scope.newOrderSet.name = orderSet.name; var orderSetMemberTemplates = _.map(orderSet.orderSetMembers, 'orderTemplate'); var promisesToCalculateDose = _.map(orderSetMemberTemplates, putCalculatedDose); - var returnOrderSet = function () { return orderSet; }; + var returnOrderSet = function () { + return orderSet; + }; return $q.all(promisesToCalculateDose).then(returnOrderSet); }; var createDrugOrderViewModel = function (orderTemplate) { diff --git a/ui/app/clinical/consultation/controllers/diagnosisController.js b/ui/app/clinical/consultation/controllers/diagnosisController.js index 89a6032031..2fda0d49dd 100644 --- a/ui/app/clinical/consultation/controllers/diagnosisController.js +++ b/ui/app/clinical/consultation/controllers/diagnosisController.js @@ -143,11 +143,13 @@ angular.module('bahmni.clinical') value: concept.matchedName || concept.conceptName, concept: { name: concept.conceptName, - uuid: concept.conceptUuid + uuid: concept.conceptUuid, + conceptSystem: concept.conceptSystem }, lookup: { name: concept.matchedName || concept.conceptName, - uuid: concept.conceptUuid + uuid: concept.conceptUuid, + conceptSystem: concept.conceptSystem } }; @@ -163,6 +165,8 @@ angular.module('bahmni.clinical') $scope.getAddConditionMethod = function () { return function (item) { + var conceptSystem = item.lookup.conceptSystem ? item.lookup.conceptSystem + "/" : ""; + item.lookup.uuid = conceptSystem + item.lookup.uuid; $scope.consultation.condition.concept.uuid = item.lookup.uuid; item.value = $scope.consultation.condition.concept.name = item.lookup.name; }; @@ -270,9 +274,9 @@ angular.module('bahmni.clinical') }; $scope.cleanOutDiagnosisList = function (allDiagnoses) { - return allDiagnoses.filter(function (diagnosis) { + return allDiagnoses ? allDiagnoses.filter(function (diagnosis) { return !alreadyAddedToDiagnosis(diagnosis); - }); + }) : []; }; var alreadyAddedToDiagnosis = function (diagnosis) { diff --git a/ui/app/clinical/consultation/mappers/encounterTransactionMapper.js b/ui/app/clinical/consultation/mappers/encounterTransactionMapper.js index 97ef4ea65e..9063a9584a 100644 --- a/ui/app/clinical/consultation/mappers/encounterTransactionMapper.js +++ b/ui/app/clinical/consultation/mappers/encounterTransactionMapper.js @@ -41,8 +41,9 @@ Bahmni.Clinical.EncounterTransactionMapper = function () { if (consultation.newlyAddedDiagnoses && consultation.newlyAddedDiagnoses.length > 0) { encounterData.bahmniDiagnoses = consultation.newlyAddedDiagnoses.map(function (diagnosis) { + var conceptSystem = diagnosis.codedAnswer.conceptSystem ? diagnosis.codedAnswer.conceptSystem + "/" : ""; return { - codedAnswer: { uuid: !diagnosis.isNonCodedAnswer ? diagnosis.codedAnswer.uuid : undefined}, + codedAnswer: { uuid: !diagnosis.isNonCodedAnswer ? conceptSystem + diagnosis.codedAnswer.uuid : undefined}, freeTextAnswer: diagnosis.isNonCodedAnswer ? diagnosis.codedAnswer.name : undefined, order: diagnosis.order, certainty: diagnosis.certainty, diff --git a/ui/app/clinical/consultation/models/drugSearchResult.js b/ui/app/clinical/consultation/models/drugSearchResult.js index 48bca0d935..f0bf48f9c4 100644 --- a/ui/app/clinical/consultation/models/drugSearchResult.js +++ b/ui/app/clinical/consultation/models/drugSearchResult.js @@ -18,7 +18,9 @@ Bahmni.Clinical.DrugSearchResult = (function () { var getMatcher = function (searchString) { return function (value) { // return value.search(new RegExp(searchString, "i")) !== -1 - return _.includes(value.toLowerCase(), searchString.toLowerCase()); + return _.every(searchString.split(" "), function (word) { + return _.includes(value.toLowerCase(), word.toLowerCase()); + }); }; }; var getSynonymCreator = function (drug) { diff --git a/ui/app/clinical/consultation/views/treatmentSections/addTreatment.html b/ui/app/clinical/consultation/views/treatmentSections/addTreatment.html index 6b4356fba7..433feded7c 100644 --- a/ui/app/clinical/consultation/views/treatmentSections/addTreatment.html +++ b/ui/app/clinical/consultation/views/treatmentSections/addTreatment.html @@ -259,9 +259,54 @@

0" class="cdss-alerts"> + {{"CDSS_" + cdssaAlerts[0].indicator.toUpperCase() | translate}} +

+ +
+ + +
+
+ {{cdssAlert.summary}} + +
+
+ {{cdssAlert.detail}} + + + +
+
+ +
+ +
+ +
+
+ +
+ +
+
+ +
diff --git a/ui/app/common/constants.js b/ui/app/common/constants.js index 9fee2e0da5..e3ab952161 100644 --- a/ui/app/common/constants.js +++ b/ui/app/common/constants.js @@ -15,6 +15,7 @@ Bahmni.Common = Bahmni.Common || {}; var BASE_URL = hostUrl + "/bahmni_config/openmrs/apps/"; var CUSTOM_URL = hostUrl + "/implementation_config/openmrs/apps/"; var IE_APPS_API = RESTWS_V1 + "/bahmniie"; + var FHIR_BASE_URL = hostUrl + "/openmrs/ws/fhir2/R4"; var serverErrorMessages = [ { @@ -75,11 +76,14 @@ Bahmni.Common = Bahmni.Common || {}; diseaseTemplateUrl: BAHMNI_CORE + "/diseaseTemplates", AllDiseaseTemplateUrl: BAHMNI_CORE + "/diseaseTemplate", emrapiConceptUrl: EMRAPI + "/concept", + bahmniapiConceptUrl: BAHMNI_COMMONS + "/terminologies/concepts", encounterConfigurationUrl: BAHMNI_CORE + "/config/bahmniencounter", patientConfigurationUrl: BAHMNI_CORE + "/config/patient", drugOrderConfigurationUrl: BAHMNI_CORE + "/config/drugOrders", emrEncounterUrl: EMRAPI + "/encounter", encounterUrl: RESTWS_V1 + "/encounter", + cdssUrl: RESTWS_V1 + "/cdss", + fhirMedicationsUrl: FHIR_BASE_URL + "/Medication", locationUrl: RESTWS_V1 + "/location", bahmniVisitLocationUrl: BAHMNI_CORE + "/visitLocation", bahmniFacilityLocationUrl: BAHMNI_CORE + "/facilityLocation", diff --git a/ui/app/common/domain/services/diagnosisService.js b/ui/app/common/domain/services/diagnosisService.js index f00bc5ea39..38309c5527 100644 --- a/ui/app/common/domain/services/diagnosisService.js +++ b/ui/app/common/domain/services/diagnosisService.js @@ -4,7 +4,7 @@ angular.module('bahmni.common.domain') .service('diagnosisService', ['$http', '$rootScope', function ($http, $rootScope) { var self = this; this.getAllFor = function (searchTerm, locale) { - var url = Bahmni.Common.Constants.emrapiConceptUrl; + var url = Bahmni.Common.Constants.bahmniapiConceptUrl; var parameters = {term: searchTerm, limit: Bahmni.Common.Constants.emrapiDiagnosisLimit}; if (locale) { parameters.locale = locale; @@ -25,6 +25,10 @@ angular.module('bahmni.common.domain') var url = Bahmni.Common.Constants.bahmniDeleteDiagnosisUrl; return $http.get(url, { params: {obsUuid: obsUuid} + }, function (response) { + return response; + }, function (error) { + return error; }); }; diff --git a/ui/app/common/services/drugService.js b/ui/app/common/services/drugService.js index d53ed6d870..f90c264b20 100644 --- a/ui/app/common/services/drugService.js +++ b/ui/app/common/services/drugService.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('bahmni.common.services') .factory('drugService', ['$http', function ($http) { - var v = 'custom:(uuid,strength,name,dosageForm,concept:(uuid,name,names:(name)))'; + var v = 'custom:(uuid,strength,drugReferenceMaps,name,dosageForm,concept:(uuid,name,names:(name)))'; var search = function (drugName, conceptUuid) { var params = { v: v, @@ -46,9 +46,52 @@ angular.module('bahmni.common.services') }); }; + var sendDiagnosisDrugBundle = function (bundle) { + return $http.post(Bahmni.Common.Constants.cdssUrl, bundle, { + withCredentials: true, + params: { service: 'medication-order-select' } + }); + }; + + var cdssAudit = function (patientUuid, eventType, message, module) { + var alertData = { + patientUuid: patientUuid, + eventType: eventType, + message: message, + module: module + }; + return $http.post(Bahmni.Common.Constants.auditLogUrl, alertData, { + withCredentials: true + }); + }; + + var getDrugConceptSourceMapping = function (drugUuid) { + var params = { + _id: drugUuid + }; + + return $http.get(Bahmni.Common.Constants.fhirMedicationsUrl, { + params: params, + withCredentials: true + }); + }; + var getCdssEnabled = function () { + return $http.get(Bahmni.Common.Constants.globalPropertyUrl, { + method: "GET", + params: { + property: 'cdss.enable' + }, + withCredentials: true + }); + }; + return { search: search, getRegimen: getRegimen, - getSetMembersOfConcept: getSetMembersOfConcept + getSetMembersOfConcept: getSetMembersOfConcept, + sendDiagnosisDrugBundle: sendDiagnosisDrugBundle, + getDrugConceptSourceMapping: getDrugConceptSourceMapping, + getCdssEnabled: getCdssEnabled, + cdssAudit: cdssAudit }; }]); diff --git a/ui/app/common/ui-helper/services/messagingService.js b/ui/app/common/ui-helper/services/messagingService.js index 691152057a..a03bb6456a 100644 --- a/ui/app/common/ui-helper/services/messagingService.js +++ b/ui/app/common/ui-helper/services/messagingService.js @@ -11,9 +11,12 @@ angular.module('bahmni.common.uiHelper') this.showMessage = function (level, message, errorEvent) { var messageObject = {'value': '', 'isServerError': false}; - messageObject.value = message; + messageObject.value = message.replace(/\[|\]|null/g, ''); if (errorEvent) { messageObject.isServerError = true; + if (!self.messages[level].length) { + this.createTimeout('error', 6000); + } } else if (level == 'info') { this.createTimeout('info', 4000); } @@ -25,7 +28,9 @@ angular.module('bahmni.common.uiHelper') if (index >= 0) { this.messages[level].splice(index, 1); } - this.messages[level].push(messageObject); + if (messageObject.value) { + this.messages[level].push(messageObject); + } }; this.createTimeout = function (level, time) { diff --git a/ui/app/i18n/clinical/locale_en.json b/ui/app/i18n/clinical/locale_en.json index da34278d2c..9eb008c78f 100644 --- a/ui/app/i18n/clinical/locale_en.json +++ b/ui/app/i18n/clinical/locale_en.json @@ -371,5 +371,18 @@ "SHARE_PRESCRIPTION_MAIL_CONTENT": "Hi #recipientName,\nThanks for visiting #locationName on #visitDate. Your prescription is attached with this email. Wish you a speedy recovery.\nThanks.\n#locationName\n#locationAddress", "CHIEF_COMPLAINT_CODED_KEY": "Chief Complaint Coded", "SIGN_SYMPTOM_DURATION_KEY": "Sign/symptom duration", - "CHIEF_COMPLAINT_DURATION_UNIT_KEY": "Chief Complaint Duration" + "CHIEF_COMPLAINT_DURATION_UNIT_KEY": "Chief Complaint Duration", + "FALSE_POSITIVE_ALERT": "The alert triggered, but it was a false positive and no action is needed.", + "NOT_APPLICABLE_TO_THE_PATIENT": "The alert does not apply to the patient in question.", + "ALREADY_RESOLVED_BY_MEDICATION_ADJUSTMENT": "The alert was previously resolved by adjusting the patient's medication.", + "ALREADY_MANAGED_BY_OTHER_MEANS": "The alert was previously managed by other means, and no further action is needed.", + "PATIENT_DECLINED_RECOMMENDED_ACTION": "The patient declined the recommended action despite the alert.", + "CLINICIAN_JUDGMENT_OVERRODE_RECOMMENDATION": "The clinician used their judgment to override the recommendation generated by the alert.", + "ALERT_TRIGGERED_IN_ERROR": "The alert triggered in error, and no action is needed.", + "INSUFFICIENT_INFORMATION_TO_ACT_ON_ALERT": "There is not enough information available to act on the alert.", + "CDSS_WARNING" :"Warning", + "CDSS_CRITICAL" :"Critical", + "CDSS_ALERT_DISMISSAL_REASON" :"Select reason for dismissal", + "CDSS_INFO" :"Info", + "CDSS_ALERT_DISMISS": "Dismiss" } diff --git a/ui/app/styles/clinical/treatment/_treatment.scss b/ui/app/styles/clinical/treatment/_treatment.scss index 4d931fc9e8..b8fe95d527 100644 --- a/ui/app/styles/clinical/treatment/_treatment.scss +++ b/ui/app/styles/clinical/treatment/_treatment.scss @@ -423,7 +423,7 @@ } } - h3.orderSet-additional-info { + h3.orderSet-additional-info, h3.cdss-alerts { font-family: OpenSansBold; color: $darkGray; font-size: 13px; @@ -432,6 +432,104 @@ margin: 0 0 10px; } + .cdss-alert { + position: relative; + margin: 0 0 10px; + padding: 10px; + border-radius: 3px; + box-sizing: border-box; + font-size: 13px; + color: $darkGray; + line-height: 1.5em; + display: flex; + + > i { + flex-shrink: 0; + } + > div { + margin-left: 0.75rem; + margin-right: 0.75rem; + } + + .cdss-alert-text { + display: inline-block; + vertical-align: middle; + } + &.alert-danger { + background: #FFD6D8; + i { + color: #FF0000; + } + } + &.alert-warning { + background: #FEEAD6; + i { + color: #FFA500; + } + } + &.alert-info { + background: #D5F5FF; + i { + color: #00A3E0; + } + } + .cdss-alert-summary { + cursor: pointer; + position: relative; + i { + position: absolute; + right: -15px; + bottom: 0px; + line-height: 1; + color: $darkGray; + text-shadow: 0 1px 0 #fff; + } + } + + .cdss-alert-details { + margin-top: 10px; + .fa { + cursor: pointer; + display: inline-block; + width: 18px; + height: 18px; + line-height: 18px; + text-align: center; + border-radius: 100%; + font-size: 20px; + color: #669999; + box-shadow: 1px 1px 1px #ccc; + background: #FFFFFF; + padding: 0; + margin-left: 5px; + } + } + + .cdss-alert-close { + position: absolute; + right: 0; + top: 0; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + background: transparent; + width: 1.5rem; + height: 1.5rem; + text-align: center; + border-radius: 50%; + border: none; + padding: 0; + cursor: pointer; + transition: opacity .15s ease-in-out; + } + } + + .cdss-alert-close-reason { + width: 100% !important; + } + #SOS { margin-right: 5px; line-height: .9em; diff --git a/ui/test/unit/clinical/consultation/controllers/diagnosisController.spec.js b/ui/test/unit/clinical/consultation/controllers/diagnosisController.spec.js index 3176ca0da9..59b7d5939d 100644 --- a/ui/test/unit/clinical/consultation/controllers/diagnosisController.spec.js +++ b/ui/test/unit/clinical/consultation/controllers/diagnosisController.spec.js @@ -107,6 +107,18 @@ describe("Diagnosis Controller", function () { expect(list[0].lookup.name).toBe("Cold xyz"); }); }); + + it("should make a call to diagnosis service getAllFor with concept source code", function () { + spyOn(mockDiagnosisService, 'getAllFor').and.returnValue(specUtil.simplePromise({data: [{"conceptName": "Cold, unspec.", "conceptUuid": "uuid1", "matchedName": null, "code": "T69.9XXA", "conceptSystem": "http://snomed.info/sct"}]})); + $scope.getDiagnosis({term: "T69.9XXA"}).then(function (list) { + expect(mockDiagnosisService.getAllFor).toHaveBeenCalledWith("T69.9XXA", "en"); + expect(list.length).toBe(1); + expect(list[0].value).toBe("Cold, unspec. (T69.9XXA)"); + expect(list[0].concept.name).toBe("Cold, unspec."); + expect(list[0].concept.uuid).toBe("uuid1"); + expect(list[0].lookup.conceptSystem).toBe("http://snomed.info/sct"); + }); + }); }); describe("should validate the diagnosis", function(){ diff --git a/ui/test/unit/clinical/controllers/addTreatmentController.spec.js b/ui/test/unit/clinical/controllers/addTreatmentController.spec.js index 734cc3caa4..4d675c3f1b 100644 --- a/ui/test/unit/clinical/controllers/addTreatmentController.spec.js +++ b/ui/test/unit/clinical/controllers/addTreatmentController.spec.js @@ -1,7 +1,6 @@ 'use strict'; describe("AddTreatmentController", function () { - beforeEach(module('bahmni.common.uiHelper')); beforeEach(module('bahmni.common.services')); beforeEach(module('bahmni.clinical')); @@ -108,12 +107,10 @@ describe("AddTreatmentController", function () { "provider": {name: "superman"} }; - var $q, scope, stateParams, rootScope, contextChangeHandler, newTreatment, editTreatment, clinicalAppConfigService, ngDialog, drugService, drugs, encounterDateTime, appService, appConfig, defaultDrugsPromise, orderSetService, locationService; - stateParams = { tabConfigName: null }; @@ -168,9 +165,9 @@ describe("AddTreatmentController", function () { orderSetService.getCalculatedDose.and.returnValue(specUtil.respondWithPromise($q, { dose: 20, doseUnit: 'mg' })); - locationService = jasmine.createSpyObj('locationService', ['getLoggedInLocation']) + locationService = jasmine.createSpyObj('locationService', ['getLoggedInLocation']); - drugService = jasmine.createSpyObj('drugService', ['getSetMembersOfConcept']); + drugService = jasmine.createSpyObj('drugService', ['getSetMembersOfConcept', 'sendDiagnosisDrugBundle', 'getCdssEnabled', 'cdssAudit', 'getDrugConceptSourceMapping']); drugs = [ {name: "T", dosageForm: {display: "something"}, uuid: "123-12321"}, {name: "A", dosageForm: {display: "something"}, uuid: "123-12321"}, @@ -178,6 +175,10 @@ describe("AddTreatmentController", function () { ]; defaultDrugsPromise = specUtil.respondWith(drugs); drugService.getSetMembersOfConcept.and.returnValue(defaultDrugsPromise); + drugService.sendDiagnosisDrugBundle.and.returnValue(specUtil.respondWith([])); + drugService.getCdssEnabled.and.returnValue(specUtil.respondWith(true)); + drugService.cdssAudit.and.returnValue(specUtil.respondWith(true)); + drugService.getDrugConceptSourceMapping.and.returnValue(specUtil.respondWithPromise($q, {entry: []})); appService.getAppDescriptor.and.returnValue(appConfig); orderSets = [{ @@ -217,10 +218,10 @@ describe("AddTreatmentController", function () { results: orderSets } }, - then : function(cb) { + then: function (cb) { cb(this.response); } - } + }; orderSetService.getOrderSetsByQuery.and.returnValue(fakePromise); $controller('AddTreatmentController', { $scope: scope, @@ -232,7 +233,7 @@ describe("AddTreatmentController", function () { clinicalAppConfigService: clinicalAppConfigService, ngDialog: ngDialog, appService: appService, - locationService :locationService, + locationService: locationService, drugService: drugService, treatmentConfig: treatmentConfig, orderSetService: orderSetService @@ -241,7 +242,7 @@ describe("AddTreatmentController", function () { scope.orderSetTreatments = []; scope.newOrderSet = {}; scope.getFilteredOrderSets('dumm'); - }) + }); }; beforeEach(initController); @@ -265,7 +266,7 @@ describe("AddTreatmentController", function () { describe("add()", function () { beforeEach(function () { scope.treatments = []; - }) + }); it("adds treatment object to list of treatments if newOrderSet flag is false", function () { var treatment = Bahmni.Tests.drugOrderViewModelMother.buildWith({}, {drug: {name: true}}); @@ -415,7 +416,7 @@ describe("AddTreatmentController", function () { scope.add(); expect(scope.treatments.length).toEqual(2); var drugOrderToBeSaved = scope.treatments.filter(function (treatment) { - return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-11-30") + return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-11-30"); })[0]; expect(DateUtil.isSameDateTime(drugOrderToBeSaved.effectiveStopDate, DateUtil.subtractSeconds("2014-12-02", 1))).toBeTruthy(); }); @@ -454,6 +455,60 @@ describe("AddTreatmentController", function () { expect(scope.treatments[2].drug.name).toEqual("ghi"); }); + describe("create FHIR bundle", function () { + var data = { + conditions: [], + diagnosis: [ + { + codedAnswer: { + name: 'Disease X', + uuid: '235856003', + conceptSystem: 'http://snomed.info/sct' + }, + certainty: 'CONFIRMED', + conceptName: 'Disease X' + } + ], + medications: [ + { + drugNameDisplay: 'Medication A 10 mg (Tablet)', + drug: { + name: 'Medication A 10 mg', + uuid: 'ea21e269-0129-42ec-b769-346d7085157c', + drugReferenceMaps: [ + { + display: 'Medication A 10 mg - SAME-AS', + uuid: 'a8c89f08-5eb0-428f-b934-201fabe8221b', + drug: { + uuid: 'ea21e269-0129-42ec-b769-346d7085157c', + display: 'Medication A 10 mg' + }, + conceptReferenceTerm: { + uuid: '041bbed8-8319-445a-baa8-ef994898edd9', + display: 'SNOMED: 108600003' + }, + conceptMapType: { + uuid: '35543629-7d8c-11e1-909d-c80aa9edcf4e', + display: 'SAME-AS' + } + } + ] + } + } + ] + }; + + it("should create FHIR bundle with diagnosis and medication orders", function () { + scope.consultation.newlyAddedDiagnoses = data.diagnosis; + scope.treatments = data.medications; + scope.createFhirBundle(scope.patient, data.conditions, data.medications, data.diagnosis).then(function (bundle) { + expect(bundle.entry.length).toBe(2); + expect(bundle.entry[0].resource.resourceType).toBe('Condition'); + expect(bundle.entry[1].resource.resourceType).toBe('MedicationRequest'); + }); + }); + }); + describe("add free text drug order()", function () { it("should save as a free text drug order on click of accept button", function () { var treatment = {drugNameDisplay: "Some New Drug", drug: {name: "CodedDrug"}}; @@ -469,7 +524,13 @@ describe("AddTreatmentController", function () { var treatment = {drugNameDisplay: "Some New Drug", drug: {name: "CodedDrug"}}; scope.treatment = treatment; treatment.changeDrug = jasmine.createSpy(treatment, 'changeDrug'); - + scope.consultation = { + patient: { + uuid: 'a751f0da-39ab-45a3-db52-21706f5ed201' + }, + conditions: [], + newlyAddedDiagnoses: [] + }; scope.onSelect({ drug: { name: "CodedDrug", @@ -482,9 +543,10 @@ describe("AddTreatmentController", function () { scope.onChange(); expect(treatment.changeDrug).toHaveBeenCalledWith({ - name: "CodedDrug", - form: "Once", - uuid: "CodedDrugUuid" + name: 'CodedDrug', + form: 'Once', + uuid: 'CodedDrugUuid', + drugReferenceMaps: undefined }); expect(scope.treatment.selectedItem).toBeUndefined(); @@ -520,6 +582,41 @@ describe("AddTreatmentController", function () { }); }); + describe("cdss alerts", function () { + var alerts = [ + { + uuid: 'some-uuid', + indicator: 'critical', + summary: 'Contraindication: Some Coded Drug is contraindicated with Some condition', + detail: 'Some Coded Drug is contraindicated with Some condition' + } + ]; + + beforeEach(function () { + scope.cdssaAlerts = alerts; + }); + + it("should close alert on clicking close button", function () { + scope.closeAlert(0); + expect(scope.cdssaAlerts.length).toBe(0); + }); + + it("should toggle alert details on clicking toggle button", function () { + scope.toggleAlertDetails(0); + expect(scope.cdssaAlerts[0].showDetails).toBeTruthy(); + scope.toggleAlertDetails(0); + expect(scope.cdssaAlerts[0].showDetails).toBeFalsy(); + }); + + it("should dismiss critical alert on submitting an audit", function () { + scope.patient = {uuid: 'some-user-uuid'}; + scope.treatment = {audit: "some-audit"}; + scope.submitAudit(0).then(function () { + expect(scope.cdssaAlerts.length).toBe(0); + }); + }); + }); + describe("isEffectiveStartDateSameAsToday", function () { var originalDateUtilNow = DateUtil.now; var today = new Date("December 17, 2007 03:24:00"); @@ -584,14 +681,12 @@ describe("AddTreatmentController", function () { }); }); describe("Detect Overlapping orders amongst new orders on Save", function () { - describe("should allow potentially overlapping order whose dates can be set and be resolved", function () { - var encounterDate = DateUtil.parse("2014-12-02"); beforeEach(function () { scope.treatments = []; - }) + }); it("new drug orders for dates 2-4 and 5-6 and 4-5 in this order", function () { var dec2_dec4order = Bahmni.Tests.drugOrderViewModelMother.buildWith({}, @@ -637,7 +732,7 @@ describe("AddTreatmentController", function () { expect(scope.treatment).not.toEqual(dec5_dec6order); expect(scope.treatments.length).toEqual(2); var dec5_dec6orderAfterSave = scope.treatments.filter(function (treatment) { - return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-12-05") + return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-12-05"); })[0]; expect(DateUtil.isSameDateTime(dec5_dec6orderAfterSave.effectiveStartDate, DateUtil.parse("2014-12-05"))).toBeTruthy(); @@ -651,7 +746,7 @@ describe("AddTreatmentController", function () { expect(scope.treatment).not.toEqual(dec4_dec5order); expect(scope.treatments.length).toEqual(3); var dec4_dec5orderAfterSave = scope.treatments.filter(function (treatment) { - return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-12-04") + return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-12-04"); })[0]; expect(DateUtil.isSameDateTime(dec4_dec5orderAfterSave.effectiveStartDate, DateUtil.parse("2014-12-04"))).toBeTruthy(); @@ -704,7 +799,7 @@ describe("AddTreatmentController", function () { expect(scope.treatment).not.toEqual(dec4_dec5order); expect(scope.treatments.length).toEqual(2); var dec4_dec5orderAfterSave = scope.treatments.filter(function (treatment) { - return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-12-04") + return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-12-04"); })[0]; expect(DateUtil.isSameDateTime(dec4_dec5orderAfterSave.effectiveStartDate, DateUtil.parse("2014-12-04"))).toBeTruthy(); @@ -718,7 +813,7 @@ describe("AddTreatmentController", function () { expect(scope.treatment).not.toEqual(dec5_dec6order); expect(scope.treatments.length).toEqual(3); var dec5_dec6orderAfterSave = scope.treatments.filter(function (treatment) { - return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-12-05") + return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-12-05"); })[0]; expect(DateUtil.isSameDateTime(dec5_dec6orderAfterSave.effectiveStartDate, DateUtil.parse("2014-12-05"))).toBeTruthy(); @@ -772,7 +867,7 @@ describe("AddTreatmentController", function () { expect(scope.treatment).not.toEqual(dec5_dec6order); expect(scope.treatments.length).toEqual(2); var dec5_dec6orderAfterSave = scope.treatments.filter(function (treatment) { - return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-12-05") + return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-12-05"); })[0]; expect(DateUtil.isSameDateTime(dec5_dec6orderAfterSave.effectiveStartDate, DateUtil.parse("2014-12-05"))).toBeTruthy(); @@ -786,7 +881,7 @@ describe("AddTreatmentController", function () { expect(scope.treatment).not.toEqual(dec4_dec5order); expect(scope.treatments.length).toEqual(3); var dec4_dec5orderAfterSave = scope.treatments.filter(function (treatment) { - return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-12-04") + return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-12-04"); })[0]; expect(DateUtil.isSameDateTime(dec4_dec5orderAfterSave.effectiveStartDate, DateUtil.parse("2014-12-04"))).toBeTruthy(); @@ -794,7 +889,6 @@ describe("AddTreatmentController", function () { expect(DateUtil.isSameDateTime(dec4_dec5orderAfterSave.scheduledDate, DateUtil.parse("2014-12-04"))).toBeTruthy(); expect(dec4_dec5orderAfterSave.autoExpireDate).toBeUndefined(); }); - }); describe("should allow potentially overlapping order whose dates can be set and be resolved", function () { @@ -802,7 +896,7 @@ describe("AddTreatmentController", function () { beforeEach(function () { scope.treatments = []; - }) + }); it("existing drug orders for dates 2-3 and 3-4 and revised drug order for 2-3", function () { var dec2_dec3order = Bahmni.Tests.drugOrderViewModelMother.buildWith({}, { @@ -868,19 +962,17 @@ describe("AddTreatmentController", function () { scope.add(); expect(scope.treatments.length).toEqual(1); expect(DateUtil.isSameDateTime(dec2_dec4order.autoExpireDate, DateUtil.subtractSeconds("2014-12-04 00:00:00", 1))).toBeTruthy(); - - }) + }); }); describe("should not allow overlapping order", function () { var encounterDate = DateUtil.parse("2014-12-02"); beforeEach(function () { - scope.treatments = [] - }) + scope.treatments = []; + }); it("new orders for dates 2-4 and 3-6", function () { - var dec2_dec4order = Bahmni.Tests.drugOrderViewModelMother.buildWith({}, { drug: { name: "abc", @@ -1036,7 +1128,6 @@ describe("AddTreatmentController", function () { scope.add(); expect(scope.treatments.length).toEqual(2); - var overlappingOrder = Bahmni.Tests.drugOrderViewModelMother.buildWith({}, { drug: { name: "abc", @@ -1102,7 +1193,6 @@ describe("AddTreatmentController", function () { }); describe("Detect Overlapping orders with existing Orders on Save", function () { - describe("should allow potentially overlapping order whose dates can be set and be resolved", function () { var encounterDate = DateUtil.parse("2014-12-02"); @@ -1142,7 +1232,7 @@ describe("AddTreatmentController", function () { scope.add(); expect(scope.treatments.length).toEqual(3); var drugOrderToBeSaved = scope.treatments.filter(function (treatment) { - return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-12-04") + return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-12-04"); })[0]; expect(DateUtil.isSameDateTime(drugOrderToBeSaved.effectiveStartDate, DateUtil.parse("2014-12-04"))).toBeTruthy(); @@ -1187,7 +1277,7 @@ describe("AddTreatmentController", function () { scope.add(); expect(scope.treatments.length).toEqual(3); var drugOrderToBeSaved = scope.treatments.filter(function (treatment) { - return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-12-06") + return DateUtil.isSameDate(treatment.effectiveStartDate, "2014-12-06"); })[0]; expect(DateUtil.isSameDateTime(drugOrderToBeSaved.effectiveStartDate, DateUtil.parse("2014-12-06"))).toBeTruthy(); expect(DateUtil.isSameDateTime(drugOrderToBeSaved.effectiveStopDate, DateUtil.parse("2014-12-07"))).toBeTruthy(); @@ -1196,9 +1286,7 @@ describe("AddTreatmentController", function () { }); }); - describe("should not allow overlapping order", function () { - it("should not allow conflicting orders for dates 2-4 and new drug order for 3-6", function () { var encounterDate = DateUtil.parse("2014-12-02"); @@ -1359,8 +1447,8 @@ describe("AddTreatmentController", function () { durationInDays: 2, concept: { name: "abc", - shortName:"abc" - }, + shortName: "abc" + } }, encounterDate); var dec5_dec6order = Bahmni.Tests.drugOrderViewModelMother.buildWith({}, { drug: { @@ -1392,10 +1480,9 @@ describe("AddTreatmentController", function () { }); describe("After selection from ng-dialog", function () { - beforeEach(function () { scope.treatments = []; - }) + }); it("should edit the drug order if conflicting order is unsaved when revise is selected", function () { var encounterDate = DateUtil.parse("2014-12-02"); @@ -1431,7 +1518,6 @@ describe("AddTreatmentController", function () { expect(dec2_dec4order.isBeingEdited).toBeTruthy(); expect(scope.treatment.isBeingEdited).toBeTruthy(); expect(scope.treatments.length).toBe(1); - }); it("should edit the drug order if conflicting order is a saved order when revise is selected", function () { var encounterDate = DateUtil.parse("2014-12-02"); @@ -1449,7 +1535,6 @@ describe("AddTreatmentController", function () { scope.consultation.activeAndScheduledDrugOrders = [dec2_dec4order]; expect(scope.treatments.length).toEqual(0); - var new_dec2_dec4order = Bahmni.Tests.drugOrderViewModelMother.buildWith({}, { drug: { name: "abc", @@ -1472,12 +1557,9 @@ describe("AddTreatmentController", function () { expect(scope.treatment.previousOrderUuid).toBe("some-uuid"); scope.add(); expect(scope.treatments.length).toEqual(1); - }); - }); - describe("Save", function () { it("should check for any incomplete drug orders", function () { scope.treatment.drug = {name: "calpol"}; @@ -1487,7 +1569,6 @@ describe("AddTreatmentController", function () { scope.addForm = {$invalid: true, $valid: false}; expect(scope.incompleteDrugOrders()).toBeTruthy(); - }); it("should check for any unadded drug orders", function () { scope.addForm = {$valid: true}; @@ -1510,7 +1591,7 @@ describe("AddTreatmentController", function () { }; beforeEach(function () { - scope.treatments = [] + scope.treatments = []; }); it("should do nothing if form is blank", function () { @@ -1542,7 +1623,6 @@ describe("AddTreatmentController", function () { scope.clearForm(); expect(scope.startNewDrugEntry).toBeTruthy(); }); - }); describe("Edit DrugOrder()", function () { @@ -1592,7 +1672,6 @@ describe("AddTreatmentController", function () { }); describe("saveTreatment()", function () { - it("should not save the treatment if a discontinued drug order is added at the same time", function () { var drugOrder = Bahmni.Tests.drugOrderViewModelMother.build({}, []); drugOrder.durationUnit = {name: "Days"}; @@ -1606,7 +1685,6 @@ describe("AddTreatmentController", function () { scope.consultation.newlyAddedTreatments = []; scope.consultation.newlyAddedTreatments.push(drugOrder); - var discontinuedDrug = drugOrder; discontinuedDrug.isMarkedForDiscontinue = true; @@ -1657,7 +1735,6 @@ describe("AddTreatmentController", function () { describe("when discontinued", function () { it("should mark the drug order for discontinue", function () { - var drugOrder = Bahmni.Clinical.DrugOrderViewModel.createFromContract(activeDrugOrder); rootScope.$broadcast("event:discontinueDrugOrder", drugOrder); @@ -1730,12 +1807,11 @@ describe("AddTreatmentController", function () { expect(scope.consultation.discontinuedDrugs.length).toBe(1); expect(scope.consultation.discontinuedDrugs[0]).toBe(drugOrder1); - }) + }); }); describe("add orderset", function () { it("should add order set drugs to orderSetTreatments list in scope", function () { - var orderSetDate = moment("2015-03-02").toDate(); var stopDate = moment("2015-03-04").toDate(); scope.newOrderSet.date = orderSetDate; @@ -1754,10 +1830,8 @@ describe("AddTreatmentController", function () { expect(firstOrderSetTreatment.durationUnit).toEqual("Day(s)"); expect(firstOrderSetTreatment.additionalInstructions).toEqual("Additional Instructions"); expect(firstOrderSetTreatment.quantity).toEqual(80); - //expect(ngDialog.open).not.toHaveBeenCalled(); + // expect(ngDialog.open).not.toHaveBeenCalled(); expect(scope.isSearchDisabled).toBeTruthy(); - - }); it('should reset include flag for all orderSetTreatments if any of them is conflicting with active or scheduled drug', function () { @@ -1776,8 +1850,7 @@ describe("AddTreatmentController", function () { expect(scope.orderSetTreatments[0].include).toBeFalsy(); expect(scope.orderSetTreatments[1].include).toBeFalsy(); expect(ngDialog.open).toHaveBeenCalled(); - - }) + }); }); describe("remove orderset", function () { @@ -1793,7 +1866,7 @@ describe("AddTreatmentController", function () { expect(scope.orderSetTreatments.length).toBe(0); expect(scope.newOrderSet).toEqual({}); expect(scope.isSearchDisabled).toBeFalsy(); - }) + }); }); describe('include orderSetMember checkbox', function () { @@ -1816,6 +1889,6 @@ describe("AddTreatmentController", function () { expect(orderSetDrugOrder.include).toBeFalsy(); expect(ngDialog.open).toHaveBeenCalled(); - }) - }) + }); + }); }); diff --git a/ui/test/unit/clinical/models/drugSearchResult.spec.js b/ui/test/unit/clinical/models/drugSearchResult.spec.js index 3364f93193..553b0cd14a 100644 --- a/ui/test/unit/clinical/models/drugSearchResult.spec.js +++ b/ui/test/unit/clinical/models/drugSearchResult.spec.js @@ -58,6 +58,20 @@ describe("DrugSchedule", function () { expect(allMatchingSynonyms[0].label).toBe("paracetamoluse => Paracetamol 200mg"); }); + it("should return only the search results of drugs whose name matches with multiple prefix search string",function () { + var drug = {name: "Diphenhydramine hydrochloride 25 mg tablet", dosageForm: null, concept:{ + names:[ + {name:"Diphenhydramine hydrochloride"} + ] + }}; + + var searchString = "Diph hy"; + var allMatchingSynonyms = Bahmni.Clinical.DrugSearchResult.getAllMatchingSynonyms(drug, searchString); + + expect(allMatchingSynonyms.length).toBe(1); + expect(allMatchingSynonyms[0].label).toBe("Diphenhydramine hydrochloride 25 mg tablet"); + }); + it("should return unique list of search results when more than one name is same",function () { var drug = {name: "Paracetamol 200mg", dosageForm: null, concept:{ names:[