Skip to content

Conversation

@obinna-h-n
Copy link
Contributor

@obinna-h-n obinna-h-n commented Nov 10, 2025

Fixes #13631

Summary by CodeRabbit

  • New Features
    • Added Epipulse export functionality for disease case-based reporting with status tracking (pending, in-progress, completed, failed, cancelled).
    • Introduced NUTS code fields for geographic entities (Community, Country, District, Region).
    • Added new user permissions for Epipulse export operations (view, create, download, delete).
    • Implemented export management interface with filtering, scheduling, and file download capabilities.

@obinna-h-n obinna-h-n merged commit f234482 into development Nov 10, 2025
3 of 8 checks passed
@obinna-h-n obinna-h-n deleted the feature-13631-epipulse-export-module branch November 10, 2025 09:24
@coderabbitai
Copy link

coderabbitai bot commented Nov 10, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This pull request introduces a comprehensive Epipulse export module enabling SORMAS to export disease surveillance data (specifically Pertussis) to the European Centre for Disease Prevention and Control's EpiPulse platform. It includes API contracts, backend services with scheduling, database schema, and a complete UI layer for managing exports with filtering, creation, cancellation, and download capabilities across disease-specific reporting periods.

Changes

Cohort / File(s) Summary
API: Core Epipulse Contracts
sormas-api/src/main/java/de/symeda/sormas/api/epipulse/{EpipulseDiseaseExportFacade, EpipulseExportFacade, EpipulseExportCriteria}.java
Remote EJB facades defining export operations and filtering criteria
API: Epipulse DTOs
sormas-api/src/main/java/de/symeda/sormas/api/epipulse/{EpipulseDiseaseExportEntryDto, EpipulseDiseaseExportResult, EpipulseExportDto, EpipulseExportIndexDto, EpipulseExportReferenceDto}.java
Data transfer objects for export entries, results, and index views with CSV generation logic
API: Epipulse Support DTOs
sormas-api/src/main/java/de/symeda/sormas/api/epipulse/{EpipulseHospitalizationCheckDto, EpipulseImmunizationCheckDto, EpipulsePathogentTestCheckDto, EpipulseVaccinationCheckDto}.java
Nested DTOs for hospitalization, immunization, pathogen tests, and vaccination data
API: Epipulse Enums
sormas-api/src/main/java/de/symeda/sormas/api/epipulse/{EpipulseExportStatus, EpipulseSubjectCode}.java
Status and subject code enumerations for export tracking and disease mapping
API: Epipulse Reference Mappings
sormas-api/src/main/java/de/symeda/sormas/api/epipulse/referencevalue/{EpipulseCaseClassificationRef, EpipulseCaseOutcomeRef, EpipulseDiseaseRef, EpipulseGenderRef, EpipulsePathogenTestTypeRef, EpipulseStatusRef, EpipulseVaccinationStatusRef}.java
Reference mappings between Epipulse and SORMAS enumerations
API: Infrastructure Extensions
sormas-api/src/main/java/de/symeda/sormas/api/infrastructure/{community/CommunityDto, country/{CountryDto, CountryIndexDto}, district/{DistrictDto, DistrictIndexDto}, region/{RegionDto, RegionIndexDto}}.java
Added NUTS code fields to geographic entities
API: Access Control
sormas-api/src/main/java/de/symeda/sormas/api/user/{UserRight, UserRightGroup, FeatureType}.java
New user rights for Epipulse export operations and feature flag
API: i18n
sormas-api/src/main/java/de/symeda/sormas/api/i18n/{Captions, Strings}.java
sormas-api/src/main/resources/{captions, enum, strings}.properties
Internationalization strings, captions, and enum labels for UI and export metadata
API: Utilities
sormas-api/src/main/java/de/symeda/sormas/api/utils/DateHelper.java
sormas-api/src/main/java/de/symeda/sormas/api/FacadeProvider.java
Added date formatting utility and new facade accessor
Backend: JPA Entities
sormas-backend/src/main/java/de/symeda/sormas/backend/epipulse/{EpipulseExport, EpipulseDatasourceConfiguration, EpipulseLocationConfiguration, EpipulseSubjectcodeConfiguration}.java
Database entities for export records and reference configurations
Backend: EJB Facades
sormas-backend/src/main/java/de/symeda/sormas/backend/epipulse/{EpipulseExportFacadeEjb, EpipulseDiseaseExportFacadeEjb}.java
Stateless EJB implementations for export lifecycle management and disease export execution
Backend: Services
sormas-backend/src/main/java/de/symeda/sormas/backend/epipulse/{EpipulseExportService, EpipulseDiseaseExportService, EpipulseExportTimerEjb}.java
Business logic for export filtering, status updates, CSV generation, and async scheduling
Backend: Query Helpers
sormas-backend/src/main/java/de/symeda/sormas/backend/epipulse/{EpipulseExportQueryContext, EpipulseExportJoins, EpipulseExportIndexDtoResultTransformer}.java
JPA criteria query construction and result mapping utilities
Backend: Infrastructure Extensions
sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/{community/{Community, CommunityFacadeEjb, CommunityService}, country/{Country, CountryFacadeEjb}, district/{District, DistrictFacadeEjb}, region/{Region, RegionFacadeEjb}}.java
NUTS code property propagation through entities and facades
Backend: Database Schema
sormas-backend/src/main/resources/META-INF/persistence.xml
sormas-backend/src/main/resources/sql/sormas_schema.sql
New JPA entity mappings and database tables/columns for Epipulse exports and NUTS codes
UI: Controller & Forms
sormas-ui/src/main/java/de/symeda/sormas/ui/epipulse/{EpiPulseExportController, EpipulseEditForm}.java
Export creation, cancellation, deletion, and download orchestration
UI: Grid & Components
sormas-ui/src/main/java/de/symeda/sormas/ui/epipulse/{EpipulseExportGrid, EpipulseExportGridComponent, EpipulseExportGridFilterForm, EpipulseExportInfoLayout}.java
Vaadin grid, filtering, and detail display components with localization and lazy loading
UI: View
sormas-ui/src/main/java/de/symeda/sormas/ui/epipulse/EpipulseExportView.java
Statistics view for export management with menu integration and polling support
UI: Infrastructure Extensions
sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/{CommunitiesGrid, CommunityEditForm, CountriesGrid, CountryEditForm, DistrictEditForm, DistrictsGrid, RegionEditForm, RegionsGrid}.java
Added NUTS code columns and fields to geographic data management UIs
UI: Integration & Styling
sormas-ui/src/main/java/de/symeda/sormas/ui/{ControllerProvider, statistics/{AbstractStatisticsView, StatisticsController}, utils/{CssStyles, AbstractFilterForm, components/{ApplyResetButtonsComponent, FormActionButtonsComponent}}}.java
sormas-ui/src/main/webapp/VAADIN/themes/sormas/components/grid.scss
Controller wiring, menu integration, CSS classes for status styling, and component accessor methods

Sequence Diagram(s)

sequenceDiagram
    participant User as User (UI)
    participant Controller as EpiPulseExportController
    participant Facade as EpipulseExportFacadeEjb
    participant Timer as EpipulseExportTimerEjb
    participant DiseaseExport as EpipulseDiseaseExportFacadeEjb
    participant Service as EpipulseDiseaseExportService
    participant DB as Database

    User->>Controller: create(callback)
    Controller->>Facade: saveEpipulseExport(dto)
    Facade->>DB: persist EpipulseExport (PENDING)
    Facade-->>Controller: ✓ saved
    Controller->>Timer: scheduleExportDisease(uuid, PERT)
    Timer->>Timer: schedule delayed timer (60s)
    Note over Timer: After delay...
    Timer->>DiseaseExport: exportPertussisCaseBased(uuid)
    DiseaseExport->>Service: exportPertussisCaseBased(exportDto)
    Service->>DB: fetch case data via SQL
    Service->>Service: transform to CSV entries
    Service->>Service: write CSV file
    Service-->>DiseaseExport: EpipulseDiseaseExportResult
    DiseaseExport->>Facade: updateStatusForBackgroundProcess(IN_PROGRESS→COMPLETED)
    Facade->>DB: update status, file metadata
    User->>Controller: view(exportIndexDto)
    Controller->>Facade: getEpiPulseExportByUuid(uuid)
    Facade-->>Controller: EpipulseExportDto
    Note over Controller: Show detail with status
    alt Status is COMPLETED
        User->>Controller: download(exportIndexDto)
        Controller->>Controller: validate file
        Controller-->>User: StreamResource (CSV)
    else Status is PENDING/IN_PROGRESS
        User->>Controller: cancel action
        Controller->>Facade: cancelEpipulseExport(uuid)
        Facade->>DB: update status to CANCELLED
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring particular attention:

  • EpipulseDiseaseExportEntryDto (calculateAge(), getPathogenDetectionMethodsForCsv(), getVaccinationStatusForCsv(), parsing helpers): Complex date/age calculations, nullable handling, and CSV value derivation logic needs validation
  • EpipulseDiseaseExportService: Large native SQL query aggregating case data with joins across cases, samples, immunizations, vaccinations—verify correctness of joins and data transformation mappings
  • EpipulseExportFacadeEjb: Full CRUD with complex criteria-based JPA queries; validate filtering logic, especially for status transitions and relevance status handling
  • Database schema (sormas_schema.sql): Verify foreign key constraints, column naming consistency, and proper index placement on frequently queried fields
  • EpipulseExportTimerEjb: Note timing constant EXPORT_DELAY_MS = 60000 (60 seconds) contradicts comment claiming "5 seconds"; verify intended delay and exception handling in exportDiseaseTimeout
  • File download path handling (EpiPulseExportController): Ensure path construction and file existence checks prevent directory traversal or missing file errors
  • EpipulseExportGrid: Complex Vaadin grid configuration with renderers, style generators, and lazy loading—verify proper data provider wiring and column type handling

Possibly related issues

  • Epipulse export implementation for Pertussis #13634: Epipulse export for Pertussis — The PR fully implements Pertussis case-based export via EpipulseDiseaseExportFacadeEjb.exportPertussisCaseBased() and corresponding service layer, directly addressing this requirement with complete data transformation and CSV generation.

Suggested reviewers

  • raulbob
  • KarnaiahPesula

Poem

🐰 A bundle so grand, with exports so clean,
Epipulse data flows in SQL's keen stream,
NUTS codes and timers, DTOs galore,
Backend to UI, this feature's no bore!
CSV files dance, with CSV grace,
SORMAS now speaks to the EU with pride!

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature-13631-epipulse-export-module

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 21b4c01 and 79aab9e.

📒 Files selected for processing (84)
  • sormas-api/src/main/java/de/symeda/sormas/api/FacadeProvider.java (2 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/EpipulseDiseaseExportEntryDto.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/EpipulseDiseaseExportFacade.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/EpipulseDiseaseExportResult.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/EpipulseExportCriteria.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/EpipulseExportDto.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/EpipulseExportFacade.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/EpipulseExportIndexDto.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/EpipulseExportReferenceDto.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/EpipulseExportStatus.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/EpipulseHospitalizationCheckDto.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/EpipulseImmunizationCheckDto.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/EpipulsePathogentTestCheckDto.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/EpipulseSubjectCode.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/EpipulseVaccinationCheckDto.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/referencevalue/EpipulseCaseClassificationRef.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/referencevalue/EpipulseCaseOutcomeRef.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/referencevalue/EpipulseDiseaseRef.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/referencevalue/EpipulseGenderRef.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/referencevalue/EpipulsePathogenTestTypeRef.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/referencevalue/EpipulseStatusRef.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/epipulse/referencevalue/EpipulseVaccinationStatusRef.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/feature/FeatureType.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/i18n/Captions.java (7 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/i18n/Strings.java (7 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/infrastructure/community/CommunityDto.java (3 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/infrastructure/country/CountryDto.java (4 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/infrastructure/country/CountryIndexDto.java (3 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/infrastructure/district/DistrictDto.java (3 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/infrastructure/district/DistrictIndexDto.java (3 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/infrastructure/region/RegionDto.java (3 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/infrastructure/region/RegionIndexDto.java (3 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/user/UserRight.java (2 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/user/UserRightGroup.java (1 hunks)
  • sormas-api/src/main/java/de/symeda/sormas/api/utils/DateHelper.java (4 hunks)
  • sormas-api/src/main/resources/captions.properties (7 hunks)
  • sormas-api/src/main/resources/enum.properties (4 hunks)
  • sormas-api/src/main/resources/strings.properties (2 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/epipulse/EpipulseDatasourceConfiguration.java (1 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/epipulse/EpipulseDiseaseExportFacadeEjb.java (1 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/epipulse/EpipulseDiseaseExportService.java (1 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/epipulse/EpipulseExport.java (1 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/epipulse/EpipulseExportFacadeEjb.java (1 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/epipulse/EpipulseExportIndexDtoResultTransformer.java (1 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/epipulse/EpipulseExportJoins.java (1 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/epipulse/EpipulseExportQueryContext.java (1 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/epipulse/EpipulseExportService.java (1 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/epipulse/EpipulseExportTimerEjb.java (1 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/epipulse/EpipulseLocationConfiguration.java (1 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/epipulse/EpipulseSubjectcodeConfiguration.java (1 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/community/Community.java (2 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/community/CommunityFacadeEjb.java (2 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/community/CommunityService.java (1 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/country/Country.java (2 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/country/CountryFacadeEjb.java (4 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/district/District.java (2 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/district/DistrictFacadeEjb.java (4 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/region/Region.java (3 hunks)
  • sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/region/RegionFacadeEjb.java (4 hunks)
  • sormas-backend/src/main/resources/META-INF/persistence.xml (1 hunks)
  • sormas-backend/src/main/resources/sql/sormas_schema.sql (1 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/ControllerProvider.java (5 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/CommunitiesGrid.java (1 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/CommunityEditForm.java (2 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/CountriesGrid.java (1 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/CountryEditForm.java (2 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/DistrictEditForm.java (2 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/DistrictsGrid.java (1 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/RegionEditForm.java (2 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/RegionsGrid.java (1 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/epipulse/EpiPulseExportController.java (1 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/epipulse/EpipulseEditForm.java (1 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/epipulse/EpipulseExportGrid.java (1 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/epipulse/EpipulseExportGridComponent.java (1 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/epipulse/EpipulseExportGridFilterForm.java (1 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/epipulse/EpipulseExportInfoLayout.java (1 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/epipulse/EpipulseExportView.java (1 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/statistics/AbstractStatisticsView.java (2 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/statistics/StatisticsController.java (2 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractFilterForm.java (1 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/utils/CssStyles.java (1 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/utils/components/ApplyResetButtonsComponent.java (1 hunks)
  • sormas-ui/src/main/java/de/symeda/sormas/ui/utils/components/FormActionButtonsComponent.java (1 hunks)
  • sormas-ui/src/main/webapp/VAADIN/themes/sormas/components/grid.scss (1 hunks)

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.

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.

Epipulse export module

2 participants