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 e76d6fed286..10e1b1012b8 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 @@ -1204,6 +1204,7 @@ public interface Strings { String messageCaseTransfered = "messageCaseTransfered"; String messageChangePathogenTestResult = "messageChangePathogenTestResult"; String messageChangingCaseOutcome = "messageChangingCaseOutcome"; + String messageChangingPersonPresentCondition = "messageChangingPersonPresentCondition"; String messageCheckInputData = "messageCheckInputData"; String messageClinicalCourseSaved = "messageClinicalCourseSaved"; String messageClinicalVisitCreated = "messageClinicalVisitCreated"; diff --git a/sormas-api/src/main/resources/strings.properties b/sormas-api/src/main/resources/strings.properties index e7b735a272c..551b80be742 100644 --- a/sormas-api/src/main/resources/strings.properties +++ b/sormas-api/src/main/resources/strings.properties @@ -1575,6 +1575,7 @@ messageSyncUsersFromAuthProviderConfigurationError=Syncing users from authentica 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: +messageChangingPersonPresentCondition = Changing this information will also affect the associated cases. # Notifications notificationCaseClassificationChanged = The classification of case %s has changed to %s. diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonController.java index 88f53a0b9e9..1a7ad87d03d 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonController.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonController.java @@ -19,6 +19,8 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Map; @@ -29,13 +31,16 @@ import org.apache.commons.lang3.StringUtils; +import com.vaadin.icons.VaadinIcons; import com.vaadin.navigator.Navigator; import com.vaadin.server.Page; +import com.vaadin.server.Sizeable; import com.vaadin.server.Sizeable.Unit; import com.vaadin.shared.ui.ContentMode; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.Grid; +import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.Notification; import com.vaadin.ui.Notification.Type; @@ -48,6 +53,8 @@ import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.caze.CaseClassification; +import de.symeda.sormas.api.caze.CaseDataDto; +import de.symeda.sormas.api.caze.CaseOutcome; import de.symeda.sormas.api.event.EventParticipantSelectionDto; import de.symeda.sormas.api.event.EventReferenceDto; import de.symeda.sormas.api.externaljournal.ExternalJournalSyncResponseDto; @@ -55,6 +62,7 @@ import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; import de.symeda.sormas.api.i18n.Validations; +import de.symeda.sormas.api.person.CauseOfDeath; import de.symeda.sormas.api.person.PersonContext; import de.symeda.sormas.api.person.PersonCriteria; import de.symeda.sormas.api.person.PersonDto; @@ -62,6 +70,7 @@ import de.symeda.sormas.api.person.PersonHelper; import de.symeda.sormas.api.person.PersonIndexDto; import de.symeda.sormas.api.person.PersonReferenceDto; +import de.symeda.sormas.api.person.PresentCondition; import de.symeda.sormas.api.person.SimilarPersonDto; import de.symeda.sormas.api.user.UserRight; import de.symeda.sormas.api.utils.DataHelper; @@ -75,6 +84,8 @@ import de.symeda.sormas.ui.utils.ButtonHelper; import de.symeda.sormas.ui.utils.CommitDiscardWrapperComponent; import de.symeda.sormas.ui.utils.ConfirmationComponent; +import de.symeda.sormas.ui.utils.CssStyles; +import de.symeda.sormas.ui.utils.DateFormatHelper; import de.symeda.sormas.ui.utils.VaadinUiUtil; import de.symeda.sormas.ui.utils.ViewMode; import de.symeda.sormas.ui.utils.components.page.title.TitleLayout; @@ -418,7 +429,7 @@ public CommitDiscardWrapperComponent getPersonEditComponent(Stri editView.addCommitListener(() -> { if (!editForm.getFieldGroup().isModified()) { PersonDto dto = editForm.getValue(); - savePerson(dto); + savePersonWithPersonConditionChanged(dto); } }); @@ -443,7 +454,7 @@ public CommitDiscardWrapperComponent getPersonEditComponent( editView.addCommitListener(() -> { if (!editForm.getFieldGroup().isModified()) { PersonDto dto = editForm.getValue(); - savePerson(dto); + savePersonWithPersonConditionChanged(dto); } }); @@ -478,9 +489,9 @@ public CommitDiscardWrapperComponent getPersonEditComponent( CommitDiscardWrapperComponent content = (CommitDiscardWrapperComponent) editView.getWrappedComponent().getWarningSimilarPersons().getContent(); content.getDiscardButton().setVisible(true); - content.addCommitListener(() -> savePerson(dto)); + content.addCommitListener(() -> savePersonWithPersonConditionChanged(dto)); } else { - savePerson(dto); + savePersonWithPersonConditionChanged(dto); } } }); @@ -488,6 +499,112 @@ public CommitDiscardWrapperComponent getPersonEditComponent( return editView; } + private void savePersonWithPersonConditionChanged(PersonDto editedPerson) { + PersonDto initialPerson = personFacade.getByUuid(editedPerson.getUuid()); + PresentCondition initialPresentCondition = initialPerson.getPresentCondition(); + + CaseDataDto lastCase; + if (editedPerson.getCauseOfDeathDisease() != null) { + List personCases = FacadeProvider.getCaseFacade() + .getAllCasesOfPerson(editedPerson.getUuid()) + .stream() + .filter(caseDataDto -> caseDataDto.getDisease().equals(editedPerson.getCauseOfDeathDisease())) + .collect(Collectors.toList()); + lastCase = Collections.max(personCases, Comparator.comparing(CaseDataDto::getReportDate)); + } else { + lastCase = null; + } + + PresentCondition editedPresentCondition = editedPerson.getPresentCondition(); + if (lastCase != null + && (Arrays.asList(PresentCondition.BURIED, PresentCondition.DEAD).contains(editedPresentCondition)) + && !(Arrays.asList(PresentCondition.BURIED, PresentCondition.DEAD).contains(initialPresentCondition)) + && editedPerson.getCauseOfDeath().equals(CauseOfDeath.EPIDEMIC_DISEASE)) { + + if (lastCase.getOutcome().equals(CaseOutcome.DECEASED) + && editedPerson.getDeathDate() != null + && editedPerson.getDeathDate().equals(lastCase.getOutcomeDate())) { + savePerson(editedPerson); + return; + } else { + 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.messageChangingPersonPresentCondition)); + CssStyles.style(infoLabel, CssStyles.LABEL_LARGE, CssStyles.LABEL_WHITE_SPACE_NORMAL); + warningLayout.addComponent(infoLabel); + + // case information + warningLayout.addComponent(new Label(lastCase.buildCaption())); + + // 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(CaseDataDto.I18N_PREFIX, CaseDataDto.OUTCOME))); + fieldsLayout.addComponent(new Label(I18nProperties.getPrefixCaption(CaseDataDto.I18N_PREFIX, CaseDataDto.OUTCOME_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)); + + 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(CaseOutcome.DECEASED.toString())); + valuesLayout.addComponent(new Label(DateFormatHelper.formatDate(editedPerson.getDeathDate()))); + + changesLayout.addComponent(fieldsLayout); + changesLayout.addComponent(arrowsLayout); + changesLayout.addComponent(valuesLayout); + warningLayout.addComponent(changesLayout); + + // actions + warningComponent.addCommitListener(() -> { + savePerson(editedPerson); + lastCase.setOutcome(CaseOutcome.DECEASED); + if (editedPerson.getDeathDate() != null) { + lastCase.setOutcomeDate(editedPerson.getDeathDate()); + } + FacadeProvider.getCaseFacade().save(lastCase); + popupWindow.close(); + }); + + warningComponent.addDiscardListener(() -> popupWindow.close()); + + // popup configuration + popupWindow.addCloseListener(e -> popupWindow.close()); + popupWindow.setWidth(600, Sizeable.Unit.PIXELS); + + return; + } + +// savePerson(editedPerson); + } + + savePerson(editedPerson); + } + private void savePerson(PersonDto personDto) { DataHelper.Pair saveResult = personFacade.savePersonWithoutNotifyingExternalJournal(personDto);