Skip to content

Malaria & Dengue Doctors declaration and lab message changes#13912

Merged
KarnaiahPesula merged 6 commits into
developmentfrom
feature-13837-malaria-doctors-declarations
Apr 23, 2026
Merged

Malaria & Dengue Doctors declaration and lab message changes#13912
KarnaiahPesula merged 6 commits into
developmentfrom
feature-13837-malaria-doctors-declarations

Conversation

@KarnaiahPesula
Copy link
Copy Markdown
Contributor

@KarnaiahPesula KarnaiahPesula commented Apr 23, 2026

Fixes #
#13837
#13838
#13835
#13836
#13813
#13800
#13903

Summary by CodeRabbit

  • New Features

    • Added blood donation & bone marrow donation activity options
    • Added travel purpose and prophylaxis adherence (with details) for exposures
    • Added airport worker & healthcare professional flags, place of infection and residence-at-onset fields
    • Added fatal risk symptom for dengue
    • Expanded malaria transmission routes, exposure categories, exposure settings/subsettings and serotype support (including Unknown)
    • New exposure-period heading in forms
  • Bug Fixes

    • Improved URL handling in case definition displays
  • Documentation

    • Updated captions and UI strings for new fields and enums

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

Warning

Rate limit exceeded

@KarnaiahPesula has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 43 minutes and 33 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 43 minutes and 33 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 37869598-cbf6-44f2-80d3-00df1ab20ba9

📥 Commits

Reviewing files that changed from the base of the PR and between e9b45f0 and e2f07f5.

📒 Files selected for processing (1)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java
📝 Walkthrough

Walkthrough

Adds malaria/dengue exposure, transmission, serotype, occupational and prophylaxis fields across API, backend, UI, i18n, mapping logic and DB schema; introduces TravelPurpose and ProphylaxisAdherence enums and extends doctor-declaration mapping to populate malaria-specific health/exposure data.

Changes

Cohort / File(s) Summary
API Enums
sormas-api/src/main/java/de/symeda/sormas/api/activityascase/ActivityAsCaseType.java, .../exposure/ExposureCategory.java, .../exposure/ExposureSetting.java, .../exposure/ExposureSubSetting.java, .../exposure/ModeOfTransmission.java, .../exposure/ProphylaxisAdherence.java, .../exposure/TravelPurpose.java, .../sample/Serotype.java
Added new enum constants for donations, medical/lab/other exposure categories/settings/subsettings and malaria-specific ModeOfTransmission entries; introduced TravelPurpose and ProphylaxisAdherence; added Serotype.UNKNOWN and refactored fromString implementation.
API DTOs & Mappers
sormas-api/src/main/java/.../epidata/EpiDataDto.java, .../exposure/ExposureDto.java, .../externalmessage/ExternalMessageDto.java, .../externalmessage/labmessage/TestReportDto.java, .../externalmessage/processing/ExternalMessageMapper.java
Added new DTO fields/constants/getters/setters for airportWorker, healthcareProfessional, placeOfInfection, residenceAtOnset, travelPurpose (+details), prophylaxisAdherence (+details), malaria flags/year, modeOfTransmission/type; changed serotype type to Serotype and added serotypeText; updated mapping for pathogen/test serotype fields.
Backend Entities & Facades
sormas-backend/src/main/java/.../epidata/EpiData.java, .../epidata/EpiDataFacadeEjb.java, .../exposure/Exposure.java, .../externalmessage/ExternalMessage.java, .../ExternalMessageFacadeEjb.java, .../externalmessage/labmessage/TestReport.java, .../externalmessage/labmessage/TestReportFacadeEjb.java, .../symptoms/Symptoms.java, .../symptoms/SymptomsFacadeEjb.java
Persisted new fields (airportWorker, healthcareProfessional, placeOfInfection, residenceAtOnset; travelPurpose+details; prophylaxisAdherence+details; malaria flags/year; modeOfTransmission/type; fatalRisk); updated DTO↔entity mapping logic and serotype handling with serotypeText fallback/parse.
Doctor Declaration Processing
sormas-api/src/main/java/.../processing/doctordeclaration/AbstractDoctorDeclarationMessageProcessingFlow.java
Added malaria-specific post-build health-conditions routine and logging; extended exposure/epi-data enrichment to copy transmission/role attributes from ExternalMessage.
UI (Forms & Utilities)
sormas-ui/src/main/java/.../caze/CaseDataForm.java, .../clinicalcourse/HealthConditionsForm.java, .../epidata/EpiDataForm.java, .../exposure/ExposureForm.java, .../samples/pathogentestlink/PathogenTestListEntry.java, .../symptoms/SymptomsForm.java, .../utils/AbstractEditForm.java
Registered and rendered new fields/headings (placeOfInfection, residenceAtOnset, airport/healthcare flags, travelPurpose/prophylaxis + details, fatalRisk), added centralized visibility helper updateFieldVisibility, sanitized/linkified case-definition text, adjusted visibility rules and form layouts.
I18n & Resource Files
sormas-api/src/main/java/de/symeda/sormas/api/i18n/Captions.java, .../i18n/Strings.java, sormas-api/src/main/resources/{captions.properties,enum.properties,strings.properties}
Added/updated caption and string keys for new fields, enums and enum captions; removed obsolete DiseaseTransmission caption keys; small wording/whitespace edits.
DB Migration
sormas-backend/src/main/resources/sql/sormas_schema.sql
Schema migration adding new nullable columns (epidata, exposures, symptoms, externalmessage and _history tables) and inserted new schema version record.
Tests
sormas-backend/src/test/java/de/symeda/sormas/backend/externalmessage/labmessage/TestReportFacadeEjbMappingTest.java
Updated test to use Serotype enum and assert serotypeText mapping.

Sequence Diagram

sequenceDiagram
    participant EM as ExternalMessage
    participant DDF as DoctorDeclarationFlow
    participant HC as HealthConditionsDto/Builder
    participant EXP as ExposureBuilder
    participant EPI as EpiDataDto

    EM->>DDF: postBuildHealthConditions(externalMsg)
    alt externalMsg.disease == MALARIA
        DDF->>HC: postBuildMalariaHealthConditions(externalMsg)
        HC->>HC: set malaria, infectedYear, airportWorker, healthcareProfessional
        HC->>DDF: debug log set values
    else
        DDF->>DDF: debug log (skip/other disease)
    end

    DDF->>EXP: postBuildExposures(externalMsg)
    EXP->>EXP: map exposure list and sub-settings
    EXP->>EPI: set exposures plus modeOfTransmission, modeOfTransmissionType, airport/healthcare flags
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • obinna-h-n
  • raulbob

