/** * This Source Code Form is subject to the terms of the Mozilla Public License, * v. 2.0. If a copy of the MPL was not distributed with this file, You can * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. * * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS * graphic logo is a trademark of OpenMRS Inc. */ package org.openmrs.module.radiology.order.web; import static org.openmrs.module.radiology.RadiologyPrivileges.ADD_RADIOLOGY_REPORTS; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import org.openmrs.Order; import org.openmrs.Patient; import org.openmrs.api.APIException; import org.openmrs.api.context.Context; import org.openmrs.module.radiology.RadiologyProperties; import org.openmrs.module.radiology.dicom.DicomWebViewer; import org.openmrs.module.radiology.dicom.code.PerformedProcedureStepStatus; import org.openmrs.module.radiology.order.RadiologyOrder; import org.openmrs.module.radiology.order.RadiologyOrderService; import org.openmrs.module.radiology.order.RadiologyOrderValidator; import org.openmrs.module.radiology.report.RadiologyReport; import org.openmrs.module.radiology.report.RadiologyReportService; import org.openmrs.module.radiology.study.RadiologyStudy; import org.openmrs.web.WebConstants; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; /** * Controller for the form handling entry, display, discontinuation of {@code RadiologyOrder's}. */ @Controller @RequestMapping(RadiologyOrderFormController.RADIOLOGY_ORDER_FORM_REQUEST_MAPPING) public class RadiologyOrderFormController { public static final String RADIOLOGY_ORDER_FORM_REQUEST_MAPPING = "/module/radiology/radiologyOrder.form"; static final String RADIOLOGY_ORDER_CREATION_FORM_VIEW = "/module/radiology/orders/radiologyOrderCreationForm"; static final String RADIOLOGY_ORDER_FORM_VIEW = "/module/radiology/orders/radiologyOrderForm"; @Autowired private RadiologyOrderService radiologyOrderService; @Autowired private RadiologyReportService radiologyReportService; @Autowired private RadiologyProperties radiologyProperties; @Autowired private DicomWebViewer dicomWebViewer; @Autowired private RadiologyOrderValidator radiologyOrderValidator; @Autowired private DiscontinuationOrderRequestValidator discontinuationOrderRequestValidator; @InitBinder("discontinuationOrderRequest") protected void initBinderDiscontinuationOrderRequest(WebDataBinder webDataBinder) { webDataBinder.setValidator(discontinuationOrderRequestValidator); } /** * Handles requests for a new {@code RadiologyOrder}. * * @return model and view containing new radiology order * @should populate model and view with new radiology order */ @RequestMapping(method = RequestMethod.GET) protected ModelAndView getRadiologyOrderFormWithNewRadiologyOrder() { final ModelAndView modelAndView = new ModelAndView(RADIOLOGY_ORDER_CREATION_FORM_VIEW); modelAndView.addObject("order", new Order()); modelAndView.addObject("radiologyReport", null); final RadiologyOrder radiologyOrder = new RadiologyOrder(); radiologyOrder.setStudy(new RadiologyStudy()); modelAndView.addObject("radiologyOrder", radiologyOrder); return modelAndView; } /** * Handles requests for a new {@code RadiologyOrder} for a specific patient. * * @param patient the existing patient which should be associated with a new radiology order * returned in the model and view * @return model and view containing new radiology order * @should populate model and view with new radiology order prefilled with given patient */ @RequestMapping(method = RequestMethod.GET, params = "patientId") protected ModelAndView getRadiologyOrderFormWithNewRadiologyOrderAndPrefilledPatient(@RequestParam("patientId") Patient patient) { final ModelAndView modelAndView = getRadiologyOrderFormWithNewRadiologyOrder(); final Order order = (Order) modelAndView.getModel() .get("radiologyOrder"); order.setPatient(patient); modelAndView.addObject("patientId", patient.getPatientId()); return modelAndView; } /** * Handles requests for getting existing {@code RadiologyOrder's}. * * @param order the order of an existing radiology order which should be returned * @return model and view containing radiology order * @should populate model and view with existing radiology order if given order id matches a * radiology order and no dicom viewer url if order is not completed * @should populate model and view with existing radiology order if given order id matches a * radiology order and dicom viewer url if order completed * @should populate model and view with existing order if given order id only matches an order * and not a radiology order */ @RequestMapping(method = RequestMethod.GET, params = "orderId") protected ModelAndView getRadiologyOrderFormWithExistingRadiologyOrder(@RequestParam("orderId") Order order) { final ModelAndView modelAndView = new ModelAndView(RADIOLOGY_ORDER_FORM_VIEW); modelAndView.addObject("order", order); modelAndView.addObject("discontinuationOrderRequest", new DiscontinuationOrderRequest()); if (order instanceof RadiologyOrder) { final RadiologyOrder radiologyOrder = (RadiologyOrder) order; modelAndView.addObject("radiologyOrder", radiologyOrder); if (radiologyOrder.isCompleted()) { modelAndView.addObject("dicomViewerUrl", dicomWebViewer.getDicomViewerUrl(radiologyOrder.getStudy())); } } if (Context.getAuthenticatedUser() .hasPrivilege(ADD_RADIOLOGY_REPORTS)) { radiologyReportNeedsToBeCreated(modelAndView, order); } return modelAndView; } /** * Handles requests for saving a new {@code RadiologyOrder}. * * @param request the http servlet request issued to save the radiology order * @param radiologyOrder the radiology order to be saved * @param resultRadiologyOrder the binding result for given radiology order * @return the model and view for the radiology order form containing binding result errors if given radiology order is * not valid * @should save given radiology order if valid and set http session attribute openmrs message to order saved and redirect * to the new radiology order * @should not save given radiology order if it is not valid and not redirect * @should not redirect and set session attribute with openmrs error if api exception is thrown by place radiology * order */ @RequestMapping(method = RequestMethod.POST, params = "saveRadiologyOrder") protected ModelAndView saveRadiologyOrder(HttpServletRequest request, @ModelAttribute RadiologyOrder radiologyOrder, BindingResult resultRadiologyOrder) { final ModelAndView modelAndView = new ModelAndView(RADIOLOGY_ORDER_CREATION_FORM_VIEW); radiologyOrderValidator.validate(radiologyOrder, resultRadiologyOrder); if (resultRadiologyOrder.hasErrors()) { modelAndView.addObject("order", (Order) radiologyOrder); modelAndView.addObject("radiologyOrder", radiologyOrder); return modelAndView; } try { radiologyOrderService.placeRadiologyOrder(radiologyOrder); request.getSession() .setAttribute(WebConstants.OPENMRS_MSG_ATTR, "Order.saved"); modelAndView.setViewName( "redirect:" + RADIOLOGY_ORDER_FORM_REQUEST_MAPPING + "?orderId=" + radiologyOrder.getOrderId()); return modelAndView; } catch (APIException apiException) { request.getSession() .setAttribute(WebConstants.OPENMRS_ERROR_ATTR, apiException.getMessage()); } modelAndView.addObject("order", (Order) radiologyOrder); modelAndView.addObject("radiologyOrder", radiologyOrder); return modelAndView; } /** * Handles requests to discontinue a {@code RadiologyOrder}. * * @param request the http servlet request issued to discontinue the radiology order * @param radiologyOrderToDiscontinue the radiology order to discontinue * @param discontinuationOrderRequest the discontinuation order request containing provider and reason * @param resultDiscontinuationOrderRequest the binding result for given discontinuation order request * @return the model and view populated with discontinuation order * @throws Exception * @should discontinue non discontinued radiology order and redirect to discontinuation order * @should not discontinue given radiology order and not redirect if discontinuation order request is not valid * @should not redirect and set session attribute with openmrs error if api exception is thrown by discontinue radiology * order */ @RequestMapping(method = RequestMethod.POST, params = "discontinueOrder") protected ModelAndView discontinueRadiologyOrder(HttpServletRequest request, @RequestParam("orderId") RadiologyOrder radiologyOrderToDiscontinue, @Valid @ModelAttribute DiscontinuationOrderRequest discontinuationOrderRequest, BindingResult resultDiscontinuationOrderRequest) throws Exception { final ModelAndView modelAndView = new ModelAndView(RADIOLOGY_ORDER_FORM_VIEW); if (resultDiscontinuationOrderRequest.hasErrors()) { modelAndView.addObject("order", radiologyOrderToDiscontinue); modelAndView.addObject("radiologyOrder", radiologyOrderToDiscontinue); return modelAndView; } try { final Order discontinuationOrder = radiologyOrderService.discontinueRadiologyOrder(radiologyOrderToDiscontinue, discontinuationOrderRequest.getOrderer(), discontinuationOrderRequest.getReasonNonCoded()); request.getSession() .setAttribute(WebConstants.OPENMRS_MSG_ATTR, "Order.discontinuedSuccessfully"); modelAndView.setViewName( "redirect:" + RADIOLOGY_ORDER_FORM_REQUEST_MAPPING + "?orderId=" + discontinuationOrder.getOrderId()); return modelAndView; } catch (APIException apiException) { request.getSession() .setAttribute(WebConstants.OPENMRS_ERROR_ATTR, apiException.getMessage()); } modelAndView.addObject("order", radiologyOrderToDiscontinue); modelAndView.addObject("radiologyOrder", radiologyOrderToDiscontinue); return modelAndView; } /** * Convenient method to check if a {@code RadiologyReport} needs to be created for a {@code RadiologyOrder}. * * @param modelAndView the model and view to which an object indicating if a report needs to be created is added * @param order the order to be checked for the need of a radiology report * @return true if a radiology report needs to be created and false otherwise * @should return false if order is not a radiology order * @should return false if radiology order is not completed * @should return false if radiology order is completed but has a claimed report * @should return false if radiology order is completed but has a completed report * @should return true if radiology order is completed and has no claimed report */ private boolean radiologyReportNeedsToBeCreated(ModelAndView modelAndView, Order order) { final RadiologyOrder radiologyOrder; if (order instanceof RadiologyOrder) { radiologyOrder = (RadiologyOrder) order; } else { modelAndView.addObject("radiologyReportNeedsToBeCreated", false); return false; } if (radiologyOrder.isNotCompleted()) { modelAndView.addObject("radiologyReportNeedsToBeCreated", false); return false; } final RadiologyReport radiologyReport = radiologyReportService.getActiveRadiologyReportByRadiologyOrder(radiologyOrder); if (radiologyReport == null) { modelAndView.addObject("radiologyReportNeedsToBeCreated", true); return true; } else { modelAndView.addObject("radiologyReportNeedsToBeCreated", false); modelAndView.addObject("radiologyReport", radiologyReport); return false; } } @ModelAttribute("urgencies") private List<String> getUrgenciesList() { final List<String> urgencies = new LinkedList<String>(); for (final Order.Urgency urgency : Order.Urgency.values()) { urgencies.add(urgency.name()); } return urgencies; } @ModelAttribute("performedStatuses") private Map<String, String> getPerformedStatusList() { final Map<String, String> performedStatuses = new HashMap<String, String>(); performedStatuses.put("", "Select"); for (final PerformedProcedureStepStatus performedStatus : PerformedProcedureStepStatus.values()) { performedStatuses.put(performedStatus.name(), performedStatus.name()); } return performedStatuses; } /** * Gets the names of the concept classes that should be filtered * * @return names of concept classes */ @ModelAttribute("radiologyConceptClassNames") private String getRadiologyConceptClassNames() { return radiologyProperties.getRadiologyConceptClassNames(); } /** * Gets the names of the concept classes that should be filtered for the order reason field * * @return names of concept classes containing concepts for the order reason field */ @ModelAttribute("radiologyOrderReasonConceptClassNames") private String getRadiologyOrderReasonConceptClassNames() { return radiologyProperties.getRadiologyOrderReasonConceptClassNames(); } }