@Test
  public void shouldAddNewDrugOrderWhenPrnIsTrueWIthNoDosageFrequencyOrDosageInstruction() {

    EncounterTransaction.DrugOrder drugOrder =
        new DrugOrderBuilder()
            .withBasicValues("drug-uuid", "test-concept-uuid", today, today, 3, "", "")
            .withPrn(true)
            .build();
    Concept drugConcept = new Concept(3);
    OrderType drugOrderType = new OrderType("Drug Order", "this is a drug order type");

    when(orderService.getAllOrderTypes()).thenReturn(asList(drugOrderType));
    when(conceptService.getConceptByUuid("test-concept-uuid")).thenReturn(drugConcept);
    Drug drug = new Drug();
    drug.setName("test drug");
    when(conceptService.getDrugByUuid("drug-uuid")).thenReturn(drug);

    encounterDrugOrderServiceHelper.update(encounter, asList(drugOrder));

    assertThat(encounter.getOrders().size(), is(1));
    org.openmrs.DrugOrder order = (org.openmrs.DrugOrder) encounter.getOrders().iterator().next();
    assertEquals(drugConcept, order.getConcept());
    assertEquals(drugOrderType, order.getOrderType());
    assertEquals(patient, order.getPatient());
    assertEquals(encounter, order.getEncounter());
    assertEquals(today, order.getStartDate());
    assertEquals(today, order.getAutoExpireDate());
    assertEquals(drug.getDisplayName(), order.getDrug().getDisplayName());
    assertEquals(Double.valueOf(3), order.getDose());

    assertEquals(true, order.getPrn());
    assertEquals(null, order.getFrequency());
    assertEquals(null, order.getUnits());
  }
  @Test
  public void shouldAddNewDrugOrder() throws Exception {
    executeDataSet("shouldAddNewDrugOrder.xml");

    String json =
        "{ \"patientUuid\" : \"a76e8d23-0c38-408c-b2a8-ea5540f01b51\", "
            + "\"visitTypeUuid\" : \"b45ca846-c79a-11e2-b0c0-8e397087571c\", "
            + "\"encounterTypeUuid\": \"2b377dba-62c3-4e53-91ef-b51c68899890\", "
            + "\"encounterDateTime\" : \"2005-01-02T00:00:00.000+0000\", "
            + "\"testOrders\":["
            + "{\"concept\":{ \"uuid\": \"d102c80f-1yz9-4da3-bb88-8122ce8868dd\"}, "
            + "\"instructions\":\"do it\", \"orderTypeUuid\": \"1a61ef2a-250c-11e3-b832-0800271c1b75\" }],"
            + "\"drugOrders\":["
            + "{\"uuid\": \"4d6fb6e0-4950-426c-9a9b-1f97e6037893\","
            + "\"concept\": {\"uuid\": \"29dc4a20-507f-40ed-9545-d47e932483fa\"},"
            + "\"notes\": \"Take as needed\","
            + "\"startDate\": \"2013-09-30T09:26:09.717Z\","
            + "\"endDate\": \"2013-10-02T09:26:09.717Z\","
            + "\"numberPerDosage\": 1,"
            + "\"dosageInstruction\": {\"uuid\": \"632aa422-2696-11e3-895c-0800271c1b75\"},"
            + "\"dosageFrequency\": {\"uuid\": \"6302096d-2696-11e3-895c-0800271c1b75\"},"
            + "\"prn\": true}"
            + "]}";

    EncounterTransaction response =
        deserialize(
            handle(newPostRequest("/rest/emrapi/encounter", json)), EncounterTransaction.class);

    Visit visit = visitService.getVisitByUuid(response.getVisitUuid());
    Encounter encounter = visit.getEncounters().iterator().next();
    assertEquals(2, encounter.getOrders().size());

    List<Order> orders = new ArrayList<Order>(encounter.getOrders());

    List<DrugOrder> drugOrders = getOrdersOfType(orders, DrugOrder.class);
    assertEquals(1, drugOrders.size());
    DrugOrder drugOrder = drugOrders.get(0);
    assertEquals("a76e8d23-0c38-408c-b2a8-ea5540f01b51", drugOrder.getPatient().getUuid());
    assertEquals("f13d6fae-baa9-4553-955d-920098bec08f", drugOrder.getEncounter().getUuid());
    assertEquals("29dc4a20-507f-40ed-9545-d47e932483fa", drugOrder.getConcept().getUuid());
    assertEquals("1a61ef2a-250c-11e3-b832-9876541c1b75", drugOrder.getOrderType().getUuid());
    assertEquals("Take as needed", drugOrder.getInstructions());
    assertEquals(new DateTime("2013-09-30T09:26:09.717Z").toDate(), drugOrder.getStartDate());
    assertEquals(new DateTime("2013-10-02T09:26:09.717Z").toDate(), drugOrder.getAutoExpireDate());
    assertEquals("6302096d-2696-11e3-895c-0800271c1b75", drugOrder.getFrequency());
    assertEquals("632aa422-2696-11e3-895c-0800271c1b75", drugOrder.getUnits());
    assertEquals("test drug", drugOrder.getDrug().getDisplayName());
    assertEquals(Double.valueOf(1), drugOrder.getDose());
    assertEquals(true, drugOrder.getPrn());

    List<TestOrder> testOrders = getOrdersOfType(orders, TestOrder.class);
    assertEquals(1, testOrders.size());
    TestOrder testOrder = testOrders.get(0);
    assertEquals("d102c80f-1yz9-4da3-bb88-8122ce8868dd", testOrder.getConcept().getUuid());
    assertEquals("a76e8d23-0c38-408c-b2a8-ea5540f01b51", testOrder.getPatient().getUuid());
    assertEquals("f13d6fae-baa9-4553-955d-920098bec08f", testOrder.getEncounter().getUuid());
    assertEquals("1a61ef2a-250c-11e3-b832-0800271c1b75", testOrder.getOrderType().getUuid());
    assertEquals("do it", testOrder.getInstructions());
  }
  @Override
  public EncounterTransaction.DrugOrder mapDrugOrder(DrugOrder openMRSDrugOrder) {
    EncounterTransaction.DrugOrder drugOrder = new EncounterTransaction.DrugOrder();
    drugOrder.setUuid(openMRSDrugOrder.getUuid());
    if (openMRSDrugOrder.getCareSetting() != null) {
      drugOrder.setCareSetting(
          CareSettingType.valueOf(
              openMRSDrugOrder.getCareSetting().getCareSettingType().toString()));
    }
    drugOrder.setAction(openMRSDrugOrder.getAction().name());
    drugOrder.setOrderType(openMRSDrugOrder.getOrderType().getName());

    org.openmrs.Order previousOrder = openMRSDrugOrder.getPreviousOrder();
    if (previousOrder != null && StringUtils.isNotBlank(previousOrder.getUuid())) {
      drugOrder.setPreviousOrderUuid(previousOrder.getUuid());
    }

    EncounterTransaction.Drug encounterTransactionDrug =
        new DrugMapper1_11().map(openMRSDrugOrder.getDrug());
    drugOrder.setDrug(encounterTransactionDrug);

    drugOrder.setDosingInstructionType(openMRSDrugOrder.getDosingType().getName());
    drugOrder.setDuration(openMRSDrugOrder.getDuration());
    drugOrder.setDurationUnits(getConceptName(openMRSDrugOrder.getDurationUnits()));

    drugOrder.setScheduledDate(openMRSDrugOrder.getScheduledDate());
    drugOrder.setDateActivated(openMRSDrugOrder.getDateActivated());
    drugOrder.setEffectiveStartDate(openMRSDrugOrder.getEffectiveStartDate());
    drugOrder.setAutoExpireDate(openMRSDrugOrder.getAutoExpireDate());
    drugOrder.setEffectiveStopDate(openMRSDrugOrder.getEffectiveStopDate());

    drugOrder.setDateStopped(openMRSDrugOrder.getDateStopped());

    EncounterTransaction.DosingInstructions dosingInstructions =
        new EncounterTransaction.DosingInstructions();
    dosingInstructions.setDose(openMRSDrugOrder.getDose());
    dosingInstructions.setDoseUnits(getConceptName(openMRSDrugOrder.getDoseUnits()));
    dosingInstructions.setRoute(getConceptName(openMRSDrugOrder.getRoute()));
    dosingInstructions.setAsNeeded(openMRSDrugOrder.getAsNeeded());
    if (openMRSDrugOrder.getFrequency() != null) {
      dosingInstructions.setFrequency(openMRSDrugOrder.getFrequency().getName());
    }
    if (openMRSDrugOrder.getQuantity() != null) {
      dosingInstructions.setQuantity(openMRSDrugOrder.getQuantity());
    }
    dosingInstructions.setQuantityUnits(getConceptName(openMRSDrugOrder.getQuantityUnits()));
    dosingInstructions.setAdministrationInstructions(openMRSDrugOrder.getDosingInstructions());
    drugOrder.setDosingInstructions(dosingInstructions);

    drugOrder.setInstructions(openMRSDrugOrder.getInstructions());
    drugOrder.setCommentToFulfiller(openMRSDrugOrder.getCommentToFulfiller());

    drugOrder.setVoided(openMRSDrugOrder.getVoided());
    drugOrder.setVoidReason(openMRSDrugOrder.getVoidReason());
    drugOrder.setOrderNumber(openMRSDrugOrder.getOrderNumber());

    return drugOrder;
  }
  /* here's the logic for what happens if there is a future regimen:
  *
  *
  *      //1.  if no drug order of a specific DrugOrder, (create the new order).  (OUTCOME1)

         //2.  if DrugOrder, for all DrugOrders:
             //a.  if new start is before old start
                 //NEW ORDER HAS STOP DATE -- create the older as is, and make adjustments:
                     //1.  if new end is before or equal to old start (create the new order)  (OUTCOME2)
                     //2.  if new end is after old start and ( before old end or old end is infinite)
                        //if order is different, adjust the start date of the old order to the end date of the new (create the new order) (OUTCOME3)
                        //if order is same void old order(doesn't matter if old order has infinite stop date or not) (create the new order) (OUTCOME4)
                     //3. if end date is greater than or equal to old end -- void old order   (create the new order)  (OUTCOME5)
                 //NEW ORDER DOESN'T HAVE STOP DATE
                     //4. orders are different
                          //set end date of new to beginning of old and stop iterating over existing drug orders time sequence (create the new order, modified) (OUTCOME6)
                     //5. orders are the same
                         //delete the old order (create the new order) (OUTCOME7)
             //b. if start is the same
                 // void existing (create the new order) (OUTCOME8)

             //c.  if start is after existing start
                 //1. if order is after old drug end  (create the new order) (OUTCOME9)
                 //2. if order is before old drug end or equal to old drug end or old drug end date is infinite
                     //if orders are the same update the old order with the new, taking the new end date value (Do not create new order) (OUTCOME10)
                     //if orders are different adjust the old to end on new start date (create the new order) (OUTCOME11)

  * */
  public static void setRegimen(
      Patient patient,
      Date effectiveDate,
      Collection<DrugOrder> drugOrders,
      Concept reasonForChange,
      Encounter encounterForChange) {
    RegimenHistory history = getRegimenHistory(patient);
    Regimen regOnDate = history.getRegimen(effectiveDate);
    List<Regimen> regAfterDate = history.getRegimensAfter(effectiveDate);
    OrderService os = Context.getOrderService();
    if (encounterForChange != null) {
      Context.getEncounterService().saveEncounter(encounterForChange);
      for (DrugOrder drugOrder : drugOrders) {
        drugOrder.setEncounter(encounterForChange);
      }
    }

    if (!anyRegimens(regAfterDate)) {
      if (regOnDate == null || regOnDate.getComponents().isEmpty()) {
        // case:  there is no existing regimen on the regimen start date, and there are no new
        // regimens after this date
        // go ahead and create the regimen:
        for (DrugOrder drugOrder : drugOrders) {
          Context.getOrderService().saveOrder(drugOrder);
        }
      } else {

        // case: there are still open orders and there are no new regimens after this date
        // first see what existing things we need to stop
        for (RegimenComponent before : regOnDate.getComponents()) {
          // stop the old order only if it isn't exactly identical to a new order (excluding
          // discontinued_date)
          for (DrugOrder newOrder : drugOrders) {
            // but either concept or drug is the same
            if (!before.getDrugOrder().getDiscontinued()
                && drugOrderMatchesDrugConcept(before.getDrugOrder(), newOrder)
                && !regimenComponentIsTheSameAsDrugOrderExcludingDates(
                    before.getDrugOrder(), newOrder)) {
              discontinueOrder(before.getDrugOrder(), effectiveDate, reasonForChange);
            }
          }
        }
        // now see what new things to start (or extend)
        for (DrugOrder newOrder : drugOrders) {

          // create a new order if there isn't already an existing match,
          // or if there is (excluding discontinued date) you need to extend, or null the stop date

          boolean alreadyExists = false;
          for (RegimenComponent before : regOnDate.getComponents()) {

            if (!before.getDrugOrder().getDiscontinued()
                && regimenComponentIsTheSameAsDrugOrderExcludingDates(
                    before.getDrugOrder(), newOrder)) {
              alreadyExists = true;
              before.getDrugOrder().setDiscontinuedDate(newOrder.getDiscontinuedDate());
              before.getDrugOrder().setAutoExpireDate(newOrder.getAutoExpireDate());
              before.getDrugOrder().setPrn(newOrder.getPrn());
              before.getDrugOrder().setInstructions(newOrder.getInstructions());
              os.saveOrder(before.getDrugOrder());
              newOrder.setOrderId(before.getDrugOrder().getOrderId());
              break;
            }
          }
          if (!alreadyExists) {
            os.saveOrder(newOrder);
          }
        }
      }
    } else { // there is a regimen change after the new drug order start date
      for (DrugOrder newOrder : drugOrders) {
        boolean saveOrder = false;
        boolean merged = false;
        history = getRegimenHistory(patient);
        List<DrugOrder> existingDrugOrders = getDrugOrdersInOrderByDrugOrConcept(history, newOrder);
        if (existingDrugOrders.size() == 0) {
          saveOrder = setSaveOrder(merged); // (OUTCOME1)
        } else {
          for (DrugOrder before : existingDrugOrders) {
            if (newOrder.getStartDate().before(before.getStartDate())) {
              if (newOrder.getDiscontinuedDate() != null) {
                if (newOrder.getDiscontinuedDate().before(before.getStartDate())
                    || newOrder.getDiscontinuedDate().equals(before.getStartDate())) {
                  saveOrder = setSaveOrder(merged); // (OUTCOME2)
                } else if (newOrder.getDiscontinuedDate().after(before.getStartDate())
                    && (before.getDiscontinuedDate() == null
                        || newOrder.getDiscontinuedDate().before(before.getDiscontinuedDate()))) {
                  if (!regimenComponentIsTheSameAsDrugOrderExcludingDates(before, newOrder)) {
                    // (OUTCOME3)
                    before.setStartDate(newOrder.getDiscontinuedDate());
                    os.saveOrder(before);
                    saveOrder = setSaveOrder(merged);
                  } else {
                    // (OUTCOME4)
                    os.voidOrder(before, "overwritten");
                    saveOrder = setSaveOrder(merged);
                  }
                } else if (before.getDiscontinuedDate() != null
                    && (newOrder.getDiscontinuedDate().after(before.getDiscontinuedDate())
                        || newOrder.getDiscontinuedDate().equals(before.getDiscontinuedDate()))) {
                  // (OUTCOME5)
                  os.voidOrder(before, "overwritten");
                  saveOrder = setSaveOrder(merged);
                }
              } else { // new order has infinite end date
                if (!regimenComponentIsTheSameAsDrugOrderExcludingDates(before, newOrder)) {
                  // (OUTCOME6)
                  newOrder.setDiscontinuedDate(before.getStartDate());
                  saveOrder = setSaveOrder(merged);
                  break;
                } else {
                  // (OUTCOME7)
                  os.voidOrder(before, "overwritten");
                  saveOrder = setSaveOrder(merged);
                }
              }
            } else if (newOrder.getStartDate().equals(before.getStartDate())) { // b
              // (OUTCOME8)
              os.voidOrder(before, "overwritten");
              saveOrder = setSaveOrder(merged);
            } else { // c -- start date is after or equal to old end date
              if (before.getDiscontinuedDate() != null
                  && newOrder.getStartDate().after(before.getDiscontinuedDate())) // 1
                // (OUTCOME9)
                saveOrder = setSaveOrder(merged);

              if (before.getDiscontinuedDate() == null
                  || newOrder.getStartDate().before(before.getDiscontinuedDate())
                  || newOrder.getStartDate().equals(before.getDiscontinuedDate())) { // 2
                if (regimenComponentIsTheSameAsDrugOrderExcludingDates(before, newOrder)) {
                  // (OUTCOME10)
                  before.setDiscontinuedDate(newOrder.getDiscontinuedDate());
                  before.setAutoExpireDate(newOrder.getAutoExpireDate());
                  before.setPrn(newOrder.getPrn());
                  before.setInstructions(newOrder.getInstructions());
                  os.saveOrder(before);
                  saveOrder = false;
                  newOrder.setOrderId(before.getOrderId());
                  merged = true;
                } else {
                  // (OUTCOME11)
                  before.setDiscontinuedDate(newOrder.getStartDate());
                  os.saveOrder(before);
                  saveOrder = setSaveOrder(merged);
                }
              }
            }
          }
        }
        if (saveOrder) os.saveOrder(newOrder);
      }
    }
  }
  protected ModelAndView handleRequestInternal(
      HttpServletRequest request, HttpServletResponse response) throws Exception {

    ModelAndView mav = new ModelAndView();

    Drug drug = null;
    Location dftLoc = null;
    LocationService locationService = Context.getLocationService();

    String locationStr =
        Context.getAuthenticatedUser()
            .getUserProperties()
            .get(OpenmrsConstants.USER_PROPERTY_DEFAULT_LOCATION);

    try {
      dftLoc = locationService.getLocation(Integer.valueOf(locationStr));
    } catch (Exception e) {
      mav.addObject("msg", "pharmacymanagement.missingDftLoc");
    }
    @SuppressWarnings("unused")
    String pharmacyId = null;
    DrugLotDate dld = null;
    List<DrugLotDate> dlds = new ArrayList<DrugLotDate>();
    String patientIdStr = null;
    Patient patient = null;
    DrugOrderService service = Context.getService(DrugOrderService.class);
    List<Pharmacy> pharmacyList = service.getPharmacyByLocation(dftLoc);
    List<DrugOrder> drugOrders = new ArrayList<DrugOrder>();
    ConceptService conceptService = Context.getConceptService();
    Pharmacy pharmacy = null;

    List<DrugOrder> drugOrderList = new ArrayList<DrugOrder>();
    pharmacyId = pharmacyList.size() > 0 ? "not empty" : "";

    if (request.getParameter("patientId") != null
        && !request.getParameter("patientId").equals("")) {
      patientIdStr = request.getParameter("patientId");

      patient = Context.getPatientService().getPatient(Integer.valueOf(patientIdStr));
    }

    if (patient != null
        && request.getParameter("pharmacyId") != null
        && !request.getParameter("pharmacyId").equals("")) {

      drugOrders = Context.getOrderService().getDrugOrdersByPatient(patient);

      pharmacy = service.getPharmacyById(Integer.valueOf(request.getParameter("pharmacyId")));
      List<Integer> drugIdList = new ArrayList<Integer>();
      for (DrugOrder dor : drugOrders) {
        if (dor.getDiscontinued() == false) {
          drugOrderList.add(dor);
        }
      }

      Set<DrugProduct> lotNos = new HashSet<DrugProduct>();
      int solde = 0;

      List<Integer> drugIdss = new ArrayList<Integer>();
      List<DrugOrder> drugOrders1 = new ArrayList<DrugOrder>();
      for (DrugOrder drOr : drugOrderList) {
        if (!drugIdss.contains(drOr.getDrug().getDrugId()) && drOr.getAutoExpireDate() == null) {
          dld = new DrugLotDate();
          drugOrders1.add(drOr);
          drugIdList.add(drOr.getDrug().getDrugId());

          dld.setDrugOrder(drOr);
          drug = conceptService.getDrug(drOr.getDrug().getDrugId());
          dld.setDrug(drug);
          Map<String, String> dpMap = new HashMap<String, String>();
          lotNos =
              Utils.getLotsExpDp(
                  null, drOr.getDrug().getDrugId() + "", null, pharmacy.getPharmacyId() + "");

          /**
           * TO DO change this list of lotNos by the testLots in the Utils class remember to
           * retrieve a list of list instead of a unique set!!!!!!!!!!!!!!!!
           */
          if (lotNos.size() > 0) {
            for (DrugProduct drugproduct : lotNos) {
              if (drug != null)
                solde =
                    service.getCurrSoldeDisp(
                        drug.getDrugId() + "",
                        null,
                        pharmacy.getPharmacyId() + "",
                        drugproduct.getExpiryDate() + "",
                        drugproduct.getLotNo(),
                        null);

              if (solde != 0) {
                dpMap.put(
                    drugproduct.getLotNo()
                        + " / "
                        + solde
                        + " ("
                        + drugproduct.getExpiryDate()
                        + ") ",
                    drugproduct.getDrugproductId() + "");
                dld.setDpMap(dpMap);
              }
            }
            if (dpMap.size() > 0) dlds.add(dld);
          }
        }
        drugIdss.add(drOr.getDrug().getDrugId());
      }

      mav.addObject("patient", patient);
    }

    if (dlds.size() != 0) {
      mav.addObject("dlds", dlds);
    }

    List<Object[]> lots = null;
    DrugProduct drugproduct = null;
    if (request.getParameter("drugproductId") != null
        && !request.getParameter("drugproductId").equals("")) {
      drugproduct =
          service.getDrugProductById(Integer.valueOf(request.getParameter("drugproductId")));
      if (drugproduct != null) {
        if (drugproduct.getCmddrugId() != null) {
          if (drugproduct.getCmddrugId().getDestination().getLocationId()
              == dftLoc.getLocationId()) {
            if (drugproduct.getDrugId() != null)
              lots =
                  service.getLotNumbersExpirationDates(
                      drugproduct.getDrugId().getDrugId() + "",
                      null,
                      dftLoc.getLocationId() + "",
                      null);
            else
              lots =
                  service.getLotNumbersExpirationDates(
                      null,
                      drugproduct.getConceptId().getConceptId() + "",
                      dftLoc.getLocationId() + "",
                      null);
          }
        } else {
          if (service.getReturnStockByDP(drugproduct).get(0).getDestination().getLocationId()
              == dftLoc.getLocationId()) {
            if (drugproduct.getDrugId() != null)
              lots =
                  service.getLotNumbersExpirationDates(
                      drugproduct.getDrugId().getDrugId() + "",
                      null,
                      dftLoc.getLocationId() + "",
                      null);
            else
              lots =
                  service.getLotNumbersExpirationDates(
                      null,
                      drugproduct.getConceptId().getConceptId() + "",
                      dftLoc.getLocationId() + "",
                      null);
          }
        }
      }
      mav.addObject("lots", lots);
    }

    if (request.getParameter("dpFromGet") != null
        && !request.getParameter("dpFromGet").equals("")) {
      DrugProduct dp =
          service.getDrugProductById(Integer.valueOf(request.getParameter("dpFromGet")));
      String dateStr = dp.getExpiryDate().toString();
      String[] dateArr = dateStr.split("-");
      String date = dateArr[2] + "/" + dateArr[1] + "/" + dateArr[0];
      mav.addObject("date", date);
    }

    mav.setViewName(getViewName());
    return mav;
  }