@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());
    }
  }
  @Test
  @Transactional(readOnly = true)
  public void shouldVoidObservationsEvenWithDuplicateCalls()
      throws UserAlreadyExistsException, ObservationNotFoundException {

    MRSPerson personCreator = new MRSPerson().firstName("SampleTest");
    MRSPerson personJohn = new MRSPerson().firstName("John");
    patientAlan = createPatient(facility);
    MRSUser userCreator =
        createUser(
            new MRSUser()
                .userName("UserSuper")
                .systemId("1000015")
                .securityRole("Provider")
                .person(personCreator));
    MRSUser userJohn =
        createUser(
            new MRSUser()
                .userName("UserJohn")
                .systemId("1000027")
                .securityRole("Provider")
                .person(personJohn));
    MRSPerson provider = userJohn.getPerson();

    Set<MRSObservation> observations = new HashSet<MRSObservation>();
    observations.add(new MRSObservation<Double>(new Date(), "GRAVIDA", Double.valueOf("100.0")));
    final String encounterType = "PEDSRETURN";
    MRSEncounter expectedEncounter =
        new MRSEncounter(
            provider.getId(),
            userCreator.getId(),
            facility.getId(),
            new Date(),
            patientAlan.getId(),
            observations,
            encounterType);
    mrsEncounterAdapter.createEncounter(expectedEncounter);

    final MRSObservation mrsObservation =
        openMrsObservationAdapter.findObservation(patientAlan.getMotechId(), "GRAVIDA");

    openMrsObservationAdapter.voidObservation(
        mrsObservation, "reason 1", patientAlan.getMotechId());
    final String reason2 = "reason 2";
    openMrsObservationAdapter.voidObservation(mrsObservation, reason2, patientAlan.getMotechId());

    final Obs actualOpenMRSObs = obsService.getObs(Integer.valueOf(mrsObservation.getId()));
    assertTrue(actualOpenMRSObs.isVoided());
    assertThat(actualOpenMRSObs.getVoidReason(), is(reason2));
  }
    private void assertObsExists(boolean lookForVoided, int conceptId, Object value) {
      // quick checks
      Assert.assertNotNull(encounterCreated);
      Collection<Obs> temp = encounterCreated.getAllObs(lookForVoided);
      Assert.assertNotNull(temp);

      String valueAsString = TestUtil.valueAsStringHelper(value);
      for (Obs obs : temp) {
        if (lookForVoided && !obs.isVoided()) continue;
        if (obs.getConcept().getConceptId() == conceptId) {
          if (valueAsString == null) return;
          if (valueAsString.equals(obs.getValueAsString(Context.getLocale()))) return;
        }
      }
      Assert.fail("Could not find obs with conceptId " + conceptId + " and value " + valueAsString);
    }
  /**
   * @see org.openmrs.api.EncounterService#voidEncounter(org.openmrs.Encounter, java.lang.String)
   */
  public Encounter voidEncounter(Encounter encounter, String reason) {

    // if authenticated user is not supposed to edit encounter of certain type
    if (!canEditEncounter(encounter, null)) {
      throw new APIException(
          String.format(
              "Privilege %s required to void encounters of this type",
              encounter.getEncounterType().getEditPrivilege()));
    }

    if (reason == null) {
      throw new IllegalArgumentException("The argument 'reason' is required and so cannot be null");
    }

    ObsService os = Context.getObsService();
    for (Obs o : encounter.getObsAtTopLevel(false)) {
      if (!o.isVoided()) {
        os.voidObs(o, reason);
      }
    }

    OrderService orderService = Context.getOrderService();
    for (Order o : encounter.getOrders()) {
      if (!o.isVoided()) {
        orderService.voidOrder(o, reason);
      }
    }

    encounter.setVoided(true);
    encounter.setVoidedBy(Context.getAuthenticatedUser());
    // we expect the dateVoided to be already set by AOP logic at this point unless this method was
    // called within the API,
    // this ensures that original ParentVoidedDate and the dateVoided of associated objects will
    // always match for the
    // unvoid handler to work
    if (encounter.getDateVoided() == null) {
      encounter.setDateVoided(new Date());
    }
    encounter.setVoidReason(reason);
    Context.getEncounterService().saveEncounter(encounter);
    return encounter;
  }
  @Test
  @Verifies(
      value = "should return encounter with all child objects voided according to schema",
      method = "voidEncounterByHtmlFormSchema")
  public void testVoidEncounterByHtmlFormSchema_shouldReturnEncounterCorrectly() 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));

    // add a bunch of obs...
    TestUtil.addObs(e, 2474, Context.getConceptService().getConcept(656), date); // matches
    TestUtil.addObs(e, 3017, Context.getConceptService().getConcept(767), date); // matches
    TestUtil.addObs(e, 3032, new Date(), date); // matches
    TestUtil.addObs(e, 1, 5000, date); //   matches
    TestUtil.addObs(e, 2, 5000, date); // not in form schema
    TestUtil.addObs(e, 3, 5000, date); // not in form schema
    TestUtil.addObs(e, 6, "blah blah", date); //   matches
    // 1004 is ANOTHER ALLERGY CONSTRUCT, 1005 is HYPER-ALLERGY CODED, 1001 is PENICILLIN
    TestUtil.addObsGroup(
        e,
        1004,
        new Date(),
        1005,
        Context.getConceptService().getConcept(1001),
        new Date()); // matches
    // 7 IS ALLERGY CONSTRUCT, 1000 IS ALLERGY CODED, 1003 IS OPENMRS
    TestUtil.addObsGroup(
        e,
        7,
        new Date(),
        1000,
        Context.getConceptService().getConcept(1003),
        new Date()); // matches
    TestUtil.addObsGroup(
        e,
        1000,
        new Date(),
        7,
        Context.getConceptService().getConcept(1003),
        new Date()); // does not match
    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);

    // this is going to test out the voided state of the obs in the encounter after processing:
    Assert.assertTrue(!e.isVoided());
    for (Obs o : e.getAllObs(true)) {
      if (o.getConcept().getConceptId().equals(2474)) Assert.assertTrue(o.isVoided());
      if (o.getConcept().getConceptId().equals(3017)) Assert.assertTrue(o.isVoided());
      if (o.getConcept().getConceptId().equals(3032)) Assert.assertTrue(o.isVoided());
      if (o.getConcept().getConceptId().equals(1)) Assert.assertTrue(o.isVoided());
      if (o.getConcept().getConceptId().equals(2)) Assert.assertTrue(!o.isVoided()); // not matched
      if (o.getConcept().getConceptId().equals(3)) Assert.assertTrue(!o.isVoided()); // not matched
      if (o.getConcept().getConceptId().equals(6)) Assert.assertTrue(o.isVoided());
      if (o.getConcept().getConceptId().equals(1004)) Assert.assertTrue(o.isVoided());
      if (o.getConcept().getConceptId().equals(1005)) Assert.assertTrue(o.isVoided());

      // obsGroups
      if (o.getConcept().getConceptId().equals(7) && o.isObsGrouping())
        Assert.assertTrue(o.isVoided());
      if (o.getConcept().getConceptId().equals(7) && !o.isObsGrouping())
        Assert.assertTrue(!o.isVoided()); // not matched
      if (o.getConcept().getConceptId().equals(1000) && o.isObsGrouping())
        Assert.assertTrue(!o.isVoided()); // not matched
      if (o.getConcept().getConceptId().equals(1000) && !o.isObsGrouping())
        Assert.assertTrue(o.isVoided());
    }
  }