Poem

🐰 I hopped through enums, fields, and strings,
Mapping mosquitoes, serotypes, and wings.
Airport workers and travels I spy,
Prophylaxis notes beneath the sky.
A tiny rabbit cheers the new data spring!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description references multiple issue numbers but lacks detail about what changes are being made or why, relying entirely on issue links without explaining the actual modifications. Add a detailed description explaining the key changes, their purpose, and how they address the referenced issues. Include information about new fields, enums, UI modifications, and database schema updates.
Docstring Coverage ⚠️ Warning Docstring coverage is 8.27% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding malaria and dengue-related doctor declarations and lab message functionality across the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature-13837-malaria-doctors-declarations

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.

Actionable comments posted: 15

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java (1)

248-253: ⚠️ Potential issue | 🟠 Major

Re-add DENGUE_FEVER_TYPE to the disease type column layout in CaseDataForm.

The field is created at line 566 and visibility is managed at lines 1255–1262, but it has been removed from the layout. This prevents users from entering Dengue fever type data despite the infrastructure supporting it. Compare with BulkCaseDataForm.java (line 103), which correctly includes this field in the layout. The field is also used in import/export functionality, confirming it should remain in the UI.

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

In `@sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java` around
lines 248 - 253, The disease type column layout in CaseDataForm is missing the
DENGUE_FEVER_TYPE field; update the layout call that builds the right-side
fluidColumn (the locs(...) group containing CaseDataDto.DISEASE_DETAILS,
CaseDataDto.PLAGUE_TYPE, CaseDataDto.RABIES_TYPE) to also include
CaseDataDto.DENGUE_FEVER_TYPE so the form displays the Dengue fever type field
(the field is created in CaseDataForm and its visibility is handled later around
the existing visibility logic at lines ~1255–1262).
sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/doctordeclaration/AbstractDoctorDeclarationMessageProcessingFlow.java (1)

357-390: ⚠️ Potential issue | 🟠 Major

Don’t gate EpiData-level fields on the presence of exposure rows.

airportWorker, healthcareProfessional, modeOfTransmission, and modeOfTransmissionType are copied only when externalMessageDto.getExposures() is non-empty. Doctor declarations that carry these top-level fields without detailed exposure entries will silently drop them.

Proposed fix
 protected void postBuildExposure(CaseDataDto caseDto, ExternalMessageDto externalMessageDto) {
+	boolean hasTopLevelEpiData =
+		externalMessageDto.getAirportWorker() != null
+			|| externalMessageDto.getHealthcareProfessional() != null
+			|| externalMessageDto.getModeOfTransmission() != null
+			|| externalMessageDto.getModeOfTransmissionType() != null;
 
 	if (externalMessageDto.getExposures() != null && !externalMessageDto.getExposures().isEmpty()) {
 		final ArrayList<ExposureDto> exposures = new ArrayList<>();
 
@@
 
 				epiData.setExposureDetailsKnown(YesNoUnknown.YES);
 				epiData.setExposures(exposures);
-				epiData.setAirportWorker(externalMessageDto.getAirportWorker());
-				epiData.setHealthcareProfessional(externalMessageDto.getHealthcareProfessional());
-				epiData.setModeOfTransmission(externalMessageDto.getModeOfTransmission());
-				epiData.setModeOfTransmissionType(externalMessageDto.getModeOfTransmissionType());
 			}
 
 		} else {
 			logger.debug("[POST BUILD CASE] No exposures to set for case with UUID: {}", caseDto.getUuid());
 		}
+
+	if (hasTopLevelEpiData) {
+		EpiDataDto epiData = caseDto.getEpiData();
+		if (epiData == null) {
+			epiData = EpiDataDto.build();
+			caseDto.setEpiData(epiData);
+		}
+
+		epiData.setAirportWorker(externalMessageDto.getAirportWorker());
+		epiData.setHealthcareProfessional(externalMessageDto.getHealthcareProfessional());
+		epiData.setModeOfTransmission(externalMessageDto.getModeOfTransmission());
+		epiData.setModeOfTransmissionType(externalMessageDto.getModeOfTransmissionType());
+	}
 	}
🤖 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/doctordeclaration/AbstractDoctorDeclarationMessageProcessingFlow.java`
around lines 357 - 390, The code currently only copies airportWorker,
healthcareProfessional, modeOfTransmission, and modeOfTransmissionType into
caseDto.getEpiData() when externalMessageDto.getExposures() is non-null and
non-empty, causing those top-level EpiData fields to be lost for messages
without exposure rows; change the flow so you always ensure EpiDataDto exists
(use EpiDataDto.build() and caseDto.setEpiData(epiData) as now) and then
unconditionally set
epiData.setAirportWorker(externalMessageDto.getAirportWorker()),
epiData.setHealthcareProfessional(externalMessageDto.getHealthcareProfessional()),
epiData.setModeOfTransmission(externalMessageDto.getModeOfTransmission()), and
epiData.setModeOfTransmissionType(externalMessageDto.getModeOfTransmissionType())
outside (or before) the exposures.isEmpty() check while leaving exposures-only
logic that sets exposures and exposureDetailsKnown intact.
🧹 Nitpick comments (2)
sormas-api/src/main/java/de/symeda/sormas/api/exposure/ExposureDto.java (1)

439-456: LGTM — new Malaria/Dengue exposure fields are wired consistently.

The four new fields (prophylaxisAdherence, prophylaxisAdherenceDetails, travelPurpose, travelPurposeDetails) follow the established pattern: @Diseases({MALARIA, DENGUE}) for disease scoping and @Size(max = CHARACTER_LIMIT_TEXT, message = Validations.textTooLong) on the detail strings. Getters/setters and constants are in place.

One thing worth double-checking: the detail fields are not annotated with @SensitiveData, unlike many other free-text exposure fields in this DTO (e.g. gatheringDetails, habitationDetails, typeOfAnimalDetails). If travel purpose / prophylaxis adherence notes can contain identifying or sensitive personal info, consider adding @SensitiveData so pseudonymization treats them consistently.

🤖 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/exposure/ExposureDto.java`
around lines 439 - 456, The detail fields prophylaxisAdherenceDetails and
travelPurposeDetails in ExposureDto currently lack `@SensitiveData`; if these
free-text notes can contain identifying information, annotate both fields with
`@SensitiveData` to ensure pseudonymization, i.e., add the `@SensitiveData`
annotation above the private String prophylaxisAdherenceDetails and private
String travelPurposeDetails declarations in the ExposureDto class so they follow
the same treatment as other sensitive free-text fields like gatheringDetails and
habitationDetails.
sormas-backend/src/main/java/de/symeda/sormas/backend/epidata/EpiData.java (1)

