From be146e45a069a7cba007cf204220957280b7c4ca Mon Sep 17 00:00:00 2001 From: Levente Gal Date: Tue, 14 Jan 2025 14:22:24 +0200 Subject: [PATCH] #13209 Update Person when case outcome is changed to "Deceased" --- .../de/symeda/sormas/api/i18n/Captions.java | 2 + .../de/symeda/sormas/api/i18n/Strings.java | 3 + .../src/main/resources/captions.properties | 3 + .../src/main/resources/strings.properties | 3 + .../symeda/sormas/ui/caze/CaseController.java | 101 +++++++++++++++++- .../SurveillanceReportList.java | 2 + 6 files changed, 110 insertions(+), 4 deletions(-) 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 1862ce0ba60..97b1c0b1654 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 @@ -972,6 +972,8 @@ public interface Captions { String Configuration_LineListing = "Configuration.LineListing"; String Configuration_Outbreaks = "Configuration.Outbreaks"; String Configuration_PointsOfEntry = "Configuration.PointsOfEntry"; + String confirmChangesField = "confirmChangesField"; + String confirmChangesValue = "confirmChangesValue"; String Contact = "Contact"; String Contact_additionalDetails = "Contact.additionalDetails"; String Contact_ageAndBirthDate = "Contact.ageAndBirthDate"; 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 20a31f30878..e76d6fed286 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 @@ -1203,6 +1203,7 @@ public interface Strings { String messageCasesRestored = "messageCasesRestored"; String messageCaseTransfered = "messageCaseTransfered"; String messageChangePathogenTestResult = "messageChangePathogenTestResult"; + String messageChangingCaseOutcome = "messageChangingCaseOutcome"; String messageCheckInputData = "messageCheckInputData"; String messageClinicalCourseSaved = "messageClinicalCourseSaved"; String messageClinicalVisitCreated = "messageClinicalVisitCreated"; @@ -1509,6 +1510,7 @@ public interface Strings { String messageRelatedSampleAndLabMessagesFound = "messageRelatedSampleAndLabMessagesFound"; String messageRelatedSampleFound = "messageRelatedSampleFound"; String messageRestoreNotPossibleAlreadyInEvent = "messageRestoreNotPossibleAlreadyInEvent"; + String messageReviewChangesAndConfirm = "messageReviewChangesAndConfirm"; String messageSampleErrors = "messageSampleErrors"; String messageSampleOpened = "messageSampleOpened"; String messageSampleSaved = "messageSampleSaved"; @@ -1819,6 +1821,7 @@ public interface Strings { String unsavedChanges_warningTitle = "unsavedChanges.warningTitle"; String until = "until"; String uuidOf = "uuidOf"; + String warning = "warning"; String warningDashboardMapTooManyMarkers = "warningDashboardMapTooManyMarkers"; String warningNetworkDiagramTooManyContacts = "warningNetworkDiagramTooManyContacts"; String week = "week"; diff --git a/sormas-api/src/main/resources/captions.properties b/sormas-api/src/main/resources/captions.properties index 815de5ffe31..d1debee0d62 100644 --- a/sormas-api/src/main/resources/captions.properties +++ b/sormas-api/src/main/resources/captions.properties @@ -3392,3 +3392,6 @@ selfReportDeletedEnvironments=Deleted self reports selfReportSelfReportsList=Self reports list selfReportProcess=Process +confirmChangesField=Field: +confirmChangesValue=Will be changed to: + diff --git a/sormas-api/src/main/resources/strings.properties b/sormas-api/src/main/resources/strings.properties index b091bed4353..e7b735a272c 100644 --- a/sormas-api/src/main/resources/strings.properties +++ b/sormas-api/src/main/resources/strings.properties @@ -85,6 +85,7 @@ nameOf = Name of %s uuidOf = UUID of %s listOf = List of %s mapOf = Map of <%s , %s> +warning = Warning # Aggregate Report aggregateReportLegend = %s = %s; %s = %s; %s = %s @@ -1572,6 +1573,8 @@ messageAdverseEventInvestigationSaved=Adverse event investigation saved messagePersonNationalHealthIdInvalid=The entered national health ID does not seem to be correct messageSyncUsersFromAuthProviderConfigurationError=Syncing users from authentication provider is not possible because the configuration is incorrect. Please contact an admin and inform them about this issue. messageCountriesExcludedFromDataProtection=Countries excluded from data protection for this field: +messageChangingCaseOutcome=Changing this information will also affect the associated person. +messageReviewChangesAndConfirm=Please review the changes and confirm them: # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. 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 2c0b8db9493..3d293a30e35 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 @@ -27,6 +27,7 @@ import org.apache.commons.collections4.CollectionUtils; +import com.vaadin.icons.VaadinIcons; import com.vaadin.navigator.Navigator; import com.vaadin.server.ExternalResource; import com.vaadin.server.Page; @@ -61,6 +62,7 @@ import de.symeda.sormas.api.caze.CaseIndexDto; import de.symeda.sormas.api.caze.CaseLogic; import de.symeda.sormas.api.caze.CaseOrigin; +import de.symeda.sormas.api.caze.CaseOutcome; import de.symeda.sormas.api.caze.CaseSelectionDto; import de.symeda.sormas.api.caze.CaseSimilarityCriteria; import de.symeda.sormas.api.caze.classification.ClassificationHtmlRenderer; @@ -97,8 +99,10 @@ import de.symeda.sormas.api.infrastructure.pointofentry.PointOfEntryDto; import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto; import de.symeda.sormas.api.messaging.MessageType; +import de.symeda.sormas.api.person.CauseOfDeath; import de.symeda.sormas.api.person.PersonDto; import de.symeda.sormas.api.person.PersonReferenceDto; +import de.symeda.sormas.api.person.PresentCondition; import de.symeda.sormas.api.symptoms.SymptomsContext; import de.symeda.sormas.api.symptoms.SymptomsDto; import de.symeda.sormas.api.symptoms.SymptomsHelper; @@ -139,6 +143,7 @@ import de.symeda.sormas.ui.utils.ButtonHelper; import de.symeda.sormas.ui.utils.CommitDiscardWrapperComponent; import de.symeda.sormas.ui.utils.CssStyles; +import de.symeda.sormas.ui.utils.DateFormatHelper; import de.symeda.sormas.ui.utils.DeleteRestoreHandlers; import de.symeda.sormas.ui.utils.DetailSubComponentWrapper; import de.symeda.sormas.ui.utils.FieldAccessHelper; @@ -1442,13 +1447,13 @@ public void saveCaseWithFacilityChangedPrompt(CaseDataDto caze, CaseDataDto oldC switch (option) { case OPTION1: { caze.getHospitalization().setAdmittedToHealthFacility((YesNoUnknown) admittedToHealthFacilityField.getNullableValue()); - saveCase(caze); + saveCaseWithOutcomeChangedWarning(caze, oldCase); ControllerProvider.getCaseController().navigateToView(HospitalizationView.VIEW_NAME, caze.getUuid(), null); } break; case OPTION2: { caze.getHospitalization().setAdmittedToHealthFacility((YesNoUnknown) admittedToHealthFacilityField.getNullableValue()); - saveCase(caze); + saveCaseWithOutcomeChangedWarning(caze, oldCase); ControllerProvider.getCaseController().navigateToView(CaseDataView.VIEW_NAME, caze.getUuid(), null); } break; @@ -1468,12 +1473,100 @@ public void saveCaseWithFacilityChangedPrompt(CaseDataDto caze, CaseDataDto oldC 500, e -> { CaseLogic.handleHospitalization(caze, oldCase, e.booleanValue()); - saveCase(caze); + saveCaseWithOutcomeChangedWarning(caze, oldCase); SormasUI.refreshView(); }); } else { - saveCase(caze); + saveCaseWithOutcomeChangedWarning(caze, oldCase); + } + } + + private void saveCaseWithOutcomeChangedWarning(CaseDataDto caze, CaseDataDto oldCase) { + PersonDto person = FacadeProvider.getPersonFacade().getByUuid(caze.getPerson().getUuid()); + PresentCondition presentCondition = person.getPresentCondition(); + if (caze.getOutcome() == CaseOutcome.DECEASED + && oldCase.getOutcome() != CaseOutcome.DECEASED + && presentCondition != PresentCondition.DEAD + && presentCondition != PresentCondition.BURIED) { + + if (!DataHelper.equal(person.getDeathDate(), caze.getOutcomeDate()) + || !DataHelper.equal(person.getCauseOfDeath(), CauseOfDeath.EPIDEMIC_DISEASE) + || !DataHelper.equal(person.getCauseOfDeathDisease(), caze.getDisease())) { + VerticalLayout warningLayout = new VerticalLayout(); + warningLayout.setSpacing(false); + CommitDiscardWrapperComponent warningComponent = new CommitDiscardWrapperComponent<>(warningLayout); + warningComponent.setWidth(100, Unit.PERCENTAGE); + + Window popupWindow = VaadinUiUtil.showPopupWindow(warningComponent, I18nProperties.getString(Strings.warning)); + Label infoLabel = new Label(I18nProperties.getString(Strings.messageChangingCaseOutcome)); + CssStyles.style(infoLabel, CssStyles.LABEL_LARGE, CssStyles.LABEL_WHITE_SPACE_NORMAL); + warningLayout.addComponent(infoLabel); + + // Person information + warningLayout.addComponent(new Label(person.buildCaption() + " - " + person.getUuid())); + + // confirmation message + Label confirmationMessage = new Label(I18nProperties.getString(Strings.messageReviewChangesAndConfirm)); + confirmationMessage.addStyleName(CssStyles.VSPACE_TOP_3); + warningLayout.addComponent(confirmationMessage); + + // changes listed + HorizontalLayout changesLayout = new HorizontalLayout(); + changesLayout.setMargin(false); + changesLayout.addStyleNames(CssStyles.VSPACE_TOP_1, CssStyles.VSPACE_2); + + VerticalLayout fieldsLayout = new VerticalLayout(); + fieldsLayout.setMargin(false); + + Label fieldsLabel = new Label(I18nProperties.getCaption(Captions.confirmChangesField)); + fieldsLayout.addComponent(fieldsLabel); + fieldsLabel.addStyleName(CssStyles.LABEL_SECONDARY); + fieldsLayout.addComponent(new Label(I18nProperties.getPrefixCaption(PersonDto.I18N_PREFIX, PersonDto.PRESENT_CONDITION))); + fieldsLayout.addComponent(new Label(I18nProperties.getPrefixCaption(PersonDto.I18N_PREFIX, PersonDto.CAUSE_OF_DEATH))); + fieldsLayout.addComponent(new Label(I18nProperties.getPrefixCaption(PersonDto.I18N_PREFIX, PersonDto.CAUSE_OF_DEATH_DISEASE))); + fieldsLayout.addComponent(new Label(I18nProperties.getPrefixCaption(PersonDto.I18N_PREFIX, PersonDto.DEATH_DATE))); + + VerticalLayout arrowsLayout = new VerticalLayout(); + arrowsLayout.setMargin(false); + + arrowsLayout.addComponent(new Label()); + arrowsLayout.addComponent(new Label(VaadinIcons.ARROW_RIGHT.getHtml(), ContentMode.HTML)); + arrowsLayout.addComponent(new Label(VaadinIcons.ARROW_RIGHT.getHtml(), ContentMode.HTML)); + arrowsLayout.addComponent(new Label(VaadinIcons.ARROW_RIGHT.getHtml(), ContentMode.HTML)); + arrowsLayout.addComponent(new Label(VaadinIcons.ARROW_RIGHT.getHtml(), ContentMode.HTML)); + + VerticalLayout valuesLayout = new VerticalLayout(); + valuesLayout.setMargin(false); + + Label valuesLabel = new Label(I18nProperties.getCaption(Captions.confirmChangesValue)); + valuesLabel.addStyleName(CssStyles.LABEL_SECONDARY); + valuesLayout.addComponent(valuesLabel); + valuesLayout.addComponent( + new Label((person.getPresentCondition() == null ? PresentCondition.DEAD : person.getPresentCondition()).toString())); + valuesLayout.addComponent(new Label(CauseOfDeath.EPIDEMIC_DISEASE.toString())); + valuesLayout.addComponent(new Label(caze.getDisease().toString())); + valuesLayout.addComponent(new Label(DateFormatHelper.formatDate(caze.getOutcomeDate()))); + + changesLayout.addComponent(fieldsLayout); + changesLayout.addComponent(arrowsLayout); + changesLayout.addComponent(valuesLayout); + warningLayout.addComponent(changesLayout); + + // actions + warningComponent.addCommitListener(() -> { + saveCase(caze); + popupWindow.close(); + }); + warningComponent.addDiscardListener(() -> popupWindow.close()); + + // popup configuration + popupWindow.addCloseListener(e -> popupWindow.close()); + popupWindow.setWidth(600, Sizeable.Unit.PIXELS); + + return; + } } + saveCase(caze); } public void referFromPointOfEntry(CaseDataDto caze) { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/surveillancereport/SurveillanceReportList.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/surveillancereport/SurveillanceReportList.java index 9ca92f682cc..cd878124bff 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/surveillancereport/SurveillanceReportList.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/surveillancereport/SurveillanceReportList.java @@ -189,6 +189,7 @@ private HorizontalLayout createRow(@Null String label, Object value, String prop HorizontalLayout row = new HorizontalLayout(); row.setMargin(false); row.setSpacing(false); + row.setWidth(100, Unit.PERCENTAGE); if (label != null) { Label rowLabel = new Label(DataHelper.toStringNullable(label) + ":"); @@ -197,6 +198,7 @@ private HorizontalLayout createRow(@Null String label, Object value, String prop } Label rowValue = new Label(DataHelper.toStringNullable(value)); + rowValue.addStyleName(CssStyles.LABEL_WHITE_SPACE_NORMAL); if (!fieldAccessCheckers.isAccessible(SurveillanceReportDto.class, propertyId)) { rowValue.addStyleName(CssStyles.INACCESSIBLE_LABEL); }