From 66d17caf7e1bc64ae5eae401ac531f577cd19dfd Mon Sep 17 00:00:00 2001 From: Kevin Zurek Date: Fri, 12 May 2017 12:13:08 -0400 Subject: [PATCH] Spice up the inventory / formulary code -Separate ViewModels for custom/existing/formulary pages -Update instructions -Better error handeling for custom medications --- .../admin/InventoryController.java | 102 ++++++++-- .../admin/inventory/CustomViewModelGet.java | 39 ++++ ...odelPost.java => CustomViewModelPost.java} | 38 +--- .../admin/inventory/ExistingViewModelGet.java | 31 +++ .../inventory/ExistingViewModelPost.java | 18 ++ ...wModelGet.java => ManageViewModelGet.java} | 2 +- .../views/admin/inventory/custom.scala.html | 106 ++++++++++ .../views/admin/inventory/existing.scala.html | 54 +++++ .../views/admin/inventory/manage.scala.html | 188 ++++-------------- .../admin/inventory/inventoryMenu.scala.html | 26 +++ conf/routes | 5 +- public/css/admin/inventory.css | 10 + 12 files changed, 421 insertions(+), 198 deletions(-) create mode 100644 app/femr/ui/models/admin/inventory/CustomViewModelGet.java rename app/femr/ui/models/admin/inventory/{InventoryViewModelPost.java => CustomViewModelPost.java} (67%) create mode 100644 app/femr/ui/models/admin/inventory/ExistingViewModelGet.java create mode 100644 app/femr/ui/models/admin/inventory/ExistingViewModelPost.java rename app/femr/ui/models/admin/inventory/{InventoryViewModelGet.java => ManageViewModelGet.java} (98%) create mode 100644 app/femr/ui/views/admin/inventory/custom.scala.html create mode 100644 app/femr/ui/views/admin/inventory/existing.scala.html create mode 100644 app/femr/ui/views/partials/admin/inventory/inventoryMenu.scala.html diff --git a/app/femr/ui/controllers/admin/InventoryController.java b/app/femr/ui/controllers/admin/InventoryController.java index 34973ad0e..f8630e862 100644 --- a/app/femr/ui/controllers/admin/InventoryController.java +++ b/app/femr/ui/controllers/admin/InventoryController.java @@ -28,7 +28,7 @@ import femr.ui.helpers.security.FEMRAuthenticated; import femr.ui.models.admin.inventory.*; import femr.common.models.MedicationItem; -import femr.ui.views.html.admin.inventory.manage; +import femr.ui.views.html.admin.inventory.*; import play.data.DynamicForm; import play.data.Form; import play.data.FormFactory; @@ -68,11 +68,14 @@ public InventoryController(FormFactory formFactory, this.sessionService = sessionService; } + /** + * Serves up the inventory homepage. POST communication for updating quantity + * is handled by AJAX calls + */ public Result manageGet() { CurrentUser currentUser = sessionService.retrieveCurrentUserSession(); - - InventoryViewModelGet viewModel = new InventoryViewModelGet(); + ManageViewModelGet viewModel = new ManageViewModelGet(); // If the use does not have a trip ID, we cannot retrieve the list of medications // since they are tied to a trip @@ -80,11 +83,14 @@ public Result manageGet() { ServiceResponse> medicationServiceResponse = inventoryService.retrieveMedicationInventorysByTripId(currentUser.getTripId()); if (medicationServiceResponse.hasErrors()) { + throw new RuntimeException(); } else { + viewModel.setMedications(medicationServiceResponse.getResponseObject()); } + ServiceResponse missionTripServiceResponse = missionTripService.retrieveAllTripInformationByTripId(currentUser.getTripId()); if (missionTripServiceResponse.hasErrors()) { @@ -94,17 +100,28 @@ public Result manageGet() { viewModel.setMissionTripItem(missionTripServiceResponse.getResponseObject()); } - } - else{ + } else { - viewModel.setMedications( new ArrayList<>() ); + viewModel.setMedications(new ArrayList<>()); } - ServiceResponse> conceptMedicationServiceResponse = conceptService.retrieveAllMedicationConcepts(); - if (conceptMedicationServiceResponse.hasErrors()) { + return ok(manage.render(currentUser, viewModel)); + } + + + /** + * Page for adding a new custom medication + */ + public Result customGet() { + CurrentUser currentUser = sessionService.retrieveCurrentUserSession(); + + CustomViewModelGet viewModel = new CustomViewModelGet(); + + ServiceResponse> availableMedicationFormsResponse = medicationService.retrieveAvailableMedicationForms(); + if (availableMedicationFormsResponse.hasErrors()) { throw new RuntimeException(); } else { - viewModel.setConceptMedications(conceptMedicationServiceResponse.getResponseObject()); + viewModel.setAvailableForms(availableMedicationFormsResponse.getResponseObject()); } ServiceResponse> availableMedicationUnitsResponse = medicationService.retrieveAvailableMedicationUnits(); @@ -114,25 +131,28 @@ public Result manageGet() { viewModel.setAvailableUnits(availableMedicationUnitsResponse.getResponseObject()); } - ServiceResponse> availableMedicationFormsResponse = medicationService.retrieveAvailableMedicationForms(); - if (availableMedicationFormsResponse.hasErrors()) { + ServiceResponse missionTripServiceResponse = missionTripService.retrieveAllTripInformationByTripId(currentUser.getTripId()); + if (missionTripServiceResponse.hasErrors()) { + throw new RuntimeException(); } else { - viewModel.setAvailableForms(availableMedicationFormsResponse.getResponseObject()); + + viewModel.setMissionTripItem(missionTripServiceResponse.getResponseObject()); } - return ok(manage.render(currentUser, viewModel)); + return ok(custom.render(currentUser, viewModel)); } /** - * Handles the submission of a new medication from the Admin Inventory Tracking screen. + * Handles the submission of a new custom medication from an Admin */ - public Result managePost() { - + public Result customPost(){ CurrentUser currentUser = sessionService.retrieveCurrentUserSession(); - final Form inventoryViewModelPostForm = formFactory.form(InventoryViewModelPost.class); - Form form = inventoryViewModelPostForm.bindFromRequest(); + final Form inventoryViewModelPostForm = formFactory.form(CustomViewModelPost.class); + + Form form = inventoryViewModelPostForm.bindFromRequest(); + if (form.hasErrors()) { return redirect("/admin/inventory"); @@ -145,7 +165,9 @@ public Result managePost() { } - InventoryViewModelPost inventoryViewModelPost = form.bindFromRequest().get(); + CustomViewModelPost inventoryViewModelPost = form.bindFromRequest().get(); + + // create a new medicationItem for managing the compilation of active ingredients // (this could potentially be moved into the service layer) @@ -191,18 +213,56 @@ public Result managePost() { } + return redirect("/admin/inventory"); + } + + /** + * Page for adding a new medication from the concept dictionary + */ + public Result existingGet() { + CurrentUser currentUser = sessionService.retrieveCurrentUserSession(); + + ExistingViewModelGet viewModel = new ExistingViewModelGet(); + + ServiceResponse> conceptMedicationServiceResponse = conceptService.retrieveAllMedicationConcepts(); + if (conceptMedicationServiceResponse.hasErrors()) { + throw new RuntimeException(); + } else { + viewModel.setConceptMedications(conceptMedicationServiceResponse.getResponseObject()); + } + + ServiceResponse missionTripServiceResponse = missionTripService.retrieveAllTripInformationByTripId(currentUser.getTripId()); + if (missionTripServiceResponse.hasErrors()) { + + throw new RuntimeException(); + } else { + + viewModel.setMissionTripItem(missionTripServiceResponse.getResponseObject()); + } + + return ok(existing.render(currentUser, viewModel)); + } + + /** + * Handles the submission of an existing medication from an Admin + */ + public Result existingPost() { + CurrentUser currentUser = sessionService.retrieveCurrentUserSession(); + final Form existingViewModelPostForm = formFactory.form(ExistingViewModelPost.class); + Form existingForm = existingViewModelPostForm.bindFromRequest(); + ExistingViewModelPost existingViewModelPost = existingForm.bindFromRequest().get(); //if just adding medications from the concept dictionary, there won't be any amount involved //and knowledge of the ingredients already exists. - if (inventoryViewModelPost.getNewConceptMedicationsForInventory() != null) { + if (existingViewModelPost.getNewConceptMedicationsForInventory() != null) { ServiceResponse conceptMedicationServiceResponse; ServiceResponse medicationItemServiceResponse; MedicationItem conceptMedicationItem; //for each concept medication id that was sent from the select2 form - for (Integer conceptMedicationId : inventoryViewModelPost.getNewConceptMedicationsForInventory()) { + for (Integer conceptMedicationId : existingViewModelPost.getNewConceptMedicationsForInventory()) { //get the actual concept MedicationItem from the id that was sent in conceptMedicationServiceResponse = conceptService.retrieveConceptMedication(conceptMedicationId); diff --git a/app/femr/ui/models/admin/inventory/CustomViewModelGet.java b/app/femr/ui/models/admin/inventory/CustomViewModelGet.java new file mode 100644 index 000000000..6f1c6f8b9 --- /dev/null +++ b/app/femr/ui/models/admin/inventory/CustomViewModelGet.java @@ -0,0 +1,39 @@ +package femr.ui.models.admin.inventory; + +import femr.common.models.MissionTripItem; + +import java.util.List; + +/** + * Created by kevin on 14/05/17. + */ +public class CustomViewModelGet { + + private List availableUnits; + private List availableForms; + private MissionTripItem missionTripItem; + + public List getAvailableUnits() { + return availableUnits; + } + + public void setAvailableUnits(List availableUnits) { + this.availableUnits = availableUnits; + } + + public List getAvailableForms() { + return availableForms; + } + + public void setAvailableForms(List availableForms) { + this.availableForms = availableForms; + } + + public MissionTripItem getMissionTripItem() { + return missionTripItem; + } + + public void setMissionTripItem(MissionTripItem missionTripItem) { + this.missionTripItem = missionTripItem; + } +} diff --git a/app/femr/ui/models/admin/inventory/InventoryViewModelPost.java b/app/femr/ui/models/admin/inventory/CustomViewModelPost.java similarity index 67% rename from app/femr/ui/models/admin/inventory/InventoryViewModelPost.java rename to app/femr/ui/models/admin/inventory/CustomViewModelPost.java index 013108ab5..56b971e55 100644 --- a/app/femr/ui/models/admin/inventory/InventoryViewModelPost.java +++ b/app/femr/ui/models/admin/inventory/CustomViewModelPost.java @@ -24,7 +24,7 @@ import java.util.ArrayList; import java.util.List; -public class InventoryViewModelPost { +public class CustomViewModelPost { private Integer medicationQuantity; private String medicationForm; @@ -32,49 +32,31 @@ public class InventoryViewModelPost { private List medicationStrength; private List medicationUnit; private List medicationIngredient; - //this is a list of IDs that come out of the select2 textbox for adding - //existing medicine. - private List newConceptMedicationsForInventory; + public List validate(){ List errors = new ArrayList<>(); + //if nothing is entered for quantity, default to 0 if (medicationQuantity == null) { medicationQuantity = 0; //errors.add(new ValidationError("medicationQuantity", "quantity is a required field")); } // Based on fEMR-95 in JIRA. medicationForm is used to be able to add medication to inventory. - if (StringUtils.isNullOrWhiteSpace(medicationName) && newConceptMedicationsForInventory == null) + if (StringUtils.isNullOrWhiteSpace(medicationName)) errors.add(new ValidationError("medicationName", "name is a required field")); if (StringUtils.isNullOrWhiteSpace(medicationForm)) errors.add(new ValidationError("medicationForm", "a form is required")); // Based on the error from JIRA fEMR-278, generic name is required - if (newConceptMedicationsForInventory.isEmpty()){ - for(int i = 0; i < medicationIngredient.size(); i++){ - if(StringUtils.isNullOrWhiteSpace(medicationIngredient.get(i)) && medicationStrength.get(i) > 0.0){ - errors.add(new ValidationError("medicationGeneric", "a generic name is required")); - } + for (int i = 0; i < medicationIngredient.size(); i++) { + if (StringUtils.isNullOrWhiteSpace(medicationIngredient.get(i)) || medicationStrength.get(i) == null) { + errors.add(new ValidationError("medicationGeneric", "a generic name is required")); } } - - /* - for (Integer i : medicationStrength){ - if (i == null) - errors.add(new ValidationError("medicationStrength", "all strength fields are required")); - } - for (String ms : medicationUnit){ - if (StringUtils.isNullOrWhiteSpace(ms)) - errors.add(new ValidationError("medicationUnit", "all units are required")); - } - for (String mi : medicationIngredient){ - if (StringUtils.isNullOrWhiteSpace(mi)) - errors.add(new ValidationError("medicationIngredient", "all ingredients required")); - } -*/ return errors.isEmpty() ? null : errors; } @@ -127,11 +109,5 @@ public void setMedicationIngredient(List medicationIngredient) { this.medicationIngredient = medicationIngredient; } - public List getNewConceptMedicationsForInventory() { - return newConceptMedicationsForInventory; - } - public void setNewConceptMedicationsForInventory(List newConceptMedicationsForInventory) { - this.newConceptMedicationsForInventory = newConceptMedicationsForInventory; - } } diff --git a/app/femr/ui/models/admin/inventory/ExistingViewModelGet.java b/app/femr/ui/models/admin/inventory/ExistingViewModelGet.java new file mode 100644 index 000000000..596d8812f --- /dev/null +++ b/app/femr/ui/models/admin/inventory/ExistingViewModelGet.java @@ -0,0 +1,31 @@ +package femr.ui.models.admin.inventory; + +import femr.common.models.MedicationItem; +import femr.common.models.MissionTripItem; + +import java.util.List; + +/** + * Created by kevin on 14/05/17. + */ +public class ExistingViewModelGet { + + private List conceptMedications; + private MissionTripItem missionTripItem; + + public List getConceptMedications() { + return conceptMedications; + } + + public void setConceptMedications(List conceptMedications) { + this.conceptMedications = conceptMedications; + } + + public MissionTripItem getMissionTripItem() { + return missionTripItem; + } + + public void setMissionTripItem(MissionTripItem missionTripItem) { + this.missionTripItem = missionTripItem; + } +} diff --git a/app/femr/ui/models/admin/inventory/ExistingViewModelPost.java b/app/femr/ui/models/admin/inventory/ExistingViewModelPost.java new file mode 100644 index 000000000..082529d50 --- /dev/null +++ b/app/femr/ui/models/admin/inventory/ExistingViewModelPost.java @@ -0,0 +1,18 @@ +package femr.ui.models.admin.inventory; + +import java.util.List; + +public class ExistingViewModelPost { + + //this is a list of IDs that come out of the select2 textbox for adding + //existing medicine. + private List newConceptMedicationsForInventory; + + public List getNewConceptMedicationsForInventory() { + return newConceptMedicationsForInventory; + } + + public void setNewConceptMedicationsForInventory(List newConceptMedicationsForInventory) { + this.newConceptMedicationsForInventory = newConceptMedicationsForInventory; + } +} diff --git a/app/femr/ui/models/admin/inventory/InventoryViewModelGet.java b/app/femr/ui/models/admin/inventory/ManageViewModelGet.java similarity index 98% rename from app/femr/ui/models/admin/inventory/InventoryViewModelGet.java rename to app/femr/ui/models/admin/inventory/ManageViewModelGet.java index 022590715..347eb9d13 100644 --- a/app/femr/ui/models/admin/inventory/InventoryViewModelGet.java +++ b/app/femr/ui/models/admin/inventory/ManageViewModelGet.java @@ -23,7 +23,7 @@ import java.util.List; -public class InventoryViewModelGet { +public class ManageViewModelGet { private List medications; private List conceptMedications; private List availableUnits; diff --git a/app/femr/ui/views/admin/inventory/custom.scala.html b/app/femr/ui/views/admin/inventory/custom.scala.html new file mode 100644 index 000000000..3c2dc07cf --- /dev/null +++ b/app/femr/ui/views/admin/inventory/custom.scala.html @@ -0,0 +1,106 @@ +@(currentUser: femr.common.dtos.CurrentUser, viewModel: femr.ui.models.admin.inventory.CustomViewModelGet) + +@import femr.ui.controllers.admin.routes.InventoryController +@import femr.ui.views.html.partials.admin.inventory.inventoryMenu +@import femr.ui.views.html.layouts.admin + +@additionalStyles = { + + + +} +@additionalScripts = { + + + +} + +@admin("Inventory - Add Custom Medication", currentUser, styles = additionalStyles, scripts = additionalScripts) { + + @inventoryMenu(viewModel.getMissionTripItem) + + @if(currentUser.getTripId == null) { +
+ } + + @helper.form(action = InventoryController.customPost()) { + +

Add Custom Medicine To Formulary:

+
    +
  • If a medication does not exist in the concept dictionary, add it below
  • +
+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+
+
+ +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + + - + + +
+ + + + + +
+
+
+ +
+ +
+ @if(currentUser.getTripId == null) { +
+ } + + } +} \ No newline at end of file diff --git a/app/femr/ui/views/admin/inventory/existing.scala.html b/app/femr/ui/views/admin/inventory/existing.scala.html new file mode 100644 index 000000000..7eb5f14ad --- /dev/null +++ b/app/femr/ui/views/admin/inventory/existing.scala.html @@ -0,0 +1,54 @@ +@(currentUser: femr.common.dtos.CurrentUser, viewModel: femr.ui.models.admin.inventory.ExistingViewModelGet) + +@import femr.ui.controllers.admin.routes.InventoryController +@import femr.ui.views.html.layouts.admin +@import femr.ui.views.html.partials.admin.inventory.inventoryMenu + +@additionalStyles = { + + + + +} +@additionalScripts = { + + + + + +} + +@admin("Inventory - Add Existing Medication", currentUser, styles = additionalStyles, scripts = additionalScripts) { + + @inventoryMenu(viewModel.getMissionTripItem) + + @if(currentUser.getTripId == null) { +
+ } + + @helper.form(action = InventoryController.existingPost()) { + +

Add Existing Medicine To Formulary:

+
    +
  • Add medication(s) from fEMR's concept dictionary below
  • +
  • Adjust current/initial quantity in the Formulary after adding
  • +
+
+ + +
+ +
+
+ + @if(currentUser.getTripId == null) { +
+ } + } +} \ No newline at end of file diff --git a/app/femr/ui/views/admin/inventory/manage.scala.html b/app/femr/ui/views/admin/inventory/manage.scala.html index c80645b72..7cdf7925e 100644 --- a/app/femr/ui/views/admin/inventory/manage.scala.html +++ b/app/femr/ui/views/admin/inventory/manage.scala.html @@ -1,9 +1,9 @@ -@(currentUser: femr.common.dtos.CurrentUser, viewModel: femr.ui.models.admin.inventory.InventoryViewModelGet) +@import femr.ui.models.admin.inventory.ManageViewModelGet +@(currentUser: femr.common.dtos.CurrentUser, viewModel: ManageViewModelGet) @import femr.ui.controllers.admin.routes.InventoryController -@import femr.ui.controllers.admin.routes.TripController - +@import femr.ui.views.html.partials.admin.inventory.inventoryMenu @import femr.ui.views.html.layouts.admin @additionalStyles = { @@ -20,133 +20,33 @@ } -@admin("Inventory", currentUser, styles = additionalStyles, scripts = additionalScripts) { - - @if( viewModel.getMissionTripItem == null ){ -
- -

Your account is not assigned to a trip

- -

In order to manage your formulary, you must be assigned to a trip. Please assign yourself to a trip before using the inventory feature.

- - Manage Trip Users » -
- } else { - - @defining(viewModel.getMissionTripItem) { trip => -

You are viewing the formulary for @trip.getFriendlyTripTitle

- } -
- } - - @helper.form(action = InventoryController.managePost()) { - - @if( currentUser.getTripId == null ){ -
- } -

Add Existing Medicine To Formulary:

-

-Add medication(s) from the concept dictionary. Adjust current/initial quantity in the Current Formulary section after clicking Submit.

- - -

Add Custom Medicine To Formulary:

-

-Add a new medication that does not exist in the concept dictionary.

-
- -
-
- - -
- -
- - -
- -
- - -
+@admin("Inventory - Formulary", currentUser, styles = additionalStyles, scripts = additionalScripts) { -
-
-
- -
- -
- - -
- -
- - -
- -
- - -
- - - - - - -
- - - + - -
-
-
- -
+ @inventoryMenu(viewModel.getMissionTripItem) -
- @if( currentUser.getTripId() == null ){ -
- } - } -

Current Formulary:

-
- -As medications are dispensed, quantity will be subtracted from the Current Quantity column. -
-
- @if( currentUser.getTripId() == null ){ - - Export as CSV - } else { - - Export as CSV - } +
+
    +
  • Add medications using the buttons above
  • +
  • Formulary only applies to Users on the trip mentioned above
  • +
  • Manually edit Current/Initial quantity below
  • +
  • Quantity will be subtracted from the Current Quantity column after being dispensed in Pharmacy
  • +
  • Export your inventory data using the "Export as CSV" button to the right
  • +
+
+
+ @if( currentUser.getTripId() == null ){ + + Export as CSV + } else { + + Export as CSV + } -
+
@@ -160,36 +60,36 @@

Current Formulary:

@for(m <- 1 to viewModel.getMedications.size) { @if(viewModel.getMedications.get(m - 1).getIsDeleted == null){ - - - + + + - + - - + - + + } } diff --git a/app/femr/ui/views/partials/admin/inventory/inventoryMenu.scala.html b/app/femr/ui/views/partials/admin/inventory/inventoryMenu.scala.html new file mode 100644 index 000000000..049f15248 --- /dev/null +++ b/app/femr/ui/views/partials/admin/inventory/inventoryMenu.scala.html @@ -0,0 +1,26 @@ +@(missionTripItem: femr.common.models.MissionTripItem) + +@import femr.ui.controllers.admin.routes.InventoryController +@import femr.ui.controllers.admin.routes.TripController + +@if(missionTripItem == null) { +
+ +

Your account is not assigned to a trip

+ +

In order to manage your formulary, you must be assigned to a trip. Please assign yourself to a trip before using the inventory feature.

+ + Manage Trip Users » +
+ +} else { + + +

You are viewing the formulary for @missionTripItem.getFriendlyTripTitle

+} + diff --git a/conf/routes b/conf/routes index 53e3d7075..686a536cc 100644 --- a/conf/routes +++ b/conf/routes @@ -16,7 +16,10 @@ GET /admin/users/edit/:id @femr.ui.controll POST /admin/users/toggle/:id @femr.ui.controllers.admin.UsersController.toggleUser(id: Integer) GET /admin/users @femr.ui.controllers.admin.UsersController.manageGet() GET /admin/inventory @femr.ui.controllers.admin.InventoryController.manageGet() -POST /admin/inventory @femr.ui.controllers.admin.InventoryController.managePost() +GET /admin/inventory/custom @femr.ui.controllers.admin.InventoryController.customGet() +POST /admin/inventory/custom @femr.ui.controllers.admin.InventoryController.customPost() +GET /admin/inventory/existing @femr.ui.controllers.admin.InventoryController.existingGet() +POST /admin/inventory/existing @femr.ui.controllers.admin.InventoryController.existingPost() GET /admin/inventory/export/:tripId @femr.ui.controllers.admin.InventoryController.exportGet(tripId: Integer) POST /admin/inventory/delete/:id/:tripId @femr.ui.controllers.admin.InventoryController.ajaxDelete(id: Integer, tripId: Integer) POST /admin/inventory/editCurrent/:id/:tripId @femr.ui.controllers.admin.InventoryController.ajaxEditCurrent(id: Integer, tripId: Integer) diff --git a/public/css/admin/inventory.css b/public/css/admin/inventory.css index a2ed1a1f2..ab56ccd8a 100644 --- a/public/css/admin/inventory.css +++ b/public/css/admin/inventory.css @@ -171,6 +171,16 @@ margin-bottom: 5px; } +#inventoryOptionsWrap{ + display: inline-block; +} + +.medicationBtn{ + width: 225px; + margin-bottom: 5px; + float: left; +} + @media only screen and (max-width : 1200px) { .newMedicationWrap .ingredientWrap {
@m@viewModel.getMedications.get(m - 1).getFullName
@m@viewModel.getMedications.get(m - 1).getFullName + - @viewModel.getMedications.get(m - 1).getQuantityCurrent - - - - + @viewModel.getMedications.get(m - 1).getQuantityCurrent + + + + - + - @viewModel.getMedications.get(m - 1).getQuantityTotal - - - - + @viewModel.getMedications.get(m - 1).getQuantityTotal + + + + - + - + -