Skip to content

Feature 13294 doctor declarations xml esante adapter #13575

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

raulbob
Copy link
Contributor

@raulbob raulbob commented Aug 12, 2025

  • Adds more updates to external message processing including hospitalization handling
  • Adds support for pathogen tests to doctor declaration and support for Tuberculosis
  • Includes IPI specific requirements for external message processing

Summary by CodeRabbit

  • New Features

    • Create/edit/view notifier with reporting agent (blocked when a surveillance report exists).
    • Tri-state therapy selector (started / not applicable / unknown) with start date.
    • Richer external message clinical data: hospitalization (facility, department, dates), deceased date, case comments, radiography, TB/HIV fields, vaccination status.
    • Test reports: added test type details.
    • UI: sample selection/edit flows and multi-sample confirmation.
  • Improvements

    • Hospital facility lookup by external ID or name (pattern).
    • Previous hospitalization department persisted and shown in UI.
    • New localization captions and strings for notifications, therapy, and facility department.

raulbob and others added 12 commits August 12, 2025 02:20
- Added missing fields for doctor declaration hospitalization data.
`ExternalMessageDto`
`ExternalMessage`
`ExternalMessageFacadeEjbMappingTest`

- Added `caseComments` field to support comments from the doctor declaration.
`ExternalMessageDto`
`ExternalMessage`
`ExternalMessageFacadeEjbMappingTest`

- Corrected `treatmentStarted` to YesNoUnknown type.
`ExternalMessageDto`
`ExternalMessage`
`ExternalMessageFacadeEjbMappingTest`

- Added a generic infrastructure check method
`AbstractProcessingFlow`

- Added methods for retrieving hospitals by UUID and name.
`ExternalMessageProcessingFacade`
`FacilityFacade`
`FacilityFacadeEjb`
`FacilityService`
`ExternalMessageFacadeEjb`

- Added support for doctor declaration hospitalization data.
`AbstractDoctorDeclarationMessageProcessingFlow`
`DoctorDeclarationMessageProcessingFlow`

- Added `healthFacilityDepartment` field to support department information.
`PreviousHospitalizationDto`
`PreviousHospitalization`
`Captions`
`captions.properties`
`HospitalizationFacadeEjbPseudonymizationTest`
`HospitalizationFacadeEjb`
`PreviousHospitalizationEditForm`

- Added additional fields for hospitalization data.
`sormas_schema.sql`
- Introduced a new form for editing notifications
- Updated side view components to support notification editing
- Improved treatment options handling
- Fixed the button label for creating a new notification to use the correct caption.
- Added a badge to indicate the type of notification (phone or external).
…be processed in the same flow.

Moved the sample and test processing logic into the common base class `AbstractMessageProcessingFlowBase`.
Updated `DoctorDeclarationMessageProcessingFlow` and `LabMessageProcessingFlow` to make use of the shared logic.

Added test type details field to `TestReportDto` to accommodate additional information in case of Other test types.
- Added additional fields to `ExternalMessageDto` and `ExternalMessage`
- Updated `AbstractDoctorDeclarationMessageProcessingFlow` to handle additional fields
- Updated `AbstractDoctorDeclarationMessageProcessingFlow` to handle health conditions
- Fixed `PathogenTestForm` to display updated values for test type and test results plus text
@raulbob raulbob requested a review from obinna-h-n August 12, 2025 18:09
Copy link

coderabbitai bot commented Aug 12, 2025

Walkthrough

Extends external message, hospitalization, TB/HIV, therapy, notifier, symptoms, and lab-report models and UI; adds facility lookup and infra-data check hook; refactors processing orchestration for sampling and doctor-declaration post-build; updates mappings, DB schema/histories, i18n keys, and notifier UI flows.

Changes

