/** @see {@link ExistingOrNewVisitAssignmentHandler#beforeCreateEncounter(Encounter)} */
  @Test
  @Verifies(
      value = "should resolve encounter and visit type uuids as global property values",
      method = "beforeCreateEncounter(Encounter)")
  public void beforeCreateEncounter_shouldResolveEncounterAndVisitTypeUuidsAsGlobalPropertyValues()
      throws Exception {
    final String encounterTypeUuid = "759799ab-c9a5-435e-b671-77773ada74e4";
    final String visitTypeUuid = "c0c579b0-8e59-401d-8a4a-976a0b183519";
    Encounter encounter = Context.getEncounterService().getEncounter(1);
    Assert.assertNull(encounter.getVisit());
    Assert.assertEquals(encounterTypeUuid, encounter.getEncounterType().getUuid());

    Calendar calendar = Calendar.getInstance();
    calendar.setTime(encounter.getEncounterDatetime());
    calendar.set(Calendar.YEAR, 1900);

    encounter.setEncounterDatetime(calendar.getTime());

    GlobalProperty gp =
        new GlobalProperty(
            OpenmrsConstants.GP_ENCOUNTER_TYPE_TO_VISIT_TYPE_MAPPING,
            encounterTypeUuid + ":" + visitTypeUuid);
    Context.getAdministrationService().saveGlobalProperty(gp);

    new ExistingOrNewVisitAssignmentHandler().beforeCreateEncounter(encounter);

    Assert.assertNotNull(encounter.getVisit());

    // should be set according toencounterTypeUuid:visitTypeUuid
    Assert.assertEquals(1, encounter.getEncounterType().getEncounterTypeId().intValue());
    Assert.assertEquals(
        Context.getVisitService().getVisitTypeByUuid(visitTypeUuid),
        encounter.getVisit().getVisitType());
  }
  public EncounterListItem(Encounter encounter) {

    if (encounter != null) {
      encounterId = encounter.getEncounterId();
      encounterDateTime = encounter.getEncounterDatetime();
      encounterDateString = Format.format(encounter.getEncounterDatetime());
      PersonName pn = encounter.getPatient().getPersonName();
      if (pn != null) {
        personName = "";
        if (pn.getGivenName() != null) {
          personName += pn.getGivenName();
        }
        if (pn.getMiddleName() != null) {
          personName += " " + pn.getMiddleName();
        }
        if (pn.getFamilyName() != null) {
          personName += " " + pn.getFamilyName();
        }
      }
      if (encounter.getProvider() != null) {
        providerName = encounter.getProvider().getPersonName().getFullName();
      }
      if (encounter.getLocation() != null) {
        location = encounter.getLocation().getName();
      }
      if (encounter.getEncounterType() != null) {
        encounterType = encounter.getEncounterType().getName();
      }
      if (encounter.getForm() != null) {
        formName = encounter.getForm().getName();
        formId = encounter.getForm().getFormId();
      }
      voided = encounter.isVoided();
      if (encounter.getCreator() != null) {
        PersonName entererPersonName = encounter.getCreator().getPersonName();
        if (entererPersonName != null) {
          entererName = "";
          if (entererPersonName.getGivenName() != null) {
            entererName += entererPersonName.getGivenName();
          }
          if (entererPersonName.getMiddleName() != null) {
            entererName += " " + entererPersonName.getMiddleName();
          }
          if (entererPersonName.getFamilyName() != null) {
            entererName += " " + entererPersonName.getFamilyName();
          }
        }
      }
    }
  }
  /** @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
  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());
  }
  /** @see {@link ExistingVisitAssignmentHandler#beforeCreateEncounter(Encounter)} */
  @Test
  @Verifies(
      value = "should assign mapping global property visit type",
      method = "beforeCreateEncounter(Encounter)")
  public void beforeCreateEncounter_shouldAssignMappingGlobalPropertyVisitType() throws Exception {
    Encounter encounter = Context.getEncounterService().getEncounter(1);
    Assert.assertNull(encounter.getVisit());

    Calendar calendar = Calendar.getInstance();
    calendar.setTime(encounter.getEncounterDatetime());
    calendar.set(Calendar.YEAR, 1900);

    encounter.setEncounterDatetime(calendar.getTime());

    GlobalProperty gp =
        new GlobalProperty(
            OpenmrsConstants.GP_ENCOUNTER_TYPE_TO_VISIT_TYPE_MAPPING, "3:4, 5:2, 1:2, 2:2");
    Context.getAdministrationService().saveGlobalProperty(gp);

    new ExistingOrNewVisitAssignmentHandler().beforeCreateEncounter(encounter);

    Assert.assertNotNull(encounter.getVisit());

    // should be set according to: 1:2 encounterTypeId:visitTypeId
    Assert.assertEquals(1, encounter.getEncounterType().getEncounterTypeId().intValue());
    Assert.assertEquals(
        Context.getVisitService().getVisitType(2), encounter.getVisit().getVisitType());
  }
  /** @see org.openmrs.api.EncounterService#purgeEncounter(Encounter, boolean) */
  public void purgeEncounter(Encounter encounter, boolean cascade) 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.purge",
          new Object[] {encounter.getEncounterType().getEditPrivilege()});
    }

    if (cascade) {
      ObsService obsService = Context.getObsService();
      List<Encounter> justThisEncounter = new ArrayList<Encounter>();
      justThisEncounter.add(encounter);
      List<Obs> observations = new Vector<Obs>();
      observations.addAll(
          obsService.getObservations(
              null, justThisEncounter, null, null, null, null, null, null, null, null, null, true));
      for (Obs o : observations) {
        obsService.purgeObs(o);
      }
      Set<Order> orders = encounter.getOrders();
      for (Order o : orders) {
        Context.getOrderService().purgeOrder(o);
      }
    }
    Context.getEncounterService().purgeEncounter(encounter);
  }
 private Encounter getEncounterByTypeUuid(Set<Encounter> encounters, String encounterUuid) {
   for (Encounter encounter : encounters) {
     if (encounter.getEncounterType().getUuid().equals(encounterUuid)) {
       return encounter;
     }
   }
   return null;
 }
 /** @see org.openmrs.api.EncounterService#purgeEncounter(org.openmrs.Encounter) */
 public void purgeEncounter(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.purge",
         new Object[] {encounter.getEncounterType().getEditPrivilege()});
   }
   dao.deleteEncounter(encounter);
 }
  /**
   * @see org.openmrs.api.EncounterService#canEditEncounter(org.openmrs.Encounter, org.openmrs.User)
   */
  @Override
  public boolean canEditEncounter(Encounter encounter, User user) {
    // if passed in encounter is null raise an exception
    if (encounter == null) {
      throw new IllegalArgumentException("The encounter argument can not be null");
    }
    // since we restrict by encounter type, if it does not exist, then anyone is allowed to edit the
    // encounter
    if (encounter.getEncounterType() == null) {
      return Boolean.TRUE;
    }
    // if user is not specified, then use authenticated user from context by default
    if (user == null) {
      user = Context.getAuthenticatedUser();
    }

    return userHasEncounterPrivilege(encounter.getEncounterType().getEditPrivilege(), user);
  }
 /** @see org.openmrs.api.EncounterService#purgeEncounter(org.openmrs.Encounter) */
 public void purgeEncounter(Encounter encounter) throws APIException {
   // 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 purge encounters of this type",
             encounter.getEncounterType().getEditPrivilege()));
   }
   dao.deleteEncounter(encounter);
 }
 public static List<Encounter> getEncountersByTreatment(Patient patient, String treatmentType) {
   List<Encounter> encounters = Context.getEncounterService().getEncountersByPatient(patient);
   List<Encounter> treatmentEncounters = new ArrayList<Encounter>();
   for (Encounter encounter : encounters) {
     if (!encounter.isVoided() && treatmentType.equals(encounter.getEncounterType().getName())) {
       treatmentEncounters.add(encounter);
     }
   }
   return treatmentEncounters;
 }
 public static Encounter getLatestEncounterByTreatment(Patient patient, String treatmentType) {
   List<Encounter> encounters = Context.getEncounterService().getEncountersByPatient(patient);
   Encounter treatmentEncounter = null;
   for (Encounter encounter : encounters) {
     if (!encounter.isVoided() && treatmentType.equals(encounter.getEncounterType().getName())) {
       if (treatmentEncounter == null) treatmentEncounter = encounter;
       else if (treatmentEncounter.getDateCreated().before(encounter.getDateCreated()))
         treatmentEncounter = encounter;
     }
   }
   return treatmentEncounter;
 }
 /** @see org.openmrs.api.EncounterService#getEncounter(java.lang.Integer) */
 @Transactional(readOnly = true)
 public Encounter getEncounter(Integer encounterId) throws APIException {
   Encounter encounter = dao.getEncounter(encounterId);
   if (encounter == null) {
     return null;
   } else if (canViewEncounter(encounter, null)) {
     return encounter;
   } else {
     throw new APIException(
         "Encounter.error.privilege.required.view",
         new Object[] {encounter.getEncounterType().getViewPrivilege()});
   }
 }
  /**
   * This method is synchronized to prevent multiple check-ins in a row at the same location and
   * during the same visit. See #579.
   *
   * @see org.openmrs.module.emrapi.adt.AdtService#checkInPatient(org.openmrs.Patient,
   *     org.openmrs.Location, org.openmrs.Provider, java.util.List, java.util.List, boolean)
   */
  @Override
  @Transactional
  public synchronized Encounter checkInPatient(
      Patient patient,
      Location where,
      Provider checkInClerk,
      List<Obs> obsForCheckInEncounter,
      List<Order> ordersForCheckInEncounter,
      boolean newVisit) {
    if (checkInClerk == null) {
      checkInClerk = getProvider(Context.getAuthenticatedUser());
    }

    Visit activeVisit = getActiveVisitHelper(patient, where);

    if (activeVisit != null && newVisit) {
      closeAndSaveVisit(activeVisit);
      activeVisit = null;
    }

    if (activeVisit == null) {
      activeVisit = ensureActiveVisit(patient, where);
    }

    Encounter lastEncounter = getLastEncounter(patient);
    if (lastEncounter != null
        && activeVisit.equals(lastEncounter.getVisit())
        && emrApiProperties.getCheckInEncounterType().equals(lastEncounter.getEncounterType())
        && where.equals(lastEncounter.getLocation())) {
      log.warn(
          "Patient id:{} tried to check-in twice in a row at id:{} during the same visit",
          patient.getId(),
          where.getId());
      return lastEncounter;
    }

    Encounter encounter =
        buildEncounter(
            emrApiProperties.getCheckInEncounterType(),
            patient,
            where,
            null,
            new Date(),
            obsForCheckInEncounter,
            ordersForCheckInEncounter);
    encounter.addProvider(emrApiProperties.getCheckInClerkEncounterRole(), checkInClerk);
    activeVisit.addEncounter(encounter);
    encounterService.saveEncounter(encounter);
    return encounter;
  }
 /** @see org.openmrs.api.EncounterService#getEncounter(java.lang.Integer) */
 @Transactional(readOnly = true)
 public Encounter getEncounter(Integer encounterId) throws APIException {
   Encounter encounter = dao.getEncounter(encounterId);
   if (encounter == null) {
     return null;
   } else if (canViewEncounter(encounter, null)) {
     return encounter;
   } else {
     throw new APIException(
         String.format(
             "Privilege %s required to view encounters of this type",
             encounter.getEncounterType().getViewPrivilege()));
   }
 }
  /**
   * @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;
  }
 /**
  * @see org.openmrs.api.EncounterService#filterEncountersByViewPermissions(java.util.List,
  *     org.openmrs.User)
  */
 @Override
 @Transactional(readOnly = true)
 public List<Encounter> filterEncountersByViewPermissions(List<Encounter> encounters, User user) {
   if (encounters != null) {
     // if user is not specified then use authenticated user from context by default
     if (user == null) {
       user = Context.getAuthenticatedUser();
     }
     for (Iterator<Encounter> iterator = encounters.iterator(); iterator.hasNext(); ) {
       Encounter encounter = iterator.next();
       // determine whether it's need to include this encounter into result or not
       // as it can be not accessed by current user due to permissions lack
       EncounterType et = encounter.getEncounterType();
       if (et != null && !userHasEncounterPrivilege(et.getViewPrivilege(), user)) {
         // exclude this encounter from result
         iterator.remove();
       }
     }
   }
   return encounters;
 }
  /** @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;
  }