84-87: Consider whether placeOfInfection / residenceAtOnset need length bounds and sensitive-data handling.

These are persisted as unbounded text columns with no corresponding @Size constraint on the DTO side (based on the summary). Two suggestions:

  1. If the DTO fields don't already have @Size(max = CHARACTER_LIMIT_TEXT, ...), please add one — matches the pattern used for other free-text EpiData/Exposure fields and prevents abuse/accidental huge payloads.
  2. residenceAtOnset is effectively an address and almost certainly PII; placeOfInfection may be too. On the corresponding DTO fields, consider @PersonalData / @SensitiveData annotations so pseudonymization and jurisdiction-based access work correctly.

Not blocking, but worth confirming before release given the GDPR implications.

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

In `@sormas-backend/src/main/java/de/symeda/sormas/backend/epidata/EpiData.java`
around lines 84 - 87, EpiData currently has unbounded text fields
placeOfInfection and residenceAtOnset; please add input-length constraints and
mark sensitive data on the corresponding DTO: on the DTO add `@Size`(max =
CHARACTER_LIMIT_TEXT, ...) to the placeOfInfection and residenceAtOnset
properties (matching the pattern used for other EpiData/Exposure free-text
fields) and annotate residenceAtOnset (and consider placeOfInfection) with
`@PersonalData` or `@SensitiveData` to ensure pseudonymization/access controls
apply; update any validation/messages accordingly so persistence still uses text
but DTO enforces the limit and sensitivity metadata.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@sormas-api/src/main/java/de/symeda/sormas/api/epidata/EpiDataDto.java`:
- Around line 152-157: The field airportWorker is missing disease/country
visibility annotations so it shows up unconditionally; add the same annotations
used on healthcareProfessional (e.g., `@Diseases`({Disease.MALARIA}) and
`@HideForCountriesExcept`(countries = {CountryHelper.COUNTRY_CODE_LUXEMBOURG})) to
the airportWorker declaration so it is scoped to the intended malaria/Luxembourg
declaration (refer to the airportWorker field in EpiDataDto and how EpiDataForm
uses it).

In
`@sormas-api/src/main/java/de/symeda/sormas/api/exposure/ExposureCategory.java`:
- Around line 31-37: The hasNoSetting() implementation in ExposureCategory
currently omits OTHER, causing getValues(ExposureCategory.OTHER) to return empty
and the form to show an empty required dropdown; update
ExposureCategory.hasNoSetting() to include OTHER in the EnumSet (i.e., add OTHER
to EnumSet.of(ANIMAL_CONTACT, FOMITE_TRANSMISSION, FOOD_BORNE, MEDICAL_CARE,
LAB)) so hasNoSetting() returns true for OTHER, or alternatively add one or more
ExposureSetting enum entries that declare support for ExposureCategory.OTHER so
getValues(ExposureCategory.OTHER) is non-empty.

In
`@sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/labmessage/TestReportDto.java`:
- Around line 216-217: TestReportDto.serotypeText is unbounded in the DTO and
can exceed the DB column size; add a validation constraint that matches the
persisted column length (e.g., annotate serotypeText with `@Size`(max =
<columnLength>) or otherwise trim/validate input in TestReportDto) so validation
fails before save; apply the same change to the other DTO string fields flagged
in the review (the other serotype/related text properties referenced) to ensure
DTO validation mirrors the entity column sizes.

In `@sormas-api/src/main/resources/captions.properties`:
- Around line 1615-1616: The caption for Exposure.travelPurposeDetails is
ambiguous; update Exposure.travelPurposeDetails to mirror the paired pattern and
make it clear it's the "Other/Specify" field for the travelPurpose dropdown
(e.g., "Travel purpose details" or "Other travel purpose details") so it aligns
with Exposure.travelPurpose and other "*Details" keys like
Exposure.prophylaxisAdherenceDetails and Exposure.gatheringDetails; modify the
value for Exposure.travelPurposeDetails accordingly.

In `@sormas-api/src/main/resources/enum.properties`:
- Line 3010: The caption for ExposureSubSetting.BLOOD_TRANSFUSION_RECIPIENT
contains a typo ("recepient"); update the value to the correct spelling by
replacing "Blood transfusion recepient" with "Blood transfusion recipient" for
the ExposureSubSetting.BLOOD_TRANSFUSION_RECIPIENT entry so the UI/exports show
the correct label.
- Line 2983: The enum caption for ExposureSetting.OTHER_DIRECT_CONTACT currently
duplicates ExposureSetting.OTHER ("Other"), causing ambiguity in the UI; update
the caption for ExposureSetting.OTHER_DIRECT_CONTACT to a distinct, descriptive
label (e.g., "Other (direct contact)" or "Other - direct contact") so it is
distinguishable from ExposureSetting.OTHER in enum.properties and any UI
consumers that rely on these keys.

In
`@sormas-backend/src/main/java/de/symeda/sormas/backend/exposure/Exposure.java`:
- Around line 978-984: The getter/setter for prophylaxisAdherenceDetails lack a
text column mapping, so long free-text can fail on persist; add the same text
column annotation used by other *Details fields (e.g. annotate the
prophylaxisAdherenceDetails field or its getter with `@Column`(columnDefinition =
"text") or `@Lob` as used elsewhere) so the property is persisted as a TEXT
column; update the Exposure class members around getProphylaxisAdherenceDetails
and setProphylaxisAdherenceDetails accordingly.

In
`@sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/labmessage/TestReportFacadeEjb.java`:
- Around line 256-257: The mapping in TestReportFacadeEjb currently copies only
source.getSerotype() into target.setSerotype() which leaves target.serotype null
when callers provide only free-text in source.getSerotypeText(); update the
mapping (around target.setSerotype(...) and target.setSerotypeText(...)) to
mirror PathogenTestFacadeEjb: set target.serotype to the enum value when
source.getSerotype() is non-null, otherwise attempt to resolve the enum from
source.getSerotypeText() (fall back to parsing/lookup of the enum by name/value)
before saving target.setSerotypeText(source.getSerotypeText()); ensure you reuse
the same enum lookup logic used in PathogenTestFacadeEjb to keep behavior
consistent.

In `@sormas-backend/src/main/resources/sql/sormas_schema.sql`:
- Line 15824: The INSERT into schema_version uses a comment string with a typo
("##13838") and omits some PR ticket numbers; update the VALUES tuple in the
INSERT INTO schema_version statement so the comment uses a single '#' for 13838
(e.g., '#13838') and include all referenced ticket numbers from this PR so the
comment lists every relevant issue (edit the string in the INSERT INTO
schema_version ... VALUES (624, '...') to correct '##13838' -> '#13838' and
append the missing ticket IDs).
- Around line 15790-15823: The SQL migration uses mixed-case camelCase column
names (placeOfInfection, residenceAtOnset) and inconsistent
casing/keywords/types (ADD column, varchar vs character varying) which will
mismatch Hibernate's implicit naming; update the ALTER TABLE statements for
epidata, epidata_history, exposures, exposures_history, symptoms,
symptoms_history, externalmessage, and externalmessage_history to use normalized
lowercase column identifiers (e.g., placeofinfection, residenceatonset,
airportworker, prophylaxisadherence, prophylaxisadherencedetails, travelpurpose,
travelpurposedetails, fatalrisk, malaria, malariainfectedyear,
healthcareprofessional, modeoftransmission, modeoftransmissiontype) and
standardize the syntax to "ADD COLUMN <name> character varying(255)" (or
consistently "varchar(255)") and consistent "ADD COLUMN" casing across all
statements.

In
`@sormas-backend/src/test/java/de/symeda/sormas/backend/externalmessage/labmessage/TestReportFacadeEjbMappingTest.java`:
- Line 276: The test in TestReportFacadeEjbMappingTest sets
source.setSerotype(Serotype.OTHER) but does not assert the mapped values; add
assertions after the mapping invocation to verify the serotype and the
serotypeText fields: assert that the mapped object's serotype equals
Serotype.OTHER (e.g., assertEquals(Serotype.OTHER, mapped.getSerotype())) and
assert the mapped.getSerotypeText() matches the expected value (either
assertNull(mapped.getSerotypeText()) if none was set on source or
assertEquals(source.getSerotypeText(), mapped.getSerotypeText()) if the source
had a value). Ensure these assertions reference the existing variables/methods
used in this test (source.setSerotype, getSerotype/getSerotypeText, and the
mapping call in TestReportFacadeEjbMappingTest).

In `@sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java`:
- Line 221: The case-definition text is currently rendered as ContentMode.HTML
after only a regex replacement (see EMAIL_REGEX) which allows injected HTML/JS;
replace that flow by escaping non-link text and only inserting safe anchor tags
for detected URLs: add a URL_PATTERN constant, implement a helper like
linkifyPlainTextCaseDefinition(String) that iterates matches, appends
escapeHtml(...) for text segments, and inserts anchors built from the escaped
URL with target="_blank" and rel="noopener noreferrer"; use escapeHtml(String)
to replace &, <, >, " and ' before assembling the final HTML and render that
result as ContentMode.HTML in the CaseDataForm where caseDefinitionText is used.

In
`@sormas-ui/src/main/java/de/symeda/sormas/ui/clinicalcourse/HealthConditionsForm.java`:
- Line 325: The visibility listener for the MALARIA field doesn't apply the
current value and clears the year field on every change; update the code that
uses getField(MALARIA), malInfectedYearCB, and lblInfectedYear so you call
fieldVisibilityCheck(...) once immediately to set initial visibility, and inside
the change listener call fieldVisibilityCheck(...) on value changes but only
clear malInfectedYearCB (and/or its model) when the field is being hidden
(visibility false); make the identical adjustment for the other similar listener
block (the one analogous to lines 351-358) so both initialize visibility and
only clear when hiding.

In `@sormas-ui/src/main/java/de/symeda/sormas/ui/epidata/EpiDataForm.java`:
- Line 183: The call that sets caseFollowUpEnabled using
FacadeProvider.getDiseaseConfigurationFacade().hasFollowUp(disease) must be
guarded against a null disease to avoid a construction-time NPE; update
EpiDataForm so that before invoking hasFollowUp(disease) you check if disease ==
null (or move the assignment after the null-check in addFields()), and if null
set caseFollowUpEnabled to false (or compute it only when disease is non-null)
so the code tolerates a null disease without failing.

In `@sormas-ui/src/main/java/de/symeda/sormas/ui/exposure/ExposureForm.java`:
- Around line 476-495: Remove visibility registrations for fields that are not
present on the form and eliminate the duplicate registration: delete or guard
the FieldHelper.setVisibleWhen calls that reference
ExposureDto.TRAVEL_ACCOMMODATION, ExposureDto.TRAVEL_ACCOMMODATION_TYPE,
ExposureDto.SWIMMING_LOCATION, and ExposureDto.SWIMMING_LOCATION_TYPE (or wrap
them in a check that getFieldGroup().getField(...) != null before calling), and
remove the duplicated FieldHelper.setVisibleWhen call for
ExposureDto.PROPHYLAXIS_ADHERENCE_DETAILS so it is only registered once with
ProphylaxisAdherence.OTHER.

---

Outside diff comments:
In
`@sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/doctordeclaration/AbstractDoctorDeclarationMessageProcessingFlow.java`:
- Around line 357-390: The code currently only copies airportWorker,
healthcareProfessional, modeOfTransmission, and modeOfTransmissionType into
caseDto.getEpiData() when externalMessageDto.getExposures() is non-null and
non-empty, causing those top-level EpiData fields to be lost for messages
without exposure rows; change the flow so you always ensure EpiDataDto exists
(use EpiDataDto.build() and caseDto.setEpiData(epiData) as now) and then
unconditionally set
epiData.setAirportWorker(externalMessageDto.getAirportWorker()),
epiData.setHealthcareProfessional(externalMessageDto.getHealthcareProfessional()),
epiData.setModeOfTransmission(externalMessageDto.getModeOfTransmission()), and
epiData.setModeOfTransmissionType(externalMessageDto.getModeOfTransmissionType())
outside (or before) the exposures.isEmpty() check while leaving exposures-only
logic that sets exposures and exposureDetailsKnown intact.

In `@sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java`:
- Around line 248-253: The disease type column layout in CaseDataForm is missing
the DENGUE_FEVER_TYPE field; update the layout call that builds the right-side
fluidColumn (the locs(...) group containing CaseDataDto.DISEASE_DETAILS,
CaseDataDto.PLAGUE_TYPE, CaseDataDto.RABIES_TYPE) to also include
CaseDataDto.DENGUE_FEVER_TYPE so the form displays the Dengue fever type field
(the field is created in CaseDataForm and its visibility is handled later around
the existing visibility logic at lines ~1255–1262).

---

Nitpick comments:
In `@sormas-api/src/main/java/de/symeda/sormas/api/exposure/ExposureDto.java`:
- Around line 439-456: The detail fields prophylaxisAdherenceDetails and
travelPurposeDetails in ExposureDto currently lack `@SensitiveData`; if these
free-text notes can contain identifying information, annotate both fields with
`@SensitiveData` to ensure pseudonymization, i.e., add the `@SensitiveData`
annotation above the private String prophylaxisAdherenceDetails and private
String travelPurposeDetails declarations in the ExposureDto class so they follow
the same treatment as other sensitive free-text fields like gatheringDetails and
habitationDetails.

In `@sormas-backend/src/main/java/de/symeda/sormas/backend/epidata/EpiData.java`:
- Around line 84-87: EpiData currently has unbounded text fields
placeOfInfection and residenceAtOnset; please add input-length constraints and
mark sensitive data on the corresponding DTO: on the DTO add `@Size`(max =
CHARACTER_LIMIT_TEXT, ...) to the placeOfInfection and residenceAtOnset
properties (matching the pattern used for other EpiData/Exposure free-text
fields) and annotate residenceAtOnset (and consider placeOfInfection) with
`@PersonalData` or `@SensitiveData` to ensure pseudonymization/access controls
apply; update any validation/messages accordingly so persistence still uses text
but DTO enforces the limit and sensitivity metadata.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: be9cb0ad-2729-48b0-affb-1c97bc113ae1

📥 Commits

Reviewing files that changed from the base of the PR and between 72ac3ed and 9836f9b.

📒 Files selected for processing (37)
  • sormas-api/src/main/java/de/symeda/sormas/api/activityascase/ActivityAsCaseType.java
  • sormas-api/src/main/java/de/symeda/sormas/api/epidata/EpiDataDto.java
  • sormas-api/src/main/java/de/symeda/sormas/api/exposure/ExposureCategory.java
  • sormas-api/src/main/java/de/symeda/sormas/api/exposure/ExposureDto.java
  • sormas-api/src/main/java/de/symeda/sormas/api/exposure/ExposureSetting.java
  • sormas-api/src/main/java/de/symeda/sormas/api/exposure/ExposureSubSetting.java
  • sormas-api/src/main/java/de/symeda/sormas/api/exposure/ModeOfTransmission.java
  • sormas-api/src/main/java/de/symeda/sormas/api/exposure/ProphylaxisAdherence.java
  • sormas-api/src/main/java/de/symeda/sormas/api/exposure/TravelPurpose.java
  • sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/ExternalMessageDto.java
  • sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/labmessage/TestReportDto.java
  • sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/ExternalMessageMapper.java
  • sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/doctordeclaration/AbstractDoctorDeclarationMessageProcessingFlow.java
  • sormas-api/src/main/java/de/symeda/sormas/api/i18n/Captions.java
  • sormas-api/src/main/java/de/symeda/sormas/api/i18n/Strings.java
  • sormas-api/src/main/java/de/symeda/sormas/api/sample/Serotype.java
  • sormas-api/src/main/java/de/symeda/sormas/api/symptoms/SymptomsDto.java
  • sormas-api/src/main/resources/captions.properties
  • sormas-api/src/main/resources/enum.properties
  • sormas-api/src/main/resources/strings.properties
  • sormas-backend/src/main/java/de/symeda/sormas/backend/epidata/EpiData.java
  • sormas-backend/src/main/java/de/symeda/sormas/backend/epidata/EpiDataFacadeEjb.java
  • sormas-backend/src/main/java/de/symeda/sormas/backend/exposure/Exposure.java
  • sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/ExternalMessage.java
  • sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjb.java
  • sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/labmessage/TestReport.java
  • sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/labmessage/TestReportFacadeEjb.java
  • sormas-backend/src/main/java/de/symeda/sormas/backend/symptoms/Symptoms.java
  • sormas-backend/src/main/java/de/symeda/sormas/backend/symptoms/SymptomsFacadeEjb.java
  • sormas-backend/src/main/resources/sql/sormas_schema.sql
  • sormas-backend/src/test/java/de/symeda/sormas/backend/externalmessage/labmessage/TestReportFacadeEjbMappingTest.java
  • sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java
  • sormas-ui/src/main/java/de/symeda/sormas/ui/clinicalcourse/HealthConditionsForm.java
  • sormas-ui/src/main/java/de/symeda/sormas/ui/epidata/EpiDataForm.java
  • sormas-ui/src/main/java/de/symeda/sormas/ui/exposure/ExposureForm.java
  • sormas-ui/src/main/java/de/symeda/sormas/ui/samples/pathogentestlink/PathogenTestListEntry.java
  • sormas-ui/src/main/java/de/symeda/sormas/ui/symptoms/SymptomsForm.java

Comment thread sormas-api/src/main/java/de/symeda/sormas/api/exposure/ExposureCategory.java Outdated
Comment thread sormas-api/src/main/resources/captions.properties Outdated
ExposureSetting.INDOOR=Indoor
ExposureSetting.OUTDOOR=Outdoor
ExposureSetting.PERSON_TO_PERSON=Person to person
ExposureSetting.OTHER_DIRECT_CONTACT=Other
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use a distinct caption for OTHER_DIRECT_CONTACT to avoid ambiguous options.

ExposureSetting.OTHER_DIRECT_CONTACT=Other duplicates the existing generic ExposureSetting.OTHER=Other, making UI choices indistinguishable.

🧭 Proposed fix
-ExposureSetting.OTHER_DIRECT_CONTACT=Other
+ExposureSetting.OTHER_DIRECT_CONTACT=Other direct contact
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ExposureSetting.OTHER_DIRECT_CONTACT=Other
ExposureSetting.OTHER_DIRECT_CONTACT=Other direct contact
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sormas-api/src/main/resources/enum.properties` at line 2983, The enum caption
for ExposureSetting.OTHER_DIRECT_CONTACT currently duplicates
ExposureSetting.OTHER ("Other"), causing ambiguity in the UI; update the caption
for ExposureSetting.OTHER_DIRECT_CONTACT to a distinct, descriptive label (e.g.,
"Other (direct contact)" or "Other - direct contact") so it is distinguishable
from ExposureSetting.OTHER in enum.properties and any UI consumers that rely on
these keys.

