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..c6eb627c51e 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 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 0705c1f1f4e..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 @@ -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,6 +169,25 @@ 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())) { + 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()); 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..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 @@ -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, true); + return result.stream().map(Case::getUuid).collect(Collectors.toList()); + } + }