Cohort / File(s) Summary of changes
External Message clinical extensions
sormas-api/.../externalmessage/ExternalMessageDto.java, sormas-backend/.../externalmessage/ExternalMessage.java, sormas-backend/.../externalmessage/ExternalMessageFacadeEjb.java, sormas-api/.../processing/ExternalMessageMapper.java, sormas-backend/.../externalmessage/ExternalMessageFacadeEjbMappingTest.java, sormas-backend/.../sql/sormas_schema.sql
Added constants, fields, getters/setters for treatmentNotApplicable, radiographyCompatibility, otherDiagnosticCriteria, TB/HIV fields, vaccinationStatus, hospitalization details, deceasedDate, caseComments; changed treatmentStarted to YesNoUnknown; mapping/tests/schema/history updated.
Lab TestReport: testTypeDetails
sormas-api/.../labmessage/TestReportDto.java, sormas-backend/.../labmessage/TestReport.java, sormas-backend/.../labmessage/TestReportFacadeEjb.java, sormas-backend/.../labmessage/TestReportFacadeEjbMappingTest.java, sormas-backend/.../sql/sormas_schema.sql
Added TEST_TYPE_DETAILS constant, field with validation, entity column, mapping round-trip, tests, and schema addition.
Processing flow infrastructure & orchestration
sormas-api/.../processing/AbstractProcessingFlow.java, sormas-api/.../processing/AbstractMessageProcessingFlowBase.java, sormas-api/.../processing/labmessage/AbstractLabMessageProcessingFlow.java, sormas-ui/.../externalmessage/doctordeclaration/DoctorDeclarationMessageProcessingFlow.java, sormas-ui/.../externalmessage/labmessage/LabMessageProcessingFlow.java, sormas-ui/.../externalmessage/processing/ExternalMessageProcessingUIHelper.java
Added infra-data async hook (handleInfraDataChecks); converted several abstract flow handlers into concrete orchestration with sampling helpers and multi-sample confirmation; removed/streamlined some lab-message abstract sample orchestration; UI flows now use wrapper helpers and new addLabelIfAvailable.
Facility lookup additions
sormas-api/.../infrastructure/facility/FacilityFacade.java, sormas-backend/.../infrastructure/facility/FacilityFacadeEjb.java, sormas-backend/.../infrastructure/facility/FacilityService.java, sormas-api/.../processing/ExternalMessageProcessingFacade.java
Added methods to fetch active facilities by type and name-regex and hospital-specific facility lookup helpers.
Hospitalization: previous hospitalization department
sormas-api/.../hospitalization/PreviousHospitalizationDto.java, sormas-backend/.../hospitalization/PreviousHospitalization.java, sormas-backend/.../hospitalization/HospitalizationFacadeEjb.java, sormas-ui/.../hospitalization/PreviousHospitalizationEditForm.java, sormas-backend/.../hospitalization/HospitalizationFacadeEjbPseudonymizationTest.java, sormas-api/.../i18n/Captions.java, sormas-api/.../resources/captions.properties, sormas-backend/.../sql/sormas_schema.sql
Added healthFacilityDepartment field/constant and accessors; mapping, UI form, tests, captions/properties, and schema/history updated.
Notifier data and UI
sormas-api/.../person/notifier/NotifierDto.java, sormas-backend/.../person/notifier/Notifier.java, sormas-backend/.../person/notifier/NotifierEjb.java, sormas-backend/.../person/notifier/NotifierService.java, sormas-ui/.../caze/notifier/CaseNotifierForm.java, sormas-ui/.../caze/notifier/CaseNotifierSideViewComponent.java, sormas-ui/.../caze/notifier/CaseNotifierSideViewContent.java, sormas-ui/.../caze/notifier/CaseNotifierSideViewController.java, sormas-backend/.../person/notifier/NotifierTestBase.java, sormas-api/.../i18n/Strings.java, sormas-api/.../i18n/Captions.java, sormas-api/.../resources/captions.properties, sormas-api/.../resources/strings.properties, sormas-backend/.../sql/sormas_schema.sql
Added agentFirstName/agentLastName to DTO/entity/mappings/service and history; added notifier create/edit/view UI flows with gating by surveillance reports; i18n keys and schema columns updated.
Symptoms: unknownSymptom
sormas-api/.../symptoms/SymptomsDto.java, sormas-backend/.../symptoms/Symptoms.java, sormas-backend/.../symptoms/SymptomsFacadeEjb.java, sormas-ui/.../symptoms/SymptomsForm.java, sormas-api/.../i18n/Captions.java, sormas-api/.../resources/captions.properties, sormas-backend/.../sql/sormas_schema.sql
Added UNKNOWN_SYMPTOM constant/field/accessors, mapping, UI inclusion, i18n caption, and schema/history column.
Therapy: treatment fields
sormas-api/.../therapy/TherapyDto.java, sormas-backend/.../therapy/Therapy.java, sormas-backend/.../therapy/TherapyFacadeEjb.java, sormas-ui/.../caze/notifier/TreatmentOption.java, sormas-ui/.../caze/notifier/CaseNotifierSideViewController.java, sormas-api/.../i18n/Captions.java, sormas-api/.../resources/captions.properties, sormas-backend/.../sql/sormas_schema.sql
Added treatmentStarted (YesNoUnknown), treatmentNotApplicable, treatmentStartDate to entity/DTO/mapping; UI TreatmentOption rewritten with NOT_APPLICABLE and ordering; controller mapping updates; i18n and schema changes.
Person: death date & lookup
sormas-api/.../processing/ExternalMessageMapper.java, sormas-ui/.../person/PersonCreateForm.java, sormas-api/.../person/PersonFacade.java
Mapper now maps deceasedDate to Person; PersonCreateForm copies deathDate; added getByNationalHealthId to PersonFacade API.
UI sampling / pathogen-test form
sormas-ui/.../samples/PathogenTestForm.java
testType and testResult fields are synchronized in setValue and form marked dirty.
Doctor declaration post-build refactor
sormas-api/.../processing/doctordeclaration/AbstractDoctorDeclarationMessageProcessingFlow.java
Removed several event/case/contact selection flow methods; added modular post-build handlers to augment case data, health conditions (including TB/HIV), therapy, and hospitalization with facility resolution logic.
Miscellaneous
sormas-backend/.../clinicalcourse/HealthConditionsMapper.java
Removed unused imports.

Sequence Diagram(s)

sequenceDiagram
  participant UI as UI
  participant Flow as AbstractProcessingFlow
  participant Impl as Flow subclass

  UI->>Flow: startProcessing(message)
  Flow->>Flow: checkDisease()
  Flow->>Impl: handleInfraDataChecks()
  alt infra checks pass
    Impl-->>Flow: completion(true)
    Flow->>Flow: continue processing
  else infra checks fail
    Impl-->>Flow: completion(false)
    Flow-->>UI: cancel processing (default result)
  end
Loading
sequenceDiagram
  participant Processor as AbstractMessageProcessingFlowBase
  participant Handler as concrete doXFlow
  participant UI as ExternalMessageProcessingUIHelper
  participant Lab as Lab/Sample services

  Processor->>Handler: doCreateEventParticipantFlow(...)
  Handler->>UI: show/create participant
  Handler->>Processor: doCreateEventParticipantAndSamplesFlow(...)
  Processor->>Lab: doPickOrCreateSamplesFlow(...)
  alt multiple sample reports
    Lab->>UI: handleMultipleSampleConfirmation()
    UI-->>Lab: user confirms/cancels
  end
  Lab->>Processor: create/pick samples -> createOneSampleAndPathogenTests(...)
  Processor->>Processor: continue processing
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~90 minutes

Poem

A rabbit taps code with gentle care,
Adding wards and tests to share.
Notifiers nod, TB notes align,
Therapy toggles, captions shine.
Hop through flows where checks now play—data blooms like spring today. 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature-13294_doctor_declarations_xml_esante_adapter

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@raulbob raulbob requested a review from KarnaiahPesula August 12, 2025 18:09
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: 21

🔭 Outside diff range comments (9)
sormas-api/src/main/java/de/symeda/sormas/api/hospitalization/PreviousHospitalizationDto.java (1)

39-39: Enum constant typo likely breaks compilation: CASE_SURVEILANCE → CASE_SURVEILLANCE

The FeatureType name appears misspelled. If the enum is FeatureType.CASE_SURVEILLANCE (double “l”), this will not compile or will silently disable the feature gating.

-@DependingOnFeatureType(featureType = FeatureType.CASE_SURVEILANCE)
+@DependingOnFeatureType(featureType = FeatureType.CASE_SURVEILLANCE)
sormas-backend/src/main/java/de/symeda/sormas/backend/person/notifier/NotifierService.java (1)

103-108: Avoid NoResultException by using getResultList

getSingleResult throws NoResultException if no row is found. The method contract allows returning null; switch to getResultList to avoid exception-driven flow.

Apply this diff:

-        Query query = em.createNativeQuery(sql, Notifier.class);
-        query.setParameter("uuid", uuid);
-        query.setParameter("changeDate", timestamp);
-
-        return (Notifier) query.getSingleResult();
+        Query query = em.createNativeQuery(sql, Notifier.class);
+        query.setParameter("uuid", uuid);
+        query.setParameter("changeDate", timestamp);
+
+        @SuppressWarnings("unchecked")
+        java.util.List<Notifier> results = query.getResultList();
+        return results.isEmpty() ? null : results.get(0);

Note: You’ll need to ensure java.util.List is imported or fully qualify as in the snippet.

sormas-ui/src/main/java/de/symeda/sormas/ui/symptoms/SymptomsForm.java (1)

730-736: Exclude UNKNOWN_SYMPTOM from symptomatic triggers

The list unconditionalSymptomFieldIds drives:

  • soft‐required styling (addSoftRequiredStyleWhenSymptomaticAndCooperative)
  • onset‐date/onset‐symptom enabling
  • the “clear all” and bulk‐set‐cleared actions

