Search in sources :

Example 46 with PersonAddress

use of org.openmrs.PersonAddress in project openmrs-core by openmrs.

the class PersonServiceTest method savePerson_shouldNotSetAVoidedNameOrAddressAsPreferred.

/**
 * @see PersonService#savePerson(Person)
 */
@Test
public void savePerson_shouldNotSetAVoidedNameOrAddressAsPreferred() throws Exception {
    Person person = new Person();
    person.setGender("M");
    PersonName name = new PersonName("givenName", "middleName", "familyName");
    PersonName preferredName = new PersonName("givenName", "middleName", "familyName");
    preferredName.setPreferred(true);
    preferredName.setVoided(true);
    person.addName(name);
    person.addName(preferredName);
    PersonAddress address = new PersonAddress();
    address.setAddress1("some address");
    PersonAddress preferredAddress = new PersonAddress();
    preferredAddress.setAddress1("another address");
    preferredAddress.setPreferred(true);
    preferredAddress.setVoided(true);
    person.addAddress(address);
    person.addAddress(preferredAddress);
    personService.savePerson(person);
    Assert.assertFalse(preferredName.getPreferred());
    Assert.assertFalse(preferredAddress.getPreferred());
    assertTrue(name.getPreferred());
    assertTrue(address.getPreferred());
}
Also used : PersonName(org.openmrs.PersonName) PersonAddress(org.openmrs.PersonAddress) Person(org.openmrs.Person) Test(org.junit.Test) BaseContextSensitiveTest(org.openmrs.test.BaseContextSensitiveTest)

Example 47 with PersonAddress

use of org.openmrs.PersonAddress in project openmrs-module-pihcore by PIH.

the class WristbandTemplate method generateWristband.

public String generateWristband(Patient patient, Location location) {
    // TODO figure out why this isn't getting autowired properly (at least for tests)
    if (addressHierarchyService == null) {
        addressHierarchyService = Context.getService(AddressHierarchyService.class);
    }
    StringBuffer data = new StringBuffer();
    data.append("^XA");
    // specify Unicode encoding
    data.append("^CI28");
    // set direct transfer type
    data.append("^MTD");
    // set orientation
    data.append("^FWB");
    // visit location & current data
    data.append("^FO050,200^FB2150,1,0,L,0^AS^FD" + adtService.getLocationThatSupportsVisits(location).getName() + " " + fullDate.format(new Date()) + "^FS");
    // patient name: for now, only printing given and family names
    String patientName = null;
    if (patient.getPersonName() != null) {
        patientName = (patient.getPersonName().getGivenName() != null ? patient.getPersonName().getGivenName() : "") + " " + (patient.getPersonName().getFamilyName() != null ? patient.getPersonName().getFamilyName() : "");
    }
    data.append("^FO100,200^FB2150,1,0,L,0^AU^FD" + patientName + "^FS");
    if (patient.getBirthdate() != null) {
        // birthdate (we only show year if birthdate is estimated
        DateFormat df = patient.getBirthdateEstimated() ? yearOnly : fullDate;
        data.append("^FO160,200^FB2150,1,0,L,0^AU^FD" + df.format(patient.getBirthdate()) + "^FS");
    }
    if (patient.getAge() != null) {
        // age
        data.append("^FO160,200^FB1850,1,0,L,0^AT^FD" + messageSourceService.getMessage("coreapps.ageYears", Collections.singletonList(patient.getAge()).toArray(), locale) + "^FS");
    }
    // gender
    data.append("^FO160,200^FB1650,1,0,L,0^AU^FD" + messageSourceService.getMessage("coreapps.gender." + patient.getGender(), null, locale) + "  ");
    // paper record identifier
    PatientIdentifier paperRecordIdentifier = getAppropriatePaperRecordIdentifierForLocation(patient, location);
    if (paperRecordIdentifier != null) {
        data.append(paperRecordIdentifier.getIdentifier().substring(0, paperRecordIdentifier.getIdentifier().length() - 6) + " " + paperRecordIdentifier.getIdentifier().substring(paperRecordIdentifier.getIdentifier().length() - 6));
    }
    data.append("^FS");
    // address (based on address hierarchy)
    PersonAddress address = patient.getPersonAddress();
    AddressHierarchyLevel level = addressHierarchyService.getBottomAddressHierarchyLevel();
    int numberOfLevels = addressHierarchyService.getAddressHierarchyLevelsCount();
    if (address != null && numberOfLevels > 0) {
        int levelCount = 1;
        if (LOWEST_LEVEL_ON_SEPARATE_LINE) {
            String lowestLevelStr = AddressHierarchyUtil.getAddressFieldValue(address, level.getAddressField());
            if (StringUtils.isNotBlank(address.getAddress2())) {
                data.append("^FO220,200^FB2150,1,0,L,0^AS^FD" + lowestLevelStr + "^FS");
            }
            levelCount++;
        }
        StringBuffer addressStr = new StringBuffer();
        while (levelCount < numberOfLevels || (!SKIP_HIGHEST_LEVEL && levelCount <= numberOfLevels) && level.getParent() != null) {
            // level.getParent() should never equal null as long as levelCount <= numberOfLevels, but just to be safe we will check
            level = level.getParent();
            String levelStr = AddressHierarchyUtil.getAddressFieldValue(address, level.getAddressField());
            if (StringUtils.isNotBlank(levelStr)) {
                addressStr.append(levelStr + ", ");
            }
            levelCount++;
        }
        if (StringUtils.isNotBlank(addressStr.toString())) {
            // trim off trailing comma and space
            addressStr.delete(addressStr.length() - 2, addressStr.length());
            data.append("^FO270,200^FB2150,1,0,L,0^AS^FD" + addressStr.toString() + "^FS");
        }
    }
    // barcode with primary identifier
    PatientIdentifier primaryIdentifier = patient.getPatientIdentifier(emrApiProperties.getPrimaryIdentifierType());
    if (primaryIdentifier != null) {
        data.append("^FO100,2400^AT^BY4^BC,150,N^FD" + primaryIdentifier.getIdentifier() + "^XZ");
    }
    return data.toString();
}
Also used : PersonAddress(org.openmrs.PersonAddress) SimpleDateFormat(java.text.SimpleDateFormat) DateFormat(java.text.DateFormat) AddressHierarchyService(org.openmrs.module.addresshierarchy.service.AddressHierarchyService) Date(java.util.Date) PatientIdentifier(org.openmrs.PatientIdentifier) AddressHierarchyLevel(org.openmrs.module.addresshierarchy.AddressHierarchyLevel)