Comment thread sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java Outdated
Comment thread sormas-ui/src/main/java/de/symeda/sormas/ui/epidata/EpiDataForm.java Outdated
Comment thread sormas-ui/src/main/java/de/symeda/sormas/ui/exposure/ExposureForm.java Outdated
…tions

# Conflicts:
#	sormas-ui/src/main/java/de/symeda/sormas/ui/exposure/ExposureForm.java
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.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java (1)

250-255: ⚠️ Potential issue | 🟠 Major

Restore the dengue fever type location or remove the field consistently.

CaseDataDto.DENGUE_FEVER_TYPE is still registered on Line 568 and visibility-controlled on Lines 1257-1264, but no longer has a layout location here, so dengue cases can lose the edit-form UI for that value. Related forms still expose it in sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseCreateForm.java:212, CaseCreateForm.java:500, and sormas-ui/src/main/java/de/symeda/sormas/ui/caze/BulkCaseDataForm.java:176.

🐛 Proposed fix if the field should remain editable
 							fluidColumn(6, 0, locs(
 									CaseDataDto.DISEASE_DETAILS,
 									CaseDataDto.PLAGUE_TYPE,
+									CaseDataDto.DENGUE_FEVER_TYPE,
 									CaseDataDto.RABIES_TYPE))) +
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java` around
lines 250 - 255, The layout removed CaseDataDto.DENGUE_FEVER_TYPE from
CaseDataForm's fluidRow causing the field to be invisible even though it's still
registered and visibility-controlled elsewhere; either restore DENGUE_FEVER_TYPE
into the form layout (e.g., add CaseDataDto.DENGUE_FEVER_TYPE back into the
fluidColumn/locs block next to DISEASE/DISEASE_DETAILS/PLAGUE_TYPE/RABIES_TYPE
inside CaseDataForm) or consistently remove it everywhere (delete its
registration and visibility logic in CaseDataForm plus the related occurrences
in CaseCreateForm and BulkCaseDataForm) so the field is either editable in all
relevant forms or fully removed. Ensure the chosen approach keeps
CaseDataDto.DENGUE_FEVER_TYPE in sync across CaseDataForm, CaseCreateForm, and
BulkCaseDataForm.
♻️ Duplicate comments (1)
sormas-backend/src/main/java/de/symeda/sormas/backend/exposure/Exposure.java (1)

960-985: ⚠️ Potential issue | 🟡 Minor

Keep new free-text detail columns consistent with existing details fields.

travelPurposeDetails and prophylaxisAdherenceDetails are “OTHER” free-text fields, but both are capped at CHARACTER_LIMIT_DEFAULT while most neighboring *Details fields in this entity use text. If the DTO/UI does not enforce the same max length, longer doctor-declaration details can fail on persist. The prophylaxisAdherenceDetails part is the same concern already raised previously.

Proposed alignment
-	`@Column`(length = CHARACTER_LIMIT_DEFAULT)
+	`@Column`(columnDefinition = "text")
 	public String getTravelPurposeDetails() {
 		return travelPurposeDetails;
 	}
@@
-	`@Column`(length = CHARACTER_LIMIT_DEFAULT)
+	`@Column`(columnDefinition = "text")
 	public String getProphylaxisAdherenceDetails() {
 		return prophylaxisAdherenceDetails;
 	}

Also align the SQL schema migration/history table column types if these are changed to text.

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

In `@sormas-backend/src/main/java/de/symeda/sormas/backend/exposure/Exposure.java`
around lines 960 - 985, The two free-text fields travelPurposeDetails and
prophylaxisAdherenceDetails in Exposure (accessors getTravelPurposeDetails and
getProphylaxisAdherenceDetails) are annotated with `@Column`(length =
CHARACTER_LIMIT_DEFAULT) but should allow unrestricted text like neighboring
*Details fields; change their mapping to a text type (e.g. replace
length=CHARACTER_LIMIT_DEFAULT with `@Column`(columnDefinition = "text") or use
`@Lob`) so the JPA column can hold long free text, update any related
DTO/validation only if needed, and add a corresponding SQL migration to alter
the schema/history table column types to text to keep DB schema consistent.
🧹 Nitpick comments (2)
sormas-ui/src/main/java/de/symeda/sormas/ui/epidata/EpiDataForm.java (1)

255-258: PLACE_OF_INFECTION / RESIDENCE_AT_ONSET fields need an explicit type and length.

These are String DTO properties scoped to Disease.DENGUE + Luxembourg. Calling the untyped addField(propertyId) falls through to the generic Field.class path, which means the factory picks a default editor that isn't explicitly a TextField and no max-length is enforced. Compare with CLUSTER_TYPE_TEXT (line 260) which explicitly uses a TextField.

Combined with the missing @Size on the DTO (see EpiDataDto comment), long user input may silently break the round-trip. Prefer the typed call and, if the domain expects multi-line (e.g., addresses for residenceAtOnset), consider TextArea.class instead.

-		addField(EpiDataDto.PLACE_OF_INFECTION);
-		addField(EpiDataDto.RESIDENCE_AT_ONSET);
+		addField(EpiDataDto.PLACE_OF_INFECTION, TextField.class);
+		addField(EpiDataDto.RESIDENCE_AT_ONSET, TextField.class);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sormas-ui/src/main/java/de/symeda/sormas/ui/epidata/EpiDataForm.java` around
lines 255 - 258, The untyped calls to addField for EpiDataDto.PLACE_OF_INFECTION
and EpiDataDto.RESIDENCE_AT_ONSET let the factory pick a generic editor and omit
max-length enforcement; change those calls to the typed variant (e.g.,
addField(EpiDataDto.PLACE_OF_INFECTION, TextField.class) or TextArea.class for
multi-line) to match how CLUSTER_TYPE_TEXT is declared, and ensure the UI
enforces the expected length consistent with the DTO/domain rules for
Disease.DENGUE + Luxembourg.
sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java (1)

