Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
ec89022
IMPLEMENTS: #13832: External Survey Integration (NgSurvey).
Pa-Touche Feb 18, 2026
ad4c38f
missing translation message
Pa-Touche Feb 18, 2026
37a4960
prepared patch-api
Pa-Touche Feb 19, 2026
cc030af
Prepared registries.
Pa-Touche Feb 19, 2026
f9c146b
Added comments and placeholders.
Pa-Touche Feb 19, 2026
8f2f262
continued preparation.
Pa-Touche Feb 19, 2026
772df3b
Added some mapper implementations
Pa-Touche Feb 20, 2026
ab4bdf6
Added some mapper mapper implementations
Pa-Touche Feb 20, 2026
332d100
Added some todos: added replacement type check.
Pa-Touche Feb 20, 2026
5231cb4
TODO: prepare ReferenceData code
Pa-Touche Feb 20, 2026
1f5affc
imagined single source to fetch referenceData. To check if this is ad…
Pa-Touche Feb 20, 2026
c991e46
Continued patching logic
Pa-Touche Feb 23, 2026
7fcc124
Minor enhancements for tests.
Pa-Touche Feb 23, 2026
44d5005
Minor enhancements for tests.
Pa-Touche Feb 23, 2026
c031858
added checks
Pa-Touche Feb 24, 2026
262016f
after discussion with xavier
Pa-Touche Feb 24, 2026
97e68cb
Added disease handling on patching.
Pa-Touche Feb 25, 2026
ac35c96
Integrated visibility checkers logic
Pa-Touche Feb 25, 2026
f126bd5
Added feature checker to be complete
Pa-Touche Feb 26, 2026
8a9455a
java enums can be patched
Pa-Touche Feb 26, 2026
c937ab4
CustomEnums a hack
Pa-Touche Feb 26, 2026
43792f2
Added naive implementation of reference search
Pa-Touche Feb 26, 2026
2cddd50
now all tests except non-defautl custom enum works.
Pa-Touche Feb 26, 2026
7a8b678
♻️ enhanced error messages
Pa-Touche Feb 26, 2026
17e829c
Supporting multiple fields + custom enum defaults
Pa-Touche Feb 26, 2026
41db295
♻️ added request to patcher to allow more config
Pa-Touche Feb 26, 2026
c184c3a
languages are now taken into account from input
Pa-Touche Feb 26, 2026
7d8fdd8
minor enhancements: code coverage / javaDoc etc.
Pa-Touche Feb 27, 2026
c4f5940
♻️ reduced size of methods
Pa-Touche Feb 27, 2026
41e0fc9
✨ add handling for partial update
Pa-Touche Feb 27, 2026
d6ead1c
♻️ before adding path alias helper. CaseDataPatcherImpl are (almost a…
Pa-Touche Feb 27, 2026
a735413
♻️ refactored code
Pa-Touche Mar 2, 2026
84434f4
✨ integrated alias usage
Pa-Touche Mar 2, 2026
8f58794
🚧 PartialRetrieval logic
Pa-Touche Mar 2, 2026
05483e0
🚧 prepared somewhat logic for RSV
Pa-Touche Mar 4, 2026
f7204b8
📝 added explanation how to implement the GroupedFieldsMapper logic. N…
Pa-Touche Mar 4, 2026
143d3d6
drafted impl
Pa-Touche Mar 5, 2026
51540d3
integrated api doesn't break anything for now, to see how it goes
Pa-Touche Mar 5, 2026
9a0f4bc
🚧: WIP: started groupedFields impl.
Pa-Touche Mar 5, 2026
642c922
before changing branch, does not build
Pa-Touche Mar 5, 2026
ec675d6
now using BusinessDtoFacade to have a single entry
Pa-Touche Mar 9, 2026
eab9db4
naive vaccination implementation
Pa-Touche Mar 10, 2026
540e59f
✨🚧 naive mother vaccination implementation
Pa-Touche Mar 10, 2026
9452b3c
✅ ignored null value
Pa-Touche Mar 10, 2026
475b840
Started boilerplate for ExternalMessage-API.
Pa-Touche Mar 11, 2026
4a14b43
✅ broken tests due to missing permission
Pa-Touche Mar 11, 2026
d905100
Preparing partial retrieve.
Pa-Touche Mar 12, 2026
896d7e0
🚧 preparing partial retrieval.
Pa-Touche Mar 12, 2026
da97e95
✨ added TypeToDisplayValueMappers.
Pa-Touche Mar 12, 2026
458f134
🐛 Displaying values in nice format works now.
Pa-Touche Mar 13, 2026
9d48180
♻️ registry mapped type
Pa-Touche Mar 13, 2026
c62e941
♻️ registry mapped type. Added failure for invalid path type
Pa-Touche Mar 13, 2026
9bcbc64
before breaking partial retriever
Pa-Touche Mar 13, 2026
69fb179
in my understanding works as it should
Pa-Touche Mar 13, 2026
aedb4e4
♻️📝 minor API enhancements
Pa-Touche Mar 16, 2026
5fe7e6d
🚧 Added symptoms in SymptomsDto only for now.
Pa-Touche Mar 17, 2026
fd6b197
🚧 ✨ : naive UI implementation for processing external messages of typ…
Pa-Touche Mar 17, 2026
cb57f53
📝 missing javadoc
Pa-Touche Mar 17, 2026
dd1a725
💬 translated failure causes
Pa-Touche Mar 17, 2026
a9d0bf5
Added symptoms mapping
Pa-Touche Mar 17, 2026
b3d8126
cleanup
Pa-Touche Mar 17, 2026
36cba46
✨ respect skip if already processed during cron
Pa-Touche Mar 17, 2026
c5738fd
✨ display of questionnaire results
Pa-Touche Mar 17, 2026
45e5309
💡cleanup and minor enhancements
Pa-Touche Mar 17, 2026
bd659d1
reverting format
Pa-Touche Mar 18, 2026
81a6f51
single caption change
Pa-Touche Mar 18, 2026
d7e3edb
merge development
Pa-Touche Mar 18, 2026
00a1947
💡cleanup and minor enhancements
Pa-Touche Mar 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
https://github.com/SORMAS-Foundation/SORMAS-Project/compare/feat/13832-ngsurvey-integration?expand=1


<p align="center">
<a href="https://sormas.org/">
<img
Expand All @@ -20,12 +23,15 @@
## FAQ (Frequently Asked Questions)

### Where can I find the documentation?

We provide an extensive documentation of SORMAS for users, system administrators, Developers and DevOps in our <a href="https://wiki.sorm.as" target="_blank">Wiki</a>.

### How Does it Work?

You can give SORMAS a try on our demo server at <https://demo.sormas.org>!

### How Can I Get Involved?

Read through our [*Contributing Readme*](docs/CONTRIBUTING.md) and contact us at info@sormas.org to learn how you can help to drive the development of SORMAS forward,
or check out our [Discussions](https://github.com/sormas-foundation/SORMAS-Project/discussions) to get development support from the core developers and other community members.
SORMAS is a community-driven project, and we'd love to have you on board!
Expand All @@ -34,26 +40,31 @@ If you want to contribute to the code, please strictly adhere to the [*Developme
Please also make sure that you've read the [*Development Contributing Guidelines*](docs/CONTRIBUTING.md#development-contributing-guidelines) before you start to develop.

### How Can I Report a Bug or Request a Feature?

If you want to report a **security issue**, please read and follow our [*Security Policies*](docs/SECURITY.md). For bugs without security implications, change and feature requests, please [create a new issue](https://github.com/sormas-foundation/SORMAS-Project/issues/new/choose) and
read the [*Submitting an Issue*](docs/CONTRIBUTING.md#submitting-an-issue) guide for more detailed instructions. We appreciate your help!

### Which Browsers and Android Versions are Supported?

SORMAS officially supports and is tested on **Chromium-based browsers** (like Google Chrome) and **Mozilla Firefox**, and all Android versions starting from **Android 7.0** (Nougat). In principle, SORMAS should be usable with all web browsers that are supported by Vaadin 8 (Chrome, Firefox, Safari, Edge, Internet Explorer 11; see <https://vaadin.com/faq>).

Making use of the SORMAS web application through a mobile device web browser is possible and acceptable also in countries that are subject to the General Data Protection Regulation (GDPR) as enforced by the European Union. However, in such countries that are subject to the GDPR, the Android application (.apk file) for SORMAS should not be used on mobile devices until further notice.

### Is there a ReST API documentation?

Yes! Please download the [latest release](https://github.com/sormas-foundation/SORMAS-Project/releases/latest) and copy the content of /deploy/openapi/sormas-rest.yaml to an editor that generates a visual API documentation(e.g. <https://editor.swagger.io/>).
A runtime Swagger documentation of the External Visits Resource (used by external symptom journals such as CLIMEDO or PIA) is available at ``<<host>>/sormas-rest/openapi.json`` or ``<<host>>/sormas-rest/openapi.yaml``

### Who is responsible for Data Protection and Data Security?

We herewith explicitly would like to draw your attention to the fact, that the respective public health agency running SORMAS is in charge of data security and data protection and has to ensure compliance with national data protection and data security regulations in their respective jurisdiction.
It has to ensure that state-of-the art requirements for data protection and data security are fulfilled. All those prerequisites and examinations have to be done in the context of the country and its respective legal framework.
For these reasons, HZI cannot take the responsibility from the respective public health agency running the SORMAS systems and is not liable for any violation of data protection of the agency as the data generated by SORMAS belong to that very agency.

<p align="center"><img src="https://user-images.githubusercontent.com/23701005/74659600-ebb8fc00-5194-11ea-836b-a7ca9d682301.png"/></p>

## Guidelines and Resources

If you want to learn more about the development and contribution process, setting up or customizing your own system, or technical details, please consider the following guides and resources available in this repository. You can also view this readme and all guides outside the Wiki with a full table of content and search functionality here: <https://sormas-foundation.github.io/SORMAS-Project/>

* **[GitHub Wiki](https://github.com/sormas-foundation/SORMAS-Project/wiki) - Our wiki contains additional guides for server customization and development instructions. Please have a look at it if you need information on anything that this readme does not contain.**
Expand All @@ -69,12 +80,14 @@ If you want to learn more about the development and contribution process, settin
* [Third-Party License Acknowledgement](docs/3RD_PARTY_ACK.md) - This resource contains the names and license copies of external resources that SORMAS is using.

If you want to set up a SORMAS instance for production, testing or development purposes, please refer to the following guides:

* [Installing a SORMAS Server](docs/SERVER_SETUP.md)
* [Updating a SORMAS Server](docs/SERVER_UPDATE.md)
* [Setup Development environment](docs/DEVELOPMENT_ENVIRONMENT.md)
* [Creating a Demo Android App](docs/DEMO_APP.md)

## Project Structure

The project consists of the following modules:

- [**sormas-api:**](/sormas-api) General business logic and definitions for data exchange between app and server
Expand Down
10 changes: 10 additions & 0 deletions sormas-api/src/main/java/de/symeda/sormas/api/Disease.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import com.google.common.collect.ImmutableSet;

import de.symeda.sormas.api.i18n.I18nProperties;
import de.symeda.sormas.api.statistics.StatisticsGroupingKey;
Expand Down Expand Up @@ -93,6 +97,12 @@ public enum Disease
OTHER(true, true, true, false, true, 21, false, false, false, false, 0, 0),
UNDEFINED(true, true, true, false, true, 0, false, false, false, false, 0, 0);

/**
* Immutable that eager loads all available diseases.
*/
public static final Set<Disease> ALL_DISEASES =
Arrays.stream(Disease.values()).collect(Collectors.collectingAndThen(Collectors.toSet(), ImmutableSet::copyOf));

private final boolean defaultActive;
private final boolean defaultPrimary;
private final boolean defaultCaseSurveillanceEnabled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,8 @@ public String getString(String key, String defaultValue) {
public String getString(String key) {
return getString(key, null);
}

public java.util.ResourceBundle getResourceBundle() {
return resourceBundle;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
package de.symeda.sormas.api.caze;

import de.symeda.sormas.api.i18n.I18nProperties;
import de.symeda.sormas.api.patch.mapping.ValueMapperDefault;

public enum InfectionSetting {

@ValueMapperDefault
UNKNOWN(null),
AMBULATORY(null),
MEDICAL_PRACTICE(AMBULATORY),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@
package de.symeda.sormas.api.caze;

import de.symeda.sormas.api.i18n.I18nProperties;
import de.symeda.sormas.api.patch.mapping.ValueMapperDefault;

public enum QuarantineReason {

IDENTIFIED_BY_CONTACT_TRACING,
ENTRY_FROM_RISK_AREA,
SWISS_COVID_APP_NOTIFICATION,
OUTBREAK_INVESTIGATION,
@ValueMapperDefault
OTHER_REASON;

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package de.symeda.sormas.api.caze;

import de.symeda.sormas.api.i18n.I18nProperties;
import de.symeda.sormas.api.patch.mapping.ValueMapperDefault;

public enum Trimester {

FIRST,
SECOND,
THIRD,
@ValueMapperDefault
UNKNOWN;

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ public class HealthConditionsDto extends PseudonymizableDto {
private YesNoUnknown hivArt;
private YesNoUnknown chronicLiverDisease;
private YesNoUnknown malignancyChemotherapy;

//TODO: rename ? general heart issue
@HideForCountries(countries = {
CountryHelper.COUNTRY_CODE_GERMANY,
CountryHelper.COUNTRY_CODE_SWITZERLAND })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import javax.annotation.Nullable;
import javax.validation.constraints.Size;

import de.symeda.sormas.api.CountryHelper;
Expand All @@ -32,6 +34,7 @@
import de.symeda.sormas.api.clinicalcourse.ComplianceWithTreatment;
import de.symeda.sormas.api.disease.DiseaseVariant;
import de.symeda.sormas.api.externalmessage.labmessage.SampleReportDto;
import de.symeda.sormas.api.externalmessage.survey.ExternalSurveyResponseData;
import de.symeda.sormas.api.feature.FeatureType;
import de.symeda.sormas.api.i18n.Validations;
import de.symeda.sormas.api.infrastructure.country.CountryReferenceDto;
Expand Down Expand Up @@ -266,6 +269,9 @@ public class ExternalMessageDto extends SormasToSormasShareableDto {
private Boolean tuberculosisMdrXdrTuberculosis;
private Boolean tuberculosisBeijingLineage;

@Nullable
private ExternalSurveyResponseData surveyResponseData;

public ExternalMessageType getType() {
return type;
}
Expand Down Expand Up @@ -959,4 +965,186 @@ public Boolean getTuberculosisBeijingLineage() {
public void setTuberculosisBeijingLineage(Boolean tuberculosisBeijingLineage) {
this.tuberculosisBeijingLineage = tuberculosisBeijingLineage;
}

public ExternalSurveyResponseData getSurveyResponseData() {
return surveyResponseData;
}

public ExternalMessageDto setSurveyResponseData(ExternalSurveyResponseData surveyResponseData) {
this.surveyResponseData = surveyResponseData;
return this;
}

@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass())
return false;
if (!super.equals(o))
return false;
ExternalMessageDto that = (ExternalMessageDto) o;
return automaticProcessingPossible == that.automaticProcessingPossible
&& type == that.type
&& disease == that.disease
&& Objects.equals(diseaseVariant, that.diseaseVariant)
&& Objects.equals(diseaseVariantDetails, that.diseaseVariantDetails)
&& Objects.equals(messageDateTime, that.messageDateTime)
&& caseClassification == that.caseClassification
&& Objects.equals(caseReportDate, that.caseReportDate)
&& Objects.equals(caseSymptoms, that.caseSymptoms)
&& Objects.equals(reporterName, that.reporterName)
&& Objects.equals(reporterExternalIds, that.reporterExternalIds)
&& Objects.equals(reporterPostalCode, that.reporterPostalCode)
&& Objects.equals(reporterCity, that.reporterCity)
&& Objects.equals(personFirstName, that.personFirstName)
&& Objects.equals(personLastName, that.personLastName)
&& Objects.equals(personExternalId, that.personExternalId)
&& Objects.equals(personNationalHealthId, that.personNationalHealthId)
&& personSex == that.personSex
&& personPresentCondition == that.personPresentCondition
&& Objects.equals(personBirthDateDD, that.personBirthDateDD)
&& Objects.equals(personBirthDateMM, that.personBirthDateMM)
&& Objects.equals(personBirthDateYYYY, that.personBirthDateYYYY)
&& Objects.equals(personPostalCode, that.personPostalCode)
&& Objects.equals(personCity, that.personCity)
&& Objects.equals(personStreet, that.personStreet)
&& Objects.equals(personHouseNumber, that.personHouseNumber)
&& Objects.equals(personCountry, that.personCountry)
&& Objects.equals(personFacility, that.personFacility)
&& Objects.equals(personPhone, that.personPhone)
&& personPhoneNumberType == that.personPhoneNumberType
&& Objects.equals(personEmail, that.personEmail)
&& Objects.equals(personGuardianFirstName, that.personGuardianFirstName)
&& Objects.equals(personGuardianLastName, that.personGuardianLastName)
&& Objects.equals(personGuardianRelationship, that.personGuardianRelationship)
&& Objects.equals(personGuardianPhone, that.personGuardianPhone)
&& Objects.equals(personGuardianEmail, that.personGuardianEmail)
&& Objects.equals(personOccupation, that.personOccupation)
&& treatmentStarted == that.treatmentStarted
&& Objects.equals(treatmentNotApplicable, that.treatmentNotApplicable)
&& Objects.equals(treatmentStartedDate, that.treatmentStartedDate)
&& Objects.equals(diagnosticDate, that.diagnosticDate)
&& Objects.equals(deceasedDate, that.deceasedDate)
&& Objects.equals(sampleReports, that.sampleReports)
&& Objects.equals(surveillanceReport, that.surveillanceReport)
&& Objects.equals(externalMessageDetails, that.externalMessageDetails)
&& Objects.equals(caseComments, that.caseComments)
&& Objects.equals(reportId, that.reportId)
&& Objects.equals(reportMessageId, that.reportMessageId)
&& status == that.status
&& Objects.equals(assignee, that.assignee)
&& Objects.equals(reportingUser, that.reportingUser)
&& Objects.equals(personAdditionalDetails, that.personAdditionalDetails)
&& vaccinationStatus == that.vaccinationStatus
&& admittedToHealthFacility == that.admittedToHealthFacility
&& Objects.equals(hospitalizationFacilityName, that.hospitalizationFacilityName)
&& Objects.equals(hospitalizationFacilityExternalId, that.hospitalizationFacilityExternalId)
&& Objects.equals(hospitalizationFacilityDepartment, that.hospitalizationFacilityDepartment)
&& Objects.equals(hospitalizationAdmissionDate, that.hospitalizationAdmissionDate)
&& Objects.equals(hospitalizationDischargeDate, that.hospitalizationDischargeDate)
&& Objects.equals(notifierFirstName, that.notifierFirstName)
&& Objects.equals(notifierLastName, that.notifierLastName)
&& Objects.equals(notifierRegistrationNumber, that.notifierRegistrationNumber)
&& Objects.equals(notifierAddress, that.notifierAddress)
&& Objects.equals(notifierEmail, that.notifierEmail)
&& Objects.equals(notifierPhone, that.notifierPhone)
&& Objects.equals(activitiesAsCase, that.activitiesAsCase)
&& Objects.equals(exposures, that.exposures)
&& radiographyCompatibility == that.radiographyCompatibility
&& Objects.equals(otherDiagnosticCriteria, that.otherDiagnosticCriteria)
&& tuberculosis == that.tuberculosis
&& hiv == that.hiv
&& hivArt == that.hivArt
&& Objects.equals(tuberculosisInfectionYear, that.tuberculosisInfectionYear)
&& previousTuberculosisTreatment == that.previousTuberculosisTreatment
&& complianceWithTreatment == that.complianceWithTreatment
&& Objects.equals(tuberculosisDirectlyObservedTreatment, that.tuberculosisDirectlyObservedTreatment)
&& Objects.equals(tuberculosisMdrXdrTuberculosis, that.tuberculosisMdrXdrTuberculosis)
&& Objects.equals(tuberculosisBeijingLineage, that.tuberculosisBeijingLineage)
&& Objects.equals(surveyResponseData, that.surveyResponseData);
}

@Override
public int hashCode() {
return Objects.hash(
super.hashCode(),
type,
disease,
diseaseVariant,
diseaseVariantDetails,
messageDateTime,
caseClassification,
caseReportDate,
caseSymptoms,
reporterName,
reporterExternalIds,
reporterPostalCode,
reporterCity,
personFirstName,
personLastName,
personExternalId,
personNationalHealthId,
personSex,
personPresentCondition,
personBirthDateDD,
personBirthDateMM,
personBirthDateYYYY,
personPostalCode,
personCity,
personStreet,
personHouseNumber,
personCountry,
personFacility,
personPhone,
personPhoneNumberType,
personEmail,
personGuardianFirstName,
personGuardianLastName,
personGuardianRelationship,
personGuardianPhone,
personGuardianEmail,
personOccupation,
treatmentStarted,
treatmentNotApplicable,
treatmentStartedDate,
diagnosticDate,
deceasedDate,
sampleReports,
surveillanceReport,
externalMessageDetails,
caseComments,
reportId,
reportMessageId,
status,
assignee,
reportingUser,
automaticProcessingPossible,
personAdditionalDetails,
vaccinationStatus,
admittedToHealthFacility,
hospitalizationFacilityName,
hospitalizationFacilityExternalId,
hospitalizationFacilityDepartment,
hospitalizationAdmissionDate,
hospitalizationDischargeDate,
notifierFirstName,
notifierLastName,
notifierRegistrationNumber,
notifierAddress,
notifierEmail,
notifierPhone,
activitiesAsCase,
exposures,
radiographyCompatibility,
otherDiagnosticCriteria,
tuberculosis,
hiv,
hivArt,
tuberculosisInfectionYear,
previousTuberculosisTreatment,
complianceWithTreatment,
tuberculosisDirectlyObservedTreatment,
tuberculosisMdrXdrTuberculosis,
tuberculosisBeijingLineage,
surveyResponseData);
}
}
Loading
Loading