From b9a38bb0138120d743571d3478133458cc973fa4 Mon Sep 17 00:00:00 2001 From: Karnaiah Pesula Date: Mon, 4 May 2026 12:47:56 +0200 Subject: [PATCH 1/3] Not allowing disease variant to update, if it is used in any case. Otherwise user will see the unwanted error message while opening the case/case management. --- .../symeda/sormas/api/i18n/Validations.java | 1 + .../src/main/resources/validations.properties | 1 + .../CustomizableEnumFacadeEjb.java | 15 +++++++++- .../CustomizableEnumValueService.java | 28 +++++++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) 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 3a6f7e6d1a4..08b0b796a8e 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 @@ -51,6 +51,7 @@ public interface Validations { String contactFollowUpUntilDateSoftValidation = "contactFollowUpUntilDateSoftValidation"; String contactWithoutInfrastructureData = "contactWithoutInfrastructureData"; String customizableEnumValueAllowedCharacters = "customizableEnumValueAllowedCharacters"; + String customizableEnumValueAlreadyInUse = "customizableEnumValueAlreadyInUse"; String customizableEnumValueDuplicateLanguage = "customizableEnumValueDuplicateLanguage"; String customizableEnumValueDuplicateValue = "customizableEnumValueDuplicateValue"; String customizableEnumValueEmptyTranslations = "customizableEnumValueEmptyTranslations"; diff --git a/sormas-api/src/main/resources/validations.properties b/sormas-api/src/main/resources/validations.properties index 00c7618f90e..82c3062fdf8 100644 --- a/sormas-api/src/main/resources/validations.properties +++ b/sormas-api/src/main/resources/validations.properties @@ -332,3 +332,4 @@ smsAuthKeyValueValidation = SMS Auth key value is not valid smsAuthSecretValueValidation = SMS Auth secret value is not valid systemConfigurationValueValidationInvalidBackgroundColor = Pre-defined values are: green, red, indigo, gray, default (case-sensitive) otherwise must match hexadecimal format (with or without hash "#"), example: #dd2b0e or #4AA or dd2b0e systemConfigurationValueValidationMenuSubtitle = Can be empty or up to 16 (any) characters. Can be used to define name of the environment: PRODUCTION - TEST etc. +customizableEnumValueAlreadyInUse = The customizable value %s is using for %s case(s) and cannot be deleted or deactivated. Please update all references to this value before trying again. 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 0705c1f1f4e..46dc5758d82 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 @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -168,7 +169,19 @@ public CustomizableEnumValueDto save(CustomizableEnumValueDto dto) { validate(dto); CustomizableEnumValue existingEntity = service.getByUuid(dto.getUuid()); - + // if existingEntity disease removed and it is mapped to the cases, shouldn't allow to save the entity + if (existingEntity != null && CollectionUtils.isNotEmpty(existingEntity.getDiseases()) && CollectionUtils.isNotEmpty(dto.getDiseases())) { + existingEntity.getDiseases().stream().filter(disease -> !dto.getDiseases().contains(disease)).findAny().ifPresent(disease -> { + List uuids = service.areCasesUsingCustomizableEnumValue(disease, getEnumValue(dto.getDataType(), disease, dto.getValue())); + if (!uuids.isEmpty()) { + throw new ValidationRuntimeException( + I18nProperties.getValidationError( + Validations.customizableEnumValueAlreadyInUse, + disease.getName(), + uuids.stream().filter(Objects::nonNull).collect(Collectors.joining(", ")))); + } + }); + } for (Disease disease : dto.getDiseases()) { List dataTypeValues = enumValues.get(dto.getDataType()).getOrDefault(disease, Collections.emptyList()); if (existingEntity == null && dataTypeValues != null && dataTypeValues.contains(dto.getValue())) { 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 f5e5bff9aad..754769bd407 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 @@ -15,6 +15,10 @@ package de.symeda.sormas.backend.customizableenum; +import java.util.List; +import java.util.stream.Collectors; + +import javax.ejb.EJB; import javax.ejb.LocalBean; import javax.ejb.Stateless; import javax.persistence.criteria.CriteriaBuilder; @@ -23,8 +27,13 @@ import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.caze.CaseCriteria; import de.symeda.sormas.api.customizableenum.CustomizableEnumCriteria; +import de.symeda.sormas.api.disease.DiseaseVariant; import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.backend.caze.Case; +import de.symeda.sormas.backend.caze.CaseService; import de.symeda.sormas.backend.common.AdoServiceWithUserFilterAndJurisdiction; import de.symeda.sormas.backend.common.CriteriaBuilderHelper; @@ -32,6 +41,9 @@ @LocalBean public class CustomizableEnumValueService extends AdoServiceWithUserFilterAndJurisdiction { + @EJB + private CaseService caseService; + public CustomizableEnumValueService() { super(CustomizableEnumValue.class); } @@ -70,4 +82,20 @@ public Predicate buildCriteriaFilter(CustomizableEnumCriteria criteria, Criteria return filter; } + /** + * Get all cases for a specific disease and disease variant that are using a customizable enum value. This is used to determine whether + * a customizable enum value can be deleted or not. + * + * @param disease + * @param diseaseVariant + * @return + */ + public List areCasesUsingCustomizableEnumValue(Disease disease, DiseaseVariant diseaseVariant) { + CaseCriteria caseCriteria = new CaseCriteria(); + caseCriteria.setDisease(disease); + caseCriteria.setDiseaseVariant(diseaseVariant); + List result = caseService.findBy(caseCriteria, false); + return result.stream().map(Case::getUuid).collect(Collectors.toList()); + } + } From d44c76cca796f2a6ef313edd51e724a77ff3a456 Mon Sep 17 00:00:00 2001 From: Karnaiah Pesula Date: Wed, 6 May 2026 11:59:48 +0200 Subject: [PATCH 2/3] Updated the validation message. --- sormas-api/src/main/resources/validations.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sormas-api/src/main/resources/validations.properties b/sormas-api/src/main/resources/validations.properties index 82c3062fdf8..313b748cf71 100644 --- a/sormas-api/src/main/resources/validations.properties +++ b/sormas-api/src/main/resources/validations.properties @@ -332,4 +332,4 @@ smsAuthKeyValueValidation = SMS Auth key value is not valid smsAuthSecretValueValidation = SMS Auth secret value is not valid systemConfigurationValueValidationInvalidBackgroundColor = Pre-defined values are: green, red, indigo, gray, default (case-sensitive) otherwise must match hexadecimal format (with or without hash "#"), example: #dd2b0e or #4AA or dd2b0e systemConfigurationValueValidationMenuSubtitle = Can be empty or up to 16 (any) characters. Can be used to define name of the environment: PRODUCTION - TEST etc. -customizableEnumValueAlreadyInUse = The customizable value %s is using for %s case(s) and cannot be deleted or deactivated. Please update all references to this value before trying again. +customizableEnumValueAlreadyInUse = The customizable value %s is being used for %s case(IDs) and therefore cannot be deleted or deactivated. Please remove all references to this value before attempting to deactivate. From 81acf7b86ac545119ff498f064174d84bc34d979 Mon Sep 17 00:00:00 2001 From: Karnaiah Pesula Date: Wed, 6 May 2026 12:49:39 +0200 Subject: [PATCH 3/3] fixed the possible issues. --- .../src/main/resources/validations.properties | 2 +- .../CustomizableEnumFacadeEjb.java | 27 ++++++++++++------- .../CustomizableEnumValueService.java | 2 +- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/sormas-api/src/main/resources/validations.properties b/sormas-api/src/main/resources/validations.properties index 313b748cf71..c6eb627c51e 100644 --- a/sormas-api/src/main/resources/validations.properties +++ b/sormas-api/src/main/resources/validations.properties @@ -332,4 +332,4 @@ smsAuthKeyValueValidation = SMS Auth key value is not valid smsAuthSecretValueValidation = SMS Auth secret value is not valid systemConfigurationValueValidationInvalidBackgroundColor = Pre-defined values are: green, red, indigo, gray, default (case-sensitive) otherwise must match hexadecimal format (with or without hash "#"), example: #dd2b0e or #4AA or dd2b0e systemConfigurationValueValidationMenuSubtitle = Can be empty or up to 16 (any) characters. Can be used to define name of the environment: PRODUCTION - TEST etc. -customizableEnumValueAlreadyInUse = The customizable value %s is being used for %s case(IDs) and therefore cannot be deleted or deactivated. Please remove all references to this value before attempting to deactivate. +customizableEnumValueAlreadyInUse = The customizable value %s is being used by case IDs %s and therefore cannot be deleted or deactivated. Please remove all references to this value before attempting to deactivate. 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 46dc5758d82..2c4b8b0f3c8 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 @@ -170,18 +170,25 @@ public CustomizableEnumValueDto save(CustomizableEnumValueDto dto) { CustomizableEnumValue existingEntity = service.getByUuid(dto.getUuid()); // if existingEntity disease removed and it is mapped to the cases, shouldn't allow to save the entity - if (existingEntity != null && CollectionUtils.isNotEmpty(existingEntity.getDiseases()) && CollectionUtils.isNotEmpty(dto.getDiseases())) { - existingEntity.getDiseases().stream().filter(disease -> !dto.getDiseases().contains(disease)).findAny().ifPresent(disease -> { - List uuids = service.areCasesUsingCustomizableEnumValue(disease, getEnumValue(dto.getDataType(), disease, dto.getValue())); - if (!uuids.isEmpty()) { - throw new ValidationRuntimeException( - I18nProperties.getValidationError( - Validations.customizableEnumValueAlreadyInUse, - disease.getName(), - uuids.stream().filter(Objects::nonNull).collect(Collectors.joining(", ")))); + + if (existingEntity != null && CollectionUtils.isNotEmpty(existingEntity.getDiseases())) { + Set incomingDiseases = dto.getDiseases() != null ? dto.getDiseases() : Collections.emptySet(); + for (Disease removedDisease : existingEntity.getDiseases()) { + if (!incomingDiseases.contains(removedDisease)) { + List uuids = service.areCasesUsingCustomizableEnumValue( + removedDisease, + getEnumValue(dto.getDataType(), removedDisease, existingEntity.getValue())); + if (!uuids.isEmpty()) { + throw new ValidationRuntimeException( + I18nProperties.getValidationError( + Validations.customizableEnumValueAlreadyInUse, + removedDisease.getName(), + uuids.stream().filter(Objects::nonNull).collect(Collectors.joining(", ")))); + } } - }); + } } + for (Disease disease : dto.getDiseases()) { List dataTypeValues = enumValues.get(dto.getDataType()).getOrDefault(disease, Collections.emptyList()); if (existingEntity == null && dataTypeValues != null && dataTypeValues.contains(dto.getValue())) { 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 754769bd407..4f0b6574ea5 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 @@ -94,7 +94,7 @@ public List areCasesUsingCustomizableEnumValue(Disease disease, DiseaseV CaseCriteria caseCriteria = new CaseCriteria(); caseCriteria.setDisease(disease); caseCriteria.setDiseaseVariant(diseaseVariant); - List result = caseService.findBy(caseCriteria, false); + List result = caseService.findBy(caseCriteria, true); return result.stream().map(Case::getUuid).collect(Collectors.toList()); }