/** @see org.openmrs.api.EncounterService#unvoidEncounter(org.openmrs.Encounter) */
  public Encounter unvoidEncounter(Encounter encounter) throws APIException {

    // if authenticated user is not supposed to edit encounter of certain type
    if (!canEditEncounter(encounter, null)) {
      throw new APIException(
          "Encounter.error.privilege.required.unvoid",
          new Object[] {encounter.getEncounterType().getEditPrivilege()});
    }

    String voidReason = encounter.getVoidReason();
    if (voidReason == null) {
      voidReason = "";
    }

    ObsService os = Context.getObsService();
    for (Obs o : encounter.getObsAtTopLevel(true)) {
      if (voidReason.equals(o.getVoidReason())) {
        os.unvoidObs(o);
      }
    }

    OrderService orderService = Context.getOrderService();
    for (Order o : encounter.getOrders()) {
      if (voidReason.equals(o.getVoidReason())) {
        orderService.unvoidOrder(o);
      }
    }

    encounter.setVoided(false);
    encounter.setVoidedBy(null);
    encounter.setDateVoided(null);
    encounter.setVoidReason(null);
    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_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"));
    }
  }
  @Test
  public void testEvaluate() throws Exception {
    EncounterEvaluationContext context = new EncounterEvaluationContext();
    context.setBaseEncounters(new EncounterIdSet(encounter.getId()));

    EvaluatedEncounterData result =
        encounterDataService.evaluate(new AuditInfoEncounterDataDefinition(), context);
    assertThat(result.getData().size(), is(1));
    AuditInfo auditInfo = (AuditInfo) result.getData().get(encounter.getId());
    assertThat(auditInfo.getCreator(), is(encounter.getCreator()));
    assertThat(auditInfo.getDateCreated(), is(encounter.getDateCreated()));
    assertThat(auditInfo.getChangedBy(), is(encounter.getChangedBy()));
    assertThat(auditInfo.getDateChanged(), is(encounter.getDateChanged()));
    assertThat(auditInfo.getVoided(), is(encounter.getVoided()));
    assertThat(auditInfo.getVoidedBy(), is(encounter.getVoidedBy()));
    assertThat(auditInfo.getDateVoided(), is(encounter.getDateVoided()));
    assertThat(auditInfo.getVoidReason(), is(encounter.getVoidReason()));
  }
  /**
   * The onSubmit function receives the form/command object that was modified by the input form and
   * saves it to the db
   *
   * @see
   *     org.springframework.web.servlet.mvc.SimpleFormController#onSubmit(javax.servlet.http.HttpServletRequest,
   *     javax.servlet.http.HttpServletResponse, java.lang.Object,
   *     org.springframework.validation.BindException)
   * @should transfer encounter to another patient when encounter patient was changed
   */
  @Override
  protected ModelAndView onSubmit(
      HttpServletRequest request, HttpServletResponse response, Object obj, BindException errors)
      throws Exception {

    HttpSession httpSession = request.getSession();

    String view = getFormView();

    try {
      Context.addProxyPrivilege(PrivilegeConstants.VIEW_USERS);
      Context.addProxyPrivilege(PrivilegeConstants.VIEW_PATIENTS);

      if (Context.isAuthenticated()) {
        Encounter encounter = (Encounter) obj;

        Integer patientId = null;

        if (request.getParameter("patientId") != null) {
          patientId = Integer.valueOf(request.getParameter("patientId"));
        }

        if (encounter.getEncounterId() == null) {
          // if this is a new encounter, they can specify a patient.  add it
          if (patientId != null) {
            encounter.setPatient(Context.getPatientService().getPatient(patientId));
          }
        } else {
          Patient oldPatient = encounter.getPatient();
          Patient newPatient = Context.getPatientService().getPatient(patientId);
          if (newPatient != null && oldPatient != null && !newPatient.equals(oldPatient)) {
            encounter = Context.getEncounterService().transferEncounter(encounter, newPatient);
          }
        }

        if (encounter.isVoided() && encounter.getVoidedBy() == null) {
          // if this is a "new" voiding, call voidEncounter to set appropriate attributes
          Context.getEncounterService().voidEncounter(encounter, encounter.getVoidReason());
        } else if (!encounter.isVoided() && encounter.getVoidedBy() != null) {
          // if this was just unvoided, call unvoidEncounter to unset appropriate attributes
          Context.getEncounterService().unvoidEncounter(encounter);
        } else {
          Context.getEncounterService().saveEncounter(encounter);
        }

        view = getSuccessView();
        view = view + "?encounterId=" + encounter.getEncounterId();

        httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "Encounter.saved");
      }
    } catch (APIException e) {
      log.error("Error while trying to save the encounter", e);
      httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "Encounter.cannot.save");
      errors.reject("encounter", "Encounter.cannot.save");
      // return to the form because an exception was thrown
      return showForm(request, response, errors);
    } finally {
      Context.removeProxyPrivilege(PrivilegeConstants.VIEW_USERS);
      Context.removeProxyPrivilege(PrivilegeConstants.VIEW_PATIENTS);
    }

    return new ModelAndView(new RedirectView(view));
  }