Skip to content

Conversation

@Binayak490-cyber
Copy link

This PR enhances PatientValidator to ensure that a patient must have identifiers for all required and non-retired PatientIdentifierTypes before validation passes.

Changes included:

Added validation logic to check that every required, non-retired identifier type has a corresponding non-voided patient identifier.

Updated and added unit tests to cover the following scenarios:

Patient missing a required identifier (validation fails)

Patient with required identifier present (validation passes)

Required identifier is voided (validation fails)

Required identifier type is retired (validation ignored)

This change ensures data consistency and aligns patient validation with the configured identifier requirements.All tests pass locally.

@Binayak490-cyber
Copy link
Author

Hi @ibacher,

This PR addresses TRUNK-6529 by ensuring that a patient must have identifiers for all required, non-retired PatientIdentifierTypes before validation passes.

I’ve added validation logic and updated unit tests to cover missing, present, voided, and retired required identifiers.

All tests pass locally (mvn clean test).

Please review when convenient.Thanks!

@Binayak490-cyber
Copy link
Author

Hi @ibacher,
Just a gentle reminder regarding this PR for TRUNK-6529: Ensure patient has all required identifiers.
The fix ensures validation for required patient identifiers and all tests are passing.
Please let me know if any changes or improvements are needed from my side.

@kmvipin
Copy link
Contributor

kmvipin commented Feb 4, 2026

@Binayak490-cyber, kindly mention the ticket which is related to this PR!

@Binayak490-cyber
Copy link
Author

@Binayak490-cyber, can you please mention the ticket which is related to this PR!

@kmvipin, it is the issue ticket TRUNK-6529 i.e; https://openmrs.atlassian.net/browse/TRUNK-6529?focusedCommentId=184800

@Binayak490-cyber
Copy link
Author

Hi @ibacher,
Quick follow-up on TRUNK-6529.
This PR introduces a new method along with tests that validate ensuring patients have all required identifiers.
Would appreciate a review.
Thanks!

Copy link
Member

@ibacher ibacher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This needs some work. Also, instead of the O(n^2) algorithm you might be able to do something clever with sets to just get the difference between the "set of required identifiers" and the "set of identifiers the patient has", but it's not a big deal as the set of identifiers is normally very small.

Collection<PatientIdentifierType> identifierTypes = Context.getPatientService().getAllPatientIdentifierTypes(false);

for (PatientIdentifierType type : identifierTypes) {
if (Boolean.TRUE.equals(type.getRequired()) && !type.getRetired()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already know that these types are not retired, so the check here is redundant.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okk @ibacher, I removed the !type.getRetired() check as getAllPatientIdentifierTypes(false) already guarantees that only non-retired types are returned, making the additional check redundant and misleading.

if (!found) {
errors.rejectValue(
"identifiers",
"Patient.missingRequiredIdentifier",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to actually add this string to the message.properties file.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ibacher, I’ve added Patient.missingRequiredIdentifier to messages.properties and pushed the update.

errors.rejectValue(
"identifiers",
"Patient.missingRequiredIdentifier",
"Missing required patient identifier: " + type.getName()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please lookup how you add parameters to a Spring errors object. Setting the default string isn't the right thing to do.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ibacher, I have updated to use Spring Errors.rejectValue with message parameters and added the message to messages.properties.
Removed the default message as suggested.


for (PatientIdentifierType type : identifierTypes) {
if (Boolean.TRUE.equals(type.getRequired()) && !type.getRetired()) {
boolean found = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't a case where we want to fail-fast. Instead we want to collect all missing required identifiers and send that back to the user as a single string.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okk @ibacher, for not getting fail-fast, i have updated the validator to collect all missing required identifier types and report them back as a single validation error.
The error now uses Spring’s Errors.rejectValue with parameters.

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.Assert.*;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not permit * imports.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ibacher, yepp i mistakenly added the full imported package which is not at all required for my added tests also and therefore, i have removed it.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 6, 2026

@Binayak490-cyber
Copy link
Author

Hi @ibacher,
Any further changes required in this PR.
Waiting for further review!

@Binayak490-cyber
Copy link
Author

Hi @ibacher,
Any update for this PR...!

@Binayak490-cyber
Copy link
Author

Hi @ibacher,
Any update for this year...!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants