Skip to content

🐛: FIX: 14130/14136: ngSurvey: Missing facilities, Enhacements Hospitalization handling, customizable fields#14138

Merged
Pa-Touche merged 7 commits into
developmentfrom
fix/14130-facility-facility
Jul 3, 2026
Merged

🐛: FIX: 14130/14136: ngSurvey: Missing facilities, Enhacements Hospitalization handling, customizable fields#14138
Pa-Touche merged 7 commits into
developmentfrom
fix/14130-facility-facility

Conversation

@Pa-Touche

@Pa-Touche Pa-Touche commented Jul 2, 2026

Copy link
Copy Markdown
Contributor
  • Reversed condition for cron activation
  • copy-paste issue in log
  • NPE exception for some occurrences

Fixes #14130
Fixes #14136

Summary by CodeRabbit

  • Bug Fixes
    • Adjusted scheduled survey response fetching so it runs only when external messages are enabled and survey fetching is explicitly set to true.
    • Improved automatic survey response processing: failures now leave responses marked as unprocessed, and related status/log messaging was corrected.
    • Updated facility reference data caching to serve the intended facility set.
    • Fixed customizable-field patching so EPIDATA context values are resolved correctly.
  • New Features
    • Enhanced date patching to accept partial inputs like MM/yyyy (mapped to the first day of the month).
  • Tests
    • Expanded date mapper tests for partial-date formats and additional invalid date cases.

- Reversed condition for cron activation
- copy-paste issue in log
- NPE exception for some occurrences
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Pa-Touche, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 47 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3cdfd50c-1e54-4dc6-9e98-e963f61573cb

📥 Commits

Reviewing files that changed from the base of the PR and between 15007a0 and d215012.

📒 Files selected for processing (3)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/patch/DataPatcherImpl.java
  • sormas-backend/src/main/java/de/symeda/sormas/backend/patch/customizablefield/CustomizableFieldDataPatcher.java
  • sormas-backend/src/test/java/de/symeda/sormas/patch/DataPatcherImplTest.java
📝 Walkthrough

Walkthrough

Backend changes adjust survey-response handling, customizable-field patch dictionary plumbing, and date patch parsing. They also add EPIDATA patch coverage and update tests for the new date behavior.

Changes

Survey processing fixes

Layer / File(s) Summary
Facility reference lookup
sormas-backend/.../ReferenceDataValueInstanceProviderImpl.java
Changes the facility reference supplier to query facilities with getAllAfter(DATE_ALL_VALUES).
Survey fetch guard
sormas-backend/.../CronService.java
Inverts the SURVEY_FETCH_ENABLED check so fetchSurveyResponses() returns early unless the property is true.
Survey response processing status
sormas-backend/.../ExternalMessageFacadeEjb.java, sormas-backend/.../AutomaticSurveyResponseProcessor.java
Treats null processing results as canceled, corrects the interrupted-response log text, and marks external messages UNPROCESSED on runtime failures during automatic processing.

Customizable-field patching

Layer / File(s) Summary
Patch transaction boundary
sormas-backend/.../DataPatcherImpl.java
Adds explicit imports and marks patch(...) as REQUIRES_NEW with rollback on Exception.
Customizable-field UUID suppliers
sormas-backend/.../CustomizableFieldDataPatchRequest.java, sormas-backend/.../DataPatcherImpl.java, sormas-backend/.../CustomizableFieldDataPatcher.java
Changes the entity UUID dictionary to Supplier<String>, builds it from entity cache plus case data, adds EPIDATA UUID support, and resolves suppliers during patching.
Customizable-field patch tests
sormas-backend/.../DataPatcherImplTest.java
Adds EPIDATA patch coverage and refactors helpers to create custom fields and value lookups by context.

Partial date parsing

