@Test
  public void shouldChangeObservationsOfPreviousEncounters() throws Exception {
    Date visitStartDate = getDateFromString("2014-06-22 00:00:00");
    Date encounterDate = getDateFromString("2014-06-23 00:00:00");

    List<Document> documents = new ArrayList<>();
    documents.add(
        new Document(
            "/radiology/foo.jpg",
            null,
            "5f596de5-5caa-11e3-a4c0-0800271c1b75",
            "6d0ae386-707a-4629-9850-f15206e63kj0",
            encounterDate,
            false));

    VisitDocumentRequest visitDocumentRequest =
        new VisitDocumentRequest(
            patientUUID,
            firstVisitUuid,
            visitTypeUUID,
            visitStartDate,
            null,
            secondEncounterTypeUUID,
            encounterDate,
            documents,
            secondProviderUuid,
            secondLocationUuid,
            null);
    executeDataSet("visitDocumentData.xml");
    visitDocumentService.upload(visitDocumentRequest);

    Context.flushSession();
    Context.clearSession();

    Encounter encounter = encounterService.getEncounterByUuid(secondEncounterUuid);
    for (Obs obs : encounter.getAllObs(true)) {
      if (obs.getUuid().equals("6d0ae386-707a-4629-9850-f15606e63666")
          || obs.getUuid().equals("6d0ae386-707a-4629-9850-f15206e63kj0")) {
        assertThat(obs.getVoided(), is(true));
      }
    }

    Obs savedDoc = getSavedDocument(encounter.getAllObs(), "5f596de5-5caa-11e3-a4c0-0800271c1b75");

    assertNotNull(savedDoc);
    assertThat(savedDoc.getConcept().getId(), is(333));
    assertThat(
        savedDoc.getGroupMembers().iterator().next().getValueText(), is("/radiology/foo.jpg"));
    assertEquals(FIRST_LOCATION_UUID, encounter.getLocation().getUuid());
  }
 public void printEncounterCreated() {
   if (encounterCreated == null) {
     System.out.println("No encounter created");
   } else {
     System.out.println("=== Encounter created ===");
     System.out.println(
         "Created: "
             + encounterCreated.getDateCreated()
             + "  Edited: "
             + encounterCreated.getDateChanged());
     System.out.println("Date: " + encounterCreated.getEncounterDatetime());
     System.out.println("Location: " + encounterCreated.getLocation().getName());
     System.out.println("Provider: " + encounterCreated.getProvider().getPersonName());
     System.out.println("    (obs)");
     Collection<Obs> obs = encounterCreated.getAllObs(false);
     if (obs == null) {
       System.out.println("None");
     } else {
       for (Obs o : obs) {
         System.out.println(
             o.getConcept().getName() + " -> " + o.getValueAsString(Context.getLocale()));
       }
     }
   }
 }
    /**
     * Fails if there isn't an obs group with these exact characteristics
     *
     * @param groupingConceptId the concept id of the grouping obs
     * @param conceptIdsAndValues these parameters must be given in pairs, the first element of
     *     which is the conceptId of a child obs (Integer) and the second element of which is the
     *     value of the child obs
     */
    public void assertObsGroupCreated(int groupingConceptId, Object... conceptIdsAndValues) {
      // quick checks
      Assert.assertNotNull(encounterCreated);
      Collection<Obs> temp = encounterCreated.getAllObs();
      Assert.assertNotNull(temp);

      List<ObsValue> expected = new ArrayList<ObsValue>();
      for (int i = 0; i < conceptIdsAndValues.length; i += 2) {
        int conceptId = (Integer) conceptIdsAndValues[i];
        Object value = conceptIdsAndValues[i + 1];
        expected.add(new ObsValue(conceptId, value));
      }

      for (Obs o : temp) {
        if (o.getConcept().getConceptId() == groupingConceptId) {
          if (o.getValueCoded() != null
              || o.getValueComplex() != null
              || o.getValueDatetime() != null
              || o.getValueDrug() != null
              || o.getValueNumeric() != null
              || o.getValueText() != null) {
            Assert.fail(
                "Obs group with groupingConceptId "
                    + groupingConceptId
                    + " should has a non-null value");
          }
          if (TestUtil.isMatchingObsGroup(o, expected)) {
            return;
          }
        }
      }
      Assert.fail("Cannot find an obs group matching " + expected);
    }
 /** @return the number of obs groups in encounterCreated (0 if no encounter was created) */
 public int getObsGroupCreatedCount() {
   if (encounterCreated == null) return 0;
   Collection<Obs> temp = encounterCreated.getAllObs();
   if (temp == null) return 0;
   int count = 0;
   for (Obs o : temp) {
     if (o.isObsGrouping()) ++count;
   }
   return count;
 }
  @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"));
    }
  }
  public QueueItem saveQueueItem(QueueItem queueItem) {
    log.debug("saveQueueItem(). Entering");
    boolean isNew = false;
    Date newDate = queueItem.getEncounter().getEncounterDatetime();
    log.debug("Encounter date: " + newDate);
    Date originalDate = null;

    if (queueItem.getQueueItemId() == null) {
      isNew = true;
      log.debug("Got a  new queue item");
    }

    // Not new we update some of the Encounter info
    if (!isNew) {
      log.info("Updating previously queued encounter!");
      Encounter encounter = queueItem.getEncounter();
      Patient p = encounter.getPatient();
      originalDate = encounter.getEncounterDatetime();
      if (OpenmrsUtil.compare(originalDate, newDate) != 0) {

        // if the obs datetime is the same as the
        // original encounter datetime, fix it
        if (OpenmrsUtil.compare(queueItem.getDateCreated(), originalDate) == 0) {
          encounter.setEncounterDatetime(newDate);
        }
      }

      // if the Person in the encounter doesn't match the Patient in the ,
      // fix it
      if (!encounter.getPatient().getPersonId().equals(p.getPatientId())) {
        encounter.setPatient(p);
      }

      for (Obs obs : encounter.getAllObs(true)) {
        // if the date was changed
        if (OpenmrsUtil.compare(originalDate, newDate) != 0) {

          // if the obs datetime is the same as the
          // original encounter datetime, fix it
          if (OpenmrsUtil.compare(obs.getObsDatetime(), originalDate) == 0) {
            obs.setObsDatetime(newDate);
          }
        }

        // if the Person in the obs doesn't match the Patient in the
        // encounter, fix it
        if (!obs.getPerson().getPersonId().equals(p.getPatientId())) {
          obs.setPerson(p);
        }
      }
    }
    log.debug("Saving queu item.");
    dao.saveQueueItem(queueItem);
    return queueItem;
  }
  @Test
  @Verifies(value = "should delete encounter correctly", method = "voidEncounterByHtmlFormSchema")
  public void testVoidEncounterByHtmlFormSchema_shouldDeleteEncounter() 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, voided Obs
    for (Obs o : e.getAllObs(true)) {
      o.setVoided(true);
      o.setVoidedBy(Context.getUserService().getUser(1));
      o.setVoidReason("blah");
      o.setDateVoided(new Date());
    }

    // and adding a voided drug order
    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.setVoided(true);
    dor.setVoidedBy(Context.getUserService().getUser(1));
    dor.setVoidReason("blah");
    dor.setDateVoided(new Date());
    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);

    // encounter had no non-voided objects, should be voided
    Assert.assertTrue(e.isVoided());
  }
    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);
    }
  @Test
  public void shouldPreferVoidOverUpdateWhenEditingADocument() throws Exception {
    Date visitStartDate = getDateFromString("2014-06-22 00:00:00");
    Date encounterDate = getDateFromString("2014-06-23 00:00:00");

    List<Document> documents = new ArrayList<>();
    String obsUuid = "6d0ae386-707a-4629-9850-f15206e63kj0";
    documents.add(
        new Document(
            "/radiology/foo.jpg",
            null,
            "3f596de5-5caa-11e3-a4c0-0800271c1b75",
            obsUuid,
            encounterDate,
            true));

    VisitDocumentRequest visitDocumentRequest =
        new VisitDocumentRequest(
            patientUUID,
            firstVisitUuid,
            visitTypeUUID,
            visitStartDate,
            null,
            secondEncounterTypeUUID,
            encounterDate,
            documents,
            secondProviderUuid,
            secondLocationUuid,
            null);
    visitDocumentService.upload(visitDocumentRequest);

    Context.flushSession();
    Context.clearSession();

    Encounter encounter = encounterService.getEncounterByUuid(secondEncounterUuid);

    Obs savedObs = obsService.getObsByUuid(obsUuid);
    assertTrue("Observation is not voided", savedObs.getVoided());
    assertTrue(
        "Observation is not voided", savedObs.getGroupMembers(true).iterator().next().getVoided());

    Obs savedDoc = getSavedDocument(encounter.getAllObs(), "3f596de5-5caa-11e3-a4c0-0800271c1b75");

    assertNull(savedDoc);
  }
  @Test
  public void shouldUseVisitStartTimeAsEncounterDateTimeForPreviousVisits() throws Exception {
    Date visitStartDate = getDateFromString("2010-09-22 00:00:00");

    List<Document> documents = new ArrayList<>();
    documents.add(
        new Document(
            "/radiology/foo-lalala.jpg",
            null,
            "3f596de5-5caa-11e3-a4c0-0800271c1b75",
            null,
            null,
            false));

    VisitDocumentRequest visitDocumentRequest =
        new VisitDocumentRequest(
            patientUUID,
            firstVisitUuid,
            visitTypeUUID,
            null,
            null,
            firstEncounterTypeUUID,
            null,
            documents,
            secondProviderUuid,
            null,
            null);
    executeDataSet("visitDocumentData.xml");

    //        Date currentDate = new Date(System.currentTimeMillis() - 1000);
    visitDocumentService.upload(visitDocumentRequest);
    Context.flushSession();
    Context.clearSession();

    Visit visit = visitService.getVisit(1);
    Set<Encounter> encounters = visit.getEncounters();
    Encounter encounter = getEncounterByTypeUuid(encounters, firstEncounterTypeUUID);
    boolean condition = encounter.getEncounterDatetime().compareTo(visitStartDate) >= 0;
    assertTrue(condition);

    Set<Obs> allObs = encounter.getAllObs();
    Obs savedDocument = getSavedDocument(allObs, "3f596de5-5caa-11e3-a4c0-0800271c1b75");
    assertTrue(savedDocument.getObsDatetime().compareTo(visitStartDate) == 0);
  }
  @Test
  public void shouldNotChangeObservationsIfSameDetailsProvidedOnceAgain() throws Exception {
    Date visitStartDate = getDateFromString("2014-06-22 00:00:00");
    Date encounterDate = getDateFromString("2014-06-23 00:00:00");

    List<Document> documents = new ArrayList<>();
    documents.add(
        new Document(
            "/radiology/foo.jpg",
            null,
            conceptUuid,
            "6d0ae386-707a-4629-9850-f15206e63kj0",
            encounterDate,
            false));

    VisitDocumentRequest visitDocumentRequest =
        new VisitDocumentRequest(
            patientUUID,
            firstVisitUuid,
            visitTypeUUID,
            visitStartDate,
            null,
            secondEncounterTypeUUID,
            encounterDate,
            documents,
            secondProviderUuid,
            secondLocationUuid,
            null);
    visitDocumentService.upload(visitDocumentRequest);

    Context.flushSession();
    Context.clearSession();

    Encounter encounter = encounterService.getEncounterByUuid(secondEncounterUuid);

    Obs savedDoc = getSavedDocument(encounter.getAllObs(), conceptUuid);

    assertNotNull(savedDoc);
    Set<Obs> groupMembers = savedDoc.getGroupMembers();
    assertThat(groupMembers.size(), is(equalTo(1)));
    assertThat(groupMembers.iterator().next().getValueText(), is("/radiology/foo.jpg"));
    assertThat(
        groupMembers.iterator().next().getUuid(), is("6d0ae386-707a-4629-9850-f15606e63666"));
  }
  @Test
  public void shouldAddNewObservationGroup() throws Exception {
    executeDataSet("shouldAddNewObservation.xml");
    String encounterDateTime = "2005-01-02T00:00:00.000+0000";
    String observationTime = "2005-01-02T12:00:00.000+0000";
    String json =
        "{ \"patientUuid\" : \"a76e8d23-0c38-408c-b2a8-ea5540f01b51\", "
            + "\"visitTypeUuid\" : \"b45ca846-c79a-11e2-b0c0-8e397087571c\", "
            + "\"encounterTypeUuid\": \"2b377dba-62c3-4e53-91ef-b51c68899890\", "
            + "\"encounterDateTime\" : \""
            + encounterDateTime
            + "\", "
            + "\"observations\":["
            + "{\"concept\":{\"uuid\": \"e102c80f-1yz9-4da3-bb88-8122ce8868dd\"}, "
            + " \"groupMembers\" : [{\"concept\":{\"uuid\": \"d102c80f-1yz9-4da3-bb88-8122ce8868dd\"}, \"value\":20, \"comment\":\"overweight\", \"observationDateTime\": \""
            + observationTime
            + "\"}] }"
            + "]}";

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

    Visit visit = visitService.getVisitByUuid(response.getVisitUuid());
    Encounter encounter = (Encounter) visit.getEncounters().toArray()[0];

    assertEquals(1, encounter.getObs().size());
    Obs obs = (Obs) encounter.getAllObs().toArray()[0];
    assertEquals("e102c80f-1yz9-4da3-bb88-8122ce8868dd", obs.getConcept().getUuid());

    assertEquals(1, obs.getGroupMembers().size());
    Obs member = obs.getGroupMembers().iterator().next();
    assertEquals("d102c80f-1yz9-4da3-bb88-8122ce8868dd", member.getConcept().getUuid());
    assertEquals(new Double(20.0), member.getValueNumeric());
    assertEquals("a76e8d23-0c38-408c-b2a8-ea5540f01b51", member.getPerson().getUuid());
    assertEquals("f13d6fae-baa9-4553-955d-920098bec08f", member.getEncounter().getUuid());
    assertEquals("overweight", member.getComment());
    assertEquals(
        new SimpleDateFormat(dateTimeFormat).parse(observationTime), member.getObsDatetime());
  }
  @Test
  public void shouldUseNewDateAsEncounterDateTimeForActiveVisits() throws Exception {
    Date visitStartDate = getDateFromString("2014-06-22 00:00:00");
    Date encounterDate = getDateFromString("2014-06-23 00:00:00");
    Date obsDate = getDateFromString("2014-06-24 00:10:00");

    List<Document> documents = new ArrayList<>();
    documents.add(new Document("/radiology/fooo-bar.jpg", null, conceptUuid, null, obsDate, false));

    visitDocumentRequest =
        new VisitDocumentRequest(
            patientUUID,
            secondVisitUuid,
            visitTypeUUID,
            visitStartDate,
            null,
            secondEncounterTypeUUID,
            encounterDate,
            documents,
            firstProviderUuid,
            null,
            null);

    Date currentDate = new Date(System.currentTimeMillis() - 1000);
    visitDocumentService.upload(visitDocumentRequest);
    Context.flushSession();
    Context.clearSession();

    Visit visit = visitService.getVisit(2);
    Set<Encounter> encounters = visit.getEncounters();
    Encounter encounter = getEncounterByTypeUuid(encounters, secondEncounterTypeUUID);
    boolean condition = encounter.getEncounterDatetime().compareTo(currentDate) >= 0;
    assertTrue(condition);

    Set<Obs> allObs = encounter.getAllObs();
    Obs savedDocument = getSavedDocument(allObs, conceptUuid);
    assertTrue(savedDocument.getObsDatetime().compareTo(currentDate) >= 0);
  }
  @Test
  public void shouldCreateObservations() throws Exception {
    Date visitStartDate = getDateFromString("2014-06-22 00:00:00");
    Date encounterDate = getDateFromString("2014-06-23 00:00:00");
    Date obsDate = getDateFromString("2014-06-24 00:10:00");

    List<Document> documents = new ArrayList<>();
    documents.add(new Document("/radiology/fooo-bar.jpg", null, conceptUuid, null, obsDate, false));

    visitDocumentRequest =
        new VisitDocumentRequest(
            patientUUID,
            secondVisitUuid,
            visitTypeUUID,
            visitStartDate,
            null,
            firstEncounterTypeUUID,
            encounterDate,
            documents,
            firstProviderUuid,
            FIRST_LOCATION_UUID,
            null);

    visitDocumentService.upload(visitDocumentRequest);

    Context.flushSession();
    Context.clearSession();

    Encounter encounter = encounterService.getEncounterByUuid(firstEncounterUuid);

    Obs savedDoc = getSavedDocument(encounter.getAllObs(), conceptUuid);

    assertNotNull(savedDoc);
    assertThat(savedDoc.getConcept().getId(), is(222));
    assertThat(
        savedDoc.getGroupMembers().iterator().next().getValueText(), is("/radiology/fooo-bar.jpg"));
    assertEquals(FIRST_LOCATION_UUID, encounter.getLocation().getUuid());
  }
  @Test
  public void shouldUploadImagesInOrderOfRequest() throws Exception {
    Date visitStartDate = getDateFromString("2014-06-22 00:00:00");
    Date encounterDate = getDateFromString("2014-06-23 00:00:00");
    Date obsDate = getDateFromString("2014-06-24 00:10:00");

    List<Document> documents = new ArrayList<>();
    documents.add(new Document("/radiology/1.jpg", null, conceptUuid, null, obsDate, false));
    documents.add(new Document("/radiology/2.jpg", null, conceptUuid, null, obsDate, false));
    documents.add(new Document("/radiology/3.jpg", null, conceptUuid, null, obsDate, false));
    documents.add(new Document("/radiology/4.jpg", null, conceptUuid, null, obsDate, false));

    visitDocumentRequest =
        new VisitDocumentRequest(
            patientUUID,
            secondVisitUuid,
            visitTypeUUID,
            visitStartDate,
            null,
            firstEncounterTypeUUID,
            encounterDate,
            documents,
            firstProviderUuid,
            FIRST_LOCATION_UUID,
            null);
    visitDocumentService.upload(visitDocumentRequest);

    Context.flushSession();
    Context.clearSession();

    Encounter encounter = encounterService.getEncounterByUuid(firstEncounterUuid);
    List<Obs> savedDocuments = getSavedDocuments(encounter.getAllObs(), conceptUuid);
    assertEquals(4, savedDocuments.size());
    assertEquals("/radiology/1.jpg", getImageName(savedDocuments.get(0)));
    assertEquals("/radiology/2.jpg", getImageName(savedDocuments.get(1)));
    assertEquals("/radiology/3.jpg", getImageName(savedDocuments.get(2)));
    assertEquals("/radiology/4.jpg", getImageName(savedDocuments.get(3)));
  }
  @Test
  public void shouldDeleteObservationsOfPreviousEncounters() throws ParseException {
    Date visitStartDate = getDateFromString("2014-06-22 00:00:00");
    Date encounterDate = getDateFromString("2014-06-23 00:00:00");

    List<Document> documents = new ArrayList<>();
    String testUuid = "3f596de5-5caa-11e3-a4c0-0800271c1b75";
    String obsUuid = "6d0ae386-707a-4629-9850-f15206e63j8s";
    String providerUuid = "331c6bf8-7846-11e3-a96a-0800271c1b75";
    documents.add(new Document("/patient_file", null, testUuid, obsUuid, encounterDate, true));

    visitDocumentRequest =
        new VisitDocumentRequest(
            patientUUID,
            secondVisitUuid,
            visitTypeUUID,
            visitStartDate,
            null,
            firstEncounterTypeUUID,
            encounterDate,
            documents,
            providerUuid,
            null,
            null);
    visitDocumentService.upload(visitDocumentRequest);

    Context.flushSession();
    Context.clearSession();

    Encounter encounter = encounterService.getEncounterByUuid(firstEncounterUuid);
    for (Obs obs : encounter.getAllObs(true)) {
      if (obs.getUuid().equals(obsUuid)) {
        assertThat(obs.getVoided(), is(true));
        assertThat(obs.getGroupMembers(true).iterator().next().getVoided(), is(true));
      }
    }
  }
  @RequestMapping(method = RequestMethod.GET)
  public String showPatientInfo(
      @RequestParam("patientId") Integer patientId,
      @RequestParam(value = "encounterId", required = false) Integer encounterId,
      @RequestParam(value = "reprint", required = false) Boolean reprint,
      Model model)
      throws IOException, ParseException {

    Patient patient = Context.getPatientService().getPatient(patientId);
    PatientModel patientModel = new PatientModel(patient);
    model.addAttribute("patient", patientModel);
    model.addAttribute(
        "OPDs", RegistrationWebUtils.getSubConcepts(RegistrationConstants.CONCEPT_NAME_OPD_WARD));

    // Get current date
    SimpleDateFormat sdf = new SimpleDateFormat("EEE dd/MM/yyyy kk:mm");
    model.addAttribute("currentDateTime", sdf.format(new Date()));

    // Get patient registration fee
    if (GlobalPropertyUtil.getInteger(RegistrationConstants.PROPERTY_NUMBER_OF_DATE_VALIDATION, 0)
        > 0) {
      List<RegistrationFee> fees =
          Context.getService(RegistrationService.class)
              .getRegistrationFees(
                  patient,
                  GlobalPropertyUtil.getInteger(
                      RegistrationConstants.PROPERTY_NUMBER_OF_DATE_VALIDATION, 0));
      if (!CollectionUtils.isEmpty(fees)) {
        RegistrationFee fee = fees.get(0);
        Calendar dueDate = Calendar.getInstance();
        dueDate.setTime(fee.getCreatedOn());
        dueDate.add(Calendar.DATE, 30);
        model.addAttribute("dueDate", RegistrationUtils.formatDate(dueDate.getTime()));
        model.addAttribute("daysLeft", dateDiff(dueDate.getTime(), new Date()));
      }
    }

    // Get selected OPD room if this is the first time of visit
    if (encounterId != null) {
      Encounter encounter = Context.getEncounterService().getEncounter(encounterId);
      for (Obs obs : encounter.getObs()) {
        if (obs.getConcept()
            .getName()
            .getName()
            .equalsIgnoreCase(RegistrationConstants.CONCEPT_NAME_OPD_WARD)) {
          model.addAttribute("selectedOPD", obs.getValueCoded().getConceptId());
        }
      }
    }

    // If reprint, get the latest registration encounter
    if ((reprint != null) && reprint) {

      /** June 7th 2012 - Supported #250 - Registration 2.2.14 (Mohali): Date on Reprint */
      HospitalCoreService hcs = Context.getService(HospitalCoreService.class);
      model.addAttribute("currentDateTime", sdf.format(hcs.getLastVisitTime(patientId)));

      Encounter encounter = Context.getService(RegistrationService.class).getLastEncounter(patient);
      if (encounter != null) {
        Map<Integer, String> observations = new HashMap<Integer, String>();

        for (Obs obs : encounter.getAllObs()) {
          if (obs.getConcept()
              .getDisplayString()
              .equalsIgnoreCase(RegistrationConstants.CONCEPT_NAME_TEMPORARY_CATEGORY)) {
            model.addAttribute("tempCategoryId", obs.getConcept().getConceptId());
          } else if (obs.getConcept()
              .getDisplayString()
              .equalsIgnoreCase(RegistrationConstants.CONCEPT_NAME_OPD_WARD)) {
            model.addAttribute("opdWardId", obs.getConcept().getConceptId());
          }
          observations.put(obs.getConcept().getConceptId(), ObsUtils.getValueAsString(obs));
        }
        model.addAttribute("observations", observations);
      }
    }

    return "/module/registration/patient/showPatientInfo";
  }
  @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());
    }
  }
 /** @return the number of obs in encounterCreated (0 if no encounter was created) */
 public int getObsCreatedCount() {
   if (encounterCreated == null) return 0;
   Collection<Obs> temp = encounterCreated.getAllObs();
   if (temp == null) return 0;
   return temp.size();
 }
  /** @see org.openmrs.api.EncounterService#saveEncounter(org.openmrs.Encounter) */
  public Encounter saveEncounter(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.edit",
          new Object[] {encounter.getEncounterType().getEditPrivilege()});
    }

    // If new encounter, try to assign a visit using the registered visit assignment handler.
    if (encounter.getEncounterId() == null) {

      // Am using Context.getEncounterService().getActiveEncounterVisitHandler() instead of just
      // getActiveEncounterVisitHandler() for modules which may want to AOP around this call.
      EncounterVisitHandler encounterVisitHandler =
          Context.getEncounterService().getActiveEncounterVisitHandler();
      if (encounterVisitHandler != null) {
        encounterVisitHandler.beforeCreateEncounter(encounter);

        // If we have been assigned a new visit, persist it.
        if (encounter.getVisit() != null && encounter.getVisit().getVisitId() == null) {
          Context.getVisitService().saveVisit(encounter.getVisit());
        }
      }
    }

    boolean isNewEncounter = false;
    Date newDate = encounter.getEncounterDatetime();
    Date originalDate = null;
    Location newLocation = encounter.getLocation();
    Location originalLocation = null;
    // check permissions
    if (encounter.getEncounterId() == null) {
      isNewEncounter = true;
      Context.requirePrivilege(PrivilegeConstants.ADD_ENCOUNTERS);
    } else {
      Context.requirePrivilege(PrivilegeConstants.EDIT_ENCOUNTERS);
    }

    // This must be done after setting dateCreated etc on the obs because
    // of the way the ORM tools flush things and check for nullity
    // This also must be done before the save encounter so we can use the
    // orig date
    // after the save
    Patient p = encounter.getPatient();

    if (!isNewEncounter) {
      // fetch the datetime from the database prior to saving for this
      // encounter
      // to see if it has changed and change all obs after saving if so
      originalDate = dao.getSavedEncounterDatetime(encounter);
      if (encounter.getLocation() != null) {
        originalLocation = dao.getSavedEncounterLocation(encounter);
      }
      // Our data model duplicates the patient column to allow for
      // observations to
      // not have to look up the parent Encounter to find the patient
      // Therefore, encounter.patient must always equal
      // encounter.observations[0-n].patient

      // If we are changing encounter.encounterDatetime, then we need to
      // also apply that
      // to Obs that inherited their obsDatetime from the encounter in the
      // first place

      for (Obs obs : encounter.getAllObs(true)) {
        // if the date was changed
        if (OpenmrsUtil.compare(originalDate, newDate) != 0
            && OpenmrsUtil.compare(obs.getObsDatetime(), originalDate) == 0) {

          // if the obs datetime is the same as the
          // original encounter datetime, fix it
          obs.setObsDatetime(newDate);
        }

        if (!OpenmrsUtil.nullSafeEquals(newLocation, originalLocation)
            && obs.getLocation().equals(originalLocation)) {
          obs.setLocation(newLocation);
        }

        // if the Person in the obs doesn't match the Patient in the
        // encounter, fix it
        if (!obs.getPerson().getPersonId().equals(p.getPatientId())) {
          obs.setPerson(p);
        }
      }
    }
    // same goes for Orders
    for (Order o : encounter.getOrders()) {
      if (!p.equals(o.getPatient())) {
        o.setPatient(p);
      }
    }

    // do the actual saving to the database
    dao.saveEncounter(encounter);

    // save the new orders
    for (Order o : encounter.getOrders()) {
      if (o.getOrderId() == null) {
        Context.getOrderService().saveOrder(o, null);
      }
    }
    return encounter;
  }
    /**
     *
     * Returns the encounter with the obs that aren't used when populating form are removed.
     * This *doesn't* save the encounter.
     * TODO: handle Orders?
     *
     * @param e
     * @param htmlform
     * @return
     * @throws Exception
     */
    public static Encounter trimEncounterToMatchForm(Encounter e, HtmlForm htmlform) throws Exception {

       //this should move existing obs from session to tag handlers.
        FormEntrySession session = new FormEntrySession(e.getPatient(), e, FormEntryContext.Mode.VIEW, htmlform, null); // session gets a null HttpSession
        session.getHtmlToDisplay();

        if (log.isDebugEnabled()){
            Map<Concept, List<Obs>>  map = session.getContext().getExistingObs();
            if (map != null){
                for (Map.Entry<Concept, List<Obs>> existingObs : map.entrySet()){
                    List<Obs> oList = existingObs.getValue();
                    for (Obs oInner : oList)
                        log.debug("Obs in existingObs " + existingObs.getKey() + " " + oInner.getConcept());
                }
            }
            Map<Obs, Set<Obs>> map2 = session.getContext().getExistingObsInGroups();
            if (map2 != null){
                for (Map.Entry<Obs, Set<Obs>> existingObsInGroups : map2.entrySet()){
                    Set<Obs> oList = existingObsInGroups.getValue();
                    for (Obs oInner : oList)
                        log.debug("Obs in existingObsInGroups " + existingObsInGroups.getKey().getConcept() + " " + oInner.getConcept());
                }
            }
        }
        Encounter ret = new Encounter();
        ret.setCreator(e.getCreator());
        ret.setEncounterDatetime(e.getEncounterDatetime());
        EncounterCompatibility.setProvider(ret, EncounterCompatibility.getProvider(e));
        ret.setLocation(e.getLocation());
        ret.setDateCreated(e.getDateCreated());
        ret.setPatient(e.getPatient());
        //renders new encounter unsave-able:
        ret.setEncounterId(e.getEncounterId());

        for (Obs oTest : e.getAllObs()){
            boolean found = false;
            if (session.getContext().getExistingObs() != null && !oTest.isObsGrouping()){
                List<Obs> obsList = session.getContext().getExistingObs().get(oTest.getConcept());
                if (obsList != null && obsList.size() > 0){
                    for (Obs o : obsList){
                        if (o.getObsId().equals(oTest.getObsId())){
                            found = true;
                            continue;
                        }
                    }
                }
            }
            if (!found && session.getContext().getExistingObsInGroups() != null){
                for (Map.Entry<Obs, Set<Obs>> mapEntry : session.getContext().getExistingObsInGroups().entrySet()){
                    if (mapEntry.getKey().equals(oTest)){
                        found = true;
                        continue;
                    } else {
                        Set<Obs> oSet = mapEntry.getValue();
                        //note: oSet.contains fails for some reason
                        for (Obs o:oSet){
                              if (o.getObsId().equals(oTest.getObsId())){
                                  found = true;
                                  continue;
                              }
                        }
                    }
                }
            }
            if (!found)
                ret.addObs(oTest);
        }
        session = null;
        return ret;
    }