Example 48 with PersonAddress

use of org.openmrs.PersonAddress in project openmrs-module-pihcore by PIH.

the class PihPatientSearchAlgorithmTest method exactAddressFieldMatchShouldIncreaseScore.

@Test
public void exactAddressFieldMatchShouldIncreaseScore() {
    // first get the base score for this patient
    Patient patient = new Patient();
    PersonName name = new PersonName();
    patient.addName(name);
    name.setGivenName("Jarusz");
    name.setFamilyName("Rapondee");
    patient.setBirthdate(new Date());
    patient.setGender("M");
    List<PatientAndMatchQuality> results = searchAlgorithm.findSimilarPatients(patient, null, null, 10);
    double scoreWithoutAddress = results.get(0).getScore();
    // now add in address and recalculate
    PersonAddress address = new PersonAddress();
    address.setCityVillage("shiseso");
    patient.addAddress(address);
    results = searchAlgorithm.findSimilarPatients(patient, null, null, 10);
    double scoreWithAddress = results.get(0).getScore();
    // in our test config we've weighed cityVillage at 1 point
    assertThat(scoreWithAddress - scoreWithoutAddress, is(1.0));
    assertTrue(results.get(0).getMatchedFields().contains("addresses.cityVillage"));
}
Also used : PersonName(org.openmrs.PersonName) PersonAddress(org.openmrs.PersonAddress) PatientAndMatchQuality(org.openmrs.module.registrationcore.api.search.PatientAndMatchQuality) Patient(org.openmrs.Patient) Date(java.util.Date) Test(org.junit.Test) PihCoreContextSensitiveTest(org.openmrs.module.pihcore.PihCoreContextSensitiveTest)

Example 49 with PersonAddress

use of org.openmrs.PersonAddress in project openmrs-module-pihcore by PIH.

the class PihPatientSearchAlgorithm method findSimilarPatients.

