Skip to content

#13589 - Adds person phone and email update to external message processing flow#13834

Merged
raulbob merged 1 commit intodevelopmentfrom
bugfix-13589-external_message_update_person_phone_email
Feb 17, 2026
Merged

#13589 - Adds person phone and email update to external message processing flow#13834
raulbob merged 1 commit intodevelopmentfrom
bugfix-13589-external_message_update_person_phone_email

Conversation

@raulbob
Copy link
Copy Markdown
Contributor

@raulbob raulbob commented Feb 17, 2026

Fixes #13589

  • new phone number and e-mail are added as primary contacts (the old ones are kept)
  • if the new phone number/e-mail exist they will be made primary

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced contact information handling during message processing to properly manage phone numbers and email addresses with correct primary designations.

…ssing flow

- Additionally to the existing address update, the phone and email are now updated as well.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 17, 2026

📝 Walkthrough

Walkthrough

The change enhances person data processing in external messages by adding automatic updates for phone numbers and email addresses alongside existing address updates. A doUpdate flag tracks whether changes occurred, and contact details are created or promoted to primary as needed before persisting changes.

Changes

Cohort / File(s) Summary
Person Contact Details Enhancement
sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/AbstractMessageProcessingFlowBase.java
Added imports for PersonContactDetailDto, PersonContactDetailType, and PhoneNumberType. Fixed JavaDoc formatting. Enhanced doPersonUpdates method with doUpdate flag to track changes. Implemented phone number handling to identify existing primary/telephone entries, adjust primary flags, or create new entries. Implemented email handling with similar logic for primary identification and creation. Updated method to persist Person changes via updatePerson when modifications occur.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • obinna-h-n
  • KarnaiahPesula

Poem