755-772: Add null guards and parameterize the Field type.

Two concerns on this new helper:

  1. label is dereferenced unconditionally; callers that pass null (e.g. when no custom label exists) will NPE. Same for field.
  2. The Field parameter is raw. Prefer Field<?> for consistency with the rest of this class and to silence rawtype warnings.
♻️ Suggested change
-	protected void updateFieldVisibility(NullableOptionGroup input, Field field, Label label) {
+	protected void updateFieldVisibility(NullableOptionGroup input, Field<?> field, Label label) {
 		boolean visible = YesNoUnknown.YES.equals(FieldHelper.getNullableSourceFieldValue(input));
-		field.setVisible(visible);
-		label.setVisible(visible);
-		if (!visible) {
+		if (field != null) {
+			field.setVisible(visible);
+		}
+		if (label != null) {
+			label.setVisible(visible);
+		}
+		if (!visible && field != null) {
 			field.clear();
 		}
 	}

Also note: this helper only sets visibility once at call time — it doesn't attach a value-change listener to input, so the visibility won't update when the user toggles the source field. If that's the intended behavior, the Javadoc wording "when the input is set to NO or UNKNOWN" is misleading; consider renaming to something like applyFieldVisibility or adding a listener inside the helper.

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

In `@sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java`
around lines 755 - 772, The method updateFieldVisibility(NullableOptionGroup
input, Field field, Label label) can NPE and uses a raw Field; change the
signature to use Field<?> and guard against null for both field and label
(return early if field is null; only call label.setVisible/clear if label !=
null) and null-check input before calling
FieldHelper.getNullableSourceFieldValue; also update the Javadoc to reflect
whether this applies once (rename to applyFieldVisibility) or, if dynamic
behavior is desired, attach a value-change listener to the NullableOptionGroup
inside updateFieldVisibility so visibility updates when the source value
changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@sormas-api/src/main/java/de/symeda/sormas/api/epidata/EpiDataDto.java`:
- Around line 161-171: Add javax.validation constraint `@Size`(max = 255) to the
EpiDataDto fields placeOfInfection and residenceAtOnset so DTO validation
enforces the database VARCHAR(255) limit; update the DTO around the fields
annotated as `@Diseases`(Disease.DENGUE) and `@HideForCountriesExcept`(...) to
include this validator, and align the persistence side by changing the EpiData
entity column definitions for placeOfInfection and residenceAtOnset (currently
annotated with `@Column`(columnDefinition = "text")) to use a 255-length VARCHAR
(or otherwise make both DTO and DB consistently allow the same max length) so
validation fails cleanly before JPA/database constraints are hit.

In `@sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java`:
- Around line 1663-1665: The inline style for the link in CaseDataForm.java
mistakenly includes backticks around the color value ("color: `#197de1`;") which
can prevent the color from being applied; update the string built by the
result.append(...) call that constructs the anchor tag (the line using
escapedUrl and result.append(...).append("\" target=... style=...")) to remove
the backticks so the style reads "color: `#197de1`; text-decoration: underline;".

In `@sormas-ui/src/main/java/de/symeda/sormas/ui/exposure/ExposureForm.java`:
- Around line 652-668: When ExposureSubSetting.TRAVELED_ABROAD is not present in
subSettings, the parent combo fields (prophylaxisAdherenceField,
travelPurposeField) are hidden but their previous values (and *_DETAILS
visibility/values) remain; update the logic so that when subSettings == null or
does not contain ExposureSubSetting.TRAVELED_ABROAD you explicitly clear/reset
prophylaxisAdherenceField and travelPurposeField (setValue(null) or equivalent)
and also hide and clear prophylaxisAdherenceDetailsField and
travelPurposeDetailsField so no stale OTHER values remain bound on submit.

---

Outside diff comments:
In `@sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java`:
- Around line 250-255: The layout removed CaseDataDto.DENGUE_FEVER_TYPE from
CaseDataForm's fluidRow causing the field to be invisible even though it's still
registered and visibility-controlled elsewhere; either restore DENGUE_FEVER_TYPE
into the form layout (e.g., add CaseDataDto.DENGUE_FEVER_TYPE back into the
fluidColumn/locs block next to DISEASE/DISEASE_DETAILS/PLAGUE_TYPE/RABIES_TYPE
inside CaseDataForm) or consistently remove it everywhere (delete its
registration and visibility logic in CaseDataForm plus the related occurrences
in CaseCreateForm and BulkCaseDataForm) so the field is either editable in all
relevant forms or fully removed. Ensure the chosen approach keeps
CaseDataDto.DENGUE_FEVER_TYPE in sync across CaseDataForm, CaseCreateForm, and
BulkCaseDataForm.

---

Duplicate comments:
In
`@sormas-backend/src/main/java/de/symeda/sormas/backend/exposure/Exposure.java`:
- Around line 960-985: The two free-text fields travelPurposeDetails and
prophylaxisAdherenceDetails in Exposure (accessors getTravelPurposeDetails and
getProphylaxisAdherenceDetails) are annotated with `@Column`(length =
CHARACTER_LIMIT_DEFAULT) but should allow unrestricted text like neighboring
*Details fields; change their mapping to a text type (e.g. replace
length=CHARACTER_LIMIT_DEFAULT with `@Column`(columnDefinition = "text") or use
`@Lob`) so the JPA column can hold long free text, update any related
DTO/validation only if needed, and add a corresponding SQL migration to alter
the schema/history table column types to text to keep DB schema consistent.

---

Nitpick comments:
In `@sormas-ui/src/main/java/de/symeda/sormas/ui/epidata/EpiDataForm.java`:
- Around line 255-258: The untyped calls to addField for
EpiDataDto.PLACE_OF_INFECTION and EpiDataDto.RESIDENCE_AT_ONSET let the factory
pick a generic editor and omit max-length enforcement; change those calls to the
typed variant (e.g., addField(EpiDataDto.PLACE_OF_INFECTION, TextField.class) or
TextArea.class for multi-line) to match how CLUSTER_TYPE_TEXT is declared, and
ensure the UI enforces the expected length consistent with the DTO/domain rules
for Disease.DENGUE + Luxembourg.

In `@sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java`:
- Around line 755-772: The method updateFieldVisibility(NullableOptionGroup
input, Field field, Label label) can NPE and uses a raw Field; change the
signature to use Field<?> and guard against null for both field and label
(return early if field is null; only call label.setVisible/clear if label !=
null) and null-check input before calling
FieldHelper.getNullableSourceFieldValue; also update the Javadoc to reflect
whether this applies once (rename to applyFieldVisibility) or, if dynamic
behavior is desired, attach a value-change listener to the NullableOptionGroup
inside updateFieldVisibility so visibility updates when the source value
changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8fdf3fe3-b308-4f78-88a4-77473190b25b

📥 Commits

Reviewing files that changed from the base of the PR and between 9836f9b and e215482.

📒 Files selected for processing (12)
  • sormas-api/src/main/java/de/symeda/sormas/api/epidata/EpiDataDto.java
  • sormas-api/src/main/java/de/symeda/sormas/api/exposure/ExposureCategory.java
  • sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/labmessage/TestReportDto.java
  • sormas-api/src/main/resources/captions.properties
  • sormas-backend/src/main/java/de/symeda/sormas/backend/exposure/Exposure.java
  • sormas-backend/src/main/resources/sql/sormas_schema.sql
  • sormas-backend/src/test/java/de/symeda/sormas/backend/externalmessage/labmessage/TestReportFacadeEjbMappingTest.java
  • sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java
  • sormas-ui/src/main/java/de/symeda/sormas/ui/clinicalcourse/HealthConditionsForm.java
  • sormas-ui/src/main/java/de/symeda/sormas/ui/epidata/EpiDataForm.java
  • sormas-ui/src/main/java/de/symeda/sormas/ui/exposure/ExposureForm.java
  • sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java
🚧 Files skipped from review as they are similar to previous changes (5)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/clinicalcourse/HealthConditionsForm.java
  • sormas-backend/src/main/resources/sql/sormas_schema.sql
  • sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/labmessage/TestReportDto.java
  • sormas-api/src/main/java/de/symeda/sormas/api/exposure/ExposureCategory.java
  • sormas-api/src/main/resources/captions.properties

Comment on lines +1663 to +1665
result.append("<a href=\"")
.append(escapedUrl)
.append("\" target=\"_blank\" rel=\"noopener noreferrer\" style=\"color: `#197de1`; text-decoration: underline;\">")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove the backticks from the link color CSS.

The generated style contains color: `#197de1`;, so the intended link color may be ignored.

🎨 Proposed fix
 			result.append("<a href=\"")
 				.append(escapedUrl)
-				.append("\" target=\"_blank\" rel=\"noopener noreferrer\" style=\"color: `#197de1`; text-decoration: underline;\">")
+				.append("\" target=\"_blank\" rel=\"noopener noreferrer\" style=\"color: `#197de1`; text-decoration: underline;\">")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
result.append("<a href=\"")
.append(escapedUrl)
.append("\" target=\"_blank\" rel=\"noopener noreferrer\" style=\"color: `#197de1`; text-decoration: underline;\">")
result.append("<a href=\"")
.append(escapedUrl)
.append("\" target=\"_blank\" rel=\"noopener noreferrer\" style=\"color: `#197de1`; text-decoration: underline;\">")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java` around
lines 1663 - 1665, The inline style for the link in CaseDataForm.java mistakenly
includes backticks around the color value ("color: `#197de1`;") which can
prevent the color from being applied; update the string built by the
result.append(...) call that constructs the anchor tag (the line using
escapedUrl and result.append(...).append("\" target=... style=...")) to remove
the backticks so the style reads "color: `#197de1`; text-decoration: underline;".

Comment thread sormas-ui/src/main/java/de/symeda/sormas/ui/exposure/ExposureForm.java Outdated
@KarnaiahPesula KarnaiahPesula requested a review from raulbob April 23, 2026 09:57
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.

♻️ Duplicate comments (1)
sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/labmessage/TestReportFacadeEjb.java (1)

161-166: ⚠️ Potential issue | 🟠 Major

Prefer the typed serotype before parsing fallback text.

Both mappings currently prioritize serotypeText. Since Serotype.fromString(...) returns OTHER for unrecognized non-blank text, a report with a concrete serotype plus free text can be downgraded to OTHER during DTO mapping or persistence. Use the text fallback only when the typed value is missing.

🐛 Proposed mapping fix
-		if (source.getSerotypeText() != null && !source.getSerotypeText().trim().isEmpty()) {
-			target.setSerotype(Serotype.fromString(source.getSerotypeText()));
-		} else {
-			target.setSerotype(source.getSerotype());
-		}
+		target.setSerotype(resolveSerotype(source.getSerotype(), source.getSerotypeText()));
 		target.setSerotypeText(source.getSerotypeText());
-		if (source.getSerotypeText() != null && !source.getSerotypeText().trim().isEmpty()) {
-			target.setSerotype(Serotype.fromString(source.getSerotypeText()));
-		} else {
-			target.setSerotype(source.getSerotype());
-		}
+		target.setSerotype(resolveSerotype(source.getSerotype(), source.getSerotypeText()));
 		target.setSerotypeText(source.getSerotypeText());

Add the shared helper inside TestReportFacadeEjb:

+	private static Serotype resolveSerotype(Serotype serotype, String serotypeText) {
+		return serotype != null ? serotype : Serotype.fromString(serotypeText);
+	}
+
 	`@LocalBean`
 	`@Stateless`
 	public static class TestReportFacadeEjbLocal extends TestReportFacadeEjb {

Also applies to: 261-266

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

In
`@sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/labmessage/TestReportFacadeEjb.java`
around lines 161 - 166, The mapping currently prefers serotypeText and parses it
with Serotype.fromString(...), which can downgrade an existing typed value to
OTHER; change the logic in TestReportFacadeEjb so you first use
source.getSerotype() if non-null and only fall back to parsing
source.getSerotypeText() when the typed value is null/absent, then always copy
source.getSerotypeText() to target.setSerotypeText(...); update both mapping
sites (the block currently calling
target.setSerotype(Serotype.fromString(source.getSerotypeText())) /
target.setSerotype(source.getSerotype()) and the analogous block around lines
261-266) to follow this ordering and consider extracting a small helper method
to centralize the preference logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In
`@sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/labmessage/TestReportFacadeEjb.java`:
- Around line 161-166: The mapping currently prefers serotypeText and parses it
with Serotype.fromString(...), which can downgrade an existing typed value to
OTHER; change the logic in TestReportFacadeEjb so you first use
source.getSerotype() if non-null and only fall back to parsing
source.getSerotypeText() when the typed value is null/absent, then always copy
source.getSerotypeText() to target.setSerotypeText(...); update both mapping
sites (the block currently calling
target.setSerotype(Serotype.fromString(source.getSerotypeText())) /
target.setSerotype(source.getSerotype()) and the analogous block around lines
261-266) to follow this ordering and consider extracting a small helper method
to centralize the preference logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8b268d14-792f-4be3-aa45-2523c9d19534

📥 Commits

Reviewing files that changed from the base of the PR and between e215482 and e9b45f0.

📒 Files selected for processing (4)
  • sormas-api/src/main/java/de/symeda/sormas/api/epidata/EpiDataDto.java
  • sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/labmessage/TestReportFacadeEjb.java
  • sormas-backend/src/main/resources/sql/sormas_schema.sql
  • sormas-ui/src/main/java/de/symeda/sormas/ui/exposure/ExposureForm.java
🚧 Files skipped from review as they are similar to previous changes (3)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/exposure/ExposureForm.java
  • sormas-backend/src/main/resources/sql/sormas_schema.sql
  • sormas-api/src/main/java/de/symeda/sormas/api/epidata/EpiDataDto.java

@KarnaiahPesula KarnaiahPesula merged commit 1b83f81 into development Apr 23, 2026
7 of 10 checks passed
@KarnaiahPesula KarnaiahPesula deleted the feature-13837-malaria-doctors-declarations branch April 23, 2026 11:31
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.

Implement functionality to receive doctor's declarations for Malaria

2 participants