@RequestMapping("/module/hirifxray/createParticipant.form") public String createParticipant( ModelMap model, @RequestParam(value = "identifier", required = true) String identifier, @RequestParam(value = "gender", required = true) String gender) throws Exception { Patient p = new Patient(); PersonName pn = new PersonName(); pn.setGivenName("XXXX"); pn.setFamilyName("XXXX"); p.addName(pn); p.setGender(gender); DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); p.setBirthdate(df.parse("1900-01-01")); PatientIdentifier pi = new PatientIdentifier(); pi.setPatient(p); pi.setLocation(HirifMetadata.getUnknownLocation()); pi.setIdentifierType(HirifMetadata.getIdentifierType()); pi.setIdentifier(identifier); p.addIdentifier(pi); p = Context.getPatientService().savePatient(p); return "redirect:/module/hirifxray/participant.form?id=" + p.getPatientId(); }
/** @see ShortPatientFormValidator#validate(Object,Errors) */ @Test @Verifies( value = "should fail if all identifiers have been voided", method = "validate(Object,Errors)") public void validate_shouldFailIfAllIdentifiersHaveBeenVoided() throws Exception { Patient p = ps.getPatient(2); for (PatientIdentifier pId : p.getActiveIdentifiers()) pId.setVoided(true); ShortPatientModel model = new ShortPatientModel(p); Errors errors = new BindException(model, "patientModel"); validator.validate(model, errors); Assert.assertEquals(true, errors.hasGlobalErrors()); }
@Test public void testEstimatedBirthDate() { visitLocation.setName("Hôpital Universitaire de Mirebalais"); Patient patient = new Patient(); patient.setGender("M"); patient.setBirthdate(new DateTime(1940, 7, 7, 5, 5, 5).toDate()); patient.setBirthdateEstimated(true); PatientIdentifier primaryIdentifier = new PatientIdentifier(); primaryIdentifier.setIdentifier("ZL1234"); primaryIdentifier.setIdentifierType(primaryIdentifierType); primaryIdentifier.setVoided(false); patient.addIdentifier(primaryIdentifier); PatientIdentifier paperRecordIdentifier = new PatientIdentifier(); paperRecordIdentifier.setIdentifier("A00005"); paperRecordIdentifier.setIdentifierType(paperRecordIdentifierType); paperRecordIdentifier.setVoided(false); patient.addIdentifier(paperRecordIdentifier); PersonName name = new PersonName(); name.setGivenName("Ringo"); name.setFamilyName("Starr"); patient.addName(name); String output = wristbandTemplate.generateWristband(patient, new Location()); assertThat(output, containsString("^FO160,200^FB2150,1,0,L,0^AU^FD1940^FS")); }
@RequestMapping("/module/hirifxray/updateParticipant.form") public String updateParticipant( ModelMap model, @RequestParam(value = "patientId", required = true) Integer patientId, @RequestParam(value = "identifier", required = true) String identifier, @RequestParam(value = "gender", required = true) String gender) { Patient p = Context.getPatientService().getPatient(patientId); p.setGender(gender); PatientIdentifier pi = p.getPatientIdentifier(); pi.setIdentifier(identifier); p = Context.getPatientService().savePatient(p); return "redirect:/module/hirifxray/participant.form?id=" + p.getPatientId(); }
/** * Validates the given Patient. Currently just checks for errors in identifiers. TODO: Check for * errors in all Patient fields. * * @param obj The patient to validate. * @param errors Errors * @see org.springframework.validation.Validator#validate(java.lang.Object, * org.springframework.validation.Errors) * @should fail validation if gender is blank * @should fail validation if birthdate makes patient older that 120 years old * @should fail validation if birthdate is a future date * @should fail validation if a preferred patient identifier is not chosen * @should fail validation if voidReason is blank when patient is voided * @should fail validation if causeOfDeath is blank when patient is dead * @should fail validation if a preferred patient identifier is not chosen for voided patients * @should not fail when patient has only one identifier and its not preferred * @should pass validation if field lengths are correct * @should fail validation if field lengths are not correct */ public void validate(Object obj, Errors errors) { if (log.isDebugEnabled()) { log.debug(this.getClass().getName() + ".validate..."); } if (obj == null) { return; } super.validate(obj, errors); Patient patient = (Patient) obj; ValidationUtils.rejectIfEmptyOrWhitespace(errors, "gender", "Person.gender.required"); // Make sure they chose a preferred ID Boolean preferredIdentifierChosen = false; // Voided patients have only voided identifiers since they were voided with the patient, // so get all otherwise get the active ones Collection<PatientIdentifier> identifiers = patient.isVoided() ? patient.getIdentifiers() : patient.getActiveIdentifiers(); for (PatientIdentifier pi : identifiers) { if (pi.isPreferred()) { preferredIdentifierChosen = true; } } if (!preferredIdentifierChosen && identifiers.size() != 1) { errors.reject("error.preferredIdentifier"); } int index = 0; if (!errors.hasErrors()) { // Validate PatientIdentifers if (patient.getIdentifiers() != null) { for (PatientIdentifier identifier : patient.getIdentifiers()) { errors.pushNestedPath("identifiers[" + index + "]"); patientIdentifierValidator.validate(identifier, errors); errors.popNestedPath(); index++; } } } ValidateUtil.validateFieldLengths(errors, obj.getClass(), "voidReason"); }
private Patient getMrsPatient(org.openmrs.Patient savedPatient) { final List<Attribute> attributes = project( savedPatient.getAttributes(), Attribute.class, on(PersonAttribute.class).getAttributeType().toString(), on(PersonAttribute.class).getValue()); PersonName firstName = patientHelper.getFirstName(savedPatient); final PatientIdentifier patientIdentifier = savedPatient.getPatientIdentifier(); return new Patient( String.valueOf(savedPatient.getId()), firstName.getGivenName(), firstName.getMiddleName(), firstName.getFamilyName(), patientHelper.getPreferredName(savedPatient), savedPatient.getBirthdate(), savedPatient.getBirthdateEstimated(), savedPatient.getGender(), patientHelper.getAddress(savedPatient), attributes, (patientIdentifier != null) ? facilityAdaptor.convertLocationToFacility(patientIdentifier.getLocation()) : null); }
/** * Checks that the given {@link PatientIdentifier} is valid * * @param pi - the {@link PatientIdentifier} to validate * @throws PatientIdentifierException if the {@link PatientIdentifier} is invalid * @should fail validation if PatientIdentifier is null * @should pass validation if PatientIdentifier is voided * @should fail validation if another patient has a matching identifier of the same type * @should pass if in use and id type uniqueness is set to non unique * @see #validateIdentifier(String, PatientIdentifierType) */ public static void validateIdentifier(PatientIdentifier pi) throws PatientIdentifierException { // Validate that the identifier is non-null if (pi == null) { throw new BlankIdentifierException("PatientIdentifier.error.null"); } // Only validate if the PatientIdentifier is not voided if (!pi.isVoided()) { // Check that this is a valid identifier validateIdentifier(pi.getIdentifier(), pi.getIdentifierType()); // Check that location is included if it is required (default behavior is to require it) LocationBehavior lb = pi.getIdentifierType().getLocationBehavior(); if (pi.getLocation() == null && (lb == null || lb == LocationBehavior.REQUIRED)) { String identifierString = (pi.getIdentifier() != null) ? pi.getIdentifier() : ""; throw new PatientIdentifierException( Context.getMessageSourceService() .getMessage( "PatientIdentifier.location.null", new Object[] {identifierString}, Context.getLocale())); } if (pi.getIdentifierType().getUniquenessBehavior() != UniquenessBehavior.NON_UNIQUE && Context.getPatientService().isIdentifierInUseByAnotherPatient(pi)) { // Check is already in use by another patient throw new IdentifierNotUniqueException( Context.getMessageSourceService() .getMessage( "PatientIdentifier.error.notUniqueWithParameter", new Object[] {pi.getIdentifier()}, Context.getLocale()), pi); } } }
/** * Adds the column headers and column data to the DataSet * * @param dataSet * @param encounters * @param patientIdentifierTypes * @param optionalColumns * @param columnDisplayFormat * @param maxColumnHeaderWidth * @param allColumns * @param fieldMap * @return */ public DataSet addData( SimpleDataSet dataSet, List<Encounter> encounters, List<PatientIdentifierType> patientIdentifierTypes, List<EncounterAndObsDataSetDefinition.ObsOptionalColumn> optionalColumns, List<EncounterAndObsDataSetDefinition.ColumnDisplayFormat> columnDisplayFormat, Integer maxColumnHeaderWidth, Set<ObsColumnDescriptor> allColumns, Map<Encounter, Map<ObsColumnDescriptor, Obs>> fieldMap) { for (Encounter encounter : encounters) { DataSetRow row = new DataSetRow(); List<String> providerNames = new ArrayList<String>(); for (EncounterProvider ep : encounter.getEncounterProviders()) { providerNames.add(ep.getProvider().getName()); } // Add the standard columns for encounters DataSetColumn c1 = new DataSetColumn( ObjectUtil.trimStringIfNeeded("ENCOUNTER_ID", maxColumnHeaderWidth), ObjectUtil.trimStringIfNeeded("ENCOUNTER_ID", maxColumnHeaderWidth), Integer.class); row.addColumnValue(c1, encounter.getEncounterId()); DataSetColumn c2 = new DataSetColumn( ObjectUtil.trimStringIfNeeded("ENCOUNTER_DATETIME", maxColumnHeaderWidth), ObjectUtil.trimStringIfNeeded("ENCOUNTER_DATETIME", maxColumnHeaderWidth), String.class); row.addColumnValue(c2, encounter.getEncounterDatetime().toString()); DataSetColumn c3 = new DataSetColumn( ObjectUtil.trimStringIfNeeded("LOCATION", maxColumnHeaderWidth), ObjectUtil.trimStringIfNeeded("LOCATION", maxColumnHeaderWidth), String.class); row.addColumnValue( c3, (encounter.getLocation() != null) ? encounter.getLocation().getName() : EMPTY); DataSetColumn c4 = new DataSetColumn( ObjectUtil.trimStringIfNeeded("PROVIDER", maxColumnHeaderWidth), ObjectUtil.trimStringIfNeeded("PROVIDER", maxColumnHeaderWidth), String.class); row.addColumnValue(c4, OpenmrsUtil.join(providerNames, ", ")); DataSetColumn c5 = new DataSetColumn( ObjectUtil.trimStringIfNeeded("INTERNAL_PATIENT_ID", maxColumnHeaderWidth), ObjectUtil.trimStringIfNeeded("INTERNAL_PATIENT_ID", maxColumnHeaderWidth), Integer.class); row.addColumnValue( c5, encounter.getPatient() != null ? encounter.getPatient().getPatientId() : EMPTY); if (patientIdentifierTypes != null) { for (PatientIdentifierType pit : patientIdentifierTypes) { List<PatientIdentifier> patientIdentifiers = encounter.getPatient().getPatientIdentifiers(pit); StringBuffer sbPatientIdentifiers = new StringBuffer(); int count = 0; for (PatientIdentifier patientIdentifier : patientIdentifiers) { if (count > 0) { sbPatientIdentifiers.append(", "); } sbPatientIdentifiers.append(patientIdentifier.toString()); count++; } DataSetColumn c6 = new DataSetColumn( pit.getName(), ObjectUtil.trimStringIfNeeded(pit.getName(), maxColumnHeaderWidth), String.class); row.addColumnValue(c6, sbPatientIdentifiers.toString()); } } Map<ObsColumnDescriptor, Obs> obsInEncounter = fieldMap.get(encounter); // Look up all obs for a given encounter based on column headers for all encounters for (ObsColumnDescriptor columnKey : allColumns) { Obs obs = obsInEncounter.get(columnKey); String columnName = columnKey.format(columnDisplayFormat, maxColumnHeaderWidth); DataSetColumn obsDsc = new DataSetColumn(columnName, columnName, String.class); StringBuffer columnValue = new StringBuffer(); if (obs != null && obs.getValueCoded() != null) { if (columnDisplayFormat.contains( EncounterAndObsDataSetDefinition.ColumnDisplayFormat.ID)) { columnValue.append(obs.getValueCoded()); } if (columnDisplayFormat.contains(EncounterAndObsDataSetDefinition.ColumnDisplayFormat.ID) && columnDisplayFormat.contains( EncounterAndObsDataSetDefinition.ColumnDisplayFormat.BEST_SHORT_NAME)) { columnValue.append("_"); } if (columnDisplayFormat.contains( EncounterAndObsDataSetDefinition.ColumnDisplayFormat.BEST_SHORT_NAME)) { String conceptName = obs.getValueAsString(Context.getLocale()); columnValue.append( maxColumnHeaderWidth != null && conceptName.length() > maxColumnHeaderWidth - columnValue.length() ? conceptName.substring(0, maxColumnHeaderWidth - columnValue.length() - 1) : conceptName); } row.addColumnValue(obsDsc, (obs != null) ? columnValue.toString() : EMPTY); } else { row.addColumnValue( obsDsc, (obs != null) ? obs.getValueAsString(Context.getLocale()) : EMPTY); } String dateColumnName = columnKey.format( columnDisplayFormat, maxColumnHeaderWidth != null ? maxColumnHeaderWidth - 5 : null); DataSetColumn obsDscDate = new DataSetColumn(dateColumnName + "_DATE", dateColumnName + "_DATE", String.class); row.addColumnValue(obsDscDate, (obs != null) ? obs.getObsDatetime().toString() : EMPTY); String parentColumnName = columnKey.format( columnDisplayFormat, maxColumnHeaderWidth != null ? maxColumnHeaderWidth - 7 : null); DataSetColumn obsDscParent = new DataSetColumn( parentColumnName + "_PARENT", parentColumnName + "_PARENT", String.class); row.addColumnValue( obsDscParent, (obs != null && obs.getObsGroup() != null) ? obs.getObsGroup().getId() : EMPTY); if (optionalColumns != null) { if (optionalColumns.contains( EncounterAndObsDataSetDefinition.ObsOptionalColumn.VALUE_MODIFIER)) { String valModColumnName = columnKey.format( columnDisplayFormat, maxColumnHeaderWidth != null ? maxColumnHeaderWidth - 10 : null); DataSetColumn obsDscValueModifier = new DataSetColumn( valModColumnName + "_VALUE_MOD", valModColumnName + "_VALUE_MOD", String.class); row.addColumnValue(obsDscValueModifier, (obs != null) ? obs.getValueModifier() : EMPTY); } if (optionalColumns.contains( EncounterAndObsDataSetDefinition.ObsOptionalColumn.ACCESSION_NUMBER)) { String accessionNumColumnName = columnKey.format( columnDisplayFormat, maxColumnHeaderWidth != null ? maxColumnHeaderWidth - 14 : null); DataSetColumn obsDscAccessionNumber = new DataSetColumn( accessionNumColumnName + "_ACCESSION_NUM", accessionNumColumnName + "_ACCESSION_NUM", String.class); row.addColumnValue( obsDscAccessionNumber, (obs != null) ? obs.getAccessionNumber() : EMPTY); } if (optionalColumns.contains( EncounterAndObsDataSetDefinition.ObsOptionalColumn.COMMENT)) { String commentColumnName = columnKey.format( columnDisplayFormat, maxColumnHeaderWidth != null ? maxColumnHeaderWidth - 8 : null); DataSetColumn obsDscComment = new DataSetColumn( commentColumnName + "_COMMENT", commentColumnName + "_COMMENT", String.class); row.addColumnValue(obsDscComment, (obs != null) ? obs.getComment() : EMPTY); } } } dataSet.addRow(row); } return dataSet; }
/** * Validates the given Patient. * * @param obj The patient to validate. * @param errors The patient to validate. * @see org.springframework.validation.Validator#validate(java.lang.Object, * org.springframework.validation.Errors) * @should pass if the minimum required fields are provided and are valid * @should fail validation if gender is blank * @should fail validation if birthdate is blank * @should fail validation if birthdate makes patient 120 years old or older * @should fail validation if birthdate is a future date * @should fail validation if causeOfDeath is blank when patient is dead * @should fail if all name fields are empty or white space characters * @should fail if no identifiers are added * @should fail if all identifiers have been voided * @should fail if any name has more than 50 characters * @should fail validation if deathdate is a future date * @should fail if the deathdate is before the birthdate incase the patient is dead * @should reject a duplicate name * @should reject a duplicate address */ public void validate(Object obj, Errors errors) { if (log.isDebugEnabled()) { log.debug( this.getClass().getName() + ": Validating patient data from the short patient form...."); } ShortPatientModel shortPatientModel = (ShortPatientModel) obj; PersonName personName = shortPatientModel.getPersonName(); // TODO We should be able to let developers and implementations to specify which person name // fields should be used to determine uniqueness // check if this name has a unique givenName, middleName and familyName combination for (PersonName possibleDuplicate : shortPatientModel.getPatient().getNames()) { // don't compare the name to itself if (OpenmrsUtil.nullSafeEquals(possibleDuplicate.getId(), personName.getId())) { continue; } if (OpenmrsUtil.nullSafeEqualsIgnoreCase( possibleDuplicate.getGivenName(), personName.getGivenName()) && OpenmrsUtil.nullSafeEqualsIgnoreCase( possibleDuplicate.getMiddleName(), personName.getMiddleName()) && OpenmrsUtil.nullSafeEqualsIgnoreCase( possibleDuplicate.getFamilyName(), personName.getFamilyName())) { errors.reject( "Patient.duplicateName", new Object[] {personName.getFullName()}, personName.getFullName() + " is a duplicate name for the same patient"); } } Errors nameErrors = new BindException(personName, "personName"); new PersonNameValidator().validatePersonName(personName, nameErrors, false, true); if (nameErrors.hasErrors()) { // pick all the personName errors and bind them to the formObject Iterator<ObjectError> it = nameErrors.getAllErrors().iterator(); Set<String> errorCodesWithNoArguments = new HashSet<String>(); while (it.hasNext()) { ObjectError error = it.next(); // don't show similar error message multiple times in the view // unless they take in arguments which will make them atleast different if (error.getCode() != null && (!errorCodesWithNoArguments.contains(error.getCode()) || (error.getArguments() != null && error.getArguments().length > 0))) { errors.reject(error.getCode(), error.getArguments(), ""); if (error.getArguments() == null || error.getArguments().length == 0) { errorCodesWithNoArguments.add(error.getCode()); } } } // drop the collection errorCodesWithNoArguments = null; } // TODO We should be able to let developers and implementations to specify which // person address fields should be used to determine uniqueness // check if this address is unique PersonAddress personAddress = shortPatientModel.getPersonAddress(); for (PersonAddress possibleDuplicate : shortPatientModel.getPatient().getAddresses()) { // don't compare the address to itself if (OpenmrsUtil.nullSafeEquals(possibleDuplicate.getId(), personAddress.getId())) { continue; } if (!possibleDuplicate.isBlank() && !personAddress.isBlank() && possibleDuplicate.toString().equalsIgnoreCase(personAddress.toString())) { errors.reject( "Patient.duplicateAddress", new Object[] {personAddress.toString()}, personAddress.toString() + " is a duplicate address for the same patient"); } } if (CollectionUtils.isEmpty(shortPatientModel.getIdentifiers())) { errors.reject("PatientIdentifier.error.insufficientIdentifiers"); } else { boolean nonVoidedIdentifierFound = false; for (PatientIdentifier pId : shortPatientModel.getIdentifiers()) { // no need to validate unsaved identifiers that have been removed if (pId.getPatientIdentifierId() == null && pId.isVoided()) { continue; } if (!pId.isVoided()) { nonVoidedIdentifierFound = true; } new PatientIdentifierValidator().validate(pId, errors); } // if all the names are voided if (!nonVoidedIdentifierFound) { errors.reject("PatientIdentifier.error.insufficientIdentifiers"); } } // Make sure they chose a gender if (StringUtils.isBlank(shortPatientModel.getPatient().getGender())) { errors.rejectValue("patient.gender", "Person.gender.required"); } // check patients birthdate against future dates and really old dates if (shortPatientModel.getPatient().getBirthdate() != null) { if (shortPatientModel.getPatient().getBirthdate().after(new Date())) { errors.rejectValue("patient.birthdate", "error.date.future"); } else { Calendar c = Calendar.getInstance(); c.setTime(new Date()); c.add(Calendar.YEAR, -120); // patient cannot be older than 120 // years old if (shortPatientModel.getPatient().getBirthdate().before(c.getTime())) { errors.rejectValue("patient.birthdate", "error.date.nonsensical"); } } } else { errors.rejectValue( "patient.birthdate", "error.required", new Object[] {Context.getMessageSourceService().getMessage("Person.birthdate")}, ""); } // validate the personAddress if (shortPatientModel.getPersonAddress() != null) { try { errors.pushNestedPath("personAddress"); ValidationUtils.invokeValidator( new PersonAddressValidator(), shortPatientModel.getPersonAddress(), errors); } finally { errors.popNestedPath(); } } if (shortPatientModel.getPatient().getDead()) { if (shortPatientModel.getPatient().getCauseOfDeath() == null) { errors.rejectValue("patient.causeOfDeath", "Person.dead.causeOfDeathNull"); } if (shortPatientModel.getPatient().getDeathDate() != null) { if (shortPatientModel.getPatient().getDeathDate().after(new Date())) { errors.rejectValue("patient.deathDate", "error.date.future"); } // death date has to be after birthdate if both are specified if (shortPatientModel.getPatient().getBirthdate() != null && shortPatientModel .getPatient() .getDeathDate() .before(shortPatientModel.getPatient().getBirthdate())) { errors.rejectValue("patient.deathDate", "error.deathdate.before.birthdate"); } } } }
@Test public void testWristBandTemplate() { Date today = new Date(); visitLocation.setName("Hôpital Universitaire de Mirebalais"); Patient patient = new Patient(); patient.setGender("M"); patient.setBirthdate(new DateTime(1940, 7, 7, 5, 5, 5).toDate()); PatientIdentifier primaryIdentifier = new PatientIdentifier(); primaryIdentifier.setIdentifier("ZL1234"); primaryIdentifier.setIdentifierType(primaryIdentifierType); primaryIdentifier.setVoided(false); patient.addIdentifier(primaryIdentifier); PatientIdentifier paperRecordIdentifier = new PatientIdentifier(); paperRecordIdentifier.setIdentifier("A000005"); paperRecordIdentifier.setIdentifierType(paperRecordIdentifierType); paperRecordIdentifier.setVoided(false); paperRecordIdentifier.setLocation(visitLocation); patient.addIdentifier(paperRecordIdentifier); PersonAddress address = new PersonAddress(); address.setAddress2("Avant Eglise Chretienne des perlerlerin de la siant tete de moliere"); address.setAddress1("Saut D'Eau"); address.setAddress3("1ere Riviere Canot"); address.setCityVillage("Saut d'Eau"); address.setStateProvince("Centre"); patient.addAddress(address); PersonName name = new PersonName(); name.setGivenName("Ringo"); name.setFamilyName("Starr"); patient.addName(name); when(messageSourceService.getMessage( "coreapps.ageYears", Collections.singletonList(patient.getAge()).toArray(), locale)) .thenReturn("75 an(s)"); String output = wristbandTemplate.generateWristband(patient, visitLocation); assertThat(output, containsString("^XA^CI28^MTD^FWB")); assertThat( output, containsString( "^FO050,200^FB2150,1,0,L,0^AS^FDHôpital Universitaire de Mirebalais " + df.format(today) + "^FS")); assertThat(output, containsString("^FO100,200^FB2150,1,0,L,0^AU^FDRingo Starr^FS")); assertThat(output, containsString("^FO160,200^FB2150,1,0,L,0^AU^FD07 juil. 1940^FS")); assertThat( output, containsString("^FO160,200^FB1850,1,0,L,0^AT^FD" + patient.getAge() + " an(s)^FS")); assertThat(output, containsString("^FO160,200^FB1650,1,0,L,0^AU^FDMasculin A 000005^FS")); assertThat( output, containsString( "^FO220,200^FB2150,1,0,L,0^AS^FDAvant Eglise Chretienne des perlerlerin de la siant tete de moliere^FS")); assertThat( output, containsString( "^FO270,200^FB2150,1,0,L,0^AS^FDSaut D'Eau, 1ere Riviere Canot, Saut d'Eau, Centre^FS")); assertThat(output, containsString("^FO100,2400^AT^BY4^BC,150,N^FDZL1234^XZ")); }