@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;
  }
  @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;
  }
  @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;
  }
 @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);
       }
     }
   }
 }
  /** @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;
  }