Skip to content

Adds Salmonellosis disease in relation to exposure, symptoms & Hospitalization#13921

Open
roldy wants to merge 8 commits intodevelopmentfrom
feature-13917-salmonellosis-exposure
Open

Adds Salmonellosis disease in relation to exposure, symptoms & Hospitalization#13921
roldy wants to merge 8 commits intodevelopmentfrom
feature-13917-salmonellosis-exposure

Conversation

@roldy
Copy link
Copy Markdown
Contributor

@roldy roldy commented Apr 30, 2026

Fixes #13914, #13915, #13916

Summary by CodeRabbit

  • New Features
    • Added Salmonellosis disease support with specialized epidemiological data fields.
    • New date range fields for tracking exposure investigation and activity-as-case periods.
    • Added eating out venue categories and food shopping details for exposure documentation.
    • Three new symptoms introduced: constipation, dysuria, and eye irritation (available in Luxembourg).

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

Warning

Rate limit exceeded

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

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ 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: 3cea0c15-7eaa-436b-b26e-5ba4be32136a

📥 Commits

Reviewing files that changed from the base of the PR and between 6f24690 and eae51b7.

📒 Files selected for processing (7)
  • sormas-api/src/main/java/de/symeda/sormas/api/epidata/EpiDataDto.java
  • sormas-backend/src/main/resources/sql/sormas_schema.sql
  • sormas-ui/src/main/java/de/symeda/sormas/ui/epidata/EpiDataForm.java
  • sormas-ui/src/main/java/de/symeda/sormas/ui/hospitalization/HospitalizationForm.java
  • sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java
  • sormas-ui/src/main/java/de/symeda/sormas/ui/utils/CssStyles.java
  • sormas-ui/src/main/webapp/VAADIN/themes/sormas/views/disease.scss
📝 Walkthrough

Walkthrough

This pull request introduces comprehensive Salmonellosis disease surveillance support to SORMAS for Luxembourg. It adds a new SALMONELLOSIS disease enum entry, extends epidemiological investigation data with date-range fields, introduces a new EatingOutVenue enum for food exposure tracking, adds three new symptoms (constipation, dysuria, eye irritation), and updates related DTOs, backend entities, database schema, UI forms, and localization resources to accommodate the disease across case management, exposure investigation, and symptom tracking workflows.

Changes

