public boolean areConsecutiveVisits(List<Integer> visits, Patient patient) {
   if (patient != null && visits != null && (visits.size() > 0)) {
     List<Visit> patientVisits = visitService.getVisitsByPatient(patient, true, false);
     if ((patientVisits != null) && (patientVisits.size() > 0)) {
       ArrayList<Integer> allVisits = new ArrayList<Integer>();
       int j = 0;
       for (Visit visit : patientVisits) {
         allVisits.add(j++, visit.getId());
       }
       if (allVisits.containsAll(visits)) {
         // find the index of the first candidate for a consecutive visit
         int i = allVisits.indexOf(visits.get(0));
         // make sure there are still more elements in the list than the the number of candidate
         // consecutives
         if ((allVisits.size() - i) >= visits.size()) {
           for (Integer candidateVisit : visits) {
             if (allVisits.get(i).compareTo(candidateVisit) == 0) {
               i++;
             } else {
               return false;
             }
           }
           return true;
         }
       }
     }
   }
   return false;
 }
  public Visit mergeVisits(Visit preferred, Visit nonPreferred) {
    // extend date range of winning
    if (OpenmrsUtil.compareWithNullAsEarliest(
            nonPreferred.getStartDatetime(), preferred.getStartDatetime())
        < 0) {
      preferred.setStartDatetime(nonPreferred.getStartDatetime());
    }
    if (preferred.getStopDatetime() != null
        && OpenmrsUtil.compareWithNullAsLatest(
                preferred.getStopDatetime(), nonPreferred.getStopDatetime())
            < 0) {
      preferred.setStopDatetime(nonPreferred.getStopDatetime());
    }

    // move encounters from losing into winning
    if (nonPreferred.getEncounters() != null) {
      for (Encounter e : nonPreferred.getEncounters()) {
        e.setPatient(preferred.getPatient());
        preferred.addEncounter(e);
        encounterService.saveEncounter(e);
      }
    }
    nonPreferred.setEncounters(
        null); // we need to manually the encounters from the non-preferred visit before voiding or
               // all the encounters we just moved will also get voided!

    visitService.voidVisit(
        nonPreferred, "EMR - Merge Patients: merged into visit " + preferred.getVisitId());
    visitService.saveVisit(preferred);
    return preferred;
  }
  @Transactional
  public Visit ensureVisit(Patient patient, Date visitTime, Location department) {
    if (visitTime == null) {
      visitTime = new Date();
    }
    Visit visit = null;
    List<Patient> patientList = Collections.singletonList(patient);

    // visits that have not ended by the encounter date.
    List<Visit> candidates =
        visitService.getVisits(
            null, patientList, null, null, null, visitTime, null, null, null, true, false);
    if (candidates != null) {
      for (Visit candidate : candidates) {
        if (isSuitableVisit(candidate, department, visitTime)) {
          return candidate;
        }
      }
    }
    if (visit == null) {
      visit = buildVisit(patient, department, visitTime);
      visitService.saveVisit(visit);
    }
    return visit;
  }
 /**
  * @See {@link VisitAttributeTypeController#purge(String, javax.servlet.http.HttpServletRequest,
  * HttpServletResponse)}
  */
 @Test
 public void purge_shouldPurgeAVisitAttributeType() throws Exception {
   final String visitAttributeTypeUuid = "6770f6d6-7673-11e0-8f03-001e378eb67g";
   Assert.assertNotNull(service.getVisitAttributeTypeByUuid(visitAttributeTypeUuid));
   int originalCount = service.getAllVisitAttributeTypes().size();
   controller.purge(visitAttributeTypeUuid, emptyRequest(), emptyResponse());
   Assert.assertNull(service.getVisitAttributeTypeByUuid(visitAttributeTypeUuid));
   Assert.assertEquals(originalCount - 1, service.getAllVisitAttributeTypes().size());
 }
 /**
  * @see VisitAttributeTypeController#delete(String, String, javax.servlet.http.HttpServletRequest,
  *     HttpServletResponse)
  */
 @Test
 public void delete_shouldRetireAVisitAttributeType() throws Exception {
   VisitAttributeType visitAttributeType = service.getVisitAttributeType(1);
   Assert.assertFalse(visitAttributeType.isRetired());
   controller.delete(
       Rest19ExtTestConstants.VISIT_ATTRIBUTE_TYPE_UUID, "test", emptyRequest(), emptyResponse());
   visitAttributeType = service.getVisitAttributeType(1);
   Assert.assertTrue(visitAttributeType.isRetired());
   Assert.assertEquals("test", visitAttributeType.getRetireReason());
 }
 /**
  * @see VisitAttributeTypeController#create(SimpleObject, javax.servlet.http.HttpServletRequest,
  *     HttpServletResponse)
  */
 @Test
 public void create_shouldCreateANewVisitAttributeType() throws Exception {
   int before = service.getAllVisitAttributeTypes().size();
   String json =
       "{ \"name\":\"Some attributeType\",\"description\":\"Attribute Type for visit\",\"datatypeClassname\":\"org.openmrs.customdatatype.datatype.FreeTextDatatype\"}";
   SimpleObject post = new ObjectMapper().readValue(json, SimpleObject.class);
   Object visitAttributeType = controller.create(post, emptyRequest(), emptyResponse());
   Assert.assertNotNull(visitAttributeType);
   Assert.assertEquals(before + 1, service.getAllVisitAttributeTypes().size());
 }
 public Visit mergeConsecutiveVisits(List<Integer> visits, Patient patient) {
   if (areConsecutiveVisits(visits, patient)) {
     Visit mergedVisit = visitService.getVisit(visits.get(0));
     if (visits.size() > 1) {
       for (int i = 1; i < visits.size(); i++) {
         mergedVisit = mergeVisits(mergedVisit, visitService.getVisit(visits.get(i)));
       }
     }
     return mergedVisit;
   }
   return null;
 }
  @Override
  @Transactional
  public VisitDomainWrapper createRetrospectiveVisit(
      Patient patient, Location location, Date startDatetime, Date stopDatetime)
      throws ExistingVisitDuringTimePeriodException {

    if (startDatetime.after(new Date())) {
      throw new IllegalArgumentException("emrapi.retrospectiveVisit.startDateCannotBeInFuture");
    }

    if (stopDatetime.after(new Date())) {
      throw new IllegalArgumentException("emrapi.retrospectiveVisit.stopDateCannotBeInFuture");
    }

    if (startDatetime.after(stopDatetime)) {
      throw new IllegalArgumentException("emrapi.retrospectiveVisit.endDateBeforeStartDateMessage");
    }

    if (hasVisitDuring(patient, location, startDatetime, stopDatetime)) {
      throw new ExistingVisitDuringTimePeriodException(
          "emrapi.retrospectiveVisit.patientAlreadyHasVisit");
    }

    Visit visit = buildVisit(patient, location, startDatetime);
    visit.setStopDatetime(stopDatetime);

    return wrap(visitService.saveVisit(visit));
  }
  @Override
  public List<VisitDomainWrapper> getInpatientVisits(Location visitLocation, Location ward) {

    if (visitLocation == null) {
      throw new IllegalArgumentException("Location is required");
    }
    Set<Location> locations = getChildLocationsRecursively(visitLocation, null);
    List<Visit> candidates =
        visitService.getVisits(
            null, null, locations, null, null, null, null, null, null, false, false);

    List<VisitDomainWrapper> inpatientVisits = new ArrayList<VisitDomainWrapper>();
    for (Visit candidate : candidates) {
      VisitDomainWrapper visitDomainWrapper = wrap(candidate);
      if (itBelongsToARealPatient(candidate) && visitDomainWrapper.isAdmitted()) {
        if (ward != null) {
          Encounter latestAdtEncounter = visitDomainWrapper.getLatestAdtEncounter();
          if (latestAdtEncounter != null
              && (latestAdtEncounter.getLocation().getId().compareTo(ward.getId()) == 0)) {
            inpatientVisits.add(visitDomainWrapper);
          }
        } else {
          inpatientVisits.add(visitDomainWrapper);
        }
      }
    }

    return inpatientVisits;
  }
  @Override
  @Transactional(readOnly = true)
  public List<VisitDomainWrapper> getVisits(
      Patient patient, Location location, Date startDatetime, Date endDatetime) {

    List<VisitDomainWrapper> visitDomainWrappers = new ArrayList<VisitDomainWrapper>();

    for (Visit visit :
        visitService.getVisits(
            Collections.singletonList(emrApiProperties.getAtFacilityVisitType()),
            Collections.singletonList(patient),
            Collections.singletonList(getLocationThatSupportsVisits(location)),
            null,
            null,
            endDatetime,
            startDatetime,
            null,
            null,
            true,
            false)) {
      visitDomainWrappers.add(wrap(visit));
    }

    return visitDomainWrappers;
  }
  @Test
  public void shouldAddNewTestOrder() throws Exception {
    executeDataSet("shouldAddNewTestOrder.xml");

    String json =
        "{ \"patientUuid\" : \"a76e8d23-0c38-408c-b2a8-ea5540f01b51\", "
            + "\"visitTypeUuid\" : \"b45ca846-c79a-11e2-b0c0-8e397087571c\", "
            + "\"encounterTypeUuid\": \"2b377dba-62c3-4e53-91ef-b51c68899890\", "
            + "\"encounterDateTime\" : \"2005-01-02T00:00:00.000+0000\", "
            + "\"testOrders\":["
            + "{\"concept\": {\"uuid\": \"d102c80f-1yz9-4da3-bb88-8122ce8868dd\"}, \"instructions\":\"do it\", \"orderTypeUuid\": \"1a61ef2a-250c-11e3-b832-0800271c1b75\" }]}";

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

    Visit visit = visitService.getVisitByUuid(response.getVisitUuid());
    Encounter encounter = visit.getEncounters().iterator().next();

    assertEquals(1, encounter.getOrders().size());
    Order testOrder = encounter.getOrders().iterator().next();
    assertEquals("d102c80f-1yz9-4da3-bb88-8122ce8868dd", testOrder.getConcept().getUuid());
    assertEquals("a76e8d23-0c38-408c-b2a8-ea5540f01b51", testOrder.getPatient().getUuid());
    assertEquals("f13d6fae-baa9-4553-955d-920098bec08f", testOrder.getEncounter().getUuid());
    assertEquals("1a61ef2a-250c-11e3-b832-0800271c1b75", testOrder.getOrderType().getUuid());
    assertEquals("do it", testOrder.getInstructions());
  }
  @Override
  public void action(
      EncounterDomainWrapper encounterDomainWrapper,
      Obs dispositionObsGroupBeingCreated,
      Map<String, String[]> requestParameters) {

    if (encounterDomainWrapper.getVisit() == null) {
      return;
    }

    VisitDomainWrapper visitDomainWrapper = adtService.wrap(encounterDomainWrapper.getVisit());

    // if this is an active visit, we close it... *as long as* there are no subsequent encounters on
    // following days
    // (if there are subsequent encounters on following days, this is some sort of retrospective
    // entry, and we can't
    // determine exactly what should happen, so just do nothing)

    if (visitDomainWrapper.isActive()) {
      Date mostRecentEncounterDatetime =
          visitDomainWrapper.getMostRecentEncounter().getEncounterDatetime();

      if (!new DateMidnight(mostRecentEncounterDatetime)
          .isAfter(new DateMidnight(encounterDomainWrapper.getEncounterDatetime()))) {
        visitDomainWrapper.closeOnLastEncounterDatetime();
        visitService.saveVisit(visitDomainWrapper.getVisit());
      }
    }
  }
  @Test
  public void shouldCreateNewEncounter() throws Exception {
    executeDataSet("shouldCreateMatchingEncounter.xml");

    String encounterDateTimeString = "2011-05-01T12:10:06.000+0530";
    Date encounterDateTime = new SimpleDateFormat(dateTimeFormat).parse(encounterDateTimeString);

    String json =
        "{ \"patientUuid\" : \"a76e8d23-0c38-408c-b2a8-ea5540f01b51\", "
            + "\"visitTypeUuid\" : \"b45ca846-c79a-11e2-b0c0-8e397087571c\", "
            + "\"encounterDateTime\" : \""
            + encounterDateTimeString
            + "\", "
            + "\"encounterTypeUuid\": \"2b377dba-62c3-4e53-91ef-b51c68899890\" }";

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

    assertEquals("1e5d5d48-6b78-11e0-93c3-18a905e044dc", response.getVisitUuid());

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

    assertEquals("a76e8d23-0c38-408c-b2a8-ea5540f01b51", encounter.getPatient().getUuid());
    assertEquals("2b377dba-62c3-4e53-91ef-b51c68899890", encounter.getEncounterType().getUuid());
    assertEquals(encounterDateTime, encounter.getEncounterDatetime());
  }
  @Test
  public void shouldAddNewDrugOrder() throws Exception {
    executeDataSet("shouldAddNewDrugOrder.xml");

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

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

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

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

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

    List<TestOrder> testOrders = getOrdersOfType(orders, TestOrder.class);
    assertEquals(1, testOrders.size());
    TestOrder testOrder = testOrders.get(0);
    assertEquals("d102c80f-1yz9-4da3-bb88-8122ce8868dd", testOrder.getConcept().getUuid());
    assertEquals("a76e8d23-0c38-408c-b2a8-ea5540f01b51", testOrder.getPatient().getUuid());
    assertEquals("f13d6fae-baa9-4553-955d-920098bec08f", testOrder.getEncounter().getUuid());
    assertEquals("1a61ef2a-250c-11e3-b832-0800271c1b75", testOrder.getOrderType().getUuid());
    assertEquals("do it", testOrder.getInstructions());
  }
 /**
  * @see VisitAttributeTypeController#update(String, SimpleObject,
  *     javax.servlet.http.HttpServletRequest, HttpServletResponse)
  */
 @Test
 public void update_shouldChangeAPropertyOnAVisitAttributeType() throws Exception {
   SimpleObject post =
       new ObjectMapper()
           .readValue("{\"description\":\"Updated description\"}", SimpleObject.class);
   controller.update(
       Rest19ExtTestConstants.VISIT_ATTRIBUTE_TYPE_UUID, post, emptyRequest(), emptyResponse());
   Assert.assertEquals("Updated description", service.getVisitAttributeType(1).getDescription());
 }
  /**
   * @see RadiologyEncounterMatcher#findEncounter(Visit,EncounterParameters)
   * @verifies throw illegal argument exception if given encounterParameters is null
   */
  @Test
  public void findEncounter_shouldThrowIllegalArgumentExceptionIfGivenEncounterParametersIsNull()
      throws Exception {
    // given
    Visit visit = visitService.getVisit(VISIT_ID_WITH_VOIDED_ENCOUNTER);

    expectedException.expect(IllegalArgumentException.class);
    expectedException.expectMessage("encounterParameters are required");
    radiologyEncounterMatcher.findEncounter(visit, null);
  }
 @Override
 @Transactional
 public Visit ensureActiveVisit(Patient patient, Location department) {
   Visit activeVisit = getActiveVisitHelper(patient, department);
   if (activeVisit == null) {
     Date now = new Date();
     activeVisit = buildVisit(patient, department, now);
     visitService.saveVisit(activeVisit);
   }
   return activeVisit;
 }
  /**
   * @see RadiologyEncounterMatcher#findEncounter(Visit,EncounterParameters)
   * @verifies return null given visit without non voided encounters
   */
  @Test
  public void findEncounter_shouldReturnNullGivenVisitWithoutNonVoidedEncounters()
      throws Exception {
    // given
    EncounterParameters encounterParameters =
        EncounterParameters.instance()
            .setEncounterType(radiologyProperties.getRadiologyOrderEncounterType());
    Visit visit = visitService.getVisit(VISIT_ID_WITHOUT_ENCOUNTER);

    Encounter encounter = radiologyEncounterMatcher.findEncounter(visit, encounterParameters);

    assertThat(encounter, is(nullValue()));
  }
  /**
   * Anything that calls this needs to be @Transactional
   *
   * @param patient
   * @param department
   * @return
   */
  private Visit getActiveVisitHelper(Patient patient, Location department) {
    Date now = new Date();

    List<Visit> candidates = visitService.getVisitsByPatient(patient);
    Visit ret = null;
    for (Visit candidate : candidates) {
      if (isSuitableVisit(candidate, department, now)) {
        ret = candidate;
      }
    }

    return ret;
  }
  /**
   * @see RadiologyEncounterMatcher#findEncounter(Visit,EncounterParameters)
   * @verifies return null if encounter uuid given by encounter parameters is voided
   */
  @Test
  public void findEncounter_shouldReturnNullIfEncounterUuidGivenByEncounterParametersIsVoided()
      throws Exception {
    // given
    EncounterParameters encounterParameters =
        EncounterParameters.instance()
            .setEncounterType(radiologyProperties.getRadiologyOrderEncounterType())
            .setEncounterUuid(VOIDED_ENCOUNTER_UUID);
    Visit visit = visitService.getVisit(VISIT_ID_WITH_VOIDED_ENCOUNTER);

    Encounter encounter = radiologyEncounterMatcher.findEncounter(visit, encounterParameters);

    assertThat(encounter, is(nullValue()));
  }
 @Override
 public void closeInactiveVisits() {
   List<Visit> openVisits =
       visitService.getVisits(null, null, null, null, null, null, null, null, null, false, false);
   for (Visit visit : openVisits) {
     if (shouldBeClosed(visit)) {
       try {
         closeAndSaveVisit(visit);
       } catch (Exception ex) {
         log.warn("Failed to close inactive visit " + visit, ex);
       }
     }
   }
 }
  @Test
  public void shouldCreateVisitWhenNoVisitsAreActive() throws Exception {
    executeDataSet("shouldCreateVisitWhenNoVisitsAreActive.xml");

    String json =
        "{ \"patientUuid\" : \"a76e8d23-0c38-408c-b2a8-ea5540f01b51\", \"visitTypeUuid\" : \"b45ca846-c79a-11e2-b0c0-8e397087571c\","
            + "\"encounterTypeUuid\": \"2b377dba-62c3-4e53-91ef-b51c68899890\" }";

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

    Visit visit = visitService.getVisitByUuid(response.getVisitUuid());
    assertEquals("a76e8d23-0c38-408c-b2a8-ea5540f01b51", visit.getPatient().getUuid());
    assertEquals("b45ca846-c79a-11e2-b0c0-8e397087571c", visit.getVisitType().getUuid());
  }
  @Test
  public void shouldAddNewObservation() throws Exception {
    executeDataSet("shouldAddNewObservation.xml");
    String encounterDateTime = "2005-01-02T00: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\": \"d102c80f-1yz9-4da3-bb88-8122ce8868dd\"}, \"conceptName\":\"Should be Ignored\", \"value\":20}, "
            + "{\"concept\": {\"uuid\": \"8f8e7340-a067-11e3-a5e2-0800200c9a66\"}, \"value\": {\"uuid\": \"e7167090-a067-11e3-a5e2-0800200c9a66\"}}, "
            + "{\"concept\": {\"uuid\": \"e102c80f-1yz9-4da3-bb88-8122ce8868dd\"}, \"value\":\"text value\", \"comment\":\"overweight\"}]}";

    MockHttpServletResponse response1 = handle(newPostRequest("/rest/emrapi/encounter", json));

    EncounterTransaction response = deserialize(response1, EncounterTransaction.class);

    Visit visit = visitService.getVisitByUuid(response.getVisitUuid());
    Encounter encounter = visit.getEncounters().iterator().next();

    assertEquals(3, encounter.getObs().size());
    Iterator<Obs> obsIterator = encounter.getObs().iterator();

    Map<String, Obs> map = new HashMap<String, Obs>();
    while (obsIterator.hasNext()) {
      Obs obs = obsIterator.next();
      map.put(obs.getConcept().getDatatype().getHl7Abbreviation(), obs);
    }
    Obs textObservation = map.get(ConceptDatatype.TEXT);
    assertEquals("text value", textObservation.getValueText());
    assertEquals("a76e8d23-0c38-408c-b2a8-ea5540f01b51", textObservation.getPerson().getUuid());
    assertEquals("e102c80f-1yz9-4da3-bb88-8122ce8868dd", textObservation.getConcept().getUuid());
    assertEquals("f13d6fae-baa9-4553-955d-920098bec08f", textObservation.getEncounter().getUuid());
    assertEquals("overweight", textObservation.getComment());
    //        TODO : change the observation startTime logic to take current time as start time when
    // startTime is not passed by the client
    //        assertEquals(DateUtils.parseDate(encounterDateTime, dateTimeFormat),
    // textObservation.getObsDatetime());

    assertEquals(
        "e7167090-a067-11e3-a5e2-0800200c9a66",
        map.get(ConceptDatatype.CODED).getValueCoded().getUuid());
    assertEquals(new Double(20.0), map.get(ConceptDatatype.NUMERIC).getValueNumeric());
  }
  @Test
  public void shouldAddDiagnosesAdObservation() throws Exception {
    executeDataSet("baseMetaData.xml");
    executeDataSet("diagnosisMetaData.xml");
    executeDataSet("shouldAddDiagnosisAsObservation.xml");
    String cancerDiagnosisUuid = "d102c80f-1yz9-4da3-bb88-8122ce8868dh";
    String encounterDateTime = "2005-01-02T00:00:00.000+0000";
    String diagnosisDateTime = "2005-01-02T01:00:00.000+0000";
    String postData =
        "{"
            + "\"patientUuid\" : \"a76e8d23-0c38-408c-b2a8-ea5540f01b51\", "
            + "\"visitTypeUuid\" : \"b45ca846-c79a-11e2-b0c0-8e397087571c\", "
            + "\"encounterTypeUuid\": \"2b377dba-62c3-4e53-91ef-b51c68899891\", "
            + "\"encounterDateTime\" : \""
            + encounterDateTime
            + "\", "
            + "\"diagnoses\":["
            + "{\"order\":\"PRIMARY\", \"certainty\": \"CONFIRMED\", \"codedAnswer\": { \"uuid\": \""
            + cancerDiagnosisUuid
            + "\"}, \"diagnosisDateTime\": \""
            + diagnosisDateTime
            + "\" }"
            + "]"
            + "}";

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

    Visit visit = visitService.getVisitByUuid(response.getVisitUuid());
    Encounter encounter = visit.getEncounters().iterator().next();

    Set<Obs> obsAtTopLevel = encounter.getObsAtTopLevel(false);
    assertEquals(1, obsAtTopLevel.size());
    Obs parentObservation = obsAtTopLevel.iterator().next();
    assertTrue(parentObservation.isObsGrouping());
    assertEquals(
        DateUtils.parseDate(diagnosisDateTime, dateTimeFormat), parentObservation.getObsDatetime());

    Set<Obs> diagnosisObservationGroupMembers = parentObservation.getGroupMembers();
    assertEquals(3, diagnosisObservationGroupMembers.size());
    ArrayList<String> valueCodedNames = getValuCodedNames(diagnosisObservationGroupMembers);
    assertTrue(valueCodedNames.contains("Confirmed"));
    assertTrue(valueCodedNames.contains("Primary"));
    assertTrue(valueCodedNames.contains("Cancer"));
  }
  @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);
  }
  /** @see org.openmrs.module.emrapi.adt.AdtService#getActiveVisits(org.openmrs.Location) */
  @Override
  public List<VisitDomainWrapper> getActiveVisits(Location location) {
    if (location == null) {
      throw new IllegalArgumentException("Location is required");
    }
    Set<Location> locations = getChildLocationsRecursively(location, null);
    List<Visit> candidates =
        visitService.getVisits(
            null, null, locations, null, null, null, null, null, null, false, false);

    List<VisitDomainWrapper> active = new ArrayList<VisitDomainWrapper>();
    for (Visit candidate : candidates) {
      if (itBelongsToARealPatient(candidate)) {
        active.add(wrap(candidate));
      }
    }

    return active;
  }
  @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 shouldUpdateObservations() throws Exception {
    executeDataSet("shouldUpdateObservations.xml");

    String json =
        "{ \"patientUuid\" : \"a76e8d23-0c38-408c-b2a8-ea5540f01b51\", "
            + "\"visitTypeUuid\" : \"b45ca846-c79a-11e2-b0c0-8e397087571c\", "
            + "\"encounterTypeUuid\": \"2b377dba-62c3-4e53-91ef-b51c68899890\","
            + "\"encounterDateTime\" : \"2013-01-01T00:00:00.000+0000\", "
            + "\"observations\":["
            + "{\"uuid\":\"z9fb7f47-e80a-4056-9285-bd798be13c63\", "
            + " \"groupMembers\" : [{\"uuid\":\"ze48cdcb-6a76-47e3-9f2e-2635032f3a9a\", \"value\":20, \"comment\":\"new gc\" }] }, "
            + "{\"uuid\":\"zf616900-5e7c-4667-9a7f-dcb260abf1de\", \"comment\" : \"new c\", \"value\":100 }"
            + "]}";

    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(2, encounter.getObsAtTopLevel(false).size());
    Iterator<Obs> iterator = encounter.getObsAtTopLevel(false).iterator();

    Obs obs1 = iterator.next();
    assertEquals("zf616900-5e7c-4667-9a7f-dcb260abf1de", obs1.getUuid());
    assertEquals(new Double(100), obs1.getValueNumeric());
    assertEquals("new c", obs1.getComment());

    Obs obs2 = iterator.next();
    assertEquals("z9fb7f47-e80a-4056-9285-bd798be13c63", obs2.getUuid());
    assertEquals(1, obs2.getGroupMembers().size());
    Obs member = obs2.getGroupMembers().iterator().next();
    assertEquals(new Double(20), member.getValueNumeric());
    assertEquals("new gc", member.getComment());
  }
  @Transactional
  @Override
  public void mergePatients(Patient preferred, Patient notPreferred) {
    boolean preferredWasUnknown =
        domainWrapperFactory.newPatientDomainWrapper(preferred).isUnknownPatient();
    boolean notPreferredWasUnknown =
        domainWrapperFactory.newPatientDomainWrapper(notPreferred).isUnknownPatient();
    if (preferredWasUnknown && !notPreferredWasUnknown) {
      throw new IllegalArgumentException("Cannot merge a permanent record into an unknown one");
    }

    List<Visit> preferredVisits = visitService.getVisitsByPatient(preferred, true, false);
    List<Visit> notPreferredVisits = visitService.getVisitsByPatient(notPreferred, true, false);

    // if the non-preferred patient has any visits that overlap with visits of the preferred
    // patient, we need to merge them together
    for (Visit losing : notPreferredVisits) {
      if (!losing.isVoided()) {
        for (Visit winning : preferredVisits) {
          if (!winning.isVoided() && visitsOverlap(losing, winning)) {
            mergeVisits(winning, losing);
            break;
          }
        }
      }
    }

    // merging in visits from the non-preferred patient (and extending visit durations) may have
    // caused preferred-patient visits to overlap
    Collections.sort(
        preferredVisits,
        new Comparator<Visit>() {
          @Override
          public int compare(Visit left, Visit right) {
            return OpenmrsUtil.compareWithNullAsEarliest(
                left.getStartDatetime(), right.getStartDatetime());
          }
        });
    for (int i = 0; i < preferredVisits.size(); ++i) {
      Visit visit = preferredVisits.get(i);
      if (!visit.isVoided()) {
        for (int j = i + 1; j < preferredVisits.size(); ++j) {
          Visit candidate = preferredVisits.get(j);
          if (!candidate.isVoided() && visitsOverlap(visit, candidate)) {
            mergeVisits(visit, candidate);
          }
        }
      }
    }

    if (patientMergeActions != null) {
      for (PatientMergeAction patientMergeAction : patientMergeActions) {
        patientMergeAction.beforeMergingPatients(preferred, notPreferred);
      }
    }

    try {
      patientService.mergePatients(preferred, notPreferred);
      // if we merged an unknown record into a permanent one, remove the unknown flag; if we merged
      // two unknown records, keep it
      if (!preferredWasUnknown) {
        removeAttributeOfUnknownPatient(preferred);
      }
    } catch (SerializationException e) {
      throw new APIException("Unable to merge patients due to serialization error", e);
    }

    if (patientMergeActions != null) {
      for (PatientMergeAction patientMergeAction : patientMergeActions) {
        patientMergeAction.afterMergingPatients(preferred, notPreferred);
      }
    }
  }