🐰✨ A rabbit hops through contact details with care,
Phone numbers and emails floating in air,
Primary flags wave and adjust just right,
External messages processed with delight,
Person data updates, fresh and bright! 📬

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR addresses phone/email updates but does not fully implement the core requirement from #13589 to update person's address during external message processing. Verify that address update functionality is implemented in this PR or reference another PR where address updates were completed as per issue #13589.
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive Phone and email updates exceed the scope of issue #13589, which specifically requires address updates; unclear if this expansion was intentional or necessary. Clarify in PR comments why phone and email functionality was added beyond the original address update requirement in issue #13589.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding phone and email updates to the external message processing flow.
Description check ✅ Passed The description includes the issue reference (#13589) and clearly explains the phone and email handling behavior.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bugfix-13589-external_message_update_person_phone_email

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (4)
sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/AbstractMessageProcessingFlowBase.java (4)

1123-1137: Duplicate setPrimaryContact(true) call and ordering issue when creating a new phone

Line 1125 and Line 1127 both call setPrimaryContact(true) — the second is redundant. More importantly, the old primary is demoted after the new entry is added to the list (Line 1131 vs Line 1134). While functionally this still works because the objects are independent, demoting the old primary before adding the new one would be clearer and consistent with the existingPhone != null branch above.

Proposed cleanup
             } else {
                 // we do not have the new phone number in the list so we need to create a new one
+                // demote old primary first
+                if (primaryPhone != null) {
+                    primaryPhone.setPrimaryContact(false);
+                }
                 final PersonContactDetailDto personContactDetail = new PersonContactDetailDto();
                 personContactDetail.setPerson(person.toReference());
                 personContactDetail.setPrimaryContact(true);
                 personContactDetail.setPersonContactDetailType(PersonContactDetailType.PHONE);
-                personContactDetail.setPrimaryContact(true);
                 personContactDetail.setPhoneNumberType(phoneNumberType);
                 personContactDetail.setContactInformation(phoneNumber);
                 personContactDetail.setThirdParty(false);
                 personContactDetails.add(personContactDetail);
-
-                // we need to set the old primary to false
-                if(primaryPhone != null) {
-                    primaryPhone.setPrimaryContact(false);
-                }
             }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/AbstractMessageProcessingFlowBase.java`
around lines 1123 - 1137, Remove the duplicate
personContactDetail.setPrimaryContact(true) call and move the demotion of the
previous primary before adding the new phone to the list: in
AbstractMessageProcessingFlowBase where personContactDetail is created, call
setPrimaryContact(true) only once on the new PersonContactDetailDto, ensure
primaryPhone.setPrimaryContact(false) is executed before
personContactDetails.add(personContactDetail), and keep behavior consistent with
the existingPhone != null branch so the old primary is demoted prior to adding
the new entry.

1097-1181: Phone and email update blocks are near-identical — extract a helper

The phone block (Lines 1102–1140) and email block (Lines 1144–1181) share the same structure: find existing primary, find matching entry, promote or create. The only differences are the PersonContactDetailType, the contact information value, and the optional phoneNumberType. Extracting a common method (e.g., upsertPrimaryContactDetail(...)) would eliminate ~40 lines of duplication and make this easier to maintain.

Sketch of extracted helper
private boolean upsertPrimaryContactDetail(
    PersonDto person,
    List<PersonContactDetailDto> contactDetails,
    PersonContactDetailType type,
    String contactInfo,
    PhoneNumberType phoneNumberType) {

    if (contactInfo == null || contactInfo.isBlank()) {
        return false;
    }

    PersonContactDetailDto primary = contactDetails.stream()
        .filter(cd -> cd.getPersonContactDetailType() == type && !cd.isThirdParty() && cd.isPrimaryContact())
        .findFirst().orElse(null);

    PersonContactDetailDto existing = contactDetails.stream()
        .filter(cd -> cd.getPersonContactDetailType() == type && !cd.isThirdParty() && contactInfo.equals(cd.getContactInformation()))
        .findFirst().orElse(null);

    if (existing != null) {
        if (primary != null) {
            primary.setPrimaryContact(false);
        }
        existing.setPrimaryContact(true);
    } else {
        if (primary != null) {
            primary.setPrimaryContact(false);
        }
        PersonContactDetailDto newDetail = new PersonContactDetailDto();
        newDetail.setPerson(person.toReference());
        newDetail.setPrimaryContact(true);
        newDetail.setPersonContactDetailType(type);
        newDetail.setPhoneNumberType(phoneNumberType);
        newDetail.setContactInformation(contactInfo);
        newDetail.setThirdParty(false);
        contactDetails.add(newDetail);
    }
    return true;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/AbstractMessageProcessingFlowBase.java`
around lines 1097 - 1181, The phone and email handling in
AbstractMessageProcessingFlowBase are duplicated; implement a helper method
upsertPrimaryContactDetail(PersonDto person, List<PersonContactDetailDto>
contactDetails, PersonContactDetailType type, String contactInfo,
PhoneNumberType phoneNumberType) that encapsulates the shared logic (skip if
null/blank, find primary and existing via
getPersonContactDetailType/isThirdParty/isPrimaryContact and contactInformation,
promote existing or create new PersonContactDetailDto, ensure old primary is
unset, set phoneNumberType only when provided) and returns a boolean indicating
whether an update was made; then replace both inline blocks to call this helper
(pass PhoneNumberType for phone and null for email) and set doUpdate |=
upsertPrimaryContactDetail(...).

1092-1095: doUpdate set unconditionally when personAddress is non-null