Cohort / File(s) Summary
Disease Definition
sormas-api/src/main/java/de/symeda/sormas/api/Disease.java, sormas-api/src/main/resources/enum.properties, sormas-api/src/main/resources/captions.properties
Adds SALMONELLOSIS enum constant to Disease with corresponding property file entries for full and short form captions.
EpiData Investigation Fields
sormas-api/src/main/java/de/symeda/sormas/api/epidata/EpiDataDto.java, 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-ui/src/main/java/de/symeda/sormas/ui/epidata/EpiDataForm.java
Adds four date-range fields (exposure investigation from/to, activity-as-case from/to) across DTO, entity, facade mapping, and UI form; updates disease annotations for importedCase and country fields to include SALMONELLOSIS.
Exposure Food-Related Fields
sormas-api/src/main/java/de/symeda/sormas/api/exposure/EatingOutVenue.java, sormas-api/src/main/java/de/symeda/sormas/api/exposure/ExposureDto.java, sormas-api/src/main/java/de/symeda/sormas/api/exposure/ExposureSubSetting.java, sormas-backend/src/main/java/de/symeda/sormas/backend/exposure/Exposure.java, sormas-backend/src/main/java/de/symeda/sormas/backend/epidata/EpiDataFacadeEjb.java, sormas-ui/src/main/java/de/symeda/sormas/ui/exposure/ExposureForm.java
Introduces new EatingOutVenue enum with 18 venue categories, adds SHOPPING_FOR_FOOD exposure sub-setting, extends ExposureDto/entity with eating-out venues set and food-shopping detail fields, implements conditional visibility and multi-select UI with dependent "other" field.
Symptoms
sormas-api/src/main/java/de/symeda/sormas/api/symptoms/SymptomsDto.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-ui/src/main/java/de/symeda/sormas/ui/symptoms/SymptomsForm.java
Adds three new symptoms (constipation, dysuria, eyeIrritation) with Salmonellosis-specific disease/country constraints, includes bidirectional DTO↔entity mapping, and updates UI form to include these fields in symptom layout and handling.
Cross-Cutting Disease Annotations
sormas-api/src/main/java/de/symeda/sormas/api/person/PersonDto.java, sormas-api/src/main/java/de/symeda/sormas/api/hospitalization/HospitalizationDto.java, sormas-ui/src/main/java/de/symeda/sormas/ui/hospitalization/HospitalizationForm.java, sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java
Extends @Diseases annotations for workPlace fields to include SALMONELLOSIS; updates stillHospitalized field and hospitalization form logic to treat Salmonellosis same as RSV/giardiasis/cryptosporidiosis; adds conditional workplace field visibility for Luxembourg/Salmonellosis.
Localization
sormas-api/src/main/resources/captions.properties, sormas-api/src/main/resources/enum.properties
Adds 11 new caption keys for investigation dates, exposure details, and symptoms; adds 18 EatingOutVenue enum captions and fixes file formatting issues.
Database Schema
sormas-backend/src/main/resources/sql/sormas_schema.sql
Adds diseaseconfiguration row for SALMONELLOSIS, creates four investigation/activity date columns in epidata/epidata_history, adds eating-out fields and new exposures_eatingoutvenues join table with history tracking, adds three symptom columns to symptoms/symptoms_history, records migrations via schema versions 625–628.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • raulbob
  • obinna-h-n
  • KarnaiahPesula

