/*
fEMR - fast Electronic Medical Records
Copyright (C) 2014 Team fEMR
fEMR is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
fEMR is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with fEMR. If not, see <http://www.gnu.org/licenses/>. If
you have any questions, contact <info@teamfemr.org>.
*/
package femr.ui.controllers.admin;
import com.google.inject.Inject;
import femr.business.services.core.*;
import femr.common.dtos.CurrentUser;
import femr.common.dtos.ServiceResponse;
import femr.common.models.MissionTripItem;
import femr.data.models.mysql.Roles;
import femr.ui.helpers.security.AllowedRoles;
import femr.ui.helpers.security.FEMRAuthenticated;
import femr.ui.models.admin.inventory.*;
import femr.common.models.MedicationItem;
import femr.ui.views.html.admin.inventory.*;
import play.data.DynamicForm;
import play.data.Form;
import play.data.FormFactory;
import play.mvc.Controller;
import play.mvc.Result;
import play.mvc.Security;
import java.util.ArrayList;
import java.util.List;
import java.text.SimpleDateFormat;
import java.util.Date;
@Security.Authenticated(FEMRAuthenticated.class)
@AllowedRoles({Roles.ADMINISTRATOR, Roles.SUPERUSER})
public class InventoryController extends Controller {
private final FormFactory formFactory;
private final IConceptService conceptService;
private final IInventoryService inventoryService;
private final IMedicationService medicationService;
private final IMissionTripService missionTripService;
private final ISessionService sessionService;
@Inject
public InventoryController(FormFactory formFactory,
IConceptService conceptService,
IInventoryService inventoryService,
IMedicationService medicationService,
IMissionTripService missionTripService,
ISessionService sessionService) {
this.formFactory = formFactory;
this.conceptService = conceptService;
this.inventoryService = inventoryService;
this.medicationService = medicationService;
this.missionTripService = missionTripService;
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();
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
if( currentUser.getTripId() != null ){
ServiceResponse<List<MedicationItem>> medicationServiceResponse = inventoryService.retrieveMedicationInventorysByTripId(currentUser.getTripId());
if (medicationServiceResponse.hasErrors()) {
throw new RuntimeException();
} else {
viewModel.setMedications(medicationServiceResponse.getResponseObject());
}
ServiceResponse<MissionTripItem> missionTripServiceResponse = missionTripService.retrieveAllTripInformationByTripId(currentUser.getTripId());
if (missionTripServiceResponse.hasErrors()) {
throw new RuntimeException();
} else {
viewModel.setMissionTripItem(missionTripServiceResponse.getResponseObject());
}
} else {
viewModel.setMedications(new ArrayList<>());
}
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<List<String>> availableMedicationFormsResponse = medicationService.retrieveAvailableMedicationForms();
if (availableMedicationFormsResponse.hasErrors()) {
throw new RuntimeException();
} else {
viewModel.setAvailableForms(availableMedicationFormsResponse.getResponseObject());
}
ServiceResponse<List<String>> availableMedicationUnitsResponse = medicationService.retrieveAvailableMedicationUnits();
if (availableMedicationUnitsResponse.hasErrors()) {
throw new RuntimeException();
} else {
viewModel.setAvailableUnits(availableMedicationUnitsResponse.getResponseObject());
}
ServiceResponse<MissionTripItem> missionTripServiceResponse = missionTripService.retrieveAllTripInformationByTripId(currentUser.getTripId());
if (missionTripServiceResponse.hasErrors()) {
throw new RuntimeException();
} else {
viewModel.setMissionTripItem(missionTripServiceResponse.getResponseObject());
}
return ok(custom.render(currentUser, viewModel));
}
/**
* Handles the submission of a new custom medication from an Admin
*/
public Result customPost(){
CurrentUser currentUser = sessionService.retrieveCurrentUserSession();
final Form<CustomViewModelPost> inventoryViewModelPostForm = formFactory.form(CustomViewModelPost.class);
Form<CustomViewModelPost> form = inventoryViewModelPostForm.bindFromRequest();
if (form.hasErrors()) {
return redirect("/admin/inventory");
//System.out.println(form.errors().toString());
//if the request gets past the javascript validation and fails validation in the viewmodel, then
//don't proceed to save anything. In the future, this should alert the user as to what they did
//wrong.
/* Should be validated client side and server-side throws error
//throw new RuntimeException(); */
}
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)
MedicationItem medicationItem = new MedicationItem();
// assumes medication strength is a good indicator of how many
// strength/unit/ingredients (active ingredietns) are involved
// *denominator field not taken into consideration - always false
if (inventoryViewModelPost.getMedicationStrength().get(0) != null) {
for (int genericIndex = 0; genericIndex < inventoryViewModelPost.getMedicationStrength().size(); genericIndex++) {
if (inventoryViewModelPost.getMedicationIngredient().get(genericIndex) != null &&
inventoryViewModelPost.getMedicationUnit().get(genericIndex) != null &&
inventoryViewModelPost.getMedicationStrength().get(genericIndex) != null) {
medicationItem.addActiveIngredient(
inventoryViewModelPost.getMedicationIngredient().get(genericIndex),
inventoryViewModelPost.getMedicationUnit().get(genericIndex),
inventoryViewModelPost.getMedicationStrength().get(genericIndex),
false
);
}
}
ServiceResponse<MedicationItem> createMedicationServiceResponse = medicationService.createMedication(
inventoryViewModelPost.getMedicationName(),
inventoryViewModelPost.getMedicationForm(),
medicationItem.getActiveIngredients());
// check for errors before updating the quantity to ensure a medication ID has been returned in the response
// object.
if (createMedicationServiceResponse.hasErrors()) {
return internalServerError();
}
ServiceResponse<MedicationItem> setQuantityServiceResponse = inventoryService.setQuantityTotal(
createMedicationServiceResponse.getResponseObject().getId(),
currentUser.getTripId(),
inventoryViewModelPost.getMedicationQuantity());
if (setQuantityServiceResponse.hasErrors()){
return internalServerError();
}
}
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<List<MedicationItem>> conceptMedicationServiceResponse = conceptService.retrieveAllMedicationConcepts();
if (conceptMedicationServiceResponse.hasErrors()) {
throw new RuntimeException();
} else {
viewModel.setConceptMedications(conceptMedicationServiceResponse.getResponseObject());
}
ServiceResponse<MissionTripItem> 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<ExistingViewModelPost> existingViewModelPostForm = formFactory.form(ExistingViewModelPost.class);
Form<ExistingViewModelPost> 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 (existingViewModelPost.getNewConceptMedicationsForInventory() != null) {
ServiceResponse<MedicationItem> conceptMedicationServiceResponse;
ServiceResponse<MedicationItem> medicationItemServiceResponse;
MedicationItem conceptMedicationItem;
//for each concept medication id that was sent from the select2 form
for (Integer conceptMedicationId : existingViewModelPost.getNewConceptMedicationsForInventory()) {
//get the actual concept MedicationItem from the id that was sent in
conceptMedicationServiceResponse = conceptService.retrieveConceptMedication(conceptMedicationId);
if (conceptMedicationServiceResponse.hasErrors()) {
return internalServerError();
} else {
//create a non-concept MedicationItem from the concept MedicationItem
conceptMedicationItem = conceptMedicationServiceResponse.getResponseObject();
medicationItemServiceResponse = medicationService.createMedication(conceptMedicationItem.getName(), conceptMedicationItem.getForm(), conceptMedicationItem.getActiveIngredients());
if (medicationItemServiceResponse.hasErrors()) {
return internalServerError();
}else{
ServiceResponse<MedicationItem> setQuantityServiceResponse = inventoryService.setQuantityTotal(medicationItemServiceResponse.getResponseObject().getId(), currentUser.getTripId(), 0);
if (setQuantityServiceResponse.hasErrors()){
return internalServerError();
}
}
}
}
}
return redirect("/admin/inventory");
}
/**
* Called when a user wants to export the data to a CSV file.
*/
public Result exportGet(int tripId) {
CurrentUser currentUser = sessionService.retrieveCurrentUserSession();
ServiceResponse<String> exportServiceResponse = inventoryService.exportCSV(tripId);
SimpleDateFormat format = new SimpleDateFormat("MMddyy-HHmmss");
String timestamp = format.format(new Date());
String csvFileName = "inventory-"+timestamp+".csv";
response().setHeader("Content-disposition", "attachment; filename=" + csvFileName);
return ok(exportServiceResponse.getResponseObject()).as("application/x-download");
}
public Result ajaxDelete(int medicationID, int tripId) {
ServiceResponse<MedicationItem> inventoryServiceResponse = inventoryService.deleteInventoryMedication(medicationID, tripId);
if (inventoryServiceResponse.hasErrors()) {
throw new RuntimeException();
}
return ok("true");
}
/**
* Alters medication based on submit.
*/
public Result ajaxEditCurrent(int medicationID, int tripId) {
// Get POST data
DynamicForm df = formFactory.form().bindFromRequest();
int quantity = Integer.parseInt(df.get("quantity"));
ServiceResponse<MedicationItem> inventoryServiceResponse = inventoryService.setQuantityCurrent(medicationID, tripId, quantity);
if (inventoryServiceResponse.hasErrors()) {
throw new RuntimeException();
}
return ok("true");
}
/**
* Alters medication based on submit.
*/
public Result ajaxEditTotal(int medicationID, int tripId) {
// Get POST data
DynamicForm df = formFactory.form().bindFromRequest();
int quantity = Integer.parseInt(df.get("quantity"));
ServiceResponse<MedicationItem> inventoryServiceResponse = inventoryService.setQuantityTotal(medicationID, tripId, quantity);
if (inventoryServiceResponse.hasErrors()) {
throw new RuntimeException();
}
return ok("true");
}
}