doUpdate is set to true even when every address field from the external message is null (i.e., nothing actually changed). This causes a needless updatePerson call. Consider tracking whether at least one field was actually written.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/AbstractMessageProcessingFlowBase.java`
around lines 1092 - 1095, The code currently sets doUpdate = true whenever
personAddress is non-null, causing updatePerson to be called even if no address
fields were actually modified; change the logic in
AbstractMessageProcessingFlowBase so that you track whether at least one field
was written (e.g., introduce a boolean flag like addressFieldsChanged) while
assigning to personAddress fields and only set doUpdate = true if that flag is
true (or if other change flags indicate modifications); ensure this check is
performed before calling updatePerson and reference the doUpdate variable,
personAddress assignments, and the updatePerson invocation when making the
change.

1163-1178: Same duplicate setPrimaryContact(true) and ordering issue in the email branch

Lines 1167 and 1169 duplicate setPrimaryContact(true). Same cleanup as the phone branch applies here.

Proposed cleanup
             } else {
+                if (primaryEmail != null) {
+                    primaryEmail.setPrimaryContact(false);
+                }
                 final PersonContactDetailDto personContactDetail = new PersonContactDetailDto();
                 personContactDetail.setPerson(person.toReference());
                 personContactDetail.setPrimaryContact(true);
                 personContactDetail.setPersonContactDetailType(PersonContactDetailType.EMAIL);
-                personContactDetail.setPrimaryContact(true);
                 personContactDetail.setContactInformation(emailAddress);
                 personContactDetail.setThirdParty(false);
                 personContactDetails.add(personContactDetail);
-
-                if(primaryEmail != null) {
-                    primaryEmail.setPrimaryContact(false);
-                }
             }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/AbstractMessageProcessingFlowBase.java`
around lines 1163 - 1178, Remove the duplicate
personContactDetail.setPrimaryContact(true) call and ensure primaryEmail is
demoted before marking the new contact as primary: in the email branch involving
PersonContactDetailDto, call primaryEmail.setPrimaryContact(false) (if
primaryEmail != null) before setting personContactDetail.setPrimaryContact(true)
and adding personContactDetail to personContactDetails, and only call
setPrimaryContact(true) once.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/AbstractMessageProcessingFlowBase.java`:
- Around line 1123-1137: Remove the duplicate
personContactDetail.setPrimaryContact(true) call and move the demotion of the
previous primary before adding the new phone to the list: in
AbstractMessageProcessingFlowBase where personContactDetail is created, call
setPrimaryContact(true) only once on the new PersonContactDetailDto, ensure
primaryPhone.setPrimaryContact(false) is executed before
personContactDetails.add(personContactDetail), and keep behavior consistent with
the existingPhone != null branch so the old primary is demoted prior to adding
the new entry.
- Around line 1097-1181: The phone and email handling in
AbstractMessageProcessingFlowBase are duplicated; implement a helper method
upsertPrimaryContactDetail(PersonDto person, List<PersonContactDetailDto>
contactDetails, PersonContactDetailType type, String contactInfo,
PhoneNumberType phoneNumberType) that encapsulates the shared logic (skip if
null/blank, find primary and existing via
getPersonContactDetailType/isThirdParty/isPrimaryContact and contactInformation,
promote existing or create new PersonContactDetailDto, ensure old primary is
unset, set phoneNumberType only when provided) and returns a boolean indicating
whether an update was made; then replace both inline blocks to call this helper
(pass PhoneNumberType for phone and null for email) and set doUpdate |=
upsertPrimaryContactDetail(...).
- Around line 1092-1095: The code currently sets doUpdate = true whenever
personAddress is non-null, causing updatePerson to be called even if no address
fields were actually modified; change the logic in
AbstractMessageProcessingFlowBase so that you track whether at least one field
was written (e.g., introduce a boolean flag like addressFieldsChanged) while
assigning to personAddress fields and only set doUpdate = true if that flag is
true (or if other change flags indicate modifications); ensure this check is
performed before calling updatePerson and reference the doUpdate variable,
personAddress assignments, and the updatePerson invocation when making the
change.
- Around line 1163-1178: Remove the duplicate
personContactDetail.setPrimaryContact(true) call and ensure primaryEmail is
demoted before marking the new contact as primary: in the email branch involving
PersonContactDetailDto, call primaryEmail.setPrimaryContact(false) (if
primaryEmail != null) before setting personContactDetail.setPrimaryContact(true)
and adding personContactDetail to personContactDetails, and only call
setPrimaryContact(true) once.

@sormas-vitagroup
Copy link
Copy Markdown
Contributor

@raulbob raulbob merged commit bde5f20 into development Feb 17, 2026
7 of 13 checks passed
@raulbob raulbob deleted the bugfix-13589-external_message_update_person_phone_email branch February 17, 2026 18:43
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.

Update Person's Address when processing External Messages

3 participants