Layer / File(s) Summary
Partial date mapping
sormas-backend/.../DatePatchMapper.java
Extends date mapping to parse year-only and MM/yyyy inputs, adds month/year parsing support, and removes the null-value short-circuit before conversion.
Date mapper tests
sormas-backend/.../DateMapperTest.java
Updates invalid-date assertions and adds coverage for day/month/year, month/year, and invalid month inputs across Date, LocalDate, and LocalDateTime.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested reviewers: roldy, KarnaiahPesula

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR bundles unrelated cron, date parsing, and custom-field patching changes that are outside #14130. Move the unrelated fixes into separate PRs or link the additional issues in the review scope.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The facility reference-data change aligns with the hospitalisation mapping failure described in #14130.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title is noisy, but it clearly refers to the main fixes around survey handling, facilities, and customizable fields.
Description check ✅ Passed The description matches the required template with a brief change summary and linked issue references.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/14130-facility-facility

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@sormas-backend/src/main/java/de/symeda/sormas/backend/ReferenceDataValueInstanceProviderImpl.java`:
- Around line 58-63: The FacilityReferenceDto lookup in
ReferenceDataValueInstanceProviderImpl is now ambiguous because it returns all
facilities and the downstream getOne/findAny resolution can select an arbitrary
FacilityDto when external IDs are duplicated. Restrict the facility dictionary
to a unique, deterministic set before mapping in the
FacilityFacade/getAllAfter(DATE_ALL_VALUES) path, and make sure the generic
reference resolution logic used by getOne prefers an unambiguous unique key
rather than caption/externalId matching that can return multiple candidates.
🪄 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: 0dfcb58d-7d78-40ef-a940-3f1232a517da

📥 Commits

Reviewing files that changed from the base of the PR and between 0477813 and aa7c1ac.

📒 Files selected for processing (4)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/ReferenceDataValueInstanceProviderImpl.java
  • sormas-backend/src/main/java/de/symeda/sormas/backend/common/CronService.java
  • sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjb.java
  • sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/survey/AutomaticSurveyResponseProcessor.java

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)
sormas-backend/src/main/java/de/symeda/sormas/backend/patch/mapping/impl/valuemapper/DatePatchMapper.java (1)

54-56: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Preserve null-date mapping before calling toString().

Line 56 now crashes for null patch values, but null replacements are allowed by the patch flow and should map as successful null values instead of throwing.

🐛 Proposed fix
 	Object value = request.getValue();
 
+	if (value == null) {
+		return ValueMappingResult.withData(null);
+	}
+
 	String str = value.toString().trim();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@sormas-backend/src/main/java/de/symeda/sormas/backend/patch/mapping/impl/valuemapper/DatePatchMapper.java`
around lines 54 - 56, The DatePatchMapper value handling currently calls
toString() on request.getValue() without guarding null, which breaks null patch
replacements. Update the DatePatchMapper logic so the null-date mapping is
preserved before any toString() call: detect a null value from
request.getValue(), return the successful null mapping path, and only trim/parse
when the value is non-null. Use the DatePatchMapper mapping flow and the
request.getValue() access as the key place to fix this.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@sormas-backend/src/main/java/de/symeda/sormas/backend/patch/mapping/impl/valuemapper/DatePatchMapper.java`:
- Around line 54-56: The DatePatchMapper value handling currently calls
toString() on request.getValue() without guarding null, which breaks null patch
replacements. Update the DatePatchMapper logic so the null-date mapping is
preserved before any toString() call: detect a null value from
request.getValue(), return the successful null mapping path, and only trim/parse
when the value is non-null. Use the DatePatchMapper mapping flow and the
request.getValue() access as the key place to fix this.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d38f944d-fd24-4cbb-a4a0-66ed166bdc9d

📥 Commits

Reviewing files that changed from the base of the PR and between aa7c1ac and d5ba929.

📒 Files selected for processing (4)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/patch/DataPatcherImpl.java
  • sormas-backend/src/main/java/de/symeda/sormas/backend/patch/mapping/impl/valuemapper/DatePatchMapper.java
  • sormas-backend/src/test/java/de/symeda/sormas/backend/patch/mapping/impl/valuemapper/DateMapperTest.java
  • sormas-backend/src/test/java/de/symeda/sormas/patch/DataPatcherImplTest.java
✅ Files skipped from review due to trivial changes (1)
  • sormas-backend/src/test/java/de/symeda/sormas/patch/DataPatcherImplTest.java

@Pa-Touche Pa-Touche changed the title 🐛: FIX: Only facilities without regions/districts can be patched. 🐛: FIX: 14130/14136: ngSurvey: Missing facilities, Enhacements Hospitalization handling, customizable fields Jul 3, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (2)
sormas-backend/src/main/java/de/symeda/sormas/backend/patch/DataPatcherImpl.java (2)

190-216: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Custom exposure fields still need a UUID seed. buildEntityUuidDictionaryFrom only populates from entityCache and only backfills EPIDATA; a request with only Custom.Exposure.* fields can still reach entityUuidDictionary.get(...).get() with no exposure entry and NPE. The broader Immunization example doesn’t apply here; this patcher only maps CASE, EPIDATA, and EXPOSURE. Resolve the exposure target before building this dictionary instead of special-casing only EPIDATA.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@sormas-backend/src/main/java/de/symeda/sormas/backend/patch/DataPatcherImpl.java`
around lines 190 - 216, The UUID dictionary builder in DataPatcherImpl only
backfills EPIDATA, so Custom.Exposure fields can still miss a UUID seed and
later fail when entityUuidDictionary is read. Update
buildEntityUuidDictionaryFrom to also resolve and include the EXPOSURE entity
UUID from caseData before returning the map, instead of special-casing only
CustomizableFieldContext.EPIDATA. Use the existing
CustomizableFieldContextPatchMapping and CustomizableContextIndexKey flow so
both EPIDATA and EXPOSURE contexts are present whenever requested.