🐰 In Luxembourg, the salmonella hops along,
New venues for food and dates all day long,
From constipation to eyes that may sting,
The surveys grow richer—what data we'll bring!
Four dates and some venues, a foodborne delight,
Our schema's expanded; the tracking's just right! 🥗✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: adding Salmonellosis disease support across exposure, symptoms, and hospitalization features.
Description check ✅ Passed The description references three linked issues (#13914, #13915, #13916) following the required template format, though minimal detail is provided beyond issue numbers.
Linked Issues check ✅ Passed The PR successfully implements Salmonellosis disease registration and integrates it across EpiData, Symptoms, Exposure, and Hospitalization features as required by the primary objective in #13914.
Out of Scope Changes check ✅ Passed All changes are directly related to Salmonellosis integration: disease enum addition, epidemiological data fields, symptom tracking, exposure details, and database schema updates align with the linked objectives.

✏️ 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-13917-salmonellosis-exposure

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
Review rate limit: 0/1 reviews remaining, refill in 9 minutes and 22 seconds.

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

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/exposure/ExposureForm.java (1)

327-440: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Existing eating-out data can be silently cleared on edit

The new fields are cleared by the sub-settings listener during setValue re-initialization, but they are never restored afterward. This can null out existing EATING_OUT_VENUES, EATING_OUT_VENUE_OTHER, and SHOPPING_FOR_FOOD_DETAILS on save.

💡 Suggested fix
@@
-		OptionGroup eatingOutVenuesField = addField(exposureDetailsLayout, ExposureDto.EATING_OUT_VENUES, OptionGroup.class);
+		eatingOutVenuesField = addField(exposureDetailsLayout, ExposureDto.EATING_OUT_VENUES, OptionGroup.class);
@@
-		TextField eatingOutVenueOtherField = addField(exposureDetailsLayout, ExposureDto.EATING_OUT_VENUE_OTHER, TextField.class);
+		eatingOutVenueOtherField = addField(exposureDetailsLayout, ExposureDto.EATING_OUT_VENUE_OTHER, TextField.class);
@@
-		TextField shoppingForFoodDetailsField = addField(exposureDetailsLayout, ExposureDto.SHOPPING_FOR_FOOD_DETAILS, TextField.class);
+		shoppingForFoodDetailsField = addField(exposureDetailsLayout, ExposureDto.SHOPPING_FOR_FOOD_DETAILS, TextField.class);
@@
-			TravelPurpose travelPurpose = newFieldValue.getTravelPurpose();
+			TravelPurpose travelPurpose = newFieldValue.getTravelPurpose();
 			String travelPurposeDetails = newFieldValue.getTravelPurposeDetails();
+			Set<EatingOutVenue> eatingOutVenues = newFieldValue.getEatingOutVenues();
+			String eatingOutVenueOther = newFieldValue.getEatingOutVenueOther();
+			String shoppingForFoodDetails = newFieldValue.getShoppingForFoodDetails();
@@
 			if (subSettings != null && !subSettings.isEmpty()) {
 				subSettingsField.setValue(subSettings);
 			}
+			boolean hasEatingOutside = subSettings != null && subSettings.contains(ExposureSubSetting.EATING_OUTSIDE);
+			eatingOutVenuesField.setVisible(hasEatingOutside);
+			if (hasEatingOutside && eatingOutVenues != null && !eatingOutVenues.isEmpty()) {
+				eatingOutVenuesField.setValue(eatingOutVenues);
+			}
+			boolean hasEatingOutOther = eatingOutVenues != null && eatingOutVenues.contains(EatingOutVenue.OTHER);
+			eatingOutVenueOtherField.setVisible(hasEatingOutside && hasEatingOutOther);
+			eatingOutVenueOtherField.setValue(hasEatingOutside && hasEatingOutOther ? eatingOutVenueOther : null);
+
+			boolean hasShoppingForFood = subSettings != null && subSettings.contains(ExposureSubSetting.SHOPPING_FOR_FOOD);
+			shoppingForFoodDetailsField.setVisible(hasShoppingForFood);
+			shoppingForFoodDetailsField.setValue(hasShoppingForFood ? shoppingForFoodDetails : null);
🤖 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/exposure/ExposureForm.java`
around lines 327 - 440, The subSettingsField listener clears
eatingOutVenuesField, eatingOutVenueOtherField and shoppingForFoodDetailsField
during setValue re-initialization but nothing restores them afterward; fix by,
after loading the DTO into the form (or after setValue), re-applying the same
visibility/value restoration logic used in the subSettingsField listener: read
the current subSettings (subSettingsField.getValue()), compute
showEatingOutVenues and showShoppingForFood, set
eatingOutVenuesField.setVisible(...), eatingOutVenuesField.setValue(...) from
the DTO if present, set eatingOutVenueOtherField visibility/value based on
whether EatingOutVenue.OTHER is selected, and set shoppingForFoodDetailsField
visibility/value from the DTO; you can centralize this into a helper method
(e.g., restoreEatingOutAndShoppingFields) and call it from the form
initialization path so eatingOut fields are not lost on edit/save.
sormas-api/src/main/java/de/symeda/sormas/api/symptoms/SymptomsDto.java (1)

405-430: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

SALMONELLOSIS rollout is incomplete for onset capture fields.

You added SALMONELLOSIS to many symptom fields, but onsetDate and onsetSymptom still don’t include it (Line 1391 and Line 1461 blocks). That prevents capturing core onset data for Salmonellosis cases.

Suggested fix
@@
 	`@Diseases`({
 		AFP,
 		CHOLERA,
@@
 		PERTUSSIS,
+		SALMONELLOSIS,
 		GIARDIASIS,
 		CRYPTOSPORIDIOSIS })
 	`@HideForCountries`
 	`@Outbreaks`
 	private Date onsetDate;
@@
 	`@Diseases`({
 		AFP,
 		CHOLERA,
@@
 		INVASIVE_PNEUMOCOCCAL_INFECTION,
 		FHA,
+		SALMONELLOSIS,
 		PERTUSSIS })
 	`@HideForCountries`
 	`@Size`(max = FieldConstraints.CHARACTER_LIMIT_DEFAULT, message = Validations.textTooLong)
 	private String onsetSymptom;

Also applies to: 494-495, 692-693, 716-717, 847-848, 906-907, 995-996, 1299-1300, 1327-1328, 1591-1592, 1615-1616, 1822-1823, 2106-2107

🤖 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/symptoms/SymptomsDto.java`
around lines 405 - 430, The SALMONELLOSIS enum was added to many symptom
`@Diseases` lists but not added to the corresponding onset capture lists; update
the SymptomsDto entries that define onsetDate and onsetSymptom (the
fields/methods named onsetDate and onsetSymptom within SymptomsDto) to include
SALMONELLOSIS in their `@Diseases` annotations so onsetDate/onsetSymptom capture
Salmonellosis cases as well; mirror the same inclusion pattern used for other
symptoms (add SALMONELLOSIS to the same disease arrays where related symptoms
include it).
🤖 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/Disease.java`:
- Line 93: The new enum constant SALMONELLOSIS was added to Disease but
CssStyles.getDiseaseCssClass lacks a corresponding case, causing a fallback to
background-disease-undefined; update the switch in CssStyles.getDiseaseCssClass
to add a case for Disease.SALMONELLOSIS that returns the intended CSS class
(e.g., "background-disease-salmonellosis" or your project's naming convention),
ensuring the method handles this value like the other disease cases.

In `@sormas-backend/src/main/java/de/symeda/sormas/backend/epidata/EpiData.java`:
- Around line 316-327: The setters for the exposure investigation range
currently allow inverted intervals; update setExposureInvestigationFromDate(Date
exposureInvestigationFromDate) and setExposureInvestigationToDate(Date
exposureInvestigationToDate) (and the other analogous date-range setter pairs in
this class) to enforce from <= to by normalizing inputs: if the counterpart date
is non-null and the new value would invert the interval, swap the two values
(i.e., set the earlier date to the min and the later to the max) before
assigning fields; implement this logic inside each setter so persistence via
imports/API cannot create inverted ranges.

In `@sormas-backend/src/main/resources/sql/sormas_schema.sql`:
- Around line 15861-15865: The delete-history trigger call references a
non-existent key column 'id' for the exposures_eatingoutvenues table; update the
trigger invocation delete_history_trigger('exposures_eatingoutvenues_history',
'id') to use the actual key column name used by the table (exposure_id) or the
correct composite/primary key if different, ensuring the history trigger refers
to exposure_id to match the table schema (look for exposures_eatingoutvenues and
its delete_history_trigger registration).

In `@sormas-ui/src/main/java/de/symeda/sormas/ui/epidata/EpiDataForm.java`:
- Around line 256-259: The activity-as-case date fields
EpiDataDto.ACTIVITY_AS_CASE_FROM_DATE and EpiDataDto.ACTIVITY_AS_CASE_TO_DATE
are being added unconditionally; scope their addField calls to the same
case-only branch used elsewhere by checking parentClass == CaseDataDto before
calling addField (i.e., move or wrap the
addField(EpiDataDto.ACTIVITY_AS_CASE_FROM_DATE, DateField.class) and
addField(EpiDataDto.ACTIVITY_AS_CASE_TO_DATE, DateField.class) inside the
existing parentClass == CaseDataDto block so these fields are only registered
for CaseDataDto contexts).

In
`@sormas-ui/src/main/java/de/symeda/sormas/ui/hospitalization/HospitalizationForm.java`:
- Line 176: In HospitalizationForm ensure Salmonellosis participates in the ICU
visibility gate: remove Disease.SALMONELLOSIS from the exclusion List.of(...)
check (the one comparing caze.getDisease()) or alternatively add
Disease.SALMONELLOSIS to the earlier allowed set that controls visibility so
that INTENSIVE_CARE_UNIT, INTENSIVE_CARE_UNIT_START and INTENSIVE_CARE_UNIT_END
are shown for Salmonellosis; update the logic around the caze disease checks so
both the earlier visibility branch and the later List.of(...) check are
consistent.

In `@sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java`:
- Around line 528-531: When hiding the enum field PersonDto.WORK_PLACE for
Luxembourg Salmonellosis (the isLuxSalmonellosis branch), clear any existing
value so stale enum data cannot persist while only PersonDto.WORK_PLACE_TEXT is
edited; after calling setVisible(false, PersonDto.WORK_PLACE) reset/clear the
underlying value (e.g., set the WORK_PLACE field value to null via the field or
DTO) before making PersonDto.WORK_PLACE_TEXT visible.

---

Outside diff comments:
In `@sormas-api/src/main/java/de/symeda/sormas/api/symptoms/SymptomsDto.java`:
- Around line 405-430: The SALMONELLOSIS enum was added to many symptom
`@Diseases` lists but not added to the corresponding onset capture lists; update
the SymptomsDto entries that define onsetDate and onsetSymptom (the
fields/methods named onsetDate and onsetSymptom within SymptomsDto) to include
SALMONELLOSIS in their `@Diseases` annotations so onsetDate/onsetSymptom capture
Salmonellosis cases as well; mirror the same inclusion pattern used for other
symptoms (add SALMONELLOSIS to the same disease arrays where related symptoms
include it).

In `@sormas-ui/src/main/java/de/symeda/sormas/ui/exposure/ExposureForm.java`:
- Around line 327-440: The subSettingsField listener clears
eatingOutVenuesField, eatingOutVenueOtherField and shoppingForFoodDetailsField
during setValue re-initialization but nothing restores them afterward; fix by,
after loading the DTO into the form (or after setValue), re-applying the same
visibility/value restoration logic used in the subSettingsField listener: read
the current subSettings (subSettingsField.getValue()), compute
showEatingOutVenues and showShoppingForFood, set
eatingOutVenuesField.setVisible(...), eatingOutVenuesField.setValue(...) from
the DTO if present, set eatingOutVenueOtherField visibility/value based on
whether EatingOutVenue.OTHER is selected, and set shoppingForFoodDetailsField
visibility/value from the DTO; you can centralize this into a helper method
(e.g., restoreEatingOutAndShoppingFields) and call it from the form
initialization path so eatingOut fields are not lost on edit/save.
🪄 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: 17348764-684a-46f3-845c-72bd4dc96935

📥 Commits

Reviewing files that changed from the base of the PR and between 5ba0cd0 and 6f24690.

📒 Files selected for processing (22)
  • sormas-api/src/main/java/de/symeda/sormas/api/Disease.java
  • sormas-api/src/main/java/de/symeda/sormas/api/epidata/EpiDataDto.java
  • sormas-api/src/main/java/de/symeda/sormas/api/exposure/EatingOutVenue.java
  • sormas-api/src/main/java/de/symeda/sormas/api/exposure/ExposureDto.java
  • sormas-api/src/main/java/de/symeda/sormas/api/exposure/ExposureSubSetting.java
  • sormas-api/src/main/java/de/symeda/sormas/api/hospitalization/HospitalizationDto.java
  • sormas-api/src/main/java/de/symeda/sormas/api/i18n/Captions.java
  • sormas-api/src/main/java/de/symeda/sormas/api/person/PersonDto.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-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/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-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/hospitalization/HospitalizationForm.java
  • sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java
  • sormas-ui/src/main/java/de/symeda/sormas/ui/symptoms/SymptomsForm.java

Comment thread sormas-api/src/main/java/de/symeda/sormas/api/Disease.java
Comment thread sormas-backend/src/main/resources/sql/sormas_schema.sql
Comment thread sormas-ui/src/main/java/de/symeda/sormas/ui/epidata/EpiDataForm.java Outdated
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.

Add Salmonellosis disease case surveillance to SORMAS (Luxembourg)

1 participant