Skip to content

Conversation

@raulbob
Copy link
Contributor

@raulbob raulbob commented Jan 20, 2026

Fixes #13717

  • Added additional handling for missing person fields

Summary by CodeRabbit

  • New Features

    • External messages now capture and store person occupation.
    • Doctor declaration flow enriched to populate guardian name, guardian contact details, and occupation fields during processing.
  • System Updates

    • Database schema extended to include occupation in external messages.
    • Access control for infrastructure facade expanded to include additional system-level right.
    • Validation message key for email sender updated.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 20, 2026

📝 Walkthrough

Walkthrough

Adds support for a personOccupation field across API DTO, backend entity, DB schema, and processing flow; updates country facade access rights and augments doctor-declaration processing to map occupation, guardian, and third-party contact details during case creation.

Changes

Cohort / File(s) Summary
API DTO
sormas-api/.../externalmessage/ExternalMessageDto.java
Adds PERSON_OCCUPATION constant, personOccupation field with @Size, getter and setter.
Backend Entity
sormas-backend/.../externalmessage/ExternalMessage.java
Adds PERSON_OCCUPATION constant, personOccupation field, getter annotated with @Column(length = CHARACTER_LIMIT_DEFAULT), and setter.
Facade / Processing
sormas-api/.../externalmessage/processing/ExternalMessageProcessingFacade.java, sormas-backend/.../ExternalMessageFacadeEjb.java
Adds getOccupationTypeOther() to retrieve OCCUPATION_TYPE "OTHER"; maps personOccupation between DTO and entity both ways.
UI Processing Flow
sormas-ui/.../doctordeclaration/DoctorDeclarationMessageProcessingFlow.java
Adds post-update callback to set guardian name, add guardian email/phone as third-party contacts, and set occupation type/details (uses getOccupationTypeOther()); integrates with existing notifier flow.
Schema / Migrations
sormas-backend/.../sql/sormas_schema.sql
Adds externalmessage.personoccupation and externalmessage_history.personoccupation VARCHAR(255); adds schema versions 602 and 603; updates an email sender validation i18n key.
Access Control
sormas-backend/.../infrastructure/country/CountryFacadeEjb.java
Expands @RightsAllowed from UserRight._INFRASTRUCTURE_VIEW to { UserRight._INFRASTRUCTURE_VIEW, UserRight._SYSTEM }.

Sequence Diagram(s)

sequenceDiagram
    actor Sender
    participant UI as DoctorDeclarationFlow
    participant FACADE as ExternalMessageProcessingFacade
    participant ENUM as CustomizableEnumFacade
    participant PERSON as PersonService
    participant DB as Database

    Sender->>UI: Submit doctor declaration (includes occupation, guardian, contacts)
    UI->>FACADE: Process external message
    FACADE->>ENUM: lookup OCCUPATION_TYPE "OTHER" (getOccupationTypeOther)
    ENUM-->>FACADE: OccupationType ("OTHER")
    FACADE->>PERSON: Create/Update Person (set occupation, guardian name, add contact details)
    PERSON->>DB: Persist person and contact details
    DB-->>PERSON: Persisted
    PERSON-->>FACADE: Person updated
    FACADE->>DB: Create/Update Case referencing updated person
    DB-->>FACADE: Case created/updated
    FACADE-->>UI: Processing complete
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • obinna-h-n
  • KarnaiahPesula

Poem

A rabbit hops through messages at night,
Nosing out occupations, setting them right,
Guardians, contacts, stitched into place,
Hopping bytes and fields with gentle grace,
Case and person now aligned—what a sight! 🐇