// TODO what about highlighting/showing the reasons for the match on the screen?
// TODO what about exact patient search algo? do we want to still use that, or just use this with a higher cutoff?
// TODO phonetics on attributes?
// TODO what about max results on initial query? needed?
// TODO more tests? make sure matchedfields are properly included?
// TODO address hierarchy field changes don't trigger a re-search
@Override
public List<PatientAndMatchQuality> findSimilarPatients(Patient patient, Map<String, Object> otherDataPoints, Double cutoff, Integer maxResults) {
    // only do search if we have family name, given name, gender, and birthdate--return empty list otherwise
    if (!hasName(patient) || !hasBirthdate(patient, otherDataPoints) || patient.getGender() == null) {
        return new ArrayList<PatientAndMatchQuality>();
    }
    // our initial search to find a "base cohort"; hits will only occur if there is a phonetic match on both given name and family name
    List<Patient> patients = getPatientsByPhonetics(patient.getGivenName(), patient.getFamilyName());
    List<PatientAndMatchQuality> matches = new ArrayList<PatientAndMatchQuality>();
    for (Patient match : patients) {
        List<String> matchedFields = new ArrayList<String>();
        double score = 0;
        // these are matched by the fact that we made it through the name phonetics match
        matchedFields.add("names.givenName");
        matchedFields.add("names.familyName");
        // one point if gender matches
        if (patient.getGender() != null && match.getGender() != null) {
            if (patient.getGender().equals(match.getGender())) {
                score += 1;
                matchedFields.add("gender");
            } else {
                score += -8;
            }
        }
        // exact birthdate match = 10 pts; otherwise, if years between < 5, assign points based on 5-years between
        if (patient.getBirthdate() != null && match.getBirthdate() != null) {
            if (!match.getBirthdateEstimated() && new DateTime(patient.getBirthdate()).withTimeAtStartOfDay().equals(new DateTime(match.getBirthdate()).withTimeAtStartOfDay())) {
                score += 10;
                matchedFields.add("birthdate");
            } else {
                int yearsBetween = Math.abs(Years.yearsBetween(new DateTime(patient.getBirthdate()), new DateTime(match.getBirthdate())).getYears());
                if (yearsBetween <= 5) {
                    score += (6 - yearsBetween);
                    matchedFields.add("birthdate");
                } else {
                    score += -8;
                }
            }
        } else // try estimated birthdate
        {
            Integer patientEstimatedAge = null;
            if (otherDataPoints != null && otherDataPoints.containsKey("birthdateYears") && otherDataPoints.get("birthdateYears") != null) {
                patientEstimatedAge = (Integer) otherDataPoints.get("birthdateYears");
            } else if (otherDataPoints != null && otherDataPoints.containsKey("birthdateMonths") && otherDataPoints.get("birthdateMonths") != null) {
                patientEstimatedAge = 0;
            }
            if (patientEstimatedAge != null) {
                int yearsBetween = Math.abs(patientEstimatedAge - match.getAge());
                if (yearsBetween < 5) {
                    score += (6 - yearsBetween);
                    matchedFields.add("birthdate");
                }
            }
        }
        // check for *exact* name matches
        boolean familyNameMatch = false;
        boolean givenNameMatch = false;
        boolean middleNameMatch = false;
        familyNameMatch = nameExactMatch(patient.getFamilyName(), match.getFamilyName());
        givenNameMatch = nameExactMatch(patient.getGivenName(), match.getGivenName());
        middleNameMatch = nameExactMatch(patient.getMiddleName(), match.getMiddleName());
        if (familyNameMatch && givenNameMatch && middleNameMatch) {
            score += 4;
        } else if (familyNameMatch && givenNameMatch) {
            score += 2;
        } else if (familyNameMatch || givenNameMatch || middleNameMatch) {
            score += 0.5;
        }
        // check for address matches
        if (config.getRegistrationConfig() != null && config.getRegistrationConfig().getSimilarPatientsSearch() != null && config.getRegistrationConfig().getSimilarPatientsSearch().containsKey("addressFields")) {
            Map<String, String> addressFields = (Map<String, String>) config.getRegistrationConfig().getSimilarPatientsSearch().get("addressFields");
            PersonAddress patientAddress = patient.getPersonAddress();
            PersonAddress matchAddress = match.getPersonAddress();
            if (addressFields != null && patientAddress != null && matchAddress != null) {
                for (String addressField : addressFields.keySet()) {
                    try {
                        String patientField = (String) PropertyUtils.getProperty(patientAddress, addressField);
                        String matchField = (String) PropertyUtils.getProperty(matchAddress, addressField);
                        if (StringUtils.isNotBlank(patientField) && StringUtils.isNotBlank(matchField) && stripAccentMarks(patientField).equalsIgnoreCase(stripAccentMarks(matchField))) {
                            score += new Double(addressFields.get(addressField));
                            matchedFields.add("addresses." + addressField);
                        }
                    } catch (Exception e) {
                        log.error("Unable to access " + addressField + " on patient during similar patient search");
                    }
                }
            }
        }
        // check person attribute matches
        if (config.getRegistrationConfig() != null && config.getRegistrationConfig().getSimilarPatientsSearch() != null && config.getRegistrationConfig().getSimilarPatientsSearch().containsKey("personAttributeTypes")) {
            Map<String, String> personAttributeTypes = (Map<String, String>) config.getRegistrationConfig().getSimilarPatientsSearch().get("personAttributeTypes");
            for (String personAttributeType : personAttributeTypes.keySet()) {
                String patientAttribute = patient.getAttribute(personAttributeType) != null ? patient.getAttribute(personAttributeType).getValue() : null;
                String matchAttribute = match.getAttribute(personAttributeType) != null ? match.getAttribute(personAttributeType).getValue() : null;
                if (StringUtils.isNotBlank(patientAttribute) && StringUtils.isNotBlank(matchAttribute)) {
                    // special case telephone number: strip all non-numerics
                    if (personAttributeType.equalsIgnoreCase(Metadata.getPhoneNumberAttributeType().getName())) {
                        patientAttribute = patientAttribute.replaceAll("[^0-9]", "");
                        matchAttribute = matchAttribute.replaceAll("[^0-9]", "");
                    }
                    // special case First Name of Mother: convert to name phonetics
                    if (personAttributeType.equalsIgnoreCase(Metadata.getMothersFirstNameAttributeType().getName())) {
                        patientAttribute = NamePhoneticsUtil.encodeString(patientAttribute, adminService.getGlobalProperty("namephonetics.givenNameStringEncoder"));
                        matchAttribute = NamePhoneticsUtil.encodeString(matchAttribute, adminService.getGlobalProperty("namephonetics.givenNameStringEncoder"));
                    }
                    if (stripAccentMarks(patientAttribute).equalsIgnoreCase(stripAccentMarks(matchAttribute))) {
                        score += new Double(personAttributeTypes.get(personAttributeType));
                        matchedFields.add("attributes." + personAttributeType);
                    }
                }
            }
        }
        // only take matches that make the cut
        if (cutoff == null) {
            matches.add(new PatientAndMatchQuality(match, score, matchedFields));
        } else {
            if (score >= cutoff) {
                matches.add(new PatientAndMatchQuality(match, score, matchedFields));
            }
        }
    }
    Collections.sort(matches);
    if (maxResults != null && matches.size() > maxResults) {
        return matches.subList(0, maxResults);
    } else {
        return matches;
    }
}
Also used : PersonAddress(org.openmrs.PersonAddress) ArrayList(java.util.ArrayList) PatientAndMatchQuality(org.openmrs.module.registrationcore.api.search.PatientAndMatchQuality) Patient(org.openmrs.Patient) DateTime(org.joda.time.DateTime) Map(java.util.Map)

Aggregations

PersonAddress (org.openmrs.PersonAddress)49 Test (org.junit.Test)32 BaseContextSensitiveTest (org.openmrs.test.BaseContextSensitiveTest)26 PersonName (org.openmrs.PersonName)20 Patient (org.openmrs.Patient)18 BindException (org.springframework.validation.BindException)13 Errors (org.springframework.validation.Errors)13 Date (java.util.Date)12 PatientIdentifier (org.openmrs.PatientIdentifier)12 PatientServiceImplTest (org.openmrs.api.impl.PatientServiceImplTest)9 Person (org.openmrs.Person)6 Calendar (java.util.Calendar)5 Location (org.openmrs.Location)5 PatientIdentifierType (org.openmrs.PatientIdentifierType)5 ArrayList (java.util.ArrayList)4 Map (java.util.Map)3 DateTime (org.joda.time.DateTime)3 Concept (org.openmrs.Concept)3 PersonAttribute (org.openmrs.PersonAttribute)3 DateFormat (java.text.DateFormat)2