diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index a70b9951e8a..65413b836da 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -104,7 +104,7 @@ The development team uses an epic as an umbrella for large change or feature str ## Contributing to the Project -There are many ways in which you can contribute to this project as a non-developer. If there is something you would like to do that you don't find instructions about here - or if you want to learn how you can get involved - please contact us at sormas@helmholtz-hzi.de +There are many ways in which you can contribute to this project as a non-developer. If there is something you would like to do that you don't find instructions about here - or if you want to learn how you can get involved - please contact us at info@sormas.org or through our [GitHub Discussions](https://github.com/sormas-foundation/SORMAS-Project/discussions) and let us know how we can assist you! Some possibilities to contribute to SORMAS are: @@ -115,7 +115,7 @@ Some possibilities to contribute to SORMAS are: ## Contributing to the Code If you're interested in participating in the development of SORMAS, please follow the [Development Environment Setup Instructions](DEVELOPMENT_ENVIRONMENT.md) before you start developing. If you have problems setting up your development environment or need assistance in choosing the first issue to work on, -please get in touch with us through our [GitHub Discussions](https://github.com/sormas-foundation/SORMAS-Project/discussions) or by contacting us at sormas@helmholtz-hzi.de. +please get in touch with us through our [GitHub Discussions](https://github.com/sormas-foundation/SORMAS-Project/discussions) or by contacting us at info@sormas.org. Additionally, our [Wiki](https://github.com/sormas-foundation/SORMAS-Project/wiki) contains some specific development guides that cover common issues like adding new fields to an entity that we suggest to check out before you start implementing something related to those topics: @@ -249,4 +249,4 @@ These dependencies have been added to the dependabot ignore list, so no dependen #### Keycloak The Keycloak version in SORMAS-Project only defines the version of the Keycloak admin client library. When a new version of Keycloak is available this should be updated after the [Keycloak version is SORMAS-Docker](https://github.com/SORMAS-Foundation/SORMAS-Docker/blob/devops/keycloak/Dockerfile) has been updated. \ -This can be tested locally by building the updated Keycloak docker image and then using it in a [container](https://github.com/SORMAS-Foundation/SORMAS-Project/tree/development/sormas-base/setup/keycloak) together with a local Payara instance. \ No newline at end of file +This can be tested locally by building the updated Keycloak docker image and then using it in a [container](https://github.com/SORMAS-Foundation/SORMAS-Project/tree/development/sormas-base/setup/keycloak) together with a local Payara instance. diff --git a/sormas-api/pom.xml b/sormas-api/pom.xml index 793b9ef6f07..1e162e898d5 100644 --- a/sormas-api/pom.xml +++ b/sormas-api/pom.xml @@ -2,7 +2,7 @@ de.symeda.sormas sormas-base - 1.93.0 + 1.94.0 ../sormas-base 4.0.0 diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseFollowUpDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseFollowUpDto.java index 07686ce7111..a1a03d8c5a6 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseFollowUpDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseFollowUpDto.java @@ -33,7 +33,7 @@ public class CaseFollowUpDto extends FollowUpDto { private Boolean isInJurisdiction; //@formatter:off - public CaseFollowUpDto(String uuid, Date changeDate, String personFirstName, String personLastName, + public CaseFollowUpDto(String uuid, String personFirstName, String personLastName, Date reportDate, Date symptomsOnsetDate, Date followUpUntil, SymptomJournalStatus symptomJournalStatus, Disease disease, boolean isInJurisdiction diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseIndexDetailedDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseIndexDetailedDto.java index 05b63ea943d..e8c1c916f1b 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseIndexDetailedDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseIndexDetailedDto.java @@ -87,7 +87,7 @@ public CaseIndexDetailedDto(long id, String uuid, String epidNumber, String exte YesNoUnknown reInfection, String city, String street, String houseNumber, String additionalInformation, String postalCode, String phone, String reportingUserUuid, String reportingUserFirstName, String reportingUserLastName, Date symptomOnsetDate, String responsibleRegion, String responsibleCommunity, - int visitCount, long eventCount, Date latestSampleDateTime, long sampleCount, Date latestChangedDate) { + int visitCount, long eventCount, Date latestSampleDateTime, long sampleCount) { super(id, uuid, epidNumber, externalID, externalToken, internalToken, personUuid, personFirstName, personLastName, disease, diseaseVariant, diseaseDetails, caseClassification, investigationStatus, presentCondition, reportDate, creationDate, @@ -95,7 +95,7 @@ public CaseIndexDetailedDto(long id, String uuid, String epidNumber, String exte healthFacilityName, healthFacilityDetails, pointOfEntryUuid, pointOfEntryName, pointOfEntryDetails, surveillanceOfficerUuid, outcome, age, ageType, birthdateDD, birthdateMM, birthdateYYYY, sex, quarantineTo, completeness, followUpStatus, followUpUntil, symptomJournalStatus, vaccinationStatus, changeDate, facilityId, - responsibleRegionUuid, responsibleDistrictUuid, responsibleDistrictName, deletionReason, otherDeleteReason, isInJurisdiction, visitCount, latestChangedDate); + responsibleRegionUuid, responsibleDistrictUuid, responsibleDistrictName, deletionReason, otherDeleteReason, isInJurisdiction, visitCount); //@formatter:on this.reInfection = reInfection; @@ -114,38 +114,6 @@ public CaseIndexDetailedDto(long id, String uuid, String epidNumber, String exte this.responsibleCommunity = responsibleCommunity; } - //@formatter:off - public CaseIndexDetailedDto( - long id, String uuid, String epidNumber, String externalID, String externalToken, String internalToken, - String personUuid, String personFirstName, String personLastName, - Disease disease, DiseaseVariant diseaseVariant, String diseaseDetails, - CaseClassification caseClassification, InvestigationStatus investigationStatus, PresentCondition presentCondition, - Date reportDate, Date creationDate, - String regionUuid, String districtUuid, - String healthFacilityUuid, String healthFacilityName, String healthFacilityDetails, - String pointOfEntryUuid, String pointOfEntryName, String pointOfEntryDetails, String surveillanceOfficerUuid, - CaseOutcome outcome, Integer age, ApproximateAgeType ageType, Integer birthdateDD, Integer birthdateMM, Integer birthdateYYYY, - Sex sex, Date quarantineTo, Float completeness, FollowUpStatus followUpStatus, Date followUpUntil, - SymptomJournalStatus symptomJournalStatus, VaccinationStatus vaccinationStatus, Date changeDate, Long facilityId, - String responsibleRegionUuid, String responsibleDistrictUuid, String responsibleDistrictName, DeletionReason deletionReason, String otherDeleteReason, boolean isInJurisdiction, - //detailed fields - YesNoUnknown reInfection, String city, String street, String houseNumber, String additionalInformation, - String postalCode, String phone, String reportingUserUuid, String reportingUserFirstName, String reportingUserLastName, - Date symptomOnsetDate, String responsibleRegion, String responsibleCommunity, int visitCount, - Date latestSampleDateTime, long sampleCount, Date latestChangedDate) { - this(id, uuid, epidNumber, externalID, externalToken, internalToken, personUuid, personFirstName, personLastName, - disease, diseaseVariant, diseaseDetails, caseClassification, investigationStatus, presentCondition, - reportDate, creationDate, regionUuid, districtUuid, healthFacilityUuid, healthFacilityName, - healthFacilityDetails, pointOfEntryUuid, pointOfEntryName, pointOfEntryDetails, surveillanceOfficerUuid, - outcome, age, ageType, birthdateDD, birthdateMM, birthdateYYYY, sex, quarantineTo, completeness, - followUpStatus, followUpUntil, symptomJournalStatus, vaccinationStatus, changeDate, facilityId, - responsibleRegionUuid, responsibleDistrictUuid, responsibleDistrictName, deletionReason, otherDeleteReason, isInJurisdiction, reInfection, - city, street, houseNumber, additionalInformation, postalCode, phone, reportingUserUuid, - reportingUserFirstName, reportingUserLastName, symptomOnsetDate, responsibleRegion, responsibleCommunity, - visitCount, 0, latestSampleDateTime, sampleCount, latestChangedDate); - //@formatter:on - } - public YesNoUnknown getReInfection() { return reInfection; } diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseIndexDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseIndexDto.java index 5f436d5c42d..e5dc8d51a45 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseIndexDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseIndexDto.java @@ -135,29 +135,6 @@ public class CaseIndexDto extends PseudonymizableIndexDto implements MergeableIn private Boolean isInJurisdiction; - //@formatter:off - public CaseIndexDto(long id, String uuid, String epidNumber, String externalID, String externalToken, String internalToken, String personUuid, String personFirstName, String personLastName, Disease disease, - DiseaseVariant diseaseVariant, String diseaseDetails, CaseClassification caseClassification, InvestigationStatus investigationStatus, - PresentCondition presentCondition, Date reportDate, Date creationDate, String regionUuid, - String districtUuid, String healthFacilityUuid, String healthFacilityName, String healthFacilityDetails, - String pointOfEntryUuid, String pointOfEntryName, String pointOfEntryDetails, String surveillanceOfficerUuid, CaseOutcome outcome, - Integer age, ApproximateAgeType ageType, Integer birthdateDD, Integer birthdateMM, Integer birthdateYYYY, Sex sex, Date quarantineTo, - Float completeness, FollowUpStatus followUpStatus, Date followUpUntil, SymptomJournalStatus symptomJournalStatus, VaccinationStatus vaccinationStatus, Date changeDate, Long facilityId, - // responsible jurisdiction - String responsibleRegionUuid, String responsibleDistrictUuid, String responsibleDistrictName, DeletionReason deletionReason, String otherDeletionReason, boolean isInJurisdiction) { - this(id, uuid, epidNumber, externalID, externalToken, internalToken, personUuid, personFirstName, personLastName, disease, - diseaseVariant, diseaseDetails, caseClassification, investigationStatus, - presentCondition, reportDate, creationDate, regionUuid, - districtUuid, healthFacilityUuid, healthFacilityName, healthFacilityDetails, - pointOfEntryUuid, pointOfEntryName, pointOfEntryDetails, surveillanceOfficerUuid, outcome, - age, ageType, birthdateDD, birthdateMM, birthdateYYYY, sex, quarantineTo, - completeness, followUpStatus, followUpUntil, symptomJournalStatus, vaccinationStatus, changeDate, facilityId, - responsibleRegionUuid, responsibleDistrictUuid, responsibleDistrictName, deletionReason, otherDeletionReason, isInJurisdiction, - null, null - ); - } - //@formatter:on - //@formatter:off public CaseIndexDto(long id, String uuid, String epidNumber, String externalID, String externalToken, String internalToken, String personUuid, String personFirstName, String personLastName, Disease disease, DiseaseVariant diseaseVariant, String diseaseDetails, CaseClassification caseClassification, InvestigationStatus investigationStatus, @@ -170,8 +147,7 @@ public CaseIndexDto(long id, String uuid, String epidNumber, String externalID, // responsible jurisdiction String responsibleRegionUuid, String responsibleDistrictUuid, String responsibleDistrictName, DeletionReason deletionReason, String otherDeletionReason, boolean isInJurisdiction, // others - Integer visitCount, - Date latestChangedDate // unused, only here for TypedQuery mapping + Integer visitCount ) { //@formatter:on diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseMergeIndexDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseMergeIndexDto.java index 2fcbb8b27da..9f380d5c934 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseMergeIndexDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseMergeIndexDto.java @@ -1,7 +1,6 @@ package de.symeda.sormas.api.caze; import java.util.Date; -import java.util.Objects; import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.common.DeletionReason; @@ -79,7 +78,6 @@ public CaseMergeIndexDto( deletionReason, otherDeletionReason, isInJurisdiction, - null, null ); } diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/contact/ContactIndexDetailedDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/contact/ContactIndexDetailedDto.java index 9526c22ca08..33287f8fe12 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/contact/ContactIndexDetailedDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/contact/ContactIndexDetailedDto.java @@ -73,8 +73,7 @@ public ContactIndexDetailedDto(String uuid, String personUuid, String personFirs String externalID, String externalToken, String internalToken, DeletionReason deletionReason, String otherDeleteReason, boolean isInJurisdiction, boolean isCaseInJurisdiction, Sex sex, Integer approximateAge, ApproximateAgeType approximateAgeType, String city, String street, String houseNumber, String additionalInformation, String postalCode, String phone, - String reportingUserFirstName, String reportingUserLastName, ContactRelation relationToCase, int visitCount, - Date latestChangedDate // unused, only here for TypedQuery mapping + String reportingUserFirstName, String reportingUserLastName, ContactRelation relationToCase, int visitCount ) { //@formatter:on @@ -82,7 +81,7 @@ public ContactIndexDetailedDto(String uuid, String personUuid, String personFirs super(uuid, personUuid, personFirstName, personLastName, cazeUuid, disease, diseaseDetails, caseFirstName, caseLastName, regionName, districtName, lastContactDate, contactCategory, contactProximity, contactClassification, contactStatus, completeness, followUpStatus, followUpUntil, symptomJournalStatus, vaccinationStatus, contactOfficerUuid, reportingUserUuid, reportDateTime, caseClassification, - caseRegionName, caseDistrictName, changeDate, externalID, externalToken, internalToken, deletionReason, otherDeleteReason,isInJurisdiction, isCaseInJurisdiction , visitCount, latestChangedDate); + caseRegionName, caseDistrictName, changeDate, externalID, externalToken, internalToken, deletionReason, otherDeleteReason,isInJurisdiction, isCaseInJurisdiction , visitCount); //@formatter:on diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/contact/ContactIndexDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/contact/ContactIndexDto.java index 75d4a99be5a..a12aabe6e52 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/contact/ContactIndexDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/contact/ContactIndexDto.java @@ -109,8 +109,7 @@ public ContactIndexDto(String uuid, String personUuid, String personFirstName, S CaseClassification caseClassification, String caseRegionName, String caseDistrictName, Date changeDate, // XXX: unused, only here for TypedQuery mapping String externalID, String externalToken, String internalToken, DeletionReason deletionReason, String otherDeletionReason, boolean isInJurisdiction, boolean isCaseInJurisdiction, - int visitCount, - Date latestChangedDate // unused, only here for TypedQuery mapping + int visitCount ) { //@formatter:on diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/customizableenum/CustomizableEnum.java b/sormas-api/src/main/java/de/symeda/sormas/api/customizableenum/CustomizableEnum.java index 44f55bff4fd..b8c9b90ec61 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/customizableenum/CustomizableEnum.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/customizableenum/CustomizableEnum.java @@ -25,7 +25,7 @@ * Base class for customizable enums. Supposed to be extended for every enum that is made customizable to ensure type safety. */ @AuditedClass -public abstract class CustomizableEnum implements Serializable { +public abstract class CustomizableEnum implements Serializable, Cloneable { private static final long serialVersionUID = 8698428745095686559L; @@ -96,5 +96,14 @@ public int hashCode() { return Objects.hash(value); } + @Override + public CustomizableEnum clone() { + try { + return (CustomizableEnum) super.clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + } + public abstract Map> getAllProperties(); } diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/customizableenum/CustomizableEnumCriteria.java b/sormas-api/src/main/java/de/symeda/sormas/api/customizableenum/CustomizableEnumCriteria.java index 6314aeaf72d..c00cc4e1f4c 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/customizableenum/CustomizableEnumCriteria.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/customizableenum/CustomizableEnumCriteria.java @@ -27,6 +27,7 @@ public class CustomizableEnumCriteria extends BaseCriteria implements Serializab private String freeTextFilter; private CustomizableEnumType dataType; private Disease disease; + private Boolean active = true; public String getFreeTextFilter() { return freeTextFilter; @@ -55,4 +56,13 @@ public CustomizableEnumCriteria disease(Disease disease) { return this; } + public Boolean getActive() { + return active; + } + + public CustomizableEnumCriteria active(Boolean active) { + this.active = active; + return this; + } + } diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/customizableenum/CustomizableEnumFacade.java b/sormas-api/src/main/java/de/symeda/sormas/api/customizableenum/CustomizableEnumFacade.java index 1133f9f6e8e..9cf74c08a5b 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/customizableenum/CustomizableEnumFacade.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/customizableenum/CustomizableEnumFacade.java @@ -82,11 +82,11 @@ public interface CustomizableEnumFacade * Retrieves the cached contents of all enum value instances of the specified type. The results are already * internationalized based on the user's language, or the server language as a fallback. If the enum values for the * specified type and disease have not been requested yet, the cache is extended with them on demand. - * + * * @param type * The type for which to retrieve the enum values * @param disease - * The disease for which to retrieve the enum values. If null, all enum values that are disease-independent are retrieved + * The disease for which to retrieve the enum values; if null, all enum values that are disease-independent are retrieved * @param * The specific extension of {@link CustomizableEnum} for type safety * @return A list of all enum instances containing their values, internationalized captions, and optional properties diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/customizableenum/CustomizableEnumValueDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/customizableenum/CustomizableEnumValueDto.java index 92bcde6d842..cf109768988 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/customizableenum/CustomizableEnumValueDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/customizableenum/CustomizableEnumValueDto.java @@ -47,6 +47,7 @@ public class CustomizableEnumValueDto extends EntityDto { public static final String TRANSLATIONS = "translations"; public static final String DISEASES = "diseases"; public static final String PROPERTIES = "properties"; + public static final String ACTIVE = "active"; @NotNull(message = Validations.required) private CustomizableEnumType dataType; @@ -69,10 +70,12 @@ public class CustomizableEnumValueDto extends EntityDto { * or translations because they can be translated via properties files. */ private boolean defaultValue; + private boolean active; public static CustomizableEnumValueDto build() { CustomizableEnumValueDto dto = new CustomizableEnumValueDto(); dto.setUuid(DataHelper.createUuid()); + dto.setActive(true); return dto; } @@ -147,4 +150,12 @@ public boolean isDefaultValue() { public void setDefaultValue(boolean defaultValue) { this.defaultValue = defaultValue; } + + public boolean isActive() { + return active; + } + + public void setActive(boolean active) { + this.active = active; + } } diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/event/EventGroupIndexDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/event/EventGroupIndexDto.java index ad5675a0e91..6a7546b71a9 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/event/EventGroupIndexDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/event/EventGroupIndexDto.java @@ -14,8 +14,6 @@ */ package de.symeda.sormas.api.event; -import java.util.Date; - import de.symeda.sormas.api.uuid.AbstractUuidDto; public class EventGroupIndexDto extends AbstractUuidDto { @@ -27,16 +25,12 @@ public class EventGroupIndexDto extends AbstractUuidDto { public static final String UUID = "uuid"; public static final String NAME = "name"; public static final String EVENT_COUNT = "eventCount"; - public static final String CHANGED_DATE = "changeDate"; - private String name; private Long eventCount; - private Date changeDate; - public EventGroupIndexDto(String uuid, String name, Date changeDate, Long eventCount) { + public EventGroupIndexDto(String uuid, String name, Long eventCount) { super(uuid); this.name = name; - this.changeDate = changeDate; this.eventCount = eventCount; } @@ -48,14 +42,6 @@ public void setName(String name) { this.name = name; } - public Date getChangeDate() { - return changeDate; - } - - public void setChangeDate(Date changeDate) { - this.changeDate = changeDate; - } - public Long getEventCount() { return eventCount; } diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/event/EventIndexDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/event/EventIndexDto.java index b2a3db43771..1f92791d04f 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/event/EventIndexDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/event/EventIndexDto.java @@ -163,7 +163,6 @@ public EventIndexDto( String responsibleUserFirstName, String responsibleUserLastName, boolean isInJurisdictionOrOwned, - Date changeDate, EventIdentificationSource eventIdentificationSource, DeletionReason deletionReason, String otherDeletionReason) { diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/event/EventParticipantIndexDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/event/EventParticipantIndexDto.java index d40b73a7ec2..387af8c24ca 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/event/EventParticipantIndexDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/event/EventParticipantIndexDto.java @@ -5,7 +5,6 @@ import de.symeda.sormas.api.caze.VaccinationStatus; import de.symeda.sormas.api.common.DeletionReason; -import de.symeda.sormas.api.person.ApproximateAgeType; import de.symeda.sormas.api.person.Sex; import de.symeda.sormas.api.sample.PathogenTestResultType; import de.symeda.sormas.api.utils.PersonalData; @@ -64,12 +63,10 @@ public EventParticipantIndexDto( String lastName, Sex sex, Integer approximateAge, - ApproximateAgeType approximateAgeType, String involvementDescription, PathogenTestResultType pathogenTestResult, Date sampleDateTime, VaccinationStatus vaccinationStatus, - String reportingUserUuid, DeletionReason deletionReason, String otherDeletionReason, boolean isInJurisdiction, diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/AbstractProcessingFlow.java b/sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/AbstractProcessingFlow.java index 9f33aab54c0..89fcf5e30cd 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/AbstractProcessingFlow.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/AbstractProcessingFlow.java @@ -32,7 +32,6 @@ import de.symeda.sormas.api.externalmessage.processing.flow.ProcessingResult; import de.symeda.sormas.api.externalmessage.processing.flow.ProcessingResultStatus; import de.symeda.sormas.api.feature.FeatureType; -import de.symeda.sormas.api.feature.FeatureTypeProperty; import de.symeda.sormas.api.infrastructure.facility.FacilityDto; import de.symeda.sormas.api.infrastructure.facility.FacilityReferenceDto; import de.symeda.sormas.api.infrastructure.facility.FacilityType; @@ -157,7 +156,7 @@ protected CaseDataDto buildCase(PersonDto person, ExternalMessageDto externalMes caseDto.setReportDate( externalMessageDto.getCaseReportDate() != null ? externalMessageDto.getCaseReportDate() : externalMessageDto.getMessageDateTime()); - if (processingFacade.isFeaturePropertyValueTrue(FeatureType.CASE_SURVEILANCE, FeatureTypeProperty.HIDE_JURISDICTION_FIELDS)) { + if (processingFacade.isFeatureEnabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { caseDto.setResponsibleRegion(processingFacade.getDefaultRegionReference()); caseDto.setResponsibleDistrict(processingFacade.getDefaultDistrictReference()); caseDto.setResponsibleCommunity(processingFacade.getDefaultCommunityReference()); diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/ExternalMessageProcessingFacade.java b/sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/ExternalMessageProcessingFacade.java index 2202197a083..260b964ae40 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/ExternalMessageProcessingFacade.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/processing/ExternalMessageProcessingFacade.java @@ -48,7 +48,6 @@ import de.symeda.sormas.api.externalmessage.ExternalMessageFacade; import de.symeda.sormas.api.feature.FeatureConfigurationFacade; import de.symeda.sormas.api.feature.FeatureType; -import de.symeda.sormas.api.feature.FeatureTypeProperty; import de.symeda.sormas.api.infrastructure.community.CommunityFacade; import de.symeda.sormas.api.infrastructure.community.CommunityReferenceDto; import de.symeda.sormas.api.infrastructure.country.CountryFacade; @@ -253,8 +252,8 @@ public PersonDto getPersonByContext(PersonContext personContext, String personUu } - public boolean isFeaturePropertyValueTrue(FeatureType featureType, FeatureTypeProperty featureTypeProperty) { - return featureConfigurationFacade.isPropertyValueTrue(featureType, featureTypeProperty); + public boolean isFeatureEnabled(FeatureType featureType) { + return featureConfigurationFacade.isFeatureEnabled(featureType); } public RegionReferenceDto getDefaultRegionReference() { diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/feature/FeatureType.java b/sormas-api/src/main/java/de/symeda/sormas/api/feature/FeatureType.java index e58055f54e2..177ed3dd2b1 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/feature/FeatureType.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/feature/FeatureType.java @@ -40,12 +40,7 @@ public enum FeatureType { // FEATURE MODULES AGGREGATE_REPORTING(true, true, null, null, null), CAMPAIGNS(true, false, null, null, null), - CASE_SURVEILANCE(true, - true, - null, - null, - ImmutableMap - .of(FeatureTypeProperty.AUTOMATIC_RESPONSIBILITY_ASSIGNMENT, Boolean.TRUE, FeatureTypeProperty.HIDE_JURISDICTION_FIELDS, Boolean.FALSE)), + CASE_SURVEILANCE(true, true, null, null, ImmutableMap.of(FeatureTypeProperty.AUTOMATIC_RESPONSIBILITY_ASSIGNMENT, Boolean.TRUE)), CLINICAL_MANAGEMENT(true, true, null, null, null), CONTACT_TRACING(true, true, @@ -208,6 +203,7 @@ public enum FeatureType { ImmutableMap.of(FeatureTypeProperty.THRESHOLD_IN_DAYS, 90)), EDIT_ARCHIVED_ENTITIES(true, true, null, null, null), EXTERNAL_EMAILS(true, false, null, null, null), + HIDE_JURISDICTION_FIELDS(true, false, null, null, null), // SHOW/HIDE VIEW TAB FEATURES VIEW_TAB_CASES_HOSPITALIZATION(true, diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/feature/FeatureTypeProperty.java b/sormas-api/src/main/java/de/symeda/sormas/api/feature/FeatureTypeProperty.java index 7f0d0ee7cbe..6f4ec901d7f 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/feature/FeatureTypeProperty.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/feature/FeatureTypeProperty.java @@ -29,8 +29,7 @@ public enum FeatureTypeProperty { SHARE_SAMPLES(Boolean.class), SHARE_IMMUNIZATIONS(Boolean.class), SHARE_REPORTS(Boolean.class), - FETCH_MODE(Boolean.class), - HIDE_JURISDICTION_FIELDS(Boolean.class); + FETCH_MODE(Boolean.class); private final Class returnType; diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Captions.java b/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Captions.java index f6d3dd2ee08..a3b5a16b05a 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Captions.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Captions.java @@ -818,13 +818,16 @@ public interface Captions { String creationDate = "creationDate"; String CustomizableEnum_hasDetails = "CustomizableEnum.hasDetails"; String CustomizableEnum_hasDetails_short = "CustomizableEnum.hasDetails.short"; + String CustomizableEnumValue_active = "CustomizableEnumValue.active"; String CustomizableEnumValue_caption = "CustomizableEnumValue.caption"; String CustomizableEnumValue_dataType = "CustomizableEnumValue.dataType"; String CustomizableEnumValue_diseases = "CustomizableEnumValue.diseases"; String CustomizableEnumValue_properties = "CustomizableEnumValue.properties"; String CustomizableEnumValue_value = "CustomizableEnumValue.value"; + String customizableEnumValueActiveValues = "customizableEnumValueActiveValues"; String customizableEnumValueAllDiseases = "customizableEnumValueAllDiseases"; String customizableEnumValueDiseaseCount = "customizableEnumValueDiseaseCount"; + String customizableEnumValueInactiveValues = "customizableEnumValueInactiveValues"; String customizableEnumValueNoProperties = "customizableEnumValueNoProperties"; String dashboardAggregatedNumber = "dashboardAggregatedNumber"; String dashboardAlive = "dashboardAlive"; @@ -1466,6 +1469,7 @@ public interface Captions { String externalMessageProcess = "externalMessageProcess"; String externalMessageRelatedEntriesFound = "externalMessageRelatedEntriesFound"; String externalMessagesList = "externalMessagesList"; + String externalMessageValueNotSpecified = "externalMessageValueNotSpecified"; String ExternalSurveillanceToolGateway_confirmDelete = "ExternalSurveillanceToolGateway.confirmDelete"; String ExternalSurveillanceToolGateway_confirmSend = "ExternalSurveillanceToolGateway.confirmSend"; String ExternalSurveillanceToolGateway_excludeAndSend = "ExternalSurveillanceToolGateway.excludeAndSend"; diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Strings.java b/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Strings.java index e54f53c6709..fadd698da1f 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Strings.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Strings.java @@ -1397,6 +1397,7 @@ public interface Strings { String messagePersonListAddedAsEventPerticipants = "messagePersonListAddedAsEventPerticipants"; String messagePersonMergedAddressDescription = "messagePersonMergedAddressDescription"; String messagePersonMergeNoEventParticipantRights = "messagePersonMergeNoEventParticipantRights"; + String messagePersonNationalHealthIdInvalid = "messagePersonNationalHealthIdInvalid"; String messagePersonSaved = "messagePersonSaved"; String messagePersonSavedClassificationChanged = "messagePersonSavedClassificationChanged"; String messagePickEventParticipantsIncompleteSelection = "messagePickEventParticipantsIncompleteSelection"; @@ -1687,6 +1688,7 @@ public interface Strings { String reloadPageToSeeChanges = "reloadPageToSeeChanges"; String reportedBy = "reportedBy"; String reportedOn = "reportedOn"; + String reportingUser = "reportingUser"; String setTo = "setTo"; String sormasToSormasLoadingShares = "sormasToSormasLoadingShares"; String step = "step"; diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Validations.java b/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Validations.java index 5fd5571e404..29d9dfc8231 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Validations.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Validations.java @@ -144,6 +144,7 @@ public interface Validations { String importUnexpectedError = "importUnexpectedError"; String importWrongDataTypeError = "importWrongDataTypeError"; String infrastructureDataLocked = "infrastructureDataLocked"; + String invalidNationalHealthId = "invalidNationalHealthId"; String investigationStatusUnclassifiedCase = "investigationStatusUnclassifiedCase"; String jurisdictionChangeUserAssignment = "jurisdictionChangeUserAssignment"; String latitudeBetween = "latitudeBetween"; diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/user/DefaultUserRole.java b/sormas-api/src/main/java/de/symeda/sormas/api/user/DefaultUserRole.java index 79aed19247c..d08ff3355f5 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/user/DefaultUserRole.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/user/DefaultUserRole.java @@ -441,6 +441,9 @@ public Set getDefaultUserRights() { ENVIRONMENT_SAMPLE_DELETE, ENVIRONMENT_SAMPLE_IMPORT, ENVIRONMENT_SAMPLE_EXPORT, + ENVIRONMENT_PATHOGEN_TEST_CREATE, + ENVIRONMENT_PATHOGEN_TEST_EDIT, + ENVIRONMENT_PATHOGEN_TEST_DELETE, DOCUMENT_VIEW, DOCUMENT_UPLOAD, DOCUMENT_DELETE, @@ -1141,6 +1144,8 @@ public Set getDefaultUserRights() { ENVIRONMENT_SAMPLE_EDIT_DISPATCH, ENVIRONMENT_SAMPLE_EDIT_RECEIVAL, ENVIRONMENT_SAMPLE_EXPORT, + ENVIRONMENT_PATHOGEN_TEST_CREATE, + ENVIRONMENT_PATHOGEN_TEST_EDIT, DOCUMENT_VIEW, DOCUMENT_UPLOAD, EXTERNAL_EMAIL_SEND, @@ -1387,6 +1392,9 @@ public Set getDefaultUserRights() { ENVIRONMENT_SAMPLE_DELETE, ENVIRONMENT_SAMPLE_IMPORT, ENVIRONMENT_SAMPLE_EXPORT, + ENVIRONMENT_PATHOGEN_TEST_CREATE, + ENVIRONMENT_PATHOGEN_TEST_EDIT, + ENVIRONMENT_PATHOGEN_TEST_DELETE, DOCUMENT_VIEW, DOCUMENT_UPLOAD, DOCUMENT_DELETE, @@ -1546,11 +1554,10 @@ public Set getDefaultUserRights() { ENVIRONMENT_SAMPLE_DELETE, ENVIRONMENT_SAMPLE_IMPORT, ENVIRONMENT_SAMPLE_EXPORT, + ENVIRONMENT_PATHOGEN_TEST_CREATE, + ENVIRONMENT_PATHOGEN_TEST_EDIT, + ENVIRONMENT_PATHOGEN_TEST_DELETE, PERFORM_BULK_OPERATIONS, - SAMPLE_VIEW, - SAMPLE_EDIT, - PATHOGEN_TEST_CREATE, - PATHOGEN_TEST_EDIT, TASK_VIEW, TASK_CREATE, TASK_EDIT, diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/user/DtoViewAndEditRights.java b/sormas-api/src/main/java/de/symeda/sormas/api/user/DtoViewAndEditRights.java index 085794ca2dd..bc6050f4dc3 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/user/DtoViewAndEditRights.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/user/DtoViewAndEditRights.java @@ -87,7 +87,9 @@ public class DtoViewAndEditRights { viewRights.put( PathogenTestDto.class.getSimpleName(), Stream.of(UserRight.SAMPLE_VIEW, UserRight.ENVIRONMENT_SAMPLE_VIEW).collect(Collectors.toSet())); - editRights.put(PathogenTestDto.class.getSimpleName(), Collections.singleton(UserRight.PATHOGEN_TEST_EDIT)); + editRights.put( + PathogenTestDto.class.getSimpleName(), + Stream.of(UserRight.PATHOGEN_TEST_EDIT, UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT).collect(Collectors.toSet())); viewRights.put(PersonDto.class.getSimpleName(), Collections.singleton(UserRight.PERSON_VIEW)); editRights.put(PersonDto.class.getSimpleName(), Collections.singleton(UserRight.PERSON_EDIT)); diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/user/UserRight.java b/sormas-api/src/main/java/de/symeda/sormas/api/user/UserRight.java index c3ac8b92d22..cbab9a2e49a 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/user/UserRight.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/user/UserRight.java @@ -229,6 +229,9 @@ public enum UserRight { ENVIRONMENT_SAMPLE_DELETE(UserRightGroup.ENVIRONMENT, UserRight._ENVIRONMENT_SAMPLE_VIEW), ENVIRONMENT_SAMPLE_IMPORT(UserRightGroup.ENVIRONMENT, UserRight._ENVIRONMENT_SAMPLE_CREATE), ENVIRONMENT_SAMPLE_EXPORT(UserRightGroup.ENVIRONMENT, UserRight._ENVIRONMENT_SAMPLE_VIEW), + ENVIRONMENT_PATHOGEN_TEST_CREATE(UserRightGroup.ENVIRONMENT, UserRight._ENVIRONMENT_SAMPLE_VIEW), + ENVIRONMENT_PATHOGEN_TEST_EDIT(UserRightGroup.ENVIRONMENT, UserRight._ENVIRONMENT_SAMPLE_EDIT), + ENVIRONMENT_PATHOGEN_TEST_DELETE(UserRightGroup.ENVIRONMENT, UserRight._ENVIRONMENT_SAMPLE_VIEW), DOCUMENT_VIEW(UserRightGroup.DOCUMENT), DOCUMENT_UPLOAD(UserRightGroup.DOCUMENT, UserRight._DOCUMENT_VIEW), @@ -458,6 +461,9 @@ public enum UserRight { public static final String _ENVIRONMENT_SAMPLE_EDIT_DISPATCH = "ENVIRONMENT_SAMPLE_EDIT_DISPATCH"; public static final String _ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = "ENVIRONMENT_SAMPLE_EDIT_RECEIVAL"; public static final String _ENVIRONMENT_SAMPLE_DELETE = "ENVIRONMENT_SAMPLE_DELETE"; + public static final String _ENVIRONMENT_PATHOGEN_TEST_CREATE = "ENVIRONMENT_PATHOGEN_TEST_CREATE"; + public static final String _ENVIRONMENT_PATHOGEN_TEST_EDIT = "ENVIRONMENT_PATHOGEN_TEST_EDIT"; + public static final String _ENVIRONMENT_PATHOGEN_TEST_DELETE = "ENVIRONMENT_PATHOGEN_TEST_DELETE"; public static final String _DOCUMENT_VIEW = "DOCUMENT_VIEW"; public static final String _DOCUMENT_UPLOAD = "DOCUMENT_UPLOAD"; diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/utils/jurisdiction/JurisdictionValidator.java b/sormas-api/src/main/java/de/symeda/sormas/api/utils/jurisdiction/JurisdictionValidator.java index d3dd839a003..6421c683438 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/utils/jurisdiction/JurisdictionValidator.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/utils/jurisdiction/JurisdictionValidator.java @@ -23,21 +23,23 @@ public abstract class JurisdictionValidator { protected List> associatedJurisdictionValidators; + private boolean userHasRestrictedAccess; - public JurisdictionValidator(List> associatedJurisdictionValidators) { + public JurisdictionValidator(List> associatedJurisdictionValidators, boolean userHasRestrictedAccess) { this.associatedJurisdictionValidators = associatedJurisdictionValidators; + this.userHasRestrictedAccess = userHasRestrictedAccess; } // disease restriction overrules entity ownership public T inJurisdictionOrOwned() { - T rootInJurisdictionOrOwned = isRootInJurisdictionOrOwned(); + T rootInJurisdictionOrOwned = isRootAccessible(); T rootHasLimitedDisease = hasUserLimitedDisease(); if (associatedJurisdictionValidators != null && !associatedJurisdictionValidators.isEmpty()) { final List jurisdictionTypes = new ArrayList<>(); jurisdictionTypes.add(and(rootInJurisdictionOrOwned, rootHasLimitedDisease)); for (JurisdictionValidator jurisdictionValidator : associatedJurisdictionValidators) { if (jurisdictionValidator != null) { - T associatedInJurisdictionOrOwned = jurisdictionValidator.isRootInJurisdictionOrOwned(); + T associatedInJurisdictionOrOwned = jurisdictionValidator.isRootAccessible(); T associatedHasLimitedDisease = jurisdictionValidator.hasUserLimitedDisease(); jurisdictionTypes.add(and(associatedInJurisdictionOrOwned, associatedHasLimitedDisease)); } @@ -68,12 +70,21 @@ public T inJurisdiction() { } } + public T isRootAccessible() { + if (userHasRestrictedAccess) { + return isRootInJurisdictionForRestrictedAccess(); + } + return isRootInJurisdictionOrOwned(); + } + public abstract T isRootInJurisdiction(); public abstract T isRootInJurisdictionOrOwned(); public abstract T hasUserLimitedDisease(); + public abstract T isRootInJurisdictionForRestrictedAccess(); + protected T isInJurisdictionByJurisdictionLevel(JurisdictionLevel jurisdictionLevel) { switch (jurisdictionLevel) { diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/externalemail/luxembourg/CheckDigitLuhn.java b/sormas-api/src/main/java/de/symeda/sormas/api/utils/luxembourg/CheckDigitLuhn.java similarity index 95% rename from sormas-backend/src/main/java/de/symeda/sormas/backend/externalemail/luxembourg/CheckDigitLuhn.java rename to sormas-api/src/main/java/de/symeda/sormas/api/utils/luxembourg/CheckDigitLuhn.java index 698b79ce1b3..a9ba98dde08 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/externalemail/luxembourg/CheckDigitLuhn.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/utils/luxembourg/CheckDigitLuhn.java @@ -1,6 +1,6 @@ /* * SORMAS® - Surveillance Outbreak Response Management & Analysis System - * Copyright © 2016-2023 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package de.symeda.sormas.backend.externalemail.luxembourg; +package de.symeda.sormas.api.utils.luxembourg; /** * Apply Luhn algorithm to compute check digit diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/externalemail/luxembourg/CheckDigitVerhoeff.java b/sormas-api/src/main/java/de/symeda/sormas/api/utils/luxembourg/CheckDigitVerhoeff.java similarity index 98% rename from sormas-backend/src/main/java/de/symeda/sormas/backend/externalemail/luxembourg/CheckDigitVerhoeff.java rename to sormas-api/src/main/java/de/symeda/sormas/api/utils/luxembourg/CheckDigitVerhoeff.java index c34cc70d58d..88620dcd123 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/externalemail/luxembourg/CheckDigitVerhoeff.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/utils/luxembourg/CheckDigitVerhoeff.java @@ -1,6 +1,6 @@ /* * SORMAS® - Surveillance Outbreak Response Management & Analysis System - * Copyright © 2016-2023 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package de.symeda.sormas.backend.externalemail.luxembourg; +package de.symeda.sormas.api.utils.luxembourg; /** * Apply Verhoeff algorithm to compute check digit diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/utils/luxembourg/LuxembourgNationalHealthIdValidator.java b/sormas-api/src/main/java/de/symeda/sormas/api/utils/luxembourg/LuxembourgNationalHealthIdValidator.java new file mode 100644 index 00000000000..a4d6fb87cf5 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/utils/luxembourg/LuxembourgNationalHealthIdValidator.java @@ -0,0 +1,67 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.api.utils.luxembourg; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class LuxembourgNationalHealthIdValidator { + + /** + * - AAAA = année de naissance + * - MM = mois de naissance + * - JJ = jour de naissance + * - XXX = numéro aléatoire unique par date de naissance + * - C1 = numéro de contrôle calculé sur AAAAMMJJXXX suivant l’algorithme LUHN 10 + * - C2 = numéro de contrôle calculé sur AAAAMMJJXXX suivant l’algorithme VERHOEFF + */ + private static final Pattern NATIONAL_HEALTH_ID_PATTERN = Pattern.compile("(\\d{4})(\\d{2})(\\d{2})(\\d{3})(\\d)(\\d)"); + + public static boolean isValid(String nationalHealthId, Integer birthdateYYYY, Integer birthdateMM, Integer birthdateDD) { + if (nationalHealthId == null) { + return false; + } + + Matcher patternMatcher = NATIONAL_HEALTH_ID_PATTERN.matcher(nationalHealthId); + if (!patternMatcher.matches()) { + return false; + } + + String yyyy = patternMatcher.group(1); + String mm = patternMatcher.group(2); + String dd = patternMatcher.group(3); + String xxx = patternMatcher.group(4); + String c1 = patternMatcher.group(5); + String c2 = patternMatcher.group(6); + + if (isNullOrEquals(birthdateYYYY, Integer.parseInt(yyyy)) + && isNullOrEquals(birthdateMM, Integer.parseInt(mm)) + && isNullOrEquals(birthdateDD, Integer.parseInt(dd))) { + String iNumber = yyyy + mm + dd + xxx; + + if (CheckDigitLuhn.checkDigit(iNumber + c1) && CheckDigitVerhoeff.checkDigit(iNumber + c2)) { + return true; + } + } + + return false; + } + + private static boolean isNullOrEquals(Integer personBirthdateFieldValue, int yyyy) { + return personBirthdateFieldValue == null || personBirthdateFieldValue == yyyy; + } + +} diff --git a/sormas-api/src/main/resources/captions.properties b/sormas-api/src/main/resources/captions.properties index 2581ae76814..b5e788f5747 100644 --- a/sormas-api/src/main/resources/captions.properties +++ b/sormas-api/src/main/resources/captions.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_ar-SA.properties b/sormas-api/src/main/resources/captions_ar-SA.properties index b962ef802d5..a711b7f3304 100644 --- a/sormas-api/src/main/resources/captions_ar-SA.properties +++ b/sormas-api/src/main/resources/captions_ar-SA.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_cs-CZ.properties b/sormas-api/src/main/resources/captions_cs-CZ.properties index 800b76ec820..dada4e2d078 100644 --- a/sormas-api/src/main/resources/captions_cs-CZ.properties +++ b/sormas-api/src/main/resources/captions_cs-CZ.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Má detaily customizableEnumValueAllDiseases=Všechny nemoci customizableEnumValueDiseaseCount=%d nemoci customizableEnumValueNoProperties=Žádné vlastnosti +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Datový typ CustomizableEnumValue.value=Hodnota CustomizableEnumValue.caption=Popisek CustomizableEnumValue.diseases=Nemoci CustomizableEnumValue.properties=Vlastnosti +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Naživu dashboardApplyCustomFilter=Použít vlastní filtr @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Datum zprávy od... ExternalMessageCriteria.messageDateTo=... do ExternalMessageCriteria.birthDateFrom=Datum narození od... ExternalMessageCriteria.birthDateTo=... do +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Imunizace diff --git a/sormas-api/src/main/resources/captions_de-CH.properties b/sormas-api/src/main/resources/captions_de-CH.properties index 1d72d96b683..d6329821a69 100644 --- a/sormas-api/src/main/resources/captions_de-CH.properties +++ b/sormas-api/src/main/resources/captions_de-CH.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Lebendig dashboardApplyCustomFilter=Eigenen Filter anwenden @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Meldungsdatum von... ExternalMessageCriteria.messageDateTo=... bis ExternalMessageCriteria.birthDateFrom=Geburtsdatum von... ExternalMessageCriteria.birthDateTo=... bis +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunisierungen diff --git a/sormas-api/src/main/resources/captions_de-DE.properties b/sormas-api/src/main/resources/captions_de-DE.properties index 121a65ec2f2..e66f0327fa6 100644 --- a/sormas-api/src/main/resources/captions_de-DE.properties +++ b/sormas-api/src/main/resources/captions_de-DE.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Lebendig dashboardApplyCustomFilter=Eigenen Filter anwenden @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Meldungsdatum von... ExternalMessageCriteria.messageDateTo=... bis ExternalMessageCriteria.birthDateFrom=Geburtsdatum von... ExternalMessageCriteria.birthDateTo=... bis +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunisierungen diff --git a/sormas-api/src/main/resources/captions_en-AF.properties b/sormas-api/src/main/resources/captions_en-AF.properties index a63935ef48f..1e767a361ea 100644 --- a/sormas-api/src/main/resources/captions_en-AF.properties +++ b/sormas-api/src/main/resources/captions_en-AF.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_en-GH.properties b/sormas-api/src/main/resources/captions_en-GH.properties index a6b6aee3c83..5eca23c8810 100644 --- a/sormas-api/src/main/resources/captions_en-GH.properties +++ b/sormas-api/src/main/resources/captions_en-GH.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_en-NG.properties b/sormas-api/src/main/resources/captions_en-NG.properties index ed17cfa4b25..71ed97d0d6c 100644 --- a/sormas-api/src/main/resources/captions_en-NG.properties +++ b/sormas-api/src/main/resources/captions_en-NG.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_es-CU.properties b/sormas-api/src/main/resources/captions_es-CU.properties index 47c4c7dbbac..1b2bc909d01 100644 --- a/sormas-api/src/main/resources/captions_es-CU.properties +++ b/sormas-api/src/main/resources/captions_es-CU.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Tiene detalles customizableEnumValueAllDiseases=Todas las enfermedades customizableEnumValueDiseaseCount=%d enfermedades customizableEnumValueNoProperties=Sin propiedades +customizableEnumValueActiveValues=Valores activos +customizableEnumValueInactiveValues=Valores inactivos CustomizableEnumValue.dataType=Tipo de datos CustomizableEnumValue.value=Valor CustomizableEnumValue.caption=Leyenda CustomizableEnumValue.diseases=Enfermedades CustomizableEnumValue.properties=Propiedades +CustomizableEnumValue.active=Activo # Dashboard dashboardAlive=Vivo dashboardApplyCustomFilter=Aplicar filtro personalizado @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Fecha de mensaje desde... ExternalMessageCriteria.messageDateTo=... hasta ExternalMessageCriteria.birthDateFrom=Fecha de nacimiento desde... ExternalMessageCriteria.birthDateTo=... hasta +externalMessageValueNotSpecified=Valor no especificado en el mensaje externo #Physician report physiciansReportCaseImmunizations=Inmunizaciones diff --git a/sormas-api/src/main/resources/captions_es-ES.properties b/sormas-api/src/main/resources/captions_es-ES.properties index 314ec07ea6d..8ff51babe41 100644 --- a/sormas-api/src/main/resources/captions_es-ES.properties +++ b/sormas-api/src/main/resources/captions_es-ES.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_fa-AF.properties b/sormas-api/src/main/resources/captions_fa-AF.properties index 49a0ca12419..73c385a771d 100644 --- a/sormas-api/src/main/resources/captions_fa-AF.properties +++ b/sormas-api/src/main/resources/captions_fa-AF.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_fi-FI.properties b/sormas-api/src/main/resources/captions_fi-FI.properties index 1d508878220..6c79de7cfa9 100644 --- a/sormas-api/src/main/resources/captions_fi-FI.properties +++ b/sormas-api/src/main/resources/captions_fi-FI.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Elossa dashboardApplyCustomFilter=Käytä mukautettua suodatinta @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_fil-PH.properties b/sormas-api/src/main/resources/captions_fil-PH.properties index 6ba203efdd7..a27128b152b 100644 --- a/sormas-api/src/main/resources/captions_fil-PH.properties +++ b/sormas-api/src/main/resources/captions_fil-PH.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_fj-FJ.properties b/sormas-api/src/main/resources/captions_fj-FJ.properties index 6ba203efdd7..a27128b152b 100644 --- a/sormas-api/src/main/resources/captions_fj-FJ.properties +++ b/sormas-api/src/main/resources/captions_fj-FJ.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_fr-CD.properties b/sormas-api/src/main/resources/captions_fr-CD.properties index 100dbfc7d03..4a827adccc6 100644 --- a/sormas-api/src/main/resources/captions_fr-CD.properties +++ b/sormas-api/src/main/resources/captions_fr-CD.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_fr-CH.properties b/sormas-api/src/main/resources/captions_fr-CH.properties index 0b9f32b2b71..ffd13843f26 100644 --- a/sormas-api/src/main/resources/captions_fr-CH.properties +++ b/sormas-api/src/main/resources/captions_fr-CH.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Vivant dashboardApplyCustomFilter=Appliquer un filtre personnalisé @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_fr-FR.properties b/sormas-api/src/main/resources/captions_fr-FR.properties index 2a8af85d1d5..53c044cc48b 100644 --- a/sormas-api/src/main/resources/captions_fr-FR.properties +++ b/sormas-api/src/main/resources/captions_fr-FR.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=A des détails customizableEnumValueAllDiseases=Toutes les maladies customizableEnumValueDiseaseCount=%d maladies customizableEnumValueNoProperties=Aucune propriété +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Types de Donnée CustomizableEnumValue.value=Valeur CustomizableEnumValue.caption=Libellé CustomizableEnumValue.diseases=Maladies CustomizableEnumValue.properties=Propriétés +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Vivant dashboardApplyCustomFilter=Appliquer ce filtre personnalisé @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Date du message depuis... ExternalMessageCriteria.messageDateTo=... au ExternalMessageCriteria.birthDateFrom=Date de naissance de... ExternalMessageCriteria.birthDateTo=... au +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunisations diff --git a/sormas-api/src/main/resources/captions_fr-TN.properties b/sormas-api/src/main/resources/captions_fr-TN.properties index 470fe456902..2c14987797c 100644 --- a/sormas-api/src/main/resources/captions_fr-TN.properties +++ b/sormas-api/src/main/resources/captions_fr-TN.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Vivant dashboardApplyCustomFilter=Appliquer ce filtre personnalisé @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Date du message depuis... ExternalMessageCriteria.messageDateTo=... au ExternalMessageCriteria.birthDateFrom=Date de naissance de... ExternalMessageCriteria.birthDateTo=... au +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunisations diff --git a/sormas-api/src/main/resources/captions_hi-IN.properties b/sormas-api/src/main/resources/captions_hi-IN.properties index 6ba203efdd7..a27128b152b 100644 --- a/sormas-api/src/main/resources/captions_hi-IN.properties +++ b/sormas-api/src/main/resources/captions_hi-IN.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_hr-HR.properties b/sormas-api/src/main/resources/captions_hr-HR.properties index 6ba203efdd7..a27128b152b 100644 --- a/sormas-api/src/main/resources/captions_hr-HR.properties +++ b/sormas-api/src/main/resources/captions_hr-HR.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_it-CH.properties b/sormas-api/src/main/resources/captions_it-CH.properties index ae94b5bbfc0..12f249fc4e8 100644 --- a/sormas-api/src/main/resources/captions_it-CH.properties +++ b/sormas-api/src/main/resources/captions_it-CH.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=In vita dashboardApplyCustomFilter=Applica filtro personalizzato @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_it-IT.properties b/sormas-api/src/main/resources/captions_it-IT.properties index 68948bf3cc5..15b4e718992 100644 --- a/sormas-api/src/main/resources/captions_it-IT.properties +++ b/sormas-api/src/main/resources/captions_it-IT.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=In vita dashboardApplyCustomFilter=Applica filtro personalizzato @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_ja-JP.properties b/sormas-api/src/main/resources/captions_ja-JP.properties index 6ba203efdd7..a27128b152b 100644 --- a/sormas-api/src/main/resources/captions_ja-JP.properties +++ b/sormas-api/src/main/resources/captions_ja-JP.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_ne-NP.properties b/sormas-api/src/main/resources/captions_ne-NP.properties index b962ef802d5..a711b7f3304 100644 --- a/sormas-api/src/main/resources/captions_ne-NP.properties +++ b/sormas-api/src/main/resources/captions_ne-NP.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_nl-NL.properties b/sormas-api/src/main/resources/captions_nl-NL.properties index 28752af0c13..ecbea55be98 100644 --- a/sormas-api/src/main/resources/captions_nl-NL.properties +++ b/sormas-api/src/main/resources/captions_nl-NL.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_no-NO.properties b/sormas-api/src/main/resources/captions_no-NO.properties index 6ba203efdd7..a27128b152b 100644 --- a/sormas-api/src/main/resources/captions_no-NO.properties +++ b/sormas-api/src/main/resources/captions_no-NO.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_pl-PL.properties b/sormas-api/src/main/resources/captions_pl-PL.properties index 45727e4b14d..edfde41853e 100644 --- a/sormas-api/src/main/resources/captions_pl-PL.properties +++ b/sormas-api/src/main/resources/captions_pl-PL.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_ps-AF.properties b/sormas-api/src/main/resources/captions_ps-AF.properties index ff61e684f82..f878894d394 100644 --- a/sormas-api/src/main/resources/captions_ps-AF.properties +++ b/sormas-api/src/main/resources/captions_ps-AF.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=ژوندی dashboardApplyCustomFilter=کستم فلتر عملی کړه @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_pt-PT.properties b/sormas-api/src/main/resources/captions_pt-PT.properties index 00399a50a3e..857bdf279c1 100644 --- a/sormas-api/src/main/resources/captions_pt-PT.properties +++ b/sormas-api/src/main/resources/captions_pt-PT.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_ro-RO.properties b/sormas-api/src/main/resources/captions_ro-RO.properties index 6ba203efdd7..a27128b152b 100644 --- a/sormas-api/src/main/resources/captions_ro-RO.properties +++ b/sormas-api/src/main/resources/captions_ro-RO.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_ru-RU.properties b/sormas-api/src/main/resources/captions_ru-RU.properties index 153efa67b96..08c4e50c6f0 100644 --- a/sormas-api/src/main/resources/captions_ru-RU.properties +++ b/sormas-api/src/main/resources/captions_ru-RU.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_sv-SE.properties b/sormas-api/src/main/resources/captions_sv-SE.properties index 6ba203efdd7..a27128b152b 100644 --- a/sormas-api/src/main/resources/captions_sv-SE.properties +++ b/sormas-api/src/main/resources/captions_sv-SE.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_sw-KE.properties b/sormas-api/src/main/resources/captions_sw-KE.properties index 6ba203efdd7..a27128b152b 100644 --- a/sormas-api/src/main/resources/captions_sw-KE.properties +++ b/sormas-api/src/main/resources/captions_sw-KE.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_tr-TR.properties b/sormas-api/src/main/resources/captions_tr-TR.properties index 6ba203efdd7..a27128b152b 100644 --- a/sormas-api/src/main/resources/captions_tr-TR.properties +++ b/sormas-api/src/main/resources/captions_tr-TR.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_uk-UA.properties b/sormas-api/src/main/resources/captions_uk-UA.properties index 6ba203efdd7..a27128b152b 100644 --- a/sormas-api/src/main/resources/captions_uk-UA.properties +++ b/sormas-api/src/main/resources/captions_uk-UA.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/captions_ur-PK.properties b/sormas-api/src/main/resources/captions_ur-PK.properties index 1773d71a332..7b7337caea5 100644 --- a/sormas-api/src/main/resources/captions_ur-PK.properties +++ b/sormas-api/src/main/resources/captions_ur-PK.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=زندہ dashboardApplyCustomFilter=حسب ضرورت فلٹر لگائیں @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=پیغام کی تاریخ سے... ExternalMessageCriteria.messageDateTo=... تک ExternalMessageCriteria.birthDateFrom=تاریخ پیدائش سے... ExternalMessageCriteria.birthDateTo=... تک +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=امیونائزیشنز diff --git a/sormas-api/src/main/resources/captions_zh-CN.properties b/sormas-api/src/main/resources/captions_zh-CN.properties index 2c09b52be1a..cef77aeae54 100644 --- a/sormas-api/src/main/resources/captions_zh-CN.properties +++ b/sormas-api/src/main/resources/captions_zh-CN.properties @@ -866,11 +866,14 @@ CustomizableEnum.hasDetails.short=Has details customizableEnumValueAllDiseases=All diseases customizableEnumValueDiseaseCount=%d diseases customizableEnumValueNoProperties=No properties +customizableEnumValueActiveValues=Active values +customizableEnumValueInactiveValues=Inactive values CustomizableEnumValue.dataType=Data type CustomizableEnumValue.value=Value CustomizableEnumValue.caption=Caption CustomizableEnumValue.diseases=Diseases CustomizableEnumValue.properties=Properties +CustomizableEnumValue.active=Active # Dashboard dashboardAlive=Alive dashboardApplyCustomFilter=Apply custom filter @@ -1606,6 +1609,7 @@ externalMessageCriteria.messageDateFrom=Message date from... ExternalMessageCriteria.messageDateTo=... to ExternalMessageCriteria.birthDateFrom=Birth date from... ExternalMessageCriteria.birthDateTo=... to +externalMessageValueNotSpecified=Value not specified in external message #Physician report physiciansReportCaseImmunizations=Immunizations diff --git a/sormas-api/src/main/resources/doc/SORMAS_Data_Dictionary.xlsx b/sormas-api/src/main/resources/doc/SORMAS_Data_Dictionary.xlsx index e058e33fa20..39fb8289ac0 100644 Binary files a/sormas-api/src/main/resources/doc/SORMAS_Data_Dictionary.xlsx and b/sormas-api/src/main/resources/doc/SORMAS_Data_Dictionary.xlsx differ diff --git a/sormas-api/src/main/resources/doc/SORMAS_User_Roles.xlsx b/sormas-api/src/main/resources/doc/SORMAS_User_Roles.xlsx index e3882ca342e..77b355ff3cd 100644 Binary files a/sormas-api/src/main/resources/doc/SORMAS_User_Roles.xlsx and b/sormas-api/src/main/resources/doc/SORMAS_User_Roles.xlsx differ diff --git a/sormas-api/src/main/resources/enum.properties b/sormas-api/src/main/resources/enum.properties index 0cc051ecb54..8efb5414ea3 100644 --- a/sormas-api/src/main/resources/enum.properties +++ b/sormas-api/src/main/resources/enum.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_ar-SA.properties b/sormas-api/src/main/resources/enum_ar-SA.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_ar-SA.properties +++ b/sormas-api/src/main/resources/enum_ar-SA.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_cs-CZ.properties b/sormas-api/src/main/resources/enum_cs-CZ.properties index 47c3bfd20c7..0ac8fc97d1c 100644 --- a/sormas-api/src/main/resources/enum_cs-CZ.properties +++ b/sormas-api/src/main/resources/enum_cs-CZ.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Upravit příchozí informace vzork UserRight.ENVIRONMENT_SAMPLE_DELETE = Odstranit vzorky prostředí ze systému UserRight.ENVIRONMENT_SAMPLE_IMPORT = Importovat vzorky prostředí UserRight.ENVIRONMENT_SAMPLE_EXPORT = Exportovat vzorky prostředí +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Odeslat externí e-maily UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Připojit dokumenty k externím e-mailům @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Může upravit příchozí inf UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Může odstranit vzorky prostředí ze systému UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Může importovat vzorky prostředí UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Může exportovat vzorky prostředí +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Může spravovat šablony e-mailů UserRight.Desc.EXTERNAL_EMAIL_SEND=Může odeslat externí e-maily UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Může připojit dokumenty k externím e-mailům diff --git a/sormas-api/src/main/resources/enum_de-CH.properties b/sormas-api/src/main/resources/enum_de-CH.properties index ab9a6d9e52c..570805998e9 100644 --- a/sormas-api/src/main/resources/enum_de-CH.properties +++ b/sormas-api/src/main/resources/enum_de-CH.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_de-DE.properties b/sormas-api/src/main/resources/enum_de-DE.properties index e5533382649..b056d1d1a26 100644 --- a/sormas-api/src/main/resources/enum_de-DE.properties +++ b/sormas-api/src/main/resources/enum_de-DE.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_en-AF.properties b/sormas-api/src/main/resources/enum_en-AF.properties index e87f52231b8..950ca20b7df 100644 --- a/sormas-api/src/main/resources/enum_en-AF.properties +++ b/sormas-api/src/main/resources/enum_en-AF.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_en-GH.properties b/sormas-api/src/main/resources/enum_en-GH.properties index 0d2c938c3a1..00ac6fc3d2b 100644 --- a/sormas-api/src/main/resources/enum_en-GH.properties +++ b/sormas-api/src/main/resources/enum_en-GH.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_en-NG.properties b/sormas-api/src/main/resources/enum_en-NG.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_en-NG.properties +++ b/sormas-api/src/main/resources/enum_en-NG.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_es-CU.properties b/sormas-api/src/main/resources/enum_es-CU.properties index acc97cdd169..de6e967f55a 100644 --- a/sormas-api/src/main/resources/enum_es-CU.properties +++ b/sormas-api/src/main/resources/enum_es-CU.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Editar información de recepción d UserRight.ENVIRONMENT_SAMPLE_DELETE = Eliminar muestras ambientales del sistema UserRight.ENVIRONMENT_SAMPLE_IMPORT = Importar muestras ambientales UserRight.ENVIRONMENT_SAMPLE_EXPORT = Exportar muestras ambientales +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Crear pruebas de patógeno para muestra de ambiente +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Editar pruebas de patógeno para muestra de ambiente +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Eliminar pruebas de patógeno para muestra de ambiente UserRight.EMAIL_TEMPLATE_MANAGEMENT=Administrar plantillas de mensajes UserRight.EXTERNAL_EMAIL_SEND=Enviar mensajes externos UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Adjuntar documentos a mensajes externos @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Puede editar información de r UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Puede eliminar muestras ambientales del sistema UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Puede importar muestras ambientales UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Puede exportar muestras ambientales +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Puede crear pruebas de patógeno para muestra de ambiente +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Puede editar pruebas de patógeno para muestra de ambiente +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Puede eliminar pruebas de patógeno para muestra de ambiente UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Puede administrar plantillas de mensajes UserRight.Desc.EXTERNAL_EMAIL_SEND=Puede enviar mensajes externos UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Puede adjuntar documentos a mensajes externos diff --git a/sormas-api/src/main/resources/enum_es-ES.properties b/sormas-api/src/main/resources/enum_es-ES.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_es-ES.properties +++ b/sormas-api/src/main/resources/enum_es-ES.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_fa-AF.properties b/sormas-api/src/main/resources/enum_fa-AF.properties index 205cd4f4008..341abb1c0aa 100644 --- a/sormas-api/src/main/resources/enum_fa-AF.properties +++ b/sormas-api/src/main/resources/enum_fa-AF.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_fi-FI.properties b/sormas-api/src/main/resources/enum_fi-FI.properties index a14bf0d736d..bce2a53f569 100644 --- a/sormas-api/src/main/resources/enum_fi-FI.properties +++ b/sormas-api/src/main/resources/enum_fi-FI.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_fil-PH.properties b/sormas-api/src/main/resources/enum_fil-PH.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_fil-PH.properties +++ b/sormas-api/src/main/resources/enum_fil-PH.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_fj-FJ.properties b/sormas-api/src/main/resources/enum_fj-FJ.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_fj-FJ.properties +++ b/sormas-api/src/main/resources/enum_fj-FJ.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_fr-CD.properties b/sormas-api/src/main/resources/enum_fr-CD.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_fr-CD.properties +++ b/sormas-api/src/main/resources/enum_fr-CD.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_fr-CH.properties b/sormas-api/src/main/resources/enum_fr-CH.properties index 455ef397721..24428f05498 100644 --- a/sormas-api/src/main/resources/enum_fr-CH.properties +++ b/sormas-api/src/main/resources/enum_fr-CH.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_fr-FR.properties b/sormas-api/src/main/resources/enum_fr-FR.properties index 81e657a7437..b379752459e 100644 --- a/sormas-api/src/main/resources/enum_fr-FR.properties +++ b/sormas-api/src/main/resources/enum_fr-FR.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Gérer les modèles d'e-mail UserRight.EXTERNAL_EMAIL_SEND=Envoyer des e-mails externes UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Joindre des documents aux e-mails externes @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Capable de gérer les modèles d'e-mail UserRight.Desc.EXTERNAL_EMAIL_SEND=Capable d'envoyer des e-mails externes UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Capable de joindre des documents à des e-mails externes diff --git a/sormas-api/src/main/resources/enum_fr-TN.properties b/sormas-api/src/main/resources/enum_fr-TN.properties index fee97038e88..0b4268d50bd 100644 --- a/sormas-api/src/main/resources/enum_fr-TN.properties +++ b/sormas-api/src/main/resources/enum_fr-TN.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_hi-IN.properties b/sormas-api/src/main/resources/enum_hi-IN.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_hi-IN.properties +++ b/sormas-api/src/main/resources/enum_hi-IN.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_hr-HR.properties b/sormas-api/src/main/resources/enum_hr-HR.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_hr-HR.properties +++ b/sormas-api/src/main/resources/enum_hr-HR.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_it-CH.properties b/sormas-api/src/main/resources/enum_it-CH.properties index 5c4ae7e1726..e531aae5c28 100644 --- a/sormas-api/src/main/resources/enum_it-CH.properties +++ b/sormas-api/src/main/resources/enum_it-CH.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_it-IT.properties b/sormas-api/src/main/resources/enum_it-IT.properties index 30b8a7f37b3..3d870fa1a7c 100644 --- a/sormas-api/src/main/resources/enum_it-IT.properties +++ b/sormas-api/src/main/resources/enum_it-IT.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_ja-JP.properties b/sormas-api/src/main/resources/enum_ja-JP.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_ja-JP.properties +++ b/sormas-api/src/main/resources/enum_ja-JP.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_ne-NP.properties b/sormas-api/src/main/resources/enum_ne-NP.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_ne-NP.properties +++ b/sormas-api/src/main/resources/enum_ne-NP.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_nl-NL.properties b/sormas-api/src/main/resources/enum_nl-NL.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_nl-NL.properties +++ b/sormas-api/src/main/resources/enum_nl-NL.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_no-NO.properties b/sormas-api/src/main/resources/enum_no-NO.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_no-NO.properties +++ b/sormas-api/src/main/resources/enum_no-NO.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_pl-PL.properties b/sormas-api/src/main/resources/enum_pl-PL.properties index 5da3af65949..7cdd984388f 100644 --- a/sormas-api/src/main/resources/enum_pl-PL.properties +++ b/sormas-api/src/main/resources/enum_pl-PL.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_ps-AF.properties b/sormas-api/src/main/resources/enum_ps-AF.properties index 205cd4f4008..341abb1c0aa 100644 --- a/sormas-api/src/main/resources/enum_ps-AF.properties +++ b/sormas-api/src/main/resources/enum_ps-AF.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_pt-PT.properties b/sormas-api/src/main/resources/enum_pt-PT.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_pt-PT.properties +++ b/sormas-api/src/main/resources/enum_pt-PT.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_ro-RO.properties b/sormas-api/src/main/resources/enum_ro-RO.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_ro-RO.properties +++ b/sormas-api/src/main/resources/enum_ro-RO.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_ru-RU.properties b/sormas-api/src/main/resources/enum_ru-RU.properties index ea3d90d12bb..4aa47fbadad 100644 --- a/sormas-api/src/main/resources/enum_ru-RU.properties +++ b/sormas-api/src/main/resources/enum_ru-RU.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_sv-SE.properties b/sormas-api/src/main/resources/enum_sv-SE.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_sv-SE.properties +++ b/sormas-api/src/main/resources/enum_sv-SE.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_sw-KE.properties b/sormas-api/src/main/resources/enum_sw-KE.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_sw-KE.properties +++ b/sormas-api/src/main/resources/enum_sw-KE.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_tr-TR.properties b/sormas-api/src/main/resources/enum_tr-TR.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_tr-TR.properties +++ b/sormas-api/src/main/resources/enum_tr-TR.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_uk-UA.properties b/sormas-api/src/main/resources/enum_uk-UA.properties index d35b6f4fc91..a470fa223b8 100644 --- a/sormas-api/src/main/resources/enum_uk-UA.properties +++ b/sormas-api/src/main/resources/enum_uk-UA.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_ur-PK.properties b/sormas-api/src/main/resources/enum_ur-PK.properties index d6e6398422b..186192e1801 100644 --- a/sormas-api/src/main/resources/enum_ur-PK.properties +++ b/sormas-api/src/main/resources/enum_ur-PK.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/enum_zh-CN.properties b/sormas-api/src/main/resources/enum_zh-CN.properties index 1b60829c8be..e2d538c91aa 100644 --- a/sormas-api/src/main/resources/enum_zh-CN.properties +++ b/sormas-api/src/main/resources/enum_zh-CN.properties @@ -1585,6 +1585,9 @@ UserRight.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Edit environment samples receival i UserRight.ENVIRONMENT_SAMPLE_DELETE = Delete environment samples from the system UserRight.ENVIRONMENT_SAMPLE_IMPORT = Import environment samples UserRight.ENVIRONMENT_SAMPLE_EXPORT = Export environment samples +UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE = Create environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT = Edit environment sample pathogen tests +UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE = Delete environment sample pathogen tests UserRight.EMAIL_TEMPLATE_MANAGEMENT=Manage email templates UserRight.EXTERNAL_EMAIL_SEND=Send external emails UserRight.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Attach documents to external emails @@ -1783,6 +1786,9 @@ UserRight.Desc.ENVIRONMENT_SAMPLE_EDIT_RECEIVAL = Able to edit environment sampl UserRight.Desc.ENVIRONMENT_SAMPLE_DELETE = Able to delete environment samples from the system UserRight.Desc.ENVIRONMENT_SAMPLE_IMPORT = Able to import environment samples UserRight.Desc.ENVIRONMENT_SAMPLE_EXPORT = Able to export environment samples +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_CREATE = Able to create environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_EDIT = Able to edit environment sample pathogen tests +UserRight.Desc.ENVIRONMENT_PATHOGEN_TEST_DELETE = Able to delete environment sample pathogen tests UserRight.Desc.EMAIL_TEMPLATE_MANAGEMENT=Able to manage email templates UserRight.Desc.EXTERNAL_EMAIL_SEND=Able to send external emails UserRight.Desc.EXTERNAL_EMAIL_ATTACH_DOCUMENTS=Able to attach documents to external emails diff --git a/sormas-api/src/main/resources/strings.properties b/sormas-api/src/main/resources/strings.properties index 6188641d36f..4c5d537912f 100644 --- a/sormas-api/src/main/resources/strings.properties +++ b/sormas-api/src/main/resources/strings.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_ar-SA.properties b/sormas-api/src/main/resources/strings_ar-SA.properties index e4e38383b71..2d0700018e9 100644 --- a/sormas-api/src/main/resources/strings_ar-SA.properties +++ b/sormas-api/src/main/resources/strings_ar-SA.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_cs-CZ.properties b/sormas-api/src/main/resources/strings_cs-CZ.properties index c9571bc9a7b..a9bf85558be 100644 --- a/sormas-api/src/main/resources/strings_cs-CZ.properties +++ b/sormas-api/src/main/resources/strings_cs-CZ.properties @@ -59,6 +59,7 @@ quarantineEnd = Karanténa končí na konci následných opatření quarterShort = Q reportedBy = Nahlášeno reportedOn = Nahlášeno dne +reportingUser = Reporting user\: step = Krok setTo = Nastavit na toCase = k případu @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = Klasifikace případu %s se změnila na %s. notificationCaseInvestigationDone = Vyšetřování případu %s bylo dokončeno. diff --git a/sormas-api/src/main/resources/strings_de-CH.properties b/sormas-api/src/main/resources/strings_de-CH.properties index cad56da96fb..c4cc70667da 100644 --- a/sormas-api/src/main/resources/strings_de-CH.properties +++ b/sormas-api/src/main/resources/strings_de-CH.properties @@ -59,6 +59,7 @@ quarantineEnd = Isolation endet mit dem Ende des Follow-Ups quarterShort = Q reportedBy = Gemeldet von reportedOn = Gemeldet am +reportingUser = Reporting user\: step = Step setTo = Festlegen auf toCase = \ gehört zu Fall @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = Die Falldefinitionskategorie des Falls %s wurde auf %s geändert. notificationCaseInvestigationDone = Die Untersuchung des Falls %s wurde durchgeführt. diff --git a/sormas-api/src/main/resources/strings_de-DE.properties b/sormas-api/src/main/resources/strings_de-DE.properties index 607d769fc35..b43aab471fc 100644 --- a/sormas-api/src/main/resources/strings_de-DE.properties +++ b/sormas-api/src/main/resources/strings_de-DE.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantäne endet mit dem Ende des Follow-Ups quarterShort = Q reportedBy = Gemeldet von reportedOn = Gemeldet am +reportingUser = Reporting user\: step = Schritt setTo = gesetzt auf toCase = zu Fall @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = Die Falldefinitionskategorie des Falls %s wurde auf %s geändert. notificationCaseInvestigationDone = Die Untersuchung des Falls %s wurde durchgeführt. diff --git a/sormas-api/src/main/resources/strings_en-AF.properties b/sormas-api/src/main/resources/strings_en-AF.properties index b7aaf4b74f9..f4b0caca1f3 100644 --- a/sormas-api/src/main/resources/strings_en-AF.properties +++ b/sormas-api/src/main/resources/strings_en-AF.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_en-GH.properties b/sormas-api/src/main/resources/strings_en-GH.properties index f055ff748bb..f3cf428cf05 100644 --- a/sormas-api/src/main/resources/strings_en-GH.properties +++ b/sormas-api/src/main/resources/strings_en-GH.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_en-NG.properties b/sormas-api/src/main/resources/strings_en-NG.properties index d8d8b151b91..dd4efa2a14d 100644 --- a/sormas-api/src/main/resources/strings_en-NG.properties +++ b/sormas-api/src/main/resources/strings_en-NG.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_es-CU.properties b/sormas-api/src/main/resources/strings_es-CU.properties index c371292f522..45e01fe437f 100644 --- a/sormas-api/src/main/resources/strings_es-CU.properties +++ b/sormas-api/src/main/resources/strings_es-CU.properties @@ -59,6 +59,7 @@ quarantineEnd = La cuarentena termina al final del seguimiento quarterShort = T reportedBy = Informado por reportedOn = Informado en +reportingUser = Usuario informante\: step = Paso setTo = Establecer como toCase = para el caso @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=Sin archivos adjuntos messageCustomizableEnumValueSaved = Valor de enumeración personalizable guardado messageExternalEmailAttachmentPassword=Por favor, utilice esta contraseña para abrir los documentos que se le envíen por correo electrónico desde SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=No se pueden adjuntar documentos porque el cifrado no sería posible. Para cifrar documentos, la persona debe tener un carnet de identidad, o un número de teléfono móvil con capacidad de enviar SMS especificado en este sistema. +messagePersonNationalHealthIdInvalid=El carnet de identidad introducido no parece ser correcto # Notifications notificationCaseClassificationChanged = La clasificación del caso %s se cambió a %s. notificationCaseInvestigationDone = La investigación del caso %s fue realizada. diff --git a/sormas-api/src/main/resources/strings_es-ES.properties b/sormas-api/src/main/resources/strings_es-ES.properties index 1a5e1ed321c..0091ff3dc78 100644 --- a/sormas-api/src/main/resources/strings_es-ES.properties +++ b/sormas-api/src/main/resources/strings_es-ES.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_fa-AF.properties b/sormas-api/src/main/resources/strings_fa-AF.properties index 1a5e1ed321c..0091ff3dc78 100644 --- a/sormas-api/src/main/resources/strings_fa-AF.properties +++ b/sormas-api/src/main/resources/strings_fa-AF.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_fi-FI.properties b/sormas-api/src/main/resources/strings_fi-FI.properties index 4a7eecaf1f5..05ce1403ee8 100644 --- a/sormas-api/src/main/resources/strings_fi-FI.properties +++ b/sormas-api/src/main/resources/strings_fi-FI.properties @@ -59,6 +59,7 @@ quarantineEnd = Karanteeni päättyy seurannan lopussa quarterShort = N reportedBy = Ilmoittaja reportedOn = Ilmoitettu +reportingUser = Reporting user\: step = Vaihe setTo = Set to toCase = potilaalle @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = Potilaan %s luokitus on muuttunut luokkaan %s. notificationCaseInvestigationDone = Potilaan %s selvittely tehty. diff --git a/sormas-api/src/main/resources/strings_fil-PH.properties b/sormas-api/src/main/resources/strings_fil-PH.properties index 1a5e1ed321c..0091ff3dc78 100644 --- a/sormas-api/src/main/resources/strings_fil-PH.properties +++ b/sormas-api/src/main/resources/strings_fil-PH.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_fj-FJ.properties b/sormas-api/src/main/resources/strings_fj-FJ.properties index 1a5e1ed321c..0091ff3dc78 100644 --- a/sormas-api/src/main/resources/strings_fj-FJ.properties +++ b/sormas-api/src/main/resources/strings_fj-FJ.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_fr-CD.properties b/sormas-api/src/main/resources/strings_fr-CD.properties index b073e6e7b55..aa31e536daf 100644 --- a/sormas-api/src/main/resources/strings_fr-CD.properties +++ b/sormas-api/src/main/resources/strings_fr-CD.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_fr-CH.properties b/sormas-api/src/main/resources/strings_fr-CH.properties index 20643553e04..2ec96563590 100644 --- a/sormas-api/src/main/resources/strings_fr-CH.properties +++ b/sormas-api/src/main/resources/strings_fr-CH.properties @@ -59,6 +59,7 @@ quarantineEnd = L'isolation se termine à la fin du suivi quarterShort = Q reportedBy = Signalé par reportedOn = Signalé le +reportingUser = Reporting user\: step = Etape setTo = Set to toCase = au cas @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = La classification du cas %s a changé en %s. notificationCaseInvestigationDone = L'enquête du cas %s a été effectuée. diff --git a/sormas-api/src/main/resources/strings_fr-FR.properties b/sormas-api/src/main/resources/strings_fr-FR.properties index 9fd7c416320..b415fde8883 100644 --- a/sormas-api/src/main/resources/strings_fr-FR.properties +++ b/sormas-api/src/main/resources/strings_fr-FR.properties @@ -59,6 +59,7 @@ quarantineEnd = La quarantaine se termine à la fin du suivi quarterShort = Q reportedBy = Signalée par reportedOn = Signalé le +reportingUser = Reporting user\: step = Etape setTo = Régler sur toCase = au cas @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Valeur de l'énumération personnalisable enregistrée messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = La classification du cas %s a changé en %s. notificationCaseInvestigationDone = L'enquête du cas %s a été effectuée. diff --git a/sormas-api/src/main/resources/strings_fr-TN.properties b/sormas-api/src/main/resources/strings_fr-TN.properties index ed5d948b958..05a108a14d1 100644 --- a/sormas-api/src/main/resources/strings_fr-TN.properties +++ b/sormas-api/src/main/resources/strings_fr-TN.properties @@ -59,6 +59,7 @@ quarantineEnd = La quarantaine se termine à la fin du suivi quarterShort = Q reportedBy = Signalée par reportedOn = Signalé le +reportingUser = Reporting user\: step = Etape setTo = Régler sur toCase = au cas @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = La classification du cas %s a changé en %s. notificationCaseInvestigationDone = L'enquête du cas %s a été effectuée. diff --git a/sormas-api/src/main/resources/strings_hi-IN.properties b/sormas-api/src/main/resources/strings_hi-IN.properties index 1a5e1ed321c..0091ff3dc78 100644 --- a/sormas-api/src/main/resources/strings_hi-IN.properties +++ b/sormas-api/src/main/resources/strings_hi-IN.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_hr-HR.properties b/sormas-api/src/main/resources/strings_hr-HR.properties index 1a5e1ed321c..0091ff3dc78 100644 --- a/sormas-api/src/main/resources/strings_hr-HR.properties +++ b/sormas-api/src/main/resources/strings_hr-HR.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_it-CH.properties b/sormas-api/src/main/resources/strings_it-CH.properties index f4e1bf2b82f..9994005645d 100644 --- a/sormas-api/src/main/resources/strings_it-CH.properties +++ b/sormas-api/src/main/resources/strings_it-CH.properties @@ -59,6 +59,7 @@ quarantineEnd = La quarantena termina alla fine del follow-up quarterShort = Q reportedBy = Segnalato da reportedOn = Segnalato il +reportingUser = Reporting user\: step = Fase setTo = Set to toCase = nel caso @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = La classificazione del caso %s è cambiata in %s. notificationCaseInvestigationDone = La ricerca sul caso %s è stata effettuata. diff --git a/sormas-api/src/main/resources/strings_it-IT.properties b/sormas-api/src/main/resources/strings_it-IT.properties index 4cb759c9270..7c5a3cdbb60 100644 --- a/sormas-api/src/main/resources/strings_it-IT.properties +++ b/sormas-api/src/main/resources/strings_it-IT.properties @@ -59,6 +59,7 @@ quarantineEnd = La quarantena termina alla fine del follow-up quarterShort = Q reportedBy = Segnalato da reportedOn = Segnalato il +reportingUser = Reporting user\: step = Fase setTo = Set to toCase = nel caso @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = La classificazione del caso %s è cambiata in %s. notificationCaseInvestigationDone = La ricerca sul caso %s è stata effettuata. diff --git a/sormas-api/src/main/resources/strings_ja-JP.properties b/sormas-api/src/main/resources/strings_ja-JP.properties index 1a5e1ed321c..0091ff3dc78 100644 --- a/sormas-api/src/main/resources/strings_ja-JP.properties +++ b/sormas-api/src/main/resources/strings_ja-JP.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_ne-NP.properties b/sormas-api/src/main/resources/strings_ne-NP.properties index e4e38383b71..2d0700018e9 100644 --- a/sormas-api/src/main/resources/strings_ne-NP.properties +++ b/sormas-api/src/main/resources/strings_ne-NP.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_nl-NL.properties b/sormas-api/src/main/resources/strings_nl-NL.properties index 1a5e1ed321c..0091ff3dc78 100644 --- a/sormas-api/src/main/resources/strings_nl-NL.properties +++ b/sormas-api/src/main/resources/strings_nl-NL.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_no-NO.properties b/sormas-api/src/main/resources/strings_no-NO.properties index 1a5e1ed321c..0091ff3dc78 100644 --- a/sormas-api/src/main/resources/strings_no-NO.properties +++ b/sormas-api/src/main/resources/strings_no-NO.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_pl-PL.properties b/sormas-api/src/main/resources/strings_pl-PL.properties index 0021767deb7..d6c192f1ec0 100644 --- a/sormas-api/src/main/resources/strings_pl-PL.properties +++ b/sormas-api/src/main/resources/strings_pl-PL.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_ps-AF.properties b/sormas-api/src/main/resources/strings_ps-AF.properties index eac76349a27..1ca076e3e47 100644 --- a/sormas-api/src/main/resources/strings_ps-AF.properties +++ b/sormas-api/src/main/resources/strings_ps-AF.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_pt-PT.properties b/sormas-api/src/main/resources/strings_pt-PT.properties index 1a5e1ed321c..0091ff3dc78 100644 --- a/sormas-api/src/main/resources/strings_pt-PT.properties +++ b/sormas-api/src/main/resources/strings_pt-PT.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_ro-RO.properties b/sormas-api/src/main/resources/strings_ro-RO.properties index 1a5e1ed321c..0091ff3dc78 100644 --- a/sormas-api/src/main/resources/strings_ro-RO.properties +++ b/sormas-api/src/main/resources/strings_ro-RO.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_ru-RU.properties b/sormas-api/src/main/resources/strings_ru-RU.properties index 4694646b208..71fde68a288 100644 --- a/sormas-api/src/main/resources/strings_ru-RU.properties +++ b/sormas-api/src/main/resources/strings_ru-RU.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_sv-SE.properties b/sormas-api/src/main/resources/strings_sv-SE.properties index 1a5e1ed321c..0091ff3dc78 100644 --- a/sormas-api/src/main/resources/strings_sv-SE.properties +++ b/sormas-api/src/main/resources/strings_sv-SE.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_sw-KE.properties b/sormas-api/src/main/resources/strings_sw-KE.properties index 1a5e1ed321c..0091ff3dc78 100644 --- a/sormas-api/src/main/resources/strings_sw-KE.properties +++ b/sormas-api/src/main/resources/strings_sw-KE.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_tr-TR.properties b/sormas-api/src/main/resources/strings_tr-TR.properties index 1a5e1ed321c..0091ff3dc78 100644 --- a/sormas-api/src/main/resources/strings_tr-TR.properties +++ b/sormas-api/src/main/resources/strings_tr-TR.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_uk-UA.properties b/sormas-api/src/main/resources/strings_uk-UA.properties index 1a5e1ed321c..0091ff3dc78 100644 --- a/sormas-api/src/main/resources/strings_uk-UA.properties +++ b/sormas-api/src/main/resources/strings_uk-UA.properties @@ -59,6 +59,7 @@ quarantineEnd = Quarantine ends at the end of follow-up quarterShort = Q reportedBy = Reported By reportedOn = Reported on +reportingUser = Reporting user\: step = Step setTo = Set to toCase = to case @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/strings_ur-PK.properties b/sormas-api/src/main/resources/strings_ur-PK.properties index f1129df9b04..97e988efb1e 100644 --- a/sormas-api/src/main/resources/strings_ur-PK.properties +++ b/sormas-api/src/main/resources/strings_ur-PK.properties @@ -59,6 +59,7 @@ quarantineEnd = فالو اپ کے اختتام پر قرنطینہ ختم ہو quarterShort = Q reportedBy = رپورٹ کنندہ reportedOn = پر رپورٹ کیا +reportingUser = Reporting user\: step = قدم setTo = پر سیٹ کریں toCase = کیس کے لئے @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = کیس %s کی درجہ بندی %s میں تبدیل ہو گئی ہے۔ notificationCaseInvestigationDone = کیس %s کی تفتیش ہو چکی ہے۔ diff --git a/sormas-api/src/main/resources/strings_zh-CN.properties b/sormas-api/src/main/resources/strings_zh-CN.properties index d104d9d8c6f..d0e2835ccad 100644 --- a/sormas-api/src/main/resources/strings_zh-CN.properties +++ b/sormas-api/src/main/resources/strings_zh-CN.properties @@ -59,6 +59,7 @@ quarantineEnd = 检疫在后续行动结束时结束 quarterShort = Q reportedBy = 报告由 reportedOn = 报告于 +reportingUser = Reporting user\: step = 步骤 setTo = 设置为 toCase = 对案例 @@ -1497,6 +1498,7 @@ messageExternalEmailNoAttachments=No attachments messageCustomizableEnumValueSaved = Customizable enum value saved messageExternalEmailAttachmentPassword=Please use this password to open the documents sent to you via email from SORMAS\: %s messageExternalEmailAttachmentNotAvailableInfo=Attaching documents is disabled because encryption would not be possible. To encrypt documents, the person needs to have either a national health ID specified, or a primary mobile phone number set with SMS sending set up on this system. +messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. notificationCaseInvestigationDone = The investigation of case %s has been done. diff --git a/sormas-api/src/main/resources/validations.properties b/sormas-api/src/main/resources/validations.properties index 5e92dd5e38c..2f55e0e2a24 100644 --- a/sormas-api/src/main/resources/validations.properties +++ b/sormas-api/src/main/resources/validations.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_ar-SA.properties b/sormas-api/src/main/resources/validations_ar-SA.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_ar-SA.properties +++ b/sormas-api/src/main/resources/validations_ar-SA.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_cs-CZ.properties b/sormas-api/src/main/resources/validations_cs-CZ.properties index 48002e8c4b2..54c85230e7d 100644 --- a/sormas-api/src/main/resources/validations_cs-CZ.properties +++ b/sormas-api/src/main/resources/validations_cs-CZ.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Hodnota se může skládat pouze z velk customizableEnumValueEmptyTranslations = Vyberte jazyky a zadejte popisky pro všechny překlady v seznamu. customizableEnumValueDuplicateLanguage = Přidejte pouze jeden překlad pro každý jazyk. customizableEnumValueDuplicateValue = Hodnota %s již existuje pro datový typ %s. Hodnoty Enum musí být jedinečné. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_de-CH.properties b/sormas-api/src/main/resources/validations_de-CH.properties index bc8fa7f9aad..1a9b00623e3 100644 --- a/sormas-api/src/main/resources/validations_de-CH.properties +++ b/sormas-api/src/main/resources/validations_de-CH.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_de-DE.properties b/sormas-api/src/main/resources/validations_de-DE.properties index b49531cf805..13cccfc2159 100644 --- a/sormas-api/src/main/resources/validations_de-DE.properties +++ b/sormas-api/src/main/resources/validations_de-DE.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_en-AF.properties b/sormas-api/src/main/resources/validations_en-AF.properties index 78cc9588ad2..9c415edd895 100644 --- a/sormas-api/src/main/resources/validations_en-AF.properties +++ b/sormas-api/src/main/resources/validations_en-AF.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_en-GH.properties b/sormas-api/src/main/resources/validations_en-GH.properties index 73c9e715bef..083ea9a7118 100644 --- a/sormas-api/src/main/resources/validations_en-GH.properties +++ b/sormas-api/src/main/resources/validations_en-GH.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_en-NG.properties b/sormas-api/src/main/resources/validations_en-NG.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_en-NG.properties +++ b/sormas-api/src/main/resources/validations_en-NG.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_es-CU.properties b/sormas-api/src/main/resources/validations_es-CU.properties index 9f845f0fbc7..c4eb9f4e8e1 100644 --- a/sormas-api/src/main/resources/validations_es-CU.properties +++ b/sormas-api/src/main/resources/validations_es-CU.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = El valor sólo puede consistir en letra customizableEnumValueEmptyTranslations = Por favor, seleccione idiomas e introduzca leyendas para todas las traducciones de la lista. customizableEnumValueDuplicateLanguage = Por favor, sólo añada una traducción por idioma. customizableEnumValueDuplicateValue = El valor %s ya existe para el tipo de datos %s. Los valores de enumeración deben ser únicos. -attachedDocumentNotRelatedToEntity=El documento adjunto no está relacionado con la entidad. \ No newline at end of file +attachedDocumentNotRelatedToEntity=El documento adjunto no está relacionado con la entidad. +invalidNationalHealthId=Este valor no parece ser un carnet de identidad correcto \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_es-ES.properties b/sormas-api/src/main/resources/validations_es-ES.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_es-ES.properties +++ b/sormas-api/src/main/resources/validations_es-ES.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_fa-AF.properties b/sormas-api/src/main/resources/validations_fa-AF.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_fa-AF.properties +++ b/sormas-api/src/main/resources/validations_fa-AF.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_fi-FI.properties b/sormas-api/src/main/resources/validations_fi-FI.properties index 1869e2e301d..353764dc451 100644 --- a/sormas-api/src/main/resources/validations_fi-FI.properties +++ b/sormas-api/src/main/resources/validations_fi-FI.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_fil-PH.properties b/sormas-api/src/main/resources/validations_fil-PH.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_fil-PH.properties +++ b/sormas-api/src/main/resources/validations_fil-PH.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_fj-FJ.properties b/sormas-api/src/main/resources/validations_fj-FJ.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_fj-FJ.properties +++ b/sormas-api/src/main/resources/validations_fj-FJ.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_fr-CD.properties b/sormas-api/src/main/resources/validations_fr-CD.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_fr-CD.properties +++ b/sormas-api/src/main/resources/validations_fr-CD.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_fr-CH.properties b/sormas-api/src/main/resources/validations_fr-CH.properties index b340452e185..af79483ed48 100644 --- a/sormas-api/src/main/resources/validations_fr-CH.properties +++ b/sormas-api/src/main/resources/validations_fr-CH.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_fr-FR.properties b/sormas-api/src/main/resources/validations_fr-FR.properties index c07fe009fb6..935dcabc62f 100644 --- a/sormas-api/src/main/resources/validations_fr-FR.properties +++ b/sormas-api/src/main/resources/validations_fr-FR.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = La valeur ne peut contenir que des lett customizableEnumValueEmptyTranslations = Veuillez sélectionner les langues et saisir des légendes pour toutes les traductions de la liste. customizableEnumValueDuplicateLanguage = Veuillez ajouter une seule traduction par langue. customizableEnumValueDuplicateValue = La valeur %s existe déjà pour le type de données %s. Les valeurs Enum doivent être uniques. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_fr-TN.properties b/sormas-api/src/main/resources/validations_fr-TN.properties index 45397dd1196..764a4b0c535 100644 --- a/sormas-api/src/main/resources/validations_fr-TN.properties +++ b/sormas-api/src/main/resources/validations_fr-TN.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_hi-IN.properties b/sormas-api/src/main/resources/validations_hi-IN.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_hi-IN.properties +++ b/sormas-api/src/main/resources/validations_hi-IN.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_hr-HR.properties b/sormas-api/src/main/resources/validations_hr-HR.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_hr-HR.properties +++ b/sormas-api/src/main/resources/validations_hr-HR.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_it-CH.properties b/sormas-api/src/main/resources/validations_it-CH.properties index 4de9dcf0978..e410535ef83 100644 --- a/sormas-api/src/main/resources/validations_it-CH.properties +++ b/sormas-api/src/main/resources/validations_it-CH.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_it-IT.properties b/sormas-api/src/main/resources/validations_it-IT.properties index ccb2b2817e8..53948a0f676 100644 --- a/sormas-api/src/main/resources/validations_it-IT.properties +++ b/sormas-api/src/main/resources/validations_it-IT.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_ja-JP.properties b/sormas-api/src/main/resources/validations_ja-JP.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_ja-JP.properties +++ b/sormas-api/src/main/resources/validations_ja-JP.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_ne-NP.properties b/sormas-api/src/main/resources/validations_ne-NP.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_ne-NP.properties +++ b/sormas-api/src/main/resources/validations_ne-NP.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_nl-NL.properties b/sormas-api/src/main/resources/validations_nl-NL.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_nl-NL.properties +++ b/sormas-api/src/main/resources/validations_nl-NL.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_no-NO.properties b/sormas-api/src/main/resources/validations_no-NO.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_no-NO.properties +++ b/sormas-api/src/main/resources/validations_no-NO.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_pl-PL.properties b/sormas-api/src/main/resources/validations_pl-PL.properties index dded0ebca59..296d58a2806 100644 --- a/sormas-api/src/main/resources/validations_pl-PL.properties +++ b/sormas-api/src/main/resources/validations_pl-PL.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_ps-AF.properties b/sormas-api/src/main/resources/validations_ps-AF.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_ps-AF.properties +++ b/sormas-api/src/main/resources/validations_ps-AF.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_pt-PT.properties b/sormas-api/src/main/resources/validations_pt-PT.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_pt-PT.properties +++ b/sormas-api/src/main/resources/validations_pt-PT.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_ro-RO.properties b/sormas-api/src/main/resources/validations_ro-RO.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_ro-RO.properties +++ b/sormas-api/src/main/resources/validations_ro-RO.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_ru-RU.properties b/sormas-api/src/main/resources/validations_ru-RU.properties index 897e32acb26..8d7fbfb7092 100644 --- a/sormas-api/src/main/resources/validations_ru-RU.properties +++ b/sormas-api/src/main/resources/validations_ru-RU.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_sv-SE.properties b/sormas-api/src/main/resources/validations_sv-SE.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_sv-SE.properties +++ b/sormas-api/src/main/resources/validations_sv-SE.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_sw-KE.properties b/sormas-api/src/main/resources/validations_sw-KE.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_sw-KE.properties +++ b/sormas-api/src/main/resources/validations_sw-KE.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_tr-TR.properties b/sormas-api/src/main/resources/validations_tr-TR.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_tr-TR.properties +++ b/sormas-api/src/main/resources/validations_tr-TR.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_uk-UA.properties b/sormas-api/src/main/resources/validations_uk-UA.properties index aea21edec85..a2113fed499 100644 --- a/sormas-api/src/main/resources/validations_uk-UA.properties +++ b/sormas-api/src/main/resources/validations_uk-UA.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_ur-PK.properties b/sormas-api/src/main/resources/validations_ur-PK.properties index d5ecdc4714c..3719965a46d 100644 --- a/sormas-api/src/main/resources/validations_ur-PK.properties +++ b/sormas-api/src/main/resources/validations_ur-PK.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-api/src/main/resources/validations_zh-CN.properties b/sormas-api/src/main/resources/validations_zh-CN.properties index 3d7687efa5e..26ade444ac6 100644 --- a/sormas-api/src/main/resources/validations_zh-CN.properties +++ b/sormas-api/src/main/resources/validations_zh-CN.properties @@ -291,4 +291,5 @@ customizableEnumValueAllowedCharacters = Value may only consist of uppercase let customizableEnumValueEmptyTranslations = Please select languages and enter captions for all translations in the list. customizableEnumValueDuplicateLanguage = Please only add one translation per language. customizableEnumValueDuplicateValue = The value %s already exists for data type %s. Enum values have to be unique. -attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. \ No newline at end of file +attachedDocumentNotRelatedToEntity=The attached document is not related to the entity. +invalidNationalHealthId=This value does not seem to be a correct national health ID \ No newline at end of file diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseDao.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseDao.java index dba95207911..e208e9a2c11 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseDao.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseDao.java @@ -701,6 +701,17 @@ public void deleteCaseAndAllDependingEntities(String caseUuid) throws SQLExcepti deleteCascade(caze); } + public List getByPerson(Person person) { + try { + QueryBuilder qb = queryBuilder(); + qb.where().eq(Case.PERSON, person); + return qb.query(); + } catch (SQLException e) { + Log.e(getTableName(), "Could not perform queryByCriteria on Contact"); + throw new RuntimeException(e); + } + } + public List getSimilarCases(CaseSimilarityCriteria criteria) { try { QueryBuilder queryBuilder = queryBuilder(); diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseJurisdictionBooleanValidator.java index 2eda6522496..a5df9821794 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseJurisdictionBooleanValidator.java @@ -43,10 +43,19 @@ public Boolean isRootInJurisdiction() { return isInJurisdictionByJurisdictionLevel(userJurisdiction.getJurisdictionLevel()); } - @Override - public Boolean isRootInJurisdictionOrOwned() { - return userJurisdiction.getUuid().equals(caseJurisdiction.getReportingUserUuid()) || inJurisdiction(); - } + @Override + public Boolean isRootInJurisdictionOrOwned() { + return getReportedByCurrentUser() || inJurisdiction(); + } + + private boolean getReportedByCurrentUser() { + return userJurisdiction.getUuid().equals(caseJurisdiction.getReportingUserUuid()); + } + + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + return getReportedByCurrentUser() || userJurisdiction.getUuid().equals(caseJurisdiction.getSurveillanceOfficerUuid()); + } @Override protected Disease getDisease() { diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseJurisdictionDto.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseJurisdictionDto.java index c05cff34c43..6c1b75dd0de 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseJurisdictionDto.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/caze/CaseJurisdictionDto.java @@ -34,6 +34,7 @@ public class CaseJurisdictionDto implements Serializable { private String healthFacilityUuid; private String pointOfEntryUuid; private List sampleLabUuids; + private String surveillanceOfficerUuid; public CaseJurisdictionDto() { } @@ -118,4 +119,13 @@ public List getSampleLabUuids() { public void setSampleLabUuids(List sampleLabUuids) { this.sampleLabUuids = sampleLabUuids; } + + public String getSurveillanceOfficerUuid() { + return surveillanceOfficerUuid; + } + + public CaseJurisdictionDto setSurveillanceOfficerUuid(String surveillanceOfficerUuid) { + this.surveillanceOfficerUuid = surveillanceOfficerUuid; + return this; + } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/common/DatabaseHelper.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/common/DatabaseHelper.java index fe774f6b16d..1d87f17f965 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/common/DatabaseHelper.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/common/DatabaseHelper.java @@ -190,7 +190,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public static final String DATABASE_NAME = "sormas.db"; // any time you make changes to your database objects, you may have to increase the database version - public static final int DATABASE_VERSION = 357; + public static final int DATABASE_VERSION = 359; private static DatabaseHelper instance = null; @@ -3170,6 +3170,15 @@ public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int currentVersion = 356; getDao(PathogenTest.class).executeRaw("ALTER TABLE pathogenTest ADD COLUMN testedPathogenDetails varchar(512);"); + case 357: + currentVersion = 357; + getDao(CustomizableEnumValue.class).executeRaw("ALTER TABLE customizableEnumValue ADD COLUMN active boolean default true;"); + + case 358: + currentVersion = 358; + getDao(UserRole.class) + .executeRaw("ALTER TABLE userroles ADD COLUMN restrictAccessToAssignedEntities boolean NOT NULL DEFAULT false;"); + // ATTENTION: break should only be done after last version break; diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactDao.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactDao.java index 15211b359fe..67c548a0da0 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactDao.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactDao.java @@ -196,6 +196,17 @@ public List queryByCriteria(ContactCriteria criteria, long offset, long } } + public List getByPerson(Person person) { + try { + QueryBuilder qb = queryBuilder(); + qb.where().eq(Contact.PERSON, person); + return qb.query(); + } catch (SQLException e) { + Log.e(getTableName(), "Could not perform queryByCriteria on Contact"); + throw new RuntimeException(e); + } + } + private QueryBuilder buildQueryBuilder(ContactCriteria contactCriteria) throws SQLException { QueryBuilder queryBuilder = queryBuilder(); diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionBooleanValidator.java index b85b5c546bd..f403de6e02a 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionBooleanValidator.java @@ -46,11 +46,20 @@ public Boolean isRootInJurisdiction() { return isInJurisdictionByJurisdictionLevel(userJurisdiction.getJurisdictionLevel()); } - @Override - public Boolean isRootInJurisdictionOrOwned() { - return userJurisdiction.getUuid().equals(contactJurisdictionDto.getReportingUserUuid()) || inJurisdiction(); + @Override + public Boolean isRootInJurisdictionOrOwned() { + return isReportedByCurrentUser() || inJurisdiction(); + } + + private boolean isReportedByCurrentUser(){ + return userJurisdiction.getUuid().equals(contactJurisdictionDto.getReportingUserUuid()); } + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + return isReportedByCurrentUser() || userJurisdiction.getUuid().equals(contactJurisdictionDto.getContactOfficerUuid()); + } + @Override protected Disease getDisease() { return null; diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionDto.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionDto.java index 0ffd8d9839a..5a87edade7b 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionDto.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactJurisdictionDto.java @@ -45,6 +45,8 @@ public class ContactJurisdictionDto implements Serializable { private CaseJurisdictionDto caseJurisdiction; + private String contactOfficerUuid; + public ContactJurisdictionDto() { } @@ -110,4 +112,13 @@ public List getSampleLabUuids() { public void setSampleLabUuids(List sampleLabUuids) { this.sampleLabUuids = sampleLabUuids; } + + public String getContactOfficerUuid() { + return contactOfficerUuid; + } + + public ContactJurisdictionDto setContactOfficerUuid(String contactOfficerUuid) { + this.contactOfficerUuid = contactOfficerUuid; + return this; + } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/customizableenum/CustomizableEnumCacheInfo.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/customizableenum/CustomizableEnumCacheInfo.java new file mode 100644 index 00000000000..6804102ae2c --- /dev/null +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/customizableenum/CustomizableEnumCacheInfo.java @@ -0,0 +1,37 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2023 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.app.backend.customizableenum; + +import java.util.Map; + +public class CustomizableEnumCacheInfo { + + private final Map properties; + private final boolean active; + + public CustomizableEnumCacheInfo(Map properties, boolean active) { + this.properties = properties; + this.active = active; + } + + public Map getProperties() { + return properties; + } + + public boolean isActive() { + return active; + } +} diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/customizableenum/CustomizableEnumValue.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/customizableenum/CustomizableEnumValue.java index 0b2e890f8a3..d6273275b5a 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/customizableenum/CustomizableEnumValue.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/customizableenum/CustomizableEnumValue.java @@ -68,6 +68,9 @@ public class CustomizableEnumValue extends AbstractDomainObject { private String propertiesJson; private Map properties; + @DatabaseField + private boolean active; + public CustomizableEnumType getDataType() { return dataType; } @@ -232,6 +235,14 @@ public void setDefaultValue(boolean defaultValue) { this.defaultValue = defaultValue; } + public boolean isActive() { + return active; + } + + public void setActive(boolean active) { + this.active = active; + } + @Override public String getI18nPrefix() { return I18N_PREFIX; diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/customizableenum/CustomizableEnumValueDao.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/customizableenum/CustomizableEnumValueDao.java index 6bd3c74018b..6b345234cf3 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/customizableenum/CustomizableEnumValueDao.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/customizableenum/CustomizableEnumValueDao.java @@ -15,11 +15,6 @@ package de.symeda.sormas.app.backend.customizableenum; -import com.j256.ormlite.dao.Dao; - -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -27,6 +22,11 @@ import java.util.Optional; import java.util.stream.Collectors; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; + +import com.j256.ormlite.dao.Dao; + import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.Language; import de.symeda.sormas.api.customizableenum.CustomizableEnum; @@ -53,10 +53,10 @@ public class CustomizableEnumValueDao extends AbstractAdoDao, Map>> enumValuesByDisease = new HashMap<>(); /** - * Maps a customizable enum type to a map with all enum values of this type as its keys and the properties defined for these - * enum values as its values. + * Maps a customizable enum type to a map with all enum values of this type as its keys and and info, e.g. properties and active status, + * defined for these enum values as its values. */ - private final Map>> enumProperties = new HashMap<>(); + private final Map> enumInfo = new HashMap<>(); public CustomizableEnumValueDao(Dao innerDao) { super(innerDao); @@ -87,15 +87,19 @@ public T getEnumValue(CustomizableEnumType type, St T enumValue = enumClass.newInstance(); enumValue.setValue(value); enumValue.setCaption(enumValuesByLanguage.get(enumClass).get(language).get(value)); - enumValue.setProperties(enumProperties.get(type).get(value)); + enumValue.setProperties(getEnumInfo(type, value).getProperties()); return enumValue; } catch (InstantiationException | IllegalAccessException e) { throw new RuntimeException(e); } } - @SuppressWarnings("unchecked") public List getEnumValues(CustomizableEnumType type, Disease disease) { + return getEnumValues(type, null, disease); + } + + @SuppressWarnings("unchecked") + public List getEnumValues(CustomizableEnumType type, String selectedValue, Disease disease) { if (customizableEnumsByType.isEmpty() || (long) customizableEnumsByType.values().stream().mapToInt(i -> i.size()).sum() != countOf()) { loadData(); @@ -122,7 +126,7 @@ public List getEnumValues(CustomizableEnumType t enumValue = enumClass.newInstance(); enumValue.setValue(value); enumValue.setCaption(caption); - enumValue.setProperties(enumProperties.get(type).get(value)); + enumValue.setProperties(getEnumInfo(type, value).getProperties()); enumValues.add(enumValue); } catch (InstantiationException | IllegalAccessException e) { throw new RuntimeException(e); @@ -131,13 +135,17 @@ public List getEnumValues(CustomizableEnumType t return enumValues.stream() .filter( - e -> enumValuesByDisease.get(enumClass).get(disease).contains(e.getValue()) - || enumValuesByDisease.get(enumClass).get(null).contains(e.getValue())) + e -> (getEnumInfo(type, e.getValue()).isActive() || (selectedValue != null && selectedValue.equals(e.getValue()))) + && (enumValuesByDisease.get(enumClass).get(disease).contains(e.getValue()) + || enumValuesByDisease.get(enumClass).get(null).contains(e.getValue()))) .collect(Collectors.toList()); } - public boolean hasEnumValues(CustomizableEnumType type, Disease disease) { - return !getEnumValues(type, disease).isEmpty(); + public void clearCache() { + customizableEnumsByType.clear(); + enumValuesByLanguage.clear(); + enumValuesByDisease.clear(); + enumInfo.clear(); } private void initCaches(CustomizableEnumType type, Language language) { @@ -200,10 +208,7 @@ private void addValuesByDisease(CustomizableEnumTyp } private void loadData() { - customizableEnumsByType.clear(); - enumValuesByLanguage.clear(); - enumValuesByDisease.clear(); - enumProperties.clear(); + clearCache(); for (CustomizableEnumType enumType : CustomizableEnumType.values()) { customizableEnumsByType.putIfAbsent(enumType, new ArrayList<>()); @@ -212,9 +217,16 @@ private void loadData() { for (CustomizableEnumValue customizableEnumValue : queryForAll()) { CustomizableEnumType enumType = customizableEnumValue.getDataType(); customizableEnumsByType.get(enumType).add(customizableEnumValue); - enumProperties.putIfAbsent(enumType, new HashMap<>()); - enumProperties.get(enumType).putIfAbsent(customizableEnumValue.getValue(), customizableEnumValue.getProperties()); + enumInfo.putIfAbsent(enumType, new HashMap<>()); + enumInfo.get(enumType) + .putIfAbsent( + customizableEnumValue.getValue(), + new CustomizableEnumCacheInfo(customizableEnumValue.getProperties(), customizableEnumValue.isActive())); } } + private CustomizableEnumCacheInfo getEnumInfo(CustomizableEnumType type, String value) { + return enumInfo.get(type).get(value); + } + } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/customizableenum/CustomizableEnumValueDtoHelper.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/customizableenum/CustomizableEnumValueDtoHelper.java index cbd48d03191..0483500d1bd 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/customizableenum/CustomizableEnumValueDtoHelper.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/customizableenum/CustomizableEnumValueDtoHelper.java @@ -20,6 +20,7 @@ import de.symeda.sormas.api.PostResponse; import de.symeda.sormas.api.customizableenum.CustomizableEnumValueDto; import de.symeda.sormas.app.backend.common.AdoDtoHelper; +import de.symeda.sormas.app.backend.common.DatabaseHelper; import de.symeda.sormas.app.rest.NoConnectionException; import de.symeda.sormas.app.rest.RetroProvider; import retrofit2.Call; @@ -62,6 +63,7 @@ public void fillInnerFromDto(CustomizableEnumValue target, CustomizableEnumValue target.setDescriptionTranslations(source.getDescriptionTranslations()); target.setProperties(source.getProperties()); target.setDefaultValue(source.isDefaultValue()); + target.setActive(source.isActive()); } @Override @@ -69,6 +71,14 @@ public void fillInnerFromAdo(CustomizableEnumValueDto target, CustomizableEnumVa // Not supported } + @Override + protected void executeHandlePulledListAddition(int listSize) { + if (listSize > 0) { + // Clear the customizable enum value cache if values have changed + DatabaseHelper.getCustomizableEnumValueDao().clearCache(); + } + } + @Override protected long getApproximateJsonSizeInBytes() { return 0; diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/EnvironmentJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/EnvironmentJurisdictionBooleanValidator.java index cef4d1c6dd9..7ac7dea3d40 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/EnvironmentJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/EnvironmentJurisdictionBooleanValidator.java @@ -32,9 +32,20 @@ public Boolean isRootInJurisdiction() { @Override public Boolean isRootInJurisdictionOrOwned() { - return userJurisdiction.getUuid().equals(environmentJurisdiction.getReportingUserUuid()) - || userJurisdiction.getUuid().equals(environmentJurisdiction.getResponsibleUserUuid()) - || inJurisdiction(); + return isReportedByCurrentUser() || isResponsibleByCurrentUser() || inJurisdiction(); + } + + private boolean isReportedByCurrentUser() { + return userJurisdiction.getUuid().equals(environmentJurisdiction.getReportingUserUuid()); + } + + private boolean isResponsibleByCurrentUser() { + return userJurisdiction.getUuid().equals(environmentJurisdiction.getResponsibleUserUuid()); + } + + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + return isReportedByCurrentUser() || isResponsibleByCurrentUser(); } @Override diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionBooleanValidator.java index a2fac30eba9..5711aef48bb 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionBooleanValidator.java @@ -51,7 +51,16 @@ public Boolean isRootInJurisdiction() { @Override public Boolean isRootInJurisdictionOrOwned() { - return userJurisdiction.getUuid().equals(environmentSampleJurisdiction.getReportingUserUuid()) || inJurisdiction(); + return isReportedByCurrentUser() || inJurisdiction(); + } + + private boolean isReportedByCurrentUser() { + return userJurisdiction.getUuid().equals(environmentSampleJurisdiction.getReportingUserUuid()); + } + + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + return isReportedByCurrentUser() || userJurisdiction.getUuid().equals(environmentSampleJurisdiction.getEnvironmentResponsibleUser()); } @Override diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionDto.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionDto.java index 06cb2d78021..ed01eeabfff 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionDto.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/environment/environmentsample/EnvironmentSampleJurisdictionDto.java @@ -23,6 +23,7 @@ public class EnvironmentSampleJurisdictionDto implements Serializable { private String regionUuid; private String districtUuid; private String communityUuid; + private String environmentResponsibleUser; public EnvironmentSampleJurisdictionDto() { } @@ -67,4 +68,11 @@ public void setCommunityUuid(String communityUuid) { this.communityUuid = communityUuid; } + public String getEnvironmentResponsibleUser() { + return environmentResponsibleUser; + } + + public void setEnvironmentResponsibleUser(String environmentResponsibleUser) { + this.environmentResponsibleUser = environmentResponsibleUser; + } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventDao.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventDao.java index 9b44f2d9fd8..422f616f6fe 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventDao.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventDao.java @@ -39,7 +39,9 @@ import de.symeda.sormas.app.backend.common.DaoException; import de.symeda.sormas.app.backend.common.DatabaseHelper; import de.symeda.sormas.app.backend.config.ConfigProvider; +import de.symeda.sormas.app.backend.contact.Contact; import de.symeda.sormas.app.backend.location.Location; +import de.symeda.sormas.app.backend.person.Person; import de.symeda.sormas.app.backend.task.Task; import de.symeda.sormas.app.util.DiseaseConfigurationCache; import de.symeda.sormas.app.util.LocationService; @@ -260,4 +262,19 @@ private QueryBuilder buildQueryBuilder(EventCriteria criteria) thro return queryBuilder; } + public List getByEventParticipantPerson(Person person){ + try { + QueryBuilder queryBuilder = queryBuilder(); + QueryBuilder eventParticipantBuilder = DatabaseHelper.getEventParticipantDao().queryBuilder(); + queryBuilder.leftJoin(eventParticipantBuilder); + Where where = eventParticipantBuilder.where(); + + where.eq(EventParticipant.PERSON + "_id", person.getId()); + + return queryBuilder.query(); + } catch (SQLException e) { + Log.e(getTableName(), "Could not perform queryByCriteria on Event"); + throw new RuntimeException(e); + } + } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionBooleanValidator.java index 196b60c13e4..0e36bdcd101 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionBooleanValidator.java @@ -43,10 +43,23 @@ public Boolean isRootInJurisdiction() { return isInJurisdictionByJurisdictionLevel(userJurisdiction.getJurisdictionLevel()); } - @Override - public Boolean isRootInJurisdictionOrOwned() { - return userJurisdiction.getUuid().equals(eventJurisdictionDto.getReportingUserUuid()) || userJurisdiction.getUuid().equals(eventJurisdictionDto.getResponsibleUserUuid()) || inJurisdiction(); - } + @Override + public Boolean isRootInJurisdictionOrOwned() { + return getReportedByCurrentUser() || isCurrentUserResponsible() || inJurisdiction(); + } + + private boolean getReportedByCurrentUser() { + return userJurisdiction.getUuid().equals(eventJurisdictionDto.getReportingUserUuid()); + } + + public boolean isCurrentUserResponsible() { + return userJurisdiction.getUuid().equals(eventJurisdictionDto.getResponsibleUserUuid()); + } + + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + return getReportedByCurrentUser() || isCurrentUserResponsible(); + } @Override protected Disease getDisease() { diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionDto.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionDto.java index aa44b8437cb..4ed06b2256a 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionDto.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventJurisdictionDto.java @@ -56,8 +56,9 @@ public String getResponsibleUserUuid() { return responsibleUserUuid; } - public void setResponsibleUserUuid(String responsibleUserUuid) { + public EventJurisdictionDto setResponsibleUserUuid(String responsibleUserUuid) { this.responsibleUserUuid = responsibleUserUuid; + return this; } public String getRegionUuid() { diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantDao.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantDao.java index 9e53fb24180..b151b28bd2f 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantDao.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantDao.java @@ -21,11 +21,11 @@ import com.j256.ormlite.dao.Dao; import android.util.Log; - import de.symeda.sormas.app.backend.caze.Case; import de.symeda.sormas.app.backend.common.AbstractAdoDao; import de.symeda.sormas.app.backend.common.AbstractDomainObject; import de.symeda.sormas.app.backend.config.ConfigProvider; +import de.symeda.sormas.app.backend.person.Person; public class EventParticipantDao extends AbstractAdoDao { @@ -66,6 +66,34 @@ public List getByEvent(Event event) { } } + public List getByEventAndPerson(Event event, Person person) { + + if (event.isSnapshot()) { + throw new IllegalArgumentException("Does not support snapshot entities"); + } + + try { + return queryBuilder().where() + .eq(EventParticipant.EVENT + "_id", event) + .and() + .eq(AbstractDomainObject.SNAPSHOT, false) + .and() + .eq(EventParticipant.PERSON + "_id", person) + .query(); + } catch (SQLException e) { + Log.e(getTableName(), "Could not perform getByEventAndPerson on EventParticipant"); + throw new RuntimeException(e); + } + } + + public boolean eventParticipantAlreadyExists(Event event, Person person) { + if (event.isSnapshot()) { + throw new IllegalArgumentException("Does not support snapshot entities"); + } + + return getByEventAndPerson(event, person).size() > 0; + } + public Long countByEvent(Event event) { if (event.isSnapshot()) { throw new IllegalArgumentException("Does not support snapshot entities"); diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantJurisdictionBooleanValidator.java index cf36d72997e..704dbc8c653 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantJurisdictionBooleanValidator.java @@ -48,7 +48,16 @@ public Boolean isRootInJurisdiction() { @Override public Boolean isRootInJurisdictionOrOwned() { - return userJurisdiction.getUuid().equals(eventParticipantJurisdictionDto.getReportingUserUuid()) || inJurisdiction(); + return getReportedByCurrentUser() || inJurisdiction(); + } + + private boolean getReportedByCurrentUser() { + return userJurisdiction.getUuid().equals(eventParticipantJurisdictionDto.getReportingUserUuid()); + } + + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + return getReportedByCurrentUser() || userJurisdiction.getUuid().equals(eventParticipantJurisdictionDto.getEventResponsibleUserUuid()); } @Override diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantJurisdictionDto.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantJurisdictionDto.java index c5880f62388..094343a4ee5 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantJurisdictionDto.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantJurisdictionDto.java @@ -28,6 +28,7 @@ public class EventParticipantJurisdictionDto implements Serializable { private String districtUuid; private String eventUuid; private EventJurisdictionDto eventJurisdictionDto; + private String eventResponsibleUserUuid; public EventParticipantJurisdictionDto() { } @@ -96,4 +97,12 @@ public EventJurisdictionDto getEventJurisdictionDto() { public void setEventJurisdictionDto(EventJurisdictionDto eventJurisdictionDto) { this.eventJurisdictionDto = eventJurisdictionDto; } + + public String getEventResponsibleUserUuid() { + return eventResponsibleUserUuid; + } + + public void setEventResponsibleUserUuid(String eventResponsibleUserUuid) { + this.eventResponsibleUserUuid = eventResponsibleUserUuid; + } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionBooleanValidator.java index 7de10c4d76a..4bdb9c35d9c 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionBooleanValidator.java @@ -15,9 +15,14 @@ package de.symeda.sormas.app.backend.immunization; +import java.util.ArrayList; +import java.util.List; + import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.app.backend.caze.CaseJurisdictionDto; import de.symeda.sormas.app.backend.caze.ResponsibleJurisdictionDto; +import de.symeda.sormas.app.backend.person.PersonJurisdictionBooleanValidator; import de.symeda.sormas.app.util.BooleanJurisdictionValidator; import de.symeda.sormas.app.util.UserJurisdiction; @@ -48,6 +53,13 @@ public Boolean isRootInJurisdictionOrOwned() { return userJurisdiction.getUuid().equals(immunizationJurisdiction.getReportingUserUuid()) || inJurisdiction(); } + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + PersonJurisdictionBooleanValidator personJurisdictionBooleanValidator = new PersonJurisdictionBooleanValidator(userJurisdiction, immunizationJurisdiction.getPersonJurisdiction()); + + return isRootInJurisdictionOrOwned() && personJurisdictionBooleanValidator.isRootInJurisdictionForRestrictedAccess(); + } + @Override protected Disease getDisease() { return null; diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionDto.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionDto.java index 0efa6fa1175..1299991e94b 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionDto.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/immunization/ImmunizationJurisdictionDto.java @@ -21,12 +21,13 @@ import java.io.Serializable; import de.symeda.sormas.app.backend.caze.ResponsibleJurisdictionDto; +import de.symeda.sormas.app.backend.person.PersonJurisdictionDto; public class ImmunizationJurisdictionDto implements Serializable { private String reportingUserUuid; private ResponsibleJurisdictionDto responsibleJurisdiction; - + private PersonJurisdictionDto personJurisdiction; public ImmunizationJurisdictionDto() { } @@ -52,4 +53,12 @@ public ResponsibleJurisdictionDto getResponsibleJurisdiction() { public void setResponsibleJurisdiction(ResponsibleJurisdictionDto responsibleJurisdiction) { this.responsibleJurisdiction = responsibleJurisdiction; } + + public PersonJurisdictionDto getPersonJurisdiction() { + return personJurisdiction; + } + + public void setPersonJurisdiction(PersonJurisdictionDto personJurisdiction) { + this.personJurisdiction = personJurisdiction; + } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionBooleanValidator.java new file mode 100644 index 00000000000..54bec46e25e --- /dev/null +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionBooleanValidator.java @@ -0,0 +1,103 @@ +package de.symeda.sormas.app.backend.person; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.app.backend.caze.CaseJurisdictionDto; +import de.symeda.sormas.app.backend.contact.ContactJurisdictionDto; +import de.symeda.sormas.app.backend.event.EventJurisdictionDto; +import de.symeda.sormas.app.core.NotImplementedException; +import de.symeda.sormas.app.util.BooleanJurisdictionValidator; +import de.symeda.sormas.app.util.UserJurisdiction; + +public class PersonJurisdictionBooleanValidator extends BooleanJurisdictionValidator { + + private final PersonJurisdictionDto personJurisdiction; + protected final UserJurisdiction userJurisdiction; + + public PersonJurisdictionBooleanValidator(UserJurisdiction userJurisdiction, PersonJurisdictionDto personJurisdiction) { + super(null, userJurisdiction); + this.personJurisdiction = personJurisdiction; + this.userJurisdiction = userJurisdiction; + } + + @Override + protected Disease getDisease() { + return null; + } + + @Override + public Boolean isRootInJurisdiction() { + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); + } + + @Override + public Boolean isRootInJurisdictionOrOwned() { + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); + } + + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + + boolean currentUserIsSurveillanceOfficer = personJurisdiction.getCaseJurisdictions() + .stream() + .map(CaseJurisdictionDto::getSurveillanceOfficerUuid) + .anyMatch(surveillanceOfficer -> surveillanceOfficer.equals(userJurisdiction.getUuid())); + + if (currentUserIsSurveillanceOfficer) { + return true; + } + + boolean currentUserIsContactOfficer = personJurisdiction.getContactJurisdictions() + .stream() + .map(ContactJurisdictionDto::getContactOfficerUuid) + .anyMatch(contactOfficer -> contactOfficer.equals(userJurisdiction.getUuid())); + + if (currentUserIsContactOfficer) { + return true; + } + + return personJurisdiction.getEventJurisdictions() + .stream() + .map(EventJurisdictionDto::getResponsibleUserUuid) + .anyMatch(responsibleUser -> responsibleUser.equals(userJurisdiction.getUuid())); + } + + @Override + protected Boolean whenNotAllowed() { + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); + } + + @Override + protected Boolean whenNationalLevel() { + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); + } + + @Override + protected Boolean whenRegionalLevel() { + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); + } + + @Override + protected Boolean whenDistrictLevel() { + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); + } + + @Override + protected Boolean whenCommunityLevel() { + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); + } + + @Override + protected Boolean whenFacilityLevel() { + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); + } + + @Override + protected Boolean whenPointOfEntryLevel() { + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); + } + + @Override + protected Boolean whenLaboratoryLevel() { + throw new NotImplementedException("Person jurisdiction depends on linked core entity jurisdiction"); + } +} diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionDto.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionDto.java new file mode 100644 index 00000000000..f57a6db55bc --- /dev/null +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/person/PersonJurisdictionDto.java @@ -0,0 +1,65 @@ +package de.symeda.sormas.app.backend.person; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import de.symeda.sormas.app.backend.caze.CaseJurisdictionDto; +import de.symeda.sormas.app.backend.contact.ContactJurisdictionDto; +import de.symeda.sormas.app.backend.event.EventJurisdictionDto; +import de.symeda.sormas.app.backend.immunization.ImmunizationJurisdictionDto; + +public class PersonJurisdictionDto implements Serializable { + + private List caseJurisdictions = new ArrayList<>(); + private List contactJurisdictions = new ArrayList<>(); + private List eventJurisdictions = new ArrayList<>(); + private List immunizationJurisdictions = new ArrayList<>(); + + public PersonJurisdictionDto() { + + } + + public PersonJurisdictionDto( + List caseJurisdictions, + List contactJurisdictions, + List eventJurisdictions, + List immunizationJurisdictions) { + this.caseJurisdictions = caseJurisdictions; + this.contactJurisdictions = contactJurisdictions; + this.eventJurisdictions = eventJurisdictions; + this.immunizationJurisdictions = immunizationJurisdictions; + } + + public List getCaseJurisdictions() { + return caseJurisdictions; + } + + public void setCaseJurisdictions(List caseJurisdictions) { + this.caseJurisdictions = caseJurisdictions; + } + + public List getContactJurisdictions() { + return contactJurisdictions; + } + + public void setContactJurisdictions(List contactJurisdictions) { + this.contactJurisdictions = contactJurisdictions; + } + + public List getEventJurisdictions() { + return eventJurisdictions; + } + + public void setEventJurisdictions(List eventJurisdictions) { + this.eventJurisdictions = eventJurisdictions; + } + + public List getImmunizationJurisdictions() { + return immunizationJurisdictions; + } + + public void setImmunizationJurisdictions(List immunizationJurisdictions) { + this.immunizationJurisdictions = immunizationJurisdictions; + } +} diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/sample/SampleJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/sample/SampleJurisdictionBooleanValidator.java index 5a9364f0915..adf8711e39b 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/sample/SampleJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/sample/SampleJurisdictionBooleanValidator.java @@ -74,6 +74,16 @@ public Boolean isRootInJurisdictionOrOwned() { return userJurisdiction.getUuid().equals(sampleJurisdictionDto.getReportingUserUuid()) || inJurisdiction(); } + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + + boolean currentUserIsSurveilanceOfficer = userJurisdiction.getUuid().equals(sampleJurisdictionDto.getCaseJurisdiction().getSurveillanceOfficerUuid()); + boolean currentUserIsContactOfficer = userJurisdiction.getUuid().equals(sampleJurisdictionDto.getContactJurisdiction().getContactOfficerUuid()); + boolean currentUserIsResponsibleOfficer = userJurisdiction.getUuid().equals(sampleJurisdictionDto.getEventParticipantJurisdiction().getEventResponsibleUserUuid()); + + return currentUserIsSurveilanceOfficer || currentUserIsContactOfficer || currentUserIsResponsibleOfficer; + } + @Override protected Disease getDisease() { return null; diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/task/TaskJurisdictionBooleanValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/task/TaskJurisdictionBooleanValidator.java index 788613b2b84..f44def5a56f 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/task/TaskJurisdictionBooleanValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/task/TaskJurisdictionBooleanValidator.java @@ -69,7 +69,20 @@ public Boolean isRootInJurisdiction() { @Override public Boolean isRootInJurisdictionOrOwned() { - return userJurisdiction.getUuid().equals(taskJurisdictionDto.getCreatorUserUuid()) || userJurisdiction.getUuid().equals(taskJurisdictionDto.getAssigneeUserUuid()) || inJurisdiction(); + return getCreatedByCurrentUser() || getAssignedToCurrentUser() || inJurisdiction(); + } + + private boolean getAssignedToCurrentUser() { + return userJurisdiction.getUuid().equals(taskJurisdictionDto.getAssigneeUserUuid()); + } + + private boolean getCreatedByCurrentUser() { + return userJurisdiction. getUuid().equals(taskJurisdictionDto.getCreatorUserUuid()); + } + + @Override + public Boolean isRootInJurisdictionForRestrictedAccess() { + return isRootInJurisdictionOrOwned(); } @Override diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserDtoHelper.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserDtoHelper.java index 647aa000902..eeb1ee3e4ba 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserDtoHelper.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserDtoHelper.java @@ -132,4 +132,10 @@ public static UserReferenceDto toReferenceDto(User ado) { UserReferenceDto dto = new UserReferenceDto(ado.getUuid()); return dto; } + public static boolean isRestrictedToAssignEntities(User user) { + if (user != null && !user.getUserRoles().isEmpty()) { + return user.getUserRoles().stream().allMatch(UserRole::isRestrictAccessToAssignedEntities); + } + return false; + } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserRole.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserRole.java index f4520cd7da9..715a009d80a 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserRole.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserRole.java @@ -69,6 +69,8 @@ public class UserRole extends AbstractDomainObject { private JurisdictionLevel jurisdictionLevel; @Enumerated(EnumType.STRING) private DefaultUserRole linkedDefaultUserRole; + @Column + private boolean restrictAccessToAssignedEntities; public String getUserRightsJson() { return userRightsJson; @@ -147,6 +149,14 @@ public void setPortHealthUser(boolean portHealthUser) { this.portHealthUser = portHealthUser; } + public boolean isRestrictAccessToAssignedEntities() { + return restrictAccessToAssignedEntities; + } + + public void setRestrictAccessToAssignedEntities(boolean restrictAccessToAssignedEntities) { + this.restrictAccessToAssignedEntities = restrictAccessToAssignedEntities; + } + public JurisdictionLevel getJurisdictionLevel() { return jurisdictionLevel; } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserRoleDtoHelper.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserRoleDtoHelper.java index 951f76d4489..e4f1133b0f1 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserRoleDtoHelper.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/user/UserRoleDtoHelper.java @@ -63,6 +63,7 @@ public void fillInnerFromDto(UserRole target, UserRoleDto source) { target.setHasOptionalHealthFacility(source.getHasOptionalHealthFacility()); target.setJurisdictionLevel(source.getJurisdictionLevel()); target.setLinkedDefaultUserRole(source.getLinkedDefaultUserRole()); + target.setRestrictAccessToAssignedEntities(source.isRestrictAccessToAssignedEntities()); } @Override @@ -76,6 +77,7 @@ public void fillInnerFromAdo(UserRoleDto target, UserRole source) { target.setHasOptionalHealthFacility(source.hasOptionalHealthFacility()); target.setJurisdictionLevel(source.getJurisdictionLevel()); target.setLinkedDefaultUserRole(source.getLinkedDefaultUserRole()); + target.setRestrictAccessToAssignedEntities(source.isRestrictAccessToAssignedEntities()); } @Override diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditActivity.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditActivity.java index 2e4c69c19fb..0f727c9e8ee 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditActivity.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditActivity.java @@ -23,13 +23,14 @@ import android.content.Context; import android.os.AsyncTask; import android.view.Menu; - import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.caze.CaseClassification; import de.symeda.sormas.api.caze.CaseOrigin; import de.symeda.sormas.api.caze.CaseReferenceDto; import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.feature.FeatureTypeProperty; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.i18n.Strings; import de.symeda.sormas.api.user.UserRight; import de.symeda.sormas.api.utils.DataHelper; import de.symeda.sormas.api.utils.ValidationException; @@ -345,15 +346,24 @@ private void linkEventToCase() { EventPickOrCreateDialog.pickOrCreateEvent(caze, null, event -> { if (event != null) { - //link existing event to case - EventParticipant eventParticipantToSave = DatabaseHelper.getEventParticipantDao().build(); - eventParticipantToSave.setPerson(caze.getPerson()); - eventParticipantToSave.setEvent(event); - eventParticipantToSave.setResultingCaseUuid(caze.getUuid()); EventParticipantSaver eventParticipantSaver = new EventParticipantSaver(this); + //link existing event to case if (!isEventLinkedToCase(caze, event)) { - eventParticipantSaver.saveEventParticipantLinkedToCase(eventParticipantToSave); + boolean eventParticipantAlreadyExists = + DatabaseHelper.getEventParticipantDao().eventParticipantAlreadyExists(event, caze.getPerson()); + EventParticipant eventParticipant; + if (eventParticipantAlreadyExists) { + eventParticipant = DatabaseHelper.getEventParticipantDao().getByEventAndPerson(event, caze.getPerson()).get(0); + NotificationHelper.showNotification(this, WARNING, I18nProperties.getString(Strings.messagePersonAlreadyEventParticipant)); + } else { + eventParticipant = DatabaseHelper.getEventParticipantDao().build(); + eventParticipant.setPerson(caze.getPerson()); + eventParticipant.setEvent(event); + } + eventParticipant.setResultingCaseUuid(caze.getUuid()); + eventParticipantSaver.saveEventParticipantLinkedToCase(eventParticipant, eventParticipantAlreadyExists); + } else { NotificationHelper .showNotification(this, WARNING, getString(R.string.message_Event_already_linked_to_Case) + " " + caze.getUuid()); diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditFragment.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditFragment.java index 03af89dd176..2d90b97b14b 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditFragment.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditFragment.java @@ -21,13 +21,14 @@ import static de.symeda.sormas.api.caze.CaseConfirmationBasis.EPIDEMIOLOGICAL_CONFIRMATION; import static de.symeda.sormas.api.caze.CaseConfirmationBasis.LABORATORY_DIAGNOSTIC_CONFIRMATION; +import java.util.Date; +import java.util.List; +import java.util.Optional; + import android.webkit.WebView; import androidx.fragment.app.FragmentActivity; -import java.util.Date; -import java.util.List; - import de.symeda.sormas.api.CountryHelper; import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.caze.CaseClassification; @@ -48,6 +49,7 @@ import de.symeda.sormas.api.caze.Trimester; import de.symeda.sormas.api.caze.VaccinationStatus; import de.symeda.sormas.api.contact.QuarantineType; +import de.symeda.sormas.api.customizableenum.CustomizableEnum; import de.symeda.sormas.api.customizableenum.CustomizableEnumType; import de.symeda.sormas.api.disease.DiseaseVariant; import de.symeda.sormas.api.event.TypeOfPlace; @@ -340,8 +342,11 @@ record = getActivityRootData(); if (record.getDisease() != null && !diseases.contains(record.getDisease())) { diseaseList.add(DataUtils.toItem(record.getDisease())); } - List diseaseVariants = - DatabaseHelper.getCustomizableEnumValueDao().getEnumValues(CustomizableEnumType.DISEASE_VARIANT, record.getDisease()); + List diseaseVariants = DatabaseHelper.getCustomizableEnumValueDao() + .getEnumValues( + CustomizableEnumType.DISEASE_VARIANT, + Optional.ofNullable(record.getDiseaseVariant()).map(CustomizableEnum::getValue).orElse(null), + record.getDisease()); diseaseVariantList = DataUtils.toItems(diseaseVariants); if (record.getDiseaseVariant() != null && !diseaseVariants.contains(record.getDiseaseVariant())) { diseaseVariantList.add(DataUtils.toItem(record.getDiseaseVariant())); @@ -671,7 +676,7 @@ public void onAfterLayoutBinding(final FragmentCaseEditLayoutBinding contentBind contentBinding.caseDataClassifiedBy.setValue(getResources().getString(R.string.system)); } - if(!isFieldAccessible(CaseDataDto.class, contentBinding.caseDataHealthFacility)){ + if (!isFieldAccessible(CaseDataDto.class, contentBinding.caseDataHealthFacility)) { FieldVisibilityAndAccessHelper.setFieldInaccessibleValue(contentBinding.facilityOrHome); FieldVisibilityAndAccessHelper.setFieldInaccessibleValue(contentBinding.facilityTypeGroup); } else if (record.getCaseOrigin() == CaseOrigin.POINT_OF_ENTRY && record.getHealthFacility() == null) { @@ -710,8 +715,11 @@ public void onAfterLayoutBinding(final FragmentCaseEditLayoutBinding contentBind } private void updateDiseaseVariantsField(FragmentCaseEditLayoutBinding contentBinding) { - List diseaseVariants = - DatabaseHelper.getCustomizableEnumValueDao().getEnumValues(CustomizableEnumType.DISEASE_VARIANT, record.getDisease()); + List diseaseVariants = DatabaseHelper.getCustomizableEnumValueDao() + .getEnumValues( + CustomizableEnumType.DISEASE_VARIANT, + Optional.ofNullable(record.getDiseaseVariant()).map(CustomizableEnum::getValue).orElse(null), + record.getDisease()); diseaseVariantList.clear(); diseaseVariantList.addAll(DataUtils.toItems(diseaseVariants)); contentBinding.caseDataDiseaseVariant.setSpinnerData(diseaseVariantList); diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseNewActivity.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseNewActivity.java index 86b7bac1a83..05223153c56 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseNewActivity.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseNewActivity.java @@ -227,7 +227,7 @@ public void saveData() { // Person selection can be skipped if the case was created from a contact or event participant if (contactUuid == null && eventParticipantUuid == null) { - SelectOrCreatePersonDialog.selectOrCreatePerson(caze.getPerson(), person -> { + SelectOrCreatePersonDialog.selectOrCreatePerson(caze.getPerson(), caze, person -> { if (person != null) { caze.setPerson(person); pickOrCreateCaseAndSave(caze, fragment); diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/component/dialog/SynchronizationDialog.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/component/dialog/SynchronizationDialog.java index f5c359956fb..d74ac042c45 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/component/dialog/SynchronizationDialog.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/component/dialog/SynchronizationDialog.java @@ -369,6 +369,16 @@ private void showPushNewProgressItems() { Strings.entityEventParticipants, allowedEntities, DtoFeatureConfigHelper.isFeatureConfigForEventParticipantsEnabled()); + addEntityIfEditAllowed( + EnvironmentDto.class, + Strings.entityEnvironments, + allowedEntities, + DtoFeatureConfigHelper.isFeatureConfigForEnvironmentEnabled()); + addEntityIfEditAllowed( + EnvironmentSampleDto.class, + Strings.entityEnvironmentSamples, + allowedEntities, + DtoFeatureConfigHelper.isFeatureConfigForEnvironmentSamplesEnabled()); addEntityIfEditAllowed(SampleDto.class, Strings.entitySamples, allowedEntities, DtoFeatureConfigHelper.isFeatureConfigForSampleEnabled()); addEntityIfEditAllowed( PathogenTestDto.class, @@ -380,16 +390,6 @@ private void showPushNewProgressItems() { Strings.entityAdditionalTests, allowedEntities, DtoFeatureConfigHelper.isFeatureConfigForAdditionalTestsEnabled()); - addEntityIfEditAllowed( - EnvironmentDto.class, - Strings.entityEnvironments, - allowedEntities, - DtoFeatureConfigHelper.isFeatureConfigForEnvironmentEnabled()); - addEntityIfEditAllowed( - EnvironmentSampleDto.class, - Strings.entityEnvironmentSamples, - allowedEntities, - DtoFeatureConfigHelper.isFeatureConfigForEnvironmentSamplesEnabled()); addEntityIfEditAllowed(ContactDto.class, Strings.entityContacts, allowedEntities, DtoFeatureConfigHelper.isFeatureConfigForContactsEnabled()); addEntityIfEditAllowedWithFeatureDependencies( VisitDto.class, @@ -530,6 +530,16 @@ private void showSynchronizeProgressItems() { Strings.entityEventParticipants, allowedEntities, DtoFeatureConfigHelper.isFeatureConfigForEventParticipantsEnabled()); + addEntityIfViewOrEditAllowed( + EnvironmentDto.class, + Strings.entityEnvironments, + allowedEntities, + DtoFeatureConfigHelper.isFeatureConfigForEnvironmentEnabled()); + addEntityIfViewOrEditAllowed( + EnvironmentSampleDto.class, + Strings.entityEnvironmentSamples, + allowedEntities, + DtoFeatureConfigHelper.isFeatureConfigForEnvironmentSamplesEnabled()); addEntityIfViewOrEditAllowed( SampleDto.class, Strings.entitySamples, @@ -545,16 +555,6 @@ private void showSynchronizeProgressItems() { Strings.entityAdditionalTests, allowedEntities, DtoFeatureConfigHelper.isFeatureConfigForAdditionalTestsEnabled()); - addEntityIfViewOrEditAllowed( - EnvironmentDto.class, - Strings.entityEnvironments, - allowedEntities, - DtoFeatureConfigHelper.isFeatureConfigForEnvironmentEnabled()); - addEntityIfViewOrEditAllowed( - EnvironmentSampleDto.class, - Strings.entityEnvironmentSamples, - allowedEntities, - DtoFeatureConfigHelper.isFeatureConfigForEnvironmentSamplesEnabled()); addEntityIfViewOrEditAllowed( ContactDto.class, Strings.entityContacts, @@ -611,6 +611,16 @@ private void showPullModifiedProgressItems() { Strings.entityEventParticipants, allowedEntities, DtoFeatureConfigHelper.isFeatureConfigForEventParticipantsEnabled()); + addEntityIfViewAllowed( + EnvironmentDto.class, + Strings.entityEnvironments, + allowedEntities, + DtoFeatureConfigHelper.isFeatureConfigForEnvironmentEnabled()); + addEntityIfViewAllowed( + EnvironmentSampleDto.class, + Strings.entityEnvironmentSamples, + allowedEntities, + DtoFeatureConfigHelper.isFeatureConfigForEnvironmentSamplesEnabled()); addEntityIfViewAllowed(SampleDto.class, Strings.entitySamples, allowedEntities, DtoFeatureConfigHelper.isFeatureConfigForSampleEnabled()); addEntityIfViewAllowed( PathogenTestDto.class, @@ -622,16 +632,6 @@ private void showPullModifiedProgressItems() { Strings.entityAdditionalTests, allowedEntities, DtoFeatureConfigHelper.isFeatureConfigForAdditionalTestsEnabled()); - addEntityIfViewAllowed( - EnvironmentDto.class, - Strings.entityEnvironments, - allowedEntities, - DtoFeatureConfigHelper.isFeatureConfigForEnvironmentEnabled()); - addEntityIfViewAllowed( - EnvironmentSampleDto.class, - Strings.entityEnvironmentSamples, - allowedEntities, - DtoFeatureConfigHelper.isFeatureConfigForEnvironmentSamplesEnabled()); addEntityIfViewAllowed(ContactDto.class, Strings.entityContacts, allowedEntities, DtoFeatureConfigHelper.isFeatureConfigForContactsEnabled()); addEntityIfViewAllowedWithFeatureDependencies( VisitDto.class, diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/contact/edit/ContactNewActivity.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/contact/edit/ContactNewActivity.java index 0610f469e51..6db81a6d4bd 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/contact/edit/ContactNewActivity.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/contact/edit/ContactNewActivity.java @@ -177,7 +177,7 @@ public void saveData() { return; } - SelectOrCreatePersonDialog.selectOrCreatePerson(contactToSave.getPerson(), new Consumer() { + SelectOrCreatePersonDialog.selectOrCreatePerson(contactToSave.getPerson(), contactToSave, new Consumer() { @Override public void accept(Person person) { diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/environmentsample/edit/EnvironmentSampleEditPathogenTestListFragment.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/environmentsample/edit/EnvironmentSampleEditPathogenTestListFragment.java index c16d9aa5f84..a40e53c1d8c 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/environmentsample/edit/EnvironmentSampleEditPathogenTestListFragment.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/environmentsample/edit/EnvironmentSampleEditPathogenTestListFragment.java @@ -104,6 +104,6 @@ public boolean isShowSaveAction() { @Override public boolean isShowNewAction() { - return ConfigProvider.hasUserRight(UserRight.PATHOGEN_TEST_CREATE); + return ConfigProvider.hasUserRight(UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE); } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/event/edit/EventEditFragment.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/event/edit/EventEditFragment.java index f2cedd9fc70..bbf24f45553 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/event/edit/EventEditFragment.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/event/edit/EventEditFragment.java @@ -19,11 +19,13 @@ import static android.view.View.VISIBLE; import static de.symeda.sormas.app.core.notification.NotificationType.ERROR; -import android.view.View; - import java.util.List; +import java.util.Optional; + +import android.view.View; import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.customizableenum.CustomizableEnum; import de.symeda.sormas.api.customizableenum.CustomizableEnumType; import de.symeda.sormas.api.disease.DiseaseVariant; import de.symeda.sormas.api.event.DiseaseTransmissionMode; @@ -189,14 +191,20 @@ record = getActivityRootData(); if (record.getDisease() != null && !diseases.contains(record.getDisease())) { diseaseList.add(DataUtils.toItem(record.getDisease())); } - List diseaseVariants = - DatabaseHelper.getCustomizableEnumValueDao().getEnumValues(CustomizableEnumType.DISEASE_VARIANT, record.getDisease()); + List diseaseVariants = DatabaseHelper.getCustomizableEnumValueDao() + .getEnumValues( + CustomizableEnumType.DISEASE_VARIANT, + Optional.ofNullable(record.getDiseaseVariant()).map(CustomizableEnum::getValue).orElse(null), + record.getDisease()); diseaseVariantList = DataUtils.toItems(diseaseVariants); if (record.getDiseaseVariant() != null && !diseaseVariants.contains(record.getDiseaseVariant())) { diseaseVariantList.add(DataUtils.toItem(record.getDiseaseVariant())); } - List specificRisks = - DatabaseHelper.getCustomizableEnumValueDao().getEnumValues(CustomizableEnumType.SPECIFIC_EVENT_RISK, record.getDisease()); + List specificRisks = DatabaseHelper.getCustomizableEnumValueDao() + .getEnumValues( + CustomizableEnumType.SPECIFIC_EVENT_RISK, + Optional.ofNullable(record.getSpecificRisk()).map(CustomizableEnum::getValue).orElse(null), + record.getDisease()); specificRiskList = DataUtils.toItems(specificRisks); if (record.getSpecificRisk() != null && !specificRisks.contains(record.getSpecificRisk())) { specificRiskList.add(DataUtils.toItem(record.getSpecificRisk())); @@ -305,8 +313,11 @@ public void onAfterLayoutBinding(FragmentEventEditLayoutBinding contentBinding) private void updateCustomizableEnumFields(FragmentEventEditLayoutBinding contentBinding) { // Disease variant DiseaseVariant selectedVariant = (DiseaseVariant) contentBinding.eventDiseaseVariant.getValue(); - List diseaseVariants = - DatabaseHelper.getCustomizableEnumValueDao().getEnumValues(CustomizableEnumType.DISEASE_VARIANT, record.getDisease()); + List diseaseVariants = DatabaseHelper.getCustomizableEnumValueDao() + .getEnumValues( + CustomizableEnumType.DISEASE_VARIANT, + Optional.ofNullable(record.getDiseaseVariant()).map(CustomizableEnum::getValue).orElse(null), + record.getDisease()); diseaseVariantList.clear(); diseaseVariantList.addAll(DataUtils.toItems(diseaseVariants)); contentBinding.eventDiseaseVariant.setSpinnerData(diseaseVariantList); @@ -319,8 +330,11 @@ private void updateCustomizableEnumFields(FragmentEventEditLayoutBinding content // Specific risk SpecificRisk selectedRisk = (SpecificRisk) contentBinding.eventSpecificRisk.getValue(); - List specificRisks = - DatabaseHelper.getCustomizableEnumValueDao().getEnumValues(CustomizableEnumType.SPECIFIC_EVENT_RISK, record.getDisease()); + List specificRisks = DatabaseHelper.getCustomizableEnumValueDao() + .getEnumValues( + CustomizableEnumType.SPECIFIC_EVENT_RISK, + Optional.ofNullable(record.getSpecificRisk()).map(CustomizableEnum::getValue).orElse(null), + record.getDisease()); specificRiskList.clear(); specificRiskList.addAll(DataUtils.toItems(specificRisks)); contentBinding.eventSpecificRisk.setSpinnerData(specificRiskList); diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/event/edit/EventEditPersonsInvolvedListFragment.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/event/edit/EventEditPersonsInvolvedListFragment.java index 1198573e91b..db6fa03a322 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/event/edit/EventEditPersonsInvolvedListFragment.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/event/edit/EventEditPersonsInvolvedListFragment.java @@ -15,6 +15,8 @@ package de.symeda.sormas.app.event.edit; +import java.util.List; + import android.os.Bundle; import android.view.View; @@ -23,10 +25,10 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import java.util.List; - +import de.symeda.sormas.api.user.UserRight; import de.symeda.sormas.app.BaseEditFragment; import de.symeda.sormas.app.R; +import de.symeda.sormas.app.backend.config.ConfigProvider; import de.symeda.sormas.app.backend.event.Event; import de.symeda.sormas.app.backend.event.EventParticipant; import de.symeda.sormas.app.core.adapter.databinding.OnListItemClickListener; @@ -35,6 +37,7 @@ import de.symeda.sormas.app.event.eventparticipant.edit.EventParticipantEditActivity; import de.symeda.sormas.app.event.eventparticipant.list.EventParticipantListAdapter; import de.symeda.sormas.app.event.eventparticipant.list.EventParticipantListViewModel; +import de.symeda.sormas.app.event.eventparticipant.read.EventParticipantReadActivity; public class EventEditPersonsInvolvedListFragment extends BaseEditFragment, Event> implements OnListItemClickListener { @@ -106,8 +109,13 @@ public boolean isShowNewAction() { @Override public void onListItemClick(View view, int position, Object item) { + EventParticipant o = (EventParticipant) item; - EventParticipantEditActivity - .startActivity(getContext(), o.getUuid(), getActivityRootData().getUuid(), EventParticipantSection.EVENT_PARTICIPANT_INFO); + if (ConfigProvider.hasUserRight(UserRight.EVENTPARTICIPANT_EDIT)) { + EventParticipantEditActivity + .startActivity(getContext(), o.getUuid(), getActivityRootData().getUuid(), EventParticipantSection.EVENT_PARTICIPANT_INFO); + } else { + EventParticipantReadActivity.startActivity(getContext(), o.getUuid(), getActivityRootData().getUuid()); + } } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/event/edit/EventNewActivity.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/event/edit/EventNewActivity.java index b024977ac19..bb275c23ca8 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/event/edit/EventNewActivity.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/event/edit/EventNewActivity.java @@ -175,7 +175,7 @@ protected void onPostExecute(AsyncTaskResult taskResult) { eventParticipantToSave.setEvent(eventToSave); eventParticipantToSave.setResultingCaseUuid(linkedCase.getUuid()); EventParticipantSaver eventParticipantSaver = new EventParticipantSaver(EventNewActivity.this); - eventParticipantSaver.saveEventParticipantLinkedToCase(eventParticipantToSave); + eventParticipantSaver.saveEventParticipantLinkedToCase(eventParticipantToSave, false); } else { EventEditActivity.startActivity(getContext(), eventToSave.getUuid(), EventSection.EVENT_PARTICIPANTS); } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/event/eventparticipant/EventParticipantSaver.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/event/eventparticipant/EventParticipantSaver.java index 0e39523a2b3..d4a8ccbd1d0 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/event/eventparticipant/EventParticipantSaver.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/event/eventparticipant/EventParticipantSaver.java @@ -15,7 +15,7 @@ public EventParticipantSaver(BaseActivity parentActivity) { this.parentActivity = parentActivity; } - public void saveEventParticipantLinkedToCase(EventParticipant eventParticipantToSave) { + public void saveEventParticipantLinkedToCase(EventParticipant eventParticipantToSave, boolean eventParticipantAlreadyExists) { new SavingAsyncTask(parentActivity.getRootView(), eventParticipantToSave) { @@ -32,7 +32,11 @@ protected void doInBackground(TaskResultHolder resultHolder) throws Exception { @Override protected void onPostExecute(AsyncTaskResult taskResult) { parentActivity.hidePreloader(); - super.onPostExecute(taskResult); + + if (!eventParticipantAlreadyExists) { + super.onPostExecute(taskResult); + } + if (taskResult.getResultStatus().isSuccess()) { parentActivity.finish(); } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/event/eventparticipant/edit/EventParticipantNewActivity.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/event/eventparticipant/edit/EventParticipantNewActivity.java index 07a3c1e1711..1a2e2e77980 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/event/eventparticipant/edit/EventParticipantNewActivity.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/event/eventparticipant/edit/EventParticipantNewActivity.java @@ -135,7 +135,9 @@ public void saveData() { return; } - SelectOrCreatePersonDialog.selectOrCreatePerson(eventParticipantToSave.getPerson(), new Consumer() { + final Event event = DatabaseHelper.getEventDao().queryUuid(eventUuid); + + SelectOrCreatePersonDialog.selectOrCreatePerson(eventParticipantToSave.getPerson(), event, new Consumer() { @Override public void accept(Person person) { @@ -151,7 +153,6 @@ protected void onPreExecute() { @Override protected void doInBackground(TaskResultHolder resultHolder) throws Exception { DatabaseHelper.getPersonDao().saveAndSnapshot(eventParticipantToSave.getPerson()); - final Event event = DatabaseHelper.getEventDao().queryUuid(eventUuid); eventParticipantToSave.setEvent(event); DatabaseHelper.getEventParticipantDao().saveAndSnapshot(eventParticipantToSave); } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/immunization/edit/ImmunizationNewActivity.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/immunization/edit/ImmunizationNewActivity.java index 6a83ddd6e4f..d022496404c 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/immunization/edit/ImmunizationNewActivity.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/immunization/edit/ImmunizationNewActivity.java @@ -182,7 +182,7 @@ public void saveData() { if (caseUuid != null || contactUuid != null || eventParticipantUuid != null) { pickOrCreateImmunizationAndSave(immunization, fragment); } else { - SelectOrCreatePersonDialog.selectOrCreatePerson(immunization.getPerson(), person -> { + SelectOrCreatePersonDialog.selectOrCreatePerson(immunization.getPerson(), immunization, person -> { if (person != null) { immunization.setPerson(person); pickOrCreateImmunizationAndSave(immunization, fragment); diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/pathogentest/edit/PathogenTestEditFragment.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/pathogentest/edit/PathogenTestEditFragment.java index 2b53851e327..71e97a7f938 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/pathogentest/edit/PathogenTestEditFragment.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/pathogentest/edit/PathogenTestEditFragment.java @@ -20,11 +20,13 @@ import java.util.Arrays; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import android.view.View; import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.customizableenum.CustomizableEnum; import de.symeda.sormas.api.customizableenum.CustomizableEnumType; import de.symeda.sormas.api.disease.DiseaseVariant; import de.symeda.sormas.api.environment.environmentsample.Pathogen; @@ -101,14 +103,21 @@ record = getActivityRootData(); diseaseList.add(DataUtils.toItem(record.getTestedDisease())); } - List diseaseVariants = - DatabaseHelper.getCustomizableEnumValueDao().getEnumValues(CustomizableEnumType.DISEASE_VARIANT, record.getTestedDisease()); + List diseaseVariants = DatabaseHelper.getCustomizableEnumValueDao() + .getEnumValues( + CustomizableEnumType.DISEASE_VARIANT, + Optional.ofNullable(record.getTestedDiseaseVariant()).map(CustomizableEnum::getValue).orElse(null), + record.getTestedDisease()); diseaseVariantList = DataUtils.toItems(diseaseVariants); if (record.getTestedDiseaseVariant() != null && !diseaseVariants.contains(record.getTestedDiseaseVariant())) { diseaseVariantList.add(DataUtils.toItem(record.getTestedDiseaseVariant())); } - List pathogens = DatabaseHelper.getCustomizableEnumValueDao().getEnumValues(CustomizableEnumType.PATHOGEN, null); + List pathogens = DatabaseHelper.getCustomizableEnumValueDao() + .getEnumValues( + CustomizableEnumType.PATHOGEN, + Optional.ofNullable(record.getTestedPathogen()).map(CustomizableEnum::getValue).orElse(null), + null); pathogenList = DataUtils.toItems(pathogens); if (record.getTestedPathogen() != null && !diseaseVariants.contains(record.getTestedPathogen())) { pathogenList.add(DataUtils.toItem(record.getTestedPathogen())); @@ -239,8 +248,11 @@ public void onChange(ControlPropertyField field) { private void updateDiseaseVariantsField(FragmentPathogenTestEditLayoutBinding contentBinding) { DiseaseVariant selectedVariant = (DiseaseVariant) contentBinding.pathogenTestTestedDiseaseVariant.getValue(); - List diseaseVariants = - DatabaseHelper.getCustomizableEnumValueDao().getEnumValues(CustomizableEnumType.DISEASE_VARIANT, record.getTestedDisease()); + List diseaseVariants = DatabaseHelper.getCustomizableEnumValueDao() + .getEnumValues( + CustomizableEnumType.DISEASE_VARIANT, + Optional.ofNullable(record.getTestedDiseaseVariant()).map(CustomizableEnum::getValue).orElse(null), + record.getTestedDisease()); diseaseVariantList.clear(); diseaseVariantList.addAll(DataUtils.toItems(diseaseVariants)); contentBinding.pathogenTestTestedDiseaseVariant.setSpinnerData(diseaseVariantList); diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/pathogentest/read/PathogenTestReadActivity.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/pathogentest/read/PathogenTestReadActivity.java index a62a71abd0d..2d81523f9bb 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/pathogentest/read/PathogenTestReadActivity.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/pathogentest/read/PathogenTestReadActivity.java @@ -56,7 +56,10 @@ protected BaseReadFragment buildReadFragment(PageMenuItem menuItem, PathogenTest public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); getEditMenu().setTitle(R.string.action_edit_pathogen_test); - getEditMenu().setVisible(ConfigProvider.hasUserRight(UserRight.PATHOGEN_TEST_EDIT)); + getEditMenu().setVisible( + getStoredRootEntity().getSample() != null + ? ConfigProvider.hasUserRight(UserRight.PATHOGEN_TEST_EDIT) + : ConfigProvider.hasUserRight(UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT)); return true; } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/person/SelectOrCreatePersonDialog.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/person/SelectOrCreatePersonDialog.java index 87caa38f439..361b26142c0 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/person/SelectOrCreatePersonDialog.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/person/SelectOrCreatePersonDialog.java @@ -21,20 +21,22 @@ import android.content.Context; import android.view.View; - import androidx.databinding.Observable; import androidx.databinding.ObservableArrayList; import androidx.databinding.ObservableField; import androidx.databinding.ViewDataBinding; import androidx.databinding.library.baseAdapters.BR; import androidx.fragment.app.FragmentActivity; - +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.i18n.Strings; import de.symeda.sormas.api.person.PersonHelper; import de.symeda.sormas.api.person.PersonNameDto; import de.symeda.sormas.api.person.PersonSimilarityCriteria; import de.symeda.sormas.app.BaseActivity; import de.symeda.sormas.app.R; import de.symeda.sormas.app.backend.common.DatabaseHelper; +import de.symeda.sormas.app.backend.common.PseudonymizableAdo; +import de.symeda.sormas.app.backend.event.Event; import de.symeda.sormas.app.backend.person.Person; import de.symeda.sormas.app.component.controls.ControlButton; import de.symeda.sormas.app.component.dialog.AbstractDialog; @@ -61,9 +63,11 @@ public class SelectOrCreatePersonDialog extends AbstractDialog { private Callback createCallback; private final ObservableField selectedPerson = new ObservableField<>(); + private View selectedPersonItemView; + // Static methods - public static void selectOrCreatePerson(final Person person, final Consumer resultConsumer) { + public static void selectOrCreatePerson(final Person person, PseudonymizableAdo ado, final Consumer resultConsumer) { final SelectOrCreatePersonDialog personDialog = new SelectOrCreatePersonDialog(BaseActivity.getActiveActivity(), person); if (!personDialog.hasSimilarPersons()) { @@ -73,7 +77,20 @@ public static void selectOrCreatePerson(final Person person, final Consumer { if (personDialog.getSelectedPerson() != null) { - resultConsumer.accept(personDialog.getSelectedPerson()); + if (ado instanceof Event + && DatabaseHelper.getEventParticipantDao().eventParticipantAlreadyExists((Event) ado, personDialog.getSelectedPerson())) { + personDialog.suppressNextDismiss(); + personDialog.setSelectedPerson(null); + personDialog.setSelectedPersonItemView(null); + + NotificationHelper.showDialogNotification( + personDialog, + NotificationType.WARNING, + I18nProperties.getString(Strings.messageAlreadyEventParticipant)); + + } else { + resultConsumer.accept(personDialog.getSelectedPerson()); + } } else { personDialog.suppressNextDismiss(); NotificationHelper.showDialogNotification(personDialog, NotificationType.ERROR, R.string.info_select_create_person); @@ -150,8 +167,10 @@ private void setUpControlListeners() { if (itemViewId == vId && v.isSelected()) { itemView.setSelected(false); + setSelectedPerson(personItem); } else if (itemViewId == vId && !v.isSelected()) { itemView.setSelected(true); + setSelectedPersonItemView(itemView); setSelectedPerson(personItem); } else { itemView.setSelected(false); @@ -193,6 +212,10 @@ public void onPropertyChanged(Observable observable, int i) { if (getSelectedPerson() == null) { btnCreate.setVisibility(View.VISIBLE); btnSelect.setVisibility(View.GONE); + + if (selectedPersonItemView != null) { + selectedPersonItemView.setSelected(false); + } } else { btnCreate.setVisibility(View.GONE); btnSelect.setVisibility(View.VISIBLE); @@ -229,4 +252,8 @@ private Person getSelectedPerson() { private void setSelectedPerson(Person selectedPerson) { this.selectedPerson.set(selectedPerson); } + + public void setSelectedPersonItemView(View selectedPersonItemView) { + this.selectedPersonItemView = selectedPersonItemView; + } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/person/edit/PersonEditFragment.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/person/edit/PersonEditFragment.java index 281dd1a408b..263e3de8287 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/person/edit/PersonEditFragment.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/person/edit/PersonEditFragment.java @@ -23,6 +23,7 @@ import java.util.Date; import java.util.GregorianCalendar; import java.util.List; +import java.util.Optional; import android.view.View; import android.view.ViewGroup; @@ -32,6 +33,7 @@ import de.symeda.sormas.api.CountryHelper; import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.customizableenum.CustomizableEnum; import de.symeda.sormas.api.customizableenum.CustomizableEnumType; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; @@ -157,8 +159,12 @@ private void setUpLayoutBinding(final BaseEditFragment fragment, final Person re List initialPlaceOfBirthFacilities = InfrastructureDaoHelper.loadFacilities(record.getPlaceOfBirthDistrict(), record.getPlaceOfBirthCommunity(), null); - List occupationTypeList = - DataUtils.toItems(DatabaseHelper.getCustomizableEnumValueDao().getEnumValues(CustomizableEnumType.OCCUPATION_TYPE, null)); + List occupationTypeList = DataUtils.toItems( + DatabaseHelper.getCustomizableEnumValueDao() + .getEnumValues( + CustomizableEnumType.OCCUPATION_TYPE, + Optional.ofNullable(record.getOccupationType()).map(CustomizableEnum::getValue).orElse(null), + null)); List placeOfBirthFacilityTypeList = DataUtils.toItems(FacilityType.getPlaceOfBirthTypes(), true); List countryList = InfrastructureDaoHelper.loadCountries(); diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/util/BooleanJurisdictionValidator.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/util/BooleanJurisdictionValidator.java index 5bdbee6f159..2a47be84acf 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/util/BooleanJurisdictionValidator.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/util/BooleanJurisdictionValidator.java @@ -21,13 +21,15 @@ import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.utils.jurisdiction.JurisdictionValidator; +import de.symeda.sormas.app.backend.config.ConfigProvider; +import de.symeda.sormas.app.backend.user.UserDtoHelper; public abstract class BooleanJurisdictionValidator extends JurisdictionValidator { private final UserJurisdiction userJurisdiction; public BooleanJurisdictionValidator(List associatedJurisdictionValidators, UserJurisdiction userJurisdiction) { - super(associatedJurisdictionValidators); + super(associatedJurisdictionValidators, UserDtoHelper.isRestrictedToAssignEntities(ConfigProvider.getUser())); this.userJurisdiction = userJurisdiction; } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/util/JurisdictionHelper.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/util/JurisdictionHelper.java index 51bf97b6bc5..df50cbc7573 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/util/JurisdictionHelper.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/util/JurisdictionHelper.java @@ -21,6 +21,8 @@ import de.symeda.sormas.app.backend.immunization.Immunization; import de.symeda.sormas.app.backend.immunization.ImmunizationJurisdictionDto; import de.symeda.sormas.app.backend.location.Location; +import de.symeda.sormas.app.backend.person.Person; +import de.symeda.sormas.app.backend.person.PersonJurisdictionDto; import de.symeda.sormas.app.backend.region.Community; import de.symeda.sormas.app.backend.region.District; import de.symeda.sormas.app.backend.region.Region; @@ -93,6 +95,9 @@ public static CaseJurisdictionDto createCaseJurisdictionDto(Case caze) { dto.setSampleLabUuids( samples.stream().filter(sample -> sample.getLab() != null).map(sample -> sample.getLab().getUuid()).collect(Collectors.toList())); } + if (caze.getSurveillanceOfficer() != null) { + dto.setSurveillanceOfficerUuid(caze.getSurveillanceOfficer().getUuid()); + } return dto; } @@ -118,6 +123,9 @@ public static ContactJurisdictionDto createContactJurisdictionDto(Contact contac dto.setCaseJurisdiction(JurisdictionHelper.createCaseJurisdictionDto(caseOfContact)); } + if (contact.getContactOfficer() != null) { + dto.setContactOfficerUuid(contact.getContactOfficer().getUuid()); + } return dto; } @@ -139,9 +147,43 @@ public static ImmunizationJurisdictionDto createImmunizationJurisdictionDto(Immu immunization.getHealthFacility()); immunizationJurisdictionDto.setResponsibleJurisdiction(responsibleJurisdiction); + Person immunizationPerson = immunization.getPerson(); + immunizationJurisdictionDto.setPersonJurisdiction(createPersonJurisdictionDto(immunizationPerson)); + return immunizationJurisdictionDto; } + public static PersonJurisdictionDto createPersonJurisdictionDto(Person person) { + if (person == null) { + return null; + } + + PersonJurisdictionDto personJurisdiction = new PersonJurisdictionDto(); + + personJurisdiction.setCaseJurisdictions( + DatabaseHelper.getCaseDao() + .getByPerson(person) + .stream() + .map(surveillanceOfficer -> new CaseJurisdictionDto().setSurveillanceOfficerUuid(surveillanceOfficer.getUuid())) + .collect(Collectors.toList())); + + personJurisdiction.setContactJurisdictions( + DatabaseHelper.getContactDao() + .getByPerson(person) + .stream() + .map(contactOfficer -> new ContactJurisdictionDto().setContactOfficerUuid(contactOfficer.getUuid())) + .collect(Collectors.toList())); + + personJurisdiction.setEventJurisdictions( + DatabaseHelper.getEventDao() + .getByEventParticipantPerson(person) + .stream() + .map(responsibleUser -> new EventJurisdictionDto().setResponsibleUserUuid(responsibleUser.getUuid())) + .collect(Collectors.toList())); + + return personJurisdiction; + } + public static EventJurisdictionDto createEventJurisdictionDto(Event event) { if (event == null) { return null; @@ -199,6 +241,10 @@ public static EventParticipantJurisdictionDto createEventParticipantJurisdiction jurisdiction.setEventJurisdictionDto(JurisdictionHelper.createEventJurisdictionDto(event)); } + if (event.getResponsibleUser() != null) { + jurisdiction.setEventResponsibleUserUuid(event.getResponsibleUser().getUuid()); + } + return jurisdiction; } @@ -261,6 +307,10 @@ public static EnvironmentSampleJurisdictionDto createEnvironmentSampleJurisdicti } } + if (sample.getEnvironment().getResponsibleUser() != null) { + environmentSampleJurisdiction.setEnvironmentResponsibleUser(sample.getEnvironment().getResponsibleUser().getUuid()); + } + return environmentSampleJurisdiction; } diff --git a/sormas-app/pom.xml b/sormas-app/pom.xml index fed197cc482..b32c643205b 100644 --- a/sormas-app/pom.xml +++ b/sormas-app/pom.xml @@ -3,7 +3,7 @@ sormas-base de.symeda.sormas - 1.93.0 + 1.94.0 ../sormas-base 4.0.0 diff --git a/sormas-backend/pom.xml b/sormas-backend/pom.xml index c179f7898b4..566bb487cfa 100644 --- a/sormas-backend/pom.xml +++ b/sormas-backend/pom.xml @@ -3,7 +3,7 @@ sormas-base de.symeda.sormas - 1.93.0 + 1.94.0 ../sormas-base 4.0.0 @@ -213,11 +213,11 @@ slf4j-api - - org.apache.pdfbox - pdfbox - - + + org.apache.pdfbox + pdfbox + 3.0.0 + diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/action/ActionService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/action/ActionService.java index 8cc84e7bb73..12698b51144 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/action/ActionService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/action/ActionService.java @@ -296,7 +296,7 @@ public List getEventActionIndexList(EventCriteria criteria, List actions = new ArrayList<>(); IterableHelper.executeBatched(indexListIds, ModelConstants.PARAMETER_LIMIT, batchedIds -> { final CriteriaBuilder cb = em.getCriteriaBuilder(); - final CriteriaQuery cq = cb.createQuery(Object[].class); + final CriteriaQuery cq = cb.createQuery(Tuple.class); final Root action = cq.from(getElementClass()); final ActionQueryContext queryContext = new ActionQueryContext(cb, cq, action); final ActionJoins actionJoins = queryContext.getJoins(); @@ -360,11 +360,7 @@ public List getEventActionIndexList(EventCriteria criteria, cq.orderBy(getOrderList(sortProperties, queryContext)); cq.distinct(true); - //noinspection unchecked - actions.addAll( - createQuery(cq, first, max).unwrap(org.hibernate.query.Query.class) - .setResultTransformer(new EventActionIndexDtoReasultTransformer()) - .getResultList()); + actions.addAll(QueryHelper.getResultList(em, cq, new EventActionIndexDtoReasultTransformer(), first, max)); }); return actions; diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/CampaignFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/CampaignFacadeEjb.java index 70e9940a5b4..cfb60baf0a4 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/CampaignFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/CampaignFacadeEjb.java @@ -103,11 +103,13 @@ public List getIndexList(CampaignCriteria campaignCriteria, In Expression expression; switch (sortProperty.propertyName) { case CampaignIndexDto.UUID: - case CampaignIndexDto.NAME: case CampaignIndexDto.START_DATE: case CampaignIndexDto.END_DATE: expression = campaign.get(sortProperty.propertyName); break; + case CampaignIndexDto.NAME: + expression = cb.lower(campaign.get(sortProperty.propertyName)); + break; default: throw new IllegalArgumentException(sortProperty.propertyName); } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/data/CampaignFormDataFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/data/CampaignFormDataFacadeEjb.java index 5f5b23027ba..0ea40a8e2b6 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/data/CampaignFormDataFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/data/CampaignFormDataFacadeEjb.java @@ -313,19 +313,19 @@ public List getIndexList( expression = root.get(sortProperty.propertyName); break; case CampaignFormDataIndexDto.CAMPAIGN: - expression = campaignJoin.get(Campaign.NAME); + expression = cb.lower(campaignJoin.get(Campaign.NAME)); break; case CampaignFormDataIndexDto.FORM: - expression = campaignFormMetaJoin.get(CampaignFormMeta.FORM_NAME); + expression = cb.lower(campaignFormMetaJoin.get(CampaignFormMeta.FORM_NAME)); break; case CampaignFormDataIndexDto.REGION: - expression = regionJoin.get(Region.NAME); + expression = cb.lower(regionJoin.get(Region.NAME)); break; case CampaignFormDataIndexDto.DISTRICT: - expression = districtJoin.get(District.NAME); + expression = cb.lower(districtJoin.get(District.NAME)); break; case CampaignFormDataIndexDto.COMMUNITY: - expression = communityJoin.get(Community.NAME); + expression = cb.lower(communityJoin.get(Community.NAME)); break; default: throw new IllegalArgumentException(sortProperty.propertyName); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/data/CampaignFormDataJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/data/CampaignFormDataJurisdictionPredicateValidator.java index ba800042423..a77f7bd2afd 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/data/CampaignFormDataJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/data/CampaignFormDataJurisdictionPredicateValidator.java @@ -46,6 +46,11 @@ public Predicate isRootInJurisdictionOrOwned() { return cb.or(reportedByCurrentUser, isRootInJurisdiction()); } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + return cb.disjunction(); + } + @Override protected Predicate whenNotAllowed() { return cb.disjunction(); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseFacadeEjb.java index 67319f28f7e..876f0906da5 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseFacadeEjb.java @@ -16,6 +16,7 @@ package de.symeda.sormas.backend.caze; import static de.symeda.sormas.backend.common.CriteriaBuilderHelper.and; +import static de.symeda.sormas.backend.common.CriteriaBuilderHelper.createOrderBuilder; import static de.symeda.sormas.backend.common.CriteriaBuilderHelper.or; import static de.symeda.sormas.backend.visit.VisitLogic.getVisitResult; import static java.util.Objects.isNull; @@ -43,6 +44,7 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.Nullable; import javax.annotation.Resource; @@ -241,8 +243,8 @@ import de.symeda.sormas.backend.common.AbstractDomainObject; import de.symeda.sormas.backend.common.ConfigFacadeEjb.ConfigFacadeEjbLocal; import de.symeda.sormas.backend.common.CriteriaBuilderHelper; +import de.symeda.sormas.backend.common.CriteriaBuilderHelper.OrderBuilder; import de.symeda.sormas.backend.common.NotificationService; -import de.symeda.sormas.backend.manualmessagelog.ManualMessageLogService; import de.symeda.sormas.backend.common.messaging.MessageContents; import de.symeda.sormas.backend.common.messaging.MessageSubject; import de.symeda.sormas.backend.common.messaging.MessagingService; @@ -297,6 +299,7 @@ import de.symeda.sormas.backend.infrastructure.region.RegionFacadeEjb; import de.symeda.sormas.backend.infrastructure.region.RegionService; import de.symeda.sormas.backend.location.Location; +import de.symeda.sormas.backend.manualmessagelog.ManualMessageLogService; import de.symeda.sormas.backend.outbreak.Outbreak; import de.symeda.sormas.backend.outbreak.OutbreakService; import de.symeda.sormas.backend.person.Person; @@ -342,6 +345,7 @@ import de.symeda.sormas.backend.travelentry.services.TravelEntryService; import de.symeda.sormas.backend.user.User; import de.symeda.sormas.backend.user.UserFacadeEjb; +import de.symeda.sormas.backend.user.UserHelper; import de.symeda.sormas.backend.user.UserReference; import de.symeda.sormas.backend.user.UserRoleFacadeEjb; import de.symeda.sormas.backend.user.UserRoleService; @@ -592,8 +596,8 @@ public List getIndexList(CaseCriteria caseCriteria, Integer first, List cases = new ArrayList<>(); IterableHelper.executeBatched(indexListIds, ModelConstants.PARAMETER_LIMIT, batchedIds -> { - CriteriaQuery cq = listQueryBuilder.buildIndexCriteria(caseCriteria, sortProperties, batchedIds); - cases.addAll(QueryHelper.getResultList(em, cq, null, null)); + CriteriaQuery cq = listQueryBuilder.buildIndexCriteria(caseCriteria, sortProperties, batchedIds); + cases.addAll(QueryHelper.getResultList(em, cq, new CaseIndexDtoResultTransformer(), null, null)); }); List caseIds = cases.stream().map(CaseIndexDto::getId).collect(Collectors.toList()); @@ -646,8 +650,8 @@ public List getIndexDetailedList(CaseCriteria caseCriteria List cases = new ArrayList<>(); IterableHelper.executeBatched(indexListIds, ModelConstants.PARAMETER_LIMIT, batchedIds -> { - CriteriaQuery cq = listQueryBuilder.buildIndexDetailedCriteria(caseCriteria, sortProperties, batchedIds); - cases.addAll(QueryHelper.getResultList(em, cq, null, null)); + CriteriaQuery cq = listQueryBuilder.buildIndexDetailedCriteria(caseCriteria, sortProperties, batchedIds); + cases.addAll(QueryHelper.getResultList(em, cq, new CaseIndexDetailedDtoResultTransformer(), null, null)); }); // Load latest events info @@ -2434,7 +2438,12 @@ public void setCaseResponsible( Random rand = new Random(); if (!hospitalUsers.isEmpty()) { - caze.setSurveillanceOfficer(hospitalUsers.get(rand.nextInt(hospitalUsers.size())).getAssociatedOfficer()); + caze.setSurveillanceOfficer( + hospitalUsers.stream() + .filter(user -> !UserHelper.isRestrictedToAssignEntities(user)) + .collect(Collectors.toList()) + .get(rand.nextInt(hospitalUsers.size())) + .getAssociatedOfficer()); } else { @@ -4050,23 +4059,14 @@ public List getCaseFollowUpList( Date start = DateHelper.getStartOfDay(DateHelper.subtractDays(end, interval)); CriteriaBuilder cb = em.getCriteriaBuilder(); - CriteriaQuery cq = cb.createQuery(CaseFollowUpDto.class); + CriteriaQuery cq = cb.createQuery(Tuple.class); Root caze = cq.from(Case.class); final CaseQueryContext caseQueryContext = new CaseQueryContext(cb, cq, caze); final CaseJoins joins = caseQueryContext.getJoins(); - cq.multiselect( - caze.get(Case.UUID), - caze.get(Case.CHANGE_DATE), - joins.getPerson().get(Person.FIRST_NAME), - joins.getPerson().get(Person.LAST_NAME), - caze.get(Case.REPORT_DATE), - joins.getSymptoms().get(Symptoms.ONSET_DATE), - caze.get(Case.FOLLOW_UP_UNTIL), - joins.getPerson().get(Person.SYMPTOM_JOURNAL_STATUS), - caze.get(Case.DISEASE), - JurisdictionHelper.booleanSelector(cb, service.inJurisdictionOrOwned(caseQueryContext))); + Path firstName = joins.getPerson().get(Person.FIRST_NAME); + Path lastName = joins.getPerson().get(Person.LAST_NAME); Predicate filter = CriteriaBuilderHelper.and(cb, service.createUserFilter(caseQueryContext), service.createCriteriaFilter(caseCriteria, caseQueryContext)); @@ -4077,38 +4077,56 @@ public List getCaseFollowUpList( cq.distinct(true); + final List orderList = new ArrayList<>(); if (sortProperties != null && !sortProperties.isEmpty()) { - List order = new ArrayList<>(sortProperties.size()); for (SortProperty sortProperty : sortProperties) { - Expression expression; + OrderBuilder builder = createOrderBuilder(cb, sortProperty.ascending); + final List order; + switch (sortProperty.propertyName) { case FollowUpDto.UUID: case FollowUpDto.REPORT_DATE: case FollowUpDto.FOLLOW_UP_UNTIL: - expression = caze.get(sortProperty.propertyName); + order = builder.build(caze.get(sortProperty.propertyName)); break; case FollowUpDto.FIRST_NAME: - expression = joins.getPerson().get(Person.FIRST_NAME); - order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); + order = builder.build(cb.lower(firstName)); break; case FollowUpDto.SYMPTOM_JOURNAL_STATUS: - expression = joins.getPerson().get(Person.SYMPTOM_JOURNAL_STATUS); + order = builder.build(joins.getPerson().get(Person.SYMPTOM_JOURNAL_STATUS)); break; case FollowUpDto.LAST_NAME: - expression = joins.getPerson().get(Person.LAST_NAME); - order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); + order = builder.build(cb.lower(lastName)); break; default: throw new IllegalArgumentException(sortProperty.propertyName); } - order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); + + orderList.addAll(order); } - cq.orderBy(order); } else { - cq.orderBy(cb.desc(caze.get(Case.CHANGE_DATE))); + orderList.add(cb.desc(caze.get(Case.CHANGE_DATE))); } - List resultList = QueryHelper.getResultList(em, cq, first, max); + cq.multiselect( + Stream + .concat( + Stream.of( + caze.get(Case.UUID), + firstName, + lastName, + caze.get(Case.REPORT_DATE), + joins.getSymptoms().get(Symptoms.ONSET_DATE), + caze.get(Case.FOLLOW_UP_UNTIL), + joins.getPerson().get(Person.SYMPTOM_JOURNAL_STATUS), + caze.get(Case.DISEASE), + JurisdictionHelper.booleanSelector(cb, service.inJurisdictionOrOwned(caseQueryContext))), + orderList.stream().map(Order::getExpression)) + .collect(Collectors.toList())); + + cq.orderBy(orderList); + + List resultList = QueryHelper.getResultList(em, cq, new CaseFollowUpDtoResultTransformer(), first, max); if (!resultList.isEmpty()) { List caseUuids = resultList.stream().map(FollowUpDto::getUuid).collect(Collectors.toList()); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseFollowUpDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseFollowUpDtoResultTransformer.java new file mode 100644 index 00000000000..73aaa4d5fec --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseFollowUpDtoResultTransformer.java @@ -0,0 +1,49 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.backend.caze; + +import java.util.Date; +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.caze.CaseFollowUpDto; +import de.symeda.sormas.api.person.SymptomJournalStatus; + +public class CaseFollowUpDtoResultTransformer implements ResultTransformer { + + private static final long serialVersionUID = 4356617588814093951L; + + @Override + public CaseFollowUpDto transformTuple(Object[] tuple, String[] aliases) { + int index = -1; + + //@formatter:off + return new CaseFollowUpDto( + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (Date) tuple[++index], (Date) tuple[++index], (Date) tuple[++index], (SymptomJournalStatus) tuple[++index], + (Disease) tuple[++index], (Boolean) tuple[++index] + ); + //@formatter:on + } + + @Override + @SuppressWarnings("rawtypes") + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseIndexDetailedDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseIndexDetailedDtoResultTransformer.java new file mode 100644 index 00000000000..a0a34be5ab9 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseIndexDetailedDtoResultTransformer.java @@ -0,0 +1,69 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.backend.caze; + +import java.util.Date; +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.caze.CaseClassification; +import de.symeda.sormas.api.caze.CaseIndexDetailedDto; +import de.symeda.sormas.api.caze.CaseOutcome; +import de.symeda.sormas.api.caze.InvestigationStatus; +import de.symeda.sormas.api.caze.VaccinationStatus; +import de.symeda.sormas.api.common.DeletionReason; +import de.symeda.sormas.api.contact.FollowUpStatus; +import de.symeda.sormas.api.disease.DiseaseVariant; +import de.symeda.sormas.api.person.ApproximateAgeType; +import de.symeda.sormas.api.person.PresentCondition; +import de.symeda.sormas.api.person.Sex; +import de.symeda.sormas.api.person.SymptomJournalStatus; +import de.symeda.sormas.api.utils.YesNoUnknown; + +public class CaseIndexDetailedDtoResultTransformer implements ResultTransformer { + + private static final long serialVersionUID = -4616187250169484589L; + + @Override + public CaseIndexDetailedDto transformTuple(Object[] tuple, String[] aliases) { + int index = -1; + + //@formatter:off + return new CaseIndexDetailedDto((Long)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (Disease)tuple[++index], + (DiseaseVariant) tuple[++index], (String)tuple[++index], (CaseClassification)tuple[++index], (InvestigationStatus)tuple[++index], + (PresentCondition)tuple[++index], (Date)tuple[++index], (Date)tuple[++index], (String)tuple[++index], + (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], + (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (CaseOutcome) tuple[++index], + (Integer)tuple[++index], (ApproximateAgeType) tuple[++index], (Integer)tuple[++index], (Integer)tuple[++index], (Integer)tuple[++index], (Sex) tuple[++index], (Date)tuple[++index], + (Float)tuple[++index], (FollowUpStatus) tuple[++index], (Date)tuple[++index], (SymptomJournalStatus) tuple[++index], (VaccinationStatus) tuple[++index], + (Date)tuple[++index], (Long)tuple[++index], + (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (DeletionReason)tuple[++index], (String)tuple[++index], (Boolean)tuple[++index], + (YesNoUnknown) tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], + (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (Date)tuple[++index], + (String)tuple[++index], (String)tuple[++index], + (int)tuple[++index], (long)tuple[++index], (Date)tuple[++index], (long)tuple[++index] + ); + //@formatter:on + } + + @Override + @SuppressWarnings("rawtypes") + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseIndexDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseIndexDtoResultTransformer.java new file mode 100644 index 00000000000..6b31f916f3e --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseIndexDtoResultTransformer.java @@ -0,0 +1,65 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.backend.caze; + +import java.util.Date; +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.caze.CaseClassification; +import de.symeda.sormas.api.caze.CaseIndexDto; +import de.symeda.sormas.api.caze.CaseOutcome; +import de.symeda.sormas.api.caze.InvestigationStatus; +import de.symeda.sormas.api.caze.VaccinationStatus; +import de.symeda.sormas.api.common.DeletionReason; +import de.symeda.sormas.api.contact.FollowUpStatus; +import de.symeda.sormas.api.disease.DiseaseVariant; +import de.symeda.sormas.api.person.ApproximateAgeType; +import de.symeda.sormas.api.person.PresentCondition; +import de.symeda.sormas.api.person.Sex; +import de.symeda.sormas.api.person.SymptomJournalStatus; + +public class CaseIndexDtoResultTransformer implements ResultTransformer { + + private static final long serialVersionUID = -2993938038006111671L; + + @Override + public CaseIndexDto transformTuple(Object[] tuple, String[] aliases) { + int index = -1; + + //@formatter:off + return new CaseIndexDto((Long)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (Disease)tuple[++index], + (DiseaseVariant) tuple[++index], (String)tuple[++index], (CaseClassification)tuple[++index], (InvestigationStatus)tuple[++index], + (PresentCondition)tuple[++index], (Date)tuple[++index], (Date)tuple[++index], (String)tuple[++index], + (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], + (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (CaseOutcome) tuple[++index], + (Integer)tuple[++index], (ApproximateAgeType) tuple[++index], (Integer)tuple[++index], (Integer)tuple[++index], (Integer)tuple[++index], (Sex) tuple[++index], (Date)tuple[++index], + (Float)tuple[++index], (FollowUpStatus) tuple[++index], (Date)tuple[++index], (SymptomJournalStatus) tuple[++index], (VaccinationStatus) tuple[++index], + (Date)tuple[++index], (Long)tuple[++index], + (String)tuple[++index], (String)tuple[++index], (String)tuple[++index], (DeletionReason)tuple[++index], (String)tuple[++index], (Boolean)tuple[++index], + (Integer)tuple[++index] + ); + //@formatter:on + } + + @Override + @SuppressWarnings("rawtypes") + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseJurisdictionPredicateValidator.java index f9a4f579690..ed445687126 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseJurisdictionPredicateValidator.java @@ -80,13 +80,26 @@ public Predicate isRootInJurisdiction() { @Override public Predicate isRootInJurisdictionOrOwned() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + return cb.or(reportedByCurrentUser, this.isRootInJurisdiction()); + } + + private Predicate getReportedByCurrentUser() { final Predicate reportedByCurrentUser = cb.and( cb.isNotNull(joins.getRoot().get(Case.REPORTING_USER)), user != null ? cb.equal(joins.getRoot().get(Case.REPORTING_USER).get(User.ID), user.getId()) : cb.equal(joins.getRoot().get(Case.REPORTING_USER).get(User.ID), userPath.get(User.ID))); + return reportedByCurrentUser; + } - return cb.or(reportedByCurrentUser, this.isRootInJurisdiction()); + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + final Predicate restrictedAccess = user != null + ? cb.equal(joins.getRoot().get(Case.SURVEILLANCE_OFFICER).get(User.ID), user.getId()) + : cb.equal(joins.getRoot().get(Case.SURVEILLANCE_OFFICER).get(User.ID), userPath.get(User.ID)); + return cb.or(reportedByCurrentUser, restrictedAccess); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseListCriteriaBuilder.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseListCriteriaBuilder.java index e0dca473768..3e13e0e79af 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseListCriteriaBuilder.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseListCriteriaBuilder.java @@ -71,43 +71,25 @@ public class CaseListCriteriaBuilder { @Inject private CurrentUserService currentUserService; - public CriteriaQuery buildIndexCriteria(CaseCriteria caseCriteria, List sortProperties, List ids) { - return buildIndexCriteria(CaseIndexDto.class, this::getCaseIndexSelections, caseCriteria, this::getIndexOrders, sortProperties, false, ids); + public CriteriaQuery buildIndexCriteria(CaseCriteria caseCriteria, List sortProperties, List ids) { + return buildIndexCriteria(this::getCaseIndexSelections, caseCriteria, this::getIndexOrders, sortProperties, false, ids); } - public CriteriaQuery buildIndexDetailedCriteria( - CaseCriteria caseCriteria, - List sortProperties, - List ids) { + public CriteriaQuery buildIndexDetailedCriteria(CaseCriteria caseCriteria, List sortProperties, List ids) { - return buildIndexCriteria( - CaseIndexDetailedDto.class, - this::getCaseIndexDetailedSelections, - caseCriteria, - this::getIndexDetailOrders, - sortProperties, - true, - ids); + return buildIndexCriteria(this::getCaseIndexDetailedSelections, caseCriteria, this::getIndexDetailOrders, sortProperties, true, ids); } public CriteriaQuery buildIndexCriteriaPrefetchIds(CaseCriteria caseCriteria, List sortProperties) { - return buildIndexCriteria(Tuple.class, this::getCaseIndexSelections, caseCriteria, this::getIndexOrders, sortProperties, false, null); + return buildIndexCriteria(this::getCaseIndexSelections, caseCriteria, this::getIndexOrders, sortProperties, false, null); } public CriteriaQuery buildIndexDetailedCriteriaPrefetchIds(CaseCriteria caseCriteria, List sortProperties) { - return buildIndexCriteria( - Tuple.class, - this::getCaseIndexDetailedSelections, - caseCriteria, - this::getIndexDetailOrders, - sortProperties, - true, - null); + return buildIndexCriteria(this::getCaseIndexDetailedSelections, caseCriteria, this::getIndexDetailOrders, sortProperties, true, null); } - private CriteriaQuery buildIndexCriteria( - Class type, + private CriteriaQuery buildIndexCriteria( BiFunction, CaseQueryContext, List>> selectionProvider, CaseCriteria caseCriteria, OrderExpressionProvider orderExpressionProvider, @@ -118,7 +100,7 @@ private CriteriaQuery buildIndexCriteria( boolean prefetchIds = ids == null; CriteriaBuilder cb = em.getCriteriaBuilder(); - CriteriaQuery cq = cb.createQuery(type); + CriteriaQuery cq = cb.createQuery(Tuple.class); Root caze = cq.from(Case.class); final CaseQueryContext caseQueryContext = new CaseQueryContext(cb, cq, caze); final CaseJoins joins = caseQueryContext.getJoins(); @@ -133,23 +115,22 @@ private CriteriaQuery buildIndexCriteria( Expression latestChangedDateFunction = cb.function(ExtendedPostgreSQL94Dialect.GREATEST, Date.class, caze.get(Contact.CHANGE_DATE), joins.getPerson().get(Person.CHANGE_DATE)); - List> selectionListPrefetchIds = new ArrayList<>(); + List> orderBySelections = new ArrayList<>(); if (!CollectionUtils.isEmpty(sortProperties)) { List order = new ArrayList<>(sortProperties.size()); for (SortProperty sortProperty : sortProperties) { List> expressions = orderExpressionProvider.forProperty(sortProperty, caze, joins, cb); - selectionListPrefetchIds.addAll(expressions); + orderBySelections.addAll(expressions); order.addAll(expressions.stream().map(e -> sortProperty.ascending ? cb.asc(e) : cb.desc(e)).collect(Collectors.toList())); } cq.orderBy(order); } else { - selectionListPrefetchIds.add(latestChangedDateFunction); + orderBySelections.add(latestChangedDateFunction); cq.orderBy(cb.desc(latestChangedDateFunction)); } if (prefetchIds) { selectionList.add(caze.get(AbstractDomainObject.ID)); - selectionList.addAll(selectionListPrefetchIds); } else { selectionList.addAll(selectionProvider.apply(caze, caseQueryContext)); selectionList.add(visitCountSq); @@ -191,11 +172,11 @@ private CriteriaQuery buildIndexCriteria( sampleCountSq.select(cb.countDistinct(sampleCountRoot.get(AbstractDomainObject.ID))); selectionList.add(sampleCountSq); } - - // This is needed in selection because of the combination of distinct and orderBy clauses - every operator in the orderBy has to be part of the select IF distinct is used - selectionList.add(latestChangedDateFunction); } + // include order by in the select + selectionList.addAll(orderBySelections); + cq.multiselect(selectionList); cq.distinct(true); @@ -204,9 +185,6 @@ private CriteriaQuery buildIndexCriteria( caseUserFilterCriteria.setIncludeCasesFromOtherJurisdictions(caseCriteria.getIncludeCasesFromOtherJurisdictions()); } - if (currentUserService.hasRestrictedAccessToAssignedEntities()) { - caseUserFilterCriteria.setRestrictAccessToAssignedEntities(true); - } Predicate filter = caseService.createUserFilter(caseQueryContext, caseUserFilterCriteria); if (!prefetchIds) { @@ -282,14 +260,12 @@ public List> getCaseIndexSelections(From root, CaseQueryCo private List> getIndexOrders(SortProperty sortProperty, Root caze, CaseJoins joins, CriteriaBuilder cb) { switch (sortProperty.propertyName) { + case CaseIndexDto.PERSON_UUID: + return Collections.singletonList(joins.getPerson().get(Person.UUID)); case CaseIndexDto.ID: case CaseIndexDto.UUID: case CaseIndexDto.EPID_NUMBER: - case CaseIndexDto.EXTERNAL_ID: - case CaseIndexDto.EXTERNAL_TOKEN: - case CaseIndexDto.INTERNAL_TOKEN: case CaseIndexDto.DISEASE: - case CaseIndexDto.DISEASE_DETAILS: case CaseIndexDto.CASE_CLASSIFICATION: case CaseIndexDto.INVESTIGATION_STATUS: case CaseIndexDto.REPORT_DATE: @@ -303,12 +279,15 @@ private List> getIndexOrders(SortProperty sortProperty, Root case CaseIndexDto.VACCINATION_STATUS: case CaseIndexDto.DISEASE_VARIANT: return Collections.singletonList(caze.get(sortProperty.propertyName)); - case CaseIndexDto.PERSON_UUID: - return Collections.singletonList(joins.getPerson().get(Person.UUID)); + case CaseIndexDto.EXTERNAL_ID: + case CaseIndexDto.EXTERNAL_TOKEN: + case CaseIndexDto.INTERNAL_TOKEN: + case CaseIndexDto.DISEASE_DETAILS: + return Collections.singletonList(cb.lower(caze.get(sortProperty.propertyName))); case CaseIndexDto.PERSON_FIRST_NAME: - return Collections.singletonList(joins.getPerson().get(Person.FIRST_NAME)); + return Collections.singletonList(cb.lower(joins.getPerson().get(Person.FIRST_NAME))); case CaseIndexDto.PERSON_LAST_NAME: - return Collections.singletonList(joins.getPerson().get(Person.LAST_NAME)); + return Collections.singletonList(cb.lower(joins.getPerson().get(Person.LAST_NAME))); case CaseIndexDto.PRESENT_CONDITION: case CaseIndexDto.SEX: case ContactIndexDto.SYMPTOM_JOURNAL_STATUS: @@ -320,13 +299,13 @@ private List> getIndexOrders(SortProperty sortProperty, Root case CaseIndexDto.DISTRICT_UUID: return Collections.singletonList(joins.getDistrict().get(District.UUID)); case CaseIndexDto.RESPONSIBLE_DISTRICT_NAME: - return Collections.singletonList(joins.getResponsibleDistrict().get(District.NAME)); + return Collections.singletonList(cb.lower(joins.getResponsibleDistrict().get(District.NAME))); case CaseIndexDto.HEALTH_FACILITY_UUID: return Collections.singletonList(joins.getFacility().get(Facility.UUID)); case CaseIndexDto.HEALTH_FACILITY_NAME: - return Arrays.asList(joins.getFacility(), caze.get(Case.HEALTH_FACILITY_DETAILS)); + return Arrays.asList(joins.getFacility(), cb.lower(caze.get(Case.HEALTH_FACILITY_DETAILS))); case CaseIndexDto.POINT_OF_ENTRY_NAME: - return Collections.singletonList(joins.getPointOfEntry().get(PointOfEntry.NAME)); + return Collections.singletonList(cb.lower(joins.getPointOfEntry().get(PointOfEntry.NAME))); case CaseIndexDto.SURVEILLANCE_OFFICER_UUID: return Collections.singletonList(joins.getSurveillanceOfficer().get(User.UUID)); default: @@ -373,17 +352,17 @@ private List> getIndexDetailOrders(SortProperty sortProperty, Root case CaseIndexDetailedDto.HOUSE_NUMBER: case CaseIndexDetailedDto.ADDITIONAL_INFORMATION: case CaseIndexDetailedDto.POSTAL_CODE: - return Collections.singletonList(joins.getPersonAddress().get(sortProperty.propertyName)); + return Collections.singletonList(cb.lower(joins.getPersonAddress().get(sortProperty.propertyName))); case CaseIndexDetailedDto.PHONE: return Collections.singletonList(joins.getPersonJoins().getPhone().get(PersonContactDetail.CONTACT_INFORMATION)); case CaseIndexDetailedDto.REPORTING_USER: - return Arrays.asList(joins.getReportingUser().get(User.FIRST_NAME), joins.getReportingUser().get(User.LAST_NAME)); + return Arrays.asList(cb.lower(joins.getReportingUser().get(User.FIRST_NAME)), cb.lower(joins.getReportingUser().get(User.LAST_NAME))); case CaseIndexDetailedDto.SYMPTOM_ONSET_DATE: return Collections.singletonList(joins.getSymptoms().get(Symptoms.ONSET_DATE)); case CaseIndexDetailedDto.RESPONSIBLE_REGION: - return Collections.singletonList(joins.getResponsibleRegion().get(Region.NAME)); + return Collections.singletonList(cb.lower(joins.getResponsibleRegion().get(Region.NAME))); case CaseIndexDetailedDto.RESPONSIBLE_COMMUNITY: - return Collections.singletonList(joins.getResponsibleCommunity().get(Community.NAME)); + return Collections.singletonList(cb.lower(joins.getResponsibleCommunity().get(Community.NAME))); default: return getIndexOrders(sortProperty, caze, joins, cb); } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseService.java index 684a4d73873..2a0a6c73246 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseService.java @@ -1395,7 +1395,8 @@ public Predicate createUserFilter(CaseQueryContext caseQueryContext, CaseUserFil final JurisdictionLevel jurisdictionLevel = currentUser.getJurisdictionLevel(); - if (currentUserHasRestrictedAccessToAssignedEntities()) { + final boolean restrictedToAssignedEntities = isRestrictedToAssignedEntities(); + if (restrictedToAssignedEntities) { filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(casePath.get(Case.SURVEILLANCE_OFFICER).get(User.ID), currentUser.getId())); } @@ -1410,7 +1411,7 @@ public Predicate createUserFilter(CaseQueryContext caseQueryContext, CaseUserFil filterResponsible = cb.disjunction(); } - if (!currentUserHasRestrictedAccessToAssignedEntities()) { + if (!restrictedToAssignedEntities) { switch (jurisdictionLevel) { case REGION: final Region region = currentUser.getRegion(); @@ -1490,7 +1491,14 @@ public Predicate createUserFilter(CaseQueryContext caseQueryContext, CaseUserFil } // only show cases of a specific disease if a limited disease is set - filter = CriteriaBuilderHelper.and(cb, filter, CriteriaBuilderHelper.limitedDiseasePredicate(cb, currentUser, casePath.get(Case.DISEASE))); + filter = CriteriaBuilderHelper.and( + cb, + filter, + CriteriaBuilderHelper.limitedDiseasePredicate( + cb, + currentUser, + casePath.get(Case.DISEASE), + cb.equal(casePath.get(Case.REPORTING_USER).get(User.ID), currentUser.getId()))); // port health users can only see port health cases if (currentUser.getUserRoles().stream().anyMatch(userRole -> userRole.isPortHealthUser())) { @@ -1687,20 +1695,12 @@ public EditPermissionType isAddContactAllowed(Case caze) { return EditPermissionType.REFUSED; } - if (currentUserHasRestrictedAccessToAssignedEntities() && !DataHelper.equal(caze.getSurveillanceOfficer(), getCurrentUser())) { - return EditPermissionType.REFUSED; - } - return super.getEditPermissionType(caze); } @Override public EditPermissionType getEditPermissionType(Case caze) { - if (currentUserHasRestrictedAccessToAssignedEntities() && !DataHelper.equal(caze.getSurveillanceOfficer(), getCurrentUser())) { - return EditPermissionType.REFUSED; - } - if (!inJurisdictionOrOwned(caze)) { return EditPermissionType.OUTSIDE_JURISDICTION; } @@ -1770,7 +1770,7 @@ public List getByExternalId(String externalId) { public List getCaseSelectionList(CaseCriteria caseCriteria) { final CriteriaBuilder cb = em.getCriteriaBuilder(); - final CriteriaQuery cq = cb.createQuery(Object[].class); + final CriteriaQuery cq = cb.createQuery(Tuple.class); final Root root = cq.from(Case.class); CaseQueryContext caseQueryContext = new CaseQueryContext(cb, cq, root); @@ -1831,10 +1831,7 @@ public List getCaseSelectionList(CaseCriteria caseCriteria) { cq.where(filter); } - return em.createQuery(cq) - .unwrap(org.hibernate.query.Query.class) - .setResultTransformer(new CaseSelectionDtoResultTransformer()) - .getResultList(); + return QueryHelper.getResultList(em, cq, new CaseSelectionDtoResultTransformer(), null, null); } public List getEntriesList(Long personId, Integer first, Integer max) { @@ -1843,7 +1840,7 @@ public List getEntriesList(Long personId, Integer first, Integ } final CriteriaBuilder cb = em.getCriteriaBuilder(); - final CriteriaQuery cq = cb.createQuery(Object[].class); + final CriteriaQuery cq = cb.createQuery(Tuple.class); final Root caze = cq.from(Case.class); CaseQueryContext caseQueryContext = new CaseQueryContext(cb, cq, caze); @@ -1866,9 +1863,7 @@ public List getEntriesList(Long personId, Integer first, Integ cq.distinct(true); - return createQuery(cq, first, max).unwrap(org.hibernate.query.Query.class) - .setResultTransformer(new CaseListEntryDtoResultTransformer()) - .getResultList(); + return QueryHelper.getResultList(em, cq, new CaseListEntryDtoResultTransformer(), first, max); } public Long getIdByUuid(@NotNull String uuid) { @@ -1891,7 +1886,7 @@ public Long getIdByUuid(@NotNull String uuid) { public List getSimilarCases(CaseSimilarityCriteria criteria) { CriteriaBuilder cb = em.getCriteriaBuilder(); - CriteriaQuery cq = cb.createQuery(Object[].class); + CriteriaQuery cq = cb.createQuery(Tuple.class); Root root = cq.from(Case.class); CaseQueryContext queryContext = new CaseQueryContext(cb, cq, root); CaseJoins joins = queryContext.getJoins(); @@ -1924,10 +1919,7 @@ public List getSimilarCases(CaseSimilarityCriteria criteria) { cq.where(filter); - return em.createQuery(cq) - .unwrap(org.hibernate.query.Query.class) - .setResultTransformer(new CaseSelectionDtoResultTransformer()) - .getResultList(); + return QueryHelper.getResultList(em, cq, new CaseSelectionDtoResultTransformer(), null, null); } public boolean hasSimilarCases(CaseSimilarityCriteria criteria) { diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseUserFilterCriteria.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseUserFilterCriteria.java index 58a9cbe5687..0fa3eb01809 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseUserFilterCriteria.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseUserFilterCriteria.java @@ -8,7 +8,6 @@ public class CaseUserFilterCriteria { private boolean excludeCasesFromContacts; private Boolean includeCasesFromOtherJurisdictions = Boolean.FALSE; private boolean excludeLimitedSyncRestrictions; - private boolean restrictAccessToAssignedEntities; public boolean isExcludeCasesFromContacts() { return excludeCasesFromContacts; @@ -40,12 +39,4 @@ public CaseUserFilterCriteria excludeLimitedSyncRestrictions(boolean excludeLimi this.excludeLimitedSyncRestrictions = excludeLimitedSyncRestrictions; return this; } - - public boolean isRestrictAccessToAssignedEntities() { - return restrictAccessToAssignedEntities; - } - - public void setRestrictAccessToAssignedEntities(boolean restrictAccessToAssignedEntities) { - this.restrictAccessToAssignedEntities = restrictAccessToAssignedEntities; - } } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/common/BaseAdoService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/common/BaseAdoService.java index 1c8d252c7ae..518ea9237c9 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/common/BaseAdoService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/common/BaseAdoService.java @@ -94,8 +94,8 @@ public User getCurrentUser() { return currentUserService.getCurrentUser(); } - public boolean currentUserHasRestrictedAccessToAssignedEntities() { - return currentUserService.hasRestrictedAccessToAssignedEntities(); + public boolean isRestrictedToAssignedEntities() { + return currentUserService.isRestrictedToAssignedEntities(); } public boolean hasRight(UserRight right) { diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/common/CriteriaBuilderHelper.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/common/CriteriaBuilderHelper.java index adfcf769416..8ad0e6b776b 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/common/CriteriaBuilderHelper.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/common/CriteriaBuilderHelper.java @@ -8,11 +8,13 @@ import java.util.Optional; import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.Collectors; import java.util.stream.Stream; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.Expression; import javax.persistence.criteria.Join; +import javax.persistence.criteria.Order; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; @@ -214,4 +216,15 @@ public static Expression dateDiff(CriteriaBuilder cb, Expression date cb.function("date_part", Double.class, cb.literal("epoch"), date1), cb.function("date_part", Double.class, cb.literal("epoch"), date2))); } + + public static List orders(CriteriaBuilder cb, boolean ascending, Expression... expressions) { + return Stream.of(expressions).map(e -> ascending ? cb.asc(e) : cb.desc(e)).collect(Collectors.toList()); + } + + public interface OrderBuilder { + List build(Expression... expressions); + } + public static OrderBuilder createOrderBuilder(CriteriaBuilder cb, boolean ascending) { + return (Expression... expressions) -> Stream.of(expressions).map(e -> ascending ? cb.asc(e) : cb.desc(e)).collect(Collectors.toList()); + } } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactFacadeEjb.java index c050e6fdbb3..b307d7260c8 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactFacadeEjb.java @@ -41,6 +41,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.Resource; import javax.annotation.security.PermitAll; @@ -1148,26 +1149,33 @@ public List getContactFollowUpList( Date start = DateHelper.getStartOfDay(DateHelper.subtractDays(end, interval)); CriteriaBuilder cb = em.getCriteriaBuilder(); - CriteriaQuery cq = cb.createQuery(ContactFollowUpDto.class); + CriteriaQuery cq = cb.createQuery(Tuple.class); Root contact = cq.from(Contact.class); final ContactQueryContext contactQueryContext = new ContactQueryContext(cb, cq, contact); final ContactJoins joins = contactQueryContext.getJoins(); + List orderList = getFollowupOrderList(sortProperties, contact, joins, cb); + cq.multiselect( - contact.get(Contact.UUID), - contact.get(Contact.CHANGE_DATE), - joins.getPerson().get(Person.FIRST_NAME), - joins.getPerson().get(Person.LAST_NAME), - joins.getContactOfficer().get(User.UUID), - joins.getContactOfficer().get(User.FIRST_NAME), - joins.getContactOfficer().get(User.LAST_NAME), - contact.get(Contact.LAST_CONTACT_DATE), - contact.get(Contact.REPORT_DATE_TIME), - contact.get(Contact.FOLLOW_UP_UNTIL), - joins.getPerson().get(Person.SYMPTOM_JOURNAL_STATUS), - contact.get(Contact.DISEASE), - jurisdictionSelector(contactQueryContext)); + Stream + .concat( + Stream.of( + contact.get(Contact.UUID), + contact.get(Contact.CHANGE_DATE), + joins.getPerson().get(Person.FIRST_NAME), + joins.getPerson().get(Person.LAST_NAME), + joins.getContactOfficer().get(User.UUID), + joins.getContactOfficer().get(User.FIRST_NAME), + joins.getContactOfficer().get(User.LAST_NAME), + contact.get(Contact.LAST_CONTACT_DATE), + contact.get(Contact.REPORT_DATE_TIME), + contact.get(Contact.FOLLOW_UP_UNTIL), + joins.getPerson().get(Person.SYMPTOM_JOURNAL_STATUS), + contact.get(Contact.DISEASE), + jurisdictionSelector(contactQueryContext)), + orderList.stream().map(Order::getExpression)) + .collect(Collectors.toList())); // Only use user filter if no restricting case is specified Predicate filter = listCriteriaBuilder.buildContactFilter(contactCriteria, contactQueryContext); @@ -1177,45 +1185,9 @@ public List getContactFollowUpList( } cq.distinct(true); + cq.orderBy(orderList); - if (sortProperties != null && sortProperties.size() > 0) { - List order = new ArrayList(sortProperties.size()); - for (SortProperty sortProperty : sortProperties) { - Expression expression; - switch (sortProperty.propertyName) { - case FollowUpDto.UUID: - case ContactFollowUpDto.LAST_CONTACT_DATE: - case FollowUpDto.FOLLOW_UP_UNTIL: - expression = contact.get(sortProperty.propertyName); - break; - case FollowUpDto.REPORT_DATE: - expression = contact.get(Contact.REPORT_DATE_TIME); - break; - case FollowUpDto.SYMPTOM_JOURNAL_STATUS: - expression = joins.getPerson().get(Person.SYMPTOM_JOURNAL_STATUS); - break; - case FollowUpDto.FIRST_NAME: - expression = joins.getPerson().get(Person.FIRST_NAME); - break; - case FollowUpDto.LAST_NAME: - expression = joins.getPerson().get(Person.LAST_NAME); - break; - case ContactFollowUpDto.CONTACT_OFFICER: - expression = joins.getContactOfficer().get(User.FIRST_NAME); - order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - expression = joins.getContactOfficer().get(User.LAST_NAME); - break; - default: - throw new IllegalArgumentException(sortProperty.propertyName); - } - order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - } - cq.orderBy(order); - } else { - cq.orderBy(cb.desc(contact.get(Contact.CHANGE_DATE))); - } - - List resultList = QueryHelper.getResultList(em, cq, first, max); + List resultList = QueryHelper.getResultList(em, cq, new ContactFollowUpDtoResultTransformer(), first, max); if (!resultList.isEmpty()) { @@ -1264,6 +1236,51 @@ public List getContactFollowUpList( return resultList; } + private static List getFollowupOrderList( + List sortProperties, + Root contact, + ContactJoins joins, + CriteriaBuilder cb) { + List orderList = new ArrayList<>(); + + if (sortProperties != null && !sortProperties.isEmpty()) { + for (SortProperty sortProperty : sortProperties) { + CriteriaBuilderHelper.OrderBuilder orderBuilder = CriteriaBuilderHelper.createOrderBuilder(cb, sortProperty.ascending); + final List order; + switch (sortProperty.propertyName) { + case FollowUpDto.UUID: + case ContactFollowUpDto.LAST_CONTACT_DATE: + case FollowUpDto.FOLLOW_UP_UNTIL: + order = orderBuilder.build(contact.get(sortProperty.propertyName)); + break; + case FollowUpDto.REPORT_DATE: + order = orderBuilder.build(contact.get(Contact.REPORT_DATE_TIME)); + break; + case FollowUpDto.SYMPTOM_JOURNAL_STATUS: + order = orderBuilder.build(joins.getPerson().get(Person.SYMPTOM_JOURNAL_STATUS)); + break; + case FollowUpDto.FIRST_NAME: + order = orderBuilder.build(cb.lower(joins.getPerson().get(Person.FIRST_NAME))); + break; + case FollowUpDto.LAST_NAME: + order = orderBuilder.build(cb.lower(joins.getPerson().get(Person.LAST_NAME))); + break; + case ContactFollowUpDto.CONTACT_OFFICER: + order = orderBuilder + .build(cb.lower(joins.getContactOfficer().get(User.FIRST_NAME)), cb.lower(joins.getContactOfficer().get(User.LAST_NAME))); + break; + default: + throw new IllegalArgumentException(sortProperty.propertyName); + } + orderList.addAll(order); + } + } else { + orderList.add(cb.desc(contact.get(Contact.CHANGE_DATE))); + } + + return orderList; + } + private Expression jurisdictionSelector(ContactQueryContext qc) { return JurisdictionHelper.booleanSelector(qc.getCriteriaBuilder(), service.inJurisdictionOrOwned(qc)); } @@ -1288,8 +1305,8 @@ public List getIndexList(ContactCriteria contactCriteria, Integ List dtos = new ArrayList<>(); IterableHelper.executeBatched(indexListIds, ModelConstants.PARAMETER_LIMIT, batchedIds -> { - CriteriaQuery query = listCriteriaBuilder.buildIndexCriteria(contactCriteria, sortProperties, batchedIds); - dtos.addAll(QueryHelper.getResultList(em, query, null, null)); + CriteriaQuery cq = listCriteriaBuilder.buildIndexCriteria(contactCriteria, sortProperties, batchedIds); + dtos.addAll(QueryHelper.getResultList(em, cq, new ContactIndexDtoResultTransformer(), null, null)); }); Pseudonymizer pseudonymizer = Pseudonymizer.getDefault(userService::hasRight, I18nProperties.getCaption(Captions.inaccessibleValue)); @@ -1337,9 +1354,8 @@ public List getIndexDetailedList( List dtos = new ArrayList<>(); IterableHelper.executeBatched(indexListIds, ModelConstants.PARAMETER_LIMIT, batchedIds -> { - CriteriaQuery query = - listCriteriaBuilder.buildIndexDetailedCriteria(contactCriteria, sortProperties, batchedIds); - dtos.addAll(QueryHelper.getResultList(em, query, null, null)); + CriteriaQuery cq = listCriteriaBuilder.buildIndexDetailedCriteria(contactCriteria, sortProperties, batchedIds); + dtos.addAll(QueryHelper.getResultList(em, cq, new ContactIndexDetailedDtoResultTransformer(), null, null)); }); if (userService.hasRight(UserRight.EVENT_VIEW)) { diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactFollowUpDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactFollowUpDtoResultTransformer.java new file mode 100644 index 00000000000..960f8363620 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactFollowUpDtoResultTransformer.java @@ -0,0 +1,50 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.backend.contact; + +import java.util.Date; +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.contact.ContactFollowUpDto; +import de.symeda.sormas.api.person.SymptomJournalStatus; + +public class ContactFollowUpDtoResultTransformer implements ResultTransformer { + + private static final long serialVersionUID = -3235008141852193636L; + + @Override + public ContactFollowUpDto transformTuple(Object[] tuple, String[] aliases) { + int index = -1; + + //@formatter:off + return new ContactFollowUpDto( + (String) tuple[++index], (Date) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (Date) tuple[++index], (Date) tuple[++index], + (Date) tuple[++index], (SymptomJournalStatus) tuple[++index], (Disease) tuple[++index], + (Boolean) tuple[++index] + ); + //@formatter:on + } + + @Override + @SuppressWarnings("rawtypes") + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactIndexDetailedDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactIndexDetailedDtoResultTransformer.java new file mode 100644 index 00000000000..0a862cfbbc5 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactIndexDetailedDtoResultTransformer.java @@ -0,0 +1,69 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.backend.contact; + +import java.util.Date; +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.caze.CaseClassification; +import de.symeda.sormas.api.caze.VaccinationStatus; +import de.symeda.sormas.api.common.DeletionReason; +import de.symeda.sormas.api.contact.ContactCategory; +import de.symeda.sormas.api.contact.ContactClassification; +import de.symeda.sormas.api.contact.ContactIndexDetailedDto; +import de.symeda.sormas.api.contact.ContactProximity; +import de.symeda.sormas.api.contact.ContactRelation; +import de.symeda.sormas.api.contact.ContactStatus; +import de.symeda.sormas.api.contact.FollowUpStatus; +import de.symeda.sormas.api.person.ApproximateAgeType; +import de.symeda.sormas.api.person.Sex; +import de.symeda.sormas.api.person.SymptomJournalStatus; + +public class ContactIndexDetailedDtoResultTransformer implements ResultTransformer { + + private static final long serialVersionUID = -6779500917075910677L; + + @Override + public ContactIndexDetailedDto transformTuple(Object[] tuple, String[] aliases) { + int index = -1; + + //@formatter:off + return new ContactIndexDetailedDto( + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (Disease) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (Date) tuple[++index], (ContactCategory) tuple[++index], + (ContactProximity) tuple[++index], (ContactClassification) tuple[++index], (ContactStatus) tuple[++index], (Float) tuple[++index], + (FollowUpStatus) tuple[++index], (Date) tuple[++index], (SymptomJournalStatus) tuple[++index], (VaccinationStatus) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (Date) tuple[++index], + (CaseClassification) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (Date) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (DeletionReason) tuple[++index], (String) tuple[++index], (Boolean) tuple[++index], (Boolean) tuple[++index], + (Sex) tuple[++index], (Integer) tuple[++index], (ApproximateAgeType) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (ContactRelation) tuple[++index], (Integer) tuple[++index] + ); + //@formatter:on + } + + @Override + @SuppressWarnings("rawtypes") + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactIndexDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactIndexDtoResultTransformer.java new file mode 100644 index 00000000000..7b92ede69f8 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactIndexDtoResultTransformer.java @@ -0,0 +1,62 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.backend.contact; + +import java.util.Date; +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.caze.CaseClassification; +import de.symeda.sormas.api.caze.VaccinationStatus; +import de.symeda.sormas.api.common.DeletionReason; +import de.symeda.sormas.api.contact.ContactCategory; +import de.symeda.sormas.api.contact.ContactClassification; +import de.symeda.sormas.api.contact.ContactIndexDto; +import de.symeda.sormas.api.contact.ContactProximity; +import de.symeda.sormas.api.contact.ContactStatus; +import de.symeda.sormas.api.contact.FollowUpStatus; +import de.symeda.sormas.api.person.SymptomJournalStatus; + +public class ContactIndexDtoResultTransformer implements ResultTransformer { + + private static final long serialVersionUID = 5931775440959375461L; + + @Override + public ContactIndexDto transformTuple(Object[] tuple, String[] aliases) { + int index = -1; + //@formatter:off + return new ContactIndexDto( + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (Disease) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (Date) tuple[++index], (ContactCategory) tuple[++index], + (ContactProximity) tuple[++index], (ContactClassification) tuple[++index], (ContactStatus) tuple[++index], (Float) tuple[++index], + (FollowUpStatus) tuple[++index], (Date) tuple[++index], (SymptomJournalStatus) tuple[++index], (VaccinationStatus) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (Date) tuple[++index], + (CaseClassification) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (Date) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (DeletionReason) tuple[++index], (String) tuple[++index], (Boolean) tuple[++index], (Boolean) tuple[++index], + (Integer) tuple[++index] + ); + //@formatter:on + } + + @SuppressWarnings("rawtypes") + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactJurisdictionPredicateValidator.java index c6fd995a537..579dc89aa2d 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactJurisdictionPredicateValidator.java @@ -77,13 +77,27 @@ public static ContactJurisdictionPredicateValidator of(ContactQueryContext qc, P @Override public Predicate isRootInJurisdictionOrOwned() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + + return cb.or(reportedByCurrentUser, inJurisdiction()); + } + + private Predicate getReportedByCurrentUser() { final Predicate reportedByCurrentUser = cb.and( cb.isNotNull(joins.getRoot().get(Contact.REPORTING_USER)), user != null ? cb.equal(joins.getRoot().get(Contact.REPORTING_USER).get(User.ID), user.getId()) : cb.equal(joins.getRoot().get(Contact.REPORTING_USER).get(User.ID), userPath.get(User.ID))); + return reportedByCurrentUser; + } - return cb.or(reportedByCurrentUser, inJurisdiction()); + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + final Predicate restrictedAccess = user != null + ? cb.equal(joins.getRoot().get(Contact.CONTACT_OFFICER).get(User.ID), user.getId()) + : cb.equal(joins.getRoot().get(Contact.CONTACT_OFFICER).get(User.ID), userPath.get(User.ID)); + return cb.or(reportedByCurrentUser, restrictedAccess); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactListCriteriaBuilder.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactListCriteriaBuilder.java index 80940bed806..2f0b57c8658 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactListCriteriaBuilder.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactListCriteriaBuilder.java @@ -58,17 +58,14 @@ public class ContactListCriteriaBuilder { @EJB private ContactService contactService; - public CriteriaQuery buildIndexCriteria(ContactCriteria contactCriteria, List sortProperties, List ids) { - return buildIndexCriteria(ContactIndexDto.class, this::getContactIndexSelections, contactCriteria, this::getIndexOrders, sortProperties, ids); + public CriteriaQuery buildIndexCriteria(ContactCriteria contactCriteria, List sortProperties, List ids) { + return buildIndexCriteria(Tuple.class, this::getContactIndexSelections, contactCriteria, this::getIndexOrders, sortProperties, ids); } - public CriteriaQuery buildIndexDetailedCriteria( - ContactCriteria contactCriteria, - List sortProperties, - List ids) { + public CriteriaQuery buildIndexDetailedCriteria(ContactCriteria contactCriteria, List sortProperties, List ids) { return buildIndexCriteria( - ContactIndexDetailedDto.class, + Tuple.class, this::getContactIndexDetailedSelections, contactCriteria, this::getIndexDetailOrders, @@ -93,7 +90,7 @@ public CriteriaQuery buildIndexDetailedCriteriaPrefetchIds(ContactCriteri public List> getContactIndexSelections(Root contact, ContactQueryContext contactQueryContext) { - ContactJoins joins = (ContactJoins) contactQueryContext.getJoins(); + ContactJoins joins = contactQueryContext.getJoins(); CriteriaBuilder cb = contactQueryContext.getCriteriaBuilder(); return Arrays.asList( @@ -142,7 +139,7 @@ public List> getContactIndexSelections(Root contact, Conta public List> getMergeContactIndexSelections(Root contact, ContactQueryContext contactQueryContext) { - ContactJoins joins = (ContactJoins) contactQueryContext.getJoins(); + ContactJoins joins = contactQueryContext.getJoins(); CriteriaBuilder cb = contactQueryContext.getCriteriaBuilder(); return Arrays.asList( @@ -193,29 +190,33 @@ private List> getIndexOrders(SortProperty sortProperty, Root> getIndexOrders(SortProperty sortProperty, Root> getContactIndexDetailedSelections(Root contact, ContactQueryContext contactQueryContext) { - final ContactJoins joins = (ContactJoins) contactQueryContext.getJoins(); + final ContactJoins joins = contactQueryContext.getJoins(); Join phone = joins.getPersonJoins().getPhone(); CriteriaBuilder cb = contactQueryContext.getCriteriaBuilder(); @@ -263,15 +264,15 @@ private List> getIndexDetailOrders(SortProperty sortProperty, Root case ContactIndexDetailedDto.PHONE: return Collections.singletonList(joins.getPersonJoins().getPhone().get(PersonContactDetail.CONTACT_INFORMATION)); case ContactIndexDetailedDto.DISTRICT_NAME: - return Collections.singletonList(joins.getDistrict().get(District.NAME)); + return Collections.singletonList(cb.lower(joins.getDistrict().get(District.NAME))); case ContactIndexDetailedDto.CITY: case ContactIndexDetailedDto.STREET: case ContactIndexDetailedDto.HOUSE_NUMBER: case ContactIndexDetailedDto.ADDITIONAL_INFORMATION: case ContactIndexDetailedDto.POSTAL_CODE: - return Collections.singletonList(joins.getAddress().get(sortProperty.propertyName)); + return Collections.singletonList(cb.lower(joins.getAddress().get(sortProperty.propertyName))); case ContactIndexDetailedDto.REPORTING_USER: - return Arrays.asList(joins.getReportingUser().get(User.FIRST_NAME), joins.getReportingUser().get(User.LAST_NAME)); + return Arrays.asList(cb.lower(joins.getReportingUser().get(User.FIRST_NAME)), cb.lower(joins.getReportingUser().get(User.LAST_NAME))); case ContactIndexDetailedDto.RELATION_TO_CASE: return Collections.singletonList(contact.get(Contact.RELATION_TO_CASE)); default: @@ -300,15 +301,15 @@ private CriteriaQuery buildIndexCriteria( Expression latestChangedDateFunction = cb .function(ExtendedPostgreSQL94Dialect.GREATEST, Date.class, contact.get(Contact.CHANGE_DATE), joins.getPerson().get(Person.CHANGE_DATE)); - List> selectionListPrefetchIds = new ArrayList<>(); + List> orderBySelections = new ArrayList<>(); if (CollectionUtils.isEmpty(sortProperties)) { - selectionListPrefetchIds.add(latestChangedDateFunction); + orderBySelections.add(latestChangedDateFunction); cq.orderBy(cb.desc(latestChangedDateFunction)); } else { List order = new ArrayList<>(sortProperties.size()); for (SortProperty sortProperty : sortProperties) { List> expressions = orderExpressionProvider.forProperty(sortProperty, contact, joins, cb); - selectionListPrefetchIds.addAll(expressions); + orderBySelections.addAll(expressions); order.addAll(expressions.stream().map(e -> sortProperty.ascending ? cb.asc(e) : cb.desc(e)).collect(Collectors.toList())); } cq.orderBy(order); @@ -316,14 +317,15 @@ private CriteriaQuery buildIndexCriteria( if (prefetchIds) { selections.add(contact.get(AbstractDomainObject.ID)); - selections.addAll(selectionListPrefetchIds); } else { selections.addAll(selectionProvider.apply(contact, contactQueryContext)); selections.add(cb.size(contact.get(Contact.VISITS))); // This is needed in selection because of the combination of distinct and orderBy clauses - every operator in the orderBy has to be part of the select IF distinct is used - selections.add(latestChangedDateFunction); } + // include order by in the select + selections.addAll(orderBySelections); + Predicate filter = buildContactFilter(contactCriteria, contactQueryContext); if (!prefetchIds) { diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactService.java index eca0c747ad0..b2aa0d1df70 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactService.java @@ -36,6 +36,7 @@ import javax.ejb.EJB; import javax.ejb.LocalBean; import javax.ejb.Stateless; +import javax.persistence.Tuple; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; @@ -140,6 +141,7 @@ import de.symeda.sormas.backend.util.IterableHelper; import de.symeda.sormas.backend.util.JurisdictionHelper; import de.symeda.sormas.backend.util.ModelConstants; +import de.symeda.sormas.backend.util.QueryHelper; import de.symeda.sormas.backend.visit.Visit; import de.symeda.sormas.backend.visit.VisitFacadeEjb; import de.symeda.sormas.backend.visit.VisitService; @@ -1080,7 +1082,8 @@ public Predicate createUserFilterWithoutCase(ContactQueryContext qc, ContactCrit Predicate filter = null; - if (currentUserHasRestrictedAccessToAssignedEntities()) { + final boolean restrictedToAssignedEntities = isRestrictedToAssignedEntities(); + if (restrictedToAssignedEntities) { filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(contactRoot.get(Contact.CONTACT_OFFICER).get(User.ID), getCurrentUser().getId())); } @@ -1096,7 +1099,7 @@ public Predicate createUserFilterWithoutCase(ContactQueryContext qc, ContactCrit filter = cb.or(filter, cb.equal(contactRoot.get(Contact.CONTACT_OFFICER), currentUser)); } - if (!currentUserHasRestrictedAccessToAssignedEntities()) { + if (!restrictedToAssignedEntities) { switch (jurisdictionLevel) { case REGION: final Region region = currentUser.getRegion(); @@ -1133,8 +1136,13 @@ public Predicate createUserFilterWithoutCase(ContactQueryContext qc, ContactCrit filter = CriteriaBuilderHelper.and( cb, filter, - CriteriaBuilderHelper - .limitedDiseasePredicate(cb, currentUser, contactRoot.get(Contact.DISEASE), cb.isNull(contactRoot.get(Contact.DISEASE)))); + CriteriaBuilderHelper.limitedDiseasePredicate( + cb, + currentUser, + contactRoot.get(Contact.DISEASE), + cb.or( + cb.isNull(contactRoot.get(Contact.DISEASE)), + cb.equal(contactRoot.get(Contact.REPORTING_USER).get(User.ID), currentUser.getId())))); if ((contactCriteria == null || !contactCriteria.isExcludeLimitedSyncRestrictions()) && featureConfigurationFacade @@ -1844,10 +1852,6 @@ public EditPermissionType getEditPermissionType(Contact contact) { return EditPermissionType.OUTSIDE_JURISDICTION; } - if (currentUserHasRestrictedAccessToAssignedEntities() && !DataHelper.equal(contact.getContactOfficer(), (getCurrentUser()))) { - return EditPermissionType.REFUSED; - } - if (sormasToSormasShareInfoService.isContactOwnershipHandedOver(contact) || (contact.getSormasToSormasOriginInfo() != null && !contact.getSormasToSormasOriginInfo().isOwnershipHandedOver())) { return EditPermissionType.WITHOUT_OWNERSHIP; @@ -1942,7 +1946,7 @@ public List getEntriesList(Long personId, Integer first, In } final CriteriaBuilder cb = em.getCriteriaBuilder(); - final CriteriaQuery cq = cb.createQuery(Object[].class); + final CriteriaQuery cq = cb.createQuery(Tuple.class); final Root contact = cq.from(Contact.class); ContactQueryContext contactQueryContext = new ContactQueryContext(cb, cq, contact); @@ -1966,9 +1970,7 @@ public List getEntriesList(Long personId, Integer first, In cq.distinct(true); - return createQuery(cq, first, max).unwrap(org.hibernate.query.Query.class) - .setResultTransformer(new ContactListEntryDtoResultTransformer()) - .getResultList(); + return QueryHelper.getResultList(em, cq, new ContactListEntryDtoResultTransformer(), first, max); } public long getContactCount(CaseReferenceDto caze) { diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumCacheInfo.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumCacheInfo.java new file mode 100644 index 00000000000..3c289366151 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumCacheInfo.java @@ -0,0 +1,37 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2023 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.backend.customizableenum; + +import java.util.Map; + +public class CustomizableEnumCacheInfo { + + private final Map properties; + private final boolean active; + + public CustomizableEnumCacheInfo(Map properties, boolean active) { + this.properties = properties; + this.active = active; + } + + public Map getProperties() { + return properties; + } + + public boolean isActive() { + return active; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumFacadeEjb.java index 0eccc6f0049..34fc2b3dfa9 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumFacadeEjb.java @@ -87,10 +87,10 @@ public class CustomizableEnumFacadeEjb */ private final EnumMap> enumValues = new EnumMap<>(CustomizableEnumType.class); /** - * Maps a customizable enum type to a map with all enum values of this type as its keys and the properties defined for these - * enum values as its values. + * Maps a customizable enum type to a map with all enum values of this type as its keys and info, e.g. properties and active status, + * defined for these enum values as its values. */ - private final EnumMap>> enumProperties = new EnumMap<>(CustomizableEnumType.class); + private final EnumMap> enumInfo = new EnumMap<>(CustomizableEnumType.class); /** * Maps a customizable enum type (defined by its class) to a map which in turn maps all languages for which translations exist to * the possible enum values of this type, which then finally map to their translated captions. @@ -136,6 +136,7 @@ protected CustomizableEnumValue fillOrBuildEntity(CustomizableEnumValueDto sourc target.setDescriptionTranslations(source.getDescriptionTranslations()); target.setProperties(source.getProperties()); target.setDefaultValue(source.isDefaultValue()); + target.setActive(source.isActive()); return target; } @@ -222,9 +223,11 @@ public List getIndexList( switch (sortProperty.propertyName) { case CustomizableEnumValue.DATA_TYPE: case CustomizableEnumValue.VALUE: - case CustomizableEnumValue.CAPTION: expression = root.get(sortProperty.propertyName); break; + case CustomizableEnumValue.CAPTION: + expression = cb.lower(root.get(sortProperty.propertyName)); + break; default: throw new IllegalArgumentException(sortProperty.propertyName); } @@ -326,7 +329,8 @@ public List getEnumValues(CustomizableEnumType t diseaseValuesStream = enumValuesByDisease.get(enumClass).get(Optional.empty()).stream(); } - return diseaseValuesStream.map(value -> buildCustomizableEnum(type, value, language, enumClass)) + return diseaseValuesStream.filter(value -> getEnumInfo(type, value).isActive()) + .map(value -> buildCustomizableEnum(type, value, language, enumClass)) .sorted(Comparator.comparing(CustomizableEnum::getCaption)) .collect(Collectors.toList()); } @@ -342,7 +346,7 @@ private T buildCustomizableEnum(CustomizableEnumTyp T enumValue = enumClass.getDeclaredConstructor().newInstance(); enumValue.setValue(value); enumValue.setCaption(enumValuesByLanguage.get(enumClass).get(language).get(value)); - enumValue.setProperties(enumProperties.get(type).get(value)); + enumValue.setProperties(getEnumInfo(type, value).getProperties()); return enumValue; } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { throw new RuntimeException(e); @@ -416,9 +420,9 @@ private synchronized void fillDiseaseCache( public void loadData() { enumValueEntities.clear(); enumValues.clear(); + enumInfo.clear(); enumValuesByLanguage.clear(); enumValuesByDisease.clear(); - enumProperties.clear(); for (CustomizableEnumType enumType : CustomizableEnumType.values()) { enumValueEntities.putIfAbsent(enumType, new ArrayList<>()); @@ -435,8 +439,9 @@ public void loadData() { "Enum value " + value + " for customizable enum type " + enumType.toString() + " is not unique"); } enumValues.get(enumType).add(value); - enumProperties.putIfAbsent(enumType, new HashMap<>()); - enumProperties.get(enumType).putIfAbsent(customizableEnumValue.getValue(), customizableEnumValue.getProperties()); + enumInfo.putIfAbsent(enumType, new HashMap<>()); + enumInfo.get(enumType) + .putIfAbsent(value, new CustomizableEnumCacheInfo(customizableEnumValue.getProperties(), customizableEnumValue.isActive())); } for (CustomizableEnumType enumType : CustomizableEnumType.values()) { @@ -450,6 +455,10 @@ public void loadData() { } } + private CustomizableEnumCacheInfo getEnumInfo(CustomizableEnumType type, String value) { + return enumInfo.get(type).get(value); + } + public CustomizableEnumValueDto toDto(CustomizableEnumValue source) { if (source == null) { @@ -468,6 +477,7 @@ public CustomizableEnumValueDto toDto(CustomizableEnumValue source) { target.setDescriptionTranslations(source.getDescriptionTranslations()); target.setProperties(source.getProperties()); target.setDefaultValue(source.isDefaultValue()); + target.setActive(source.isActive()); return target; } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumValue.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumValue.java index 8ba71f9cb0b..2097ab0e235 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumValue.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumValue.java @@ -52,6 +52,7 @@ public class CustomizableEnumValue extends AbstractDomainObject { public static final String VALUE = "value"; public static final String CAPTION = "caption"; public static final String DISEASES = "diseases"; + public static final String ACTIVE = "active"; private CustomizableEnumType dataType; private String value; @@ -66,6 +67,7 @@ public class CustomizableEnumValue extends AbstractDomainObject { * or translations because they can be translated via properties files. */ private boolean defaultValue; + private boolean active; @Enumerated(EnumType.STRING) @Column(nullable = false) @@ -152,4 +154,13 @@ public boolean isDefaultValue() { public void setDefaultValue(boolean defaultValue) { this.defaultValue = defaultValue; } + + @Column + public boolean isActive() { + return active; + } + + public void setActive(boolean active) { + this.active = active; + } } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumValueService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumValueService.java index 1b3740d40ac..f5e5bff9aad 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumValueService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumValueService.java @@ -44,7 +44,7 @@ public Predicate createUserFilter(CriteriaBuilder cb, CriteriaQuery cq, From from) { - Predicate filter = null; + Predicate filter = cb.equal(from.get(CustomizableEnumValue.ACTIVE), criteria.getActive()); if (criteria.getFreeTextFilter() != null) { String[] textFilters = criteria.getFreeTextFilter().split("\\s+"); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/EnvironmentJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/EnvironmentJurisdictionPredicateValidator.java index af2996049e1..df5418203d1 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/EnvironmentJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/EnvironmentJurisdictionPredicateValidator.java @@ -51,14 +51,26 @@ public static EnvironmentJurisdictionPredicateValidator of(EnvironmentQueryConte @Override public Predicate isRootInJurisdictionOrOwned() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + return cb.or(reportedByCurrentUser, isRootInJurisdiction()); + } + private Predicate getReportedByCurrentUser() { final Predicate reportedByCurrentUser = cb.and( cb.isNotNull(joins.getRoot().get(Environment.REPORTING_USER)), user != null ? cb.equal(joins.getRoot().get(Environment.REPORTING_USER).get(User.ID), user.getId()) : cb.equal(joins.getRoot().get(Environment.REPORTING_USER).get(User.ID), userPath.get(User.ID))); + return reportedByCurrentUser; + } - return cb.or(reportedByCurrentUser, isRootInJurisdiction()); + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + final Predicate restrictedAccess = user != null + ? cb.equal(joins.getRoot().get(Environment.RESPONSIBLE_USER).get(User.ID), user.getId()) + : cb.equal(joins.getRoot().get(Environment.RESPONSIBLE_USER).get(User.ID), userPath.get(User.ID)); + return cb.or(reportedByCurrentUser, restrictedAccess); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/EnvironmentService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/EnvironmentService.java index 199498a56bf..1136e2dc7c8 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/EnvironmentService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/EnvironmentService.java @@ -90,7 +90,7 @@ public Predicate createUserFilter(EnvironmentQueryContext queryContext) { final EnvironmentJoins environmentJoins = queryContext.getJoins(); final From environmentJoin = queryContext.getRoot(); - if (currentUserHasRestrictedAccessToAssignedEntities()) { + if (isRestrictedToAssignedEntities()) { filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(environmentJoin.get(Environment.RESPONSIBLE_USER).get(User.ID), currentUser.getId())); } else { @@ -403,10 +403,6 @@ public EditPermissionType getEditPermissionType(Environment environment) { return EditPermissionType.OUTSIDE_JURISDICTION; } - if (currentUserHasRestrictedAccessToAssignedEntities() && !DataHelper.equal(environment.getResponsibleUser(), getCurrentUser())) { - return EditPermissionType.REFUSED; - } - return super.getEditPermissionType(environment); } @@ -442,4 +438,10 @@ public void delete(Environment environment, DeletionDetails deletionDetails) { environment.getEnvironmentSamples().forEach(s -> environmentSampleService.delete(s, deletionDetails)); super.delete(environment, deletionDetails); } + + @Override + public void restore(Environment environment) { + environment.getEnvironmentSamples().forEach(sample -> environmentSampleService.restore(sample)); + super.restore(environment); + } } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjb.java index a53a5722469..7245450f90a 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjb.java @@ -31,6 +31,7 @@ import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; +import javax.persistence.criteria.From; import javax.persistence.criteria.Join; import javax.persistence.criteria.Order; import javax.persistence.criteria.Path; @@ -317,40 +318,43 @@ private List> sortBy(List sortProperties, Environment CriteriaBuilder cb = queryContext.getCriteriaBuilder(); CriteriaQuery cq = queryContext.getQuery(); + EnvironmentSampleJoins joins = queryContext.getJoins(); + From sample = queryContext.getRoot(); + if (sortProperties != null && !sortProperties.isEmpty()) { List order = new ArrayList<>(sortProperties.size()); for (SortProperty sortProperty : sortProperties) { Expression expression; - /* - * joins.getLocationJoins().getDistrict().get(District.NAME), - * joins.getLaboratory().get(Facility.NAME), - */ - switch (sortProperty.propertyName) { case EnvironmentSampleIndexDto.UUID: - case EnvironmentSampleIndexDto.FIELD_SAMPLE_ID: case EnvironmentSampleIndexDto.SAMPLE_DATE_TIME: case EnvironmentSampleIndexDto.DISPATCHED: case EnvironmentSampleIndexDto.DISPATCH_DATE: case EnvironmentSampleIndexDto.RECEIVED: case EnvironmentSampleIndexDto.SAMPLE_MATERIAL: - expression = queryContext.getRoot().get(sortProperty.propertyName); + expression = sample.get(sortProperty.propertyName); + break; + case EnvironmentSampleIndexDto.FIELD_SAMPLE_ID: + expression = cb.lower(sample.get(sortProperty.propertyName)); break; case EnvironmentSampleIndexDto.ENVIRONMENT: - expression = queryContext.getJoins().getEnvironment().get(Environment.ENVIRONMENT_NAME); + expression = cb.lower(joins.getEnvironment().get(Environment.ENVIRONMENT_NAME)); break; case EnvironmentSampleIndexDto.LOCATION: - Join location = queryContext.getJoins().getLocation(); - expression = cb.concat( - cb.concat(cb.concat(location.get(Location.STREET), location.get(Location.HOUSE_NUMBER)), location.get(Location.POSTAL_CODE)), - location.get(Location.CITY)); + Join location = joins.getLocation(); + expression = cb.lower( + cb.concat( + cb.concat( + cb.concat(location.get(Location.STREET), location.get(Location.HOUSE_NUMBER)), + location.get(Location.POSTAL_CODE)), + location.get(Location.CITY))); break; case EnvironmentSampleIndexDto.DISTRICT: - expression = queryContext.getJoins().getLocationJoins().getDistrict().get(District.NAME); + expression = cb.lower(joins.getLocationJoins().getDistrict().get(District.NAME)); break; case EnvironmentSampleIndexDto.LABORATORY: - expression = queryContext.getJoins().getLaboratory().get(Facility.NAME); + expression = cb.lower(joins.getLaboratory().get(Facility.NAME)); break; default: throw new IllegalArgumentException(sortProperty.propertyName); @@ -360,7 +364,7 @@ private List> sortBy(List sortProperties, Environment } cq.orderBy(order); } else { - Path changeDate = queryContext.getRoot().get(EnvironmentSample.CHANGE_DATE); + Path changeDate = sample.get(EnvironmentSample.CHANGE_DATE); cq.orderBy(cb.desc(changeDate)); selections.add(changeDate); } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleJurisdictionValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleJurisdictionValidator.java index 5ca583b4a31..83f0fe4497b 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleJurisdictionValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleJurisdictionValidator.java @@ -46,17 +46,6 @@ public static EnvironmentSampleJurisdictionValidator of(EnvironmentSampleQueryCo return new EnvironmentSampleJurisdictionValidator(qc.getCriteriaBuilder(), user, qc.getJoins(), null); } - public Predicate isRootInJurisdictionOrOwned(boolean currentHasUserRestrictedAccess) { - if (currentHasUserRestrictedAccess) { - final Predicate reportedByCurrentUser = getReportedByCurrentUserPredicate(); - final Predicate restrictedAccess = - cb.equal(joins.getEnvironment().get(Environment.RESPONSIBLE_USER).get(User.ID), user.getChangeUser().getId()); - return cb.or(reportedByCurrentUser, restrictedAccess); - } else { - return isRootInJurisdictionOrOwned(); - } - } - private Predicate getReportedByCurrentUserPredicate() { return cb.and( cb.isNotNull(joins.getRoot().get(EnvironmentSample.REPORTING_USER)), @@ -71,6 +60,15 @@ public Predicate isRootInJurisdictionOrOwned() { return cb.or(reportedByCurrentUser, isRootInJurisdiction()); } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + final Predicate reportedByCurrentUser = getReportedByCurrentUserPredicate(); + final Predicate restrictedAccess = user != null + ? cb.equal(joins.getEnvironment().get(Environment.RESPONSIBLE_USER).get(User.ID), user.getId()) + : cb.equal(joins.getEnvironment().get(Environment.RESPONSIBLE_USER).get(User.ID), userPath.get(User.ID)); + return cb.or(reportedByCurrentUser, restrictedAccess); + } + @Override protected Predicate whenNotAllowed() { return cb.disjunction(); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleService.java index d1793c97732..35ac3d17963 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleService.java @@ -30,6 +30,7 @@ import de.symeda.sormas.api.EditPermissionType; import de.symeda.sormas.api.EntityRelevanceStatus; import de.symeda.sormas.api.common.DeletableEntityType; +import de.symeda.sormas.api.common.DeletionDetails; import de.symeda.sormas.api.environment.environmentsample.EnvironmentSampleCriteria; import de.symeda.sormas.api.sample.PathogenTestDto; import de.symeda.sormas.api.utils.DataHelper; @@ -40,6 +41,8 @@ import de.symeda.sormas.backend.infrastructure.district.District; import de.symeda.sormas.backend.infrastructure.facility.Facility; import de.symeda.sormas.backend.infrastructure.region.Region; +import de.symeda.sormas.backend.sample.PathogenTest; +import de.symeda.sormas.backend.sample.PathogenTestService; import de.symeda.sormas.backend.user.UserService; @Stateless @@ -48,6 +51,8 @@ public class EnvironmentSampleService extends AbstractDeletableAdoService cq, From from) { return EnvironmentSampleJurisdictionValidator .of(new EnvironmentSampleQueryContext(cb, cq, from, new EnvironmentSampleJoins(from)), userService.getCurrentUser()) - .isRootInJurisdictionOrOwned(currentUserHasRestrictedAccessToAssignedEntities()); + .inJurisdictionOrOwned(); + } + + @Override + public void delete(EnvironmentSample sample, DeletionDetails deletionDetails) { + + // Mark all pathogen tests of this sample as deleted + for (PathogenTest pathogenTest : sample.getPathogenTests()) { + pathogenTestService.delete(pathogenTest, deletionDetails); + } + + super.delete(sample, deletionDetails); + } + + @Override + public void restore(EnvironmentSample sample) { + for (PathogenTest pathogenTest : sample.getPathogenTests()) { + pathogenTestService.restore(pathogenTest); + } + super.restore(sample); } } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventFacadeEjb.java index d16a61c0554..187e54add85 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventFacadeEjb.java @@ -19,6 +19,7 @@ import java.sql.Timestamp; import java.time.LocalDate; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; @@ -44,7 +45,6 @@ import javax.persistence.Tuple; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Expression; import javax.persistence.criteria.Join; import javax.persistence.criteria.JoinType; import javax.persistence.criteria.Order; @@ -469,7 +469,7 @@ public List getIndexList(EventCriteria eventCriteria, Integer fir IterableHelper.executeBatched(indexListIds, ModelConstants.PARAMETER_LIMIT, batchedIds -> { - CriteriaQuery cq = cb.createQuery(EventIndexDto.class); + CriteriaQuery cq = cb.createQuery(Tuple.class); Root event = cq.from(Event.class); EventQueryContext eventQueryContext = new EventQueryContext(cb, cq, event); @@ -483,74 +483,60 @@ public List getIndexList(EventCriteria eventCriteria, Integer fir Join reportingUser = eventJoins.getReportingUser(); Join responsibleUser = eventJoins.getResponsibleUser(); - cq.multiselect( - event.get(Event.ID), - event.get(Event.UUID), - event.get(Event.EXTERNAL_ID), - event.get(Event.EXTERNAL_TOKEN), - event.get(Event.INTERNAL_TOKEN), - event.get(Event.EVENT_STATUS), - event.get(Event.RISK_LEVEL), - event.get(Event.SPECIFIC_RISK), - event.get(Event.EVENT_INVESTIGATION_STATUS), - event.get(Event.EVENT_MANAGEMENT_STATUS), - event.get(Event.DISEASE), - event.get(Event.DISEASE_VARIANT), - event.get(Event.DISEASE_DETAILS), - event.get(Event.START_DATE), - event.get(Event.END_DATE), - event.get(Event.EVOLUTION_DATE), - event.get(Event.EVENT_TITLE), - region.get(Region.UUID), - region.get(Region.NAME), - district.get(District.UUID), - district.get(District.NAME), - community.get(Community.UUID), - community.get(Community.NAME), - location.get(Location.CITY), - location.get(Location.STREET), - location.get(Location.HOUSE_NUMBER), - location.get(Location.ADDITIONAL_INFORMATION), - event.get(Event.SRC_TYPE), - event.get(Event.SRC_FIRST_NAME), - event.get(Event.SRC_LAST_NAME), - event.get(Event.SRC_TEL_NO), - event.get(Event.SRC_MEDIA_WEBSITE), - event.get(Event.SRC_MEDIA_NAME), - event.get(Event.REPORT_DATE_TIME), - reportingUser.get(User.UUID), - reportingUser.get(User.FIRST_NAME), - reportingUser.get(User.LAST_NAME), - responsibleUser.get(User.UUID), - responsibleUser.get(User.FIRST_NAME), - responsibleUser.get(User.LAST_NAME), - JurisdictionHelper.booleanSelector(cb, service.inJurisdictionOrOwned(eventQueryContext)), - event.get(Event.CHANGE_DATE), - event.get(Event.EVENT_IDENTIFICATION_SOURCE), - event.get(Event.DELETION_REASON), - event.get(Event.OTHER_DELETION_REASON)); - - Predicate filter = event.get(Event.ID).in(batchedIds); - - if (eventCriteria != null) { - if (eventCriteria.getUserFilterIncluded()) { - EventUserFilterCriteria eventUserFilterCriteria = new EventUserFilterCriteria(); - eventUserFilterCriteria.includeUserCaseAndEventParticipantFilter(true); - filter = service.createUserFilter(eventQueryContext, eventUserFilterCriteria); - } - - Predicate criteriaFilter = service.buildCriteriaFilter(eventCriteria, eventQueryContext); - filter = CriteriaBuilderHelper.and(cb, filter, criteriaFilter); - } - - if (filter != null) { - cq.where(filter); - } - - sortBy(sortProperties, eventQueryContext); + List> selection = new ArrayList<>( + Arrays.asList( + event.get(Event.ID), + event.get(Event.UUID), + event.get(Event.EXTERNAL_ID), + event.get(Event.EXTERNAL_TOKEN), + event.get(Event.INTERNAL_TOKEN), + event.get(Event.EVENT_STATUS), + event.get(Event.RISK_LEVEL), + event.get(Event.SPECIFIC_RISK), + event.get(Event.EVENT_INVESTIGATION_STATUS), + event.get(Event.EVENT_MANAGEMENT_STATUS), + event.get(Event.DISEASE), + event.get(Event.DISEASE_VARIANT), + event.get(Event.DISEASE_DETAILS), + event.get(Event.START_DATE), + event.get(Event.END_DATE), + event.get(Event.EVOLUTION_DATE), + event.get(Event.EVENT_TITLE), + region.get(Region.UUID), + region.get(Region.NAME), + district.get(District.UUID), + district.get(District.NAME), + community.get(Community.UUID), + community.get(Community.NAME), + location.get(Location.CITY), + location.get(Location.STREET), + location.get(Location.HOUSE_NUMBER), + location.get(Location.ADDITIONAL_INFORMATION), + event.get(Event.SRC_TYPE), + event.get(Event.SRC_FIRST_NAME), + event.get(Event.SRC_LAST_NAME), + event.get(Event.SRC_TEL_NO), + event.get(Event.SRC_MEDIA_WEBSITE), + event.get(Event.SRC_MEDIA_NAME), + event.get(Event.REPORT_DATE_TIME), + reportingUser.get(User.UUID), + reportingUser.get(User.FIRST_NAME), + reportingUser.get(User.LAST_NAME), + responsibleUser.get(User.UUID), + responsibleUser.get(User.FIRST_NAME), + responsibleUser.get(User.LAST_NAME), + JurisdictionHelper.booleanSelector(cb, service.inJurisdictionOrOwned(eventQueryContext)), + event.get(Event.EVENT_IDENTIFICATION_SOURCE), + event.get(Event.DELETION_REASON), + event.get(Event.OTHER_DELETION_REASON))); + + selection.addAll(sortBy(sortProperties, eventQueryContext)); + + cq.multiselect(selection); + cq.where(event.get(Event.ID).in(batchedIds)); cq.distinct(true); - indexList.addAll(QueryHelper.getResultList(em, cq, null, null)); + indexList.addAll(QueryHelper.getResultList(em, cq, new EventIndexDtoResultTransformer(), null, null)); }); Map participantCounts = new HashMap<>(); @@ -746,12 +732,11 @@ private List> sortBy(List sortProperties, EventQueryC List order = new ArrayList<>(sortProperties.size()); for (SortProperty sortProperty : sortProperties) { - Expression expression; + CriteriaBuilderHelper.OrderBuilder orderBuilder = CriteriaBuilderHelper.createOrderBuilder(cb, sortProperty.ascending); + final List orderList; + switch (sortProperty.propertyName) { case EventIndexDto.UUID: - case EventIndexDto.EXTERNAL_ID: - case EventIndexDto.EXTERNAL_TOKEN: - case EventIndexDto.INTERNAL_TOKEN: case EventIndexDto.EVENT_STATUS: case EventIndexDto.RISK_LEVEL: case EventIndexDto.SPECIFIC_RISK: @@ -759,58 +744,55 @@ private List> sortBy(List sortProperties, EventQueryC case EventIndexDto.EVENT_MANAGEMENT_STATUS: case EventIndexDto.DISEASE: case EventIndexDto.DISEASE_VARIANT: - case EventIndexDto.DISEASE_DETAILS: case EventIndexDto.START_DATE: case EventIndexDto.EVOLUTION_DATE: + case EventIndexDto.SRC_TYPE: + case EventIndexDto.REPORT_DATE_TIME: + case EventIndexDto.EVENT_IDENTIFICATION_SOURCE: + orderList = orderBuilder.build(eventQueryContext.getRoot().get(sortProperty.propertyName)); + break; + case EventIndexDto.EXTERNAL_ID: + case EventIndexDto.EXTERNAL_TOKEN: + case EventIndexDto.INTERNAL_TOKEN: + case EventIndexDto.DISEASE_DETAILS: case EventIndexDto.EVENT_TITLE: case EventIndexDto.SRC_FIRST_NAME: case EventIndexDto.SRC_LAST_NAME: case EventIndexDto.SRC_TEL_NO: - case EventIndexDto.SRC_TYPE: - case EventIndexDto.REPORT_DATE_TIME: - case EventIndexDto.EVENT_IDENTIFICATION_SOURCE: - expression = eventQueryContext.getRoot().get(sortProperty.propertyName); + orderList = orderBuilder.build(cb.lower(eventQueryContext.getRoot().get(sortProperty.propertyName))); break; case EventIndexDto.EVENT_LOCATION: - expression = region.get(Region.NAME); - order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - expression = district.get(District.NAME); - order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - expression = community.get(Community.NAME); + orderList = orderBuilder + .build(cb.lower(region.get(Region.NAME)), cb.lower(district.get(District.NAME)), cb.lower(community.get(Community.NAME))); break; case EventIndexDto.REGION: - expression = region.get(Region.NAME); + orderList = orderBuilder.build(cb.lower(region.get(Region.NAME))); break; case EventIndexDto.DISTRICT: - expression = district.get(District.NAME); + orderList = orderBuilder.build(cb.lower(district.get(District.NAME))); break; case EventIndexDto.COMMUNITY: - expression = community.get(Community.NAME); + orderList = orderBuilder.build(cb.lower(community.get(Community.NAME))); break; case EventIndexDto.ADDRESS: - expression = location.get(Location.CITY); - order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - expression = location.get(Location.STREET); - order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - expression = location.get(Location.HOUSE_NUMBER); - order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - expression = location.get(Location.ADDITIONAL_INFORMATION); + orderList = orderBuilder.build( + cb.lower(location.get(Location.CITY)), + cb.lower(location.get(Location.STREET)), + cb.lower(location.get(Location.HOUSE_NUMBER)), + cb.lower(location.get(Location.ADDITIONAL_INFORMATION))); break; case EventIndexDto.REPORTING_USER: - expression = reportingUser.get(User.FIRST_NAME); - order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - expression = reportingUser.get(User.LAST_NAME); + orderList = orderBuilder.build(cb.lower(reportingUser.get(User.FIRST_NAME)), cb.lower(reportingUser.get(User.LAST_NAME))); break; case EventIndexDto.RESPONSIBLE_USER: - expression = responsibleUser.get(User.FIRST_NAME); - order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - expression = responsibleUser.get(User.LAST_NAME); + orderList = orderBuilder.build(cb.lower(responsibleUser.get(User.FIRST_NAME)), cb.lower(responsibleUser.get(User.LAST_NAME))); break; default: throw new IllegalArgumentException(sortProperty.propertyName); } - order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - selections.add(expression); + + order.addAll(orderList); + selections.addAll(orderList.stream().map(Order::getExpression).collect(Collectors.toList())); } cq.orderBy(order); } else { diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventGroupDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventGroupDtoResultTransformer.java new file mode 100644 index 00000000000..0b89dba859a --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventGroupDtoResultTransformer.java @@ -0,0 +1,44 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.backend.event; + +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.event.EventGroupIndexDto; + +public class EventGroupDtoResultTransformer implements ResultTransformer { + + private static final long serialVersionUID = 7542708757907090891L; + + @Override + public EventGroupIndexDto transformTuple(Object[] tuple, String[] aliases) { + int index = -1; + + //@formatter:off + return new EventGroupIndexDto( + (String) tuple[++index], (String) tuple[++index], (Long) tuple[++index] + ); + //@formatter:on + } + + @Override + @SuppressWarnings("rawtypes") + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventGroupFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventGroupFacadeEjb.java index 8377a2a6a56..283deaaa27b 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventGroupFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventGroupFacadeEjb.java @@ -25,6 +25,7 @@ import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.ejb.EJB; import javax.ejb.LocalBean; @@ -179,7 +180,7 @@ public List getIndexList( List eventGroups = new ArrayList<>(); IterableHelper.executeBatched(indexListIds, ModelConstants.PARAMETER_LIMIT, batchedIds -> { CriteriaBuilder cb = em.getCriteriaBuilder(); - CriteriaQuery cq = cb.createQuery(EventGroupIndexDto.class); + CriteriaQuery cq = cb.createQuery(Tuple.class); Root eventGroup = cq.from(EventGroup.class); EventGroupQueryContext queryContext = new EventGroupQueryContext(cb, cq, eventGroup); @@ -193,17 +194,19 @@ public List getIndexList( eventService.createDefaultFilter(cb, eventSubQueryJoin))); eventCountSubquery.groupBy(eventGroupSubQuery.get(EventGroup.ID)); - cq.multiselect( - eventGroup.get(EventGroup.UUID), - eventGroup.get(EventGroup.NAME), - eventGroup.get(EventGroup.CHANGE_DATE), - eventCountSubquery.getSelection()); + List orderList = getOrderList(sortProperties, queryContext); + cq.multiselect( + Stream + .concat( + Stream.of(eventGroup.get(EventGroup.UUID), eventGroup.get(EventGroup.NAME), eventCountSubquery.getSelection()), + orderList.stream().map(Order::getExpression)) + .collect(Collectors.toList())); cq.where(eventGroup.get(EventGroup.ID).in(batchedIds)); - cq.orderBy(getOrderList(sortProperties, queryContext)); + cq.orderBy(orderList); cq.distinct(true); - eventGroups.addAll(QueryHelper.getResultList(em, cq, first, max)); + eventGroups.addAll(QueryHelper.getResultList(em, cq, new EventGroupDtoResultTransformer(), null, null)); }); return eventGroups; @@ -258,9 +261,11 @@ private List getOrderList(List sortProperties, EventGroupQu Expression expression; switch (sortProperty.propertyName) { case EventGroupIndexDto.UUID: - case EventGroupIndexDto.NAME: expression = eventGroupRoot.get(sortProperty.propertyName); break; + case EventGroupIndexDto.NAME: + expression = cb.lower(eventGroupRoot.get(sortProperty.propertyName)); + break; default: throw new IllegalArgumentException(sortProperty.propertyName); } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventIndexDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventIndexDtoResultTransformer.java new file mode 100644 index 00000000000..eace54ae644 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventIndexDtoResultTransformer.java @@ -0,0 +1,65 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.backend.event; + +import java.util.Date; +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.common.DeletionReason; +import de.symeda.sormas.api.disease.DiseaseVariant; +import de.symeda.sormas.api.event.EventIdentificationSource; +import de.symeda.sormas.api.event.EventIndexDto; +import de.symeda.sormas.api.event.EventInvestigationStatus; +import de.symeda.sormas.api.event.EventManagementStatus; +import de.symeda.sormas.api.event.EventSourceType; +import de.symeda.sormas.api.event.EventStatus; +import de.symeda.sormas.api.event.RiskLevel; +import de.symeda.sormas.api.event.SpecificRisk; + +public class EventIndexDtoResultTransformer implements ResultTransformer { + + private static final long serialVersionUID = -4148979506301338752L; + + @Override + public EventIndexDto transformTuple(Object[] tuple, String[] aliases) { + int index = -1; + + //@formatter:off + return new EventIndexDto( + (Long) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (EventStatus) tuple[++index], (RiskLevel) tuple[++index], (SpecificRisk) tuple[++index], (EventInvestigationStatus) tuple[++index], + (EventManagementStatus) tuple[++index], (Disease) tuple[++index], (DiseaseVariant) tuple[++index], (String) tuple[++index], + (Date) tuple[++index], (Date) tuple[++index], (Date) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (EventSourceType) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (Date) tuple[++index], (String) tuple[++index],(String) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (Boolean) tuple[++index], (EventIdentificationSource) tuple[++index], + (DeletionReason) tuple[++index], (String) tuple[++index] + ); + //@formatter:on + } + + @Override + @SuppressWarnings("rawtypes") + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventJurisdictionPredicateValidator.java index 16873d588c5..40921480a93 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventJurisdictionPredicateValidator.java @@ -59,20 +59,34 @@ public Predicate isRootInJurisdiction() { @Override public Predicate isRootInJurisdictionOrOwned() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + final Predicate currentUserResponsible = getCurrentUserResponsible(); + return cb.or(reportedByCurrentUser, currentUserResponsible, this.isRootInJurisdiction()); + } + + private Predicate getReportedByCurrentUser() { final Predicate reportedByCurrentUser = cb.and( cb.isNotNull(joins.getRoot().get(Event.REPORTING_USER)), user != null ? cb.equal(joins.getRoot().get(Event.REPORTING_USER).get(User.ID), user.getId()) : cb.equal(joins.getRoot().get(Event.REPORTING_USER).get(User.ID), userPath.get(User.ID))); + return reportedByCurrentUser; + } - final Predicate currentUserResponsible = cb.and( + private Predicate getCurrentUserResponsible() { + return cb.and( cb.isNotNull(joins.getRoot().get(Event.RESPONSIBLE_USER)), user != null ? cb.equal(joins.getRoot().get(Event.RESPONSIBLE_USER).get(User.ID), user.getId()) : cb.equal(joins.getRoot().get(Event.RESPONSIBLE_USER).get(User.ID), userPath.get(User.ID))); + } - return cb.or(reportedByCurrentUser, currentUserResponsible, this.isRootInJurisdiction()); + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + final Predicate currentUserResponsible = getCurrentUserResponsible(); + return cb.or(reportedByCurrentUser, currentUserResponsible); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjb.java index 5f9a75eaa12..701d942faec 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjb.java @@ -31,6 +31,7 @@ import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.security.PermitAll; import javax.ejb.EJB; @@ -43,6 +44,7 @@ import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; +import javax.persistence.criteria.From; import javax.persistence.criteria.Join; import javax.persistence.criteria.JoinType; import javax.persistence.criteria.Order; @@ -596,7 +598,7 @@ public List getIndexList( IterableHelper.executeBatched(indexListIds, ModelConstants.PARAMETER_LIMIT, batchedIds -> { final CriteriaBuilder cb = em.getCriteriaBuilder(); - final CriteriaQuery cq = cb.createQuery(EventParticipantIndexDto.class); + final CriteriaQuery cq = cb.createQuery(Tuple.class); final Root eventParticipant = cq.from(EventParticipant.class); final EventParticipantQueryContext queryContext = new EventParticipantQueryContext(cb, cq, eventParticipant); EventParticipantJoins joins = queryContext.getJoins(); @@ -626,42 +628,33 @@ public List getIndexList( Expression inJurisdictionSelector = JurisdictionHelper.booleanSelector(cb, service.inJurisdiction(queryContext)); Expression inJurisdictionOrOwnedSelector = JurisdictionHelper.booleanSelector(cb, service.inJurisdictionOrOwned(queryContext)); - cq.multiselect( - eventParticipant.get(EventParticipant.UUID), - person.get(Person.UUID), - resultingCase.get(Case.UUID), - event.get(Event.UUID), - person.get(Person.FIRST_NAME), - person.get(Person.LAST_NAME), - person.get(Person.SEX), - person.get(Person.APPROXIMATE_AGE), - person.get(Person.APPROXIMATE_AGE_TYPE), - eventParticipant.get(EventParticipant.INVOLVEMENT_DESCRIPTION), - labResultSq, - sampleDateSq, - eventParticipant.get(EventParticipant.VACCINATION_STATUS), - joins.getEventParticipantReportingUser().get(User.UUID), - eventParticipant.get(EventParticipant.DELETION_REASON), - eventParticipant.get(EventParticipant.OTHER_DELETION_REASON), - inJurisdictionSelector, - inJurisdictionOrOwnedSelector); - - Predicate filter = service.buildCriteriaFilter(eventParticipantCriteria, queryContext); - - if (eventParticipantCriteria.getPathogenTestResult() != null) { - filter = CriteriaBuilderHelper - .and(cb, filter, cb.equal(samples.get(Sample.PATHOGEN_TEST_RESULT), eventParticipantCriteria.getPathogenTestResult())); - } - - filter = CriteriaBuilderHelper.and(cb, filter, eventParticipant.get(EventParticipant.ID).in(batchedIds)); - if (filter != null) { - cq.where(filter); - } + cq.multiselect( + Stream + .concat( + Stream.of( + eventParticipant.get(EventParticipant.UUID), + person.get(Person.UUID), + resultingCase.get(Case.UUID), + event.get(Event.UUID), + person.get(Person.FIRST_NAME), + person.get(Person.LAST_NAME), + person.get(Person.SEX), + person.get(Person.APPROXIMATE_AGE), + eventParticipant.get(EventParticipant.INVOLVEMENT_DESCRIPTION), + labResultSq, + sampleDateSq, + eventParticipant.get(EventParticipant.VACCINATION_STATUS), + eventParticipant.get(EventParticipant.DELETION_REASON), + eventParticipant.get(EventParticipant.OTHER_DELETION_REASON), + inJurisdictionSelector, + inJurisdictionOrOwnedSelector), + sortBy(sortProperties, queryContext).stream()) + .collect(Collectors.toList())); + cq.where(eventParticipant.get(EventParticipant.ID).in(batchedIds)); cq.distinct(true); - sortBy(sortProperties, queryContext); - indexList.addAll(QueryHelper.getResultList(em, cq, null, null)); + indexList.addAll(QueryHelper.getResultList(em, cq, new EventParticipantIndexDtoResultTransformer(), null, null)); }); if (!indexList.isEmpty()) { @@ -726,6 +719,7 @@ private List> sortBy(List sortProperties, EventPartic List> selections = new ArrayList<>(); CriteriaBuilder cb = eventParticipantQueryContext.getCriteriaBuilder(); CriteriaQuery cq = eventParticipantQueryContext.getQuery(); + From eventParticipantRoot = eventParticipantQueryContext.getRoot(); EventParticipantJoins joins = eventParticipantQueryContext.getJoins(); if (sortProperties != null && sortProperties.size() > 0) { @@ -734,21 +728,25 @@ private List> sortBy(List sortProperties, EventPartic Expression expression; switch (sortProperty.propertyName) { case EventParticipantIndexDto.UUID: - case EventParticipantIndexDto.INVOLVEMENT_DESCRIPTION: case EventParticipantIndexDto.VACCINATION_STATUS: - expression = eventParticipantQueryContext.getRoot().get(sortProperty.propertyName); + expression = eventParticipantRoot.get(sortProperty.propertyName); + break; + case EventParticipantIndexDto.INVOLVEMENT_DESCRIPTION: + expression = cb.lower(eventParticipantRoot.get(sortProperty.propertyName)); break; case EventParticipantIndexDto.PERSON_UUID: expression = joins.getPerson().get(Person.UUID); break; case EventParticipantIndexDto.APPROXIMATE_AGE: case EventParticipantIndexDto.SEX: + expression = joins.getPerson().get(sortProperty.propertyName); + break; case EventParticipantIndexDto.LAST_NAME: case EventParticipantIndexDto.FIRST_NAME: - expression = joins.getPerson().get(sortProperty.propertyName); + expression = cb.lower(joins.getPerson().get(sortProperty.propertyName)); break; case EventParticipantIndexDto.CASE_UUID: - expression = joins.getResultingCase().get(Case.UUID); + expression = cb.lower(joins.getResultingCase().get(Case.UUID)); break; default: throw new IllegalArgumentException(sortProperty.propertyName); @@ -758,9 +756,9 @@ private List> sortBy(List sortProperties, EventPartic } cq.orderBy(order); } else { - Expression lastName = joins.getPerson().get(Person.LAST_NAME); - cq.orderBy(cb.desc(lastName)); - selections.add(lastName); + Expression changeDate = eventParticipantRoot.get(EventParticipant.CHANGE_DATE); + cq.orderBy(cb.desc(changeDate)); + selections.add(changeDate); } return selections; diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantIndexDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantIndexDtoResultTransformer.java new file mode 100644 index 00000000000..0d7943448ff --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantIndexDtoResultTransformer.java @@ -0,0 +1,54 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.backend.event; + +import java.util.Date; +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.caze.VaccinationStatus; +import de.symeda.sormas.api.common.DeletionReason; +import de.symeda.sormas.api.event.EventParticipantIndexDto; +import de.symeda.sormas.api.person.Sex; +import de.symeda.sormas.api.sample.PathogenTestResultType; + +public class EventParticipantIndexDtoResultTransformer implements ResultTransformer { + + private static final long serialVersionUID = -3094710938640972422L; + + @Override + public EventParticipantIndexDto transformTuple(Object[] tuple, String[] aliases) { + int index = -1; + + //@formatter:off + return new EventParticipantIndexDto( + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (Sex) tuple[++index], (Integer) tuple[++index], + (String) tuple[++index], + (PathogenTestResultType) tuple[++index], (Date) tuple[++index], (VaccinationStatus) tuple[++index], + (DeletionReason) tuple[++index], (String) tuple[++index], + (Boolean) tuple[++index], (Boolean) tuple[++index] + ); + //@formatter:on + } + + @Override + @SuppressWarnings("rawtypes") + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantJurisdictionPredicateValidator.java index 25a3b376a8a..51ab0b440e8 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantJurisdictionPredicateValidator.java @@ -46,10 +46,24 @@ public static EventParticipantJurisdictionPredicateValidator of(EventParticipant @Override public Predicate isRootInJurisdictionOrOwned() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + return cb.or(reportedByCurrentUser, this.isRootInJurisdiction()); + } + + private Predicate getReportedByCurrentUser() { final Predicate reportedByCurrentUser = cb.and( cb.isNotNull(joins.getRoot().get(EventParticipant.REPORTING_USER)), cb.equal(joins.getRoot().get(EventParticipant.REPORTING_USER).get(User.ID), user.getId())); - return cb.or(reportedByCurrentUser, this.isRootInJurisdiction()); + return reportedByCurrentUser; + } + + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + final Predicate restrictedAccess = user != null + ? cb.equal(joins.getEvent().get(Event.RESPONSIBLE_USER).get(User.ID), user.getId()) + : cb.equal(joins.getEvent().get(Event.RESPONSIBLE_USER).get(User.ID), userPath.get(User.ID)); + return cb.or(reportedByCurrentUser, restrictedAccess); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventService.java index a6173b103d0..7f3af660e3a 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventService.java @@ -466,7 +466,7 @@ public Predicate createUserFilter(final EventQueryContext queryContext, final Ev final EventJoins eventJoins = queryContext.getJoins(); final From eventJoin = queryContext.getRoot(); - if (currentUserHasRestrictedAccessToAssignedEntities()) { + if (isRestrictedToAssignedEntities()) { filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(eventJoin.get(Event.RESPONSIBLE_USER).get(User.ID), currentUser.getId())); } else { if (jurisdictionLevel != JurisdictionLevel.NATION) { @@ -1067,10 +1067,6 @@ public EditPermissionType getEditPermissionType(Event event) { return EditPermissionType.OUTSIDE_JURISDICTION; } - if (currentUserHasRestrictedAccessToAssignedEntities() && !DataHelper.equal(event.getResponsibleUser(), getCurrentUser())) { - return EditPermissionType.REFUSED; - } - if (sormasToSormasShareInfoService.isEventOwnershipHandedOver(event) || event.getSormasToSormasOriginInfo() != null && !event.getSormasToSormasOriginInfo().isOwnershipHandedOver()) { return EditPermissionType.WITHOUT_OWNERSHIP; diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/externalemail/ExternalEmailFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/externalemail/ExternalEmailFacadeEjb.java index aba01f432fe..3bd6cfe6825 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/externalemail/ExternalEmailFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/externalemail/ExternalEmailFacadeEjb.java @@ -60,6 +60,7 @@ import de.symeda.sormas.api.travelentry.TravelEntryReferenceDto; import de.symeda.sormas.api.utils.DataHelper.Pair; import de.symeda.sormas.api.utils.ValidationRuntimeException; +import de.symeda.sormas.api.utils.luxembourg.LuxembourgNationalHealthIdValidator; import de.symeda.sormas.backend.caze.CaseService; import de.symeda.sormas.backend.common.ConfigFacadeEjb.ConfigFacadeEjbLocal; import de.symeda.sormas.backend.common.messaging.EmailService; @@ -75,7 +76,6 @@ import de.symeda.sormas.backend.document.DocumentService; import de.symeda.sormas.backend.document.DocumentStorageService; import de.symeda.sormas.backend.event.EventParticipantService; -import de.symeda.sormas.backend.externalemail.luxembourg.NationalHealthIdValidator; import de.symeda.sormas.backend.manualmessagelog.ManualMessageLog; import de.symeda.sormas.backend.manualmessagelog.ManualMessageLogService; import de.symeda.sormas.backend.person.Person; @@ -151,8 +151,8 @@ public void sendEmail(@Valid ExternalEmailOptionsDto options) throws DocumentTem User currentUser = userService.getCurrentUser(); DocumentTemplateEntities documentEntities = templateEntitiesBuilder.resolveEntities( - new RootEntities().addReference(options.getRootEntityType(), options.getRootEntityReference()) - .addEntity(RootEntityType.ROOT_USER, currentUser)); + new RootEntities().addReference(options.getRootEntityType(), options.getRootEntityReference()) + .addEntity(RootEntityType.ROOT_USER, currentUser)); PersonReferenceDto personRef = (PersonReferenceDto) documentEntities.getEntity(RootEntityType.ROOT_PERSON); Person person = personService.getByReferenceDto(personRef); @@ -176,7 +176,7 @@ public void sendEmail(@Valid ExternalEmailOptionsDto options) throws DocumentTem } String generatedText = - documentTemplateFacade.generateDocumentTxtFromEntities(options.getDocumentWorkflow(), options.getTemplateName(), documentEntities, null); + documentTemplateFacade.generateDocumentTxtFromEntities(options.getDocumentWorkflow(), options.getTemplateName(), documentEntities, null); EmailTemplateTexts emailTexts = splitTemplateContent(generatedText); try { @@ -184,10 +184,10 @@ public void sendEmail(@Valid ExternalEmailOptionsDto options) throws DocumentTem if (passwordType == PasswordType.RANDOM) { messagingService.sendManualMessage( - person, - null, - String.format(I18nProperties.getString(Strings.messageExternalEmailAttachmentPassword), password), - MessageType.SMS); + person, + null, + String.format(I18nProperties.getString(Strings.messageExternalEmailAttachmentPassword), password), + MessageType.SMS); } } catch (MessagingException | NotificationDeliveryFailedException e) { logger.error("Error sending email", e); @@ -201,9 +201,9 @@ public void sendEmail(@Valid ExternalEmailOptionsDto options) throws DocumentTem private static void validateAttachedDocuments(List sormasDocuments, ExternalEmailOptionsDto options) { DocumentRelatedEntityType documentRelatedEntityType = DOCUMENT_WORKFLOW_DOCUMENT_RELATION_MAPPING.get(options.getDocumentWorkflow()); if (sormasDocuments.stream() - .anyMatch( - d -> d.getRelatedEntityType() != documentRelatedEntityType - && !Objects.equals(d.getRelatedEntityUuid(), options.getRootEntityReference().getUuid()))) { + .anyMatch( + d -> d.getRelatedEntityType() != documentRelatedEntityType + && !Objects.equals(d.getRelatedEntityUuid(), options.getRootEntityReference().getUuid()))) { throw new ValidationRuntimeException(I18nProperties.getValidationError(Validations.attachedDocumentNotRelatedToEntity)); } } @@ -238,30 +238,30 @@ private Pair getPassword(Person person) throws ExternalEma PasswordType passwordType = getApplicablePasswordType(person); switch (passwordType) { - case HEALTH_ID: - return new Pair<>(person.getNationalHealthId(), passwordType); - case RANDOM: - return new Pair<>(generateRandomPassword(), passwordType); - case NONE: - default: - throw new ExternalEmailException(I18nProperties.getString(Strings.errorExternalEmailAttachmentCannotEncrypt)); + case HEALTH_ID: + return new Pair<>(person.getNationalHealthId(), passwordType); + case RANDOM: + return new Pair<>(generateRandomPassword(), passwordType); + case NONE: + default: + throw new ExternalEmailException(I18nProperties.getString(Strings.errorExternalEmailAttachmentCannotEncrypt)); } } private static String generateRandomPassword() { return new RandomStringGenerator.Builder().withinRange( - new char[]{ - 'a', - 'z'}, - new char[]{ - 'A', - 'Z'}, - new char[]{ - '2', - '9'}) - .filteredBy(codePoint -> !"lIO".contains(String.valueOf((char) codePoint))) - .build() - .generate(ATTACHMENT_PASSWORD_LENGTH); + new char[] { + 'a', + 'z' }, + new char[] { + 'A', + 'Z' }, + new char[] { + '2', + '9' }) + .filteredBy(codePoint -> !"lIO".contains(String.valueOf((char) codePoint))) + .build() + .generate(ATTACHMENT_PASSWORD_LENGTH); } private static void validateOptions(ExternalEmailOptionsDto options) { @@ -272,10 +272,10 @@ private static void validateOptions(ExternalEmailOptionsDto options) { } private ManualMessageLog createMessageLog( - ExternalEmailOptionsDto options, - PersonReferenceDto personRef, - User currentUser, - List attachedDocuments) { + ExternalEmailOptionsDto options, + PersonReferenceDto personRef, + User currentUser, + List attachedDocuments) { ManualMessageLog log = new ManualMessageLog(); log.setMessageType(MessageType.EMAIL); @@ -290,10 +290,10 @@ private ManualMessageLog createMessageLog( log.setCaze(caseService.getByReferenceDto(getRootEntityReference(options, RootEntityType.ROOT_CASE, CaseReferenceDto.class))); log.setContact(contactService.getByReferenceDto(getRootEntityReference(options, RootEntityType.ROOT_CONTACT, ContactReferenceDto.class))); log.setEventParticipant( - eventParticipantService - .getByReferenceDto(getRootEntityReference(options, RootEntityType.ROOT_EVENT_PARTICIPANT, EventParticipantReferenceDto.class))); + eventParticipantService + .getByReferenceDto(getRootEntityReference(options, RootEntityType.ROOT_EVENT_PARTICIPANT, EventParticipantReferenceDto.class))); log.setTravelEntry( - travelEntryService.getByReferenceDto(getRootEntityReference(options, RootEntityType.ROOT_TRAVEL_ENTRY, TravelEntryReferenceDto.class))); + travelEntryService.getByReferenceDto(getRootEntityReference(options, RootEntityType.ROOT_TRAVEL_ENTRY, TravelEntryReferenceDto.class))); return log; } @@ -312,7 +312,7 @@ private static boolean isValidLuxembourgNationalHealthId(String nationalHealthId return false; } - return NationalHealthIdValidator.isValid(nationalHealthId, person); + return LuxembourgNationalHealthIdValidator.isValid(nationalHealthId, person.getBirthdateYYYY(), person.getBirthdateMM(), person.getBirthdateDD()); } @Stateless diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/externalemail/luxembourg/NationalHealthIdValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/externalemail/luxembourg/NationalHealthIdValidator.java deleted file mode 100644 index cbb3e995f4e..00000000000 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/externalemail/luxembourg/NationalHealthIdValidator.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * SORMAS® - Surveillance Outbreak Response Management & Analysis System - * Copyright © 2016-2023 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package de.symeda.sormas.backend.externalemail.luxembourg; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import de.symeda.sormas.backend.person.Person; - -public class NationalHealthIdValidator { - - /** - * - AAAA = année de naissance - * - MM = mois de naissance - * - JJ = jour de naissance - * - XXX = numéro aléatoire unique par date de naissance - * - C1 = numéro de contrôle calculé sur AAAAMMJJXXX suivant l’algorithme LUHN 10 - * - C2 = numéro de contrôle calculé sur AAAAMMJJXXX suivant l’algorithme VERHOEFF - */ - private static final Pattern NATIONAL_HEALTH_ID_PATTERN = Pattern.compile("(\\d{4})(\\d{2})(\\d{2})(\\d{3})(\\d)(\\d)"); - - public static boolean isValid(String nationalHealthId, Person person) { - if (nationalHealthId == null) { - return false; - } - - Matcher patternMatcher = NATIONAL_HEALTH_ID_PATTERN.matcher(nationalHealthId); - if (!patternMatcher.matches()) { - return false; - } - - String yyyy = patternMatcher.group(1); - String mm = patternMatcher.group(2); - String dd = patternMatcher.group(3); - String xxx = patternMatcher.group(4); - String c1 = patternMatcher.group(5); - String c2 = patternMatcher.group(6); - - if (isNullOrEquals(person.getBirthdateYYYY(), Integer.parseInt(yyyy)) - && isNullOrEquals(person.getBirthdateMM(), Integer.parseInt(mm)) - && isNullOrEquals(person.getBirthdateDD(), Integer.parseInt(dd))) { - String iNumber = yyyy + mm + dd + xxx; - - if (CheckDigitLuhn.checkDigit(iNumber + c1) && CheckDigitVerhoeff.checkDigit(iNumber + c2)) { - return true; - } - } - - return false; - } - - private static boolean isNullOrEquals(Integer personBirthdateFieldValue, int yyyy) { - return personBirthdateFieldValue == null || personBirthdateFieldValue == yyyy; - } - -} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjb.java index a7e459f82b2..fe1f05f479e 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjb.java @@ -3,7 +3,6 @@ import static java.util.stream.Collectors.toList; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.List; @@ -11,6 +10,7 @@ import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.security.PermitAll; import javax.ejb.EJB; @@ -106,19 +106,6 @@ public class ExternalMessageFacadeEjb implements ExternalMessageFacade { private final Logger logger = LoggerFactory.getLogger(getClass()); - public static final List VALID_SORT_PROPERTY_NAMES = Arrays.asList( - ExternalMessageIndexDto.UUID, - ExternalMessageIndexDto.TYPE, - ExternalMessageIndexDto.PERSON_FIRST_NAME, - ExternalMessageIndexDto.PERSON_LAST_NAME, - ExternalMessageIndexDto.PERSON_POSTAL_CODE, - ExternalMessageIndexDto.REPORTER_NAME, - ExternalMessageIndexDto.REPORTER_POSTAL_CODE, - ExternalMessageIndexDto.MESSAGE_DATE_TIME, - ExternalMessageIndexDto.STATUS, - ExternalMessageIndexDto.DISEASE, - ExternalMessageIndexDto.DISEASE_VARIANT); - @PersistenceContext(unitName = ModelConstants.PERSISTENCE_UNIT_NAME) private EntityManager em; @@ -471,34 +458,41 @@ public List getIndexList( IterableHelper.executeBatched(indexListIds, ModelConstants.PARAMETER_LIMIT, batchedIds -> { CriteriaBuilder cb = em.getCriteriaBuilder(); - CriteriaQuery cq = cb.createQuery(ExternalMessageIndexDto.class); + CriteriaQuery cq = cb.createQuery(Tuple.class); Root externalMessage = cq.from(ExternalMessage.class); Join userJoin = externalMessage.join(ExternalMessage.ASSIGNEE, JoinType.LEFT); + List orderList = getOrderList(sortProperties, cb, externalMessage); + cq.multiselect( - externalMessage.get(ExternalMessage.UUID), - externalMessage.get(ExternalMessage.TYPE), - externalMessage.get(ExternalMessage.MESSAGE_DATE_TIME), - externalMessage.get(ExternalMessage.REPORTER_NAME), - externalMessage.get(ExternalMessage.REPORTER_POSTAL_CODE), - externalMessage.get(ExternalMessage.DISEASE), - externalMessage.get(ExternalMessage.DISEASE_VARIANT), - externalMessage.get(ExternalMessage.PERSON_FIRST_NAME), - externalMessage.get(ExternalMessage.PERSON_LAST_NAME), - externalMessage.get(ExternalMessage.PERSON_BIRTH_DATE_YYYY), - externalMessage.get(ExternalMessage.PERSON_BIRTH_DATE_MM), - externalMessage.get(ExternalMessage.PERSON_BIRTH_DATE_DD), - externalMessage.get(ExternalMessage.PERSON_POSTAL_CODE), - externalMessage.get(ExternalMessage.STATUS), - userJoin.get(User.UUID), - userJoin.get(User.FIRST_NAME), - userJoin.get(User.LAST_NAME)); + Stream + .concat( + Stream.of( + externalMessage.get(ExternalMessage.UUID), + externalMessage.get(ExternalMessage.TYPE), + externalMessage.get(ExternalMessage.MESSAGE_DATE_TIME), + externalMessage.get(ExternalMessage.REPORTER_NAME), + externalMessage.get(ExternalMessage.REPORTER_POSTAL_CODE), + externalMessage.get(ExternalMessage.DISEASE), + externalMessage.get(ExternalMessage.DISEASE_VARIANT), + externalMessage.get(ExternalMessage.PERSON_FIRST_NAME), + externalMessage.get(ExternalMessage.PERSON_LAST_NAME), + externalMessage.get(ExternalMessage.PERSON_BIRTH_DATE_YYYY), + externalMessage.get(ExternalMessage.PERSON_BIRTH_DATE_MM), + externalMessage.get(ExternalMessage.PERSON_BIRTH_DATE_DD), + externalMessage.get(ExternalMessage.PERSON_POSTAL_CODE), + externalMessage.get(ExternalMessage.STATUS), + userJoin.get(User.UUID), + userJoin.get(User.FIRST_NAME), + userJoin.get(User.LAST_NAME)), + orderList.stream().map(Order::getExpression)) + .collect(toList())); cq.where(externalMessage.get(ExternalMessage.ID).in(batchedIds)); - cq.orderBy(getOrderList(sortProperties, cb, externalMessage)); + cq.orderBy(orderList); cq.distinct(true); - messages.addAll(QueryHelper.getResultList(em, cq, null, null)); + messages.addAll(QueryHelper.getResultList(em, cq, new ExternalMessageIndexDtoResultTransformer(), null, null)); }); return messages; @@ -540,16 +534,36 @@ private List getOrderList(List sortProperties, CriteriaBuil if (!CollectionUtils.isEmpty(sortProperties)) { for (SortProperty sortProperty : sortProperties) { - if (ExternalMessageIndexDto.PERSON_BIRTH_DATE.equals(sortProperty.propertyName)) { - Expression birthdateYYYY = externalMessageRoot.get(ExternalMessage.PERSON_BIRTH_DATE_YYYY); - order.add(sortProperty.ascending ? cb.asc(birthdateYYYY) : cb.desc(birthdateYYYY)); - Expression birthdateMM = externalMessageRoot.get(ExternalMessage.PERSON_BIRTH_DATE_MM); - order.add(sortProperty.ascending ? cb.asc(birthdateMM) : cb.desc(birthdateMM)); - Expression birthdateDD = externalMessageRoot.get(ExternalMessage.PERSON_BIRTH_DATE_DD); - order.add(sortProperty.ascending ? cb.asc(birthdateDD) : cb.desc(birthdateDD)); - } else if (VALID_SORT_PROPERTY_NAMES.contains(sortProperty.propertyName)) { - Expression expression = externalMessageRoot.get(sortProperty.propertyName); - order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); + CriteriaBuilderHelper.OrderBuilder orderBuilder = CriteriaBuilderHelper.createOrderBuilder(cb, sortProperty.ascending); + switch (sortProperty.propertyName) { + case ExternalMessageIndexDto.PERSON_BIRTH_DATE: + order.addAll( + orderBuilder.build( + externalMessageRoot.get(ExternalMessage.PERSON_BIRTH_DATE_YYYY), + externalMessageRoot.get(ExternalMessage.PERSON_BIRTH_DATE_MM), + externalMessageRoot.get(ExternalMessage.PERSON_BIRTH_DATE_DD))); + break; + case ExternalMessageIndexDto.ASSIGNEE: + Join userJoin = externalMessageRoot.join(ExternalMessage.ASSIGNEE, JoinType.LEFT); + order.addAll(orderBuilder.build(cb.lower(userJoin.get(User.FIRST_NAME)), cb.lower(userJoin.get(User.LAST_NAME)))); + break; + case ExternalMessageIndexDto.UUID: + case ExternalMessageIndexDto.TYPE: + case ExternalMessageIndexDto.MESSAGE_DATE_TIME: + case ExternalMessageIndexDto.STATUS: + case ExternalMessageIndexDto.DISEASE: + case ExternalMessageIndexDto.DISEASE_VARIANT: + order.addAll(orderBuilder.build(externalMessageRoot.get(sortProperty.propertyName))); + break; + case ExternalMessageIndexDto.PERSON_FIRST_NAME: + case ExternalMessageIndexDto.PERSON_LAST_NAME: + case ExternalMessageIndexDto.PERSON_POSTAL_CODE: + case ExternalMessageIndexDto.REPORTER_NAME: + case ExternalMessageIndexDto.REPORTER_POSTAL_CODE: + order.addAll(orderBuilder.build(cb.lower(externalMessageRoot.get(sortProperty.propertyName)))); + break; + default: + throw new IllegalArgumentException("Unknown sort property: " + sortProperty.propertyName); } } } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/ExternalMessageIndexDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/ExternalMessageIndexDtoResultTransformer.java new file mode 100644 index 00000000000..0c00756ee2a --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/ExternalMessageIndexDtoResultTransformer.java @@ -0,0 +1,54 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.backend.externalmessage; + +import java.util.Date; +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.disease.DiseaseVariant; +import de.symeda.sormas.api.externalmessage.ExternalMessageIndexDto; +import de.symeda.sormas.api.externalmessage.ExternalMessageStatus; +import de.symeda.sormas.api.externalmessage.ExternalMessageType; + +public class ExternalMessageIndexDtoResultTransformer implements ResultTransformer { + + private static final long serialVersionUID = -6398347469304554495L; + + @Override + public ExternalMessageIndexDto transformTuple(Object[] tuple, String[] aliases) { + int index = -1; + + //@formatter:off + return new ExternalMessageIndexDto( + (String) tuple[++index], (ExternalMessageType) tuple[++index], (Date) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (Disease) tuple[++index], (DiseaseVariant) tuple[++index], + (String) tuple[++index], (String) tuple[++index], + (Integer) tuple[++index], (Integer) tuple[++index], (Integer) tuple[++index], + (String) tuple[++index], (ExternalMessageStatus) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index] + ); + //@formatter:on + } + + @Override + @SuppressWarnings("rawtypes") + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/feature/FeatureConfigurationFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/feature/FeatureConfigurationFacadeEjb.java index fa3f18e08f7..a1f21298561 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/feature/FeatureConfigurationFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/feature/FeatureConfigurationFacadeEjb.java @@ -217,10 +217,10 @@ private List getIndexList( Expression expression; switch (sortProperty.propertyName) { case FeatureConfiguration.REGION: - expression = regionJoin.get(Region.NAME); + expression = cb.lower(regionJoin.get(Region.NAME)); break; case FeatureConfiguration.DISTRICT: - expression = root.get(District.NAME); + expression = cb.lower(root.get(District.NAME)); break; default: throw new IllegalArgumentException(sortProperty.propertyName); @@ -229,8 +229,9 @@ private List getIndexList( } cq.orderBy(order); } else { - cq.orderBy(cb.asc(regionJoin.get(Region.NAME))); + cq.orderBy(cb.asc(root.get(FeatureConfiguration.CHANGE_DATE))); } + return QueryHelper.getResultList(em, cq, offset, size); } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationJurisdictionPredicateValidator.java index fc30cdb99dc..12f5d79fcdc 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationJurisdictionPredicateValidator.java @@ -1,34 +1,45 @@ package de.symeda.sormas.backend.immunization; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import javax.persistence.criteria.Subquery; +import de.symeda.sormas.api.person.PersonAssociation; +import de.symeda.sormas.backend.common.AbstractDomainObject; import de.symeda.sormas.backend.immunization.entity.Immunization; import de.symeda.sormas.backend.infrastructure.community.Community; import de.symeda.sormas.backend.infrastructure.district.District; import de.symeda.sormas.backend.infrastructure.facility.Facility; import de.symeda.sormas.backend.infrastructure.region.Region; +import de.symeda.sormas.backend.person.PersonJurisdictionPredicateValidator; import de.symeda.sormas.backend.user.User; import de.symeda.sormas.backend.util.PredicateJurisdictionValidator; public final class DirectoryImmunizationJurisdictionPredicateValidator extends PredicateJurisdictionValidator { private final DirectoryImmunizationJoins joins; + private final DirectoryImmunizationQueryContext queryContext; private DirectoryImmunizationJurisdictionPredicateValidator( CriteriaBuilder cb, DirectoryImmunizationJoins joins, User user, - List associatedJurisdictionValidators) { + List associatedJurisdictionValidators, + DirectoryImmunizationQueryContext queryContext) { super(cb, user, null, associatedJurisdictionValidators); this.joins = joins; + this.queryContext = queryContext; } public static DirectoryImmunizationJurisdictionPredicateValidator of(DirectoryImmunizationQueryContext qc, User user) { - return new DirectoryImmunizationJurisdictionPredicateValidator(qc.getCriteriaBuilder(), qc.getJoins(), user, null); + return new DirectoryImmunizationJurisdictionPredicateValidator(qc.getCriteriaBuilder(), qc.getJoins(), user, null, qc); } @Override @@ -38,9 +49,38 @@ public Predicate isRootInJurisdiction() { @Override public Predicate isRootInJurisdictionOrOwned() { + final Predicate reportedByCurrentUser = getReportedByCurrentUser(); + return cb.or(reportedByCurrentUser, this.isRootInJurisdiction()); + } + + private Predicate getReportedByCurrentUser() { final Path reportingUserPath = joins.getRoot().get(Immunization.REPORTING_USER); final Predicate reportedByCurrentUser = cb.and(cb.isNotNull(reportingUserPath), cb.equal(reportingUserPath.get(User.ID), user.getId())); - return cb.or(reportedByCurrentUser, this.isRootInJurisdiction()); + return reportedByCurrentUser; + } + + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + //for restricted access the immunization is only accessible when the associated person is accessible + Predicate isRootInJurisdiction = isRootInJurisdictionOrOwned(); + + final CriteriaQuery cq = queryContext.getQuery(); + + Subquery personSubquery = cq.subquery(Boolean.class); + final Root from = personSubquery.from(Immunization.class); + ImmunizationJoins immunizationJoins = new ImmunizationJoins(from); + final Predicate isPersonInJurisdiction = PersonJurisdictionPredicateValidator + .of( + cq, + cb, + immunizationJoins.getPersonJoins(), + user, + new HashSet<>(Arrays.asList(PersonAssociation.CASE, PersonAssociation.CONTACT, PersonAssociation.EVENT_PARTICIPANT))) + .isRootInJurisdictionForRestrictedAccess(); + personSubquery.select(from.get(AbstractDomainObject.ID)); + personSubquery.where(isPersonInJurisdiction, cb.equal(from.get(AbstractDomainObject.ID), joins.getRoot().get(AbstractDomainObject.ID))); + + return and(isRootInJurisdiction, cb.exists(personSubquery)); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationService.java index 24541c52581..bf7f19d79ab 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/DirectoryImmunizationService.java @@ -3,14 +3,18 @@ import static de.symeda.sormas.backend.common.CriteriaBuilderHelper.andEquals; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.ejb.EJB; import javax.ejb.LocalBean; import javax.ejb.Stateless; import javax.persistence.Tuple; +import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; @@ -32,6 +36,8 @@ import de.symeda.sormas.api.immunization.ImmunizationDateType; import de.symeda.sormas.api.immunization.ImmunizationIndexDto; import de.symeda.sormas.api.immunization.ImmunizationManagementStatus; +import de.symeda.sormas.api.person.PersonAssociation; +import de.symeda.sormas.api.person.PersonCriteria; import de.symeda.sormas.api.person.PersonIndexDto; import de.symeda.sormas.api.utils.DataHelper; import de.symeda.sormas.api.utils.DateHelper; @@ -87,7 +93,7 @@ public List getIndexList(ImmunizationCriteria criteria, In IterableHelper.executeBatched(indexListIds, ModelConstants.PARAMETER_LIMIT, batchedIds -> { final CriteriaBuilder cb = em.getCriteriaBuilder(); - final CriteriaQuery cq = cb.createQuery(Object[].class); + final CriteriaQuery cq = cb.createQuery(Tuple.class); final Root immunization = cq.from(DirectoryImmunization.class); DirectoryImmunizationQueryContext directoryImmunizationQueryContext = new DirectoryImmunizationQueryContext(cb, cq, immunization); @@ -100,40 +106,40 @@ public List getIndexList(ImmunizationCriteria criteria, In final Join lastVaccineType = joins.getLastVaccineType(); cq.multiselect( - immunization.get(Immunization.UUID), - person.get(Person.UUID), - person.get(Person.FIRST_NAME), - person.get(Person.LAST_NAME), - immunization.get(Immunization.DISEASE), - person.get(Person.APPROXIMATE_AGE), - person.get(Person.APPROXIMATE_AGE_TYPE), - person.get(Person.BIRTHDATE_DD), - person.get(Person.BIRTHDATE_MM), - person.get(Person.BIRTHDATE_YYYY), - person.get(Person.SEX), - district.get(District.NAME), - immunization.get(Immunization.MEANS_OF_IMMUNIZATION), - immunization.get(Immunization.IMMUNIZATION_MANAGEMENT_STATUS), - immunization.get(Immunization.IMMUNIZATION_STATUS), - immunization.get(Immunization.START_DATE), - immunization.get(Immunization.END_DATE), - lastVaccineType.get(LastVaccineType.VACCINE_TYPE), - immunization.get(Immunization.RECOVERY_DATE), - immunization.get(Immunization.DELETION_REASON), - immunization.get(Immunization.OTHER_DELETION_REASON), - JurisdictionHelper.booleanSelector(cb, isInJurisdictionOrOwned(directoryImmunizationQueryContext)), - immunization.get(Immunization.CHANGE_DATE)); - - Predicate filter = immunization.get(Immunization.ID).in(batchedIds); - buildWhereCondition(criteria, cb, cq, directoryImmunizationQueryContext, filter); - - sortBy(sortProperties, directoryImmunizationQueryContext); + Stream + .concat( + Stream.of( + immunization.get(Immunization.UUID), + person.get(Person.UUID), + person.get(Person.FIRST_NAME), + person.get(Person.LAST_NAME), + immunization.get(Immunization.DISEASE), + person.get(Person.APPROXIMATE_AGE), + person.get(Person.APPROXIMATE_AGE_TYPE), + person.get(Person.BIRTHDATE_DD), + person.get(Person.BIRTHDATE_MM), + person.get(Person.BIRTHDATE_YYYY), + person.get(Person.SEX), + district.get(District.NAME), + immunization.get(Immunization.MEANS_OF_IMMUNIZATION), + immunization.get(Immunization.IMMUNIZATION_MANAGEMENT_STATUS), + immunization.get(Immunization.IMMUNIZATION_STATUS), + immunization.get(Immunization.START_DATE), + immunization.get(Immunization.END_DATE), + lastVaccineType.get(LastVaccineType.VACCINE_TYPE), + immunization.get(Immunization.RECOVERY_DATE), + immunization.get(Immunization.DELETION_REASON), + immunization.get(Immunization.OTHER_DELETION_REASON), + JurisdictionHelper.booleanSelector(cb, isInJurisdictionOrOwned(directoryImmunizationQueryContext)), + immunization.get(Immunization.CHANGE_DATE)), + // add sort properties to select + sortBy(sortProperties, directoryImmunizationQueryContext).stream()) + .collect(Collectors.toList())); + + buildWhereCondition(criteria, cb, cq, directoryImmunizationQueryContext, immunization.get(Immunization.ID).in(batchedIds)); cq.distinct(true); - immunizations.addAll( - createQuery(cq, null, null).unwrap(org.hibernate.query.Query.class) - .setResultTransformer(new ImmunizationIndexDtoResultTransformer()) - .getResultList()); + immunizations.addAll(QueryHelper.getResultList(em, cq, new ImmunizationIndexDtoResultTransformer(), null, null)); }); return immunizations; @@ -142,7 +148,7 @@ public List getIndexList(ImmunizationCriteria criteria, In private List getIndexListIds(ImmunizationCriteria criteria, Integer first, Integer max, List sortProperties) { final CriteriaBuilder cb = em.getCriteriaBuilder(); - final CriteriaQuery cq = cb.createTupleQuery();; + final CriteriaQuery cq = cb.createTupleQuery(); final Root immunization = cq.from(DirectoryImmunization.class); DirectoryImmunizationQueryContext directoryImmunizationQueryContext = new DirectoryImmunizationQueryContext(cb, cq, immunization); @@ -187,10 +193,10 @@ private List> sortBy(List sortProperties, DirectoryIm expression = immunizationQueryContext.getJoins().getPerson().get(Person.UUID); break; case ImmunizationIndexDto.PERSON_FIRST_NAME: - expression = immunizationQueryContext.getJoins().getPerson().get(Person.FIRST_NAME); + expression = cb.lower(immunizationQueryContext.getJoins().getPerson().get(Person.FIRST_NAME)); break; case ImmunizationIndexDto.PERSON_LAST_NAME: - expression = immunizationQueryContext.getJoins().getPerson().get(Person.LAST_NAME); + expression = cb.lower(immunizationQueryContext.getJoins().getPerson().get(Person.LAST_NAME)); break; case ImmunizationIndexDto.AGE_AND_BIRTH_DATE: expression = immunizationQueryContext.getJoins().getPerson().get(Person.APPROXIMATE_AGE); @@ -199,7 +205,7 @@ private List> sortBy(List sortProperties, DirectoryIm expression = immunizationQueryContext.getJoins().getPerson().get(Person.SEX); break; case ImmunizationIndexDto.DISTRICT: - expression = immunizationQueryContext.getJoins().getPersonJoins().getAddressJoins().getDistrict().get(District.NAME); + expression = cb.lower(immunizationQueryContext.getJoins().getPersonJoins().getAddressJoins().getDistrict().get(District.NAME)); break; case ImmunizationIndexDto.LAST_VACCINE_TYPE: expression = immunizationQueryContext.getJoins().getLastVaccineType().get(LastVaccineType.VACCINE_TYPE); @@ -395,8 +401,9 @@ private Predicate createUserFilter(DirectoryImmunizationQueryContext qc) { return null; } final CriteriaBuilder cb = qc.getCriteriaBuilder(); + Predicate filter = null; - Predicate filter = isInJurisdictionOrOwned(qc); + filter = isInJurisdictionOrOwned(qc); filter = CriteriaBuilderHelper .and(cb, filter, CriteriaBuilderHelper.limitedDiseasePredicate(cb, currentUser, qc.getRoot().get(Immunization.DISEASE))); @@ -416,7 +423,12 @@ private Predicate isInJurisdictionOrOwned(DirectoryImmunizationQueryContext qc) cb, cb.equal(qc.getRoot().get(Immunization.REPORTING_USER), currentUser), PersonJurisdictionPredicateValidator - .of(qc.getQuery(), cb, new PersonJoins(qc.getJoins().getPerson()), currentUser, personService.getPermittedAssociations()) + .of( + qc.getQuery(), + cb, + new PersonJoins(qc.getJoins().getPerson()), + currentUser, + new HashSet<>(Arrays.asList(PersonAssociation.CASE, PersonAssociation.CONTACT, PersonAssociation.EVENT_PARTICIPANT))) .inJurisdictionOrOwned()); } return filter; diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationJurisdictionPredicateValidator.java index c3d93818271..0c4a4adec42 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationJurisdictionPredicateValidator.java @@ -15,24 +15,32 @@ package de.symeda.sormas.backend.immunization; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import javax.persistence.criteria.Subquery; +import de.symeda.sormas.api.person.PersonAssociation; +import de.symeda.sormas.backend.common.AbstractDomainObject; import de.symeda.sormas.backend.immunization.entity.Immunization; import de.symeda.sormas.backend.infrastructure.community.Community; import de.symeda.sormas.backend.infrastructure.district.District; import de.symeda.sormas.backend.infrastructure.facility.Facility; import de.symeda.sormas.backend.infrastructure.region.Region; +import de.symeda.sormas.backend.person.PersonJurisdictionPredicateValidator; import de.symeda.sormas.backend.user.User; import de.symeda.sormas.backend.util.PredicateJurisdictionValidator; public class ImmunizationJurisdictionPredicateValidator extends PredicateJurisdictionValidator { private final ImmunizationJoins joins; + private final CriteriaQuery cq; private ImmunizationJurisdictionPredicateValidator( CriteriaQuery cq, @@ -43,6 +51,7 @@ private ImmunizationJurisdictionPredicateValidator( super(cb, user, null, associatedJurisdictionValidators); this.joins = joins; + this.cq = cq; } public static ImmunizationJurisdictionPredicateValidator of(ImmunizationQueryContext qc, User user) { @@ -61,6 +70,27 @@ public Predicate isRootInJurisdictionOrOwned() { return cb.or(reportedByCurrentUser, this.isRootInJurisdiction()); } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + Predicate isRootInJurisdiction = isRootInJurisdictionOrOwned(); + + Subquery personSubquery = cq.subquery(Boolean.class); + final Root from = personSubquery.from(Immunization.class); + ImmunizationJoins immunizationJoins = new ImmunizationJoins(from); + final Predicate isPersonInJurisdiction = PersonJurisdictionPredicateValidator + .of( + cq, + cb, + immunizationJoins.getPersonJoins(), + user, + new HashSet<>(Arrays.asList(PersonAssociation.CASE, PersonAssociation.CONTACT, PersonAssociation.EVENT_PARTICIPANT))) + .isRootInJurisdictionForRestrictedAccess(); + personSubquery.select(from.get(AbstractDomainObject.ID)); + personSubquery.where(isPersonInJurisdiction, cb.equal(from.get(AbstractDomainObject.ID), joins.getRoot().get(AbstractDomainObject.ID))); + + return and(isRootInJurisdiction, cb.exists(personSubquery)); + } + @Override protected Predicate whenNotAllowed() { return cb.disjunction(); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationService.java index 1b113f82ccf..1ef94f30efa 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/immunization/ImmunizationService.java @@ -17,15 +17,19 @@ import java.sql.Timestamp; import java.time.Instant; +import java.util.Arrays; import java.util.Date; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.stream.Collectors; import javax.ejb.EJB; import javax.ejb.LocalBean; import javax.ejb.Stateless; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; +import javax.persistence.Tuple; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaUpdate; @@ -48,6 +52,8 @@ import de.symeda.sormas.api.immunization.ImmunizationSimilarityCriteria; import de.symeda.sormas.api.immunization.ImmunizationStatus; import de.symeda.sormas.api.immunization.MeansOfImmunization; +import de.symeda.sormas.api.person.PersonAssociation; +import de.symeda.sormas.api.person.PersonCriteria; import de.symeda.sormas.api.sormastosormas.share.incoming.ShareRequestStatus; import de.symeda.sormas.backend.caze.Case; import de.symeda.sormas.backend.common.AbstractCoreAdoService; @@ -64,6 +70,7 @@ import de.symeda.sormas.backend.person.Person; import de.symeda.sormas.backend.person.PersonJoins; import de.symeda.sormas.backend.person.PersonJurisdictionPredicateValidator; +import de.symeda.sormas.backend.person.PersonQueryContext; import de.symeda.sormas.backend.person.PersonService; import de.symeda.sormas.backend.sormastosormas.origin.SormasToSormasOriginInfo; import de.symeda.sormas.backend.sormastosormas.share.outgoing.ShareRequestInfo; @@ -79,6 +86,7 @@ import de.symeda.sormas.backend.util.QueryHelper; import de.symeda.sormas.backend.vaccination.LastVaccinationDate; import de.symeda.sormas.backend.vaccination.Vaccination; +import org.hibernate.query.Query; @Stateless @LocalBean @@ -124,7 +132,7 @@ public void deletePermanent(Immunization immunization) { public List getEntriesList(Long personId, Disease disease, Integer first, Integer max) { final CriteriaBuilder cb = em.getCriteriaBuilder(); - final CriteriaQuery cq = cb.createQuery(Object[].class); + final CriteriaQuery cq = cb.createQuery(Tuple.class); final Root immunization = cq.from(Immunization.class); ImmunizationQueryContext immunizationQueryContext = new ImmunizationQueryContext(cb, cq, immunization); @@ -149,9 +157,7 @@ public List getEntriesList(Long personId, Disease dise cq.distinct(true); - return createQuery(cq, first, max).unwrap(org.hibernate.query.Query.class) - .setResultTransformer(new ImmunizationListEntryDtoResultTransformer()) - .getResultList(); + return QueryHelper.getResultList(em, cq, new ImmunizationListEntryDtoResultTransformer(), first, max); } @Override @@ -171,24 +177,17 @@ public Predicate inJurisdictionOrOwned(ImmunizationQueryContext qc) { cb, cb.equal(qc.getRoot().get(Immunization.REPORTING_USER), currentUser), PersonJurisdictionPredicateValidator - .of(qc.getQuery(), cb, new PersonJoins(qc.getJoins().getPerson()), currentUser, personService.getPermittedAssociations()) + .of( + qc.getQuery(), + cb, + new PersonJoins(qc.getJoins().getPerson()), + currentUser, + new HashSet<>(Arrays.asList(PersonAssociation.CASE, PersonAssociation.CONTACT, PersonAssociation.EVENT_PARTICIPANT))) .inJurisdictionOrOwned()); } return filter; } - @Override - public boolean inJurisdictionOrOwned(Immunization immunization) { - - CriteriaBuilder cb = em.getCriteriaBuilder(); - CriteriaQuery cq = cb.createQuery(Boolean.class); - Root root = cq.from(Immunization.class); - // Deviation from super implementation: createUserFilter - cq.multiselect(JurisdictionHelper.booleanSelector(cb, createUserFilter(new ImmunizationQueryContext(cb, cq, root)))); - cq.where(cb.equal(root.get(Immunization.UUID), immunization.getUuid())); - return em.createQuery(cq).getResultStream().anyMatch(isInJurisdiction -> isInJurisdiction); - } - public Predicate createActiveImmunizationsFilter(CriteriaBuilder cb, From root) { return cb.and(cb.isFalse(root.get(Immunization.ARCHIVED)), cb.isFalse(root.get(Immunization.DELETED))); } @@ -558,9 +557,9 @@ public Predicate createUserFilter(ImmunizationQueryContext qc) { return null; } + final CriteriaBuilder cb = qc.getCriteriaBuilder(); Predicate filter = inJurisdictionOrOwned(qc); - final CriteriaBuilder cb = qc.getCriteriaBuilder(); filter = CriteriaBuilderHelper .and(cb, filter, CriteriaBuilderHelper.limitedDiseasePredicate(cb, currentUser, qc.getRoot().get(Immunization.DISEASE))); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/area/AreaFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/area/AreaFacadeEjb.java index ae630bdef14..66ca5169b50 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/area/AreaFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/area/AreaFacadeEjb.java @@ -78,7 +78,7 @@ public List getIndexList(AreaCriteria criteria, Integer first, Integer switch (sortProperty.propertyName) { case Area.NAME: case Area.EXTERNAL_ID: - expression = areaRoot.get(sortProperty.propertyName); + expression = cb.lower(areaRoot.get(sortProperty.propertyName)); break; default: throw new IllegalArgumentException(sortProperty.propertyName); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/community/CommunityService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/community/CommunityService.java index 76882f16270..ff13c1f0f58 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/community/CommunityService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/community/CommunityService.java @@ -187,16 +187,18 @@ public List getIndexList(CommunityCriteria criteria, Integer first, I Expression expression; switch (sortProperty.propertyName) { case Community.NAME: - case Community.GROWTH_RATE: case Community.EXTERNAL_ID: + expression = cb.lower(community.get(sortProperty.propertyName)); + break; + case Community.GROWTH_RATE: case Community.DEFAULT_INFRASTRUCTURE: expression = community.get(sortProperty.propertyName); break; case District.REGION: - expression = region.get(Region.NAME); + expression = cb.lower(region.get(Region.NAME)); break; case Community.DISTRICT: - expression = district.get(District.NAME); + expression = cb.lower(district.get(District.NAME)); break; default: throw new IllegalArgumentException(sortProperty.propertyName); @@ -205,7 +207,10 @@ public List getIndexList(CommunityCriteria criteria, Integer first, I } cq.orderBy(order); } else { - cq.orderBy(cb.asc(region.get(Region.NAME)), cb.asc(district.get(District.NAME)), cb.asc(community.get(Community.NAME))); + cq.orderBy( + cb.asc(cb.lower(region.get(Region.NAME))), + cb.asc(cb.lower(district.get(District.NAME))), + cb.asc(cb.lower(community.get(Community.NAME)))); } cq.select(community); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/continent/ContinentFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/continent/ContinentFacadeEjb.java index bc6727a152e..74c6b742f2d 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/continent/ContinentFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/continent/ContinentFacadeEjb.java @@ -140,7 +140,7 @@ public List getIndexList(ContinentCriteria criteria, Integer Predicate filter = service.buildCriteriaFilter(criteria, cb, continent); if (filter != null) { - cq.where(filter).distinct(true); + cq.where(filter); } if (CollectionUtils.isNotEmpty(sortProperties)) { @@ -149,10 +149,10 @@ public List getIndexList(ContinentCriteria criteria, Integer Expression expression; switch (sortProperty.propertyName) { case ContinentIndexDto.DISPLAY_NAME: - expression = continent.get(Continent.DEFAULT_NAME); + expression = cb.lower(continent.get(Continent.DEFAULT_NAME)); break; case ContinentDto.EXTERNAL_ID: - expression = continent.get(sortProperty.propertyName); + expression = cb.lower(continent.get(sortProperty.propertyName)); break; default: throw new IllegalArgumentException(sortProperty.propertyName); @@ -161,7 +161,7 @@ public List getIndexList(ContinentCriteria criteria, Integer } cq.orderBy(order); } else { - cq.orderBy(cb.asc(continent.get(Continent.DEFAULT_NAME))); + cq.orderBy(cb.asc(cb.lower(continent.get(Continent.DEFAULT_NAME)))); } cq.select(continent); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/country/CountryFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/country/CountryFacadeEjb.java index 3975d12d455..da24a05e1d8 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/country/CountryFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/country/CountryFacadeEjb.java @@ -155,15 +155,15 @@ public List getIndexList(CountryCriteria criteria, Integer firs Expression expression; switch (sortProperty.propertyName) { case CountryIndexDto.DISPLAY_NAME: - expression = country.get(Country.DEFAULT_NAME); + expression = cb.lower(country.get(Country.DEFAULT_NAME)); break; case CountryIndexDto.SUBCONTINENT: - expression = subcontinent.get(Subcontinent.DEFAULT_NAME); + expression = cb.lower(subcontinent.get(Subcontinent.DEFAULT_NAME)); break; case CountryIndexDto.EXTERNAL_ID: case CountryIndexDto.ISO_CODE: case CountryIndexDto.UNO_CODE: - expression = country.get(sortProperty.propertyName); + expression = cb.lower(country.get(sortProperty.propertyName)); break; default: throw new IllegalArgumentException(sortProperty.propertyName); @@ -172,7 +172,7 @@ public List getIndexList(CountryCriteria criteria, Integer firs } cq.orderBy(order); } else { - cq.orderBy(cb.asc(country.get(Country.ISO_CODE))); + cq.orderBy(cb.asc(cb.lower(country.get(Country.ISO_CODE)))); } cq.select(country); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/district/DistrictFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/district/DistrictFacadeEjb.java index c718fc984c0..fd9c55d0754 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/district/DistrictFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/district/DistrictFacadeEjb.java @@ -149,13 +149,15 @@ public List getIndexList(DistrictCriteria criteria, Integer fi switch (sortProperty.propertyName) { case District.NAME: case District.EPID_CODE: - case District.GROWTH_RATE: case District.EXTERNAL_ID: + expression = cb.lower(district.get(sortProperty.propertyName)); + break; + case District.GROWTH_RATE: case District.DEFAULT_INFRASTRUCTURE: expression = district.get(sortProperty.propertyName); break; case District.REGION: - expression = region.get(Region.NAME); + expression = cb.lower(region.get(Region.NAME)); break; default: throw new IllegalArgumentException(sortProperty.propertyName); @@ -164,7 +166,7 @@ public List getIndexList(DistrictCriteria criteria, Integer fi } cq.orderBy(order); } else { - cq.orderBy(cb.asc(region.get(Region.NAME)), cb.asc(district.get(District.NAME))); + cq.orderBy(cb.asc(cb.lower(region.get(Region.NAME))), cb.asc(cb.lower(district.get(District.NAME)))); } cq.select(district); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/facility/FacilityFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/facility/FacilityFacadeEjb.java index cf754955777..5cca4fabb3e 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/facility/FacilityFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/facility/FacilityFacadeEjb.java @@ -453,20 +453,22 @@ public List getIndexList(FacilityCriteria facilityCriteria, In case Facility.STREET: case Facility.HOUSE_NUMBER: case Facility.ADDITIONAL_INFORMATION: + case Facility.EXTERNAL_ID: + expression = cb.lower(facility.get(sortProperty.propertyName)); + break; case Facility.LATITUDE: case Facility.LONGITUDE: - case Facility.EXTERNAL_ID: case Facility.TYPE: expression = facility.get(sortProperty.propertyName); break; case Facility.REGION: - expression = region.get(Region.NAME); + expression = cb.lower(region.get(Region.NAME)); break; case Facility.DISTRICT: - expression = district.get(District.NAME); + expression = cb.lower(district.get(District.NAME)); break; case Facility.COMMUNITY: - expression = community.get(Community.NAME); + expression = cb.lower(community.get(Community.NAME)); break; default: throw new IllegalArgumentException(sortProperty.propertyName); @@ -476,10 +478,10 @@ public List getIndexList(FacilityCriteria facilityCriteria, In cq.orderBy(order); } else { cq.orderBy( - cb.asc(region.get(Region.NAME)), - cb.asc(district.get(District.NAME)), - cb.asc(community.get(Community.NAME)), - cb.asc(facility.get(Facility.NAME))); + cb.asc(cb.lower(region.get(Region.NAME))), + cb.asc(cb.lower(district.get(District.NAME))), + cb.asc(cb.lower(community.get(Community.NAME))), + cb.asc(cb.lower(facility.get(Facility.NAME)))); } cq.multiselect( diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/pointofentry/PointOfEntryFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/pointofentry/PointOfEntryFacadeEjb.java index 88d36bf3a75..376c45cba77 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/pointofentry/PointOfEntryFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/pointofentry/PointOfEntryFacadeEjb.java @@ -200,18 +200,20 @@ public List getIndexList(PointOfEntryCriteria criteria, Integer Expression expression; switch (sortProperty.propertyName) { case PointOfEntry.NAME: + case PointOfEntry.EXTERNAL_ID: + expression = cb.lower(root.get(sortProperty.propertyName)); + break; case PointOfEntry.POINT_OF_ENTRY_TYPE: case PointOfEntry.LATITUDE: case PointOfEntry.LONGITUDE: case PointOfEntry.ACTIVE: - case PointOfEntry.EXTERNAL_ID: expression = root.get(sortProperty.propertyName); break; case Facility.REGION: - expression = region.get(Region.NAME); + expression = cb.lower(region.get(Region.NAME)); break; case Facility.DISTRICT: - expression = district.get(District.NAME); + expression = cb.lower(district.get(District.NAME)); break; default: throw new IllegalArgumentException(sortProperty.propertyName); @@ -220,7 +222,10 @@ public List getIndexList(PointOfEntryCriteria criteria, Integer } cq.orderBy(order); } else { - cq.orderBy(cb.asc(region.get(Region.NAME)), cb.asc(district.get(District.NAME)), cb.asc(root.get(PointOfEntry.NAME))); + cq.orderBy( + cb.asc(cb.lower(region.get(Region.NAME))), + cb.asc(cb.lower(district.get(District.NAME))), + cb.asc(cb.lower(root.get(PointOfEntry.NAME)))); } cq.select(root); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/region/RegionFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/region/RegionFacadeEjb.java index 27826f1c831..054e93df790 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/region/RegionFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/region/RegionFacadeEjb.java @@ -160,16 +160,18 @@ public List getIndexList(RegionCriteria criteria, Integer first, switch (sortProperty.propertyName) { case Region.NAME: case Region.EPID_CODE: - case Region.GROWTH_RATE: case Region.EXTERNAL_ID: + expression = cb.lower(region.get(sortProperty.propertyName)); + break; + case Region.GROWTH_RATE: case Region.DEFAULT_INFRASTRUCTURE: expression = region.get(sortProperty.propertyName); break; case Region.AREA: - expression = area.get(Area.NAME); + expression = cb.lower(area.get(Area.NAME)); break; case RegionIndexDto.COUNTRY: - expression = country.get(Country.DEFAULT_NAME); + expression = cb.lower(country.get(Country.DEFAULT_NAME)); break; default: throw new IllegalArgumentException(sortProperty.propertyName); @@ -178,7 +180,7 @@ public List getIndexList(RegionCriteria criteria, Integer first, } cq.orderBy(order); } else { - cq.orderBy(cb.asc(region.get(Region.NAME))); + cq.orderBy(cb.asc(cb.lower(region.get(Region.NAME)))); } cq.select(region); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/subcontinent/SubcontinentFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/subcontinent/SubcontinentFacadeEjb.java index e128b5cd07e..946ed9269bb 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/subcontinent/SubcontinentFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/infrastructure/subcontinent/SubcontinentFacadeEjb.java @@ -172,13 +172,13 @@ public List getIndexList(SubcontinentCriteria criteria, In Expression expression; switch (sortProperty.propertyName) { case SubcontinentIndexDto.DISPLAY_NAME: - expression = subcontinent.get(Subcontinent.DEFAULT_NAME); + expression = cb.lower(subcontinent.get(Subcontinent.DEFAULT_NAME)); break; case SubcontinentDto.CONTINENT: - expression = continent.get(Continent.DEFAULT_NAME); + expression = cb.lower(continent.get(Continent.DEFAULT_NAME)); break; case SubcontinentDto.EXTERNAL_ID: - expression = subcontinent.get(sortProperty.propertyName); + expression = cb.lower(subcontinent.get(sortProperty.propertyName)); break; default: throw new IllegalArgumentException(sortProperty.propertyName); @@ -187,7 +187,7 @@ public List getIndexList(SubcontinentCriteria criteria, In } cq.orderBy(order); } else { - cq.orderBy(cb.asc(subcontinent.get(Subcontinent.DEFAULT_NAME))); + cq.orderBy(cb.asc(cb.lower(subcontinent.get(Subcontinent.DEFAULT_NAME)))); } cq.select(subcontinent); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/manualmessagelog/ManualMessageJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/manualmessagelog/ManualMessageJurisdictionPredicateValidator.java index 1af826fbde6..3c118343850 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/manualmessagelog/ManualMessageJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/manualmessagelog/ManualMessageJurisdictionPredicateValidator.java @@ -56,9 +56,14 @@ public Predicate isRootInJurisdictionOrOwned() { throw new UnsupportedOperationException("Jurisdiction validation should woprk through person"); } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + throw new UnsupportedOperationException("Jurisdiction validation should work through person"); + } + @Override protected Predicate whenNotAllowed() { - throw new UnsupportedOperationException("Jurisdiction validation should woprk through person"); + throw new UnsupportedOperationException("Jurisdiction validation should work through person"); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonFacadeEjb.java index 0e44cf010a7..8fe0f29b768 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonFacadeEjb.java @@ -1335,7 +1335,7 @@ public List getIndexList(PersonCriteria criteria, Integer first, IterableHelper.executeBatched(indexListIds, ModelConstants.PARAMETER_LIMIT, batchedIds -> { final CriteriaBuilder cb = em.getCriteriaBuilder(); - final CriteriaQuery cq = cb.createQuery(PersonIndexDto.class); + final CriteriaQuery cq = cb.createQuery(Tuple.class); final Root person = cq.from(Person.class); final PersonQueryContext personQueryContext = new PersonQueryContext(cb, cq, person); @@ -1350,24 +1350,30 @@ public List getIndexList(PersonCriteria criteria, Integer first, // make sure to check the sorting by the multi-select order if you extend the selections here cq.multiselect( - person.get(Person.UUID), - person.get(Person.FIRST_NAME), - person.get(Person.LAST_NAME), - person.get(Person.APPROXIMATE_AGE), - person.get(Person.APPROXIMATE_AGE_TYPE), - person.get(Person.BIRTHDATE_DD), - person.get(Person.BIRTHDATE_MM), - person.get(Person.BIRTHDATE_YYYY), - person.get(Person.SEX), - district.get(District.NAME), - location.get(Location.STREET), - location.get(Location.HOUSE_NUMBER), - location.get(Location.POSTAL_CODE), - location.get(Location.CITY), - phone.get(PersonContactDetail.CONTACT_INFORMATION), - email.get(PersonContactDetail.CONTACT_INFORMATION), - person.get(Person.CHANGE_DATE), - JurisdictionHelper.booleanSelector(cb, service.inJurisdictionOrOwned(personQueryContext))); + Stream + .concat( + Stream.of( + person.get(Person.UUID), + person.get(Person.FIRST_NAME), + person.get(Person.LAST_NAME), + person.get(Person.APPROXIMATE_AGE), + person.get(Person.APPROXIMATE_AGE_TYPE), + person.get(Person.BIRTHDATE_DD), + person.get(Person.BIRTHDATE_MM), + person.get(Person.BIRTHDATE_YYYY), + person.get(Person.SEX), + district.get(District.NAME), + location.get(Location.STREET), + location.get(Location.HOUSE_NUMBER), + location.get(Location.POSTAL_CODE), + location.get(Location.CITY), + phone.get(PersonContactDetail.CONTACT_INFORMATION), + email.get(PersonContactDetail.CONTACT_INFORMATION), + person.get(Person.CHANGE_DATE), + JurisdictionHelper.booleanSelector(cb, service.inJurisdictionOrOwned(personQueryContext))), + // add sort properties to the selection + sortBy(sortProperties, personQueryContext).stream()) + .collect(Collectors.toList())); Predicate filter = person.get(Person.ID).in(batchedIds); @@ -1379,9 +1385,7 @@ public List getIndexList(PersonCriteria criteria, Integer first, cq.where(filter); cq.distinct(true); - sortBy(sortProperties, personQueryContext); - - persons.addAll(em.createQuery(cq).getResultList()); + persons.addAll(QueryHelper.getResultList(em, cq, new PersonIndexDtoResultTransformer(), null, null)); }); Pseudonymizer pseudonymizer = Pseudonymizer.getDefault(userService::hasRight, I18nProperties.getCaption(Captions.inaccessibleValue)); @@ -1443,32 +1447,34 @@ private List> sortBy(List sortProperties, PersonQuery Expression expression; switch (sortProperty.propertyName) { case PersonIndexDto.UUID: - case PersonIndexDto.FIRST_NAME: - case PersonIndexDto.LAST_NAME: case PersonIndexDto.SEX: expression = personQueryContext.getRoot().get(sortProperty.propertyName); break; + case PersonIndexDto.FIRST_NAME: + case PersonIndexDto.LAST_NAME: + expression = cb.lower(personQueryContext.getRoot().get(sortProperty.propertyName)); + break; case PersonIndexDto.PHONE: Join phone = personQueryContext.getPhoneJoin(); expression = phone.get(PersonContactDetail.CONTACT_INFORMATION); break; case PersonIndexDto.EMAIL_ADDRESS: Join email = personQueryContext.getEmailAddressJoin(); - expression = email.get(PersonContactDetail.CONTACT_INFORMATION); + expression = cb.lower(email.get(PersonContactDetail.CONTACT_INFORMATION)); break; case PersonIndexDto.AGE_AND_BIRTH_DATE: expression = personQueryContext.getRoot().get(Person.APPROXIMATE_AGE); break; case PersonIndexDto.DISTRICT: Join district = personQueryContext.getJoins().getAddressJoins().getDistrict(); - expression = district.get(District.NAME); + expression = cb.lower(district.get(District.NAME)); break; case PersonIndexDto.STREET: case PersonIndexDto.HOUSE_NUMBER: case PersonIndexDto.POSTAL_CODE: case PersonIndexDto.CITY: Join location = personQueryContext.getJoins().getAddress(); - expression = location.get(sortProperty.propertyName); + expression = cb.lower(location.get(sortProperty.propertyName)); break; default: throw new IllegalArgumentException(sortProperty.propertyName); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonIndexDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonIndexDtoResultTransformer.java new file mode 100644 index 00000000000..4a095889d2d --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonIndexDtoResultTransformer.java @@ -0,0 +1,52 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.backend.person; + +import java.util.Date; +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.person.ApproximateAgeType; +import de.symeda.sormas.api.person.PersonIndexDto; +import de.symeda.sormas.api.person.Sex; + +public class PersonIndexDtoResultTransformer implements ResultTransformer { + + private static final long serialVersionUID = -2944594574769317387L; + + @Override + public PersonIndexDto transformTuple(Object[] tuple, String[] aliases) { + int index = -1; + + //@formatter:off + return new PersonIndexDto( + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (Integer) tuple[++index], (ApproximateAgeType) tuple[++index], + (Integer) tuple[++index], (Integer) tuple[++index], (Integer) tuple[++index], (Sex) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (String) tuple[++index], + (Date) tuple[++index], + (Boolean) tuple[++index] + ); + //@formatter:on + } + + @Override + @SuppressWarnings("rawtypes") + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonJurisdictionPredicateValidator.java index 71f3bd93bc8..7f6800a33db 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonJurisdictionPredicateValidator.java @@ -24,6 +24,7 @@ import javax.persistence.criteria.Predicate; import de.symeda.sormas.api.person.PersonAssociation; +import de.symeda.sormas.api.utils.jurisdiction.JurisdictionValidator; import de.symeda.sormas.backend.caze.CaseJurisdictionPredicateValidator; import de.symeda.sormas.backend.caze.CaseQueryContext; import de.symeda.sormas.backend.contact.ContactJurisdictionPredicateValidator; @@ -101,6 +102,19 @@ public Predicate isRootInJurisdiction() { return cb.disjunction(); } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + List associationPredicates = new ArrayList<>(associatedJurisdictionValidators.size()); + for (JurisdictionValidator associatedJurisdictionValidator : associatedJurisdictionValidators) { + if (!TravelEntryJurisdictionPredicateValidator.class.isAssignableFrom(associatedJurisdictionValidator.getClass()) + && !ImmunizationJurisdictionPredicateValidator.class.isAssignableFrom(associatedJurisdictionValidator.getClass())) { + associationPredicates.add(associatedJurisdictionValidator.isRootInJurisdictionForRestrictedAccess()); + } + } + return or(associationPredicates); + + } + @Override protected Predicate whenNotAllowed() { return cb.disjunction(); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonService.java index d4c09b19fe2..b681af27ae7 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonService.java @@ -116,6 +116,7 @@ import de.symeda.sormas.backend.user.UserService; import de.symeda.sormas.backend.util.ExternalDataUtil; import de.symeda.sormas.backend.util.IterableHelper; +import de.symeda.sormas.backend.util.JurisdictionHelper; import de.symeda.sormas.backend.util.ModelConstants; import de.symeda.sormas.backend.visit.VisitService; @@ -352,16 +353,16 @@ private Predicate createAssociationPredicate(@NotNull PersonQueryContext queryCo eventParticipantService.createDefaultFilter(cb, joins.getEventParticipant())); break; case IMMUNIZATION: - associationPredicate = CriteriaBuilderHelper.and( - cb, - immunizationService.createUserFilter(new ImmunizationQueryContext(cb, cq, joins.getImmunizationJoins())), - immunizationService.createDefaultFilter(cb, joins.getImmunization())); + associationPredicate = CriteriaBuilderHelper.and( + cb, + immunizationService.createUserFilter(new ImmunizationQueryContext(cb, cq, joins.getImmunizationJoins())), + immunizationService.createDefaultFilter(cb, joins.getImmunization())); break; case TRAVEL_ENTRY: - associationPredicate = CriteriaBuilderHelper.and( - cb, - travelEntryService.createUserFilter(new TravelEntryQueryContext(cb, cq, joins.getTravelEntryJoins())), - travelEntryService.createDefaultFilter(cb, joins.getTravelEntry())); + associationPredicate = CriteriaBuilderHelper.and( + cb, + travelEntryService.createUserFilter(new TravelEntryQueryContext(cb, cq, joins.getTravelEntryJoins())), + travelEntryService.createDefaultFilter(cb, joins.getTravelEntry())); break; case ALL: default: @@ -1093,14 +1094,10 @@ public boolean isEditAllowed(String personUuid) { cq.where( cb.equal(from.get(Person.UUID), personUuid), + cb.equal(JurisdictionHelper.booleanSelector(cb, inJurisdictionOrOwned(new PersonQueryContext(cb, cq, from))), true), cb.or( cb.and( - cb.and( - cb.isNotNull(joins.getCaze()), - cb.isFalse(joins.getCaze().get(Case.DELETED)), - currentUserHasRestrictedAccessToAssignedEntities() - ? cb.equal(joins.getCaze().get(Case.SURVEILLANCE_OFFICER).get(User.ID), getCurrentUser().getId()) - : cb.conjunction()), + cb.and(cb.isNotNull(joins.getCaze()), cb.isFalse(joins.getCaze().get(Case.DELETED))), caseService.createOwnershipPredicate(true, joins.getCaze(), cb, cq)), cb.and( cb.and(cb.isNotNull(joins.getContact()), cb.isFalse(joins.getContact().get(Contact.DELETED))), diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/PathogenTestFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/PathogenTestFacadeEjb.java index ccc04163d4a..d6e5745ec5b 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/PathogenTestFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/PathogenTestFacadeEjb.java @@ -338,7 +338,9 @@ private void handleAssociatedEntityChanges(PathogenTest pathogenTest, boolean sy } @Override - @RightsAllowed(UserRight._PATHOGEN_TEST_DELETE) + @RightsAllowed({ + UserRight._PATHOGEN_TEST_DELETE, + UserRight._ENVIRONMENT_PATHOGEN_TEST_DELETE }) public void deletePathogenTest(String pathogenTestUuid, DeletionDetails deletionDetails) { PathogenTest pathogenTest = pathogenTestService.getByUuid(pathogenTestUuid); @@ -355,7 +357,11 @@ public boolean hasPathogenTest(SampleReferenceDto sample) { public PathogenTestDto savePathogenTest(@Valid PathogenTestDto dto, boolean checkChangeDate, boolean syncShares) { PathogenTest existingSampleTest = pathogenTestService.getByUuid(dto.getUuid()); - FacadeHelper.checkCreateAndEditRights(existingSampleTest, userService, UserRight.PATHOGEN_TEST_CREATE, UserRight.PATHOGEN_TEST_EDIT); + FacadeHelper.checkCreateAndEditRights( + existingSampleTest, + userService, + dto.getSample() != null ? UserRight.PATHOGEN_TEST_CREATE : UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE, + dto.getSample() != null ? UserRight.PATHOGEN_TEST_EDIT : UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT); PathogenTestDto existingSampleTestDto = toDto(existingSampleTest); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleFacadeEjb.java index 8870c1ba99b..fc1ad181f92 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleFacadeEjb.java @@ -799,11 +799,10 @@ public List delete(List sampleUuids, DeletionDetails de long startTime = DateHelper.startTime(); List processedSamples = new ArrayList<>(); - IterableHelper - .executeBatched( - sampleUuids, - DELETED_BATCH_SIZE, - batchedSampleUuids -> processedSamples.addAll(sampleService.deleteAll(batchedSampleUuids, deletionDetails))); + IterableHelper.executeBatched( + sampleUuids, + DELETED_BATCH_SIZE, + batchedSampleUuids -> processedSamples.addAll(sampleService.deleteAll(batchedSampleUuids, deletionDetails))); logger.debug("deleteAllSamples(sampleUuids) finished. samplesCount = {}, {}ms", sampleUuids.size(), DateHelper.durationMillies(startTime)); return processedSamples; @@ -1117,7 +1116,7 @@ private void handleAssociatedEntityChanges(Sample newSample, boolean syncShares) @Override public boolean isDeleted(String sampleUuid) { - return caseService.isDeleted(sampleUuid); + return sampleService.isDeleted(sampleUuid); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleIndexDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleIndexDtoResultTransformer.java new file mode 100644 index 00000000000..c54dd02cfd3 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleIndexDtoResultTransformer.java @@ -0,0 +1,63 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.backend.sample; + +import java.util.Date; +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.common.DeletionReason; +import de.symeda.sormas.api.sample.PathogenTestResultType; +import de.symeda.sormas.api.sample.SampleIndexDto; +import de.symeda.sormas.api.sample.SampleMaterial; +import de.symeda.sormas.api.sample.SamplePurpose; +import de.symeda.sormas.api.sample.SamplingReason; +import de.symeda.sormas.api.sample.SpecimenCondition; + +public class SampleIndexDtoResultTransformer implements ResultTransformer { + + private static final long serialVersionUID = 7529121389855815451L; + + @Override + public SampleIndexDto transformTuple(Object[] tuple, String[] aliases) { + int index = -1; + + //@formatter:off + return new SampleIndexDto( + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (Date) tuple[++index], + (Boolean) tuple[++index], (Date) tuple[++index], (boolean) tuple[++index], (Date) tuple[++index], + (SampleMaterial) tuple[++index], (SamplePurpose) tuple[++index], (SpecimenCondition) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (SamplingReason) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (Disease) tuple[++index], (String) tuple[++index], (PathogenTestResultType) tuple[++index], + (Boolean) tuple[++index], (Boolean) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (DeletionReason) tuple[++index], (String) tuple[++index], + (Long) tuple[++index], + (Boolean) tuple[++index],(Boolean) tuple[++index], (Boolean) tuple[++index], (Boolean) tuple[++index], (Boolean) tuple[++index] + ); + //@formatter:on + } + + @Override + @SuppressWarnings("rawtypes") + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleJurisdictionPredicateValidator.java index 790bb1ba7ca..c7435a91c9a 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleJurisdictionPredicateValidator.java @@ -92,7 +92,7 @@ public Predicate isRootInJurisdictionOrOwned() { @Override public Predicate inJurisdictionOrOwned() { - Predicate rootInJurisdictionOrOwned = isRootInJurisdictionOrOwned(); + Predicate rootInJurisdictionOrOwned = isRootAccessible(); Predicate rootHasLimitedDisease = hasUserLimitedDisease(); if (associatedJurisdictionValidators != null && !associatedJurisdictionValidators.isEmpty()) { final List jurisdictionTypes = new ArrayList<>(); @@ -101,7 +101,7 @@ public Predicate inJurisdictionOrOwned() { diseaseJurisdictionTypes.add(rootHasLimitedDisease); for (JurisdictionValidator jurisdictionValidator : associatedJurisdictionValidators) { if (jurisdictionValidator != null) { - Predicate associatedInJurisdictionOrOwned = jurisdictionValidator.isRootInJurisdictionOrOwned(); + Predicate associatedInJurisdictionOrOwned = jurisdictionValidator.isRootAccessible(); Predicate associatedHasLimitedDisease = jurisdictionValidator.hasUserLimitedDisease(); jurisdictionTypes.add(associatedInJurisdictionOrOwned); diseaseJurisdictionTypes.add(associatedHasLimitedDisease); @@ -135,6 +135,15 @@ public Predicate inJurisdiction() { } } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + List associationPredicates = new ArrayList<>(associatedJurisdictionValidators.size()); + for (JurisdictionValidator associatedJurisdictionValidator : associatedJurisdictionValidators) { + associationPredicates.add(associatedJurisdictionValidator.isRootInJurisdictionForRestrictedAccess()); + } + return or(associationPredicates); + } + @Override protected Predicate whenNotAllowed() { return cb.disjunction(); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleService.java index fbed2be0e1f..db56f74dd51 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleService.java @@ -182,7 +182,7 @@ public List getIndexList(SampleCriteria sampleCriteria, Integer List samples = new ArrayList<>(); IterableHelper.executeBatched(indexListIds, ModelConstants.PARAMETER_LIMIT, batchedIds -> { final CriteriaBuilder cb = em.getCriteriaBuilder(); - final CriteriaQuery cq = cb.createQuery(SampleIndexDto.class); + final CriteriaQuery cq = cb.createQuery(Tuple.class); final Root sample = cq.from(Sample.class); SampleQueryContext sampleQueryContext = new SampleQueryContext(cb, cq, sample); @@ -241,13 +241,17 @@ public List getIndexList(SampleCriteria sampleCriteria, Integer selections.add(testCountSq.getSelection()); selections.addAll(getJurisdictionSelections(sampleQueryContext)); + + List orderList = getOrderList(sortProperties, sampleQueryContext); + selections.addAll(orderList.stream().map(Order::getExpression).collect(Collectors.toList())); + cq.multiselect(selections); cq.where(sample.get(Sample.ID).in(batchedIds)); - cq.orderBy(getOrderList(sortProperties, sampleQueryContext)); + cq.orderBy(orderList); cq.distinct(true); - samples.addAll(QueryHelper.getResultList(em, cq, null, null)); + samples.addAll(QueryHelper.getResultList(em, cq, new SampleIndexDtoResultTransformer(), null, null)); }); if (!samples.isEmpty()) { @@ -360,10 +364,11 @@ private List getOrderList(List sortProperties, SampleQueryC if (CollectionUtils.isNotEmpty(sortProperties)) { for (SortProperty sortProperty : sortProperties) { - Expression expression; + CriteriaBuilderHelper.OrderBuilder orderBuilder = CriteriaBuilderHelper.createOrderBuilder(cb, sortProperty.ascending); + final List order; + switch (sortProperty.propertyName) { case SampleIndexDto.UUID: - case SampleIndexDto.LAB_SAMPLE_ID: case SampleIndexDto.SHIPPED: case SampleIndexDto.RECEIVED: case SampleIndexDto.REFERRED: @@ -374,40 +379,41 @@ private List getOrderList(List sortProperties, SampleQueryC case SampleIndexDto.SAMPLE_PURPOSE: case SampleIndexDto.PATHOGEN_TEST_RESULT: case SampleIndexDto.ADDITIONAL_TESTING_STATUS: - expression = sample.get(sortProperty.propertyName); + order = orderBuilder.build(sample.get(sortProperty.propertyName)); + break; + case SampleIndexDto.LAB_SAMPLE_ID: + order = orderBuilder.build(cb.lower(sample.get(sortProperty.propertyName))); break; case SampleIndexDto.DISEASE: - expression = sampleQueryContext.getDiseaseExpression(); + order = orderBuilder.build(sampleQueryContext.getDiseaseExpression()); break; case SampleIndexDto.EPID_NUMBER: - expression = joins.getCaze().get(Case.EPID_NUMBER); + order = orderBuilder.build(cb.lower(joins.getCaze().get(Case.EPID_NUMBER))); break; case SampleIndexDto.ASSOCIATED_CASE: - expression = joins.getCasePerson().get(Person.LAST_NAME); - orderList.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - expression = joins.getCasePerson().get(Person.FIRST_NAME); + order = orderBuilder + .build(cb.lower(joins.getCasePerson().get(Person.LAST_NAME)), cb.lower(joins.getCasePerson().get(Person.FIRST_NAME))); break; case SampleIndexDto.ASSOCIATED_CONTACT: - expression = joins.getContactPerson().get(Person.LAST_NAME); - orderList.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - expression = joins.getContactPerson().get(Person.FIRST_NAME); + order = orderBuilder + .build(cb.lower(joins.getContactPerson().get(Person.LAST_NAME)), cb.lower(joins.getContactPerson().get(Person.FIRST_NAME))); break; case SampleIndexDto.ASSOCIATED_EVENT_PARTICIPANT: - expression = joins.getEventParticipantPerson().get(Person.LAST_NAME); - orderList.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - expression = joins.getEventParticipantPerson().get(Person.FIRST_NAME); + order = orderBuilder.build( + cb.lower(joins.getEventParticipantPerson().get(Person.LAST_NAME)), + cb.lower(joins.getEventParticipantPerson().get(Person.FIRST_NAME))); break; case SampleIndexDto.DISTRICT: - expression = sampleQueryContext.getDistrictNameExpression(); + order = orderBuilder.build(cb.lower(sampleQueryContext.getDistrictNameExpression())); break; case SampleIndexDto.LAB: - expression = joins.getLab().get(Facility.NAME); + order = orderBuilder.build(cb.lower(joins.getLab().get(Facility.NAME))); break; default: throw new IllegalArgumentException(sortProperty.propertyName); } - orderList.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); + orderList.addAll(order); } } else { orderList.add(cb.desc(sample.get(Sample.SAMPLE_DATE_TIME))); @@ -422,7 +428,7 @@ public List getEntriesList(SampleCriteria sampleCriteria, In } final CriteriaBuilder cb = em.getCriteriaBuilder(); - final CriteriaQuery cq = cb.createQuery(Object[].class); + final CriteriaQuery cq = cb.createQuery(Tuple.class); final Root sample = cq.from(Sample.class); SampleQueryContext sampleQueryContext = new SampleQueryContext(cb, cq, sample); @@ -470,9 +476,7 @@ public List getEntriesList(SampleCriteria sampleCriteria, In cq.orderBy(cb.desc(sample.get(Sample.SAMPLE_DATE_TIME))); - return createQuery(cq, first, max).unwrap(org.hibernate.query.Query.class) - .setResultTransformer(new SampleListEntryDtoResultTransformer()) - .getResultList(); + return QueryHelper.getResultList(em, cq, new SampleListEntryDtoResultTransformer(), first, max); } @Override @@ -656,10 +660,10 @@ public Predicate createUserFilter(SampleQueryContext sampleQueryContext, SampleC cb, filter, caseService.createUserFilter(new CaseQueryContext(cb, cq, joins.getCaseJoins()), null), - RequestContextHolder.isMobileSync() + RequestContextHolder.isMobileSync() && !isRestrictedToAssignedEntities() ? null : contactService.createUserFilter(new ContactQueryContext(cb, cq, joins.getContactJoins()), null), - RequestContextHolder.isMobileSync() + RequestContextHolder.isMobileSync() && !isRestrictedToAssignedEntities() ? null : eventParticipantService.createUserFilter(new EventParticipantQueryContext(cb, cq, joins.getEventParticipantJoins()))); } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/sormastosormas/share/incoming/SormasToSormasShareRequestFacadeEJB.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/sormastosormas/share/incoming/SormasToSormasShareRequestFacadeEJB.java index 1745b473233..4e8ba81b2ec 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/sormastosormas/share/incoming/SormasToSormasShareRequestFacadeEJB.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/sormastosormas/share/incoming/SormasToSormasShareRequestFacadeEJB.java @@ -175,11 +175,13 @@ public List getIndexList(ShareRequestCriteria criteria, In case SormasToSormasOriginInfo.ORGANIZATION_ID: case SormasToSormasOriginInfo.SENDER_NAME: case SormasToSormasOriginInfo.COMMENT: + expression = cb.lower(originInfo.get(sortProperty.propertyName)); + break; case SormasToSormasOriginInfo.OWNERSHIP_HANDED_OVER: expression = originInfo.get(sortProperty.propertyName); break; case ShareRequestIndexDto.ORGANIZATION_NAME: - expression = originInfo.get(SormasToSormasOriginInfo.ORGANIZATION_ID); + expression = cb.lower(originInfo.get(SormasToSormasOriginInfo.ORGANIZATION_ID)); break; default: throw new IllegalArgumentException(sortProperty.propertyName); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskFacadeEjb.java index 957b304ca25..ac8f1ad371b 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskFacadeEjb.java @@ -530,7 +530,7 @@ public List getIndexList(TaskCriteria taskCriteria, Integer first, IterableHelper.executeBatched(indexListIds, ModelConstants.PARAMETER_LIMIT, batchedIds -> { CriteriaBuilder cb = em.getCriteriaBuilder(); - CriteriaQuery cq = cb.createQuery(TaskIndexDto.class); + CriteriaQuery cq = cb.createQuery(Tuple.class); Root task = cq.from(Task.class); TaskQueryContext taskQueryContext = new TaskQueryContext(cb, cq, task); @@ -602,13 +602,17 @@ public List getIndexList(TaskCriteria taskCriteria, Integer first, joins.getCasePointOfEntry().get(PointOfEntry.NAME))); selections.addAll(taskService.getJurisdictionSelections(taskQueryContext)); + + List orderList = getOrderList(sortProperties, taskQueryContext); + selections.addAll(orderList.stream().map(Order::getExpression).collect(Collectors.toList())); + cq.multiselect(selections); cq.where(task.get(Task.ID).in(batchedIds)); - cq.orderBy(getOrderList(sortProperties, taskQueryContext)); + cq.orderBy(orderList); cq.distinct(true); - tasks.addAll(QueryHelper.getResultList(em, cq, null, null)); + tasks.addAll(QueryHelper.getResultList(em, cq, new TaskIndexDtoResultTransformer(), null, null)); }); if (!tasks.isEmpty()) { @@ -709,58 +713,55 @@ private List getOrderList(List sortProperties, TaskQueryCon List orderList = new ArrayList<>(); if (sortProperties != null && sortProperties.size() > 0) { for (SortProperty sortProperty : sortProperties) { - Expression expression; + CriteriaBuilderHelper.OrderBuilder orderBuilder = CriteriaBuilderHelper.createOrderBuilder(cb, sortProperty.ascending); + final List order; + switch (sortProperty.propertyName) { case TaskIndexDto.UUID: - case TaskIndexDto.ASSIGNEE_REPLY: - case TaskIndexDto.CREATOR_COMMENT: case TaskIndexDto.PRIORITY: case TaskIndexDto.DUE_DATE: case TaskIndexDto.SUGGESTED_START: case TaskIndexDto.TASK_CONTEXT: case TaskIndexDto.TASK_STATUS: case TaskIndexDto.TASK_TYPE: - expression = taskRoot.get(sortProperty.propertyName); + order = orderBuilder.build(taskRoot.get(sortProperty.propertyName)); + break; + case TaskIndexDto.ASSIGNEE_REPLY: + case TaskIndexDto.CREATOR_COMMENT: + order = orderBuilder.build(cb.lower(taskRoot.get(sortProperty.propertyName))); break; case TaskIndexDto.ASSIGNEE_USER: - expression = joins.getAssignee().get(User.LAST_NAME); - orderList.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - expression = joins.getAssignee().get(User.FIRST_NAME); + order = orderBuilder.build(cb.lower(joins.getAssignee().get(User.LAST_NAME)), cb.lower(joins.getAssignee().get(User.FIRST_NAME))); break; case TaskIndexDto.CREATOR_USER: - expression = joins.getCreator().get(User.LAST_NAME); - orderList.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - expression = joins.getCreator().get(User.FIRST_NAME); + order = orderBuilder.build(cb.lower(joins.getCreator().get(User.LAST_NAME)), cb.lower(joins.getCreator().get(User.FIRST_NAME))); break; case TaskIndexDto.ASSIGNED_BY_USER: - expression = joins.getAssignedBy().get(User.LAST_NAME); - orderList.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - expression = joins.getAssignedBy().get(User.FIRST_NAME); + order = + orderBuilder.build(cb.lower(joins.getAssignedBy().get(User.LAST_NAME)), cb.lower(joins.getAssignedBy().get(User.FIRST_NAME))); break; case TaskIndexDto.CAZE: - expression = joins.getCasePerson().get(Person.LAST_NAME); - orderList.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - expression = joins.getCasePerson().get(Person.FIRST_NAME); + order = orderBuilder + .build(cb.lower(joins.getCasePerson().get(Person.LAST_NAME)), cb.lower(joins.getCasePerson().get(Person.FIRST_NAME))); break; case TaskIndexDto.CONTACT: - expression = joins.getContactPerson().get(Person.LAST_NAME); - orderList.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - expression = joins.getContactPerson().get(Person.FIRST_NAME); + order = orderBuilder + .build(cb.lower(joins.getContactPerson().get(Person.LAST_NAME)), cb.lower(joins.getContactPerson().get(Person.FIRST_NAME))); break; case TaskIndexDto.EVENT: - expression = joins.getEvent().get(Event.START_DATE); + order = orderBuilder.build(joins.getEvent().get(Event.START_DATE)); break; case TaskIndexDto.DISTRICT: - expression = taskQueryContext.getDistrictNameForIndex(); + order = orderBuilder.build(cb.lower(taskQueryContext.getDistrictNameForIndex())); break; case TaskIndexDto.REGION: - expression = taskQueryContext.getRegionNameForIndex(); + order = orderBuilder.build(cb.lower(taskQueryContext.getRegionNameForIndex())); break; default: throw new IllegalArgumentException(sortProperty.propertyName); } - orderList.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); + orderList.addAll(order); } } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskIndexDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskIndexDtoResultTransformer.java new file mode 100644 index 00000000000..d26c460eaca --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskIndexDtoResultTransformer.java @@ -0,0 +1,65 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.backend.task; + +import java.util.Date; +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.event.EventInvestigationStatus; +import de.symeda.sormas.api.event.EventStatus; +import de.symeda.sormas.api.task.TaskContext; +import de.symeda.sormas.api.task.TaskIndexDto; +import de.symeda.sormas.api.task.TaskPriority; +import de.symeda.sormas.api.task.TaskStatus; +import de.symeda.sormas.api.task.TaskType; + +public class TaskIndexDtoResultTransformer implements ResultTransformer { + + private static final long serialVersionUID = -256528439589310194L; + + @Override + public TaskIndexDto transformTuple(Object[] tuple, String[] aliases) { + int index = -1; + + //@formatter:off + return new TaskIndexDto( + (String) tuple[++index], (TaskContext) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (Disease) tuple[++index], (String) tuple[++index], + (EventStatus) tuple[++index], (EventInvestigationStatus) tuple[++index], (Date) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (String) tuple[++index], + (TaskType) tuple[++index], (TaskPriority) tuple[++index], (Date) tuple[++index], (Date) tuple[++index], + (TaskStatus) tuple[++index], (Disease) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (String) tuple[++index],(String) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (Boolean) tuple[++index], (Boolean) tuple[++index], (Boolean) tuple[++index], (Boolean) tuple[++index], (Boolean) tuple[++index], + (Boolean) tuple[++index], (Boolean) tuple[++index] + ); + //@formatter:on + } + + @Override + @SuppressWarnings("rawtypes") + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskJurisdictionPredicateValidator.java index 6fdcc1ef91d..e1afc6bda9d 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskJurisdictionPredicateValidator.java @@ -21,12 +21,15 @@ import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.Predicate; +import de.symeda.sormas.api.utils.jurisdiction.JurisdictionValidator; import de.symeda.sormas.backend.caze.CaseJurisdictionPredicateValidator; import de.symeda.sormas.backend.caze.CaseQueryContext; import de.symeda.sormas.backend.contact.ContactJurisdictionPredicateValidator; import de.symeda.sormas.backend.contact.ContactQueryContext; import de.symeda.sormas.backend.event.EventJurisdictionPredicateValidator; import de.symeda.sormas.backend.event.EventQueryContext; +import de.symeda.sormas.backend.immunization.ImmunizationJurisdictionPredicateValidator; +import de.symeda.sormas.backend.travelentry.TravelEntryJurisdictionPredicateValidator; import de.symeda.sormas.backend.user.User; import de.symeda.sormas.backend.util.PredicateJurisdictionValidator; @@ -61,11 +64,19 @@ public static TaskJurisdictionPredicateValidator of(TaskQueryContext qc, User us @Override public Predicate isRootInJurisdictionOrOwned() { - final Predicate createdByCurrentUser = cb.and(cb.isNotNull(joins.getCreator()), cb.equal(joins.getCreator().get(User.UUID), user.getUuid())); + final Predicate createdByCurrentUser = getCreatedByCurrentUser(); + final Predicate assignedToCurrentUser = getAssignedToCurrentUser(); + return cb.or(createdByCurrentUser, assignedToCurrentUser, isRootInJurisdiction()); + } + private Predicate getAssignedToCurrentUser() { final Predicate assignedToCurrentUser = cb.and(cb.isNotNull(joins.getAssignee()), cb.equal(joins.getAssignee().get(User.UUID), user.getUuid())); - return cb.or(createdByCurrentUser, assignedToCurrentUser, isRootInJurisdiction()); + return assignedToCurrentUser; + } + + private Predicate getCreatedByCurrentUser() { + return cb.and(cb.isNotNull(joins.getCreator()), cb.equal(joins.getCreator().get(User.UUID), user.getUuid())); } @Override @@ -73,6 +84,18 @@ public Predicate isRootInJurisdiction() { return isInJurisdictionByJurisdictionLevel(user.getJurisdictionLevel()); } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + final Predicate createdByCurrentUser = getCreatedByCurrentUser(); + final Predicate assignedToCurrentUser = getAssignedToCurrentUser(); + + List associationPredicates = new ArrayList<>(associatedJurisdictionValidators.size()); + for (JurisdictionValidator associatedJurisdictionValidator : associatedJurisdictionValidators) { + associationPredicates.add(associatedJurisdictionValidator.isRootInJurisdictionForRestrictedAccess()); + } + return cb.or(createdByCurrentUser, assignedToCurrentUser, or(associationPredicates)); + } + @Override protected Predicate whenNotAllowed() { return cb.disjunction(); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskService.java index cdf58fa3342..cdc883d3c5d 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/task/TaskService.java @@ -42,6 +42,7 @@ import javax.persistence.criteria.Root; import javax.persistence.criteria.Selection; +import de.symeda.sormas.backend.util.JurisdictionHelper; import org.apache.commons.lang3.ArrayUtils; import de.symeda.sormas.api.EditPermissionType; @@ -90,7 +91,6 @@ import de.symeda.sormas.backend.user.User; import de.symeda.sormas.backend.user.UserRole; import de.symeda.sormas.backend.user.UserService; -import de.symeda.sormas.backend.util.JurisdictionHelper; @Stateless @LocalBean @@ -219,11 +219,12 @@ public Predicate createUserFilter(TaskQueryContext taskQueryContext, TaskCriteri TaskJoins joins = taskQueryContext.getJoins(); - Predicate assigneeFilter; - if (currentUserHasRestrictedAccessToAssignedEntities()) { - assigneeFilter = cb.disjunction(); + Predicate assigneeJurisdictionFilter; + if (isRestrictedToAssignedEntities()) { + //filters out tasks assigned to other users in the same jurisdiction (which are not linked to a core entity assigned to the limited user) + assigneeJurisdictionFilter = cb.disjunction(); } else { - assigneeFilter = createAssigneeFilter(cb, joins.getAssignee()); + assigneeJurisdictionFilter = createAssigneeJurisdictionFilter(cb, joins.getAssignee()); } Predicate relatedEntityNotDeletedFilter = cb.or( @@ -236,7 +237,7 @@ public Predicate createUserFilter(TaskQueryContext taskQueryContext, TaskCriteri final JurisdictionLevel jurisdictionLevel = currentUser.getJurisdictionLevel(); if (jurisdictionLevel == JurisdictionLevel.NATION && currentUser.getUserRoles().stream().noneMatch(UserRole::isPortHealthUser)) { - return cb.and(assigneeFilter, relatedEntityNotDeletedFilter); + return cb.and(assigneeJurisdictionFilter, relatedEntityNotDeletedFilter); } Predicate filter = cb.equal(taskPath.get(Task.CREATOR_USER), currentUser); @@ -280,7 +281,7 @@ public Predicate createUserFilter(TaskQueryContext taskQueryContext, TaskCriteri filter = cb.or(filter, environmantFilter); } - filter = cb.or(filter, assigneeFilter); + filter = cb.or(filter, assigneeJurisdictionFilter); if (RequestContextHolder.isMobileSync()) { Predicate limitedChangeDatePredicate = CriteriaBuilderHelper.and(cb, createLimitedChangeDateFilter(cb, taskQueryContext.getRoot())); @@ -330,7 +331,7 @@ protected Predicate getUserFilterForObsoleteUuids(CriteriaBuilder cb, CriteriaQu return createUserFilter(new TaskQueryContext(cb, cq, from), new TaskCriteria().excludeLimitedSyncRestrictions(true)); } - public Predicate createAssigneeFilter(CriteriaBuilder cb, Join assigneeUserJoin) { + public Predicate createAssigneeJurisdictionFilter(CriteriaBuilder cb, Join assigneeUserJoin) { return CriteriaBuilderHelper .or(cb, cb.isNull(assigneeUserJoin.get(User.UUID)), userService.createCurrentUserJurisdictionFilter(cb, assigneeUserJoin)); } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/TravelEntryJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/TravelEntryJurisdictionPredicateValidator.java index 925cf35e6a8..61f9a7f53d3 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/TravelEntryJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/TravelEntryJurisdictionPredicateValidator.java @@ -1,26 +1,34 @@ package de.symeda.sormas.backend.travelentry; +import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.List; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import javax.persistence.criteria.Subquery; +import de.symeda.sormas.api.person.PersonAssociation; import de.symeda.sormas.backend.caze.CaseJurisdictionPredicateValidator; import de.symeda.sormas.backend.caze.CaseQueryContext; +import de.symeda.sormas.backend.common.AbstractDomainObject; import de.symeda.sormas.backend.common.CriteriaBuilderHelper; import de.symeda.sormas.backend.infrastructure.community.Community; import de.symeda.sormas.backend.infrastructure.district.District; import de.symeda.sormas.backend.infrastructure.pointofentry.PointOfEntry; import de.symeda.sormas.backend.infrastructure.region.Region; +import de.symeda.sormas.backend.person.PersonJurisdictionPredicateValidator; import de.symeda.sormas.backend.user.User; import de.symeda.sormas.backend.util.PredicateJurisdictionValidator; public class TravelEntryJurisdictionPredicateValidator extends PredicateJurisdictionValidator { private final TravelEntryJoins joins; + private final CriteriaQuery cq; private TravelEntryJurisdictionPredicateValidator( CriteriaQuery cq, @@ -30,6 +38,7 @@ private TravelEntryJurisdictionPredicateValidator( List associatedJurisdictionValidators) { super(cb, user, null, associatedJurisdictionValidators); this.joins = joins; + this.cq = cq; } private TravelEntryJurisdictionPredicateValidator( @@ -40,6 +49,7 @@ private TravelEntryJurisdictionPredicateValidator( List associatedJurisdictionValidators) { super(cb, null, userPath, associatedJurisdictionValidators); this.joins = joins; + this.cq = cq; } public static TravelEntryJurisdictionPredicateValidator of(TravelEntryQueryContext qc, User user) { @@ -50,7 +60,7 @@ public static TravelEntryJurisdictionPredicateValidator of(TravelEntryQueryConte user, Collections.singletonList( CaseJurisdictionPredicateValidator - .of(new CaseQueryContext(qc.getCriteriaBuilder(), qc.getQuery(), ((TravelEntryJoins) qc.getJoins()).getResultingCase()), user))); + .of(new CaseQueryContext(qc.getCriteriaBuilder(), qc.getQuery(), (qc.getJoins()).getResultingCase()), user))); } public static TravelEntryJurisdictionPredicateValidator of(TravelEntryQueryContext qc, Path userPath) { @@ -60,9 +70,8 @@ public static TravelEntryJurisdictionPredicateValidator of(TravelEntryQueryConte qc.getJoins(), userPath, Collections.singletonList( - CaseJurisdictionPredicateValidator.of( - new CaseQueryContext(qc.getCriteriaBuilder(), qc.getQuery(), ((TravelEntryJoins) qc.getJoins()).getResultingCase()), - userPath))); + CaseJurisdictionPredicateValidator + .of(new CaseQueryContext(qc.getCriteriaBuilder(), qc.getQuery(), (qc.getJoins()).getResultingCase()), userPath))); } @Override @@ -81,6 +90,29 @@ public Predicate isRootInJurisdictionOrOwned() { return cb.or(reportedByCurrentUser, isRootInJurisdiction()); } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + Predicate isRootInJurisdiction = isRootInJurisdictionOrOwned(); + + Subquery personSubquery = cq.subquery(Boolean.class); + final Root from = personSubquery.from(TravelEntry.class); + TravelEntryJoins travelEntryJoins = new TravelEntryJoins(from); + + final Predicate isPersonInJurisdiction = PersonJurisdictionPredicateValidator + .of( + cq, + cb, + travelEntryJoins.getPersonJoins(), + user, + new HashSet<>(Arrays.asList(PersonAssociation.CASE, PersonAssociation.CONTACT, PersonAssociation.EVENT_PARTICIPANT))) + .isRootInJurisdictionForRestrictedAccess(); + + personSubquery.select(from.get(AbstractDomainObject.ID)); + personSubquery.where(isPersonInJurisdiction, cb.equal(from.get(AbstractDomainObject.ID), joins.getRoot().get(AbstractDomainObject.ID))); + + return and(isRootInJurisdiction, cb.exists(personSubquery)); + } + @Override protected Predicate getLimitedDiseasePredicate() { return CriteriaBuilderHelper.limitedDiseasePredicate(cb, user, joins.getRoot().get(TravelEntry.DISEASE)); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/services/BaseTravelEntryService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/services/BaseTravelEntryService.java index 746567ec458..58c11cc85fb 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/services/BaseTravelEntryService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/services/BaseTravelEntryService.java @@ -8,9 +8,13 @@ import de.symeda.sormas.api.common.DeletableEntityType; import de.symeda.sormas.api.deletionconfiguration.DeletionReference; +import de.symeda.sormas.api.person.PersonAssociation; +import de.symeda.sormas.api.person.PersonCriteria; import de.symeda.sormas.backend.common.AbstractCoreAdoService; import de.symeda.sormas.backend.common.ChangeDateBuilder; import de.symeda.sormas.backend.common.CriteriaBuilderHelper; +import de.symeda.sormas.backend.person.PersonQueryContext; +import de.symeda.sormas.backend.person.PersonService; import de.symeda.sormas.backend.travelentry.TravelEntry; import de.symeda.sormas.backend.travelentry.TravelEntryJoins; import de.symeda.sormas.backend.travelentry.TravelEntryJurisdictionPredicateValidator; @@ -22,6 +26,8 @@ public abstract class BaseTravelEntryService extends AbstractCoreAdoService getEntriesList(Long personId, Long caseId, Integer first, Integer max) { final CriteriaBuilder cb = em.getCriteriaBuilder(); - final CriteriaQuery cq = cb.createQuery(Object[].class); + final CriteriaQuery cq = cb.createQuery(Tuple.class); final Root travelEntry = cq.from(TravelEntry.class); final TravelEntryQueryContext travelEntryQueryContext = new TravelEntryQueryContext(cb, cq, travelEntry); @@ -53,9 +55,7 @@ public List getEntriesList(Long personId, Long caseId, cq.distinct(true); - return createQuery(cq, first, max).unwrap(org.hibernate.query.Query.class) - .setResultTransformer(new TravelEntryListEntryDtoResultTransformer()) - .getResultList(); + return QueryHelper.getResultList(em, cq, new TravelEntryListEntryDtoResultTransformer(), first, max); } private Predicate buildListEntryCriteriaFilter(Long personId, Long caseId, TravelEntryQueryContext travelEntryQueryContext) { diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/services/TravelEntryService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/services/TravelEntryService.java index a294ed368c6..3f70b8f1928 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/services/TravelEntryService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/travelentry/services/TravelEntryService.java @@ -5,6 +5,7 @@ import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.ejb.EJB; import javax.ejb.LocalBean; @@ -86,7 +87,7 @@ public List getIndexList(TravelEntryCriteria criteria, Inte IterableHelper.executeBatched(indexListIds, ModelConstants.PARAMETER_LIMIT, batchedIds -> { final CriteriaBuilder cb = em.getCriteriaBuilder(); - final CriteriaQuery cq = cb.createQuery(Object[].class); + final CriteriaQuery cq = cb.createQuery(Tuple.class); final Root travelEntry = cq.from(TravelEntry.class); TravelEntryQueryContext travelEntryQueryContext = new TravelEntryQueryContext(cb, cq, travelEntry); @@ -98,21 +99,27 @@ public List getIndexList(TravelEntryCriteria criteria, Inte final Join district = joins.getPersonJoins().getAddressJoins().getDistrict(); cq.multiselect( - travelEntry.get(TravelEntry.UUID), - travelEntry.get(TravelEntry.EXTERNAL_ID), - person.get(Person.FIRST_NAME), - person.get(Person.LAST_NAME), - district.get(District.NAME), - pointOfEntry.get(PointOfEntry.NAME), - travelEntry.get(TravelEntry.POINT_OF_ENTRY_DETAILS), - travelEntry.get(TravelEntry.RECOVERED), - travelEntry.get(TravelEntry.VACCINATED), - travelEntry.get(TravelEntry.TESTED_NEGATIVE), - travelEntry.get(TravelEntry.QUARANTINE_TO), - travelEntry.get(TravelEntry.DELETION_REASON), - travelEntry.get(TravelEntry.OTHER_DELETION_REASON), - JurisdictionHelper.booleanSelector(cb, inJurisdictionOrOwned(travelEntryQueryContext)), - travelEntry.get(TravelEntry.CHANGE_DATE)); + Stream + .concat( + Stream.of( + travelEntry.get(TravelEntry.UUID), + travelEntry.get(TravelEntry.EXTERNAL_ID), + person.get(Person.FIRST_NAME), + person.get(Person.LAST_NAME), + district.get(District.NAME), + pointOfEntry.get(PointOfEntry.NAME), + travelEntry.get(TravelEntry.POINT_OF_ENTRY_DETAILS), + travelEntry.get(TravelEntry.RECOVERED), + travelEntry.get(TravelEntry.VACCINATED), + travelEntry.get(TravelEntry.TESTED_NEGATIVE), + travelEntry.get(TravelEntry.QUARANTINE_TO), + travelEntry.get(TravelEntry.DELETION_REASON), + travelEntry.get(TravelEntry.OTHER_DELETION_REASON), + JurisdictionHelper.booleanSelector(cb, inJurisdictionOrOwned(travelEntryQueryContext)), + travelEntry.get(TravelEntry.CHANGE_DATE)), + // add sorting properties to the select clause + sortBy(sortProperties, travelEntryQueryContext).stream()) + .collect(Collectors.toList())); Predicate filter = travelEntry.get(TravelEntry.ID).in(batchedIds); @@ -126,13 +133,9 @@ public List getIndexList(TravelEntryCriteria criteria, Inte cq.where(filter); } - sortBy(sortProperties, travelEntryQueryContext); cq.distinct(true); - travelEntries.addAll( - createQuery(cq, null, null).unwrap(org.hibernate.query.Query.class) - .setResultTransformer(new TravelEntryIndexDtoResultTransformer()) - .getResultList()); + travelEntries.addAll(QueryHelper.getResultList(em, cq, new TravelEntryIndexDtoResultTransformer(), null, null)); }); return travelEntries; @@ -184,24 +187,26 @@ private List> sortBy(List sortProperties, TravelEntry Expression expression; switch (sortProperty.propertyName) { case TravelEntryIndexDto.UUID: - case TravelEntryIndexDto.EXTERNAL_ID: case TravelEntryIndexDto.RECOVERED: case TravelEntryIndexDto.VACCINATED: case TravelEntryIndexDto.TESTED_NEGATIVE: case TravelEntryIndexDto.QUARANTINE_TO: expression = travelEntryJoins.getRoot().get(sortProperty.propertyName); break; + case TravelEntryIndexDto.EXTERNAL_ID: + expression = cb.lower(travelEntryJoins.getRoot().get(sortProperty.propertyName)); + break; case TravelEntryIndexDto.PERSON_FIRST_NAME: - expression = person.get(Person.FIRST_NAME); + expression = cb.lower(person.get(Person.FIRST_NAME)); break; case TravelEntryIndexDto.PERSON_LAST_NAME: - expression = person.get(Person.LAST_NAME); + expression = cb.lower(person.get(Person.LAST_NAME)); break; case TravelEntryIndexDto.HOME_DISTRICT_NAME: - expression = district.get(District.NAME); + expression = cb.lower(district.get(District.NAME)); break; case TravelEntryIndexDto.POINT_OF_ENTRY_NAME: - expression = travelEntryJoins.getPointOfEntry().get(PointOfEntry.NAME); + expression = cb.lower(travelEntryJoins.getPointOfEntry().get(PointOfEntry.NAME)); break; default: throw new IllegalArgumentException(sortProperty.propertyName); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/CurrentUserService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/CurrentUserService.java index 16c3a2b3800..ddfad704911 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/CurrentUserService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/CurrentUserService.java @@ -1,7 +1,8 @@ package de.symeda.sormas.backend.user; +import static de.symeda.sormas.backend.user.UserHelper.isRestrictedToAssignEntities; + import java.util.Set; -import java.util.stream.Collectors; import javax.annotation.Resource; import javax.ejb.LocalBean; @@ -99,13 +100,8 @@ public boolean hasAnyUserRight(Set userRights) { return getCurrentUser().hasAnyUserRight(userRights); } - public boolean hasRestrictedAccessToAssignedEntities() { - if (getCurrentUser() != null && !getCurrentUser().getUserRoles().isEmpty()) { - return getCurrentUser().getUserRoles() - .stream() - .allMatch(UserRole::isRestrictAccessToAssignedEntities); - } - return false; + public boolean isRestrictedToAssignedEntities() { + return isRestrictedToAssignEntities(getCurrentUser()); } // We need a clean transaction as we do not want call potential entity listeners which would lead to recursion diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserFacadeEjb.java index bf98568c25c..fb8df2ca8d9 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserFacadeEjb.java @@ -41,7 +41,6 @@ import javax.persistence.PersistenceContext; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Expression; import javax.persistence.criteria.Join; import javax.persistence.criteria.JoinType; import javax.persistence.criteria.Order; @@ -123,11 +122,13 @@ import de.symeda.sormas.backend.infrastructure.facility.FacilityService; import de.symeda.sormas.backend.infrastructure.pointofentry.PointOfEntryFacadeEjb; import de.symeda.sormas.backend.infrastructure.pointofentry.PointOfEntryService; +import de.symeda.sormas.backend.infrastructure.region.Region; import de.symeda.sormas.backend.infrastructure.region.RegionFacadeEjb; import de.symeda.sormas.backend.infrastructure.region.RegionService; import de.symeda.sormas.backend.location.Location; import de.symeda.sormas.backend.location.LocationFacadeEjb; import de.symeda.sormas.backend.location.LocationFacadeEjb.LocationFacadeEjbLocal; +import de.symeda.sormas.backend.person.PersonService; import de.symeda.sormas.backend.task.TaskFacadeEjb; import de.symeda.sormas.backend.travelentry.TravelEntry; import de.symeda.sormas.backend.travelentry.TravelEntryJoins; @@ -178,6 +179,8 @@ public class UserFacadeEjb implements UserFacade { private UserRoleFacadeEjbLocal userRoleFacade; @EJB private UserRoleService userRoleService; + @EJB + private PersonService personService; @Inject private Event userCreateEvent; @Inject @@ -681,6 +684,7 @@ public List getIndexList(UserCriteria userCriteria, Integer first, Inte Root user = cq.from(User.class); Join district = user.join(User.DISTRICT, JoinType.LEFT); Join address = user.join(User.ADDRESS, JoinType.LEFT); + Join region = address.join(Location.REGION, JoinType.LEFT); Join facility = user.join(User.HEALTH_FACILITY, JoinType.LEFT); // TODO: We'll need a user filter for users at some point, to make sure that users can edit their own details, @@ -706,36 +710,37 @@ public List getIndexList(UserCriteria userCriteria, Integer first, Inte } if (sortProperties != null && !sortProperties.isEmpty()) { - List order = new ArrayList<>(sortProperties.size()); + List orderList = new ArrayList<>(); for (SortProperty sortProperty : sortProperties) { - Expression expression; + CriteriaBuilderHelper.OrderBuilder orderBuilder = CriteriaBuilderHelper.createOrderBuilder(cb, sortProperty.ascending); + final List order; switch (sortProperty.propertyName) { case EntityDto.UUID: case UserDto.ACTIVE: + order = orderBuilder.build(user.get(sortProperty.propertyName)); + break; case UserDto.USER_NAME: case UserDto.USER_EMAIL: - expression = user.get(sortProperty.propertyName); + order = orderBuilder.build(cb.lower(user.get(sortProperty.propertyName))); break; case UserDto.NAME: - expression = user.get(User.FIRST_NAME); - order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); - expression = user.get(User.LAST_NAME); + order = orderBuilder.build(cb.lower(user.get(User.FIRST_NAME)), cb.lower(user.get(User.LAST_NAME))); break; case UserDto.DISTRICT: - expression = district.get(District.NAME); + order = orderBuilder.build(cb.lower(district.get(District.NAME))); break; case UserDto.ADDRESS: - expression = address.get(Location.REGION); + order = orderBuilder.build(cb.lower(region.get(Region.NAME))); break; case UserDto.HEALTH_FACILITY: - expression = facility.get(Facility.NAME); + order = orderBuilder.build(cb.lower(facility.get(Facility.NAME))); break; default: throw new IllegalArgumentException(sortProperty.propertyName); } - order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); + orderList.addAll(order); } - cq.orderBy(order); + cq.orderBy(orderList); } else { cq.orderBy(cb.desc(user.get(AbstractDomainObject.CHANGE_DATE))); } @@ -951,6 +956,7 @@ private List getUsersFromCasesByDistricts(List districtsUuidsAmong Arrays.asList(UserRight.CASE_RESPONSIBLE)) .stream() .map(userReference -> userService.getByUuid(userReference.getUuid())) + .filter(user -> !UserHelper.isRestrictedToAssignEntities(user)) .collect(Collectors.toList()); return possibleUserForReplacement; } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserHelper.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserHelper.java new file mode 100644 index 00000000000..056a857bf0b --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserHelper.java @@ -0,0 +1,15 @@ +package de.symeda.sormas.backend.user; + +public class UserHelper { + + private UserHelper() { + } + + public static boolean isRestrictedToAssignEntities(User user) { + if (user != null && !user.getUserRoles().isEmpty()) { + return user.getUserRoles().stream().allMatch(UserRole::isRestrictAccessToAssignedEntities); + } + return false; + } + +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserJurisdictionPredicateValidator.java index e505958a903..ae13f3cc58e 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserJurisdictionPredicateValidator.java @@ -42,6 +42,11 @@ public Predicate isRootInJurisdictionOrOwned() { return isRootInJurisdiction(); } + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + return cb.disjunction(); + } + @Override protected Predicate whenNotAllowed() { return cb.disjunction(); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserRoleFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserRoleFacadeEjb.java index 9aebc4057a3..d50db1a747c 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserRoleFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserRoleFacadeEjb.java @@ -44,8 +44,6 @@ import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.JoinType; import javax.persistence.criteria.Order; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; @@ -391,12 +389,12 @@ public long count(UserRoleCriteria userRoleCriteria) { CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(Long.class); Root root = cq.from(UserRole.class); - Join userRightsJoin = root.join(UserRole.USER_RIGHTS, JoinType.LEFT); + UserRoleJoins joins = new UserRoleJoins(root); Predicate filter = null; if (userRoleCriteria != null) { - filter = userRoleService.buildCriteriaFilter(userRoleCriteria, cb, root, userRightsJoin); + filter = userRoleService.buildCriteriaFilter(userRoleCriteria, cb, root, joins); } if (filter != null) { @@ -412,30 +410,31 @@ public List getIndexList(UserRoleCriteria userRoleCriteria, int fir CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(UserRole.class); Root userRole = cq.from(UserRole.class); - Join userRightsJoin = userRole.join(UserRole.USER_RIGHTS, JoinType.LEFT); + UserRoleJoins joins = new UserRoleJoins(userRole); Predicate filter = null; if (userRoleCriteria != null) { - filter = userRoleService.buildCriteriaFilter(userRoleCriteria, cb, userRole, userRightsJoin); + filter = userRoleService.buildCriteriaFilter(userRoleCriteria, cb, userRole, joins); } if (filter != null) { cq.where(filter); } - cq.distinct(true); if (sortProperties != null && !sortProperties.isEmpty()) { List order = new ArrayList<>(sortProperties.size()); for (SortProperty sortProperty : sortProperties) { Expression expression; switch (sortProperty.propertyName) { case UserRoleDto.UUID: - case UserRoleDto.CAPTION: case UserRoleDto.JURISDICTION_LEVEL: - case UserRoleDto.DESCRIPTION: expression = userRole.get(sortProperty.propertyName); break; + case UserRoleDto.CAPTION: + case UserRoleDto.DESCRIPTION: + expression = cb.lower(userRole.get(sortProperty.propertyName)); + break; default: throw new IllegalArgumentException(sortProperty.propertyName); } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserRoleJoins.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserRoleJoins.java new file mode 100644 index 00000000000..57090f2ae02 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserRoleJoins.java @@ -0,0 +1,42 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.backend.user; + +import javax.persistence.criteria.From; +import javax.persistence.criteria.Join; +import javax.persistence.criteria.JoinType; + +import de.symeda.sormas.api.user.UserRight; +import de.symeda.sormas.backend.common.QueryJoins; + +public class UserRoleJoins extends QueryJoins { + private Join userRights; + + public UserRoleJoins(From root) { + super(root); + } + + public Join getUserRights() { + return getOrCreate(userRights, UserRole.USER_RIGHTS, JoinType.LEFT, this::setUserRightsJoin); + } + + private void setUserRightsJoin(Join userRightsJoin) { + this.userRights = userRightsJoin; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserRoleService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserRoleService.java index 6fc1d89e702..2ba7576570b 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserRoleService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserRoleService.java @@ -144,11 +144,7 @@ public boolean hasAnyUserRight(Collection userRoles, Collection from, - Join userRightsJoin) { + public Predicate buildCriteriaFilter(UserRoleCriteria userRoleCriteria, CriteriaBuilder cb, Root from, UserRoleJoins joins) { Predicate filter = null; @@ -157,7 +153,7 @@ public Predicate buildCriteriaFilter( } if (userRoleCriteria.getUserRight() != null) { - Predicate userRightsFilter = userRightsJoin.in(userRoleCriteria.getUserRight()); + Predicate userRightsFilter = joins.getUserRights().in(userRoleCriteria.getUserRight()); filter = CriteriaBuilderHelper.and(cb, filter, userRightsFilter); } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserService.java index 0961f9fa9c4..fd58a140468 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserService.java @@ -497,6 +497,9 @@ public List getUserReferencesByJurisdictions( filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(root.get(UserReference.ID), userRoot.get(AbstractDomainObject.ID))); } + Join rolesJoin = root.join(User.USER_ROLES, JoinType.LEFT); + filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(rolesJoin.get(UserRole.RESTRICT_ACCESS_TO_ASSIGNED_ENTITIES), false)); + if (filter != null) { cq.where(filter); } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/util/PredicateJurisdictionValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/util/PredicateJurisdictionValidator.java index bb299d3b7af..e0c6cef926c 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/util/PredicateJurisdictionValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/util/PredicateJurisdictionValidator.java @@ -25,6 +25,7 @@ import de.symeda.sormas.api.utils.jurisdiction.JurisdictionValidator; import de.symeda.sormas.backend.common.CriteriaBuilderHelper; import de.symeda.sormas.backend.user.User; +import de.symeda.sormas.backend.user.UserHelper; public abstract class PredicateJurisdictionValidator extends JurisdictionValidator { @@ -33,7 +34,7 @@ public abstract class PredicateJurisdictionValidator extends JurisdictionValidat protected final Path userPath; public PredicateJurisdictionValidator(CriteriaBuilder cb, User user, Path userPath, List jurisdictionValidators) { - super(jurisdictionValidators); + super(jurisdictionValidators, UserHelper.isRestrictedToAssignEntities(user)); this.cb = cb; this.user = user; this.userPath = userPath; diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/util/QueryHelper.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/util/QueryHelper.java index 5c1185f5e59..08c1ce8c782 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/util/QueryHelper.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/util/QueryHelper.java @@ -6,12 +6,15 @@ import javax.persistence.EntityManager; import javax.persistence.NonUniqueResultException; +import javax.persistence.Tuple; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Root; import org.apache.commons.lang3.StringUtils; +import org.hibernate.query.Query; +import org.hibernate.transform.ResultTransformer; /** * Helper methods for building JDBC queries. @@ -146,6 +149,40 @@ public static List getResultList(EntityManager em, CriteriaQuery cq, I return resultList; } + /** + * Executes a query and returns the result. Can be selected down to a definite batch + * starting at {@code first} and limited by {@code max}. + * + * @param + * Entity, DTO or simple type for the returned list. + * @param em + * The {@link EntityManager} to be invoked. + * @param cq + * The {@link CriteriaQuery} to be executed. + * @param resultTransformer + * The {@link ResultTransformer} to be used for creating dto from tuple. + * @param first + * The first entity to be returned (optional). + * @param max + * The maximum number of entries to be fetched (optional). + * @return + */ + public static List getResultList( + EntityManager em, + CriteriaQuery cq, + ResultTransformer resultTransformer, + Integer first, + Integer max) { + + TypedQuery query = em.createQuery(cq); + if (first != null && max != null) { + query = query.setFirstResult(first).setMaxResults(max); + } + + //noinspection unchecked + return query.unwrap(Query.class).setResultTransformer(resultTransformer).getResultList(); + } + /** * Executes a query and returns the result. Can be selected down to a definite batch * starting at {@code first} and limited by {@code max}. diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/visit/VisitFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/visit/VisitFacadeEjb.java index 965aac018e8..c83e62a7663 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/visit/VisitFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/visit/VisitFacadeEjb.java @@ -29,6 +29,7 @@ import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.ejb.EJB; import javax.ejb.LocalBean; @@ -36,6 +37,7 @@ import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; import javax.inject.Inject; +import javax.persistence.Tuple; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; @@ -360,44 +362,71 @@ public List getIndexList(VisitCriteria visitCriteria, Integer fir } CriteriaBuilder cb = em.getCriteriaBuilder(); - CriteriaQuery cq = cb.createQuery(VisitIndexDto.class); + CriteriaQuery cq = cb.createQuery(Tuple.class); Root visit = cq.from(Visit.class); VisitQueryContext queryContext = new VisitQueryContext(cb, cq, visit); Join symptoms = queryContext.getJoins().getSymptoms(); Join visitUser = queryContext.getJoins().getUser(); + List orderList = getOrderList(sortProperties, visit, cb, symptoms, cq); + cq.multiselect( - visit.get(Visit.ID), - visit.get(Visit.UUID), - visit.get(Visit.VISIT_DATE_TIME), - visit.get(Visit.VISIT_STATUS), - visit.get(Visit.VISIT_REMARKS), - visit.get(Visit.DISEASE), - symptoms.get(Symptoms.SYMPTOMATIC), - symptoms.get(Symptoms.TEMPERATURE), - symptoms.get(Symptoms.TEMPERATURE_SOURCE), - visit.get(Visit.ORIGIN), - visitUser.get(User.UUID), - visitUser.get(User.FIRST_NAME), - visitUser.get(User.LAST_NAME), - jurisdictionSelector(queryContext)); + Stream + .concat( + Stream.of( + visit.get(Visit.ID), + visit.get(Visit.UUID), + visit.get(Visit.VISIT_DATE_TIME), + visit.get(Visit.VISIT_STATUS), + visit.get(Visit.VISIT_REMARKS), + visit.get(Visit.DISEASE), + symptoms.get(Symptoms.SYMPTOMATIC), + symptoms.get(Symptoms.TEMPERATURE), + symptoms.get(Symptoms.TEMPERATURE_SOURCE), + visit.get(Visit.ORIGIN), + visitUser.get(User.UUID), + visitUser.get(User.FIRST_NAME), + visitUser.get(User.LAST_NAME), + jurisdictionSelector(queryContext)), + // add order by expressions to select + orderList.stream().map(Order::getExpression)) + .collect(Collectors.toList())); cq.distinct(true); cq.where(service.buildCriteriaFilter(visitCriteria, cb, visit)); + cq.orderBy(orderList); + + List indexList = QueryHelper.getResultList(em, cq, new VisitIndexDtoResultTransformer(), first, max); + + if (!indexList.isEmpty()) { + Pseudonymizer pseudonymizer = Pseudonymizer.getDefault(userService::hasRight, I18nProperties.getCaption(Captions.inaccessibleValue)); + indexList.forEach(visitIndex -> pseudonymizer.pseudonymizeDto(VisitIndexDto.class, visitIndex, visitIndex.getInJurisdiction(), null)); + } + + return indexList; + } + private static List getOrderList( + List sortProperties, + Root visit, + CriteriaBuilder cb, + Join symptoms, + CriteriaQuery cq) { + List order = new ArrayList<>(); if (sortProperties != null && !sortProperties.isEmpty()) { - List order = new ArrayList<>(sortProperties.size()); for (SortProperty sortProperty : sortProperties) { Expression expression; switch (sortProperty.propertyName) { case VisitIndexDto.VISIT_DATE_TIME: case VisitIndexDto.VISIT_STATUS: - case VisitIndexDto.VISIT_REMARKS: case VisitIndexDto.DISEASE: case VisitIndexDto.ORIGIN: expression = visit.get(sortProperty.propertyName); break; + case VisitIndexDto.VISIT_REMARKS: + expression = cb.lower(visit.get(sortProperty.propertyName)); + break; case VisitIndexDto.SYMPTOMATIC: case VisitIndexDto.TEMPERATURE: expression = symptoms.get(sortProperty.propertyName); @@ -407,19 +436,11 @@ public List getIndexList(VisitCriteria visitCriteria, Integer fir } order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); } - cq.orderBy(order); } else { - cq.orderBy(cb.desc(visit.get(Visit.VISIT_DATE_TIME))); + order.add(cb.desc(visit.get(Visit.VISIT_DATE_TIME))); } - List indexList = QueryHelper.getResultList(em, cq, first, max); - - if (!indexList.isEmpty()) { - Pseudonymizer pseudonymizer = Pseudonymizer.getDefault(userService::hasRight, I18nProperties.getCaption(Captions.inaccessibleValue)); - indexList.forEach(visitIndex -> pseudonymizer.pseudonymizeDto(VisitIndexDto.class, visitIndex, visitIndex.getInJurisdiction(), null)); - } - - return indexList; + return order; } public Page getIndexPage(VisitCriteria visitCriteria, Integer offset, Integer size, List sortProperties) { diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/visit/VisitIndexDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/visit/VisitIndexDtoResultTransformer.java new file mode 100644 index 00000000000..06ae37cb2fe --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/visit/VisitIndexDtoResultTransformer.java @@ -0,0 +1,52 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.backend.visit; + +import java.util.Date; +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.VisitOrigin; +import de.symeda.sormas.api.symptoms.TemperatureSource; +import de.symeda.sormas.api.visit.VisitIndexDto; +import de.symeda.sormas.api.visit.VisitStatus; + +public class VisitIndexDtoResultTransformer implements ResultTransformer { + + private static final long serialVersionUID = -2324887680085715948L; + + @Override + public VisitIndexDto transformTuple(Object[] tuple, String[] aliases) { + int index = -1; + + //@formatter:off + return new VisitIndexDto( + (Long) tuple[++index], (String) tuple[++index], (Date) tuple[++index], (VisitStatus) tuple[++index], (String) tuple[++index], + (Disease) tuple[++index], (Boolean) tuple[++index], (Float) tuple[++index], (TemperatureSource) tuple[++index], + (VisitOrigin) tuple[++index], (String) tuple[++index], (String) tuple[++index], (String) tuple[++index], + (Boolean) tuple[++index] + ); + //@formatter:on + } + + @Override + @SuppressWarnings("rawtypes") + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/resources/META-INF/glassfish-ejb-jar.xml b/sormas-backend/src/main/resources/META-INF/glassfish-ejb-jar.xml index 4c66be06a60..408c4ba47a5 100644 --- a/sormas-backend/src/main/resources/META-INF/glassfish-ejb-jar.xml +++ b/sormas-backend/src/main/resources/META-INF/glassfish-ejb-jar.xml @@ -907,6 +907,21 @@ ENVIRONMENT_SAMPLE_EXPORT + + ENVIRONMENT_PATHOGEN_TEST_CREATE + ENVIRONMENT_PATHOGEN_TEST_CREATE + + + + ENVIRONMENT_PATHOGEN_TEST_EDIT + ENVIRONMENT_PATHOGEN_TEST_EDIT + + + + ENVIRONMENT_PATHOGEN_TEST_DELETE + ENVIRONMENT_PATHOGEN_TEST_DELETE + + DOCUMENT_VIEW DOCUMENT_VIEW diff --git a/sormas-backend/src/main/resources/sql/sormas_schema.sql b/sormas-backend/src/main/resources/sql/sormas_schema.sql index 206da133468..b8314b70261 100644 --- a/sormas-backend/src/main/resources/sql/sormas_schema.sql +++ b/sormas-backend/src/main/resources/sql/sormas_schema.sql @@ -12833,5 +12833,51 @@ ALTER TABLE userroles_history ADD COLUMN restrictAccessToAssignedEntities boolea INSERT INTO schema_version (version_number, comment) VALUES (536, 'Assign case(s) to a User and allow them to see the data of only the assigned case(s) in the system #12697'); +-- 2023-12-18 Move hide jurisdiction fields feature property to dedicated feature type #12806 +INSERT INTO featureconfiguration (id, uuid, creationdate, changedate, enabled, featuretype)VALUES (nextval('entity_seq'), generate_base32_uuid(), now(), now(), (SELECT properties::jsonb->'HIDE_JURISDICTION_FIELDS' FROM featureconfiguration WHERE featuretype = 'CASE_SURVEILANCE')::text::boolean, 'HIDE_JURISDICTION_FIELDS'); --- *** Insert new sql commands BEFORE this line. Remember to always consider _history tables. *** \ No newline at end of file +UPDATE featureconfiguration SET properties = properties::jsonb - 'HIDE_JURISDICTION_FIELDS' WHERE featuretype = 'CASE_SURVEILANCE'; + +INSERT INTO schema_version (version_number, comment) VALUES (537, 'Move hide jurisdiction fields feature property to dedicated feature type #12806'); + +-- 2023-12-21 Introduce dedicated environment sample pathogen test rights #12836 +INSERT INTO userroles_userrights (userrole_id, userright) +SELECT id, 'ENVIRONMENT_PATHOGEN_TEST_CREATE' +FROM public.userroles +WHERE userroles.linkeddefaultuserrole in ( + 'ADMIN', + 'LAB_USER', + 'NATIONAL_USER', + 'ENVIRONMENTAL_SURVEILLANCE_USER' + ); +INSERT INTO userroles_userrights (userrole_id, userright) +SELECT id, 'ENVIRONMENT_PATHOGEN_TEST_EDIT' +FROM public.userroles +WHERE userroles.linkeddefaultuserrole in ( + 'ADMIN', + 'LAB_USER', + 'NATIONAL_USER', + 'ENVIRONMENTAL_SURVEILLANCE_USER' + ); +INSERT INTO userroles_userrights (userrole_id, userright) +SELECT id, 'ENVIRONMENT_PATHOGEN_TEST_DELETE' +FROM public.userroles +WHERE userroles.linkeddefaultuserrole in ( + 'ADMIN', + 'NATIONAL_USER', + 'ENVIRONMENTAL_SURVEILLANCE_USER' + ); +DELETE FROM userroles_userrights WHERE (userright = 'SAMPLE_VIEW' OR userright = 'SAMPLE_EDIT' OR userright = 'PATHOGEN_TEST_CREATE' OR userright = 'PATHOGEN_TEST_EDIT') +AND userrole_id IN (SELECT id FROM public.userroles WHERE userroles.linkeddefaultuserrole = 'ENVIRONMENTAL_SURVEILLANCE_USER'); + +UPDATE userroles set changedate = now() WHERE linkeddefaultuserrole in ('ADMIN', 'LAB_USER', 'NATIONAL_USER', 'ENVIRONMENTAL_SURVEILLANCE_USER'); + +INSERT INTO schema_version (version_number, comment) VALUES (538, 'Introduce dedicated environment sample pathogen test rights #12836'); + +-- 2024-01-10 Add active column to customizable enum values #12804 +ALTER TABLE customizableenumvalue ADD COLUMN active boolean default true; +ALTER TABLE customizableenumvalue_history ADD COLUMN active boolean; + +INSERT INTO schema_version (version_number, comment) VALUES (539, 'Add active column to customizable enum values #12804'); + +-- *** Insert new sql commands BEFORE this line. Remember to always consider _history tables. *** diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/TestDataCreator.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/TestDataCreator.java index 6224a457d22..77c2e5a05e2 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/TestDataCreator.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/TestDataCreator.java @@ -2200,6 +2200,7 @@ public DiseaseVariant createDiseaseVariant(String name, Disease disease) { diseases.add(disease); diseaseVariant.setDiseases(diseases); diseaseVariant.setCaption(name + " variant"); + diseaseVariant.setActive(true); beanTest.getCustomizableEnumValueService().ensurePersisted(diseaseVariant); @@ -2212,6 +2213,7 @@ public Pathogen createPathogen(String value, String caption) { pathogen.setDataType(CustomizableEnumType.PATHOGEN); pathogen.setValue(value); pathogen.setCaption(caption); + pathogen.setActive(true); beanTest.getCustomizableEnumValueService().ensurePersisted(pathogen); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/caze/CaseFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/caze/CaseFacadeEjbPseudonymizationTest.java index 6124f987568..7e9a386605c 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/caze/CaseFacadeEjbPseudonymizationTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/caze/CaseFacadeEjbPseudonymizationTest.java @@ -29,8 +29,11 @@ import java.util.Calendar; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.List; +import javax.persistence.Query; + import org.junit.jupiter.api.Test; import de.symeda.sormas.api.Disease; @@ -44,6 +47,9 @@ import de.symeda.sormas.api.caze.CaseIndexDto; import de.symeda.sormas.api.caze.InvestigationStatus; import de.symeda.sormas.api.contact.ContactDto; +import de.symeda.sormas.api.feature.FeatureConfigurationIndexDto; +import de.symeda.sormas.api.feature.FeatureType; +import de.symeda.sormas.api.feature.FeatureTypeProperty; import de.symeda.sormas.api.infrastructure.area.AreaType; import de.symeda.sormas.api.infrastructure.community.CommunityDto; import de.symeda.sormas.api.infrastructure.facility.FacilityDto; @@ -60,8 +66,10 @@ import de.symeda.sormas.api.user.UserDto; import de.symeda.sormas.api.user.UserRight; import de.symeda.sormas.api.user.UserRoleReferenceDto; +import de.symeda.sormas.api.utils.DataHelper; import de.symeda.sormas.backend.AbstractBeanTest; import de.symeda.sormas.backend.TestDataCreator; +import de.symeda.sormas.backend.feature.FeatureConfiguration; public class CaseFacadeEjbPseudonymizationTest extends AbstractBeanTest { @@ -129,6 +137,71 @@ public void testGetCaseOutsideJurisdiction() { assertPseudonymized(getCaseFacade().getCaseDataByUuid(caze.getUuid())); } + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() { + // deactivate AUTOMATIC_RESPONSIBILITY_ASSIGNMENT in order to assign the limited user to a case from outside jurisdiction + FeatureConfigurationIndexDto featureConfiguration = + new FeatureConfigurationIndexDto(DataHelper.createUuid(), null, null, null, null, null, true, null); + getFeatureConfigurationFacade().saveFeatureConfiguration(featureConfiguration, FeatureType.CASE_SURVEILANCE); + + executeInTransaction(em -> { + Query query = em.createQuery("select f from featureconfiguration f"); + FeatureConfiguration singleResult = (FeatureConfiguration) query.getSingleResult(); + HashMap properties = new HashMap<>(); + properties.put(FeatureTypeProperty.AUTOMATIC_RESPONSIBILITY_ASSIGNMENT, false); + singleResult.setProperties(properties); + em.persist(singleResult); + }); + + loginWith(nationalAdmin); + + //case with same jurisdiction as limitedUser's + CaseDataDto caze1 = createCase(rdcf1, user1); + + //case with different jurisdiction from limited User's + CaseDataDto caze2 = createCase(rdcf2, user2); + + loginWith(nationalAdmin); + UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = + creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + CaseDataDto testCase = getCaseFacade().getCaseDataByUuid(caze1.getUuid()); + assertThat(testCase.isPseudonymized(), is(true)); + assertThat(testCase.getPerson().getFirstName(), is(emptyString())); + CaseDataDto testCase2 = getCaseFacade().getCaseDataByUuid(caze2.getUuid()); + assertThat(testCase2.isPseudonymized(), is(true)); + assertThat(testCase2.getPerson().getFirstName(), is(emptyString())); + + //case created by limited user in the same jurisdiction + CaseDataDto caze3 = createCase(rdcf1, surveillanceOfficerWithRestrictedAccessToAssignedEntities); + //case created by limited user outside limited user's jurisdiction + CaseDataDto caze4 = createCase(rdcf2, surveillanceOfficerWithRestrictedAccessToAssignedEntities); + + loginWith(nationalAdmin); + caze1.setSurveillanceOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getCaseFacade().save(caze1); + caze2.setSurveillanceOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getCaseFacade().save(caze2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + CaseDataDto testForCase1 = getCaseFacade().getCaseDataByUuid(caze1.getUuid()); + assertThat(testForCase1.isPseudonymized(), is(false)); + assertThat(testForCase1.getPerson().getFirstName(), is("James")); + + CaseDataDto testForCase2 = getCaseFacade().getCaseDataByUuid(caze2.getUuid()); + assertThat(testForCase2.isPseudonymized(), is(false)); + assertThat(testForCase2.getPerson().getFirstName(), is("James")); + + CaseDataDto testForCase3 = getCaseFacade().getCaseDataByUuid(caze3.getUuid()); + assertThat(testForCase3.isPseudonymized(), is(false)); + assertThat(testForCase3.getPerson().getFirstName(), is("James")); + + CaseDataDto testForCase4 = getCaseFacade().getCaseDataByUuid(caze4.getUuid()); + assertThat(testForCase4.isPseudonymized(), is(false)); + assertThat(testForCase4.getPerson().getFirstName(), is("James")); + } + @Test public void testPseudonymizeGetByUuids() { diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/caze/CaseFacadeEjbTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/caze/CaseFacadeEjbTest.java index f2ac3b6c7f2..0ffe2ad38f4 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/caze/CaseFacadeEjbTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/caze/CaseFacadeEjbTest.java @@ -46,6 +46,7 @@ import java.util.Calendar; import java.util.Collections; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -190,6 +191,7 @@ public class CaseFacadeEjbTest extends AbstractBeanTest { private RDCF rdcf; + private RDCF rdcf1; private UserDto nationalUser; private UserDto surveillanceSupervisor; private UserDto surveillanceOfficer; @@ -200,6 +202,7 @@ public void init() { super.init(); rdcf = creator.createRDCF("Region", "District", "Community", "Facility"); + rdcf1 = creator.createRDCF("Region1", "District1", "Community1", "Facility1"); surveillanceSupervisor = creator.createSurveillanceSupervisor(rdcf); surveillanceOfficer = creator.createSurveillanceOfficer(rdcf); surveillanceOfficerWithRestrictedAccessToAssignedEntities = creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf); @@ -821,7 +824,7 @@ public void testGetIndexListByEventFreeText() { @Test public void testGetIndexListByARestrictedAccessToAssignedEntities() { loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); - assertTrue(getCurrentUserService().hasRestrictedAccessToAssignedEntities()); + assertTrue(getCurrentUserService().isRestrictedToAssignedEntities()); String lastName = "Person"; PersonDto cazePerson = creator.createPerson("Case", lastName); @@ -883,6 +886,64 @@ public void testGetIndexListByARestrictedAccessToAssignedEntities() { assertEquals(1, results2.size()); } + @Test + public void testGetIndexListWithLimitedDisease() { + + String lastName = "Person"; + PersonDto cazePerson1 = creator.createPerson("Case1", lastName); + final CaseDataDto case1 = creator.createCase( + surveillanceOfficer.toReference(), + cazePerson1.toReference(), + Disease.EVD, + CaseClassification.PROBABLE, + InvestigationStatus.PENDING, + new Date(), + rdcf); + + PersonDto cazePerson2 = creator.createPerson("Case2", lastName); + final CaseDataDto case2 = creator.createCase( + surveillanceOfficer.toReference(), + cazePerson2.toReference(), + Disease.CORONAVIRUS, + CaseClassification.PROBABLE, + InvestigationStatus.PENDING, + new Date(), + rdcf); + + PersonDto cazePerson3 = creator.createPerson("Case3", lastName); + final CaseDataDto case3 = creator.createCase( + surveillanceOfficer.toReference(), + cazePerson3.toReference(), + Disease.EVD, + CaseClassification.PROBABLE, + InvestigationStatus.PENDING, + new Date(), + rdcf1); + + PersonDto cazePerson4 = creator.createPerson("Case2", lastName); + final CaseDataDto case4 = creator.createCase( + surveillanceOfficer.toReference(), + cazePerson4.toReference(), + Disease.CORONAVIRUS, + CaseClassification.PROBABLE, + InvestigationStatus.PENDING, + new Date(), + rdcf1); + + loginWith(nationalAdmin); + Set diseaseList = new HashSet<>(); + diseaseList.add(Disease.CORONAVIRUS); + surveillanceOfficer.setLimitedDiseases(diseaseList); + getUserFacade().saveUser(surveillanceOfficer, false); + + loginWith(surveillanceOfficer); + assertEquals(2, getCaseFacade().getIndexList(null, 0, 100, null).size()); + + CaseCriteria caseCriteria = new CaseCriteria(); + caseCriteria.setIncludeCasesFromOtherJurisdictions(true); + assertEquals(4, getCaseFacade().getIndexList(caseCriteria, 0, 100, null).size()); + } + @Test public void testCaseExportWithPrescriptionsTreatmentsVisits() { diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/contact/ContactFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/contact/ContactFacadeEjbPseudonymizationTest.java index d32e306f745..9c2a06c9e23 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/contact/ContactFacadeEjbPseudonymizationTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/contact/ContactFacadeEjbPseudonymizationTest.java @@ -18,6 +18,7 @@ package de.symeda.sormas.backend.contact; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyString; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.not; @@ -127,6 +128,65 @@ public void testGetContactOutsideJurisdiction() { assertPseudonymized(getContactFacade().getByUuid(contact.getUuid())); } + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() { + + // contact & case within limited user's jurisdiction + CaseDataDto caze1 = createCase(user1, rdcf1); + ContactDto contact1 = createContact(user1, caze1, rdcf1); + + // contact & case outside limited user's jurisdiction + CaseDataDto caze2 = createCase(user2, rdcf2); + ContactDto contact2 = createContact(user2, caze2, rdcf2); + + loginWith(nationalAdmin); + UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = + creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + ContactDto testContact1 = getContactFacade().getByUuid(contact1.getUuid()); + assertThat(testContact1.isPseudonymized(), is(true)); + assertThat(testContact1.getPerson().getFirstName(), is(emptyString())); + + ContactDto testContact2 = getContactFacade().getByUuid(contact2.getUuid()); + assertThat(testContact2.isPseudonymized(), is(true)); + assertThat(testContact2.getPerson().getFirstName(), is(emptyString())); + + //contact created by limited user in the same jurisdiction + ContactDto contact3 = createContact(surveillanceOfficerWithRestrictedAccessToAssignedEntities, null, rdcf1); + //contact created by limited user outside limited user's jurisdiction + ContactDto contact4 = createContact(surveillanceOfficerWithRestrictedAccessToAssignedEntities, null, rdcf2); + + loginWith(nationalAdmin); + contact1.setContactOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getContactFacade().save(contact1); + contact2.setContactOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getContactFacade().save(contact2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + ContactDto testForContact1 = getContactFacade().getByUuid(contact1.getUuid()); + assertThat(testForContact1.isPseudonymized(), is(false)); + assertThat(testForContact1.getPerson().getFirstName(), is("James")); + CaseDataDto testForCase1 = getCaseFacade().getCaseDataByUuid(caze1.getUuid()); + assertThat(testForCase1.isPseudonymized(), is(true)); + assertThat(testForCase1.getPerson().getFirstName(), is(emptyString())); + + ContactDto testForContact2 = getContactFacade().getByUuid(contact2.getUuid()); + assertThat(testForContact2.isPseudonymized(), is(false)); + assertThat(testForContact2.getPerson().getFirstName(), is("James")); + CaseDataDto testForCase2 = getCaseFacade().getCaseDataByUuid(caze2.getUuid()); + assertThat(testForCase2.isPseudonymized(), is(true)); + assertThat(testForCase2.getPerson().getFirstName(), is(emptyString())); + + ContactDto testForContact3 = getContactFacade().getByUuid(contact3.getUuid()); + assertThat(testForContact3.isPseudonymized(), is(false)); + assertThat(testForContact3.getPerson().getFirstName(), is("James")); + + ContactDto testForContact4 = getContactFacade().getByUuid(contact4.getUuid()); + assertThat(testForContact4.isPseudonymized(), is(false)); + assertThat(testForContact4.getPerson().getFirstName(), is("James")); + } + @Test public void testPseudonymizeGetByUuids() { CaseDataDto caze = createCase(user1, rdcf1); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/contact/ContactFacadeEjbTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/contact/ContactFacadeEjbTest.java index afdfcc9b9b9..05ab41ee2ee 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/contact/ContactFacadeEjbTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/contact/ContactFacadeEjbTest.java @@ -38,7 +38,9 @@ import java.util.Arrays; import java.util.Collections; import java.util.Date; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -1019,7 +1021,7 @@ public void testGetIndexListByARestrictedAccessToAssignedEntities() { UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf); loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); - assertTrue(getCurrentUserService().hasRestrictedAccessToAssignedEntities()); + assertTrue(getCurrentUserService().isRestrictedToAssignedEntities()); final List indexList = getContactFacade().getIndexList(null, 0, 100, null); assertEquals(0, indexList.size()); @@ -1036,6 +1038,57 @@ public void testGetIndexListByARestrictedAccessToAssignedEntities() { assertEquals(2, getContactFacade().getIndexList(null, 0, 100, null).size()); } + @Test + public void testGetIndexListWithLimitedDisease() { + RDCF rdcf1 = creator.createRDCF("Region1", "District1", "Community1", "Facility1", "PointOfEntry1"); + RDCF rdcf2 = creator.createRDCF("Region2", "District2", "Community2", "Facility2", "PointOfEntry2"); + + final UserDto surveillanceOfficer = creator.createSurveillanceOfficer(rdcf1); + + PersonDto contactPerson = creator.createPerson("Contact", "Person"); + final ContactDto contact = creator.createContact( + surveillanceOfficer.toReference(), + null, + contactPerson.toReference(), + null, + new Date(), + new Date(), + Disease.CORONAVIRUS, + rdcf1); + + PersonDto contactPerson2 = creator.createPerson("Contact2", "Person2"); + final ContactDto contact2 = creator + .createContact(surveillanceOfficer.toReference(), null, contactPerson2.toReference(), null, new Date(), new Date(), Disease.EVD, rdcf1); + + PersonDto contactPerson3 = creator.createPerson("Contact3", "Person3"); + final ContactDto contact3 = creator.createContact( + surveillanceOfficer.toReference(), + null, + contactPerson3.toReference(), + null, + new Date(), + new Date(), + Disease.CORONAVIRUS, + rdcf2); + + PersonDto contactPerson4 = creator.createPerson("Contact3", "Person3"); + final ContactDto contact4 = creator + .createContact(surveillanceOfficer.toReference(), null, contactPerson4.toReference(), null, new Date(), new Date(), Disease.EVD, rdcf2); + + loginWith(nationalAdmin); + Set diseaseList = new HashSet<>(); + diseaseList.add(Disease.CORONAVIRUS); + surveillanceOfficer.setLimitedDiseases(diseaseList); + getUserFacade().saveUser(surveillanceOfficer, false); + + loginWith(surveillanceOfficer); + assertEquals(2, getContactFacade().getIndexList(new ContactCriteria(), 0, 100, null).size()); + + ContactCriteria contactCriteria = new ContactCriteria(); + contactCriteria.setIncludeContactsFromOtherJurisdictions(true); + assertEquals(4, getContactFacade().getIndexList(contactCriteria, 0, 100, null).size()); + } + @Test public void testGetContactCountsByCasesForDashboard() { diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumFacadeEjbTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumFacadeEjbTest.java index 75828d3238a..fc939ee2b92 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumFacadeEjbTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/customizableenum/CustomizableEnumFacadeEjbTest.java @@ -29,12 +29,14 @@ public void createCustomEnums() { diseases.add(Disease.CORONAVIRUS); entry.setDiseases(diseases); entry.setCaption("BF.1.2 variant"); + entry.setActive(true); getCustomizableEnumValueService().ensurePersisted(entry); entry = new CustomizableEnumValue(); entry.setDataType(CustomizableEnumType.DISEASE_VARIANT); entry.setValue("GENERIC"); entry.setCaption("Variant 2"); + entry.setActive(true); getCustomizableEnumValueService().ensurePersisted(entry); getCustomizableEnumFacade().loadData(); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/docgeneration/TemplateTestUtil.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/docgeneration/TemplateTestUtil.java index 6d6cdb9b14d..055de0fa86a 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/docgeneration/TemplateTestUtil.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/docgeneration/TemplateTestUtil.java @@ -51,4 +51,13 @@ public static void writeJsonProperty(Object object) throws JsonProcessingExcepti public static String cleanLineSeparators(String text) { return text.replaceAll("\\r\\n?", "\n"); } + + public static String updateLineSeparatorsBasedOnOS(String text) { + if (System.lineSeparator().equals("\r\n")) { + return text; + } else { + return text.replaceAll("\\r\\n?", "\n"); + } + } + } diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/EnvironmentFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/EnvironmentFacadeEjbPseudonymizationTest.java new file mode 100644 index 00000000000..1a4e187121e --- /dev/null +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/EnvironmentFacadeEjbPseudonymizationTest.java @@ -0,0 +1,102 @@ +package de.symeda.sormas.backend.environment; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyString; +import static org.hamcrest.Matchers.is; + +import org.junit.jupiter.api.Test; + +import de.symeda.sormas.api.environment.EnvironmentDto; +import de.symeda.sormas.api.environment.EnvironmentMedia; +import de.symeda.sormas.api.user.UserDto; +import de.symeda.sormas.backend.AbstractBeanTest; +import de.symeda.sormas.backend.TestDataCreator; + +public class EnvironmentFacadeEjbPseudonymizationTest extends AbstractBeanTest { + + private TestDataCreator.RDCF rdcf1; + private TestDataCreator.RDCF rdcf2; + private UserDto surveillanceOfficer1; + private UserDto nationalUser; + private UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities; + + @Override + public void init() { + + super.init(); + rdcf1 = creator.createRDCF("Region 1", "District 1", "Community 1", "Facility 1", "Point of entry 1"); + rdcf2 = creator.createRDCF("Region 2", "District 2", "Community 2", "Facility 2", "Point of entry 2"); + surveillanceOfficer1 = creator.createSurveillanceOfficer(rdcf1); + nationalUser = creator.createNationalUser(); + surveillanceOfficerWithRestrictedAccessToAssignedEntities = creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + } + + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() { + + //environment with same jurisdiction as limitedUser's + EnvironmentDto environment1 = creator.createEnvironment( + "Test Environment", + EnvironmentMedia.WATER, + surveillanceOfficer1.toReference(), + rdcf1, + (e) -> e.getLocation().setStreet("Main street")); + + //environment with different jurisdiction from limited User's + EnvironmentDto environment2 = creator.createEnvironment( + "Test Environment", + EnvironmentMedia.WATER, + nationalUser.toReference(), + rdcf2, + (e) -> e.getLocation().setStreet("Main street second")); + + //environment created by limited user in the same jurisdiction + EnvironmentDto environment3 = creator.createEnvironment( + "Test Environment", + EnvironmentMedia.WATER, + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + rdcf1, + (e) -> e.getLocation().setStreet("Main street third")); + + //environment created by limited user outside limited user's jurisdiction + EnvironmentDto environment4 = creator.createEnvironment( + "Test Environment", + EnvironmentMedia.WATER, + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + rdcf2, + (e) -> e.getLocation().setStreet("Main street fourth")); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + EnvironmentDto testEnvironment1 = getEnvironmentFacade().getByUuid(environment1.getUuid()); + assertThat(testEnvironment1.isPseudonymized(), is(true)); + assertThat(testEnvironment1.getLocation().getStreet(), is(emptyString())); + + EnvironmentDto testEnvironment2 = getEnvironmentFacade().getByUuid(environment2.getUuid()); + assertThat(testEnvironment2.isPseudonymized(), is(true)); + assertThat(testEnvironment2.getLocation().getStreet(), is(emptyString())); + + loginWith(nationalUser); + environment1.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getEnvironmentFacade().save(environment1); + environment2.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getEnvironmentFacade().save(environment2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + EnvironmentDto testForEnvironment1 = getEnvironmentFacade().getByUuid(environment1.getUuid()); + assertThat(testForEnvironment1.isPseudonymized(), is(false)); + assertThat(testForEnvironment1.getLocation().getStreet(), is("Main street")); + + EnvironmentDto testForEnvironment2 = getEnvironmentFacade().getByUuid(environment2.getUuid()); + assertThat(testForEnvironment2.isPseudonymized(), is(false)); + assertThat(testForEnvironment2.getLocation().getStreet(), is("Main street second")); + + EnvironmentDto testForEnvironment3 = getEnvironmentFacade().getByUuid(environment3.getUuid()); + assertThat(testForEnvironment3.isPseudonymized(), is(false)); + assertThat(testForEnvironment3.getLocation().getStreet(), is("Main street third")); + + EnvironmentDto testForEnvironment4 = getEnvironmentFacade().getByUuid(environment4.getUuid()); + assertThat(testForEnvironment4.isPseudonymized(), is(false)); + assertThat(testForEnvironment4.getLocation().getStreet(), is("Main street fourth")); + } + +} diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/EnvironmentFacadeEjbTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/EnvironmentFacadeEjbTest.java index 71d7acd86af..d85b20d5479 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/EnvironmentFacadeEjbTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/EnvironmentFacadeEjbTest.java @@ -128,7 +128,7 @@ public void testGetIndexListByARestrictedAccessToAssignedEntities() { UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); - assertTrue(getCurrentUserService().hasRestrictedAccessToAssignedEntities()); + assertTrue(getCurrentUserService().isRestrictedToAssignedEntities()); assertEquals(0, getEnvironmentFacade().getIndexList(new EnvironmentCriteria(), 0, 100, null).size()); loginWith(user); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbPseudonymizationTest.java new file mode 100644 index 00000000000..a050abfa006 --- /dev/null +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbPseudonymizationTest.java @@ -0,0 +1,166 @@ +package de.symeda.sormas.backend.environment.environmentsample; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyString; +import static org.hamcrest.Matchers.is; + +import org.junit.jupiter.api.Test; + +import de.symeda.sormas.api.environment.EnvironmentDto; +import de.symeda.sormas.api.environment.EnvironmentMedia; +import de.symeda.sormas.api.environment.environmentsample.EnvironmentSampleDto; +import de.symeda.sormas.api.environment.environmentsample.EnvironmentSampleMaterial; +import de.symeda.sormas.api.infrastructure.facility.FacilityDto; +import de.symeda.sormas.api.infrastructure.facility.FacilityType; +import de.symeda.sormas.api.user.DefaultUserRole; +import de.symeda.sormas.api.user.UserDto; +import de.symeda.sormas.backend.AbstractBeanTest; +import de.symeda.sormas.backend.TestDataCreator; + +public class EnvironmentSampleFacadeEjbPseudonymizationTest extends AbstractBeanTest { + + private TestDataCreator.RDCF rdcf1; + private FacilityDto lab1; + private FacilityDto lab2; + private UserDto reportingUser; + UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities; + private EnvironmentDto environment1; + private EnvironmentDto environment2; + private EnvironmentDto environment3; + private EnvironmentDto environment4; + + private TestDataCreator.RDCF rdcf2; + private UserDto userInDifferentJurisdiction; + + @Override + public void init() { + super.init(); + + rdcf1 = creator.createRDCF(); + rdcf2 = creator.createRDCF(); + lab1 = creator.createFacility("Lab", rdcf1.region, rdcf1.district, rdcf1.community, FacilityType.LABORATORY); + lab2 = creator.createFacility("Lab2", rdcf2.region, rdcf2.district, rdcf2.community, FacilityType.LABORATORY); + + reportingUser = creator.createUser(rdcf1, creator.getUserRoleReference(DefaultUserRole.ENVIRONMENTAL_SURVEILLANCE_USER)); + userInDifferentJurisdiction = + creator.createUser(rdcf2, "Env", "Surv2", creator.getUserRoleReference(DefaultUserRole.ENVIRONMENTAL_SURVEILLANCE_USER)); + surveillanceOfficerWithRestrictedAccessToAssignedEntities = creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + + environment1 = creator.createEnvironment("Test env", EnvironmentMedia.WATER, reportingUser.toReference(), rdcf1); + environment2 = creator.createEnvironment("Test environment 2", EnvironmentMedia.AIR, userInDifferentJurisdiction.toReference(), rdcf2); + environment3 = creator.createEnvironment( + "Test environment 3", + EnvironmentMedia.AIR, + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + rdcf2); + environment4 = creator.createEnvironment( + "Test environment 4", + EnvironmentMedia.AIR, + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + rdcf2); + } + + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() { + + // environment within limited user's jurisdiction + EnvironmentSampleDto sample1 = + creator.createEnvironmentSample(environment1.toReference(), reportingUser.toReference(), rdcf1, lab1.toReference(), s -> { + s.setSampleMaterial(EnvironmentSampleMaterial.OTHER); + s.setOtherSampleMaterial("Test material"); + s.setFieldSampleId("Test id"); + s.setLaboratoryDetails("Test lab details"); + s.setOtherRequestedPathogenTests("Test pathogen tests"); + s.setDispatched(true); + s.setDispatchDetails("Test dispatch details"); + s.setLabSampleId("Test lab sample id"); + s.setGeneralComment("Test comment"); + s.getLocation().setCity("Test city"); + }); + + // environment outside limited user's jurisdiction + EnvironmentSampleDto sample2 = + creator.createEnvironmentSample(environment2.toReference(), userInDifferentJurisdiction.toReference(), rdcf2, lab2.toReference(), s -> { + s.setSampleMaterial(EnvironmentSampleMaterial.OTHER); + s.setOtherSampleMaterial("Test material second"); + s.setFieldSampleId("Test id second"); + s.setLaboratoryDetails("Test lab details second"); + s.setOtherRequestedPathogenTests("Test pathogen tests second"); + s.setDispatched(true); + s.setDispatchDetails("Test dispatch details second"); + s.setLabSampleId("Test lab sample id second"); + s.setGeneralComment("Test comment second"); + s.getLocation().setCity("Test city second"); + }); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + EnvironmentSampleDto testSample1 = getEnvironmentSampleFacade().getByUuid(sample1.getUuid()); + assertThat(testSample1.isPseudonymized(), is(true)); + assertThat(testSample1.getOtherSampleMaterial(), is(emptyString())); + EnvironmentSampleDto testSample2 = getEnvironmentSampleFacade().getByUuid(sample2.getUuid()); + assertThat(testSample2.isPseudonymized(), is(true)); + assertThat(testSample2.getOtherSampleMaterial(), is(emptyString())); + + // environment within limited user's jurisdiction + loginWith(nationalAdmin); + EnvironmentSampleDto sample3 = creator.createEnvironmentSample( + environment3.toReference(), + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + rdcf1, + lab1.toReference(), + s -> { + s.setSampleMaterial(EnvironmentSampleMaterial.OTHER); + s.setOtherSampleMaterial("Test material third"); + s.setFieldSampleId("Test id third"); + s.setLaboratoryDetails("Test lab details third"); + s.setOtherRequestedPathogenTests("Test pathogen tests third"); + s.setDispatched(true); + s.setDispatchDetails("Test dispatch details third"); + s.setLabSampleId("Test lab sample id third"); + s.setGeneralComment("Test comment third"); + s.getLocation().setCity("Test city third"); + }); + + // environment outside limited user's jurisdiction + EnvironmentSampleDto sample4 = creator.createEnvironmentSample( + environment4.toReference(), + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + rdcf2, + lab2.toReference(), + s -> { + s.setSampleMaterial(EnvironmentSampleMaterial.OTHER); + s.setOtherSampleMaterial("Test material fourth"); + s.setFieldSampleId("Test id fourth"); + s.setLaboratoryDetails("Test lab details fourth"); + s.setOtherRequestedPathogenTests("Test pathogen tests fourth"); + s.setDispatched(true); + s.setDispatchDetails("Test dispatch details fourth"); + s.setLabSampleId("Test lab sample id fourth"); + s.setGeneralComment("Test comment fourth"); + s.getLocation().setCity("Test city fourth"); + }); + +// loginWith(nationalAdmin); + environment1.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getEnvironmentFacade().save(environment1); + environment2.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getEnvironmentFacade().save(environment2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + EnvironmentSampleDto returnTestSample1 = getEnvironmentSampleFacade().getByUuid(sample1.getUuid()); + assertThat(returnTestSample1.isPseudonymized(), is(false)); + assertThat(returnTestSample1.getOtherSampleMaterial(), is("Test material")); + + EnvironmentSampleDto returnTestSample2 = getEnvironmentSampleFacade().getByUuid(sample2.getUuid()); + assertThat(returnTestSample2.isPseudonymized(), is(false)); + assertThat(returnTestSample2.getOtherSampleMaterial(), is("Test material second")); + + EnvironmentSampleDto returnTestSample3 = getEnvironmentSampleFacade().getByUuid(sample3.getUuid()); + assertThat(returnTestSample3.isPseudonymized(), is(false)); + assertThat(returnTestSample3.getOtherSampleMaterial(), is("Test material third")); + + EnvironmentSampleDto returnTestSample4 = getEnvironmentSampleFacade().getByUuid(sample4.getUuid()); + assertThat(returnTestSample4.isPseudonymized(), is(false)); + assertThat(returnTestSample4.getOtherSampleMaterial(), is("Test material fourth")); + } +} diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbTest.java index c2d3e71eb49..c993b2d4fe2 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/environment/environmentsample/EnvironmentSampleFacadeEjbTest.java @@ -528,6 +528,7 @@ public void testGetIndexList() { @Test public void testGetIndexListWithRestrictedAccessToAssignedEntities() { + loginWith(nationalAdmin); EnvironmentSampleDto environmentSample = creator.createEnvironmentSample(environment.toReference(), reportingUser.toReference(), rdcf, lab.toReference(), s -> { s.setFieldSampleId("field_sample-1"); @@ -543,6 +544,9 @@ public void testGetIndexListWithRestrictedAccessToAssignedEntities() { s.setSampleMaterial(EnvironmentSampleMaterial.OTHER); s.setOtherSampleMaterial("Other sample material"); }); + environment.setResponsibleUser(reportingUser.toReference()); + getEnvironmentFacade().save(environment); + Pathogen positivePathogen = creator.createPathogen("TEST_PATHOGEN", "Test pathogen"); PathogenTestDto positiveTest = creator.createPathogenTest( environmentSample.toReference(), @@ -554,10 +558,12 @@ public void testGetIndexListWithRestrictedAccessToAssignedEntities() { null); assertThat(getEnvironmentSampleFacade().getIndexList(null, null, null, null), hasSize(1)); + loginWith(nationalAdmin); UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf); + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); - assertTrue(getCurrentUserService().hasRestrictedAccessToAssignedEntities()); + assertTrue(getCurrentUserService().isRestrictedToAssignedEntities()); assertThat(getEnvironmentSampleFacade().getIndexList(null, null, null, null), hasSize(0)); } diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventFacadeEjbPseudonymizationTest.java index 9e498756eef..e099bb843e8 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventFacadeEjbPseudonymizationTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventFacadeEjbPseudonymizationTest.java @@ -16,6 +16,7 @@ package de.symeda.sormas.backend.event; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyString; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; @@ -93,6 +94,82 @@ public void testEventOutsideJurisdiction() { assertPseudonymized(getEventFacade().getEventByUuid(event.getUuid(), false)); } + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() { + + loginWith(nationalAdmin); + + // event within limited user's jurisdiction + EventDto event1 = creator + .createEvent(EventStatus.SIGNAL, EventInvestigationStatus.PENDING, "Test title", "Test Description", user1.toReference(), rdcf1, e -> { + e.setConnectionNumber("123"); + }); + + // event outside limited user's jurisdiction + EventDto event2 = creator + .createEvent(EventStatus.SIGNAL, EventInvestigationStatus.PENDING, "Test title", "Test Description", user2.toReference(), rdcf2, e -> { + e.setConnectionNumber("456"); + }); + + UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = + creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + final EventDto testEvent1 = getEventFacade().getEventByUuid(event1.getUuid(), false); + assertThat(testEvent1.isPseudonymized(), is(true)); + assertThat(testEvent1.getConnectionNumber(), is(emptyString())); + final EventDto testEvent2 = getEventFacade().getEventByUuid(event2.getUuid(), false); + assertThat(testEvent2.isPseudonymized(), is(true)); + assertThat(testEvent2.getConnectionNumber(), is(emptyString())); + + //event created by limited user in the same jurisdiction + EventDto event3 = creator.createEvent( + EventStatus.SIGNAL, + EventInvestigationStatus.PENDING, + "Test title", + "Test Description", + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + rdcf1, + e -> { + e.setConnectionNumber("789"); + }); + + //event created by limited user outside limited user's jurisdiction + EventDto event4 = creator.createEvent( + EventStatus.SIGNAL, + EventInvestigationStatus.PENDING, + "Test title", + "Test Description", + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + rdcf2, + e -> { + e.setConnectionNumber("987"); + }); + + loginWith(nationalAdmin); + testEvent1.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getEventFacade().save(testEvent1); + testEvent2.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getEventFacade().save(testEvent2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + final EventDto testForEvent1 = getEventFacade().getEventByUuid(event1.getUuid(), false); + assertThat(testForEvent1.isPseudonymized(), is(false)); + assertThat(testForEvent1.getConnectionNumber(), is("123")); + + final EventDto testForEvent2 = getEventFacade().getEventByUuid(event2.getUuid(), false); + assertThat(testForEvent2.isPseudonymized(), is(false)); + assertThat(testForEvent2.getConnectionNumber(), is("456")); + + final EventDto testForEvent3 = getEventFacade().getEventByUuid(event3.getUuid(), false); + assertThat(testForEvent3.isPseudonymized(), is(false)); + assertThat(testForEvent3.getConnectionNumber(), is("789")); + + final EventDto testForEvent4 = getEventFacade().getEventByUuid(event4.getUuid(), false); + assertThat(testForEvent4.isPseudonymized(), is(false)); + assertThat(testForEvent4.getConnectionNumber(), is("987")); + } + @Test public void testUpdatePseudonymizedEvent() { EventDto event = createEvent(user2, rdcf2); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventFacadeEjbTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventFacadeEjbTest.java index d21d495c443..59c4323610c 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventFacadeEjbTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventFacadeEjbTest.java @@ -278,7 +278,7 @@ public void testGetIndexListByARestrictedAccessToAssignedEntities() { event.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); getEventFacade().save(event); loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); - assertTrue(getCurrentUserService().hasRestrictedAccessToAssignedEntities()); + assertTrue(getCurrentUserService().isRestrictedToAssignedEntities()); List results3 = getEventFacade().getIndexList(eventCriteria, 0, 100, null); assertEquals(1, results3.size()); } diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjbPseudonymizationTest.java index bc31fc63b1e..573b1334772 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjbPseudonymizationTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjbPseudonymizationTest.java @@ -16,6 +16,7 @@ package de.symeda.sormas.backend.event; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyString; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.notNullValue; @@ -23,6 +24,7 @@ import java.util.Arrays; import java.util.List; +import java.util.function.Consumer; import org.junit.jupiter.api.Test; @@ -87,6 +89,78 @@ public void testEventParticipantOutsideJurisdiction() { assertPseudonymized(getEventParticipantFacade().getEventParticipantByUuid(eventParticipant.getUuid())); } + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() { + loginWith(nationalAdmin); + + // event within limited user's jurisdiction + EventParticipantDto eventParticipant1 = createEventParticipant(user1, rdcf1, e -> e.setConnectionNumber("123")); + + // event outside limited user's jurisdiction + EventParticipantDto eventParticipant2 = createEventParticipant(user2, rdcf2, e -> e.setConnectionNumber("456")); + + UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = + creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + final EventDto testEvent1 = getEventFacade().getEventByUuid(eventParticipant1.getEvent().getUuid(), false); + assertThat(testEvent1.isPseudonymized(), is(true)); + assertThat(testEvent1.getConnectionNumber(), is(emptyString())); + final EventParticipantDto testEventParticipant1 = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant1.getUuid()); + assertThat(testEventParticipant1.isPseudonymized(), is(true)); + assertThat(testEventParticipant1.getPerson().getFirstName(), is("Confidential")); + + final EventDto testEvent1Second = getEventFacade().getEventByUuid(eventParticipant2.getEvent().getUuid(), false); + assertThat(testEvent1Second.isPseudonymized(), is(true)); + assertThat(testEvent1Second.getConnectionNumber(), is(emptyString())); + final EventParticipantDto testEventParticipant1Second = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant2.getUuid()); + assertThat(testEventParticipant1Second.isPseudonymized(), is(true)); + assertThat(testEventParticipant1Second.getPerson().getFirstName(), is("Confidential")); + + // event created by limited user in the same jurisdiction + EventParticipantDto eventParticipant3 = + createEventParticipant(surveillanceOfficerWithRestrictedAccessToAssignedEntities, rdcf1, e -> e.setConnectionNumber("789")); + + // event created by limited user outside it's jurisdiction + EventParticipantDto eventParticipant4 = + createEventParticipant(surveillanceOfficerWithRestrictedAccessToAssignedEntities, rdcf2, e -> e.setConnectionNumber("987")); + + loginWith(nationalAdmin); + testEvent1.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getEventFacade().save(testEvent1); + testEvent1Second.setResponsibleUser(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getEventFacade().save(testEvent1Second); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + final EventDto testEvent3 = getEventFacade().getEventByUuid(eventParticipant1.getEvent().getUuid(), false); + assertThat(testEvent3.isPseudonymized(), is(false)); + assertThat(testEvent3.getConnectionNumber(), is("123")); + final EventParticipantDto testEventParticipant3 = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant1.getUuid()); + assertThat(testEventParticipant3.isPseudonymized(), is(false)); + assertThat(testEventParticipant3.getPerson().getFirstName(), is("John")); + + final EventDto testEvent3Second = getEventFacade().getEventByUuid(eventParticipant2.getEvent().getUuid(), false); + assertThat(testEvent3Second.isPseudonymized(), is(false)); + assertThat(testEvent3Second.getConnectionNumber(), is("456")); + final EventParticipantDto testEventParticipant3Second = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant2.getUuid()); + assertThat(testEventParticipant3Second.isPseudonymized(), is(false)); + assertThat(testEventParticipant3Second.getPerson().getFirstName(), is("John")); + + final EventDto testEvent3Third = getEventFacade().getEventByUuid(eventParticipant3.getEvent().getUuid(), false); + assertThat(testEvent3Third.isPseudonymized(), is(false)); + assertThat(testEvent3Third.getConnectionNumber(), is("789")); + final EventParticipantDto testEventParticipant3Third = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant3.getUuid()); + assertThat(testEventParticipant3Third.isPseudonymized(), is(false)); + assertThat(testEventParticipant3Third.getPerson().getFirstName(), is("John")); + + final EventDto testEvent3Fourth = getEventFacade().getEventByUuid(eventParticipant4.getEvent().getUuid(), false); + assertThat(testEvent3Fourth.isPseudonymized(), is(false)); + assertThat(testEvent3Fourth.getConnectionNumber(), is("987")); + final EventParticipantDto testEventParticipant3Fourth = getEventParticipantFacade().getEventParticipantByUuid(eventParticipant4.getUuid()); + assertThat(testEventParticipant3Fourth.isPseudonymized(), is(false)); + assertThat(testEventParticipant3Fourth.getPerson().getFirstName(), is("John")); + } + @Test public void testPseudonymizeGetByUuids() { EventParticipantDto eventParticipant1 = createEventParticipant(user2, rdcf2); @@ -163,10 +237,17 @@ public void testUpdateWithPseudonymizedDto() { } private EventParticipantDto createEventParticipant(UserDto user, TestDataCreator.RDCF rdcf) { + return createEventParticipant(user, rdcf, null); + } + + private EventParticipantDto createEventParticipant(UserDto user, TestDataCreator.RDCF rdcf, Consumer eventCustomSettings) { EventDto event = creator.createEvent(EventStatus.SIGNAL, EventInvestigationStatus.PENDING, "", "", user.toReference(), null, e -> { e.getEventLocation().setRegion(rdcf.region); e.getEventLocation().setDistrict(rdcf.district); e.getEventLocation().setCommunity(rdcf.community); + if (eventCustomSettings != null) { + eventCustomSettings.accept(e); + } }); PersonDto person = creator.createPerson("John", "Smith", Sex.MALE, 1980, 10, 23, p -> { diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/externalemail/ExternalEmailFacadeEjbTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/externalemail/ExternalEmailFacadeEjbTest.java index 8ee42d2a627..bf07b5b8738 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/externalemail/ExternalEmailFacadeEjbTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/externalemail/ExternalEmailFacadeEjbTest.java @@ -15,8 +15,8 @@ package de.symeda.sormas.backend.externalemail; -import static de.symeda.sormas.backend.docgeneration.TemplateTestUtil.cleanLineSeparators; -import static de.symeda.sormas.backend.externalemail.luxembourg.NationalHealthIdValidatorTest.VALID_LU_NATIONAL_HEALTH_ID; +import static de.symeda.sormas.backend.docgeneration.TemplateTestUtil.updateLineSeparatorsBasedOnOS; +import static de.symeda.sormas.backend.util.luxembourg.LuxembourgNationalHealthIdValidatorTest.VALID_LU_NATIONAL_HEALTH_ID; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.hasItem; @@ -260,7 +260,7 @@ public void testIsAttachmentAvailableForLuxembourg() { } @Test - public void testSendEmailToCasePerson() throws DocumentTemplateException, ExternalEmailException, MessagingException, IOException { + public void testSendEmailToCasePerson() throws DocumentTemplateException, ExternalEmailException, MessagingException { CaseDataDto caze = creator.createCase(userDto.toReference(), personDto.toReference(), rdcf); @@ -270,7 +270,7 @@ public void testSendEmailToCasePerson() throws DocumentTemplateException, Extern StringWriter writer = new StringWriter(); IOUtils.copy(getClass().getResourceAsStream("/docgeneration/emailTemplates/cases/CaseEmail.cmp"), writer, "UTF-8"); - String expectedContent = cleanLineSeparators(writer.toString()); + String expectedContent = updateLineSeparatorsBasedOnOS(writer.toString()); assertThat(invocation.getArgument(2), is(expectedContent)); @@ -294,7 +294,7 @@ public void testSendEmailToCasePerson() throws DocumentTemplateException, Extern } @Test - public void testSendEmailToContactPerson() throws DocumentTemplateException, ExternalEmailException, MessagingException, IOException { + public void testSendEmailToContactPerson() throws DocumentTemplateException, ExternalEmailException, MessagingException { ContactDto contact = creator.createContact(userDto.toReference(), personDto.toReference(), Disease.CORONAVIRUS, (c) -> { c.setContactStatus(ContactStatus.ACTIVE); @@ -307,7 +307,7 @@ public void testSendEmailToContactPerson() throws DocumentTemplateException, Ext StringWriter writer = new StringWriter(); IOUtils.copy(getClass().getResourceAsStream("/docgeneration/emailTemplates/contacts/ContactEmail.cmp"), writer, "UTF-8"); - String expectedContent = cleanLineSeparators(writer.toString()); + String expectedContent = updateLineSeparatorsBasedOnOS(writer.toString()); assertThat(invocation.getArgument(2), is(expectedContent)); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/externalemail/luxembourg/NationalHealthIdValidatorTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/externalemail/luxembourg/NationalHealthIdValidatorTest.java deleted file mode 100644 index cf4d55517c7..00000000000 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/externalemail/luxembourg/NationalHealthIdValidatorTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * SORMAS® - Surveillance Outbreak Response Management & Analysis System - * Copyright © 2016-2023 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package de.symeda.sormas.backend.externalemail.luxembourg; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; - -import org.jetbrains.annotations.NotNull; -import org.junit.jupiter.api.Test; - -import de.symeda.sormas.backend.person.Person; - -public class NationalHealthIdValidatorTest { - - public static final String VALID_LU_NATIONAL_HEALTH_ID = "1980010145728"; - - @Test - public void testIsValid() { - assertThat(NationalHealthIdValidator.isValid("19800101", createPerson(1980, 1, 1)), is(false)); - assertThat(NationalHealthIdValidator.isValid("1980Jan0145728", createPerson(1980, 1, 1)), is(false)); - assertThat(NationalHealthIdValidator.isValid("1980Ja0145728", createPerson(1980, 1, 1)), is(false)); - - assertThat(NationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, createPerson(1980, 1, 1)), is(true)); - assertThat(NationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, createPerson(null, 1, 1)), is(true)); - assertThat(NationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, createPerson(1980, 1, null)), is(true)); - assertThat(NationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, createPerson(1980, null, 1)), is(true)); - assertThat(NationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, createPerson(1980, null, null)), is(true)); - assertThat(NationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, createPerson(null, null, null)), is(true)); - - assertThat(NationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, createPerson(1981, 1, 1)), is(false)); - assertThat(NationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, createPerson(1980, 2, 1)), is(false)); - assertThat(NationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, createPerson(1980, 1, 2)), is(false)); - assertThat(NationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, createPerson(1981, 1, null)), is(false)); - - assertThat(NationalHealthIdValidator.isValid("1980010145628", createPerson(1980, 1, 1)), is(false)); - assertThat(NationalHealthIdValidator.isValid("1980010145718", createPerson(1980, 1, 1)), is(false)); - assertThat(NationalHealthIdValidator.isValid("1980010145723", createPerson(1980, 1, 1)), is(false)); - assertThat(NationalHealthIdValidator.isValid("1980010345728", createPerson(1980, 1, null)), is(false)); - } - - @NotNull - private static Person createPerson(Integer birthdateYYYY, Integer birthdateMM, Integer birthdateDD) { - Person person = new Person(); - person.setBirthdateYYYY(birthdateYYYY); - person.setBirthdateMM(birthdateMM); - person.setBirthdateDD(birthdateDD); - - return person; - } -} diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjbTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjbTest.java index 035dc4dcdf2..a69ff747a70 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjbTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjbTest.java @@ -285,6 +285,7 @@ public void testDiseaseVariantDeterminationOnSave() { diseases.add(Disease.CORONAVIRUS); diseaseVariantEnumValue.setDiseases(diseases); diseaseVariantEnumValue.setCaption("BF.1.2 variant"); + diseaseVariantEnumValue.setActive(true); getCustomizableEnumValueService().ensurePersisted(diseaseVariantEnumValue); DiseaseVariant diseaseVariant = new DiseaseVariant(); @@ -295,6 +296,7 @@ public void testDiseaseVariantDeterminationOnSave() { diseaseVariantEnumValue2.setValue("BF.1.3"); diseaseVariantEnumValue2.setDiseases(diseases); diseaseVariantEnumValue2.setCaption("BF.1.3 variant"); + diseaseVariantEnumValue2.setActive(true); getCustomizableEnumValueService().ensurePersisted(diseaseVariantEnumValue2); DiseaseVariant diseaseVariant2 = new DiseaseVariant(); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjbUnitTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjbUnitTest.java index 9b3f1aec8a0..7c93da16897 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjbUnitTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/externalmessage/ExternalMessageFacadeEjbUnitTest.java @@ -1,14 +1,9 @@ package de.symeda.sormas.backend.externalmessage; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import java.util.ArrayList; -import java.util.Collections; import java.util.Date; import java.util.List; @@ -19,9 +14,7 @@ import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; import javax.persistence.criteria.Join; -import javax.persistence.criteria.JoinType; import javax.persistence.criteria.Order; -import javax.persistence.criteria.Path; import javax.persistence.criteria.Root; import org.junit.jupiter.api.Test; @@ -34,11 +27,9 @@ import de.symeda.sormas.api.externalmessage.ExternalMessageCriteria; import de.symeda.sormas.api.externalmessage.ExternalMessageDto; -import de.symeda.sormas.api.externalmessage.ExternalMessageIndexDto; import de.symeda.sormas.api.systemevents.SystemEventDto; import de.symeda.sormas.api.systemevents.SystemEventStatus; import de.symeda.sormas.api.systemevents.SystemEventType; -import de.symeda.sormas.api.utils.SortProperty; import de.symeda.sormas.backend.caze.surveillancereport.SurveillanceReportService; import de.symeda.sormas.backend.infrastructure.country.CountryService; import de.symeda.sormas.backend.infrastructure.facility.FacilityService; @@ -70,7 +61,7 @@ public class ExternalMessageFacadeEjbUnitTest { @Mock private CriteriaBuilder criteriaBuilder; @Mock - private CriteriaQuery labMessageIndexDtoCriteriaQuery; + private CriteriaQuery labMessageIndexDtoCriteriaQuery; @Mock private CriteriaQuery longCriteriaQuery; @Mock @@ -78,7 +69,7 @@ public class ExternalMessageFacadeEjbUnitTest { @Mock private Root labMessageRoot; @Mock - private TypedQuery labMessageIndexDtoTypedQuery; + private TypedQuery labMessageIndexDtoTypedQuery; @Mock private TypedQuery labMessageIndexIdsTypedQuery; @Mock @@ -105,42 +96,6 @@ public void testCount() { assertEquals(expected, result); } - @Test - public void testGetIndexList() { - - int first = 1; - int max = 1; - - when(em.getCriteriaBuilder()).thenReturn(criteriaBuilder); - - when(criteriaBuilder.createTupleQuery()).thenReturn(labMessageIndexIdsTupleCriteriaQuery); - when(labMessageIndexIdsTupleCriteriaQuery.from(ExternalMessage.class)).thenReturn(labMessageRoot); - when(em.createQuery(labMessageIndexIdsTupleCriteriaQuery)).thenReturn(labMessageIndexIdsTypedQuery); - when(labMessageIndexIdsTypedQuery.setFirstResult(first)).thenReturn(labMessageIndexIdsTypedQuery); - when(labMessageIndexIdsTypedQuery.setMaxResults(max)).thenReturn(labMessageIndexIdsTypedQuery); - when(labMessageIndexIdsTypedQuery.getResultList()).thenReturn(Collections.singletonList(mock(Tuple.class))); - when(criteriaBuilder.asc(any())).thenReturn(mock(Order.class)); - when(criteriaBuilder.desc(any())).thenReturn(mock(Order.class)); - - when(criteriaBuilder.createQuery(ExternalMessageIndexDto.class)).thenReturn(labMessageIndexDtoCriteriaQuery); - when(labMessageIndexDtoCriteriaQuery.from(ExternalMessage.class)).thenReturn(labMessageRoot); - when(em.createQuery(labMessageIndexDtoCriteriaQuery)).thenReturn(labMessageIndexDtoTypedQuery); - ArrayList expectedResult = new ArrayList<>(); - when(labMessageIndexDtoTypedQuery.getResultList()).thenReturn(expectedResult); - when(labMessageRoot.get(anyString())).thenReturn(mock(Path.class)); - when(labMessageRoot.join(ExternalMessage.ASSIGNEE, JoinType.LEFT)).thenReturn(userJoin); - when(userJoin.get((String) any())).thenReturn(null); - ArrayList sortProperties = new ArrayList<>(); - sortProperties.add(new SortProperty(ExternalMessageIndexDto.UUID)); - sortProperties.add(new SortProperty("No Valid Property")); - List result = sut.getIndexList(new ExternalMessageCriteria(), first, max, sortProperties); - - verify(labMessageIndexIdsTupleCriteriaQuery).orderBy(orderListArgumentCaptor.capture()); - verify(labMessageIndexDtoCriteriaQuery).orderBy(orderListArgumentCaptor.capture()); - assertEquals(2, orderListArgumentCaptor.getValue().size()); - assertEquals(expectedResult, result); - } - @Test public void testSave() { ExternalMessageDto externalMessageDto = new ExternalMessageDto(); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/immunization/ImmunizationFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/immunization/ImmunizationFacadeEjbPseudonymizationTest.java new file mode 100644 index 00000000000..6b4f61d54b9 --- /dev/null +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/immunization/ImmunizationFacadeEjbPseudonymizationTest.java @@ -0,0 +1,217 @@ +package de.symeda.sormas.backend.immunization; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyString; +import static org.hamcrest.Matchers.is; + +import java.util.HashMap; + +import javax.persistence.Query; + +import org.junit.jupiter.api.Test; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.caze.CaseDataDto; +import de.symeda.sormas.api.feature.FeatureConfigurationIndexDto; +import de.symeda.sormas.api.feature.FeatureType; +import de.symeda.sormas.api.feature.FeatureTypeProperty; +import de.symeda.sormas.api.immunization.ImmunizationDto; +import de.symeda.sormas.api.immunization.ImmunizationManagementStatus; +import de.symeda.sormas.api.immunization.ImmunizationStatus; +import de.symeda.sormas.api.immunization.MeansOfImmunization; +import de.symeda.sormas.api.person.PersonDto; +import de.symeda.sormas.api.user.DefaultUserRole; +import de.symeda.sormas.api.user.UserDto; +import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.backend.AbstractBeanTest; +import de.symeda.sormas.backend.TestDataCreator; +import de.symeda.sormas.backend.feature.FeatureConfiguration; + +public class ImmunizationFacadeEjbPseudonymizationTest extends AbstractBeanTest { + + private TestDataCreator.RDCF rdcf1; + private TestDataCreator.RDCF rdcf2; + + private UserDto districtUser1; + private UserDto nationalUser; + + @Override + public void init() { + super.init(); + rdcf1 = creator.createRDCF("Region 1", "District 1", "Community 1", "Facility 1", "Point of entry 1"); + rdcf2 = creator.createRDCF("Region 2", "District 2", "Community 2", "Facility 2", "Point of entry 2"); + nationalUser = creator.createUser( + rdcf1.region.getUuid(), + rdcf1.district.getUuid(), + rdcf1.community.getUuid(), + rdcf1.facility.getUuid(), + "Nat", + "User", + creator.getUserRoleReference(DefaultUserRole.NATIONAL_USER)); + + districtUser1 = creator.createUser( + rdcf1.region.getUuid(), + rdcf1.district.getUuid(), + rdcf1.facility.getUuid(), + "Surv", + "Off1", + creator.getUserRoleReference(DefaultUserRole.SURVEILLANCE_OFFICER)); + } + + @Test + public void testPseudonymized() { + loginWith(nationalAdmin); + + // immunization within limited user's jurisdiction + PersonDto person1 = creator.createPerson("John", "Doe"); + final ImmunizationDto immunization1 = creator.createImmunization( + Disease.CORONAVIRUS, + person1.toReference(), + nationalUser.toReference(), + ImmunizationStatus.ACQUIRED, + MeansOfImmunization.VACCINATION, + ImmunizationManagementStatus.COMPLETED, + rdcf1); + immunization1.setAdditionalDetails("confidential details"); + getImmunizationFacade().save(immunization1); + + // immunization outside limited user's jurisdiction + PersonDto person2 = creator.createPerson("Max", "MUstermann"); + final ImmunizationDto immunization2 = creator.createImmunization( + Disease.CORONAVIRUS, + person2.toReference(), + nationalUser.toReference(), + ImmunizationStatus.ACQUIRED, + MeansOfImmunization.VACCINATION, + ImmunizationManagementStatus.COMPLETED, + rdcf2); + immunization2.setAdditionalDetails("confidential details second"); + getImmunizationFacade().save(immunization2); + + loginWith(districtUser1); + ImmunizationDto testImmunization3 = getImmunizationFacade().getByUuid(immunization1.getUuid()); + assertThat(testImmunization3.isPseudonymized(), is(false)); + assertThat(testImmunization3.getAdditionalDetails(), is("confidential details")); + ImmunizationDto testImmunization3Second = getImmunizationFacade().getByUuid(immunization2.getUuid()); + assertThat(testImmunization3Second.isPseudonymized(), is(true)); + assertThat(testImmunization3Second.getAdditionalDetails(), is(emptyString())); + } + + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() { + + // deactivate AUTOMATIC_RESPONSIBILITY_ASSIGNMENT in order to assign the limited user to a case from outside jurisdiction + FeatureConfigurationIndexDto featureConfiguration = + new FeatureConfigurationIndexDto(DataHelper.createUuid(), null, null, null, null, null, true, null); + getFeatureConfigurationFacade().saveFeatureConfiguration(featureConfiguration, FeatureType.CASE_SURVEILANCE); + + executeInTransaction(em -> { + Query query = em.createQuery("select f from featureconfiguration f"); + FeatureConfiguration singleResult = (FeatureConfiguration) query.getSingleResult(); + HashMap properties = new HashMap<>(); + properties.put(FeatureTypeProperty.AUTOMATIC_RESPONSIBILITY_ASSIGNMENT, false); + singleResult.setProperties(properties); + em.persist(singleResult); + }); + + loginWith(nationalAdmin); + + // immunization within limited user's jurisdiction + PersonDto person1 = creator.createPerson("John", "Doe"); + final ImmunizationDto immunization1 = creator.createImmunization( + Disease.CORONAVIRUS, + person1.toReference(), + nationalUser.toReference(), rdcf1, v->{ + v.setImmunizationStatus(ImmunizationStatus.ACQUIRED); + v.setMeansOfImmunization(MeansOfImmunization.VACCINATION); + v.setImmunizationManagementStatus(ImmunizationManagementStatus.COMPLETED); + v.setAdditionalDetails("confidential details"); + } + ); + + // immunization outside limited user's jurisdiction + PersonDto person2 = creator.createPerson("Max", "MUstermann"); + final ImmunizationDto immunization2 = creator.createImmunization( + Disease.CORONAVIRUS, + person2.toReference(), + nationalUser.toReference(), rdcf2, v-> { + v.setImmunizationStatus(ImmunizationStatus.ACQUIRED); + v.setMeansOfImmunization(MeansOfImmunization.VACCINATION); + v.setImmunizationManagementStatus(ImmunizationManagementStatus.COMPLETED); + v.setAdditionalDetails("confidential details second"); + } + ); + + UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = + creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + + // immunization created by limited user within limited user's jurisdiction + PersonDto person3 = creator.createPerson("John", "Doe"); + final ImmunizationDto immunization3 = creator.createImmunization( + Disease.CORONAVIRUS, + person3.toReference(), + nationalUser.toReference(), rdcf1, v-> { + v.setImmunizationStatus(ImmunizationStatus.ACQUIRED); + v.setMeansOfImmunization(MeansOfImmunization.VACCINATION); + v.setImmunizationManagementStatus(ImmunizationManagementStatus.COMPLETED); + v.setAdditionalDetails("confidential details"); + } + ); + + // immunization created by limited user outside limited user's jurisdiction + PersonDto person4 = creator.createPerson("Max", "MUstermann"); + final ImmunizationDto immunization4 = creator.createImmunization( + Disease.CORONAVIRUS, + person4.toReference(), + nationalUser.toReference(), rdcf2, v-> { + v.setImmunizationStatus(ImmunizationStatus.ACQUIRED); + v.setMeansOfImmunization(MeansOfImmunization.VACCINATION); + v.setImmunizationManagementStatus(ImmunizationManagementStatus.COMPLETED); + v.setAdditionalDetails("confidential details second"); + } + ); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + ImmunizationDto testImmunization = getImmunizationFacade().getByUuid(immunization1.getUuid()); + assertThat(testImmunization.isPseudonymized(), is(true)); + assertThat(testImmunization.getAdditionalDetails(), is(emptyString())); + ImmunizationDto testImmunizationSecond = getImmunizationFacade().getByUuid(immunization2.getUuid()); + assertThat(testImmunizationSecond.isPseudonymized(), is(true)); + assertThat(testImmunizationSecond.getAdditionalDetails(), is(emptyString())); + + loginWith(nationalAdmin); + final CaseDataDto caseDataDto = creator.createCase(nationalUser.toReference(), person1.toReference(), rdcf1); + final CaseDataDto caseDataDtoSecond = creator.createCase(nationalUser.toReference(), person2.toReference(), rdcf2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + ImmunizationDto testImmunization2 = getImmunizationFacade().getByUuid(immunization1.getUuid()); + assertThat(testImmunization2.isPseudonymized(), is(true)); + assertThat(testImmunization2.getAdditionalDetails(), is(emptyString())); + ImmunizationDto testImmunization2Second = getImmunizationFacade().getByUuid(immunization2.getUuid()); + assertThat(testImmunization2Second.isPseudonymized(), is(true)); + assertThat(testImmunization2Second.getAdditionalDetails(), is(emptyString())); + + loginWith(nationalAdmin); + caseDataDto.setSurveillanceOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getCaseFacade().save(caseDataDto); + caseDataDtoSecond.setSurveillanceOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getCaseFacade().save(caseDataDtoSecond); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + ImmunizationDto testImmunization3 = getImmunizationFacade().getByUuid(immunization1.getUuid()); + assertThat(testImmunization3.isPseudonymized(), is(false)); + assertThat(testImmunization3.getAdditionalDetails(), is("confidential details")); + + ImmunizationDto testImmunization3Second = getImmunizationFacade().getByUuid(immunization2.getUuid()); + assertThat(testImmunization3Second.isPseudonymized(), is(true)); + assertThat(testImmunization3Second.getAdditionalDetails(), is(emptyString())); + + ImmunizationDto testImmunization3Third = getImmunizationFacade().getByUuid(immunization3.getUuid()); + assertThat(testImmunization3Third.isPseudonymized(), is(true)); + assertThat(testImmunization3Third.getAdditionalDetails(), is(emptyString())); + + ImmunizationDto testImmunization3Fourth = getImmunizationFacade().getByUuid(immunization4.getUuid()); + assertThat(testImmunization3Fourth.isPseudonymized(), is(true)); + assertThat(testImmunization3Fourth.getAdditionalDetails(), is(emptyString())); + } +} diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/sample/SampleFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/sample/SampleFacadeEjbPseudonymizationTest.java index 4300f9d6ce7..6124e0098a8 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/sample/SampleFacadeEjbPseudonymizationTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/sample/SampleFacadeEjbPseudonymizationTest.java @@ -19,23 +19,31 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.emptyString; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Calendar; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Optional; +import javax.persistence.Query; + import org.junit.jupiter.api.Test; import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.caze.CaseDataDto; import de.symeda.sormas.api.contact.ContactDto; +import de.symeda.sormas.api.feature.FeatureConfigurationIndexDto; +import de.symeda.sormas.api.feature.FeatureType; +import de.symeda.sormas.api.feature.FeatureTypeProperty; import de.symeda.sormas.api.infrastructure.facility.FacilityReferenceDto; import de.symeda.sormas.api.sample.PathogenTestResultType; import de.symeda.sormas.api.sample.PathogenTestType; @@ -49,6 +57,7 @@ import de.symeda.sormas.api.utils.DataHelper; import de.symeda.sormas.backend.AbstractBeanTest; import de.symeda.sormas.backend.TestDataCreator; +import de.symeda.sormas.backend.feature.FeatureConfiguration; import de.symeda.sormas.backend.infrastructure.facility.Facility; public class SampleFacadeEjbPseudonymizationTest extends AbstractBeanTest { @@ -107,6 +116,84 @@ public void testGetSampleWithCaseOutsideJurisdiction() { assertPseudonymized(getSampleFacade().getSampleByUuid(sample.getUuid()), "Lab"); } + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() throws InterruptedException { + + // deactivate AUTOMATIC_RESPONSIBILITY_ASSIGNMENT in order to assign the limited user to a case from outside jurisdiction + FeatureConfigurationIndexDto featureConfiguration = + new FeatureConfigurationIndexDto(DataHelper.createUuid(), null, null, null, null, null, true, null); + getFeatureConfigurationFacade().saveFeatureConfiguration(featureConfiguration, FeatureType.CASE_SURVEILANCE); + + executeInTransaction(em -> { + Query query = em.createQuery("select f from featureconfiguration f"); + FeatureConfiguration singleResult = (FeatureConfiguration) query.getSingleResult(); + HashMap properties = new HashMap<>(); + properties.put(FeatureTypeProperty.AUTOMATIC_RESPONSIBILITY_ASSIGNMENT, false); + singleResult.setProperties(properties); + em.persist(singleResult); + }); + + // case and sample within limited user's jurisdiction + CaseDataDto caze1 = creator.createCase(user1.toReference(), creator.createPerson("John", "Smith").toReference(), rdcf1); + SampleDto sample1 = createCaseSample(caze1, user1); + + // case and sample outside limited user's jurisdiction + CaseDataDto caze2 = creator.createCase(user2.toReference(), creator.createPerson("Max", "Mustermann").toReference(), rdcf2); + SampleDto sample2 = createCaseSample(caze2, user2); + + loginWith(nationalAdmin); + UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = + creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + + //case and sample created by limited user within limited user's jurisdiction + CaseDataDto caze3 = creator.createCase( + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + creator.createPerson("Max", "Mustermann").toReference(), + rdcf2); + SampleDto sample3 = createCaseSample(caze3, surveillanceOfficerWithRestrictedAccessToAssignedEntities); + + //case and sample created by limited user outside limited user's jurisdiction + CaseDataDto caze4 = creator.createCase( + surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference(), + creator.createPerson("Max", "Mustermann").toReference(), + rdcf2); + SampleDto sample4 = createCaseSample(caze4, surveillanceOfficerWithRestrictedAccessToAssignedEntities); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + assertTrue(getCurrentUserService().isRestrictedToAssignedEntities()); + final SampleDto testSample1 = getSampleFacade().getSampleByUuid(sample1.getUuid()); + final SampleDto testSample2 = getSampleFacade().getSampleByUuid(sample2.getUuid()); + assertThat(testSample1.isPseudonymized(), is(true)); + assertThat(testSample1.getComment(), is(emptyString())); + assertThat(testSample2.isPseudonymized(), is(true)); + assertThat(testSample2.getComment(), is(emptyString())); + + loginWith(nationalAdmin); + final CaseDataDto testCase1 = getCaseFacade().getCaseDataByUuid(caze1.getUuid()); + testCase1.setSurveillanceOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getCaseFacade().save(testCase1); + final CaseDataDto testCase2 = getCaseFacade().getCaseDataByUuid(caze2.getUuid()); + testCase2.setSurveillanceOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getCaseFacade().save(testCase2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + final SampleDto returnedTestSample1 = getSampleFacade().getSampleByUuid(sample1.getUuid()); + assertThat(returnedTestSample1.isPseudonymized(), is(false)); + assertThat(returnedTestSample1.getComment(), is("Test comment")); + + final SampleDto returnedTestSample2 = getSampleFacade().getSampleByUuid(sample2.getUuid()); + assertThat(returnedTestSample2.isPseudonymized(), is(false)); + assertThat(returnedTestSample2.getComment(), is("Test comment")); + + final SampleDto returnedTestSample3 = getSampleFacade().getSampleByUuid(sample3.getUuid()); + assertThat(returnedTestSample3.isPseudonymized(), is(false)); + assertThat(returnedTestSample3.getComment(), is("Test comment")); + + final SampleDto returnedTestSample4 = getSampleFacade().getSampleByUuid(sample4.getUuid()); + assertThat(returnedTestSample4.isPseudonymized(), is(false)); + assertThat(returnedTestSample4.getComment(), is("Test comment")); + } + @Test public void testGetSampleWithLabUserOfSampleLab() { loginWith(user1); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/sample/SampleFacadeEjbTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/sample/SampleFacadeEjbTest.java index 8811ec8aa87..b9331faceb9 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/sample/SampleFacadeEjbTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/sample/SampleFacadeEjbTest.java @@ -308,7 +308,7 @@ public void testGetIndexListBySampleAssociationTypeAndRestrictedAccessToAssigned UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf); loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); - assertTrue(getCurrentUserService().hasRestrictedAccessToAssignedEntities()); + assertTrue(getCurrentUserService().isRestrictedToAssignedEntities()); assertEquals(0, getSampleFacade().getIndexList(new SampleCriteria(), 0, 100, null).size()); loginWith(user); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/task/TaskFacadeEjbTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/task/TaskFacadeEjbTest.java index 3336cdd7bde..8735077f9dd 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/task/TaskFacadeEjbTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/task/TaskFacadeEjbTest.java @@ -188,7 +188,7 @@ public void testGetIndexListByARestrictedAccessToAssignedEntitiesUser() { UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf); loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); - assertTrue(getCurrentUserService().hasRestrictedAccessToAssignedEntities()); + assertTrue(getCurrentUserService().isRestrictedToAssignedEntities()); assertEquals(0, getTaskFacade().getIndexList(null, 0, 100, null).size()); loginWith(user); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/travelentry/TravelEntryFacadeEjbPseudonymizationTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/travelentry/TravelEntryFacadeEjbPseudonymizationTest.java new file mode 100644 index 00000000000..edb7f67d38a --- /dev/null +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/travelentry/TravelEntryFacadeEjbPseudonymizationTest.java @@ -0,0 +1,155 @@ +package de.symeda.sormas.backend.travelentry; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyString; +import static org.hamcrest.Matchers.is; + +import java.util.HashMap; + +import javax.persistence.Query; + +import org.junit.jupiter.api.Test; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.caze.CaseDataDto; +import de.symeda.sormas.api.feature.FeatureConfigurationIndexDto; +import de.symeda.sormas.api.feature.FeatureType; +import de.symeda.sormas.api.feature.FeatureTypeProperty; +import de.symeda.sormas.api.person.PersonDto; +import de.symeda.sormas.api.travelentry.TravelEntryDto; +import de.symeda.sormas.api.user.DefaultUserRole; +import de.symeda.sormas.api.user.UserDto; +import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.backend.AbstractBeanTest; +import de.symeda.sormas.backend.TestDataCreator; +import de.symeda.sormas.backend.feature.FeatureConfiguration; + +public class TravelEntryFacadeEjbPseudonymizationTest extends AbstractBeanTest { + + private TestDataCreator.RDCF rdcf1; + private TestDataCreator.RDCF rdcf2; + + private UserDto nationalUser; + + @Override + public void init() { + super.init(); + rdcf1 = creator.createRDCF("Region 1", "District 1", "Community 1", "Facility 1", "Point of entry 1"); + rdcf2 = creator.createRDCF("Region 2", "District 2", "Community 2", "Facility 2", "Point of entry 2"); + nationalUser = creator.createUser( + rdcf1.region.getUuid(), + rdcf1.district.getUuid(), + rdcf1.community.getUuid(), + rdcf1.facility.getUuid(), + "Nat", + "User", + creator.getUserRoleReference(DefaultUserRole.NATIONAL_USER)); + } + + @Test + public void testPseudonymizedGetByUuidWithLimitedUser() { + + // deactivate AUTOMATIC_RESPONSIBILITY_ASSIGNMENT in order to assign the limited user to a case from outside jurisdiction + FeatureConfigurationIndexDto featureConfiguration = + new FeatureConfigurationIndexDto(DataHelper.createUuid(), null, null, null, null, null, true, null); + getFeatureConfigurationFacade().saveFeatureConfiguration(featureConfiguration, FeatureType.CASE_SURVEILANCE); + + executeInTransaction(em -> { + Query query = em.createQuery("select f from featureconfiguration f"); + FeatureConfiguration singleResult = (FeatureConfiguration) query.getSingleResult(); + HashMap properties = new HashMap<>(); + properties.put(FeatureTypeProperty.AUTOMATIC_RESPONSIBILITY_ASSIGNMENT, false); + singleResult.setProperties(properties); + em.persist(singleResult); + }); + + loginWith(nationalUser); + + // travel entry within limited user's jurisdiction + PersonDto person1 = creator.createPerson("John", "Doe"); + TravelEntryDto travelEntry1 = creator.createTravelEntry( + person1.toReference(), + nationalUser.toReference(), rdcf1, v ->{ + v.setDisease(Disease.CORONAVIRUS); + v.setQuarantineHomePossibleComment("pacient can stay home"); + } + ); + + // travel entry outside limited user's jurisdiction + PersonDto person2 = creator.createPerson("John", "Doe"); + TravelEntryDto travelEntry2 = creator.createTravelEntry( + person2.toReference(), + nationalUser.toReference(),rdcf2, v -> { + v.setDisease(Disease.CORONAVIRUS); + v.setQuarantineHomePossibleComment("pacient can stay home second"); + } + ); + + loginWith(nationalAdmin); + UserDto surveillanceOfficerWithRestrictedAccessToAssignedEntities = + creator.createSurveillanceOfficerWithRestrictedAccessToAssignedEntities(rdcf1); + + // travel entry created by limited user within limited user's jurisdiction + PersonDto person3 = creator.createPerson("John", "Doe"); + TravelEntryDto travelEntry3 = creator.createTravelEntry( + person3.toReference(), + nationalUser.toReference(), rdcf1, v -> { + v.setDisease(Disease.CORONAVIRUS); + v.setQuarantineHomePossibleComment("pacient can stay home"); + } + ); + + // travel entry created by limited user outside limited user's jurisdiction + PersonDto person4 = creator.createPerson("John", "Doe"); + TravelEntryDto travelEntry4 = creator.createTravelEntry( + person4.toReference(), + nationalUser.toReference(), rdcf2, v-> { + v.setDisease(Disease.CORONAVIRUS); + v.setQuarantineHomePossibleComment("pacient can stay home second"); + } + ); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + TravelEntryDto testTravelEntry = getTravelEntryFacade().getByUuid(travelEntry1.getUuid()); + assertThat(testTravelEntry.isPseudonymized(), is(true)); + assertThat(testTravelEntry.getQuarantineHomePossibleComment(), is(emptyString())); + TravelEntryDto testTravelEntrySecond = getTravelEntryFacade().getByUuid(travelEntry2.getUuid()); + assertThat(testTravelEntrySecond.isPseudonymized(), is(true)); + assertThat(testTravelEntrySecond.getQuarantineHomePossibleComment(), is(emptyString())); + + loginWith(nationalAdmin); + final CaseDataDto caseDataDto1 = creator.createCase(nationalUser.toReference(), person1.toReference(), rdcf1); + final CaseDataDto caseDataDto2 = creator.createCase(nationalUser.toReference(), person2.toReference(), rdcf2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + TravelEntryDto testTravelEntry2 = getTravelEntryFacade().getByUuid(travelEntry1.getUuid()); + assertThat(testTravelEntry2.isPseudonymized(), is(true)); + assertThat(testTravelEntry2.getQuarantineHomePossibleComment(), is(emptyString())); + TravelEntryDto testTravelEntry2Second = getTravelEntryFacade().getByUuid(travelEntry2.getUuid()); + assertThat(testTravelEntry2Second.isPseudonymized(), is(true)); + assertThat(testTravelEntry2Second.getQuarantineHomePossibleComment(), is(emptyString())); + + loginWith(nationalAdmin); + caseDataDto1.setSurveillanceOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getCaseFacade().save(caseDataDto1); + caseDataDto2.setSurveillanceOfficer(surveillanceOfficerWithRestrictedAccessToAssignedEntities.toReference()); + getCaseFacade().save(caseDataDto2); + + loginWith(surveillanceOfficerWithRestrictedAccessToAssignedEntities); + TravelEntryDto testTravelEntry3 = getTravelEntryFacade().getByUuid(travelEntry1.getUuid()); + assertThat(testTravelEntry3.isPseudonymized(), is(false)); + assertThat(testTravelEntry3.getQuarantineHomePossibleComment(), is("pacient can stay home")); + + TravelEntryDto testTravelEntry3Second = getTravelEntryFacade().getByUuid(travelEntry2.getUuid()); + assertThat(testTravelEntry3Second.isPseudonymized(), is(true)); + assertThat(testTravelEntry3Second.getQuarantineHomePossibleComment(), is(emptyString())); + + TravelEntryDto testTravelEntry3Third = getTravelEntryFacade().getByUuid(travelEntry3.getUuid()); + assertThat(testTravelEntry3Third.isPseudonymized(), is(true)); + assertThat(testTravelEntry3Third.getQuarantineHomePossibleComment(), is(emptyString())); + + TravelEntryDto testTravelEntry3Fourth = getTravelEntryFacade().getByUuid(travelEntry4.getUuid()); + assertThat(testTravelEntry3Fourth.isPseudonymized(), is(true)); + assertThat(testTravelEntry3Fourth.getQuarantineHomePossibleComment(), is(emptyString())); + } +} diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/util/luxembourg/LuxembourgNationalHealthIdValidatorTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/util/luxembourg/LuxembourgNationalHealthIdValidatorTest.java new file mode 100644 index 00000000000..9955063e320 --- /dev/null +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/util/luxembourg/LuxembourgNationalHealthIdValidatorTest.java @@ -0,0 +1,55 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2024 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.symeda.sormas.backend.util.luxembourg; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +import org.junit.jupiter.api.Test; + +import de.symeda.sormas.api.utils.luxembourg.LuxembourgNationalHealthIdValidator; + +public class LuxembourgNationalHealthIdValidatorTest { + + public static final String VALID_LU_NATIONAL_HEALTH_ID = "1980010145728"; + + @Test + public void testIsValid() { + assertThat(LuxembourgNationalHealthIdValidator.isValid("19800101", 1980, 1, 1), is(false)); + assertThat(LuxembourgNationalHealthIdValidator.isValid("1980Jan0145728", 1980, 1, 1), is(false)); + assertThat(LuxembourgNationalHealthIdValidator.isValid("1980Ja0145728", 1980, 1, 1), is(false)); + + assertThat(LuxembourgNationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, 1980, 1, 1), is(true)); + assertThat(LuxembourgNationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, null, 1, 1), is(true)); + assertThat(LuxembourgNationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, 1980, 1, null), is(true)); + assertThat(LuxembourgNationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, 1980, null, 1), is(true)); + assertThat(LuxembourgNationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, 1980, null, null), is(true)); + assertThat(LuxembourgNationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, null, null, null), is(true)); + + assertThat(LuxembourgNationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, 1981, 1, 1), is(false)); + assertThat(LuxembourgNationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, 1980, 2, 1), is(false)); + assertThat(LuxembourgNationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, 1980, 1, 2), is(false)); + assertThat(LuxembourgNationalHealthIdValidator.isValid(VALID_LU_NATIONAL_HEALTH_ID, 1981, 1, null), is(false)); + + assertThat(LuxembourgNationalHealthIdValidator.isValid("1980010145628", 1980, 1, 1), is(false)); + assertThat(LuxembourgNationalHealthIdValidator.isValid("1980010145718", 1980, 1, 1), is(false)); + assertThat(LuxembourgNationalHealthIdValidator.isValid("1980010145723", 1980, 1, 1), is(false)); + assertThat(LuxembourgNationalHealthIdValidator.isValid("1980010345728", 1980, 1, null), is(false)); + } +} diff --git a/sormas-base/pom.xml b/sormas-base/pom.xml index cf8cba69a6a..6a77258e114 100644 --- a/sormas-base/pom.xml +++ b/sormas-base/pom.xml @@ -5,7 +5,7 @@ de.symeda.sormas sormas-base pom - 1.93.0 + 1.94.0 3.6.3 @@ -1172,13 +1172,6 @@ - - org.apache.pdfbox - pdfbox - 3.0.0 - provided - - diff --git a/sormas-cargoserver/pom.xml b/sormas-cargoserver/pom.xml index 2520cc5e2b9..e6014f3a69e 100644 --- a/sormas-cargoserver/pom.xml +++ b/sormas-cargoserver/pom.xml @@ -3,7 +3,7 @@ de.symeda.sormas sormas-base - 1.93.0 + 1.94.0 ../sormas-base diff --git a/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/events/EventParticipantsPage.java b/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/events/EventParticipantsPage.java index b2051399954..70ef231d203 100644 --- a/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/events/EventParticipantsPage.java +++ b/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/events/EventParticipantsPage.java @@ -22,6 +22,7 @@ public class EventParticipantsPage { public static final By ADD_PARTICIPANT_BUTTON = By.cssSelector("div#eventParticipantAddPerson"); + public static final By EVENT_PARTICIPANT_UUID_INPUT = By.cssSelector("input#uuid"); public static final By PARTICIPANT_FIRST_NAME_INPUT = By.cssSelector(".popupContent #firstName"); public static final By PARTICIPANT_LAST_NAME_INPUT = By.cssSelector(".popupContent #lastName"); public static final By PARTICIPANT_REGION_COMBOBOX = By.cssSelector(".popupContent #region div"); @@ -31,14 +32,19 @@ public class EventParticipantsPage { By.cssSelector(".v-window [location='sex'] [role='combobox'] div"); public static final By SEX_COMBOBOX_REQUIRED = By.xpath("//div[@id='sex' and contains(@class, 'v-required v-filterselect-required')]"); + public static final By PICK_OR_CASE_PERSON_POPUP = + By.xpath("//*[contains(text(),'Pick or Create a Case')]"); public static final By PICK_OR_CREATE_PERSON_POPUP = By.xpath("//*[contains(text(),'Pick or create person')]"); public static final By PICK_OR_CREATE_CONTACT_POPUP = By.xpath("//*[contains(text(),'Pick or create contact')]"); public static final By CREATE_NEW_PERSON_RADIO_BUTTON = By.xpath("//label[contains(text(),'Create a new person')]"); + public static final By CREATE_NEW_CASE_RADIO_BUTTON = + By.xpath("//label[contains(text(),'Create a new case')]"); public static final By EVENT_PARTICIPANTS_TAB = By.id("tab-events-eventparticipants"); public static final By PICK_OR_CREATE_POPUP_SAVE_BUTTON = By.cssSelector("#commit"); + public static final By PICK_OR_CASE_POPUP_SAVE_BUTTON = By.cssSelector(".popupContent #commit"); public static final By ERROR_MESSAGE_TEXT = By.cssSelector("p.v-Notification-description"); public static final By DISCARD_BUTTON = By.id("discard"); public static final By APPLY_FILTERS_BUTTON = By.id("actionApplyFilters"); @@ -72,6 +78,8 @@ public class EventParticipantsPage { public static final By ENTER_BULK_EDIT_MODE_BUTTON = By.id("actionEnterBulkEditMode"); public static final By EVENT_PARTICIPANTS_GRID = By.xpath("//div[@class='v-grid v-widget v-has-width v-has-height']"); + public static final By EVENT_PARTICIPANTS = + By.cssSelector(".v-tabsheet-tabitem.v-layout.v-widget.back"); public static final By EVENT_PARTICIPANT_PERSON_TAB = By.cssSelector("#tab-events-eventparticipants-person"); public static final By EVENT_PARTICIPANT_DATA_TAB = diff --git a/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/messages/MessagesDirectoryPage.java b/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/messages/MessagesDirectoryPage.java index 72a7b1c276c..d6cdfe140fc 100644 --- a/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/messages/MessagesDirectoryPage.java +++ b/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/messages/MessagesDirectoryPage.java @@ -76,7 +76,7 @@ public static By getProcessStatusByIndex(int index) { public static final By POPUP_WINDOW_CANCEL_BUTTON = By.xpath("(//*[@id='discard'])[1]"); public static final By POPUP_WINDOW_SAVE_AND_OPEN_CASE_BUTTON = By.cssSelector("#saveAndOpenEntryButton"); - public static final By POPUP_WINDOW_DISCARD_BUTTON = By.xpath("(//*[@id='discard'])[2]"); + public static final By POPUP_WINDOW_DISCARD_BUTTON = By.xpath("//*[@id='discard']"); public static final By POPUP_WINDOW_SAVE_BUTTON = By.cssSelector("#commit"); public static final By MESSAGE_DIRECTORY_HEADER_DE = By.xpath("//div[@class='v-slot v-slot-view-header']//div[text()='Meldungsverzeichnis']"); diff --git a/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/persons/EditPersonPage.java b/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/persons/EditPersonPage.java index 4e9682c8074..ab3dc1e41b9 100644 --- a/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/persons/EditPersonPage.java +++ b/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/persons/EditPersonPage.java @@ -22,6 +22,7 @@ public class EditPersonPage { public static final By UUID_INPUT = By.cssSelector("#uuid"); + public static final By NEW_CASE_BUTTON = By.cssSelector("div[id^='New case']"); public static final By USER_INFORMATION = By.cssSelector(".v-slot.v-slot-h2.v-slot-vspace-top-none.v-slot-primary"); public static final By FIRST_NAME_INPUT = By.id("firstName"); @@ -109,6 +110,7 @@ public class EditPersonPage { By.cssSelector(".v-Notification.error.v-Notification-error"); public static final By ERROR_INDICATOR = By.cssSelector(".v-errorindicator.v-errorindicator-info"); + public static final By SEE_SAMPLES_FOR_PERSON_BUTTON = By.id("See samples for this person"); public static final By SEE_CASES_FOR_PERSON_BUTTON = By.id("See cases for this person"); public static final By SEE_CASES_FOR_PERSON_BUTTON_DE = By.id("F\u00E4lle f\u00FCr diese Person ansehen"); diff --git a/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/samples/CreateNewSamplePage.java b/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/samples/CreateNewSamplePage.java index 34e249bc734..c2f63289c11 100644 --- a/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/samples/CreateNewSamplePage.java +++ b/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/samples/CreateNewSamplePage.java @@ -23,6 +23,7 @@ public class CreateNewSamplePage { public static final By SAMPLE_PURPOSE_OPTIONS = By.cssSelector(".popupContent #samplePurpose .v-select-option"); + public static final By CANCEL_ACTION = By.id("actionCancel"); public static final By SAMPLE_UUID = By.cssSelector("[class='popupContent'] [id='uuid']"); public static final By DATE_SAMPLE_COLLECTED = By.cssSelector("[id='sampleDateTime_date'] input"); public static final By COLLECTED_DATE_TIME_INPUT = diff --git a/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/samples/SamplesDirectoryPage.java b/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/samples/SamplesDirectoryPage.java index 970637db528..9ad0f644a3f 100644 --- a/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/samples/SamplesDirectoryPage.java +++ b/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/samples/SamplesDirectoryPage.java @@ -22,12 +22,15 @@ public class SamplesDirectoryPage { public static final By SAMPLE_SEARCH_INPUT = By.cssSelector("[id='caseCodeIdLike']"); + public static final By TOTAL_SAMPLE_COUNTER = By.cssSelector(".badge"); public static final By SAMPLE_EDIT_PURPOSE_OPTIONS = By.cssSelector("#samplePurpose .v-select-option"); public static final By TEST_RESULTS_SEARCH_COMBOBOX = By.cssSelector("[id='pathogenTestResult'] [class='v-filterselect-button']"); public static final By SAMPLE_GRID_RESULTS_ROWS = By.cssSelector("[class='v-grid-tablewrapper'] tbody>tr"); + public static final By RELEVANCE_STATUS_FILTER_COMBOBOX = + By.cssSelector("[id='relevanceStatusFilter'] [class='v-filterselect-button']"); public static final By SPECIMEN_CONDITION_SEARCH_COMBOBOX = By.cssSelector("[id='specimenCondition'] [class='v-filterselect-button']"); public static final By LABORATORY_SEARCH_COMBOBOX = @@ -67,4 +70,6 @@ public class SamplesDirectoryPage { public static final By BASIC_EXPORT_SAMPLE_BUTTON = By.id("exportBasic"); public static final By DETAILED_EXPORT_SAMPLE_BUTTON = By.id("exportDetailed"); public static final By COMMIT_BUTTON = By.cssSelector("#commit"); + public static final By PENDING_TEST_TABLE_RESULTS = By.xpath("//td[text()='Pending']"); + public static final By POSITIVE_TEST_TABLE_RESULTS = By.xpath("//td[text()='Positive']"); } diff --git a/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/shares/EditSharesPage.java b/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/shares/EditSharesPage.java index 638aa5fde49..b188b07901b 100644 --- a/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/shares/EditSharesPage.java +++ b/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/shares/EditSharesPage.java @@ -22,7 +22,7 @@ public class EditSharesPage { - public static final By SHARE_FIRST_EYE_ICON = By.xpath("(//span[@class='v-icon v-icon-eye'])[1]"); + public static final By SHARE_FIRST_EYE_ICON = By.cssSelector(".v-icon.v-icon-eye"); public static final By SHARE_UUID_CASE_TITLE = By.cssSelector(".popupContent [class='v-grid-cell v-grid-cell-focused'] a"); public static final By EXTRA_COMMENT_INPUT_SHARE_POPUP = By.cssSelector(".popupContent #comment"); diff --git a/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/tasks/TaskManagementPage.java b/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/tasks/TaskManagementPage.java index d73d4907ed7..dfdc3996912 100644 --- a/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/tasks/TaskManagementPage.java +++ b/sormas-e2e-tests/src/main/java/org/sormas/e2etests/pages/application/tasks/TaskManagementPage.java @@ -43,6 +43,7 @@ public class TaskManagementPage { public static final By CHANGE_STATUS_CHECKBOX = By.xpath("//label[text()='Change task status']"); public static final By TASK_ASSIGNEE_COMBOBOX = By.cssSelector("#assigneeUser div"); public static final By TASK_RADIOBUTTON = By.cssSelector(".v-radiobutton"); + public static final By EDIT_TASK_MODAL_FORM = By.xpath("//*[@aria-modal='true']"); public static final By EDIT_FIRST_SEARCH_RESULT = By.xpath("//table/tbody/tr[1]/td[1]"); public static final By TASK_CONTEXT_FIRST_RESULT = By.xpath("//td[3]"); public static final By ASSOCIATED_LINK_FIRST_RESULT = By.xpath("//td/a"); diff --git a/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/AutomationAdminUserRights.json b/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/AutomationAdminUserRights.json index 0259fed44f9..d83ae1dff27 100644 --- a/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/AutomationAdminUserRights.json +++ b/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/AutomationAdminUserRights.json @@ -1 +1 @@ - ["ACTION_CREATE","ACTION_DELETE","ACTION_EDIT","ADDITIONAL_TEST_CREATE","ADDITIONAL_TEST_DELETE","ADDITIONAL_TEST_EDIT","ADDITIONAL_TEST_VIEW","AGGREGATE_REPORT_EDIT","AGGREGATE_REPORT_EXPORT","AGGREGATE_REPORT_VIEW","CAMPAIGN_ARCHIVE","CAMPAIGN_DELETE","CAMPAIGN_EDIT","CAMPAIGN_FORM_DATA_ARCHIVE","CAMPAIGN_FORM_DATA_DELETE","CAMPAIGN_FORM_DATA_EDIT","CAMPAIGN_FORM_DATA_EXPORT","CAMPAIGN_FORM_DATA_VIEW","CAMPAIGN_VIEW","CASE_ARCHIVE","CASE_CHANGE_DISEASE","CASE_CHANGE_EPID_NUMBER","CASE_CLASSIFY","CASE_CLINICIAN_VIEW","CASE_CREATE","CASE_DELETE","CASE_EDIT","CASE_EXPORT","CASE_IMPORT","CASE_INVESTIGATE","CASE_MERGE","CASE_REFER_FROM_POE","CASE_SHARE","CASE_TRANSFER","CASE_VIEW","CLINICAL_COURSE_EDIT","CLINICAL_COURSE_VIEW","CLINICAL_VISIT_CREATE","CLINICAL_VISIT_DELETE","CLINICAL_VISIT_EDIT","CONTACT_ARCHIVE","CONTACT_CONVERT","CONTACT_CREATE","CONTACT_DELETE","CONTACT_EDIT","CONTACT_EXPORT","CONTACT_IMPORT","CONTACT_MERGE","CONTACT_REASSIGN_CASE","CONTACT_VIEW","CUSTOMIZABLE_ENUM_MANAGEMENT","DASHBOARD_CAMPAIGNS_VIEW","DASHBOARD_CONTACT_VIEW","DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS","DASHBOARD_SAMPLES_VIEW","DASHBOARD_SURVEILLANCE_VIEW","DATABASE_EXPORT_ACCESS","DEV_MODE","DOCUMENT_DELETE","DOCUMENT_TEMPLATE_MANAGEMENT","DOCUMENT_UPLOAD","DOCUMENT_VIEW","EMAIL_TEMPLATE_MANAGEMENT","ENVIRONMENT_ARCHIVE","ENVIRONMENT_CREATE","ENVIRONMENT_DELETE","ENVIRONMENT_EDIT","ENVIRONMENT_EXPORT","ENVIRONMENT_IMPORT","ENVIRONMENT_SAMPLE_CREATE","ENVIRONMENT_SAMPLE_DELETE","ENVIRONMENT_SAMPLE_EDIT","ENVIRONMENT_SAMPLE_EDIT_DISPATCH","ENVIRONMENT_SAMPLE_EDIT_RECEIVAL","ENVIRONMENT_SAMPLE_EXPORT","ENVIRONMENT_SAMPLE_IMPORT","ENVIRONMENT_SAMPLE_VIEW","ENVIRONMENT_VIEW","EVENTGROUP_ARCHIVE","EVENTGROUP_CREATE","EVENTGROUP_DELETE","EVENTGROUP_EDIT","EVENTGROUP_LINK","EVENTPARTICIPANT_ARCHIVE","EVENTPARTICIPANT_CREATE","EVENTPARTICIPANT_DELETE","EVENTPARTICIPANT_EDIT","EVENTPARTICIPANT_IMPORT","EVENTPARTICIPANT_VIEW","EVENT_ARCHIVE","EVENT_CREATE","EVENT_DELETE","EVENT_EDIT","EVENT_EXPORT","EVENT_IMPORT","EVENT_VIEW","EXPORT_DATA_PROTECTION_DATA","EXTERNAL_EMAIL_ATTACH_DOCUMENTS","EXTERNAL_EMAIL_SEND","EXTERNAL_MESSAGE_DELETE","EXTERNAL_MESSAGE_PROCESS","EXTERNAL_MESSAGE_VIEW","IMMUNIZATION_ARCHIVE","IMMUNIZATION_CREATE","IMMUNIZATION_DELETE","IMMUNIZATION_EDIT","IMMUNIZATION_VIEW","INFRASTRUCTURE_ARCHIVE","INFRASTRUCTURE_CREATE","INFRASTRUCTURE_EDIT","INFRASTRUCTURE_EXPORT","INFRASTRUCTURE_IMPORT","INFRASTRUCTURE_VIEW","LINE_LISTING_CONFIGURE","MANAGE_EXTERNAL_SYMPTOM_JOURNAL","MANAGE_PUBLIC_EXPORT_CONFIGURATION","OUTBREAK_EDIT","OUTBREAK_VIEW","PATHOGEN_TEST_CREATE","PATHOGEN_TEST_DELETE","PATHOGEN_TEST_EDIT","PERFORM_BULK_OPERATIONS","PERFORM_BULK_OPERATIONS_CASE_SAMPLES","PERFORM_BULK_OPERATIONS_EVENT","PERFORM_BULK_OPERATIONS_EVENTPARTICIPANT","PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES","PERFORM_BULK_OPERATIONS_PSEUDONYM","PERSON_CONTACT_DETAILS_DELETE","PERSON_DELETE","PERSON_EDIT","PERSON_EXPORT","PERSON_MERGE","PERSON_VIEW","POPULATION_MANAGE","PORT_HEALTH_INFO_EDIT","PORT_HEALTH_INFO_VIEW","PRESCRIPTION_CREATE","PRESCRIPTION_DELETE","PRESCRIPTION_EDIT","QUARANTINE_ORDER_CREATE","SAMPLE_CREATE","SAMPLE_DELETE","SAMPLE_EDIT","SAMPLE_EDIT_NOT_OWNED","SAMPLE_EXPORT","SAMPLE_TRANSFER","SAMPLE_VIEW","SEE_PERSONAL_DATA_IN_JURISDICTION","SEE_SENSITIVE_DATA_IN_JURISDICTION","SEND_MANUAL_EXTERNAL_MESSAGES","SORMAS_REST","SORMAS_UI","STATISTICS_ACCESS","STATISTICS_EXPORT","TASK_ARCHIVE","TASK_ASSIGN","TASK_CREATE","TASK_DELETE","TASK_EDIT","TASK_EXPORT","TASK_VIEW","THERAPY_VIEW","TRAVEL_ENTRY_ARCHIVE","TRAVEL_ENTRY_CREATE","TRAVEL_ENTRY_DELETE","TRAVEL_ENTRY_EDIT","TRAVEL_ENTRY_MANAGEMENT_ACCESS","TRAVEL_ENTRY_VIEW","TREATMENT_CREATE","TREATMENT_DELETE","TREATMENT_EDIT","USER_CREATE","USER_EDIT","USER_ROLE_DELETE","USER_ROLE_EDIT","USER_ROLE_VIEW","USER_VIEW","VISIT_CREATE","VISIT_DELETE","VISIT_EDIT","VISIT_EXPORT","WEEKLYREPORT_VIEW"] \ No newline at end of file +["ACTION_CREATE","ACTION_DELETE","ACTION_EDIT","ADDITIONAL_TEST_CREATE","ADDITIONAL_TEST_DELETE","ADDITIONAL_TEST_EDIT","ADDITIONAL_TEST_VIEW","AGGREGATE_REPORT_EDIT","AGGREGATE_REPORT_EXPORT","AGGREGATE_REPORT_VIEW","CAMPAIGN_ARCHIVE","CAMPAIGN_DELETE","CAMPAIGN_EDIT","CAMPAIGN_FORM_DATA_ARCHIVE","CAMPAIGN_FORM_DATA_DELETE","CAMPAIGN_FORM_DATA_EDIT","CAMPAIGN_FORM_DATA_EXPORT","CAMPAIGN_FORM_DATA_VIEW","CAMPAIGN_VIEW","CASE_ARCHIVE","CASE_CHANGE_DISEASE","CASE_CHANGE_EPID_NUMBER","CASE_CLASSIFY","CASE_CLINICIAN_VIEW","CASE_CREATE","CASE_DELETE","CASE_EDIT","CASE_EXPORT","CASE_IMPORT","CASE_INVESTIGATE","CASE_MERGE","CASE_REFER_FROM_POE","CASE_SHARE","CASE_TRANSFER","CASE_VIEW","CLINICAL_COURSE_EDIT","CLINICAL_COURSE_VIEW","CLINICAL_VISIT_CREATE","CLINICAL_VISIT_DELETE","CLINICAL_VISIT_EDIT","CONTACT_ARCHIVE","CONTACT_CONVERT","CONTACT_CREATE","CONTACT_DELETE","CONTACT_EDIT","CONTACT_EXPORT","CONTACT_IMPORT","CONTACT_MERGE","CONTACT_REASSIGN_CASE","CONTACT_VIEW","CUSTOMIZABLE_ENUM_MANAGEMENT","DASHBOARD_CAMPAIGNS_VIEW","DASHBOARD_CONTACT_VIEW","DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS","DASHBOARD_SAMPLES_VIEW","DASHBOARD_SURVEILLANCE_VIEW","DATABASE_EXPORT_ACCESS","DEV_MODE","DOCUMENT_DELETE","DOCUMENT_TEMPLATE_MANAGEMENT","DOCUMENT_UPLOAD","DOCUMENT_VIEW","EMAIL_TEMPLATE_MANAGEMENT","ENVIRONMENT_ARCHIVE","ENVIRONMENT_CREATE","ENVIRONMENT_DELETE","ENVIRONMENT_EDIT","ENVIRONMENT_EXPORT","ENVIRONMENT_IMPORT","ENVIRONMENT_PATHOGEN_TEST_CREATE","ENVIRONMENT_PATHOGEN_TEST_DELETE","ENVIRONMENT_PATHOGEN_TEST_EDIT","ENVIRONMENT_SAMPLE_CREATE","ENVIRONMENT_SAMPLE_DELETE","ENVIRONMENT_SAMPLE_EDIT","ENVIRONMENT_SAMPLE_EDIT_DISPATCH","ENVIRONMENT_SAMPLE_EDIT_RECEIVAL","ENVIRONMENT_SAMPLE_EXPORT","ENVIRONMENT_SAMPLE_IMPORT","ENVIRONMENT_SAMPLE_VIEW","ENVIRONMENT_VIEW","EVENTGROUP_ARCHIVE","EVENTGROUP_CREATE","EVENTGROUP_DELETE","EVENTGROUP_EDIT","EVENTGROUP_LINK","EVENTPARTICIPANT_ARCHIVE","EVENTPARTICIPANT_CREATE","EVENTPARTICIPANT_DELETE","EVENTPARTICIPANT_EDIT","EVENTPARTICIPANT_IMPORT","EVENTPARTICIPANT_VIEW","EVENT_ARCHIVE","EVENT_CREATE","EVENT_DELETE","EVENT_EDIT","EVENT_EXPORT","EVENT_IMPORT","EVENT_VIEW","EXPORT_DATA_PROTECTION_DATA","EXTERNAL_EMAIL_ATTACH_DOCUMENTS","EXTERNAL_EMAIL_SEND","EXTERNAL_MESSAGE_DELETE","EXTERNAL_MESSAGE_PROCESS","EXTERNAL_MESSAGE_VIEW","IMMUNIZATION_ARCHIVE","IMMUNIZATION_CREATE","IMMUNIZATION_DELETE","IMMUNIZATION_EDIT","IMMUNIZATION_VIEW","INFRASTRUCTURE_ARCHIVE","INFRASTRUCTURE_CREATE","INFRASTRUCTURE_EDIT","INFRASTRUCTURE_EXPORT","INFRASTRUCTURE_IMPORT","INFRASTRUCTURE_VIEW","LINE_LISTING_CONFIGURE","MANAGE_EXTERNAL_SYMPTOM_JOURNAL","MANAGE_PUBLIC_EXPORT_CONFIGURATION","OUTBREAK_EDIT","OUTBREAK_VIEW","PATHOGEN_TEST_CREATE","PATHOGEN_TEST_DELETE","PATHOGEN_TEST_EDIT","PERFORM_BULK_OPERATIONS","PERFORM_BULK_OPERATIONS_CASE_SAMPLES","PERFORM_BULK_OPERATIONS_EVENT","PERFORM_BULK_OPERATIONS_EVENTPARTICIPANT","PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES","PERFORM_BULK_OPERATIONS_PSEUDONYM","PERSON_CONTACT_DETAILS_DELETE","PERSON_DELETE","PERSON_EDIT","PERSON_EXPORT","PERSON_MERGE","PERSON_VIEW","POPULATION_MANAGE","PORT_HEALTH_INFO_EDIT","PORT_HEALTH_INFO_VIEW","PRESCRIPTION_CREATE","PRESCRIPTION_DELETE","PRESCRIPTION_EDIT","QUARANTINE_ORDER_CREATE","SAMPLE_CREATE","SAMPLE_DELETE","SAMPLE_EDIT","SAMPLE_EDIT_NOT_OWNED","SAMPLE_EXPORT","SAMPLE_TRANSFER","SAMPLE_VIEW","SEE_PERSONAL_DATA_IN_JURISDICTION","SEE_SENSITIVE_DATA_IN_JURISDICTION","SEND_MANUAL_EXTERNAL_MESSAGES","SORMAS_REST","SORMAS_UI","STATISTICS_ACCESS","STATISTICS_EXPORT","TASK_ARCHIVE","TASK_ASSIGN","TASK_CREATE","TASK_DELETE","TASK_EDIT","TASK_EXPORT","TASK_VIEW","THERAPY_VIEW","TRAVEL_ENTRY_ARCHIVE","TRAVEL_ENTRY_CREATE","TRAVEL_ENTRY_DELETE","TRAVEL_ENTRY_EDIT","TRAVEL_ENTRY_MANAGEMENT_ACCESS","TRAVEL_ENTRY_VIEW","TREATMENT_CREATE","TREATMENT_DELETE","TREATMENT_EDIT","USER_CREATE","USER_EDIT","USER_ROLE_DELETE","USER_ROLE_EDIT","USER_ROLE_VIEW","USER_VIEW","VISIT_CREATE","VISIT_DELETE","VISIT_EDIT","VISIT_EXPORT","WEEKLYREPORT_VIEW"] \ No newline at end of file diff --git a/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/AutomationAdminUserRightsDE.json b/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/AutomationAdminUserRightsDE.json index f0c80b03775..d83ae1dff27 100644 --- a/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/AutomationAdminUserRightsDE.json +++ b/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/AutomationAdminUserRightsDE.json @@ -1 +1 @@ -["ACTION_CREATE","ACTION_DELETE","ACTION_EDIT","ADDITIONAL_TEST_CREATE","ADDITIONAL_TEST_DELETE","ADDITIONAL_TEST_EDIT","ADDITIONAL_TEST_VIEW","AGGREGATE_REPORT_EDIT","AGGREGATE_REPORT_EXPORT","AGGREGATE_REPORT_VIEW","CAMPAIGN_ARCHIVE","CAMPAIGN_DELETE","CAMPAIGN_EDIT","CAMPAIGN_FORM_DATA_ARCHIVE","CAMPAIGN_FORM_DATA_DELETE","CAMPAIGN_FORM_DATA_EDIT","CAMPAIGN_FORM_DATA_EXPORT","CAMPAIGN_FORM_DATA_VIEW","CAMPAIGN_VIEW","CASE_ARCHIVE","CASE_CHANGE_DISEASE","CASE_CHANGE_EPID_NUMBER","CASE_CLASSIFY","CASE_CLINICIAN_VIEW","CASE_CREATE","CASE_DELETE","CASE_EDIT","CASE_EXPORT","CASE_IMPORT","CASE_INVESTIGATE","CASE_MERGE","CASE_REFER_FROM_POE","CASE_SHARE","CASE_TRANSFER","CASE_VIEW","CLINICAL_COURSE_EDIT","CLINICAL_COURSE_VIEW","CLINICAL_VISIT_CREATE","CLINICAL_VISIT_DELETE","CLINICAL_VISIT_EDIT","CONTACT_ARCHIVE","CONTACT_CONVERT","CONTACT_CREATE","CONTACT_DELETE","CONTACT_EDIT","CONTACT_EXPORT","CONTACT_IMPORT","CONTACT_MERGE","CONTACT_REASSIGN_CASE","CONTACT_VIEW","CUSTOMIZABLE_ENUM_MANAGEMENT","DASHBOARD_CAMPAIGNS_VIEW","DASHBOARD_CONTACT_VIEW","DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS","DASHBOARD_SAMPLES_VIEW","DASHBOARD_SURVEILLANCE_VIEW","DATABASE_EXPORT_ACCESS","DEV_MODE","DOCUMENT_DELETE","DOCUMENT_TEMPLATE_MANAGEMENT","DOCUMENT_UPLOAD","DOCUMENT_VIEW","EMAIL_TEMPLATE_MANAGEMENT","ENVIRONMENT_ARCHIVE","ENVIRONMENT_CREATE","ENVIRONMENT_DELETE","ENVIRONMENT_EDIT","ENVIRONMENT_EXPORT","ENVIRONMENT_IMPORT","ENVIRONMENT_SAMPLE_CREATE","ENVIRONMENT_SAMPLE_DELETE","ENVIRONMENT_SAMPLE_EDIT","ENVIRONMENT_SAMPLE_EDIT_DISPATCH","ENVIRONMENT_SAMPLE_EDIT_RECEIVAL","ENVIRONMENT_SAMPLE_EXPORT","ENVIRONMENT_SAMPLE_IMPORT","ENVIRONMENT_SAMPLE_VIEW","ENVIRONMENT_VIEW","EVENTGROUP_ARCHIVE","EVENTGROUP_CREATE","EVENTGROUP_DELETE","EVENTGROUP_EDIT","EVENTGROUP_LINK","EVENTPARTICIPANT_ARCHIVE","EVENTPARTICIPANT_CREATE","EVENTPARTICIPANT_DELETE","EVENTPARTICIPANT_EDIT","EVENTPARTICIPANT_IMPORT","EVENTPARTICIPANT_VIEW","EVENT_ARCHIVE","EVENT_CREATE","EVENT_DELETE","EVENT_EDIT","EVENT_EXPORT","EVENT_IMPORT","EVENT_VIEW","EXPORT_DATA_PROTECTION_DATA","EXTERNAL_EMAIL_ATTACH_DOCUMENTS","EXTERNAL_EMAIL_SEND","EXTERNAL_MESSAGE_DELETE","EXTERNAL_MESSAGE_PROCESS","EXTERNAL_MESSAGE_VIEW","IMMUNIZATION_ARCHIVE","IMMUNIZATION_CREATE","IMMUNIZATION_DELETE","IMMUNIZATION_EDIT","IMMUNIZATION_VIEW","INFRASTRUCTURE_ARCHIVE","INFRASTRUCTURE_CREATE","INFRASTRUCTURE_EDIT","INFRASTRUCTURE_EXPORT","INFRASTRUCTURE_IMPORT","INFRASTRUCTURE_VIEW","LINE_LISTING_CONFIGURE","MANAGE_EXTERNAL_SYMPTOM_JOURNAL","MANAGE_PUBLIC_EXPORT_CONFIGURATION","OUTBREAK_EDIT","OUTBREAK_VIEW","PATHOGEN_TEST_CREATE","PATHOGEN_TEST_DELETE","PATHOGEN_TEST_EDIT","PERFORM_BULK_OPERATIONS","PERFORM_BULK_OPERATIONS_CASE_SAMPLES","PERFORM_BULK_OPERATIONS_EVENT","PERFORM_BULK_OPERATIONS_EVENTPARTICIPANT","PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES","PERFORM_BULK_OPERATIONS_PSEUDONYM","PERSON_CONTACT_DETAILS_DELETE","PERSON_DELETE","PERSON_EDIT","PERSON_EXPORT","PERSON_MERGE","PERSON_VIEW","POPULATION_MANAGE","PORT_HEALTH_INFO_EDIT","PORT_HEALTH_INFO_VIEW","PRESCRIPTION_CREATE","PRESCRIPTION_DELETE","PRESCRIPTION_EDIT","QUARANTINE_ORDER_CREATE","SAMPLE_CREATE","SAMPLE_DELETE","SAMPLE_EDIT","SAMPLE_EDIT_NOT_OWNED","SAMPLE_EXPORT","SAMPLE_TRANSFER","SAMPLE_VIEW","SEE_PERSONAL_DATA_IN_JURISDICTION","SEE_SENSITIVE_DATA_IN_JURISDICTION","SEND_MANUAL_EXTERNAL_MESSAGES","SORMAS_REST","SORMAS_UI","STATISTICS_ACCESS","STATISTICS_EXPORT","TASK_ARCHIVE","TASK_ASSIGN","TASK_CREATE","TASK_DELETE","TASK_EDIT","TASK_EXPORT","TASK_VIEW","THERAPY_VIEW","TRAVEL_ENTRY_ARCHIVE","TRAVEL_ENTRY_CREATE","TRAVEL_ENTRY_DELETE","TRAVEL_ENTRY_EDIT","TRAVEL_ENTRY_MANAGEMENT_ACCESS","TRAVEL_ENTRY_VIEW","TREATMENT_CREATE","TREATMENT_DELETE","TREATMENT_EDIT","USER_CREATE","USER_EDIT","USER_ROLE_DELETE","USER_ROLE_EDIT","USER_ROLE_VIEW","USER_VIEW","VISIT_CREATE","VISIT_DELETE","VISIT_EDIT","VISIT_EXPORT","WEEKLYREPORT_VIEW"] +["ACTION_CREATE","ACTION_DELETE","ACTION_EDIT","ADDITIONAL_TEST_CREATE","ADDITIONAL_TEST_DELETE","ADDITIONAL_TEST_EDIT","ADDITIONAL_TEST_VIEW","AGGREGATE_REPORT_EDIT","AGGREGATE_REPORT_EXPORT","AGGREGATE_REPORT_VIEW","CAMPAIGN_ARCHIVE","CAMPAIGN_DELETE","CAMPAIGN_EDIT","CAMPAIGN_FORM_DATA_ARCHIVE","CAMPAIGN_FORM_DATA_DELETE","CAMPAIGN_FORM_DATA_EDIT","CAMPAIGN_FORM_DATA_EXPORT","CAMPAIGN_FORM_DATA_VIEW","CAMPAIGN_VIEW","CASE_ARCHIVE","CASE_CHANGE_DISEASE","CASE_CHANGE_EPID_NUMBER","CASE_CLASSIFY","CASE_CLINICIAN_VIEW","CASE_CREATE","CASE_DELETE","CASE_EDIT","CASE_EXPORT","CASE_IMPORT","CASE_INVESTIGATE","CASE_MERGE","CASE_REFER_FROM_POE","CASE_SHARE","CASE_TRANSFER","CASE_VIEW","CLINICAL_COURSE_EDIT","CLINICAL_COURSE_VIEW","CLINICAL_VISIT_CREATE","CLINICAL_VISIT_DELETE","CLINICAL_VISIT_EDIT","CONTACT_ARCHIVE","CONTACT_CONVERT","CONTACT_CREATE","CONTACT_DELETE","CONTACT_EDIT","CONTACT_EXPORT","CONTACT_IMPORT","CONTACT_MERGE","CONTACT_REASSIGN_CASE","CONTACT_VIEW","CUSTOMIZABLE_ENUM_MANAGEMENT","DASHBOARD_CAMPAIGNS_VIEW","DASHBOARD_CONTACT_VIEW","DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS","DASHBOARD_SAMPLES_VIEW","DASHBOARD_SURVEILLANCE_VIEW","DATABASE_EXPORT_ACCESS","DEV_MODE","DOCUMENT_DELETE","DOCUMENT_TEMPLATE_MANAGEMENT","DOCUMENT_UPLOAD","DOCUMENT_VIEW","EMAIL_TEMPLATE_MANAGEMENT","ENVIRONMENT_ARCHIVE","ENVIRONMENT_CREATE","ENVIRONMENT_DELETE","ENVIRONMENT_EDIT","ENVIRONMENT_EXPORT","ENVIRONMENT_IMPORT","ENVIRONMENT_PATHOGEN_TEST_CREATE","ENVIRONMENT_PATHOGEN_TEST_DELETE","ENVIRONMENT_PATHOGEN_TEST_EDIT","ENVIRONMENT_SAMPLE_CREATE","ENVIRONMENT_SAMPLE_DELETE","ENVIRONMENT_SAMPLE_EDIT","ENVIRONMENT_SAMPLE_EDIT_DISPATCH","ENVIRONMENT_SAMPLE_EDIT_RECEIVAL","ENVIRONMENT_SAMPLE_EXPORT","ENVIRONMENT_SAMPLE_IMPORT","ENVIRONMENT_SAMPLE_VIEW","ENVIRONMENT_VIEW","EVENTGROUP_ARCHIVE","EVENTGROUP_CREATE","EVENTGROUP_DELETE","EVENTGROUP_EDIT","EVENTGROUP_LINK","EVENTPARTICIPANT_ARCHIVE","EVENTPARTICIPANT_CREATE","EVENTPARTICIPANT_DELETE","EVENTPARTICIPANT_EDIT","EVENTPARTICIPANT_IMPORT","EVENTPARTICIPANT_VIEW","EVENT_ARCHIVE","EVENT_CREATE","EVENT_DELETE","EVENT_EDIT","EVENT_EXPORT","EVENT_IMPORT","EVENT_VIEW","EXPORT_DATA_PROTECTION_DATA","EXTERNAL_EMAIL_ATTACH_DOCUMENTS","EXTERNAL_EMAIL_SEND","EXTERNAL_MESSAGE_DELETE","EXTERNAL_MESSAGE_PROCESS","EXTERNAL_MESSAGE_VIEW","IMMUNIZATION_ARCHIVE","IMMUNIZATION_CREATE","IMMUNIZATION_DELETE","IMMUNIZATION_EDIT","IMMUNIZATION_VIEW","INFRASTRUCTURE_ARCHIVE","INFRASTRUCTURE_CREATE","INFRASTRUCTURE_EDIT","INFRASTRUCTURE_EXPORT","INFRASTRUCTURE_IMPORT","INFRASTRUCTURE_VIEW","LINE_LISTING_CONFIGURE","MANAGE_EXTERNAL_SYMPTOM_JOURNAL","MANAGE_PUBLIC_EXPORT_CONFIGURATION","OUTBREAK_EDIT","OUTBREAK_VIEW","PATHOGEN_TEST_CREATE","PATHOGEN_TEST_DELETE","PATHOGEN_TEST_EDIT","PERFORM_BULK_OPERATIONS","PERFORM_BULK_OPERATIONS_CASE_SAMPLES","PERFORM_BULK_OPERATIONS_EVENT","PERFORM_BULK_OPERATIONS_EVENTPARTICIPANT","PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES","PERFORM_BULK_OPERATIONS_PSEUDONYM","PERSON_CONTACT_DETAILS_DELETE","PERSON_DELETE","PERSON_EDIT","PERSON_EXPORT","PERSON_MERGE","PERSON_VIEW","POPULATION_MANAGE","PORT_HEALTH_INFO_EDIT","PORT_HEALTH_INFO_VIEW","PRESCRIPTION_CREATE","PRESCRIPTION_DELETE","PRESCRIPTION_EDIT","QUARANTINE_ORDER_CREATE","SAMPLE_CREATE","SAMPLE_DELETE","SAMPLE_EDIT","SAMPLE_EDIT_NOT_OWNED","SAMPLE_EXPORT","SAMPLE_TRANSFER","SAMPLE_VIEW","SEE_PERSONAL_DATA_IN_JURISDICTION","SEE_SENSITIVE_DATA_IN_JURISDICTION","SEND_MANUAL_EXTERNAL_MESSAGES","SORMAS_REST","SORMAS_UI","STATISTICS_ACCESS","STATISTICS_EXPORT","TASK_ARCHIVE","TASK_ASSIGN","TASK_CREATE","TASK_DELETE","TASK_EDIT","TASK_EXPORT","TASK_VIEW","THERAPY_VIEW","TRAVEL_ENTRY_ARCHIVE","TRAVEL_ENTRY_CREATE","TRAVEL_ENTRY_DELETE","TRAVEL_ENTRY_EDIT","TRAVEL_ENTRY_MANAGEMENT_ACCESS","TRAVEL_ENTRY_VIEW","TREATMENT_CREATE","TREATMENT_DELETE","TREATMENT_EDIT","USER_CREATE","USER_EDIT","USER_ROLE_DELETE","USER_ROLE_EDIT","USER_ROLE_VIEW","USER_VIEW","VISIT_CREATE","VISIT_DELETE","VISIT_EDIT","VISIT_EXPORT","WEEKLYREPORT_VIEW"] \ No newline at end of file diff --git a/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/NationalUserRights.json b/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/NationalUserRights.json index 5475bb26b31..f59cc339141 100644 --- a/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/NationalUserRights.json +++ b/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/NationalUserRights.json @@ -1 +1 @@ -["ACTION_CREATE","ACTION_DELETE","ACTION_EDIT","ADDITIONAL_TEST_DELETE","ADDITIONAL_TEST_VIEW","AGGREGATE_REPORT_EDIT","AGGREGATE_REPORT_EXPORT","AGGREGATE_REPORT_VIEW","CAMPAIGN_ARCHIVE","CAMPAIGN_FORM_DATA_ARCHIVE","CAMPAIGN_FORM_DATA_EDIT","CAMPAIGN_FORM_DATA_EXPORT","CAMPAIGN_FORM_DATA_VIEW","CAMPAIGN_VIEW","CASE_CHANGE_DISEASE","CASE_CHANGE_EPID_NUMBER","CASE_CLASSIFY","CASE_CREATE","CASE_DELETE","CASE_EDIT","CASE_EXPORT","CASE_INVESTIGATE","CASE_REFER_FROM_POE","CASE_SHARE","CASE_TRANSFER","CASE_VIEW","CLINICAL_COURSE_VIEW","CLINICAL_VISIT_DELETE","CONTACT_CONVERT","CONTACT_CREATE","CONTACT_DELETE","CONTACT_EDIT","CONTACT_EXPORT","CONTACT_REASSIGN_CASE","CONTACT_VIEW","DASHBOARD_CAMPAIGNS_VIEW","DASHBOARD_CONTACT_VIEW","DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS","DASHBOARD_SAMPLES_VIEW","DASHBOARD_SURVEILLANCE_VIEW","DATABASE_EXPORT_ACCESS","DOCUMENT_DELETE","DOCUMENT_UPLOAD","DOCUMENT_VIEW","ENVIRONMENT_ARCHIVE","ENVIRONMENT_CREATE","ENVIRONMENT_DELETE","ENVIRONMENT_EDIT","ENVIRONMENT_EXPORT","ENVIRONMENT_IMPORT","ENVIRONMENT_SAMPLE_CREATE","ENVIRONMENT_SAMPLE_DELETE","ENVIRONMENT_SAMPLE_EDIT","ENVIRONMENT_SAMPLE_EDIT_DISPATCH","ENVIRONMENT_SAMPLE_EDIT_RECEIVAL","ENVIRONMENT_SAMPLE_EXPORT","ENVIRONMENT_SAMPLE_IMPORT","ENVIRONMENT_SAMPLE_VIEW","ENVIRONMENT_VIEW","EVENTGROUP_CREATE","EVENTGROUP_DELETE","EVENTGROUP_EDIT","EVENTGROUP_LINK","EVENTPARTICIPANT_CREATE","EVENTPARTICIPANT_DELETE","EVENTPARTICIPANT_EDIT","EVENTPARTICIPANT_IMPORT","EVENTPARTICIPANT_VIEW","EVENT_CREATE","EVENT_DELETE","EVENT_EDIT","EVENT_EXPORT","EVENT_VIEW","EXTERNAL_EMAIL_ATTACH_DOCUMENTS","EXTERNAL_EMAIL_SEND","EXTERNAL_MESSAGE_DELETE","EXTERNAL_MESSAGE_PROCESS","EXTERNAL_MESSAGE_VIEW","IMMUNIZATION_CREATE","IMMUNIZATION_DELETE","IMMUNIZATION_EDIT","IMMUNIZATION_VIEW","INFRASTRUCTURE_ARCHIVE","INFRASTRUCTURE_EXPORT","INFRASTRUCTURE_VIEW","LINE_LISTING_CONFIGURE","MANAGE_EXTERNAL_SYMPTOM_JOURNAL","MANAGE_PUBLIC_EXPORT_CONFIGURATION","OUTBREAK_EDIT","OUTBREAK_VIEW","PATHOGEN_TEST_CREATE","PATHOGEN_TEST_DELETE","PATHOGEN_TEST_EDIT","PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES","PERSON_CONTACT_DETAILS_DELETE","PERSON_DELETE","PERSON_EDIT","PERSON_EXPORT","PERSON_MERGE","PERSON_VIEW","PORT_HEALTH_INFO_EDIT","PORT_HEALTH_INFO_VIEW","PRESCRIPTION_DELETE","QUARANTINE_ORDER_CREATE","SAMPLE_CREATE","SAMPLE_DELETE","SAMPLE_EDIT","SAMPLE_EXPORT","SAMPLE_TRANSFER","SAMPLE_VIEW","SEE_PERSONAL_DATA_IN_JURISDICTION","SEE_SENSITIVE_DATA_IN_JURISDICTION","SEND_MANUAL_EXTERNAL_MESSAGES","SORMAS_REST","SORMAS_UI","STATISTICS_ACCESS","STATISTICS_EXPORT","TASK_ARCHIVE","TASK_ASSIGN","TASK_CREATE","TASK_DELETE","TASK_EDIT","TASK_EXPORT","TASK_VIEW","THERAPY_VIEW","TRAVEL_ENTRY_CREATE","TRAVEL_ENTRY_DELETE","TRAVEL_ENTRY_EDIT","TRAVEL_ENTRY_MANAGEMENT_ACCESS","TRAVEL_ENTRY_VIEW","TREATMENT_DELETE","VISIT_CREATE","VISIT_DELETE","VISIT_EDIT","VISIT_EXPORT","WEEKLYREPORT_VIEW"] \ No newline at end of file +["ACTION_CREATE","ACTION_DELETE","ACTION_EDIT","ADDITIONAL_TEST_DELETE","ADDITIONAL_TEST_VIEW","AGGREGATE_REPORT_EDIT","AGGREGATE_REPORT_EXPORT","AGGREGATE_REPORT_VIEW","CAMPAIGN_ARCHIVE","CAMPAIGN_FORM_DATA_ARCHIVE","CAMPAIGN_FORM_DATA_EDIT","CAMPAIGN_FORM_DATA_EXPORT","CAMPAIGN_FORM_DATA_VIEW","CAMPAIGN_VIEW","CASE_CHANGE_DISEASE","CASE_CHANGE_EPID_NUMBER","CASE_CLASSIFY","CASE_CREATE","CASE_DELETE","CASE_EDIT","CASE_EXPORT","CASE_INVESTIGATE","CASE_REFER_FROM_POE","CASE_SHARE","CASE_TRANSFER","CASE_VIEW","CLINICAL_COURSE_VIEW","CLINICAL_VISIT_DELETE","CONTACT_CONVERT","CONTACT_CREATE","CONTACT_DELETE","CONTACT_EDIT","CONTACT_EXPORT","CONTACT_REASSIGN_CASE","CONTACT_VIEW","DASHBOARD_CAMPAIGNS_VIEW","DASHBOARD_CONTACT_VIEW","DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS","DASHBOARD_SAMPLES_VIEW","DASHBOARD_SURVEILLANCE_VIEW","DATABASE_EXPORT_ACCESS","DOCUMENT_DELETE","DOCUMENT_UPLOAD","DOCUMENT_VIEW","ENVIRONMENT_ARCHIVE","ENVIRONMENT_CREATE","ENVIRONMENT_DELETE","ENVIRONMENT_EDIT","ENVIRONMENT_EXPORT","ENVIRONMENT_IMPORT","ENVIRONMENT_PATHOGEN_TEST_CREATE","ENVIRONMENT_PATHOGEN_TEST_DELETE","ENVIRONMENT_PATHOGEN_TEST_EDIT","ENVIRONMENT_SAMPLE_CREATE","ENVIRONMENT_SAMPLE_DELETE","ENVIRONMENT_SAMPLE_EDIT","ENVIRONMENT_SAMPLE_EDIT_DISPATCH","ENVIRONMENT_SAMPLE_EDIT_RECEIVAL","ENVIRONMENT_SAMPLE_EXPORT","ENVIRONMENT_SAMPLE_IMPORT","ENVIRONMENT_SAMPLE_VIEW","ENVIRONMENT_VIEW","EVENTGROUP_CREATE","EVENTGROUP_DELETE","EVENTGROUP_EDIT","EVENTGROUP_LINK","EVENTPARTICIPANT_CREATE","EVENTPARTICIPANT_DELETE","EVENTPARTICIPANT_EDIT","EVENTPARTICIPANT_IMPORT","EVENTPARTICIPANT_VIEW","EVENT_CREATE","EVENT_DELETE","EVENT_EDIT","EVENT_EXPORT","EVENT_VIEW","EXTERNAL_EMAIL_ATTACH_DOCUMENTS","EXTERNAL_EMAIL_SEND","EXTERNAL_MESSAGE_DELETE","EXTERNAL_MESSAGE_PROCESS","EXTERNAL_MESSAGE_VIEW","IMMUNIZATION_CREATE","IMMUNIZATION_DELETE","IMMUNIZATION_EDIT","IMMUNIZATION_VIEW","INFRASTRUCTURE_ARCHIVE","INFRASTRUCTURE_EXPORT","INFRASTRUCTURE_VIEW","LINE_LISTING_CONFIGURE","MANAGE_EXTERNAL_SYMPTOM_JOURNAL","MANAGE_PUBLIC_EXPORT_CONFIGURATION","OUTBREAK_EDIT","OUTBREAK_VIEW","PATHOGEN_TEST_CREATE","PATHOGEN_TEST_DELETE","PATHOGEN_TEST_EDIT","PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES","PERSON_CONTACT_DETAILS_DELETE","PERSON_DELETE","PERSON_EDIT","PERSON_EXPORT","PERSON_MERGE","PERSON_VIEW","PORT_HEALTH_INFO_EDIT","PORT_HEALTH_INFO_VIEW","PRESCRIPTION_DELETE","QUARANTINE_ORDER_CREATE","SAMPLE_CREATE","SAMPLE_DELETE","SAMPLE_EDIT","SAMPLE_EXPORT","SAMPLE_TRANSFER","SAMPLE_VIEW","SEE_PERSONAL_DATA_IN_JURISDICTION","SEE_SENSITIVE_DATA_IN_JURISDICTION","SEND_MANUAL_EXTERNAL_MESSAGES","SORMAS_REST","SORMAS_UI","STATISTICS_ACCESS","STATISTICS_EXPORT","TASK_ARCHIVE","TASK_ASSIGN","TASK_CREATE","TASK_DELETE","TASK_EDIT","TASK_EXPORT","TASK_VIEW","THERAPY_VIEW","TRAVEL_ENTRY_CREATE","TRAVEL_ENTRY_DELETE","TRAVEL_ENTRY_EDIT","TRAVEL_ENTRY_MANAGEMENT_ACCESS","TRAVEL_ENTRY_VIEW","TREATMENT_DELETE","VISIT_CREATE","VISIT_DELETE","VISIT_EDIT","VISIT_EXPORT","WEEKLYREPORT_VIEW"] \ No newline at end of file diff --git a/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/NationalUserRightsDE.json b/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/NationalUserRightsDE.json index ad8be1744ac..8c3becda9dc 100644 --- a/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/NationalUserRightsDE.json +++ b/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/NationalUserRightsDE.json @@ -1 +1,2 @@ - ["ACTION_CREATE","ACTION_DELETE","ACTION_EDIT","ADDITIONAL_TEST_DELETE","ADDITIONAL_TEST_VIEW","AGGREGATE_REPORT_EDIT","AGGREGATE_REPORT_EXPORT","AGGREGATE_REPORT_VIEW","CAMPAIGN_ARCHIVE","CAMPAIGN_FORM_DATA_ARCHIVE","CAMPAIGN_FORM_DATA_EDIT","CAMPAIGN_FORM_DATA_EXPORT","CAMPAIGN_FORM_DATA_VIEW","CAMPAIGN_VIEW","CASE_CHANGE_DISEASE","CASE_CHANGE_EPID_NUMBER","CASE_CLASSIFY","CASE_CREATE","CASE_DELETE","CASE_EDIT","CASE_EXPORT","CASE_INVESTIGATE","CASE_REFER_FROM_POE","CASE_SHARE","CASE_TRANSFER","CASE_VIEW","CLINICAL_COURSE_VIEW","CLINICAL_VISIT_DELETE","CONTACT_CONVERT","CONTACT_CREATE","CONTACT_DELETE","CONTACT_EDIT","CONTACT_EXPORT","CONTACT_REASSIGN_CASE","CONTACT_VIEW","DASHBOARD_CAMPAIGNS_VIEW","DASHBOARD_CONTACT_VIEW","DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS","DASHBOARD_SAMPLES_VIEW","DASHBOARD_SURVEILLANCE_VIEW","DATABASE_EXPORT_ACCESS","DOCUMENT_DELETE","DOCUMENT_UPLOAD","DOCUMENT_VIEW","ENVIRONMENT_ARCHIVE","ENVIRONMENT_CREATE","ENVIRONMENT_DELETE","ENVIRONMENT_EDIT","ENVIRONMENT_EXPORT","ENVIRONMENT_IMPORT","ENVIRONMENT_SAMPLE_CREATE","ENVIRONMENT_SAMPLE_DELETE","ENVIRONMENT_SAMPLE_EDIT","ENVIRONMENT_SAMPLE_EDIT_DISPATCH","ENVIRONMENT_SAMPLE_EDIT_RECEIVAL","ENVIRONMENT_SAMPLE_EXPORT","ENVIRONMENT_SAMPLE_IMPORT","ENVIRONMENT_SAMPLE_VIEW","ENVIRONMENT_VIEW","EVENTGROUP_CREATE","EVENTGROUP_DELETE","EVENTGROUP_EDIT","EVENTGROUP_LINK","EVENTPARTICIPANT_CREATE","EVENTPARTICIPANT_DELETE","EVENTPARTICIPANT_EDIT","EVENTPARTICIPANT_IMPORT","EVENTPARTICIPANT_VIEW","EVENT_CREATE","EVENT_DELETE","EVENT_EDIT","EVENT_EXPORT","EVENT_VIEW","EXTERNAL_EMAIL_ATTACH_DOCUMENTS","EXTERNAL_EMAIL_SEND","EXTERNAL_MESSAGE_DELETE","EXTERNAL_MESSAGE_PROCESS","EXTERNAL_MESSAGE_VIEW","IMMUNIZATION_CREATE","IMMUNIZATION_DELETE","IMMUNIZATION_EDIT","IMMUNIZATION_VIEW","INFRASTRUCTURE_ARCHIVE","INFRASTRUCTURE_EXPORT","INFRASTRUCTURE_VIEW","LINE_LISTING_CONFIGURE","MANAGE_EXTERNAL_SYMPTOM_JOURNAL","MANAGE_PUBLIC_EXPORT_CONFIGURATION","OUTBREAK_EDIT","OUTBREAK_VIEW","PATHOGEN_TEST_CREATE","PATHOGEN_TEST_DELETE","PATHOGEN_TEST_EDIT","PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES","PERSON_CONTACT_DETAILS_DELETE","PERSON_DELETE","PERSON_EDIT","PERSON_EXPORT","PERSON_MERGE","PERSON_VIEW","PORT_HEALTH_INFO_EDIT","PORT_HEALTH_INFO_VIEW","PRESCRIPTION_DELETE","QUARANTINE_ORDER_CREATE","SAMPLE_CREATE","SAMPLE_DELETE","SAMPLE_EDIT","SAMPLE_EXPORT","SAMPLE_TRANSFER","SAMPLE_VIEW","SEE_PERSONAL_DATA_IN_JURISDICTION","SEE_SENSITIVE_DATA_IN_JURISDICTION","SEND_MANUAL_EXTERNAL_MESSAGES","SORMAS_REST","SORMAS_UI","STATISTICS_ACCESS","STATISTICS_EXPORT","TASK_ARCHIVE","TASK_ASSIGN","TASK_CREATE","TASK_DELETE","TASK_EDIT","TASK_EXPORT","TASK_VIEW","THERAPY_VIEW","TRAVEL_ENTRY_CREATE","TRAVEL_ENTRY_DELETE","TRAVEL_ENTRY_EDIT","TRAVEL_ENTRY_MANAGEMENT_ACCESS","TRAVEL_ENTRY_VIEW","TREATMENT_DELETE","VISIT_CREATE","VISIT_DELETE","VISIT_EDIT","VISIT_EXPORT","WEEKLYREPORT_VIEW"] \ No newline at end of file + +["ACTION_CREATE","ACTION_DELETE","ACTION_EDIT","ADDITIONAL_TEST_DELETE","ADDITIONAL_TEST_VIEW","AGGREGATE_REPORT_EDIT","AGGREGATE_REPORT_EXPORT","AGGREGATE_REPORT_VIEW","CAMPAIGN_ARCHIVE","CAMPAIGN_FORM_DATA_ARCHIVE","CAMPAIGN_FORM_DATA_EDIT","CAMPAIGN_FORM_DATA_EXPORT","CAMPAIGN_FORM_DATA_VIEW","CAMPAIGN_VIEW","CASE_CHANGE_DISEASE","CASE_CHANGE_EPID_NUMBER","CASE_CLASSIFY","CASE_CREATE","CASE_DELETE","CASE_EDIT","CASE_EXPORT","CASE_INVESTIGATE","CASE_REFER_FROM_POE","CASE_SHARE","CASE_TRANSFER","CASE_VIEW","CLINICAL_COURSE_VIEW","CLINICAL_VISIT_DELETE","CONTACT_CONVERT","CONTACT_CREATE","CONTACT_DELETE","CONTACT_EDIT","CONTACT_EXPORT","CONTACT_REASSIGN_CASE","CONTACT_VIEW","DASHBOARD_CAMPAIGNS_VIEW","DASHBOARD_CONTACT_VIEW","DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS","DASHBOARD_SAMPLES_VIEW","DASHBOARD_SURVEILLANCE_VIEW","DATABASE_EXPORT_ACCESS","DOCUMENT_DELETE","DOCUMENT_UPLOAD","DOCUMENT_VIEW","ENVIRONMENT_ARCHIVE","ENVIRONMENT_CREATE","ENVIRONMENT_DELETE","ENVIRONMENT_EDIT","ENVIRONMENT_EXPORT","ENVIRONMENT_IMPORT","ENVIRONMENT_PATHOGEN_TEST_CREATE","ENVIRONMENT_PATHOGEN_TEST_DELETE","ENVIRONMENT_PATHOGEN_TEST_EDIT","ENVIRONMENT_SAMPLE_CREATE","ENVIRONMENT_SAMPLE_DELETE","ENVIRONMENT_SAMPLE_EDIT","ENVIRONMENT_SAMPLE_EDIT_DISPATCH","ENVIRONMENT_SAMPLE_EDIT_RECEIVAL","ENVIRONMENT_SAMPLE_EXPORT","ENVIRONMENT_SAMPLE_IMPORT","ENVIRONMENT_SAMPLE_VIEW","ENVIRONMENT_VIEW","EVENTGROUP_CREATE","EVENTGROUP_DELETE","EVENTGROUP_EDIT","EVENTGROUP_LINK","EVENTPARTICIPANT_CREATE","EVENTPARTICIPANT_DELETE","EVENTPARTICIPANT_EDIT","EVENTPARTICIPANT_IMPORT","EVENTPARTICIPANT_VIEW","EVENT_CREATE","EVENT_DELETE","EVENT_EDIT","EVENT_EXPORT","EVENT_VIEW","EXTERNAL_EMAIL_ATTACH_DOCUMENTS","EXTERNAL_EMAIL_SEND","EXTERNAL_MESSAGE_DELETE","EXTERNAL_MESSAGE_PROCESS","EXTERNAL_MESSAGE_VIEW","IMMUNIZATION_CREATE","IMMUNIZATION_DELETE","IMMUNIZATION_EDIT","IMMUNIZATION_VIEW","INFRASTRUCTURE_ARCHIVE","INFRASTRUCTURE_EXPORT","INFRASTRUCTURE_VIEW","LINE_LISTING_CONFIGURE","MANAGE_EXTERNAL_SYMPTOM_JOURNAL","MANAGE_PUBLIC_EXPORT_CONFIGURATION","OUTBREAK_EDIT","OUTBREAK_VIEW","PATHOGEN_TEST_CREATE","PATHOGEN_TEST_DELETE","PATHOGEN_TEST_EDIT","PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES","PERSON_CONTACT_DETAILS_DELETE","PERSON_DELETE","PERSON_EDIT","PERSON_EXPORT","PERSON_MERGE","PERSON_VIEW","PORT_HEALTH_INFO_EDIT","PORT_HEALTH_INFO_VIEW","PRESCRIPTION_DELETE","QUARANTINE_ORDER_CREATE","SAMPLE_CREATE","SAMPLE_DELETE","SAMPLE_EDIT","SAMPLE_EXPORT","SAMPLE_TRANSFER","SAMPLE_VIEW","SEE_PERSONAL_DATA_IN_JURISDICTION","SEE_SENSITIVE_DATA_IN_JURISDICTION","SEND_MANUAL_EXTERNAL_MESSAGES","SORMAS_REST","SORMAS_UI","STATISTICS_ACCESS","STATISTICS_EXPORT","TASK_ARCHIVE","TASK_ASSIGN","TASK_CREATE","TASK_DELETE","TASK_EDIT","TASK_EXPORT","TASK_VIEW","THERAPY_VIEW","TRAVEL_ENTRY_CREATE","TRAVEL_ENTRY_DELETE","TRAVEL_ENTRY_EDIT","TRAVEL_ENTRY_MANAGEMENT_ACCESS","TRAVEL_ENTRY_VIEW","TREATMENT_DELETE","VISIT_CREATE","VISIT_DELETE","VISIT_EDIT","VISIT_EXPORT","WEEKLYREPORT_VIEW"] \ No newline at end of file diff --git a/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/SormasToSormasUserRights.json b/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/SormasToSormasUserRights.json index f61489c8410..ebf4e074b5a 100644 --- a/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/SormasToSormasUserRights.json +++ b/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/SormasToSormasUserRights.json @@ -1 +1 @@ -["ACTION_CREATE","ACTION_DELETE","ACTION_EDIT","ADDITIONAL_TEST_CREATE","ADDITIONAL_TEST_DELETE","ADDITIONAL_TEST_EDIT","ADDITIONAL_TEST_VIEW","AGGREGATE_REPORT_EDIT","AGGREGATE_REPORT_EXPORT","AGGREGATE_REPORT_VIEW","CAMPAIGN_ARCHIVE","CAMPAIGN_DELETE","CAMPAIGN_EDIT","CAMPAIGN_FORM_DATA_ARCHIVE","CAMPAIGN_FORM_DATA_DELETE","CAMPAIGN_FORM_DATA_EDIT","CAMPAIGN_FORM_DATA_EXPORT","CAMPAIGN_FORM_DATA_VIEW","CAMPAIGN_VIEW","CASE_ARCHIVE","CASE_CHANGE_DISEASE","CASE_CHANGE_EPID_NUMBER","CASE_CLASSIFY","CASE_CLINICIAN_VIEW","CASE_CREATE","CASE_DELETE","CASE_EDIT","CASE_EXPORT","CASE_IMPORT","CASE_INVESTIGATE","CASE_MERGE","CASE_REFER_FROM_POE","CASE_SHARE","CASE_TRANSFER","CASE_VIEW","CLINICAL_COURSE_EDIT","CLINICAL_COURSE_VIEW","CLINICAL_VISIT_CREATE","CLINICAL_VISIT_DELETE","CLINICAL_VISIT_EDIT","CONTACT_ARCHIVE","CONTACT_CONVERT","CONTACT_CREATE","CONTACT_DELETE","CONTACT_EDIT","CONTACT_EXPORT","CONTACT_IMPORT","CONTACT_MERGE","CONTACT_REASSIGN_CASE","CONTACT_VIEW","CUSTOMIZABLE_ENUM_MANAGEMENT","DASHBOARD_CAMPAIGNS_VIEW","DASHBOARD_CONTACT_VIEW","DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS","DASHBOARD_SAMPLES_VIEW","DASHBOARD_SURVEILLANCE_VIEW","DATABASE_EXPORT_ACCESS","DEV_MODE","DOCUMENT_DELETE","DOCUMENT_TEMPLATE_MANAGEMENT","DOCUMENT_UPLOAD","DOCUMENT_VIEW","EMAIL_TEMPLATE_MANAGEMENT","ENVIRONMENT_ARCHIVE","ENVIRONMENT_CREATE","ENVIRONMENT_DELETE","ENVIRONMENT_EDIT","ENVIRONMENT_EXPORT","ENVIRONMENT_IMPORT","ENVIRONMENT_SAMPLE_CREATE","ENVIRONMENT_SAMPLE_DELETE","ENVIRONMENT_SAMPLE_EDIT","ENVIRONMENT_SAMPLE_EDIT_DISPATCH","ENVIRONMENT_SAMPLE_EDIT_RECEIVAL","ENVIRONMENT_SAMPLE_EXPORT","ENVIRONMENT_SAMPLE_IMPORT","ENVIRONMENT_SAMPLE_VIEW","ENVIRONMENT_VIEW","EVENTGROUP_ARCHIVE","EVENTGROUP_CREATE","EVENTGROUP_DELETE","EVENTGROUP_EDIT","EVENTGROUP_LINK","EVENTPARTICIPANT_ARCHIVE","EVENTPARTICIPANT_CREATE","EVENTPARTICIPANT_DELETE","EVENTPARTICIPANT_EDIT","EVENTPARTICIPANT_IMPORT","EVENTPARTICIPANT_VIEW","EVENT_ARCHIVE","EVENT_CREATE","EVENT_DELETE","EVENT_EDIT","EVENT_EXPORT","EVENT_IMPORT","EVENT_VIEW","EXPORT_DATA_PROTECTION_DATA","EXTERNAL_EMAIL_ATTACH_DOCUMENTS","EXTERNAL_EMAIL_SEND","EXTERNAL_MESSAGE_DELETE","EXTERNAL_MESSAGE_PROCESS","EXTERNAL_MESSAGE_VIEW","EXTERNAL_SURVEILLANCE_DELETE","EXTERNAL_SURVEILLANCE_SHARE","IMMUNIZATION_ARCHIVE","IMMUNIZATION_CREATE","IMMUNIZATION_DELETE","IMMUNIZATION_EDIT","IMMUNIZATION_VIEW","INFRASTRUCTURE_ARCHIVE","INFRASTRUCTURE_CREATE","INFRASTRUCTURE_EDIT","INFRASTRUCTURE_EXPORT","INFRASTRUCTURE_IMPORT","INFRASTRUCTURE_VIEW","LINE_LISTING_CONFIGURE","MANAGE_EXTERNAL_SYMPTOM_JOURNAL","MANAGE_PUBLIC_EXPORT_CONFIGURATION","OUTBREAK_EDIT","OUTBREAK_VIEW","PATHOGEN_TEST_CREATE","PATHOGEN_TEST_DELETE","PATHOGEN_TEST_EDIT","PERFORM_BULK_OPERATIONS","PERFORM_BULK_OPERATIONS_CASE_SAMPLES","PERFORM_BULK_OPERATIONS_EVENT","PERFORM_BULK_OPERATIONS_EVENTPARTICIPANT","PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES","PERFORM_BULK_OPERATIONS_PSEUDONYM","PERSON_CONTACT_DETAILS_DELETE","PERSON_DELETE","PERSON_EDIT","PERSON_EXPORT","PERSON_MERGE","PERSON_VIEW","POPULATION_MANAGE","PORT_HEALTH_INFO_EDIT","PORT_HEALTH_INFO_VIEW","PRESCRIPTION_CREATE","PRESCRIPTION_DELETE","PRESCRIPTION_EDIT","QUARANTINE_ORDER_CREATE","SAMPLE_CREATE","SAMPLE_DELETE","SAMPLE_EDIT","SAMPLE_EDIT_NOT_OWNED","SAMPLE_EXPORT","SAMPLE_TRANSFER","SAMPLE_VIEW","SEE_PERSONAL_DATA_IN_JURISDICTION","SEE_SENSITIVE_DATA_IN_JURISDICTION","SEND_MANUAL_EXTERNAL_MESSAGES","SORMAS_REST","SORMAS_TO_SORMAS_PROCESS","SORMAS_TO_SORMAS_SHARE","SORMAS_UI","STATISTICS_ACCESS","STATISTICS_EXPORT","TASK_ARCHIVE","TASK_ASSIGN","TASK_CREATE","TASK_DELETE","TASK_EDIT","TASK_EXPORT","TASK_VIEW","THERAPY_VIEW","TRAVEL_ENTRY_ARCHIVE","TRAVEL_ENTRY_CREATE","TRAVEL_ENTRY_DELETE","TRAVEL_ENTRY_EDIT","TRAVEL_ENTRY_MANAGEMENT_ACCESS","TRAVEL_ENTRY_VIEW","TREATMENT_CREATE","TREATMENT_DELETE","TREATMENT_EDIT","USER_CREATE","USER_EDIT","USER_ROLE_DELETE","USER_ROLE_EDIT","USER_ROLE_VIEW","USER_VIEW","VISIT_CREATE","VISIT_DELETE","VISIT_EDIT","VISIT_EXPORT","WEEKLYREPORT_VIEW"] \ No newline at end of file +["ACTION_CREATE","ACTION_DELETE","ACTION_EDIT","ADDITIONAL_TEST_CREATE","ADDITIONAL_TEST_DELETE","ADDITIONAL_TEST_EDIT","ADDITIONAL_TEST_VIEW","AGGREGATE_REPORT_EDIT","AGGREGATE_REPORT_EXPORT","AGGREGATE_REPORT_VIEW","CAMPAIGN_ARCHIVE","CAMPAIGN_DELETE","CAMPAIGN_EDIT","CAMPAIGN_FORM_DATA_ARCHIVE","CAMPAIGN_FORM_DATA_DELETE","CAMPAIGN_FORM_DATA_EDIT","CAMPAIGN_FORM_DATA_EXPORT","CAMPAIGN_FORM_DATA_VIEW","CAMPAIGN_VIEW","CASE_ARCHIVE","CASE_CHANGE_DISEASE","CASE_CHANGE_EPID_NUMBER","CASE_CLASSIFY","CASE_CLINICIAN_VIEW","CASE_CREATE","CASE_DELETE","CASE_EDIT","CASE_EXPORT","CASE_IMPORT","CASE_INVESTIGATE","CASE_MERGE","CASE_REFER_FROM_POE","CASE_SHARE","CASE_TRANSFER","CASE_VIEW","CLINICAL_COURSE_EDIT","CLINICAL_COURSE_VIEW","CLINICAL_VISIT_CREATE","CLINICAL_VISIT_DELETE","CLINICAL_VISIT_EDIT","CONTACT_ARCHIVE","CONTACT_CONVERT","CONTACT_CREATE","CONTACT_DELETE","CONTACT_EDIT","CONTACT_EXPORT","CONTACT_IMPORT","CONTACT_MERGE","CONTACT_REASSIGN_CASE","CONTACT_VIEW","CUSTOMIZABLE_ENUM_MANAGEMENT","DASHBOARD_CAMPAIGNS_VIEW","DASHBOARD_CONTACT_VIEW","DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS","DASHBOARD_SAMPLES_VIEW","DASHBOARD_SURVEILLANCE_VIEW","DATABASE_EXPORT_ACCESS","DEV_MODE","DOCUMENT_DELETE","DOCUMENT_TEMPLATE_MANAGEMENT","DOCUMENT_UPLOAD","DOCUMENT_VIEW","EMAIL_TEMPLATE_MANAGEMENT","ENVIRONMENT_ARCHIVE","ENVIRONMENT_CREATE","ENVIRONMENT_DELETE","ENVIRONMENT_EDIT","ENVIRONMENT_EXPORT","ENVIRONMENT_IMPORT","ENVIRONMENT_PATHOGEN_TEST_CREATE","ENVIRONMENT_PATHOGEN_TEST_DELETE","ENVIRONMENT_PATHOGEN_TEST_EDIT","ENVIRONMENT_SAMPLE_CREATE","ENVIRONMENT_SAMPLE_DELETE","ENVIRONMENT_SAMPLE_EDIT","ENVIRONMENT_SAMPLE_EDIT_DISPATCH","ENVIRONMENT_SAMPLE_EDIT_RECEIVAL","ENVIRONMENT_SAMPLE_EXPORT","ENVIRONMENT_SAMPLE_IMPORT","ENVIRONMENT_SAMPLE_VIEW","ENVIRONMENT_VIEW","EVENTGROUP_ARCHIVE","EVENTGROUP_CREATE","EVENTGROUP_DELETE","EVENTGROUP_EDIT","EVENTGROUP_LINK","EVENTPARTICIPANT_ARCHIVE","EVENTPARTICIPANT_CREATE","EVENTPARTICIPANT_DELETE","EVENTPARTICIPANT_EDIT","EVENTPARTICIPANT_IMPORT","EVENTPARTICIPANT_VIEW","EVENT_ARCHIVE","EVENT_CREATE","EVENT_DELETE","EVENT_EDIT","EVENT_EXPORT","EVENT_IMPORT","EVENT_VIEW","EXPORT_DATA_PROTECTION_DATA","EXTERNAL_EMAIL_ATTACH_DOCUMENTS","EXTERNAL_EMAIL_SEND","EXTERNAL_MESSAGE_DELETE","EXTERNAL_MESSAGE_PROCESS","EXTERNAL_MESSAGE_VIEW","EXTERNAL_SURVEILLANCE_DELETE","EXTERNAL_SURVEILLANCE_SHARE","IMMUNIZATION_ARCHIVE","IMMUNIZATION_CREATE","IMMUNIZATION_DELETE","IMMUNIZATION_EDIT","IMMUNIZATION_VIEW","INFRASTRUCTURE_ARCHIVE","INFRASTRUCTURE_CREATE","INFRASTRUCTURE_EDIT","INFRASTRUCTURE_EXPORT","INFRASTRUCTURE_IMPORT","INFRASTRUCTURE_VIEW","LINE_LISTING_CONFIGURE","MANAGE_EXTERNAL_SYMPTOM_JOURNAL","MANAGE_PUBLIC_EXPORT_CONFIGURATION","OUTBREAK_EDIT","OUTBREAK_VIEW","PATHOGEN_TEST_CREATE","PATHOGEN_TEST_DELETE","PATHOGEN_TEST_EDIT","PERFORM_BULK_OPERATIONS","PERFORM_BULK_OPERATIONS_CASE_SAMPLES","PERFORM_BULK_OPERATIONS_EVENT","PERFORM_BULK_OPERATIONS_EVENTPARTICIPANT","PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES","PERFORM_BULK_OPERATIONS_PSEUDONYM","PERSON_CONTACT_DETAILS_DELETE","PERSON_DELETE","PERSON_EDIT","PERSON_EXPORT","PERSON_MERGE","PERSON_VIEW","POPULATION_MANAGE","PORT_HEALTH_INFO_EDIT","PORT_HEALTH_INFO_VIEW","PRESCRIPTION_CREATE","PRESCRIPTION_DELETE","PRESCRIPTION_EDIT","QUARANTINE_ORDER_CREATE","SAMPLE_CREATE","SAMPLE_DELETE","SAMPLE_EDIT","SAMPLE_EDIT_NOT_OWNED","SAMPLE_EXPORT","SAMPLE_TRANSFER","SAMPLE_VIEW","SEE_PERSONAL_DATA_IN_JURISDICTION","SEE_SENSITIVE_DATA_IN_JURISDICTION","SEND_MANUAL_EXTERNAL_MESSAGES","SORMAS_REST","SORMAS_TO_SORMAS_PROCESS","SORMAS_TO_SORMAS_SHARE","SORMAS_UI","STATISTICS_ACCESS","STATISTICS_EXPORT","TASK_ARCHIVE","TASK_ASSIGN","TASK_CREATE","TASK_DELETE","TASK_EDIT","TASK_EXPORT","TASK_VIEW","THERAPY_VIEW","TRAVEL_ENTRY_ARCHIVE","TRAVEL_ENTRY_CREATE","TRAVEL_ENTRY_DELETE","TRAVEL_ENTRY_EDIT","TRAVEL_ENTRY_MANAGEMENT_ACCESS","TRAVEL_ENTRY_VIEW","TREATMENT_CREATE","TREATMENT_DELETE","TREATMENT_EDIT","USER_CREATE","USER_EDIT","USER_ROLE_DELETE","USER_ROLE_EDIT","USER_ROLE_VIEW","USER_VIEW","VISIT_CREATE","VISIT_DELETE","VISIT_EDIT","VISIT_EXPORT","WEEKLYREPORT_VIEW"] \ No newline at end of file diff --git a/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/SurvnetUserRights.json b/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/SurvnetUserRights.json index f61489c8410..ebf4e074b5a 100644 --- a/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/SurvnetUserRights.json +++ b/sormas-e2e-tests/src/main/resources/userRightsJsonTemplates/SurvnetUserRights.json @@ -1 +1 @@ -["ACTION_CREATE","ACTION_DELETE","ACTION_EDIT","ADDITIONAL_TEST_CREATE","ADDITIONAL_TEST_DELETE","ADDITIONAL_TEST_EDIT","ADDITIONAL_TEST_VIEW","AGGREGATE_REPORT_EDIT","AGGREGATE_REPORT_EXPORT","AGGREGATE_REPORT_VIEW","CAMPAIGN_ARCHIVE","CAMPAIGN_DELETE","CAMPAIGN_EDIT","CAMPAIGN_FORM_DATA_ARCHIVE","CAMPAIGN_FORM_DATA_DELETE","CAMPAIGN_FORM_DATA_EDIT","CAMPAIGN_FORM_DATA_EXPORT","CAMPAIGN_FORM_DATA_VIEW","CAMPAIGN_VIEW","CASE_ARCHIVE","CASE_CHANGE_DISEASE","CASE_CHANGE_EPID_NUMBER","CASE_CLASSIFY","CASE_CLINICIAN_VIEW","CASE_CREATE","CASE_DELETE","CASE_EDIT","CASE_EXPORT","CASE_IMPORT","CASE_INVESTIGATE","CASE_MERGE","CASE_REFER_FROM_POE","CASE_SHARE","CASE_TRANSFER","CASE_VIEW","CLINICAL_COURSE_EDIT","CLINICAL_COURSE_VIEW","CLINICAL_VISIT_CREATE","CLINICAL_VISIT_DELETE","CLINICAL_VISIT_EDIT","CONTACT_ARCHIVE","CONTACT_CONVERT","CONTACT_CREATE","CONTACT_DELETE","CONTACT_EDIT","CONTACT_EXPORT","CONTACT_IMPORT","CONTACT_MERGE","CONTACT_REASSIGN_CASE","CONTACT_VIEW","CUSTOMIZABLE_ENUM_MANAGEMENT","DASHBOARD_CAMPAIGNS_VIEW","DASHBOARD_CONTACT_VIEW","DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS","DASHBOARD_SAMPLES_VIEW","DASHBOARD_SURVEILLANCE_VIEW","DATABASE_EXPORT_ACCESS","DEV_MODE","DOCUMENT_DELETE","DOCUMENT_TEMPLATE_MANAGEMENT","DOCUMENT_UPLOAD","DOCUMENT_VIEW","EMAIL_TEMPLATE_MANAGEMENT","ENVIRONMENT_ARCHIVE","ENVIRONMENT_CREATE","ENVIRONMENT_DELETE","ENVIRONMENT_EDIT","ENVIRONMENT_EXPORT","ENVIRONMENT_IMPORT","ENVIRONMENT_SAMPLE_CREATE","ENVIRONMENT_SAMPLE_DELETE","ENVIRONMENT_SAMPLE_EDIT","ENVIRONMENT_SAMPLE_EDIT_DISPATCH","ENVIRONMENT_SAMPLE_EDIT_RECEIVAL","ENVIRONMENT_SAMPLE_EXPORT","ENVIRONMENT_SAMPLE_IMPORT","ENVIRONMENT_SAMPLE_VIEW","ENVIRONMENT_VIEW","EVENTGROUP_ARCHIVE","EVENTGROUP_CREATE","EVENTGROUP_DELETE","EVENTGROUP_EDIT","EVENTGROUP_LINK","EVENTPARTICIPANT_ARCHIVE","EVENTPARTICIPANT_CREATE","EVENTPARTICIPANT_DELETE","EVENTPARTICIPANT_EDIT","EVENTPARTICIPANT_IMPORT","EVENTPARTICIPANT_VIEW","EVENT_ARCHIVE","EVENT_CREATE","EVENT_DELETE","EVENT_EDIT","EVENT_EXPORT","EVENT_IMPORT","EVENT_VIEW","EXPORT_DATA_PROTECTION_DATA","EXTERNAL_EMAIL_ATTACH_DOCUMENTS","EXTERNAL_EMAIL_SEND","EXTERNAL_MESSAGE_DELETE","EXTERNAL_MESSAGE_PROCESS","EXTERNAL_MESSAGE_VIEW","EXTERNAL_SURVEILLANCE_DELETE","EXTERNAL_SURVEILLANCE_SHARE","IMMUNIZATION_ARCHIVE","IMMUNIZATION_CREATE","IMMUNIZATION_DELETE","IMMUNIZATION_EDIT","IMMUNIZATION_VIEW","INFRASTRUCTURE_ARCHIVE","INFRASTRUCTURE_CREATE","INFRASTRUCTURE_EDIT","INFRASTRUCTURE_EXPORT","INFRASTRUCTURE_IMPORT","INFRASTRUCTURE_VIEW","LINE_LISTING_CONFIGURE","MANAGE_EXTERNAL_SYMPTOM_JOURNAL","MANAGE_PUBLIC_EXPORT_CONFIGURATION","OUTBREAK_EDIT","OUTBREAK_VIEW","PATHOGEN_TEST_CREATE","PATHOGEN_TEST_DELETE","PATHOGEN_TEST_EDIT","PERFORM_BULK_OPERATIONS","PERFORM_BULK_OPERATIONS_CASE_SAMPLES","PERFORM_BULK_OPERATIONS_EVENT","PERFORM_BULK_OPERATIONS_EVENTPARTICIPANT","PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES","PERFORM_BULK_OPERATIONS_PSEUDONYM","PERSON_CONTACT_DETAILS_DELETE","PERSON_DELETE","PERSON_EDIT","PERSON_EXPORT","PERSON_MERGE","PERSON_VIEW","POPULATION_MANAGE","PORT_HEALTH_INFO_EDIT","PORT_HEALTH_INFO_VIEW","PRESCRIPTION_CREATE","PRESCRIPTION_DELETE","PRESCRIPTION_EDIT","QUARANTINE_ORDER_CREATE","SAMPLE_CREATE","SAMPLE_DELETE","SAMPLE_EDIT","SAMPLE_EDIT_NOT_OWNED","SAMPLE_EXPORT","SAMPLE_TRANSFER","SAMPLE_VIEW","SEE_PERSONAL_DATA_IN_JURISDICTION","SEE_SENSITIVE_DATA_IN_JURISDICTION","SEND_MANUAL_EXTERNAL_MESSAGES","SORMAS_REST","SORMAS_TO_SORMAS_PROCESS","SORMAS_TO_SORMAS_SHARE","SORMAS_UI","STATISTICS_ACCESS","STATISTICS_EXPORT","TASK_ARCHIVE","TASK_ASSIGN","TASK_CREATE","TASK_DELETE","TASK_EDIT","TASK_EXPORT","TASK_VIEW","THERAPY_VIEW","TRAVEL_ENTRY_ARCHIVE","TRAVEL_ENTRY_CREATE","TRAVEL_ENTRY_DELETE","TRAVEL_ENTRY_EDIT","TRAVEL_ENTRY_MANAGEMENT_ACCESS","TRAVEL_ENTRY_VIEW","TREATMENT_CREATE","TREATMENT_DELETE","TREATMENT_EDIT","USER_CREATE","USER_EDIT","USER_ROLE_DELETE","USER_ROLE_EDIT","USER_ROLE_VIEW","USER_VIEW","VISIT_CREATE","VISIT_DELETE","VISIT_EDIT","VISIT_EXPORT","WEEKLYREPORT_VIEW"] \ No newline at end of file +["ACTION_CREATE","ACTION_DELETE","ACTION_EDIT","ADDITIONAL_TEST_CREATE","ADDITIONAL_TEST_DELETE","ADDITIONAL_TEST_EDIT","ADDITIONAL_TEST_VIEW","AGGREGATE_REPORT_EDIT","AGGREGATE_REPORT_EXPORT","AGGREGATE_REPORT_VIEW","CAMPAIGN_ARCHIVE","CAMPAIGN_DELETE","CAMPAIGN_EDIT","CAMPAIGN_FORM_DATA_ARCHIVE","CAMPAIGN_FORM_DATA_DELETE","CAMPAIGN_FORM_DATA_EDIT","CAMPAIGN_FORM_DATA_EXPORT","CAMPAIGN_FORM_DATA_VIEW","CAMPAIGN_VIEW","CASE_ARCHIVE","CASE_CHANGE_DISEASE","CASE_CHANGE_EPID_NUMBER","CASE_CLASSIFY","CASE_CLINICIAN_VIEW","CASE_CREATE","CASE_DELETE","CASE_EDIT","CASE_EXPORT","CASE_IMPORT","CASE_INVESTIGATE","CASE_MERGE","CASE_REFER_FROM_POE","CASE_SHARE","CASE_TRANSFER","CASE_VIEW","CLINICAL_COURSE_EDIT","CLINICAL_COURSE_VIEW","CLINICAL_VISIT_CREATE","CLINICAL_VISIT_DELETE","CLINICAL_VISIT_EDIT","CONTACT_ARCHIVE","CONTACT_CONVERT","CONTACT_CREATE","CONTACT_DELETE","CONTACT_EDIT","CONTACT_EXPORT","CONTACT_IMPORT","CONTACT_MERGE","CONTACT_REASSIGN_CASE","CONTACT_VIEW","CUSTOMIZABLE_ENUM_MANAGEMENT","DASHBOARD_CAMPAIGNS_VIEW","DASHBOARD_CONTACT_VIEW","DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS","DASHBOARD_SAMPLES_VIEW","DASHBOARD_SURVEILLANCE_VIEW","DATABASE_EXPORT_ACCESS","DEV_MODE","DOCUMENT_DELETE","DOCUMENT_TEMPLATE_MANAGEMENT","DOCUMENT_UPLOAD","DOCUMENT_VIEW","EMAIL_TEMPLATE_MANAGEMENT","ENVIRONMENT_ARCHIVE","ENVIRONMENT_CREATE","ENVIRONMENT_DELETE","ENVIRONMENT_EDIT","ENVIRONMENT_EXPORT","ENVIRONMENT_IMPORT","ENVIRONMENT_PATHOGEN_TEST_CREATE","ENVIRONMENT_PATHOGEN_TEST_DELETE","ENVIRONMENT_PATHOGEN_TEST_EDIT","ENVIRONMENT_SAMPLE_CREATE","ENVIRONMENT_SAMPLE_DELETE","ENVIRONMENT_SAMPLE_EDIT","ENVIRONMENT_SAMPLE_EDIT_DISPATCH","ENVIRONMENT_SAMPLE_EDIT_RECEIVAL","ENVIRONMENT_SAMPLE_EXPORT","ENVIRONMENT_SAMPLE_IMPORT","ENVIRONMENT_SAMPLE_VIEW","ENVIRONMENT_VIEW","EVENTGROUP_ARCHIVE","EVENTGROUP_CREATE","EVENTGROUP_DELETE","EVENTGROUP_EDIT","EVENTGROUP_LINK","EVENTPARTICIPANT_ARCHIVE","EVENTPARTICIPANT_CREATE","EVENTPARTICIPANT_DELETE","EVENTPARTICIPANT_EDIT","EVENTPARTICIPANT_IMPORT","EVENTPARTICIPANT_VIEW","EVENT_ARCHIVE","EVENT_CREATE","EVENT_DELETE","EVENT_EDIT","EVENT_EXPORT","EVENT_IMPORT","EVENT_VIEW","EXPORT_DATA_PROTECTION_DATA","EXTERNAL_EMAIL_ATTACH_DOCUMENTS","EXTERNAL_EMAIL_SEND","EXTERNAL_MESSAGE_DELETE","EXTERNAL_MESSAGE_PROCESS","EXTERNAL_MESSAGE_VIEW","EXTERNAL_SURVEILLANCE_DELETE","EXTERNAL_SURVEILLANCE_SHARE","IMMUNIZATION_ARCHIVE","IMMUNIZATION_CREATE","IMMUNIZATION_DELETE","IMMUNIZATION_EDIT","IMMUNIZATION_VIEW","INFRASTRUCTURE_ARCHIVE","INFRASTRUCTURE_CREATE","INFRASTRUCTURE_EDIT","INFRASTRUCTURE_EXPORT","INFRASTRUCTURE_IMPORT","INFRASTRUCTURE_VIEW","LINE_LISTING_CONFIGURE","MANAGE_EXTERNAL_SYMPTOM_JOURNAL","MANAGE_PUBLIC_EXPORT_CONFIGURATION","OUTBREAK_EDIT","OUTBREAK_VIEW","PATHOGEN_TEST_CREATE","PATHOGEN_TEST_DELETE","PATHOGEN_TEST_EDIT","PERFORM_BULK_OPERATIONS","PERFORM_BULK_OPERATIONS_CASE_SAMPLES","PERFORM_BULK_OPERATIONS_EVENT","PERFORM_BULK_OPERATIONS_EVENTPARTICIPANT","PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES","PERFORM_BULK_OPERATIONS_PSEUDONYM","PERSON_CONTACT_DETAILS_DELETE","PERSON_DELETE","PERSON_EDIT","PERSON_EXPORT","PERSON_MERGE","PERSON_VIEW","POPULATION_MANAGE","PORT_HEALTH_INFO_EDIT","PORT_HEALTH_INFO_VIEW","PRESCRIPTION_CREATE","PRESCRIPTION_DELETE","PRESCRIPTION_EDIT","QUARANTINE_ORDER_CREATE","SAMPLE_CREATE","SAMPLE_DELETE","SAMPLE_EDIT","SAMPLE_EDIT_NOT_OWNED","SAMPLE_EXPORT","SAMPLE_TRANSFER","SAMPLE_VIEW","SEE_PERSONAL_DATA_IN_JURISDICTION","SEE_SENSITIVE_DATA_IN_JURISDICTION","SEND_MANUAL_EXTERNAL_MESSAGES","SORMAS_REST","SORMAS_TO_SORMAS_PROCESS","SORMAS_TO_SORMAS_SHARE","SORMAS_UI","STATISTICS_ACCESS","STATISTICS_EXPORT","TASK_ARCHIVE","TASK_ASSIGN","TASK_CREATE","TASK_DELETE","TASK_EDIT","TASK_EXPORT","TASK_VIEW","THERAPY_VIEW","TRAVEL_ENTRY_ARCHIVE","TRAVEL_ENTRY_CREATE","TRAVEL_ENTRY_DELETE","TRAVEL_ENTRY_EDIT","TRAVEL_ENTRY_MANAGEMENT_ACCESS","TRAVEL_ENTRY_VIEW","TREATMENT_CREATE","TREATMENT_DELETE","TREATMENT_EDIT","USER_CREATE","USER_EDIT","USER_ROLE_DELETE","USER_ROLE_EDIT","USER_ROLE_VIEW","USER_VIEW","VISIT_CREATE","VISIT_DELETE","VISIT_EDIT","VISIT_EXPORT","WEEKLYREPORT_VIEW"] \ No newline at end of file diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/helpers/WebDriverHelpers.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/helpers/WebDriverHelpers.java index fc6236a4ba1..2cb9f5feeca 100755 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/helpers/WebDriverHelpers.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/helpers/WebDriverHelpers.java @@ -19,9 +19,11 @@ import static java.time.Duration.ofSeconds; import static org.awaitility.Awaitility.await; import static org.awaitility.Durations.ONE_HUNDRED_MILLISECONDS; +import static org.sormas.e2etests.steps.BaseSteps.driver; import java.nio.file.Files; import java.nio.file.Path; +import java.time.Duration; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.ArrayList; @@ -45,6 +47,8 @@ import org.openqa.selenium.WebElement; import org.openqa.selenium.WindowType; import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.WebDriverWait; import org.sormas.e2etests.common.TimerLite; import org.sormas.e2etests.steps.BaseSteps; import org.testng.Assert; @@ -72,6 +76,50 @@ public WebDriverHelpers(BaseSteps baseSteps, AssertHelpers assertHelpers) { this.assertHelpers = assertHelpers; } + public static String waitForSpinnerNotVisible(int timeOutInSeconds) { + driver.getCurrentUrl(); + if ((driver == null) || (driver.getCurrentUrl() == null) || driver.getCurrentUrl().isEmpty()) { + + return "Wrong usage of waitForSpinnerNotVisible()"; + } + try { + (new WebDriverWait(driver, Duration.ofSeconds(timeOutInSeconds))) + .until(ExpectedConditions.invisibilityOfElementLocated(By.xpath(driver.getCurrentUrl()))); + return null; + } catch (TimeoutException e) { + return "Too short time for waitForSpinnerNotVisible()"; + } + } + + public static void waitForElementPresent(By selector, int timeOutInSeconds) { + try { + driver.getCurrentUrl(); + new WebDriverWait(driver, Duration.ofSeconds(timeOutInSeconds)) + .until(ExpectedConditions.presenceOfElementLocated(selector)); + } catch (NoSuchElementException e) { + System.err.println("Element not found:" + e.getMessage()); + } catch (TimeoutException e) { + System.err.println("Timeout waiting for element:" + e.getMessage()); + } catch (Exception e) { + System.err.println("An expected error occurred: " + e.getMessage()); + } + } + + public void ClickAndWaitForNewFormLoaded(By selector, By newForm) { + try { + driver.getCurrentUrl(); + driver.findElement(selector).click(); + WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(35)); + wait.until(ExpectedConditions.visibilityOfElementLocated(newForm)); + } catch (NoSuchElementException e) { + System.err.println("Element not found:" + e.getMessage()); + } catch (TimeoutException e) { + System.err.println("Timeout waiting for element: " + e.getMessage()); + } catch (Exception e) { + System.err.println("An excepted error occurred: " + e.getMessage()); + } + } + private WebElement findElement(By selector) { try { return baseSteps.getDriver().findElement(selector); diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/cases/CaseDirectorySteps.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/cases/CaseDirectorySteps.java index 259a6e056ff..ef357afc30b 100644 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/cases/CaseDirectorySteps.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/cases/CaseDirectorySteps.java @@ -628,14 +628,16 @@ public CaseDirectorySteps( Then( "I check that number of displayed cases results is {int}", - (Integer number) -> - assertHelpers.assertWithPoll20Second( - () -> - Assert.assertEquals( - Integer.parseInt( - webDriverHelpers.getTextFromPresentWebElement(TOTAL_CASES_COUNTER)), - number.intValue(), - "Number of displayed cases is not correct"))); + (Integer number) -> { + webDriverHelpers.waitForPageLoadingSpinnerToDisappear(120); + assertHelpers.assertWithPoll20Second( + () -> + Assert.assertEquals( + Integer.parseInt( + webDriverHelpers.getTextFromPresentWebElement(TOTAL_CASES_COUNTER)), + number.intValue(), + "Number of displayed cases is not correct")); + }); And( "I filter by mocked CaseID on Case directory page", @@ -1566,7 +1568,8 @@ public CaseDirectorySteps( webDriverHelpers.waitUntilIdentifiedElementIsPresent(SEND_TO_REPORTING_TOOL_BUTTON); webDriverHelpers.clickOnWebElementBySelector(SEND_TO_REPORTING_TOOL_BUTTON); webDriverHelpers.clickOnWebElementBySelector(CONFIRM_ACTION); - webDriverHelpers.waitUntilIdentifiedElementIsPresent(REPORTING_TOOL_MESSAGE); + webDriverHelpers.waitForSpinnerNotVisible(30); + webDriverHelpers.waitForElementPresent(REPORTING_TOOL_MESSAGE, 30); }); And( @@ -1738,6 +1741,8 @@ public CaseDirectorySteps( And( "^I set the Relevance Status Filter to \"([^\"]*)\" on Case Directory page$", (String status) -> { + webDriverHelpers.waitUntilIdentifiedElementIsVisibleAndClickable( + RELEVANT_STATUS_COMBOBOX); webDriverHelpers.selectFromCombobox(RELEVANT_STATUS_COMBOBOX, status); }); } diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/cases/CreateNewCaseSteps.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/cases/CreateNewCaseSteps.java index 565e6572a08..75dbd2be6de 100644 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/cases/CreateNewCaseSteps.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/cases/CreateNewCaseSteps.java @@ -127,6 +127,9 @@ import static org.sormas.e2etests.pages.application.entries.EditTravelEntryPage.DISCARD_TASK_BUTTON; import static org.sormas.e2etests.pages.application.entries.TravelEntryPage.NEW_PERSON_RADIOBUTTON_DE; import static org.sormas.e2etests.pages.application.entries.TravelEntryPage.PICK_OR_CREATE_PERSON_HEADER_DE; +import static org.sormas.e2etests.pages.application.events.EventParticipantsPage.CREATE_NEW_CASE_RADIO_BUTTON; +import static org.sormas.e2etests.pages.application.events.EventParticipantsPage.PICK_OR_CASE_PERSON_POPUP; +import static org.sormas.e2etests.pages.application.events.EventParticipantsPage.PICK_OR_CASE_POPUP_SAVE_BUTTON; import static org.sormas.e2etests.pages.application.persons.PersonDirectoryPage.SEARCH_PERSON_BY_FREE_TEXT; import static org.sormas.e2etests.pages.application.shares.EditSharesPage.SHARE_UUID_CASE_TITLE; import static org.sormas.e2etests.steps.web.application.cases.EditCaseSteps.aCase; @@ -572,8 +575,18 @@ public CreateNewCaseSteps( webDriverHelpers.waitForPageLoadingSpinnerToDisappear(20); webDriverHelpers.waitUntilElementIsVisibleAndClickable(EditCasePage.REPORT_DATE_INPUT); webDriverHelpers.clickOnWebElementBySelector(CASE_SAVED_POPUP); + }); - TimeUnit.SECONDS.sleep(2); + When( + "^I create a new case for the same person$", + () -> { + fillAllCaseFieldsForTheSamePerson(caze); + webDriverHelpers.waitUntilIdentifiedElementIsVisibleAndClickable(CONFIRM_BUTTON_POPUP); + webDriverHelpers.clickOnWebElementBySelector(CONFIRM_BUTTON_POPUP); + if (webDriverHelpers.isElementVisibleWithTimeout(PICK_OR_CASE_PERSON_POPUP, 15)) { + webDriverHelpers.clickOnWebElementBySelector(CREATE_NEW_CASE_RADIO_BUTTON); + webDriverHelpers.clickOnWebElementBySelector(PICK_OR_CASE_POPUP_SAVE_BUTTON); + } }); Then( @@ -1847,6 +1860,21 @@ private void fillAllCaseFields(Case caze) { fillPlaceDescription(caze.getPlaceDescription()); } + private void fillAllCaseFieldsForTheSamePerson(Case caze) { + selectCaseOrigin(caze.getCaseOrigin()); + fillDisease(caze.getDisease()); + selectResponsibleRegion(caze.getResponsibleRegion()); + selectResponsibleDistrict(caze.getResponsibleDistrict()); + selectResponsibleCommunity(caze.getResponsibleCommunity()); + selectPlaceOfStay(caze.getPlaceOfStay()); + selectPresentConditionOfPerson(caze.getPresentConditionOfPerson()); + fillDateOfSymptomOnset(caze.getDateOfSymptomOnset(), Locale.ENGLISH); + fillPrimaryPhoneNumber(caze.getPrimaryPhoneNumber()); + fillPrimaryEmailAddress(caze.getPrimaryEmailAddress()); + fillDateOfReport(caze.getDateOfReport(), Locale.ENGLISH); + fillPlaceDescription(caze.getPlaceDescription()); + } + private void fillAllCaseFieldsWithSpecificRegion(Case caze, String region) { selectCaseOrigin(caze.getCaseOrigin()); fillDisease(caze.getDisease()); diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/cases/EditCaseSteps.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/cases/EditCaseSteps.java index ed7a5945ade..f8ef8cf8386 100644 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/cases/EditCaseSteps.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/cases/EditCaseSteps.java @@ -1203,7 +1203,7 @@ public EditCaseSteps( When( "I check if ([^\"]*) quarantine popup is displayed", (String option) -> { - TimeUnit.SECONDS.sleep(2); + webDriverHelpers.waitForElementPresent(QUARANTINE_COMBOBOX, 2); String quarantineText; String expectedTextReduce = "Are you sure you want to reduce the quarantine?"; String expectedTextExtend = "Are you sure you want to extend the quarantine?"; @@ -1537,8 +1537,7 @@ public EditCaseSteps( When( "I check that text appearing in hover over Expected Follow-up is based on Report date", () -> { - TimeUnit.SECONDS.sleep(2); - webDriverHelpers.waitUntilElementIsVisibleAndClickable(EXPECTED_FOLLOWUP_LABEL); + webDriverHelpers.waitForElementPresent(EXPECTED_FOLLOWUP_LABEL, 2); webDriverHelpers.hoverToElement(EXPECTED_FOLLOWUP_LABEL); String displayedText = webDriverHelpers.getTextFromWebElement(EXPECTED_FOLLOWUP_POPUP_TEXT); @@ -1576,7 +1575,7 @@ public EditCaseSteps( When( "I check that text appearing in hover based over Symptoms onset date over Expected Follow-up consists of date days is equal to symptoms onset date", () -> { - TimeUnit.SECONDS.sleep(2); + webDriverHelpers.waitForElementPresent(EXPECTED_FOLLOWUP_LABEL, 2); webDriverHelpers.scrollToElement(EXPECTED_FOLLOWUP_LABEL); webDriverHelpers.waitUntilElementIsVisibleAndClickable(EXPECTED_FOLLOWUP_LABEL); webDriverHelpers.hoverToElement(EXPECTED_FOLLOWUP_LABEL); @@ -1818,10 +1817,8 @@ public EditCaseSteps( When( "I check that case classification is set to one of the confirmed classifications in German on Edit case page", () -> { - TimeUnit.SECONDS.sleep( - 3); // Required to ensure that the value we're asserting is refreshed after saving - // sample webDriverHelpers.waitForPageLoadingSpinnerToDisappear(40); + webDriverHelpers.waitForElementPresent(CASE_CLASSIFICATION_COMBOBOX, 3); String caseClassification = webDriverHelpers.getValueFromCombobox(CASE_CLASSIFICATION_COMBOBOX); softly.assertTrue( @@ -2205,8 +2202,7 @@ public EditCaseSteps( "I check if editable fields are enabled for the case in view", () -> { webDriverHelpers.waitForPageLoadingSpinnerToDisappear(30); - TimeUnit.SECONDS.sleep(3); - webDriverHelpers.waitUntilElementIsVisibleAndClickable(BACK_TO_CASES_LIST_BUTTON); + webDriverHelpers.waitForElementPresent(BACK_TO_CASES_LIST_BUTTON, 3); softly.assertEquals( webDriverHelpers.isElementEnabled(INVESTIGATION_STATUS_OPTIONS), true, @@ -3088,7 +3084,7 @@ public EditCaseSteps( When( "I check if Follow up until date is ([^\"]*) days after last created API case report date", (Integer days) -> { - TimeUnit.SECONDS.sleep(3); + webDriverHelpers.waitForElementPresent(FOLLOW_UP_UNTIL_DATE, 3); String date = webDriverHelpers.getValueFromWebElement(FOLLOW_UP_UNTIL_DATE); softly.assertEquals( DateTimeFormatter.ofPattern("dd.MM.yyyy") diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/configuration/DistrictsSteps.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/configuration/DistrictsSteps.java index 97d766f4da8..8e646953b62 100644 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/configuration/DistrictsSteps.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/configuration/DistrictsSteps.java @@ -49,6 +49,7 @@ import static org.sormas.e2etests.pages.application.entries.CreateNewTravelEntryPage.ARRIVAL_DATE; import static org.sormas.e2etests.pages.application.entries.CreateNewTravelEntryPage.FIRST_NAME_OF_CONTACT_PERSON_INPUT; import static org.sormas.e2etests.pages.application.entries.CreateNewTravelEntryPage.LAST_NAME_OF_CONTACT_PERSON_INPUT; +import static org.sormas.e2etests.pages.application.entries.CreateNewTravelEntryPage.RESPONSIBLE_DISTRICT_COMBOBOX; import static org.sormas.e2etests.pages.application.entries.EditTravelEntryPage.DISEASE_COMBOBOX; import static org.sormas.e2etests.pages.application.entries.EditTravelEntryPage.DISEASE_NAME_INPUT; import static org.sormas.e2etests.pages.application.entries.EditTravelEntryPage.FIRST_NAME_INPUT; @@ -140,6 +141,21 @@ public DistrictsSteps( sex = travelEntry.getSex(); fillDateOfArrival(travelEntry.getDateOfArrival(), Locale.GERMAN); selectResponsibleRegion(districts.getRegion()); + long timeoutInMillis = 120000; + long startTime = System.currentTimeMillis(); + boolean districtAvailability; + districtAvailability = + webDriverHelpers.checkIfElementExistsInCombobox( + RESPONSIBLE_DISTRICT_COMBOBOX, districts.getDistrictName()); + while (districtAvailability == false + && (System.currentTimeMillis() - startTime) < timeoutInMillis) { + selectResponsibleRegion( + "Baden-W\u00FCrttemberg"); // for refresh region combobox purpose + selectResponsibleRegion(districts.getRegion()); + districtAvailability = + webDriverHelpers.checkIfElementExistsInCombobox( + RESPONSIBLE_DISTRICT_COMBOBOX, districts.getDistrictName()); + } selectResponsibleDistrict(districts.getDistrictName()); fillDisease(travelEntry.getDisease()); disease = travelEntry.getDisease(); @@ -404,8 +420,7 @@ private void selectResponsibleRegion(String selectResponsibleRegion) { } private void selectResponsibleDistrict(String responsibleDistrict) { - webDriverHelpers.selectFromCombobox( - CreateNewTravelEntryPage.RESPONSIBLE_DISTRICT_COMBOBOX, responsibleDistrict); + webDriverHelpers.selectFromCombobox(RESPONSIBLE_DISTRICT_COMBOBOX, responsibleDistrict); } private void fillDisease(String disease) { diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/entries/TravelEntryDirectorySteps.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/entries/TravelEntryDirectorySteps.java index b3fc3987277..b0b25b20f43 100644 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/entries/TravelEntryDirectorySteps.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/entries/TravelEntryDirectorySteps.java @@ -221,7 +221,7 @@ public TravelEntryDirectorySteps( When( "I open the imported person on Travel entry directory page", () -> { - TimeUnit.SECONDS.sleep(3); // waiting for grid refresh + webDriverHelpers.waitForSpinnerNotVisible(20); webDriverHelpers.waitUntilElementIsVisibleAndClickable(FIRST_RESULT_ID); webDriverHelpers.clickOnWebElementBySelector(FIRST_RESULT_ID); }); @@ -314,7 +314,7 @@ public TravelEntryDirectorySteps( (String value) -> webDriverHelpers.selectFromCombobox(TRAVEL_ENTRY_DATA_FILTER_OPTION_COMBOBOX, value)); Then( - "I apply the last epi week for week from combobox on Travel Entry directory page", + "I set the last epi week date in week from combobox field on Travel Entry directory page", () -> { int week = CreateNewTravelEntrySteps.previousWeekDate.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR); @@ -326,26 +326,26 @@ public TravelEntryDirectorySteps( }); Then( - "I apply the last epi week for week to combobox on Travel Entry directory page", + "I set the last epi week date in week to combobox field on Travel Entry directory page", () -> { int week = - CreateNewTravelEntrySteps.previousWeekDate.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR) - + 1; // because weeks are counting since end of december previous year + CreateNewTravelEntrySteps.previousWeekDate.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR); + // + 1; // because weeks are counting since end of december previous year if (week == 53) week = 1; LocalDate newYearSuprise = LocalDate.now().minusDays(7); - String lastEpiWeek = "Wo " + week + "-" + LocalDate.now().getYear(); + String lastEpiWeek = "Wo " + week + "-" + newYearSuprise.getYear(); webDriverHelpers.selectFromCombobox(WEEK_TO_OPTION_COMBOBOX, lastEpiWeek); }); Then( - "I apply the week before the last epi week for week to combobox on Travel Entry directory page", + "I set the last epi week before date in week to combobox field on Travel Entry directory page", () -> { - int week = - CreateNewTravelEntrySteps.previousWeekDate.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR); - if (week == 53) week = 1; + int weekBeforeLastEpiWeek = + CreateNewTravelEntrySteps.previousWeekDate.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR) - 1; + if (weekBeforeLastEpiWeek == 53) weekBeforeLastEpiWeek = 1; LocalDate newYearSuprise = LocalDate.now().minusDays(7); - String lastEpiWeek = "Wo " + week + "-" + newYearSuprise.getYear(); + String lastEpiWeek = "Wo " + weekBeforeLastEpiWeek + "-" + newYearSuprise.getYear(); webDriverHelpers.selectFromCombobox(WEEK_TO_OPTION_COMBOBOX, lastEpiWeek); }); diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/events/EditEventSteps.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/events/EditEventSteps.java index 8a1b98ac288..de1be326381 100644 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/events/EditEventSteps.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/events/EditEventSteps.java @@ -166,12 +166,14 @@ import static org.sormas.e2etests.pages.application.events.EventParticipantsPage.DELETE_EVENT_PARTICIPANT_BUTTTON; import static org.sormas.e2etests.pages.application.events.EventParticipantsPage.DISCARD_BUTTON; import static org.sormas.e2etests.pages.application.events.EventParticipantsPage.ERROR_MESSAGE_TEXT; +import static org.sormas.e2etests.pages.application.events.EventParticipantsPage.EVENT_PARTICIPANTS; import static org.sormas.e2etests.pages.application.events.EventParticipantsPage.EVENT_PARTICIPANTS_GRID; import static org.sormas.e2etests.pages.application.events.EventParticipantsPage.EVENT_PARTICIPANTS_TAB; import static org.sormas.e2etests.pages.application.events.EventParticipantsPage.EVENT_PARTICIPANT_DATA_TAB; import static org.sormas.e2etests.pages.application.events.EventParticipantsPage.EVENT_PARTICIPANT_DISPLAY_FILTER_COMBOBOX; import static org.sormas.e2etests.pages.application.events.EventParticipantsPage.EVENT_PARTICIPANT_PERSON_TAB; import static org.sormas.e2etests.pages.application.events.EventParticipantsPage.EVENT_PARTICIPANT_UUID; +import static org.sormas.e2etests.pages.application.events.EventParticipantsPage.EVENT_PARTICIPANT_UUID_INPUT; import static org.sormas.e2etests.pages.application.events.EventParticipantsPage.EVENT_TAB; import static org.sormas.e2etests.pages.application.events.EventParticipantsPage.GENERAL_COMMENT_TEXT_AREA; import static org.sormas.e2etests.pages.application.events.EventParticipantsPage.INVOLVEMENT_DESCRIPTION_INPUT; @@ -280,6 +282,7 @@ public class EditEventSteps implements En { private static String eventParticipantUUID; private static String eventUUID; public static List externalEventUUID = new ArrayList<>(); + public static List eventParticipantsUUIDList = new ArrayList<>(); LocalDate dateOfBirth; List eventParticipantList = new ArrayList<>(); @@ -765,6 +768,21 @@ public EditEventSteps( PARTICIPANT_DISTRICT_COMBOBOX, DistrictsValues.VoreingestellterLandkreis.getName()); }); + When( + "I add Participant to an Event with the new person data", + () -> { + String fName = faker.name().firstName(); + String lName = faker.name().lastName(); + String sexEn = GenderValues.getRandomGender(); + webDriverHelpers.fillInWebElement(PARTICIPANT_FIRST_NAME_INPUT, fName); + webDriverHelpers.fillInWebElement(PARTICIPANT_LAST_NAME_INPUT, lName); + webDriverHelpers.selectFromCombobox(SEX_COMBOBOX, sexEn); + webDriverHelpers.selectFromCombobox( + PARTICIPANT_REGION_COMBOBOX, RegionsValues.VoreingestellteBundeslander.getName()); + webDriverHelpers.selectFromCombobox( + PARTICIPANT_DISTRICT_COMBOBOX, DistrictsValues.VoreingestellterLandkreis.getName()); + }); + When( "I click on save button in Add Participant form", () -> { @@ -841,6 +859,12 @@ public EditEventSteps( webDriverHelpers.clickOnWebElementBySelector(EVENT_PARTICIPANT_DATA_TAB); }); + When( + "I click on Event Participants tab", + () -> { + webDriverHelpers.clickOnWebElementBySelector(EVENT_PARTICIPANTS); + }); + When( "I add a participant to the event in DE", () -> { @@ -2044,6 +2068,18 @@ public EditEventSteps( "^I save Add participant form$", () -> { webDriverHelpers.clickOnWebElementBySelector(SAVE_BUTTON_FOR_POPUP_WINDOWS); + if (webDriverHelpers.isElementVisibleWithTimeout(PICK_OR_CREATE_PERSON_POPUP, 15)) { + webDriverHelpers.clickOnWebElementBySelector(CREATE_NEW_PERSON_RADIO_BUTTON); + webDriverHelpers.clickOnWebElementBySelector(PICK_OR_CREATE_POPUP_SAVE_BUTTON); + } + }); + + And( + "^I collect event participant uuid$", + () -> { + String eventParticipantUuid = + webDriverHelpers.getValueFromWebElement(EVENT_PARTICIPANT_UUID_INPUT); + eventParticipantsUUIDList.add(eventParticipantUuid); }); When( diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/events/EventDirectorySteps.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/events/EventDirectorySteps.java index 817e597eb3e..88c2f77eb41 100644 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/events/EventDirectorySteps.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/events/EventDirectorySteps.java @@ -1322,7 +1322,7 @@ public EventDirectorySteps( (String option) -> { webDriverHelpers.selectFromCombobox(EVENT_PARTICIPANT_DISPLAY_FILTER_COMBOBOX, option); TimeUnit.SECONDS.sleep(3); // wait for reaction - webDriverHelpers.waitForPageLoadingSpinnerToDisappear(100); + webDriverHelpers.waitForPageLoadingSpinnerToDisappear(160); }); When( diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/immunizations/EditImmunizationSteps.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/immunizations/EditImmunizationSteps.java index 67efa25af76..f2798d18891 100644 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/immunizations/EditImmunizationSteps.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/immunizations/EditImmunizationSteps.java @@ -288,9 +288,10 @@ public EditImmunizationSteps( When( "I click on Yes option in Confirm deletion popup", () -> { + webDriverHelpers.waitUntilIdentifiedElementIsVisibleAndClickable(ACTION_CONFIRM_BUTTON); webDriverHelpers.clickOnWebElementBySelector(ACTION_CONFIRM_BUTTON); TimeUnit.SECONDS.sleep(1); // wait for page loaded - webDriverHelpers.waitForPageLoadingSpinnerToDisappear(40); + webDriverHelpers.waitForPageLoadingSpinnerToDisappear(100); }); When( diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/mSers/CreateNewAggregateReportSteps.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/mSers/CreateNewAggregateReportSteps.java index 1296e831060..d6bfcf52be5 100644 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/mSers/CreateNewAggregateReportSteps.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/mSers/CreateNewAggregateReportSteps.java @@ -166,7 +166,7 @@ public CreateNewAggregateReportSteps( Then( "^I check if last listed week from Epi week combobox is the current week of the year$", () -> { - int currentWeek = LocalDate.now().get(IsoFields.WEEK_OF_WEEK_BASED_YEAR) + 1; + int currentWeek = LocalDate.now().get(IsoFields.WEEK_OF_WEEK_BASED_YEAR); int nextYear = LocalDate.now().getYear() + 1; if (currentWeek < 52) { diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/messages/MessagesDirectorySteps.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/messages/MessagesDirectorySteps.java index 513f38e4e8b..ee78c5e48b4 100644 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/messages/MessagesDirectorySteps.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/messages/MessagesDirectorySteps.java @@ -131,6 +131,7 @@ public MessagesDirectorySteps( And( "^I verify that status for result (\\d+) is set to processed in Message Directory page$", (Integer resultNumber) -> { + TimeUnit.SECONDS.sleep(1); //waiting for refresh softly.assertEquals( webDriverHelpers.getTextFromWebElement(getProcessStatusByIndex(resultNumber)), "Verarbeitet", diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/persons/EditPersonSteps.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/persons/EditPersonSteps.java index 47b7b9d687d..e3e414f54eb 100644 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/persons/EditPersonSteps.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/persons/EditPersonSteps.java @@ -70,6 +70,7 @@ import static org.sormas.e2etests.pages.application.persons.EditPersonPage.MAP_CONTAINER_EDIT_PERSON; import static org.sormas.e2etests.pages.application.persons.EditPersonPage.MEANS_OF_IMMUNIZATION_LABEL; import static org.sormas.e2etests.pages.application.persons.EditPersonPage.NAMES_OF_GUARDIANS_INPUT; +import static org.sormas.e2etests.pages.application.persons.EditPersonPage.NEW_CASE_BUTTON; import static org.sormas.e2etests.pages.application.persons.EditPersonPage.NO_TRAVEL_ENTRY_LABEL_DE; import static org.sormas.e2etests.pages.application.persons.EditPersonPage.PERSON_CONTACT_DETAILS_CONTACT_INFORMATION_INPUT; import static org.sormas.e2etests.pages.application.persons.EditPersonPage.PERSON_CONTACT_DETAILS_TYPE_OF_DETAILS_INPUT; @@ -85,6 +86,7 @@ import static org.sormas.e2etests.pages.application.persons.EditPersonPage.SEE_CONTACTS_FOR_PERSON_BUTTON; import static org.sormas.e2etests.pages.application.persons.EditPersonPage.SEE_CONTACTS_FOR_PERSON_BUTTON_DE; import static org.sormas.e2etests.pages.application.persons.EditPersonPage.SEE_EVENTS_FOR_PERSON; +import static org.sormas.e2etests.pages.application.persons.EditPersonPage.SEE_SAMPLES_FOR_PERSON_BUTTON; import static org.sormas.e2etests.pages.application.persons.EditPersonPage.SEX_INPUT; import static org.sormas.e2etests.pages.application.persons.EditPersonPage.STAFF_OF_ARMED_FORCES_COMBOBOX; import static org.sormas.e2etests.pages.application.persons.EditPersonPage.STREET_INPUT; @@ -272,6 +274,12 @@ public EditPersonSteps( webDriverHelpers.waitForPageLoadingSpinnerToDisappear(150); webDriverHelpers.clickOnWebElementBySelector(SEE_CASES_FOR_PERSON_BUTTON); }); + Then( + "I click on See Samples for this Person button from Edit Person page", + () -> { + webDriverHelpers.waitForPageLoadingSpinnerToDisappear(150); + webDriverHelpers.clickOnWebElementBySelector(SEE_SAMPLES_FOR_PERSON_BUTTON); + }); Then( "I check if data of created immunization is in Immunization tab on Edit Person Page", () -> { @@ -396,6 +404,13 @@ public EditPersonSteps( // webDriverHelpers.waitForPageLoadingSpinnerToDisappear(150); }); + Then( + "I click on NEW CASE button from Edit Person page", + () -> { + webDriverHelpers.waitUntilIdentifiedElementIsVisibleAndClickable(NEW_CASE_BUTTON); + webDriverHelpers.clickOnWebElementBySelector(NEW_CASE_BUTTON); + }); + Then( "I click on Edit Case button from Cases card on Edit Person page", () -> { diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/samples/CreateNewSampleSteps.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/samples/CreateNewSampleSteps.java index 22893d53a1b..c9590de6131 100644 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/samples/CreateNewSampleSteps.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/samples/CreateNewSampleSteps.java @@ -29,6 +29,7 @@ import static org.sormas.e2etests.pages.application.events.EventDirectoryPage.EVENT_ACTIONS_TABLE_ROW; import static org.sormas.e2etests.pages.application.samples.CreateNewSamplePage.ADD_PATHOGEN_TEST_BUTTON; import static org.sormas.e2etests.pages.application.samples.CreateNewSamplePage.ANTIGEN_DETECTION_TEST_OPTION_BUTTON; +import static org.sormas.e2etests.pages.application.samples.CreateNewSamplePage.CANCEL_ACTION; import static org.sormas.e2etests.pages.application.samples.CreateNewSamplePage.CELLS_IN_URINE_COMBOBOX; import static org.sormas.e2etests.pages.application.samples.CreateNewSamplePage.CELLS_IN_URINE_INPUT; import static org.sormas.e2etests.pages.application.samples.CreateNewSamplePage.COLLECTED_DATE_TIME_COMBOBOX; @@ -488,6 +489,13 @@ public CreateNewSampleSteps( webDriverHelpers.clickOnWebElementBySelector(SAVE_SAMPLE_WITH_PATHOGEN_TEST_BUTTON); }); + When( + "I reject the crete Case from event participant with positive test results popup", + () -> { + webDriverHelpers.waitUntilElementIsVisibleAndClickable(CANCEL_ACTION); + webDriverHelpers.clickOnWebElementBySelector(CANCEL_ACTION); + }); + When( "^I check the created Sample is correctly displayed on Edit Sample page", () -> { diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/samples/EditSampleSteps.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/samples/EditSampleSteps.java index e22c16e4399..ca4ea504969 100644 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/samples/EditSampleSteps.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/samples/EditSampleSteps.java @@ -116,10 +116,13 @@ public EditSampleSteps( () -> { webDriverHelpers.scrollToElement(DELETE_SAMPLE_BUTTON); webDriverHelpers.clickOnWebElementBySelector(DELETE_SAMPLE_BUTTON); + webDriverHelpers.waitUntilIdentifiedElementIsVisibleAndClickable( + DELETE_SAMPLE_REASON_POPUP); webDriverHelpers.selectFromCombobox( DELETE_SAMPLE_REASON_POPUP, "Entity created without legal reason"); webDriverHelpers.clickOnWebElementBySelector(SAMPLE_DELETION_POPUP_YES_BUTTON); - webDriverHelpers.waitUntilIdentifiedElementIsPresent(SAMPLE_SEARCH_INPUT); + if (webDriverHelpers.isElementPresent(SAMPLE_SEARCH_INPUT)) + webDriverHelpers.waitUntilIdentifiedElementIsPresent(SAMPLE_SEARCH_INPUT); }); When( diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/samples/SamplesDirectorySteps.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/samples/SamplesDirectorySteps.java index 94ae005610a..cea44894674 100644 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/samples/SamplesDirectorySteps.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/samples/SamplesDirectorySteps.java @@ -25,6 +25,9 @@ import static org.sormas.e2etests.pages.application.samples.SamplesDirectoryPage.EXPORT_SAMPLE_BUTTON; import static org.sormas.e2etests.pages.application.samples.SamplesDirectoryPage.FINAL_LABORATORY_RESULT; import static org.sormas.e2etests.pages.application.samples.SamplesDirectoryPage.LABORATORY_SEARCH_COMBOBOX; +import static org.sormas.e2etests.pages.application.samples.SamplesDirectoryPage.PENDING_TEST_TABLE_RESULTS; +import static org.sormas.e2etests.pages.application.samples.SamplesDirectoryPage.POSITIVE_TEST_TABLE_RESULTS; +import static org.sormas.e2etests.pages.application.samples.SamplesDirectoryPage.RELEVANCE_STATUS_FILTER_COMBOBOX; import static org.sormas.e2etests.pages.application.samples.SamplesDirectoryPage.RESET_FILTER_BUTTON; import static org.sormas.e2etests.pages.application.samples.SamplesDirectoryPage.SAMPLE_CLASIFICATION_SEARCH_COMBOBOX; import static org.sormas.e2etests.pages.application.samples.SamplesDirectoryPage.SAMPLE_DISEASE_SEARCH_COMBOBOX; @@ -39,7 +42,9 @@ import static org.sormas.e2etests.pages.application.samples.SamplesDirectoryPage.SEARCH_RESULT_SAMPLE; import static org.sormas.e2etests.pages.application.samples.SamplesDirectoryPage.SPECIMEN_CONDITION_SEARCH_COMBOBOX; import static org.sormas.e2etests.pages.application.samples.SamplesDirectoryPage.TEST_RESULTS_SEARCH_COMBOBOX; +import static org.sormas.e2etests.pages.application.samples.SamplesDirectoryPage.TOTAL_SAMPLE_COUNTER; import static org.sormas.e2etests.steps.BaseSteps.locale; +import static org.sormas.e2etests.steps.web.application.events.EditEventSteps.eventParticipantsUUIDList; import static org.sormas.e2etests.steps.web.application.events.EventDirectorySteps.userDirPath; import com.google.common.truth.Truth; @@ -171,6 +176,12 @@ public SamplesDirectorySteps( SPECIMEN_CONDITION_SEARCH_COMBOBOX, specimenCondition); }); + When( + "I select {string} Relevance Status option among the filter options", + (String relevanceStatus) -> { + webDriverHelpers.selectFromCombobox(RELEVANCE_STATUS_FILTER_COMBOBOX, relevanceStatus); + }); + When( "I select Case classification filter value with value for case classification of the last created via API Case in Sample Directory", () -> { @@ -305,6 +316,46 @@ public SamplesDirectorySteps( SEARCH_RESULT_SAMPLE, "title", CreateNewSampleSteps.sampleId); }); + When( + "I filter the Sample for {string} event participant by {string} Final laboratory result", + (String result, String testResult) -> { + webDriverHelpers.clickOnWebElementBySelector(RESET_FILTER_BUTTON); + TimeUnit.SECONDS.sleep(2); // wait for reaction + webDriverHelpers.selectFromCombobox(TEST_RESULTS_SEARCH_COMBOBOX, testResult); + switch (result) { + case "First": + webDriverHelpers.fillAndSubmitInWebElement( + SAMPLE_SEARCH_INPUT, eventParticipantsUUIDList.get(0)); + TimeUnit.SECONDS.sleep(2); // wait for reaction + webDriverHelpers.waitForPageLoadingSpinnerToDisappear(40); + break; + case "Second": + webDriverHelpers.fillAndSubmitInWebElement( + SAMPLE_SEARCH_INPUT, eventParticipantsUUIDList.get(1)); + TimeUnit.SECONDS.sleep(2); // wait for reaction + webDriverHelpers.waitForPageLoadingSpinnerToDisappear(40); + break; + } + }); + + When( + "I check that all Sample has {string} result in in Sample directory", + (String result) -> { + Integer totalSampleCounter = + Integer.valueOf(webDriverHelpers.getTextFromPresentWebElement(TOTAL_SAMPLE_COUNTER)); + Integer totalOccurrence = 0; + switch (result) { + case "Positive": + totalOccurrence = webDriverHelpers.getNumberOfElements(POSITIVE_TEST_TABLE_RESULTS); + break; + case "Pending": + totalOccurrence = webDriverHelpers.getNumberOfElements(PENDING_TEST_TABLE_RESULTS); + break; + } + softly.assertEquals(totalSampleCounter, totalOccurrence); + softly.assertAll(); + }); + When( "I am opening the last created via API Sample by url navigation", () -> { diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/shares/SharesDirectorySteps.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/shares/SharesDirectorySteps.java index 84b181377f2..810d602ecd0 100644 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/shares/SharesDirectorySteps.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/shares/SharesDirectorySteps.java @@ -145,7 +145,7 @@ public SharesDirectorySteps( When( "I click on the The Eye Icon located in the Shares Page", () -> { - TimeUnit.SECONDS.sleep(2); // wait for the page to load all records + TimeUnit.SECONDS.sleep(3); // wait for the page to load all records webDriverHelpers.waitUntilIdentifiedElementIsPresent(SHARE_FIRST_EYE_ICON); webDriverHelpers.clickOnWebElementBySelector(SHARE_FIRST_EYE_ICON); }); @@ -175,7 +175,7 @@ public SharesDirectorySteps( () -> { webDriverHelpers.waitUntilIdentifiedElementIsVisibleAndClickable(SHARE_UUID_CASE_TITLE); webDriverHelpers.clickOnWebElementBySelector(SHARE_UUID_CASE_TITLE); - webDriverHelpers.waitForPageLoadingSpinnerToDisappear(30); + webDriverHelpers.waitForPageLoadingSpinnerToDisappear(50); }); And( diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/tasks/CreateNewTaskSteps.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/tasks/CreateNewTaskSteps.java index a481b13aa60..153dcdcd14e 100644 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/tasks/CreateNewTaskSteps.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/tasks/CreateNewTaskSteps.java @@ -86,7 +86,6 @@ public CreateNewTaskSteps( When( "^I check the created task is correctly displayed on Edit task page", () -> { - TimeUnit.SECONDS.sleep(3); //waiting for page loaded final Task actualTask = collectTaskData(); ComparisonHelper.compareEqualEntities(task, actualTask); }); diff --git a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/tasks/TaskManagementSteps.java b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/tasks/TaskManagementSteps.java index 7df2452ec4f..07bbda16036 100644 --- a/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/tasks/TaskManagementSteps.java +++ b/sormas-e2e-tests/src/test/java/org/sormas/e2etests/steps/web/application/tasks/TaskManagementSteps.java @@ -116,9 +116,9 @@ public TaskManagementSteps( webDriverHelpers.clickOnWebElementBySelector(APPLY_FILTER); webDriverHelpers.waitForPageLoadingSpinnerToDisappear(200); webDriverHelpers.scrollToElement(CreateNewTaskSteps.task.getCommentsOnExecution()); - webDriverHelpers.clickOnWebElementBySelector( - getLastCreatedEditTaskButton(CreateNewTaskSteps.task.getCommentsOnExecution())); - webDriverHelpers.waitForPageLoadingSpinnerToDisappear(200); + webDriverHelpers.ClickAndWaitForNewFormLoaded( + getLastCreatedEditTaskButton(CreateNewTaskSteps.task.getCommentsOnExecution()), + EDIT_TASK_MODAL_FORM); }); When( "^I filter out last created task from Tasks Directory$", @@ -691,9 +691,9 @@ public TaskManagementSteps( webDriverHelpers.fillInWebElement(ASSIGNED_USER_FILTER_INPUT, assignedUser); webDriverHelpers.clickOnWebElementBySelector(APPLY_FILTER); webDriverHelpers.waitForPageLoadingSpinnerToDisappear(60); - webDriverHelpers.clickOnWebElementBySelector( - getLastCreatedEditTaskButton(CreateNewTaskSteps.task.getCommentsOnExecution())); - webDriverHelpers.waitForPageLoadingSpinnerToDisappear(60); + webDriverHelpers.ClickAndWaitForNewFormLoaded( + getLastCreatedEditTaskButton(CreateNewTaskSteps.task.getCommentsOnExecution()), + EDIT_TASK_MODAL_FORM); }); When( diff --git a/sormas-e2e-tests/src/test/resources/features/sanity/web/Event.feature b/sormas-e2e-tests/src/test/resources/features/sanity/web/Event.feature index cfb361d989b..a92fdd77fd4 100644 --- a/sormas-e2e-tests/src/test/resources/features/sanity/web/Event.feature +++ b/sormas-e2e-tests/src/test/resources/features/sanity/web/Event.feature @@ -736,7 +736,6 @@ Feature: Create events Then I check the end of processing date in the archive popup And I click on the Events button from navbar Then I set Relevance Status Filter to Archived events on Event Directory page - And I search for specific event by uuid in event directory And I click on the searched event Then I click on the Event participant tab And I choose Archived event participants from combobox in the Event participant tab diff --git a/sormas-e2e-tests/src/test/resources/features/sanity/web/EventFilters.feature b/sormas-e2e-tests/src/test/resources/features/sanity/web/EventFilters.feature index 83cbd363493..5a0276c3b59 100644 --- a/sormas-e2e-tests/src/test/resources/features/sanity/web/EventFilters.feature +++ b/sormas-e2e-tests/src/test/resources/features/sanity/web/EventFilters.feature @@ -4,7 +4,6 @@ Feature: Event Directory filters check @tmsLink=SORDEV-5915 @env_main Scenario: Check all filters are working properly in Event directory Given API: I create a new event - And API: I check that POST call status code is 200 When I log in as a National User And I click on the Events button from navbar @@ -46,7 +45,6 @@ Feature: Event Directory filters check @tmsLink=SORDEV-5917 @env_de Scenario: Check all filters are working properly in Event directory for DE version Given API: I create a new event - And API: I check that POST call status code is 200 When I log in as a National User And I click on the Events button from navbar @@ -85,10 +83,8 @@ Feature: Event Directory filters check @tmsLink=SORQA-77 @env_main Scenario: Filters for Region, District, Community, Reporting user and Event statuses on Event Directory Page Given API: I create a new person - And API: I check that POST call status code is 200 When API: I create a new event - And API: I check that POST call status code is 200 When I log in as a National User And I open the last created event via api @@ -135,7 +131,6 @@ Feature: Event Directory filters check @tmsLink=SORQA-77 @env_main Scenario: Date filters and aggregation buttons in Event Directory Given API: I create a new event - And API: I check that POST call status code is 200 When I log in as a National User And I click on the Events button from navbar @@ -194,4 +189,87 @@ Feature: Event Directory filters check | status | | Geimpft | | Ungeimpft | - | Unbekannt | \ No newline at end of file + | Unbekannt | + + @tmsLink=HSP-6550 @env_main + Scenario: [Event participants] Filtering event participants based on 'Final laboratory result' [1] + Given I log in as a Admin User + And I click on the Events button from navbar + And I click on the NEW EVENT button + And I create a new event with specific data + And I click on the Events button from navbar + And I search for specific event in event directory + And I click on the searched event + Then I navigate to EVENT PARTICIPANT from edit event page + And I click on Add Participant button + Then I add Participant to an Event with the new person data + And I save Add participant form + And I collect event participant uuid + And I click on New Sample + And I create a new Sample with alternate purpose + And I set Final Laboratory Result to "Positive" on Create new Sample page + And I save the created sample + And I click on New Sample + And I create a new Sample with alternate purpose + And I set Final Laboratory Result to "Pending" on Create new Sample page + And I save the created sample + Then I click on Event Participants tab + And I click on Add Participant button + And I add Participant to an Event with the new person data + And I save Add participant form + Then I collect event participant uuid + And I click on New Sample + And I create a new Sample with alternate purpose + And I set Final Laboratory Result to "Positive" on Create new Sample page + And I save the created sample + And I click on New Sample + And I create new sample with pathogen test with "COVID-19" as disease and "PCR / RT-PCR" as type of test + And I set Final Laboratory Result to "Positive" on Create new Sample page + And I save the created sample with pathogen test + And I reject the crete Case from event participant with positive test results popup + And I click on the Sample button from navbar + Then I filter the Sample for "First" event participant by "Positive" Final laboratory result + And I check that all Sample has "Positive" result in in Sample directory + Then I filter the Sample for "Second" event participant by "Positive" Final laboratory result + And I check that all Sample has "Positive" result in in Sample directory + + @tmsLink=HSP-6550 @env_main + Scenario: [Event participants] Filtering event participants based on 'Final laboratory result' [2] + Given I log in as a Admin User + And I click on the Events button from navbar + And I click on the NEW EVENT button + And I create a new event with specific data + And I click on the Events button from navbar + And I search for specific event in event directory + And I click on the searched event + Then I navigate to EVENT PARTICIPANT from edit event page + And I click on Add Participant button + Then I add Participant to an Event with the new person data + And I save Add participant form + And I collect event participant uuid + And I click on New Sample + And I create a new Sample with alternate purpose + And I set Final Laboratory Result to "Pending" on Create new Sample page + And I save the created sample + And I click on New Sample + And I create a new Sample with alternate purpose + And I set Final Laboratory Result to "Pending" on Create new Sample page + And I save the created sample + Then I click on Event Participants tab + And I click on Add Participant button + And I add Participant to an Event with the new person data + And I save Add participant form + Then I collect event participant uuid + And I click on New Sample + And I create a new Sample with alternate purpose + And I set Final Laboratory Result to "Pending" on Create new Sample page + And I save the created sample + And I click on New Sample + And I create a new Sample with alternate purpose + And I set Final Laboratory Result to "Positive" on Create new Sample page + And I save the created sample + And I click on the Sample button from navbar + Then I filter the Sample for "First" event participant by "Pending" Final laboratory result + And I check that all Sample has "Pending" result in in Sample directory + Then I filter the Sample for "Second" event participant by "Pending" Final laboratory result + And I check that all Sample has "Pending" result in in Sample directory \ No newline at end of file diff --git a/sormas-e2e-tests/src/test/resources/features/sanity/web/SampleFilters.feature b/sormas-e2e-tests/src/test/resources/features/sanity/web/SampleFilters.feature index 58529b6f44c..cc8681941ce 100644 --- a/sormas-e2e-tests/src/test/resources/features/sanity/web/SampleFilters.feature +++ b/sormas-e2e-tests/src/test/resources/features/sanity/web/SampleFilters.feature @@ -106,4 +106,41 @@ Feature: Sample filter functionality And I select "Versandt" filter from quick filter for DE version And I select "Erhalten" filter from quick filter for DE version And I select "An ein anderes Labor weitergeleitet" filter from quick filter for DE version - And I click on reset filters button from Sample Directory \ No newline at end of file + And I click on reset filters button from Sample Directory + + @tmsLink=HSP-6554 @env_main + Scenario: [Samples] Filter for 'Person samples' with 'All active and archived samples' and 'Deleted samples' filters + Given I log in as a Admin User + And I click on the Cases button from navbar + And I click on the NEW CASE button + When I create a new case with specific data + And I click on New Sample + And I create a new Sample with alternate purpose + And I save the created sample + And I click on New Sample + And I create a new Sample with alternate purpose + And I save the created sample + Then I click on the Archive case button and confirm popup + And I navigate to case person tab + Then I collect person UUID from Edit Case Person page + And I click on NEW CASE button from Edit Person page + When I create a new case for the same person + And I click on New Sample + And I create a new Sample with alternate purpose + And I save the created sample + And I click on New Sample + And I create a new Sample with alternate purpose + And I save the created sample + When I click on edit Sample + Then I delete the sample + When I click on the Persons button from navbar + And I open the last new created person by UI in person directory + Then I click on See Samples for this Person button from Edit Person page + And I select "Active samples" Relevance Status option among the filter options + And I check that number of displayed sample results is 1 + And I select "Archived samples" Relevance Status option among the filter options + And I check that number of displayed sample results is 2 + And I select "Deleted samples" Relevance Status option among the filter options + And I check that number of displayed sample results is 1 + And I select "All active and archived samples" Relevance Status option among the filter options + And I check that number of displayed sample results is 3 \ No newline at end of file diff --git a/sormas-e2e-tests/src/test/resources/features/sanity/web/TravelEntryFilters.feature b/sormas-e2e-tests/src/test/resources/features/sanity/web/TravelEntryFilters.feature index 942a437ddd3..60f68f94f4f 100644 --- a/sormas-e2e-tests/src/test/resources/features/sanity/web/TravelEntryFilters.feature +++ b/sormas-e2e-tests/src/test/resources/features/sanity/web/TravelEntryFilters.feature @@ -72,11 +72,11 @@ Scenario: Check Travel Entry filters And I click APPLY BUTTON in Travel Entry Directory Page And I check that number of displayed Travel Entry results is 0 And I apply "Nach Epi Woche" to data filter option combobox on Travel Entry directory page - And I apply the last epi week for week from combobox on Travel Entry directory page - And I apply the last epi week for week to combobox on Travel Entry directory page + And I set the last epi week date in week from combobox field on Travel Entry directory page + And I set the last epi week date in week to combobox field on Travel Entry directory page And I click APPLY BUTTON in Travel Entry Directory Page And I check that number of displayed Travel Entry results is 1 - Then I apply the week before the last epi week for week to combobox on Travel Entry directory page + Then I set the last epi week before date in week to combobox field on Travel Entry directory page And I click APPLY BUTTON in Travel Entry Directory Page And I check that number of displayed Travel Entry results is 0 diff --git a/sormas-e2e-tests/src/test/resources/features/sanity/web/UserRoles.feature b/sormas-e2e-tests/src/test/resources/features/sanity/web/UserRoles.feature index d89f8dbaaed..6d5c32a1a0a 100644 --- a/sormas-e2e-tests/src/test/resources/features/sanity/web/UserRoles.feature +++ b/sormas-e2e-tests/src/test/resources/features/sanity/web/UserRoles.feature @@ -158,7 +158,13 @@ Feature: User roles checks @tmsLink=HSP-6300 @env_main Scenario: Check Delete Case right working without Edit rights + When API: I create a new person + And API: I check that POST call status code is 200 + Then API: I create a new case + And API: I check that POST call status code is 200 Given I log in as a Admin User + And I open the last created Case via API + Then I get the case person UUID displayed on Edit case page And I click on the Users from navbar And I check if there is any user with the "NewTestUser" role and change his role And I click on User roles tab from Users Page @@ -184,8 +190,8 @@ Feature: User roles checks Then I click on logout button from navbar And I login with new created user with chosen new role And I click on the Cases button from navbar + Then I search for the last "created" case on Case directory page And I open the first Case result in Case Directory - Then I get the case person UUID displayed on Edit case page Then I click on Delete button from case And I click on Yes option in Confirm deletion popup When I set Reason for deletion as "Deletion request by affected person according to GDPR" @@ -193,7 +199,7 @@ Feature: User roles checks And I set the Relevance Status Filter to "Deleted cases" on Case Directory page And I search for the last "deleted" case on Case directory page Then I open the first Case result in Case Directory - And Total number of read only fields should be 14 + And Total number of read only fields should be 17 Then I check that "Discard" button is readonly on Edit case page And I check that "Save" button is readonly on Edit case page Then I click on Restore button from case diff --git a/sormas-ear/pom.xml b/sormas-ear/pom.xml index 40b2ca0e56a..6a68f017583 100644 --- a/sormas-ear/pom.xml +++ b/sormas-ear/pom.xml @@ -3,7 +3,7 @@ de.symeda.sormas sormas-base - 1.93.0 + 1.94.0 ../sormas-base diff --git a/sormas-keycloak-service-provider/pom.xml b/sormas-keycloak-service-provider/pom.xml index 98727f20545..49e86fd1c29 100644 --- a/sormas-keycloak-service-provider/pom.xml +++ b/sormas-keycloak-service-provider/pom.xml @@ -3,7 +3,7 @@ sormas-base de.symeda.sormas - 1.93.0 + 1.94.0 ../sormas-base 4.0.0 diff --git a/sormas-rest/pom.xml b/sormas-rest/pom.xml index 1dd9b635d2f..1c96991f84e 100644 --- a/sormas-rest/pom.xml +++ b/sormas-rest/pom.xml @@ -3,7 +3,7 @@ de.symeda.sormas sormas-base - 1.93.0 + 1.94.0 ../sormas-base diff --git a/sormas-rest/src/main/webapp/WEB-INF/glassfish-web.xml b/sormas-rest/src/main/webapp/WEB-INF/glassfish-web.xml index 42730bea6cd..652aeb16577 100644 --- a/sormas-rest/src/main/webapp/WEB-INF/glassfish-web.xml +++ b/sormas-rest/src/main/webapp/WEB-INF/glassfish-web.xml @@ -895,6 +895,21 @@ ENVIRONMENT_SAMPLE_EXPORT + + ENVIRONMENT_PATHOGEN_TEST_CREATE + ENVIRONMENT_PATHOGEN_TEST_CREATE + + + + ENVIRONMENT_PATHOGEN_TEST_EDIT + ENVIRONMENT_PATHOGEN_TEST_EDIT + + + + ENVIRONMENT_PATHOGEN_TEST_DELETE + ENVIRONMENT_PATHOGEN_TEST_DELETE + + DOCUMENT_VIEW DOCUMENT_VIEW diff --git a/sormas-rest/src/main/webapp/WEB-INF/web.xml b/sormas-rest/src/main/webapp/WEB-INF/web.xml index c10ef61cd07..73b8b4e6511 100644 --- a/sormas-rest/src/main/webapp/WEB-INF/web.xml +++ b/sormas-rest/src/main/webapp/WEB-INF/web.xml @@ -720,6 +720,18 @@ ENVIRONMENT_SAMPLE_EXPORT + + ENVIRONMENT_PATHOGEN_TEST_CREATE + + + + ENVIRONMENT_PATHOGEN_TEST_EDIT + + + + ENVIRONMENT_PATHOGEN_TEST_DELETE + + DOCUMENT_VIEW diff --git a/sormas-rest/swagger.json b/sormas-rest/swagger.json index 42df2abc89b..b0f7fd688b2 100644 --- a/sormas-rest/swagger.json +++ b/sormas-rest/swagger.json @@ -7,7 +7,7 @@ "url" : "https://www.gnu.org/licenses/gpl-3.0.html" }, "title" : "SORMAS REST API", - "version" : "1.93.0-SNAPSHOT" + "version" : "1.94.0-SNAPSHOT" }, "servers" : [ { "url" : "/sormas-rest" @@ -9889,7 +9889,7 @@ "type" : "array", "items" : { "type" : "string", - "enum" : [ "CASE_VIEW", "CASE_CREATE", "CASE_EDIT", "CASE_ARCHIVE", "CASE_DELETE", "CASE_IMPORT", "CASE_EXPORT", "CASE_INVESTIGATE", "CASE_CLASSIFY", "CASE_CHANGE_DISEASE", "CASE_CHANGE_EPID_NUMBER", "CASE_TRANSFER", "CASE_REFER_FROM_POE", "CASE_MERGE", "CASE_SHARE", "CASE_RESPONSIBLE", "IMMUNIZATION_VIEW", "IMMUNIZATION_CREATE", "IMMUNIZATION_EDIT", "IMMUNIZATION_ARCHIVE", "IMMUNIZATION_DELETE", "PERSON_VIEW", "PERSON_EDIT", "PERSON_DELETE", "PERSON_EXPORT", "PERSON_CONTACT_DETAILS_DELETE", "PERSON_MERGE", "SAMPLE_VIEW", "SAMPLE_CREATE", "SAMPLE_EDIT", "SAMPLE_DELETE", "SAMPLE_EXPORT", "SAMPLE_TRANSFER", "SAMPLE_EDIT_NOT_OWNED", "PERFORM_BULK_OPERATIONS_CASE_SAMPLES", "PATHOGEN_TEST_CREATE", "PATHOGEN_TEST_EDIT", "PATHOGEN_TEST_DELETE", "ADDITIONAL_TEST_VIEW", "ADDITIONAL_TEST_CREATE", "ADDITIONAL_TEST_EDIT", "ADDITIONAL_TEST_DELETE", "CONTACT_VIEW", "CONTACT_CREATE", "CONTACT_EDIT", "CONTACT_ARCHIVE", "CONTACT_DELETE", "CONTACT_IMPORT", "CONTACT_EXPORT", "CONTACT_CONVERT", "CONTACT_REASSIGN_CASE", "CONTACT_MERGE", "CONTACT_RESPONSIBLE", "VISIT_CREATE", "VISIT_EDIT", "VISIT_DELETE", "VISIT_EXPORT", "TASK_VIEW", "TASK_CREATE", "TASK_EDIT", "TASK_DELETE", "TASK_EXPORT", "TASK_ASSIGN", "TASK_ARCHIVE", "ACTION_CREATE", "ACTION_DELETE", "ACTION_EDIT", "EVENT_VIEW", "EVENT_CREATE", "EVENT_EDIT", "EVENT_ARCHIVE", "EVENT_DELETE", "EVENT_IMPORT", "EVENT_EXPORT", "PERFORM_BULK_OPERATIONS_EVENT", "EVENT_RESPONSIBLE", "EVENTPARTICIPANT_VIEW", "EVENTPARTICIPANT_CREATE", "EVENTPARTICIPANT_EDIT", "EVENTPARTICIPANT_ARCHIVE", "EVENTPARTICIPANT_DELETE", "EVENTPARTICIPANT_IMPORT", "PERFORM_BULK_OPERATIONS_EVENTPARTICIPANT", "EVENTGROUP_CREATE", "EVENTGROUP_EDIT", "EVENTGROUP_ARCHIVE", "EVENTGROUP_DELETE", "EVENTGROUP_LINK", "USER_VIEW", "USER_CREATE", "USER_EDIT", "USER_ROLE_VIEW", "USER_ROLE_EDIT", "USER_ROLE_DELETE", "STATISTICS_ACCESS", "STATISTICS_EXPORT", "INFRASTRUCTURE_VIEW", "INFRASTRUCTURE_CREATE", "INFRASTRUCTURE_EDIT", "INFRASTRUCTURE_ARCHIVE", "INFRASTRUCTURE_IMPORT", "INFRASTRUCTURE_EXPORT", "POPULATION_MANAGE", "DASHBOARD_SURVEILLANCE_VIEW", "DASHBOARD_CONTACT_VIEW", "DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS", "DASHBOARD_CAMPAIGNS_VIEW", "DASHBOARD_SAMPLES_VIEW", "CASE_CLINICIAN_VIEW", "THERAPY_VIEW", "PRESCRIPTION_CREATE", "PRESCRIPTION_EDIT", "PRESCRIPTION_DELETE", "TREATMENT_CREATE", "TREATMENT_EDIT", "TREATMENT_DELETE", "CLINICAL_COURSE_VIEW", "CLINICAL_COURSE_EDIT", "CLINICAL_VISIT_CREATE", "CLINICAL_VISIT_EDIT", "CLINICAL_VISIT_DELETE", "PORT_HEALTH_INFO_VIEW", "PORT_HEALTH_INFO_EDIT", "WEEKLYREPORT_VIEW", "WEEKLYREPORT_CREATE", "AGGREGATE_REPORT_VIEW", "AGGREGATE_REPORT_EDIT", "AGGREGATE_REPORT_EXPORT", "SEE_PERSONAL_DATA_IN_JURISDICTION", "SEE_PERSONAL_DATA_OUTSIDE_JURISDICTION", "SEE_SENSITIVE_DATA_IN_JURISDICTION", "SEE_SENSITIVE_DATA_OUTSIDE_JURISDICTION", "CAMPAIGN_VIEW", "CAMPAIGN_EDIT", "CAMPAIGN_ARCHIVE", "CAMPAIGN_DELETE", "CAMPAIGN_FORM_DATA_VIEW", "CAMPAIGN_FORM_DATA_EDIT", "CAMPAIGN_FORM_DATA_ARCHIVE", "CAMPAIGN_FORM_DATA_DELETE", "CAMPAIGN_FORM_DATA_EXPORT", "TRAVEL_ENTRY_MANAGEMENT_ACCESS", "TRAVEL_ENTRY_VIEW", "TRAVEL_ENTRY_CREATE", "TRAVEL_ENTRY_EDIT", "TRAVEL_ENTRY_ARCHIVE", "TRAVEL_ENTRY_DELETE", "ENVIRONMENT_VIEW", "ENVIRONMENT_CREATE", "ENVIRONMENT_EDIT", "ENVIRONMENT_ARCHIVE", "ENVIRONMENT_DELETE", "ENVIRONMENT_IMPORT", "ENVIRONMENT_EXPORT", "ENVIRONMENT_SAMPLE_VIEW", "ENVIRONMENT_SAMPLE_CREATE", "ENVIRONMENT_SAMPLE_EDIT", "ENVIRONMENT_SAMPLE_EDIT_DISPATCH", "ENVIRONMENT_SAMPLE_EDIT_RECEIVAL", "ENVIRONMENT_SAMPLE_DELETE", "ENVIRONMENT_SAMPLE_IMPORT", "ENVIRONMENT_SAMPLE_EXPORT", "DOCUMENT_VIEW", "DOCUMENT_UPLOAD", "DOCUMENT_DELETE", "PERFORM_BULK_OPERATIONS", "PERFORM_BULK_OPERATIONS_PSEUDONYM", "QUARANTINE_ORDER_CREATE", "SORMAS_REST", "SORMAS_UI", "DATABASE_EXPORT_ACCESS", "EXPORT_DATA_PROTECTION_DATA", "BAG_EXPORT", "SEND_MANUAL_EXTERNAL_MESSAGES", "MANAGE_EXTERNAL_SYMPTOM_JOURNAL", "EXTERNAL_VISITS", "SORMAS_TO_SORMAS_CLIENT", "SORMAS_TO_SORMAS_SHARE", "SORMAS_TO_SORMAS_PROCESS", "EXTERNAL_SURVEILLANCE_SHARE", "EXTERNAL_SURVEILLANCE_DELETE", "EXTERNAL_MESSAGE_VIEW", "EXTERNAL_MESSAGE_PROCESS", "EXTERNAL_MESSAGE_PUSH", "EXTERNAL_MESSAGE_DELETE", "PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES", "OUTBREAK_VIEW", "OUTBREAK_EDIT", "MANAGE_PUBLIC_EXPORT_CONFIGURATION", "DOCUMENT_TEMPLATE_MANAGEMENT", "LINE_LISTING_CONFIGURE", "DEV_MODE", "EMAIL_TEMPLATE_MANAGEMENT", "EXTERNAL_EMAIL_SEND", "EXTERNAL_EMAIL_ATTACH_DOCUMENTS", "CUSTOMIZABLE_ENUM_MANAGEMENT" ] + "enum" : [ "CASE_VIEW", "CASE_CREATE", "CASE_EDIT", "CASE_ARCHIVE", "CASE_DELETE", "CASE_IMPORT", "CASE_EXPORT", "CASE_INVESTIGATE", "CASE_CLASSIFY", "CASE_CHANGE_DISEASE", "CASE_CHANGE_EPID_NUMBER", "CASE_TRANSFER", "CASE_REFER_FROM_POE", "CASE_MERGE", "CASE_SHARE", "CASE_RESPONSIBLE", "IMMUNIZATION_VIEW", "IMMUNIZATION_CREATE", "IMMUNIZATION_EDIT", "IMMUNIZATION_ARCHIVE", "IMMUNIZATION_DELETE", "PERSON_VIEW", "PERSON_EDIT", "PERSON_DELETE", "PERSON_EXPORT", "PERSON_CONTACT_DETAILS_DELETE", "PERSON_MERGE", "SAMPLE_VIEW", "SAMPLE_CREATE", "SAMPLE_EDIT", "SAMPLE_DELETE", "SAMPLE_EXPORT", "SAMPLE_TRANSFER", "SAMPLE_EDIT_NOT_OWNED", "PERFORM_BULK_OPERATIONS_CASE_SAMPLES", "PATHOGEN_TEST_CREATE", "PATHOGEN_TEST_EDIT", "PATHOGEN_TEST_DELETE", "ADDITIONAL_TEST_VIEW", "ADDITIONAL_TEST_CREATE", "ADDITIONAL_TEST_EDIT", "ADDITIONAL_TEST_DELETE", "CONTACT_VIEW", "CONTACT_CREATE", "CONTACT_EDIT", "CONTACT_ARCHIVE", "CONTACT_DELETE", "CONTACT_IMPORT", "CONTACT_EXPORT", "CONTACT_CONVERT", "CONTACT_REASSIGN_CASE", "CONTACT_MERGE", "CONTACT_RESPONSIBLE", "VISIT_CREATE", "VISIT_EDIT", "VISIT_DELETE", "VISIT_EXPORT", "TASK_VIEW", "TASK_CREATE", "TASK_EDIT", "TASK_DELETE", "TASK_EXPORT", "TASK_ASSIGN", "TASK_ARCHIVE", "ACTION_CREATE", "ACTION_DELETE", "ACTION_EDIT", "EVENT_VIEW", "EVENT_CREATE", "EVENT_EDIT", "EVENT_ARCHIVE", "EVENT_DELETE", "EVENT_IMPORT", "EVENT_EXPORT", "PERFORM_BULK_OPERATIONS_EVENT", "EVENT_RESPONSIBLE", "EVENTPARTICIPANT_VIEW", "EVENTPARTICIPANT_CREATE", "EVENTPARTICIPANT_EDIT", "EVENTPARTICIPANT_ARCHIVE", "EVENTPARTICIPANT_DELETE", "EVENTPARTICIPANT_IMPORT", "PERFORM_BULK_OPERATIONS_EVENTPARTICIPANT", "EVENTGROUP_CREATE", "EVENTGROUP_EDIT", "EVENTGROUP_ARCHIVE", "EVENTGROUP_DELETE", "EVENTGROUP_LINK", "USER_VIEW", "USER_CREATE", "USER_EDIT", "USER_ROLE_VIEW", "USER_ROLE_EDIT", "USER_ROLE_DELETE", "STATISTICS_ACCESS", "STATISTICS_EXPORT", "INFRASTRUCTURE_VIEW", "INFRASTRUCTURE_CREATE", "INFRASTRUCTURE_EDIT", "INFRASTRUCTURE_ARCHIVE", "INFRASTRUCTURE_IMPORT", "INFRASTRUCTURE_EXPORT", "POPULATION_MANAGE", "DASHBOARD_SURVEILLANCE_VIEW", "DASHBOARD_CONTACT_VIEW", "DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS", "DASHBOARD_CAMPAIGNS_VIEW", "DASHBOARD_SAMPLES_VIEW", "CASE_CLINICIAN_VIEW", "THERAPY_VIEW", "PRESCRIPTION_CREATE", "PRESCRIPTION_EDIT", "PRESCRIPTION_DELETE", "TREATMENT_CREATE", "TREATMENT_EDIT", "TREATMENT_DELETE", "CLINICAL_COURSE_VIEW", "CLINICAL_COURSE_EDIT", "CLINICAL_VISIT_CREATE", "CLINICAL_VISIT_EDIT", "CLINICAL_VISIT_DELETE", "PORT_HEALTH_INFO_VIEW", "PORT_HEALTH_INFO_EDIT", "WEEKLYREPORT_VIEW", "WEEKLYREPORT_CREATE", "AGGREGATE_REPORT_VIEW", "AGGREGATE_REPORT_EDIT", "AGGREGATE_REPORT_EXPORT", "SEE_PERSONAL_DATA_IN_JURISDICTION", "SEE_PERSONAL_DATA_OUTSIDE_JURISDICTION", "SEE_SENSITIVE_DATA_IN_JURISDICTION", "SEE_SENSITIVE_DATA_OUTSIDE_JURISDICTION", "CAMPAIGN_VIEW", "CAMPAIGN_EDIT", "CAMPAIGN_ARCHIVE", "CAMPAIGN_DELETE", "CAMPAIGN_FORM_DATA_VIEW", "CAMPAIGN_FORM_DATA_EDIT", "CAMPAIGN_FORM_DATA_ARCHIVE", "CAMPAIGN_FORM_DATA_DELETE", "CAMPAIGN_FORM_DATA_EXPORT", "TRAVEL_ENTRY_MANAGEMENT_ACCESS", "TRAVEL_ENTRY_VIEW", "TRAVEL_ENTRY_CREATE", "TRAVEL_ENTRY_EDIT", "TRAVEL_ENTRY_ARCHIVE", "TRAVEL_ENTRY_DELETE", "ENVIRONMENT_VIEW", "ENVIRONMENT_CREATE", "ENVIRONMENT_EDIT", "ENVIRONMENT_ARCHIVE", "ENVIRONMENT_DELETE", "ENVIRONMENT_IMPORT", "ENVIRONMENT_EXPORT", "ENVIRONMENT_SAMPLE_VIEW", "ENVIRONMENT_SAMPLE_CREATE", "ENVIRONMENT_SAMPLE_EDIT", "ENVIRONMENT_SAMPLE_EDIT_DISPATCH", "ENVIRONMENT_SAMPLE_EDIT_RECEIVAL", "ENVIRONMENT_SAMPLE_DELETE", "ENVIRONMENT_SAMPLE_IMPORT", "ENVIRONMENT_SAMPLE_EXPORT", "ENVIRONMENT_PATHOGEN_TEST_CREATE", "ENVIRONMENT_PATHOGEN_TEST_EDIT", "ENVIRONMENT_PATHOGEN_TEST_DELETE", "DOCUMENT_VIEW", "DOCUMENT_UPLOAD", "DOCUMENT_DELETE", "PERFORM_BULK_OPERATIONS", "PERFORM_BULK_OPERATIONS_PSEUDONYM", "QUARANTINE_ORDER_CREATE", "SORMAS_REST", "SORMAS_UI", "DATABASE_EXPORT_ACCESS", "EXPORT_DATA_PROTECTION_DATA", "BAG_EXPORT", "SEND_MANUAL_EXTERNAL_MESSAGES", "MANAGE_EXTERNAL_SYMPTOM_JOURNAL", "EXTERNAL_VISITS", "SORMAS_TO_SORMAS_CLIENT", "SORMAS_TO_SORMAS_SHARE", "SORMAS_TO_SORMAS_PROCESS", "EXTERNAL_SURVEILLANCE_SHARE", "EXTERNAL_SURVEILLANCE_DELETE", "EXTERNAL_MESSAGE_VIEW", "EXTERNAL_MESSAGE_PROCESS", "EXTERNAL_MESSAGE_PUSH", "EXTERNAL_MESSAGE_DELETE", "PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES", "OUTBREAK_VIEW", "OUTBREAK_EDIT", "MANAGE_PUBLIC_EXPORT_CONFIGURATION", "DOCUMENT_TEMPLATE_MANAGEMENT", "LINE_LISTING_CONFIGURE", "DEV_MODE", "EMAIL_TEMPLATE_MANAGEMENT", "EXTERNAL_EMAIL_SEND", "EXTERNAL_EMAIL_ATTACH_DOCUMENTS", "CUSTOMIZABLE_ENUM_MANAGEMENT" ] } } } @@ -9919,7 +9919,7 @@ "type" : "array", "items" : { "type" : "string", - "enum" : [ "CASE_VIEW", "CASE_CREATE", "CASE_EDIT", "CASE_ARCHIVE", "CASE_DELETE", "CASE_IMPORT", "CASE_EXPORT", "CASE_INVESTIGATE", "CASE_CLASSIFY", "CASE_CHANGE_DISEASE", "CASE_CHANGE_EPID_NUMBER", "CASE_TRANSFER", "CASE_REFER_FROM_POE", "CASE_MERGE", "CASE_SHARE", "CASE_RESPONSIBLE", "IMMUNIZATION_VIEW", "IMMUNIZATION_CREATE", "IMMUNIZATION_EDIT", "IMMUNIZATION_ARCHIVE", "IMMUNIZATION_DELETE", "PERSON_VIEW", "PERSON_EDIT", "PERSON_DELETE", "PERSON_EXPORT", "PERSON_CONTACT_DETAILS_DELETE", "PERSON_MERGE", "SAMPLE_VIEW", "SAMPLE_CREATE", "SAMPLE_EDIT", "SAMPLE_DELETE", "SAMPLE_EXPORT", "SAMPLE_TRANSFER", "SAMPLE_EDIT_NOT_OWNED", "PERFORM_BULK_OPERATIONS_CASE_SAMPLES", "PATHOGEN_TEST_CREATE", "PATHOGEN_TEST_EDIT", "PATHOGEN_TEST_DELETE", "ADDITIONAL_TEST_VIEW", "ADDITIONAL_TEST_CREATE", "ADDITIONAL_TEST_EDIT", "ADDITIONAL_TEST_DELETE", "CONTACT_VIEW", "CONTACT_CREATE", "CONTACT_EDIT", "CONTACT_ARCHIVE", "CONTACT_DELETE", "CONTACT_IMPORT", "CONTACT_EXPORT", "CONTACT_CONVERT", "CONTACT_REASSIGN_CASE", "CONTACT_MERGE", "CONTACT_RESPONSIBLE", "VISIT_CREATE", "VISIT_EDIT", "VISIT_DELETE", "VISIT_EXPORT", "TASK_VIEW", "TASK_CREATE", "TASK_EDIT", "TASK_DELETE", "TASK_EXPORT", "TASK_ASSIGN", "TASK_ARCHIVE", "ACTION_CREATE", "ACTION_DELETE", "ACTION_EDIT", "EVENT_VIEW", "EVENT_CREATE", "EVENT_EDIT", "EVENT_ARCHIVE", "EVENT_DELETE", "EVENT_IMPORT", "EVENT_EXPORT", "PERFORM_BULK_OPERATIONS_EVENT", "EVENT_RESPONSIBLE", "EVENTPARTICIPANT_VIEW", "EVENTPARTICIPANT_CREATE", "EVENTPARTICIPANT_EDIT", "EVENTPARTICIPANT_ARCHIVE", "EVENTPARTICIPANT_DELETE", "EVENTPARTICIPANT_IMPORT", "PERFORM_BULK_OPERATIONS_EVENTPARTICIPANT", "EVENTGROUP_CREATE", "EVENTGROUP_EDIT", "EVENTGROUP_ARCHIVE", "EVENTGROUP_DELETE", "EVENTGROUP_LINK", "USER_VIEW", "USER_CREATE", "USER_EDIT", "USER_ROLE_VIEW", "USER_ROLE_EDIT", "USER_ROLE_DELETE", "STATISTICS_ACCESS", "STATISTICS_EXPORT", "INFRASTRUCTURE_VIEW", "INFRASTRUCTURE_CREATE", "INFRASTRUCTURE_EDIT", "INFRASTRUCTURE_ARCHIVE", "INFRASTRUCTURE_IMPORT", "INFRASTRUCTURE_EXPORT", "POPULATION_MANAGE", "DASHBOARD_SURVEILLANCE_VIEW", "DASHBOARD_CONTACT_VIEW", "DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS", "DASHBOARD_CAMPAIGNS_VIEW", "DASHBOARD_SAMPLES_VIEW", "CASE_CLINICIAN_VIEW", "THERAPY_VIEW", "PRESCRIPTION_CREATE", "PRESCRIPTION_EDIT", "PRESCRIPTION_DELETE", "TREATMENT_CREATE", "TREATMENT_EDIT", "TREATMENT_DELETE", "CLINICAL_COURSE_VIEW", "CLINICAL_COURSE_EDIT", "CLINICAL_VISIT_CREATE", "CLINICAL_VISIT_EDIT", "CLINICAL_VISIT_DELETE", "PORT_HEALTH_INFO_VIEW", "PORT_HEALTH_INFO_EDIT", "WEEKLYREPORT_VIEW", "WEEKLYREPORT_CREATE", "AGGREGATE_REPORT_VIEW", "AGGREGATE_REPORT_EDIT", "AGGREGATE_REPORT_EXPORT", "SEE_PERSONAL_DATA_IN_JURISDICTION", "SEE_PERSONAL_DATA_OUTSIDE_JURISDICTION", "SEE_SENSITIVE_DATA_IN_JURISDICTION", "SEE_SENSITIVE_DATA_OUTSIDE_JURISDICTION", "CAMPAIGN_VIEW", "CAMPAIGN_EDIT", "CAMPAIGN_ARCHIVE", "CAMPAIGN_DELETE", "CAMPAIGN_FORM_DATA_VIEW", "CAMPAIGN_FORM_DATA_EDIT", "CAMPAIGN_FORM_DATA_ARCHIVE", "CAMPAIGN_FORM_DATA_DELETE", "CAMPAIGN_FORM_DATA_EXPORT", "TRAVEL_ENTRY_MANAGEMENT_ACCESS", "TRAVEL_ENTRY_VIEW", "TRAVEL_ENTRY_CREATE", "TRAVEL_ENTRY_EDIT", "TRAVEL_ENTRY_ARCHIVE", "TRAVEL_ENTRY_DELETE", "ENVIRONMENT_VIEW", "ENVIRONMENT_CREATE", "ENVIRONMENT_EDIT", "ENVIRONMENT_ARCHIVE", "ENVIRONMENT_DELETE", "ENVIRONMENT_IMPORT", "ENVIRONMENT_EXPORT", "ENVIRONMENT_SAMPLE_VIEW", "ENVIRONMENT_SAMPLE_CREATE", "ENVIRONMENT_SAMPLE_EDIT", "ENVIRONMENT_SAMPLE_EDIT_DISPATCH", "ENVIRONMENT_SAMPLE_EDIT_RECEIVAL", "ENVIRONMENT_SAMPLE_DELETE", "ENVIRONMENT_SAMPLE_IMPORT", "ENVIRONMENT_SAMPLE_EXPORT", "DOCUMENT_VIEW", "DOCUMENT_UPLOAD", "DOCUMENT_DELETE", "PERFORM_BULK_OPERATIONS", "PERFORM_BULK_OPERATIONS_PSEUDONYM", "QUARANTINE_ORDER_CREATE", "SORMAS_REST", "SORMAS_UI", "DATABASE_EXPORT_ACCESS", "EXPORT_DATA_PROTECTION_DATA", "BAG_EXPORT", "SEND_MANUAL_EXTERNAL_MESSAGES", "MANAGE_EXTERNAL_SYMPTOM_JOURNAL", "EXTERNAL_VISITS", "SORMAS_TO_SORMAS_CLIENT", "SORMAS_TO_SORMAS_SHARE", "SORMAS_TO_SORMAS_PROCESS", "EXTERNAL_SURVEILLANCE_SHARE", "EXTERNAL_SURVEILLANCE_DELETE", "EXTERNAL_MESSAGE_VIEW", "EXTERNAL_MESSAGE_PROCESS", "EXTERNAL_MESSAGE_PUSH", "EXTERNAL_MESSAGE_DELETE", "PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES", "OUTBREAK_VIEW", "OUTBREAK_EDIT", "MANAGE_PUBLIC_EXPORT_CONFIGURATION", "DOCUMENT_TEMPLATE_MANAGEMENT", "LINE_LISTING_CONFIGURE", "DEV_MODE", "EMAIL_TEMPLATE_MANAGEMENT", "EXTERNAL_EMAIL_SEND", "EXTERNAL_EMAIL_ATTACH_DOCUMENTS", "CUSTOMIZABLE_ENUM_MANAGEMENT" ] + "enum" : [ "CASE_VIEW", "CASE_CREATE", "CASE_EDIT", "CASE_ARCHIVE", "CASE_DELETE", "CASE_IMPORT", "CASE_EXPORT", "CASE_INVESTIGATE", "CASE_CLASSIFY", "CASE_CHANGE_DISEASE", "CASE_CHANGE_EPID_NUMBER", "CASE_TRANSFER", "CASE_REFER_FROM_POE", "CASE_MERGE", "CASE_SHARE", "CASE_RESPONSIBLE", "IMMUNIZATION_VIEW", "IMMUNIZATION_CREATE", "IMMUNIZATION_EDIT", "IMMUNIZATION_ARCHIVE", "IMMUNIZATION_DELETE", "PERSON_VIEW", "PERSON_EDIT", "PERSON_DELETE", "PERSON_EXPORT", "PERSON_CONTACT_DETAILS_DELETE", "PERSON_MERGE", "SAMPLE_VIEW", "SAMPLE_CREATE", "SAMPLE_EDIT", "SAMPLE_DELETE", "SAMPLE_EXPORT", "SAMPLE_TRANSFER", "SAMPLE_EDIT_NOT_OWNED", "PERFORM_BULK_OPERATIONS_CASE_SAMPLES", "PATHOGEN_TEST_CREATE", "PATHOGEN_TEST_EDIT", "PATHOGEN_TEST_DELETE", "ADDITIONAL_TEST_VIEW", "ADDITIONAL_TEST_CREATE", "ADDITIONAL_TEST_EDIT", "ADDITIONAL_TEST_DELETE", "CONTACT_VIEW", "CONTACT_CREATE", "CONTACT_EDIT", "CONTACT_ARCHIVE", "CONTACT_DELETE", "CONTACT_IMPORT", "CONTACT_EXPORT", "CONTACT_CONVERT", "CONTACT_REASSIGN_CASE", "CONTACT_MERGE", "CONTACT_RESPONSIBLE", "VISIT_CREATE", "VISIT_EDIT", "VISIT_DELETE", "VISIT_EXPORT", "TASK_VIEW", "TASK_CREATE", "TASK_EDIT", "TASK_DELETE", "TASK_EXPORT", "TASK_ASSIGN", "TASK_ARCHIVE", "ACTION_CREATE", "ACTION_DELETE", "ACTION_EDIT", "EVENT_VIEW", "EVENT_CREATE", "EVENT_EDIT", "EVENT_ARCHIVE", "EVENT_DELETE", "EVENT_IMPORT", "EVENT_EXPORT", "PERFORM_BULK_OPERATIONS_EVENT", "EVENT_RESPONSIBLE", "EVENTPARTICIPANT_VIEW", "EVENTPARTICIPANT_CREATE", "EVENTPARTICIPANT_EDIT", "EVENTPARTICIPANT_ARCHIVE", "EVENTPARTICIPANT_DELETE", "EVENTPARTICIPANT_IMPORT", "PERFORM_BULK_OPERATIONS_EVENTPARTICIPANT", "EVENTGROUP_CREATE", "EVENTGROUP_EDIT", "EVENTGROUP_ARCHIVE", "EVENTGROUP_DELETE", "EVENTGROUP_LINK", "USER_VIEW", "USER_CREATE", "USER_EDIT", "USER_ROLE_VIEW", "USER_ROLE_EDIT", "USER_ROLE_DELETE", "STATISTICS_ACCESS", "STATISTICS_EXPORT", "INFRASTRUCTURE_VIEW", "INFRASTRUCTURE_CREATE", "INFRASTRUCTURE_EDIT", "INFRASTRUCTURE_ARCHIVE", "INFRASTRUCTURE_IMPORT", "INFRASTRUCTURE_EXPORT", "POPULATION_MANAGE", "DASHBOARD_SURVEILLANCE_VIEW", "DASHBOARD_CONTACT_VIEW", "DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS", "DASHBOARD_CAMPAIGNS_VIEW", "DASHBOARD_SAMPLES_VIEW", "CASE_CLINICIAN_VIEW", "THERAPY_VIEW", "PRESCRIPTION_CREATE", "PRESCRIPTION_EDIT", "PRESCRIPTION_DELETE", "TREATMENT_CREATE", "TREATMENT_EDIT", "TREATMENT_DELETE", "CLINICAL_COURSE_VIEW", "CLINICAL_COURSE_EDIT", "CLINICAL_VISIT_CREATE", "CLINICAL_VISIT_EDIT", "CLINICAL_VISIT_DELETE", "PORT_HEALTH_INFO_VIEW", "PORT_HEALTH_INFO_EDIT", "WEEKLYREPORT_VIEW", "WEEKLYREPORT_CREATE", "AGGREGATE_REPORT_VIEW", "AGGREGATE_REPORT_EDIT", "AGGREGATE_REPORT_EXPORT", "SEE_PERSONAL_DATA_IN_JURISDICTION", "SEE_PERSONAL_DATA_OUTSIDE_JURISDICTION", "SEE_SENSITIVE_DATA_IN_JURISDICTION", "SEE_SENSITIVE_DATA_OUTSIDE_JURISDICTION", "CAMPAIGN_VIEW", "CAMPAIGN_EDIT", "CAMPAIGN_ARCHIVE", "CAMPAIGN_DELETE", "CAMPAIGN_FORM_DATA_VIEW", "CAMPAIGN_FORM_DATA_EDIT", "CAMPAIGN_FORM_DATA_ARCHIVE", "CAMPAIGN_FORM_DATA_DELETE", "CAMPAIGN_FORM_DATA_EXPORT", "TRAVEL_ENTRY_MANAGEMENT_ACCESS", "TRAVEL_ENTRY_VIEW", "TRAVEL_ENTRY_CREATE", "TRAVEL_ENTRY_EDIT", "TRAVEL_ENTRY_ARCHIVE", "TRAVEL_ENTRY_DELETE", "ENVIRONMENT_VIEW", "ENVIRONMENT_CREATE", "ENVIRONMENT_EDIT", "ENVIRONMENT_ARCHIVE", "ENVIRONMENT_DELETE", "ENVIRONMENT_IMPORT", "ENVIRONMENT_EXPORT", "ENVIRONMENT_SAMPLE_VIEW", "ENVIRONMENT_SAMPLE_CREATE", "ENVIRONMENT_SAMPLE_EDIT", "ENVIRONMENT_SAMPLE_EDIT_DISPATCH", "ENVIRONMENT_SAMPLE_EDIT_RECEIVAL", "ENVIRONMENT_SAMPLE_DELETE", "ENVIRONMENT_SAMPLE_IMPORT", "ENVIRONMENT_SAMPLE_EXPORT", "ENVIRONMENT_PATHOGEN_TEST_CREATE", "ENVIRONMENT_PATHOGEN_TEST_EDIT", "ENVIRONMENT_PATHOGEN_TEST_DELETE", "DOCUMENT_VIEW", "DOCUMENT_UPLOAD", "DOCUMENT_DELETE", "PERFORM_BULK_OPERATIONS", "PERFORM_BULK_OPERATIONS_PSEUDONYM", "QUARANTINE_ORDER_CREATE", "SORMAS_REST", "SORMAS_UI", "DATABASE_EXPORT_ACCESS", "EXPORT_DATA_PROTECTION_DATA", "BAG_EXPORT", "SEND_MANUAL_EXTERNAL_MESSAGES", "MANAGE_EXTERNAL_SYMPTOM_JOURNAL", "EXTERNAL_VISITS", "SORMAS_TO_SORMAS_CLIENT", "SORMAS_TO_SORMAS_SHARE", "SORMAS_TO_SORMAS_PROCESS", "EXTERNAL_SURVEILLANCE_SHARE", "EXTERNAL_SURVEILLANCE_DELETE", "EXTERNAL_MESSAGE_VIEW", "EXTERNAL_MESSAGE_PROCESS", "EXTERNAL_MESSAGE_PUSH", "EXTERNAL_MESSAGE_DELETE", "PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES", "OUTBREAK_VIEW", "OUTBREAK_EDIT", "MANAGE_PUBLIC_EXPORT_CONFIGURATION", "DOCUMENT_TEMPLATE_MANAGEMENT", "LINE_LISTING_CONFIGURE", "DEV_MODE", "EMAIL_TEMPLATE_MANAGEMENT", "EXTERNAL_EMAIL_SEND", "EXTERNAL_EMAIL_ATTACH_DOCUMENTS", "CUSTOMIZABLE_ENUM_MANAGEMENT" ] } } } @@ -15096,6 +15096,9 @@ "CustomizableEnumValueDto" : { "type" : "object", "properties" : { + "active" : { + "type" : "boolean" + }, "caption" : { "type" : "string", "maxLength" : 1000000, @@ -16937,10 +16940,6 @@ "EventGroupIndexDto" : { "type" : "object", "properties" : { - "changeDate" : { - "type" : "string", - "format" : "date-time" - }, "eventCount" : { "type" : "integer", "format" : "int64" @@ -18267,7 +18266,7 @@ "type" : "array", "items" : { "type" : "string", - "enum" : [ "AGGREGATE_REPORTING", "CAMPAIGNS", "CASE_SURVEILANCE", "CLINICAL_MANAGEMENT", "CONTACT_TRACING", "EVENT_SURVEILLANCE", "SAMPLES_LAB", "ADDITIONAL_TESTS", "TASK_MANAGEMENT", "WEEKLY_REPORTING", "IMMUNIZATION_MANAGEMENT", "TRAVEL_ENTRIES", "DASHBOARD_SURVEILLANCE", "DASHBOARD_CONTACTS", "DASHBOARD_CAMPAIGNS", "DASHBOARD_SAMPLES", "LIMITED_SYNCHRONIZATION", "ENVIRONMENT_MANAGEMENT", "ASSIGN_TASKS_TO_HIGHER_LEVEL", "CASE_FOLLOWUP", "DOCUMENTS", "DOCUMENTS_MULTI_UPLOAD", "EVENT_GROUPS", "EVENT_HIERARCHIES", "EXTERNAL_MESSAGES", "MANUAL_EXTERNAL_MESSAGES", "NATIONAL_CASE_SHARING", "SURVEILLANCE_REPORTS", "SORMAS_TO_SORMAS_ACCEPT_REJECT", "SORMAS_TO_SORMAS_SHARE_CASES", "SORMAS_TO_SORMAS_SHARE_CONTACTS", "SORMAS_TO_SORMAS_SHARE_EVENTS", "SORMAS_TO_SORMAS_SHARE_EXTERNAL_MESSAGES", "IMMUNIZATION_STATUS_AUTOMATION", "PERSON_DUPLICATE_CUSTOM_SEARCH", "EDIT_INFRASTRUCTURE_DATA", "AUTOMATIC_ARCHIVING", "EDIT_ARCHIVED_ENTITIES", "EXTERNAL_EMAILS", "VIEW_TAB_CASES_HOSPITALIZATION", "VIEW_TAB_CASES_SYMPTOMS", "VIEW_TAB_CASES_EPIDEMIOLOGICAL_DATA", "VIEW_TAB_CASES_THERAPY", "VIEW_TAB_CASES_FOLLOW_UP", "VIEW_TAB_CASES_CLINICAL_COURSE", "VIEW_TAB_CONTACTS_EPIDEMIOLOGICAL_DATA", "VIEW_TAB_CONTACTS_FOLLOW_UP_VISITS", "GDPR_CONSENT_POPUP", "INFRASTRUCTURE_TYPE_AREA", "OUTBREAKS", "PERSON_MANAGEMENT", "LINE_LISTING", "EVENT_GROUPS_MODIFICATION_NOTIFICATIONS", "EVENT_PARTICIPANT_CASE_CONFIRMED_NOTIFICATIONS", "EVENT_PARTICIPANT_RELATED_TO_OTHER_EVENTS_NOTIFICATIONS", "TASK_NOTIFICATIONS", "OTHER_NOTIFICATIONS", "TASK_GENERATION_CASE_SURVEILLANCE", "TASK_GENERATION_CONTACT_TRACING", "TASK_GENERATION_EVENT_SURVEILLANCE", "TASK_GENERATION_GENERAL", "CASE_AND_CONTACT_BULK_ACTIONS" ] + "enum" : [ "AGGREGATE_REPORTING", "CAMPAIGNS", "CASE_SURVEILANCE", "CLINICAL_MANAGEMENT", "CONTACT_TRACING", "EVENT_SURVEILLANCE", "SAMPLES_LAB", "ADDITIONAL_TESTS", "TASK_MANAGEMENT", "WEEKLY_REPORTING", "IMMUNIZATION_MANAGEMENT", "TRAVEL_ENTRIES", "DASHBOARD_SURVEILLANCE", "DASHBOARD_CONTACTS", "DASHBOARD_CAMPAIGNS", "DASHBOARD_SAMPLES", "LIMITED_SYNCHRONIZATION", "ENVIRONMENT_MANAGEMENT", "ASSIGN_TASKS_TO_HIGHER_LEVEL", "CASE_FOLLOWUP", "DOCUMENTS", "DOCUMENTS_MULTI_UPLOAD", "EVENT_GROUPS", "EVENT_HIERARCHIES", "EXTERNAL_MESSAGES", "MANUAL_EXTERNAL_MESSAGES", "NATIONAL_CASE_SHARING", "SURVEILLANCE_REPORTS", "SORMAS_TO_SORMAS_ACCEPT_REJECT", "SORMAS_TO_SORMAS_SHARE_CASES", "SORMAS_TO_SORMAS_SHARE_CONTACTS", "SORMAS_TO_SORMAS_SHARE_EVENTS", "SORMAS_TO_SORMAS_SHARE_EXTERNAL_MESSAGES", "IMMUNIZATION_STATUS_AUTOMATION", "PERSON_DUPLICATE_CUSTOM_SEARCH", "EDIT_INFRASTRUCTURE_DATA", "AUTOMATIC_ARCHIVING", "EDIT_ARCHIVED_ENTITIES", "EXTERNAL_EMAILS", "HIDE_JURISDICTION_FIELDS", "VIEW_TAB_CASES_HOSPITALIZATION", "VIEW_TAB_CASES_SYMPTOMS", "VIEW_TAB_CASES_EPIDEMIOLOGICAL_DATA", "VIEW_TAB_CASES_THERAPY", "VIEW_TAB_CASES_FOLLOW_UP", "VIEW_TAB_CASES_CLINICAL_COURSE", "VIEW_TAB_CONTACTS_EPIDEMIOLOGICAL_DATA", "VIEW_TAB_CONTACTS_FOLLOW_UP_VISITS", "GDPR_CONSENT_POPUP", "INFRASTRUCTURE_TYPE_AREA", "OUTBREAKS", "PERSON_MANAGEMENT", "LINE_LISTING", "EVENT_GROUPS_MODIFICATION_NOTIFICATIONS", "EVENT_PARTICIPANT_CASE_CONFIRMED_NOTIFICATIONS", "EVENT_PARTICIPANT_RELATED_TO_OTHER_EVENTS_NOTIFICATIONS", "TASK_NOTIFICATIONS", "OTHER_NOTIFICATIONS", "TASK_GENERATION_CASE_SURVEILLANCE", "TASK_GENERATION_CONTACT_TRACING", "TASK_GENERATION_EVENT_SURVEILLANCE", "TASK_GENERATION_GENERAL", "CASE_AND_CONTACT_BULK_ACTIONS" ] } }, "region" : { @@ -18305,7 +18304,7 @@ }, "featureType" : { "type" : "string", - "enum" : [ "AGGREGATE_REPORTING", "CAMPAIGNS", "CASE_SURVEILANCE", "CLINICAL_MANAGEMENT", "CONTACT_TRACING", "EVENT_SURVEILLANCE", "SAMPLES_LAB", "ADDITIONAL_TESTS", "TASK_MANAGEMENT", "WEEKLY_REPORTING", "IMMUNIZATION_MANAGEMENT", "TRAVEL_ENTRIES", "DASHBOARD_SURVEILLANCE", "DASHBOARD_CONTACTS", "DASHBOARD_CAMPAIGNS", "DASHBOARD_SAMPLES", "LIMITED_SYNCHRONIZATION", "ENVIRONMENT_MANAGEMENT", "ASSIGN_TASKS_TO_HIGHER_LEVEL", "CASE_FOLLOWUP", "DOCUMENTS", "DOCUMENTS_MULTI_UPLOAD", "EVENT_GROUPS", "EVENT_HIERARCHIES", "EXTERNAL_MESSAGES", "MANUAL_EXTERNAL_MESSAGES", "NATIONAL_CASE_SHARING", "SURVEILLANCE_REPORTS", "SORMAS_TO_SORMAS_ACCEPT_REJECT", "SORMAS_TO_SORMAS_SHARE_CASES", "SORMAS_TO_SORMAS_SHARE_CONTACTS", "SORMAS_TO_SORMAS_SHARE_EVENTS", "SORMAS_TO_SORMAS_SHARE_EXTERNAL_MESSAGES", "IMMUNIZATION_STATUS_AUTOMATION", "PERSON_DUPLICATE_CUSTOM_SEARCH", "EDIT_INFRASTRUCTURE_DATA", "AUTOMATIC_ARCHIVING", "EDIT_ARCHIVED_ENTITIES", "EXTERNAL_EMAILS", "VIEW_TAB_CASES_HOSPITALIZATION", "VIEW_TAB_CASES_SYMPTOMS", "VIEW_TAB_CASES_EPIDEMIOLOGICAL_DATA", "VIEW_TAB_CASES_THERAPY", "VIEW_TAB_CASES_FOLLOW_UP", "VIEW_TAB_CASES_CLINICAL_COURSE", "VIEW_TAB_CONTACTS_EPIDEMIOLOGICAL_DATA", "VIEW_TAB_CONTACTS_FOLLOW_UP_VISITS", "GDPR_CONSENT_POPUP", "INFRASTRUCTURE_TYPE_AREA", "OUTBREAKS", "PERSON_MANAGEMENT", "LINE_LISTING", "EVENT_GROUPS_MODIFICATION_NOTIFICATIONS", "EVENT_PARTICIPANT_CASE_CONFIRMED_NOTIFICATIONS", "EVENT_PARTICIPANT_RELATED_TO_OTHER_EVENTS_NOTIFICATIONS", "TASK_NOTIFICATIONS", "OTHER_NOTIFICATIONS", "TASK_GENERATION_CASE_SURVEILLANCE", "TASK_GENERATION_CONTACT_TRACING", "TASK_GENERATION_EVENT_SURVEILLANCE", "TASK_GENERATION_GENERAL", "CASE_AND_CONTACT_BULK_ACTIONS" ] + "enum" : [ "AGGREGATE_REPORTING", "CAMPAIGNS", "CASE_SURVEILANCE", "CLINICAL_MANAGEMENT", "CONTACT_TRACING", "EVENT_SURVEILLANCE", "SAMPLES_LAB", "ADDITIONAL_TESTS", "TASK_MANAGEMENT", "WEEKLY_REPORTING", "IMMUNIZATION_MANAGEMENT", "TRAVEL_ENTRIES", "DASHBOARD_SURVEILLANCE", "DASHBOARD_CONTACTS", "DASHBOARD_CAMPAIGNS", "DASHBOARD_SAMPLES", "LIMITED_SYNCHRONIZATION", "ENVIRONMENT_MANAGEMENT", "ASSIGN_TASKS_TO_HIGHER_LEVEL", "CASE_FOLLOWUP", "DOCUMENTS", "DOCUMENTS_MULTI_UPLOAD", "EVENT_GROUPS", "EVENT_HIERARCHIES", "EXTERNAL_MESSAGES", "MANUAL_EXTERNAL_MESSAGES", "NATIONAL_CASE_SHARING", "SURVEILLANCE_REPORTS", "SORMAS_TO_SORMAS_ACCEPT_REJECT", "SORMAS_TO_SORMAS_SHARE_CASES", "SORMAS_TO_SORMAS_SHARE_CONTACTS", "SORMAS_TO_SORMAS_SHARE_EVENTS", "SORMAS_TO_SORMAS_SHARE_EXTERNAL_MESSAGES", "IMMUNIZATION_STATUS_AUTOMATION", "PERSON_DUPLICATE_CUSTOM_SEARCH", "EDIT_INFRASTRUCTURE_DATA", "AUTOMATIC_ARCHIVING", "EDIT_ARCHIVED_ENTITIES", "EXTERNAL_EMAILS", "HIDE_JURISDICTION_FIELDS", "VIEW_TAB_CASES_HOSPITALIZATION", "VIEW_TAB_CASES_SYMPTOMS", "VIEW_TAB_CASES_EPIDEMIOLOGICAL_DATA", "VIEW_TAB_CASES_THERAPY", "VIEW_TAB_CASES_FOLLOW_UP", "VIEW_TAB_CASES_CLINICAL_COURSE", "VIEW_TAB_CONTACTS_EPIDEMIOLOGICAL_DATA", "VIEW_TAB_CONTACTS_FOLLOW_UP_VISITS", "GDPR_CONSENT_POPUP", "INFRASTRUCTURE_TYPE_AREA", "OUTBREAKS", "PERSON_MANAGEMENT", "LINE_LISTING", "EVENT_GROUPS_MODIFICATION_NOTIFICATIONS", "EVENT_PARTICIPANT_CASE_CONFIRMED_NOTIFICATIONS", "EVENT_PARTICIPANT_RELATED_TO_OTHER_EVENTS_NOTIFICATIONS", "TASK_NOTIFICATIONS", "OTHER_NOTIFICATIONS", "TASK_GENERATION_CASE_SURVEILLANCE", "TASK_GENERATION_CONTACT_TRACING", "TASK_GENERATION_EVENT_SURVEILLANCE", "TASK_GENERATION_GENERAL", "CASE_AND_CONTACT_BULK_ACTIONS" ] }, "properties" : { "type" : "object", @@ -25191,7 +25190,7 @@ "type" : "array", "items" : { "type" : "string", - "enum" : [ "CASE_VIEW", "CASE_CREATE", "CASE_EDIT", "CASE_ARCHIVE", "CASE_DELETE", "CASE_IMPORT", "CASE_EXPORT", "CASE_INVESTIGATE", "CASE_CLASSIFY", "CASE_CHANGE_DISEASE", "CASE_CHANGE_EPID_NUMBER", "CASE_TRANSFER", "CASE_REFER_FROM_POE", "CASE_MERGE", "CASE_SHARE", "CASE_RESPONSIBLE", "IMMUNIZATION_VIEW", "IMMUNIZATION_CREATE", "IMMUNIZATION_EDIT", "IMMUNIZATION_ARCHIVE", "IMMUNIZATION_DELETE", "PERSON_VIEW", "PERSON_EDIT", "PERSON_DELETE", "PERSON_EXPORT", "PERSON_CONTACT_DETAILS_DELETE", "PERSON_MERGE", "SAMPLE_VIEW", "SAMPLE_CREATE", "SAMPLE_EDIT", "SAMPLE_DELETE", "SAMPLE_EXPORT", "SAMPLE_TRANSFER", "SAMPLE_EDIT_NOT_OWNED", "PERFORM_BULK_OPERATIONS_CASE_SAMPLES", "PATHOGEN_TEST_CREATE", "PATHOGEN_TEST_EDIT", "PATHOGEN_TEST_DELETE", "ADDITIONAL_TEST_VIEW", "ADDITIONAL_TEST_CREATE", "ADDITIONAL_TEST_EDIT", "ADDITIONAL_TEST_DELETE", "CONTACT_VIEW", "CONTACT_CREATE", "CONTACT_EDIT", "CONTACT_ARCHIVE", "CONTACT_DELETE", "CONTACT_IMPORT", "CONTACT_EXPORT", "CONTACT_CONVERT", "CONTACT_REASSIGN_CASE", "CONTACT_MERGE", "CONTACT_RESPONSIBLE", "VISIT_CREATE", "VISIT_EDIT", "VISIT_DELETE", "VISIT_EXPORT", "TASK_VIEW", "TASK_CREATE", "TASK_EDIT", "TASK_DELETE", "TASK_EXPORT", "TASK_ASSIGN", "TASK_ARCHIVE", "ACTION_CREATE", "ACTION_DELETE", "ACTION_EDIT", "EVENT_VIEW", "EVENT_CREATE", "EVENT_EDIT", "EVENT_ARCHIVE", "EVENT_DELETE", "EVENT_IMPORT", "EVENT_EXPORT", "PERFORM_BULK_OPERATIONS_EVENT", "EVENT_RESPONSIBLE", "EVENTPARTICIPANT_VIEW", "EVENTPARTICIPANT_CREATE", "EVENTPARTICIPANT_EDIT", "EVENTPARTICIPANT_ARCHIVE", "EVENTPARTICIPANT_DELETE", "EVENTPARTICIPANT_IMPORT", "PERFORM_BULK_OPERATIONS_EVENTPARTICIPANT", "EVENTGROUP_CREATE", "EVENTGROUP_EDIT", "EVENTGROUP_ARCHIVE", "EVENTGROUP_DELETE", "EVENTGROUP_LINK", "USER_VIEW", "USER_CREATE", "USER_EDIT", "USER_ROLE_VIEW", "USER_ROLE_EDIT", "USER_ROLE_DELETE", "STATISTICS_ACCESS", "STATISTICS_EXPORT", "INFRASTRUCTURE_VIEW", "INFRASTRUCTURE_CREATE", "INFRASTRUCTURE_EDIT", "INFRASTRUCTURE_ARCHIVE", "INFRASTRUCTURE_IMPORT", "INFRASTRUCTURE_EXPORT", "POPULATION_MANAGE", "DASHBOARD_SURVEILLANCE_VIEW", "DASHBOARD_CONTACT_VIEW", "DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS", "DASHBOARD_CAMPAIGNS_VIEW", "DASHBOARD_SAMPLES_VIEW", "CASE_CLINICIAN_VIEW", "THERAPY_VIEW", "PRESCRIPTION_CREATE", "PRESCRIPTION_EDIT", "PRESCRIPTION_DELETE", "TREATMENT_CREATE", "TREATMENT_EDIT", "TREATMENT_DELETE", "CLINICAL_COURSE_VIEW", "CLINICAL_COURSE_EDIT", "CLINICAL_VISIT_CREATE", "CLINICAL_VISIT_EDIT", "CLINICAL_VISIT_DELETE", "PORT_HEALTH_INFO_VIEW", "PORT_HEALTH_INFO_EDIT", "WEEKLYREPORT_VIEW", "WEEKLYREPORT_CREATE", "AGGREGATE_REPORT_VIEW", "AGGREGATE_REPORT_EDIT", "AGGREGATE_REPORT_EXPORT", "SEE_PERSONAL_DATA_IN_JURISDICTION", "SEE_PERSONAL_DATA_OUTSIDE_JURISDICTION", "SEE_SENSITIVE_DATA_IN_JURISDICTION", "SEE_SENSITIVE_DATA_OUTSIDE_JURISDICTION", "CAMPAIGN_VIEW", "CAMPAIGN_EDIT", "CAMPAIGN_ARCHIVE", "CAMPAIGN_DELETE", "CAMPAIGN_FORM_DATA_VIEW", "CAMPAIGN_FORM_DATA_EDIT", "CAMPAIGN_FORM_DATA_ARCHIVE", "CAMPAIGN_FORM_DATA_DELETE", "CAMPAIGN_FORM_DATA_EXPORT", "TRAVEL_ENTRY_MANAGEMENT_ACCESS", "TRAVEL_ENTRY_VIEW", "TRAVEL_ENTRY_CREATE", "TRAVEL_ENTRY_EDIT", "TRAVEL_ENTRY_ARCHIVE", "TRAVEL_ENTRY_DELETE", "ENVIRONMENT_VIEW", "ENVIRONMENT_CREATE", "ENVIRONMENT_EDIT", "ENVIRONMENT_ARCHIVE", "ENVIRONMENT_DELETE", "ENVIRONMENT_IMPORT", "ENVIRONMENT_EXPORT", "ENVIRONMENT_SAMPLE_VIEW", "ENVIRONMENT_SAMPLE_CREATE", "ENVIRONMENT_SAMPLE_EDIT", "ENVIRONMENT_SAMPLE_EDIT_DISPATCH", "ENVIRONMENT_SAMPLE_EDIT_RECEIVAL", "ENVIRONMENT_SAMPLE_DELETE", "ENVIRONMENT_SAMPLE_IMPORT", "ENVIRONMENT_SAMPLE_EXPORT", "DOCUMENT_VIEW", "DOCUMENT_UPLOAD", "DOCUMENT_DELETE", "PERFORM_BULK_OPERATIONS", "PERFORM_BULK_OPERATIONS_PSEUDONYM", "QUARANTINE_ORDER_CREATE", "SORMAS_REST", "SORMAS_UI", "DATABASE_EXPORT_ACCESS", "EXPORT_DATA_PROTECTION_DATA", "BAG_EXPORT", "SEND_MANUAL_EXTERNAL_MESSAGES", "MANAGE_EXTERNAL_SYMPTOM_JOURNAL", "EXTERNAL_VISITS", "SORMAS_TO_SORMAS_CLIENT", "SORMAS_TO_SORMAS_SHARE", "SORMAS_TO_SORMAS_PROCESS", "EXTERNAL_SURVEILLANCE_SHARE", "EXTERNAL_SURVEILLANCE_DELETE", "EXTERNAL_MESSAGE_VIEW", "EXTERNAL_MESSAGE_PROCESS", "EXTERNAL_MESSAGE_PUSH", "EXTERNAL_MESSAGE_DELETE", "PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES", "OUTBREAK_VIEW", "OUTBREAK_EDIT", "MANAGE_PUBLIC_EXPORT_CONFIGURATION", "DOCUMENT_TEMPLATE_MANAGEMENT", "LINE_LISTING_CONFIGURE", "DEV_MODE", "EMAIL_TEMPLATE_MANAGEMENT", "EXTERNAL_EMAIL_SEND", "EXTERNAL_EMAIL_ATTACH_DOCUMENTS", "CUSTOMIZABLE_ENUM_MANAGEMENT" ] + "enum" : [ "CASE_VIEW", "CASE_CREATE", "CASE_EDIT", "CASE_ARCHIVE", "CASE_DELETE", "CASE_IMPORT", "CASE_EXPORT", "CASE_INVESTIGATE", "CASE_CLASSIFY", "CASE_CHANGE_DISEASE", "CASE_CHANGE_EPID_NUMBER", "CASE_TRANSFER", "CASE_REFER_FROM_POE", "CASE_MERGE", "CASE_SHARE", "CASE_RESPONSIBLE", "IMMUNIZATION_VIEW", "IMMUNIZATION_CREATE", "IMMUNIZATION_EDIT", "IMMUNIZATION_ARCHIVE", "IMMUNIZATION_DELETE", "PERSON_VIEW", "PERSON_EDIT", "PERSON_DELETE", "PERSON_EXPORT", "PERSON_CONTACT_DETAILS_DELETE", "PERSON_MERGE", "SAMPLE_VIEW", "SAMPLE_CREATE", "SAMPLE_EDIT", "SAMPLE_DELETE", "SAMPLE_EXPORT", "SAMPLE_TRANSFER", "SAMPLE_EDIT_NOT_OWNED", "PERFORM_BULK_OPERATIONS_CASE_SAMPLES", "PATHOGEN_TEST_CREATE", "PATHOGEN_TEST_EDIT", "PATHOGEN_TEST_DELETE", "ADDITIONAL_TEST_VIEW", "ADDITIONAL_TEST_CREATE", "ADDITIONAL_TEST_EDIT", "ADDITIONAL_TEST_DELETE", "CONTACT_VIEW", "CONTACT_CREATE", "CONTACT_EDIT", "CONTACT_ARCHIVE", "CONTACT_DELETE", "CONTACT_IMPORT", "CONTACT_EXPORT", "CONTACT_CONVERT", "CONTACT_REASSIGN_CASE", "CONTACT_MERGE", "CONTACT_RESPONSIBLE", "VISIT_CREATE", "VISIT_EDIT", "VISIT_DELETE", "VISIT_EXPORT", "TASK_VIEW", "TASK_CREATE", "TASK_EDIT", "TASK_DELETE", "TASK_EXPORT", "TASK_ASSIGN", "TASK_ARCHIVE", "ACTION_CREATE", "ACTION_DELETE", "ACTION_EDIT", "EVENT_VIEW", "EVENT_CREATE", "EVENT_EDIT", "EVENT_ARCHIVE", "EVENT_DELETE", "EVENT_IMPORT", "EVENT_EXPORT", "PERFORM_BULK_OPERATIONS_EVENT", "EVENT_RESPONSIBLE", "EVENTPARTICIPANT_VIEW", "EVENTPARTICIPANT_CREATE", "EVENTPARTICIPANT_EDIT", "EVENTPARTICIPANT_ARCHIVE", "EVENTPARTICIPANT_DELETE", "EVENTPARTICIPANT_IMPORT", "PERFORM_BULK_OPERATIONS_EVENTPARTICIPANT", "EVENTGROUP_CREATE", "EVENTGROUP_EDIT", "EVENTGROUP_ARCHIVE", "EVENTGROUP_DELETE", "EVENTGROUP_LINK", "USER_VIEW", "USER_CREATE", "USER_EDIT", "USER_ROLE_VIEW", "USER_ROLE_EDIT", "USER_ROLE_DELETE", "STATISTICS_ACCESS", "STATISTICS_EXPORT", "INFRASTRUCTURE_VIEW", "INFRASTRUCTURE_CREATE", "INFRASTRUCTURE_EDIT", "INFRASTRUCTURE_ARCHIVE", "INFRASTRUCTURE_IMPORT", "INFRASTRUCTURE_EXPORT", "POPULATION_MANAGE", "DASHBOARD_SURVEILLANCE_VIEW", "DASHBOARD_CONTACT_VIEW", "DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS", "DASHBOARD_CAMPAIGNS_VIEW", "DASHBOARD_SAMPLES_VIEW", "CASE_CLINICIAN_VIEW", "THERAPY_VIEW", "PRESCRIPTION_CREATE", "PRESCRIPTION_EDIT", "PRESCRIPTION_DELETE", "TREATMENT_CREATE", "TREATMENT_EDIT", "TREATMENT_DELETE", "CLINICAL_COURSE_VIEW", "CLINICAL_COURSE_EDIT", "CLINICAL_VISIT_CREATE", "CLINICAL_VISIT_EDIT", "CLINICAL_VISIT_DELETE", "PORT_HEALTH_INFO_VIEW", "PORT_HEALTH_INFO_EDIT", "WEEKLYREPORT_VIEW", "WEEKLYREPORT_CREATE", "AGGREGATE_REPORT_VIEW", "AGGREGATE_REPORT_EDIT", "AGGREGATE_REPORT_EXPORT", "SEE_PERSONAL_DATA_IN_JURISDICTION", "SEE_PERSONAL_DATA_OUTSIDE_JURISDICTION", "SEE_SENSITIVE_DATA_IN_JURISDICTION", "SEE_SENSITIVE_DATA_OUTSIDE_JURISDICTION", "CAMPAIGN_VIEW", "CAMPAIGN_EDIT", "CAMPAIGN_ARCHIVE", "CAMPAIGN_DELETE", "CAMPAIGN_FORM_DATA_VIEW", "CAMPAIGN_FORM_DATA_EDIT", "CAMPAIGN_FORM_DATA_ARCHIVE", "CAMPAIGN_FORM_DATA_DELETE", "CAMPAIGN_FORM_DATA_EXPORT", "TRAVEL_ENTRY_MANAGEMENT_ACCESS", "TRAVEL_ENTRY_VIEW", "TRAVEL_ENTRY_CREATE", "TRAVEL_ENTRY_EDIT", "TRAVEL_ENTRY_ARCHIVE", "TRAVEL_ENTRY_DELETE", "ENVIRONMENT_VIEW", "ENVIRONMENT_CREATE", "ENVIRONMENT_EDIT", "ENVIRONMENT_ARCHIVE", "ENVIRONMENT_DELETE", "ENVIRONMENT_IMPORT", "ENVIRONMENT_EXPORT", "ENVIRONMENT_SAMPLE_VIEW", "ENVIRONMENT_SAMPLE_CREATE", "ENVIRONMENT_SAMPLE_EDIT", "ENVIRONMENT_SAMPLE_EDIT_DISPATCH", "ENVIRONMENT_SAMPLE_EDIT_RECEIVAL", "ENVIRONMENT_SAMPLE_DELETE", "ENVIRONMENT_SAMPLE_IMPORT", "ENVIRONMENT_SAMPLE_EXPORT", "ENVIRONMENT_PATHOGEN_TEST_CREATE", "ENVIRONMENT_PATHOGEN_TEST_EDIT", "ENVIRONMENT_PATHOGEN_TEST_DELETE", "DOCUMENT_VIEW", "DOCUMENT_UPLOAD", "DOCUMENT_DELETE", "PERFORM_BULK_OPERATIONS", "PERFORM_BULK_OPERATIONS_PSEUDONYM", "QUARANTINE_ORDER_CREATE", "SORMAS_REST", "SORMAS_UI", "DATABASE_EXPORT_ACCESS", "EXPORT_DATA_PROTECTION_DATA", "BAG_EXPORT", "SEND_MANUAL_EXTERNAL_MESSAGES", "MANAGE_EXTERNAL_SYMPTOM_JOURNAL", "EXTERNAL_VISITS", "SORMAS_TO_SORMAS_CLIENT", "SORMAS_TO_SORMAS_SHARE", "SORMAS_TO_SORMAS_PROCESS", "EXTERNAL_SURVEILLANCE_SHARE", "EXTERNAL_SURVEILLANCE_DELETE", "EXTERNAL_MESSAGE_VIEW", "EXTERNAL_MESSAGE_PROCESS", "EXTERNAL_MESSAGE_PUSH", "EXTERNAL_MESSAGE_DELETE", "PERFORM_BULK_OPERATIONS_EXTERNAL_MESSAGES", "OUTBREAK_VIEW", "OUTBREAK_EDIT", "MANAGE_PUBLIC_EXPORT_CONFIGURATION", "DOCUMENT_TEMPLATE_MANAGEMENT", "LINE_LISTING_CONFIGURE", "DEV_MODE", "EMAIL_TEMPLATE_MANAGEMENT", "EXTERNAL_EMAIL_SEND", "EXTERNAL_EMAIL_ATTACH_DOCUMENTS", "CUSTOMIZABLE_ENUM_MANAGEMENT" ] }, "uniqueItems" : true }, diff --git a/sormas-rest/swagger.yaml b/sormas-rest/swagger.yaml index e1e459b2084..b6340d78e0e 100644 --- a/sormas-rest/swagger.yaml +++ b/sormas-rest/swagger.yaml @@ -10,7 +10,7 @@ info: name: GPL v3 url: https://www.gnu.org/licenses/gpl-3.0.html title: SORMAS REST API - version: 1.93.0-SNAPSHOT + version: 1.94.0-SNAPSHOT servers: - url: /sormas-rest paths: @@ -7179,6 +7179,9 @@ paths: - ENVIRONMENT_SAMPLE_DELETE - ENVIRONMENT_SAMPLE_IMPORT - ENVIRONMENT_SAMPLE_EXPORT + - ENVIRONMENT_PATHOGEN_TEST_CREATE + - ENVIRONMENT_PATHOGEN_TEST_EDIT + - ENVIRONMENT_PATHOGEN_TEST_DELETE - DOCUMENT_VIEW - DOCUMENT_UPLOAD - DOCUMENT_DELETE @@ -7396,6 +7399,9 @@ paths: - ENVIRONMENT_SAMPLE_DELETE - ENVIRONMENT_SAMPLE_IMPORT - ENVIRONMENT_SAMPLE_EXPORT + - ENVIRONMENT_PATHOGEN_TEST_CREATE + - ENVIRONMENT_PATHOGEN_TEST_EDIT + - ENVIRONMENT_PATHOGEN_TEST_DELETE - DOCUMENT_VIEW - DOCUMENT_UPLOAD - DOCUMENT_DELETE @@ -12991,6 +12997,8 @@ components: CustomizableEnumValueDto: type: object properties: + active: + type: boolean caption: type: string maxLength: 1000000 @@ -15255,9 +15263,6 @@ components: EventGroupIndexDto: type: object properties: - changeDate: - type: string - format: date-time eventCount: type: integer format: int64 @@ -17160,6 +17165,7 @@ components: - AUTOMATIC_ARCHIVING - EDIT_ARCHIVED_ENTITIES - EXTERNAL_EMAILS + - HIDE_JURISDICTION_FIELDS - VIEW_TAB_CASES_HOSPITALIZATION - VIEW_TAB_CASES_SYMPTOMS - VIEW_TAB_CASES_EPIDEMIOLOGICAL_DATA @@ -17309,6 +17315,7 @@ components: - AUTOMATIC_ARCHIVING - EDIT_ARCHIVED_ENTITIES - EXTERNAL_EMAILS + - HIDE_JURISDICTION_FIELDS - VIEW_TAB_CASES_HOSPITALIZATION - VIEW_TAB_CASES_SYMPTOMS - VIEW_TAB_CASES_EPIDEMIOLOGICAL_DATA @@ -25462,6 +25469,9 @@ components: - ENVIRONMENT_SAMPLE_DELETE - ENVIRONMENT_SAMPLE_IMPORT - ENVIRONMENT_SAMPLE_EXPORT + - ENVIRONMENT_PATHOGEN_TEST_CREATE + - ENVIRONMENT_PATHOGEN_TEST_EDIT + - ENVIRONMENT_PATHOGEN_TEST_DELETE - DOCUMENT_VIEW - DOCUMENT_UPLOAD - DOCUMENT_DELETE diff --git a/sormas-serverlibs/pom.xml b/sormas-serverlibs/pom.xml index ccd82d554b2..bf9fec66f4c 100644 --- a/sormas-serverlibs/pom.xml +++ b/sormas-serverlibs/pom.xml @@ -3,7 +3,7 @@ sormas-base de.symeda.sormas - 1.93.0 + 1.94.0 ../sormas-base 4.0.0 @@ -289,11 +289,6 @@ spring-context - - org.apache.pdfbox - pdfbox - - diff --git a/sormas-ui/pom.xml b/sormas-ui/pom.xml index 43a904c4814..dc14e72a3e0 100644 --- a/sormas-ui/pom.xml +++ b/sormas-ui/pom.xml @@ -3,7 +3,7 @@ sormas-base de.symeda.sormas - 1.93.0 + 1.94.0 ../sormas-base 4.0.0 @@ -287,12 +287,6 @@ test - - org.apache.pdfbox - pdfbox - test - - diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/MainScreen.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/MainScreen.java index 290b15e92b9..091cf156489 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/MainScreen.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/MainScreen.java @@ -343,10 +343,9 @@ public View getView(String viewName) { } if (UserProvider.getCurrent().hasConfigurationAccess()) { - AbstractConfigurationView.registerViews(navigator); + Class firstAccessibleView = AbstractConfigurationView.registerViews(navigator); menu.addView( - FacadeProvider.getFeatureConfigurationFacade().isFeatureEnabled(FeatureType.OUTBREAKS) - && UserProvider.getCurrent().hasUserRight(UserRight.OUTBREAK_VIEW) ? OutbreaksView.class : RegionsView.class, + firstAccessibleView, AbstractConfigurationView.ROOT_VIEW_NAME, I18nProperties.getCaption(Captions.mainMenuConfiguration), VaadinIcons.COGS); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/UiUtil.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/UiUtil.java index b28dbe97886..ece7ef2904a 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/UiUtil.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/UiUtil.java @@ -24,7 +24,11 @@ public static boolean permitted(UserRight userRight) { } public static boolean enabled(FeatureType featureType) { - return !FacadeProvider.getFeatureConfigurationFacade().isFeatureDisabled(featureType); + return !disabled(featureType); + } + + public static boolean disabled(FeatureType featureType) { + return FacadeProvider.getFeatureConfigurationFacade().isFeatureDisabled(featureType); } public static boolean enabled(Set features) { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaigndata/CampaignDataGrid.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaigndata/CampaignDataGrid.java index 72ebcb9fa28..42bb1b37ab1 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaigndata/CampaignDataGrid.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaigndata/CampaignDataGrid.java @@ -22,9 +22,11 @@ import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.campaign.data.CampaignFormDataCriteria; import de.symeda.sormas.api.campaign.data.CampaignFormDataIndexDto; +import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.utils.DateHelper; import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.utils.CssStyles; import de.symeda.sormas.ui.utils.FilteredGrid; @@ -63,6 +65,12 @@ protected void addDefaultColumns() { for (Column column : getColumns()) { column.setCaption(I18nProperties.getPrefixCaption(CampaignFormDataIndexDto.I18N_PREFIX, column.getId(), column.getCaption())); } + + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + getColumn(CampaignFormDataIndexDto.REGION).setHidden(true); + getColumn(CampaignFormDataIndexDto.DISTRICT).setHidden(true); + getColumn(CampaignFormDataIndexDto.COMMUNITY).setHidden(true); + } } public void reload() { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaigndata/CampaignFormDataEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaigndata/CampaignFormDataEditForm.java index 30e9de50485..302308b0a73 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaigndata/CampaignFormDataEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaigndata/CampaignFormDataEditForm.java @@ -36,6 +36,7 @@ import de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto; import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto; import de.symeda.sormas.api.user.UserDto; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.campaign.expressions.ExpressionProcessor; import de.symeda.sormas.ui.utils.AbstractEditForm; @@ -47,6 +48,10 @@ public class CampaignFormDataEditForm extends AbstractEditForm { RegionReferenceDto region = (RegionReferenceDto) e.getProperty().getValue(); @@ -220,4 +242,13 @@ private void buildCampaignForm(CampaignFormDataDto campaignFormData) { protected String createHtmlLayout() { return HTML_LAYOUT; } + + @Override + protected void setInternalValue(CampaignFormDataDto newValue) { + super.setInternalValue(newValue); + + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + hideAndFillJurisdictionFields(); + } + } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaigndata/CampaignFormDataFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaigndata/CampaignFormDataFilterForm.java index 9cd3d3132e9..66876352485 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaigndata/CampaignFormDataFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaigndata/CampaignFormDataFilterForm.java @@ -44,13 +44,14 @@ public class CampaignFormDataFilterForm extends AbstractFilterForm formMetaChangedCallback; private ComboBox cbCampaignForm; - private ComboBox regionFilter; - private ComboBox districtFilter; - private ComboBox communityFilter; protected CampaignFormDataFilterForm() { - super(CampaignFormDataCriteria.class, CampaignFormDataDto.I18N_PREFIX); + super( + CampaignFormDataCriteria.class, + CampaignFormDataDto.I18N_PREFIX, + JurisdictionFieldConfig + .of(CampaignFormDataCriteria.REGION, CampaignFormDataCriteria.DISTRICT, CampaignFormDataCriteria.COMMUNITY)); formActionButtonsComponent.style(CssStyles.FORCE_CAPTION); formActionButtonsComponent.setSpacing(false); formActionButtonsComponent.setSizeFull(); @@ -84,17 +85,17 @@ protected void addFields() { }); } - regionFilter = addField( + ComboBox regionFilter = addField( FieldConfiguration.withCaptionAndPixelSized(CampaignFormDataCriteria.REGION, I18nProperties.getCaption(Captions.Campaign_region), 200)); regionFilter.setInputPrompt(I18nProperties.getString(Strings.promptAllRegions)); regionFilter.addItems(FacadeProvider.getRegionFacade().getAllActiveByServerCountry()); - districtFilter = addField( + ComboBox districtFilter = addField( FieldConfiguration .withCaptionAndPixelSized(CampaignFormDataCriteria.DISTRICT, I18nProperties.getCaption(Captions.Campaign_district), 200)); districtFilter.setInputPrompt(I18nProperties.getString(Strings.promptAllDistricts)); - communityFilter = addField( + ComboBox communityFilter = addField( FieldConfiguration .withCaptionAndPixelSized(CampaignFormDataCriteria.COMMUNITY, I18nProperties.getCaption(Captions.Campaign_community), 200)); communityFilter.setInputPrompt(I18nProperties.getString(Strings.promptAllCommunities)); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaignstatistics/CampaignStatisticsFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaignstatistics/CampaignStatisticsFilterForm.java index cb22a3f0b2c..384806a00e7 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaignstatistics/CampaignStatisticsFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaignstatistics/CampaignStatisticsFilterForm.java @@ -28,13 +28,14 @@ public class CampaignStatisticsFilterForm extends AbstractFilterForm formMetaChangedCallback; private ComboBox cbCampaignForm; - private ComboBox regionFilter; - private ComboBox districtFilter; - private ComboBox communityFilter; protected CampaignStatisticsFilterForm() { - super(CampaignStatisticsCriteria.class, CampaignStatisticsDto.I18N_PREFIX); + super( + CampaignStatisticsCriteria.class, + CampaignStatisticsDto.I18N_PREFIX, + JurisdictionFieldConfig + .of(CampaignStatisticsCriteria.REGION, CampaignStatisticsCriteria.DISTRICT, CampaignStatisticsCriteria.COMMUNITY)); formActionButtonsComponent.style(CssStyles.FORCE_CAPTION); formActionButtonsComponent.setSpacing(false); formActionButtonsComponent.setSizeFull(); @@ -68,17 +69,17 @@ protected void addFields() { }); } - regionFilter = addField( + ComboBox regionFilter = addField( FieldConfiguration.withCaptionAndPixelSized(CampaignStatisticsCriteria.REGION, I18nProperties.getCaption(Captions.Campaign_region), 200)); regionFilter.setInputPrompt(I18nProperties.getString(Strings.promptAllRegions)); regionFilter.addItems(FacadeProvider.getRegionFacade().getAllActiveByServerCountry()); - districtFilter = addField( + ComboBox districtFilter = addField( FieldConfiguration .withCaptionAndPixelSized(CampaignStatisticsCriteria.DISTRICT, I18nProperties.getCaption(Captions.Campaign_district), 200)); districtFilter.setInputPrompt(I18nProperties.getString(Strings.promptAllDistricts)); - communityFilter = addField( + ComboBox communityFilter = addField( FieldConfiguration .withCaptionAndPixelSized(CampaignStatisticsCriteria.COMMUNITY, I18nProperties.getCaption(Captions.Campaign_community), 200)); communityFilter.setInputPrompt(I18nProperties.getString(Strings.promptAllCommunities)); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaignstatistics/CampaignStatisticsGrid.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaignstatistics/CampaignStatisticsGrid.java index b2af6cc165e..facf4642a11 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaignstatistics/CampaignStatisticsGrid.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaignstatistics/CampaignStatisticsGrid.java @@ -6,7 +6,9 @@ import de.symeda.sormas.api.campaign.CampaignJurisdictionLevel; import de.symeda.sormas.api.campaign.statistics.CampaignStatisticsCriteria; import de.symeda.sormas.api.campaign.statistics.CampaignStatisticsDto; +import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.utils.FilteredGrid; public class CampaignStatisticsGrid extends FilteredGrid { @@ -49,7 +51,9 @@ public void setDataProvider() { } public void setColumnsVisibility(CampaignJurisdictionLevel groupingLevel) { - setAreaColumnVisible(CampaignJurisdictionLevel.AREA.equals(groupingLevel) || CampaignJurisdictionLevel.REGION.equals(groupingLevel)); + setAreaColumnVisible( + UiUtil.disabled(FeatureType.HIDE_JURISDICTION_FIELDS) + && (CampaignJurisdictionLevel.AREA.equals(groupingLevel) || CampaignJurisdictionLevel.REGION.equals(groupingLevel))); setRegionColumnVisible( CampaignJurisdictionLevel.REGION.equals(groupingLevel) || CampaignJurisdictionLevel.DISTRICT.equals(groupingLevel) diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaignstatistics/CampaignStatisticsView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaignstatistics/CampaignStatisticsView.java index 793366ca22a..08664a754b3 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaignstatistics/CampaignStatisticsView.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaignstatistics/CampaignStatisticsView.java @@ -24,10 +24,12 @@ import de.symeda.sormas.api.campaign.form.CampaignFormMetaReferenceDto; import de.symeda.sormas.api.campaign.form.CampaignFormTranslations; import de.symeda.sormas.api.campaign.statistics.CampaignStatisticsCriteria; +import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.Strings; import de.symeda.sormas.api.user.UserDto; import de.symeda.sormas.api.user.UserRight; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.ViewModelProviders; import de.symeda.sormas.ui.campaign.AbstractCampaignView; @@ -80,18 +82,21 @@ public CampaignStatisticsView() { } VerticalLayout mainLayout = new VerticalLayout(); - - HorizontalLayout jurisdictionLayout = new HorizontalLayout(); JurisdictionSelector jurisdictionSelector = new JurisdictionSelector(); - jurisdictionSelector.addValueChangeListener(e -> { - CampaignJurisdictionLevel groupingValue = (CampaignJurisdictionLevel) e.getValue(); - criteria.setGroupingLevel(groupingValue); - grid.setColumnsVisibility(groupingValue); - grid.reload(); - }); - jurisdictionLayout.addComponent(jurisdictionSelector); - mainLayout.addComponent(jurisdictionLayout); + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + jurisdictionSelector.setVisible(false); + } else { + HorizontalLayout jurisdictionLayout = new HorizontalLayout(); + jurisdictionSelector.addValueChangeListener(e -> { + CampaignJurisdictionLevel groupingValue = (CampaignJurisdictionLevel) e.getValue(); + criteria.setGroupingLevel(groupingValue); + grid.setColumnsVisibility(groupingValue); + grid.reload(); + }); + jurisdictionLayout.addComponent(jurisdictionSelector); + mainLayout.addComponent(jurisdictionLayout); + } HorizontalLayout filtersLayout = new HorizontalLayout(); filtersLayout.setWidthFull(); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/AbstractCaseGrid.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/AbstractCaseGrid.java index 04270341103..a589a9f5378 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/AbstractCaseGrid.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/AbstractCaseGrid.java @@ -36,7 +36,6 @@ import de.symeda.sormas.api.contact.ContactIndexDto; import de.symeda.sormas.api.contact.FollowUpStatus; import de.symeda.sormas.api.feature.FeatureType; -import de.symeda.sormas.api.followup.FollowUpLogic; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.location.LocationDto; @@ -45,6 +44,7 @@ import de.symeda.sormas.api.utils.DateHelper; import de.symeda.sormas.api.utils.SortProperty; import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.ViewModelProviders; import de.symeda.sormas.ui.utils.CssStyles; @@ -105,7 +105,7 @@ protected void initColumns() { Column visitsColumn = addColumn(entry -> { Integer numberOfVisits = entry.getVisitCount(); Integer numberOfMissedVisits = entry.getMissedVisitsCount(); - if (numberOfVisits != null && numberOfMissedVisits != null ) { + if (numberOfVisits != null && numberOfMissedVisits != null) { return String.format(I18nProperties.getCaption(Captions.formatNumberOfVisitsFormat), numberOfVisits, numberOfMissedVisits); } else { return "-"; @@ -200,6 +200,10 @@ protected void initColumns() { LocationDto.I18N_PREFIX)); column.setStyleGenerator(FieldAccessColumnStyleGenerator.getDefault(getBeanType(), column.getId())); } + + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + getColumn(CaseIndexDto.RESPONSIBLE_DISTRICT_NAME).setHidden(true); + } } protected Stream getGridColumns() { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/BulkCaseDataForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/BulkCaseDataForm.java index 7076b57c907..52b98bdacbb 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/BulkCaseDataForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/BulkCaseDataForm.java @@ -52,6 +52,7 @@ import de.symeda.sormas.api.customizableenum.CustomizableEnumType; import de.symeda.sormas.api.disease.DiseaseVariant; import de.symeda.sormas.api.event.TypeOfPlace; +import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; @@ -64,6 +65,7 @@ import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto; import de.symeda.sormas.api.user.UserReferenceDto; import de.symeda.sormas.api.user.UserRight; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.utils.AbstractEditForm; import de.symeda.sormas.ui.utils.ComboBoxHelper; import de.symeda.sormas.ui.utils.ComboBoxWithPlaceholder; @@ -142,6 +144,10 @@ public class BulkCaseDataForm extends AbstractEditForm { private OptionGroup facilityOrHome; private HorizontalLayout warningLayout; + private ComboBox region; + private ComboBox district; + private ComboBox community; + public BulkCaseDataForm(DistrictReferenceDto singleSelectedDistrict, Collection selectedCases) { super(CaseBulkEditData.class, CaseDataDto.I18N_PREFIX); this.singleSelectedDistrict = singleSelectedDistrict; @@ -286,11 +292,11 @@ protected void addFields() { healthFacilityCheckbox = new CheckBox(I18nProperties.getCaption(Captions.bulkFacility)); getContent().addComponent(healthFacilityCheckbox, HEALTH_FACILITY_CHECKBOX); - ComboBox region = addInfrastructureField(CaseBulkEditData.REGION); + region = addInfrastructureField(CaseBulkEditData.REGION); region.setEnabled(false); - ComboBox district = addInfrastructureField(CaseBulkEditData.DISTRICT); + district = addInfrastructureField(CaseBulkEditData.DISTRICT); district.setEnabled(false); - ComboBox community = addInfrastructureField(CaseBulkEditData.COMMUNITY); + community = addInfrastructureField(CaseBulkEditData.COMMUNITY); community.setNullSelectionAllowed(true); community.setEnabled(false); facilityOrHome = new OptionGroup(I18nProperties.getCaption(Captions.casePlaceOfStay), TypeOfPlace.FOR_CASES); @@ -321,36 +327,42 @@ protected void addFields() { updateFacilityFields(facility, healthFacilityDetails); }); district.addValueChangeListener(e -> { - FieldHelper.removeItems(facility); - FieldHelper.removeItems(community); DistrictReferenceDto districtDto = (DistrictReferenceDto) e.getProperty().getValue(); + FieldHelper.removeItems(community); FieldHelper.updateItems( community, districtDto != null ? FacadeProvider.getCommunityFacade().getAllActiveByDistrict(districtDto.getUuid()) : null); - if (districtDto != null && facilityType.getValue() != null) { - FieldHelper.updateItems( - facility, - FacadeProvider.getFacilityFacade() - .getActiveFacilitiesByDistrictAndType(districtDto, (FacilityType) facilityType.getValue(), true, false)); + + if (!TypeOfPlace.HOME.equals(facilityOrHome.getValue())) { + FieldHelper.removeItems(facility); + if (districtDto != null && facilityType.getValue() != null) { + FieldHelper.updateItems( + facility, + FacadeProvider.getFacilityFacade() + .getActiveFacilitiesByDistrictAndType(districtDto, (FacilityType) facilityType.getValue(), true, false)); + } } }); community.addValueChangeListener(e -> { - FieldHelper.removeItems(facility); - CommunityReferenceDto communityDto = (CommunityReferenceDto) e.getProperty().getValue(); - if (facilityType.getValue() != null) { - FieldHelper.updateItems( - facility, - communityDto != null - ? FacadeProvider.getFacilityFacade() - .getActiveFacilitiesByCommunityAndType(communityDto, (FacilityType) facilityType.getValue(), true, false) - : district.getValue() != null + if (!TypeOfPlace.HOME.equals(facilityOrHome.getValue())) { + FieldHelper.removeItems(facility); + + CommunityReferenceDto communityDto = (CommunityReferenceDto) e.getProperty().getValue(); + if (facilityType.getValue() != null) { + FieldHelper.updateItems( + facility, + communityDto != null ? FacadeProvider.getFacilityFacade() - .getActiveFacilitiesByDistrictAndType( - (DistrictReferenceDto) district.getValue(), - (FacilityType) facilityType.getValue(), - true, - false) - : null); + .getActiveFacilitiesByCommunityAndType(communityDto, (FacilityType) facilityType.getValue(), true, false) + : district.getValue() != null + ? FacadeProvider.getFacilityFacade() + .getActiveFacilitiesByDistrictAndType( + (DistrictReferenceDto) district.getValue(), + (FacilityType) facilityType.getValue(), + true, + false) + : null); + } } }); facilityTypeGroup.addValueChangeListener(e -> { @@ -516,6 +528,10 @@ protected void addFields() { FieldHelper.removeSoftRequiredStyle(community); } }); + + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + hideAndFillJurisdictionFields(); + } } @Override @@ -606,4 +622,13 @@ private void updateDiseaseVariantField(ComboBox diseaseVariantField, Disease dis diseaseVariantCheckBox.setValue(false); } } + + private void hideAndFillJurisdictionFields() { + region.setVisible(false); + region.setValue(FacadeProvider.getRegionFacade().getDefaultInfrastructureReference()); + district.setVisible(false); + district.setValue(FacadeProvider.getDistrictFacade().getDefaultInfrastructureReference()); + community.setVisible(false); + community.setValue(FacadeProvider.getCommunityFacade().getDefaultInfrastructureReference()); + } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseController.java index 8e8996c8b62..94d08a2e2af 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseController.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseController.java @@ -958,7 +958,7 @@ public CommitDiscardWrapperComponent getCaseDataEditComponent(fina } if (UserProvider.getCurrent().getUserRoles().stream().anyMatch(userRoleDto -> !userRoleDto.isRestrictAccessToAssignedEntities()) - || caze.getSurveillanceOfficer().equals(UserProvider.getCurrent().getUserReference())) { + || DataHelper.isSame(caze.getSurveillanceOfficer(), UserProvider.getCurrent().getUserReference())) { appendSpecialCommands(caze, editView); } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseCreateForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseCreateForm.java index 01cb140be5a..b078fba6b9c 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseCreateForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseCreateForm.java @@ -51,7 +51,6 @@ import de.symeda.sormas.api.disease.DiseaseVariant; import de.symeda.sormas.api.event.TypeOfPlace; import de.symeda.sormas.api.feature.FeatureType; -import de.symeda.sormas.api.feature.FeatureTypeProperty; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; @@ -70,6 +69,7 @@ import de.symeda.sormas.api.user.JurisdictionLevel; import de.symeda.sormas.api.utils.fieldaccess.UiFieldAccessCheckers; import de.symeda.sormas.api.utils.fieldvisibility.FieldVisibilityCheckers; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.location.LocationEditForm; import de.symeda.sormas.ui.person.PersonCreateForm; @@ -715,8 +715,7 @@ public void setValue(CaseDataDto caseDataDto) throws com.vaadin.v7.data.Property PersonDto personByUuid = personUuid == null ? null : FacadeProvider.getPersonFacade().getByUuid(personUuid); personCreateForm.setPerson(personByUuid); - if (FacadeProvider.getFeatureConfigurationFacade() - .isPropertyValueTrue(FeatureType.CASE_SURVEILANCE, FeatureTypeProperty.HIDE_JURISDICTION_FIELDS)) { + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { hideAndFillJurisdictionFields(); } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java index 39202616626..738c70b048d 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java @@ -41,7 +41,6 @@ import java.util.Map; import java.util.stream.Collectors; -import de.symeda.sormas.ui.utils.UserField; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -128,6 +127,7 @@ import de.symeda.sormas.api.utils.fieldvisibility.checkers.CountryFieldVisibilityChecker; import de.symeda.sormas.api.utils.fieldvisibility.checkers.UserRightFieldVisibilityChecker; import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.caze.surveillancereport.CaseReinfectionCheckBoxTree; import de.symeda.sormas.ui.clinicalcourse.HealthConditionsForm; @@ -145,6 +145,7 @@ import de.symeda.sormas.ui.utils.NullableOptionGroup; import de.symeda.sormas.ui.utils.OutbreakFieldVisibilityChecker; import de.symeda.sormas.ui.utils.StringToAngularLocationConverter; +import de.symeda.sormas.ui.utils.UserField; import de.symeda.sormas.ui.utils.VaadinUiUtil; import de.symeda.sormas.ui.utils.ValidationUtils; import de.symeda.sormas.ui.utils.ViewMode; @@ -184,7 +185,7 @@ public class CaseDataForm extends AbstractEditForm { //@formatter:off private static final String MAIN_HTML_LAYOUT = loc(CASE_DATA_HEADING_LOC) + - fluidRowLocs(4, CaseDataDto.UUID, 3, CaseDataDto.REPORT_DATE, 5, CaseDataDto.REPORTING_USER) + + fluidRowLocs(4, CaseDataDto.UUID, 3, CaseDataDto.REPORT_DATE, 3, CaseDataDto.REPORTING_USER, 2, "") + inlineLocs(CaseDataDto.CASE_CLASSIFICATION, CLASSIFICATION_RULES_LOC, CASE_CONFIRMATION_BASIS, CASE_CLASSIFICATION_CALCULATE_BTN_LOC) + fluidRow(fluidColumnLoc(3, 0, CaseDataDto.CASE_REFERENCE_DEFINITION)) + fluidRowLocs(4, CaseDataDto.CLINICAL_CONFIRMATION, 4, CaseDataDto.EPIDEMIOLOGICAL_CONFIRMATION, 4, CaseDataDto.LABORATORY_DIAGNOSTIC_CONFIRMATION) + @@ -302,6 +303,7 @@ public class CaseDataForm extends AbstractEditForm { private ComboBox responsibleRegion; private ComboBox responsibleDistrict; private ComboBox responsibleCommunity; + private ComboBox regionCombo; private ComboBox districtCombo; private ComboBox communityCombo; private OptionGroup facilityOrHome; @@ -458,7 +460,7 @@ protected void addFields() { true); ComboBox diseaseField = addDiseaseField(CaseDataDto.DISEASE, false); - ComboBox diseaseVariantField = addField(CaseDataDto.DISEASE_VARIANT, ComboBox.class); + ComboBox diseaseVariantField = addCustomizableEnumField(CaseDataDto.DISEASE_VARIANT); TextField diseaseVariantDetailsField = addField(CaseDataDto.DISEASE_VARIANT_DETAILS, TextField.class); diseaseVariantDetailsField.setVisible(false); diseaseVariantField.setNullSelectionAllowed(true); @@ -779,7 +781,7 @@ protected void addFields() { differentPlaceOfStayJurisdiction = addCustomField(DIFFERENT_PLACE_OF_STAY_JURISDICTION, Boolean.class, CheckBox.class); differentPlaceOfStayJurisdiction.addStyleName(VSPACE_3); - ComboBox regionCombo = addInfrastructureField(CaseDataDto.REGION); + regionCombo = addInfrastructureField(CaseDataDto.REGION); districtCombo = addInfrastructureField(CaseDataDto.DISTRICT); communityCombo = addInfrastructureField(CaseDataDto.COMMUNITY); communityCombo.setNullSelectionAllowed(true); @@ -1415,22 +1417,21 @@ public String getFormattedHtmlMessage() { reinfectionTree.initCheckboxes(); } }); - - if (FacadeProvider.getFeatureConfigurationFacade() - .isPropertyValueTrue(FeatureType.CASE_SURVEILANCE, FeatureTypeProperty.HIDE_JURISDICTION_FIELDS)) { - hideJurisdictionFields(); - } } private void hideJurisdictionFields() { - getField(CaseDataDto.CASE_ORIGIN).setVisible(false); getContent().getComponent(RESPONSIBLE_JURISDICTION_HEADING_LOC).setVisible(false); getContent().getComponent(PLACE_OF_STAY_HEADING_LOC).setVisible(false); differentPlaceOfStayJurisdiction.setVisible(false); + responsibleRegion.setVisible(false); responsibleDistrict.setVisible(false); responsibleCommunity.setVisible(false); + + regionCombo.setVisible(false); + districtCombo.setVisible(false); + communityCombo.setVisible(false); } private void updateFacilityOrHome() { @@ -1716,6 +1717,10 @@ public void setValue(CaseDataDto newFieldValue) throws ReadOnlyException, Conver updateVisibilityDifferentPlaceOfStayJurisdiction(newFieldValue); + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + hideJurisdictionFields(); + } + // HACK: Binding to the fields will call field listeners that may clear/modify the values of other fields. // this hopefully resets everything to its correct value discard(); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseFilterForm.java index 6807f3fab63..3131758a495 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseFilterForm.java @@ -118,7 +118,11 @@ public class CaseFilterForm extends AbstractFilterForm { + loc(WEEK_AND_DATE_FILTER); protected CaseFilterForm() { - super(CaseCriteria.class, CaseDataDto.I18N_PREFIX, FieldVisibilityCheckers.withCountry(FacadeProvider.getConfigFacade().getCountryLocale())); + super( + CaseCriteria.class, + CaseDataDto.I18N_PREFIX, + FieldVisibilityCheckers.withCountry(FacadeProvider.getConfigFacade().getCountryLocale()), + JurisdictionFieldConfig.of(CaseDataDto.REGION, CaseDataDto.DISTRICT, CaseDataDto.COMMUNITY)); } @Override @@ -187,9 +191,11 @@ public void addMoreFilters(CustomLayout moreFiltersContainer) { ComboBox presentConditionField = addField(moreFiltersContainer, FieldConfiguration.pixelSized(CaseCriteria.PRESENT_CONDITION, 140)); presentConditionField.setInputPrompt(I18nProperties.getPrefixCaption(PersonDto.I18N_PREFIX, PersonDto.PRESENT_CONDITION)); - ComboBox jurisdictionTypeField = addField(moreFiltersContainer, FieldConfiguration.pixelSized(CaseCriteria.JURISDICTION_TYPE, 140)); - jurisdictionTypeField.setInputPrompt(I18nProperties.getCaption(Captions.caseJurisdictionType)); - FieldHelper.updateEnumData(jurisdictionTypeField, Arrays.asList(CaseJurisdictionType.values())); + if (UiUtil.disabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + ComboBox jurisdictionTypeField = addField(moreFiltersContainer, FieldConfiguration.pixelSized(CaseCriteria.JURISDICTION_TYPE, 140)); + jurisdictionTypeField.setInputPrompt(I18nProperties.getCaption(Captions.caseJurisdictionType)); + FieldHelper.updateEnumData(jurisdictionTypeField, Arrays.asList(CaseJurisdictionType.values())); + } ComboBox regionField = null; if (user.getRegion() == null) { @@ -345,7 +351,8 @@ public void addMoreFilters(CustomLayout moreFiltersContainer) { CaseCriteria.ONLY_CASES_WITH_EVENTS, I18nProperties.getCaption(Captions.caseFilterRelatedToEvent), I18nProperties.getDescription(Descriptions.descCaseFilterRelatedToEvent), - CssStyles.CHECKBOX_FILTER_INLINE)).setVisible(UiUtil.permitted(UserRight.EVENT_VIEW)); + CssStyles.CHECKBOX_FILTER_INLINE)) + .setVisible(UiUtil.permitted(UserRight.EVENT_VIEW)); addField( moreFiltersContainer, @@ -436,9 +443,6 @@ protected void applyDependenciesOnFieldChange(String propertyId, Property.ValueC final CaseCriteria criteria = getValue(); - final ComboBox regionField = getField(CaseDataDto.REGION); - final ComboBox districtField = getField(CaseDataDto.DISTRICT); - final ComboBox communityField = getField(CaseDataDto.COMMUNITY); final ComboBox facilityTypeGroupField = getField(CaseCriteria.FACILITY_TYPE_GROUP); final ComboBox facilityTypeField = getField(CaseCriteria.FACILITY_TYPE); final ComboBox facilityField = getField(CaseDataDto.HEALTH_FACILITY); @@ -447,7 +451,7 @@ protected void applyDependenciesOnFieldChange(String propertyId, Property.ValueC final UserDto user = currentUserDto(); final DistrictReferenceDto currentDistrict = - user.getDistrict() != null ? user.getDistrict() : (DistrictReferenceDto) districtField.getValue(); + user.getDistrict() != null ? user.getDistrict() : (DistrictReferenceDto) districtFilter.getValue(); final CaseOrigin currentCaseOrigin = caseOriginField != null ? (CaseOrigin) getField(CaseDataDto.CASE_ORIGIN).getValue() : CaseOrigin.POINT_OF_ENTRY; @@ -459,15 +463,15 @@ protected void applyDependenciesOnFieldChange(String propertyId, Property.ValueC final ComboBox officerField = getField(CaseDataDto.SURVEILLANCE_OFFICER); officerField.removeAllItems(); if (region != null) { - enableFields(districtField); - FieldHelper.updateItems(districtField, FacadeProvider.getDistrictFacade().getAllActiveByRegion(region.getUuid())); + enableFields(districtFilter); + FieldHelper.updateItems(districtFilter, FacadeProvider.getDistrictFacade().getAllActiveByRegion(region.getUuid())); disableFields(pointOfEntryField); - clearAndDisableFields(communityField, facilityField, facilityTypeField, facilityTypeGroupField); + clearAndDisableFields(communityFilter, facilityField, facilityTypeField, facilityTypeGroupField); addOfficers(officerField, region); } else { - clearAndDisableFields(districtField, communityField, facilityField, facilityTypeField, facilityTypeGroupField); + clearAndDisableFields(districtFilter, communityFilter, facilityField, facilityTypeField, facilityTypeGroupField); disableFields(pointOfEntryField); addOfficers(officerField, user.getRegion()); } @@ -482,7 +486,7 @@ protected void applyDependenciesOnFieldChange(String propertyId, Property.ValueC final ComboBox officerField = getField(CaseDataDto.SURVEILLANCE_OFFICER); officerField.removeAllItems(); if (newDistrict != null) { - enableFields(communityField, facilityTypeGroupField); + enableFields(communityFilter, facilityTypeGroupField); clearAndDisableFields(facilityField); if (facilityTypeGroupField != null) { @@ -497,7 +501,7 @@ protected void applyDependenciesOnFieldChange(String propertyId, Property.ValueC } } - FieldHelper.updateItems(communityField, FacadeProvider.getCommunityFacade().getAllActiveByDistrict(newDistrict.getUuid())); + FieldHelper.updateItems(communityFilter, FacadeProvider.getCommunityFacade().getAllActiveByDistrict(newDistrict.getUuid())); if (pointOfEntryField != null && currentCaseOrigin == CaseOrigin.POINT_OF_ENTRY) { pointOfEntryField.setEnabled(true); @@ -509,9 +513,9 @@ protected void applyDependenciesOnFieldChange(String propertyId, Property.ValueC officerField .addItems(FacadeProvider.getUserFacade().getUserRefsByDistrict(newDistrict, selectedDisease, UserRight.CASE_RESPONSIBLE)); } else { - clearAndDisableFields(communityField, pointOfEntryField, facilityField, facilityTypeField, facilityTypeGroupField); + clearAndDisableFields(communityFilter, pointOfEntryField, facilityField, facilityTypeField, facilityTypeGroupField); - final RegionReferenceDto region = regionField != null ? (RegionReferenceDto) regionField.getValue() : null; + final RegionReferenceDto region = regionFilter != null ? (RegionReferenceDto) regionFilter.getValue() : null; addOfficers(officerField, region != null ? region : user.getRegion()); } } @@ -566,7 +570,7 @@ protected void applyDependenciesOnFieldChange(String propertyId, Property.ValueC enableFields(facilityField); facilityField.setValue(null); - CommunityReferenceDto community = (CommunityReferenceDto) communityField.getValue(); + CommunityReferenceDto community = (CommunityReferenceDto) communityFilter.getValue(); if (community != null) { FieldHelper.updateItems( facilityField, diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseGridDetailed.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseGridDetailed.java index 3e90c264d55..52a23ebdbcb 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseGridDetailed.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseGridDetailed.java @@ -13,6 +13,7 @@ import de.symeda.sormas.api.caze.CaseCriteria; import de.symeda.sormas.api.caze.CaseIndexDetailedDto; import de.symeda.sormas.api.caze.CaseIndexDto; +import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.person.PersonHelper; import de.symeda.sormas.api.symptoms.SymptomsDto; @@ -153,5 +154,10 @@ protected void initColumns() { .setRenderer(new DateRenderer(DateFormatHelper.getDateFormat())) .setCaption(I18nProperties.getPrefixCaption(SymptomsDto.I18N_PREFIX, SymptomsDto.ONSET_DATE)) .setWidth(80); + + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + getColumn(CaseIndexDetailedDto.RESPONSIBLE_REGION).setHidden(true); + getColumn(CaseIndexDetailedDto.RESPONSIBLE_COMMUNITY).setHidden(true); + } } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CasePersonView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CasePersonView.java index d0c380e3202..67566201816 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CasePersonView.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CasePersonView.java @@ -48,6 +48,7 @@ protected void initView(String params) { CaseDataDto caseData = FacadeProvider.getCaseFacade().getCaseDataByUuid(getCaseRef().getUuid()); person = FacadeProvider.getPersonFacade().getByUuid(caseData.getPerson().getUuid()); + boolean isEditAllowed = isEditAllowed(); CommitDiscardWrapperComponent editComponent = ControllerProvider.getPersonController() .getPersonEditComponent( PersonContext.CASE, @@ -56,11 +57,11 @@ protected void initView(String params) { caseData.getDiseaseDetails(), UserRight.CASE_EDIT, getViewMode(), - isEditAllowed()); + isEditAllowed); DetailSubComponentWrapper componentWrapper = addComponentWrapper(editComponent); CustomLayout layout = addPageLayout(componentWrapper, editComponent); setSubComponent(componentWrapper); - addSideComponents(layout, DeletableEntityType.CASE, caseData.getUuid(), person.toReference(), this::showUnsavedChangesPopup, isEditAllowed()); + addSideComponents(layout, DeletableEntityType.CASE, caseData.getUuid(), person.toReference(), this::showUnsavedChangesPopup, isEditAllowed); setEditPermission( editComponent, UserProvider.getCurrent().hasUserRight(UserRight.PERSON_EDIT), diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/components/linelisting/LineListingLayout.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/components/linelisting/LineListingLayout.java index 178a0d481f0..e5a34e0b13d 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/components/linelisting/LineListingLayout.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/components/linelisting/LineListingLayout.java @@ -26,6 +26,7 @@ import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.caze.CaseDataDto; +import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; @@ -41,6 +42,7 @@ import de.symeda.sormas.api.user.UserRight; import de.symeda.sormas.api.utils.UtilDate; import de.symeda.sormas.api.utils.ValidationRuntimeException; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.utils.ButtonHelper; import de.symeda.sormas.ui.utils.CssStyles; @@ -101,7 +103,6 @@ public LineListingLayout(Window window) { district = new ComboBox<>(I18nProperties.getPrefixCaption(CaseDataDto.I18N_PREFIX, CaseDataDto.RESPONSIBLE_DISTRICT)); district.setItemCaptionGenerator(item -> item.buildCaption()); district.setId("lineListingDistrict"); - district.addValueChangeListener(e -> setEpidNumberPrefixes()); sharedInformationBar.addComponent(district); typeGroup = new ComboBox<>(I18nProperties.getCaption(Captions.Facility_typeGroup)); @@ -160,6 +161,13 @@ public LineListingLayout(Window window) { region.setItems(FacadeProvider.getRegionFacade().getAllActiveByServerCountry()); } + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + region.setVisible(false); + region.setValue(FacadeProvider.getRegionFacade().getDefaultInfrastructureReference()); + district.setVisible(false); + district.setValue(FacadeProvider.getDistrictFacade().getDefaultInfrastructureReference()); + } + HorizontalLayout actionBar = new HorizontalLayout(); Button addLine = ButtonHelper.createIconButton(Captions.lineListingAddLine, VaadinIcons.PLUS, e -> { CaseLineLayout newLine = buildNewLine(lineComponent); @@ -488,6 +496,11 @@ public CaseLineLayout(int lineIndex) { } else { formatAsOtherLine(); } + + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + community.setVisible(false); + community.setValue(FacadeProvider.getCommunityFacade().getDefaultInfrastructureReference()); + } } public void setBean(CaseLineDto bean) { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/AbstractConfigurationView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/AbstractConfigurationView.java index caed46b5ff3..53c9da86170 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/AbstractConfigurationView.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/AbstractConfigurationView.java @@ -61,11 +61,14 @@ protected AbstractConfigurationView(String viewName) { super(viewName); } - public static void registerViews(Navigator navigator) { + public static Class registerViews(Navigator navigator) { + + Class firstAccessibleView = null; if (FacadeProvider.getFeatureConfigurationFacade().isFeatureEnabled(FeatureType.OUTBREAKS) && UserProvider.getCurrent().hasUserRight(UserRight.OUTBREAK_VIEW)) { navigator.addView(OutbreaksView.VIEW_NAME, OutbreaksView.class); + firstAccessibleView = OutbreaksView.class; } boolean isCaseSurveillanceEnabled = FacadeProvider.getFeatureConfigurationFacade().isFeatureEnabled(FeatureType.CASE_SURVEILANCE); @@ -81,6 +84,7 @@ public static void registerViews(Navigator navigator) { navigator.addView(CountriesView.VIEW_NAME, CountriesView.class); } navigator.addView(RegionsView.VIEW_NAME, RegionsView.class); + firstAccessibleView = firstAccessibleView != null ? firstAccessibleView : RegionsView.class; navigator.addView(DistrictsView.VIEW_NAME, DistrictsView.class); navigator.addView(CommunitiesView.VIEW_NAME, CommunitiesView.class); if (isAnySurveillanceEnabled) { @@ -101,23 +105,30 @@ public static void registerViews(Navigator navigator) { if (isCaseSurveillanceEnabled && UserProvider.getCurrent().hasUserRight(UserRight.LINE_LISTING_CONFIGURE)) { navigator.addView(LineListingConfigurationView.VIEW_NAME, LineListingConfigurationView.class); + firstAccessibleView = firstAccessibleView != null ? firstAccessibleView : LineListingConfigurationView.class; } if (isAnySurveillanceEnabled && UserProvider.getCurrent().hasUserRight(UserRight.DOCUMENT_TEMPLATE_MANAGEMENT)) { navigator.addView(DocumentTemplatesView.VIEW_NAME, DocumentTemplatesView.class); + firstAccessibleView = firstAccessibleView != null ? firstAccessibleView : DocumentTemplatesView.class; } if (UiUtil.permitted(FeatureType.EXTERNAL_EMAILS, UserRight.EMAIL_TEMPLATE_MANAGEMENT)) { navigator.addView(EmailTemplatesView.VIEW_NAME, EmailTemplatesView.class); + firstAccessibleView = firstAccessibleView != null ? firstAccessibleView : EmailTemplatesView.class; } if (UserProvider.getCurrent().hasUserRight(UserRight.CUSTOMIZABLE_ENUM_MANAGEMENT)) { navigator.addView(CustomizableEnumValuesView.VIEW_NAME, CustomizableEnumValuesView.class); + firstAccessibleView = firstAccessibleView != null ? firstAccessibleView : CustomizableEnumValuesView.class; } if (FacadeProvider.getConfigFacade().isDevMode() && UserProvider.getCurrent().hasUserRight(UserRight.DEV_MODE)) { navigator.addView(DevModeView.VIEW_NAME, DevModeView.class); + firstAccessibleView = firstAccessibleView != null ? firstAccessibleView : DevModeView.class; } + + return firstAccessibleView; } @Override diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/customizableenum/CustomizableEnumValueEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/customizableenum/CustomizableEnumValueEditForm.java index fb35ec99b0d..bdd39831f5e 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/customizableenum/CustomizableEnumValueEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/customizableenum/CustomizableEnumValueEditForm.java @@ -16,6 +16,7 @@ package de.symeda.sormas.ui.configuration.customizableenum; import static de.symeda.sormas.ui.utils.LayoutUtil.fluidRowLocs; +import static de.symeda.sormas.ui.utils.LayoutUtil.fluidRowLocsCss; import static java.util.function.Predicate.not; import java.lang.reflect.InvocationTargetException; @@ -25,6 +26,7 @@ import org.apache.commons.collections.CollectionUtils; +import com.vaadin.v7.ui.CheckBox; import com.vaadin.v7.ui.ComboBox; import de.symeda.sormas.api.Disease; @@ -34,6 +36,7 @@ import de.symeda.sormas.api.utils.fieldaccess.UiFieldAccessCheckers; import de.symeda.sormas.api.utils.fieldvisibility.FieldVisibilityCheckers; import de.symeda.sormas.ui.utils.AbstractEditForm; +import de.symeda.sormas.ui.utils.CssStyles; import de.symeda.sormas.ui.utils.components.CheckboxSet; import de.symeda.sormas.ui.utils.components.CustomizableEnumPropertiesComponent; import de.symeda.sormas.ui.utils.components.CustomizableEnumTranslationComponent; @@ -47,7 +50,8 @@ public class CustomizableEnumValueEditForm extends AbstractEditForm dataTypeFilter; private ComboBox diseaseFilter; + private ComboBox relevanceStatusFilter; private final CustomizableEnumCriteria criteria; private final CustomizableEnumValuesGrid grid; @@ -63,6 +65,9 @@ public CustomizableEnumValuesView() { grid = new CustomizableEnumValuesGrid(criteria); VerticalLayout gridLayout = new VerticalLayout(); gridLayout.addComponent(createFilterBar()); + setUpRelevanceStatusFilter(); + gridLayout.addComponent(relevanceStatusFilter); + gridLayout.setComponentAlignment(relevanceStatusFilter, Alignment.MIDDLE_RIGHT); gridLayout.addComponent(grid); gridLayout.setMargin(true); gridLayout.setSpacing(false); @@ -128,6 +133,21 @@ private HorizontalLayout createFilterBar() { return filterLayout; } + private void setUpRelevanceStatusFilter() { + + relevanceStatusFilter = new ComboBox<>(); + relevanceStatusFilter.setId("relevanceStatus"); + relevanceStatusFilter.setWidth(210, Unit.PIXELS); + relevanceStatusFilter.setEmptySelectionAllowed(false); + relevanceStatusFilter.setItems(Boolean.TRUE, Boolean.FALSE); + relevanceStatusFilter.setItemCaptionGenerator( + item -> I18nProperties.getCaption(item ? Captions.customizableEnumValueActiveValues : Captions.customizableEnumValueInactiveValues)); + relevanceStatusFilter.addValueChangeListener(e -> { + criteria.active(e.getValue()); + navigateTo(criteria); + }); + } + @Override public void enter(ViewChangeListener.ViewChangeEvent event) { @@ -149,6 +169,10 @@ public void updateFilterComponents() { dataTypeFilter.setValue(criteria.getDataType()); diseaseFilter.setValue(criteria.getDisease()); + if (relevanceStatusFilter != null) { + relevanceStatusFilter.setValue(criteria.getActive()); + } + applyingCriteria = false; } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/CommunitiesGrid.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/CommunitiesGrid.java index 556473e8637..62a3d4bffbc 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/CommunitiesGrid.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/CommunitiesGrid.java @@ -20,12 +20,12 @@ import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.feature.FeatureType; -import de.symeda.sormas.api.feature.FeatureTypeProperty; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.infrastructure.community.CommunityCriteria; import de.symeda.sormas.api.infrastructure.community.CommunityDto; import de.symeda.sormas.api.user.UserRight; import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.ViewModelProviders; import de.symeda.sormas.ui.utils.BooleanRenderer; @@ -57,8 +57,7 @@ public CommunitiesGrid(CommunityCriteria criteria) { CommunityDto.REGION, CommunityDto.DISTRICT, CommunityDto.EXTERNAL_ID }; - if (FacadeProvider.getFeatureConfigurationFacade() - .isPropertyValueTrue(FeatureType.CASE_SURVEILANCE, FeatureTypeProperty.HIDE_JURISDICTION_FIELDS)) { + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { columns = ArrayUtils.add(columns, CommunityDto.DEFAULT_INFRASTRUCTURE); } setColumns(columns); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/CommunityEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/CommunityEditForm.java index 3fe257eaec5..85f012a93fa 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/CommunityEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/CommunityEditForm.java @@ -26,13 +26,13 @@ import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.feature.FeatureType; -import de.symeda.sormas.api.feature.FeatureTypeProperty; import de.symeda.sormas.api.infrastructure.InfrastructureDtoWithDefault; import de.symeda.sormas.api.infrastructure.community.CommunityDto; import de.symeda.sormas.api.infrastructure.district.DistrictDto; import de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto; import de.symeda.sormas.api.infrastructure.region.RegionDto; import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.utils.AbstractEditForm; import de.symeda.sormas.ui.utils.FieldHelper; @@ -68,8 +68,7 @@ protected void addFields() { ComboBox district = addInfrastructureField(CommunityDto.DISTRICT); addField(RegionDto.EXTERNAL_ID, TextField.class); - if (FacadeProvider.getFeatureConfigurationFacade() - .isPropertyValueTrue(FeatureType.CASE_SURVEILANCE, FeatureTypeProperty.HIDE_JURISDICTION_FIELDS)) { + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { addField(InfrastructureDtoWithDefault.DEFAULT_INFRASTRUCTURE, CheckBox.class); } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/DistrictEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/DistrictEditForm.java index c08f03bef7d..3e3bd9ea099 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/DistrictEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/DistrictEditForm.java @@ -25,10 +25,10 @@ import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.feature.FeatureType; -import de.symeda.sormas.api.feature.FeatureTypeProperty; import de.symeda.sormas.api.infrastructure.InfrastructureDtoWithDefault; import de.symeda.sormas.api.infrastructure.district.DistrictDto; import de.symeda.sormas.api.infrastructure.region.RegionDto; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.utils.AbstractEditForm; public class DistrictEditForm extends AbstractEditForm { @@ -63,8 +63,7 @@ protected void addFields() { ComboBox region = addInfrastructureField(DistrictDto.REGION); addField(RegionDto.EXTERNAL_ID, TextField.class); - if (FacadeProvider.getFeatureConfigurationFacade() - .isPropertyValueTrue(FeatureType.CASE_SURVEILANCE, FeatureTypeProperty.HIDE_JURISDICTION_FIELDS)) { + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { addField(InfrastructureDtoWithDefault.DEFAULT_INFRASTRUCTURE, CheckBox.class); } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/DistrictsGrid.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/DistrictsGrid.java index 2e76f694170..b9964c80ad2 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/DistrictsGrid.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/DistrictsGrid.java @@ -20,12 +20,12 @@ import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.feature.FeatureType; -import de.symeda.sormas.api.feature.FeatureTypeProperty; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.infrastructure.district.DistrictCriteria; import de.symeda.sormas.api.infrastructure.district.DistrictIndexDto; import de.symeda.sormas.api.user.UserRight; import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.ViewModelProviders; import de.symeda.sormas.ui.utils.BooleanRenderer; @@ -59,8 +59,7 @@ public DistrictsGrid(DistrictCriteria criteria) { DistrictIndexDto.EXTERNAL_ID, DistrictIndexDto.POPULATION, DistrictIndexDto.GROWTH_RATE }; - if (FacadeProvider.getFeatureConfigurationFacade() - .isPropertyValueTrue(FeatureType.CASE_SURVEILANCE, FeatureTypeProperty.HIDE_JURISDICTION_FIELDS)) { + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { columns = ArrayUtils.add(columns, DistrictIndexDto.DEFAULT_INFRASTRUCTURE); } setColumns(columns); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/RegionEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/RegionEditForm.java index ab78ec0248f..c44e4c8ad6c 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/RegionEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/RegionEditForm.java @@ -29,11 +29,11 @@ import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.feature.FeatureType; -import de.symeda.sormas.api.feature.FeatureTypeProperty; import de.symeda.sormas.api.infrastructure.InfrastructureDtoWithDefault; import de.symeda.sormas.api.infrastructure.region.RegionDto; import de.symeda.sormas.api.utils.fieldaccess.UiFieldAccessCheckers; import de.symeda.sormas.api.utils.fieldvisibility.FieldVisibilityCheckers; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.utils.AbstractEditForm; import de.symeda.sormas.ui.utils.FieldHelper; @@ -84,8 +84,7 @@ protected void addFields() { ComboBox area = addInfrastructureField(RegionDto.AREA); addField(RegionDto.EXTERNAL_ID, TextField.class); - if (FacadeProvider.getFeatureConfigurationFacade() - .isPropertyValueTrue(FeatureType.CASE_SURVEILANCE, FeatureTypeProperty.HIDE_JURISDICTION_FIELDS)) { + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { addField(InfrastructureDtoWithDefault.DEFAULT_INFRASTRUCTURE, CheckBox.class); } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/RegionsGrid.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/RegionsGrid.java index a2149b0d02e..e3972d0690d 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/RegionsGrid.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/configuration/infrastructure/RegionsGrid.java @@ -20,12 +20,12 @@ import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.feature.FeatureType; -import de.symeda.sormas.api.feature.FeatureTypeProperty; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.infrastructure.region.RegionCriteria; import de.symeda.sormas.api.infrastructure.region.RegionIndexDto; import de.symeda.sormas.api.user.UserRight; import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.ViewModelProviders; import de.symeda.sormas.ui.utils.BooleanRenderer; @@ -64,8 +64,7 @@ public RegionsGrid(RegionCriteria criteria) { RegionIndexDto.EXTERNAL_ID, RegionIndexDto.POPULATION, RegionIndexDto.GROWTH_RATE); - if (FacadeProvider.getFeatureConfigurationFacade() - .isPropertyValueTrue(FeatureType.CASE_SURVEILANCE, FeatureTypeProperty.HIDE_JURISDICTION_FIELDS)) { + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { columns = ArrayUtils.add(columns, RegionIndexDto.DEFAULT_INFRASTRUCTURE); } setColumns(columns); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactCreateForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactCreateForm.java index cb2fb57eede..4acfd04d07b 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactCreateForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactCreateForm.java @@ -43,6 +43,7 @@ import de.symeda.sormas.api.contact.ContactDto; import de.symeda.sormas.api.contact.ContactProximity; import de.symeda.sormas.api.contact.ContactRelation; +import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; @@ -52,6 +53,7 @@ import de.symeda.sormas.api.utils.DataHelper; import de.symeda.sormas.api.utils.fieldvisibility.FieldVisibilityCheckers; import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.person.PersonCreateForm; import de.symeda.sormas.ui.utils.AbstractEditForm; import de.symeda.sormas.ui.utils.ButtonHelper; @@ -112,6 +114,10 @@ public class ContactCreateForm extends AbstractEditForm { ComboBox relationToCase; AdoptAddressLayout adoptAddressLayout; + ComboBox region; + ComboBox district; + ComboBox community; + private final boolean showPersonSearchButton; /** @@ -151,9 +157,9 @@ protected void addFields() { getContent().addComponent(personCreateForm, ContactDto.PERSON); addField(ContactDto.RETURNING_TRAVELER, NullableOptionGroup.class); - ComboBox region = addInfrastructureField(ContactDto.REGION); - ComboBox district = addInfrastructureField(ContactDto.DISTRICT); - ComboBox community = addInfrastructureField(ContactDto.COMMUNITY); + region = addInfrastructureField(ContactDto.REGION); + district = addInfrastructureField(ContactDto.DISTRICT); + community = addInfrastructureField(ContactDto.COMMUNITY); multiDayContact = addField(ContactDto.MULTI_DAY_CONTACT, CheckBox.class); firstContactDate = addField(ContactDto.FIRST_CONTACT_DATE, DateField.class); @@ -183,7 +189,6 @@ protected void addFields() { relationToCase = addField(ContactDto.RELATION_TO_CASE, ComboBox.class); addField(ContactDto.RELATION_DESCRIPTION, TextField.class); - adoptAddressLayout = new AdoptAddressLayout(); adoptAddressLayout.setVisible(false); getContent().addComponent(adoptAddressLayout, ADOPT_ADDRESS_LOC); @@ -357,6 +362,16 @@ private void updateContactProximity() { contactProximity.setValue(value); } + private void hideAndFillJurisdictionFields() { + + region.setVisible(false); + region.setValue(FacadeProvider.getRegionFacade().getDefaultInfrastructureReference()); + district.setVisible(false); + district.setValue(FacadeProvider.getDistrictFacade().getDefaultInfrastructureReference()); + community.setVisible(false); + community.setValue(FacadeProvider.getCommunityFacade().getDefaultInfrastructureReference()); + } + @Override protected String createHtmlLayout() { return HTML_LAYOUT; @@ -387,6 +402,10 @@ public void setValue(ContactDto newFieldValue) { super.setValue(newFieldValue); updateDateComparison(); adoptAddressLayout.setContact(newFieldValue); + + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + hideAndFillJurisdictionFields(); + } } private void updateDateComparison() { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactDataForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactDataForm.java index 0a9fa4fc9a6..a880637b5c9 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactDataForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactDataForm.java @@ -126,7 +126,7 @@ public class ContactDataForm extends AbstractEditForm { fluidRowLocs(ContactDto.UUID) + fluidRowLocs(ContactDto.EXTERNAL_ID, ContactDto.EXTERNAL_TOKEN) + fluidRowLocs(ContactDto.INTERNAL_TOKEN, EXTERNAL_TOKEN_WARNING_LOC) + - fluidRowLocs(ContactDto.REPORTING_USER, ContactDto.REPORT_DATE_TIME, ContactDto.REPORTING_DISTRICT) + + fluidRowLocs(3, ContactDto.REPORTING_USER, 4, ContactDto.REPORT_DATE_TIME, 4,ContactDto.REPORTING_DISTRICT, 1, "") + fluidRowLocs(ContactDto.REGION, ContactDto.DISTRICT, ContactDto.COMMUNITY) + fluidRowLocs(ContactDto.RETURNING_TRAVELER, ContactDto.CASE_ID_EXTERNAL_SYSTEM) + loc(ContactDto.CASE_OR_EVENT_INFORMATION) + @@ -170,7 +170,9 @@ public class ContactDataForm extends AbstractEditForm { private final ViewMode viewMode; private final Disease disease; private NullableOptionGroup contactProximity; + private ComboBox region; private ComboBox district; + private ComboBox community; private UserField contactOfficerField; private Field quarantine; private DateField quarantineFrom; @@ -465,11 +467,11 @@ protected void addFields() { contactOfficerField = addField(ContactDto.CONTACT_OFFICER, UserField.class); contactOfficerField.setEnabled(true); - ComboBox region = addInfrastructureField(ContactDto.REGION); + region = addInfrastructureField(ContactDto.REGION); region.setDescription(I18nProperties.getPrefixDescription(ContactDto.I18N_PREFIX, ContactDto.REGION)); district = addInfrastructureField(ContactDto.DISTRICT); district.setDescription(I18nProperties.getPrefixDescription(ContactDto.I18N_PREFIX, ContactDto.DISTRICT)); - ComboBox community = addInfrastructureField(ContactDto.COMMUNITY); + community = addInfrastructureField(ContactDto.COMMUNITY); community.setDescription(I18nProperties.getPrefixDescription(ContactDto.I18N_PREFIX, ContactDto.COMMUNITY)); region.addValueChangeListener(e -> { RegionReferenceDto regionDto = (RegionReferenceDto) e.getProperty().getValue(); @@ -1037,6 +1039,12 @@ private void updateDateComparison() { } } + private void hideJurisdictionFields() { + region.setVisible(false); + district.setVisible(false); + community.setVisible(false); + } + @Override public void setValue(ContactDto newFieldValue) throws ReadOnlyException, Converter.ConversionException { super.setValue(newFieldValue); @@ -1054,6 +1062,10 @@ public void setValue(ContactDto newFieldValue) throws ReadOnlyException, Convert updateOverwriteFollowUpUntil(); updateFollowUpStatusComponents(); + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + hideJurisdictionFields(); + } + // HACK: Binding to the fields will call field listeners that may clear/modify the values of other fields. // this hopefully resets everything to its correct value discard(); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactGridDetailed.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactGridDetailed.java index 140682a5a13..1bdfe889b89 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactGridDetailed.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactGridDetailed.java @@ -10,6 +10,7 @@ import de.symeda.sormas.api.caze.CaseReferenceDto; import de.symeda.sormas.api.contact.ContactCriteria; import de.symeda.sormas.api.contact.ContactIndexDetailedDto; +import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.user.UserRight; import de.symeda.sormas.api.utils.SortProperty; import de.symeda.sormas.ui.ControllerProvider; @@ -77,7 +78,11 @@ protected void initColumns() { getColumn(ContactIndexDetailedDto.SEX).setWidth(80); getColumn(ContactIndexDetailedDto.APPROXIMATE_AGE).setWidth(50); - getColumn(ContactIndexDetailedDto.DISTRICT_NAME).setWidth(150); + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + getColumn(ContactIndexDetailedDto.DISTRICT_NAME).setHidden(true); + } else { + getColumn(ContactIndexDetailedDto.DISTRICT_NAME).setWidth(150); + } getColumn(ContactIndexDetailedDto.POSTAL_CODE).setWidth(100); getColumn(ContactIndexDetailedDto.CITY).setWidth(150); getColumn(ContactIndexDetailedDto.STREET).setWidth(150); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactsFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactsFilterForm.java index 5ebb67ffeb7..1cd9747bbe0 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactsFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactsFilterForm.java @@ -99,7 +99,8 @@ protected ContactsFilterForm() { super( ContactCriteria.class, ContactIndexDto.I18N_PREFIX, - FieldVisibilityCheckers.withCountry(FacadeProvider.getConfigFacade().getCountryLocale())); + FieldVisibilityCheckers.withCountry(FacadeProvider.getConfigFacade().getCountryLocale()), + JurisdictionFieldConfig.of(ContactCriteria.REGION, ContactCriteria.DISTRICT, ContactCriteria.COMMUNITY)); } @Override @@ -585,4 +586,5 @@ private List fetchContactResponsiblesByRegion(RegionReferenceD Disease selectedDisease = (Disease) getField(ContactIndexDto.DISEASE).getValue(); return FacadeProvider.getUserFacade().getUsersByRegionAndRights(regionReferenceDto, selectedDisease, UserRight.CONTACT_RESPONSIBLE); } + } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/components/linelisting/sharedinfo/SharedInfoField.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/components/linelisting/sharedinfo/SharedInfoField.java index d554f6fd854..c436bd27445 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/components/linelisting/sharedinfo/SharedInfoField.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/components/linelisting/sharedinfo/SharedInfoField.java @@ -15,11 +15,13 @@ import de.symeda.sormas.api.caze.CaseDataDto; import de.symeda.sormas.api.caze.CaseReferenceDto; import de.symeda.sormas.api.event.EventDto; +import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; import de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto; import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.contact.components.linelisting.CaseSelector; import de.symeda.sormas.ui.utils.CssStyles; @@ -48,7 +50,6 @@ public SharedInfoField(CaseReferenceDto caseReferenceDto, Disease initialDisease region.setItemCaptionGenerator(item -> item.buildCaption()); district.setItemCaptionGenerator(item -> item.buildCaption()); - this.initialDiseaseValue = initialDiseaseValue; } @@ -129,6 +130,13 @@ protected Component initContent() { region.setItems(FacadeProvider.getRegionFacade().getAllActiveByServerCountry()); } + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + region.setVisible(false); + region.setValue(FacadeProvider.getRegionFacade().getDefaultInfrastructureReference()); + district.setVisible(false); + district.setValue(FacadeProvider.getDistrictFacade().getDefaultInfrastructureReference()); + } + return layout; } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/campaigns/CampaignDashboardFilterLayout.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/campaigns/CampaignDashboardFilterLayout.java index 325ac7b102e..fc7d36c78cf 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/campaigns/CampaignDashboardFilterLayout.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/campaigns/CampaignDashboardFilterLayout.java @@ -20,6 +20,7 @@ import de.symeda.sormas.api.campaign.CampaignJurisdictionLevel; import de.symeda.sormas.api.campaign.CampaignPhase; import de.symeda.sormas.api.campaign.CampaignReferenceDto; +import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; @@ -27,6 +28,7 @@ import de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto; import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto; import de.symeda.sormas.api.user.UserDto; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.utils.ComboBoxHelper; import de.symeda.sormas.ui.utils.CssStyles; @@ -151,17 +153,6 @@ private void createJurisdictionFilters(CampaignJurisdictionLevel campaignJurisdi addComponent(districtFilter); dashboardDataProvider.setDistrict((DistrictReferenceDto) districtFilter.getValue()); - if (userRegion != null) { - areaFilter.setValue(userArea); - regionFilter.setValue(userRegion); - areaFilter.setEnabled(false); - regionFilter.setEnabled(false); - if (userDistrict != null) { - districtFilter.setValue(userDistrict); - districtFilter.setEnabled(false); - } - } - campaignJurisdictionGroupByFilter.setCaption(I18nProperties.getCaption(Captions.campaignDiagramGroupBy)); campaignJurisdictionGroupByFilter.setWidth(200, Unit.PIXELS); @@ -188,6 +179,22 @@ private void createJurisdictionFilters(CampaignJurisdictionLevel campaignJurisdi dashboardView.refreshDashboard(); }); addComponent(campaignJurisdictionGroupByFilter); + + if (userRegion != null) { + areaFilter.setValue(userArea); + regionFilter.setValue(userRegion); + areaFilter.setEnabled(false); + regionFilter.setEnabled(false); + if (userDistrict != null) { + districtFilter.setValue(userDistrict); + districtFilter.setEnabled(false); + } + } else if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + areaFilter.setVisible(false); + regionFilter.setVisible(false); + districtFilter.setVisible(false); + campaignJurisdictionGroupByFilter.setVisible(false); + } } private CampaignJurisdictionLevel getJurisdictionBelow(CampaignJurisdictionLevel campaignJurisdictionLevel) { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/components/DashboardFilterLayout.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/components/DashboardFilterLayout.java index 0c80494e7c2..6a71345c4e5 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/components/DashboardFilterLayout.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/components/DashboardFilterLayout.java @@ -44,6 +44,7 @@ import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.Language; import de.symeda.sormas.api.caze.NewCaseDateType; +import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; @@ -52,6 +53,7 @@ import de.symeda.sormas.api.utils.DateFilterOption; import de.symeda.sormas.api.utils.DateHelper; import de.symeda.sormas.api.utils.EpiWeek; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.dashboard.AbstractDashboardDataProvider; import de.symeda.sormas.ui.dashboard.AbstractDashboardView; @@ -135,7 +137,7 @@ protected void createRegionAndDistrictFilter() { } protected void createRegionFilter(String description) { - if (UserProvider.getCurrent().getUser().getRegion() == null) { + if (UserProvider.getCurrent().getUser().getRegion() == null && UiUtil.disabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { regionFilter.setWidth(200, Unit.PIXELS); regionFilter.setInputPrompt(I18nProperties.getString(Strings.promptRegion)); regionFilter.setDescription(description); @@ -151,7 +153,9 @@ protected void createRegionFilter(String description) { } protected void createDistrictFilter(String description) { - if (UserProvider.getCurrent().getUser().getRegion() != null && UserProvider.getCurrent().getUser().getDistrict() == null) { + if (UserProvider.getCurrent().getUser().getRegion() != null + && UserProvider.getCurrent().getUser().getDistrict() == null + && UiUtil.disabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { districtFilter.setWidth(200, Unit.PIXELS); districtFilter.setInputPrompt(I18nProperties.getString(Strings.promptDistrict)); districtFilter.setDescription(description); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/surveillance/components/statistics/summary/DiseaseSummaryComponent.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/surveillance/components/statistics/summary/DiseaseSummaryComponent.java index 6ecf759e214..7990f7ebbaf 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/surveillance/components/statistics/summary/DiseaseSummaryComponent.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/surveillance/components/statistics/summary/DiseaseSummaryComponent.java @@ -6,6 +6,7 @@ import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.dashboard.DashboardDataProvider; import de.symeda.sormas.ui.dashboard.statistics.DashboardStatisticsSubComponent; import de.symeda.sormas.ui.utils.CssStyles; @@ -16,7 +17,7 @@ public class DiseaseSummaryComponent extends DashboardStatisticsSubComponent { private final FatalitiesSummaryElementComponent fatalitiesSummaryElementComponent; // "Outbreak Districts" elements - private final DiseaseSummaryElementComponent lastReportedDistrict; + private DiseaseSummaryElementComponent lastReportedDistrict; private DiseaseSummaryElementComponent outbreakDistrictCount; //"cases in quarantine" elements @@ -33,11 +34,14 @@ public DiseaseSummaryComponent() { fatalitiesSummaryElementComponent = new FatalitiesSummaryElementComponent(); addComponent(fatalitiesSummaryElementComponent); - lastReportedDistrict = - new DiseaseSummaryElementComponent(Strings.headingLastReportedDistrict, I18nProperties.getString(Strings.none).toUpperCase()); - addComponent(lastReportedDistrict); + boolean jurisdictionFieldsVisible = UiUtil.disabled(FeatureType.HIDE_JURISDICTION_FIELDS); + if (jurisdictionFieldsVisible) { + lastReportedDistrict = + new DiseaseSummaryElementComponent(Strings.headingLastReportedDistrict, I18nProperties.getString(Strings.none).toUpperCase()); + addComponent(lastReportedDistrict); + } - if (FacadeProvider.getFeatureConfigurationFacade().isFeatureEnabled(FeatureType.OUTBREAKS)) { + if (UiUtil.enabled(FeatureType.OUTBREAKS) && jurisdictionFieldsVisible) { outbreakDistrictCount = new DiseaseSummaryElementComponent(Strings.headingOutbreakDistricts); addComponent(outbreakDistrictCount); } @@ -62,10 +66,13 @@ public DiseaseSummaryComponent() { public void update(DashboardDataProvider dashboardDataProvider) { fatalitiesSummaryElementComponent.update(dashboardDataProvider.getCases(), dashboardDataProvider.getPreviousCases()); - String district = dashboardDataProvider.getLastReportedDistrict(); - lastReportedDistrict.updateTotalLabel(DataHelper.isNullOrEmpty(district) ? I18nProperties.getString(Strings.none).toUpperCase() : district); + if (lastReportedDistrict != null) { + String district = dashboardDataProvider.getLastReportedDistrict(); + lastReportedDistrict + .updateTotalLabel(DataHelper.isNullOrEmpty(district) ? I18nProperties.getString(Strings.none).toUpperCase() : district); + } - if (FacadeProvider.getFeatureConfigurationFacade().isFeatureEnabled(FeatureType.OUTBREAKS)) { + if (outbreakDistrictCount != null) { outbreakDistrictCount.updateTotalLabel(dashboardDataProvider.getOutbreakDistrictCount().toString()); } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/environment/EnvironmentDataForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/environment/EnvironmentDataForm.java index a7ee73f362c..c9590db9323 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/environment/EnvironmentDataForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/environment/EnvironmentDataForm.java @@ -49,7 +49,7 @@ public class EnvironmentDataForm extends AbstractEditForm { //@formatter:off private static final String HTML_LAYOUT = fluidRowLocs(EnvironmentDto.UUID, EnvironmentDto.EXTERNAL_ID) + - fluidRowLocs(EnvironmentDto.REPORT_DATE, EnvironmentDto.REPORTING_USER) + + fluidRowLocs(6, EnvironmentDto.REPORT_DATE, 3, EnvironmentDto.REPORTING_USER, 3, "") + fluidRowLocs(EnvironmentDto.INVESTIGATION_STATUS, "") + fluidRowLocs(EnvironmentDto.ENVIRONMENT_MEDIA, "") + fluidRowLocs(EnvironmentDto.WATER_TYPE, EnvironmentDto.OTHER_WATER_TYPE) + diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/environment/EnvironmentFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/environment/EnvironmentFilterForm.java index c2171137191..a7db3ada7e6 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/environment/EnvironmentFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/environment/EnvironmentFilterForm.java @@ -61,7 +61,10 @@ public class EnvironmentFilterForm extends AbstractFilterForm(EnvironmentIndexDto.UUID, e -> ControllerProvider.getEnvironmentController().navigateToEnvironment(e.getUuid()))); + new ShowDetailsListener<>( + EnvironmentIndexDto.UUID, + e -> ControllerProvider.getEnvironmentController().navigateToEnvironment(e.getUuid()))); + + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + getColumn(EnvironmentIndexDto.REGION).setHidden(true); + getColumn(EnvironmentIndexDto.DISTRICT).setHidden(true); + getColumn(EnvironmentIndexDto.COMMUNITY).setHidden(true); + } } public void reload() { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventActionFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventActionFilterForm.java index 878e1abaa12..20c82bd3797 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventActionFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventActionFilterForm.java @@ -30,7 +30,7 @@ public class EventActionFilterForm extends AbstractFilterForm { private static final long serialVersionUID = -8661345403078183132L; protected EventActionFilterForm() { - super(ActionCriteria.class, ActionDto.I18N_PREFIX); + super(ActionCriteria.class, ActionDto.I18N_PREFIX, null); } @Override diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventDataForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventDataForm.java index 3d74a002df4..c014d086bfd 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventDataForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventDataForm.java @@ -114,7 +114,7 @@ public class EventDataForm extends AbstractEditForm { //@formatter:off private static final String HTML_LAYOUT = loc(EVENT_DATA_HEADING_LOC) + - fluidRowLocs(4, EventDto.UUID, 3, EventDto.REPORT_DATE_TIME, 5, EventDto.REPORTING_USER) + + fluidRowLocs(4, EventDto.UUID, 3, EventDto.REPORT_DATE_TIME, 3, EventDto.REPORTING_USER, 2, "") + fluidRowLocs(EventDto.EVENT_STATUS, EventDto.EVENT_MANAGEMENT_STATUS) + fluidRowLocs(EventDto.EVENT_IDENTIFICATION_SOURCE) + fluidRowLocs(EventDto.RISK_LEVEL, EventDto.SPECIFIC_RISK) + @@ -228,7 +228,7 @@ protected void addFields() { addField(EventDto.UUID, TextField.class); ComboBox diseaseField = addDiseaseField(EventDto.DISEASE, false, isCreateForm); addField(EventDto.DISEASE_DETAILS, TextField.class); - ComboBox diseaseVariantField = addField(EventDto.DISEASE_VARIANT, ComboBox.class); + ComboBox diseaseVariantField = addCustomizableEnumField(EventDto.DISEASE_VARIANT); diseaseVariantField.setNullSelectionAllowed(true); addFields(EventDto.EXTERNAL_ID); TextField diseaseVariantDetailsField = addField(EventDto.DISEASE_VARIANT_DETAILS, TextField.class); @@ -248,7 +248,7 @@ protected void addFields() { addField(EventDto.EVENT_STATUS, NullableOptionGroup.class); addField(EventDto.RISK_LEVEL); - ComboBox specificRiskField = addField(EventDto.SPECIFIC_RISK, ComboBox.class); + ComboBox specificRiskField = addCustomizableEnumField(EventDto.SPECIFIC_RISK); specificRiskField.setNullSelectionAllowed(true); addField(EventDto.EVENT_MANAGEMENT_STATUS, NullableOptionGroup.class); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventGrid.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventGrid.java index 2c8723b15b8..24042f0aa4e 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventGrid.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventGrid.java @@ -236,6 +236,12 @@ public EventGrid(EventCriteria criteria, Class viewClass) { .setCaption(I18nProperties.getPrefixCaption(EventIndexDto.I18N_PREFIX, EventIndexDto.CONTACT_COUNT)); addItemClickListener(new ShowDetailsListener<>(EventIndexDto.UUID, e -> ControllerProvider.getEventController().navigateToData(e.getUuid()))); + + if (FacadeProvider.getFeatureConfigurationFacade().isFeatureEnabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + getColumn(EventIndexDto.REGION).setHidden(true); + getColumn(EventIndexDto.DISTRICT).setHidden(true); + getColumn(EventIndexDto.COMMUNITY).setHidden(true); + } } public static String createEventDateColumn(FilteredGrid grid) { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventGroupsFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventGroupsFilterForm.java index 1d35b7c6cae..32e79cd7440 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventGroupsFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventGroupsFilterForm.java @@ -10,9 +10,9 @@ import de.symeda.sormas.api.i18n.Descriptions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; -import de.symeda.sormas.api.location.LocationDto; import de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto; import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto; +import de.symeda.sormas.api.location.LocationDto; import de.symeda.sormas.ui.utils.AbstractFilterForm; import de.symeda.sormas.ui.utils.FieldConfiguration; import de.symeda.sormas.ui.utils.FieldHelper; @@ -22,7 +22,10 @@ public class EventGroupsFilterForm extends AbstractFilterForm { @@ -133,6 +136,13 @@ public void setValue(EventParticipantDto newFieldValue) throws ReadOnlyException setRequired(jurisdictionFieldsRequired, EventParticipantDto.REGION, EventParticipantDto.DISTRICT); } + private void hideAndFillJurisdictionFields() { + region.setVisible(false); + region.setValue(FacadeProvider.getRegionFacade().getDefaultInfrastructureReference()); + district.setVisible(false); + district.setValue(FacadeProvider.getDistrictFacade().getDefaultInfrastructureReference()); + } + /** * * @return first name of the person. ATTENTION: For pseudonymised persons, this method may return an empty string! @@ -181,4 +191,13 @@ protected void enablePersonFields(Boolean enable) { getField(PersonDto.LAST_NAME).setEnabled(enable); getField(PersonDto.SEX).setEnabled(enable); } + + @Override + protected void setInternalValue(EventParticipantDto newValue) { + super.setInternalValue(newValue); + + if (FacadeProvider.getFeatureConfigurationFacade().isFeatureEnabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + hideAndFillJurisdictionFields(); + } + } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventParticipantEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventParticipantEditForm.java index 5033c2f6197..bf83e485ca9 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventParticipantEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventParticipantEditForm.java @@ -28,6 +28,7 @@ import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.event.EventDto; import de.symeda.sormas.api.event.EventParticipantDto; +import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto; import de.symeda.sormas.api.location.LocationDto; @@ -45,7 +46,7 @@ public class EventParticipantEditForm extends AbstractEditForm { @@ -107,6 +110,11 @@ protected void addFields() { setVisible(false, EventParticipantDto.DELETION_REASON, EventParticipantDto.OTHER_DELETION_REASON); } + private void hideJurisdictionFields() { + region.setVisible(false); + district.setVisible(false); + } + @Override protected String createHtmlLayout() { return HTML_LAYOUT; @@ -117,4 +125,13 @@ public void setValue(EventParticipantDto newFieldValue) throws ReadOnlyException super.setValue(newFieldValue); } + @Override + protected void setInternalValue(EventParticipantDto newValue) { + super.setInternalValue(newValue); + + if (FacadeProvider.getFeatureConfigurationFacade().isFeatureEnabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + hideJurisdictionFields(); + } + } + } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventParticipantsFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventParticipantsFilterForm.java index 641ee00d18b..6db5c41783a 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventParticipantsFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventParticipantsFilterForm.java @@ -21,7 +21,7 @@ public class EventParticipantsFilterForm extends AbstractFilterForm { protected EventParticipantsFilterForm() { - super(EventParticipantCriteria.class, EventParticipantIndexDto.I18N_PREFIX); + super(EventParticipantCriteria.class, EventParticipantIndexDto.I18N_PREFIX, null); } @Override @@ -39,7 +39,11 @@ protected String[] getMainFilterLocators() { @Override protected void addFields() { - addBirthDateFields(getContent(), EventParticipantCriteria.BIRTHDATE_YYYY, EventParticipantCriteria.BIRTHDATE_MM, EventParticipantCriteria.BIRTHDATE_DD); + addBirthDateFields( + getContent(), + EventParticipantCriteria.BIRTHDATE_YYYY, + EventParticipantCriteria.BIRTHDATE_MM, + EventParticipantCriteria.BIRTHDATE_DD); addField( FieldConfiguration.withCaptionAndPixelSized( diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventsFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventsFilterForm.java index 75523aa2e99..bedb8d8f196 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventsFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventsFilterForm.java @@ -125,7 +125,8 @@ protected EventsFilterForm(boolean hideEventStatusFilter, boolean hideActionFilt super( EventCriteria.class, EventIndexDto.I18N_PREFIX, - FieldVisibilityCheckers.withCountry(FacadeProvider.getConfigFacade().getCountryLocale())); + FieldVisibilityCheckers.withCountry(FacadeProvider.getConfigFacade().getCountryLocale()), + JurisdictionFieldConfig.of(LocationDto.REGION, LocationDto.DISTRICT, LocationDto.COMMUNITY)); this.hideEventStatusFilter = hideEventStatusFilter; this.hideActionFilters = hideActionFilters; @@ -468,23 +469,21 @@ protected void applyDependenciesOnFieldChange(String propertyId, Property.ValueC @Override protected void applyRegionFilterDependency(RegionReferenceDto region, String districtFieldId) { - final ComboBox districtField = getField(districtFieldId); if (region != null) { - FieldHelper.updateItems(districtField, FacadeProvider.getDistrictFacade().getAllActiveByRegion(region.getUuid())); - districtField.setEnabled(true); + FieldHelper.updateItems(districtFilter, FacadeProvider.getDistrictFacade().getAllActiveByRegion(region.getUuid())); + districtFilter.setEnabled(true); } else { - districtField.setEnabled(false); + districtFilter.setEnabled(false); } } @Override protected void applyDistrictDependency(DistrictReferenceDto district, String communityFieldId) { - final ComboBox communityField = getField(communityFieldId); if (district != null) { - FieldHelper.updateItems(communityField, FacadeProvider.getCommunityFacade().getAllActiveByDistrict(district.getUuid())); - communityField.setEnabled(true); + FieldHelper.updateItems(communityFilter, FacadeProvider.getCommunityFacade().getAllActiveByDistrict(district.getUuid())); + communityFilter.setEnabled(true); } else { - communityField.setEnabled(false); + communityFilter.setEnabled(false); } } @@ -560,8 +559,8 @@ private void applyDateDependencyOnNewValue(String componentId, DateFilterOption private void applyFacilityFieldsDependencies() { applyFacilityFieldsDependencies( (TypeOfPlace) getField(EventDto.TYPE_OF_PLACE).getValue(), - (DistrictReferenceDto) getField(LocationDto.DISTRICT).getValue(), - (CommunityReferenceDto) getField(LocationDto.COMMUNITY).getValue()); + (DistrictReferenceDto) districtFilter.getValue(), + (CommunityReferenceDto) communityFilter.getValue()); } private void applyFacilityFieldsDependencies( @@ -586,9 +585,7 @@ private void applyFacilityFieldsDependencies( } private void updateResponsibleUserFieldItems() { - updateResponsibleUserFieldItems( - (DistrictReferenceDto) getField(EventCriteria.DISTRICT).getValue(), - (RegionReferenceDto) getField(EventCriteria.REGION).getValue()); + updateResponsibleUserFieldItems((DistrictReferenceDto) districtFilter.getValue(), (RegionReferenceDto) regionFilter.getValue()); } private void updateResponsibleUserFieldItems(DistrictReferenceDto district, RegionReferenceDto region) { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/eventParticipantsLineListing/layout/LineListingLayout.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/eventParticipantsLineListing/layout/LineListingLayout.java index 6c0778110a8..b99c18a3228 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/eventParticipantsLineListing/layout/LineListingLayout.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/eventParticipantsLineListing/layout/LineListingLayout.java @@ -23,6 +23,7 @@ import de.symeda.sormas.api.caze.CaseDataDto; import de.symeda.sormas.api.event.EventDto; import de.symeda.sormas.api.event.EventParticipantDto; +import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; @@ -30,6 +31,7 @@ import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto; import de.symeda.sormas.api.person.PersonDto; import de.symeda.sormas.api.utils.ValidationRuntimeException; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.utils.ButtonHelper; import de.symeda.sormas.ui.utils.CssStyles; @@ -102,6 +104,12 @@ public LineListingLayout(Window window, EventDto eventDto) { region.setItems(FacadeProvider.getRegionFacade().getAllActiveByServerCountry()); } + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + region.setValue(FacadeProvider.getRegionFacade().getDefaultInfrastructureReference()); + district.setValue(FacadeProvider.getDistrictFacade().getDefaultInfrastructureReference()); + sharedInformationComponent.setVisible(false); + } + HorizontalLayout actionBar = new HorizontalLayout(); Button addLine = ButtonHelper.createIconButton(Captions.lineListingAddLine, VaadinIcons.PLUS, e -> { EventParticipantLineLayout newLine = buildNewLine(lineComponent); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/ExternalMessageGridFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/ExternalMessageGridFilterForm.java index a9b327ba818..587d2adae04 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/ExternalMessageGridFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/ExternalMessageGridFilterForm.java @@ -57,7 +57,7 @@ public class ExternalMessageGridFilterForm extends AbstractFilterForm we weekAndDateFilter.setNotificationsForMissingFilters(); } } - } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/form/ImmunizationCreationForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/form/ImmunizationCreationForm.java index cce3247405b..f8d955c3ee1 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/form/ImmunizationCreationForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/form/ImmunizationCreationForm.java @@ -35,6 +35,7 @@ import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; @@ -53,6 +54,7 @@ import de.symeda.sormas.api.person.PersonReferenceDto; import de.symeda.sormas.api.travelentry.TravelEntryDto; import de.symeda.sormas.api.utils.fieldvisibility.FieldVisibilityCheckers; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.person.PersonCreateForm; import de.symeda.sormas.ui.utils.AbstractEditForm; import de.symeda.sormas.ui.utils.ComboBoxHelper; @@ -91,6 +93,9 @@ public class ImmunizationCreationForm extends AbstractEditForm private final PersonReferenceDto personDto; private final Disease disease; + private ComboBox responsibleRegion; + private ComboBox responsibleDistrict; + private ComboBox responsibleCommunity; public ImmunizationCreationForm() { this(null, null); @@ -143,15 +148,15 @@ protected void addFields() { jurisdictionHeadingLabel.addStyleName(H3); getContent().addComponent(jurisdictionHeadingLabel, RESPONSIBLE_JURISDICTION_HEADING_LOC); - ComboBox responsibleRegion = addInfrastructureField(ImmunizationDto.RESPONSIBLE_REGION); + responsibleRegion = addInfrastructureField(ImmunizationDto.RESPONSIBLE_REGION); responsibleRegion.setRequired(true); - ComboBox responsibleDistrictCombo = addInfrastructureField(ImmunizationDto.RESPONSIBLE_DISTRICT); - responsibleDistrictCombo.setRequired(true); - ComboBox responsibleCommunityCombo = addInfrastructureField(ImmunizationDto.RESPONSIBLE_COMMUNITY); - responsibleCommunityCombo.setNullSelectionAllowed(true); - responsibleCommunityCombo.addStyleName(SOFT_REQUIRED); + responsibleDistrict = addInfrastructureField(ImmunizationDto.RESPONSIBLE_DISTRICT); + responsibleDistrict.setRequired(true); + responsibleCommunity = addInfrastructureField(ImmunizationDto.RESPONSIBLE_COMMUNITY); + responsibleCommunity.setNullSelectionAllowed(true); + responsibleCommunity.addStyleName(SOFT_REQUIRED); - InfrastructureFieldsHelper.initInfrastructureFields(responsibleRegion, responsibleDistrictCombo, responsibleCommunityCombo); + InfrastructureFieldsHelper.initInfrastructureFields(responsibleRegion, responsibleDistrict, responsibleCommunity); ComboBox facilityTypeGroup = ComboBoxHelper.createComboBoxV7(); facilityTypeGroup.setId("typeGroup"); @@ -256,7 +261,7 @@ protected void addFields() { } }); - responsibleDistrictCombo.addValueChangeListener(e -> { + responsibleDistrict.addValueChangeListener(e -> { FieldHelper.removeItems(facilityCombo); DistrictReferenceDto districtDto = (DistrictReferenceDto) e.getProperty().getValue(); if (districtDto != null && facilityType.getValue() != null) { @@ -267,7 +272,7 @@ protected void addFields() { } }); - responsibleCommunityCombo.addValueChangeListener(e -> { + responsibleCommunity.addValueChangeListener(e -> { FieldHelper.removeItems(facilityCombo); CommunityReferenceDto communityDto = (CommunityReferenceDto) e.getProperty().getValue(); if (facilityType.getValue() != null) { @@ -276,10 +281,10 @@ protected void addFields() { communityDto != null ? FacadeProvider.getFacilityFacade() .getActiveFacilitiesByCommunityAndType(communityDto, (FacilityType) facilityType.getValue(), true, false) - : responsibleDistrictCombo.getValue() != null + : responsibleDistrict.getValue() != null ? FacadeProvider.getFacilityFacade() .getActiveFacilitiesByDistrictAndType( - (DistrictReferenceDto) responsibleDistrictCombo.getValue(), + (DistrictReferenceDto) responsibleDistrict.getValue(), (FacilityType) facilityType.getValue(), true, false) @@ -293,13 +298,13 @@ protected void addFields() { }); facilityType.addValueChangeListener(e -> { FieldHelper.removeItems(facilityCombo); - if (facilityType.getValue() != null && responsibleDistrictCombo.getValue() != null) { - if (responsibleCommunityCombo.getValue() != null) { + if (facilityType.getValue() != null && responsibleDistrict.getValue() != null) { + if (responsibleCommunity.getValue() != null) { FieldHelper.updateItems( facilityCombo, FacadeProvider.getFacilityFacade() .getActiveFacilitiesByCommunityAndType( - (CommunityReferenceDto) responsibleCommunityCombo.getValue(), + (CommunityReferenceDto) responsibleCommunity.getValue(), (FacilityType) facilityType.getValue(), true, false)); @@ -308,7 +313,7 @@ protected void addFields() { facilityCombo, FacadeProvider.getFacilityFacade() .getActiveFacilitiesByDistrictAndType( - (DistrictReferenceDto) responsibleDistrictCombo.getValue(), + (DistrictReferenceDto) responsibleDistrict.getValue(), (FacilityType) facilityType.getValue(), true, false)); @@ -363,6 +368,17 @@ private void updateFacilityFields(ComboBox cbFacility, TextField tfFacilityDetai } } + private void hideAndFillJurisdictionFields() { + + getContent().getComponent(RESPONSIBLE_JURISDICTION_HEADING_LOC).setVisible(false); + responsibleRegion.setVisible(false); + responsibleRegion.setValue(FacadeProvider.getRegionFacade().getDefaultInfrastructureReference()); + responsibleDistrict.setVisible(false); + responsibleDistrict.setValue(FacadeProvider.getDistrictFacade().getDefaultInfrastructureReference()); + responsibleCommunity.setVisible(false); + responsibleCommunity.setValue(FacadeProvider.getCommunityFacade().getDefaultInfrastructureReference()); + } + public PersonDto getPerson() { PersonDto person = PersonDto.build(); personCreateForm.transferDataToPerson(person); @@ -381,4 +397,13 @@ public ImmunizationDto getValue() { immunizationDto.setImmunizationStatus((ImmunizationStatus) getField(ImmunizationDto.IMMUNIZATION_STATUS).getValue()); return immunizationDto; } + + @Override + protected void setInternalValue(ImmunizationDto newValue) { + super.setInternalValue(newValue); + + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + hideAndFillJurisdictionFields(); + } + } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/form/ImmunizationDataForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/form/ImmunizationDataForm.java index fa77448eb17..d720c609f87 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/form/ImmunizationDataForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/form/ImmunizationDataForm.java @@ -49,6 +49,7 @@ import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.caze.CaseDataDto; import de.symeda.sormas.api.caze.CaseReferenceDto; +import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.Descriptions; import de.symeda.sormas.api.i18n.I18nProperties; @@ -70,6 +71,7 @@ import de.symeda.sormas.ui.ControllerProvider; import de.symeda.sormas.ui.SearchSpecificLayout; import de.symeda.sormas.ui.SormasUI; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.utils.AbstractEditForm; import de.symeda.sormas.ui.utils.ButtonHelper; @@ -98,7 +100,7 @@ public class ImmunizationDataForm extends AbstractEditForm { //@formatter:off private static final String HTML_LAYOUT = fluidRowLocs(ImmunizationDto.UUID, ImmunizationDto.EXTERNAL_ID) - + fluidRowLocs(ImmunizationDto.REPORT_DATE, ImmunizationDto.REPORTING_USER) + + fluidRowLocs(6, ImmunizationDto.REPORT_DATE, 3,ImmunizationDto.REPORTING_USER, 3, "") + fluidRowLocs(ImmunizationDto.DISEASE, ImmunizationDto.DISEASE_DETAILS) + fluidRowLocs(ImmunizationDto.MEANS_OF_IMMUNIZATION, ImmunizationDto.MEANS_OF_IMMUNIZATION_DETAILS) + fluidRowLocs(OVERWRITE_IMMUNIZATION_MANAGEMENT_STATUS) @@ -128,6 +130,9 @@ public class ImmunizationDataForm extends AbstractEditForm { private CheckBox overwriteImmunizationManagementStatus; private ComboBoxWithPlaceholder facilityTypeGroup; private final Consumer actionCallback; + private ComboBox responsibleRegion; + private ComboBox responsibleDistrict; + private ComboBox responsibleCommunity; public ImmunizationDataForm(boolean isPseudonymized, boolean inJurisdiction, CaseReferenceDto relatedCase, Consumer actionCallback) { super( @@ -191,15 +196,15 @@ protected void addFields() { jurisdictionHeadingLabel.addStyleName(H3); getContent().addComponent(jurisdictionHeadingLabel, RESPONSIBLE_JURISDICTION_HEADING_LOC); - ComboBox responsibleRegion = addInfrastructureField(ImmunizationDto.RESPONSIBLE_REGION); + responsibleRegion = addInfrastructureField(ImmunizationDto.RESPONSIBLE_REGION); responsibleRegion.setRequired(true); - ComboBox responsibleDistrictCombo = addInfrastructureField(ImmunizationDto.RESPONSIBLE_DISTRICT); - responsibleDistrictCombo.setRequired(true); - ComboBox responsibleCommunityCombo = addInfrastructureField(ImmunizationDto.RESPONSIBLE_COMMUNITY); - responsibleCommunityCombo.setNullSelectionAllowed(true); - responsibleCommunityCombo.addStyleName(SOFT_REQUIRED); + responsibleDistrict = addInfrastructureField(ImmunizationDto.RESPONSIBLE_DISTRICT); + responsibleDistrict.setRequired(true); + responsibleCommunity = addInfrastructureField(ImmunizationDto.RESPONSIBLE_COMMUNITY); + responsibleCommunity.setNullSelectionAllowed(true); + responsibleCommunity.addStyleName(SOFT_REQUIRED); - InfrastructureFieldsHelper.initInfrastructureFields(responsibleRegion, responsibleDistrictCombo, responsibleCommunityCombo); + InfrastructureFieldsHelper.initInfrastructureFields(responsibleRegion, responsibleDistrict, responsibleCommunity); facilityTypeGroup = ComboBoxHelper.createComboBoxV7(); facilityTypeGroup.setId("typeGroup"); @@ -431,7 +436,7 @@ protected void onCancel() { } }); - responsibleDistrictCombo.addValueChangeListener(e -> { + responsibleDistrict.addValueChangeListener(e -> { FieldHelper.removeItems(facilityCombo); DistrictReferenceDto districtDto = (DistrictReferenceDto) e.getProperty().getValue(); if (districtDto != null && facilityType.getValue() != null) { @@ -442,7 +447,7 @@ protected void onCancel() { } }); - responsibleCommunityCombo.addValueChangeListener(e -> { + responsibleCommunity.addValueChangeListener(e -> { FieldHelper.removeItems(facilityCombo); CommunityReferenceDto communityDto = (CommunityReferenceDto) e.getProperty().getValue(); if (facilityType.getValue() != null) { @@ -451,10 +456,10 @@ protected void onCancel() { communityDto != null ? FacadeProvider.getFacilityFacade() .getActiveFacilitiesByCommunityAndType(communityDto, (FacilityType) facilityType.getValue(), true, false) - : responsibleDistrictCombo.getValue() != null + : responsibleDistrict.getValue() != null ? FacadeProvider.getFacilityFacade() .getActiveFacilitiesByDistrictAndType( - (DistrictReferenceDto) responsibleDistrictCombo.getValue(), + (DistrictReferenceDto) responsibleDistrict.getValue(), (FacilityType) facilityType.getValue(), true, false) @@ -474,13 +479,13 @@ protected void onCancel() { }); facilityType.addValueChangeListener(e -> { FieldHelper.removeItems(facilityCombo); - if (facilityType.getValue() != null && responsibleDistrictCombo.getValue() != null) { - if (responsibleCommunityCombo.getValue() != null) { + if (facilityType.getValue() != null && responsibleDistrict.getValue() != null) { + if (responsibleCommunity.getValue() != null) { FieldHelper.updateItems( facilityCombo, FacadeProvider.getFacilityFacade() .getActiveFacilitiesByCommunityAndType( - (CommunityReferenceDto) responsibleCommunityCombo.getValue(), + (CommunityReferenceDto) responsibleCommunity.getValue(), (FacilityType) facilityType.getValue(), true, false)); @@ -489,7 +494,7 @@ protected void onCancel() { facilityCombo, FacadeProvider.getFacilityFacade() .getActiveFacilitiesByDistrictAndType( - (DistrictReferenceDto) responsibleDistrictCombo.getValue(), + (DistrictReferenceDto) responsibleDistrict.getValue(), (FacilityType) facilityType.getValue(), true, false)); @@ -583,6 +588,14 @@ private void updateFacilityFields(ComboBox cbFacility, TextField tfFacilityDetai } } + private void hideJurisdictionFields() { + + getContent().getComponent(RESPONSIBLE_JURISDICTION_HEADING_LOC).setVisible(false); + responsibleRegion.setVisible(false); + responsibleDistrict.setVisible(false); + responsibleCommunity.setVisible(false); + } + @Override public void setValue(ImmunizationDto newFieldValue) throws ReadOnlyException, Converter.ConversionException { ignoreMeansOfImmunizationChange = true; @@ -590,6 +603,10 @@ public void setValue(ImmunizationDto newFieldValue) throws ReadOnlyException, Co ignoreMeansOfImmunizationChange = false; previousMeansOfImmunization = newFieldValue.getMeansOfImmunization(); + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + hideJurisdictionFields(); + } + // HACK: Binding to the fields will call field listeners that may clear/modify the values of other fields. // this hopefully resets everything to its correct value discard(); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/grid/ImmunizationGrid.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/grid/ImmunizationGrid.java index 236d1035397..9b54d3fa3b8 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/grid/ImmunizationGrid.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/grid/ImmunizationGrid.java @@ -15,6 +15,7 @@ import de.symeda.sormas.api.person.PersonDto; import de.symeda.sormas.api.person.PersonHelper; import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.immunization.ImmunizationPersonView; import de.symeda.sormas.ui.utils.DateFormatHelper; import de.symeda.sormas.ui.utils.FieldAccessColumnStyleGenerator; @@ -105,6 +106,10 @@ private void initColumns() { .findPrefixCaptionWithDefault(column.getId(), column.getCaption(), ImmunizationIndexDto.I18N_PREFIX, PersonDto.I18N_PREFIX)); column.setStyleGenerator(FieldAccessColumnStyleGenerator.getDefault(getBeanType(), column.getId())); } + + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + getColumn(ImmunizationIndexDto.DISTRICT).setHidden(true); + } } private void setLazyDataProvider() { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/location/LocationEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/location/LocationEditForm.java index 5e8888da8fd..cff65110501 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/location/LocationEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/location/LocationEditForm.java @@ -54,7 +54,6 @@ import de.symeda.sormas.api.EntityRelevanceStatus; import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.feature.FeatureType; -import de.symeda.sormas.api.feature.FeatureTypeProperty; import de.symeda.sormas.api.geo.GeoLatLon; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; @@ -76,6 +75,7 @@ import de.symeda.sormas.api.person.PersonAddressType; import de.symeda.sormas.api.utils.fieldaccess.UiFieldAccessCheckers; import de.symeda.sormas.api.utils.fieldvisibility.FieldVisibilityCheckers; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.map.LeafletMap; import de.symeda.sormas.ui.map.LeafletMarker; import de.symeda.sormas.ui.map.MarkerIcon; @@ -371,8 +371,7 @@ protected void addFields() { FieldHelper.removeItems(facility); // Add a visual indictator reminding the user to select a district - if (!FacadeProvider.getFeatureConfigurationFacade() - .isPropertyValueTrue(FeatureType.CASE_SURVEILANCE, FeatureTypeProperty.HIDE_JURISDICTION_FIELDS)) { + if (UiUtil.disabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { facility.setComponentError(new ErrorMessage() { @Override @@ -604,8 +603,7 @@ public void setValue(LocationDto newFieldValue) throws ReadOnlyException, Conver protected void setInternalValue(LocationDto newValue) { super.setInternalValue(newValue); - if (FacadeProvider.getFeatureConfigurationFacade() - .isPropertyValueTrue(FeatureType.CASE_SURVEILANCE, FeatureTypeProperty.HIDE_JURISDICTION_FIELDS)) { + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { hideAndFillJurisdictionFields(); } } @@ -625,8 +623,7 @@ public void discard() throws SourceException { facility.setComponentError(null); facilityDetails.setValue(locationDto.getFacilityDetails()); - if (FacadeProvider.getFeatureConfigurationFacade() - .isPropertyValueTrue(FeatureType.CASE_SURVEILANCE, FeatureTypeProperty.HIDE_JURISDICTION_FIELDS)) { + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { hideAndFillJurisdictionFields(); } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java index 4469e5ec7c1..4927c2e6d02 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java @@ -37,6 +37,7 @@ import org.apache.commons.lang3.StringUtils; +import com.vaadin.shared.ui.ErrorLevel; import com.vaadin.ui.CustomLayout; import com.vaadin.ui.Label; import com.vaadin.v7.data.Item; @@ -49,6 +50,7 @@ import com.vaadin.v7.ui.TextArea; import com.vaadin.v7.ui.TextField; +import de.symeda.sormas.api.CountryHelper; import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.caze.CaseDataDto; @@ -79,6 +81,7 @@ import de.symeda.sormas.api.utils.fieldaccess.UiFieldAccessCheckers; import de.symeda.sormas.api.utils.fieldvisibility.FieldVisibilityCheckers; import de.symeda.sormas.api.utils.fieldvisibility.checkers.CountryFieldVisibilityChecker; +import de.symeda.sormas.api.utils.luxembourg.LuxembourgNationalHealthIdValidator; import de.symeda.sormas.ui.ControllerProvider; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.location.LocationEditForm; @@ -103,6 +106,7 @@ public class PersonEditForm extends AbstractEditForm { private static final String ADDRESSES_HEADER = "addressesHeader"; private static final String CONTACT_INFORMATION_HEADER = "contactInformationHeader"; private static final String EXTERNAL_TOKEN_WARNING_LOC = "externalTokenWarningLoc"; + private static final String NATIONAL_HEALTH_ID_WARNING_LABEL = "nationalHealthIdWarningLoc"; private static final String GENERAL_COMMENT_LOC = "generalCommentLoc"; //@formatter:off private static final String HTML_LAYOUT = @@ -134,6 +138,7 @@ public class PersonEditForm extends AbstractEditForm { oneOfTwoCol(PersonDto.BURIAL_PLACE_DESCRIPTION) ) + fluidRowLocs(PersonDto.PASSPORT_NUMBER, PersonDto.NATIONAL_HEALTH_ID) + + fluidRowLocs("", NATIONAL_HEALTH_ID_WARNING_LABEL) + fluidRowLocs(PersonDto.EXTERNAL_ID, PersonDto.EXTERNAL_TOKEN) + fluidRowLocs(PersonDto.INTERNAL_TOKEN, EXTERNAL_TOKEN_WARNING_LOC) + @@ -350,7 +355,7 @@ protected void addFields() { personContactDetailsField.setCaption(null); personContactDetailsField.setPseudonymized(isPseudonymized); - ComboBox occupationTypeField = addField(PersonDto.OCCUPATION_TYPE, ComboBox.class); + ComboBox occupationTypeField = addCustomizableEnumField(PersonDto.OCCUPATION_TYPE); TextField occupationTypeDetailsField = addField(PersonDto.OCCUPATION_DETAILS, TextField.class); occupationTypeDetailsField.setVisible(false); FieldHelper @@ -366,7 +371,14 @@ protected void addFields() { addInfrastructureField(PersonDto.BIRTH_COUNTRY).addItems(countries); addInfrastructureField(PersonDto.CITIZENSHIP).addItems(countries); - addFields(PersonDto.PASSPORT_NUMBER, PersonDto.NATIONAL_HEALTH_ID); + addField(PersonDto.PASSPORT_NUMBER); + + TextField nationalHealthIdField = addField(PersonDto.NATIONAL_HEALTH_ID); + Label nationalHealthIdWarningLabel = new Label(I18nProperties.getString(Strings.messagePersonNationalHealthIdInvalid)); + nationalHealthIdWarningLabel.addStyleNames(VSPACE_3, LABEL_WHITE_SPACE_NORMAL); + nationalHealthIdWarningLabel.setVisible(false); + getContent().addComponent(nationalHealthIdWarningLabel, NATIONAL_HEALTH_ID_WARNING_LABEL); + Field externalId = addField(PersonDto.EXTERNAL_ID); if (FacadeProvider.getExternalSurveillanceToolFacade().isFeatureEnabled()) { externalId.setEnabled(false); @@ -566,13 +578,27 @@ protected void addFields() { burialDate.setValidationVisible(!burialDate.isValid()); }); - addValueChangeListener((e) -> { + addValueChangeListener(e -> { ValidationUtils.initComponentErrorValidator( externalTokenField, getValue().getExternalToken(), Validations.duplicateExternalToken, externalTokenWarningLabel, - (externalToken) -> FacadeProvider.getPersonFacade().doesExternalTokenExist(externalToken, getValue().getUuid())); + externalToken -> FacadeProvider.getPersonFacade().doesExternalTokenExist(externalToken, getValue().getUuid())); + + if (FacadeProvider.getConfigFacade().isConfiguredCountry(CountryHelper.COUNTRY_CODE_LUXEMBOURG)) { + ValidationUtils.initComponentErrorValidator( + nationalHealthIdField, + nationalHealthIdField.getValue(), + Validations.invalidNationalHealthId, + nationalHealthIdWarningLabel, + nationalHealthId -> !LuxembourgNationalHealthIdValidator.isValid( + nationalHealthId, + (Integer) birthDateYear.getValue(), + (Integer) birthDateMonth.getValue(), + (Integer) birthDateDay.getValue()), + ErrorLevel.WARNING); + } personContactDetailsField.setThisPerson((PersonDto) e.getProperty().getValue()); }); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonFilterForm.java index 915ac8ae71b..75813adaa97 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonFilterForm.java @@ -24,7 +24,10 @@ public class PersonFilterForm extends AbstractFilterForm { protected PersonFilterForm() { - super(PersonCriteria.class, PersonDto.I18N_PREFIX); + super( + PersonCriteria.class, + PersonDto.I18N_PREFIX, + JurisdictionFieldConfig.withNoPrefillOnHide(PersonCriteria.REGION, PersonCriteria.DISTRICT, PersonCriteria.COMMUNITY)); } @Override diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonGrid.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonGrid.java index 2e789d67947..e8b68d493ad 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonGrid.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonGrid.java @@ -6,6 +6,7 @@ import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.caze.AgeAndBirthDateDto; +import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.location.LocationDto; import de.symeda.sormas.api.person.PersonCriteria; @@ -14,6 +15,7 @@ import de.symeda.sormas.api.person.PersonIndexDto; import de.symeda.sormas.api.user.UserRight; import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.utils.FieldAccessColumnStyleGenerator; import de.symeda.sormas.ui.utils.FilteredGrid; @@ -80,6 +82,10 @@ private void initColumns() { LocationDto.I18N_PREFIX)); column.setStyleGenerator(FieldAccessColumnStyleGenerator.getDefault(getBeanType(), column.getId())); } + + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + getColumn(PersonIndexDto.DISTRICT).setHidden(true); + } } public void setLazyDataProvider() { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonSelectionFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonSelectionFilterForm.java index 39751b48d8c..80f261360e4 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonSelectionFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonSelectionFilterForm.java @@ -38,7 +38,7 @@ public class PersonSelectionFilterForm extends AbstractFilterForm { //@formatter:off protected static final String SAMPLE_COMMON_HTML_LAYOUT = - fluidRowLocs(SampleDto.UUID, REPORT_INFO_LABEL_LOC, SampleDto.REPORTING_USER) + + fluidRowLocs(4, SampleDto.UUID, 4, REPORT_INFO_LABEL_LOC, 3,SampleDto.REPORTING_USER, 1, "") + fluidRowLocs(SampleDto.SAMPLE_PURPOSE) + fluidRowLocs(SampleDto.SAMPLE_DATE_TIME, SampleDto.SAMPLE_MATERIAL) + fluidRowLocs("", SampleDto.SAMPLE_MATERIAL_TEXT) + diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/CollapsiblePathogenTestForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/CollapsiblePathogenTestForm.java index 691feb2715e..86b2b75e42a 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/CollapsiblePathogenTestForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/CollapsiblePathogenTestForm.java @@ -52,6 +52,7 @@ public CollapsiblePathogenTestForm(PathogenTestForm pathogenTestForm, boolean in commitDiscardForm.getCommitButton().setCaption(I18nProperties.getCaption(Captions.actionDone)); commitDiscardForm.getDiscardButton().setCaption(I18nProperties.getCaption(Captions.actionCancel)); + commitDiscardForm.getDiscardButton().setId("cancel"); commitDiscardForm.getButtonsPanel().setComponentAlignment(commitDiscardForm.getDiscardButton(), Alignment.BOTTOM_LEFT); commitDiscardForm.addDoneListener(this::collapse); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/PathogenTestController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/PathogenTestController.java index bee10cc95bd..82c91e88f42 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/PathogenTestController.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/PathogenTestController.java @@ -117,6 +117,7 @@ public CommitDiscardWrapperComponent getPathogenTestCreateComp int caseSampleCount, Consumer onSavedPathogenTest, boolean suppressNavigateToCase) { + PathogenTestForm createForm = new PathogenTestForm(sampleDto, true, caseSampleCount, false, true); // Valid because jurisdiction doesn't matter for entities that are about to be created createForm.setValue(pathogenTest); final CommitDiscardWrapperComponent editView = new CommitDiscardWrapperComponent<>( @@ -146,7 +147,7 @@ public CommitDiscardWrapperComponent getPathogenTestCreateComp final CommitDiscardWrapperComponent editView = new CommitDiscardWrapperComponent<>( createForm, - UserProvider.getCurrent().hasUserRight(UserRight.PATHOGEN_TEST_CREATE), + UserProvider.getCurrent().hasUserRight(UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE), createForm.getFieldGroup()); editView.addCommitListener(() -> { @@ -190,8 +191,9 @@ public CommitDiscardWrapperComponent getPathogenTestEditCompon // get fresh data PathogenTestDto pathogenTest = facade.getByUuid(pathogenTestUuid); + boolean forHumanSample = pathogenTest.getSample() != null; final PathogenTestForm form; - if (pathogenTest.getSample() != null) { + if (forHumanSample) { SampleDto sample = FacadeProvider.getSampleFacade().getSampleByUuid(pathogenTest.getSample().getUuid()); form = new PathogenTestForm(sample, false, 0, pathogenTest.isPseudonymized(), pathogenTest.isInJurisdiction()); } else { @@ -230,9 +232,9 @@ public CommitDiscardWrapperComponent getPathogenTestEditCompon } } editView.restrictEditableComponentsOnEditView( - UserRight.SAMPLE_EDIT, - UserRight.PATHOGEN_TEST_EDIT, - UserRight.PATHOGEN_TEST_DELETE, + forHumanSample ? UserRight.SAMPLE_EDIT : UserRight.ENVIRONMENT_SAMPLE_EDIT, + forHumanSample ? UserRight.PATHOGEN_TEST_EDIT : UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT, + forHumanSample ? UserRight.PATHOGEN_TEST_DELETE : UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE, null, pathogenTest.isInJurisdiction()); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/PathogenTestForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/PathogenTestForm.java index 07d54f3b974..c139cb17762 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/PathogenTestForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/PathogenTestForm.java @@ -258,12 +258,12 @@ protected void addFields() { // Tested Desease or Tested Pathogen, depending on sample type ComboBox diseaseField = addDiseaseField(PathogenTestDto.TESTED_DISEASE, true, create); addField(PathogenTestDto.TESTED_DISEASE_DETAILS, TextField.class); - ComboBox diseaseVariantField = addField(PathogenTestDto.TESTED_DISEASE_VARIANT, ComboBox.class); + ComboBox diseaseVariantField = addCustomizableEnumField(PathogenTestDto.TESTED_DISEASE_VARIANT); diseaseVariantField.setNullSelectionAllowed(true); TextField diseaseVariantDetailsField = addField(PathogenTestDto.TESTED_DISEASE_VARIANT_DETAILS, TextField.class); diseaseVariantDetailsField.setVisible(false); - ComboBox testedPathogenField = addField(PathogenTestDto.TESTED_PATHOGEN, ComboBox.class); + ComboBox testedPathogenField = addCustomizableEnumField(PathogenTestDto.TESTED_PATHOGEN); TextField testedPathogenDetailsField = addField(PathogenTestDto.TESTED_PATHOGEN_DETAILS, TextField.class); testedPathogenDetailsField.setVisible(false); FieldHelper.updateItems(testedPathogenField, FacadeProvider.getCustomizableEnumFacade().getEnumValues(CustomizableEnumType.PATHOGEN, null)); @@ -388,7 +388,6 @@ protected void addFields() { disease != null && isVisibleAllowed(PathogenTestDto.TESTED_DISEASE_VARIANT) && CollectionUtils.isNotEmpty(diseaseVariants)); }; - // trigger the update, as the disease may already be set updateDiseaseVariantField.accept((Disease) diseaseField.getValue()); diseaseField.addValueChangeListener((ValueChangeListener) valueChangeEvent -> { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/environmentsample/EnvironmentSampleEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/environmentsample/EnvironmentSampleEditForm.java index d25c0c9a635..af74bd89825 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/environmentsample/EnvironmentSampleEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/environmentsample/EnvironmentSampleEditForm.java @@ -76,7 +76,7 @@ public class EnvironmentSampleEditForm extends AbstractEditForm) getColumn(EnvironmentSampleIndexDto.RECEIVED)).setRenderer(new BooleanRenderer()); ((Column) getColumn(EnvironmentSampleIndexDto.LABORATORY)).setMaximumWidth(200); - ((Column>) getColumn(EnvironmentSampleIndexDto.POSITIVE_PATHOGEN_TESTS)) - .setRenderer(new TextRenderer() { - @Override - public JsonValue encode(Object value) { - if (value != null) { + Column> positivePathogenTestsColumn = + (Column>) getColumn(EnvironmentSampleIndexDto.POSITIVE_PATHOGEN_TESTS); + positivePathogenTestsColumn.setRenderer(new TextRenderer() { - return super.encode( - String.join(", ", ((List) value).stream().map(t -> t.getCaption()).collect(Collectors.toList()))); - } - return super.encode(value); + @Override + public JsonValue encode(Object value) { + if (value != null) { + + return super.encode(String.join(", ", ((List) value).stream().map(t -> t.getCaption()).collect(Collectors.toList()))); } - }); + return super.encode(value); + } + }); + positivePathogenTestsColumn.setSortable(false); + + ((Column) getColumn(EnvironmentSampleIndexDto.NUMBER_OF_TESTS)).setSortable(false); for (Column column : getColumns()) { if (!DELETE_REASON_COLUMN.equals(column.getId())) { @@ -142,6 +148,10 @@ public JsonValue encode(Object value) { } } + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + getColumn(EnvironmentSampleIndexDto.DISTRICT).setHidden(true); + } + addItemClickListener( new ShowDetailsListener<>( EnvironmentSampleIndexDto.UUID, diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/environmentsample/EnvironmentSampleGridFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/environmentsample/EnvironmentSampleGridFilterForm.java index b922e1f68f9..70efc7be26f 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/environmentsample/EnvironmentSampleGridFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/environmentsample/EnvironmentSampleGridFilterForm.java @@ -55,7 +55,10 @@ public class EnvironmentSampleGridFilterForm extends AbstractFilterForm { sampleComponent.removeComponent(separator); sampleComponent.removeComponent(collapsibleForm); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/humansample/SampleDataView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/humansample/SampleDataView.java index 0f530a95120..0de2aa39e20 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/humansample/SampleDataView.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/humansample/SampleDataView.java @@ -23,6 +23,7 @@ import com.vaadin.ui.VerticalLayout; import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.EditPermissionType; import de.symeda.sormas.api.EntityDto; import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.caze.CaseDataDto; @@ -180,9 +181,7 @@ protected void initView(String params) { final String uuid = sampleDto.getUuid(); final boolean deleted = FacadeProvider.getSampleFacade().isDeleted(uuid); - - layout.disableIfNecessary(deleted, null); - editComponent.setEnabled(isEditAllowed()); + layout.disableIfNecessary(deleted, isEditAllowed() ? EditPermissionType.ALLOWED : EditPermissionType.REFUSED); } private AbstractInfoLayout getDependentSideComponent(SampleDto sampleDto) { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/humansample/SampleGridFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/humansample/SampleGridFilterForm.java index 10b029773c9..b67edfd6f75 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/humansample/SampleGridFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/humansample/SampleGridFilterForm.java @@ -50,7 +50,7 @@ public class SampleGridFilterForm extends AbstractFilterForm { private static final long serialVersionUID = 829016959284536683L; public SampleGridFilterForm() { - super(SampleCriteria.class, SampleIndexDto.I18N_PREFIX); + super(SampleCriteria.class, SampleIndexDto.I18N_PREFIX, JurisdictionFieldConfig.of(SampleCriteria.REGION, SampleCriteria.DISTRICT, null)); } private static final String WEEK_AND_DATE_FILTER = "moreFilters"; diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/pathogentestlink/PathogenTestList.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/pathogentestlink/PathogenTestList.java index 20922e656cd..f0c1432e259 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/pathogentestlink/PathogenTestList.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/pathogentestlink/PathogenTestList.java @@ -87,10 +87,16 @@ protected void drawDisplayedEntries() { for (PathogenTestDto pathogenTest : displayedEntries) { PathogenTestListEntry listEntry = new PathogenTestListEntry(pathogenTest, true); String pathogenTestUuid = pathogenTest.getUuid(); - boolean isEditableAndHasEditRight = - UserProvider.getCurrent().hasAllUserRightsWithEditAllowedFlag(isEditable, UserRight.SAMPLE_EDIT, UserRight.PATHOGEN_TEST_EDIT); - boolean isEditableAndHasDeleteRight = - UserProvider.getCurrent().hasAllUserRightsWithEditAllowedFlag(isEditable, UserRight.PATHOGEN_TEST_DELETE); + boolean forHumanSample = pathogenTest.getSample() != null; + boolean isEditableAndHasEditRight = UserProvider.getCurrent() + .hasAllUserRightsWithEditAllowedFlag( + isEditable, + forHumanSample ? UserRight.SAMPLE_EDIT : UserRight.ENVIRONMENT_SAMPLE_EDIT, + forHumanSample ? UserRight.PATHOGEN_TEST_EDIT : UserRight.ENVIRONMENT_PATHOGEN_TEST_EDIT); + boolean isEditableAndHasDeleteRight = UserProvider.getCurrent() + .hasAllUserRightsWithEditAllowedFlag( + isEditable, + forHumanSample ? UserRight.PATHOGEN_TEST_DELETE : UserRight.ENVIRONMENT_PATHOGEN_TEST_DELETE); listEntry.addActionButton( pathogenTestUuid, diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/pathogentestlink/PathogenTestListComponent.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/pathogentestlink/PathogenTestListComponent.java index cc6790a9e3e..1aa9b3d3bb0 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/pathogentestlink/PathogenTestListComponent.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/pathogentestlink/PathogenTestListComponent.java @@ -54,7 +54,7 @@ public PathogenTestListComponent(EnvironmentSampleReferenceDto sampleRef, Consum addCreateButton( I18nProperties.getCaption(Captions.pathogenTestNewTest), () -> ControllerProvider.getPathogenTestController().create(sampleRef), - UserRight.PATHOGEN_TEST_CREATE); + UserRight.ENVIRONMENT_PATHOGEN_TEST_CREATE); } PathogenTestList pathogenTestList = new PathogenTestList(sampleRef, actionCallback, isEditAllowed); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/sormastosormas/ShareRequestFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/sormastosormas/ShareRequestFilterForm.java index 7ae693f9ed2..d4422100589 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/sormastosormas/ShareRequestFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/sormastosormas/ShareRequestFilterForm.java @@ -29,7 +29,7 @@ public class ShareRequestFilterForm extends AbstractFilterForm(task -> { boolean isInJurisdiction = task.getTaskJurisdictionFlagsDto().getInJurisdiction(); return UiFieldAccessCheckers.getDefault(!isInJurisdiction).hasRight(); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/task/TaskGridFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/task/TaskGridFilterForm.java index c921ff9b47c..9baa42ac126 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/task/TaskGridFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/task/TaskGridFilterForm.java @@ -48,7 +48,8 @@ protected TaskGridFilterForm() { super( TaskCriteria.class, TaskIndexDto.I18N_PREFIX, - FieldVisibilityCheckers.withCheckers(new UserRightFieldVisibilityChecker(UserProvider.getCurrent()::hasUserRight))); + FieldVisibilityCheckers.withCheckers(new UserRightFieldVisibilityChecker(UserProvider.getCurrent()::hasUserRight)), + JurisdictionFieldConfig.of(TaskIndexDto.REGION, TaskIndexDto.DISTRICT, null)); } @Override diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/TravelEntryDataForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/TravelEntryDataForm.java index 2fb15a11c4d..924d9341aee 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/TravelEntryDataForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/TravelEntryDataForm.java @@ -69,7 +69,7 @@ public class TravelEntryDataForm extends AbstractEditForm { //@formatter:off private static final String HTML_LAYOUT = loc(TRAVEL_ENTRY_HEADING_LOC) + - fluidRowLocs(4, TravelEntryDto.UUID, 3, TravelEntryDto.REPORT_DATE, 5, TravelEntryDto.REPORTING_USER) + + fluidRowLocs(4, TravelEntryDto.UUID, 3, TravelEntryDto.REPORT_DATE, 3, TravelEntryDto.REPORTING_USER, 2, "") + fluidRowLocs(4, TravelEntryDto.EXTERNAL_ID) + fluidRow( fluidColumnLoc(6, 0, TravelEntryDto.DISEASE), @@ -150,7 +150,7 @@ protected void addFields() { style(externalIdField, ERROR_COLOR_PRIMARY); ComboBox diseaseField = addDiseaseField(TravelEntryDto.DISEASE, false); - ComboBox diseaseVariantField = addField(TravelEntryDto.DISEASE_VARIANT, ComboBox.class); + ComboBox diseaseVariantField = addCustomizableEnumField(TravelEntryDto.DISEASE_VARIANT); diseaseVariantField.setNullSelectionAllowed(true); diseaseVariantField.setVisible(false); addField(TravelEntryDto.DISEASE_DETAILS, TextField.class); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/TravelEntryFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/TravelEntryFilterForm.java index 1a7555bc848..3f1eb858167 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/TravelEntryFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/TravelEntryFilterForm.java @@ -12,7 +12,6 @@ import com.vaadin.v7.ui.TextField; import de.symeda.sormas.api.FacadeProvider; -import de.symeda.sormas.api.caze.NewCaseDateType; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; @@ -38,7 +37,8 @@ protected TravelEntryFilterForm() { super( TravelEntryCriteria.class, TravelEntryDto.I18N_PREFIX, - FieldVisibilityCheckers.withCountry(FacadeProvider.getConfigFacade().getCountryLocale())); + FieldVisibilityCheckers.withCountry(FacadeProvider.getConfigFacade().getCountryLocale()), + null); } @Override diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/user/UserRoleCreateForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/user/UserRoleCreateForm.java index b4182aee86d..3a932216f7d 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/user/UserRoleCreateForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/user/UserRoleCreateForm.java @@ -47,8 +47,8 @@ public class UserRoleCreateForm extends AbstractEditForm { + fluidRowLocs(UserRoleDto.DESCRIPTION) + fluidRowLocs(UserRoleDto.HAS_OPTIONAL_HEALTH_FACILITY) + fluidRowLocs(UserRoleDto.HAS_ASSOCIATED_DISTRICT_USER) - + fluidRowLocs(UserRoleDto.PORT_HEALTH_USER); -// + fluidRowLocs(UserRoleDto.RESTRICT_ACCESS_TO_ASSIGNED_ENTITIES); + + fluidRowLocs(UserRoleDto.PORT_HEALTH_USER) + + fluidRowLocs(UserRoleDto.RESTRICT_ACCESS_TO_ASSIGNED_ENTITIES); protected UserRoleCreateForm() { super(UserRoleDto.class, UserRoleDto.I18N_PREFIX); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/user/UserRoleEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/user/UserRoleEditForm.java index fb51d8cf9ff..f2c5af9cb46 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/user/UserRoleEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/user/UserRoleEditForm.java @@ -59,7 +59,7 @@ public class UserRoleEditForm extends AbstractUserRoleForm { + fluidRowLocs(UserRoleDto.HAS_OPTIONAL_HEALTH_FACILITY) + fluidRowLocs(UserRoleDto.HAS_ASSOCIATED_DISTRICT_USER) + fluidRowLocs(UserRoleDto.PORT_HEALTH_USER) -// + fluidRowLocs(UserRoleDto.RESTRICT_ACCESS_TO_ASSIGNED_ENTITIES) + + fluidRowLocs(UserRoleDto.RESTRICT_ACCESS_TO_ASSIGNED_ENTITIES) + fluidRowLocs(USER_RIGHTS_LABEL_LOC) + fluidRowLocs(UserRoleDto.USER_RIGHTS); @@ -85,7 +85,7 @@ protected void addFields() { addField(UserRoleDto.HAS_OPTIONAL_HEALTH_FACILITY).addStyleName(CssStyles.VSPACE_TOP_3); addField(UserRoleDto.HAS_ASSOCIATED_DISTRICT_USER).addStyleName(CssStyles.VSPACE_TOP_3); - addField(UserRoleDto.PORT_HEALTH_USER).addStyleNames(CssStyles.VSPACE_TOP_3, CssStyles.VSPACE_3); + addField(UserRoleDto.PORT_HEALTH_USER).addStyleNames(CssStyles.VSPACE_TOP_3); addField(UserRoleDto.RESTRICT_ACCESS_TO_ASSIGNED_ENTITIES).addStyleNames(CssStyles.VSPACE_TOP_3, CssStyles.VSPACE_3); Label userRightsLabel = new Label(I18nProperties.getCaption(Captions.UserRole_userRights), ContentMode.HTML); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java index 564e511a85a..5e91c4022b7 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java @@ -39,6 +39,7 @@ import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.InfrastructureDataReferenceDto; +import de.symeda.sormas.api.customizableenum.CustomizableEnum; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; @@ -269,6 +270,20 @@ protected ComboBox addInfrastructureField(String fieldId, boolean showInactiveTa return field; } + protected ComboBox addCustomizableEnumField(String fieldId) { + ComboBox field = addField(fieldId, ComboBox.class); + // Make sure that the ComboBox still contains a pre-selected inactive customizable enum + field.addValueChangeListener(e -> { + CustomizableEnum value = (CustomizableEnum) e.getProperty().getValue(); + if (value != null && !field.containsId(value)) { + CustomizableEnum inactiveValue = value.clone(); + inactiveValue.setCaption(value.getCaption() + " (" + I18nProperties.getString(Strings.inactive) + ")"); + field.addItem(inactiveValue); + } + }); + return field; + } + @SuppressWarnings({ "unchecked", "rawtypes" }) diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractFilterForm.java index fedd2d368bd..fc79477b314 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractFilterForm.java @@ -2,11 +2,14 @@ import static de.symeda.sormas.ui.utils.LayoutUtil.div; import static de.symeda.sormas.ui.utils.LayoutUtil.filterLocs; -import static de.symeda.sormas.ui.utils.LayoutUtil.loc; import static de.symeda.sormas.ui.utils.LayoutUtil.locCss; +import java.util.Objects; +import java.util.function.Supplier; import java.util.stream.Stream; +import javax.annotation.Nullable; + import org.apache.commons.lang3.ArrayUtils; import com.vaadin.ui.Button; @@ -20,12 +23,15 @@ import com.vaadin.v7.ui.PopupDateField; import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.ReferenceDto; +import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto; import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto; import de.symeda.sormas.api.user.UserDto; import de.symeda.sormas.api.utils.fieldvisibility.FieldVisibilityCheckers; +import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.utils.components.FormActionButtonsComponent; @@ -44,16 +50,33 @@ public abstract class AbstractFilterForm extends AbstractForm { protected FormActionButtonsComponent formActionButtonsComponent; - protected AbstractFilterForm(Class type, String propertyI18nPrefix) { - this(type, propertyI18nPrefix, null); + private JurisdictionFieldConfig jurisdictionFieldConfig; + + protected ComboBox regionFilter; + protected ComboBox districtFilter; + protected ComboBox communityFilter; + + protected AbstractFilterForm(Class type, String propertyI18nPrefix, JurisdictionFieldConfig jurisdictionFieldConfig) { + this(type, propertyI18nPrefix, null, jurisdictionFieldConfig); } - protected AbstractFilterForm(Class type, String propertyI18nPrefix, boolean addFields) { - this(type, propertyI18nPrefix, null, Captions.actionApplyFilters, Captions.actionResetFilters, addFields); + protected AbstractFilterForm(Class type, String propertyI18nPrefix, JurisdictionFieldConfig jurisdictionFieldConfig, boolean addFields) { + this(type, propertyI18nPrefix, null, Captions.actionApplyFilters, Captions.actionResetFilters, jurisdictionFieldConfig, addFields); } - protected AbstractFilterForm(Class type, String propertyI18nPrefix, FieldVisibilityCheckers fieldVisibilityCheckers) { - this(type, propertyI18nPrefix, fieldVisibilityCheckers, Captions.actionApplyFilters, Captions.actionResetFilters, true); + protected AbstractFilterForm( + Class type, + String propertyI18nPrefix, + FieldVisibilityCheckers fieldVisibilityCheckers, + JurisdictionFieldConfig jurisdictionFieldConfig) { + this( + type, + propertyI18nPrefix, + fieldVisibilityCheckers, + Captions.actionApplyFilters, + Captions.actionResetFilters, + jurisdictionFieldConfig, + true); } protected AbstractFilterForm( @@ -62,9 +85,11 @@ protected AbstractFilterForm( FieldVisibilityCheckers fieldVisibilityCheckers, String applyCaptionTag, String resetCaptionTag, + JurisdictionFieldConfig jurisdictionFieldConfig, boolean addFields) { super(type, propertyI18nPrefix, new SormasFieldGroupFieldFactory(fieldVisibilityCheckers, null), addFields); + this.jurisdictionFieldConfig = jurisdictionFieldConfig; String moreFiltersHtmlLayout = createMoreFiltersHtmlLayout(); boolean hasMoreFilters = moreFiltersHtmlLayout != null && moreFiltersHtmlLayout.length() > 0; @@ -88,6 +113,22 @@ protected AbstractFilterForm( }); addStyleName(CssStyles.FILTER_FORM); + + if (addFields) { + initJurisdictionFields(jurisdictionFieldConfig); + } + } + + protected void initJurisdictionFields(JurisdictionFieldConfig jurisdictionFieldConfig) { + if (jurisdictionFieldConfig != null) { + regionFilter = jurisdictionFieldConfig.region != null ? getField(jurisdictionFieldConfig.region) : null; + districtFilter = jurisdictionFieldConfig.district != null ? getField(jurisdictionFieldConfig.district) : null; + communityFilter = jurisdictionFieldConfig.community != null ? getField(jurisdictionFieldConfig.community) : null; + } else { + regionFilter = null; + districtFilter = null; + communityFilter = null; + } } public void onChange() { @@ -163,10 +204,33 @@ public void setValue(T newFieldValue) throws ReadOnlyException, Converter.Conver applyDependenciesOnNewValue(newFieldValue); if (moreFiltersLayout != null) { - boolean hasExpandedFilter = streamFieldsForEmptyCheck(moreFiltersLayout).anyMatch(f -> !f.isEmpty()); + boolean hasExpandedFilter = streamFieldsForEmptyCheck(moreFiltersLayout).anyMatch(f -> !f.isEmpty() && f.isVisible()); formActionButtonsComponent.toggleMoreFilters(hasExpandedFilter); } }); + + if (newFieldValue != null && getJurisdictionFields().anyMatch(Field::isVisible) && UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + hideAndFillJurisdictionFilters(); + } + } + + protected Stream getJurisdictionFields() { + return Stream.of(regionFilter, districtFilter, communityFilter).filter(Objects::nonNull); + } + + private void hideAndFillJurisdictionFilters() { + hideAndFillJurisdictionField(regionFilter, () -> FacadeProvider.getRegionFacade().getDefaultInfrastructureReference()); + hideAndFillJurisdictionField(districtFilter, () -> FacadeProvider.getDistrictFacade().getDefaultInfrastructureReference()); + hideAndFillJurisdictionField(communityFilter, () -> FacadeProvider.getCommunityFacade().getDefaultInfrastructureReference()); + } + + private void hideAndFillJurisdictionField(@Nullable ComboBox field, Supplier defaultValueGetter) { + if (field != null) { + field.setVisible(false); + if (jurisdictionFieldConfig.prefillOnHide) { + field.setValue(defaultValueGetter.get()); + } + } } @SuppressWarnings("rawtypes") @@ -314,4 +378,32 @@ interface Callable { void call(); } + + protected static class JurisdictionFieldConfig { + + private final String region; + private final String district; + private final String community; + + private boolean prefillOnHide; + + private JurisdictionFieldConfig(String region, String district, String community) { + this.region = region; + this.district = district; + this.community = community; + } + + public static JurisdictionFieldConfig of(String region, String district, String community) { + JurisdictionFieldConfig names = new JurisdictionFieldConfig(region, district, community); + names.prefillOnHide = true; + return names; + } + + public static JurisdictionFieldConfig withNoPrefillOnHide(String region, String district, String community) { + JurisdictionFieldConfig names = new JurisdictionFieldConfig(region, district, community); + names.prefillOnHide = false; + return names; + } + + } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/CssStyles.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/CssStyles.java index de55e280646..130e7bfad5f 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/CssStyles.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/CssStyles.java @@ -56,6 +56,7 @@ private CssStyles() { public static final String VSPACE_TOP_3 = "vspace-top-3"; public static final String VSPACE_TOP_4 = "vspace-top-4"; public static final String VSPACE_TOP_5 = "vspace-top-5"; + public static final String VSPACE_TOP_6 = "vspace-top-6"; public static final String VSPACE_TOP_NONE = "vspace-top-none"; // Horizontal space @@ -65,6 +66,7 @@ private CssStyles() { public static final String HSPACE_LEFT_3 = "hspace-left-3"; public static final String HSPACE_LEFT_4 = "hspace-left-4"; public static final String HSPACE_LEFT_5 = "hspace-left-5"; + public static final String HSPACE_LEFT_6 = "hspace-left-6"; public static final String HSPACE_LEFT_NONE = "hspace-left-none"; public static final String HSPACE_RIGHT_0 = "hspace-right-0"; diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/UserField.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/UserField.java index 6c611acf1b0..5869d5e5e58 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/UserField.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/UserField.java @@ -57,10 +57,16 @@ protected Component initContent() { userLayout.addComponent(userContactButton); userLayout.setWidthFull(); userLayout.setExpandRatio(userCombo, 1); + userLayout.setSpacing(false); + userCombo.setWidthFull(); userCombo.addValueChangeListener(valueChangeEvent -> { - setInternalValue((UserReferenceDto) userCombo.getValue()); + super.setValue((UserReferenceDto) userCombo.getValue()); + }); + + addValueChangeListener(c -> { + userCombo.setValue(c.getProperty().getValue()); }); return userLayout; @@ -82,9 +88,15 @@ public void removeAllItems() { } protected Button createUserContactButton() { + boolean isReadOnly = userCombo.isReadOnly(); Button userContactButton = ButtonHelper.createIconButtonWithCaption("userContact", "", VaadinIcons.EYE, e -> { triggerUserContactPopUpWindow(); - }, ValoTheme.BUTTON_ICON_ONLY, ValoTheme.BUTTON_BORDERLESS, ValoTheme.BUTTON_LARGE); + }, + ValoTheme.BUTTON_ICON_ONLY, + ValoTheme.BUTTON_BORDERLESS, + ValoTheme.BUTTON_LARGE, + isReadOnly ? CssStyles.HSPACE_LEFT_6 : CssStyles.HSPACE_LEFT_NONE, + isReadOnly ? CssStyles.VSPACE_TOP_6 : CssStyles.VSPACE_NONE); return userContactButton; } @@ -121,6 +133,18 @@ protected void triggerUserContactPopUpWindow() { VerticalLayout verticalLayout = new VerticalLayout(); verticalLayout.setMargin(false); if (userDto != null) { + if (userCombo.isReadOnly()) { + HorizontalLayout reportingUserLayout = new HorizontalLayout(); + Label reportingUserLabel = new Label(I18nProperties.getString(Strings.reportingUser)); + reportingUserLabel.addStyleName(LABEL_BOLD); + reportingUserLayout.addComponent(reportingUserLabel); + + Label reportingUser = new Label(getValue().getCaption()); + reportingUserLayout.addComponent(reportingUser); + + verticalLayout.addComponent(reportingUserLayout); + } + HorizontalLayout telephoneNumberLayout = new HorizontalLayout(); Label telephoneLabel = new Label(I18nProperties.getString(Strings.promptTelephoneNumber)); telephoneLabel.addStyleName(LABEL_BOLD); @@ -177,4 +201,5 @@ protected void triggerUserContactPopUpWindow() { public Class getType() { return UserReferenceDto.class; } + } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ValidationUtils.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ValidationUtils.java index fd9a40c07bc..8a98ab668f8 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ValidationUtils.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ValidationUtils.java @@ -20,7 +20,9 @@ import org.apache.commons.lang3.StringUtils; import com.vaadin.server.UserError; +import com.vaadin.shared.ui.ErrorLevel; import com.vaadin.ui.Label; +import com.vaadin.v7.data.Property; import com.vaadin.v7.ui.TextField; import de.symeda.sormas.api.i18n.I18nProperties; @@ -36,13 +38,31 @@ public static void initComponentErrorValidator( String validationMessageTag, Label warningLabel, Function exists) { + initComponentErrorValidator(field, initialFieldValue, validationMessageTag, warningLabel, exists, ErrorLevel.ERROR); + } + + public static void initComponentErrorValidator( + TextField field, + String initialFieldValue, + String validationMessageTag, + Label warningLabel, + Function isInvlaid, + ErrorLevel errorLevel) { if (field == null) { return; } + // already initialized + if (field.getData() != null) { + // remove old listener + if (Property.ValueChangeListener.class.isAssignableFrom(field.getData().getClass())) { + field.removeValueChangeListener((Property.ValueChangeListener) field.getData()); + } + } + Function validateExternalToken = (String value) -> { - if (field.isVisible() && !StringUtils.isEmpty(value) && exists.apply(value)) { - field.setComponentError(new UserError(I18nProperties.getValidationError(validationMessageTag))); + if (field.isVisible() && !StringUtils.isEmpty(value) && isInvlaid.apply(value)) { + field.setComponentError(new UserError(I18nProperties.getValidationError(validationMessageTag), null, errorLevel)); warningLabel.setVisible(true); } else { field.setComponentError(null); @@ -53,6 +73,8 @@ public static void initComponentErrorValidator( }; validateExternalToken.apply(initialFieldValue); - field.addValueChangeListener(f -> validateExternalToken.apply((String) f.getProperty().getValue())); + Property.ValueChangeListener valueChangeListener = f -> validateExternalToken.apply((String) f.getProperty().getValue()); + field.addValueChangeListener(valueChangeListener); + field.setData(valueChangeListener); } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/vaccination/VaccinationEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/vaccination/VaccinationEditForm.java index 53a5e0f36dc..53e93e92ec9 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/vaccination/VaccinationEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/vaccination/VaccinationEditForm.java @@ -38,7 +38,7 @@ public class VaccinationEditForm extends AbstractEditForm { - private static final String HTML_LAYOUT = fluidRowLocs(VaccinationDto.REPORT_DATE, VaccinationDto.REPORTING_USER) + private static final String HTML_LAYOUT = fluidRowLocs(6, VaccinationDto.REPORT_DATE, 3, VaccinationDto.REPORTING_USER, 3, "") + fluidRow(oneOfTwoCol(VaccinationDto.VACCINATION_DATE)) + fluidRowLocs(VaccinationDto.VACCINE_NAME, VaccinationDto.OTHER_VACCINE_NAME) + fluidRowLocs(VaccinationDto.VACCINE_MANUFACTURER, VaccinationDto.OTHER_VACCINE_MANUFACTURER) diff --git a/sormas-ui/src/main/webapp/VAADIN/themes/sormas/global.scss b/sormas-ui/src/main/webapp/VAADIN/themes/sormas/global.scss index 7bbb350e92b..6e6c108f8eb 100644 --- a/sormas-ui/src/main/webapp/VAADIN/themes/sormas/global.scss +++ b/sormas-ui/src/main/webapp/VAADIN/themes/sormas/global.scss @@ -186,6 +186,9 @@ .vspace-top-5 { margin-top: 2px; } + .vspace-top-6 { + margin-top: -8px; + } .vspace-top-none { margin-top: 0 !important; } @@ -208,6 +211,9 @@ .hspace-left-5 { margin-left: 2px; } + .hspace-left-6 { + margin-left: -50px; + } .hspace-left-none { margin-left: 0 !important; } diff --git a/sormas-ui/src/main/webapp/WEB-INF/glassfish-web.xml b/sormas-ui/src/main/webapp/WEB-INF/glassfish-web.xml index 45e701e5bb7..6f71704550d 100644 --- a/sormas-ui/src/main/webapp/WEB-INF/glassfish-web.xml +++ b/sormas-ui/src/main/webapp/WEB-INF/glassfish-web.xml @@ -896,6 +896,21 @@ ENVIRONMENT_SAMPLE_EXPORT + + ENVIRONMENT_PATHOGEN_TEST_CREATE + ENVIRONMENT_PATHOGEN_TEST_CREATE + + + + ENVIRONMENT_PATHOGEN_TEST_EDIT + ENVIRONMENT_PATHOGEN_TEST_EDIT + + + + ENVIRONMENT_PATHOGEN_TEST_DELETE + ENVIRONMENT_PATHOGEN_TEST_DELETE + + DOCUMENT_VIEW DOCUMENT_VIEW diff --git a/sormas-ui/src/main/webapp/WEB-INF/web.xml b/sormas-ui/src/main/webapp/WEB-INF/web.xml index c43f9b10a09..dcea91747d4 100644 --- a/sormas-ui/src/main/webapp/WEB-INF/web.xml +++ b/sormas-ui/src/main/webapp/WEB-INF/web.xml @@ -729,6 +729,18 @@ ENVIRONMENT_SAMPLE_EXPORT + + ENVIRONMENT_PATHOGEN_TEST_CREATE + + + + ENVIRONMENT_PATHOGEN_TEST_EDIT + + + + ENVIRONMENT_PATHOGEN_TEST_DELETE + + DOCUMENT_VIEW diff --git a/sormas-widgetset/pom.xml b/sormas-widgetset/pom.xml index f9ada62161e..b0c92535cee 100644 --- a/sormas-widgetset/pom.xml +++ b/sormas-widgetset/pom.xml @@ -3,7 +3,7 @@ sormas-base de.symeda.sormas - 1.93.0 + 1.94.0 ../sormas-base 4.0.0