/**
   * @see RegimenManager#findDefinitions(String, org.openmrs.module.kenyaemr.regimen.RegimenOrder,
   *     boolean)
   */
  @Test
  public void findDefinitions_shouldFindDefinitionsForRegimen() {
    // Create regimen that matches the regimen2 definition exactly
    DrugOrder lamivudine = new DrugOrder();
    lamivudine.setConcept(Context.getConceptService().getConcept(78643));
    lamivudine.setDose(150d);
    lamivudine.setUnits("mg");
    lamivudine.setFrequency("BD");
    DrugOrder stavudine = new DrugOrder();
    stavudine.setConcept(Context.getConceptService().getConcept(84309));
    stavudine.setDose(30d);
    stavudine.setUnits("mg");
    stavudine.setFrequency("OD");
    RegimenOrder regimen =
        new RegimenOrder(new HashSet<DrugOrder>(Arrays.asList(lamivudine, stavudine)));

    // Test exact match
    List<RegimenDefinition> defsExact = regimenManager.findDefinitions("category1", regimen, true);
    Assert.assertEquals(1, defsExact.size());
    Assert.assertEquals("regimen2", defsExact.get(0).getName());

    // Test non-exact match
    List<RegimenDefinition> defsNonExact =
        regimenManager.findDefinitions("category1", regimen, false);
    Assert.assertEquals(2, defsNonExact.size());
    Assert.assertEquals("regimen2", defsNonExact.get(0).getName());
    Assert.assertEquals("regimen3", defsNonExact.get(1).getName());
  }
 /**
  * @verifies fail validation if frequency is null for SIMPLE dosingType
  * @see DrugOrderValidator#validate(Object, org.springframework.validation.Errors)
  */
 @Test
 public void validate_shouldFailValidationIfFrequencyIsNullForSIMPLEDosingType() throws Exception {
   DrugOrder order = new DrugOrder();
   order.setDosingType(DrugOrder.DosingType.SIMPLE);
   order.setFrequency(null);
   Errors errors = new BindException(order, "order");
   new DrugOrderValidator().validate(order, errors);
   Assert.assertTrue(errors.hasFieldErrors("frequency"));
 }
 @Override
 public Date getAutoExpireDate(DrugOrder drugOrder) {
   return DrugOrderUtil.calculateAutoExpireDate(
       drugOrder.getDuration(),
       drugOrder.getDurationUnits(),
       drugOrder.getNumRefills(),
       drugOrder.getEffectiveStartDate(),
       drugOrder.getFrequency());
 }
 /**
  * @verifies fail validation if doseUnits is null when dose is present
  * @see DrugOrderValidator#validate(Object, org.springframework.validation.Errors)
  */
 @Test
 public void validate_shouldFailValidationIfDoseUnitsIsNullWhenDoseIsPresent() throws Exception {
   DrugOrder order = new DrugOrder();
   order.setDosingType(DrugOrder.DosingType.FREE_TEXT);
   order.setDose(20.0);
   order.setDoseUnits(null);
   Errors errors = new BindException(order, "order");
   new DrugOrderValidator().validate(order, errors);
   Assert.assertTrue(errors.hasFieldErrors("doseUnits"));
 }
 /**
  * @verifies fail validation if dosingInstructions is null for FREE_TEXT dosingType
  * @see DrugOrderValidator#validate(Object, org.springframework.validation.Errors)
  */
 @Test
 public void validate_shouldFailValidationIfDosingInstructionsIsNullForFREE_TEXTDosingType()
     throws Exception {
   DrugOrder order = new DrugOrder();
   order.setDosingType(DrugOrder.DosingType.FREE_TEXT);
   order.setDosingInstructions(null);
   Errors errors = new BindException(order, "order");
   new DrugOrderValidator().validate(order, errors);
   Assert.assertTrue(errors.hasFieldErrors("dosingInstructions"));
 }
 @Test
 public void getAutoExpireDate_shouldInferAutoExpireDateForAKnownSNOMEDCTDurationUnit()
     throws Exception {
   DrugOrder drugOrder = new DrugOrder();
   drugOrder.setDateActivated(createDateTime("2014-07-01 10:00:00"));
   drugOrder.setDuration(30);
   drugOrder.setDurationUnits(createUnits(Duration.SNOMED_CT_SECONDS_CODE));
   Date autoExpireDate = new SimpleDosingInstructions().getAutoExpireDate(drugOrder);
   assertEquals(createDateTime("2014-07-01 10:00:29"), autoExpireDate);
 }
 private DrugOrder createValidDrugOrder() {
   DrugOrder drugOrder = new DrugOrder();
   drugOrder.setDose(10.0);
   drugOrder.setDoseUnits(createConceptWithName("ml"));
   drugOrder.setRoute(createConceptWithName("IV"));
   OrderFrequency frequency = new OrderFrequency();
   frequency.setConcept(createConceptWithName("Twice a day"));
   drugOrder.setFrequency(frequency);
   return drugOrder;
 }
  @Test
  @Verifies(
      value = "should return encounter with all child objects voided according to schema",
      method = "voidEncounterByHtmlFormSchema")
  public void testVoidEncounterByHtmlFormSchema_shouldHandleDrugOrderCorrectly() throws Exception {
    executeDataSet(
        XML_DATASET_PATH + new TestUtil().getTestDatasetFilename(XML_REGRESSION_TEST_DATASET));
    Encounter e = new Encounter();
    e.setPatient(Context.getPatientService().getPatient(2));
    Date date = Context.getDateFormat().parse("01/02/2003");
    e.setDateCreated(new Date());
    e.setEncounterDatetime(date);
    e.setLocation(Context.getLocationService().getLocation(2));
    e.setProvider(Context.getPersonService().getPerson(502));
    TestUtil.addObs(e, 1, 5000, date); // a matching obs

    DrugOrder dor = new DrugOrder();
    dor.setVoided(false);
    dor.setConcept(Context.getConceptService().getConcept(792));
    dor.setCreator(Context.getUserService().getUser(1));
    dor.setDateCreated(new Date());
    dor.setDiscontinued(false);
    dor.setDrug(Context.getConceptService().getDrug(2));
    dor.setOrderType(Context.getOrderService().getOrderType(1));
    dor.setPatient(Context.getPatientService().getPatient(2));
    dor.setStartDate(new Date());
    e.addOrder(dor);

    Context.getEncounterService().saveEncounter(e);

    Form form = new Form();
    HtmlForm htmlform = new HtmlForm();
    htmlform.setForm(form);
    form.setEncounterType(new EncounterType());
    htmlform.setDateChanged(new Date());
    htmlform.setXmlData(
        new TestUtil()
            .loadXmlFromFile(
                XML_DATASET_PATH + "returnSectionsAndConceptsInSectionsTestFormWithGroups.xml"));

    HtmlFormEntryUtil.voidEncounterByHtmlFormSchema(e, htmlform, "test void reason");

    // this is going to test out the voided state of the obs in the encounter after processing:
    // order was matched, so order was voided, and because that's the only thing in the encounter,
    // encounter was voided too.
    Assert.assertTrue(e.isVoided());
    Assert.assertTrue(e.getVoidReason().equals("test void reason"));
    for (Order o : e.getOrders()) {
      Assert.assertTrue(o.isVoided());
      Assert.assertTrue(o.getVoidReason().equals("test void reason"));
    }
    for (Obs o : e.getAllObs(true)) {
      Assert.assertTrue(o.getVoidReason().equals("test void reason"));
    }
  }
 @Override
 public DosingInstructions getDosingInstructions(DrugOrder order) {
   if (!order.getDosingType().equals(this.getClass())) {
     throw new APIException(
         "Dosing type of drug order is mismatched. Expected:"
             + this.getClass()
             + " but received:"
             + order.getDosingType());
   }
   return new FlexibleDosingInstructions();
 }
  @Test
  public void validate_shouldPassValidationIfAutoExpireDateAndDurationUnitsAreNotSet()
      throws Exception {
    DrugOrder drugOrder = createValidDrugOrder();
    drugOrder.setDurationUnits(null);
    drugOrder.setAutoExpireDate(null);
    Errors errors = new BindException(drugOrder, "drugOrder");

    new SimpleDosingInstructions().validate(drugOrder, errors);

    Assert.assertFalse(errors.hasErrors());
  }
  @Test
  public void getAutoExpireDate_shouldNotInferAutoExpireDateWhenDurationUnitsDoesNotExist()
      throws Exception {
    DrugOrder drugOrder = new DrugOrder();
    drugOrder.setDateActivated(createDateTime("2014-07-01 10:00:00"));
    drugOrder.setDuration(1);
    drugOrder.setDurationUnits(null);

    Date autoExpireDate = new SimpleDosingInstructions().getAutoExpireDate(drugOrder);

    assertEquals(null, autoExpireDate);
  }
  @Test
  @Verifies(
      value = "should return encounter with all child objects voided according to schema",
      method = "voidEncounterByHtmlFormSchema")
  public void testVoidEncounterByHtmlFormSchema_shouldHandleDrugOrderAndObsCorrectly()
      throws Exception {
    executeDataSet(
        XML_DATASET_PATH + new TestUtil().getTestDatasetFilename(XML_REGRESSION_TEST_DATASET));
    Encounter e = new Encounter();
    e.setPatient(Context.getPatientService().getPatient(2));
    Date date = Context.getDateFormat().parse("01/02/2003");
    e.setDateCreated(new Date());
    e.setEncounterDatetime(date);
    e.setLocation(Context.getLocationService().getLocation(2));
    e.setProvider(Context.getPersonService().getPerson(502));
    TestUtil.addObs(e, 3, 5000, date); // adding an un-matched Obs

    DrugOrder dor = new DrugOrder();
    dor.setVoided(false);
    dor.setConcept(Context.getConceptService().getConcept(792));
    dor.setCreator(Context.getUserService().getUser(1));
    dor.setDateCreated(new Date());
    dor.setDiscontinued(false);
    dor.setDrug(Context.getConceptService().getDrug(2));
    dor.setOrderType(Context.getOrderService().getOrderType(1));
    dor.setPatient(Context.getPatientService().getPatient(2));
    dor.setStartDate(new Date());
    e.addOrder(dor);

    Context.getEncounterService().saveEncounter(e);

    Form form = new Form();
    HtmlForm htmlform = new HtmlForm();
    htmlform.setForm(form);
    form.setEncounterType(new EncounterType());
    htmlform.setDateChanged(new Date());
    htmlform.setXmlData(
        new TestUtil()
            .loadXmlFromFile(
                XML_DATASET_PATH + "returnSectionsAndConceptsInSectionsTestFormWithGroups.xml"));

    HtmlFormEntryUtil.voidEncounterByHtmlFormSchema(e, htmlform, null);

    // order was matched, obs was not, so order should be voided, obs not, encounter not.
    Assert.assertTrue(!e.isVoided());
    for (Order o : e.getOrders()) {
      Assert.assertTrue(o.isVoided());
    }
    for (Obs o : e.getObs()) {
      Assert.assertTrue(!o.isVoided());
    }
  }
  /** @see {@link DrugOrderValidator#validate(Object,Errors)} */
  @Test
  @Verifies(
      value = "should not fail validation if drug is null",
      method = "validate(Object,Errors)")
  public void validate_shouldNotFailValidationIfDrugIsNull() throws Exception {
    DrugOrder order = new DrugOrder();
    order.setDrug(null);

    Errors errors = new BindException(order, "order");
    new DrugOrderValidator().validate(order, errors);

    Assert.assertFalse(errors.hasFieldErrors("drug"));
  }
  /**
   * @verifies reject a duration unit with a mapping of an invalid type
   * @see SimpleDosingInstructions#validate(DrugOrder, org.springframework.validation.Errors)
   */
  @Test
  public void validate_shouldRejectADurationUnitWithAMappingOfAnInvalidType() throws Exception {
    DrugOrder drugOrder = createValidDrugOrder();
    drugOrder.setDuration(30);
    Concept durationUnitWithInvalidMapType =
        createUnits("SCT", Duration.SNOMED_CT_DAYS_CODE, "Some-uuid");
    drugOrder.setDurationUnits(durationUnitWithInvalidMapType);
    Errors errors = new BindException(drugOrder, "drugOrder");

    new SimpleDosingInstructions().validate(drugOrder, errors);

    assertEquals(true, errors.hasErrors());
  }
  @Test
  public void
      getAutoExpireDate_shouldNotInferAutoExpireDateWhenConceptMappingOfSourceSNOMEDCTDurationDoesNotExist()
          throws Exception {
    DrugOrder drugOrder = new DrugOrder();
    drugOrder.setDateActivated(createDateTime("2014-07-01 10:00:00"));
    drugOrder.setDuration(30);
    drugOrder.setDurationUnits(createUnits("Other.Source", Duration.SNOMED_CT_HOURS_CODE, null));

    Date autoExpireDate = new SimpleDosingInstructions().getAutoExpireDate(drugOrder);

    assertEquals(null, autoExpireDate);
  }
  @Test
  public void getAutoExpireDate_shouldNotInferAutoExpireDateWhenDrugOrderHasOneOrMoreRefill()
      throws Exception {
    DrugOrder drugOrder = new DrugOrder();
    drugOrder.setDateActivated(createDateTime("2014-07-01 10:00:00"));
    drugOrder.setDuration(30);
    drugOrder.setDurationUnits(createUnits(Duration.SNOMED_CT_SECONDS_CODE));
    drugOrder.setNumRefills(1);

    Date autoExpireDate = new SimpleDosingInstructions().getAutoExpireDate(drugOrder);

    assertEquals(null, autoExpireDate);
  }
  /** @see {@link DrugOrderValidator#validate(Object,Errors)} */
  @Test
  @Verifies(
      value = "should fail validation if dosingType is null",
      method = "validate(Object,Errors)")
  public void validate_shouldFailValidationIfDosingTypeIsNull() throws Exception {
    DrugOrder order = new DrugOrder();
    order.setDosingType(null);
    order.setDrug(Context.getConceptService().getDrug(3));

    Errors errors = new BindException(order, "order");
    new DrugOrderValidator().validate(order, errors);

    Assert.assertTrue(errors.hasFieldErrors("dosingType"));
  }
  @Test
  public void
      validate_shouldPassValidationIfAutoExpireDateIsSetAndDurationUnitsIsNotMappedToSNOMEDCTDuration()
          throws Exception {
    DrugOrder drugOrder = createValidDrugOrder();
    drugOrder.setDuration(30);
    Concept unMappedDurationUnits = new Concept();
    drugOrder.setDurationUnits(unMappedDurationUnits);
    drugOrder.setAutoExpireDate(createDateTime("2014-07-01 10:00:00"));
    Errors errors = new BindException(drugOrder, "drugOrder");

    new SimpleDosingInstructions().validate(drugOrder, errors);

    Assert.assertFalse(errors.hasErrors());
  }
  @Test
  public void
      validate_shouldFailValidationIfAutoExpireDateIsNotSetAndDurationUnitsIsNotMappedToSNOMEDCTDuration()
          throws Exception {
    DrugOrder drugOrder = createValidDrugOrder();
    drugOrder.setDuration(30);
    Concept unMappedDurationUnits = new Concept();
    drugOrder.setDurationUnits(unMappedDurationUnits);
    drugOrder.setAutoExpireDate(null);
    Errors errors = new BindException(drugOrder, "drugOrder");

    new SimpleDosingInstructions().validate(drugOrder, errors);

    Assert.assertTrue(errors.hasFieldErrors("durationUnits"));
    Assert.assertEquals(
        "DrugOrder.error.durationUnitsNotMappedToSnomedCtDurationCode",
        errors.getFieldError("durationUnits").getCode());
  }
  /** @see {@link DrugOrderValidator#validate(Object,Errors)} */
  @Test
  @Verifies(
      value = "should fail validation if drug concept is different from order concept",
      method = "validate(Object,Errors)")
  public void validate_shouldFailValidationIfDrugConceptIsDifferentFromOrderConcept()
      throws Exception {
    DrugOrder order = new DrugOrder();
    Drug drug = Context.getConceptService().getDrug(3);
    Concept concept = Context.getConceptService().getConcept(792);
    order.setDrug(drug);
    order.setConcept(concept); // the actual concept which matches with drug is "88"
    Assert.assertNotEquals(drug.getConcept(), concept);

    Errors errors = new BindException(order, "order");
    new DrugOrderValidator().validate(order, errors);

    Assert.assertTrue(errors.hasFieldErrors("concept"));
    Assert.assertTrue(errors.hasFieldErrors("drug"));
  }
  public PatientDataResult evaluate(RowPerPatientData patientData, EvaluationContext context) {

    DateResult par = new DateResult(patientData, context);
    DateOfFirstDrugOrderStartedRestrictedByConceptSet pd =
        (DateOfFirstDrugOrderStartedRestrictedByConceptSet) patientData;

    par.setFormat(pd.getDateFormat());

    List<DrugOrder> orders = Context.getOrderService().getDrugOrdersByPatient(pd.getPatient());

    if (orders != null) {
      if (pd.getDrugConceptSetConcept() != null) {
        List<Concept> drugConcepts =
            Context.getConceptService().getConceptsByConceptSet(pd.getDrugConceptSetConcept());
        if (drugConcepts != null) {
          DrugOrder startDrugOrder = null;
          for (DrugOrder order : orders) {
            Concept drug = null;
            try {
              drug = order.getDrug().getConcept();
            } catch (Exception e) {
              log.error("Unable to retrieve a drug from the drug order: " + e.getMessage());
            }
            if (drug != null) {
              if (drugConcepts.contains(drug)) {
                if (order.getStartDate() != null
                    && (pd.getStartDate() == null
                        || OpenmrsUtil.compare(order.getStartDate(), pd.getStartDate()) >= 0)
                    && (pd.getEndDate() == null
                        || OpenmrsUtil.compare(order.getStartDate(), pd.getEndDate()) <= 0)) {
                  if (startDrugOrder == null
                      || order.getStartDate().before(startDrugOrder.getStartDate())) {
                    startDrugOrder = order;
                  }
                }
              }
            }
          }
          if (startDrugOrder != null) {
            par.setValue(startDrugOrder.getStartDate());
          }
        }
      }
    }

    return par;
  }
  /**
   * @verifies fail if route is not a valid concept
   * @see DrugOrderValidator#validate(Object, org.springframework.validation.Errors)
   */
  @Test
  public void validate_shouldFailIfRouteIsNotAValidConcept() throws Exception {
    Concept concept = Context.getConceptService().getConcept(3);
    assertThat(concept, not(isIn(Context.getOrderService().getDrugRoutes())));

    DrugOrder order = new DrugOrder();
    order.setDosingType(DrugOrder.DosingType.FREE_TEXT);
    order.setDuration(5.0);
    order.setDurationUnits(concept);
    order.setDose(1.0);
    order.setDoseUnits(concept);
    order.setQuantity(30.0);
    order.setQuantityUnits(concept);
    order.setRoute(concept);

    Errors errors = new BindException(order, "order");
    new DrugOrderValidator().validate(order, errors);
    Assert.assertTrue(errors.hasFieldErrors("route"));
    Assert.assertEquals(
        "DrugOrder.error.routeNotAmongAllowedConcepts", errors.getFieldError("route").getCode());
  }
  /**
   * @see DrugOrderValidator#validate(Object,Errors)
   * @verifies fail validation if doseUnits is not a dose unit concept
   */
  @Test
  public void validate_shouldFailValidationIfDoseUnitsIsNotADoseUnitConcept() throws Exception {
    Concept concept = Context.getConceptService().getConcept(3);
    assertThat(concept, not(isIn(Context.getOrderService().getDrugDosingUnits())));

    DrugOrder order = new DrugOrder();
    order.setDosingType(DrugOrder.DosingType.FREE_TEXT);
    order.setDuration(5.0);
    order.setDurationUnits(concept);
    order.setDose(1.0);
    order.setDoseUnits(concept);
    order.setQuantity(30.0);
    order.setQuantityUnits(concept);

    Errors errors = new BindException(order, "order");
    new DrugOrderValidator().validate(order, errors);
    Assert.assertTrue(errors.hasFieldErrors("doseUnits"));
  }
 @Test
 public void getAutoExpireDate_shouldInferAutoExpireDateForScheduledDrugOrder() throws Exception {
   DrugOrder drugOrder = new DrugOrder();
   drugOrder.setDateActivated(createDateTime("2014-07-01 00:00:00"));
   drugOrder.setScheduledDate(createDateTime("2014-07-05 00:00:00"));
   drugOrder.setUrgency(Order.Urgency.ON_SCHEDULED_DATE);
   drugOrder.setDuration(10);
   drugOrder.setDurationUnits(createUnits(Duration.SNOMED_CT_DAYS_CODE));
   Date autoExpireDate = new SimpleDosingInstructions().getAutoExpireDate(drugOrder);
   assertEquals(createDateTime("2014-07-14 23:59:59"), autoExpireDate);
 }
  /**
   * @verifies fail validation if numberOfRefills is null for outpatient careSetting
   * @see DrugOrderValidator#validate(Object, org.springframework.validation.Errors)
   */
  @Test
  public void validate_shouldFailValidationIfNumberOfRefillsIsNullForOutpatientCareSetting()
      throws Exception {
    DrugOrder OutpatientOrder = new DrugOrder();
    OutpatientOrder.setCareSetting(Context.getOrderService().getCareSetting(1));
    OutpatientOrder.setNumRefills(null);
    Errors OutpatientOrderErrors = new BindException(OutpatientOrder, "order");
    new DrugOrderValidator().validate(OutpatientOrder, OutpatientOrderErrors);
    Assert.assertTrue(OutpatientOrderErrors.hasFieldErrors("numRefills"));

    DrugOrder inPatientOrder = new DrugOrder();
    inPatientOrder.setCareSetting(Context.getOrderService().getCareSetting(2));
    inPatientOrder.setNumRefills(null);
    Errors InpatientOrderErrors = new BindException(inPatientOrder, "order");
    new DrugOrderValidator().validate(inPatientOrder, InpatientOrderErrors);
    Assert.assertFalse(InpatientOrderErrors.hasFieldErrors("numRefills"));
  }
  @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;
  }
  @Test
  public void shouldAddNewDrugOrder() {

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

    when(orderService.getAllOrderTypes()).thenReturn(asList(drugOrderType));
    int instructionConceptId = 1;
    when(conceptService.getConceptByUuid("dosage-instruction-uuid"))
        .thenReturn(new Concept(instructionConceptId));
    Integer frequencyConceptId = 2;
    when(conceptService.getConceptByUuid("dosage-frequency-uuid"))
        .thenReturn(new Concept(frequencyConceptId));
    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("this is notes", order.getInstructions());
    assertEquals("dosage-instruction-uuid", order.getUnits());
    assertEquals("dosage-frequency-uuid", order.getFrequency());
    assertEquals(today, order.getStartDate());
    assertEquals(today, order.getAutoExpireDate());
    assertEquals(drug.getDisplayName(), order.getDrug().getDisplayName());
    assertEquals(Double.valueOf(3), order.getDose());
    assertEquals(false, order.getPrn());
  }
 @Override
 public void setDosingInstructions(DrugOrder order) {
   order.setDosingType(this.getClass());
 }
  public DataSetRow renderRow(
      Patient p,
      PatientIdentifierType patientIdentifierType,
      Location location,
      Date startDate,
      Date endDate) {

    PatientDataHelper pdh = new PatientDataHelper();
    ProgramHelper ph = new ProgramHelper();
    HivMetadata hivMetadata = new HivMetadata();

    DataSetRow row = new DataSetRow();
    pdh.addCol(row, "#", p.getPatientId());
    pdh.addCol(row, "KS ID", pdh.preferredIdentifierAtLocation(p, patientIdentifierType, location));
    pdh.addCol(
        row,
        "ART ID",
        pdh.preferredIdentifierAtLocation(p, lookupPatientIdentifierType("ARV Number"), location));
    pdh.addCol(row, "Birthdate", pdh.getBirthdate(p));
    pdh.addCol(row, "Gender", pdh.getGender(p));
    pdh.addCol(row, "VHW", pdh.vhwName(p, false));
    pdh.addCol(row, "Village", pdh.getVillage(p));

    PatientProgram latestKsProgram =
        ph.getMostRecentProgramEnrollmentAtLocation(
            p, lookupProgram("Kaposis sarcoma program"), location);

    Date latestKsProgramDate = null;
    if (latestKsProgram != null) {
      latestKsProgramDate = latestKsProgram.getDateEnrolled();
      pdh.addCol(row, "KS Program Enrollment Date", pdh.formatYmd(latestKsProgramDate));

      for (PatientState ps : ph.getActiveStatesOnDate(p, latestKsProgramDate)) {
        String programName = ps.getPatientProgram().getProgram().getName();
        pdh.addCol(row, programName + " Status at Enrollment", pdh.formatStateName(ps));
        pdh.addCol(row, programName + " Status Date at Enrollment", pdh.formatStateStartDate(ps));
      }
    }

    Obs mostRecentDxDate = pdh.getLatestObs(p, "DATE OF HIV DIAGNOSIS", null, endDate);
    pdh.addCol(row, "Date HIV Diagnosis", pdh.formatValueDatetime(mostRecentDxDate));

    Program hivProgram = hivMetadata.getHivProgram();
    ProgramWorkflowState onArvState = hivMetadata.getOnArvsState();

    PatientState earliestOnArvsState = ph.getFirstTimeInState(p, hivProgram, onArvState, endDate);
    Date arvStartDate = (earliestOnArvsState == null ? null : earliestOnArvsState.getStartDate());

    if (latestKsProgramDate != null) {
      pdh.addCol(
          row,
          "On ART at KS Enrollment",
          arvStartDate != null && arvStartDate.compareTo(latestKsProgramDate) <= 0);
    }

    Map<String, String> reasonsForStartingArvs = pdh.getReasonStartingArvs(p, endDate);
    for (String reasonKey : reasonsForStartingArvs.keySet()) {
      pdh.addCol(row, "ARV Reason " + reasonKey, reasonsForStartingArvs.get(reasonKey));
    }

    if (arvStartDate != null) {
      pdh.addCol(row, "Start Date for ART", pdh.formatStateStartDate(earliestOnArvsState));
      if (latestKsProgramDate != null) {
        pdh.addCol(
            row,
            "Months on ART at KS Enrollment",
            DateUtil.monthsBetween(arvStartDate, latestKsProgramDate));
      }
    }

    if (latestKsProgramDate != null) {
      Obs artRegimen =
          pdh.getLatestObs(p, "Malawi Antiretroviral drugs received", null, latestKsProgramDate);
      pdh.addCol(row, "ART Regimen Obs at Enrollment", pdh.formatValue(artRegimen));

      Set<Concept> drugOrdersAtEnrollment = pdh.getDrugsTakingOnDate(p, latestKsProgramDate);
      pdh.addCol(
          row, "Drugs Taking at Enrollment", pdh.formatConcepts(drugOrdersAtEnrollment, "+"));

      Obs cd4 = pdh.getLatestObs(p, "CD4 count", null, latestKsProgramDate);
      pdh.addCol(row, "CD4 at enrollment", pdh.formatValue(cd4));
      pdh.addCol(row, "CD4 at enrollment date", pdh.formatObsDatetime(cd4));
    }

    Obs height = pdh.getLatestObs(p, "Height (cm)", null, endDate);
    pdh.addCol(row, "Latest Height", pdh.formatValue(height));
    pdh.addCol(row, "Latest Height Date", pdh.formatObsDatetime(height));

    Obs firstTaxolObs = pdh.getEarliestObs(p, "Paclitaxel (taxol) dose received", null, endDate);
    pdh.addCol(row, "First Taxol Dose Received Date", pdh.formatObsDatetime(firstTaxolObs));

    DrugOrder firstTaxolOrder = pdh.getEarliestDrugOrder(p, "Paclitaxel", endDate);
    pdh.addCol(row, "First Taxol Drug Order Date", pdh.formatOrderStartDate(firstTaxolOrder));

    Date firstTaxolDate = null;
    if (firstTaxolObs != null) {
      firstTaxolDate = firstTaxolObs.getObsDatetime();
    }
    if (firstTaxolOrder != null) {
      if (firstTaxolDate == null || firstTaxolOrder.getStartDate().before(firstTaxolDate)) {
        firstTaxolDate = firstTaxolOrder.getStartDate();
      }
    }
    pdh.addCol(row, "First Taxol Date", pdh.formatYmd(firstTaxolDate));

    if (firstTaxolDate != null) {
      Obs cd4AtTaxol = pdh.getLatestObs(p, "CD4 count", null, firstTaxolDate);
      pdh.addCol(row, "Most recent CD4 at First Taxol", pdh.formatValue(cd4AtTaxol));
      pdh.addCol(row, "Most recent CD4 at First Taxol Date", pdh.formatObsDatetime(cd4AtTaxol));
    }

    for (PatientState ps : ph.getActiveStatesOnDate(p, endDate)) {
      String ed = pdh.formatYmd(endDate);
      String programName = ps.getPatientProgram().getProgram().getName();
      pdh.addCol(row, programName + " Status on " + ed, pdh.formatStateName(ps));
      pdh.addCol(row, programName + " Status Date on " + ed, pdh.formatStateStartDate(ps));
    }

    pdh.addCol(row, "Death Date", pdh.formatYmd(p.getDeathDate()));

    return row;
  }
  /**
   * This method produces a model containing the following mappings:
   *
   * <pre>
   *     (always)
   *          (java.util.Date) now
   *          (String) size
   *          (Locale) locale
   *          (String) portletUUID // unique for each instance of any portlet
   *          (other parameters)
   *     (if there's currently an authenticated user)
   *          (User) authenticatedUser
   *     (if the request has a patientId attribute)
   *          (Integer) patientId
   *          (Patient) patient
   *          (List<Obs>) patientObs
   *          (List<Encounter>) patientEncounters
   *          (List<DrugOrder>) patientDrugOrders
   *          (List<DrugOrder>) currentDrugOrders
   *          (List<DrugOrder>) completedDrugOrders
   *          (Obs) patientWeight // most recent weight obs
   *          (Obs) patientHeight // most recent height obs
   *          (Double) patientBmi // BMI derived from most recent weight and most recent height
   *          (String) patientBmiAsString // BMI rounded to one decimal place, or "?" if unknown
   *          (Integer) personId
   *          (if the patient has any obs for the concept in the global property 'concept.reasonExitedCare')
   *              (Obs) patientReasonForExit
   *     (if the request has a personId or patientId attribute)
   *          (Person) person
   *          (List<Relationship>) personRelationships
   *          (Map<RelationshipType, List<Relationship>>) personRelationshipsByType
   *     (if the request has an encounterId attribute)
   *          (Integer) encounterId
   *          (Encounter) encounter
   *          (Set<Obs>) encounterObs
   *     (if the request has a userId attribute)
   *          (Integer) userId
   *          (User) user
   *     (if the request has a patientIds attribute, which should be a (String) comma-separated list of patientIds)
   *          (PatientSet) patientSet
   *          (String) patientIds
   *     (if the request has a conceptIds attribute, which should be a (String) commas-separated list of conceptIds)
   *          (Map<Integer, Concept>) conceptMap
   *          (Map<String, Concept>) conceptMapByStringIds
   * </pre>
   *
   * @should calculate bmi into patientBmiAsString
   * @should not fail with empty height and weight properties
   */
  @SuppressWarnings("unchecked")
  public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    AdministrationService as = Context.getAdministrationService();
    ConceptService cs = Context.getConceptService();

    // find the portlet that was identified in the openmrs:portlet taglib
    Object uri = request.getAttribute("javax.servlet.include.servlet_path");
    String portletPath = "";
    Map<String, Object> model = null;
    {
      HttpSession session = request.getSession();
      String uniqueRequestId = (String) request.getAttribute(WebConstants.INIT_REQ_UNIQUE_ID);
      String lastRequestId =
          (String) session.getAttribute(WebConstants.OPENMRS_PORTLET_LAST_REQ_ID);
      if (uniqueRequestId.equals(lastRequestId)) {
        model =
            (Map<String, Object>) session.getAttribute(WebConstants.OPENMRS_PORTLET_CACHED_MODEL);

        // remove cached parameters
        List<String> parameterKeys = (List<String>) model.get("parameterKeys");
        for (String key : parameterKeys) {
          model.remove(key);
        }
      }
      if (model == null) {
        log.debug("creating new portlet model");
        model = new HashMap<String, Object>();
        session.setAttribute(WebConstants.OPENMRS_PORTLET_LAST_REQ_ID, uniqueRequestId);
        session.setAttribute(WebConstants.OPENMRS_PORTLET_CACHED_MODEL, model);
      }
    }

    if (uri != null) {
      long timeAtStart = System.currentTimeMillis();
      portletPath = uri.toString();

      // Allowable extensions are '' (no extension) and '.portlet'
      if (portletPath.endsWith("portlet")) portletPath = portletPath.replace(".portlet", "");
      else if (portletPath.endsWith("jsp"))
        throw new ServletException(
            "Illegal extension used for portlet: '.jsp'. Allowable extensions are '' (no extension) and '.portlet'");

      log.debug("Loading portlet: " + portletPath);

      String id = (String) request.getAttribute("org.openmrs.portlet.id");
      String size = (String) request.getAttribute("org.openmrs.portlet.size");
      Map<String, Object> params =
          (Map<String, Object>) request.getAttribute("org.openmrs.portlet.parameters");
      Map<String, Object> moreParams =
          (Map<String, Object>) request.getAttribute("org.openmrs.portlet.parameterMap");

      model.put("now", new Date());
      model.put("id", id);
      model.put("size", size);
      model.put("locale", Context.getLocale());
      model.put("portletUUID", UUID.randomUUID().toString().replace("-", ""));
      List<String> parameterKeys = new ArrayList<String>(params.keySet());
      model.putAll(params);
      if (moreParams != null) {
        model.putAll(moreParams);
        parameterKeys.addAll(moreParams.keySet());
      }
      model.put("parameterKeys", parameterKeys); // so we can clean these up in the next request

      // if there's an authenticated user, put them, and their patient set, in the model
      if (Context.getAuthenticatedUser() != null) {
        model.put("authenticatedUser", Context.getAuthenticatedUser());
      }

      Integer personId = null;

      // if a patient id is available, put patient data documented above in the model
      Object o = request.getAttribute("org.openmrs.portlet.patientId");
      if (o != null) {
        String patientVariation = "";
        Integer patientId = (Integer) o;
        if (!model.containsKey("patient")) {
          // we can't continue if the user can't view patients
          if (Context.hasPrivilege(PrivilegeConstants.VIEW_PATIENTS)) {
            Patient p = Context.getPatientService().getPatient(patientId);
            model.put("patient", p);

            // add encounters if this user can view them
            if (Context.hasPrivilege(PrivilegeConstants.VIEW_ENCOUNTERS))
              model.put(
                  "patientEncounters", Context.getEncounterService().getEncountersByPatient(p));

            if (Context.hasPrivilege(PrivilegeConstants.VIEW_OBS)) {
              List<Obs> patientObs = Context.getObsService().getObservationsByPerson(p);
              model.put("patientObs", patientObs);
              Obs latestWeight = null;
              Obs latestHeight = null;
              String bmiAsString = "?";
              try {
                String weightString = as.getGlobalProperty("concept.weight");
                ConceptNumeric weightConcept = null;
                if (StringUtils.hasLength(weightString))
                  weightConcept =
                      cs.getConceptNumeric(
                          cs.getConcept(Integer.valueOf(weightString)).getConceptId());
                String heightString = as.getGlobalProperty("concept.height");
                ConceptNumeric heightConcept = null;
                if (StringUtils.hasLength(heightString))
                  heightConcept =
                      cs.getConceptNumeric(
                          cs.getConcept(Integer.valueOf(heightString)).getConceptId());
                for (Obs obs : patientObs) {
                  if (obs.getConcept().equals(weightConcept)) {
                    if (latestWeight == null
                        || obs.getObsDatetime().compareTo(latestWeight.getObsDatetime()) > 0)
                      latestWeight = obs;
                  } else if (obs.getConcept().equals(heightConcept)) {
                    if (latestHeight == null
                        || obs.getObsDatetime().compareTo(latestHeight.getObsDatetime()) > 0)
                      latestHeight = obs;
                  }
                }
                if (latestWeight != null) model.put("patientWeight", latestWeight);
                if (latestHeight != null) model.put("patientHeight", latestHeight);
                if (latestWeight != null && latestHeight != null) {
                  double weightInKg;
                  double heightInM;
                  if (weightConcept.getUnits().equals("kg"))
                    weightInKg = latestWeight.getValueNumeric();
                  else if (weightConcept.getUnits().equals("lb"))
                    weightInKg = latestWeight.getValueNumeric() * 0.45359237;
                  else
                    throw new IllegalArgumentException(
                        "Can't handle units of weight concept: " + weightConcept.getUnits());
                  if (heightConcept.getUnits().equals("cm"))
                    heightInM = latestHeight.getValueNumeric() / 100;
                  else if (heightConcept.getUnits().equals("m"))
                    heightInM = latestHeight.getValueNumeric();
                  else if (heightConcept.getUnits().equals("in"))
                    heightInM = latestHeight.getValueNumeric() * 0.0254;
                  else
                    throw new IllegalArgumentException(
                        "Can't handle units of height concept: " + heightConcept.getUnits());
                  double bmi = weightInKg / (heightInM * heightInM);
                  model.put("patientBmi", bmi);
                  String temp = "" + bmi;
                  bmiAsString = temp.substring(0, temp.indexOf('.') + 2);
                }
              } catch (Exception ex) {
                if (latestWeight != null && latestHeight != null)
                  log.error(
                      "Failed to calculate BMI even though a weight and height were found", ex);
              }
              model.put("patientBmiAsString", bmiAsString);
            } else {
              model.put("patientObs", new HashSet<Obs>());
            }

            // information about whether or not the patient has exited care
            Obs reasonForExitObs = null;
            String reasonForExitConceptString = as.getGlobalProperty("concept.reasonExitedCare");
            if (StringUtils.hasLength(reasonForExitConceptString)) {
              Concept reasonForExitConcept = cs.getConcept(reasonForExitConceptString);
              if (reasonForExitConcept != null) {
                List<Obs> patientExitObs =
                    Context.getObsService()
                        .getObservationsByPersonAndConcept(p, reasonForExitConcept);
                if (patientExitObs != null) {
                  log.debug("Exit obs is size " + patientExitObs.size());
                  if (patientExitObs.size() == 1) {
                    reasonForExitObs = patientExitObs.iterator().next();
                    Concept exitReason = reasonForExitObs.getValueCoded();
                    Date exitDate = reasonForExitObs.getObsDatetime();
                    if (exitReason != null && exitDate != null) {
                      patientVariation = "Exited";
                    }
                  } else {
                    if (patientExitObs.size() == 0) {
                      log.debug("Patient has no reason for exit");
                    } else {
                      log.error("Too many reasons for exit - not putting data into model");
                    }
                  }
                }
              }
            }
            model.put("patientReasonForExit", reasonForExitObs);

            if (Context.hasPrivilege(PrivilegeConstants.VIEW_ORDERS)) {
              List<DrugOrder> drugOrderList = Context.getOrderService().getDrugOrdersByPatient(p);
              model.put("patientDrugOrders", drugOrderList);
              List<DrugOrder> currentDrugOrders = new ArrayList<DrugOrder>();
              List<DrugOrder> discontinuedDrugOrders = new ArrayList<DrugOrder>();
              Date rightNow = new Date();
              for (Iterator<DrugOrder> iter = drugOrderList.iterator(); iter.hasNext(); ) {
                DrugOrder next = iter.next();
                if (next.isCurrent() || next.isFuture()) currentDrugOrders.add(next);
                if (next.isDiscontinued(rightNow)) discontinuedDrugOrders.add(next);
              }
              model.put("currentDrugOrders", currentDrugOrders);
              model.put("completedDrugOrders", discontinuedDrugOrders);

              List<RegimenSuggestion> standardRegimens =
                  Context.getOrderService().getStandardRegimens();
              if (standardRegimens != null) model.put("standardRegimens", standardRegimens);
            }

            if (Context.hasPrivilege(PrivilegeConstants.VIEW_PROGRAMS)
                && Context.hasPrivilege(PrivilegeConstants.VIEW_PATIENT_PROGRAMS)) {
              model.put(
                  "patientPrograms",
                  Context.getProgramWorkflowService()
                      .getPatientPrograms(p, null, null, null, null, null, false));
              model.put(
                  "patientCurrentPrograms",
                  Context.getProgramWorkflowService()
                      .getPatientPrograms(p, null, null, new Date(), new Date(), null, false));
            }

            model.put("patientId", patientId);
            if (p != null) {
              personId = p.getPatientId();
              model.put("personId", personId);
            }

            model.put("patientVariation", patientVariation);
          }
        }
      }

      // if a person id is available, put person and relationships in the model
      if (personId == null) {
        o = request.getAttribute("org.openmrs.portlet.personId");
        if (o != null) {
          personId = (Integer) o;
          model.put("personId", personId);
        }
      }
      if (personId != null) {
        if (!model.containsKey("person")) {
          Person p = (Person) model.get("patient");
          if (p == null) p = Context.getPersonService().getPerson(personId);
          model.put("person", p);

          if (Context.hasPrivilege(PrivilegeConstants.VIEW_RELATIONSHIPS)) {
            List<Relationship> relationships = new ArrayList<Relationship>();
            relationships.addAll(Context.getPersonService().getRelationshipsByPerson(p));
            Map<RelationshipType, List<Relationship>> relationshipsByType =
                new HashMap<RelationshipType, List<Relationship>>();
            for (Relationship rel : relationships) {
              List<Relationship> list = relationshipsByType.get(rel.getRelationshipType());
              if (list == null) {
                list = new ArrayList<Relationship>();
                relationshipsByType.put(rel.getRelationshipType(), list);
              }
              list.add(rel);
            }

            model.put("personRelationships", relationships);
            model.put("personRelationshipsByType", relationshipsByType);
          }
        }
      }

      // if an encounter id is available, put "encounter" and "encounterObs" in the model
      o = request.getAttribute("org.openmrs.portlet.encounterId");
      if (o != null && !model.containsKey("encounterId")) {
        if (!model.containsKey("encounter")) {
          if (Context.hasPrivilege(PrivilegeConstants.VIEW_ENCOUNTERS)) {
            Encounter e = Context.getEncounterService().getEncounter((Integer) o);
            model.put("encounter", e);
            if (Context.hasPrivilege(PrivilegeConstants.VIEW_OBS))
              model.put("encounterObs", e.getObs());
          }
          model.put("encounterId", (Integer) o);
        }
      }

      // if a user id is available, put "user" in the model
      o = request.getAttribute("org.openmrs.portlet.userId");
      if (o != null) {
        if (!model.containsKey("user")) {
          if (Context.hasPrivilege(PrivilegeConstants.VIEW_USERS)) {
            User u = Context.getUserService().getUser((Integer) o);
            model.put("user", u);
          }
          model.put("userId", (Integer) o);
        }
      }

      // if a list of patient ids is available, make a patientset out of it
      o = request.getAttribute("org.openmrs.portlet.patientIds");
      if (o != null && !"".equals(o) && !model.containsKey("patientIds")) {
        if (!model.containsKey("patientSet")) {
          Cohort ps = new Cohort((String) o);
          model.put("patientSet", ps);
          model.put("patientIds", (String) o);
        }
      }

      o = model.get("conceptIds");
      if (o != null && !"".equals(o)) {
        if (!model.containsKey("conceptMap")) {
          log.debug("Found conceptIds parameter: " + o);
          Map<Integer, Concept> concepts = new HashMap<Integer, Concept>();
          Map<String, Concept> conceptsByStringIds = new HashMap<String, Concept>();
          String conceptIds = (String) o;
          String[] ids = conceptIds.split(",");
          for (String cId : ids) {
            try {
              Integer i = Integer.valueOf(cId);
              Concept c = cs.getConcept(i);
              concepts.put(i, c);
              conceptsByStringIds.put(i.toString(), c);
            } catch (Exception ex) {
            }
          }
          model.put("conceptMap", concepts);
          model.put("conceptMapByStringIds", conceptsByStringIds);
        }
      }

      populateModel(request, model);
      log.debug(portletPath + " took " + (System.currentTimeMillis() - timeAtStart) + " ms");
    }

    return new ModelAndView(portletPath, "model", model);
  }