Treating UNKNOWN_SYMPTOM as a symptom‐presence trigger causes onset requirements and styling to fire when “Unknown symptom” is marked. It should not. Please remove it:

File: sormas-ui/src/main/java/de/symeda/sormas/ui/symptoms/SymptomsForm.java
Around line 594:

 unconditonalSymptomFieldIds = Arrays.asList(
     …,
-    UNKNOWN_SYMPTOM,
     OTHER_CLINICAL_PRESENTATION);

Follow-up: if you still want “Unknown symptom” cleared by your bulk‐clear buttons, split this into two lists—one for symptomatic triggers (without UNKNOWN_SYMPTOM) and one for clear-all/bulk-set actions (including it).

sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjb.java (1)

161-219: Missing round-trip test for deceasedDate
Mapping tests cover caseComments, treatmentNotApplicable, and treatmentStartedDate, but I don’t see any assertion for deceasedDate in ExternalMessageFacadeEjbMappingTest.

• File:

  • sormas-backend/src/test/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjbMappingTest.java

• Suggested fix:
Add an assertion for deceasedDate in both DTO→entity and entity→DTO sections, for example:

assertEquals(source.getDeceasedDate(), result.getDeceasedDate());
sormas-ui/src/main/java/de/symeda/sormas/ui/caze/notifier/CaseNotifierSideViewComponent.java (1)

47-47: Compile error: missing Sizeable.Unit import

Unit is unresolved here. Either re-import com.vaadin.server.Sizeable.Unit or fully qualify in the method call.

Apply this minimal diff to avoid adding an import:

- setWidth(100, Unit.PERCENTAGE);
+ setWidth(100, com.vaadin.server.Sizeable.Unit.PERCENTAGE);
sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/labmessage/LabMessageProcessingFlow.java (2)

118-136: Typo in FeatureType constant likely breaks compilation

FeatureType.CASE_SURVEILANCE looks misspelled. In SORMAS it’s typically CASE_SURVEILLANCE (double “l”). Please verify and fix.

Apply this diff:

-            .addCreateEntry(EntrySelectionField.OptionType.CREATE_CASE, FeatureType.CASE_SURVEILANCE, UserRight.CASE_CREATE, UserRight.CASE_EDIT)
+            .addCreateEntry(EntrySelectionField.OptionType.CREATE_CASE, FeatureType.CASE_SURVEILLANCE, UserRight.CASE_CREATE, UserRight.CASE_EDIT)

416-418: Returning null for CompletionStage can cause NPEs; return a completed future

If callers chain on the returned stage, null will break them. Return a completed future instead.

Apply this diff:

-    @Override
-    protected CompletionStage<Void> notifyCorrectionsSaved() {
-        return null;
-    }
+    @Override
+    protected CompletionStage<Void> notifyCorrectionsSaved() {
+        return java.util.concurrent.CompletableFuture.completedFuture(null);
+    }
sormas-ui/src/main/java/de/symeda/sormas/ui/caze/notifier/TreatmentOption.java (1)

80-87: Compute captions dynamically to respect current user language

Captions are resolved at class-load time; this locks them to whatever language was active then. Resolve captions on access so they reflect the current thread’s language.

Update getCaption/toString to compute dynamically (no diff since this block wasn’t part of the changed hunk). Example implementation:

@Override
public String getCaption() {
    if ("NA".equals(value)) {
        return I18nProperties.getString(Strings.notApplicable);
    }
    if (YesNoUnknown.YES.toString().equals(value)) {
        return I18nProperties.getEnumCaption(YesNoUnknown.YES);
    } else if (YesNoUnknown.NO.toString().equals(value)) {
        return I18nProperties.getEnumCaption(YesNoUnknown.NO);
    } else if (YesNoUnknown.UNKNOWN.toString().equals(value)) {
        return I18nProperties.getEnumCaption(YesNoUnknown.UNKNOWN);
    }
    return value; // fallback
}

@Override
public String toString() {
    return getCaption();
}

Optionally, drop the caption field entirely to avoid stale state.

sormas-api/src/main/resources/captions.properties (1)

1151-1151: Bulk action caption added

The caption bulkActionCreatDocuments=Create quarantine order documents has been added. Note there's a typo in the key name.

Fix typo in caption key

The key bulkActionCreatDocuments appears to have a typo - it should be bulkActionCreateDocuments (missing 'e' in 'Create').

-bulkActionCreatDocuments=Create quarantine order documents
+bulkActionCreateDocuments=Create quarantine order documents
🧹 Nitpick comments (41)
sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonCreateForm.java (1)

373-373: Death date sync added — verify consistency with present condition

Copying deathDate is fine, but please verify that presentCondition is consistently set when a death date is present (and cleared when removed). Otherwise, you can end up with a non-deceased present condition while a death date is set.

Would you like a follow-up patch that adjusts presentCondition when deathDate is provided/cleared?

sormas-api/src/main/resources/strings.properties (1)

1974-1975: Wording consistency: “Notifier” vs “Notification” and capitalization

  • Keys are about “notification…”, but the value for notificationCreationNotAllowedWithoutSurveillanceReport uses “Notifier creation…”, which can be confusing. Consider aligning the noun (“notification” vs “notifier”) with the rest of the UI.
  • Consider sentence case for consistency with the rest of strings (e.g., “Cannot create or edit notification”).

Proposed wording (if “notification” is the intended concept):

  • notificationCannotCreate=Cannot create or edit notification
  • notificationCreationNotAllowedWithoutSurveillanceReport=Notification creation or modification is not allowed when a surveillance report already exists for this case.
sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/AbstractProcessingFlow.java (1)

83-92: Javadoc nit: mention CompletionStage instead of CompletableFuture

The method returns a CompletionStage. Update the doc to avoid confusion.

Apply:

-	 * @return A CompletableFuture containing the processing result.
+	 * @return A CompletionStage containing the processing result.
sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/AbstractMessageProcessingFlowBase.java (1)

74-94: Clarify intent of forceSampleCreation and prefer primitive boolean

Using a boxed Boolean for forceSampleCreation introduces a third state (null) that is not needed and complicates reasoning. If null is not intentionally used, switch to a primitive boolean and simplify checks.

Example changes:

  • Field: private final boolean forceSampleCreation;
  • Ctor param: boolean forceSampleCreation
  • Usage: if (forceSampleCreation) { ... } instead of Boolean.TRUE.equals(forceSampleCreation)
sormas-backend/src/main/java/de/symeda/sormas/backend/person/notifier/NotifierService.java (2)

7-7: Fix GPL header punctuation