111-115: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Keep patching idempotent across retries. Moving patch() to REQUIRES_NEW lets it commit even if survey-message persistence later rolls back, so a retry can apply the same response again; when replacementStrategy is ALWAYS, that can create duplicate child records. Consider keeping the whole flow in one transaction or adding a deduplication guard.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@sormas-backend/src/main/java/de/symeda/sormas/backend/patch/DataPatcherImpl.java`
around lines 111 - 115, The patch flow in DataPatcherImpl.patch is no longer
safely idempotent across retries because the REQUIRES_NEW transaction can commit
the response before later survey-message persistence rolls back. Keep the full
patch-and-persist flow in a single transaction, or add a deduplication guard in
patch() and the ALWAYS replacementStrategy path so repeated retries cannot
create duplicate child records.
🧹 Nitpick comments (1)
sormas-backend/src/test/java/de/symeda/sormas/patch/DataPatcherImplTest.java (1)

1179-1204: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding an update-path assertion and group-context "alone" coverage.

This test only covers the initial-write path for EPIDATA (unlike patch_customizableField_text, which also verifies an override). More importantly, given the DataPatcherImpl fix is EPIDATA-specific, consider adding a test for a group-based context (e.g., Exposure) patched via customizable fields only, with no companion plain field, to confirm whether the same NPE risk exists there.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sormas-backend/src/test/java/de/symeda/sormas/patch/DataPatcherImplTest.java`
around lines 1179 - 1204, This EPIDATA test only covers the initial create/write
path in DataPatcherImplTest.patch_customizableField_text_epidata; add an
update-path assertion like the existing patch_customizableField_text test so the
field is patched twice and the replacement behavior is verified. Also add a
separate customizable-fields-only test for a group-based context such as
Exposure using the same patch flow but without any plain companion field, to
exercise the path in DataPatcherImpl and confirm the NPE fix does not regress
there.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@sormas-backend/src/main/java/de/symeda/sormas/backend/patch/DataPatcherImpl.java`:
- Around line 190-216: The UUID dictionary builder in DataPatcherImpl only
backfills EPIDATA, so Custom.Exposure fields can still miss a UUID seed and
later fail when entityUuidDictionary is read. Update
buildEntityUuidDictionaryFrom to also resolve and include the EXPOSURE entity
UUID from caseData before returning the map, instead of special-casing only
CustomizableFieldContext.EPIDATA. Use the existing
CustomizableFieldContextPatchMapping and CustomizableContextIndexKey flow so
both EPIDATA and EXPOSURE contexts are present whenever requested.
- Around line 111-115: The patch flow in DataPatcherImpl.patch is no longer
safely idempotent across retries because the REQUIRES_NEW transaction can commit
the response before later survey-message persistence rolls back. Keep the full
patch-and-persist flow in a single transaction, or add a deduplication guard in
patch() and the ALWAYS replacementStrategy path so repeated retries cannot
create duplicate child records.

---

Nitpick comments:
In
`@sormas-backend/src/test/java/de/symeda/sormas/patch/DataPatcherImplTest.java`:
- Around line 1179-1204: This EPIDATA test only covers the initial create/write
path in DataPatcherImplTest.patch_customizableField_text_epidata; add an
update-path assertion like the existing patch_customizableField_text test so the
field is patched twice and the replacement behavior is verified. Also add a
separate customizable-fields-only test for a group-based context such as
Exposure using the same patch flow but without any plain companion field, to
exercise the path in DataPatcherImpl and confirm the NPE fix does not regress
there.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: aee25f76-b3bd-4f8d-8a8e-86893c4bacd9

📥 Commits

Reviewing files that changed from the base of the PR and between 2a1b1f3 and 15007a0.

📒 Files selected for processing (4)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/patch/DataPatcherImpl.java
  • sormas-backend/src/main/java/de/symeda/sormas/backend/patch/customizablefield/CustomizableFieldDataPatchRequest.java
  • sormas-backend/src/main/java/de/symeda/sormas/backend/patch/customizablefield/CustomizableFieldDataPatcher.java
  • sormas-backend/src/test/java/de/symeda/sormas/patch/DataPatcherImplTest.java

@Pa-Touche Pa-Touche requested a review from KarnaiahPesula July 3, 2026 12:30
@Pa-Touche Pa-Touche merged commit 9d5d562 into development Jul 3, 2026
7 checks passed
@Pa-Touche Pa-Touche deleted the fix/14130-facility-facility branch July 3, 2026 13:17
@Pa-Touche Pa-Touche self-assigned this Jul 6, 2026
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.

Survey Intergation _ difficulty to process survey response Survey Tool: the mapping for Hospitalisation is not working

2 participants