🚥 Pre-merge checks | ✅ 2 | ❌ 3
❌ Failed checks (3 warnings)
Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR adds personOccupation field handling and post-update processing logic for occupation data, but does not address all reported missing fields (country/address, tutor, hospitalization dates, symptoms, diagnosis date). Verify whether the PR scope intentionally covers only occupation fields or if other missing fields require implementation. Update PR description to clarify scope or expand implementation to address all reported missing fields.
Out of Scope Changes check ⚠️ Warning The CountryFacadeEjb access control annotation change from _INFRASTRUCTURE_VIEW to include _SYSTEM rights appears unrelated to person field handling or external message processing. Remove the CountryFacadeEjb annotation change or clarify its relationship to issue #13717 if intentional. Ensure all changes directly support the stated objective of adding missing person fields.
Docstring Coverage ⚠️ Warning Docstring coverage is 5.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding missing person fields (specifically personOccupation) to handle external message processing.
Description check ✅ Passed The description references issue #13717 and explains that additional handling for missing person fields was added, though it lacks specific details about which fields were addressed.

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

✨ Finishing touches
  • 📝 Generate docstrings

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

@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.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In
`@sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/ExternalMessageProcessingFacade.java`:
- Around line 245-247: Replace the non-throwing call in getOccupationTypeOther()
that uses
customizableEnumFacade.getEnumValue(CustomizableEnumType.OCCUPATION_TYPE, null,
"OTHER") with the throwing variant used elsewhere (see how getDiseaseVariant
calls the facade) so that a missing "OTHER" occupation constant triggers
CustomEnumNotFoundException instead of returning null; update
getOccupationTypeOther() to call the same throwing signature on
customizableEnumFacade for OCCUPATION_TYPE/"OTHER".

In
`@sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/doctordeclaration/DoctorDeclarationMessageProcessingFlow.java`:
- Around line 385-419: Replace the null-unsafe contains() checks in
DoctorDeclarationMessageProcessingFlow with exact, null-safe equality checks:
for the email block use
externalMessage.getPersonGuardianEmail().equals(pc.getContactInformation())
inside the stream noneMatch (since externalMessage.getPersonGuardianEmail() is
already checked non-null/non-blank), and do the same for the phone block using
externalMessage.getPersonGuardianPhone().equals(pc.getContactInformation());
this prevents partial matches and avoids NPE when
PersonContactDetailDto.getContactInformation() is null.
- Around line 366-368: The code fetches PersonDto casePerson via
getExternalMessageProcessingFacade().getPersonByContext(PersonContext.CASE,
result.getUuid()) but only checks for null later, which risks NPE because
casePerson is used between lines 369–426; immediately after calling
getPersonByContext move the null check for casePerson (and early-return or
handle accordingly) so no subsequent code that references casePerson runs when
it's null, and then remove the delayed null check further down; keep doUpdate
handling and any subsequent logic intact.
🧹 Nitpick comments (1)
sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/doctordeclaration/DoctorDeclarationMessageProcessingFlow.java (1)

385-419: Consider extracting contact detail creation into a helper method.

The logic for adding guardian email (lines 385-401) and phone (lines 403-419) contact details is nearly identical. Extracting this into a helper method would reduce duplication and improve maintainability.

♻️ Example helper method
private boolean addGuardianContactDetailIfAbsent(
    PersonDto casePerson,
    String contactInfo,
    PersonContactDetailType type,
    String guardianName,
    String guardianRelationship) {
    
    if (contactInfo == null || contactInfo.isBlank()) {
        return false;
    }
    
    List<PersonContactDetailDto> contactDetails = casePerson.getPersonContactDetails();
    if (contactDetails.stream().noneMatch(pc -> contactInfo.equals(pc.getContactInformation()))) {
        PersonContactDetailDto pcd = new PersonContactDetailDto();
        pcd.setPerson(casePerson.toReference());
        pcd.setPrimaryContact(false);
        pcd.setPersonContactDetailType(type);
        pcd.setContactInformation(contactInfo);
        pcd.setThirdParty(true);
        pcd.setThirdPartyRole(guardianRelationship);
        pcd.setThirdPartyName(guardianName);
        contactDetails.add(pcd);
        return true;
    }
    return false;
}

@sormas-vitagroup
Copy link
Contributor

@sormas-vitagroup
Copy link
Contributor

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

Labels

None yet

Projects

None yet

3 participants