Minor nit: The sentence reads “(at any later version.” and is missing a closing parenthesis. Consider aligning with the standard GPL header text.


98-101: SQL concatenation is correct; consider readability and avoid accidental whitespace issues

String concatenation creates a valid query. For maintainability, consider using a multiline string or StringBuilder to avoid subtle spacing bugs and improve readability, especially as more columns are projected.

Example using String.join or text block (if using Java 15+):

  • Use a text block with proper aliases and line breaks.
sormas-ui/src/main/java/de/symeda/sormas/ui/hospitalization/PreviousHospitalizationEditForm.java (1)

125-126: Consider visibility/required rules for department field

Depending on requirements, HEALTH_FACILITY_DEPARTMENT might only be relevant when a concrete health facility (not OTHER/NONE/unknown) is selected. If so, add FieldHelper visibility and required rules similar to healthFacilityDetails.

I can provide a small patch to bind visibility/required to healthFacilityCombo selection if needed.

sormas-backend/src/main/java/de/symeda/sormas/backend/therapy/TherapyFacadeEjb.java (1)

37-39: Map new therapy fields and consider enforcing invariants when not applicable

The new fields treatmentStarted, treatmentNotApplicable, and treatmentStartDate are mapped correctly in both directions.

Optional improvement: if treatmentNotApplicable is true, consider normalizing state by clearing treatmentStarted/treatmentStartDate to avoid contradictory state.

Apply this after setting the three fields in fillOrBuildEntity:

 entity.setTreatmentStarted(source.getTreatmentStarted());
 entity.setTreatmentNotApplicable(source.isTreatmentNotApplicable());
 entity.setTreatmentStartDate(source.getTreatmentStartDate());
+// Normalize contradictory state
+if (entity.isTreatmentNotApplicable()) {
+	entity.setTreatmentStarted(null);
+	entity.setTreatmentStartDate(null);
+}

Also applies to: 57-59

sormas-backend/src/main/java/de/symeda/sormas/backend/symptoms/Symptoms.java (1)

263-265: Clarify the comment for unknownSymptom

The current wording is hard to parse. Suggest rephrasing for clarity.

Proposed:

-	// Added in case, enrolling person is not known about the symptoms, but sure of the case.
+	// Captures cases where the enrolling person does not know the symptoms, but the case classification is certain.
sormas-backend/src/test/java/de/symeda/sormas/backend/externalmessage/labmessage/TestReportFacadeEjbMappingTest.java (1)

107-107: Add symmetric coverage for fromDto mapping of testTypeDetails

Currently, fromDto() isn’t asserting testTypeDetails propagation. Add it to prevent regressions.

Suggested change within testFromDto():

 	@Test
 	public void testFromDto() {
@@
 		source.setTestType(PathogenTestType.ANTIBODY_DETECTION);
+		source.setTestTypeDetails("Test Type Details");
 		source.setTestDateTime(new Date(9999999L));
@@
 		assertEquals(source.getTestType(), result.getTestType());
+		assertEquals(source.getTestTypeDetails(), result.getTestTypeDetails());

Also applies to: 125-125

sormas-backend/src/main/java/de/symeda/sormas/backend/person/notifier/Notifier.java (1)

49-51: Agent first/last name fields added — OK, consider minor consistency tweaks

The new fields and accessors look correct.

Optional refinements:

  • Add public static field name constants for agentFirstName/agentLastName to mirror the existing pattern (e.g., FIRST_NAME_FIELD_NAME, etc.).
  • If applicable, specify a length using FieldConstraints (e.g., CHARACTER_LIMIT_DEFAULT) to align with other string columns in the project.

Given the PR context indicates DTO, EJB, and service updates, no functional issues here.

Also applies to: 106-122

sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/ExternalMessageMapper.java (1)

70-75: Death date mapping added — verify normalization and condition alignment

Good to map PersonDto.DEATH_DATE from external messages before approximate age calculation.

Two follow-ups to consider:

  • If PersonDto.DEATH_DATE is a date-only field in UI/DB, normalize the time (e.g., start of day) with the Mapping.of overload that applies a converter.
  • Optionally, when a death date is provided but present condition isn’t, align presentCondition with DECEASED (unless the team decided to map it strictly from the message only).

Example normalization (if needed):

- Mapping.of(person::setDeathDate, person.getDeathDate(), externalMessage.getDeceasedDate(), PersonDto.DEATH_DATE),
+ Mapping.of(person::setDeathDate, person.getDeathDate(), externalMessage.getDeceasedDate(), DateHelper::getStartOfDay, PersonDto.DEATH_DATE),
sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/processing/ExternalMessageProcessingUIHelper.java (1)

544-552: Helper addLabelIfAvailable — concise and safe

  • Skips blank text, uses i18n caption with fallback behavior, and keeps Label in TEXT mode by default (safe against HTML injection).
  • WidthUndefined is appropriate for inline labels.

Optional: If captionKey might be null in any callsites, defensively handle it (e.g., requireNonNull or a default caption) to avoid odd “prefix.null” lookups.

sormas-api/src/main/java/de/symeda/sormas/api/symptoms/SymptomsDto.java (1)

2579-2583: Consider adding @order to unknownSymptom for stable import/export positioning.

Many SymptomsDto fields define @order to keep CSV/import templates stable. unknownSymptom currently has none. Optional, but adding an @order near related clinical presentation fields avoids future reordering surprises.

sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/facility/FacilityFacadeEjb.java (1)

114-131: Consider pushing name filtering down to the service/DB

Filtering all active facilities in-memory with a regex can be costly in large deployments. If feasible, consider extending the service to support a name filter (e.g., case-insensitive LIKE or DB-side regex) to reduce payload and CPU usage on the application node.

sormas-api/src/main/java/de/symeda/sormas/api/therapy/TherapyDto.java (1)

46-49: Add missing constant for treatmentStartDate for consistency

Other properties expose String constants; adding one for treatmentStartDate keeps API symmetry and eases binder usage.

Apply this diff just below the existing constants:

 public static final String TREATMENT_STARTED = "treatmentStarted";
 public static final String TREATMENT_NOT_APPLICABLE = "treatmentNotApplicable";
+public static final String TREATMENT_START_DATE = "treatmentStartDate";

Also applies to: 85-107

sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjb.java (1)

1-15: License header year looks off (2026)

Align the end year with the current year to avoid tooling/license checks flagging it.

Apply this diff:

- * Copyright © 2016-2026 SORMAS Foundation gGmbH
+ * Copyright © 2016-2025 SORMAS Foundation gGmbH
sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/ExternalMessageProcessingFacade.java (1)

200-206: Null-guard externalId to avoid unexpected service call with null

If externalId is null, short-circuit to null to avoid passing null to the facade and relying on its null-handling.

Apply this diff:

 public FacilityReferenceDto getHospitalFacilityReferenceByExternalId(String externalId) {
-		return facilityFacade.getByExternalIdAndType(externalId, FacilityType.HOSPITAL, false)
+		if (externalId == null) {
+			return null;
+		}
+		return facilityFacade.getByExternalIdAndType(externalId, FacilityType.HOSPITAL, false)
 			.stream()
 			.filter(Objects::nonNull)
 			.findFirst()
 			.orElse(null);
 	}
sormas-backend/src/main/java/de/symeda/sormas/backend/therapy/Therapy.java (1)

36-39: Consider nullable type for not-applicable and align naming with related models

  • treatmentNotApplicable is a primitive boolean here, while ExternalMessage uses a boxed Boolean for the same concept. If “not applicable” needs a tri-state (true/false/unknown) or to represent absence, use Boolean for consistency and nullability.
  • Therapy uses treatmentStartDate while ExternalMessage uses treatmentStartedDate. The divergence is easy to miss and can introduce mapping confusions.

Do we need a tri-state for treatmentNotApplicable in Therapy? If yes, switch to Boolean. Also confirm the intended naming across layers; if alignment is desired, consider renaming to treatmentStartedDate or adjusting mapping helpers accordingly.

sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/labmessage/LabMessageProcessingFlow.java (1)

331-346: Prefer localized formatting for date and enum captions

  • sampleDateTime.toString() is not localized; use a date formatter aligned with user locale.
  • sampleMaterial.toString() likely prints enum name; better to use I18nProperties.getEnumCaption(sampleMaterial).

Example minimal changes within this block:

-        ExternalMessageProcessingUIHelper.addLabelIfAvailable(
-            sampleDetailsLayout,
-            sampleDateTime == null ? null : sampleDateTime.toString(),
+        ExternalMessageProcessingUIHelper.addLabelIfAvailable(
+            sampleDetailsLayout,
+            sampleDateTime == null ? null : de.symeda.sormas.ui.utils.DateFormatHelper.formatDateTime(sampleDateTime),
             ExternalMessageDto.I18N_PREFIX,
             SampleReportDto.SAMPLE_DATE_TIME);
-        ExternalMessageProcessingUIHelper
-            .addLabelIfAvailable(sampleDetailsLayout, sampleReport.getLabSampleId(), ExternalMessageDto.I18N_PREFIX, SampleReportDto.LAB_SAMPLE_ID);
+        ExternalMessageProcessingUIHelper.addLabelIfAvailable(
+            sampleDetailsLayout,
+            sampleReport.getLabSampleId(),
+            ExternalMessageDto.I18N_PREFIX,
+            SampleReportDto.LAB_SAMPLE_ID);
...
-        ExternalMessageProcessingUIHelper.addLabelIfAvailable(
-            sampleDetailsLayout,
-            sampleMaterial == null ? null : sampleMaterial.toString(),
+        ExternalMessageProcessingUIHelper.addLabelIfAvailable(
+            sampleDetailsLayout,
+            sampleMaterial == null ? null : I18nProperties.getEnumCaption(sampleMaterial),
             ExternalMessageDto.I18N_PREFIX,
             SampleReportDto.SAMPLE_MATERIAL);

If DateFormatHelper doesn’t exist, I can provide a small helper for localized formatting.

sormas-backend/src/test/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjbMappingTest.java (4)

115-118: Fix duplicated birth date setter: set MM instead of DD twice

You’re calling setPersonBirthDateDD twice; the second should set month (MM).

Apply this diff:

-        source.setPersonBirthDateDD(1);
+        source.setPersonBirthDateMM(1);

228-241: Fix duplicated birth date setter in toDto test as well

Same issue as above.

Apply this diff:

-        source.setPersonBirthDateDD(1);
+        source.setPersonBirthDateMM(1);

215-217: Strengthen mapping test by stubbing SampleReport mapping to a non-null DTO

Currently sampleReportFacade.toDto(sampleReport) returns null (mock default), so the assertion only checks a list with null. Stub the mock to return a real DTO to actually verify the mapping.

Apply this diff:

-        SampleReportDto sampleReportDto = sampleReportFacade.toDto(sampleReport);
+        SampleReportDto sampleReportDto = new SampleReportDto();
+        when(sampleReportFacade.toDto(sampleReport)).thenReturn(sampleReportDto);

268-271: Also assert treatmentNotApplicable on toDto path

You added assertions for treatmentStarted and dates; include treatmentNotApplicable to cover the new field both ways.

Apply this diff:

-        source.setTreatmentStarted(YesNoUnknown.YES);
+        source.setTreatmentStarted(YesNoUnknown.YES);
+        source.setTreatmentNotApplicable(Boolean.TRUE);
...
-        assertEquals(source.getTreatmentStarted(), result.getTreatmentStarted());
+        assertEquals(source.getTreatmentStarted(), result.getTreatmentStarted());
+        assertEquals(source.getTreatmentNotApplicable(), result.getTreatmentNotApplicable());

Also applies to: 315-316

sormas-ui/src/main/java/de/symeda/sormas/ui/caze/notifier/CaseNotifierForm.java (3)

147-151: Use i18n key instead of hardcoded “Notifier Information”

Avoid hardcoded English strings to maintain localization.

Apply this diff (adjust key if different in your bundles):

-        Label datesLabel = new Label("Notifier Information");
+        Label datesLabel = new Label(I18nProperties.getString(Strings.headingNotifierInformation));

158-166: Externalize field descriptions to i18n and avoid hardcoded English

Descriptions for notification/diagnostic dates are hardcoded. Move them to I18n resources for consistency.

I can provide the necessary keys and wiring if you confirm the target bundles (Strings vs Captions) and phrasing.


299-324: Use localized validation messages instead of hardcoded “Required field”

To keep consistency with the rest of the UI, use i18n-based messages.

Example:

firstNameField.setComponentError(new UserError(I18nProperties.getString(Strings.messageRequiredField)));

If there’s a canonical validation key (e.g., Validations.fieldIsRequired), prefer that.

sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/doctordeclaration/DoctorDeclarationMessageProcessingFlow.java (1)

117-172: Infrastructure data validation implementation

The handleInfraDataChecks() method implements a comprehensive hospital facility validation flow:

  1. Attempts to retrieve hospital facility reference
  2. Shows appropriate warning dialogs based on missing data
  3. Returns false to skip hospitalization if data is incomplete

The implementation correctly handles both missing hospital data and unmatched facilities.

Consider extracting UI message strings to constants

The hardcoded messages in lines 142-143 and 155-156 could be moved to the i18n properties files for better maintainability and localization support.

sormas-ui/src/main/java/de/symeda/sormas/ui/caze/notifier/CaseNotifierSideViewController.java (2)

261-304: Consider extracting magic dates to constants

The therapy update logic is well-structured with clear conditional paths. However, consider extracting the default date (new java.util.Date()) to a method parameter or configuration for better testability.

 private void updateTherapyBasedOnSelection(CaseDataDto caze, TreatmentOption selectedOption) {
+    updateTherapyBasedOnSelection(caze, selectedOption, new Date());
+}
+
+private void updateTherapyBasedOnSelection(CaseDataDto caze, TreatmentOption selectedOption, Date defaultStartDate) {

     if (selectedOption == null) {
         return;
     }

     TherapyDto therapy = caze.getTherapy();

     if (therapy == null) {
         therapy = TherapyDto.build();
     }

     if (selectedOption.equals(TreatmentOption.YES)) {
         therapy.setTreatmentStarted(YesNoUnknown.YES);
         therapy.setTreatmentNotApplicable(false);
         if (therapy.getTreatmentStartDate() == null) {
-            therapy.setTreatmentStartDate(new java.util.Date());
+            therapy.setTreatmentStartDate(defaultStartDate);
         }
         return;
     }

315-317: TODO comment needs implementation plan

The placeholder method for diagnostic date handling contains a TODO without any implementation details or tracking reference.

Would you like me to create an issue to track the implementation of diagnostic date handling functionality?

sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/doctordeclaration/AbstractDoctorDeclarationMessageProcessingFlow.java (2)

447-478: Complex facility matching logic could benefit from documentation

The facility reference lookup implements a three-tier fallback strategy (external ID → ID in name → name match). While the implementation is correct, consider adding method-level documentation explaining the matching priority.

 /**
  * Retrieves the hospital facility reference based on the external message data.
  * It first tries to find the facility by external ID and then by name containing external ID.
+ * 
+ * Matching priority:
+ * 1. Exact match by external ID
+ * 2. Name contains external ID (with word boundaries)  
+ * 3. Name contains the provided hospital name
  *
  * @param externalMessageDto
  *            The external message containing hospitalization facility information.
  * @return The facility reference DTO for the hospital, or null if not found.
  */
 protected FacilityReferenceDto getHospitalFacilityReference(ExternalMessageDto externalMessageDto) {

461-464: Consider extracting regex pattern to constant

The complex regex pattern for hospital ID matching could be extracted to a constant for better readability and reusability.

+private static final String HOSPITAL_ID_NAME_PATTERN_FORMAT = "^(\\b%s\\b)?.*?(\\b%s\\b).*?$";
+
 protected FacilityReferenceDto getHospitalFacilityReference(ExternalMessageDto externalMessageDto) {
     // ... existing code ...
     
     // Search for a hospital facility containing the external ID in name if not found by external ID
     if (hospitalFacilityReference == null && StringUtils.isNotBlank(hospitalExternalId)) {
-        final Pattern hospitalIdInNamePattern = Pattern.compile(
-            "^(\\b" + Pattern.quote(hospitalExternalId) + "\\b)?.*?(\\b" + Pattern.quote(hospitalExternalId) + "\\b).*?$",
-            Pattern.CASE_INSENSITIVE);
+        final String quotedId = Pattern.quote(hospitalExternalId);
+        final Pattern hospitalIdInNamePattern = Pattern.compile(
+            String.format(HOSPITAL_ID_NAME_PATTERN_FORMAT, quotedId, quotedId),
+            Pattern.CASE_INSENSITIVE);
         hospitalFacilityReference = getExternalMessageProcessingFacade().getHospitalFacilityReferenceNameMatching(hospitalIdInNamePattern)
sormas-backend/src/main/resources/sql/sormas_schema.sql (4)

14426-14427: Case comments length likely too small

Free-text comments are often longer than 255. We’ve moved many comment fields to 512 or even 4096 across the schema for similar reasons.

Consider increasing to at least 512 to be consistent and prevent truncation.

-ALTER TABLE externalmessage ADD COLUMN casecomments varchar(255);
-ALTER TABLE externalmessage_history ADD COLUMN casecomments varchar(255);
+ALTER TABLE externalmessage ADD COLUMN casecomments varchar(512);
+ALTER TABLE externalmessage_history ADD COLUMN casecomments varchar(512);

14488-14490: Column name casing: will become lowercase in PostgreSQL; verify ORM/mappers

PostgreSQL folds unquoted identifiers to lowercase. Adding testTypeDetails will create testtypedetails on disk. Ensure your mappers/SQL reference the lowercase name, and consider aligning with existing testtypetext naming for consistency.

-ALTER TABLE testreport ADD COLUMN testTypeDetails varchar(255);
-ALTER TABLE testreport_history ADD COLUMN testTypeDetails varchar(255);
+ALTER TABLE testreport ADD COLUMN testtypedetails varchar(255);
+ALTER TABLE testreport_history ADD COLUMN testtypedetails varchar(255);

14446-14455: Make DDL idempotent with IF NOT EXISTS for repeatable deployments

You’ve used IF NOT EXISTS here, but the surrounding blocks (e.g., Lines 14426-14444) don’t. For operational safety when migrations are re-run or applied to partially-upgraded environments, prefer IF NOT EXISTS across the board in this file section.

-ALTER TABLE externalmessage ADD COLUMN casecomments varchar(255);
+ALTER TABLE externalmessage ADD COLUMN IF NOT EXISTS casecomments varchar(255);
...
-ALTER TABLE externalmessage_history ADD COLUMN casecomments varchar(255);
+ALTER TABLE externalmessage_history ADD COLUMN IF NOT EXISTS casecomments varchar(255);

Apply the same pattern to the newly added hospitalization* and previoushospitalization.healthfacilitydepartment columns in this section.


14426-14438: Optional: include case comments in full-text search (tsv) if used for message search

The externalmessage tsv is currently built from externalmessagedetails only. If casecomments should be discoverable via content search, extend the tsv trigger function to include it.

Outside this hunk (function defined around Lines 12334-12344), update trigger function:

CREATE OR REPLACE FUNCTION externalmessage_tsv_update() RETURNS TRIGGER AS $$
BEGIN
    IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN
        NEW.tsv = to_tsvector(
            'simple',
            unaccent(
                regexp_replace(
                    coalesce(NEW.externalmessagedetails, '') || ' ' || coalesce(NEW.casecomments, ''),
                    E'[<>]',
                    ' ',
                    'g'
                )
            )
        );
    END IF;

    RETURN NEW;
END
$$ LANGUAGE 'plpgsql';

If you want, I can prepare a full diff adjusting the trigger and recreating it safely (drop/recreate) in a new schema version step.

sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/ExternalMessageDto.java (5)

106-119: Public constants added — consider adding a constant for caseComments as well

The new constants look consistent and useful. If caseComments is referenced in UI/mapping layers similarly to other fields, consider adding:

  • public static final String CASE_COMMENTS = "caseComments";

If not used anywhere, feel free to ignore.


188-188: Deceased date semantics and cross-field consistency

  • Clarify whether deceasedDate is a date-only or date-time; the field name implies date-only. If date-only is intended, consider normalizing time or documenting the expected semantics.
  • Consider validating consistency with personPresentCondition to avoid states like deceasedDate set while condition is ALIVE.

Also applies to: 832-838


197-199: caseComments field and accessors look fine

Length constraint matches other long-text fields. If caseComments is used in UI bindings similarly to other fields, see earlier note about adding a CASE_COMMENTS constant.

Also applies to: 546-552


221-229: Hospitalization fields: add date-range and presence validation

The new fields are valuable. Consider adding:

  • Date-range validation to ensure discharge date is not before admission date.
  • If admittedToHealthFacility is YES, require an admission date (and optionally at least one of facilityName/externalId).

You can add object-level Bean Validation methods (outside the touched lines):

import javax.validation.constraints.AssertTrue;

@AssertTrue
public boolean isHospitalizationDateRangeValid() {
	if (hospitalizationAdmissionDate != null && hospitalizationDischargeDate != null) {
		return !hospitalizationDischargeDate.before(hospitalizationAdmissionDate);
	}
	return true;
}

@AssertTrue
public boolean isHospitalizationAdmissionPresenceValid() {
	return admittedToHealthFacility != YesNoUnknown.YES || hospitalizationAdmissionDate != null;
}

Also applies to: 610-648


250-257: TB/HIV fields: consider cross-field consistency checks

Potential rules to prevent contradictory states:

  • hivArt should not be YES when hiv is NO.
  • If previousTuberculosisTreatment is YES, tuberculosis should likely not be NO (or enforce domain-specific logic).
  • tuberculosisInfectionYear should be a reasonable year (not in the future).

If you want to enforce some of these with Bean Validation (outside the touched lines):

import javax.validation.constraints.AssertTrue;

@AssertTrue
public boolean isHivArtConsistent() {
	return hiv != YesNoUnknown.NO || hivArt != YesNoUnknown.YES;
}

For tuberculosisInfectionYear, since @max requires a compile-time constant, confirm validation happens elsewhere (e.g., service layer) to ensure it’s not in the future and within a sensible range.

Also applies to: 856-902

Comment on lines +239 to +246
// TODO - NotifierFacade doesn't seem to have delete functionality yet
// if (canDelete) {
// editView.addDeleteListener(() -> {
// // Delete functionality would go here
// window.close();
// callback.run();
// }, "Notifier");
// }
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Commented delete functionality needs clarification

The delete functionality is commented out with a TODO noting that NotifierFacade doesn't have delete capability. This should either be implemented or the commented code should be removed to avoid confusion.


🏁 Script executed:

#!/bin/bash
# Check if NotifierFacade has any delete methods
ast-grep --pattern 'interface NotifierFacade {
  $$$
  delete($$$) {
    $$$
  }
  $$$
}'

# Also check for any delete-related methods
rg "delete|remove" --type java -A 2 -B 2 $(fd NotifierFacade.java)

Length of output: 242


To ensure we’re accurately detecting any delete/remove capabilities in NotifierFacade, let’s print out its contents and search more exhaustively:


🏁 Script executed:

#!/bin/bash
# 1) Locate the interface file
file=$(fd NotifierFacade.java)

# 2) Show the first 200 lines of the interface
echo "=== ${file} (lines 1–200) ==="
sed -n '1,200p' "$file"

# 3) Search for any delete/remove method signatures
echo "=== delete/remove occurrences ==="
rg -nE "delete|remove" --type java "$file"

Length of output: 5681


Let’s verify whether NotifierFacade inherits any delete/remove methods from its parent BaseFacade:


🏁 Script executed:

#!/bin/bash
# Locate and inspect BaseFacade
file=$(fd BaseFacade.java)

echo "=== ${file} (first 200 lines) ==="
sed -n '1,200p' "$file"

echo "=== delete/remove occurrences in BaseFacade ==="
rg -nE "delete|remove" --type java "$file"

Length of output: 1676


Delete functionality missing in NotifierFacade
The commented-out delete listener in CaseNotifierSideViewController refers to a delete operation, but neither NotifierFacade nor its BaseFacade parent declares any delete/remove method. Please address this by either:

  • Adding and implementing a delete(String uuid) (or similar) method in NotifierFacade (and its server-side implementation) before re-enabling the UI code, or
  • Removing the commented delete block (and its TODO) to avoid leaving dead code.

Locations:

  • sormas-ui/src/main/java/de/symeda/sormas/ui/caze/notifier/CaseNotifierSideViewController.java (lines 239–246)
  • sormas-api/src/main/java/de/symeda/sormas/api/person/notifier/NotifierFacade.java
🤖 Prompt for AI Agents
In
sormas-ui/src/main/java/de/symeda/sormas/ui/caze/notifier/CaseNotifierSideViewController.java
around lines 239–246 the commented delete listener references a delete operation
that does not exist in NotifierFacade/BaseFacade; either implement delete
functionality in the API and server or remove the dead code: Option A - add a
delete(String uuid) (or deleteById) method to
sormas-api/src/main/java/de/symeda/sormas/api/person/notifier/NotifierFacade.java
(and its BaseFacade parent if appropriate), implement the server-side removal
logic and tests, then re-enable the UI delete listener to call that method and
invoke callback on success; Option B - if deletion is not required now, delete
the commented block and its TODO in the UI controller to avoid dead code and
leave a clear TODO or issue reference for future implementation.

@sormas-vitagroup
Copy link
Contributor

@sormas-vitagroup
Copy link
Contributor

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: 0

🔭 Outside diff range comments (1)
sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/doctordeclaration/DoctorDeclarationMessageProcessingFlow.java (1)

699-702: Missing implementation for notifyCorrectionsSaved

The notifyCorrectionsSaved method returns null but should return a completed CompletionStage. This could cause issues in the processing flow.

 @Override
 protected CompletionStage<Void> notifyCorrectionsSaved() {
     LOGGER.debug("Notifying corrections saved for externalMessage: {}", getExternalMessage());
-    return null;
+    return CompletableFuture.completedFuture(null);
 }
♻️ Duplicate comments (1)
sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/doctordeclaration/DoctorDeclarationMessageProcessingFlow.java (1)

323-329: Improved reporter name parsing logic

The updated implementation correctly handles hyphenated names by treating all parts except the last as the first name, which is more robust than the previous approach. This addresses the concerns raised in the past review comment about handling names like "Marie-Claire" or "Jean-Pierre".

🧹 Nitpick comments (3)
sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/doctordeclaration/DoctorDeclarationMessageProcessingFlow.java (3)

3-3: Update copyright year range to 2024

The copyright year should be 2024, not 2026, as we are currently in 2024.

- * Copyright © 2016-2026 SORMAS Foundation gGmbH
+ * Copyright © 2016-2024 SORMAS Foundation gGmbH

164-164: Remove commented-out code

This commented line appears to be leftover debug code and should be removed.

-				//commitDiscardWrapperComponent.addCommitListener(() -> ret.complete(true));

639-663: Consider extracting pathogen test logic to a helper method

The getSampleCreateComponent method is doing multiple responsibilities. Consider extracting the pathogen test setup logic (lines 648-659) into a separate helper method for better modularity and testability.

private CommitDiscardWrapperComponent<SampleCreateForm> getSampleCreateComponent(
    SampleDto sample,
    boolean lastSample,
    List<PathogenTestDto> pathogenTests,
    Disease disease,
    Consumer<PathogenTestDto> pathogenTestSaveHandler) {
    SampleController sampleController = ControllerProvider.getSampleController();
    CommitDiscardWrapperComponent<SampleCreateForm> sampleCreateComponent = sampleController.getSampleCreateComponent(sample, disease, null);

-    // add pathogen test create components
-    List<PathogenTestDto> pathogenTestsToAdd = new ArrayList<>(pathogenTests);
-    // always build at least one PathogenTestDto
-    if (pathogenTestsToAdd.isEmpty()) {
-        pathogenTestsToAdd.add(LabMessageProcessingHelper.buildPathogenTest(null, getMapper(), sample, getUser()));
-    }
-
-    ExternalMessageProcessingUIHelper.addNewPathogenTests(pathogenTestsToAdd, sampleCreateComponent, true, pathogenTestSaveHandler, null);
-
-    // add option to create additional pathogen tests
-    sampleController.addPathogenTestButton(sampleCreateComponent, true, null, null, pathogenTestSaveHandler);
+    setupPathogenTests(sampleCreateComponent, sample, pathogenTests, pathogenTestSaveHandler, sampleController);

    LabMessageUiHelper.establishCommitButtons(sampleCreateComponent, lastSample);

    return sampleCreateComponent;
}

+private void setupPathogenTests(
+    CommitDiscardWrapperComponent<SampleCreateForm> sampleCreateComponent,
+    SampleDto sample,
+    List<PathogenTestDto> pathogenTests,
+    Consumer<PathogenTestDto> pathogenTestSaveHandler,
+    SampleController sampleController) {
+    
+    // add pathogen test create components
+    List<PathogenTestDto> pathogenTestsToAdd = new ArrayList<>(pathogenTests);
+    // always build at least one PathogenTestDto
+    if (pathogenTestsToAdd.isEmpty()) {
+        pathogenTestsToAdd.add(LabMessageProcessingHelper.buildPathogenTest(null, getMapper(), sample, getUser()));
+    }
+    
+    ExternalMessageProcessingUIHelper.addNewPathogenTests(pathogenTestsToAdd, sampleCreateComponent, true, pathogenTestSaveHandler, null);
+    
+    // add option to create additional pathogen tests
+    sampleController.addPathogenTestButton(sampleCreateComponent, true, null, null, pathogenTestSaveHandler);
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cfd8ee9 and 129bf94.

📒 Files selected for processing (2)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/caze/notifier/TreatmentOption.java (2 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/doctordeclaration/DoctorDeclarationMessageProcessingFlow.java (13 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/caze/notifier/TreatmentOption.java
🧰 Additional context used
🧬 Code Graph Analysis (1)
sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/doctordeclaration/DoctorDeclarationMessageProcessingFlow.java (12)
sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/PickOrCreateEventResult.java (1)
  • PickOrCreateEventResult (20-45)
sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/PickOrCreateSampleResult.java (1)
  • PickOrCreateSampleResult (20-45)
sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/doctordeclaration/AbstractDoctorDeclarationMessageProcessingFlow.java (1)
  • AbstractDoctorDeclarationMessageProcessingFlow (69-480)
sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/labmessage/LabMessageProcessingHelper.java (1)
  • LabMessageProcessingHelper (31-56)
sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/labmessage/SampleAndPathogenTests.java (1)
  • SampleAndPathogenTests (23-40)
sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/processing/EntrySelectionComponentForExternalMessage.java (1)
  • EntrySelectionComponentForExternalMessage (26-55)
sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/processing/ExternalMessageProcessingUIHelper.java (1)
  • ExternalMessageProcessingUIHelper (88-554)
sormas-ui/src/main/java/de/symeda/sormas/ui/samples/humansample/SampleController.java (1)
  • SampleController (100-746)
sormas-ui/src/main/java/de/symeda/sormas/ui/samples/humansample/SampleCreateForm.java (1)
  • SampleCreateForm (24-51)
sormas-ui/src/main/java/de/symeda/sormas/ui/samples/humansample/SampleEditPathogenTestListHandler.java (1)
  • SampleEditPathogenTestListHandler (25-46)
sormas-ui/src/main/java/de/symeda/sormas/ui/samples/humansample/SampleSelectionField.java (1)
  • SampleSelectionField (33-212)
sormas-ui/src/main/java/de/symeda/sormas/ui/utils/processing/ProcessingUiHelper.java (1)
  • ProcessingUiHelper (34-68)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Lint Code Base
  • GitHub Check: SORMAS CI
  • GitHub Check: android app test (28)
  • GitHub Check: android app test (27)
  • GitHub Check: android app test (26)
🔇 Additional comments (4)
sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/doctordeclaration/DoctorDeclarationMessageProcessingFlow.java (4)

119-174: LGTM! Well-structured infrastructure data validation

The handleInfraDataChecks method properly validates hospital facility references and provides appropriate user feedback through modal dialogs. The logic correctly handles the different scenarios:

  1. Hospital facility found - continues processing
  2. Missing hospital data - allows continuation with a warning
  3. Hospital not found with valid identifier - blocks processing

211-237: LGTM! Enhanced person matching logic

The implementation intelligently handles cases where patient name fields are missing or match the national health ID, attempting to find existing persons by their health ID first. This prevents duplicate person records and improves data quality.


533-589: LGTM! Comprehensive sample selection UI

The handlePickOrCreateSample method provides a well-structured UI for sample selection with appropriate details display including sample date/time, lab sample ID, and sample material. The implementation follows the established UI patterns and provides clear user interaction flow.


609-637: LGTM! Well-integrated sample and pathogen test creation

The handleCreateSampleAndPathogenTests method properly orchestrates the creation of samples with associated pathogen tests. The post-commit listener ensures that pathogen tests are saved after the sample is created, maintaining referential integrity.

@sormas-vitagroup
Copy link
Contributor

@raulbob raulbob merged commit 997f366 into development Aug 13, 2025
6 of 14 checks passed
@raulbob raulbob deleted the feature-13294_doctor_declarations_xml_esante_adapter branch August 13, 2025 08:11
@raulbob raulbob restored the feature-13294_doctor_declarations_xml_esante_adapter branch August 13, 2025 18:42
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.

Check for existing case-person in system with same national health ID before creating via doctor´s declaration
3 participants