From 24b5234ea4feb3fe711efc8673a551babf84975b Mon Sep 17 00:00:00 2001 From: Obinna Henry <55580796+obinna-h-n@users.noreply.github.com> Date: Sat, 17 Feb 2024 18:33:34 +0100 Subject: [PATCH 1/5] #12634 - Started development of AEFI module - #12728 - Added a new AEFI entity, related entities, dto's and enumerations - #12772 - Added AEFI user rights - #12767 - Added an AEFI directory for the web app - #12769 - Added a create/edit form for AEFI in the web app - #12976 - Added a basic AEFI dashboard --- .../de/symeda/sormas/api/FacadeProvider.java | 10 + .../AdverseEventState.java | 33 + .../AdverseEventsDto.java | 186 ++++++ .../AefiAgeGroup.java | 35 + .../AefiCriteria.java | 232 +++++++ .../AefiDashboardFilterDateType.java | 32 + .../AefiDateType.java | 33 + .../AefiDto.java | 614 ++++++++++++++++++ .../AefiFacade.java | 31 + .../AefiHelper.java | 87 +++ .../AefiIndexDto.java | 277 ++++++++ .../AefiListCriteria.java | 48 ++ .../AefiListEntryDto.java | 97 +++ .../AefiOutcome.java | 36 + .../AefiReferenceDto.java | 45 ++ .../AefiType.java | 41 ++ .../SeizureType.java | 32 + .../SeriousAefiReason.java | 36 + .../api/common/DeletableEntityType.java | 1 + .../api/dashboard/AefiDashboardCriteria.java | 49 ++ .../AefiChartData.java | 58 ++ .../AefiChartSeries.java | 61 ++ .../AefiDashboardFacade.java | 44 ++ .../MapAefiDto.java | 78 +++ .../sormas/api/feature/FeatureType.java | 1 + .../de/symeda/sormas/api/i18n/Captions.java | 106 +++ .../symeda/sormas/api/i18n/Descriptions.java | 3 + .../de/symeda/sormas/api/i18n/Strings.java | 33 + .../symeda/sormas/api/i18n/Validations.java | 3 + .../de/symeda/sormas/api/user/UserRight.java | 13 + .../sormas/api/user/UserRightGroup.java | 1 + .../src/main/resources/captions.properties | 112 ++++ .../main/resources/descriptions.properties | 6 +- sormas-api/src/main/resources/enum.properties | 52 ++ .../src/main/resources/strings.properties | 42 +- .../src/main/resources/validations.properties | 3 + .../AdverseEventsMapper.java | 82 +++ .../AefiFacadeEjb.java | 455 +++++++++++++ .../AefiJurisdictionPredicateValidator.java | 108 +++ .../AefiQueryContext.java | 45 ++ .../AefiService.java | 521 +++++++++++++++ .../entity/AdverseEvents.java | 179 +++++ .../entity/Aefi.java | 606 +++++++++++++++++ .../entity/AefiJoins.java | 162 +++++ .../AefiIndexDtoResultTransformer.java | 86 +++ .../AefiListEntryDtoResultTransformer.java | 60 ++ .../AefiDashboardFacadeEjb.java | 76 +++ .../AefiDashboardService.java | 515 +++++++++++++++ .../immunization/ImmunizationService.java | 21 + .../main/resources/META-INF/persistence.xml | 3 + .../symeda/sormas/ui/ControllerProvider.java | 7 + .../java/de/symeda/sormas/ui/MainScreen.java | 24 +- .../AbstractAefiView.java | 115 ++++ .../AefiController.java | 195 ++++++ .../AefiDataView.java | 128 ++++ .../AefiView.java | 208 ++++++ .../aefilink/AefiList.java | 89 +++ .../aefilink/AefiListComponent.java | 56 ++ .../aefilink/AefiListEntry.java | 79 +++ .../components/directory/AefiDataLayout.java | 42 ++ .../components/directory/AefiFilterForm.java | 420 ++++++++++++ .../directory/AefiFilterFormLayout.java | 53 ++ .../components/directory/AefiGrid.java | 132 ++++ ...imarySuspectVaccinationSelectionField.java | 146 +++++ .../vaccines/AefiVaccinationsField.java | 200 ++++++ .../vaccines/AefiVaccinationsField_2.java | 198 ++++++ .../components/form/AdverseEventsForm.java | 149 +++++ .../components/form/AefiDataForm.java | 303 +++++++++ .../information/AefiImmunizationInfo.java | 109 ++++ .../information/AefiPersonInfo.java | 142 ++++ .../ui/dashboard/AbstractDashboardView.java | 8 + .../ui/dashboard/DashboardController.java | 5 + .../sormas/ui/dashboard/DashboardType.java | 3 +- .../AefiDashboardDataProvider.java | 81 +++ .../AefiDashboardFilterLayout.java | 112 ++++ .../AefiDashboardView.java | 230 +++++++ .../AefiEpiCurveComponent.java | 97 +++ .../components/AefiByVaccineDoseChart.java | 158 +++++ .../components/AefiCountTilesComponent.java | 204 ++++++ .../components/AefiDashboardMapComponent.java | 161 +++++ .../AefiReactionsByGenderChart.java | 166 +++++ .../AefiTypeStatisticsComponent.java | 100 +++ .../AefiTypeStatisticsGroupComponent.java | 64 ++ .../ui/immunization/ImmunizationDataView.java | 20 +- .../sormas/ui/utils/ArchiveHandlers.java | 6 + .../sormas/ui/utils/ArchiveMessages.java | 17 + .../de/symeda/sormas/ui/utils/CssStyles.java | 17 + .../utils/SormasFieldGroupFieldFactory.java | 18 +- .../webapp/VAADIN/themes/sormas/global.scss | 67 ++ 89 files changed, 9812 insertions(+), 7 deletions(-) create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AdverseEventState.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AdverseEventsDto.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiAgeGroup.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiCriteria.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiDashboardFilterDateType.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiDateType.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiDto.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiFacade.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiHelper.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiIndexDto.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiListCriteria.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiListEntryDto.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiOutcome.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiReferenceDto.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiType.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/SeizureType.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/SeriousAefiReason.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/dashboard/AefiDashboardCriteria.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiChartData.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiChartSeries.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiDashboardFacade.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/MapAefiDto.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AdverseEventsMapper.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiFacadeEjb.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiJurisdictionPredicateValidator.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiQueryContext.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiService.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AdverseEvents.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/Aefi.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiJoins.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiIndexDtoResultTransformer.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiListEntryDtoResultTransformer.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/dashboard/adverseeventsfollowingimmunization/AefiDashboardFacadeEjb.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/dashboard/adverseeventsfollowingimmunization/AefiDashboardService.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiView.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiController.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiDataView.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiView.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiList.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiListComponent.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiListEntry.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiDataLayout.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiFilterForm.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiFilterFormLayout.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiGrid.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiPrimarySuspectVaccinationSelectionField.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiVaccinationsField.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiVaccinationsField_2.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/AdverseEventsForm.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/AefiDataForm.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/information/AefiImmunizationInfo.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/information/AefiPersonInfo.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardDataProvider.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardFilterLayout.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardView.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiEpiCurveComponent.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiByVaccineDoseChart.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiCountTilesComponent.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiDashboardMapComponent.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiReactionsByGenderChart.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiTypeStatisticsComponent.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiTypeStatisticsGroupComponent.java diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/FacadeProvider.java b/sormas-api/src/main/java/de/symeda/sormas/api/FacadeProvider.java index e731a9dd8e0..f7570d1c269 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/FacadeProvider.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/FacadeProvider.java @@ -19,6 +19,7 @@ import javax.naming.NamingException; import de.symeda.sormas.api.action.ActionFacade; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiFacade; import de.symeda.sormas.api.audit.AuditLoggerFacade; import de.symeda.sormas.api.bagexport.BAGExportFacade; import de.symeda.sormas.api.campaign.CampaignFacade; @@ -38,6 +39,7 @@ import de.symeda.sormas.api.contact.ContactFacade; import de.symeda.sormas.api.customizableenum.CustomizableEnumFacade; import de.symeda.sormas.api.dashboard.DashboardFacade; +import de.symeda.sormas.api.dashboard.adverseeventsfollowingimmunization.AefiDashboardFacade; import de.symeda.sormas.api.dashboard.sample.SampleDashboardFacade; import de.symeda.sormas.api.deletionconfiguration.DeletionConfigurationFacade; import de.symeda.sormas.api.disease.DiseaseConfigurationFacade; @@ -148,6 +150,10 @@ public static ImmunizationFacade getImmunizationFacade() { return get().lookupEjbRemote(ImmunizationFacade.class); } + public static AefiFacade getAefiFacade() { + return get().lookupEjbRemote(AefiFacade.class); + } + public static VaccinationFacade getVaccinationFacade() { return get().lookupEjbRemote(VaccinationFacade.class); } @@ -320,6 +326,10 @@ public static SampleDashboardFacade getSampleDashboardFacade() { return get().lookupEjbRemote(SampleDashboardFacade.class); } + public static AefiDashboardFacade getAefiDashboardFacade() { + return get().lookupEjbRemote(AefiDashboardFacade.class); + } + public static DiseaseConfigurationFacade getDiseaseConfigurationFacade() { return get().lookupEjbRemote(DiseaseConfigurationFacade.class); } diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AdverseEventState.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AdverseEventState.java new file mode 100644 index 00000000000..73d64393393 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AdverseEventState.java @@ -0,0 +1,33 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum AdverseEventState { + + YES, + NO, + UNKNOWN; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AdverseEventsDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AdverseEventsDto.java new file mode 100644 index 00000000000..94551919c89 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AdverseEventsDto.java @@ -0,0 +1,186 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.feature.FeatureType; +import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.api.utils.DependingOnFeatureType; +import de.symeda.sormas.api.utils.Order; +import de.symeda.sormas.api.utils.pseudonymization.PseudonymizableDto; + +@DependingOnFeatureType(featureType = { + FeatureType.IMMUNIZATION_MANAGEMENT, + FeatureType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_MANAGEMENT }) +public class AdverseEventsDto extends PseudonymizableDto { + + private static final long serialVersionUID = 8081578717541472008L; + + public static final String I18N_PREFIX = "AdverseEvents"; + + public static final String SEVERE_LOCAL_REACTION = "severeLocalReaction"; + public static final String SEVERE_LOCAL_REACTION_MORE_THAN_THREE_DAYS = "severeLocalReactionMoreThanThreeDays"; + public static final String SEVERE_LOCAL_REACTION_BEYOND_NEAREST_JOINT = "severeLocalReactionBeyondNearestJoint"; + public static final String SEIZURES = "seizures"; + public static final String SEIZURE_TYPE = "seizureType"; + public static final String ABSCESS = "abscess"; + public static final String SEPSIS = "sepsis"; + public static final String ENCEPHALOPATHY = "encephalopathy"; + public static final String TOXIC_SHOCK_SYNDROME = "toxicShockSyndrome"; + public static final String THROMBOCYTOPENIA = "thrombocytopenia"; + public static final String ANAPHYLAXIS = "anaphylaxis"; + public static final String FEVERISH_FEELING = "feverishFeeling"; + public static final String OTHER_ADVERSE_EVENT_DETAILS = "otherAdverseEventDetails"; + + private AdverseEventState severeLocalReaction; + private boolean severeLocalReactionMoreThanThreeDays; + private boolean severeLocalReactionBeyondNearestJoint; + private AdverseEventState seizures; + private SeizureType seizureType; + private AdverseEventState abscess; + private AdverseEventState sepsis; + private AdverseEventState encephalopathy; + private AdverseEventState toxicShockSyndrome; + private AdverseEventState thrombocytopenia; + private AdverseEventState anaphylaxis; + private AdverseEventState feverishFeeling; + private String otherAdverseEventDetails; + + public static AdverseEventsDto build() { + AdverseEventsDto adverseEvents = new AdverseEventsDto(); + adverseEvents.setUuid(DataHelper.createUuid()); + return adverseEvents; + } + + @Order(1) + public AdverseEventState getSevereLocalReaction() { + return severeLocalReaction; + } + + public void setSevereLocalReaction(AdverseEventState severeLocalReaction) { + this.severeLocalReaction = severeLocalReaction; + } + + @Order(2) + public boolean isSevereLocalReactionMoreThanThreeDays() { + return severeLocalReactionMoreThanThreeDays; + } + + public void setSevereLocalReactionMoreThanThreeDays(boolean severeLocalReactionMoreThanThreeDays) { + this.severeLocalReactionMoreThanThreeDays = severeLocalReactionMoreThanThreeDays; + } + + @Order(3) + public boolean isSevereLocalReactionBeyondNearestJoint() { + return severeLocalReactionBeyondNearestJoint; + } + + public void setSevereLocalReactionBeyondNearestJoint(boolean severeLocalReactionBeyondNearestJoint) { + this.severeLocalReactionBeyondNearestJoint = severeLocalReactionBeyondNearestJoint; + } + + @Order(4) + public AdverseEventState getSeizures() { + return seizures; + } + + public void setSeizures(AdverseEventState seizures) { + this.seizures = seizures; + } + + @Order(5) + public SeizureType getSeizureType() { + return seizureType; + } + + public void setSeizureType(SeizureType seizureType) { + this.seizureType = seizureType; + } + + @Order(6) + public AdverseEventState getAbscess() { + return abscess; + } + + public void setAbscess(AdverseEventState abscess) { + this.abscess = abscess; + } + + @Order(7) + public AdverseEventState getSepsis() { + return sepsis; + } + + public void setSepsis(AdverseEventState sepsis) { + this.sepsis = sepsis; + } + + @Order(7) + public AdverseEventState getEncephalopathy() { + return encephalopathy; + } + + public void setEncephalopathy(AdverseEventState encephalopathy) { + this.encephalopathy = encephalopathy; + } + + @Order(8) + public AdverseEventState getToxicShockSyndrome() { + return toxicShockSyndrome; + } + + public void setToxicShockSyndrome(AdverseEventState toxicShockSyndrome) { + this.toxicShockSyndrome = toxicShockSyndrome; + } + + @Order(9) + public AdverseEventState getThrombocytopenia() { + return thrombocytopenia; + } + + public void setThrombocytopenia(AdverseEventState thrombocytopenia) { + this.thrombocytopenia = thrombocytopenia; + } + + @Order(10) + public AdverseEventState getAnaphylaxis() { + return anaphylaxis; + } + + public void setAnaphylaxis(AdverseEventState anaphylaxis) { + this.anaphylaxis = anaphylaxis; + } + + @Order(11) + public AdverseEventState getFeverishFeeling() { + return feverishFeeling; + } + + public void setFeverishFeeling(AdverseEventState feverishFeeling) { + this.feverishFeeling = feverishFeeling; + } + + @Order(12) + public String getOtherAdverseEventDetails() { + return otherAdverseEventDetails; + } + + public void setOtherAdverseEventDetails(String otherAdverseEventDetails) { + this.otherAdverseEventDetails = otherAdverseEventDetails; + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiAgeGroup.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiAgeGroup.java new file mode 100644 index 00000000000..4e57132ea70 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiAgeGroup.java @@ -0,0 +1,35 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum AefiAgeGroup { + + ZERO_TO_ONE, + ONE_TO_FIVE, + FIVE_TO_EIGHTEEN, + EIGHTEEN_TO_SIXTY, + SIXY_AND_ABOVE; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiCriteria.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiCriteria.java new file mode 100644 index 00000000000..742df524387 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiCriteria.java @@ -0,0 +1,232 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import java.io.Serializable; +import java.util.Date; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.EntityRelevanceStatus; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.caze.VaccineManufacturer; +import de.symeda.sormas.api.infrastructure.community.CommunityReferenceDto; +import de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto; +import de.symeda.sormas.api.infrastructure.facility.FacilityReferenceDto; +import de.symeda.sormas.api.infrastructure.facility.FacilityType; +import de.symeda.sormas.api.infrastructure.facility.FacilityTypeGroup; +import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto; +import de.symeda.sormas.api.utils.DateFilterOption; +import de.symeda.sormas.api.utils.criteria.BaseCriteria; + +public class AefiCriteria extends BaseCriteria implements Serializable { + + public static final String I18N_PREFIX = "AefiCriteria"; + + public static final String DISEASE = "disease"; + public static final String NAME_ADDRESS_PHONE_EMAIL_LIKE = "nameAddressPhoneEmailLike"; + public static final String AEFI_TYPE = "aefiType"; + public static final String OUTCOME = "outcome"; + public static final String VACCINE_NAME = "vaccineName"; + public static final String VACCINE_MANUFACTURER = "vaccineManufacturer"; + public static final String REGION = "region"; + public static final String DISTRICT = "district"; + public static final String COMMUNITY = "community"; + public static final String FACILITY_TYPE_GROUP = "facilityTypeGroup"; + public static final String FACILITY_TYPE = "facilityType"; + public static final String HEALTH_FACILITY = "healthFacility"; + public static final String DATE_FILTER_OPTION = "dateFilterOption"; + public static final String AEFI_DATE_TYPE = "aefiDateType"; + public static final String FROM_DATE = "fromDate"; + public static final String TO_DATE = "toDate"; + public static final String RELEVANCE_STATUS = "relevanceStatus"; + + private Disease disease; + private String nameAddressPhoneEmailLike; + private AefiType aefiType; + private AefiOutcome outcome; + private Vaccine vaccineName; + private VaccineManufacturer vaccineManufacturer; + private RegionReferenceDto region; + private DistrictReferenceDto district; + private CommunityReferenceDto community; + private FacilityTypeGroup facilityTypeGroup; + private FacilityType facilityType; + private FacilityReferenceDto healthFacility; + private DateFilterOption dateFilterOption = DateFilterOption.DATE; + private AefiDateType aefiDateType; + private Date fromDate; + private Date toDate; + private EntityRelevanceStatus relevanceStatus; + + public Disease getDisease() { + return disease; + } + + public void setDisease(Disease disease) { + this.disease = disease; + } + + public String getNameAddressPhoneEmailLike() { + return nameAddressPhoneEmailLike; + } + + public void setNameAddressPhoneEmailLike(String nameAddressPhoneEmailLike) { + this.nameAddressPhoneEmailLike = nameAddressPhoneEmailLike; + } + + public AefiType getAefiType() { + return aefiType; + } + + public void setAefiType(AefiType aefiType) { + this.aefiType = aefiType; + } + + public AefiOutcome getOutcome() { + return outcome; + } + + public void setOutcome(AefiOutcome outcome) { + this.outcome = outcome; + } + + public Vaccine getVaccineName() { + return vaccineName; + } + + public void setVaccineName(Vaccine vaccineName) { + this.vaccineName = vaccineName; + } + + public VaccineManufacturer getVaccineManufacturer() { + return vaccineManufacturer; + } + + public void setVaccineManufacturer(VaccineManufacturer vaccineManufacturer) { + this.vaccineManufacturer = vaccineManufacturer; + } + + public RegionReferenceDto getRegion() { + return region; + } + + public void setRegion(RegionReferenceDto region) { + this.region = region; + } + + public DistrictReferenceDto getDistrict() { + return district; + } + + public void setDistrict(DistrictReferenceDto district) { + this.district = district; + } + + public CommunityReferenceDto getCommunity() { + return community; + } + + public void setCommunity(CommunityReferenceDto community) { + this.community = community; + } + + public FacilityTypeGroup getFacilityTypeGroup() { + return facilityTypeGroup; + } + + public void setFacilityTypeGroup(FacilityTypeGroup facilityTypeGroup) { + this.facilityTypeGroup = facilityTypeGroup; + } + + public FacilityType getFacilityType() { + return facilityType; + } + + public void setFacilityType(FacilityType facilityType) { + this.facilityType = facilityType; + } + + public FacilityReferenceDto getHealthFacility() { + return healthFacility; + } + + public void setHealthFacility(FacilityReferenceDto healthFacility) { + this.healthFacility = healthFacility; + } + + public DateFilterOption getDateFilterOption() { + return dateFilterOption; + } + + public void setDateFilterOption(DateFilterOption dateFilterOption) { + this.dateFilterOption = dateFilterOption; + } + + public AefiDateType getAefiDateType() { + return aefiDateType; + } + + public void setAefiDateType(AefiDateType aefiDateType) { + this.aefiDateType = aefiDateType; + } + + public Date getFromDate() { + return fromDate; + } + + public void setFromDate(Date fromDate) { + this.fromDate = fromDate; + } + + public Date getToDate() { + return toDate; + } + + public void setToDate(Date toDate) { + this.toDate = toDate; + } + + public EntityRelevanceStatus getRelevanceStatus() { + return relevanceStatus; + } + + public void setRelevanceStatus(EntityRelevanceStatus relevanceStatus) { + this.relevanceStatus = relevanceStatus; + } + + public AefiCriteria disease(Disease disease) { + this.disease = disease; + return this; + } + + public AefiCriteria region(RegionReferenceDto region) { + this.region = region; + return this; + } + + public AefiCriteria district(DistrictReferenceDto district) { + this.district = district; + return this; + } + + public AefiCriteria aefiType(AefiType aefiType) { + this.aefiType = aefiType; + return this; + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiDashboardFilterDateType.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiDashboardFilterDateType.java new file mode 100644 index 00000000000..984641a06e5 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiDashboardFilterDateType.java @@ -0,0 +1,32 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum AefiDashboardFilterDateType { + + REPORT_DATE, + START_DATE; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiDateType.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiDateType.java new file mode 100644 index 00000000000..9eef385ce9c --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiDateType.java @@ -0,0 +1,33 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum AefiDateType { + + REPORT_DATE, + START_DATE, + VACCINATION_DATE; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiDto.java new file mode 100644 index 00000000000..7d32221109d --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiDto.java @@ -0,0 +1,614 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import de.symeda.sormas.api.caze.Trimester; +import de.symeda.sormas.api.common.DeletionReason; +import de.symeda.sormas.api.feature.FeatureType; +import de.symeda.sormas.api.i18n.Validations; +import de.symeda.sormas.api.immunization.ImmunizationReferenceDto; +import de.symeda.sormas.api.infrastructure.community.CommunityReferenceDto; +import de.symeda.sormas.api.infrastructure.country.CountryReferenceDto; +import de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto; +import de.symeda.sormas.api.infrastructure.facility.FacilityReferenceDto; +import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto; +import de.symeda.sormas.api.location.LocationDto; +import de.symeda.sormas.api.person.PersonReferenceDto; +import de.symeda.sormas.api.user.UserReferenceDto; +import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.api.utils.DependingOnFeatureType; +import de.symeda.sormas.api.utils.FieldConstraints; +import de.symeda.sormas.api.utils.YesNoUnknown; +import de.symeda.sormas.api.utils.pseudonymization.PseudonymizableDto; +import de.symeda.sormas.api.vaccination.VaccinationDto; + +@DependingOnFeatureType(featureType = { + FeatureType.IMMUNIZATION_MANAGEMENT, + FeatureType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_MANAGEMENT }) +public class AefiDto extends PseudonymizableDto { + + private static final long serialVersionUID = 5023410664970514090L; + + public static final long APPROXIMATE_JSON_SIZE_IN_BYTES = 25455; + + public static final String I18N_PREFIX = "Aefi"; + + public static final String IMMUNIZATION = "immunization"; + public static final String ADDRESS = "address"; + public static final String VACCINATIONS = "vaccinations"; + public static final String PRIMARY_SUSPECT_VACCINE = "primarySuspectVaccine"; + public static final String ADVERSE_EVENTS = "adverseEvents"; + public static final String PERSON = "person"; + public static final String REPORT_DATE = "reportDate"; + public static final String REPORTING_USER = "reportingUser"; + public static final String EXTERNAL_ID = "externalId"; + public static final String RESPONSIBLE_REGION = "responsibleRegion"; + public static final String RESPONSIBLE_DISTRICT = "responsibleDistrict"; + public static final String RESPONSIBLE_COMMUNITY = "responsibleCommunity"; + public static final String COUNTRY = "country"; + public static final String REPORTING_ID_NUMBER = "reportingIdNumber"; + public static final String PHONE_NUMBER = "phoneNumber"; + public static final String PREGNANT = "pregnant"; + public static final String TRIMESTER = "trimester"; + public static final String LACTATING = "lactating"; + public static final String ONSET_AGE_YEARS = "onsetAgeYears"; + public static final String ONSET_AGE_MONTHS = "onsetAgeMonths"; + public static final String ONSET_AGE_DAYS = "onsetAgeDays"; + public static final String AGE_GROUP = "ageGroup"; + public static final String HEALTH_FACILITY = "healthFacility"; + public static final String HEALTH_FACILITY_DETAILS = "healthFacilityDetails"; + public static final String REPORTER_NAME = "reporterName"; + public static final String REPORTER_INSTITUTION = "reporterInstitution"; + public static final String REPORTER_DESIGNATION = "reporterDesignation"; + public static final String REPORTER_DEPARTMENT = "reporterDepartment"; + public static final String REPORTER_ADDRESS = "reporterAddress"; + public static final String REPORTER_PHONE = "reporterPhone"; + public static final String REPORTER_EMAIL = "reporterEmail"; + public static final String TODAYS_DATE = "todaysDate"; + public static final String START_DATE_TIME = "startDateTime"; + public static final String AEFI_DESCRIPTION = "aefiDescription"; + public static final String SERIOUS = "serious"; + public static final String SERIOUS_REASON = "seriousReason"; + public static final String SERIOUS_REASON_DETAILS = "seriousReasonDetails"; + public static final String OUTCOME = "outcome"; + public static final String DEATH_DATE = "deathDate"; + public static final String AUTOPSY_DONE = "autopsyDone"; + public static final String PAST_MEDICAL_HISTORY = "pastMedicalHistory"; + public static final String INVESTIGATION_NEEDED = "investigationNeeded"; + public static final String INVESTIGATION_PLANNED_DATE = "investigationPlannedDate"; + public static final String RECEIVED_AT_NATIONAL_LEVEL_DATE = "receivedAtNationalLevelDate"; + public static final String WORLD_WIDE_ID = "worldwideId"; + public static final String NATIONAL_LEVEL_COMMENT = "nationalLevelComment"; + public static final String DELETION_REASON = "deletionReason"; + public static final String OTHER_DELETION_REASON = "otherDeletionReason"; + + @NotNull(message = Validations.validImmunization) + private ImmunizationReferenceDto immunization; + private PersonReferenceDto person; + private LocationDto address; + @NotEmpty(message = Validations.aefiWithoutSuspectVaccine) + private List vaccinations = new ArrayList<>(); + @NotNull(message = Validations.aefiWithoutPrimarySuspectVaccine) + private VaccinationDto primarySuspectVaccine; + @NotNull(message = Validations.aefiWithoutAdverseEvents) + private AdverseEventsDto adverseEvents; + @NotNull(message = Validations.validReportDateTime) + private Date reportDate; + private UserReferenceDto reportingUser; + @Size(max = FieldConstraints.CHARACTER_LIMIT_SMALL, message = Validations.textTooLong) + private String externalId; + private RegionReferenceDto responsibleRegion; + private DistrictReferenceDto responsibleDistrict; + private CommunityReferenceDto responsibleCommunity; + private CountryReferenceDto country; + @Size(max = FieldConstraints.CHARACTER_LIMIT_DEFAULT, message = Validations.textTooLong) + private String reportingIdNumber; + private String phoneNumber; + private YesNoUnknown pregnant; + private Trimester trimester; + private YesNoUnknown lactating; + private Integer onsetAgeYears; + private Integer onsetAgeMonths; + private Integer onsetAgeDays; + private AefiAgeGroup ageGroup; + private FacilityReferenceDto healthFacility; + @Size(max = FieldConstraints.CHARACTER_LIMIT_DEFAULT, message = Validations.textTooLong) + private String healthFacilityDetails; + @Size(max = FieldConstraints.CHARACTER_LIMIT_SMALL, message = Validations.textTooLong) + private String reporterName; + private FacilityReferenceDto reporterInstitution; + @Size(max = FieldConstraints.CHARACTER_LIMIT_SMALL, message = Validations.textTooLong) + private String reporterDesignation; + @Size(max = FieldConstraints.CHARACTER_LIMIT_SMALL, message = Validations.textTooLong) + private String reporterDepartment; + private LocationDto reporterAddress; + @Size(max = FieldConstraints.CHARACTER_LIMIT_SMALL, message = Validations.textTooLong) + private String reporterPhone; + @Size(max = FieldConstraints.CHARACTER_LIMIT_SMALL, message = Validations.textTooLong) + private String reporterEmail; + private Date todaysDate; + private Date startDateTime; + @Size(max = FieldConstraints.CHARACTER_LIMIT_TEXT, message = Validations.textTooLong) + private String aefiDescription; + private YesNoUnknown serious; + private SeriousAefiReason seriousReason; + @Size(max = FieldConstraints.CHARACTER_LIMIT_SMALL, message = Validations.textTooLong) + private String seriousReasonDetails; + private AefiOutcome outcome; + private Date deathDate; + private YesNoUnknown autopsyDone; + @Size(max = FieldConstraints.CHARACTER_LIMIT_TEXT, message = Validations.textTooLong) + private String pastMedicalHistory; + private YesNoUnknown investigationNeeded; + private Date investigationPlannedDate; + private Date receivedAtNationalLevelDate; + @Size(max = FieldConstraints.CHARACTER_LIMIT_SMALL, message = Validations.textTooLong) + private String worldwideId; + @Size(max = FieldConstraints.CHARACTER_LIMIT_TEXT, message = Validations.textTooLong) + private String nationalLevelComment; + private boolean archived; + private boolean deleted; + private DeletionReason deletionReason; + @Size(max = FieldConstraints.CHARACTER_LIMIT_TEXT, message = Validations.textTooLong) + private String otherDeletionReason; + + public static AefiDto build(UserReferenceDto user) { + + final AefiDto aefiDto = new AefiDto(); + aefiDto.setUuid(DataHelper.createUuid()); + aefiDto.setReportingUser(user); + aefiDto.setReportDate(new Date()); + aefiDto.setAdverseEvents(AdverseEventsDto.build()); + + return aefiDto; + } + + public static AefiDto build(ImmunizationReferenceDto immunization) { + + final AefiDto aefiDto = new AefiDto(); + aefiDto.setUuid(DataHelper.createUuid()); + aefiDto.setImmunization(immunization); + aefiDto.setReportDate(new Date()); + aefiDto.setAdverseEvents(AdverseEventsDto.build()); + + return aefiDto; + } + + public static AefiDto build(AefiReferenceDto aefiReferenceDto) { + + final AefiDto aefiDto = new AefiDto(); + aefiDto.setUuid(aefiReferenceDto.getUuid()); + aefiDto.setReportDate(new Date()); + aefiDto.setAdverseEvents(AdverseEventsDto.build()); + + return aefiDto; + } + + public AefiReferenceDto toReference() { + return new AefiReferenceDto(getUuid(), getPerson().getCaption(), getExternalId()); + } + + public ImmunizationReferenceDto getImmunization() { + return immunization; + } + + public void setImmunization(ImmunizationReferenceDto immunization) { + this.immunization = immunization; + } + + public PersonReferenceDto getPerson() { + return person; + } + + public void setPerson(PersonReferenceDto person) { + this.person = person; + } + + public LocationDto getAddress() { + return address; + } + + public void setAddress(LocationDto address) { + this.address = address; + } + + public List getVaccinations() { + return vaccinations; + } + + public void setVaccinations(List vaccinations) { + this.vaccinations = vaccinations; + } + + public AdverseEventsDto getAdverseEvents() { + return adverseEvents; + } + + public VaccinationDto getPrimarySuspectVaccine() { + return primarySuspectVaccine; + } + + public void setPrimarySuspectVaccine(VaccinationDto primarySuspectVaccine) { + this.primarySuspectVaccine = primarySuspectVaccine; + } + + public void setAdverseEvents(AdverseEventsDto adverseEvents) { + this.adverseEvents = adverseEvents; + } + + public Date getReportDate() { + return reportDate; + } + + public void setReportDate(Date reportDate) { + this.reportDate = reportDate; + } + + public UserReferenceDto getReportingUser() { + return reportingUser; + } + + public void setReportingUser(UserReferenceDto reportingUser) { + this.reportingUser = reportingUser; + } + + public String getExternalId() { + return externalId; + } + + public void setExternalId(String externalId) { + this.externalId = externalId; + } + + public RegionReferenceDto getResponsibleRegion() { + return responsibleRegion; + } + + public void setResponsibleRegion(RegionReferenceDto responsibleRegion) { + this.responsibleRegion = responsibleRegion; + } + + public DistrictReferenceDto getResponsibleDistrict() { + return responsibleDistrict; + } + + public void setResponsibleDistrict(DistrictReferenceDto responsibleDistrict) { + this.responsibleDistrict = responsibleDistrict; + } + + public CommunityReferenceDto getResponsibleCommunity() { + return responsibleCommunity; + } + + public void setResponsibleCommunity(CommunityReferenceDto responsibleCommunity) { + this.responsibleCommunity = responsibleCommunity; + } + + public CountryReferenceDto getCountry() { + return country; + } + + public void setCountry(CountryReferenceDto country) { + this.country = country; + } + + public String getReportingIdNumber() { + return reportingIdNumber; + } + + public void setReportingIdNumber(String reportingIdNumber) { + this.reportingIdNumber = reportingIdNumber; + } + + public String getPhoneNumber() { + return phoneNumber; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + public YesNoUnknown getPregnant() { + return pregnant; + } + + public void setPregnant(YesNoUnknown pregnant) { + this.pregnant = pregnant; + } + + public Trimester getTrimester() { + return trimester; + } + + public void setTrimester(Trimester trimester) { + this.trimester = trimester; + } + + public YesNoUnknown getLactating() { + return lactating; + } + + public void setLactating(YesNoUnknown lactating) { + this.lactating = lactating; + } + + public Integer getOnsetAgeYears() { + return onsetAgeYears; + } + + public void setOnsetAgeYears(Integer onsetAgeYears) { + this.onsetAgeYears = onsetAgeYears; + } + + public Integer getOnsetAgeMonths() { + return onsetAgeMonths; + } + + public void setOnsetAgeMonths(Integer onsetAgeMonths) { + this.onsetAgeMonths = onsetAgeMonths; + } + + public Integer getOnsetAgeDays() { + return onsetAgeDays; + } + + public void setOnsetAgeDays(Integer onsetAgeDays) { + this.onsetAgeDays = onsetAgeDays; + } + + public AefiAgeGroup getAgeGroup() { + return ageGroup; + } + + public void setAgeGroup(AefiAgeGroup ageGroup) { + this.ageGroup = ageGroup; + } + + public FacilityReferenceDto getHealthFacility() { + return healthFacility; + } + + public void setHealthFacility(FacilityReferenceDto healthFacility) { + this.healthFacility = healthFacility; + } + + public String getHealthFacilityDetails() { + return healthFacilityDetails; + } + + public void setHealthFacilityDetails(String healthFacilityDetails) { + this.healthFacilityDetails = healthFacilityDetails; + } + + public String getReporterName() { + return reporterName; + } + + public void setReporterName(String reporterName) { + this.reporterName = reporterName; + } + + public FacilityReferenceDto getReporterInstitution() { + return reporterInstitution; + } + + public void setReporterInstitution(FacilityReferenceDto reporterInstitution) { + this.reporterInstitution = reporterInstitution; + } + + public String getReporterDesignation() { + return reporterDesignation; + } + + public void setReporterDesignation(String reporterDesignation) { + this.reporterDesignation = reporterDesignation; + } + + public String getReporterDepartment() { + return reporterDepartment; + } + + public void setReporterDepartment(String reporterDepartment) { + this.reporterDepartment = reporterDepartment; + } + + public LocationDto getReporterAddress() { + return reporterAddress; + } + + public void setReporterAddress(LocationDto reporterAddress) { + this.reporterAddress = reporterAddress; + } + + public String getReporterPhone() { + return reporterPhone; + } + + public void setReporterPhone(String reporterPhone) { + this.reporterPhone = reporterPhone; + } + + public String getReporterEmail() { + return reporterEmail; + } + + public void setReporterEmail(String reporterEmail) { + this.reporterEmail = reporterEmail; + } + + public Date getTodaysDate() { + return todaysDate; + } + + public void setTodaysDate(Date todaysDate) { + this.todaysDate = todaysDate; + } + + public Date getStartDateTime() { + return startDateTime; + } + + public void setStartDateTime(Date startDateTime) { + this.startDateTime = startDateTime; + } + + public String getAefiDescription() { + return aefiDescription; + } + + public void setAefiDescription(String aefiDescription) { + this.aefiDescription = aefiDescription; + } + + public YesNoUnknown getSerious() { + return serious; + } + + public void setSerious(YesNoUnknown serious) { + this.serious = serious; + } + + public SeriousAefiReason getSeriousReason() { + return seriousReason; + } + + public void setSeriousReason(SeriousAefiReason seriousReason) { + this.seriousReason = seriousReason; + } + + public String getSeriousReasonDetails() { + return seriousReasonDetails; + } + + public void setSeriousReasonDetails(String seriousReasonDetails) { + this.seriousReasonDetails = seriousReasonDetails; + } + + public AefiOutcome getOutcome() { + return outcome; + } + + public void setOutcome(AefiOutcome outcome) { + this.outcome = outcome; + } + + public Date getDeathDate() { + return deathDate; + } + + public void setDeathDate(Date deathDate) { + this.deathDate = deathDate; + } + + public YesNoUnknown getAutopsyDone() { + return autopsyDone; + } + + public void setAutopsyDone(YesNoUnknown autopsyDone) { + this.autopsyDone = autopsyDone; + } + + public String getPastMedicalHistory() { + return pastMedicalHistory; + } + + public void setPastMedicalHistory(String pastMedicalHistory) { + this.pastMedicalHistory = pastMedicalHistory; + } + + public YesNoUnknown getInvestigationNeeded() { + return investigationNeeded; + } + + public void setInvestigationNeeded(YesNoUnknown investigationNeeded) { + this.investigationNeeded = investigationNeeded; + } + + public Date getInvestigationPlannedDate() { + return investigationPlannedDate; + } + + public void setInvestigationPlannedDate(Date investigationPlannedDate) { + this.investigationPlannedDate = investigationPlannedDate; + } + + public Date getReceivedAtNationalLevelDate() { + return receivedAtNationalLevelDate; + } + + public void setReceivedAtNationalLevelDate(Date receivedAtNationalLevelDate) { + this.receivedAtNationalLevelDate = receivedAtNationalLevelDate; + } + + public String getWorldwideId() { + return worldwideId; + } + + public void setWorldwideId(String worldwideId) { + this.worldwideId = worldwideId; + } + + public String getNationalLevelComment() { + return nationalLevelComment; + } + + public void setNationalLevelComment(String nationalLevelComment) { + this.nationalLevelComment = nationalLevelComment; + } + + public boolean isArchived() { + return archived; + } + + public void setArchived(boolean archived) { + this.archived = archived; + } + + public boolean isDeleted() { + return deleted; + } + + public void setDeleted(boolean deleted) { + this.deleted = deleted; + } + + public DeletionReason getDeletionReason() { + return deletionReason; + } + + public void setDeletionReason(DeletionReason deletionReason) { + this.deletionReason = deletionReason; + } + + public String getOtherDeletionReason() { + return otherDeletionReason; + } + + public void setOtherDeletionReason(String otherDeletionReason) { + this.otherDeletionReason = otherDeletionReason; + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiFacade.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiFacade.java new file mode 100644 index 00000000000..4267d27a9b5 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiFacade.java @@ -0,0 +1,31 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import java.util.List; + +import javax.ejb.Remote; + +import de.symeda.sormas.api.CoreFacade; + +@Remote +public interface AefiFacade extends CoreFacade { + + List getEntriesList(AefiListCriteria criteria, Integer first, Integer max); +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiHelper.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiHelper.java new file mode 100644 index 00000000000..815c46365dc --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiHelper.java @@ -0,0 +1,87 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import java.util.ArrayList; +import java.util.List; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public final class AefiHelper { + + private AefiHelper() { + + } + + public static String buildAdverseEventsString( + AdverseEventState severeLocalReaction, + boolean severeLocalReactionMoreThanThreeDays, + boolean severeLocalReactionBeyondNearestJoint, + AdverseEventState seizures, + SeizureType seizureType, + AdverseEventState abscess, + AdverseEventState sepsis, + AdverseEventState encephalopathy, + AdverseEventState toxicShockSyndrome, + AdverseEventState thrombocytopenia, + AdverseEventState anaphylaxis, + AdverseEventState feverishFeeling, + String otherAdverseEventDetails) { + + List adverseEventsList = new ArrayList<>(); + + if (severeLocalReaction == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.SEVERE_LOCAL_REACTION)); + } + + if (seizures == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.SEIZURES)); + } + + if (abscess == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.ABSCESS)); + } + + if (sepsis == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.SEPSIS)); + } + + if (encephalopathy == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.ENCEPHALOPATHY)); + } + + if (toxicShockSyndrome == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.TOXIC_SHOCK_SYNDROME)); + } + + if (thrombocytopenia == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.THROMBOCYTOPENIA)); + } + + if (anaphylaxis == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.ANAPHYLAXIS)); + } + + if (feverishFeeling == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.FEVERISH_FEELING)); + } + + return String.join(", ", adverseEventsList); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiIndexDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiIndexDto.java new file mode 100644 index 00000000000..e389093fc00 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiIndexDto.java @@ -0,0 +1,277 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import java.io.Serializable; +import java.util.Date; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.caze.AgeAndBirthDateDto; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.common.DeletionReason; +import de.symeda.sormas.api.person.Sex; +import de.symeda.sormas.api.utils.PersonalData; +import de.symeda.sormas.api.utils.SensitiveData; +import de.symeda.sormas.api.utils.YesNoUnknown; +import de.symeda.sormas.api.utils.pseudonymization.PseudonymizableIndexDto; + +public class AefiIndexDto extends PseudonymizableIndexDto implements Serializable, Cloneable { + + public static final String I18N_PREFIX = "AefiIndex"; + + public static final String UUID = "uuid"; + public static final String IMMUNIZATION_UUID = "immunizationUuid"; + public static final String PERSON_UUID = "personUuid"; + public static final String PERSON_FIRST_NAME = "personFirstName"; + public static final String PERSON_LAST_NAME = "personLastName"; + public static final String REPORT_DATE = "reportDate"; + public static final String DISEASE = "disease"; + public static final String AGE_AND_BIRTH_DATE = "ageAndBirthDate"; + public static final String SEX = "sex"; + public static final String REGION = "region"; + public static final String DISTRICT = "district"; + public static final String SERIOUS = "serious"; + public static final String PRIMARY_VACCINE_NAME = "primaryVaccine"; + public static final String OUTCOME = "outcome"; + public static final String VACCINATION_DATE = "vaccinationDate"; + public static final String START_DATE_TIME = "startDateTime"; + public static final String ADVERSE_EVENTS = "adverseEvents"; + + private String immunizationUuid; + private String personUuid; + @PersonalData + @SensitiveData + private String personFirstName; + @PersonalData + @SensitiveData + private String personLastName; + private Date reportDate; + private Disease disease; + private AgeAndBirthDateDto ageAndBirthDate; + private Sex sex; + private String region; + private String district; + private YesNoUnknown serious; + private Vaccine primaryVaccine; + private AefiOutcome outcome; + private Date vaccinationDate; + private Date startDateTime; + private String adverseEvents; + private DeletionReason deletionReason; + private String otherDeletionReason; + private boolean isInJurisdiction; + + public AefiIndexDto( + String uuid, + String immunizationUuid, + String personUuid, + String personFirstName, + String personLastName, + Disease disease, + AgeAndBirthDateDto ageAndBirthDate, + Sex sex, + String region, + String district, + YesNoUnknown serious, + Vaccine primaryVaccine, + AefiOutcome outcome, + Date vaccinationDate, + Date reportDate, + Date startDateTime, + String adverseEvents, + DeletionReason deletionReason, + String otherDeletionReason, + boolean isInJurisdiction) { + + super(uuid); + this.immunizationUuid = immunizationUuid; + this.personUuid = personUuid; + this.personFirstName = personFirstName; + this.personLastName = personLastName; + this.disease = disease; + this.ageAndBirthDate = ageAndBirthDate; + this.sex = sex; + this.region = region; + this.district = district; + this.serious = serious; + this.primaryVaccine = primaryVaccine; + this.outcome = outcome; + this.vaccinationDate = vaccinationDate; + this.reportDate = reportDate; + this.startDateTime = startDateTime; + this.adverseEvents = adverseEvents; + this.deletionReason = deletionReason; + this.otherDeletionReason = otherDeletionReason; + this.isInJurisdiction = isInJurisdiction; + } + + public String getImmunizationUuid() { + return immunizationUuid; + } + + public void setImmunizationUuid(String immunizationUuid) { + this.immunizationUuid = immunizationUuid; + } + + public String getPersonUuid() { + return personUuid; + } + + public void setPersonUuid(String personUuid) { + this.personUuid = personUuid; + } + + public String getPersonFirstName() { + return personFirstName; + } + + public void setPersonFirstName(String personFirstName) { + this.personFirstName = personFirstName; + } + + public String getPersonLastName() { + return personLastName; + } + + public void setPersonLastName(String personLastName) { + this.personLastName = personLastName; + } + + public Date getReportDate() { + return reportDate; + } + + public void setReportDate(Date reportDate) { + this.reportDate = reportDate; + } + + public Disease getDisease() { + return disease; + } + + public void setDisease(Disease disease) { + this.disease = disease; + } + + public AgeAndBirthDateDto getAgeAndBirthDate() { + return ageAndBirthDate; + } + + public void setAgeAndBirthDate(AgeAndBirthDateDto ageAndBirthDate) { + this.ageAndBirthDate = ageAndBirthDate; + } + + public Sex getSex() { + return sex; + } + + public void setSex(Sex sex) { + this.sex = sex; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public String getDistrict() { + return district; + } + + public void setDistrict(String district) { + this.district = district; + } + + public YesNoUnknown getSerious() { + return serious; + } + + public void setSerious(YesNoUnknown serious) { + this.serious = serious; + } + + public Vaccine getPrimaryVaccine() { + return primaryVaccine; + } + + public void setPrimaryVaccine(Vaccine primaryVaccine) { + this.primaryVaccine = primaryVaccine; + } + + public AefiOutcome getOutcome() { + return outcome; + } + + public void setOutcome(AefiOutcome outcome) { + this.outcome = outcome; + } + + public Date getVaccinationDate() { + return vaccinationDate; + } + + public void setVaccinationDate(Date vaccinationDate) { + this.vaccinationDate = vaccinationDate; + } + + public Date getStartDateTime() { + return startDateTime; + } + + public void setStartDateTime(Date startDateTime) { + this.startDateTime = startDateTime; + } + + public String getAdverseEvents() { + return adverseEvents; + } + + public void setAdverseEvents(String adverseEvents) { + this.adverseEvents = adverseEvents; + } + + public DeletionReason getDeletionReason() { + return deletionReason; + } + + public void setDeletionReason(DeletionReason deletionReason) { + this.deletionReason = deletionReason; + } + + public String getOtherDeletionReason() { + return otherDeletionReason; + } + + public void setOtherDeletionReason(String otherDeletionReason) { + this.otherDeletionReason = otherDeletionReason; + } + + @Override + public boolean isInJurisdiction() { + return isInJurisdiction; + } + + @Override + public void setInJurisdiction(boolean inJurisdiction) { + isInJurisdiction = inJurisdiction; + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiListCriteria.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiListCriteria.java new file mode 100644 index 00000000000..80ae6536c0a --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiListCriteria.java @@ -0,0 +1,48 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.immunization.ImmunizationReferenceDto; +import de.symeda.sormas.api.utils.criteria.BaseCriteria; + +public class AefiListCriteria extends BaseCriteria { + + private final ImmunizationReferenceDto immunizationReferenceDto; + + public static class Builder { + + private final ImmunizationReferenceDto immunizationReferenceDto; + + public Builder(ImmunizationReferenceDto immunizationReferenceDto) { + this.immunizationReferenceDto = immunizationReferenceDto; + } + + public AefiListCriteria build() { + return new AefiListCriteria(this); + } + } + + private AefiListCriteria(Builder builder) { + this.immunizationReferenceDto = builder.immunizationReferenceDto; + } + + public ImmunizationReferenceDto getImmunization() { + return immunizationReferenceDto; + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiListEntryDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiListEntryDto.java new file mode 100644 index 00000000000..706e97da2b2 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiListEntryDto.java @@ -0,0 +1,97 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import java.io.Serializable; +import java.util.Date; + +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.utils.YesNoUnknown; +import de.symeda.sormas.api.utils.pseudonymization.PseudonymizableIndexDto; + +public class AefiListEntryDto extends PseudonymizableIndexDto implements Serializable, Cloneable { + + public static final String I18N_PREFIX = "Aefi"; + + public static final String UUID = "uuid"; + public static final String SERIOUS = "serious"; + public static final String PRIMARY_VACCINE_NAME = "primaryVaccineName"; + public static final String PRIMARY_VACCINE_DOSE = "primaryVaccineDose"; + public static final String PRIMARY_VACCINE_VACCINATION_DATE = "primaryVaccineVaccinationDate"; + private String ADVERSE_EVENTS = "adverseEvents"; + + private YesNoUnknown serious; + private Vaccine primaryVaccineName; + private String primaryVaccineDose; + private Date primaryVaccineVaccinationDate; + private String adverseEvents; + + public AefiListEntryDto( + String uuid, + YesNoUnknown serious, + Vaccine primaryVaccineName, + String primaryVaccineDose, + Date primaryVaccineVaccinationDate, + String adverseEvents) { + + super(uuid); + this.serious = serious; + this.primaryVaccineName = primaryVaccineName; + this.primaryVaccineDose = primaryVaccineDose; + this.primaryVaccineVaccinationDate = primaryVaccineVaccinationDate; + this.adverseEvents = adverseEvents; + } + + public YesNoUnknown getSerious() { + return serious; + } + + public void setSerious(YesNoUnknown serious) { + this.serious = serious; + } + + public Vaccine getPrimaryVaccineName() { + return primaryVaccineName; + } + + public void setPrimaryVaccineName(Vaccine primaryVaccineName) { + this.primaryVaccineName = primaryVaccineName; + } + + public String getPrimaryVaccineDose() { + return primaryVaccineDose; + } + + public void setPrimaryVaccineDose(String primaryVaccineDose) { + this.primaryVaccineDose = primaryVaccineDose; + } + + public Date getPrimaryVaccineVaccinationDate() { + return primaryVaccineVaccinationDate; + } + + public void setPrimaryVaccineVaccinationDate(Date primaryVaccineVaccinationDate) { + this.primaryVaccineVaccinationDate = primaryVaccineVaccinationDate; + } + + public String getAdverseEvents() { + return adverseEvents; + } + + public void setAdverseEvents(String adverseEvents) { + this.adverseEvents = adverseEvents; + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiOutcome.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiOutcome.java new file mode 100644 index 00000000000..20d22beacbe --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiOutcome.java @@ -0,0 +1,36 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum AefiOutcome { + + RECOVERING, + RECOVERED, + RECOVERED_WITH_SEQUELAE, + NOT_RECOVERED, + UNKNOWN, + DIED; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiReferenceDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiReferenceDto.java new file mode 100644 index 00000000000..51acac53ec1 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiReferenceDto.java @@ -0,0 +1,45 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.ReferenceDto; +import de.symeda.sormas.api.feature.FeatureType; +import de.symeda.sormas.api.utils.DependingOnFeatureType; + +@DependingOnFeatureType(featureType = FeatureType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_MANAGEMENT) +public class AefiReferenceDto extends ReferenceDto { + + private String externalId; + + public AefiReferenceDto() { + } + + public AefiReferenceDto(String uuid, String caption, String externalId) { + super(uuid, caption); + this.externalId = externalId; + } + + public String getExternalId() { + return externalId; + } + + public void setExternalId(String externalId) { + this.externalId = externalId; + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiType.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiType.java new file mode 100644 index 00000000000..952eb1bc1cd --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiType.java @@ -0,0 +1,41 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.utils.YesNoUnknown; + +public enum AefiType { + + SERIOUS, + NON_SERIOUS; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } + + public static String toString(YesNoUnknown serious) { + if (serious == YesNoUnknown.YES) { + return AefiType.SERIOUS.toString(); + } else { + return AefiType.NON_SERIOUS.toString(); + } + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/SeizureType.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/SeizureType.java new file mode 100644 index 00000000000..d5abb2d27ce --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/SeizureType.java @@ -0,0 +1,32 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum SeizureType { + + FEBRILE, + AFEBRILE; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/SeriousAefiReason.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/SeriousAefiReason.java new file mode 100644 index 00000000000..17156c90bbd --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/SeriousAefiReason.java @@ -0,0 +1,36 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum SeriousAefiReason { + + DEATH, + LIFE_THREATENING, + DISABILITY, + HOSPITALIZATION, + CONGENITAL_ANOMALY, + OTHER; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/common/DeletableEntityType.java b/sormas-api/src/main/java/de/symeda/sormas/api/common/DeletableEntityType.java index 0d01e715da0..0e3a694ec31 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/common/DeletableEntityType.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/common/DeletableEntityType.java @@ -23,6 +23,7 @@ public enum DeletableEntityType { EVENT, EVENT_PARTICIPANT, IMMUNIZATION, + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION, TRAVEL_ENTRY, CAMPAIGN, SAMPLE, diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/AefiDashboardCriteria.java b/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/AefiDashboardCriteria.java new file mode 100644 index 00000000000..cf245b5a25a --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/AefiDashboardCriteria.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.api.dashboard; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDashboardFilterDateType; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; + +public class AefiDashboardCriteria extends BaseDashboardCriteria { + + private AefiDashboardFilterDateType aefiDashboardFilterDateType; + private AefiType aefiType; + + public AefiDashboardCriteria() { + super(AefiDashboardCriteria.class); + } + + public AefiDashboardFilterDateType getAefiDashboardFilterDateType() { + return aefiDashboardFilterDateType; + } + + public AefiType getAefiType() { + return aefiType; + } + + public AefiDashboardCriteria aefiDashboardDateType(AefiDashboardFilterDateType aefiDashboardFilterDateType) { + this.aefiDashboardFilterDateType = aefiDashboardFilterDateType; + + return self; + } + + public AefiDashboardCriteria aefiType(AefiType aefiType) { + this.aefiType = aefiType; + + return self; + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiChartData.java b/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiChartData.java new file mode 100644 index 00000000000..0ba1d2093bc --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiChartData.java @@ -0,0 +1,58 @@ +/* + * 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.dashboard.adverseeventsfollowingimmunization; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +public class AefiChartData implements Serializable { + + private static final long serialVersionUID = 3538219674050390425L; + + private List xAxisCategories = new ArrayList<>(); + private List series = new ArrayList<>(); + + public AefiChartData() { + } + + public List getxAxisCategories() { + return xAxisCategories; + } + + public void setxAxisCategories(List xAxisCategories) { + this.xAxisCategories = xAxisCategories; + } + + public List getSeries() { + return series; + } + + public void setSeries(List series) { + this.series = series; + } + + public void addXAxisCategory(Object category) { + xAxisCategories.add(category); + } + + public void addSeries(AefiChartSeries chartSeries) { + series.add(chartSeries); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiChartSeries.java b/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiChartSeries.java new file mode 100644 index 00000000000..67824645c4e --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiChartSeries.java @@ -0,0 +1,61 @@ +/* + * 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.dashboard.adverseeventsfollowingimmunization; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +public class AefiChartSeries implements Serializable { + + private static final long serialVersionUID = 8537929721515000783L; + + private Object name; + private String color; + private List seriesData = new ArrayList<>(); + + public AefiChartSeries(Object name) { + this.name = name; + } + + public Object getName() { + return name; + } + + public void setName(Object name) { + this.name = name; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } + + public List getSeriesData() { + return seriesData; + } + + public void setSeriesData(List seriesData) { + this.seriesData = seriesData; + } + + public void addData(String data) { + seriesData.add(data); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiDashboardFacade.java b/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiDashboardFacade.java new file mode 100644 index 00000000000..2e61f221bc5 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiDashboardFacade.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.api.dashboard.adverseeventsfollowingimmunization; + +import java.util.List; +import java.util.Map; + +import javax.ejb.Remote; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.dashboard.AefiDashboardCriteria; + +@Remote +public interface AefiDashboardFacade { + + Map getAefiCountsByType(AefiDashboardCriteria dashboardCriteria); + + Map> getAefiCountsByVaccine(AefiDashboardCriteria dashboardCriteria); + + AefiChartData getAefiByVaccineDoseChartData(AefiDashboardCriteria dashboardCriteria); + + AefiChartData getAefiEventsByGenderChartData(AefiDashboardCriteria dashboardCriteria); + + Long countAefiForMap(AefiDashboardCriteria criteria); + + List getAefiForMap(AefiDashboardCriteria criteria); +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/MapAefiDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/MapAefiDto.java new file mode 100644 index 00000000000..66b1f573c05 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/MapAefiDto.java @@ -0,0 +1,78 @@ +/* + * 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.dashboard.adverseeventsfollowingimmunization; + +import java.io.Serializable; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; +import de.symeda.sormas.api.utils.YesNoUnknown; + +public class MapAefiDto implements Serializable { + + private static final long serialVersionUID = -7323648840592752250L; + + private Double latitude; + private Double longitude; + + private AefiType aefiType; + + public MapAefiDto(Double longitude, Double latitude, Double associatedEntityLongitude, Double associatedEntityLatitude) { + if (!setLatLonIfPresent(longitude, latitude, null)) + setLatLonIfPresent(associatedEntityLongitude, associatedEntityLatitude, null); + } + + public MapAefiDto( + Double aefiLon, + Double aefiLat, + Double immunizationFacilityLon, + Double immunizationFacilityLat, + Double immunizationPersonLon, + Double immunizationPersonLat, + YesNoUnknown serious) { + + aefiType = serious == YesNoUnknown.YES ? AefiType.SERIOUS : AefiType.NON_SERIOUS; + if (!setLatLonIfPresent(aefiLon, aefiLat, aefiType)) + if (!setLatLonIfPresent(immunizationFacilityLon, immunizationFacilityLat, aefiType)) + setLatLonIfPresent(immunizationPersonLon, immunizationPersonLat, aefiType); + } + + private boolean setLatLonIfPresent(Double longitude, Double latitude, AefiType aefiType) { + if (longitude != null && latitude != null) { + this.longitude = longitude; + this.latitude = latitude; + this.aefiType = aefiType; + + return true; + } + + return false; + } + + public Double getLatitude() { + return latitude; + } + + public Double getLongitude() { + return longitude; + } + + public AefiType getAefiType() { + return aefiType; + } +} 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 bd3180491d4..ca44b364a12 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 @@ -69,6 +69,7 @@ public enum FeatureType { TASK_MANAGEMENT(true, true, null, null, ImmutableMap.of(FeatureTypeProperty.ALLOW_FREE_EDITING, Boolean.FALSE)), WEEKLY_REPORTING(true, true, null, null, null), IMMUNIZATION_MANAGEMENT(true, true, null, null, ImmutableMap.of(FeatureTypeProperty.REDUCED, Boolean.FALSE)), + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_MANAGEMENT(true, false, null, null, ImmutableMap.of(FeatureTypeProperty.REDUCED, Boolean.FALSE)), TRAVEL_ENTRIES(true, false, null, null, null), DASHBOARD_SURVEILLANCE(true, true, null, null, null), 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 de514090097..ac9fd632af3 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 @@ -40,6 +40,8 @@ public interface Captions { String Action_title = "Action.title"; String actionAccept = "actionAccept"; String actionAdjustChanges = "actionAdjustChanges"; + String actionAefiAssignNewReportingIdNumber = "actionAefiAssignNewReportingIdNumber"; + String actionAefiSelectPrimarySuspectVaccination = "actionAefiSelectPrimarySuspectVaccination"; String actionApply = "actionApply"; String actionApplyDateFilter = "actionApplyDateFilter"; String actionApplyFilters = "actionApplyFilters"; @@ -177,6 +179,105 @@ public interface Captions { String address = "address"; String adoptHomeAddressOfCasePerson = "adoptHomeAddressOfCasePerson"; String adoptHomeAddressOfCasePersonIfRelationMatches = "adoptHomeAddressOfCasePersonIfRelationMatches"; + String AdverseEvents_abscess = "AdverseEvents.abscess"; + String AdverseEvents_anaphylaxis = "AdverseEvents.anaphylaxis"; + String AdverseEvents_encephalopathy = "AdverseEvents.encephalopathy"; + String AdverseEvents_feverishFeeling = "AdverseEvents.feverishFeeling"; + String AdverseEvents_otherAdverseEventDetails = "AdverseEvents.otherAdverseEventDetails"; + String AdverseEvents_seizures = "AdverseEvents.seizures"; + String AdverseEvents_seizureType = "AdverseEvents.seizureType"; + String AdverseEvents_sepsis = "AdverseEvents.sepsis"; + String AdverseEvents_severeLocalReaction = "AdverseEvents.severeLocalReaction"; + String AdverseEvents_severeLocalReactionBeyondNearestJoint = "AdverseEvents.severeLocalReactionBeyondNearestJoint"; + String AdverseEvents_severeLocalReactionMoreThanThreeDays = "AdverseEvents.severeLocalReactionMoreThanThreeDays"; + String AdverseEvents_thrombocytopenia = "AdverseEvents.thrombocytopenia"; + String AdverseEvents_toxicShockSyndrome = "AdverseEvents.toxicShockSyndrome"; + String Aefi_aefiDescription = "Aefi.aefiDescription"; + String Aefi_ageGroup = "Aefi.ageGroup"; + String Aefi_autopsyDone = "Aefi.autopsyDone"; + String Aefi_changeDate = "Aefi.changeDate"; + String Aefi_country = "Aefi.country"; + String Aefi_creationDate = "Aefi.creationDate"; + String Aefi_deathDate = "Aefi.deathDate"; + String Aefi_deletionReason = "Aefi.deletionReason"; + String Aefi_externalId = "Aefi.externalId"; + String Aefi_healthFacility = "Aefi.healthFacility"; + String Aefi_healthFacilityDetails = "Aefi.healthFacilityDetails"; + String Aefi_investigationNeeded = "Aefi.investigationNeeded"; + String Aefi_investigationPlannedDate = "Aefi.investigationPlannedDate"; + String Aefi_lactating = "Aefi.lactating"; + String Aefi_nationalLevelComment = "Aefi.nationalLevelComment"; + String Aefi_onsetAgeDays = "Aefi.onsetAgeDays"; + String Aefi_onsetAgeMonths = "Aefi.onsetAgeMonths"; + String Aefi_onsetAgeYears = "Aefi.onsetAgeYears"; + String Aefi_otherDeletionReason = "Aefi.otherDeletionReason"; + String Aefi_outcome = "Aefi.outcome"; + String Aefi_pastMedicalHistory = "Aefi.pastMedicalHistory"; + String Aefi_pregnant = "Aefi.pregnant"; + String Aefi_primaryVaccineVaccinationDate = "Aefi.primaryVaccineVaccinationDate"; + String Aefi_receivedAtNationalLevelDate = "Aefi.receivedAtNationalLevelDate"; + String Aefi_reportDate = "Aefi.reportDate"; + String Aefi_reporterDepartment = "Aefi.reporterDepartment"; + String Aefi_reporterDesignation = "Aefi.reporterDesignation"; + String Aefi_reporterEmail = "Aefi.reporterEmail"; + String Aefi_reporterInstitution = "Aefi.reporterInstitution"; + String Aefi_reporterName = "Aefi.reporterName"; + String Aefi_reporterPhone = "Aefi.reporterPhone"; + String Aefi_reportingIdNumber = "Aefi.reportingIdNumber"; + String Aefi_reportingUser = "Aefi.reportingUser"; + String Aefi_responsibleCommunity = "Aefi.responsibleCommunity"; + String Aefi_responsibleDistrict = "Aefi.responsibleDistrict"; + String Aefi_responsibleRegion = "Aefi.responsibleRegion"; + String Aefi_serious = "Aefi.serious"; + String Aefi_seriousReason = "Aefi.seriousReason"; + String Aefi_seriousReasonDetails = "Aefi.seriousReasonDetails"; + String Aefi_startDateTime = "Aefi.startDateTime"; + String Aefi_todaysDate = "Aefi.todaysDate"; + String Aefi_trimester = "Aefi.trimester"; + String Aefi_uuid = "Aefi.uuid"; + String Aefi_worldwideId = "Aefi.worldwideId"; + String aefiActiveAdverseEvents = "aefiActiveAdverseEvents"; + String aefiAefiDataView = "aefiAefiDataView"; + String aefiAefiList = "aefiAefiList"; + String aefiAllActiveAndArchivedAdverseEvents = "aefiAllActiveAndArchivedAdverseEvents"; + String aefiArchivedAdverseEvents = "aefiArchivedAdverseEvents"; + String AefiCriteria_aefiType = "AefiCriteria.aefiType"; + String AefiCriteria_outcome = "AefiCriteria.outcome"; + String AefiCriteria_vaccineManufacturer = "AefiCriteria.vaccineManufacturer"; + String AefiCriteria_vaccineName = "AefiCriteria.vaccineName"; + String aefiDashboardAllAefi = "aefiDashboardAllAefi"; + String aefiDashboardNonSerious = "aefiDashboardNonSerious"; + String aefiDashboardNonSeriousAefi = "aefiDashboardNonSeriousAefi"; + String aefiDashboardSerious = "aefiDashboardSerious"; + String aefiDashboardSeriousAefi = "aefiDashboardSeriousAefi"; + String aefiDashboardShowNonSeriousAefi = "aefiDashboardShowNonSeriousAefi"; + String aefiDashboardShowSeriousAefi = "aefiDashboardShowSeriousAefi"; + String aefiDeletedAdverseEvents = "aefiDeletedAdverseEvents"; + String AefiIndex_adverseEvents = "AefiIndex.adverseEvents"; + String AefiIndex_ageAndBirthDate = "AefiIndex.ageAndBirthDate"; + String AefiIndex_disease = "AefiIndex.disease"; + String AefiIndex_district = "AefiIndex.district"; + String AefiIndex_immunizationUuid = "AefiIndex.immunizationUuid"; + String AefiIndex_outcome = "AefiIndex.outcome"; + String AefiIndex_personFirstName = "AefiIndex.personFirstName"; + String AefiIndex_personLastName = "AefiIndex.personLastName"; + String AefiIndex_personUuid = "AefiIndex.personUuid"; + String AefiIndex_primaryVaccine = "AefiIndex.primaryVaccine"; + String AefiIndex_region = "AefiIndex.region"; + String AefiIndex_reportDate = "AefiIndex.reportDate"; + String AefiIndex_serious = "AefiIndex.serious"; + String AefiIndex_sex = "AefiIndex.sex"; + String AefiIndex_startDateTime = "AefiIndex.startDateTime"; + String AefiIndex_uuid = "AefiIndex.uuid"; + String AefiIndex_vaccinationDate = "AefiIndex.vaccinationDate"; + String aefiNewAdverseEvent = "aefiNewAdverseEvent"; + String aefiVaccinationsDiluentBatchLotNumber = "aefiVaccinationsDiluentBatchLotNumber"; + String aefiVaccinationsDiluentExpiryDate = "aefiVaccinationsDiluentExpiryDate"; + String aefiVaccinationsDiluentInformation = "aefiVaccinationsDiluentInformation"; + String aefiVaccinationsDiluentTimeOfReconstitution = "aefiVaccinationsDiluentTimeOfReconstitution"; + String aefiVaccinationsPrimaryVaccine = "aefiVaccinationsPrimaryVaccine"; + String aefiVaccinationsVaccineDetails = "aefiVaccinationsVaccineDetails"; + String aefiVaccinationsVaccineInformation = "aefiVaccinationsVaccineInformation"; String AggregateReport_deaths = "AggregateReport.deaths"; String AggregateReport_disease = "AggregateReport.disease"; String AggregateReport_grouping = "AggregateReport.grouping"; @@ -914,6 +1015,7 @@ public interface Captions { String dashboardNotVisitedFor = "dashboardNotVisitedFor"; String dashboardNotYetClassified = "dashboardNotYetClassified"; String dashboardNotYetClassifiedOnly = "dashboardNotYetClassifiedOnly"; + String dashboardNumberOfAdverseEvents = "dashboardNumberOfAdverseEvents"; String dashboardNumberOfCases = "dashboardNumberOfCases"; String dashboardNumberOfContacts = "dashboardNumberOfContacts"; String dashboardNumberOfSamples = "dashboardNumberOfSamples"; @@ -1690,6 +1792,7 @@ public interface Captions { String LoginSidebar_outbreakResponse = "LoginSidebar.outbreakResponse"; String LoginSidebar_poweredBy = "LoginSidebar.poweredBy"; String mainMenuAbout = "mainMenuAbout"; + String mainMenuAdverseEvents = "mainMenuAdverseEvents"; String mainMenuAggregateReports = "mainMenuAggregateReports"; String mainMenuCampaigns = "mainMenuCampaigns"; String mainMenuCases = "mainMenuCases"; @@ -1914,6 +2017,7 @@ public interface Captions { String personCreateNew = "personCreateNew"; String personDistrictPrompt = "personDistrictPrompt"; String personFindMatching = "personFindMatching"; + String personFullName = "personFullName"; String personLinkToCases = "personLinkToCases"; String personLinkToContacts = "personLinkToContacts"; String personLinkToEvents = "personLinkToEvents"; @@ -2748,6 +2852,7 @@ public interface Captions { String versionIsMissing = "versionIsMissing"; String view = "view"; String View_actions = "View.actions"; + String View_adverseevents = "View.adverseevents"; String View_aggregatereports = "View.aggregatereports"; String View_aggregatereports_aggregatereporting = "View.aggregatereports.aggregatereporting"; String View_aggregatereports_reportdata = "View.aggregatereports.reportdata"; @@ -2821,6 +2926,7 @@ public interface Captions { String View_contacts_person = "View.contacts.person"; String View_contacts_sub = "View.contacts.sub"; String View_contacts_visits = "View.contacts.visits"; + String View_dashboard_adverseevents = "View.dashboard.adverseevents"; String View_dashboard_campaigns = "View.dashboard.campaigns"; String View_dashboard_contacts = "View.dashboard.contacts"; String View_dashboard_samples = "View.dashboard.samples"; diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Descriptions.java b/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Descriptions.java index 2b093c11be0..e45b067dca1 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Descriptions.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Descriptions.java @@ -10,6 +10,9 @@ public interface Descriptions { * 1. java:S115: Violation of name convention for constants of this class is accepted: Close as false positive. */ + String aefiDashboardDiseaseFilter = "aefiDashboardDiseaseFilter"; + String aefiDashboardDistrictFilter = "aefiDashboardDistrictFilter"; + String aefiDashboardRegionFilter = "aefiDashboardRegionFilter"; String Campaign_calculatedBasedOn = "Campaign.calculatedBasedOn"; String Campaign_campaignPhase = "Campaign.campaignPhase"; String CaseData_caseClassification = "CaseData.caseClassification"; 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 ed87fae2ee3..42c2dd68365 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 @@ -53,6 +53,7 @@ public interface Strings { String close = "close"; String comparedTo = "comparedTo"; String confirmationAlsoAdjustQuarantine = "confirmationAlsoAdjustQuarantine"; + String confirmationArchiveAdverseEvent = "confirmationArchiveAdverseEvent"; String confirmationArchiveArea = "confirmationArchiveArea"; String confirmationArchiveAreas = "confirmationArchiveAreas"; String confirmationArchiveCampaign = "confirmationArchiveCampaign"; @@ -96,6 +97,7 @@ public interface Strings { String confirmationCancelFollowUp = "confirmationCancelFollowUp"; String confirmationChangeCaseDisease = "confirmationChangeCaseDisease"; String confirmationContactSourceCaseDiscardUnsavedChanges = "confirmationContactSourceCaseDiscardUnsavedChanges"; + String confirmationDearchiveAdverseEvent = "confirmationDearchiveAdverseEvent"; String confirmationDearchiveArea = "confirmationDearchiveArea"; String confirmationDearchiveAreas = "confirmationDearchiveAreas"; String confirmationDearchiveCampaign = "confirmationDearchiveCampaign"; @@ -217,6 +219,8 @@ public interface Strings { String entityActivityAsCase = "entityActivityAsCase"; String entityAdditionalTest = "entityAdditionalTest"; String entityAdditionalTests = "entityAdditionalTests"; + String entityAdverseEvent = "entityAdverseEvent"; + String entityAdverseEvents = "entityAdverseEvents"; String entityAggregateReports = "entityAggregateReports"; String entityAreas = "entityAreas"; String entityAutomaticSoftDeletion = "entityAutomaticSoftDeletion"; @@ -298,6 +302,7 @@ public interface Strings { String entityWeeklyReports = "entityWeeklyReports"; String epiWeek = "epiWeek"; String errorAccessDenied = "errorAccessDenied"; + String errorAdverseEventNotEditable = "errorAdverseEventNotEditable"; String errorCampaignDiagramTotalsCalculationError = "errorCampaignDiagramTotalsCalculationError"; String errorCampaignNotEditable = "errorCampaignNotEditable"; String errorCaseDuplicateDeletion = "errorCaseDuplicateDeletion"; @@ -412,9 +417,21 @@ public interface Strings { String headingActivityAsCaseDetails = "headingActivityAsCaseDetails"; String headingAdditionalTests = "headingAdditionalTests"; String headingAdjustQuarantine = "headingAdjustQuarantine"; + String headingAefiAdverseEvents = "headingAefiAdverseEvents"; + String headingAefiDashboardEpiCurve = "headingAefiDashboardEpiCurve"; + String headingAefiDashboardMap = "headingAefiDashboardMap"; + String headingAefiFirstDecisionLevel = "headingAefiFirstDecisionLevel"; + String headingAefiNationalDecisionLevel = "headingAefiNationalDecisionLevel"; + String headingAefiPatientsAgeAtOnset = "headingAefiPatientsAgeAtOnset"; + String headingAefiPatientsIdentification = "headingAefiPatientsIdentification"; + String headingAefiPickPrimarySuspectVaccine = "headingAefiPickPrimarySuspectVaccine"; + String headingAefiReportersInformation = "headingAefiReportersInformation"; + String headingAefiReportingInformation = "headingAefiReportingInformation"; + String headingAefiVaccinations = "headingAefiVaccinations"; String headingAllContacts = "headingAllContacts"; String headingAnimalContactDetails = "headingAnimalContactDetails"; String headingAnimalContacts = "headingAnimalContacts"; + String headingArchiveAdverseEvent = "headingArchiveAdverseEvent"; String headingArchiveCampaign = "headingArchiveCampaign"; String headingArchiveCase = "headingArchiveCase"; String headingArchiveContact = "headingArchiveContact"; @@ -535,6 +552,7 @@ public interface Strings { String headingCustomizableEnumConfigurationInfo = "headingCustomizableEnumConfigurationInfo"; String headingDatabaseExportFailed = "headingDatabaseExportFailed"; String headingDataImport = "headingDataImport"; + String headingDearchiveAdverseEvent = "headingDearchiveAdverseEvent"; String headingDearchiveCampaign = "headingDearchiveCampaign"; String headingDearchiveCase = "headingDearchiveCase"; String headingDearchiveContact = "headingDearchiveContact"; @@ -644,6 +662,7 @@ public interface Strings { String headingHospitalization = "headingHospitalization"; String headingHowToMergeCases = "headingHowToMergeCases"; String headingHowToMergeContacts = "headingHowToMergeContacts"; + String headingImmunizationAdverseEvents = "headingImmunizationAdverseEvents"; String headingImmunizationsDeleted = "headingImmunizationsDeleted"; String headingImmunizationsNotDeleted = "headingImmunizationsNotDeleted"; String headingImmunizationsNotRestored = "headingImmunizationsNotRestored"; @@ -874,6 +893,8 @@ public interface Strings { String inColumn = "inColumn"; String infoActivityAsCaseInvestigation = "infoActivityAsCaseInvestigation"; String infoAddTestsToSample = "infoAddTestsToSample"; + String infoAefiSelectPrimarySuspectVaccine = "infoAefiSelectPrimarySuspectVaccine"; + String infoArchivedAefiEntries = "infoArchivedAefiEntries"; String infoArchivedCases = "infoArchivedCases"; String infoArchivedContacts = "infoArchivedContacts"; String infoArchivedEventParticipants = "infoArchivedEventParticipants"; @@ -967,6 +988,7 @@ public interface Strings { String infoExposuresRiskAreaHint = "infoExposuresRiskAreaHint"; String infoFacilityCsvImport = "infoFacilityCsvImport"; String infoFacilityNeedsDistrict = "infoFacilityNeedsDistrict"; + String infoHeadingAefiDashboardMap = "infoHeadingAefiDashboardMap"; String infoHeadingEnvironmentSampleDashboardMap = "infoHeadingEnvironmentSampleDashboardMap"; String infoHeadingSampleDashboardMap = "infoHeadingSampleDashboardMap"; String infoHowToMergeCases = "infoHowToMergeCases"; @@ -998,6 +1020,7 @@ public interface Strings { String infoNoDiseaseSelected = "infoNoDiseaseSelected"; String infoNoEnvironmentSamples = "infoNoEnvironmentSamples"; String infoNoEventGroups = "infoNoEventGroups"; + String infoNoImmunizationAdverseEvents = "infoNoImmunizationAdverseEvents"; String infoNoNetworkDiagram = "infoNoNetworkDiagram"; String infoNoPathogenTests = "infoNoPathogenTests"; String infoNoSourceCase = "infoNoSourceCase"; @@ -1095,6 +1118,9 @@ public interface Strings { String messageActivateAccount = "messageActivateAccount"; String messageAdditionalTestDeleted = "messageAdditionalTestDeleted"; String messageAdditionalTestSaved = "messageAdditionalTestSaved"; + String messageAdverseEventArchived = "messageAdverseEventArchived"; + String messageAdverseEventDearchived = "messageAdverseEventDearchived"; + String messageAdverseEventSaved = "messageAdverseEventSaved"; String messageAggregatedReportEpiWeekFilterNotFilled = "messageAggregatedReportEpiWeekFilterNotFilled"; String messageAggregateReportDelete = "messageAggregateReportDelete"; String messageAggregateReportExpiredAgeGroups = "messageAggregateReportExpiredAgeGroups"; @@ -1618,6 +1644,13 @@ public interface Strings { String promptActionDateTo = "promptActionDateTo"; String promptActionEpiWeekFrom = "promptActionEpiWeekFrom"; String promptActionEpiWeekTo = "promptActionEpiWeekTo"; + String promptAefiDashboardFilterDateType = "promptAefiDashboardFilterDateType"; + String promptAefiDateFrom = "promptAefiDateFrom"; + String promptAefiDateTo = "promptAefiDateTo"; + String promptAefiDateType = "promptAefiDateType"; + String promptAefiEpiWeekFrom = "promptAefiEpiWeekFrom"; + String promptAefiEpiWeekTo = "promptAefiEpiWeekTo"; + String promptAefiValidFrom = "promptAefiValidFrom"; String promptAllAreas = "promptAllAreas"; String promptAllCommunities = "promptAllCommunities"; String promptAllDistricts = "promptAllDistricts"; 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 b4b553421e9..68a9fbe69a4 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 @@ -10,6 +10,9 @@ public interface Validations { * 1. java:S115: Violation of name convention for constants of this class is accepted: Close as false positive. */ + String aefiWithoutAdverseEvents = "aefiWithoutAdverseEvents"; + String aefiWithoutPrimarySuspectVaccine = "aefiWithoutPrimarySuspectVaccine"; + String aefiWithoutSuspectVaccine = "aefiWithoutSuspectVaccine"; String afterDate = "afterDate"; String afterDateSoft = "afterDateSoft"; String afterDateWithDate = "afterDateWithDate"; 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 9d43f73733f..64684f3a800 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 @@ -63,6 +63,12 @@ public enum UserRight { IMMUNIZATION_ARCHIVE(UserRightGroup.IMMUNIZATION, UserRight._IMMUNIZATION_VIEW), IMMUNIZATION_VIEW_ARCHIVED(UserRightGroup.IMMUNIZATION), + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW(UserRightGroup.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION), + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE(UserRightGroup.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION), + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT(UserRightGroup.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION), + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE(UserRightGroup.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION), + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE(UserRightGroup.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION), + PERSON_VIEW(UserRightGroup.PERSON), PERSON_EDIT(UserRightGroup.PERSON, UserRight._PERSON_VIEW), PERSON_DELETE(UserRightGroup.PERSON, UserRight._PERSON_VIEW, UserRight._VISIT_DELETE), @@ -169,6 +175,7 @@ public enum UserRight { DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS(UserRightGroup.DASHBOARD, UserRight._DASHBOARD_CONTACT_VIEW), DASHBOARD_CAMPAIGNS_VIEW(UserRightGroup.DASHBOARD, UserRight._CAMPAIGN_VIEW), DASHBOARD_SAMPLES_VIEW(UserRightGroup.DASHBOARD, UserRight._SAMPLE_VIEW), + DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW(UserRightGroup.DASHBOARD, UserRight._ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW), CASE_CLINICIAN_VIEW(UserRightGroup.CASE_MANAGEMENT, UserRight._CASE_VIEW), @@ -324,6 +331,11 @@ public enum UserRight { public static final String _IMMUNIZATION_EDIT = "IMMUNIZATION_EDIT"; public static final String _IMMUNIZATION_DELETE = "IMMUNIZATION_DELETE"; public static final String _IMMUNIZATION_ARCHIVE = "IMMUNIZATION_ARCHIVE"; + public static final String _ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW = "ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW"; + public static final String _ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE = "ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE"; + public static final String _ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT = "ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT"; + public static final String _ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE = "ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE"; + public static final String _ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE = "ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE"; public static final String _PERSON_VIEW = "PERSON_VIEW"; public static final String _PERSON_EDIT = "PERSON_EDIT"; public static final String _PERSON_DELETE = "PERSON_DELETE"; @@ -419,6 +431,7 @@ public enum UserRight { public static final String _DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS = "DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS"; public static final String _DASHBOARD_CAMPAIGNS_VIEW = "DASHBOARD_CAMPAIGNS_VIEW"; public static final String _DASHBOARD_SAMPLES_VIEW = "DASHBOARD_SAMPLES_VIEW"; + public static final String _DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW = "DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW"; public static final String _CASE_CLINICIAN_VIEW = "CASE_CLINICIAN_VIEW"; public static final String _THERAPY_VIEW = "THERAPY_VIEW"; public static final String _PRESCRIPTION_CREATE = "PRESCRIPTION_CREATE"; diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/user/UserRightGroup.java b/sormas-api/src/main/java/de/symeda/sormas/api/user/UserRightGroup.java index ece02973739..7fa2dd34069 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/user/UserRightGroup.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/user/UserRightGroup.java @@ -35,6 +35,7 @@ public enum UserRightGroup { EVENT, SAMPLE, IMMUNIZATION, + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION, TRAVEL_ENTRY, CAMPAIGN, ENVIRONMENT, diff --git a/sormas-api/src/main/resources/captions.properties b/sormas-api/src/main/resources/captions.properties index a2fdb57909f..70623db15e1 100644 --- a/sormas-api/src/main/resources/captions.properties +++ b/sormas-api/src/main/resources/captions.properties @@ -195,6 +195,8 @@ actionOkAndGoToPersonDirectory = Okay, and continue to person directory actionExecuteAutomaticDeletion = Execute automatic deletion actionDone = Done actionConfirmAction = Confirm action +actionAefiSelectPrimarySuspectVaccination = Select Suspect Vaccination +actionAefiAssignNewReportingIdNumber = "Assign New AEFI ID" activityAsCaseFlightNumber=Flight number ActivityAsCase=Activity as case ActivityAsCase.startDate=Start of activity @@ -1003,6 +1005,7 @@ dashboardAggregatedNumber=Count dashboardProportion=Proportion (%) dashboardViewAsColumnChart=View as Column Chart dashboardViewAsBarChart=View as Bar Chart +dashboardNumberOfAdverseEvents=Number of Adverse Events #SampleDashboard sampleDashboardAllSamples=All Samples sampleDashboardFinalLabResults=Final Laboratory Results @@ -1018,6 +1021,15 @@ sampleDashboardShowCaseSamples=Show Case Samples sampleDashboardShowContactSamples=Show Contact Samples sampleDashboardShowEventParticipantSamples=Show Event Participant Samples sampleDashboardShowEnvironmentSamples=Show Environment Samples +#AefiDashboard +aefiDashboardAllAefi=All AEFI +aefiDashboardSerious=Serious +aefiDashboardNonSerious=Non Serious +aefiDashboardSeriousAefi=Serious AEFI +aefiDashboardNonSeriousAefi=Non-Serious AEFI +aefiDashboardShowSeriousAefi=Show Serious AEFI +aefiDashboardShowNonSeriousAefi=Show Non-Serious AEFI + captionDefault=Default defaultRegion=Default Region defaultDistrict=Default District @@ -1697,6 +1709,7 @@ mainMenuEntries=Entries mainMenuEvents=Events mainMenuExternalMessages=Messages mainMenuImmunizations=Immunizations +mainMenuAdverseEvents=Adverse Events mainMenuReports=Reports mainMenuSamples=Samples mainMenuEnvironments=Environments @@ -1794,6 +1807,7 @@ personFindMatching=Find matching persons personSelect=Select a matching person personSearchAndSelect=Select a different person personAgeAndBirthdate=Age and birth date +personFullName=Full name personNoEventParticipantLinkedToPerson=No event participant linked to person personNoCaseLinkedToPerson=No case linked to person personNoContactLinkedToPerson=No contact linked to person @@ -2228,6 +2242,102 @@ immunizationOnlyPersonsWithOverdueImmunization=Only show persons with overdue im immunizationOverwriteImmunization=Overwrite the existing immunization with this data immunizationCreateNewImmunization=Create the new immunization anyway immunizationNoImmunizationsForPerson=There are no immunizations for this person +# Adverse Events Following Immunization +Aefi.primaryVaccineVaccinationDate=Vaccination date +Aefi.uuid=Adverse event UUID +Aefi.reportDate=Date of report +Aefi.reportingUser=Reporting user +Aefi.externalId=External ID +Aefi.responsibleRegion=Responsible region +Aefi.responsibleDistrict=Responsible district +Aefi.responsibleCommunity=Responsible community +Aefi.country=Country +Aefi.reportingIdNumber=Reporting ID Number +Aefi.pregnant=Pregnant +Aefi.trimester=Trimester +Aefi.lactating=Lactating +Aefi.onsetAgeYears=Years +Aefi.onsetAgeMonths=Months +Aefi.onsetAgeDays=Days +Aefi.ageGroup=Age group +Aefi.healthFacility=Facility +Aefi.healthFacilityDetails=Facility name & description +Aefi.reporterName=Name +Aefi.reporterInstitution=Insitution +Aefi.reporterDesignation=Designation +Aefi.reporterDepartment=Department +Aefi.reporterPhone=Phone number +Aefi.reporterEmail=Email +Aefi.todaysDate=Today's date +Aefi.startDateTime=Date and time AEFI started +Aefi.aefiDescription=Describe AEFI (Signs and symptoms) +Aefi.serious=Serious +Aefi.seriousReason=Reason for serious +Aefi.seriousReasonDetails=Reason for serious details +Aefi.outcome=Outcome +Aefi.deathDate=Date of death +Aefi.autopsyDone=Autopsy done +Aefi.pastMedicalHistory=Past medical history +Aefi.investigationNeeded=Investigation needed +Aefi.investigationPlannedDate=Date investigation planned +Aefi.receivedAtNationalLevelDate=Date received at national +Aefi.worldwideId=AEFI worldwide unique ID +Aefi.nationalLevelComment=Comment +Aefi.deletionReason=Reason for deletion +Aefi.otherDeletionReason=Reason for deletion details +Aefi.creationDate=Creation date +Aefi.changeDate=Date of last change +aefiNewAdverseEvent=New Adverse Event +aefiAefiList=Adverse Events List +aefiAefiDataView=Adverse Event +aefiVaccinationsVaccineInformation=Vaccine Information +aefiVaccinationsPrimaryVaccine=Primary +aefiVaccinationsVaccineDetails=Vaccine details +aefiVaccinationsDiluentInformation=Diluent Information +aefiVaccinationsDiluentBatchLotNumber=Batch/Lot number +aefiVaccinationsDiluentExpiryDate=Expiry date +aefiVaccinationsDiluentTimeOfReconstitution=Reconstitution time +aefiActiveAdverseEvents = Active adverse events +aefiArchivedAdverseEvents = Archived adverse events +aefiAllActiveAndArchivedAdverseEvents = All active and archived adverse events +aefiDeletedAdverseEvents = Deleted adverse events +# Adverse Events +AdverseEvents.severeLocalReaction=Severe local reaction +AdverseEvents.severeLocalReactionMoreThanThreeDays=>3 days +AdverseEvents.severeLocalReactionBeyondNearestJoint=Beyond nearest joint +AdverseEvents.seizures=Seizures +AdverseEvents.seizureType=Seizure type +AdverseEvents.abscess=Abscess +AdverseEvents.sepsis=Sepsis +AdverseEvents.encephalopathy=Encephalopathy +AdverseEvents.toxicShockSyndrome=Toxic shock syndrome +AdverseEvents.thrombocytopenia=Thrombocytopenia +AdverseEvents.anaphylaxis=Anaphylaxis +AdverseEvents.feverishFeeling=Fever >38degC +AdverseEvents.otherAdverseEventDetails=Other (specify) +# Adverse Events Index +AefiIndex.uuid=AEFI ID +AefiIndex.immunizationUuid=Immunization ID +AefiIndex.personUuid=Person ID +AefiIndex.personFirstName=First Name +AefiIndex.personLastName=Last Name +AefiIndex.reportDate=Date of report +AefiIndex.disease=Disease +AefiIndex.ageAndBirthDate=Age and birth date +AefiIndex.sex=Sex +AefiIndex.region=Region +AefiIndex.district=District +AefiIndex.serious=Serious +AefiIndex.primaryVaccine=Suspect Vaccine +AefiIndex.outcome=Outcome +AefiIndex.vaccinationDate=Date of vaccination +AefiIndex.startDateTime=Date of AEFI onset +AefiIndex.adverseEvents=Adverse events +# Advers Events Criteria +AefiCriteria.aefiType=AEFI Type +AefiCriteria.outcome=Outcome +AefiCriteria.vaccineName=Vaccine +AefiCriteria.vaccineManufacturer=Manufacturer # Statistics statisticsAddFilter=Add filter statisticsAttribute=Attribute @@ -2712,6 +2822,7 @@ View.dashboard.contacts=Contacts Dashboard View.dashboard.surveillance=Surveillance Dashboard View.dashboard.campaigns=Campaigns Dashboard View.dashboard.samples=Samples Dashboard +View.dashboard.adverseevents=Adverse Events Dashboard View.events=Event Directory View.events.archive=Event Archive View.events.data=Event Information @@ -2728,6 +2839,7 @@ View.samples.data=Sample Information View.samples.sub= View.travelEntries=Travel Entries Directory View.immunizations=Immunization Directory +View.adverseevents=Adverse Events Directory View.statistics=Statistics View.statistics.database-export=Database export View.tasks=Task Management diff --git a/sormas-api/src/main/resources/descriptions.properties b/sormas-api/src/main/resources/descriptions.properties index 74693af7bd6..66bc7df81fd 100644 --- a/sormas-api/src/main/resources/descriptions.properties +++ b/sormas-api/src/main/resources/descriptions.properties @@ -232,4 +232,8 @@ sampleDashboardRegionFilter= The region of the associated Case/Contact/Event par sampleDashboardDistrictFilter= The district of the associated Case/Contact/Event participant sampleDashboardDiseaseFilter= The disease of the associated Case/Contact/Event participant's event sampleDashboardCountsByShipmentStatus=Only samples with the purpose external lab testing are considered -sampleDashboardCountsBySpecimenCondition=Only samples received and with the purpose external lab testing are considered \ No newline at end of file +sampleDashboardCountsBySpecimenCondition=Only samples received and with the purpose external lab testing are considered + +aefiDashboardRegionFilter= The region of the associated immunization +aefiDashboardDistrictFilter= The district of the associated immunization +aefiDashboardDiseaseFilter= The disease of the associated immunization \ No newline at end of file diff --git a/sormas-api/src/main/resources/enum.properties b/sormas-api/src/main/resources/enum.properties index 35fa86fe9f5..5880c9e0f00 100644 --- a/sormas-api/src/main/resources/enum.properties +++ b/sormas-api/src/main/resources/enum.properties @@ -291,6 +291,7 @@ CustomizableEnumType.PATHOGEN = Pathogen DashboardType.CONTACTS = Contacts DashboardType.SURVEILLANCE = Surveillance DashboardType.CAMPAIGNS = Campaigns +DashboardType.ADVERSE_EVENTS = Adverse Events # DatabaseTable DatabaseTable.ACTIONS = Actions @@ -1550,6 +1551,11 @@ UserRight.IMMUNIZATION_CREATE = Create new immunizations and vaccinations UserRight.IMMUNIZATION_EDIT = Edit existing immunizations and vaccinations UserRight.IMMUNIZATION_DELETE = Delete immunizations and vaccinations from the system UserRight.IMMUNIZATION_ARCHIVE = Archive immunizations +UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW = View existing adverse events following immunization +UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE = Create new adverse event following immunization +UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT = Edit existing adverse event following immunization +UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE = Delete adverse events following immunization from the system +UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE = Archive adverse events following immunization UserRight.PERSON_EXPORT = Export persons UserRight.CONTACT_MERGE = Merge contacts UserRight.EVENTGROUP_CREATE = Create new event groups @@ -1768,6 +1774,11 @@ UserRight.Desc.IMMUNIZATION_CREATE = Able to create new immunizations and vaccin UserRight.Desc.IMMUNIZATION_EDIT = Able to edit existing immunizations and vaccinations UserRight.Desc.IMMUNIZATION_DELETE = Able to delete immunizations and vaccinations from the system UserRight.Desc.IMMUNIZATION_ARCHIVE = Able to archive immunizations +UserRight.Desc.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW = Able to view existing adverse events following immunization +UserRight.Desc.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE = Able to create new adverse event following immunization +UserRight.Desc.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT = Able to edit existing adverse events following immunization +UserRight.Desc.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE = Able to delete adverse events following immunization from the system +UserRight.Desc.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE = Able to archive adverse events following immunization UserRight.Desc.PERSON_EXPORT = Able to export persons UserRight.Desc.CONTACT_MERGE = Able to merge contacts UserRight.Desc.EVENTGROUP_CREATE = Able to create new event groups @@ -1838,6 +1849,7 @@ UserRightGroup.CONTACT = Contact Surveillance UserRightGroup.VISIT = Follow-Up UserRightGroup.SAMPLE = Sample Testing UserRightGroup.IMMUNIZATION = Immunization +UserRightGroup.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION = Adverse Events Following Immunization UserRightGroup.TRAVEL_ENTRY = Travel Entries UserRightGroup.TASK = Tasks UserRightGroup.EVENT = Events @@ -2333,3 +2345,43 @@ SelfReportInvestigationStatus.REJECTED=Rejected # SelfReportProcessingStatus SelfReportProcessingStatus.UNPROCESSED=Unprocessed SelfReportProcessingStatus.PROCESSED=Processed + +# AefiAgeGroup +AefiAgeGroup.ZERO_TO_ONE = 0 < 1 year +AefiAgeGroup.ONE_TO_FIVE = 1- 5 years +AefiAgeGroup.FIVE_TO_EIGHTEEN = > 5 years - 18 years +AefiAgeGroup.EIGHTEEN_TO_SIXTY = > 18 years - 60 years +AefiAgeGroup.SIXY_AND_ABOVE = > 60 years + +# SeizureType +SeizureType.FEBRILE=Febrile +SeizureType.AFEBRILE=Afebrile + +# SeriousAefiReason +SeriousAefiReason.DEATH=Death +SeriousAefiReason.LIFE_THREATENING=Life threatening +SeriousAefiReason.DISABILITY=Disability +SeriousAefiReason.HOSPITALIZATION=Hospitalization +SeriousAefiReason.CONGENITAL_ANOMALY=Congenital anomaly +SeriousAefiReason.OTHER=Other + +# AefiOutcome +AefiOutcome.RECOVERING=Recovering +AefiOutcome.RECOVERED=Recovered +AefiOutcome.RECOVERED_WITH_SEQUELAE=Recovered with sequelae +AefiOutcome.NOT_RECOVERED=Not Recovered +AefiOutcome.UNKNOWN=Unknown +AefiOutcome.DIED=Died + +# AefiType +AefiType.SERIOUS=Serious +AefiType.NON_SERIOUS=Non-serious + +# AefiDateType +AefiDateType.REPORT_DATE=Date of report +AefiDateType.START_DATE=Date of onset +AefiDateType.VACCINATION_DATE=Date of vaccination + +# AefiDashboardFilterDateType +AefiDashboardFilterDateType.REPORT_DATE=Date of report +AefiDashboardFilterDateType.START_DATE=Date of onset \ No newline at end of file diff --git a/sormas-api/src/main/resources/strings.properties b/sormas-api/src/main/resources/strings.properties index fc1854df695..845fd0c6f1f 100644 --- a/sormas-api/src/main/resources/strings.properties +++ b/sormas-api/src/main/resources/strings.properties @@ -136,6 +136,7 @@ confirmationArchiveEvent = Are you sure you want to archive this event? This wil confirmationArchiveEvents = Are you sure you want to archive all %d selected events? confirmationArchiveEventParticipant = Are you sure you want to archive this event participant? This will not remove it from the system or any statistics, but only hide it from the list of event participants. confirmationArchiveImmunization = Are you sure you want to archive this immunization? This will not remove it from the system or any statistics, but only hide it from the normal immunization directory. +confirmationArchiveAdverseEvent = Are you sure you want to archive this adverse event? This will not remove it from the system or any statistics, but only hide it from the normal adverse events directory. confirmationArchiveTask = Are you sure you want to archive this task? This will not remove it from the system or any statistics, but only hide it from the normal task management. confirmationArchiveTasks = Are you sure you want to archive all %d selected tasks? confirmationArchiveTravelEntry = Are you sure you want to archive this travel entry? This will not remove it from the system or any statistics, but only hide it from the normal travel entry directory. @@ -217,6 +218,7 @@ confirmationDearchiveCommunities = Are you sure you want to de-archive all %d se confirmationArchiveFacilities = Are you sure you want to archive all %d selected facilities? confirmationDearchiveFacilities = Are you sure you want to de-archive all %d selected facilities? confirmationDearchiveImmunization = Are you sure you want to de-archive this immunization? This will make it appear in the normal immunization directory again. +confirmationDearchiveAdverseEvent = Are you sure you want to de-archive this adverse event? This will make it appear in the normal adverse events directory again. confirmationArchiveLaboratories = Are you sure you want to archive all %d selected laboratories? confirmationDearchiveLaboratories = Are you sure you want to de-archive all %d selected laboratories? confirmationDearchiveTask = Are you sure you want to de-archive this task? This will make it appear in the normal task directory again. @@ -339,6 +341,12 @@ entityUsers = Users entityVaccinations = Vaccinations entityVisits = Visits entityWeeklyReports = Weekly reports +entityOutbreaks = Outbreaks +entityCustomizableEnumValues = Customizable enum values +entityCampaignFormMeta = Campaign form meta +entityCampaignFormData = Campaign form data +entityAdverseEvent = Adverse event +entityAdverseEvents = Adverse events # Error Messages errorAccessDenied=You do not have the required rights to view this page. @@ -426,6 +434,7 @@ errorEnvironmentSampleNoDispatchRight = You do not have the necessary user right errorEnvironmentSampleNoReceivalRight = You do not have the necessary user right to change the receival status of this environment sample errorSendingExternalEmail = Email could not be sent. Please contact an admin and notify them about this problem. errorExternalEmailAttachmentCannotEncrypt=Can't send email with attachments. The person has no national health id or primary phone number to send the password to or the SMS service is not set up in the system. +errorAdverseEventNotEditable = This adverse event is not editable anymore errorExternalEmailMissingPersonEmailAddress=This person does not have an email address # headings @@ -442,6 +451,7 @@ headingArchiveEvent = Archive event headingArchiveEventParticipant = Archive event participant headingArchiveEventGroup = Archive event group headingArchiveImmunization = Archive immunization +headingArchiveAdverseEvent = Archive adverse event headingArchiveTravelEntry = Archive travel entry headingCampaignBasics = Campaign basics headingCampaignData = Campaign data @@ -873,6 +883,16 @@ headingLimitedDiseases=Disease restrictions headingExternalEmailSend=Send email headingExternalEmailDetails=Email details headingCustomizableEnumConfigurationInfo=Customizable enum configuration +headingImmunizationAdverseEvents=Adverse events +headingAefiReportingInformation=Reporting information +headingAefiPatientsIdentification=Patients identification +headingAefiPatientsAgeAtOnset=Age at onset +headingAefiVaccinations=Vaccinations +headingAefiAdverseEvents=Adverse events +headingAefiFirstDecisionLevel=First decision Level +headingAefiNationalDecisionLevel=National Decision Level +headingAefiReportersInformation=Reporter's information +headingAefiPickPrimarySuspectVaccine=Select primary suspect vaccine # Info texts infoActivityAsCaseInvestigation = Please document ALL relevant activities after infection: @@ -1032,6 +1052,7 @@ infoContactsViewRegionDistrictFilter = When you select a region and/or district infoDeveloperOptions = You can use the controls below to generate dummy cases and contacts based on the selected restraints. Please note that generating a lot of data at once might take some time.
Generated data is neither fully deterministic, nor fully random, and intended for testing and demonstration purposes only. infoDeveloperOptionsContactGeneration = When generating contacts, the generator will pick random existing cases as source. Please make sure the case database is not empty before generating contacts. infoDeveloperOptionsSeedUsage = Using the seed will create identical datasets, provided the starting conditions (configuration & database) are also identical +infoCreateNewSampleDiscardsChangesCase = Creating a new sample will discard all unsaved changes made to this case infoCreateNewSampleDiscardsChangesContact = Creating a new sample will discard all unsaved changes made to this contact infoCreateNewSampleDiscardsChangesEventParticipant = Creating a new sample will discard all unsaved changes made to this event participant infoUsageOfEditableCampaignGrids = You can edit the campaign data and dashboard definitions by clicking inside one of the cells in the grid, and you can reorder the dashboard elements by dragging and dropping the grid rows @@ -1074,6 +1095,9 @@ infoNoEnvironmentSamples = No samples have been created for this environment infoRestrictDiseasesDescription=Mark all diseases that the user is supposed to have access to infoNoCustomizableEnumTranslations = Click on the + button below to add translations to this customizable enum value. infoCustomizableEnumConfigurationInfo = Customizable enums are value sets that can be customized in order to react to the individual needs of your country or a specific epidemiological situation. The table on this screen contains all customizable enum values in the database. Each value is associated with a data type, e.g. disease variants or occupation types. Some of these data types have default values that are automatically added to the database when SORMAS is set up or new data types are added to the system.

You can add new enum values or edit existing ones, add translations for languages supported by SORMAS, select the diseases that the value should be visible for (by default, customizable enum values are visible for all diseases), and configure additional properties.

Properties are used to further control the behaviour of customizable enum values. E.g. the "has details" property that is supported by most enum values toggles whether selecting this enum value would bring up an additional text field that users can add more information to. +infoNoImmunizationAdverseEvents = No adverse events have been created for this immunization +infoAefiSelectPrimarySuspectVaccine = The list below contains all vaccinations of the immunization. Please select the suspect vaccination related to this adverse event. +infoArchivedAefiEntries = Adverse event entries are automatically archived after %d days without changes to the data. # Messages messageActionOutsideJurisdictionDeletionDenied = The action outside user's jurisdiction cannot be deleted @@ -1255,6 +1279,8 @@ messageImmunizationDearchived = Immunization has been de-archived messageImmunizationOutsideJurisdictionDeletionDenied = The immunization outside user's jurisdiction cannot be deleted messageImmunizationSaved = Immunization data saved. messageImmunizationSavedVaccinationStatusUpdated = Immunization data saved. The vaccination status of matching cases, contacts, and event participants of the immunization person has been updated to vaccinated. +messageAdverseEventArchived = Adverse event has been archived +messageAdverseEventDearchived = Adverse event has been de-archived messageImportCanceled = Import canceled!
The import has been canceled. All already processed rows have been successfully imported. You can now close this window. messageImportCanceledErrors = Import canceled!
The import has been canceled. Some of the already processed rows could not be imported due to malformed data.
Please close this window and download the error report. messageImportError = Could not import file. @@ -1520,6 +1546,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. +messageAdverseEventSaved=Adverse event 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. @@ -1642,6 +1669,7 @@ promptImmunizationDateFrom = New immunizations from... promptImmunizationDateTo = ... to promptImmunizationEpiWeekFrom = New immunizations from epi week... promptImmunizationEpiWeekTo = ... to epi week +promptEmail = Email: promptExternalMessagesSearchField = UUID, name, postal code, reporter name, reporter postal code promptExternalMessagesContentSearchField = External message content promptExternalMessagesDateFrom = Message date from... @@ -1660,6 +1688,7 @@ promptSampleEpiWeekTo = ... to epi week promtSampleDataType = Sample reference date promptSearch = Search... promptTaskSearchField = Case or contact ID/name, Event ID/title +promptTelephoneNumber = Phone number: promptTaskDateType = Task reference date promptTaskDateFrom = Tasks from... promptTaskDateTo = ... to @@ -1685,7 +1714,13 @@ promptAllDistricts=All districts promptAllCommunities=All communities promptExternalIdExternalSurveillanceTool=Will adopt external reporting tool GUID promptExternalJournalForceDeletion=Do you want to force the cancellation in SORMAS? This would mark the person as deleted from the external journal in SORMAS, while there is a high probability of personal data still remaining in the external journal. -promptPersonDuplicateSearchIdExternalId=First Name, Last Name, ID, External ID, External token +promptPersonDuplicateSearchIdExternalId=First Name, Last Name, ID, External ID, External token +promptAefiDateType = Aefi reference date +promptAefiValidFrom = New adverse events valid from... +promptAefiDateFrom = New adverse events from... +promptAefiDateTo = ... to +promptAefiEpiWeekFrom = New adverse events from epi week... +promptAefiEpiWeekTo = ... to epi week #DiseaseNetworkDiagram DiseaseNetworkDiagram.Classification.HEALTHY = Healthy DiseaseNetworkDiagram.heading = Disease network diagram @@ -1798,6 +1833,11 @@ headingSampleDashboardMap=Sample Status Map infoHeadingSampleDashboardMap=Samples are shown using the GPS coordinate of the person's home address. infoHeadingEnvironmentSampleDashboardMap=Environment samples are shown using the GPS coordinates of those samples or, if not available, their associated environment. +promptAefiDashboardFilterDateType=AEFI reference date +headingAefiDashboardEpiCurve=Adverse Events Type Chart +headingAefiDashboardMap=Adverse Events Status Map +infoHeadingAefiDashboardMap=Adverse events are shown using the GPS coordinate of the facility or person's home address. + headingSpecailCaseAccess = Grant special access headingCreateSpecailCaseAccess = Create new special access headingEditSpecailCaseAccess = Edit special access diff --git a/sormas-api/src/main/resources/validations.properties b/sormas-api/src/main/resources/validations.properties index 2e875813934..ac49b31d7e3 100644 --- a/sormas-api/src/main/resources/validations.properties +++ b/sormas-api/src/main/resources/validations.properties @@ -297,6 +297,9 @@ customizableEnumValueEmptyTranslations = Please select languages and enter capti 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. +aefiWithoutSuspectVaccine=You have to select at least one suspect vaccine +aefiWithoutPrimarySuspectVaccine=You have to select the primary suspect vaccine +aefiWithoutAdverseEvents=You have to select at least one adverse event invalidNationalHealthId=This value does not seem to be a correct national health ID invalidSelfReportType = Invalid SelfReport type selfReportAlreadyProcessedError = The self report was processed by another user in the meantime. diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AdverseEventsMapper.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AdverseEventsMapper.java new file mode 100644 index 00000000000..24b4abb88ea --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AdverseEventsMapper.java @@ -0,0 +1,82 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import javax.ejb.LocalBean; +import javax.ejb.Stateless; +import javax.validation.constraints.NotNull; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AdverseEvents; +import de.symeda.sormas.backend.util.DtoHelper; + +@LocalBean +@Stateless(name = "AdverseEventsMapper") +public class AdverseEventsMapper { + + public static AdverseEventsDto toDto(AdverseEvents source) { + + if (source == null) { + return null; + } + + AdverseEventsDto target = new AdverseEventsDto(); + DtoHelper.fillDto(target, source); + + target.setSevereLocalReaction(source.getSevereLocalReaction()); + target.setSevereLocalReactionMoreThanThreeDays(source.isSevereLocalReactionMoreThanThreeDays()); + target.setSevereLocalReactionBeyondNearestJoint(source.isSevereLocalReactionBeyondNearestJoint()); + target.setSeizures(source.getSeizures()); + target.setSeizureType(source.getSeizureType()); + target.setAbscess(source.getAbscess()); + target.setSepsis(source.getSepsis()); + target.setEncephalopathy(source.getEncephalopathy()); + target.setToxicShockSyndrome(source.getToxicShockSyndrome()); + target.setThrombocytopenia(source.getThrombocytopenia()); + target.setAnaphylaxis(source.getAnaphylaxis()); + target.setFeverishFeeling(source.getFeverishFeeling()); + target.setOtherAdverseEventDetails(source.getOtherAdverseEventDetails()); + + return target; + } + + public AdverseEvents fillOrBuildEntity(@NotNull AdverseEventsDto source, AdverseEvents target, boolean checkChangeDate) { + if (source == null) { + return null; + } + + target = DtoHelper.fillOrBuildEntity(source, target, AdverseEvents::new, checkChangeDate); + + target.setSevereLocalReaction(source.getSevereLocalReaction()); + target.setSevereLocalReactionMoreThanThreeDays(source.isSevereLocalReactionMoreThanThreeDays()); + target.setSevereLocalReactionBeyondNearestJoint(source.isSevereLocalReactionBeyondNearestJoint()); + target.setSeizures(source.getSeizures()); + target.setSeizureType(source.getSeizureType()); + target.setAbscess(source.getAbscess()); + target.setSepsis(source.getSepsis()); + target.setEncephalopathy(source.getEncephalopathy()); + target.setToxicShockSyndrome(source.getToxicShockSyndrome()); + target.setThrombocytopenia(source.getThrombocytopenia()); + target.setAnaphylaxis(source.getAnaphylaxis()); + target.setFeverishFeeling(source.getFeverishFeeling()); + target.setOtherAdverseEventDetails(source.getOtherAdverseEventDetails()); + + return target; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiFacadeEjb.java new file mode 100644 index 00000000000..0d91053215e --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiFacadeEjb.java @@ -0,0 +1,455 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import javax.ejb.EJB; +import javax.ejb.LocalBean; +import javax.ejb.Stateless; +import javax.inject.Inject; +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventState; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiCriteria; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiFacade; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiIndexDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiListCriteria; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiListEntryDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiReferenceDto; +import de.symeda.sormas.api.common.DeletableEntityType; +import de.symeda.sormas.api.common.DeletionDetails; +import de.symeda.sormas.api.common.progress.ProcessedEntity; +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.immunization.ImmunizationDto; +import de.symeda.sormas.api.user.UserRight; +import de.symeda.sormas.api.utils.AccessDeniedException; +import de.symeda.sormas.api.utils.DateHelper; +import de.symeda.sormas.api.utils.SortProperty; +import de.symeda.sormas.api.utils.ValidationRuntimeException; +import de.symeda.sormas.api.vaccination.VaccinationDto; +import de.symeda.sormas.backend.FacadeHelper; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.Aefi; +import de.symeda.sormas.backend.common.AbstractCoreFacadeEjb; +import de.symeda.sormas.backend.immunization.ImmunizationFacadeEjb; +import de.symeda.sormas.backend.immunization.ImmunizationFacadeEjb.ImmunizationFacadeEjbLocal; +import de.symeda.sormas.backend.immunization.ImmunizationService; +import de.symeda.sormas.backend.infrastructure.community.CommunityFacadeEjb; +import de.symeda.sormas.backend.infrastructure.community.CommunityService; +import de.symeda.sormas.backend.infrastructure.country.CountryFacadeEjb; +import de.symeda.sormas.backend.infrastructure.country.CountryService; +import de.symeda.sormas.backend.infrastructure.district.DistrictFacadeEjb; +import de.symeda.sormas.backend.infrastructure.district.DistrictService; +import de.symeda.sormas.backend.infrastructure.facility.FacilityFacadeEjb; +import de.symeda.sormas.backend.infrastructure.facility.FacilityService; +import de.symeda.sormas.backend.infrastructure.region.RegionFacadeEjb; +import de.symeda.sormas.backend.infrastructure.region.RegionService; +import de.symeda.sormas.backend.location.LocationFacadeEjb; +import de.symeda.sormas.backend.location.LocationFacadeEjb.LocationFacadeEjbLocal; +import de.symeda.sormas.backend.person.PersonFacadeEjb; +import de.symeda.sormas.backend.person.PersonService; +import de.symeda.sormas.backend.user.User; +import de.symeda.sormas.backend.user.UserFacadeEjb; +import de.symeda.sormas.backend.util.DtoHelper; +import de.symeda.sormas.backend.util.Pseudonymizer; +import de.symeda.sormas.backend.util.RightsAllowed; +import de.symeda.sormas.backend.vaccination.Vaccination; +import de.symeda.sormas.backend.vaccination.VaccinationFacadeEjb; +import de.symeda.sormas.backend.vaccination.VaccinationFacadeEjb.VaccinationFacadeEjbLocal; +import de.symeda.sormas.backend.vaccination.VaccinationService; + +@Stateless(name = "AefiFacade") +@RightsAllowed(UserRight._ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW) +public class AefiFacadeEjb extends AbstractCoreFacadeEjb + implements AefiFacade { + + private final Logger logger = LoggerFactory.getLogger(AefiFacadeEjb.class); + + @EJB + private ImmunizationFacadeEjbLocal immunizationFacade; + @EJB + private ImmunizationService immunizationService; + @EJB + private PersonService personService; + @EJB + private LocationFacadeEjbLocal locationFacade; + @EJB + private VaccinationFacadeEjbLocal vaccinationFacade; + @EJB + private VaccinationService vaccinationService; + @EJB + private RegionService regionService; + @EJB + private DistrictService districtService; + @EJB + private CommunityService communityService; + @EJB + private FacilityService facilityService; + @EJB + private CountryService countryService; + @EJB + private AdverseEventsMapper adverseEventsMapper; + + public AefiFacadeEjb() { + } + + @Inject + public AefiFacadeEjb(AefiService service) { + super(Aefi.class, AefiDto.class, service); + } + + @Override + @RightsAllowed({ + UserRight._ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE, + UserRight._ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT }) + public AefiDto save(@Valid @NotNull AefiDto dto) { + return save(dto, true, true); + } + + @RightsAllowed({ + UserRight._ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE, + UserRight._ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT }) + public AefiDto save(@Valid @NotNull AefiDto dto, boolean checkChangeDate, boolean internal) { + Aefi existingAefi = service.getByUuid(dto.getUuid()); + + FacadeHelper.checkCreateAndEditRights( + existingAefi, + userService, + UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE, + UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT); + + if (internal && existingAefi != null && !service.isEditAllowed(existingAefi)) { + throw new AccessDeniedException(I18nProperties.getString(Strings.errorAdverseEventNotEditable)); + } + + AefiDto existingDto = toDto(existingAefi); + + Pseudonymizer pseudonymizer = createPseudonymizer(existingAefi); + restorePseudonymizedDto(dto, existingDto, existingAefi, pseudonymizer); + + validate(dto); + + Aefi aefi = fillOrBuildEntity(dto, existingAefi, checkChangeDate); + + service.ensurePersisted(aefi); + + return toPseudonymizedDto(aefi, pseudonymizer); + } + + @Override + public long count(AefiCriteria criteria) { + return service.count(criteria); + } + + @Override + public List getIndexList(AefiCriteria criteria, Integer first, Integer max, List sortProperties) { + List resultsList = service.getIndexList(criteria, first, max, sortProperties); + Pseudonymizer pseudonymizer = createGenericPlaceholderPseudonymizer(); + pseudonymizer.pseudonymizeDtoCollection(AefiIndexDto.class, resultsList, AefiIndexDto::isInJurisdiction, null); + return resultsList; + } + + @Override + public List getEntriesList(AefiListCriteria criteria, Integer first, Integer max) { + Long immunizationId = immunizationService.getIdByUuid(criteria.getImmunization().getUuid()); + return service.getEntriesList(immunizationId, first, max); + } + + @Override + public void validate(AefiDto aefiDto) throws ValidationRuntimeException { + if (DateHelper.isDateAfter(aefiDto.getStartDateTime(), aefiDto.getReportDate())) { + String validationError = String.format( + I18nProperties.getValidationError(Validations.afterDate), + I18nProperties.getPrefixCaption(ImmunizationDto.I18N_PREFIX, AefiDto.START_DATE_TIME), + I18nProperties.getPrefixCaption(ImmunizationDto.I18N_PREFIX, AefiDto.REPORT_DATE)); + throw new ValidationRuntimeException(validationError); + } + + // Check whether any required field that does not have a not null constraint in the database is empty + if (aefiDto.getImmunization() == null) { + throw new ValidationRuntimeException(I18nProperties.getValidationError(Validations.validImmunization)); + } + + if (aefiDto.getPrimarySuspectVaccine() == null) { + throw new ValidationRuntimeException(I18nProperties.getValidationError(Validations.aefiWithoutPrimarySuspectVaccine)); + } + + AdverseEventsDto adverseEvents = aefiDto.getAdverseEvents(); + if (adverseEvents == null) { + throw new ValidationRuntimeException(I18nProperties.getValidationError(Validations.aefiWithoutAdverseEvents)); + } else { + if (adverseEvents.getSevereLocalReaction() == null + && adverseEvents.getSeizures() == null + && adverseEvents.getAbscess() == null + && adverseEvents.getSepsis() == null + && adverseEvents.getEncephalopathy() == null + && adverseEvents.getToxicShockSyndrome() == null + && adverseEvents.getThrombocytopenia() == null + && adverseEvents.getAnaphylaxis() == null + && adverseEvents.getFeverishFeeling() == null + && StringUtils.isBlank(adverseEvents.getOtherAdverseEventDetails())) { + throw new ValidationRuntimeException(I18nProperties.getValidationError(Validations.aefiWithoutAdverseEvents)); + } + + boolean adverseEventSelected = adverseEvents.getSevereLocalReaction() == AdverseEventState.YES + || adverseEvents.getSeizures() == AdverseEventState.YES + || adverseEvents.getAbscess() == AdverseEventState.YES + || adverseEvents.getSepsis() == AdverseEventState.YES + || adverseEvents.getEncephalopathy() == AdverseEventState.YES + || adverseEvents.getToxicShockSyndrome() == AdverseEventState.YES + || adverseEvents.getThrombocytopenia() == AdverseEventState.YES + || adverseEvents.getAnaphylaxis() == AdverseEventState.YES + || adverseEvents.getFeverishFeeling() == AdverseEventState.YES + || !StringUtils.isBlank(adverseEvents.getOtherAdverseEventDetails()); + + if (!adverseEventSelected) { + throw new ValidationRuntimeException(I18nProperties.getValidationError(Validations.aefiWithoutAdverseEvents)); + } + } + + if (aefiDto.getReportingUser() == null && !aefiDto.isPseudonymized()) { + throw new ValidationRuntimeException(I18nProperties.getValidationError(Validations.validReportingUser)); + } + } + + @Override + public List getArchivedUuidsSince(Date since) { + return null; + } + + @Override + public List delete(List uuids, DeletionDetails deletionDetails) { + return null; + } + + @Override + public List restore(List uuids) { + return null; + } + + @Override + protected Aefi fillOrBuildEntity(AefiDto source, Aefi target, boolean checkChangeDate) { + return fillOrBuildEntity(source, target, checkChangeDate, false); + } + + protected Aefi fillOrBuildEntity(@NotNull AefiDto source, Aefi target, boolean checkChangeDate, boolean includeVaccinations) { + + target = DtoHelper.fillOrBuildEntity(source, target, Aefi::build, checkChangeDate); + + target.setImmunization(immunizationService.getByReferenceDto(source.getImmunization())); + target.setPerson(personService.getByReferenceDto(source.getPerson())); + target.setAddress(locationFacade.fillOrBuildEntity(source.getAddress(), target.getAddress(), checkChangeDate)); + + if (includeVaccinations) { + List vaccinationEntities = new ArrayList<>(); + for (VaccinationDto vaccinationDto : source.getVaccinations()) { + Vaccination vaccination = vaccinationService.getByUuid(vaccinationDto.getUuid()); + vaccination = vaccinationFacade.fillOrBuildEntity(vaccinationDto, vaccination, checkChangeDate); + vaccinationEntities.add(vaccination); + } + target.getVaccinations().clear(); + target.getVaccinations().addAll(vaccinationEntities); + } + + target.setPrimarySuspectVaccine(vaccinationService.getByUuid(source.getPrimarySuspectVaccine().getUuid())); + target.setAdverseEvents(adverseEventsMapper.fillOrBuildEntity(source.getAdverseEvents(), target.getAdverseEvents(), checkChangeDate)); + target.setReportDate(source.getReportDate()); + target.setReportingUser(userService.getByReferenceDto(source.getReportingUser())); + target.setExternalId(source.getExternalId()); + target.setResponsibleRegion(regionService.getByReferenceDto(source.getResponsibleRegion())); + target.setResponsibleDistrict(districtService.getByReferenceDto(source.getResponsibleDistrict())); + target.setResponsibleCommunity(communityService.getByReferenceDto(source.getResponsibleCommunity())); + target.setCountry(countryService.getByReferenceDto(source.getCountry())); + target.setReportingIdNumber(source.getReportingIdNumber()); + target.setPhoneNumber(source.getPhoneNumber()); + target.setPregnant(source.getPregnant()); + target.setTrimester(source.getTrimester()); + target.setLactating(source.getLactating()); + target.setOnsetAgeYears(source.getOnsetAgeYears()); + target.setOnsetAgeMonths(source.getOnsetAgeMonths()); + target.setOnsetAgeDays(source.getOnsetAgeDays()); + target.setAgeGroup(source.getAgeGroup()); + target.setHealthFacility(facilityService.getByReferenceDto(source.getHealthFacility())); + target.setHealthFacilityDetails(source.getHealthFacilityDetails()); + target.setReporterName(source.getReporterName()); + target.setReporterInstitution(facilityService.getByReferenceDto(source.getReporterInstitution())); + target.setReporterDesignation(source.getReporterDesignation()); + target.setReporterDepartment(source.getReporterDepartment()); + target.setReporterAddress(locationFacade.fillOrBuildEntity(source.getReporterAddress(), target.getReporterAddress(), checkChangeDate)); + target.setReporterPhone(source.getReporterPhone()); + target.setReporterEmail(source.getReporterEmail()); + target.setTodaysDate(source.getTodaysDate()); + target.setStartDateTime(source.getStartDateTime()); + target.setAefiDescription(source.getAefiDescription()); + target.setSerious(source.getSerious()); + target.setSeriousReason(source.getSeriousReason()); + target.setSeriousReasonDetails(source.getSeriousReasonDetails()); + target.setOutcome(source.getOutcome()); + target.setDeathDate(source.getDeathDate()); + target.setAutopsyDone(source.getAutopsyDone()); + target.setPastMedicalHistory(source.getPastMedicalHistory()); + target.setInvestigationNeeded(source.getInvestigationNeeded()); + target.setInvestigationPlannedDate(source.getInvestigationPlannedDate()); + target.setReceivedAtNationalLevelDate(source.getReceivedAtNationalLevelDate()); + target.setWorldwideId(source.getWorldwideId()); + target.setNationalLevelComment(source.getNationalLevelComment()); + target.setArchived(source.isArchived()); + target.setDeleted(source.isDeleted()); + target.setDeletionReason(source.getDeletionReason()); + target.setOtherDeletionReason(source.getOtherDeletionReason()); + + return target; + } + + @Override + protected AefiDto toDto(Aefi entity) { + return toAefiDto(entity); + } + + public static AefiDto toAefiDto(Aefi entity) { + + if (entity == null) { + return null; + } + AefiDto dto = new AefiDto(); + DtoHelper.fillDto(dto, entity); + + dto.setImmunization(ImmunizationFacadeEjb.toReferenceDto(entity.getImmunization())); + dto.setPerson(PersonFacadeEjb.toReferenceDto(entity.getPerson())); + dto.setAddress(LocationFacadeEjb.toDto(entity.getAddress())); + + List vaccinationDtos = new ArrayList<>(); + for (Vaccination vaccination : entity.getImmunization().getVaccinations()) { + VaccinationDto vaccinationDto = VaccinationFacadeEjb.toVaccinationDto(vaccination); + vaccinationDtos.add(vaccinationDto); + } + dto.setVaccinations(vaccinationDtos); + + dto.setPrimarySuspectVaccine(VaccinationFacadeEjb.toVaccinationDto(entity.getPrimarySuspectVaccine())); + dto.setAdverseEvents(AdverseEventsMapper.toDto(entity.getAdverseEvents())); + dto.setReportDate(entity.getReportDate()); + dto.setReportingUser(UserFacadeEjb.toReferenceDto(entity.getReportingUser())); + dto.setExternalId(entity.getExternalId()); + dto.setResponsibleRegion(RegionFacadeEjb.toReferenceDto(entity.getResponsibleRegion())); + dto.setResponsibleDistrict(DistrictFacadeEjb.toReferenceDto(entity.getResponsibleDistrict())); + dto.setResponsibleCommunity(CommunityFacadeEjb.toReferenceDto(entity.getResponsibleCommunity())); + dto.setCountry(CountryFacadeEjb.toReferenceDto(entity.getCountry())); + dto.setReportingIdNumber(entity.getReportingIdNumber()); + dto.setPhoneNumber(entity.getPhoneNumber()); + dto.setPregnant(entity.getPregnant()); + dto.setTrimester(entity.getTrimester()); + dto.setLactating(entity.getLactating()); + dto.setOnsetAgeYears(entity.getOnsetAgeYears()); + dto.setOnsetAgeMonths(entity.getOnsetAgeMonths()); + dto.setOnsetAgeDays(entity.getOnsetAgeDays()); + dto.setAgeGroup(entity.getAgeGroup()); + dto.setHealthFacility(FacilityFacadeEjb.toReferenceDto(entity.getHealthFacility())); + dto.setHealthFacilityDetails(entity.getHealthFacilityDetails()); + dto.setReporterName(entity.getReporterName()); + dto.setReporterInstitution(FacilityFacadeEjb.toReferenceDto(entity.getReporterInstitution())); + dto.setReporterDesignation(entity.getReporterDesignation()); + dto.setReporterDepartment(entity.getReporterDepartment()); + dto.setReporterAddress(LocationFacadeEjb.toDto(entity.getReporterAddress())); + dto.setReporterPhone(entity.getReporterPhone()); + dto.setReporterEmail(entity.getReporterEmail()); + dto.setTodaysDate(entity.getTodaysDate()); + dto.setStartDateTime(entity.getStartDateTime()); + dto.setAefiDescription(entity.getAefiDescription()); + dto.setSerious(entity.getSerious()); + dto.setSeriousReason(entity.getSeriousReason()); + dto.setSeriousReasonDetails(entity.getSeriousReasonDetails()); + dto.setOutcome(entity.getOutcome()); + dto.setDeathDate(entity.getDeathDate()); + dto.setAutopsyDone(entity.getAutopsyDone()); + dto.setPastMedicalHistory(entity.getPastMedicalHistory()); + dto.setInvestigationNeeded(entity.getInvestigationNeeded()); + dto.setInvestigationPlannedDate(entity.getInvestigationPlannedDate()); + dto.setReceivedAtNationalLevelDate(entity.getReceivedAtNationalLevelDate()); + dto.setWorldwideId(entity.getWorldwideId()); + dto.setNationalLevelComment(entity.getNationalLevelComment()); + dto.setArchived(entity.isArchived()); + dto.setDeleted(entity.isDeleted()); + dto.setDeletionReason(entity.getDeletionReason()); + dto.setOtherDeletionReason(entity.getOtherDeletionReason()); + + return dto; + } + + @Override + protected AefiReferenceDto toRefDto(Aefi aefi) { + return toReferenceDto(aefi); + } + + public static AefiReferenceDto toReferenceDto(Aefi entity) { + + if (entity == null) { + return null; + } + + return new AefiReferenceDto(entity.getUuid(), "", ""); + } + + @Override + protected void pseudonymizeDto(Aefi source, AefiDto dto, Pseudonymizer pseudonymizer, boolean inJurisdiction) { + + if (dto != null) { + pseudonymizer.pseudonymizeDto(AefiDto.class, dto, inJurisdiction, c -> { + pseudonymizer.pseudonymizeUser(source.getReportingUser(), userService.getCurrentUser(), dto::setReportingUser, dto); + }); + } + } + + @Override + protected void restorePseudonymizedDto(AefiDto dto, AefiDto existingDto, Aefi entity, Pseudonymizer pseudonymizer) { + + if (existingDto != null) { + final boolean inJurisdiction = service.inJurisdictionOrOwned(entity); + final User currentUser = userService.getCurrentUser(); + pseudonymizer.restoreUser(entity.getReportingUser(), currentUser, dto, dto::setReportingUser); + pseudonymizer.restorePseudonymizedValues(AefiDto.class, dto, existingDto, inJurisdiction); + } + } + + @Override + protected DeletableEntityType getDeletableEntityType() { + return null; + } + + @LocalBean + @Stateless + public static class AefiFacadeEjbLocal extends AefiFacadeEjb { + + public AefiFacadeEjbLocal() { + super(); + } + + @Inject + public AefiFacadeEjbLocal(AefiService service) { + super(service); + } + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiJurisdictionPredicateValidator.java new file mode 100644 index 00000000000..215572a9d48 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiJurisdictionPredicateValidator.java @@ -0,0 +1,108 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import java.util.List; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.Path; +import javax.persistence.criteria.Predicate; + +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.Aefi; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AefiJoins; +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.user.User; +import de.symeda.sormas.backend.util.PredicateJurisdictionValidator; + +public class AefiJurisdictionPredicateValidator extends PredicateJurisdictionValidator { + + private final AefiJoins joins; + + public AefiJurisdictionPredicateValidator( + CriteriaBuilder cb, + AefiJoins joins, + User user, + List jurisdictionValidators) { + super(cb, user, null, jurisdictionValidators); + this.joins = joins; + } + + public static AefiJurisdictionPredicateValidator of(AefiQueryContext qc, User user) { + return new AefiJurisdictionPredicateValidator(qc.getCriteriaBuilder(), qc.getJoins(), user, null); + } + + @Override + public Predicate isRootInJurisdiction() { + return isInJurisdictionByJurisdictionLevel(user.getJurisdictionLevel()); + } + + @Override + public Predicate isRootInJurisdictionOrOwned() { + 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()); + } + + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + return null; + } + + @Override + protected Predicate whenNotAllowed() { + return cb.disjunction(); + } + + @Override + protected Predicate whenNationalLevel() { + return cb.conjunction(); + } + + @Override + protected Predicate whenRegionalLevel() { + return cb.equal(joins.getRoot().get(Aefi.IMMUNIZATION).get(Immunization.RESPONSIBLE_REGION).get(Region.ID), user.getRegion().getId()); + } + + @Override + protected Predicate whenDistrictLevel() { + return cb.equal(joins.getRoot().get(Aefi.IMMUNIZATION).get(Immunization.RESPONSIBLE_DISTRICT).get(District.ID), user.getDistrict().getId()); + } + + @Override + protected Predicate whenCommunityLevel() { + return cb + .equal(joins.getRoot().get(Aefi.IMMUNIZATION).get(Immunization.RESPONSIBLE_COMMUNITY).get(Community.ID), user.getCommunity().getId()); + } + + @Override + protected Predicate whenFacilityLevel() { + return cb.equal(joins.getRoot().get(Aefi.IMMUNIZATION).get(Immunization.HEALTH_FACILITY).get(Facility.ID), user.getHealthFacility().getId()); + } + + @Override + protected Predicate whenPointOfEntryLevel() { + return cb.disjunction(); + } + + @Override + protected Predicate whenLaboratoryLevel() { + return cb.disjunction(); + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiQueryContext.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiQueryContext.java new file mode 100644 index 00000000000..fa7ec727d58 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiQueryContext.java @@ -0,0 +1,45 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Expression; +import javax.persistence.criteria.From; + +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.Aefi; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AefiJoins; +import de.symeda.sormas.backend.common.QueryContext; + +public class AefiQueryContext extends QueryContext { + + public AefiQueryContext(CriteriaBuilder cb, CriteriaQuery query, From root) { + super(cb, query, root, new AefiJoins(root)); + } + + public AefiQueryContext(CriteriaBuilder cb, CriteriaQuery query, AefiJoins joins) { + super(cb, query, joins.getRoot(), joins); + } + + public AefiQueryContext(CriteriaBuilder cb, CriteriaQuery query, From root, AefiJoins joins) { + super(cb, query, root, joins); + } + + @Override + protected Expression createExpression(String name) { + return null; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiService.java new file mode 100644 index 00000000000..5d18a99795b --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiService.java @@ -0,0 +1,521 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import static de.symeda.sormas.backend.common.CriteriaBuilderHelper.andEquals; + +import java.util.ArrayList; +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.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; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import javax.persistence.criteria.Selection; + +import org.apache.commons.collections4.CollectionUtils; + +import de.symeda.sormas.api.EntityRelevanceStatus; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiCriteria; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDateType; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiIndexDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiListEntryDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; +import de.symeda.sormas.api.common.DeletableEntityType; +import de.symeda.sormas.api.feature.FeatureType; +import de.symeda.sormas.api.feature.FeatureTypeProperty; +import de.symeda.sormas.api.person.PersonIndexDto; +import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.api.utils.SortProperty; +import de.symeda.sormas.api.utils.YesNoUnknown; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AdverseEvents; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.Aefi; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AefiJoins; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.transformers.AefiIndexDtoResultTransformer; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.transformers.AefiListEntryDtoResultTransformer; +import de.symeda.sormas.backend.common.AbstractCoreAdoService; +import de.symeda.sormas.backend.common.CriteriaBuilderHelper; +import de.symeda.sormas.backend.feature.FeatureConfigurationFacadeEjb; +import de.symeda.sormas.backend.immunization.entity.Immunization; +import de.symeda.sormas.backend.infrastructure.district.District; +import de.symeda.sormas.backend.infrastructure.region.Region; +import de.symeda.sormas.backend.location.Location; +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.user.User; +import de.symeda.sormas.backend.user.UserService; +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.vaccination.Vaccination; + +@Stateless +@LocalBean +public class AefiService extends AbstractCoreAdoService { + + @EJB + private PersonService personService; + @EJB + private UserService userService; + @EJB + private FeatureConfigurationFacadeEjb.FeatureConfigurationFacadeEjbLocal featureConfigurationFacade; + + public AefiService() { + super(Aefi.class, DeletableEntityType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION); + } + + public List getEntriesList(Long immunizationId, Integer first, Integer max) { + final CriteriaBuilder cb = em.getCriteriaBuilder(); + final CriteriaQuery cq = cb.createQuery(Tuple.class); + final Root aefi = cq.from(Aefi.class); + + AefiQueryContext aefiQueryContext = new AefiQueryContext(cb, cq, aefi); + AefiJoins joins = aefiQueryContext.getJoins(); + + Join primarySuspectVaccine = joins.getPrimarySuspectVaccination(); + Join adverseEvents = joins.getAdverseEvents(); + + cq.multiselect( + aefi.get(Aefi.UUID), + aefi.get(Aefi.SERIOUS), + primarySuspectVaccine.get(Vaccination.VACCINE_NAME), + primarySuspectVaccine.get(Vaccination.VACCINE_DOSE), + primarySuspectVaccine.get(Vaccination.VACCINATION_DATE), + adverseEvents.get(AdverseEvents.SEVERE_LOCAL_REACTION), + adverseEvents.get(AdverseEvents.SEVERE_LOCAL_REACTION_MORE_THAN_THREE_DAYS), + adverseEvents.get(AdverseEvents.SEVERE_LOCAL_REACTION_BEYOND_NEAREST_JOINT), + adverseEvents.get(AdverseEvents.SEIZURES), + adverseEvents.get(AdverseEvents.SEIZURE_TYPE), + adverseEvents.get(AdverseEvents.ABSCESS), + adverseEvents.get(AdverseEvents.SEPSIS), + adverseEvents.get(AdverseEvents.ENCEPHALOPATHY), + adverseEvents.get(AdverseEvents.TOXIC_SHOCK_SYNDROME), + adverseEvents.get(AdverseEvents.THROMBOCYTOPENIA), + adverseEvents.get(AdverseEvents.ANAPHYLAXIS), + adverseEvents.get(AdverseEvents.FEVERISH_FEELING), + adverseEvents.get(AdverseEvents.OTHER_ADVERSE_EVENT_DETAILS), + aefi.get(Aefi.CHANGE_DATE), + JurisdictionHelper.booleanSelector(cb, isInJurisdictionOrOwned(aefiQueryContext))); + + final Predicate criteriaFilter = buildCriteriaFilter(immunizationId, aefiQueryContext); + if (criteriaFilter != null) { + cq.where(criteriaFilter); + } + + cq.orderBy(cb.desc(aefi.get(Aefi.CHANGE_DATE))); + + cq.distinct(true); + + return QueryHelper.getResultList(em, cq, new AefiListEntryDtoResultTransformer(), first, max); + } + + private Predicate buildCriteriaFilter(Long immunizationId, AefiQueryContext aefiQueryContext) { + + final CriteriaBuilder cb = aefiQueryContext.getCriteriaBuilder(); + final From from = aefiQueryContext.getRoot(); + + Predicate filter = cb.equal(from.get(Aefi.IMMUNIZATION_ID), immunizationId); + + filter = CriteriaBuilderHelper.and(cb, filter, cb.isFalse(from.get(Aefi.DELETED))); + + return filter; + } + + public long count(AefiCriteria criteria) { + final CriteriaBuilder cb = em.getCriteriaBuilder(); + final CriteriaQuery cq = cb.createQuery(Long.class); + final Root aefi = cq.from(Aefi.class); + + AefiQueryContext aefiQueryContext = new AefiQueryContext(cb, cq, aefi); + + buildWhereCondition(criteria, cb, cq, aefiQueryContext, null); + + cq.select(cb.countDistinct(aefi)); + return em.createQuery(cq).getSingleResult(); + } + + public List getIndexList(AefiCriteria criteria, Integer first, Integer max, List sortProperties) { + + List indexListIds = getIndexListIds(criteria, first, max, sortProperties); + List aefiIndexDtos = new ArrayList<>(); + + IterableHelper.executeBatched(indexListIds, ModelConstants.PARAMETER_LIMIT, batchedIds -> { + + final CriteriaBuilder cb = em.getCriteriaBuilder(); + final CriteriaQuery cq = cb.createQuery(Tuple.class); + final Root aefi = cq.from(Aefi.class); + + AefiQueryContext aefiQueryContext = new AefiQueryContext(cb, cq, aefi); + AefiJoins joins = aefiQueryContext.getJoins(); + + final Join immunization = joins.getImmunization(); + final Join person = joins.getImmunizationJoins().getPerson(); + + final Join responsibleRegion = joins.getImmunizationJoins().getResponsibleRegion(); + final Join responsibleDistrict = joins.getImmunizationJoins().getResponsibleDistrict(); + + final Join primarySuspectVaccine = joins.getPrimarySuspectVaccination(); + final Join adverseEvents = joins.getAdverseEvents(); + + cq.multiselect( + Stream + .concat( + Stream.of( + aefi.get(Aefi.UUID), + immunization.get(Immunization.UUID), + immunization.get(Immunization.DISEASE), + 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), + responsibleRegion.get(Region.NAME), + responsibleDistrict.get(District.NAME), + aefi.get(Aefi.SERIOUS), + primarySuspectVaccine.get(Vaccination.VACCINE_NAME), + aefi.get(Aefi.OUTCOME), + primarySuspectVaccine.get(Vaccination.VACCINATION_DATE), + aefi.get(Aefi.REPORT_DATE), + aefi.get(Aefi.START_DATE_TIME), + adverseEvents.get(AdverseEvents.SEVERE_LOCAL_REACTION), + adverseEvents.get(AdverseEvents.SEVERE_LOCAL_REACTION_MORE_THAN_THREE_DAYS), + adverseEvents.get(AdverseEvents.SEVERE_LOCAL_REACTION_BEYOND_NEAREST_JOINT), + adverseEvents.get(AdverseEvents.SEIZURES), + adverseEvents.get(AdverseEvents.SEIZURE_TYPE), + adverseEvents.get(AdverseEvents.ABSCESS), + adverseEvents.get(AdverseEvents.SEPSIS), + adverseEvents.get(AdverseEvents.ENCEPHALOPATHY), + adverseEvents.get(AdverseEvents.TOXIC_SHOCK_SYNDROME), + adverseEvents.get(AdverseEvents.THROMBOCYTOPENIA), + adverseEvents.get(AdverseEvents.ANAPHYLAXIS), + adverseEvents.get(AdverseEvents.FEVERISH_FEELING), + adverseEvents.get(AdverseEvents.OTHER_ADVERSE_EVENT_DETAILS), + aefi.get(Aefi.DELETION_REASON), + aefi.get(Aefi.OTHER_DELETION_REASON), + JurisdictionHelper.booleanSelector(cb, isInJurisdictionOrOwned(aefiQueryContext)), + aefi.get(Aefi.CHANGE_DATE)), + // add sort properties to select + sortBy(sortProperties, aefiQueryContext).stream()) + .collect(Collectors.toList())); + + buildWhereCondition(criteria, cb, cq, aefiQueryContext, aefi.get(Aefi.ID).in(batchedIds)); + cq.distinct(true); + + aefiIndexDtos.addAll(QueryHelper.getResultList(em, cq, new AefiIndexDtoResultTransformer(), null, null)); + }); + + return aefiIndexDtos; + } + + private List getIndexListIds(AefiCriteria criteria, Integer first, Integer max, List sortProperties) { + + final CriteriaBuilder cb = em.getCriteriaBuilder(); + final CriteriaQuery cq = cb.createTupleQuery(); + final Root aefi = cq.from(Aefi.class); + + AefiQueryContext aefiQueryContext = new AefiQueryContext(cb, cq, aefi); + + List> selections = new ArrayList<>(); + selections.add(aefi.get(Aefi.ID)); + selections.addAll(sortBy(sortProperties, aefiQueryContext)); + + cq.multiselect(selections); + + buildWhereCondition(criteria, cb, cq, aefiQueryContext, null); + cq.distinct(true); + + List aefiResultList = QueryHelper.getResultList(em, cq, first, max); + return aefiResultList.stream().map(t -> t.get(0, Long.class)).collect(Collectors.toList()); + } + + private List> sortBy(List sortProperties, AefiQueryContext aefiQueryContext) { + + List> selections = new ArrayList<>(); + CriteriaBuilder cb = aefiQueryContext.getCriteriaBuilder(); + CriteriaQuery cq = aefiQueryContext.getQuery(); + + if (CollectionUtils.isNotEmpty(sortProperties)) { + List order = new ArrayList<>(sortProperties.size()); + for (SortProperty sortProperty : sortProperties) { + Expression expression; + switch (sortProperty.propertyName) { + case AefiIndexDto.UUID: + case AefiIndexDto.DISEASE: + case AefiIndexDto.START_DATE_TIME: + expression = aefiQueryContext.getRoot().get(sortProperty.propertyName); + break; + case AefiIndexDto.PERSON_UUID: + expression = aefiQueryContext.getJoins().getImmunizationJoins().getPerson().get(Person.UUID); + break; + case AefiIndexDto.PERSON_FIRST_NAME: + expression = cb.lower(aefiQueryContext.getJoins().getImmunizationJoins().getPerson().get(Person.FIRST_NAME)); + break; + case AefiIndexDto.PERSON_LAST_NAME: + expression = cb.lower(aefiQueryContext.getJoins().getImmunizationJoins().getPerson().get(Person.LAST_NAME)); + break; + case AefiIndexDto.AGE_AND_BIRTH_DATE: + expression = aefiQueryContext.getJoins().getImmunizationJoins().getPerson().get(Person.APPROXIMATE_AGE); + break; + case AefiIndexDto.SEX: + expression = aefiQueryContext.getJoins().getImmunizationJoins().getPerson().get(Person.SEX); + break; + case AefiIndexDto.REGION: + expression = + cb.lower(aefiQueryContext.getJoins().getImmunizationJoins().getPersonJoins().getAddressJoins().getRegion().get(Region.NAME)); + break; + case AefiIndexDto.DISTRICT: + expression = cb.lower( + aefiQueryContext.getJoins().getImmunizationJoins().getPersonJoins().getAddressJoins().getDistrict().get(District.NAME)); + break; + case AefiIndexDto.PRIMARY_VACCINE_NAME: + expression = aefiQueryContext.getJoins().getPrimarySuspectVaccination().get(Vaccination.VACCINE_NAME); + break; + case AefiIndexDto.VACCINATION_DATE: + expression = aefiQueryContext.getJoins().getPrimarySuspectVaccination().get(Vaccination.VACCINATION_DATE); + break; + case AefiIndexDto.SERIOUS: + expression = aefiQueryContext.getRoot().get(Aefi.SERIOUS); + break; + case AefiIndexDto.OUTCOME: + expression = aefiQueryContext.getRoot().get(Aefi.OUTCOME); + break; + default: + throw new IllegalArgumentException(sortProperty.propertyName); + } + order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); + selections.add(expression); + } + cq.orderBy(order); + } else { + Path changeDate = aefiQueryContext.getRoot().get(Aefi.CHANGE_DATE); + cq.orderBy(cb.desc(changeDate)); + selections.add(changeDate); + } + + return selections; + } + + private void buildWhereCondition( + AefiCriteria criteria, + CriteriaBuilder cb, + CriteriaQuery cq, + AefiQueryContext aefiQueryContext, + Predicate additionalFilter) { + + Predicate filter = createUserFilter(aefiQueryContext); + if (additionalFilter != null) { + filter = CriteriaBuilderHelper.and(cb, additionalFilter, filter); + } + + if (criteria != null) { + final Predicate criteriaFilter = buildCriteriaFilter(criteria, aefiQueryContext); + filter = CriteriaBuilderHelper.and(cb, filter, criteriaFilter); + } + + if (filter != null) { + cq.where(filter); + } + } + + public Predicate buildCriteriaFilter(AefiCriteria criteria, AefiQueryContext aefiQueryContext) { + + final AefiJoins joins = aefiQueryContext.getJoins(); + final CriteriaBuilder cb = aefiQueryContext.getCriteriaBuilder(); + final From from = aefiQueryContext.getRoot(); + final Join immunization = joins.getImmunization(); + final Join person = joins.getImmunizationJoins().getPerson(); + final Join primarySuspectVaccine = joins.getPrimarySuspectVaccination(); + + final Join location = joins.getImmunizationJoins().getPersonJoins().getAddress(); + + Predicate filter = null; + if (criteria.getDisease() != null) { + filter = CriteriaBuilderHelper.and(cb, null, cb.equal(immunization.get(Immunization.DISEASE), criteria.getDisease())); + } + + if (!DataHelper.isNullOrEmpty(criteria.getNameAddressPhoneEmailLike())) { + final CriteriaQuery cq = cb.createQuery(PersonIndexDto.class); + final PersonQueryContext personQueryContext = new PersonQueryContext(cb, cq, joins.getImmunizationJoins().getPersonJoins()); + + String[] textFilters = criteria.getNameAddressPhoneEmailLike().split("\\s+"); + + for (String textFilter : textFilters) { + if (DataHelper.isNullOrEmpty(textFilter)) { + continue; + } + + Predicate likeFilters = cb.or( + CriteriaBuilderHelper.ilike(cb, from.get(Aefi.UUID), textFilter), + CriteriaBuilderHelper.unaccentedIlike(cb, person.get(Person.FIRST_NAME), textFilter), + CriteriaBuilderHelper.unaccentedIlike(cb, person.get(Person.LAST_NAME), textFilter), + CriteriaBuilderHelper.ilike(cb, person.get(Person.UUID), textFilter), + CriteriaBuilderHelper.ilike(cb, personQueryContext.getSubqueryExpression(PersonQueryContext.PERSON_EMAIL_SUBQUERY), textFilter), + phoneNumberPredicate(cb, personQueryContext.getSubqueryExpression(PersonQueryContext.PERSON_PHONE_SUBQUERY), textFilter), + CriteriaBuilderHelper + .ilike(cb, personQueryContext.getSubqueryExpression(PersonQueryContext.PERSON_PRIMARY_OTHER_SUBQUERY), textFilter), + CriteriaBuilderHelper.unaccentedIlike(cb, location.get(Location.STREET), textFilter), + CriteriaBuilderHelper.unaccentedIlike(cb, location.get(Location.CITY), textFilter), + CriteriaBuilderHelper.ilike(cb, location.get(Location.POSTAL_CODE), textFilter), + CriteriaBuilderHelper.ilike(cb, person.get(Person.INTERNAL_TOKEN), textFilter), + CriteriaBuilderHelper.ilike(cb, person.get(Person.EXTERNAL_ID), textFilter), + CriteriaBuilderHelper.ilike(cb, person.get(Person.EXTERNAL_TOKEN), textFilter)); + filter = CriteriaBuilderHelper.and(cb, filter, likeFilters); + } + } + if (criteria.getAefiType() != null) { + if (criteria.getAefiType() == AefiType.SERIOUS) { + filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(from.get(Aefi.SERIOUS), YesNoUnknown.YES)); + } else { + filter = CriteriaBuilderHelper.and(cb, filter, cb.notEqual(from.get(Aefi.SERIOUS), YesNoUnknown.YES)); + } + } + if (criteria.getOutcome() != null) { + filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(from.get(Aefi.OUTCOME), criteria.getOutcome())); + } + if (criteria.getVaccineName() != null) { + filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(primarySuspectVaccine.get(Vaccination.VACCINE_NAME), criteria.getVaccineName())); + } + if (criteria.getVaccineManufacturer() != null) { + filter = CriteriaBuilderHelper + .and(cb, filter, cb.equal(primarySuspectVaccine.get(Vaccination.VACCINE_MANUFACTURER), criteria.getVaccineManufacturer())); + } + filter = andEquals(cb, () -> joins.getImmunizationJoins().getResponsibleRegion(), filter, criteria.getRegion()); + filter = andEquals(cb, () -> joins.getImmunizationJoins().getResponsibleDistrict(), filter, criteria.getDistrict()); + filter = andEquals(cb, () -> joins.getImmunizationJoins().getResponsibleCommunity(), filter, criteria.getCommunity()); + if (criteria.getFacilityType() != null) { + filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(immunization.get(Immunization.FACILITY_TYPE), criteria.getFacilityType())); + } + filter = andEquals(cb, () -> joins.getImmunizationJoins().getHealthFacility(), filter, criteria.getHealthFacility()); + if (criteria.getAefiDateType() != null) { + Path path = buildPathForDateFilter(criteria.getAefiDateType(), aefiQueryContext); + if (path != null) { + filter = CriteriaBuilderHelper.applyDateFilter(cb, filter, path, criteria.getFromDate(), criteria.getToDate()); + } + } + + if (criteria.getRelevanceStatus() != null) { + if (criteria.getRelevanceStatus() == EntityRelevanceStatus.ACTIVE) { + filter = CriteriaBuilderHelper.and(cb, filter, cb.or(cb.equal(from.get(Aefi.ARCHIVED), false), cb.isNull(from.get(Aefi.ARCHIVED)))); + } else if (criteria.getRelevanceStatus() == EntityRelevanceStatus.ARCHIVED) { + filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(from.get(Aefi.ARCHIVED), true)); + } else if (criteria.getRelevanceStatus() == EntityRelevanceStatus.DELETED) { + filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(from.get(Aefi.DELETED), true)); + } + } + if (criteria.getRelevanceStatus() != EntityRelevanceStatus.DELETED) { + filter = CriteriaBuilderHelper.and(cb, filter, cb.isFalse(from.get(Aefi.DELETED))); + } + + return filter; + } + + private Path buildPathForDateFilter(AefiDateType aefiDateType, AefiQueryContext aefiQueryContext) { + Path path = null; + String dateField = getDateFieldFromDateType(aefiDateType); + if (dateField != null) { + if (Vaccination.VACCINATION_DATE.equals(dateField)) { + final Join primarySuspectVaccination = aefiQueryContext.getJoins().getPrimarySuspectVaccination(); + path = primarySuspectVaccination.get(Vaccination.VACCINATION_DATE); + } else { + path = aefiQueryContext.getRoot().get(dateField); + } + } + return path; + } + + private String getDateFieldFromDateType(AefiDateType aefiDateType) { + switch (aefiDateType) { + case REPORT_DATE: + return Aefi.REPORT_DATE; + case START_DATE: + return Aefi.START_DATE_TIME; + case VACCINATION_DATE: + return Vaccination.VACCINATION_DATE; + } + return null; + } + + public Predicate createUserFilter(AefiQueryContext qc) { + + User currentUser = getCurrentUser(); + if (currentUser == null) { + return null; + } + final CriteriaBuilder cb = qc.getCriteriaBuilder(); + + Predicate filter = isInJurisdictionOrOwned(qc); + + filter = CriteriaBuilderHelper.and( + cb, + filter, + CriteriaBuilderHelper.limitedDiseasePredicate(cb, currentUser, qc.getRoot().get(Aefi.IMMUNIZATION).get(Immunization.DISEASE))); + + return filter; + } + + private Predicate isInJurisdictionOrOwned(AefiQueryContext qc) { + + final User currentUser = userService.getCurrentUser(); + CriteriaBuilder cb = qc.getCriteriaBuilder(); + Predicate filter; + if (!featureConfigurationFacade + .isPropertyValueTrue(FeatureType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_MANAGEMENT, FeatureTypeProperty.REDUCED)) { + filter = AefiJurisdictionPredicateValidator.of(qc, currentUser).inJurisdictionOrOwned(); + } else { + filter = CriteriaBuilderHelper.or( + cb, + cb.equal(qc.getRoot().get(Immunization.REPORTING_USER), currentUser), + PersonJurisdictionPredicateValidator + .of(qc.getQuery(), cb, new PersonJoins(qc.getJoins().getPerson()), currentUser, personService.getPermittedAssociations()) + .inJurisdictionOrOwned()); + } + return filter; + } + + @Override + protected Predicate createUserFilterInternal(CriteriaBuilder cb, CriteriaQuery cq, From from) { + return createUserFilter(new AefiQueryContext(cb, cq, from)); + } + + @Override + protected AefiJoins toJoins(From adoPath) { + return new AefiJoins(adoPath); + } + + @Override + public Predicate inJurisdictionOrOwned(CriteriaBuilder cb, CriteriaQuery query, From from) { + return isInJurisdictionOrOwned(new AefiQueryContext(cb, query, from)); + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AdverseEvents.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AdverseEvents.java new file mode 100644 index 00000000000..2513cb06548 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AdverseEvents.java @@ -0,0 +1,179 @@ +/* + * 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.adverseeventsfollowingimmunization.entity; + +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.Table; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventState; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.SeizureType; +import de.symeda.sormas.backend.common.AbstractDomainObject; + +@Entity +@Table(name = "adverseevents") +public class AdverseEvents extends AbstractDomainObject { + + private static final long serialVersionUID = 5407524640930885029L; + + public static final String TABLE_NAME = "adverseevents"; + + public static final String SEVERE_LOCAL_REACTION = "severeLocalReaction"; + public static final String SEVERE_LOCAL_REACTION_MORE_THAN_THREE_DAYS = "severeLocalReactionMoreThanThreeDays"; + public static final String SEVERE_LOCAL_REACTION_BEYOND_NEAREST_JOINT = "severeLocalReactionBeyondNearestJoint"; + public static final String SEIZURES = "seizures"; + public static final String SEIZURE_TYPE = "seizureType"; + public static final String ABSCESS = "abscess"; + public static final String SEPSIS = "sepsis"; + public static final String ENCEPHALOPATHY = "encephalopathy"; + public static final String TOXIC_SHOCK_SYNDROME = "toxicShockSyndrome"; + public static final String THROMBOCYTOPENIA = "thrombocytopenia"; + public static final String ANAPHYLAXIS = "anaphylaxis"; + public static final String FEVERISH_FEELING = "feverishFeeling"; + public static final String OTHER_ADVERSE_EVENT_DETAILS = "otherAdverseEventDetails"; + + private AdverseEventState severeLocalReaction; + private boolean severeLocalReactionMoreThanThreeDays; + private boolean severeLocalReactionBeyondNearestJoint; + private AdverseEventState seizures; + private SeizureType seizureType; + private AdverseEventState abscess; + private AdverseEventState sepsis; + private AdverseEventState encephalopathy; + private AdverseEventState toxicShockSyndrome; + private AdverseEventState thrombocytopenia; + private AdverseEventState anaphylaxis; + private AdverseEventState feverishFeeling; + private String otherAdverseEventDetails; + + @Enumerated(EnumType.STRING) + public AdverseEventState getSevereLocalReaction() { + return severeLocalReaction; + } + + public void setSevereLocalReaction(AdverseEventState severeLocalReaction) { + this.severeLocalReaction = severeLocalReaction; + } + + public boolean isSevereLocalReactionMoreThanThreeDays() { + return severeLocalReactionMoreThanThreeDays; + } + + public void setSevereLocalReactionMoreThanThreeDays(boolean severeLocalReactionMoreThanThreeDays) { + this.severeLocalReactionMoreThanThreeDays = severeLocalReactionMoreThanThreeDays; + } + + public boolean isSevereLocalReactionBeyondNearestJoint() { + return severeLocalReactionBeyondNearestJoint; + } + + public void setSevereLocalReactionBeyondNearestJoint(boolean severeLocalReactionBeyondNearestJoint) { + this.severeLocalReactionBeyondNearestJoint = severeLocalReactionBeyondNearestJoint; + } + + @Enumerated(EnumType.STRING) + public AdverseEventState getSeizures() { + return seizures; + } + + public void setSeizures(AdverseEventState seizures) { + this.seizures = seizures; + } + + @Enumerated(EnumType.STRING) + public SeizureType getSeizureType() { + return seizureType; + } + + public void setSeizureType(SeizureType seizureType) { + this.seizureType = seizureType; + } + + @Enumerated(EnumType.STRING) + public AdverseEventState getAbscess() { + return abscess; + } + + public void setAbscess(AdverseEventState abscess) { + this.abscess = abscess; + } + + @Enumerated(EnumType.STRING) + public AdverseEventState getSepsis() { + return sepsis; + } + + public void setSepsis(AdverseEventState sepsis) { + this.sepsis = sepsis; + } + + @Enumerated(EnumType.STRING) + public AdverseEventState getEncephalopathy() { + return encephalopathy; + } + + public void setEncephalopathy(AdverseEventState encephalopathy) { + this.encephalopathy = encephalopathy; + } + + @Enumerated(EnumType.STRING) + public AdverseEventState getToxicShockSyndrome() { + return toxicShockSyndrome; + } + + public void setToxicShockSyndrome(AdverseEventState toxicShockSyndrome) { + this.toxicShockSyndrome = toxicShockSyndrome; + } + + @Enumerated(EnumType.STRING) + public AdverseEventState getThrombocytopenia() { + return thrombocytopenia; + } + + public void setThrombocytopenia(AdverseEventState thrombocytopenia) { + this.thrombocytopenia = thrombocytopenia; + } + + @Enumerated(EnumType.STRING) + public AdverseEventState getAnaphylaxis() { + return anaphylaxis; + } + + public void setAnaphylaxis(AdverseEventState anaphylaxis) { + this.anaphylaxis = anaphylaxis; + } + + @Enumerated(EnumType.STRING) + public AdverseEventState getFeverishFeeling() { + return feverishFeeling; + } + + public void setFeverishFeeling(AdverseEventState feverishFeeling) { + this.feverishFeeling = feverishFeeling; + } + + public String getOtherAdverseEventDetails() { + return otherAdverseEventDetails; + } + + public void setOtherAdverseEventDetails(String otherAdverseEventDetails) { + this.otherAdverseEventDetails = otherAdverseEventDetails; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/Aefi.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/Aefi.java new file mode 100644 index 00000000000..1b62575f5e4 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/Aefi.java @@ -0,0 +1,606 @@ +/* + * 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.adverseeventsfollowingimmunization.entity; + +import static de.symeda.sormas.api.utils.FieldConstraints.CHARACTER_LIMIT_DEFAULT; + +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; +import javax.persistence.OneToOne; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiAgeGroup; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiOutcome; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.SeriousAefiReason; +import de.symeda.sormas.api.caze.Trimester; +import de.symeda.sormas.api.utils.YesNoUnknown; +import de.symeda.sormas.backend.common.CoreAdo; +import de.symeda.sormas.backend.immunization.entity.Immunization; +import de.symeda.sormas.backend.infrastructure.community.Community; +import de.symeda.sormas.backend.infrastructure.country.Country; +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.location.Location; +import de.symeda.sormas.backend.person.Person; +import de.symeda.sormas.backend.user.User; +import de.symeda.sormas.backend.vaccination.Vaccination; + +@Entity +@Table(name = "adverseeventsfollowingimmunization") +public class Aefi extends CoreAdo { + + private static final long serialVersionUID = -7845660472641846292L; + + public static final String TABLE_NAME = "adverseeventsfollowingimmunization"; + public static final String AEFI_VACCINATIONS_TABLE_NAME = "adverseeventsfollowingimmunization_vaccinations"; + + public static final String IMMUNIZATION = "immunization"; + public static final String IMMUNIZATION_ID = "immunizationId"; + public static final String ADDRESS = "address"; + public static final String VACCINATIONS = "vaccinations"; + public static final String PRIMARY_SUSPECT_VACCINE = "primarySuspectVaccine"; + public static final String ADVERSE_EVENTS = "adverseEvents"; + public static final String PERSON = "person"; + public static final String PERSON_ID = "personId"; + public static final String REPORT_DATE = "reportDate"; + public static final String REPORTING_USER = "reportingUser"; + public static final String EXTERNAL_ID = "externalId"; + public static final String RESPONSIBLE_REGION = "responsibleRegion"; + public static final String RESPONSIBLE_DISTRICT = "responsibleDistrict"; + public static final String RESPONSIBLE_COMMUNITY = "responsibleCommunity"; + public static final String COUNTRY = "country"; + public static final String REPORTINGID_NUMBER = "reportingIdNumber"; + public static final String PREGNANT = "pregnant"; + public static final String PHONE_NUMBER = "phoneNumber"; + public static final String TRIMESTER = "trimester"; + public static final String LACTATING = "lactating"; + public static final String ONSET_AGE_YEARS = "onsetAgeYears"; + public static final String ONSET_AGE_MONTHS = "onsetAgeMonths"; + public static final String ONSET_AGE_DAYS = "onsetAgeDays"; + public static final String AGE_GROUP = "ageGroup"; + public static final String HEALTH_FACILITY = "healthFacility"; + public static final String HEALTH_FACILITY_DETAILS = "healthFacilityDetails"; + public static final String REPORTER_NAME = "reporterName"; + public static final String REPORTER_INSTITUTION = "reporterInstitution"; + public static final String REPORTER_DESIGNATION = "reporterDesignation"; + public static final String REPORTER_DEPARTMENT = "reporterDepartment"; + public static final String REPORTER_ADDRESS = "reporterAddress"; + public static final String REPORTER_PHONE = "reporterPhone"; + public static final String REPORTER_EMAIL = "reporterEmail"; + public static final String TODAYS_DATE = "todaysDate"; + public static final String START_DATE_TIME = "startDateTime"; + public static final String AEFI_DESCRIPTION = "aefiDescription"; + public static final String SERIOUS = "serious"; + public static final String SERIOUS_REASON = "seriousReason"; + public static final String SERIOUS_REASON_DETAILS = "seriousReasonDetails"; + public static final String OUTCOME = "outcome"; + public static final String DEATH_DATE = "deathDate"; + public static final String AUTOPSY_DONE = "autopsyDone"; + public static final String PAST_MEDICAL_HISTORY = "pastMedicalHistory"; + public static final String INVESTIGATION_NEEDED = "investigationNeeded"; + public static final String INVESTIGATION_PLANNED_DATE = "investigationPlannedDate"; + public static final String RECEIVED_AT_NATIONAL_LEVEL_DATE = "receivedAtNationalLevelDate"; + public static final String WORLD_WIDE_ID = "worldwideId"; + public static final String NATIONAL_LEVEL_COMMENT = "nationalLevelComment"; + + private Immunization immunization; + private Long immunizationId; + private Person person; + private Long personId; + private Location address; + private Set vaccinations = new HashSet<>(); + private Vaccination primarySuspectVaccine; + private AdverseEvents adverseEvents; + private Date reportDate; + private User reportingUser; + private String externalId; + private Region responsibleRegion; + private District responsibleDistrict; + private Community responsibleCommunity; + private Country country; + private String reportingIdNumber; + private String phoneNumber; + private YesNoUnknown pregnant; + private Trimester trimester; + private YesNoUnknown lactating; + private Integer onsetAgeYears; + private Integer onsetAgeMonths; + private Integer onsetAgeDays; + private AefiAgeGroup ageGroup; + private Facility healthFacility; + private String healthFacilityDetails; + private String reporterName; + private Facility reporterInstitution; + private String reporterDesignation; + private String reporterDepartment; + private Location reporterAddress; + private String reporterPhone; + private String reporterEmail; + private Date todaysDate; + private Date startDateTime; + private String aefiDescription; + private YesNoUnknown serious; + private SeriousAefiReason seriousReason; + private String seriousReasonDetails; + private AefiOutcome outcome; + private Date deathDate; + private YesNoUnknown autopsyDone; + private String pastMedicalHistory; + private YesNoUnknown investigationNeeded; + private Date investigationPlannedDate; + private Date receivedAtNationalLevelDate; + private String worldwideId; + private String nationalLevelComment; + + public static Aefi build() { + Aefi aefi = new Aefi(); + return aefi; + } + + @ManyToOne + @JoinColumn(nullable = false) + public Immunization getImmunization() { + return immunization; + } + + public void setImmunization(Immunization immunization) { + this.immunization = immunization; + } + + @Column(name = "immunization_id", updatable = false, insertable = false) + public Long getImmunizationId() { + return immunizationId; + } + + public void setImmunizationId(Long immunizationId) { + this.immunizationId = immunizationId; + } + + @ManyToMany(fetch = FetchType.LAZY) + @JoinTable(name = AEFI_VACCINATIONS_TABLE_NAME, + joinColumns = @JoinColumn(name = "adverseeventsfollowingimmunization_id"), + inverseJoinColumns = @JoinColumn(name = "vaccination_id")) + public Set getVaccinations() { + return vaccinations; + } + + public void setVaccinations(Set vaccinations) { + this.vaccinations = vaccinations; + } + + @OneToOne + public Vaccination getPrimarySuspectVaccine() { + return primarySuspectVaccine; + } + + public void setPrimarySuspectVaccine(Vaccination primarySuspectVaccine) { + this.primarySuspectVaccine = primarySuspectVaccine; + } + + @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JoinColumn(nullable = false) + //@ManyToOne + public AdverseEvents getAdverseEvents() { + return adverseEvents; + } + + public void setAdverseEvents(AdverseEvents adverseEvents) { + this.adverseEvents = adverseEvents; + } + + @ManyToOne + public Person getPerson() { + return person; + } + + public void setPerson(Person person) { + this.person = person; + } + + @Column(name = "person_id", updatable = false, insertable = false) + public Long getPersonId() { + return personId; + } + + public void setPersonId(Long personId) { + this.personId = personId; + } + + @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) + public Location getAddress() { + if (address == null) { + address = new Location(); + } + return address; + } + + public void setAddress(Location address) { + this.address = address; + } + + @Temporal(TemporalType.TIMESTAMP) + @Column(nullable = false) + public Date getReportDate() { + return reportDate; + } + + public void setReportDate(Date reportDate) { + this.reportDate = reportDate; + } + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(nullable = false) + public User getReportingUser() { + return reportingUser; + } + + public void setReportingUser(User reportingUser) { + this.reportingUser = reportingUser; + } + + @Column(length = CHARACTER_LIMIT_DEFAULT) + public String getExternalId() { + return externalId; + } + + @ManyToOne(fetch = FetchType.LAZY) + public Region getResponsibleRegion() { + return responsibleRegion; + } + + public void setResponsibleRegion(Region responsibleRegion) { + this.responsibleRegion = responsibleRegion; + } + + @ManyToOne(fetch = FetchType.LAZY) + public District getResponsibleDistrict() { + return responsibleDistrict; + } + + public void setResponsibleDistrict(District responsibleDistrict) { + this.responsibleDistrict = responsibleDistrict; + } + + @ManyToOne(fetch = FetchType.LAZY) + public Community getResponsibleCommunity() { + return responsibleCommunity; + } + + public void setResponsibleCommunity(Community responsibleCommunity) { + this.responsibleCommunity = responsibleCommunity; + } + + @ManyToOne(fetch = FetchType.LAZY) + public Country getCountry() { + return country; + } + + public void setCountry(Country country) { + this.country = country; + } + + public void setExternalId(String externalId) { + this.externalId = externalId; + } + + @Column(length = CHARACTER_LIMIT_DEFAULT) + public String getReportingIdNumber() { + return reportingIdNumber; + } + + public void setReportingIdNumber(String reportingIdNumber) { + this.reportingIdNumber = reportingIdNumber; + } + + public String getPhoneNumber() { + return phoneNumber; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getPregnant() { + return pregnant; + } + + public void setPregnant(YesNoUnknown pregnant) { + this.pregnant = pregnant; + } + + @Enumerated(EnumType.STRING) + public Trimester getTrimester() { + return trimester; + } + + public void setTrimester(Trimester trimester) { + this.trimester = trimester; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getLactating() { + return lactating; + } + + public void setLactating(YesNoUnknown lactating) { + this.lactating = lactating; + } + + public Integer getOnsetAgeYears() { + return onsetAgeYears; + } + + public void setOnsetAgeYears(Integer onsetAgeYears) { + this.onsetAgeYears = onsetAgeYears; + } + + public Integer getOnsetAgeMonths() { + return onsetAgeMonths; + } + + public void setOnsetAgeMonths(Integer onsetAgeMonths) { + this.onsetAgeMonths = onsetAgeMonths; + } + + public Integer getOnsetAgeDays() { + return onsetAgeDays; + } + + public void setOnsetAgeDays(Integer onsetAgeDays) { + this.onsetAgeDays = onsetAgeDays; + } + + @Enumerated(EnumType.STRING) + public AefiAgeGroup getAgeGroup() { + return ageGroup; + } + + public void setAgeGroup(AefiAgeGroup ageGroup) { + this.ageGroup = ageGroup; + } + + @ManyToOne(fetch = FetchType.LAZY) + public Facility getHealthFacility() { + return healthFacility; + } + + public void setHealthFacility(Facility healthFacility) { + this.healthFacility = healthFacility; + } + + @Column(length = CHARACTER_LIMIT_DEFAULT) + public String getHealthFacilityDetails() { + return healthFacilityDetails; + } + + public void setHealthFacilityDetails(String healthFacilityDetails) { + this.healthFacilityDetails = healthFacilityDetails; + } + + public String getReporterName() { + return reporterName; + } + + public void setReporterName(String reporterName) { + this.reporterName = reporterName; + } + + @ManyToOne(fetch = FetchType.LAZY) + public Facility getReporterInstitution() { + return reporterInstitution; + } + + public void setReporterInstitution(Facility reporterInstitution) { + this.reporterInstitution = reporterInstitution; + } + + public String getReporterDesignation() { + return reporterDesignation; + } + + public void setReporterDesignation(String reporterDesignation) { + this.reporterDesignation = reporterDesignation; + } + + public String getReporterDepartment() { + return reporterDepartment; + } + + public void setReporterDepartment(String reporterDepartment) { + this.reporterDepartment = reporterDepartment; + } + + @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @JoinColumn(name = "reporteraddress_id") + public Location getReporterAddress() { + return reporterAddress; + } + + public void setReporterAddress(Location reporterAddress) { + this.reporterAddress = reporterAddress; + } + + public String getReporterPhone() { + return reporterPhone; + } + + public void setReporterPhone(String reporterPhone) { + this.reporterPhone = reporterPhone; + } + + public String getReporterEmail() { + return reporterEmail; + } + + public void setReporterEmail(String reporterEmail) { + this.reporterEmail = reporterEmail; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getTodaysDate() { + return todaysDate; + } + + public void setTodaysDate(Date todaysDate) { + this.todaysDate = todaysDate; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getStartDateTime() { + return startDateTime; + } + + public void setStartDateTime(Date startDateTime) { + this.startDateTime = startDateTime; + } + + @Column(columnDefinition = "text") + public String getAefiDescription() { + return aefiDescription; + } + + public void setAefiDescription(String aefiDescription) { + this.aefiDescription = aefiDescription; + } + + @Enumerated(EnumType.STRING) + @Column(nullable = false) + public YesNoUnknown getSerious() { + return serious; + } + + public void setSerious(YesNoUnknown serious) { + this.serious = serious; + } + + @Enumerated(EnumType.STRING) + public SeriousAefiReason getSeriousReason() { + return seriousReason; + } + + public void setSeriousReason(SeriousAefiReason seriousReason) { + this.seriousReason = seriousReason; + } + + @Column(columnDefinition = "text") + public String getSeriousReasonDetails() { + return seriousReasonDetails; + } + + public void setSeriousReasonDetails(String seriousReasonDetails) { + this.seriousReasonDetails = seriousReasonDetails; + } + + @Enumerated(EnumType.STRING) + @Column(nullable = false) + public AefiOutcome getOutcome() { + return outcome; + } + + public void setOutcome(AefiOutcome outcome) { + this.outcome = outcome; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getDeathDate() { + return deathDate; + } + + public void setDeathDate(Date deathDate) { + this.deathDate = deathDate; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getAutopsyDone() { + return autopsyDone; + } + + public void setAutopsyDone(YesNoUnknown autopsyDone) { + this.autopsyDone = autopsyDone; + } + + @Column(columnDefinition = "text") + public String getPastMedicalHistory() { + return pastMedicalHistory; + } + + public void setPastMedicalHistory(String pastMedicalHistory) { + this.pastMedicalHistory = pastMedicalHistory; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getInvestigationNeeded() { + return investigationNeeded; + } + + public void setInvestigationNeeded(YesNoUnknown investigationNeeded) { + this.investigationNeeded = investigationNeeded; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getInvestigationPlannedDate() { + return investigationPlannedDate; + } + + public void setInvestigationPlannedDate(Date investigationPlannedDate) { + this.investigationPlannedDate = investigationPlannedDate; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getReceivedAtNationalLevelDate() { + return receivedAtNationalLevelDate; + } + + public void setReceivedAtNationalLevelDate(Date receivedAtNationalLevelDate) { + this.receivedAtNationalLevelDate = receivedAtNationalLevelDate; + } + + public String getWorldwideId() { + return worldwideId; + } + + public void setWorldwideId(String worldwideId) { + this.worldwideId = worldwideId; + } + + @Column(columnDefinition = "text") + public String getNationalLevelComment() { + return nationalLevelComment; + } + + public void setNationalLevelComment(String nationalLevelComment) { + this.nationalLevelComment = nationalLevelComment; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiJoins.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiJoins.java new file mode 100644 index 00000000000..33f71570b4f --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiJoins.java @@ -0,0 +1,162 @@ +/* + * 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.adverseeventsfollowingimmunization.entity; + +import javax.persistence.criteria.From; +import javax.persistence.criteria.Join; +import javax.persistence.criteria.JoinType; + +import de.symeda.sormas.backend.common.QueryJoins; +import de.symeda.sormas.backend.immunization.ImmunizationJoins; +import de.symeda.sormas.backend.immunization.entity.Immunization; +import de.symeda.sormas.backend.infrastructure.community.Community; +import de.symeda.sormas.backend.infrastructure.country.Country; +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.location.Location; +import de.symeda.sormas.backend.person.Person; +import de.symeda.sormas.backend.user.User; +import de.symeda.sormas.backend.vaccination.Vaccination; + +public class AefiJoins extends QueryJoins { + + private Join immunization; + private Join address; + private Join primarySuspectVaccination; + private Join adverseEvents; + private Join person; + private Join reportingUser; + private Join responsibleRegion; + private Join responsibleDistrict; + private Join responsibleCommunity; + private Join country; + private Join healthFacility; + private Join reporterInstitution; + + private ImmunizationJoins immunizationJoins; + + public AefiJoins(From root) { + super(root); + } + + public Join getImmunization() { + return getOrCreate(immunization, Aefi.IMMUNIZATION, JoinType.LEFT, this::setImmunization); + } + + public void setImmunization(Join immunization) { + this.immunization = immunization; + } + + public ImmunizationJoins getImmunizationJoins() { + return getOrCreate(immunizationJoins, () -> new ImmunizationJoins(getImmunization()), this::setImmunizationJoins); + } + + public void setImmunizationJoins(ImmunizationJoins immunizationJoins) { + this.immunizationJoins = immunizationJoins; + } + + public Join getAddress() { + return getOrCreate(address, Aefi.ADDRESS, JoinType.LEFT, this::setAddress); + } + + public void setAddress(Join address) { + this.address = address; + } + + public Join getPrimarySuspectVaccination() { + return getOrCreate(primarySuspectVaccination, Aefi.PRIMARY_SUSPECT_VACCINE, JoinType.LEFT, this::setPrimarySuspectVaccination); + } + + public void setPrimarySuspectVaccination(Join primarySuspectVaccination) { + this.primarySuspectVaccination = primarySuspectVaccination; + } + + public Join getAdverseEvents() { + return getOrCreate(adverseEvents, Aefi.ADVERSE_EVENTS, JoinType.LEFT, this::setAdverseEvents); + } + + public void setAdverseEvents(Join adverseEvents) { + this.adverseEvents = adverseEvents; + } + + public Join getPerson() { + return getOrCreate(person, Aefi.PERSON, JoinType.LEFT, this::setPerson); + } + + public void setPerson(Join person) { + this.person = person; + } + + public Join getReportingUser() { + return getOrCreate(reportingUser, Aefi.REPORTING_USER, JoinType.LEFT, this::setReportingUser); + } + + public void setReportingUser(Join reportingUser) { + this.reportingUser = reportingUser; + } + + public Join getResponsibleRegion() { + return getOrCreate(responsibleRegion, Aefi.RESPONSIBLE_REGION, JoinType.LEFT, this::setResponsibleRegion); + } + + public void setResponsibleRegion(Join responsibleRegion) { + this.responsibleRegion = responsibleRegion; + } + + public Join getResponsibleDistrict() { + return getOrCreate(responsibleDistrict, Aefi.RESPONSIBLE_DISTRICT, JoinType.LEFT, this::setResponsibleDistrict); + } + + public void setResponsibleDistrict(Join responsibleDistrict) { + this.responsibleDistrict = responsibleDistrict; + } + + public Join getResponsibleCommunity() { + return getOrCreate(responsibleCommunity, Aefi.RESPONSIBLE_COMMUNITY, JoinType.LEFT, this::setResponsibleCommunity); + } + + public void setResponsibleCommunity(Join responsibleCommunity) { + this.responsibleCommunity = responsibleCommunity; + } + + public Join getCountry() { + return getOrCreate(country, Aefi.COUNTRY, JoinType.LEFT, this::setCountry); + } + + public void setCountry(Join country) { + this.country = country; + } + + public Join getHealthFacility() { + return getOrCreate(healthFacility, Aefi.HEALTH_FACILITY, JoinType.LEFT, this::setHealthFacility); + } + + public void setHealthFacility(Join healthFacility) { + this.healthFacility = healthFacility; + } + + public Join getReporterInstitution() { + return getOrCreate(reporterInstitution, Aefi.REPORTER_INSTITUTION, JoinType.LEFT, this::setReporterInstitution); + } + + public void setReporterInstitution(Join reporterInstitution) { + this.reporterInstitution = reporterInstitution; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiIndexDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiIndexDtoResultTransformer.java new file mode 100644 index 00000000000..73594a78f5f --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiIndexDtoResultTransformer.java @@ -0,0 +1,86 @@ +/* + * 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.adverseeventsfollowingimmunization.transformers; + +import java.util.Date; +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventState; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiHelper; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiIndexDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiOutcome; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.SeizureType; +import de.symeda.sormas.api.caze.AgeAndBirthDateDto; +import de.symeda.sormas.api.caze.Vaccine; +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.utils.YesNoUnknown; + +public class AefiIndexDtoResultTransformer implements ResultTransformer { + + @Override + public Object transformTuple(Object[] objects, String[] strings) { + + Integer age = objects[6] != null ? (int) objects[6] : null; + ApproximateAgeType approximateAgeType = (ApproximateAgeType) objects[7]; + Integer birthdateDD = objects[8] != null ? (int) objects[8] : null; + Integer birthdateMM = objects[9] != null ? (int) objects[9] : null; + Integer birthdateYYYY = objects[10] != null ? (int) objects[10] : null; + + //@formatter:off + String adverseEvents = AefiHelper + .buildAdverseEventsString((AdverseEventState) objects[20], (boolean) objects[21], (boolean) objects[22], + (AdverseEventState) objects[23], (SeizureType) objects[24], (AdverseEventState) objects[25], + (AdverseEventState) objects[26], (AdverseEventState) objects[27], (AdverseEventState) objects[28], + (AdverseEventState) objects[29], (AdverseEventState) objects[30], (AdverseEventState) objects[31], + (String) objects[32]); + //@formatter:on + + return new AefiIndexDto( + (String) objects[0], + (String) objects[1], + (String) objects[3], + (String) objects[4], + (String) objects[5], + (Disease) objects[2], + new AgeAndBirthDateDto(age, approximateAgeType, birthdateDD, birthdateMM, birthdateYYYY), + (Sex) objects[11], + (String) objects[12], + (String) objects[13], + (YesNoUnknown) objects[14], + (Vaccine) objects[15], + (AefiOutcome) objects[16], + (Date) objects[17], + (Date) objects[18], + (Date) objects[19], + adverseEvents, + (DeletionReason) objects[33], + (String) objects[34], + (boolean) objects[35]); + } + + @Override + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiListEntryDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiListEntryDtoResultTransformer.java new file mode 100644 index 00000000000..02e9082cace --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiListEntryDtoResultTransformer.java @@ -0,0 +1,60 @@ +/* + * 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.adverseeventsfollowingimmunization.transformers; + +import java.util.Date; +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventState; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiHelper; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiListEntryDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.SeizureType; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.utils.YesNoUnknown; + +public class AefiListEntryDtoResultTransformer implements ResultTransformer { + + @Override + public Object transformTuple(Object[] objects, String[] strings) { + + //@formatter:off + String adverseEvents = AefiHelper + .buildAdverseEventsString((AdverseEventState) objects[5], (boolean) objects[6], (boolean) objects[7], + (AdverseEventState) objects[8], (SeizureType) objects[9], (AdverseEventState) objects[10], + (AdverseEventState) objects[11], (AdverseEventState) objects[12], (AdverseEventState) objects[13], + (AdverseEventState) objects[14], (AdverseEventState) objects[15], (AdverseEventState) objects[16], + (String) objects[17]); + //@formatter:on + + return new AefiListEntryDto( + (String) objects[0], + (YesNoUnknown) objects[1], + (Vaccine) objects[2], + (String) objects[3], + (Date) objects[4], + adverseEvents); + } + + @Override + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/dashboard/adverseeventsfollowingimmunization/AefiDashboardFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/dashboard/adverseeventsfollowingimmunization/AefiDashboardFacadeEjb.java new file mode 100644 index 00000000000..91471089e92 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/dashboard/adverseeventsfollowingimmunization/AefiDashboardFacadeEjb.java @@ -0,0 +1,76 @@ +/* + * 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.dashboard.adverseeventsfollowingimmunization; + +import java.util.List; +import java.util.Map; + +import javax.ejb.EJB; +import javax.ejb.LocalBean; +import javax.ejb.Stateless; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.dashboard.AefiDashboardCriteria; +import de.symeda.sormas.api.dashboard.adverseeventsfollowingimmunization.AefiChartData; +import de.symeda.sormas.api.dashboard.adverseeventsfollowingimmunization.AefiDashboardFacade; +import de.symeda.sormas.api.dashboard.adverseeventsfollowingimmunization.MapAefiDto; +import de.symeda.sormas.api.user.UserRight; +import de.symeda.sormas.backend.util.RightsAllowed; + +@Stateless(name = "AefiDashboardFacade") +@RightsAllowed(UserRight._DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW) +public class AefiDashboardFacadeEjb implements AefiDashboardFacade { + + @EJB + private AefiDashboardService aefiDashboardService; + + @Override + public Map getAefiCountsByType(AefiDashboardCriteria dashboardCriteria) { + return aefiDashboardService.getAefiCountsByType(dashboardCriteria); + } + + @Override + public Map> getAefiCountsByVaccine(AefiDashboardCriteria dashboardCriteria) { + return aefiDashboardService.getAefiCountsByVaccine(dashboardCriteria); + } + + @Override + public AefiChartData getAefiByVaccineDoseChartData(AefiDashboardCriteria dashboardCriteria) { + return aefiDashboardService.getAefiByVaccineDoseChartData(dashboardCriteria); + } + + @Override + public AefiChartData getAefiEventsByGenderChartData(AefiDashboardCriteria dashboardCriteria) { + return aefiDashboardService.getAefiEventsByGenderChartData(dashboardCriteria); + } + + @Override + public Long countAefiForMap(AefiDashboardCriteria criteria) { + return aefiDashboardService.countAefiForMap(criteria); + } + + @Override + public List getAefiForMap(AefiDashboardCriteria criteria) { + return aefiDashboardService.getAefiForMap(criteria); + } + + @LocalBean + @Stateless + public static class AefiDashboardFacadeEjbLocal extends AefiDashboardFacadeEjb { + + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/dashboard/adverseeventsfollowingimmunization/AefiDashboardService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/dashboard/adverseeventsfollowingimmunization/AefiDashboardService.java new file mode 100644 index 00000000000..41a50bed7a5 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/dashboard/adverseeventsfollowingimmunization/AefiDashboardService.java @@ -0,0 +1,515 @@ +/* + * 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.dashboard.adverseeventsfollowingimmunization; + +import java.math.BigInteger; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.stream.Collectors; + +import javax.ejb.EJB; +import javax.ejb.LocalBean; +import javax.ejb.Stateless; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import javax.persistence.Tuple; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.From; +import javax.persistence.criteria.Join; +import javax.persistence.criteria.Path; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiCriteria; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDashboardFilterDateType; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.dashboard.AefiDashboardCriteria; +import de.symeda.sormas.api.dashboard.adverseeventsfollowingimmunization.AefiChartData; +import de.symeda.sormas.api.dashboard.adverseeventsfollowingimmunization.AefiChartSeries; +import de.symeda.sormas.api.dashboard.adverseeventsfollowingimmunization.MapAefiDto; +import de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto; +import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto; +import de.symeda.sormas.api.person.Sex; +import de.symeda.sormas.api.utils.DateHelper; +import de.symeda.sormas.api.utils.YesNoUnknown; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.AefiQueryContext; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.AefiService; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AdverseEvents; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.Aefi; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AefiJoins; +import de.symeda.sormas.backend.common.AbstractDomainObject; +import de.symeda.sormas.backend.common.CriteriaBuilderHelper; +import de.symeda.sormas.backend.immunization.entity.Immunization; +import de.symeda.sormas.backend.infrastructure.district.District; +import de.symeda.sormas.backend.infrastructure.district.DistrictService; +import de.symeda.sormas.backend.infrastructure.facility.Facility; +import de.symeda.sormas.backend.infrastructure.region.Region; +import de.symeda.sormas.backend.infrastructure.region.RegionService; +import de.symeda.sormas.backend.location.Location; +import de.symeda.sormas.backend.person.Person; +import de.symeda.sormas.backend.util.ModelConstants; +import de.symeda.sormas.backend.util.QueryHelper; + +@Stateless +@LocalBean +public class AefiDashboardService { + + private final Logger logger = LoggerFactory.getLogger(AefiDashboardService.class); + + @PersistenceContext(unitName = ModelConstants.PERSISTENCE_UNIT_NAME) + private EntityManager em; + + public static final String SERIOUS_SERIES_COLOR = "#E04A5B"; + public static final String NON_SERIOUS_SERIES_COLOR = "#7565B8"; + public static final String MALE_SERIES_COLOR = "#544FC5"; + public static final String FEMALE_SERIES_COLOR = "#2CAFFE"; + + @EJB + private AefiService aefiService; + @EJB + private RegionService regionService; + @EJB + private DistrictService districtService; + + public Map getAefiCountsByType(AefiDashboardCriteria dashboardCriteria) { + + Map result = new HashMap<>(); + + Map dataMap = getAefiCountsByEnumProperty(Aefi.SERIOUS, YesNoUnknown.class, dashboardCriteria, null); + + result.put(AefiType.SERIOUS, dataMap.getOrDefault(YesNoUnknown.YES, 0L)); + result.put(AefiType.NON_SERIOUS, dataMap.getOrDefault(YesNoUnknown.NO, 0L) + dataMap.getOrDefault(YesNoUnknown.UNKNOWN, 0L)); + + return result; + } + + public Map> getAefiCountsByVaccine(AefiDashboardCriteria dashboardCriteria) { + + Map> countsByVaccine = new HashMap<>(); + + Disease disease = dashboardCriteria.getDisease(); + RegionReferenceDto regionReference = dashboardCriteria.getRegion(); + DistrictReferenceDto districtReference = dashboardCriteria.getDistrict(); + + String whereConditions = createAefiNativeQueryFilter(dashboardCriteria); + if (StringUtils.isBlank(whereConditions)) { + whereConditions = " primaryvaccine.vaccinename is not null"; + } else { + whereConditions = whereConditions + " AND primaryvaccine.vaccinename is not null"; + } + + //@formatter:off + String queryString = "select primaryvaccine.vaccinename as vaccine_name " + + " , count(CASE WHEN aefi.serious = 'YES' THEN 1 END) as serious" + + " , count(CASE WHEN aefi.serious <> 'YES' THEN 1 END) as non_serious" + + " from adverseeventsfollowingimmunization aefi" + + " join immunization on aefi.immunization_id = immunization.id" + + " join vaccination primaryvaccine on aefi.primarysuspectvaccine_id = primaryvaccine.id" + + " where " + whereConditions + + " group by primaryvaccine.vaccinename" + + " order by primaryvaccine.vaccinename"; + //@formatter:on + + Query dataQuery = em.createNativeQuery(queryString); + + if (disease != null) { + dataQuery.setParameter("disease", disease.name()); + } + + if (regionReference != null) { + Region region = regionService.getByReferenceDto(regionReference); + dataQuery.setParameter("responsibleregion_id", region.getId()); + } + + if (districtReference != null) { + District district = districtService.getByReferenceDto(districtReference); + dataQuery.setParameter("responsibledistrict_id", district.getId()); + } + + if (dashboardCriteria.getDateFrom() != null && dashboardCriteria.getDateTo() != null) { + Date dateFrom = DateHelper.getStartOfDay(dashboardCriteria.getDateFrom()); + Date dateTo = DateHelper.getEndOfDay(dashboardCriteria.getDateTo()); + + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + String dateFromStr = DateHelper.formatLocalDate(dateFrom, simpleDateFormat); + String dateToStr = DateHelper.formatLocalDate(dateTo, simpleDateFormat); + + dataQuery.setParameter("dateFrom", dateFromStr); + dataQuery.setParameter("dateTo", dateToStr); + } + + @SuppressWarnings("unchecked") + List resultList = dataQuery.getResultList(); + + Map aefiTypeDataMap; + for (Object[] result : resultList) { + aefiTypeDataMap = new HashMap<>(); + aefiTypeDataMap.put(AefiType.SERIOUS, ((BigInteger) result[1]).longValue()); + aefiTypeDataMap.put(AefiType.NON_SERIOUS, ((BigInteger) result[2]).longValue()); + + countsByVaccine.put(Vaccine.valueOf((String) result[0]), aefiTypeDataMap); + } + + return countsByVaccine; + } + + public AefiChartData getAefiByVaccineDoseChartData(AefiDashboardCriteria dashboardCriteria) { + + AefiChartData chartData = new AefiChartData(); + + AefiChartSeries seriousSeries = new AefiChartSeries(AefiType.SERIOUS); + seriousSeries.setColor(SERIOUS_SERIES_COLOR); + AefiChartSeries nonSeriousSeries = new AefiChartSeries(AefiType.NON_SERIOUS); + nonSeriousSeries.setColor(NON_SERIOUS_SERIES_COLOR); + + chartData.addSeries(seriousSeries); + chartData.addSeries(nonSeriousSeries); + + Disease disease = dashboardCriteria.getDisease(); + RegionReferenceDto regionReference = dashboardCriteria.getRegion(); + DistrictReferenceDto districtReference = dashboardCriteria.getDistrict(); + + String whereConditions = createAefiNativeQueryFilter(dashboardCriteria); + if (StringUtils.isBlank(whereConditions)) { + whereConditions = " primaryvaccine.vaccinedose is not null"; + } else { + whereConditions = whereConditions + " AND primaryvaccine.vaccinedose is not null"; + } + + //@formatter:off + String queryString = "select primaryvaccine.vaccinedose as vaccine_dose " + + " , count(CASE WHEN aefi.serious = 'YES' THEN 1 END) as serious" + + " , count(CASE WHEN aefi.serious <> 'YES' THEN 1 END) as non_serious" + + " from adverseeventsfollowingimmunization aefi" + + " join immunization on aefi.immunization_id = immunization.id" + + " join vaccination primaryvaccine on aefi.primarysuspectvaccine_id = primaryvaccine.id" + + " where " + whereConditions + + " group by primaryvaccine.vaccinedose" + + " order by primaryvaccine.vaccinedose"; + //@formatter:on + + Query dataQuery = em.createNativeQuery(queryString); + + if (disease != null) { + dataQuery.setParameter("disease", disease.name()); + } + + if (regionReference != null) { + Region region = regionService.getByReferenceDto(regionReference); + dataQuery.setParameter("responsibleregion_id", region.getId()); + } + + if (districtReference != null) { + District district = districtService.getByReferenceDto(districtReference); + dataQuery.setParameter("responsibledistrict_id", district.getId()); + } + + if (dashboardCriteria.getDateFrom() != null && dashboardCriteria.getDateTo() != null) { + Date dateFrom = DateHelper.getStartOfDay(dashboardCriteria.getDateFrom()); + Date dateTo = DateHelper.getEndOfDay(dashboardCriteria.getDateTo()); + + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + String dateFromStr = DateHelper.formatLocalDate(dateFrom, simpleDateFormat); + String dateToStr = DateHelper.formatLocalDate(dateTo, simpleDateFormat); + + dataQuery.setParameter("dateFrom", dateFromStr); + dataQuery.setParameter("dateTo", dateToStr); + } + + @SuppressWarnings("unchecked") + List resultList = dataQuery.getResultList(); + + for (Object[] result : resultList) { + chartData.addXAxisCategory(result[0]); + seriousSeries.addData(result[1].toString()); + nonSeriousSeries.addData(result[2].toString()); + } + + return chartData; + } + + public AefiChartData getAefiEventsByGenderChartData(AefiDashboardCriteria dashboardCriteria) { + + AefiChartData chartData = new AefiChartData(); + + AefiChartSeries maleSeries = new AefiChartSeries(Sex.MALE); + maleSeries.setColor(MALE_SERIES_COLOR); + AefiChartSeries femaleSeries = new AefiChartSeries(Sex.FEMALE); + femaleSeries.setColor(FEMALE_SERIES_COLOR); + + chartData.addSeries(maleSeries); + chartData.addSeries(femaleSeries); + + Disease disease = dashboardCriteria.getDisease(); + RegionReferenceDto regionReference = dashboardCriteria.getRegion(); + DistrictReferenceDto districtReference = dashboardCriteria.getDistrict(); + + List adverseEventsList = new ArrayList<>(); + adverseEventsList.add(AdverseEvents.SEVERE_LOCAL_REACTION); + adverseEventsList.add(AdverseEvents.SEIZURES); + adverseEventsList.add(AdverseEvents.ABSCESS); + adverseEventsList.add(AdverseEvents.SEPSIS); + adverseEventsList.add(AdverseEvents.ENCEPHALOPATHY); + adverseEventsList.add(AdverseEvents.TOXIC_SHOCK_SYNDROME); + adverseEventsList.add(AdverseEvents.THROMBOCYTOPENIA); + adverseEventsList.add(AdverseEvents.ANAPHYLAXIS); + adverseEventsList.add(AdverseEvents.FEVERISH_FEELING); + + String queryString; + String queryFilter = createAefiNativeQueryFilter(dashboardCriteria); + String whereConditions; + String adverseEventCondition; + String lowerCaseAdverseEvent; + + for (String adverseEvent : adverseEventsList) { + + whereConditions = queryFilter; + lowerCaseAdverseEvent = adverseEvent.toLowerCase(); + adverseEventCondition = " adverseevents." + lowerCaseAdverseEvent + " = 'YES'"; + if (StringUtils.isBlank(whereConditions)) { + whereConditions = adverseEventCondition; + } else { + whereConditions = whereConditions + " AND " + adverseEventCondition; + } + + //@formatter:off + queryString = "select adverseevents." + lowerCaseAdverseEvent + " as " + lowerCaseAdverseEvent + + " , count(CASE WHEN person.sex = 'MALE' THEN 1 END) as total_male" + + " , count(CASE WHEN person.sex = 'FEMALE' THEN 1 END) as total_female" + + " from adverseeventsfollowingimmunization aefi" + + " join immunization on aefi.immunization_id = immunization.id" + + " join person on immunization.person_id = person.id" + + " join adverseevents on aefi.adverseevents_id = adverseevents.id" + + " where " + whereConditions + + " group by adverseevents." + lowerCaseAdverseEvent; + //@formatter:on + + Query dataQuery = em.createNativeQuery(queryString); + + if (disease != null) { + dataQuery.setParameter("disease", disease.name()); + } + + if (regionReference != null) { + Region region = regionService.getByReferenceDto(regionReference); + dataQuery.setParameter("responsibleregion_id", region.getId()); + } + + if (districtReference != null) { + District district = districtService.getByReferenceDto(districtReference); + dataQuery.setParameter("responsibledistrict_id", district.getId()); + } + + if (dashboardCriteria.getDateFrom() != null && dashboardCriteria.getDateTo() != null) { + Date dateFrom = DateHelper.getStartOfDay(dashboardCriteria.getDateFrom()); + Date dateTo = DateHelper.getEndOfDay(dashboardCriteria.getDateTo()); + + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + String dateFromStr = DateHelper.formatLocalDate(dateFrom, simpleDateFormat); + String dateToStr = DateHelper.formatLocalDate(dateTo, simpleDateFormat); + + dataQuery.setParameter("dateFrom", dateFromStr); + dataQuery.setParameter("dateTo", dateToStr); + } + + chartData.addXAxisCategory(adverseEvent); + + @SuppressWarnings("unchecked") + List resultList = dataQuery.getResultList(); + + if (!resultList.isEmpty()) { + Object[] firstResult = resultList.get(0); + maleSeries.addData(firstResult[1].toString()); + femaleSeries.addData(firstResult[2].toString()); + } else { + maleSeries.addData("0"); + femaleSeries.addData("0"); + } + } + + return chartData; + } + + private > Map getAefiCountsByEnumProperty( + String property, + Class propertyType, + AefiDashboardCriteria dashboardCriteria, + BiFunction, Predicate> additionalFilters) { + final CriteriaBuilder cb = em.getCriteriaBuilder(); + final CriteriaQuery cq = cb.createTupleQuery(); + final Root aefiRoot = cq.from(Aefi.class); + final Path groupingProperty = aefiRoot.get(property); + + cq.multiselect(groupingProperty, cb.count(aefiRoot)); + + final Predicate criteriaFilter = createAefiFilter(new AefiQueryContext(cb, cq, aefiRoot), dashboardCriteria); + cq.where(CriteriaBuilderHelper.and(cb, criteriaFilter, additionalFilters != null ? additionalFilters.apply(cb, aefiRoot) : null)); + + cq.groupBy(groupingProperty); + + return QueryHelper.getResultList(em, cq, null, null, Function.identity()) + .stream() + .collect(Collectors.toMap(t -> propertyType.cast(t.get(0)), t -> (Long) t.get(1))); + } + + public Long countAefiForMap(AefiDashboardCriteria criteria) { + + final CriteriaBuilder cb = em.getCriteriaBuilder(); + final CriteriaQuery cq = cb.createQuery(Long.class); + final Root aefiRoot = cq.from(Aefi.class); + + AefiQueryContext aefiQueryContext = new AefiQueryContext(cb, cq, aefiRoot); + AefiJoins joins = aefiQueryContext.getJoins(); + + cq.select(cb.count(aefiRoot)); + + final Predicate criteriaFilter = createAefiFilter(aefiQueryContext, criteria); + + cq.where(CriteriaBuilderHelper.and(cb, criteriaFilter)); + + return QueryHelper.getSingleResult(em, cq); + } + + public List getAefiForMap(AefiDashboardCriteria criteria) { + + final CriteriaBuilder cb = em.getCriteriaBuilder(); + final CriteriaQuery cq = cb.createQuery(MapAefiDto.class); + final Root aefiRoot = cq.from(Aefi.class); + + AefiQueryContext aefiQueryContext = new AefiQueryContext(cb, cq, aefiRoot); + AefiJoins joins = aefiQueryContext.getJoins(); + + Join aefiFacility = joins.getHealthFacility(); + Join immunizationFacility = joins.getImmunizationJoins().getHealthFacility(); + Join immunizationPersonAddress = joins.getImmunizationJoins().getPersonJoins().getAddress(); + + cq.multiselect( + aefiFacility.get(Facility.LATITUDE), + aefiFacility.get(Facility.LONGITUDE), + immunizationFacility.get(Facility.LATITUDE), + immunizationFacility.get(Facility.LONGITUDE), + immunizationPersonAddress.get(Facility.LATITUDE), + immunizationPersonAddress.get(Facility.LONGITUDE), + aefiRoot.get(Aefi.SERIOUS)); + + final Predicate criteriaFilter = createAefiFilter(aefiQueryContext, criteria); + + cq.where(CriteriaBuilderHelper.and(cb, criteriaFilter)); + + return QueryHelper.getResultList(em, cq, null, null); + } + + private Predicate createAefiFilter(AefiQueryContext queryContext, AefiDashboardCriteria criteria) { + CriteriaBuilder cb = queryContext.getCriteriaBuilder(); + CriteriaQuery cq = queryContext.getQuery(); + From aefiRoot = queryContext.getRoot(); + AefiJoins joins = queryContext.getJoins(); + + Predicate filter = aefiService.createUserFilter(queryContext); + + filter = CriteriaBuilderHelper.and( + cb, + filter, + aefiService.buildCriteriaFilter( + new AefiCriteria().disease(criteria.getDisease()) + .region(criteria.getRegion()) + .district(criteria.getDistrict()) + .aefiType(criteria.getAefiType()), + queryContext)); + + if (criteria.getDateFrom() != null && criteria.getDateTo() != null) { + final Predicate dateFilter; + Date dateFrom = DateHelper.getStartOfDay(criteria.getDateFrom()); + Date dateTo = DateHelper.getEndOfDay(criteria.getDateTo()); + + AefiDashboardFilterDateType aefiDashboardFilterDateType = criteria.getAefiDashboardFilterDateType() != null + ? criteria.getAefiDashboardFilterDateType() + : AefiDashboardFilterDateType.REPORT_DATE; + + switch (aefiDashboardFilterDateType) { + case REPORT_DATE: + dateFilter = cb.between(aefiRoot.get(Aefi.REPORT_DATE), dateFrom, dateTo); + break; + case START_DATE: + dateFilter = cb.between(aefiRoot.get(Aefi.START_DATE_TIME), dateFrom, dateTo); + break; + default: + throw new RuntimeException("Unhandled date type [" + aefiDashboardFilterDateType + "]"); + } + + filter = CriteriaBuilderHelper.and(cb, filter, dateFilter); + } + + return CriteriaBuilderHelper.and( + cb, + filter, + // Exclude deleted adverse events. Archived adverse events should stay included + cb.isFalse(aefiRoot.get(Aefi.DELETED))); + } + + private String createAefiNativeQueryFilter(AefiDashboardCriteria criteria) { + + List whereConditions = new ArrayList<>(); + + if (criteria.getDisease() != null) { + whereConditions.add("immunization.disease = :disease"); + } + + if (criteria.getRegion() != null) { + whereConditions.add("immunization.responsibleregion_id = :responsibleregion_id"); + } + + if (criteria.getDistrict() != null) { + whereConditions.add("immunization.responsibledistrict_id = :responsibledistrict_id"); + } + + if (criteria.getDateFrom() != null && criteria.getDateTo() != null) { + AefiDashboardFilterDateType aefiDashboardFilterDateType = criteria.getAefiDashboardFilterDateType() != null + ? criteria.getAefiDashboardFilterDateType() + : AefiDashboardFilterDateType.REPORT_DATE; + + switch (aefiDashboardFilterDateType) { + case REPORT_DATE: + whereConditions.add("(aefi.reportdate >= cast(:dateFrom as timestamp) and aefi.reportdate <= cast(:dateTo as timestamp))"); + break; + case START_DATE: + whereConditions.add("(aefi.startdatetime >= cast(:dateFrom as timestamp) and aefi.startdatetime <= cast(:dateTo as timestamp))"); + break; + default: + throw new RuntimeException("Unhandled date type [" + aefiDashboardFilterDateType + "]"); + } + } + + return String.join(" AND ", whereConditions); + } +} 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 237cdad9507..a52daa2c309 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 @@ -30,16 +30,19 @@ import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; import javax.persistence.Tuple; +import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaUpdate; import javax.persistence.criteria.From; import javax.persistence.criteria.Join; import javax.persistence.criteria.JoinType; +import javax.persistence.criteria.ParameterExpression; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import javax.persistence.criteria.Subquery; +import javax.validation.constraints.NotNull; import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.EditPermissionType; @@ -108,6 +111,24 @@ public ImmunizationService() { super(Immunization.class, DeletableEntityType.IMMUNIZATION); } + public Long getIdByUuid(@NotNull String uuid) { + + if (uuid == null) { + return null; + } + + CriteriaBuilder cb = em.getCriteriaBuilder(); + ParameterExpression uuidParam = cb.parameter(String.class, AbstractDomainObject.UUID); + CriteriaQuery cq = cb.createQuery(Long.class); + Root from = cq.from(Immunization.class); + cq.select(from.get(AbstractDomainObject.ID)); + cq.where(cb.equal(from.get(AbstractDomainObject.UUID), uuidParam)); + + TypedQuery q = em.createQuery(cq).setParameter(uuidParam, uuid); + + return q.getResultList().stream().findFirst().orElse(null); + } + @Override public void deletePermanent(Immunization immunization) { diff --git a/sormas-backend/src/main/resources/META-INF/persistence.xml b/sormas-backend/src/main/resources/META-INF/persistence.xml index b792ff39147..e0dd26ad9b2 100644 --- a/sormas-backend/src/main/resources/META-INF/persistence.xml +++ b/sormas-backend/src/main/resources/META-INF/persistence.xml @@ -86,6 +86,9 @@ de.symeda.sormas.backend.externalmessage.labmessage.TestReport de.symeda.sormas.backend.deletionconfiguration.DeletionConfiguration de.symeda.sormas.backend.externalmessage.labmessage.SampleReport + de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.Aefi + de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AdverseEvents + de.symeda.sormas.backend.specialcaseaccess.SpecialCaseAccess de.symeda.sormas.backend.specialcaseaccess.SpecialCaseAccess de.symeda.sormas.backend.selfreport.SelfReport diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/ControllerProvider.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/ControllerProvider.java index 12b32cf2f3c..7e2f4581fc1 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/ControllerProvider.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/ControllerProvider.java @@ -18,6 +18,7 @@ package de.symeda.sormas.ui; import de.symeda.sormas.ui.action.ActionController; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.AefiController; import de.symeda.sormas.ui.campaign.CampaignController; import de.symeda.sormas.ui.caze.CaseController; import de.symeda.sormas.ui.caze.surveillancereport.SurveillanceReportController; @@ -89,6 +90,7 @@ public class ControllerProvider extends BaseControllerProvider { private final DocGenerationController docGenerationController; private final TravelEntryController travelEntryController; private final ImmunizationController immunizationController; + private final AefiController aefiController; private final VaccinationController vaccinationController; private final ArchivingController archivingController; private final DeleteRestoreController deleteRestoreController; @@ -132,6 +134,7 @@ public ControllerProvider() { docGenerationController = new DocGenerationController(); travelEntryController = new TravelEntryController(); immunizationController = new ImmunizationController(); + aefiController = new AefiController(); vaccinationController = new VaccinationController(); archivingController = new ArchivingController(); deleteRestoreController = new DeleteRestoreController(); @@ -264,6 +267,10 @@ public static ImmunizationController getImmunizationController() { return get().immunizationController; } + public static AefiController getAefiController() { + return get().aefiController; + } + public static VaccinationController getVaccinationController() { return get().vaccinationController; } 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 890097e8b3b..00ecea96b08 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 @@ -52,6 +52,7 @@ import de.symeda.sormas.api.user.UserRight; import de.symeda.sormas.api.utils.DataHelper; import de.symeda.sormas.api.utils.criteria.BaseCriteria; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.AefiView; import de.symeda.sormas.ui.campaign.AbstractCampaignView; import de.symeda.sormas.ui.campaign.campaigndata.CampaignDataView; import de.symeda.sormas.ui.campaign.campaigns.CampaignsView; @@ -69,6 +70,7 @@ import de.symeda.sormas.ui.configuration.outbreak.OutbreaksView; import de.symeda.sormas.ui.contact.ContactsView; import de.symeda.sormas.ui.dashboard.AbstractDashboardView; +import de.symeda.sormas.ui.dashboard.adverseeventsfollowingimmunization.AefiDashboardView; import de.symeda.sormas.ui.dashboard.campaigns.CampaignDashboardView; import de.symeda.sormas.ui.dashboard.contacts.ContactsDashboardView; import de.symeda.sormas.ui.dashboard.sample.SampleDashboardView; @@ -231,6 +233,12 @@ public View getView(String viewName) { AbstractDashboardView.ROOT_VIEW_NAME, I18nProperties.getCaption(Captions.mainMenuDashboard), VaadinIcons.DASHBOARD); + } else if (aefiDashboardPermitted()) { + menu.addView( + AefiDashboardView.class, + AbstractDashboardView.ROOT_VIEW_NAME, + I18nProperties.getCaption(Captions.mainMenuDashboard), + VaadinIcons.DASHBOARD); } if (permitted(FeatureType.TASK_MANAGEMENT, UserRight.TASK_VIEW)) { @@ -299,6 +307,13 @@ public View getView(String viewName) { VaadinIcons.HEALTH_CARD); } + if (permitted(FeatureType.IMMUNIZATION_MANAGEMENT, UserRight.IMMUNIZATION_VIEW) + && !FacadeProvider.getFeatureConfigurationFacade().isPropertyValueTrue(FeatureType.IMMUNIZATION_MANAGEMENT, FeatureTypeProperty.REDUCED) + && permitted(FeatureType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_MANAGEMENT, UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW)) { + ControllerProvider.getAefiController().registerViews(navigator); + menu.addView(AefiView.class, AefiView.VIEW_NAME, I18nProperties.getCaption(Captions.mainMenuAdverseEvents), VaadinIcons.BELL_SLASH); + } + if (permitted(FeatureType.TRAVEL_ENTRIES, UserRight.TRAVEL_ENTRY_MANAGEMENT_ACCESS) && FacadeProvider.getConfigFacade().isConfiguredCountry(CountryHelper.COUNTRY_CODE_GERMANY)) { ControllerProvider.getTravelEntryController().registerViews(navigator); @@ -439,6 +454,12 @@ private static boolean sampleDashboardPermitted() { return permitted(EnumSet.of(FeatureType.DASHBOARD_SAMPLES, FeatureType.SAMPLES_LAB), UserRight.DASHBOARD_SAMPLES_VIEW); } + private static boolean aefiDashboardPermitted() { + return permitted( + EnumSet.of(FeatureType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_MANAGEMENT), + UserRight.DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW); + } + private static Set initKnownViews() { final Set views = new HashSet<>( Arrays.asList( @@ -468,7 +489,8 @@ private static Set initKnownViews() { CountriesView.VIEW_NAME, ExternalMessagesView.VIEW_NAME, TravelEntriesView.VIEW_NAME, - ImmunizationsView.VIEW_NAME)); + ImmunizationsView.VIEW_NAME, + AefiView.VIEW_NAME)); if (surveillanceDashboardPermitted()) { views.add(SurveillanceDashboardView.VIEW_NAME); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiView.java new file mode 100644 index 00000000000..3e082e0657a --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiView.java @@ -0,0 +1,115 @@ +/* + * 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.ui.adverseeventsfollowingimmunization; + +import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; + +import de.symeda.sormas.api.EditPermissionFacade; +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiReferenceDto; +import de.symeda.sormas.api.i18n.Captions; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.immunization.ImmunizationDto; +import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.SubMenu; +import de.symeda.sormas.ui.immunization.ImmunizationDataView; +import de.symeda.sormas.ui.immunization.ImmunizationPersonView; +import de.symeda.sormas.ui.utils.AbstractEditAllowedDetailView; + +public abstract class AbstractAefiView extends AbstractEditAllowedDetailView { + + public static final String ROOT_VIEW_NAME = AefiView.VIEW_NAME; + + protected AbstractAefiView(String viewName) { + super(viewName); + } + + @Override + protected AefiReferenceDto getReferenceByUuid(String uuid) { + + final AefiReferenceDto reference; + + boolean isCreateAction = ControllerProvider.getAefiController().isCreateAction(uuid); + + if (isCreateAction) { + reference = new AefiReferenceDto(); + reference.setUuid(DataHelper.createUuid()); + } else { + if (FacadeProvider.getAefiFacade().exists(uuid)) { + reference = FacadeProvider.getAefiFacade().getReferenceByUuid(uuid); + } else { + reference = null; + } + } + return reference; + } + + @Override + protected String getRootViewName() { + return ROOT_VIEW_NAME; + } + + @Override + protected void initView(String params) { + + } + + @Override + protected EditPermissionFacade getEditPermissionFacade() { + return FacadeProvider.getAefiFacade(); + } + + @Override + public void enter(ViewChangeEvent event) { + + super.enter(event); + initOrRedirect(event); + } + + @Override + public void refreshMenu(SubMenu menu, String params) { + + if (!findReferenceByParams(params)) { + return; + } + + boolean isCreateAction = ControllerProvider.getAefiController().isCreateAction(params); + + String immunizationUuid = ""; + if (isCreateAction) { + immunizationUuid = ControllerProvider.getAefiController().getCreateActionImmunizationUuid(params); + } else { + AefiDto aefiDto = FacadeProvider.getAefiFacade().getByUuid(params); + immunizationUuid = aefiDto.getImmunization().getUuid(); + } + + menu.removeAllViews(); + menu.addView(AefiView.VIEW_NAME, I18nProperties.getCaption(Captions.aefiAefiList)); + menu.addView(ImmunizationDataView.VIEW_NAME, I18nProperties.getCaption(ImmunizationDto.I18N_PREFIX), immunizationUuid); + menu.addView( + ImmunizationPersonView.VIEW_NAME, + I18nProperties.getPrefixCaption(ImmunizationDto.I18N_PREFIX, ImmunizationDto.PERSON), + immunizationUuid); + menu.addView(AefiDataView.VIEW_NAME, I18nProperties.getCaption(Captions.aefiAefiDataView), params); + + setMainHeaderComponent(ControllerProvider.getAefiController().getAefiViewTitleLayout(params, immunizationUuid, isCreateAction)); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiController.java new file mode 100644 index 00000000000..a3200c25c27 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiController.java @@ -0,0 +1,195 @@ +/* + * 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.ui.adverseeventsfollowingimmunization; + +import java.util.function.Consumer; + +import org.apache.commons.lang3.StringUtils; + +import com.vaadin.navigator.Navigator; +import com.vaadin.server.Sizeable; +import com.vaadin.ui.Notification; + +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +import de.symeda.sormas.api.common.DeletionReason; +import de.symeda.sormas.api.deletionconfiguration.DeletionInfoDto; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.i18n.Strings; +import de.symeda.sormas.api.immunization.ImmunizationDto; +import de.symeda.sormas.api.person.PersonDto; +import de.symeda.sormas.api.user.UserRight; +import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.api.vaccination.VaccinationDto; +import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.SormasUI; +import de.symeda.sormas.ui.UserProvider; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.fields.vaccines.AefiPrimarySuspectVaccinationSelectionField; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.form.AefiDataForm; +import de.symeda.sormas.ui.utils.ArchiveHandlers; +import de.symeda.sormas.ui.utils.CommitDiscardWrapperComponent; +import de.symeda.sormas.ui.utils.VaadinUiUtil; +import de.symeda.sormas.ui.utils.components.automaticdeletion.DeletionLabel; +import de.symeda.sormas.ui.utils.components.page.title.TitleLayout; +import de.symeda.sormas.ui.utils.components.page.title.TitleLayoutHelper; + +public class AefiController { + + public void registerViews(Navigator navigator) { + navigator.addView(AefiView.VIEW_NAME, AefiView.class); + //navigator.addView(ImmunizationDataView.VIEW_NAME, ImmunizationDataView.class); + //navigator.addView(ImmunizationPersonView.VIEW_NAME, ImmunizationPersonView.class); + navigator.addView(AefiDataView.VIEW_NAME, AefiDataView.class); + } + + public void selectPrimarySuspectVaccination(AefiDto aefiDto, Consumer commitCallback) { + + AefiPrimarySuspectVaccinationSelectionField selectionField = + new AefiPrimarySuspectVaccinationSelectionField(aefiDto.getVaccinations(), aefiDto.getPrimarySuspectVaccine()); + selectionField.setWidth(1024, Sizeable.Unit.PIXELS); + + final CommitDiscardWrapperComponent component = + new CommitDiscardWrapperComponent<>(selectionField); + component.addCommitListener(() -> { + VaccinationDto selectedVaccination = selectionField.getValue(); + if (selectedVaccination != null) { + aefiDto.setPrimarySuspectVaccine(selectedVaccination); + + if (commitCallback != null) { + commitCallback.accept(selectedVaccination); + } + } + }); + + selectionField.setSelectionChangeCallback((commitAllowed) -> component.getCommitButton().setEnabled(commitAllowed)); + VaadinUiUtil.showModalPopupWindow(component, I18nProperties.getString(Strings.headingAefiPickPrimarySuspectVaccine)); + } + + public void navigateToAefi(String uuid) { + navigateToView(AefiDataView.VIEW_NAME, uuid); + } + + public void navigateToView(String viewName, String uuid) { + final String navigationState = viewName + "/" + uuid; + SormasUI.get().getNavigator().navigateTo(navigationState); + } + + public CommitDiscardWrapperComponent getAefiDataEditComponent( + boolean isCreateAction, + AefiDto aefiDto, + Consumer actionCallback) { + + AefiDataForm aefiDataForm = new AefiDataForm(isCreateAction, aefiDto.isPseudonymized(), aefiDto.isInJurisdiction(), actionCallback); + aefiDataForm.setValue(aefiDto); + + CommitDiscardWrapperComponent editComponent = + new CommitDiscardWrapperComponent<>(aefiDataForm, true, aefiDataForm.getFieldGroup()); + + if (!isCreateAction) { + DeletionInfoDto automaticDeletionInfoDto = FacadeProvider.getAefiFacade().getAutomaticDeletionInfo(aefiDto.getUuid()); + DeletionInfoDto manuallyDeletionInfoDto = FacadeProvider.getAefiFacade().getManuallyDeletionInfo(aefiDto.getUuid()); + + editComponent.getButtonsPanel() + .addComponentAsFirst(new DeletionLabel(automaticDeletionInfoDto, manuallyDeletionInfoDto, aefiDto.isDeleted(), AefiDto.I18N_PREFIX)); + + if (aefiDto.isDeleted()) { + editComponent.getWrappedComponent().getField(AefiDto.DELETION_REASON).setVisible(true); + if (editComponent.getWrappedComponent().getField(AefiDto.DELETION_REASON).getValue() == DeletionReason.OTHER_REASON) { + editComponent.getWrappedComponent().getField(AefiDto.OTHER_DELETION_REASON).setVisible(true); + } + } + } + + editComponent.addCommitListener(() -> { + if (!aefiDataForm.getFieldGroup().isModified()) { + AefiDto aefiDataFormValue = aefiDataForm.getValue(); + + AefiDto savedAefiDto = FacadeProvider.getAefiFacade().save(aefiDataFormValue); + Notification.show(I18nProperties.getString(Strings.messageAdverseEventSaved), Notification.Type.WARNING_MESSAGE); + + if (isCreateAction) { + navigateToAefi(savedAefiDto.getUuid()); + } else { + SormasUI.refreshView(); + } + } + }); + + if (!isCreateAction) { + // Initialize 'Delete' button + if (UserProvider.getCurrent().hasUserRight(UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE)) { + editComponent.addDeleteWithReasonOrRestoreListener( + AefiView.VIEW_NAME, + null, + I18nProperties.getString(Strings.entityAdverseEvent), + aefiDto.getUuid(), + FacadeProvider.getAefiFacade()); + } + + // Initialize 'Archive' button + if (UserProvider.getCurrent().hasUserRight(UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE)) { + ControllerProvider.getArchiveController() + .addArchivingButton(aefiDto, ArchiveHandlers.forAefi(), editComponent, () -> navigateToAefi(aefiDto.getUuid())); + } + + editComponent.restrictEditableComponentsOnEditView( + UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT, + null, + UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE, + UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE, + FacadeProvider.getAefiFacade().getEditPermissionType(aefiDto.getUuid()), + aefiDto.isInJurisdiction()); + } + + return editComponent; + } + + public TitleLayout getAefiViewTitleLayout(String aefiUuid, String immunizationUuid, boolean isCreateAction) { + + if (!isCreateAction) { + AefiDto aefiDto = findAefi(aefiUuid); + immunizationUuid = aefiDto.getImmunization().getUuid(); + } + + TitleLayout titleLayout = new TitleLayout(); + + String shortUuid = DataHelper.getShortUuid(immunizationUuid); + ImmunizationDto immunizationDto = FacadeProvider.getImmunizationFacade().getByUuid(immunizationUuid); + PersonDto person = FacadeProvider.getPersonFacade().getByUuid(immunizationDto.getPerson().getUuid()); + StringBuilder mainRowText = TitleLayoutHelper.buildPersonString(person); + mainRowText.append(mainRowText.length() > 0 ? " (" + shortUuid + ")" : shortUuid); + titleLayout.addMainRow(mainRowText.toString()); + + return titleLayout; + } + + private AefiDto findAefi(String uuid) { + return FacadeProvider.getAefiFacade().getByUuid(uuid); + } + + public boolean isCreateAction(String params) { + return StringUtils.startsWith(params, "immunization") && StringUtils.endsWith(params, "create"); + } + + public String getCreateActionImmunizationUuid(String params) { + return StringUtils.contains(params, "/") + ? StringUtils.substringBetween(params, "/", "/") + : StringUtils.substringBetween(params, "immunization", "create"); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiDataView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiDataView.java new file mode 100644 index 00000000000..adc07afc106 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiDataView.java @@ -0,0 +1,128 @@ +/* + * 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.ui.adverseeventsfollowingimmunization; + +import java.util.ArrayList; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.EditPermissionType; +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +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.person.PersonDto; +import de.symeda.sormas.api.user.UserRight; +import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.UserProvider; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.form.AefiDataForm; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.information.AefiImmunizationInfo; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.information.AefiPersonInfo; +import de.symeda.sormas.ui.utils.CommitDiscardWrapperComponent; +import de.symeda.sormas.ui.utils.CssStyles; +import de.symeda.sormas.ui.utils.DetailSubComponentWrapper; +import de.symeda.sormas.ui.utils.LayoutWithSidePanel; + +public class AefiDataView extends AbstractAefiView { + + public static final String VIEW_NAME = ROOT_VIEW_NAME + "/data"; + + public static final String ADVERSE_EVENT_LOC = "adverseEventLoc"; + public static final String PERSON_LOC = "personLoc"; + public static final String IMMUNIZATION_LOC = "immunizationLoc"; + public static final String INVESTIGATIONS_LOC = "investigationsLoc"; + + private CommitDiscardWrapperComponent editComponent; + + public AefiDataView() { + super(VIEW_NAME); + } + + @Override + protected String getRootViewName() { + return super.getRootViewName(); + } + + @Override + protected void initView(String params) { + setHeightUndefined(); + + AefiDto aefi; + ImmunizationDto immunization; + + boolean isCreateAction = ControllerProvider.getAefiController().isCreateAction(params); + if (isCreateAction) { + aefi = AefiDto.build(getReference()); + + String immunizationUuid = ControllerProvider.getAefiController().getCreateActionImmunizationUuid(params); + immunization = FacadeProvider.getImmunizationFacade().getByUuid(immunizationUuid); + + aefi.setImmunization(immunization.toReference()); + aefi.setVaccinations(new ArrayList<>(immunization.getVaccinations())); + aefi.setReportingUser(UserProvider.getCurrent().getUserReference()); + } else { + aefi = FacadeProvider.getAefiFacade().getByUuid(getReference().getUuid()); + immunization = FacadeProvider.getImmunizationFacade().getByUuid(aefi.getImmunization().getUuid()); + } + + editComponent = ControllerProvider.getAefiController().getAefiDataEditComponent(isCreateAction, aefi, this::showUnsavedChangesPopup); + + DetailSubComponentWrapper container = new DetailSubComponentWrapper(() -> editComponent); + container.setWidth(100, Unit.PERCENTAGE); + container.setMargin(true); + setSubComponent(container); + container.setEnabled(true); + + LayoutWithSidePanel layout = new LayoutWithSidePanel(editComponent, PERSON_LOC, IMMUNIZATION_LOC, INVESTIGATIONS_LOC); + + container.addComponent(layout); + + UserProvider currentUser = UserProvider.getCurrent(); + if (currentUser.hasAllUserRights(UserRight.PERSON_VIEW)) { + PersonDto personDto = FacadeProvider.getPersonFacade().getByUuid(immunization.getPerson().getUuid()); + Disease disease = immunization.getDisease(); + + AefiPersonInfo aefiPersonInfo = new AefiPersonInfo(personDto, disease); + CssStyles.style(aefiPersonInfo, CssStyles.VIEW_SECTION); + + layout.addSidePanelComponent(aefiPersonInfo, PERSON_LOC); + } + + if (FacadeProvider.getFeatureConfigurationFacade().isFeatureEnabled(FeatureType.IMMUNIZATION_MANAGEMENT) + && currentUser != null + && currentUser.hasUserRight(UserRight.IMMUNIZATION_VIEW)) { + if (!FacadeProvider.getFeatureConfigurationFacade() + .isPropertyValueTrue(FeatureType.IMMUNIZATION_MANAGEMENT, FeatureTypeProperty.REDUCED)) { + + AefiImmunizationInfo aefiImmunizationInfo = new AefiImmunizationInfo(immunization, (r) -> { + }); + CssStyles.style(aefiImmunizationInfo, CssStyles.VIEW_SECTION, CssStyles.VSPACE_TOP_3); + + layout.addSidePanelComponent(aefiImmunizationInfo, IMMUNIZATION_LOC); + } + } + + if (!isCreateAction) { + final String uuid = aefi.getUuid(); + final EditPermissionType aefiEditAllowed = FacadeProvider.getAefiFacade().getEditPermissionType(uuid); + final boolean deleted = FacadeProvider.getAefiFacade().isDeleted(uuid); + layout.disableIfNecessary(deleted, aefiEditAllowed); + } + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiView.java new file mode 100644 index 00000000000..daa30665c50 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiView.java @@ -0,0 +1,208 @@ +/* + * 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.ui.adverseeventsfollowingimmunization; + +import java.util.Objects; + +import com.vaadin.icons.VaadinIcons; +import com.vaadin.navigator.ViewChangeListener; +import com.vaadin.shared.ui.ContentMode; +import com.vaadin.ui.Alignment; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.v7.ui.ComboBox; + +import de.symeda.sormas.api.EntityRelevanceStatus; +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiCriteria; +import de.symeda.sormas.api.common.DeletableEntityType; +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; +import de.symeda.sormas.api.user.UserRight; +import de.symeda.sormas.ui.UserProvider; +import de.symeda.sormas.ui.ViewModelProviders; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.directory.AefiDataLayout; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.directory.AefiFilterFormLayout; +import de.symeda.sormas.ui.utils.AbstractView; +import de.symeda.sormas.ui.utils.ComboBoxHelper; +import de.symeda.sormas.ui.utils.CssStyles; + +public class AefiView extends AbstractView { + + public static final String VIEW_NAME = "adverseevents"; + + private final AefiCriteria criteria; + + private AefiFilterFormLayout filterFormLayout; + private final AefiDataLayout dataLayout; + + // Filters + private Label relevanceStatusInfoLabel; + private ComboBox relevanceStatusFilter; + + public AefiView() { + super(VIEW_NAME); + + CssStyles.style(getViewTitleLabel(), CssStyles.PAGE_TITLE); + + criteria = ViewModelProviders.of(AefiView.class).get(AefiCriteria.class); + if (criteria.getRelevanceStatus() == null) { + criteria.setRelevanceStatus(EntityRelevanceStatus.ACTIVE); + } + dataLayout = new AefiDataLayout(criteria); + + final VerticalLayout mainLayout = new VerticalLayout(); + mainLayout.addComponent(createFilterBar()); + + final VerticalLayout gridLayout = new VerticalLayout(); + gridLayout.setMargin(false); + gridLayout.setSpacing(false); + gridLayout.setSizeFull(); + CssStyles.style(gridLayout, CssStyles.VIEW_SECTION, CssStyles.VSPACE_TOP_3); + + gridLayout.addComponent(createStatusFilterBar()); + gridLayout.addComponent(dataLayout); + gridLayout.setExpandRatio(dataLayout, 1); + + mainLayout.addComponent(gridLayout); + + mainLayout.setMargin(true); + mainLayout.setSpacing(false); + mainLayout.setSizeFull(); + mainLayout.setExpandRatio(gridLayout, 1); + mainLayout.setStyleName("crud-main-layout"); + + addComponent(mainLayout); + } + + private void updateFilterComponents() { + // TODO replace with Vaadin 8 databinding + applyingCriteria = true; + + if (relevanceStatusFilter != null) { + relevanceStatusFilter.setValue(criteria.getRelevanceStatus()); + } + + filterFormLayout.setValue(criteria); + + applyingCriteria = false; + } + + private AefiFilterFormLayout createFilterBar() { + filterFormLayout = new AefiFilterFormLayout(); + + filterFormLayout.addResetHandler(clickEvent -> { + ViewModelProviders.of(AefiView.class).remove(AefiCriteria.class); + navigateTo(null, true); + }); + + filterFormLayout.addApplyHandler(clickEvent -> { + dataLayout.refreshGrid(); + }); + + return filterFormLayout; + } + + public HorizontalLayout createStatusFilterBar() { + HorizontalLayout statusFilterLayout = new HorizontalLayout(); + statusFilterLayout.setSpacing(true); + statusFilterLayout.setMargin(false); + statusFilterLayout.setWidth(100, Unit.PERCENTAGE); + statusFilterLayout.addStyleName(CssStyles.VSPACE_3); + + HorizontalLayout actionButtonsLayout = new HorizontalLayout(); + actionButtonsLayout.setSpacing(true); + + // Show active/archived/all dropdown + if (Objects.nonNull(UserProvider.getCurrent()) + && UserProvider.getCurrent().hasUserRight(UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW)) { + + if (FacadeProvider.getFeatureConfigurationFacade() + .isFeatureEnabled(FeatureType.AUTOMATIC_ARCHIVING, DeletableEntityType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION)) { + + int daysAfterAefiEntryGetsArchived = FacadeProvider.getFeatureConfigurationFacade() + .getProperty( + FeatureType.AUTOMATIC_ARCHIVING, + DeletableEntityType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION, + FeatureTypeProperty.THRESHOLD_IN_DAYS, + Integer.class); + if (daysAfterAefiEntryGetsArchived > 0) { + relevanceStatusInfoLabel = new Label( + VaadinIcons.INFO_CIRCLE.getHtml() + " " + + String.format(I18nProperties.getString(Strings.infoArchivedAefiEntries), daysAfterAefiEntryGetsArchived), + ContentMode.HTML); + relevanceStatusInfoLabel.setVisible(false); + relevanceStatusInfoLabel.addStyleName(CssStyles.LABEL_VERTICAL_ALIGN_SUPER); + actionButtonsLayout.addComponent(relevanceStatusInfoLabel); + actionButtonsLayout.setComponentAlignment(relevanceStatusInfoLabel, Alignment.MIDDLE_RIGHT); + } + } + relevanceStatusFilter = ComboBoxHelper.createComboBoxV7(); + relevanceStatusFilter.setId("relevanceStatus"); + relevanceStatusFilter.setWidth(260, Unit.PIXELS); + relevanceStatusFilter.setNullSelectionAllowed(false); + relevanceStatusFilter.setTextInputAllowed(false); + relevanceStatusFilter.addItems((Object[]) EntityRelevanceStatus.values()); + relevanceStatusFilter.setItemCaption(EntityRelevanceStatus.ACTIVE, I18nProperties.getCaption(Captions.aefiActiveAdverseEvents)); + relevanceStatusFilter.setItemCaption(EntityRelevanceStatus.ARCHIVED, I18nProperties.getCaption(Captions.aefiArchivedAdverseEvents)); + relevanceStatusFilter + .setItemCaption(EntityRelevanceStatus.ACTIVE_AND_ARCHIVED, I18nProperties.getCaption(Captions.aefiAllActiveAndArchivedAdverseEvents)); + relevanceStatusFilter.setCaption(null); + relevanceStatusFilter.addStyleName(CssStyles.VSPACE_NONE); + + if (UserProvider.getCurrent().hasUserRight(UserRight.IMMUNIZATION_DELETE)) { + relevanceStatusFilter.setItemCaption(EntityRelevanceStatus.DELETED, I18nProperties.getCaption(Captions.aefiDeletedAdverseEvents)); + } else { + relevanceStatusFilter.removeItem(EntityRelevanceStatus.DELETED); + } + + relevanceStatusFilter.addValueChangeListener(e -> { + if (relevanceStatusInfoLabel != null) { + relevanceStatusInfoLabel.setVisible(EntityRelevanceStatus.ARCHIVED.equals(e.getProperty().getValue())); + } + criteria.setRelevanceStatus((EntityRelevanceStatus) e.getProperty().getValue()); + navigateTo(criteria); + }); + actionButtonsLayout.addComponent(relevanceStatusFilter); + } + + if (actionButtonsLayout.getComponentCount() > 0) { + statusFilterLayout.addComponent(actionButtonsLayout); + statusFilterLayout.setComponentAlignment(actionButtonsLayout, Alignment.TOP_RIGHT); + statusFilterLayout.setExpandRatio(actionButtonsLayout, 1); + } + + return statusFilterLayout; + } + + @Override + public void enter(ViewChangeListener.ViewChangeEvent event) { + + String params = event.getParameters().trim(); + if (params.startsWith("?")) { + params = params.substring(1); + criteria.fromUrlParams(params); + } + updateFilterComponents(); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiList.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiList.java new file mode 100644 index 00000000000..1c88db1072b --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiList.java @@ -0,0 +1,89 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.aefilink; + +import java.util.List; +import java.util.function.Consumer; + +import org.apache.commons.collections.CollectionUtils; + +import com.vaadin.ui.Button; +import com.vaadin.ui.Label; + +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiListCriteria; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiListEntryDto; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.i18n.Strings; +import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.utils.PaginationList; + +@SuppressWarnings("serial") +public class AefiList extends PaginationList { + + private static final int MAX_DISPLAYED_ENTRIES = 5; + + private AefiListCriteria aefiListCriteria; + private Consumer actionCallback; + private final boolean isEditable; + private Label noAdverseEventsLabel; + + public AefiList(AefiListCriteria aefiListCriteria, Consumer actionCallback, boolean isEditable) { + + super(MAX_DISPLAYED_ENTRIES); + + this.aefiListCriteria = aefiListCriteria; + this.actionCallback = actionCallback; + this.isEditable = isEditable; + + noAdverseEventsLabel = new Label(I18nProperties.getString(Strings.infoNoImmunizationAdverseEvents)); + } + + @Override + public void reload() { + + List aefiListEntries = FacadeProvider.getAefiFacade().getEntriesList(aefiListCriteria, 0, maxDisplayedEntries * 20); + + setEntries(aefiListEntries); + if (CollectionUtils.isNotEmpty(aefiListEntries)) { + showPage(1); + } else { + listLayout.removeAllComponents(); + updatePaginationLayout(); + listLayout.addComponent(noAdverseEventsLabel); + } + } + + @Override + protected void drawDisplayedEntries() { + + List displayedEntries = getDisplayedEntries(); + for (AefiListEntryDto aefiListEntry : displayedEntries) { + AefiListEntry listEntry = new AefiListEntry(aefiListEntry); + + String aefiUuid = aefiListEntry.getUuid(); + listEntry.addEditButton( + "edit-aefi-" + aefiUuid, + (Button.ClickListener) event -> ControllerProvider.getAefiController().navigateToAefi(aefiUuid)); + + listEntry.setEnabled(isEditable); + listLayout.addComponent(listEntry); + } + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiListComponent.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiListComponent.java new file mode 100644 index 00000000000..400715182cb --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiListComponent.java @@ -0,0 +1,56 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.aefilink; + +import java.util.function.Consumer; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiListCriteria; +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.user.UserRight; +import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.utils.components.sidecomponent.SideComponent; + +@SuppressWarnings("serial") +public class AefiListComponent extends SideComponent { + + public AefiListComponent(AefiListCriteria aefiListCriteria, Consumer actionCallback, boolean isEditAllowed, int totalVaccinations) { + super(I18nProperties.getString(Strings.headingImmunizationAdverseEvents), actionCallback); + + setMargin(false); + setWidth(100, Unit.PERCENTAGE); + + if (isEditAllowed) { + addCreateButton( + I18nProperties.getCaption(Captions.aefiNewAdverseEvent), + () -> ControllerProvider.getAefiController() + .navigateToAefi("immunization/" + aefiListCriteria.getImmunization().getUuid() + "/create"), + UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE); + + if (totalVaccinations == 0) { + createButton.setEnabled(false); + } + } + + AefiList aefiList = new AefiList(aefiListCriteria, actionCallback, isEditAllowed); + addComponent(aefiList); + aefiList.reload(); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiListEntry.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiListEntry.java new file mode 100644 index 00000000000..a47a70bfe60 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiListEntry.java @@ -0,0 +1,79 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.aefilink; + +import org.apache.commons.lang3.StringUtils; + +import com.vaadin.ui.Label; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiListEntryDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.utils.YesNoUnknown; +import de.symeda.sormas.api.vaccination.VaccinationDto; +import de.symeda.sormas.ui.utils.CssStyles; +import de.symeda.sormas.ui.utils.DateFormatHelper; +import de.symeda.sormas.ui.utils.components.sidecomponent.SideComponentField; + +@SuppressWarnings("serial") +public class AefiListEntry extends SideComponentField { + + public static final String SEPARATOR = ": "; + + private final AefiListEntryDto aefiListEntryDto; + + public AefiListEntry(AefiListEntryDto aefiListEntryDto) { + + this.aefiListEntryDto = aefiListEntryDto; + + Label labelAefiType = new Label(AefiType.toString(aefiListEntryDto.getSerious())); + CssStyles.style(labelAefiType, CssStyles.LABEL_BOLD, CssStyles.LABEL_UPPERCASE); + if (aefiListEntryDto.getSerious() == YesNoUnknown.YES) { + CssStyles.style(labelAefiType, CssStyles.LABEL_CRITICAL); + } + addComponentToField(labelAefiType); + + Label labelVaccineName = new Label(aefiListEntryDto.getPrimaryVaccineName().toString()); + CssStyles.style(labelVaccineName, CssStyles.LABEL_BOLD, CssStyles.LABEL_UPPERCASE); + addComponentToField(labelVaccineName); + + if (!StringUtils.isBlank(aefiListEntryDto.getPrimaryVaccineDose())) { + Label labelVaccineDose = new Label( + I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, VaccinationDto.VACCINE_DOSE) + + SEPARATOR + + aefiListEntryDto.getPrimaryVaccineDose()); + CssStyles.style(labelVaccineDose, CssStyles.LABEL_BOLD, CssStyles.LABEL_UPPERCASE); + addComponentToField(labelVaccineDose); + } + + Label labelVaccineDate = new Label( + I18nProperties.getPrefixCaption(AefiListEntryDto.I18N_PREFIX, AefiListEntryDto.PRIMARY_VACCINE_VACCINATION_DATE) + + SEPARATOR + + DateFormatHelper.formatLocalDate(aefiListEntryDto.getPrimaryVaccineVaccinationDate())); + addComponentToField(labelVaccineDate); + + Label labelAdverseEvents = new Label(StringUtils.abbreviate(aefiListEntryDto.getAdverseEvents(), 56)); + CssStyles.style(labelAdverseEvents, CssStyles.LABEL_BOLD, CssStyles.LABEL_UPPERCASE); + addComponentToField(labelAdverseEvents); + } + + public AefiListEntryDto getAefiListEntryDto() { + return aefiListEntryDto; + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiDataLayout.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiDataLayout.java new file mode 100644 index 00000000000..fa96538ee1e --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiDataLayout.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.ui.adverseeventsfollowingimmunization.components.directory; + +import com.vaadin.ui.VerticalLayout; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiCriteria; + +public class AefiDataLayout extends VerticalLayout { + + private final AefiGrid grid; + + public AefiDataLayout(AefiCriteria criteria) { + grid = new AefiGrid(criteria); + addComponent(grid); + + setMargin(false); + setSpacing(false); + setSizeFull(); + setExpandRatio(grid, 1); + } + + public void refreshGrid() { + grid.reload(); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiFilterForm.java new file mode 100644 index 00000000000..3f83e93210e --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiFilterForm.java @@ -0,0 +1,420 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.components.directory; + +import static de.symeda.sormas.ui.utils.LayoutUtil.divCss; +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.Date; +import java.util.stream.Stream; + +import org.apache.commons.lang3.ArrayUtils; + +import com.vaadin.ui.CustomLayout; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.v7.data.Property; +import com.vaadin.v7.ui.ComboBox; +import com.vaadin.v7.ui.Field; +import com.vaadin.v7.ui.TextField; + +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiCriteria; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDateType; +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.infrastructure.community.CommunityReferenceDto; +import de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto; +import de.symeda.sormas.api.infrastructure.facility.FacilityType; +import de.symeda.sormas.api.infrastructure.facility.FacilityTypeGroup; +import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto; +import de.symeda.sormas.api.user.JurisdictionLevel; +import de.symeda.sormas.api.user.UserDto; +import de.symeda.sormas.api.utils.DataHelper; +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.UserProvider; +import de.symeda.sormas.ui.utils.AbstractFilterForm; +import de.symeda.sormas.ui.utils.CssStyles; +import de.symeda.sormas.ui.utils.EpiWeekAndDateFilterComponent; +import de.symeda.sormas.ui.utils.FieldConfiguration; +import de.symeda.sormas.ui.utils.FieldHelper; + +public class AefiFilterForm extends AbstractFilterForm { + + private static final String ACTION_BUTTONS_ID = "actionButtons"; + private static final String MORE_FILTERS_ID = "moreFilters"; + private static final String WEEK_AND_DATE_FILTER = "weekAndDateFilter"; + + private static final String MORE_FILTERS_HTML = loc(WEEK_AND_DATE_FILTER); + + public AefiFilterForm() { + super( + AefiCriteria.class, + AefiCriteria.I18N_PREFIX, + JurisdictionFieldConfig.of(AefiCriteria.REGION, AefiCriteria.DISTRICT, AefiCriteria.COMMUNITY)); + } + + @Override + protected String createHtmlLayout() { + return divCss( + CssStyles.VIEW_SECTION, + filterLocs(ArrayUtils.addAll(getMainFilterLocators(), ACTION_BUTTONS_ID)) + locCss(CssStyles.VSPACE_TOP_NONE, MORE_FILTERS_ID)); + + } + + @Override + protected String[] getMainFilterLocators() { + return new String[] { + AefiCriteria.DISEASE, + AefiCriteria.NAME_ADDRESS_PHONE_EMAIL_LIKE, + AefiCriteria.AEFI_TYPE, + AefiCriteria.VACCINE_NAME, + AefiCriteria.REGION, + AefiCriteria.DISTRICT, + AefiCriteria.COMMUNITY, + AefiCriteria.OUTCOME }; + } + + @Override + protected String createMoreFiltersHtmlLayout() { + return MORE_FILTERS_HTML; + } + + @Override + protected void addFields() { + addField(FieldConfiguration.pixelSized(AefiCriteria.DISEASE, 140)); + + final TextField searchField = addField( + FieldConfiguration.withCaptionAndPixelSized( + AefiCriteria.NAME_ADDRESS_PHONE_EMAIL_LIKE, + I18nProperties.getString(Strings.promptPersonsSearchField), + 200)); + searchField.setNullRepresentation(""); + + addFields(FieldConfiguration.pixelSized(AefiCriteria.AEFI_TYPE, 140), FieldConfiguration.pixelSized(AefiCriteria.VACCINE_NAME, 140)); + + if (currentUserDto().getRegion() == null) { + ComboBox regionFilter = addField(getContent(), FieldConfiguration.pixelSized(AefiCriteria.REGION, 140)); + regionFilter.addItems(FacadeProvider.getRegionFacade().getAllActiveByServerCountry()); + } + + ComboBox districtFilter = addField(getContent(), FieldConfiguration.pixelSized(AefiCriteria.DISTRICT, 140)); + districtFilter.setDescription(I18nProperties.getDescription(Descriptions.descDistrictFilter)); + if (currentUserDto().getDistrict() != null) { + districtFilter.setVisible(false); + } + + addField(getContent(), FieldConfiguration.pixelSized(AefiCriteria.COMMUNITY, 140)); + + addField(FieldConfiguration.pixelSized(AefiCriteria.OUTCOME, 140)); + } + + @Override + public void addMoreFilters(CustomLayout moreFiltersContainer) { + moreFiltersContainer.addComponent(buildWeekAndDateFilter(), WEEK_AND_DATE_FILTER); + } + + @Override + protected void applyDependenciesOnFieldChange(String propertyId, Property.ValueChangeEvent event) { + + super.applyDependenciesOnFieldChange(propertyId, event); + + final AefiCriteria criteria = getValue(); + + final ComboBox facilityTypeGroupField = getField(AefiCriteria.FACILITY_TYPE_GROUP); + final ComboBox facilityTypeField = getField(AefiCriteria.FACILITY_TYPE); + final ComboBox facilityField = getField(AefiCriteria.HEALTH_FACILITY); + + final UserDto user = currentUserDto(); + final DistrictReferenceDto currentDistrict = + user.getDistrict() != null ? user.getDistrict() : (DistrictReferenceDto) districtFilter.getValue(); + + switch (propertyId) { + case AefiCriteria.REGION: { + final RegionReferenceDto region = user.getRegion() != null ? user.getRegion() : (RegionReferenceDto) event.getProperty().getValue(); + + if (!DataHelper.equal(region, criteria.getRegion())) { + if (region != null) { + enableFields(districtFilter); + FieldHelper.updateItems(districtFilter, FacadeProvider.getDistrictFacade().getAllActiveByRegion(region.getUuid())); + } else { + clearAndDisableFields(districtFilter); + } + clearAndDisableFields(communityFilter, facilityField, facilityTypeField, facilityTypeGroupField); + } + + break; + } + case AefiCriteria.DISTRICT: { + final DistrictReferenceDto newDistrict = (DistrictReferenceDto) event.getProperty().getValue(); + + if (!DataHelper.equal(newDistrict, criteria.getDistrict())) { + if (newDistrict != null) { + enableFields(communityFilter, facilityTypeGroupField); + + clearAndDisableFields(facilityField); + if (facilityTypeGroupField != null) { + if (facilityTypeGroupField.getValue() != null && facilityTypeField.getValue() != null) { + FieldHelper.updateItems( + facilityField, + FacadeProvider.getFacilityFacade() + .getActiveFacilitiesByDistrictAndType(newDistrict, (FacilityType) facilityTypeField.getValue(), true, false)); + enableFields(facilityField); + } else { + FieldHelper.updateEnumData(facilityTypeGroupField, FacilityTypeGroup.getAccomodationGroups()); + } + } + + FieldHelper.updateItems(communityFilter, FacadeProvider.getCommunityFacade().getAllActiveByDistrict(newDistrict.getUuid())); + } else { + clearAndDisableFields(communityFilter, facilityField, facilityTypeField, facilityTypeGroupField); + } + } + + break; + } + case AefiCriteria.COMMUNITY: { + CommunityReferenceDto community = (CommunityReferenceDto) event.getProperty().getValue(); + if (!DataHelper.equal(community, criteria.getCommunity())) { + if (facilityField != null) { + facilityField.setValue(null); + } + + final FacilityType facilityType = facilityTypeField != null ? (FacilityType) facilityTypeField.getValue() : null; + + if (facilityType == null && facilityField != null) { + facilityField.removeAllItems(); + } else if (facilityField != null) { + if (community == null) { + FieldHelper.updateItems( + facilityField, + FacadeProvider.getFacilityFacade().getActiveFacilitiesByDistrictAndType(currentDistrict, facilityType, true, false)); + } else { + FieldHelper.updateItems( + facilityField, + FacadeProvider.getFacilityFacade().getActiveFacilitiesByCommunityAndType(community, facilityType, true, false)); + } + } + } + break; + } + case AefiCriteria.FACILITY_TYPE_GROUP: { + FacilityTypeGroup typeGroup = (FacilityTypeGroup) event.getProperty().getValue(); + if (!DataHelper.equal(typeGroup, criteria.getFacilityTypeGroup())) { + if (typeGroup != null) { + enableFields(AefiCriteria.FACILITY_TYPE); + FieldHelper.updateEnumData(facilityTypeField, FacilityType.getAccommodationTypes(typeGroup)); + facilityField.setValue(null); + } else { + clearAndDisableFields(facilityTypeField, facilityField); + } + } + + break; + } + case AefiCriteria.FACILITY_TYPE: { + FacilityType facilityType = (FacilityType) event.getProperty().getValue(); + if (!DataHelper.equal(facilityType, criteria.getFacilityType())) { + if (facilityType == null) { + clearAndDisableFields(facilityField); + } else { + enableFields(facilityField); + facilityField.setValue(null); + + CommunityReferenceDto community = (CommunityReferenceDto) communityFilter.getValue(); + if (community != null) { + FieldHelper.updateItems( + facilityField, + FacadeProvider.getFacilityFacade().getActiveFacilitiesByCommunityAndType(community, facilityType, true, false)); + } else if (currentDistrict != null) { + FieldHelper.updateItems( + facilityField, + FacadeProvider.getFacilityFacade().getActiveFacilitiesByDistrictAndType(currentDistrict, facilityType, true, false)); + } + } + } + break; + } + } + } + + @Override + protected void applyDependenciesOnNewValue(AefiCriteria criteria) { + + final UserDto user = currentUserDto(); + + UserProvider currentUserProvider = UserProvider.getCurrent(); + final JurisdictionLevel userJurisdictionLevel = currentUserProvider != null ? UserProvider.getCurrent().getJurisdictionLevel() : null; + + final ComboBox facilityTypeGroupField = getField(AefiCriteria.FACILITY_TYPE_GROUP); + final ComboBox facilityTypeField = getField(AefiCriteria.FACILITY_TYPE); + final ComboBox facilityField = getField(AefiCriteria.HEALTH_FACILITY); + + // Disable all fields + clearAndDisableFields(districtFilter, communityFilter, facilityTypeGroupField, facilityTypeField, facilityField); + + // Get initial field values according to user and criteria + final RegionReferenceDto region = user.getRegion() == null ? criteria.getRegion() : user.getRegion(); + final DistrictReferenceDto district = user.getDistrict() == null ? criteria.getDistrict() : user.getDistrict(); + final CommunityReferenceDto community = user.getCommunity() == null ? criteria.getCommunity() : user.getCommunity(); + final FacilityTypeGroup facilityTypeGroup = criteria.getFacilityTypeGroup(); + final FacilityType facilityType = criteria.getFacilityType(); + + // district + if (region != null) { + enableFields(districtFilter); + districtFilter.addItems(FacadeProvider.getDistrictFacade().getAllActiveByRegion(region.getUuid())); + // community + if (district != null) { + districtFilter.setValue(district); + communityFilter.addItems(FacadeProvider.getCommunityFacade().getAllActiveByDistrict(district.getUuid())); + enableFields(communityFilter); + if (community != null) { + communityFilter.setValue(community); + } + } else { + clearAndDisableFields(communityFilter); + } + } else { + clearAndDisableFields(districtFilter, communityFilter); + } + + // facility + if (userJurisdictionLevel == JurisdictionLevel.HEALTH_FACILITY) { + facilityField.setValue(user.getHealthFacility()); + disableFields(facilityTypeGroupField, facilityTypeField, facilityField); + } else if (facilityTypeGroupField != null && district != null) { + enableFields(facilityTypeGroupField); + FieldHelper.updateEnumData(facilityTypeGroupField, FacilityTypeGroup.getAccomodationGroups()); + if (facilityTypeGroup != null) { + facilityTypeGroupField.setValue(facilityTypeGroup); + enableFields(facilityTypeField); + FieldHelper.updateEnumData(facilityTypeField, FacilityType.getAccommodationTypes(facilityTypeGroup)); + if (facilityType != null) { + facilityTypeField.setValue(facilityType); + enableFields(facilityField); + if (community != null) { + facilityField + .addItems(FacadeProvider.getFacilityFacade().getActiveFacilitiesByCommunityAndType(community, facilityType, true, false)); + } else { + facilityField + .addItems(FacadeProvider.getFacilityFacade().getActiveFacilitiesByDistrictAndType(district, facilityType, true, false)); + } + } else { + disableFields(facilityField); + } + } else { + disableFields(facilityTypeField); + } + } + + // Disable fields according to user & jurisdiction + if (userJurisdictionLevel == JurisdictionLevel.DISTRICT) { + clearAndDisableFields(districtFilter); + } else if (userJurisdictionLevel == JurisdictionLevel.COMMUNITY) { + clearAndDisableFields(districtFilter, communityFilter); + } else if (userJurisdictionLevel == JurisdictionLevel.HEALTH_FACILITY) { + clearAndDisableFields(districtFilter, communityFilter, facilityTypeGroupField, facilityTypeField, facilityField); + } + + // Date/Epi week filter + HorizontalLayout dateFilterLayout = (HorizontalLayout) getMoreFiltersContainer().getComponent(WEEK_AND_DATE_FILTER); + @SuppressWarnings("unchecked") + EpiWeekAndDateFilterComponent weekAndDateFilter = + (EpiWeekAndDateFilterComponent) dateFilterLayout.getComponent(0); + + AefiDateType aefiDateType = criteria.getAefiDateType(); + weekAndDateFilter.getDateTypeSelector().setValue(aefiDateType); + weekAndDateFilter.getDateFilterOptionFilter().setValue(criteria.getDateFilterOption()); + Date dateFrom = criteria.getFromDate(); + Date dateTo = criteria.getToDate(); + + if (DateFilterOption.EPI_WEEK.equals(criteria.getDateFilterOption())) { + weekAndDateFilter.getWeekFromFilter().setValue(dateFrom == null ? null : DateHelper.getEpiWeek(dateFrom)); + weekAndDateFilter.getWeekToFilter().setValue(dateTo == null ? null : DateHelper.getEpiWeek(dateTo)); + } else { + weekAndDateFilter.getDateFromFilter().setValue(dateFrom); + weekAndDateFilter.getDateToFilter().setValue(dateTo); + } + } + + @Override + protected Stream streamFieldsForEmptyCheck(CustomLayout layout) { + HorizontalLayout dateFilterLayout = (HorizontalLayout) getMoreFiltersContainer().getComponent(WEEK_AND_DATE_FILTER); + EpiWeekAndDateFilterComponent weekAndDateFilter = + (EpiWeekAndDateFilterComponent) dateFilterLayout.getComponent(0); + + return super.streamFieldsForEmptyCheck(layout).filter(f -> f != weekAndDateFilter.getDateFilterOptionFilter()); + } + + private HorizontalLayout buildWeekAndDateFilter() { + + EpiWeekAndDateFilterComponent weekAndDateFilter = new EpiWeekAndDateFilterComponent<>( + false, + false, + null, + AefiDateType.values(), + I18nProperties.getString(Strings.promptAefiDateType), + null, + this); + weekAndDateFilter.getWeekFromFilter().setInputPrompt(I18nProperties.getString(Strings.promptAefiEpiWeekFrom)); + weekAndDateFilter.getWeekToFilter().setInputPrompt(I18nProperties.getString(Strings.promptAefiEpiWeekTo)); + weekAndDateFilter.getDateFromFilter().setInputPrompt(I18nProperties.getString(Strings.promptAefiDateFrom)); + weekAndDateFilter.getDateToFilter().setInputPrompt(I18nProperties.getString(Strings.promptAefiDateTo)); + + addApplyHandler(e -> onApplyClick(weekAndDateFilter)); + + HorizontalLayout dateFilterRowLayout = new HorizontalLayout(); + dateFilterRowLayout.setSpacing(true); + dateFilterRowLayout.setSizeUndefined(); + + dateFilterRowLayout.addComponent(weekAndDateFilter); + + return dateFilterRowLayout; + } + + private void onApplyClick(EpiWeekAndDateFilterComponent weekAndDateFilter) { + AefiCriteria criteria = getValue(); + + DateFilterOption dateFilterOption = (DateFilterOption) weekAndDateFilter.getDateFilterOptionFilter().getValue(); + Date fromDate, toDate; + if (dateFilterOption == DateFilterOption.DATE) { + Date dateFrom = weekAndDateFilter.getDateFromFilter().getValue(); + fromDate = dateFrom != null ? DateHelper.getStartOfDay(dateFrom) : null; + Date dateTo = weekAndDateFilter.getDateToFilter().getValue(); + toDate = dateFrom != null ? DateHelper.getEndOfDay(dateTo) : null; + } else { + fromDate = DateHelper.getEpiWeekStart((EpiWeek) weekAndDateFilter.getWeekFromFilter().getValue()); + toDate = DateHelper.getEpiWeekEnd((EpiWeek) weekAndDateFilter.getWeekToFilter().getValue()); + } + if ((fromDate != null && toDate != null) || (fromDate == null && toDate == null)) { + criteria.setDateFilterOption(dateFilterOption); + AefiDateType AefiDateType = (AefiDateType) weekAndDateFilter.getDateTypeSelector().getValue(); + criteria.setAefiDateType(AefiDateType); + criteria.setFromDate(fromDate); + criteria.setToDate(toDate); + } else { + weekAndDateFilter.setNotificationsForMissingFilters(); + } + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiFilterFormLayout.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiFilterFormLayout.java new file mode 100644 index 00000000000..801b80ae08c --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiFilterFormLayout.java @@ -0,0 +1,53 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.components.directory; + +import com.vaadin.ui.Button; +import com.vaadin.ui.VerticalLayout; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiCriteria; + +public class AefiFilterFormLayout extends VerticalLayout { + + private static final float PERCENTAGE_WIDTH = 100; + + private final AefiFilterForm filterForm; + + public AefiFilterFormLayout() { + setSpacing(false); + setMargin(false); + setWidth(PERCENTAGE_WIDTH, Unit.PERCENTAGE); + + filterForm = new AefiFilterForm(); + addComponent(filterForm); + } + + public AefiCriteria getValue() { + return filterForm.getValue(); + } + + public void setValue(AefiCriteria criteria) { + filterForm.setValue(criteria); + } + + public void addResetHandler(Button.ClickListener listener) { + filterForm.addResetHandler(listener); + } + + public void addApplyHandler(Button.ClickListener listener) { + filterForm.addApplyHandler(listener); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiGrid.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiGrid.java new file mode 100644 index 00000000000..8a27926187e --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiGrid.java @@ -0,0 +1,132 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.components.directory; + +import java.util.Date; + +import com.vaadin.ui.renderers.DateRenderer; +import com.vaadin.ui.renderers.TextRenderer; + +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiCriteria; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiIndexDto; +import de.symeda.sormas.api.caze.AgeAndBirthDateDto; +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.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; +import de.symeda.sormas.ui.utils.FilteredGrid; +import de.symeda.sormas.ui.utils.ShowDetailsListener; +import de.symeda.sormas.ui.utils.UuidRenderer; + +public class AefiGrid extends FilteredGrid { + + public AefiGrid(AefiCriteria criteria) { + super(AefiIndexDto.class); + setSizeFull(); + setLazyDataProvider(); + setCriteria(criteria); + + Column deleteColumn = addColumn(entry -> { + if (entry.getDeletionReason() != null) { + return entry.getDeletionReason() + (entry.getOtherDeletionReason() != null ? ": " + entry.getOtherDeletionReason() : ""); + } else { + return "-"; + } + }); + deleteColumn.setId(DELETE_REASON_COLUMN); + deleteColumn.setSortable(false); + deleteColumn.setCaption(I18nProperties.getCaption(Captions.deletionReason)); + + initColumns(); + + addItemClickListener(new ShowDetailsListener<>(AefiIndexDto.UUID, e -> ControllerProvider.getAefiController().navigateToAefi(e.getUuid()))); + addItemClickListener(new ShowDetailsListener<>(AefiIndexDto.IMMUNIZATION_UUID, e -> { + ControllerProvider.getImmunizationController().navigateToImmunization(e.getImmunizationUuid()); + })); + addItemClickListener(new ShowDetailsListener<>(AefiIndexDto.PERSON_UUID, e -> { + ControllerProvider.getImmunizationController().navigateToView(ImmunizationPersonView.VIEW_NAME, e.getImmunizationUuid()); + })); + } + + public void reload() { + getDataProvider().refreshAll(); + } + + private void initColumns() { + setColumns( + AefiIndexDto.UUID, + AefiIndexDto.IMMUNIZATION_UUID, + AefiIndexDto.PERSON_UUID, + AefiIndexDto.PERSON_FIRST_NAME, + AefiIndexDto.PERSON_LAST_NAME, + AefiIndexDto.DISEASE, + AefiIndexDto.AGE_AND_BIRTH_DATE, + AefiIndexDto.SEX, + AefiIndexDto.REGION, + AefiIndexDto.DISTRICT, + AefiIndexDto.SERIOUS, + AefiIndexDto.PRIMARY_VACCINE_NAME, + AefiIndexDto.OUTCOME, + AefiIndexDto.VACCINATION_DATE, + AefiIndexDto.REPORT_DATE, + AefiIndexDto.START_DATE_TIME, + AefiIndexDto.ADVERSE_EVENTS, + DELETE_REASON_COLUMN); + + ((Column) getColumn(AefiIndexDto.UUID)).setRenderer(new UuidRenderer()); + ((Column) getColumn(AefiIndexDto.IMMUNIZATION_UUID)).setRenderer(new UuidRenderer()); + ((Column) getColumn(AefiIndexDto.PERSON_UUID)).setRenderer(new UuidRenderer()); + + ((Column) getColumn(AefiIndexDto.AGE_AND_BIRTH_DATE)).setRenderer( + value -> value == null + ? "" + : PersonHelper.getAgeAndBirthdateString( + value.getAge(), + value.getAgeType(), + value.getDateOfBirthDD(), + value.getDateOfBirthMM(), + value.getDateOfBirthYYYY()), + new TextRenderer()); + + ((Column) getColumn(AefiIndexDto.VACCINATION_DATE)).setRenderer(new DateRenderer(DateFormatHelper.getDateFormat())); + ((Column) getColumn(AefiIndexDto.REPORT_DATE)).setRenderer(new DateRenderer(DateFormatHelper.getDateFormat())); + ((Column) getColumn(AefiIndexDto.START_DATE_TIME)).setRenderer(new DateRenderer(DateFormatHelper.getDateFormat())); + + for (Column column : getColumns()) { + column.setCaption(I18nProperties.findPrefixCaptionWithDefault(column.getId(), column.getCaption(), AefiIndexDto.I18N_PREFIX)); + column.setStyleGenerator(FieldAccessColumnStyleGenerator.getDefault(getBeanType(), column.getId())); + } + + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + getColumn(AefiIndexDto.REGION).setHidden(true); + getColumn(AefiIndexDto.DISTRICT).setHidden(true); + } + } + + private void setLazyDataProvider() { + + setLazyDataProvider(FacadeProvider.getAefiFacade()::getIndexList, FacadeProvider.getAefiFacade()::count); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiPrimarySuspectVaccinationSelectionField.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiPrimarySuspectVaccinationSelectionField.java new file mode 100644 index 00000000000..6f86f5792bc --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiPrimarySuspectVaccinationSelectionField.java @@ -0,0 +1,146 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.components.fields.vaccines; + +import java.util.List; +import java.util.function.Consumer; + +import com.vaadin.shared.ui.grid.HeightMode; +import com.vaadin.ui.Component; +import com.vaadin.ui.CustomField; +import com.vaadin.ui.Grid; +import com.vaadin.ui.VerticalLayout; + +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.caze.VaccineManufacturer; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.i18n.Strings; +import de.symeda.sormas.api.vaccination.VaccinationDto; +import de.symeda.sormas.ui.utils.CssStyles; +import de.symeda.sormas.ui.utils.DateFormatHelper; +import de.symeda.sormas.ui.utils.VaadinUiUtil; + +public class AefiPrimarySuspectVaccinationSelectionField extends CustomField { + + private VerticalLayout mainLayout; + private Grid vaccinationGrid; + private final String infoAefiSelectPrimarySuspectVaccine; + private Consumer selectionChangeCallback; + private List vaccinationDtoList; + private VaccinationDto primarySuspectVaccine; + + public AefiPrimarySuspectVaccinationSelectionField(List vaccinationDtoList, VaccinationDto primarySuspectVaccine) { + this.vaccinationDtoList = vaccinationDtoList; + this.primarySuspectVaccine = primarySuspectVaccine; + this.infoAefiSelectPrimarySuspectVaccine = I18nProperties.getString(Strings.infoAefiSelectPrimarySuspectVaccine); + + initializeGrid(); + } + + private void addInfoComponent() { + mainLayout.addComponent(VaadinUiUtil.createInfoComponent(infoAefiSelectPrimarySuspectVaccine)); + } + + public void initializeGrid() { + + vaccinationGrid = new Grid<>(); + vaccinationGrid.setSizeFull(); + vaccinationGrid.setSelectionMode(Grid.SelectionMode.SINGLE); + vaccinationGrid.setHeightByRows(5); + vaccinationGrid.setHeightMode(HeightMode.ROW); + + vaccinationGrid.setItems(vaccinationDtoList); + + if (primarySuspectVaccine != null) { + vaccinationGrid.select(primarySuspectVaccine); + } + + vaccinationGrid.addColumn(vaccinationDto -> DateFormatHelper.formatDate(vaccinationDto.getVaccinationDate())) + .setCaption(I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, VaccinationDto.VACCINATION_DATE)); + + vaccinationGrid + .addColumn( + vaccinationDto -> Vaccine.OTHER.equals(vaccinationDto.getVaccineName()) + ? vaccinationDto.getOtherVaccineName() + : vaccinationDto.getVaccineName()) + .setCaption(I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, VaccinationDto.VACCINE_NAME)); + + vaccinationGrid + .addColumn( + vaccinationDto -> VaccineManufacturer.OTHER.equals(vaccinationDto.getVaccineManufacturer()) + ? vaccinationDto.getOtherVaccineManufacturer() + : vaccinationDto.getVaccineManufacturer()) + .setCaption(I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, VaccinationDto.VACCINE_MANUFACTURER)); + + vaccinationGrid.addColumn(VaccinationDto::getVaccineType) + .setCaption(I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, VaccinationDto.VACCINE_TYPE)); + + vaccinationGrid.addColumn(VaccinationDto::getVaccineDose) + .setCaption(I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, VaccinationDto.VACCINE_DOSE)); + + vaccinationGrid.addSelectionListener(e -> { + + if (selectionChangeCallback != null) { + selectionChangeCallback.accept(!e.getAllSelectedItems().isEmpty()); + } + }); + } + + @Override + protected Component initContent() { + + mainLayout = new VerticalLayout(); + mainLayout.setSpacing(true); + mainLayout.setMargin(false); + mainLayout.setSizeUndefined(); + mainLayout.setWidth(100, Unit.PERCENTAGE); + CssStyles.style(mainLayout, CssStyles.VSPACE_2); + + addInfoComponent(); + + mainLayout.addComponent(vaccinationGrid); + + return mainLayout; + } + + @Override + protected void doSetValue(VaccinationDto vaccinationDto) { + if (vaccinationDto != null) { + vaccinationGrid.select(vaccinationDto); + } + } + + @Override + public VaccinationDto getValue() { + if (vaccinationGrid != null) { + VaccinationDto value = vaccinationGrid.getSelectedItems().stream().findFirst().orElse(null); + return value; + } + + return null; + } + + public void setSelectionChangeCallback(Consumer callback) { + this.selectionChangeCallback = callback; + } + + public Grid getVaccinationGrid() { + return vaccinationGrid; + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiVaccinationsField.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiVaccinationsField.java new file mode 100644 index 00000000000..03742120e3a --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiVaccinationsField.java @@ -0,0 +1,200 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.components.fields.vaccines; + +import java.util.function.Consumer; + +import org.apache.commons.lang3.StringUtils; + +import com.vaadin.icons.VaadinIcons; +import com.vaadin.shared.ui.ContentMode; +import com.vaadin.ui.Label; +import com.vaadin.v7.data.util.BeanItemContainer; +import com.vaadin.v7.ui.Table; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.i18n.Captions; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.utils.DateFormatHelper; +import de.symeda.sormas.api.utils.fieldaccess.UiFieldAccessCheckers; +import de.symeda.sormas.api.vaccination.VaccinationDto; +import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.caze.AbstractTableField; + +public class AefiVaccinationsField extends AbstractTableField { + + private AefiDto aefiDto; + private VaccinationDto primarySuspectVaccination; + private final UiFieldAccessCheckers fieldAccessCheckers; + + public AefiVaccinationsField(UiFieldAccessCheckers fieldAccessCheckers) { + super(fieldAccessCheckers); + this.fieldAccessCheckers = fieldAccessCheckers; + + updateAddButtonCaption(); + } + + @Override + public Class getEntryType() { + return VaccinationDto.class; + } + + @Override + protected void editEntry(VaccinationDto entry, boolean create, Consumer commitCallback) { + + if (create) { + ControllerProvider.getAefiController().selectPrimarySuspectVaccination(aefiDto, this::selectPrimarySuspectVaccination); + } + } + + public void updateAddButtonCaption() { + getAddButton().setCaption(I18nProperties.getCaption(Captions.actionAefiSelectPrimarySuspectVaccination)); + } + + /* + * @Override + * protected VaccinationDto createEntry() { + * UserDto user = UserProvider.getCurrent().getUser(); + * return VaccinationDto.build(user.toReference()); + * } + */ + + /* + * @Override + * protected Table createTable() { + * Table table = super.createTable(); + * table.addGeneratedColumn(VaccinationDto.UUID, (Table.ColumnGenerator) (source, itemId, columnId) -> { + * Label textField = new Label(DataHelper.getShortUuid(((EntityDto) itemId).getUuid())); + * return textField; + * }); + * table.addGeneratedColumn(VaccinationDto.VACCINATION_DATE, (Table.ColumnGenerator) (source, itemId, columnId) -> { + * Label textField = new Label(DateFormatHelper.formatDate(((VaccinationDto) itemId).getVaccinationDate())); + * return textField; + * }); + * return table; + * } + */ + + @Override + protected void updateColumns() { + Table table = getTable(); + + table.addGeneratedColumn(Captions.aefiVaccinationsPrimaryVaccine, (Table.ColumnGenerator) (source, itemId, columnId) -> { + VaccinationDto vaccinationDto = (VaccinationDto) itemId; + return new Label( + primarySuspectVaccination != null && StringUtils.equals(vaccinationDto.getUuid(), primarySuspectVaccination.getUuid()) + ? VaadinIcons.CHECK_CIRCLE.getHtml() + : "", + ContentMode.HTML); + }); + + table.addGeneratedColumn(Captions.aefiVaccinationsVaccineDetails, (Table.ColumnGenerator) (source, item, columnId) -> { + VaccinationDto vaccinationDto = (VaccinationDto) item; + + StringBuilder vaccineDetailsBuilder = new StringBuilder(); + vaccineDetailsBuilder.append(vaccinationDto.getVaccineManufacturer()); + vaccineDetailsBuilder.append(", ") + .append( + Vaccine.OTHER.equals(vaccinationDto.getVaccineName()) ? vaccinationDto.getOtherVaccineName() : vaccinationDto.getVaccineName()); + + if (vaccinationDto.getVaccinationDate() != null) { + vaccineDetailsBuilder.append(", ").append(DateFormatHelper.formatDate(vaccinationDto.getVaccinationDate())); + } + + if (!StringUtils.isBlank(vaccinationDto.getVaccineDose())) { + vaccineDetailsBuilder.append(", Dose ").append(vaccinationDto.getVaccineDose()); + } + + return vaccineDetailsBuilder.toString(); + }); + + table.addGeneratedColumn(Captions.aefiVaccinationsDiluentBatchLotNumber, (Table.ColumnGenerator) (source, item, columnId) -> { + VaccinationDto vaccinationDto = (VaccinationDto) item; + return "-"; + }); + + table.addGeneratedColumn(Captions.aefiVaccinationsDiluentExpiryDate, (Table.ColumnGenerator) (source, item, columnId) -> { + VaccinationDto vaccinationDto = (VaccinationDto) item; + return "-"; + }); + + table.addGeneratedColumn(Captions.aefiVaccinationsDiluentTimeOfReconstitution, (Table.ColumnGenerator) (source, item, columnId) -> { + VaccinationDto vaccinationDto = (VaccinationDto) item; + return "-"; + }); + + table.setVisibleColumns( + Captions.aefiVaccinationsPrimaryVaccine, + Captions.aefiVaccinationsVaccineDetails, + Captions.aefiVaccinationsDiluentBatchLotNumber, + Captions.aefiVaccinationsDiluentExpiryDate, + Captions.aefiVaccinationsDiluentTimeOfReconstitution); + + for (Object columnId : table.getVisibleColumns()) { + if (columnId.equals(ACTION_COLUMN_ID)) { + table.setColumnHeader(columnId, " "); + } else if (columnId.equals(Captions.aefiVaccinationsPrimaryVaccine)) { + table.setColumnHeader(columnId, I18nProperties.getCaption(Captions.aefiVaccinationsPrimaryVaccine)); + } else if (columnId.equals(Captions.aefiVaccinationsVaccineDetails)) { + table.setColumnHeader(columnId, I18nProperties.getCaption(Captions.aefiVaccinationsVaccineDetails)); + } else if (columnId.equals(Captions.aefiVaccinationsDiluentBatchLotNumber)) { + table.setColumnHeader(columnId, I18nProperties.getCaption(Captions.aefiVaccinationsDiluentBatchLotNumber)); + } else if (columnId.equals(Captions.aefiVaccinationsDiluentExpiryDate)) { + table.setColumnHeader(columnId, I18nProperties.getCaption(Captions.aefiVaccinationsDiluentExpiryDate)); + } else if (columnId.equals(Captions.aefiVaccinationsDiluentTimeOfReconstitution)) { + table.setColumnHeader(columnId, I18nProperties.getCaption(Captions.aefiVaccinationsDiluentTimeOfReconstitution)); + } else { + table.setColumnHeader(columnId, I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, (String) columnId)); + } + } + } + + public void refreshTable() { + Table table = getTable(); + + BeanItemContainer container = getContainer(); + if (container == null) { + return; + } + + container.removeAllItems(); + container.addAll(aefiDto.getVaccinations()); + table.refreshRowCache(); + } + + public void setAefiDto(AefiDto aefiDto) { + this.aefiDto = aefiDto; + } + + public void selectPrimarySuspectVaccination(VaccinationDto vaccinationDto) { + primarySuspectVaccination = vaccinationDto; + refreshTable(); + } + + @Override + protected boolean isEmpty(VaccinationDto entry) { + return false; + } + + @Override + protected boolean isModified(VaccinationDto oldEntry, VaccinationDto newEntry) { + return false; + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiVaccinationsField_2.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiVaccinationsField_2.java new file mode 100644 index 00000000000..659ae920839 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiVaccinationsField_2.java @@ -0,0 +1,198 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.components.fields.vaccines; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.vaadin.ui.Alignment; +import com.vaadin.ui.Button; +import com.vaadin.ui.Component; +import com.vaadin.ui.Grid; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.themes.ValoTheme; +import com.vaadin.v7.data.Property; +import com.vaadin.v7.data.util.converter.Converter; +import com.vaadin.v7.ui.CustomField; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.caze.VaccineManufacturer; +import de.symeda.sormas.api.i18n.Captions; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.utils.fieldaccess.UiFieldAccessCheckers; +import de.symeda.sormas.api.vaccination.VaccinationDto; +import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.utils.ButtonHelper; +import de.symeda.sormas.ui.utils.CssStyles; +import de.symeda.sormas.ui.utils.DateFormatHelper; + +@SuppressWarnings({ + "serial", + "rawtypes" }) +public class AefiVaccinationsField_2 extends CustomField { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private VerticalLayout mainLayout; + private Label captionLabel; + private Button addButton; + private Grid vaccinationGrid; + private List value = new ArrayList<>(); + private AefiDto aefiDto; + private VaccinationDto primarySuspectVaccination; + protected UiFieldAccessCheckers fieldAccessCheckers; + + public AefiVaccinationsField_2(UiFieldAccessCheckers fieldAccessCheckers) { + this.fieldAccessCheckers = fieldAccessCheckers; + + getContent(); + //setValue(value); + } + + public void initializeGrid() { + + vaccinationGrid = new Grid<>(); + vaccinationGrid.setSizeFull(); + vaccinationGrid.setSelectionMode(Grid.SelectionMode.SINGLE); + /* vaccinationGrid.setHeightMode(HeightMode.ROW); */ + + vaccinationGrid.addColumn(vaccinationDto -> DateFormatHelper.formatDate(vaccinationDto.getVaccinationDate())) + .setCaption(I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, VaccinationDto.VACCINATION_DATE)); + + vaccinationGrid + .addColumn( + vaccinationDto -> Vaccine.OTHER.equals(vaccinationDto.getVaccineName()) + ? vaccinationDto.getOtherVaccineName() + : vaccinationDto.getVaccineName()) + .setCaption(I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, VaccinationDto.VACCINE_NAME)); + + vaccinationGrid + .addColumn( + vaccinationDto -> VaccineManufacturer.OTHER.equals(vaccinationDto.getVaccineManufacturer()) + ? vaccinationDto.getOtherVaccineManufacturer() + : vaccinationDto.getVaccineManufacturer()) + .setCaption(I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, VaccinationDto.VACCINE_MANUFACTURER)); + + vaccinationGrid.addColumn(VaccinationDto::getVaccineType) + .setCaption(I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, VaccinationDto.VACCINE_TYPE)); + + vaccinationGrid.addColumn(VaccinationDto::getVaccineDose) + .setCaption(I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, VaccinationDto.VACCINE_DOSE)); + + vaccinationGrid.setStyleGenerator(vaccinationDto -> { + if (primarySuspectVaccination != null) { + return vaccinationDto.getUuid().equals(primarySuspectVaccination.getUuid()) ? CssStyles.GRID_ROW_SELECTED : null; + } + return null; + }); + } + + @Override + protected Component initContent() { + mainLayout = new VerticalLayout(); + mainLayout.setSpacing(false); + mainLayout.setMargin(false); + + HorizontalLayout headerLayout = new HorizontalLayout(); + { + headerLayout.setWidth(100, Unit.PERCENTAGE); + + captionLabel = new Label(getCaption()); + captionLabel.setSizeUndefined(); + headerLayout.addComponent(captionLabel); + headerLayout.setComponentAlignment(captionLabel, Alignment.BOTTOM_LEFT); + headerLayout.setExpandRatio(captionLabel, 0); + + addButton = ButtonHelper.createButton(Captions.actionAefiSelectPrimarySuspectVaccination, (event) -> { + ControllerProvider.getAefiController().selectPrimarySuspectVaccination(aefiDto, this::selectPrimarySuspectVaccination); + }, ValoTheme.BUTTON_LINK); + headerLayout.addComponent(addButton); + headerLayout.setComponentAlignment(addButton, Alignment.BOTTOM_RIGHT); + headerLayout.setExpandRatio(addButton, 1); + } + mainLayout.addComponent(headerLayout); + + initializeGrid(); + mainLayout.addComponent(vaccinationGrid); + + return mainLayout; + } + + @Override + public Class getType() { + return Collection.class; + } + + @Override + public void setPropertyDataSource(Property newDataSource) { + super.setPropertyDataSource(newDataSource); + } + + /* + * @Override + * protected void setValue(Collection newFieldValue, boolean repaintIsNotNeeded, boolean ignoreReadOnly) + * throws ReadOnlyException, Converter.ConversionException, Validator.InvalidValueException { + * super.setValue(newFieldValue, repaintIsNotNeeded, ignoreReadOnly); + * value = new ArrayList<>(newFieldValue); + * vaccinationGrid.setItems(newFieldValue); + * fireValueChange(repaintIsNotNeeded); + * } + */ + + @Override + public void setValue(Collection newFieldValue) throws ReadOnlyException, Converter.ConversionException { + value = new ArrayList<>(newFieldValue); + vaccinationGrid.setItems(newFieldValue); + + super.setValue(newFieldValue); + } + + /* + * @Override + * protected void doSetValue(Collection collection) { + * value = new ArrayList<>(collection); + * vaccinationGrid.setItems(collection); + * } + */ + + @Override + public Collection getValue() { + return value; + } + + public void setAefiDto(AefiDto aefiDto) { + this.aefiDto = aefiDto; + } + + public void setPrimarySuspectVaccination(VaccinationDto primarySuspectVaccination) { + this.primarySuspectVaccination = primarySuspectVaccination; + } + + public void selectPrimarySuspectVaccination(VaccinationDto vaccinationDto) { + primarySuspectVaccination = vaccinationDto; + vaccinationGrid.select(primarySuspectVaccination); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/AdverseEventsForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/AdverseEventsForm.java new file mode 100644 index 00000000000..4eade7d908a --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/AdverseEventsForm.java @@ -0,0 +1,149 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.components.form; + +import static de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto.ABSCESS; +import static de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto.ANAPHYLAXIS; +import static de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto.ENCEPHALOPATHY; +import static de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto.FEVERISH_FEELING; +import static de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto.I18N_PREFIX; +import static de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto.OTHER_ADVERSE_EVENT_DETAILS; +import static de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto.SEIZURES; +import static de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto.SEIZURE_TYPE; +import static de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto.SEPSIS; +import static de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto.SEVERE_LOCAL_REACTION; +import static de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto.SEVERE_LOCAL_REACTION_BEYOND_NEAREST_JOINT; +import static de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto.SEVERE_LOCAL_REACTION_MORE_THAN_THREE_DAYS; +import static de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto.THROMBOCYTOPENIA; +import static de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto.TOXIC_SHOCK_SYNDROME; +import static de.symeda.sormas.ui.utils.CssStyles.H3; +import static de.symeda.sormas.ui.utils.LayoutUtil.divCss; +import static de.symeda.sormas.ui.utils.LayoutUtil.fluidColumn; +import static de.symeda.sormas.ui.utils.LayoutUtil.fluidRow; +import static de.symeda.sormas.ui.utils.LayoutUtil.fluidRowLocs; +import static de.symeda.sormas.ui.utils.LayoutUtil.loc; +import static de.symeda.sormas.ui.utils.LayoutUtil.locs; + +import java.util.Arrays; + +import com.vaadin.ui.CustomLayout; +import com.vaadin.ui.Label; +import com.vaadin.v7.ui.CheckBox; +import com.vaadin.v7.ui.Field; +import com.vaadin.v7.ui.TextArea; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventState; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto; +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.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.FieldHelper; + +public class AdverseEventsForm extends AbstractEditForm { + + private static final long serialVersionUID = 5081846814610543073L; + + private static final String ADVERSE_EVENTS_HEADINGS_LOC = "adverseEventsHeadingLoc"; + private static final String EMPTY_LABEL_LOC = "emptyLabelLoc"; + + //@formatter:off + private static final String HTML_LAYOUT = + loc(ADVERSE_EVENTS_HEADINGS_LOC) + + fluidRow( + fluidColumn(6, 0, locs( + SEVERE_LOCAL_REACTION, SEIZURES, + ABSCESS, SEPSIS, ENCEPHALOPATHY, + TOXIC_SHOCK_SYNDROME, THROMBOCYTOPENIA, + ANAPHYLAXIS, FEVERISH_FEELING)), + fluidColumn(5, 0, + divCss(CssStyles.VSPACE_TOP_4, + fluidRowLocs(4, SEVERE_LOCAL_REACTION_MORE_THAN_THREE_DAYS, + 6, SEVERE_LOCAL_REACTION_BEYOND_NEAREST_JOINT, + 2, EMPTY_LABEL_LOC)) + + divCss(CssStyles.VSPACE_TOP_3, + fluidRowLocs(10, SEIZURE_TYPE))) + ) + + loc(OTHER_ADVERSE_EVENT_DETAILS); + //@formatter:on + + public AdverseEventsForm(FieldVisibilityCheckers fieldVisibilityCheckers, UiFieldAccessCheckers fieldAccessCheckers) { + super(AdverseEventsDto.class, I18N_PREFIX, true, fieldVisibilityCheckers, fieldAccessCheckers); + } + + @Override + protected String createHtmlLayout() { + return HTML_LAYOUT; + } + + @Override + protected void addFields() { + Label adverseEventsHeadingLabel = new Label(I18nProperties.getString(Strings.headingAefiAdverseEvents)); + adverseEventsHeadingLabel.addStyleName(H3); + getContent().addComponent(adverseEventsHeadingLabel, ADVERSE_EVENTS_HEADINGS_LOC); + + addFields( + SEVERE_LOCAL_REACTION, + SEIZURES, + ABSCESS, + SEPSIS, + ENCEPHALOPATHY, + TOXIC_SHOCK_SYNDROME, + THROMBOCYTOPENIA, + ANAPHYLAXIS, + FEVERISH_FEELING); + + addField(SEVERE_LOCAL_REACTION_MORE_THAN_THREE_DAYS, CheckBox.class); + addField(SEVERE_LOCAL_REACTION_BEYOND_NEAREST_JOINT, CheckBox.class); + + Label emptyLabel = new Label(""); + emptyLabel.addStyleName(H3); + getContent().addComponent(emptyLabel, EMPTY_LABEL_LOC); + + addField(SEIZURE_TYPE); + + TextArea otherAdverseEvents = addField(OTHER_ADVERSE_EVENT_DETAILS, TextArea.class); + otherAdverseEvents.setRows(6); + otherAdverseEvents.setDescription( + I18nProperties.getPrefixDescription(AdverseEventsDto.I18N_PREFIX, OTHER_ADVERSE_EVENT_DETAILS, "") + "\n" + + I18nProperties.getDescription(Descriptions.descGdpr)); + + initializeVisibilitiesAndAllowedVisibilities(); + initializeAccessAndAllowedAccesses(); + + FieldHelper.setVisibleWhen( + getFieldGroup(), + Arrays.asList(SEVERE_LOCAL_REACTION_MORE_THAN_THREE_DAYS, SEVERE_LOCAL_REACTION_BEYOND_NEAREST_JOINT), + SEVERE_LOCAL_REACTION, + Arrays.asList(AdverseEventState.YES), + true); + + FieldHelper.setVisibleWhen(getFieldGroup(), SEIZURE_TYPE, SEIZURES, Arrays.asList(AdverseEventState.YES), true); + } + + @Override + protected F addFieldToLayout(CustomLayout layout, String propertyId, F field) { + field.addValueChangeListener(e -> fireValueChange(false)); + + return super.addFieldToLayout(layout, propertyId, field); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/AefiDataForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/AefiDataForm.java new file mode 100644 index 00000000000..3bbd3e2e4c0 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/AefiDataForm.java @@ -0,0 +1,303 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.components.form; + +import static de.symeda.sormas.ui.utils.CssStyles.FORCE_CAPTION; +import static de.symeda.sormas.ui.utils.CssStyles.H3; +import static de.symeda.sormas.ui.utils.CssStyles.H4; +import static de.symeda.sormas.ui.utils.LayoutUtil.divCss; +import static de.symeda.sormas.ui.utils.LayoutUtil.fluidRow; +import static de.symeda.sormas.ui.utils.LayoutUtil.fluidRowLocs; +import static de.symeda.sormas.ui.utils.LayoutUtil.loc; + +import java.util.Arrays; +import java.util.function.Consumer; + +import com.vaadin.ui.Button; +import com.vaadin.ui.Label; +import com.vaadin.ui.themes.ValoTheme; +import com.vaadin.v7.data.util.converter.Converter; +import com.vaadin.v7.ui.ComboBox; +import com.vaadin.v7.ui.DateField; +import com.vaadin.v7.ui.PasswordField; +import com.vaadin.v7.ui.TextArea; +import com.vaadin.v7.ui.TextField; + +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiOutcome; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.SeriousAefiReason; +import de.symeda.sormas.api.i18n.Captions; +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.i18n.Validations; +import de.symeda.sormas.api.immunization.ImmunizationDto; +import de.symeda.sormas.api.utils.YesNoUnknown; +import de.symeda.sormas.api.utils.fieldaccess.UiFieldAccessCheckers; +import de.symeda.sormas.api.utils.fieldvisibility.FieldVisibilityCheckers; +import de.symeda.sormas.ui.UserProvider; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.fields.vaccines.AefiVaccinationsField; +import de.symeda.sormas.ui.utils.AbstractEditForm; +import de.symeda.sormas.ui.utils.ButtonHelper; +import de.symeda.sormas.ui.utils.CssStyles; +import de.symeda.sormas.ui.utils.DateTimeField; +import de.symeda.sormas.ui.utils.FieldHelper; +import de.symeda.sormas.ui.utils.NullableOptionGroup; +import de.symeda.sormas.ui.utils.UserField; + +@SuppressWarnings("deprecation") +public class AefiDataForm extends AbstractEditForm { + + private static final String ASSIGN_NEW_AEFI_ID_LOC = "assignNewAefiIdLoc"; + private static final String REPORTING_INFORMATION_HEADING_LOC = "reportingInformationHeadingLoc"; + private static final String PATIENTS_IDENTIFICATION_HEADING_LOC = "patientsIdentificationHeadingLoc"; + private static final String PATIENTS_IDENTIFICATION_AGE_AT_ONSET = "patientsIdentificationAgeAtOnsetHeadingLoc"; + private static final String VACCINATIONS_HEADING_LOC = "vaccinationsHeadingLoc"; + private static final String ADVERSE_EVENTS_HEADING_LOC = "adverseEventsHeadingLoc"; + private static final String FIRST_DECISION_LEVEL_HEADING_LOC = "firstDecisionLevelHeadingLoc"; + private static final String NATIONAL_DECISION_LEVEL_HEADING_LOC = "nationalDecisionLevelHeadingLoc"; + private static final String REPORTERS_INFORMATION_HEADING_LOC = "reportersInformationHeadingLoc"; + + //@formatter:off + private static final String HTML_LAYOUT = + divCss(CssStyles.VIEW_SECTION_MARGIN_TOP_4_MARGIN_X_4, + loc(REPORTING_INFORMATION_HEADING_LOC) + + fluidRowLocs(4, AefiDto.UUID, 3, AefiDto.REPORT_DATE, 3, AefiDto.REPORTING_USER, 2, "") + + fluidRowLocs(4, AefiDto.REPORTING_ID_NUMBER, 3, ASSIGN_NEW_AEFI_ID_LOC) + ) + + divCss(CssStyles.VIEW_SECTION_MARGIN_X_4 + " " + CssStyles.VSPACE_TOP_3, + loc(PATIENTS_IDENTIFICATION_HEADING_LOC) + + fluidRowLocs(AefiDto.PREGNANT, AefiDto.TRIMESTER, AefiDto.LACTATING) + + loc(PATIENTS_IDENTIFICATION_AGE_AT_ONSET) + + fluidRow( + fluidRowLocs(AefiDto.ONSET_AGE_YEARS, AefiDto.ONSET_AGE_MONTHS, AefiDto.ONSET_AGE_DAYS), + fluidRowLocs(6, AefiDto.AGE_GROUP) + ) + ) + + divCss(CssStyles.VIEW_SECTION_MARGIN_X_4 + " " + CssStyles.VSPACE_TOP_3, + loc(VACCINATIONS_HEADING_LOC) + + fluidRowLocs(AefiDto.VACCINATIONS) + ) + + divCss(CssStyles.VIEW_SECTION_MARGIN_X_4 + " " + CssStyles.VSPACE_TOP_3, + loc(ADVERSE_EVENTS_HEADING_LOC) + + fluidRowLocs(AefiDto.ADVERSE_EVENTS) + + fluidRowLocs(6, AefiDto.START_DATE_TIME) + + fluidRowLocs(AefiDto.AEFI_DESCRIPTION) + + fluidRowLocs(4, AefiDto.SERIOUS, 4, AefiDto.SERIOUS_REASON, 4, AefiDto.SERIOUS_REASON_DETAILS) + + fluidRowLocs(AefiDto.OUTCOME) + + fluidRowLocs(4, AefiDto.DEATH_DATE, 4, AefiDto.AUTOPSY_DONE) + + fluidRowLocs(AefiDto.PAST_MEDICAL_HISTORY) + ) + + divCss(CssStyles.VIEW_SECTION_MARGIN_X_4 + " " + CssStyles.VSPACE_TOP_3, + loc(FIRST_DECISION_LEVEL_HEADING_LOC) + + fluidRowLocs(4, AefiDto.INVESTIGATION_NEEDED, 4, AefiDto.INVESTIGATION_PLANNED_DATE) + ) + + divCss(CssStyles.VIEW_SECTION_MARGIN_X_4 + " " + CssStyles.VSPACE_2 + " " + CssStyles.VSPACE_TOP_3, + loc(NATIONAL_DECISION_LEVEL_HEADING_LOC) + + fluidRowLocs(4, AefiDto.RECEIVED_AT_NATIONAL_LEVEL_DATE, 4, AefiDto.WORLD_WIDE_ID) + + fluidRowLocs(AefiDto.NATIONAL_LEVEL_COMMENT) + ); + //@formatter:on + + private boolean isCreateAction; + private final Consumer actionCallback; + private AefiVaccinationsField vaccinationsField; + + public AefiDataForm(boolean isCreateAction, boolean isPseudonymized, boolean inJurisdiction, Consumer actionCallback) { + super( + AefiDto.class, + AefiDto.I18N_PREFIX, + false, + FieldVisibilityCheckers.withCountry(FacadeProvider.getConfigFacade().getCountryLocale()), + UiFieldAccessCheckers.forDataAccessLevel(UserProvider.getCurrent().getPseudonymizableDataAccessLevel(inJurisdiction), isPseudonymized)); + + this.isCreateAction = isCreateAction; + this.actionCallback = actionCallback; + + if (isCreateAction) { + hideValidationUntilNextCommit(); + } + + addFields(); + } + + @Override + protected String createHtmlLayout() { + return HTML_LAYOUT; + } + + @Override + protected void addFields() { + + Label reportingInformationHeadingLabel = new Label(I18nProperties.getString(Strings.headingAefiReportingInformation)); + reportingInformationHeadingLabel.addStyleName(H3); + getContent().addComponent(reportingInformationHeadingLabel, REPORTING_INFORMATION_HEADING_LOC); + + if (isCreateAction) { + addField(AefiDto.UUID, PasswordField.class); + } else { + addField(AefiDto.UUID); + } + addField(AefiDto.REPORT_DATE, DateField.class); + addField(ImmunizationDto.REPORTING_USER, UserField.class); + + TextField reportIdField = addField(AefiDto.REPORTING_ID_NUMBER, TextField.class); + /* + * reportIdField.setInvalidCommitted(true); + * reportIdField.setMaxLength(24); + * style(reportIdField, ERROR_COLOR_PRIMARY); + */ + + // Button to automatically assign a new reporting ID + Button assignNewReportingIdNumberButton = ButtonHelper.createButton(Captions.actionAefiAssignNewReportingIdNumber, e -> { + }, ValoTheme.BUTTON_DANGER, FORCE_CAPTION); + + getContent().addComponent(assignNewReportingIdNumberButton, ASSIGN_NEW_AEFI_ID_LOC); + assignNewReportingIdNumberButton.setVisible(false); + + Label patientsIdentificationHeadingLabel = new Label(I18nProperties.getString(Strings.headingAefiPatientsIdentification)); + patientsIdentificationHeadingLabel.addStyleName(H3); + getContent().addComponent(patientsIdentificationHeadingLabel, PATIENTS_IDENTIFICATION_HEADING_LOC); + + addField(AefiDto.PREGNANT, NullableOptionGroup.class); + addField(AefiDto.TRIMESTER, NullableOptionGroup.class); + addField(AefiDto.LACTATING, NullableOptionGroup.class); + + Label patientsAgeAtOnsetHeadingLabel = new Label(I18nProperties.getString(Strings.headingAefiPatientsAgeAtOnset)); + patientsAgeAtOnsetHeadingLabel.addStyleName(H4); + getContent().addComponent(patientsAgeAtOnsetHeadingLabel, PATIENTS_IDENTIFICATION_AGE_AT_ONSET); + + TextField onsetAgeYearsField = addField(AefiDto.ONSET_AGE_YEARS, TextField.class); + onsetAgeYearsField + .setConversionError(I18nProperties.getValidationError(Validations.onlyIntegerNumbersAllowed, onsetAgeYearsField.getCaption())); + + TextField onsetAgeMonthsField = addField(AefiDto.ONSET_AGE_MONTHS, TextField.class); + onsetAgeMonthsField + .setConversionError(I18nProperties.getValidationError(Validations.onlyIntegerNumbersAllowed, onsetAgeMonthsField.getCaption())); + + TextField onsetAgeDaysField = addField(AefiDto.ONSET_AGE_DAYS, TextField.class); + onsetAgeDaysField + .setConversionError(I18nProperties.getValidationError(Validations.onlyIntegerNumbersAllowed, onsetAgeDaysField.getCaption())); + + addField(AefiDto.AGE_GROUP, ComboBox.class); + + Label vaccinationsHeadingLabel = new Label(I18nProperties.getString(Strings.headingAefiVaccinations)); + vaccinationsHeadingLabel.addStyleName(H3); + getContent().addComponent(vaccinationsHeadingLabel, VACCINATIONS_HEADING_LOC); + + vaccinationsField = addField(AefiDto.VACCINATIONS, AefiVaccinationsField.class); + + addField(AefiDto.ADVERSE_EVENTS, AdverseEventsForm.class).setCaption(null); + + final DateTimeField startDateField = addField(AefiDto.START_DATE_TIME, DateTimeField.class); + startDateField.setInvalidCommitted(false); + + TextArea aefiDescriptionField = addField(AefiDto.AEFI_DESCRIPTION, TextArea.class); + aefiDescriptionField.setRows(6); + aefiDescriptionField.setDescription( + I18nProperties.getPrefixDescription(AefiDto.I18N_PREFIX, AefiDto.AEFI_DESCRIPTION, "") + "\n" + + I18nProperties.getDescription(Descriptions.descGdpr)); + + addField(AefiDto.SERIOUS, NullableOptionGroup.class); + addField(AefiDto.SERIOUS_REASON, ComboBox.class); + addField(AefiDto.SERIOUS_REASON_DETAILS, TextField.class); + addField(AefiDto.OUTCOME, NullableOptionGroup.class); + addField(AefiDto.DEATH_DATE, DateField.class); + addField(AefiDto.AUTOPSY_DONE, NullableOptionGroup.class); + + TextArea pastMedicalHistoryField = addField(AefiDto.PAST_MEDICAL_HISTORY, TextArea.class); + pastMedicalHistoryField.setRows(6); + pastMedicalHistoryField.setDescription( + I18nProperties.getPrefixDescription(AefiDto.I18N_PREFIX, AefiDto.PAST_MEDICAL_HISTORY, "") + "\n" + + I18nProperties.getDescription(Descriptions.descGdpr)); + + Label firstDecisionLevelHeadingLabel = new Label(I18nProperties.getString(Strings.headingAefiFirstDecisionLevel)); + firstDecisionLevelHeadingLabel.addStyleName(H3); + getContent().addComponent(firstDecisionLevelHeadingLabel, FIRST_DECISION_LEVEL_HEADING_LOC); + + addField(AefiDto.INVESTIGATION_NEEDED, NullableOptionGroup.class); + addField(AefiDto.INVESTIGATION_PLANNED_DATE, DateField.class); + + Label nationalDecisionLevelHeadingLabel = new Label(I18nProperties.getString(Strings.headingAefiNationalDecisionLevel)); + nationalDecisionLevelHeadingLabel.addStyleName(H3); + getContent().addComponent(nationalDecisionLevelHeadingLabel, NATIONAL_DECISION_LEVEL_HEADING_LOC); + + addField(AefiDto.RECEIVED_AT_NATIONAL_LEVEL_DATE, DateField.class); + addField(AefiDto.WORLD_WIDE_ID, TextField.class); + + TextArea nationalLevelCommentField = addField(AefiDto.NATIONAL_LEVEL_COMMENT, TextArea.class); + nationalLevelCommentField.setRows(6); + nationalLevelCommentField.setDescription( + I18nProperties.getPrefixDescription(AefiDto.I18N_PREFIX, AefiDto.NATIONAL_LEVEL_COMMENT, "") + "\n" + + I18nProperties.getDescription(Descriptions.descGdpr)); + + //set visibility, read only and required status + FieldHelper.setVisibleWhen(getFieldGroup(), AefiDto.TRIMESTER, AefiDto.PREGNANT, Arrays.asList(YesNoUnknown.YES), true); + FieldHelper.setVisibleWhen(getFieldGroup(), AefiDto.SERIOUS_REASON, AefiDto.SERIOUS, Arrays.asList(YesNoUnknown.YES), true); + FieldHelper + .setVisibleWhen(getFieldGroup(), AefiDto.SERIOUS_REASON_DETAILS, AefiDto.SERIOUS_REASON, Arrays.asList(SeriousAefiReason.OTHER), true); + FieldHelper.setVisibleWhen( + getFieldGroup(), + Arrays.asList(AefiDto.DEATH_DATE, AefiDto.AUTOPSY_DONE), + AefiDto.OUTCOME, + Arrays.asList(AefiOutcome.DIED), + true); + FieldHelper + .setVisibleWhen(getFieldGroup(), AefiDto.INVESTIGATION_PLANNED_DATE, AefiDto.INVESTIGATION_NEEDED, Arrays.asList(YesNoUnknown.YES), true); + + setReadOnly(true, AefiDto.UUID, AefiDto.REPORTING_USER); + + setRequired(true, AefiDto.REPORT_DATE, AefiDto.REPORTING_ID_NUMBER, AefiDto.SERIOUS, AefiDto.OUTCOME); + FieldHelper.setRequiredWhen(getFieldGroup(), AefiDto.SERIOUS_REASON, Arrays.asList(AefiDto.SERIOUS_REASON), Arrays.asList(YesNoUnknown.YES)); + } + + @Override + public void attach() { + super.attach(); + + vaccinationsField.setAefiDto(getValue()); + if (getValue().getPrimarySuspectVaccine() != null) { + vaccinationsField.selectPrimarySuspectVaccination(getValue().getPrimarySuspectVaccine()); + } + } + + /* + * @Override + * public AefiDto getValue() { + * return super.getValue(); + * } + */ + + @Override + public void setValue(AefiDto newFieldValue) throws ReadOnlyException, Converter.ConversionException { + super.setValue(newFieldValue); + + getValue(); + + // 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(); + } + + @Override + public void discard() throws SourceException { + super.discard(); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/information/AefiImmunizationInfo.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/information/AefiImmunizationInfo.java new file mode 100644 index 00000000000..94341c9e0bd --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/information/AefiImmunizationInfo.java @@ -0,0 +1,109 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.components.information; + +import java.util.function.Consumer; + +import com.vaadin.ui.Alignment; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; + +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.i18n.Strings; +import de.symeda.sormas.api.immunization.ImmunizationDto; +import de.symeda.sormas.api.immunization.ImmunizationListEntryDto; +import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.ui.utils.CssStyles; +import de.symeda.sormas.ui.utils.DateFormatHelper; +import de.symeda.sormas.ui.utils.components.sidecomponent.SideComponent; + +public class AefiImmunizationInfo extends SideComponent { + + public static final String SEPARATOR = ": "; + + private ImmunizationDto immunization; + private final VerticalLayout mainLayout; + + public AefiImmunizationInfo(ImmunizationDto immunization, Consumer actionCallback) { + super(I18nProperties.getString(Strings.entityImmunization), actionCallback); + + this.immunization = immunization; + mainLayout = new VerticalLayout(); + mainLayout.setWidth(100, Unit.PERCENTAGE); + mainLayout.setMargin(false); + mainLayout.setSpacing(false); + + buildMainLayout(); + addComponent(mainLayout); + } + + public void buildMainLayout() { + + HorizontalLayout uuidReportLayout = new HorizontalLayout(); + uuidReportLayout.setMargin(false); + uuidReportLayout.setSpacing(true); + + Label immunizationUuidLabel = new Label(DataHelper.getShortUuid(immunization.getUuid())); + immunizationUuidLabel.setDescription(immunization.getUuid()); + CssStyles.style(immunizationUuidLabel, CssStyles.LABEL_BOLD, CssStyles.LABEL_UPPERCASE); + uuidReportLayout.addComponent(immunizationUuidLabel); + + Label diseaseLabel = new Label(DataHelper.toStringNullable(immunization.getDisease())); + CssStyles.style(diseaseLabel, CssStyles.LABEL_BOLD, CssStyles.LABEL_UPPERCASE); + uuidReportLayout.addComponent(diseaseLabel); + + uuidReportLayout.setWidthFull(); + uuidReportLayout.setComponentAlignment(immunizationUuidLabel, Alignment.MIDDLE_LEFT); + uuidReportLayout.setComponentAlignment(diseaseLabel, Alignment.MIDDLE_RIGHT); + mainLayout.addComponent(uuidReportLayout); + + HorizontalLayout meansOfImmunizationLayout = new HorizontalLayout(); + Label meansOfImmunizationLabel = new Label( + I18nProperties.getPrefixCaption(ImmunizationListEntryDto.I18N_PREFIX, ImmunizationListEntryDto.MEANS_OF_IMMUNIZATION) + + SEPARATOR + + DataHelper.toStringNullable(immunization.getMeansOfImmunization())); + meansOfImmunizationLayout.addComponent(meansOfImmunizationLabel); + mainLayout.addComponent(meansOfImmunizationLayout); + + HorizontalLayout immunizationStatusLayout = new HorizontalLayout(); + Label immunizationStatusLabel = new Label( + I18nProperties.getPrefixCaption(ImmunizationListEntryDto.I18N_PREFIX, ImmunizationListEntryDto.IMMUNIZATION_STATUS) + + SEPARATOR + + DataHelper.toStringNullable(immunization.getImmunizationStatus())); + immunizationStatusLayout.addComponent(immunizationStatusLabel); + mainLayout.addComponent(immunizationStatusLayout); + + HorizontalLayout managementStatusLayout = new HorizontalLayout(); + Label managementStatusLabel = new Label( + I18nProperties.getPrefixCaption(ImmunizationListEntryDto.I18N_PREFIX, ImmunizationListEntryDto.IMMUNIZATION_MANAGEMENT_STATUS) + + SEPARATOR + + DataHelper.toStringNullable(immunization.getImmunizationManagementStatus())); + managementStatusLayout.addComponent(managementStatusLabel); + mainLayout.addComponent(managementStatusLayout); + + HorizontalLayout immunizationPeriodLayout = new HorizontalLayout(); + Label reportDateLabel = new Label( + I18nProperties.getPrefixCaption(ImmunizationListEntryDto.I18N_PREFIX, ImmunizationListEntryDto.IMMUNIZATION_PERIOD) + + SEPARATOR + + DateFormatHelper.buildPeriodString(immunization.getStartDate(), immunization.getEndDate())); + immunizationPeriodLayout.addComponent(reportDateLabel); + mainLayout.addComponent(immunizationPeriodLayout); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/information/AefiPersonInfo.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/information/AefiPersonInfo.java new file mode 100644 index 00000000000..3f378ccf0b0 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/information/AefiPersonInfo.java @@ -0,0 +1,142 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.components.information; + +import com.vaadin.server.Sizeable; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.i18n.Strings; +import de.symeda.sormas.api.immunization.ImmunizationDto; +import de.symeda.sormas.api.person.ApproximateAgeType; +import de.symeda.sormas.api.person.PersonDto; +import de.symeda.sormas.api.user.UserRight; +import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.api.utils.fieldaccess.UiFieldAccessCheckers; +import de.symeda.sormas.ui.AbstractInfoLayout; +import de.symeda.sormas.ui.UserProvider; +import de.symeda.sormas.ui.utils.CssStyles; + +@SuppressWarnings("serial") +public class AefiPersonInfo extends AbstractInfoLayout { + + public static final String PERSON_FULL_NAME = "personFullName"; + public static final String DISEASE = "disease"; + + private PersonDto personDto; + private Disease disease; + + public AefiPersonInfo(PersonDto personDto, Disease disease) { + super( + PersonDto.class, + UiFieldAccessCheckers.forDataAccessLevel( + UserProvider.getCurrent().getPseudonymizableDataAccessLevel(personDto.isInJurisdiction()), + personDto.isPseudonymized())); + + this.personDto = personDto; + this.disease = disease; + + setSpacing(true); + setMargin(false); + setWidth(100, Unit.PERCENTAGE); + updatePersonInfo(); + } + + private void updatePersonInfo() { + + this.removeAllComponents(); + + VerticalLayout mainLayout = new VerticalLayout(); + mainLayout.setWidth(100, Sizeable.Unit.PERCENTAGE); + CssStyles.style(mainLayout, CssStyles.PADDING_NONE); + + HorizontalLayout componentHeader = new HorizontalLayout(); + componentHeader.setMargin(false); + componentHeader.setSpacing(false); + componentHeader.setWidth(100, Sizeable.Unit.PERCENTAGE); + + Label headingLabel = new Label(I18nProperties.getString(Strings.headingPersonInformation)); + headingLabel.addStyleName(CssStyles.H3); + componentHeader.addComponent(headingLabel); + componentHeader.setExpandRatio(headingLabel, 1); + + HorizontalLayout infoColumnsLayout = new HorizontalLayout(); + infoColumnsLayout.setMargin(false); + infoColumnsLayout.setSpacing(false); + infoColumnsLayout.setWidth(100, Sizeable.Unit.PERCENTAGE); + + VerticalLayout leftColumnLayout = new VerticalLayout(); + leftColumnLayout.setMargin(false); + leftColumnLayout.setSpacing(true); + boolean hasUserRightPersonView = UserProvider.getCurrent().hasUserRight(UserRight.PERSON_VIEW); + { + final Label personIdLabel = addDescLabel( + leftColumnLayout, + PersonDto.UUID, + DataHelper.getShortUuid(personDto.getUuid()), + I18nProperties.getPrefixCaption(PersonDto.I18N_PREFIX, PersonDto.UUID)); + personIdLabel.setId("personIdLabel"); + personIdLabel.setDescription(personDto.getUuid()); + + if (hasUserRightPersonView) { + addDescLabel(leftColumnLayout, PersonDto.LAST_NAME, personDto.buildCaption(), I18nProperties.getCaption(PERSON_FULL_NAME)); + + HorizontalLayout ageSexLayout = new HorizontalLayout(); + ageSexLayout.setMargin(false); + ageSexLayout.setSpacing(true); + addCustomDescLabel( + ageSexLayout, + PersonDto.class, + PersonDto.APPROXIMATE_AGE, + ApproximateAgeType.ApproximateAgeHelper.formatApproximateAge(personDto.getApproximateAge(), personDto.getApproximateAgeType()), + I18nProperties.getPrefixCaption(PersonDto.I18N_PREFIX, PersonDto.APPROXIMATE_AGE)); + addCustomDescLabel( + ageSexLayout, + PersonDto.class, + PersonDto.SEX, + personDto.getSex(), + I18nProperties.getPrefixCaption(PersonDto.I18N_PREFIX, PersonDto.SEX)); + leftColumnLayout.addComponent(ageSexLayout); + } + } + infoColumnsLayout.addComponent(leftColumnLayout); + + VerticalLayout rightColumnLayout = new VerticalLayout(); + rightColumnLayout.setMargin(false); + rightColumnLayout.setSpacing(true); + { + addDescLabel(rightColumnLayout, DISEASE, disease, I18nProperties.getPrefixCaption(ImmunizationDto.I18N_PREFIX, ImmunizationDto.DISEASE)); + + addDescLabel( + rightColumnLayout, + PersonDto.PHONE, + personDto.getPhone(), + I18nProperties.getPrefixCaption(PersonDto.I18N_PREFIX, PersonDto.PHONE)); + } + infoColumnsLayout.addComponent(rightColumnLayout); + + mainLayout.addComponent(componentHeader); + mainLayout.addComponent(infoColumnsLayout); + + this.addComponent(mainLayout); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/AbstractDashboardView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/AbstractDashboardView.java index 2dc0fdf58b1..aec6e9ecf83 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/AbstractDashboardView.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/AbstractDashboardView.java @@ -29,6 +29,7 @@ import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.user.UserRight; import de.symeda.sormas.ui.SormasUI; +import de.symeda.sormas.ui.dashboard.adverseeventsfollowingimmunization.AefiDashboardView; import de.symeda.sormas.ui.dashboard.campaigns.CampaignDashboardView; import de.symeda.sormas.ui.dashboard.contacts.ContactsDashboardView; import de.symeda.sormas.ui.dashboard.sample.SampleDashboardView; @@ -66,6 +67,11 @@ protected AbstractDashboardView(String viewName) { dashboardSwitcher.setItemCaption(DashboardType.SAMPLES, I18nProperties.getEnumCaption(DashboardType.SAMPLES)); } + if (permitted(FeatureType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_MANAGEMENT, UserRight.DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW)) { + dashboardSwitcher.addItem(DashboardType.ADVERSE_EVENTS); + dashboardSwitcher.setItemCaption(DashboardType.ADVERSE_EVENTS, I18nProperties.getEnumCaption(DashboardType.ADVERSE_EVENTS)); + } + if (permitted(FeatureType.CAMPAIGNS, UserRight.DASHBOARD_CAMPAIGNS_VIEW)) { dashboardSwitcher.addItem(DashboardType.CAMPAIGNS); dashboardSwitcher.setItemCaption(DashboardType.CAMPAIGNS, I18nProperties.getEnumCaption(DashboardType.CAMPAIGNS)); @@ -96,6 +102,8 @@ protected void navigateToDashboardView(Property.ValueChangeEvent e) { SormasUI.get().getNavigator().navigateTo(ContactsDashboardView.VIEW_NAME); } else if (DashboardType.SAMPLES.equals(e.getProperty().getValue())) { SormasUI.get().getNavigator().navigateTo(SampleDashboardView.VIEW_NAME); + } else if (DashboardType.ADVERSE_EVENTS.equals(e.getProperty().getValue())) { + SormasUI.get().getNavigator().navigateTo(AefiDashboardView.VIEW_NAME); } else { SormasUI.get().getNavigator().navigateTo(CampaignDashboardView.VIEW_NAME); } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/DashboardController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/DashboardController.java index d65f29e12a0..d8a6414fbd7 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/DashboardController.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/DashboardController.java @@ -23,6 +23,7 @@ import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.user.UserRight; +import de.symeda.sormas.ui.dashboard.adverseeventsfollowingimmunization.AefiDashboardView; import de.symeda.sormas.ui.dashboard.campaigns.CampaignDashboardView; import de.symeda.sormas.ui.dashboard.contacts.ContactsDashboardView; import de.symeda.sormas.ui.dashboard.sample.SampleDashboardView; @@ -48,5 +49,9 @@ public void registerViews(Navigator navigator) { if (permitted(FeatureType.SAMPLES_LAB, UserRight.DASHBOARD_SAMPLES_VIEW)) { navigator.addView(SampleDashboardView.VIEW_NAME, SampleDashboardView.class); } + + if (permitted(FeatureType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_MANAGEMENT, UserRight.DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW)) { + navigator.addView(AefiDashboardView.VIEW_NAME, AefiDashboardView.class); + } } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/DashboardType.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/DashboardType.java index 245918b091d..d1325b7ccb7 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/DashboardType.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/DashboardType.java @@ -24,7 +24,8 @@ public enum DashboardType { SURVEILLANCE, CONTACTS, CAMPAIGNS, - SAMPLES; + SAMPLES, + ADVERSE_EVENTS; @Override public String toString() { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardDataProvider.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardDataProvider.java new file mode 100644 index 00000000000..fb6a77afc5a --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardDataProvider.java @@ -0,0 +1,81 @@ +/* + * 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.ui.dashboard.adverseeventsfollowingimmunization; + +import java.util.Map; + +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDashboardFilterDateType; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.dashboard.AefiDashboardCriteria; +import de.symeda.sormas.api.dashboard.adverseeventsfollowingimmunization.AefiChartData; +import de.symeda.sormas.ui.dashboard.AbstractDashboardDataProvider; + +public class AefiDashboardDataProvider extends AbstractDashboardDataProvider { + + private AefiDashboardFilterDateType dateType = AefiDashboardFilterDateType.REPORT_DATE; + + private Map aefiCountsByType; + private Map> aefiCountsByVaccine; + private AefiChartData aefiByVaccineDoseChartData; + private AefiChartData aefiEventsByGenderChartData; + + @Override + public void refreshData() { + aefiCountsByType = FacadeProvider.getAefiDashboardFacade().getAefiCountsByType(buildDashboardCriteriaWithDates()); + aefiCountsByVaccine = FacadeProvider.getAefiDashboardFacade().getAefiCountsByVaccine(buildDashboardCriteriaWithDates()); + aefiByVaccineDoseChartData = FacadeProvider.getAefiDashboardFacade().getAefiByVaccineDoseChartData(buildDashboardCriteriaWithDates()); + aefiEventsByGenderChartData = FacadeProvider.getAefiDashboardFacade().getAefiEventsByGenderChartData(buildDashboardCriteriaWithDates()); + } + + @Override + protected AefiDashboardCriteria newCriteria() { + return new AefiDashboardCriteria(); + } + + @Override + protected AefiDashboardCriteria buildDashboardCriteria() { + return super.buildDashboardCriteria().aefiDashboardDateType(dateType); + } + + public AefiDashboardFilterDateType getDateType() { + return dateType; + } + + public void setDateType(AefiDashboardFilterDateType dateType) { + this.dateType = dateType; + } + + public Map getAefiCountsByType() { + return aefiCountsByType; + } + + public Map> getAefiCountsByVaccine() { + return aefiCountsByVaccine; + } + + public AefiChartData getAefiByVaccineDoseChartData() { + return aefiByVaccineDoseChartData; + } + + public AefiChartData getAefiEventsByGenderChartData() { + return aefiEventsByGenderChartData; + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardFilterLayout.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardFilterLayout.java new file mode 100644 index 00000000000..0c4df88ccf6 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardFilterLayout.java @@ -0,0 +1,112 @@ +/* + * 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.ui.dashboard.adverseeventsfollowingimmunization; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.vaadin.v7.ui.ComboBox; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDashboardFilterDateType; +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.ui.dashboard.components.DashboardFilterLayout; +import de.symeda.sormas.ui.utils.ComboBoxHelper; +import de.symeda.sormas.ui.utils.components.datetypeselector.DateTypeSelectorComponent; + +public class AefiDashboardFilterLayout extends DashboardFilterLayout { + + public static final String DATE_TYPE_FILTER = "dateTypeFilter"; + public static final String DISEASE_FILTER = "diseaseFilter"; + + private final static String[] FILTERS = new String[] { + DATE_TYPE_FILTER, + REGION_FILTER, + DISTRICT_FILTER, + DISEASE_FILTER }; + + public AefiDashboardFilterLayout(AefiDashboardView dashboardView, AefiDashboardDataProvider dashboardDataProvider) { + super(dashboardView, dashboardDataProvider, FILTERS); + } + + @Override + public void populateLayout() { + super.populateLayout(); + + createDateTypeSelector(); + createRegionFilter(I18nProperties.getDescription(Descriptions.aefiDashboardRegionFilter)); + createDistrictFilter(I18nProperties.getDescription(Descriptions.aefiDashboardDistrictFilter)); + createDiseaseFilter(); + } + + private void createDateTypeSelector() { + @SuppressWarnings("unchecked") + DateTypeSelectorComponent dateTypeSelectorComponent = new DateTypeSelectorComponent.Builder<>(AefiDashboardFilterDateType.class) + .dateTypePrompt(I18nProperties.getString(Strings.promptAefiDashboardFilterDateType)) + .defaultDateType(dashboardDataProvider.getDateType()) + .build(); + + dateTypeSelectorComponent.addValueChangeListener(e -> { + dashboardDataProvider.setDateType((AefiDashboardFilterDateType) e.getProperty().getValue()); + }); + + addCustomComponent(dateTypeSelectorComponent, DATE_TYPE_FILTER); + } + + private void createDiseaseFilter() { + ComboBox diseaseFilter = ComboBoxHelper.createComboBoxV7(); + diseaseFilter.setWidth(200, Unit.PIXELS); + diseaseFilter.setInputPrompt(I18nProperties.getString(Strings.promptDisease)); + diseaseFilter.setDescription(I18nProperties.getDescription(Descriptions.aefiDashboardDiseaseFilter)); + List availableDisease = FacadeProvider.getDiseaseConfigurationFacade().getAllDiseasesWithFollowUp(true, true, true); + + diseaseFilter + .addItems(Stream.concat(availableDisease.stream(), Stream.of(AefiDashboardCustomDiseaseFilter.values())).collect(Collectors.toList())); + diseaseFilter.setValue(dashboardDataProvider.getDisease()); + + diseaseFilter.addValueChangeListener(e -> { + Object filterValue = diseaseFilter.getValue(); + if (filterValue instanceof Disease) { + dashboardDataProvider.setDisease((Disease) filterValue); + } else if (filterValue == AefiDashboardCustomDiseaseFilter.NO_DISEASE) { + dashboardDataProvider.setDisease(null); + } else if (filterValue == null) { + dashboardDataProvider.setDisease(null); + } else { + throw new RuntimeException("Disease filter [" + filterValue + "] not handled!"); + } + }); + + addCustomComponent(diseaseFilter, DISEASE_FILTER); + } + + enum AefiDashboardCustomDiseaseFilter { + + NO_DISEASE; + + @Override + public String toString() { + return I18nProperties.getEnumCaptionShort(this); + } + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardView.java new file mode 100644 index 00000000000..15bc987c333 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardView.java @@ -0,0 +1,230 @@ +/* + * 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.ui.dashboard.adverseeventsfollowingimmunization; + +import static de.symeda.sormas.ui.utils.LayoutUtil.fluidColumn; +import static de.symeda.sormas.ui.utils.LayoutUtil.fluidColumnLoc; +import static de.symeda.sormas.ui.utils.LayoutUtil.fluidRowCss; +import static de.symeda.sormas.ui.utils.LayoutUtil.locCss; + +import com.vaadin.ui.Component; +import com.vaadin.ui.CustomLayout; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.VerticalLayout; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; +import de.symeda.sormas.api.i18n.Captions; +import de.symeda.sormas.ui.dashboard.AbstractDashboardView; +import de.symeda.sormas.ui.dashboard.DashboardCssStyles; +import de.symeda.sormas.ui.dashboard.DashboardType; +import de.symeda.sormas.ui.dashboard.adverseeventsfollowingimmunization.components.AefiByVaccineDoseChart; +import de.symeda.sormas.ui.dashboard.adverseeventsfollowingimmunization.components.AefiCountTilesComponent; +import de.symeda.sormas.ui.dashboard.adverseeventsfollowingimmunization.components.AefiDashboardMapComponent; +import de.symeda.sormas.ui.dashboard.adverseeventsfollowingimmunization.components.AefiReactionsByGenderChart; +import de.symeda.sormas.ui.dashboard.adverseeventsfollowingimmunization.components.AefiTypeStatisticsGroupComponent; +import de.symeda.sormas.ui.dashboard.components.DashboardHeadingComponent; +import de.symeda.sormas.ui.utils.CssStyles; + +public class AefiDashboardView extends AbstractDashboardView { + + public static final String VIEW_NAME = ROOT_VIEW_NAME + "/adverseevents"; + + private static final int EPI_CURVE_AND_MAP_HEIGHT = 555; + + private static final String HEADING_LOC = "headingLoc"; + private static final String AEFI_TYPE_LOC = "aefiTypeLoc"; + private static final String VACCINES_LOC = "vaccinesLoc"; + private static final String VACCINE_DOSE_LOC = "vaccineDoseLoc"; + private static final String REACTIONS_LOC = "reactionsLoc"; + + private final AefiDashboardDataProvider dataProvider; + + private final CustomLayout aefiCountsLayout; + private final HorizontalLayout epiCurveAndMapLayout; + private final VerticalLayout epiCurveLayout; + private final VerticalLayout mapLayout; + + private final DashboardHeadingComponent heading; + private final AefiCountTilesComponent aefiCountsByType; + private final AefiTypeStatisticsGroupComponent aefiCountsByVaccine; + private final AefiByVaccineDoseChart vaccineDoseChart; + private final AefiReactionsByGenderChart reactionsByGenderChart; + private final AefiEpiCurveComponent epiCurveComponent; + private final AefiDashboardMapComponent mapComponent; + + public AefiDashboardView() { + super(VIEW_NAME); + + CssStyles.style(getViewTitleLabel(), CssStyles.PAGE_TITLE); + + dashboardSwitcher.setValue(DashboardType.ADVERSE_EVENTS); + dashboardSwitcher.addValueChangeListener(this::navigateToDashboardView); + + dashboardLayout.setHeightUndefined(); + + dataProvider = new AefiDashboardDataProvider(); + AefiDashboardFilterLayout filterLayout = new AefiDashboardFilterLayout(this, dataProvider); + + dashboardLayout.addComponent(filterLayout); + dashboardLayout.setExpandRatio(filterLayout, 0); + + aefiCountsLayout = new CustomLayout(); + //@formatter:off + aefiCountsLayout.setTemplateContents( + fluidRowCss( + CssStyles.PADDING_X_20 + " " + CssStyles.VSPACE_TOP_2, + fluidColumn(6, 0, locCss("", HEADING_LOC)), + fluidColumn(4, 0, locCss("", AEFI_TYPE_LOC)) + ) + + fluidRowCss( + CssStyles.VSPACE_TOP_2, + fluidColumnLoc(12, 0, 12, 0, VACCINES_LOC) + ) + + fluidRowCss( + CssStyles.PADDING_X_20 + " " + CssStyles.VSPACE_TOP_2, + fluidColumn(6, 0, locCss("", VACCINE_DOSE_LOC)), + fluidColumn(6, 0, locCss("", REACTIONS_LOC)) + ) + ); + //@formatter:on + dashboardLayout.addComponent(aefiCountsLayout); + + heading = new DashboardHeadingComponent(Captions.aefiDashboardAllAefi, null); + heading.setMargin(false); + aefiCountsLayout.addComponent(heading, HEADING_LOC); + + aefiCountsByType = new AefiCountTilesComponent<>(AefiType.class, "", this::getBackgroundStyleForAefiCountByType, null); + aefiCountsByType.setTitleStyleNames(CssStyles.H3, CssStyles.VSPACE_TOP_5); + aefiCountsByType.setGroupLabelStyle(CssStyles.LABEL_LARGE + " " + CssStyles.LABEL_WHITE_SPACE_NORMAL); + aefiCountsLayout.addComponent(aefiCountsByType, AEFI_TYPE_LOC); + + aefiCountsByVaccine = new AefiTypeStatisticsGroupComponent(); + aefiCountsByVaccine.addStyleNames(CssStyles.PADDING_X_20); + aefiCountsLayout.addComponent(aefiCountsByVaccine, VACCINES_LOC); + + vaccineDoseChart = new AefiByVaccineDoseChart(); + aefiCountsLayout.addComponent(vaccineDoseChart, VACCINE_DOSE_LOC); + + reactionsByGenderChart = new AefiReactionsByGenderChart(); + aefiCountsLayout.addComponent(reactionsByGenderChart, REACTIONS_LOC); + + epiCurveComponent = new AefiEpiCurveComponent(dataProvider); + epiCurveLayout = createEpiCurveLayout(); + + mapComponent = new AefiDashboardMapComponent(dataProvider); + mapLayout = createMapLayout(mapComponent); + + epiCurveAndMapLayout = createEpiCurveAndMapLayout(epiCurveLayout, mapLayout); + epiCurveAndMapLayout.addStyleName(CssStyles.VSPACE_TOP_1); + dashboardLayout.addComponent(epiCurveAndMapLayout); + dashboardLayout.setExpandRatio(epiCurveAndMapLayout, 1); + } + + @Override + public void refreshDashboard() { + dataProvider.refreshData(); + + heading.updateTotalLabel(String.valueOf(dataProvider.getAefiCountsByType().values().stream().mapToLong(Long::longValue).sum())); + + aefiCountsByType.update(dataProvider.getAefiCountsByType()); + aefiCountsByVaccine.update(dataProvider.getAefiCountsByVaccine()); + vaccineDoseChart.update(dataProvider.getAefiByVaccineDoseChartData()); + reactionsByGenderChart.update(dataProvider.getAefiEventsByGenderChartData()); + epiCurveComponent.clearAndFillEpiCurveChart(); + mapComponent.refreshMap(); + } + + private String getBackgroundStyleForAefiCountByType(AefiType aefiType) { + return aefiType == AefiType.SERIOUS ? "background-shipment-status-not-shipped" : "background-internal-lab-samples"; + } + + protected HorizontalLayout createEpiCurveAndMapLayout(VerticalLayout epiCurveLayout, VerticalLayout mapLayout) { + HorizontalLayout layout = new HorizontalLayout(epiCurveLayout, mapLayout); + layout.addStyleName(DashboardCssStyles.CURVE_AND_MAP_LAYOUT); + layout.setWidth(100, Unit.PERCENTAGE); + layout.setMargin(false); + layout.setSpacing(false); + + return layout; + } + + protected VerticalLayout createEpiCurveLayout() { + if (epiCurveComponent == null) { + throw new UnsupportedOperationException("EpiCurveComponent needs to be initialized before calling createEpiCurveLayout"); + } + + VerticalLayout layout = new VerticalLayout(); + layout.setMargin(false); + layout.setSpacing(false); + layout.setHeight(EPI_CURVE_AND_MAP_HEIGHT, Unit.PIXELS); + + epiCurveComponent.setSizeFull(); + + layout.addComponent(epiCurveComponent); + layout.setExpandRatio(epiCurveComponent, 1); + + epiCurveComponent.setExpandListener(expanded -> { + setExpanded(expanded, layout, mapLayout, 1); + }); + + return layout; + } + + private VerticalLayout createMapLayout(AefiDashboardMapComponent mapComponent) { + VerticalLayout layout = new VerticalLayout(); + layout.setMargin(false); + layout.setSpacing(false); + layout.setHeight(EPI_CURVE_AND_MAP_HEIGHT, Unit.PIXELS); + + mapComponent.setSizeFull(); + + layout.addComponent(mapComponent); + layout.setExpandRatio(mapComponent, 1); + + mapComponent.setExpandListener(expanded -> { + setExpanded(expanded, layout, epiCurveLayout, 0); + }); + + return layout; + } + + private void setExpanded(Boolean expanded, Component componentToExpand, Component componentToRemove, int removedComponentIndex) { + if (expanded) { + dashboardLayout.removeComponent(heading); + dashboardLayout.removeComponent(aefiCountsLayout); + epiCurveAndMapLayout.removeComponent(componentToRemove); + setHeight(100, Unit.PERCENTAGE); + + epiCurveAndMapLayout.setHeightFull(); + setHeightFull(); + componentToExpand.setSizeFull(); + dashboardLayout.setHeightFull(); + } else { + dashboardLayout.addComponent(heading, 1); + dashboardLayout.addComponent(aefiCountsLayout, 2); + epiCurveAndMapLayout.addComponent(componentToRemove, removedComponentIndex); + mapComponent.refreshMap(); + + componentToExpand.setHeight(EPI_CURVE_AND_MAP_HEIGHT, Unit.PIXELS); + setHeightUndefined(); + epiCurveAndMapLayout.setHeightUndefined(); + dashboardLayout.setHeightUndefined(); + } + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiEpiCurveComponent.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiEpiCurveComponent.java new file mode 100644 index 00000000000..0cc3a0ef910 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiEpiCurveComponent.java @@ -0,0 +1,97 @@ +/* + * 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.ui.dashboard.adverseeventsfollowingimmunization; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import com.vaadin.ui.AbstractComponent; + +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; +import de.symeda.sormas.api.dashboard.AefiDashboardCriteria; +import de.symeda.sormas.api.dashboard.EpiCurveGrouping; +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.utils.DateHelper; +import de.symeda.sormas.ui.dashboard.diagram.AbstractEpiCurveBuilder; +import de.symeda.sormas.ui.dashboard.diagram.AbstractEpiCurveComponent; +import de.symeda.sormas.ui.dashboard.diagram.EpiCurveSeriesElement; + +public class AefiEpiCurveComponent extends AbstractEpiCurveComponent { + + private static final long serialVersionUID = 6767165953640006853L; + + public AefiEpiCurveComponent(AefiDashboardDataProvider dashboardDataProvider) { + super(dashboardDataProvider); + epiCurveLabel.setValue(I18nProperties.getString(Strings.headingAefiDashboardEpiCurve)); + } + + @Override + protected AbstractComponent createEpiCurveModeSelector() { + return null; + } + + @Override + public void clearAndFillEpiCurveChart() { + epiCurveChart.setHcjs(new AefiEpiCurveBuilder(epiCurveGrouping).buildFrom(buildListOfFilteredDates(), dashboardDataProvider)); + } + + private static class AefiEpiCurveBuilder extends AbstractEpiCurveBuilder { + + public AefiEpiCurveBuilder(EpiCurveGrouping epiCurveGrouping) { + super(Captions.dashboardNumberOfAdverseEvents, epiCurveGrouping); + } + + @Override + protected List getEpiCurveElements(List datesGroupedBy, AefiDashboardDataProvider dashboardDataProvider) { + int[] seriousNumbers = new int[datesGroupedBy.size()]; + int[] nonSeriousNumbers = new int[datesGroupedBy.size()]; + + for (int i = 0; i < datesGroupedBy.size(); i++) { + Date date = datesGroupedBy.get(i); + + AefiDashboardCriteria criteria = + dashboardDataProvider.buildDashboardCriteria().aefiDashboardDateType(dashboardDataProvider.getDateType()); + if (epiCurveGrouping == EpiCurveGrouping.DAY) { + criteria.dateBetween(DateHelper.getStartOfDay(date), DateHelper.getEndOfDay(date)); + } else if (epiCurveGrouping == EpiCurveGrouping.WEEK) { + criteria.dateBetween(DateHelper.getStartOfWeek(date), DateHelper.getEndOfWeek(date)); + } else { + criteria.dateBetween(DateHelper.getStartOfMonth(date), DateHelper.getEndOfMonth(date)); + } + + Map aefiCounts = FacadeProvider.getAefiDashboardFacade().getAefiCountsByType(criteria); + + Long seriousCount = aefiCounts.get(AefiType.SERIOUS); + Long nonSeriousCount = aefiCounts.get(AefiType.NON_SERIOUS); + + seriousNumbers[i] = seriousCount != null ? seriousCount.intValue() : 0; + nonSeriousNumbers[i] = nonSeriousCount != null ? nonSeriousCount.intValue() : 0; + } + + return Arrays.asList( + new EpiCurveSeriesElement(AefiType.SERIOUS, "#c80000", seriousNumbers), + new EpiCurveSeriesElement(AefiType.NON_SERIOUS, "#32CD32", nonSeriousNumbers)); + } + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiByVaccineDoseChart.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiByVaccineDoseChart.java new file mode 100644 index 00000000000..964db0c07cd --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiByVaccineDoseChart.java @@ -0,0 +1,158 @@ +/* + * 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.ui.dashboard.adverseeventsfollowingimmunization.components; + +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +import com.vaadin.ui.VerticalLayout; + +import de.symeda.sormas.api.dashboard.adverseeventsfollowingimmunization.AefiChartData; +import de.symeda.sormas.api.dashboard.adverseeventsfollowingimmunization.AefiChartSeries; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.ui.highcharts.HighChart; + +public class AefiByVaccineDoseChart extends VerticalLayout { + + protected final HighChart chart; + + public AefiByVaccineDoseChart() { + + setMargin(false); + setSpacing(false); + setSizeFull(); + + chart = new HighChart(); + chart.setSizeFull(); + + addComponent(chart); + setExpandRatio(chart, 1); + } + + public void update(AefiChartData chartData) { + + StringBuilder hcjs = new StringBuilder(); + + //@formatter:off + hcjs.append( + "var options = {" + + " chart: {" + + " type: 'bar'," + + " borderRadius: '8px'" + + " }," + + " title: {" + + " text: 'Adverse events by vaccine dose'," + + " align: 'left'," + + " style: {" + + " fontSize: '15px'," + + " fontWeight: 'bold'" + + " }" + + " }," + + " subtitle: {" + + " text: ''," + + " align: 'left'" + + " }," + ); + //@formatter:on + + List xAxisCategories = chartData.getxAxisCategories(); + + StringBuilder categoryBuilder = new StringBuilder(); + if (!xAxisCategories.isEmpty()) { + categoryBuilder.append("["); + } + for (Object s : xAxisCategories) { + if (xAxisCategories.indexOf(s) == xAxisCategories.size() - 1) { + categoryBuilder.append("'" + I18nProperties.getCaption(String.valueOf(s)) + "']"); + } else { + categoryBuilder.append("'" + I18nProperties.getCaption(String.valueOf(s)) + "', "); + } + } + String categories = !StringUtils.isBlank(categoryBuilder.toString()) ? categoryBuilder.toString() : "[]"; + + //@formatter:off + hcjs.append("xAxis: { " + + " categories: " + categories + "," + + " title: {" + + " text: 'Vaccine dose'," + + " style: {" + + " fontWeight: 'bold'" + + " }" + + " }," + + "},"); + //@formatter:on + + //@formatter:off + hcjs.append("yAxis: {" + + " min: 0," + + " title: {" + + " text: 'No. of AEFI Reports'," + + " align: 'high'," + + " style: {" + + " fontWeight: 'bold'" + + " }" + + " }," + + " labels: {" + + " overflow: 'justify'" + + " }," + + " gridLineWidth: 0" + + " }," + + " tooltip: {" + + " valueSuffix: ''" + + " }," + + " plotOptions: {" + + " bar: {" + + " dataLabels: {" + + " enabled: true" + + " }," + + " groupPadding: 0.1" + + " }" + + " }," + + " credits: {" + + " enabled: false" + + " },"); + //@formatter:on + + hcjs.append("series: ["); + List chartSeries = chartData.getSeries(); + for (AefiChartSeries series : chartSeries) { + hcjs.append("{") + .append("name: '") + .append(series.getName()) + .append("',") + .append("color: '") + .append(series.getColor()) + .append("',") + .append("data: [") + .append(String.join(",", series.getSeriesData())) + .append("]") + .append("}"); + + if (chartSeries.indexOf(series) < chartSeries.size() - 1) { + hcjs.append(","); + } + } + hcjs.append("]"); + + hcjs.append("};"); + + chart.setHcjs(hcjs.toString()); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiCountTilesComponent.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiCountTilesComponent.java new file mode 100644 index 00000000000..a3308e23824 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiCountTilesComponent.java @@ -0,0 +1,204 @@ +/* + * 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.ui.dashboard.adverseeventsfollowingimmunization.components; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; +import java.util.Map; +import java.util.function.Function; + +import javax.annotation.Nullable; + +import org.apache.commons.lang3.StringUtils; + +import com.vaadin.icons.VaadinIcons; +import com.vaadin.shared.ui.ContentMode; +import com.vaadin.ui.Alignment; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; + +import de.symeda.sormas.api.i18n.Captions; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.ui.utils.CssStyles; + +public class AefiCountTilesComponent> extends VerticalLayout { + + private static final long serialVersionUID = 3342746874277667267L; + private final Class groupType; + private final Function tileBackgroundFactory; + private boolean withPercentage; + private String groupLabelStyle; + + private final Label title; + private Label infoIcon; + private final HorizontalLayout countsLayout; + private String[] titleStyleNames = new String[] { + CssStyles.H3 }; + + public AefiCountTilesComponent( + Class groupType, + String titleCaption, + Function tileBackgroundFactory, + @Nullable String descriptionTag) { + this.groupType = groupType; + this.tileBackgroundFactory = tileBackgroundFactory; + + setMargin(false); + setSpacing(false); + setWidthFull(); + + HorizontalLayout titleLayout = new HorizontalLayout(); + titleLayout.setMargin(false); + titleLayout.setSpacing(false); + addComponent(titleLayout); + + title = new Label(I18nProperties.getCaption(titleCaption)); + title.addStyleNames(titleStyleNames); + + titleLayout.addComponent(title); + + if (StringUtils.isNotBlank(descriptionTag)) { + infoIcon = new Label(VaadinIcons.INFO_CIRCLE.getHtml(), ContentMode.HTML); + infoIcon.setDescription(I18nProperties.getDescription(descriptionTag)); + infoIcon.addStyleName(CssStyles.HSPACE_LEFT_4); + infoIcon.addStyleNames(titleStyleNames); + + titleLayout.addComponent(infoIcon); + } + + countsLayout = new HorizontalLayout(); + countsLayout.setWidthFull(); + addComponent(countsLayout); + } + + public void update(Map counts) { + countsLayout.removeAllComponents(); + + Long total = null; + if (withPercentage) { + total = counts.values().stream().reduce(0L, Long::sum); + } + + addTiles(counts, total); + } + + private void addTiles(Map counts, @Nullable Long total) { + for (T group : groupType.getEnumConstants()) { + addTileForGroup(counts, group, total, String.valueOf(group)); + } + + if (counts.containsKey(null)) { + addTileForGroup(counts, null, total, I18nProperties.getCaption(Captions.notSpecified)); + } + } + + private void addTileForGroup(Map counts, T group, Long total, String groupCaption) { + Long count = counts.getOrDefault(group, 0L); + + BigDecimal percentage = null; + if (total != null) { + percentage = total == 0 + ? BigDecimal.ZERO + : BigDecimal.valueOf(count).divide(BigDecimal.valueOf(total), MathContext.DECIMAL32).multiply(new BigDecimal(100)); + percentage = percentage.setScale(0, RoundingMode.HALF_UP); + } + + TileComponent tile = new TileComponent<>(groupCaption, count, percentage, groupLabelStyle, tileBackgroundFactory.apply(group)); + tile.setWidthFull(); + + countsLayout.addComponent(tile); + countsLayout.setExpandRatio(tile, 1); + } + + public void setTitleStyleNames(String... styleNames) { + title.removeStyleNames(titleStyleNames); + title.addStyleNames(styleNames); + + if (infoIcon != null) { + infoIcon.removeStyleNames(titleStyleNames); + infoIcon.addStyleNames(styleNames); + } + + this.titleStyleNames = styleNames; + } + + public void setWithPercentage(boolean withPercentage) { + this.withPercentage = withPercentage; + } + + public void setGroupLabelStyle(String groupLabelStyle) { + this.groupLabelStyle = groupLabelStyle; + } + + private static class TileComponent extends VerticalLayout { + + private static final long serialVersionUID = 5055236377479070515L; + + TileComponent(String group, Long count, @Nullable BigDecimal percentage, String groupLabelStyle, String backgroundStyle) { + setSpacing(false); + setMargin(false); + + VerticalLayout numbersLayout = new VerticalLayout(); + numbersLayout.setWidthFull(); + numbersLayout.setMargin(false); + numbersLayout.setSpacing(false); + numbersLayout.addStyleNames(backgroundStyle, CssStyles.ROUNDED_BORDER_TOP); + addComponent(numbersLayout); + + Label countLabel = new Label(count.toString()); + countLabel + .addStyleNames(CssStyles.LABEL_WHITE, CssStyles.LABEL_BOLD, CssStyles.LABEL_LARGE, CssStyles.ALIGN_CENTER, CssStyles.VSPACE_TOP_4); + + numbersLayout.addComponent(countLabel); + numbersLayout.setComponentAlignment(countLabel, Alignment.TOP_CENTER); + + if (percentage != null) { + Label percentageLabel = new Label(percentage + "%"); + percentageLabel.addStyleNames(CssStyles.LABEL_WHITE, CssStyles.ALIGN_CENTER, CssStyles.VSPACE_4); + + numbersLayout.addComponent(percentageLabel); + numbersLayout.setComponentAlignment(percentageLabel, Alignment.MIDDLE_CENTER); + } + + Label groupLabel = new Label(group); + groupLabel.addStyleNames( + CssStyles.LABEL_WHITE, + CssStyles.LABEL_BOLD, + CssStyles.VSPACE_TOP_4, + CssStyles.VSPACE_4, + CssStyles.HSPACE_LEFT_4, + CssStyles.HSPACE_RIGHT_4); + + if (groupLabelStyle != null) { + groupLabel.addStyleName(groupLabelStyle); + } + + VerticalLayout groupLabelLayout = new VerticalLayout(); + groupLabelLayout.setMargin(false); + groupLabelLayout.setSpacing(false); + groupLabelLayout.addStyleNames(backgroundStyle, CssStyles.BACKGROUND_DARKER, CssStyles.ROUNDED_BORDER_BOTTOM); + groupLabelLayout.addComponent(groupLabel); + groupLabelLayout.setComponentAlignment(groupLabel, Alignment.TOP_CENTER); + + addComponent(groupLabelLayout); + } + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiDashboardMapComponent.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiDashboardMapComponent.java new file mode 100644 index 00000000000..be94e75e9a4 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiDashboardMapComponent.java @@ -0,0 +1,161 @@ +/* + * 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.ui.dashboard.adverseeventsfollowingimmunization.components; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +import com.vaadin.ui.Component; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.v7.ui.CheckBox; + +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; +import de.symeda.sormas.api.dashboard.AefiDashboardCriteria; +import de.symeda.sormas.api.dashboard.adverseeventsfollowingimmunization.MapAefiDto; +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.ui.dashboard.adverseeventsfollowingimmunization.AefiDashboardDataProvider; +import de.symeda.sormas.ui.dashboard.map.BaseDashboardMapComponent; +import de.symeda.sormas.ui.map.LeafletMarker; +import de.symeda.sormas.ui.map.MarkerIcon; +import de.symeda.sormas.ui.utils.CssStyles; + +public class AefiDashboardMapComponent extends BaseDashboardMapComponent { + + public AefiDashboardMapComponent(AefiDashboardDataProvider dashboardDataProvider) { + super(Strings.headingAefiDashboardMap, dashboardDataProvider, Strings.infoHeadingAefiDashboardMap); + } + + @Override + protected void addComponents() { + super.addComponents(); + } + + @Override + protected Long getMarkerCount(Date fromDate, Date toDate, int maxCount) { + return FacadeProvider.getAefiDashboardFacade().countAefiForMap(dashboardDataProvider.buildDashboardCriteriaWithDates()); + } + + @Override + protected void loadMapData(Date fromDate, Date toDate) { + String markerGroup = "adverseevents"; + map.removeGroup(markerGroup); + + AefiDashboardCriteria criteria = dashboardDataProvider.buildDashboardCriteriaWithDates(); + List aefiMapData = FacadeProvider.getAefiDashboardFacade().getAefiForMap(criteria); + + //temporary fix: remove data without coordinates + //ideally do this in the backend code + List filteredAefiMapData = new ArrayList<>(); + for (MapAefiDto mapAefiDto : aefiMapData) { + if (mapAefiDto.getLatitude() != null && mapAefiDto.getLongitude() != null) { + filteredAefiMapData.add(mapAefiDto); + } + } + + List markers = new ArrayList<>(aefiMapData.size()); + + markers.addAll(filteredAefiMapData.stream().map(mapAefiDto -> { + LeafletMarker marker = new LeafletMarker(); + switch (mapAefiDto.getAefiType()) { + case SERIOUS: + marker.setIcon(MarkerIcon.SAMPLE_CASE); + break; + case NON_SERIOUS: + marker.setIcon(MarkerIcon.SAMPLE_CONTACT); + break; + default: + marker.setIcon(MarkerIcon.SAMPLE_EVENT_PARTICIPANT); + } + marker.setLatLon(mapAefiDto.getLatitude(), mapAefiDto.getLongitude()); + + return marker; + }).collect(Collectors.toList())); + + map.addMarkerGroup(markerGroup, markers); + } + + @Override + protected void addLayerOptions(VerticalLayout layersLayout) { + + CheckBox showSeriousAefiCheckBox = new CheckBox(); + showSeriousAefiCheckBox.setId(Captions.aefiDashboardShowSeriousAefi); + showSeriousAefiCheckBox.setCaption(I18nProperties.getCaption(Captions.aefiDashboardShowSeriousAefi)); + showSeriousAefiCheckBox.setValue(shouldShowSeriousAefi()); + showSeriousAefiCheckBox.addValueChangeListener(e -> { + dashboardDataProvider.buildDashboardCriteriaWithDates().aefiType(AefiType.SERIOUS); + + refreshMap(true); + }); + + layersLayout.addComponent(showSeriousAefiCheckBox); + + CheckBox showNonSeriousAefiCheckBox = new CheckBox(); + showNonSeriousAefiCheckBox.setId(Captions.aefiDashboardShowNonSeriousAefi); + showNonSeriousAefiCheckBox.setCaption(I18nProperties.getCaption(Captions.aefiDashboardShowNonSeriousAefi)); + showNonSeriousAefiCheckBox.setValue(shouldShowNonSeriousAefi()); + showNonSeriousAefiCheckBox.addValueChangeListener(e -> { + dashboardDataProvider.buildDashboardCriteriaWithDates().aefiType(AefiType.NON_SERIOUS); + + refreshMap(true); + }); + + layersLayout.addComponent(showNonSeriousAefiCheckBox); + } + + @Override + protected List getLegendComponents() { + + HorizontalLayout samplesLegendLayout = new HorizontalLayout(); + samplesLegendLayout.setSpacing(false); + samplesLegendLayout.setMargin(false); + + //if (shouldShowSeriousAefi()) { + HorizontalLayout seriousLegendEntry = + buildMarkerLegendEntry(MarkerIcon.SAMPLE_CASE, I18nProperties.getCaption(Captions.aefiDashboardSeriousAefi)); + CssStyles.style(seriousLegendEntry, CssStyles.HSPACE_RIGHT_3); + samplesLegendLayout.addComponent(seriousLegendEntry); + //} + + //if (shouldShowNonSeriousAefi()) { + HorizontalLayout nonSeriousLegendEntry = + buildMarkerLegendEntry(MarkerIcon.SAMPLE_CONTACT, I18nProperties.getCaption(Captions.aefiDashboardNonSeriousAefi)); + CssStyles.style(nonSeriousLegendEntry, CssStyles.HSPACE_RIGHT_3); + samplesLegendLayout.addComponent(nonSeriousLegendEntry); + //} + + return Collections.singletonList(samplesLegendLayout); + } + + private boolean shouldShowSeriousAefi() { + return dashboardDataProvider.buildDashboardCriteriaWithDates().getAefiType() == AefiType.SERIOUS; + } + + private boolean shouldShowNonSeriousAefi() { + return dashboardDataProvider.buildDashboardCriteriaWithDates().getAefiType() == AefiType.NON_SERIOUS; + } + + @Override + protected void onMarkerClicked(String groupId, int markerIndex) { + + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiReactionsByGenderChart.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiReactionsByGenderChart.java new file mode 100644 index 00000000000..464872634f0 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiReactionsByGenderChart.java @@ -0,0 +1,166 @@ +/* + * 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.ui.dashboard.adverseeventsfollowingimmunization.components; + +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +import com.vaadin.ui.VerticalLayout; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto; +import de.symeda.sormas.api.dashboard.adverseeventsfollowingimmunization.AefiChartData; +import de.symeda.sormas.api.dashboard.adverseeventsfollowingimmunization.AefiChartSeries; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.ui.highcharts.HighChart; + +public class AefiReactionsByGenderChart extends VerticalLayout { + + protected final HighChart chart; + + public AefiReactionsByGenderChart() { + + setMargin(false); + setSpacing(false); + setSizeFull(); + + chart = new HighChart(); + chart.setSizeFull(); + + addComponent(chart); + setExpandRatio(chart, 1); + } + + public void update(AefiChartData chartData) { + + StringBuilder hcjs = new StringBuilder(); + + //@formatter:off + hcjs.append( + "var options = {" + + " chart: {" + + " type: 'bar'," + + " borderRadius: '8px'" + + " }," + + " title: {" + + " text: 'Proportion of AEFI reactions (events) by gender'," + + " align: 'left'," + + " style: {" + + " fontSize: '15px'," + + " fontWeight: 'bold'" + + " }" + + " }," + + " subtitle: {" + + " text: ''," + + " align: 'left'" + + " }," + ); + //@formatter:on + + List xAxisCategories = chartData.getxAxisCategories(); + + StringBuilder categoryBuilder = new StringBuilder(); + if (!xAxisCategories.isEmpty()) { + categoryBuilder.append("["); + } + for (Object s : xAxisCategories) { + if (xAxisCategories.indexOf(s) == xAxisCategories.size() - 1) { + categoryBuilder.append("'" + I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, String.valueOf(s)) + "']"); + } else { + categoryBuilder.append("'" + I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, String.valueOf(s)) + "', "); + } + } + String categories = !StringUtils.isBlank(categoryBuilder.toString()) ? categoryBuilder.toString() : "[]"; + + //@formatter:off + hcjs.append("xAxis: [{" + + " categories: " + categories + "," + + " title: {" + + " text: 'AEFI Reactions (events)'," + + " style: {" + + " fontWeight: 'bold'" + + " }" + + " }," + + " reversed: true," + + " labels: {" + + " step: 1" + + " }" + + " }, { " + + " title: {" + + " text: 'AEFI Reactions (events)'," + + " style: {" + + " fontWeight: 'bold'" + + " }" + + " }," + + " opposite: true," + + " reversed: false," + + " categories: " + categories + "," + + " linkedTo: 0," + + " labels: {" + + " step: 1" + + " }" + + " }],"); + //@formatter:on + + //@formatter:off + hcjs.append("yAxis: {" + + " title: {" + + " text: 'Proportion of AEFI reactions'," + + " align: 'high'," + + " style: {" + + " fontWeight: 'bold'" + + " }" + + " }," + + " }," + + " plotOptions: {" + + " series: {" + + " stacking: 'normal'" + + " }" + + " }," + + " credits: {" + + " enabled: false" + + " },"); + //@formatter:on + + hcjs.append("series: ["); + List chartSeries = chartData.getSeries(); + for (AefiChartSeries series : chartSeries) { + hcjs.append("{") + .append("name: '") + .append(series.getName()) + .append("',") + .append("color: '") + .append(series.getColor()) + .append("',") + .append("data: [") + .append(String.join(",", series.getSeriesData())) + .append("]") + .append("}"); + + if (chartSeries.indexOf(series) < chartSeries.size() - 1) { + hcjs.append(","); + } + } + hcjs.append("]"); + + hcjs.append("};"); + + chart.setHcjs(hcjs.toString()); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiTypeStatisticsComponent.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiTypeStatisticsComponent.java new file mode 100644 index 00000000000..697d17fe4d3 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiTypeStatisticsComponent.java @@ -0,0 +1,100 @@ +/* + * 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.ui.dashboard.adverseeventsfollowingimmunization.components; + +import java.util.Map; + +import com.vaadin.ui.Label; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; +import de.symeda.sormas.api.i18n.Captions; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.ui.dashboard.components.DashboardHeadingComponent; +import de.symeda.sormas.ui.dashboard.statistics.CountElementStyle; +import de.symeda.sormas.ui.dashboard.statistics.DashboardStatisticsCountElement; +import de.symeda.sormas.ui.dashboard.surveillance.components.statistics.DiseaseSectionStatisticsComponent; +import de.symeda.sormas.ui.utils.CssStyles; + +public class AefiTypeStatisticsComponent extends DiseaseSectionStatisticsComponent { + + private final DashboardStatisticsCountElement seriousCount; + private final DashboardStatisticsCountElement nonSeriousCount; + private boolean withPercentage; + + public AefiTypeStatisticsComponent(String titleCaption, String description, String subtitleCaption, boolean showInfoIcon) { + super(titleCaption, description, ""); + + setWidthUndefined(); + + if (subtitleCaption != null) { + Label subTitleLabel = new Label(I18nProperties.getCaption(subtitleCaption)); + CssStyles.style(subTitleLabel, CssStyles.H3, CssStyles.VSPACE_TOP_5); + addComponent(subTitleLabel); + } + + // Count layout + seriousCount = new DashboardStatisticsCountElement(I18nProperties.getCaption(Captions.aefiDashboardSerious), CountElementStyle.CRITICAL); + nonSeriousCount = + new DashboardStatisticsCountElement(I18nProperties.getCaption(Captions.aefiDashboardNonSerious), CountElementStyle.POSITIVE); + + buildCountLayout(seriousCount, nonSeriousCount); + } + + public void update(Map aefiTypeData) { + if (aefiTypeData != null) { + Long totalCount = null; + Long seriousTotal = aefiTypeData.getOrDefault(AefiType.SERIOUS, 0L); + Long nonSeriousTotal = aefiTypeData.getOrDefault(AefiType.NON_SERIOUS, 0L); + + //updateTotalLabel(((Long) aefiTypeData.values().stream().mapToLong(Long::longValue).sum()).toString()); + if (withPercentage) { + totalCount = aefiTypeData.values().stream().reduce(0L, Long::sum); + seriousCount.updateCountLabel(seriousTotal + " (" + calculatePercentage(totalCount, seriousTotal) + " %)"); + nonSeriousCount.updateCountLabel(nonSeriousTotal + " (" + calculatePercentage(totalCount, nonSeriousTotal) + " %)"); + } else { + seriousCount.updateCountLabel(seriousTotal.toString()); + nonSeriousCount.updateCountLabel(nonSeriousTotal.toString()); + } + } + } + + public int calculatePercentage(Long totalCount, Long labResultCount) { + return totalCount == 0 ? 0 : (int) ((labResultCount * 100.0f) / totalCount); + } + + public void setWithPercentage(boolean withPercentage) { + this.withPercentage = withPercentage; + } + + public void setTitleStyleNamesOnTitleLabel(String... styleNames) { + DashboardHeadingComponent dashboardHeadingComponent = this.getHeading(); + Label titleLabel = dashboardHeadingComponent.getTitleLabel(); + + titleLabel.removeStyleNames(dashboardHeadingComponent.getTitleStyleNames()); + titleLabel.addStyleNames(styleNames); + } + + public void setTitleStyleNamesOnTotalLabel(String... styleNames) { + DashboardHeadingComponent dashboardHeadingComponent = this.getHeading(); + Label totalLabel = dashboardHeadingComponent.getTotalLabel(); + + totalLabel.removeStyleNames(dashboardHeadingComponent.getTotalLabelStyleNames()); + totalLabel.addStyleNames(styleNames); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiTypeStatisticsGroupComponent.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiTypeStatisticsGroupComponent.java new file mode 100644 index 00000000000..45e459ac760 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiTypeStatisticsGroupComponent.java @@ -0,0 +1,64 @@ +/* + * 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.ui.dashboard.adverseeventsfollowingimmunization.components; + +import java.util.HashMap; +import java.util.Map; + +import com.vaadin.ui.CssLayout; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.ui.utils.CssStyles; + +public class AefiTypeStatisticsGroupComponent extends CssLayout { + + Map componentMap = new HashMap<>(); + + public AefiTypeStatisticsGroupComponent() { + + setWidthFull(); + } + + public void update(Map> countsByVaccineData) { + + //temporary fix: re-use stored components and hide/unhide if not in new update + if (countsByVaccineData.isEmpty()) { + removeAllComponents(); + componentMap.clear(); + } + + AefiTypeStatisticsComponent statisticsComponent; + + for (Map.Entry> entry : countsByVaccineData.entrySet()) { + if (componentMap.containsKey(entry.getKey())) { + componentMap.get(entry.getKey()).update(entry.getValue()); + } else { + statisticsComponent = new AefiTypeStatisticsComponent("", null, entry.getKey().toString(), false); + //statisticsComponent.getHeading().getTitleLabel().setValue(entry.getKey().toString()); + statisticsComponent.hideHeading(); + statisticsComponent.update(entry.getValue()); + statisticsComponent.addStyleNames(CssStyles.VIEW_SECTION, CssStyles.PADDING_X_8, CssStyles.HSPACE_RIGHT_3); + componentMap.put(entry.getKey(), statisticsComponent); + + addComponent(statisticsComponent); + } + } + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/ImmunizationDataView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/ImmunizationDataView.java index bc59daabd97..d2cba6a96d0 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/ImmunizationDataView.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/ImmunizationDataView.java @@ -4,20 +4,25 @@ import de.symeda.sormas.api.EditPermissionType; import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiListCriteria; import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.immunization.ImmunizationDto; +import de.symeda.sormas.api.immunization.MeansOfImmunization; import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.aefilink.AefiListComponent; import de.symeda.sormas.ui.immunization.components.form.ImmunizationDataForm; import de.symeda.sormas.ui.sormastosormas.SormasToSormasListComponent; import de.symeda.sormas.ui.utils.CommitDiscardWrapperComponent; import de.symeda.sormas.ui.utils.CssStyles; import de.symeda.sormas.ui.utils.DetailSubComponentWrapper; import de.symeda.sormas.ui.utils.LayoutWithSidePanel; +import de.symeda.sormas.ui.utils.components.sidecomponent.SideComponentLayout; public class ImmunizationDataView extends AbstractImmunizationView { public static final String VIEW_NAME = ROOT_VIEW_NAME + "/data"; public static final String IMMUNIZATION_LOC = "immunization"; + public static final String ADVERSE_EVENTS_LOC = "adverseEvents"; public static final String SORMAS_TO_SORMAS_LOC = "sormsToSormas"; private CommitDiscardWrapperComponent editComponent; @@ -46,11 +51,24 @@ protected void initView(String params) { setSubComponent(container); container.setEnabled(true); - LayoutWithSidePanel layout = new LayoutWithSidePanel(editComponent, SORMAS_TO_SORMAS_LOC); + LayoutWithSidePanel layout = new LayoutWithSidePanel(editComponent, SORMAS_TO_SORMAS_LOC, ADVERSE_EVENTS_LOC); container.addComponent(layout); ImmunizationDto immunization = FacadeProvider.getImmunizationFacade().getImmunizationByUuid(getReference().getUuid()); + + if (FacadeProvider.getFeatureConfigurationFacade().isFeatureEnabled(FeatureType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_MANAGEMENT) + && (immunization.getMeansOfImmunization() == MeansOfImmunization.VACCINATION + || immunization.getMeansOfImmunization() == MeansOfImmunization.VACCINATION_RECOVERY)) { + AefiListCriteria aefiListCriteria = new AefiListCriteria.Builder(getReference()).build(); + + AefiListComponent aefiListComponent = + new AefiListComponent(aefiListCriteria, this::showUnsavedChangesPopup, isEditAllowed(), immunization.getVaccinations().size()); + CssStyles.style(aefiListComponent, CssStyles.VIEW_SECTION); + + layout.addSidePanelComponent(new SideComponentLayout(aefiListComponent), ADVERSE_EVENTS_LOC); + } + boolean sormasToSormasEnabled = FacadeProvider.getSormasToSormasFacade() .isAnyFeatureConfigured( FeatureType.SORMAS_TO_SORMAS_SHARE_CASES, diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ArchiveHandlers.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ArchiveHandlers.java index 48f3db9e746..5bfa1ac1249 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ArchiveHandlers.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ArchiveHandlers.java @@ -30,6 +30,8 @@ import de.symeda.sormas.api.CoreFacade; import de.symeda.sormas.api.EntityDto; import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiFacade; import de.symeda.sormas.api.campaign.CampaignDto; import de.symeda.sormas.api.campaign.CampaignFacade; import de.symeda.sormas.api.caze.CaseDataDto; @@ -93,6 +95,10 @@ public static CoreEntityArchiveHandler forI return new CoreEntityArchiveHandler<>(FacadeProvider.getImmunizationFacade(), ArchiveMessages.IMMUNIZATION); } + public static CoreEntityArchiveHandler forAefi() { + return new CoreEntityArchiveHandler<>(FacadeProvider.getAefiFacade(), ArchiveMessages.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION); + } + public static CoreEntityArchiveHandler forTravelEntry() { return new CoreEntityArchiveHandler<>(FacadeProvider.getTravelEntryFacade(), ArchiveMessages.TRAVEL_ENTRY); } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ArchiveMessages.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ArchiveMessages.java index 8b0aef3c5e9..079f167ae09 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ArchiveMessages.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ArchiveMessages.java @@ -106,6 +106,23 @@ public enum ArchiveMessages { null, null), + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION(Strings.headingArchiveImmunization, + Strings.confirmationArchiveImmunization, + null, + Strings.messageImmunizationArchived, + Strings.headingDearchiveImmunization, + Strings.confirmationDearchiveImmunization, + null, + Strings.messageImmunizationDearchived, + null, + null, + null, + null, + null, + null, + null, + null), + TRAVEL_ENTRY(Strings.headingArchiveTravelEntry, Strings.confirmationArchiveTravelEntry, null, 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 130e7bfad5f..1c82e66f59f 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 @@ -80,6 +80,7 @@ private CssStyles() { public static final String INDENT_LEFT_1 = "indent-left-1"; public static final String INDENT_LEFT_2 = "indent-left-2"; public static final String INDENT_LEFT_3 = "indent-left-3"; + public static final String PADDING_NONE = "padding-none"; public static final String VAADIN_LABEL = "v-label"; public static final String VAADIN_CAPTION = "v-caption"; @@ -238,6 +239,7 @@ private CssStyles() { public static final String GRID_ROW_STATUS_PROGRESS = "status-progress"; public static final String GRID_ROW_TITLE = "row-title"; + public static final String GRID_ROW_SELECTED = "v-grid-row-selected"; public static final String LABEL_CONFIGURATION_SEVERITY_INDICATOR = "severity-indicator"; public static final String BADGE = "badge"; @@ -309,6 +311,21 @@ private CssStyles() { @Deprecated public static final String CALLOUT = "callout"; + public static final String VIEW_SECTION = "view-section"; + public static final String PAGE_TITLE = "page-title"; + public static final String ROUNDED_BORDER = "rounded-border"; + public static final String ROUNDED_BORDER_TOP = "rounded-border-top"; + public static final String ROUNDED_BORDER_BOTTOM = "rounded-border-bottom"; + public static final String ROUNDED_BORDER_SM = "rounded-border-sm"; + public static final String ROUNDED_BORDER_TOP_SM = "rounded-border-sm-top"; + public static final String ROUNDED_BORDER_BOTTOM_SM = "rounded-border-sm-bottom"; + public static final String MARGIN_X_4 = "margin-x-4"; + public static final String MARGIN_TOP_4 = "margin-top-4"; + public static final String PADDING_X_8 = "padding-x-8"; + public static final String PADDING_X_20 = "padding-x-20"; + public static final String VIEW_SECTION_MARGIN_X_4 = VIEW_SECTION + " " + MARGIN_X_4; + public static final String VIEW_SECTION_MARGIN_TOP_4_MARGIN_X_4 = VIEW_SECTION + " " + MARGIN_X_4 + " " + MARGIN_TOP_4; + public static String buildVaadinStyle(String primaryStyle, String... styles) { StringBuilder styleBuilder = new StringBuilder(); styleBuilder.append(primaryStyle); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/SormasFieldGroupFieldFactory.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/SormasFieldGroupFieldFactory.java index ad062f3b4b8..6e0290496cd 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/SormasFieldGroupFieldFactory.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/SormasFieldGroupFieldFactory.java @@ -19,6 +19,9 @@ import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.ReferenceDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventState; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.SeizureType; +import de.symeda.sormas.api.caze.Trimester; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.symptoms.SymptomState; import de.symeda.sormas.api.utils.FieldConstraints; @@ -26,6 +29,9 @@ import de.symeda.sormas.api.utils.fieldaccess.UiFieldAccessCheckers; import de.symeda.sormas.api.utils.fieldvisibility.FieldVisibilityCheckers; import de.symeda.sormas.ui.ActivityAsCase.ActivityAsCaseField; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.fields.vaccines.AefiVaccinationsField; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.fields.vaccines.AefiVaccinationsField_2; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.form.AdverseEventsForm; import de.symeda.sormas.ui.clinicalcourse.HealthConditionsForm; import de.symeda.sormas.ui.exposure.ExposuresField; import de.symeda.sormas.ui.hospitalization.PreviousHospitalizationsField; @@ -72,7 +78,11 @@ public SormasFieldGroupFieldFactory( public T createField(Class type, Class fieldType) { if (type.isEnum()) { if (fieldType.isAssignableFrom(Field.class) // no specific fieldType defined? - && (SymptomState.class.isAssignableFrom(type) || YesNoUnknown.class.isAssignableFrom(type))) { + && (SymptomState.class.isAssignableFrom(type) + || YesNoUnknown.class.isAssignableFrom(type) + || AdverseEventState.class.isAssignableFrom(type) + || SeizureType.class.isAssignableFrom(type) + || Trimester.class.isAssignableFrom(type))) { NullableOptionGroup field = new NullableOptionGroup(); field.setImmediate(true); populateWithEnumData(field, (Class) type); @@ -177,7 +187,11 @@ public T createField(Class type, Class fieldType) { return (T) new CustomizableEnumPropertiesComponent(); } else if (UserField.class.isAssignableFrom(fieldType)) { return (T) new UserField(); - } else if (CheckBoxTree.class.isAssignableFrom(fieldType)) { + } else if (AefiVaccinationsField.class.isAssignableFrom(fieldType)) { + return (T) new AefiVaccinationsField(fieldAccessCheckers); + } else if (AdverseEventsForm.class.isAssignableFrom(fieldType)) { + return (T) new AdverseEventsForm(fieldVisibilityCheckers, fieldAccessCheckers); + }else if (CheckBoxTree.class.isAssignableFrom(fieldType)){ return (T) new CheckBoxTree<>(); } return super.createField(type, fieldType); 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 6e6c108f8eb..a84710ea9e3 100644 --- a/sormas-ui/src/main/webapp/VAADIN/themes/sormas/global.scss +++ b/sormas-ui/src/main/webapp/VAADIN/themes/sormas/global.scss @@ -250,6 +250,27 @@ margin-left: 45px; } + .margin-x-4{ + margin-left: 4px; + margin-right: 4px; + } + + .margin-top-4{ + margin-top: 4px; + } + + .padding-none{ + padding: 0 !important; + } + + .padding-x-8{ + padding: 0 8px !important; + } + + .padding-x-20{ + padding: 0 20px !important; + } + .vertical-rule { border-right: 1px solid #CDD8EC; } @@ -343,6 +364,52 @@ padding: 6px; } + .view-section{ + padding: 10px 10px; + border-radius: 4px; + background-color: #ffffff; + border-width: 0; + border-style: solid; + border-color: #ffffff; + + /*box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, .2), 0px 1px 1px 0px rgba(0, 0, 0, .14), 0px 1px 3px 0px rgba(0, 0, 0, .12);*/ + + -webkit-box-shadow: 0 0 2px rgba(0,0,0,0.12), 0 2px 4px rgba(0,0,0,0.14);; + box-shadow: 0 0 2px rgba(0,0,0,0.12), 0 2px 4px rgba(0,0,0,0.14);; + } + + .page-title{ + font-size: 24px !important; + } + + .rounded-border{ + border-radius: 8px; + } + + .rounded-border-top{ + border-top-left-radius: 8px; + border-top-right-radius: 8px; + } + + .rounded-border-bottom{ + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + } + + .rounded-border-sm{ + border-radius: 4px; + } + + .rounded-border-sm-top{ + border-top-left-radius: 4px; + border-top-right-radius: 4px; + } + + .rounded-border-sm-bottom{ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + } + .spacing-small { .v-spacing { width: 4px; From 0b1cd5850698b08cd49ce5919e71daa57404b69f Mon Sep 17 00:00:00 2001 From: Obinna Henry <55580796+obinna-h-n@users.noreply.github.com> Date: Sun, 24 Mar 2024 12:58:34 +0100 Subject: [PATCH 2/5] #12634 - AEFI module - AEFI Investigation - #13053 - Create a new AEFI investigation entity and IndexDTO - #13056 - Add an AEFI Investigations directory for the web app - #13054 - Add a create/edit form for AEFI investigations in the web app - #13055 - Add an AEFI investigations list to AEFI report forms --- .../de/symeda/sormas/api/FacadeProvider.java | 5 + .../AefiCausality.java | 29 + .../AefiClassification.java | 30 + .../AefiClassificationSubType.java | 39 + .../AefiCriteria.java | 35 +- .../AefiDto.java | 91 +- .../AefiExportDto.java | 568 +++++ .../AefiFacade.java | 6 +- .../AefiHelper.java | 46 +- .../AefiImmunizationPeriod.java | 30 + .../AefiIndexDto.java | 16 +- .../AefiInvestigationCriteria.java | 240 +++ .../AefiInvestigationDateType.java | 30 + .../AefiInvestigationDto.java | 1684 +++++++++++++++ .../AefiInvestigationFacade.java | 29 + .../AefiInvestigationIndexDto.java | 372 ++++ .../AefiInvestigationListCriteria.java | 44 + .../AefiInvestigationListEntryDto.java | 156 ++ .../AefiInvestigationReferenceDto.java | 42 + .../AefiInvestigationStage.java | 30 + .../AefiInvestigationStatus.java | 33 + .../AefiReferenceDto.java | 7 +- .../AefiVaccinationPeriod.java | 30 + .../BirthTerm.java | 30 + .../DeliveryProcedure.java | 31 + .../PatientStatusAtAefiInvestigation.java | 32 + .../PlaceOfVaccination.java | 30 + .../SeriousAefiInfoSource.java | 31 + .../SyringeType.java | 31 + .../VaccinationActivity.java | 30 + .../VaccinationSite.java | 32 + .../VaccineCarrier.java | 30 + .../de/symeda/sormas/api/caze/Vaccine.java | 12 + .../sormas/api/caze/VaccineManufacturer.java | 12 + .../AefiDashboardFacade.java | 9 +- .../de/symeda/sormas/api/i18n/Captions.java | 261 +++ .../de/symeda/sormas/api/i18n/Strings.java | 26 +- .../symeda/sormas/api/i18n/Validations.java | 5 +- .../de/symeda/sormas/api/user/UserRight.java | 2 + .../src/main/resources/captions.properties | 270 ++- sormas-api/src/main/resources/enum.properties | 102 +- .../src/main/resources/strings.properties | 33 +- .../src/main/resources/validations.properties | 5 +- .../AefiFacadeEjb.java | 42 +- .../AefiInvestigationFacadeEjb.java | 641 ++++++ ...igationJurisdictionPredicateValidator.java | 116 ++ .../AefiInvestigationQueryContext.java | 45 + .../AefiInvestigationService.java | 548 +++++ .../AefiJurisdictionPredicateValidator.java | 2 +- .../AefiService.java | 166 +- .../entity/Aefi.java | 99 +- .../entity/AefiInvestigation.java | 1832 +++++++++++++++++ .../entity/AefiInvestigationJoins.java | 138 ++ .../entity/AefiJoins.java | 5 +- .../AefiIndexDtoResultTransformer.java | 24 +- ...nvestigationIndexDtoResultTransformer.java | 84 + ...tigationListEntryDtoResultTransformer.java | 53 + .../AefiDashboardFacadeEjb.java | 13 + .../AefiDashboardService.java | 177 +- .../main/resources/META-INF/persistence.xml | 4 +- .../symeda/sormas/ui/ControllerProvider.java | 7 + .../AbstractAefiDataView.java | 113 + .../AbstractAefiInvestigationDataView.java | 122 ++ .../AbstractAefiView.java | 87 +- .../AefiController.java | 38 +- .../AefiDataView.java | 21 +- .../AefiInvestigationController.java | 229 +++ .../AefiInvestigationDataForm.java | 950 +++++++++ .../AefiInvestigationDataView.java | 132 ++ .../AefiInvestigationView.java | 244 +++ .../AefiView.java | 69 +- .../AefiInvestigationList.java | 88 + .../AefiInvestigationListComponent.java | 57 + .../AefiInvestigationListEntry.java | 76 + .../aefilink/AefiListComponent.java | 5 +- .../components/directory/AefiDataLayout.java | 7 +- .../components/directory/AefiFilterForm.java | 12 +- .../components/directory/AefiGrid.java | 26 +- .../AefiInvestigationDataLayout.java | 43 + .../AefiInvestigationFilterForm.java | 418 ++++ .../AefiInvestigationFilterFormLayout.java | 53 + .../directory/AefiInvestigationGrid.java | 151 ++ .../vaccines/AefiVaccinationsField.java | 52 +- .../vaccines/AefiVaccinationsField_2.java | 198 -- .../components/form/AdverseEventsForm.java | 9 +- .../components/form/AefiDataForm.java | 45 +- .../components/form/FormSectionAccordion.java | 55 + .../form/FormSectionAccordionPanel.java | 77 + .../components/information/AefiInfo.java | 89 + .../AefiDashboardDataProvider.java | 30 +- .../AefiDashboardFilterLayout.java | 5 +- .../AefiDashboardView.java | 103 +- .../components/AefiCountTilesComponent.java | 5 +- .../AefiReactionsByGenderChart.java | 15 +- .../AefiTypeStatisticsGroupComponent.java | 11 +- .../sormas/ui/utils/AefiDownloadUtil.java | 67 + .../sormas/ui/utils/ArchiveHandlers.java | 8 + .../sormas/ui/utils/ArchiveMessages.java | 28 +- .../de/symeda/sormas/ui/utils/CssStyles.java | 2 + .../sormas/ui/utils/ExportEntityName.java | 3 + .../utils/SormasFieldGroupFieldFactory.java | 9 +- 101 files changed, 11747 insertions(+), 607 deletions(-) create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiCausality.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiClassification.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiClassificationSubType.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiExportDto.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiImmunizationPeriod.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationCriteria.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationDateType.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationDto.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationFacade.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationIndexDto.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationListCriteria.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationListEntryDto.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationReferenceDto.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationStage.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationStatus.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiVaccinationPeriod.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/BirthTerm.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/DeliveryProcedure.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/PatientStatusAtAefiInvestigation.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/PlaceOfVaccination.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/SeriousAefiInfoSource.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/SyringeType.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/VaccinationActivity.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/VaccinationSite.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/VaccineCarrier.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiInvestigationFacadeEjb.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiInvestigationJurisdictionPredicateValidator.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiInvestigationQueryContext.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiInvestigationService.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiInvestigation.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiInvestigationJoins.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiInvestigationIndexDtoResultTransformer.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiInvestigationListEntryDtoResultTransformer.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiDataView.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiInvestigationDataView.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationController.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationDataForm.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationDataView.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationView.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefiinvestigationlink/AefiInvestigationList.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefiinvestigationlink/AefiInvestigationListComponent.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefiinvestigationlink/AefiInvestigationListEntry.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiInvestigationDataLayout.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiInvestigationFilterForm.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiInvestigationFilterFormLayout.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiInvestigationGrid.java delete mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiVaccinationsField_2.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/FormSectionAccordion.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/FormSectionAccordionPanel.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/information/AefiInfo.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AefiDownloadUtil.java diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/FacadeProvider.java b/sormas-api/src/main/java/de/symeda/sormas/api/FacadeProvider.java index f7570d1c269..bf85edda351 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/FacadeProvider.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/FacadeProvider.java @@ -20,6 +20,7 @@ import de.symeda.sormas.api.action.ActionFacade; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiFacade; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationFacade; import de.symeda.sormas.api.audit.AuditLoggerFacade; import de.symeda.sormas.api.bagexport.BAGExportFacade; import de.symeda.sormas.api.campaign.CampaignFacade; @@ -154,6 +155,10 @@ public static AefiFacade getAefiFacade() { return get().lookupEjbRemote(AefiFacade.class); } + public static AefiInvestigationFacade getAefiInvestigationFacade() { + return get().lookupEjbRemote(AefiInvestigationFacade.class); + } + public static VaccinationFacade getVaccinationFacade() { return get().lookupEjbRemote(VaccinationFacade.class); } diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiCausality.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiCausality.java new file mode 100644 index 00000000000..c29b81af2a7 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiCausality.java @@ -0,0 +1,29 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum AefiCausality { + + CONFIRMED, + INCONCLUSIVE; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiClassification.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiClassification.java new file mode 100644 index 00000000000..8f8771c4c18 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiClassification.java @@ -0,0 +1,30 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum AefiClassification { + + RELATED_TO_VACCINE_OR_VACCINATION, + COINCIDENTAL_ADVERSE_EVENT, + UNDETERMINED; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiClassificationSubType.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiClassificationSubType.java new file mode 100644 index 00000000000..e94d6a7010b --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiClassificationSubType.java @@ -0,0 +1,39 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import static de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiClassification.RELATED_TO_VACCINE_OR_VACCINATION; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum AefiClassificationSubType { + + VACCINE_PRODUCT_RELATED(RELATED_TO_VACCINE_OR_VACCINATION), + VACCINE_QUALITY_DEFECT_RELATED(RELATED_TO_VACCINE_OR_VACCINATION), + IMMUNIZATION_ERROR_RELATED(RELATED_TO_VACCINE_OR_VACCINATION), + IMMUNIZATION_ANXIETY_RELATED(RELATED_TO_VACCINE_OR_VACCINATION); + + private AefiClassification aefiClassification; + + AefiClassificationSubType(AefiClassification aefiClassification) { + this.aefiClassification = aefiClassification; + } + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiCriteria.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiCriteria.java index 742df524387..4edcde120d6 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiCriteria.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiCriteria.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -39,14 +36,14 @@ public class AefiCriteria extends BaseCriteria implements Serializable { public static final String I18N_PREFIX = "AefiCriteria"; public static final String DISEASE = "disease"; - public static final String NAME_ADDRESS_PHONE_EMAIL_LIKE = "nameAddressPhoneEmailLike"; + public static final String PERSON_LIKE = "personLike"; public static final String AEFI_TYPE = "aefiType"; - public static final String OUTCOME = "outcome"; public static final String VACCINE_NAME = "vaccineName"; public static final String VACCINE_MANUFACTURER = "vaccineManufacturer"; public static final String REGION = "region"; public static final String DISTRICT = "district"; public static final String COMMUNITY = "community"; + public static final String OUTCOME = "outcome"; public static final String FACILITY_TYPE_GROUP = "facilityTypeGroup"; public static final String FACILITY_TYPE = "facilityType"; public static final String HEALTH_FACILITY = "healthFacility"; @@ -57,14 +54,14 @@ public class AefiCriteria extends BaseCriteria implements Serializable { public static final String RELEVANCE_STATUS = "relevanceStatus"; private Disease disease; - private String nameAddressPhoneEmailLike; + private String personLike; private AefiType aefiType; - private AefiOutcome outcome; private Vaccine vaccineName; private VaccineManufacturer vaccineManufacturer; private RegionReferenceDto region; private DistrictReferenceDto district; private CommunityReferenceDto community; + private AefiOutcome outcome; private FacilityTypeGroup facilityTypeGroup; private FacilityType facilityType; private FacilityReferenceDto healthFacility; @@ -82,12 +79,12 @@ public void setDisease(Disease disease) { this.disease = disease; } - public String getNameAddressPhoneEmailLike() { - return nameAddressPhoneEmailLike; + public String getPersonLike() { + return personLike; } - public void setNameAddressPhoneEmailLike(String nameAddressPhoneEmailLike) { - this.nameAddressPhoneEmailLike = nameAddressPhoneEmailLike; + public void setPersonLike(String personLike) { + this.personLike = personLike; } public AefiType getAefiType() { @@ -98,14 +95,6 @@ public void setAefiType(AefiType aefiType) { this.aefiType = aefiType; } - public AefiOutcome getOutcome() { - return outcome; - } - - public void setOutcome(AefiOutcome outcome) { - this.outcome = outcome; - } - public Vaccine getVaccineName() { return vaccineName; } @@ -146,6 +135,14 @@ public void setCommunity(CommunityReferenceDto community) { this.community = community; } + public AefiOutcome getOutcome() { + return outcome; + } + + public void setOutcome(AefiOutcome outcome) { + this.outcome = outcome; + } + public FacilityTypeGroup getFacilityTypeGroup() { return facilityTypeGroup; } diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiDto.java index 7d32221109d..e98c7ca0d9e 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiDto.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -81,13 +78,13 @@ public class AefiDto extends PseudonymizableDto { public static final String AGE_GROUP = "ageGroup"; public static final String HEALTH_FACILITY = "healthFacility"; public static final String HEALTH_FACILITY_DETAILS = "healthFacilityDetails"; - public static final String REPORTER_NAME = "reporterName"; - public static final String REPORTER_INSTITUTION = "reporterInstitution"; - public static final String REPORTER_DESIGNATION = "reporterDesignation"; - public static final String REPORTER_DEPARTMENT = "reporterDepartment"; - public static final String REPORTER_ADDRESS = "reporterAddress"; - public static final String REPORTER_PHONE = "reporterPhone"; - public static final String REPORTER_EMAIL = "reporterEmail"; + public static final String REPORTING_OFFICER_NAME = "reportingOfficerName"; + public static final String REPORTING_OFFICER_FACILITY = "reportingOfficerFacility"; + public static final String REPORTING_OFFICER_DESIGNATION = "reportingOfficerDesignation"; + public static final String REPORTING_OFFICER_DEPARTMENT = "reportingOfficerDepartment"; + public static final String REPORTING_OFFICER_ADDRESS = "reportingOfficerAddress"; + public static final String REPORTING_OFFICER_PHONE_NUMBER = "reportingOfficerPhoneNumber"; + public static final String REPORTING_OFFICER_EMAIL = "reportingOfficerEmail"; public static final String TODAYS_DATE = "todaysDate"; public static final String START_DATE_TIME = "startDateTime"; public static final String AEFI_DESCRIPTION = "aefiDescription"; @@ -110,7 +107,7 @@ public class AefiDto extends PseudonymizableDto { private ImmunizationReferenceDto immunization; private PersonReferenceDto person; private LocationDto address; - @NotEmpty(message = Validations.aefiWithoutSuspectVaccine) + @NotEmpty(message = Validations.aefiWithoutSuspectVaccines) private List vaccinations = new ArrayList<>(); @NotNull(message = Validations.aefiWithoutPrimarySuspectVaccine) private VaccinationDto primarySuspectVaccine; @@ -139,17 +136,17 @@ public class AefiDto extends PseudonymizableDto { @Size(max = FieldConstraints.CHARACTER_LIMIT_DEFAULT, message = Validations.textTooLong) private String healthFacilityDetails; @Size(max = FieldConstraints.CHARACTER_LIMIT_SMALL, message = Validations.textTooLong) - private String reporterName; - private FacilityReferenceDto reporterInstitution; + private String reportingOfficerName; + private FacilityReferenceDto reportingOfficerFacility; @Size(max = FieldConstraints.CHARACTER_LIMIT_SMALL, message = Validations.textTooLong) - private String reporterDesignation; + private String reportingOfficerDesignation; @Size(max = FieldConstraints.CHARACTER_LIMIT_SMALL, message = Validations.textTooLong) - private String reporterDepartment; - private LocationDto reporterAddress; + private String reportingOfficerDepartment; + private LocationDto reportingOfficerAddress; @Size(max = FieldConstraints.CHARACTER_LIMIT_SMALL, message = Validations.textTooLong) - private String reporterPhone; + private String reportingOfficerPhoneNumber; @Size(max = FieldConstraints.CHARACTER_LIMIT_SMALL, message = Validations.textTooLong) - private String reporterEmail; + private String reportingOfficerEmail; private Date todaysDate; private Date startDateTime; @Size(max = FieldConstraints.CHARACTER_LIMIT_TEXT, message = Validations.textTooLong) @@ -209,7 +206,7 @@ public static AefiDto build(AefiReferenceDto aefiReferenceDto) { } public AefiReferenceDto toReference() { - return new AefiReferenceDto(getUuid(), getPerson().getCaption(), getExternalId()); + return new AefiReferenceDto(getUuid(), getExternalId()); } public ImmunizationReferenceDto getImmunization() { @@ -404,60 +401,60 @@ public void setHealthFacilityDetails(String healthFacilityDetails) { this.healthFacilityDetails = healthFacilityDetails; } - public String getReporterName() { - return reporterName; + public String getReportingOfficerName() { + return reportingOfficerName; } - public void setReporterName(String reporterName) { - this.reporterName = reporterName; + public void setReportingOfficerName(String reportingOfficerName) { + this.reportingOfficerName = reportingOfficerName; } - public FacilityReferenceDto getReporterInstitution() { - return reporterInstitution; + public FacilityReferenceDto getReportingOfficerFacility() { + return reportingOfficerFacility; } - public void setReporterInstitution(FacilityReferenceDto reporterInstitution) { - this.reporterInstitution = reporterInstitution; + public void setReportingOfficerFacility(FacilityReferenceDto reportingOfficerFacility) { + this.reportingOfficerFacility = reportingOfficerFacility; } - public String getReporterDesignation() { - return reporterDesignation; + public String getReportingOfficerDesignation() { + return reportingOfficerDesignation; } - public void setReporterDesignation(String reporterDesignation) { - this.reporterDesignation = reporterDesignation; + public void setReportingOfficerDesignation(String reportingOfficerDesignation) { + this.reportingOfficerDesignation = reportingOfficerDesignation; } - public String getReporterDepartment() { - return reporterDepartment; + public String getReportingOfficerDepartment() { + return reportingOfficerDepartment; } - public void setReporterDepartment(String reporterDepartment) { - this.reporterDepartment = reporterDepartment; + public void setReportingOfficerDepartment(String reportingOfficerDepartment) { + this.reportingOfficerDepartment = reportingOfficerDepartment; } - public LocationDto getReporterAddress() { - return reporterAddress; + public LocationDto getReportingOfficerAddress() { + return reportingOfficerAddress; } - public void setReporterAddress(LocationDto reporterAddress) { - this.reporterAddress = reporterAddress; + public void setReportingOfficerAddress(LocationDto reportingOfficerAddress) { + this.reportingOfficerAddress = reportingOfficerAddress; } - public String getReporterPhone() { - return reporterPhone; + public String getReportingOfficerPhoneNumber() { + return reportingOfficerPhoneNumber; } - public void setReporterPhone(String reporterPhone) { - this.reporterPhone = reporterPhone; + public void setReportingOfficerPhoneNumber(String reportingOfficerPhoneNumber) { + this.reportingOfficerPhoneNumber = reportingOfficerPhoneNumber; } - public String getReporterEmail() { - return reporterEmail; + public String getReportingOfficerEmail() { + return reportingOfficerEmail; } - public void setReporterEmail(String reporterEmail) { - this.reporterEmail = reporterEmail; + public void setReportingOfficerEmail(String reportingOfficerEmail) { + this.reportingOfficerEmail = reportingOfficerEmail; } public Date getTodaysDate() { diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiExportDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiExportDto.java new file mode 100644 index 00000000000..2c41a8827ac --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiExportDto.java @@ -0,0 +1,568 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import java.io.Serializable; +import java.util.Date; + +import org.apache.commons.lang3.StringUtils; + +import de.symeda.sormas.api.caze.BirthDateDto; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.caze.VaccineManufacturer; +import de.symeda.sormas.api.person.Sex; +import de.symeda.sormas.api.utils.Order; +import de.symeda.sormas.api.utils.YesNoUnknown; +import de.symeda.sormas.api.utils.pseudonymization.PseudonymizableIndexDto; + +public class AefiExportDto extends PseudonymizableIndexDto implements Serializable { + + private static final long serialVersionUID = 4568112808032880384L; + + public static final String I18N_PREFIX = "AefiExport"; + + public static final String RECEIVED_AT_NATIONAL_LEVEL_DATE = "receivedAtNationalLevelDate"; + public static final String VACCINATION_FACILITY_NAME = "vaccinationFacilityName"; + public static final String VACCINATION_FACILITY_REGION = "vaccinationFacilityRegion"; + public static final String VACCINATION_FACILITY_DISTRICT = "vaccinationFacilityDistrict"; + public static final String VACCINATION_FACILITY_COMMUNITY = "vaccinationFacilityCommunity"; + public static final String REPORTING_OFFICER_ADDRESS_COUNTRY_NAME = "reportingOfficerAddressCountryName"; + public static final String PATIENT_ADDRESS_REGION = "patientAddressRegion"; + public static final String PATIENT_ADDRESS_DISTRICT = "patientAddressDistrict"; + public static final String PATIENT_ADDRESS_COMMUNITY = "patientAddressCommunity"; + public static final String PATIENT_ADDRESS_DETAILS = "patientAddressDetails"; + public static final String REPORTING_ID_NUMBER = "reportingIdNumber"; + public static final String WORLDWIDE_ID = "worldWideId"; + public static final String FIRST_NAME = "firstName"; + public static final String LAST_NAME = "lastName"; + public static final String BIRTH_DATE = "birthDate"; + public static final String ONSET_AGE_YEARS = "onsetAgeYears"; + public static final String ONSET_AGE_MONTHS = "onsetAgeMonths"; + public static final String ONSET_AGE_DAYS = "onsetAgeDays"; + public static final String ONSET_AGE_GROUP = "onsetAgeGroup"; + public static final String SEX = "sex"; + public static final String AEFI_DESCRIPTION = "aefiDescription"; + public static final String PRIMARY_SUSPECT_VACCINE_NAME = "primarySuspectVaccineName"; + public static final String PRIMARY_SUSPECT_VACCINE_OTHER_NAME = "primarySuspectVaccineOtherName"; + public static final String PRIMARY_SUSPECT_VACCINE_BRAND = "primarySuspectVaccineBrand"; + public static final String PRIMARY_SUSPECT_VACCINE_MANUFACTURER = "primarySuspectVaccineManufacturer"; + public static final String PRIMARY_SUSPECT_VACCINE_BATCH_NUMBER = "primarySuspectVaccineBatchNumber"; + public static final String PRIMARY_SUSPECT_VACCINE_DOSE = "primarySuspectVaccineDose"; + public static final String PRIMARY_SUSPECT_VACCINE_DILUENT_BATCH_NUMBER = "primarySuspectVaccineDiluentBatchNumber"; + public static final String PRIMARY_SUSPECT_VACCINE_VACCINATION_DATE = "primarySuspectVaccineVaccinationDate"; + public static final String START_DATE_TIME = "startDateTime"; + public static final String SEVERE_LOCAL_REACTION = "severeLocalReaction"; + public static final String SEVERE_LOCAL_REACTION_MORE_THAN_THREE_DAYS = "severeLocalReactionMoreThanThreeDays"; + public static final String SEVERE_LOCAL_REACTION_BEYOND_NEAREST_JOINT = "severeLocalReactionBeyondNearestJoint"; + public static final String SEIZURES = "seizures"; + public static final String SEIZURE_TYPE = "seizureType"; + public static final String ABSCESS = "abscess"; + public static final String SEPSIS = "sepsis"; + public static final String ENCEPHALOPATHY = "encephalopathy"; + public static final String TOXIC_SHOCK_SYNDROME = "toxicShockSyndrome"; + public static final String THROMBOCYTOPENIA = "thrombocytopenia"; + public static final String ANAPHYLAXIS = "anaphylaxis"; + public static final String FEVERISH_FEELING = "feverishFeeling"; + public static final String OTHER_ADVERSE_EVENT_DETAILS = "otherAdverseEventDetails"; + public static final String OUTCOME = "outcome"; + public static final String SERIOUS = "serious"; + public static final String REPORTING_OFFICER_NAME = "reportingOfficerName"; + public static final String REPORTING_OFFICER_FACILITY_NAME = "reportingOfficerFacilityName"; + public static final String REPORTING_OFFICER_FACILITY_REGION = "reportingOfficerFacilityRegion"; + public static final String REPORTING_OFFICER_FACILITY_DISTRICT = "reportingOfficerFacilityDistrict"; + public static final String REPORTING_OFFICER_FACILITY_COMMUNITY = "reportingOfficerFacilityCommunity"; + public static final String REPORTING_OFFICER_DESIGNATION = "reportingOfficerDesignation"; + public static final String REPORTING_OFFICER_DEPARTMENT = "reportingOfficerDepartment"; + public static final String REPORTING_OFFICER_EMAIL = "reportingOfficerEmail"; + public static final String REPORTING_OFFICER_PHONE_NUMBER = "reportingOfficerPhoneNumber"; + public static final String REPORT_DATE = "reportDate"; + public static final String NATIONAL_LEVEL_COMMENT = "nationalLevelComment"; + + private Date receivedAtNationalLevelDate; + private String vaccinationFacilityName; + private String vaccinationFacilityRegion; + private String vaccinationFacilityDistrict; + private String vaccinationFacilityCommunity; + private String reportingOfficerAddressCountryName; + private String patientAddressRegion; + private String patientAddressDistrict; + private String patientAddressCommunity; + private String patientAddressDetails; + private String reportingIdNumber; + private String worldWideId; + private String firstName; + private String lastName; + private BirthDateDto birthDate; + private Integer onsetAgeYears; + private Integer onsetAgeMonths; + private Integer onsetAgeDays; + private AefiAgeGroup onsetAgeGroup; + private Sex sex; + private String aefiDescription; + private Vaccine primarySuspectVaccineName; + private String primarySuspectVaccineOtherName; + private String primarySuspectVaccineBrandName; + private VaccineManufacturer primarySuspectVaccineManufacturer; + private String primarySuspectVaccineBatchNumber; + private String primarySuspectVaccineDose; + private String primarySuspectVaccineDiluentBatchNumber; + private Date primarySuspectVaccineVaccinationDate; + private Date startDateTime; + private AdverseEventState severeLocalReaction; + private boolean severeLocalReactionMoreThanThreeDays; + private boolean severeLocalReactionBeyondNearestJoint; + private AdverseEventState seizures; + private SeizureType seizureType; + private AdverseEventState abscess; + private AdverseEventState sepsis; + private AdverseEventState encephalopathy; + private AdverseEventState toxicShockSyndrome; + private AdverseEventState thrombocytopenia; + private AdverseEventState anaphylaxis; + private AdverseEventState feverishFeeling; + private String otherAdverseEventDetails; + private AefiOutcome outcome; + private YesNoUnknown serious; + private String reportingOfficerName; + private String reportingOfficerFacilityName; + private String reportingOfficerFacilityRegion; + private String reportingOfficerFacilityDistrict; + private String reportingOfficerFacilityCommunity; + private String reportingOfficerDesignation; + private String reportingOfficerDepartment; + private String reportingOfficerEmail; + private String reportingOfficerPhoneNumber; + private Date reportDate; + private String nationalLevelComment; + private Boolean isInJurisdiction; + + public AefiExportDto( + String uuid, + Date receivedAtNationalLevelDate, + String vaccinationFacilityName, + String vaccinationFacilityRegion, + String vaccinationFacilityDistrict, + String vaccinationFacilityCommunity, + String reportingOfficerAddressCountryName, + String patientAddressRegion, + String patientAddressDistrict, + String patientAddressCommunity, + String street, + String houseNumber, + String postalCode, + String city, + String reportingIdNumber, + String worldWideId, + String firstName, + String lastName, + Integer birthdateDD, + Integer birthdateMM, + Integer birthdateYYYY, + Integer onsetAgeYears, + Integer onsetAgeMonths, + Integer onsetAgeDays, + AefiAgeGroup onsetAgeGroup, + Sex sex, + String aefiDescription, + Vaccine primarySuspectVaccineName, + String primarySuspectVaccineOtherName, + VaccineManufacturer primarySuspectVaccineManufacturer, + String primarySuspectVaccineBatchNumber, + String primarySuspectVaccineDose, + Date primarySuspectVaccineVaccinationDate, + Date startDateTime, + AdverseEventState severeLocalReaction, + boolean severeLocalReactionMoreThanThreeDays, + boolean severeLocalReactionBeyondNearestJoint, + AdverseEventState seizures, + SeizureType seizureType, + AdverseEventState abscess, + AdverseEventState sepsis, + AdverseEventState encephalopathy, + AdverseEventState toxicShockSyndrome, + AdverseEventState thrombocytopenia, + AdverseEventState anaphylaxis, + AdverseEventState feverishFeeling, + String otherAdverseEventDetails, + AefiOutcome outcome, + YesNoUnknown serious, + String reportingOfficerFirstName, + String reportingOfficerLastName, + String reportingOfficerFacilityName, + String reportingOfficerFacilityRegion, + String reportingOfficerFacilityDistrict, + String reportingOfficerFacilityCommunity, + String reportingOfficerEmail, + String reportingOfficerPhoneNumber, + Date reportDate, + String nationalLevelComment, + boolean isInJurisdiction) { + super(uuid); + this.receivedAtNationalLevelDate = receivedAtNationalLevelDate; + this.vaccinationFacilityName = vaccinationFacilityName; + this.vaccinationFacilityRegion = vaccinationFacilityRegion; + this.vaccinationFacilityDistrict = vaccinationFacilityDistrict; + this.vaccinationFacilityCommunity = vaccinationFacilityCommunity; + this.reportingOfficerAddressCountryName = reportingOfficerAddressCountryName; + this.patientAddressRegion = patientAddressRegion; + this.patientAddressDistrict = patientAddressDistrict; + this.patientAddressCommunity = patientAddressCommunity; + + StringBuilder patientAddressBuilder = new StringBuilder(); + if (!StringUtils.isBlank(houseNumber)) { + patientAddressBuilder.append(houseNumber); + } + if (!StringUtils.isBlank(street)) { + patientAddressBuilder.append(", ").append(street); + } + if (!StringUtils.isBlank(postalCode)) { + patientAddressBuilder.append(", ").append(postalCode); + } + if (!StringUtils.isBlank(city)) { + patientAddressBuilder.append(", ").append(city); + } + + this.patientAddressDetails = patientAddressBuilder.toString(); + + this.reportingIdNumber = reportingIdNumber; + this.worldWideId = worldWideId; + this.firstName = firstName; + this.lastName = lastName; + this.birthDate = new BirthDateDto(birthdateDD, birthdateMM, birthdateYYYY); + this.onsetAgeYears = onsetAgeYears; + this.onsetAgeMonths = onsetAgeMonths; + this.onsetAgeDays = onsetAgeDays; + this.onsetAgeGroup = onsetAgeGroup; + this.sex = sex; + this.aefiDescription = aefiDescription; + this.primarySuspectVaccineName = primarySuspectVaccineName; + this.primarySuspectVaccineOtherName = primarySuspectVaccineOtherName; + this.primarySuspectVaccineManufacturer = primarySuspectVaccineManufacturer; + this.primarySuspectVaccineBatchNumber = primarySuspectVaccineBatchNumber; + this.primarySuspectVaccineDose = primarySuspectVaccineDose; + this.primarySuspectVaccineVaccinationDate = primarySuspectVaccineVaccinationDate; + this.startDateTime = startDateTime; + this.severeLocalReaction = severeLocalReaction; + this.severeLocalReactionMoreThanThreeDays = severeLocalReactionMoreThanThreeDays; + this.severeLocalReactionBeyondNearestJoint = severeLocalReactionBeyondNearestJoint; + this.seizures = seizures; + this.seizureType = seizureType; + this.abscess = abscess; + this.sepsis = sepsis; + this.encephalopathy = encephalopathy; + this.toxicShockSyndrome = toxicShockSyndrome; + this.thrombocytopenia = thrombocytopenia; + this.anaphylaxis = anaphylaxis; + this.feverishFeeling = feverishFeeling; + this.otherAdverseEventDetails = otherAdverseEventDetails; + this.outcome = outcome; + this.serious = serious; + this.reportingOfficerName = reportingOfficerFirstName + " " + reportingOfficerLastName; + this.reportingOfficerFacilityName = reportingOfficerFacilityName; + this.reportingOfficerFacilityRegion = reportingOfficerFacilityRegion; + this.reportingOfficerFacilityDistrict = reportingOfficerFacilityDistrict; + this.reportingOfficerFacilityCommunity = reportingOfficerFacilityCommunity; + this.reportingOfficerEmail = reportingOfficerEmail; + this.reportingOfficerPhoneNumber = reportingOfficerPhoneNumber; + this.reportDate = reportDate; + this.nationalLevelComment = nationalLevelComment; + this.isInJurisdiction = isInJurisdiction; + } + + @Order(0) + public Date getReceivedAtNationalLevelDate() { + return receivedAtNationalLevelDate; + } + + @Order(1) + public String getVaccinationFacilityName() { + return vaccinationFacilityName; + } + + @Order(2) + public String getVaccinationFacilityRegion() { + return vaccinationFacilityRegion; + } + + @Order(3) + public String getVaccinationFacilityDistrict() { + return vaccinationFacilityDistrict; + } + + @Order(4) + public String getVaccinationFacilityCommunity() { + return vaccinationFacilityCommunity; + } + + @Order(5) + public String getReportingOfficerAddressCountryName() { + return reportingOfficerAddressCountryName; + } + + @Order(6) + public String getPatientAddressRegion() { + return patientAddressRegion; + } + + @Order(7) + public String getPatientAddressDistrict() { + return patientAddressDistrict; + } + + @Order(8) + public String getPatientAddressCommunity() { + return patientAddressCommunity; + } + + @Order(9) + public String getPatientAddressDetails() { + return patientAddressDetails; + } + + @Order(10) + public String getReportingIdNumber() { + return reportingIdNumber; + } + + @Order(11) + public String getWorldWideId() { + return worldWideId; + } + + @Order(12) + public String getFirstName() { + return firstName; + } + + @Order(13) + public String getLastName() { + return lastName; + } + + @Order(14) + public BirthDateDto getBirthDate() { + return birthDate; + } + + @Order(15) + public Integer getOnsetAgeYears() { + return onsetAgeYears; + } + + @Order(16) + public Integer getOnsetAgeMonths() { + return onsetAgeMonths; + } + + @Order(17) + public Integer getOnsetAgeDays() { + return onsetAgeDays; + } + + @Order(18) + public AefiAgeGroup getOnsetAgeGroup() { + return onsetAgeGroup; + } + + @Order(19) + public Sex getSex() { + return sex; + } + + @Order(20) + public String getAefiDescription() { + return aefiDescription; + } + + @Order(21) + public Vaccine getPrimarySuspectVaccineName() { + return primarySuspectVaccineName; + } + + @Order(22) + public String getPrimarySuspectVaccineOtherName() { + return primarySuspectVaccineOtherName; + } + + @Order(23) + public String getPrimarySuspectVaccineBrandName() { + return primarySuspectVaccineBrandName; + } + + @Order(24) + public VaccineManufacturer getPrimarySuspectVaccineManufacturer() { + return primarySuspectVaccineManufacturer; + } + + @Order(25) + public String getPrimarySuspectVaccineBatchNumber() { + return primarySuspectVaccineBatchNumber; + } + + @Order(26) + public String getPrimarySuspectVaccineDose() { + return primarySuspectVaccineDose; + } + + @Order(27) + public String getPrimarySuspectVaccineDiluentBatchNumber() { + return primarySuspectVaccineDiluentBatchNumber; + } + + @Order(28) + public Date getPrimarySuspectVaccineVaccinationDate() { + return primarySuspectVaccineVaccinationDate; + } + + @Order(29) + public Date getStartDateTime() { + return startDateTime; + } + + @Order(30) + public AdverseEventState getSevereLocalReaction() { + return severeLocalReaction; + } + + @Order(31) + public boolean isSevereLocalReactionMoreThanThreeDays() { + return severeLocalReactionMoreThanThreeDays; + } + + @Order(32) + public boolean isSevereLocalReactionBeyondNearestJoint() { + return severeLocalReactionBeyondNearestJoint; + } + + @Order(33) + public AdverseEventState getSeizures() { + return seizures; + } + + @Order(34) + public SeizureType getSeizureType() { + return seizureType; + } + + @Order(35) + public AdverseEventState getAbscess() { + return abscess; + } + + @Order(36) + public AdverseEventState getSepsis() { + return sepsis; + } + + @Order(37) + public AdverseEventState getEncephalopathy() { + return encephalopathy; + } + + @Order(38) + public AdverseEventState getToxicShockSyndrome() { + return toxicShockSyndrome; + } + + @Order(39) + public AdverseEventState getThrombocytopenia() { + return thrombocytopenia; + } + + @Order(40) + public AdverseEventState getAnaphylaxis() { + return anaphylaxis; + } + + @Order(41) + public AdverseEventState getFeverishFeeling() { + return feverishFeeling; + } + + @Order(42) + public String getOtherAdverseEventDetails() { + return otherAdverseEventDetails; + } + + @Order(43) + public AefiOutcome getOutcome() { + return outcome; + } + + @Order(44) + public YesNoUnknown getSerious() { + return serious; + } + + @Order(45) + public String getReportingOfficerName() { + return reportingOfficerName; + } + + @Order(46) + public String getReportingOfficerFacilityName() { + return reportingOfficerFacilityName; + } + + @Order(47) + public String getReportingOfficerFacilityRegion() { + return reportingOfficerFacilityRegion; + } + + @Order(48) + public String getReportingOfficerFacilityDistrict() { + return reportingOfficerFacilityDistrict; + } + + @Order(49) + public String getReportingOfficerFacilityCommunity() { + return reportingOfficerFacilityCommunity; + } + + @Order(50) + public String getReportingOfficerDesignation() { + return reportingOfficerDesignation; + } + + @Order(51) + public String getReportingOfficerDepartment() { + return reportingOfficerDepartment; + } + + @Order(52) + public String getReportingOfficerEmail() { + return reportingOfficerEmail; + } + + @Order(53) + public String getReportingOfficerPhoneNumber() { + return reportingOfficerPhoneNumber; + } + + @Order(54) + public Date getReportDate() { + return reportDate; + } + + @Order(55) + public String getNationalLevelComment() { + return nationalLevelComment; + } + + public Boolean getInJurisdiction() { + return isInJurisdiction; + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiFacade.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiFacade.java index 4267d27a9b5..a7ed73ac4bb 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiFacade.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiFacade.java @@ -1,23 +1,21 @@ /* * 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.adverseeventsfollowingimmunization; +import java.util.Collection; import java.util.List; import javax.ejb.Remote; @@ -28,4 +26,6 @@ public interface AefiFacade extends CoreFacade { List getEntriesList(AefiListCriteria criteria, Integer first, Integer max); + + List getExportList(AefiCriteria criteria, Collection selectedRows, int first, int max); } diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiHelper.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiHelper.java index 815c46365dc..2d4d2b80395 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiHelper.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiHelper.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -29,6 +26,49 @@ private AefiHelper() { } + public static String buildAdverseEventsString(AdverseEventsDto adverseEventsDto) { + + List adverseEventsList = new ArrayList<>(); + + if (adverseEventsDto.getSevereLocalReaction() == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.SEVERE_LOCAL_REACTION)); + } + + if (adverseEventsDto.getSeizures() == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.SEIZURES)); + } + + if (adverseEventsDto.getAbscess() == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.ABSCESS)); + } + + if (adverseEventsDto.getSepsis() == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.SEPSIS)); + } + + if (adverseEventsDto.getEncephalopathy() == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.ENCEPHALOPATHY)); + } + + if (adverseEventsDto.getToxicShockSyndrome() == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.TOXIC_SHOCK_SYNDROME)); + } + + if (adverseEventsDto.getThrombocytopenia() == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.THROMBOCYTOPENIA)); + } + + if (adverseEventsDto.getAnaphylaxis() == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.ANAPHYLAXIS)); + } + + if (adverseEventsDto.getFeverishFeeling() == AdverseEventState.YES) { + adverseEventsList.add(I18nProperties.getPrefixCaption(AdverseEventsDto.I18N_PREFIX, AdverseEventsDto.FEVERISH_FEELING)); + } + + return String.join(", ", adverseEventsList); + } + public static String buildAdverseEventsString( AdverseEventState severeLocalReaction, boolean severeLocalReactionMoreThanThreeDays, diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiImmunizationPeriod.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiImmunizationPeriod.java new file mode 100644 index 00000000000..e8e943fe41d --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiImmunizationPeriod.java @@ -0,0 +1,30 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum AefiImmunizationPeriod { + + WITHIN_FIRST_VACCINATIONS, + WITHIN_LAST_VACCINATIONS, + UNKNOWN; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiIndexDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiIndexDto.java index e389093fc00..ad982aeff95 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiIndexDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiIndexDto.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -33,6 +30,8 @@ public class AefiIndexDto extends PseudonymizableIndexDto implements Serializable, Cloneable { + private static final long serialVersionUID = 2873180122463056859L; + public static final String I18N_PREFIX = "AefiIndex"; public static final String UUID = "uuid"; @@ -69,6 +68,7 @@ public class AefiIndexDto extends PseudonymizableIndexDto implements Serializabl private String district; private YesNoUnknown serious; private Vaccine primaryVaccine; + private String primaryVaccineDetails; private AefiOutcome outcome; private Date vaccinationDate; private Date startDateTime; @@ -90,6 +90,7 @@ public AefiIndexDto( String district, YesNoUnknown serious, Vaccine primaryVaccine, + String primaryVaccineDetails, AefiOutcome outcome, Date vaccinationDate, Date reportDate, @@ -111,6 +112,7 @@ public AefiIndexDto( this.district = district; this.serious = serious; this.primaryVaccine = primaryVaccine; + this.primaryVaccineDetails = primaryVaccineDetails; this.outcome = outcome; this.vaccinationDate = vaccinationDate; this.reportDate = reportDate; @@ -217,6 +219,14 @@ public void setPrimaryVaccine(Vaccine primaryVaccine) { this.primaryVaccine = primaryVaccine; } + public String getPrimaryVaccineDetails() { + return primaryVaccineDetails; + } + + public void setPrimaryVaccineDetails(String primaryVaccineDetails) { + this.primaryVaccineDetails = primaryVaccineDetails; + } + public AefiOutcome getOutcome() { return outcome; } diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationCriteria.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationCriteria.java new file mode 100644 index 00000000000..f54efee9f85 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationCriteria.java @@ -0,0 +1,240 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import java.io.Serializable; +import java.util.Date; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.EntityRelevanceStatus; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.caze.VaccineManufacturer; +import de.symeda.sormas.api.infrastructure.community.CommunityReferenceDto; +import de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto; +import de.symeda.sormas.api.infrastructure.facility.FacilityReferenceDto; +import de.symeda.sormas.api.infrastructure.facility.FacilityType; +import de.symeda.sormas.api.infrastructure.facility.FacilityTypeGroup; +import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto; +import de.symeda.sormas.api.utils.DateFilterOption; +import de.symeda.sormas.api.utils.criteria.BaseCriteria; + +public class AefiInvestigationCriteria extends BaseCriteria implements Serializable { + + private static final long serialVersionUID = 6520144798481981253L; + + public static final String I18N_PREFIX = "AefiInvestigationCriteria"; + public static final String AEFI_REPORT_LIKE = "aefiReportLike"; + public static final String INVESTIGATION_CASE_ID = "investigationCaseId"; + public static final String DISEASE = "disease"; + public static final String PERSON_LIKE = "personLike"; + public static final String AEFI_TYPE = "aefiType"; + public static final String VACCINE_NAME = "vaccineName"; + public static final String VACCINE_MANUFACTURER = "vaccineManufacturer"; + public static final String REGION = "region"; + public static final String DISTRICT = "district"; + public static final String COMMUNITY = "community"; + public static final String STATUS_ON_DATE_OF_INVESTIGATION = "statusAtAefiInvestigation"; + public static final String AEFI_CLASSIFICATION = "aefiClassification"; + public static final String FACILITY_TYPE_GROUP = "facilityTypeGroup"; + public static final String FACILITY_TYPE = "facilityType"; + public static final String HEALTH_FACILITY = "healthFacility"; + public static final String DATE_FILTER_OPTION = "dateFilterOption"; + public static final String AEFI_DATE_TYPE = "aefiDateType"; + public static final String FROM_DATE = "fromDate"; + public static final String TO_DATE = "toDate"; + public static final String RELEVANCE_STATUS = "relevanceStatus"; + + private String aefiReportLike; + private String investigationCaseId; + private Disease disease; + private String personLike; + private AefiType aefiType; + private Vaccine vaccineName; + private VaccineManufacturer vaccineManufacturer; + private RegionReferenceDto region; + private DistrictReferenceDto district; + private CommunityReferenceDto community; + private PatientStatusAtAefiInvestigation statusAtAefiInvestigation; + private AefiClassification aefiClassification; + private FacilityTypeGroup facilityTypeGroup; + private FacilityType facilityType; + private FacilityReferenceDto healthFacility; + private DateFilterOption dateFilterOption = DateFilterOption.DATE; + private AefiInvestigationDateType aefiInvestigationDateType; + private Date fromDate; + private Date toDate; + private EntityRelevanceStatus relevanceStatus; + + public String getAefiReportLike() { + return aefiReportLike; + } + + public void setAefiReportLike(String aefiReportLike) { + this.aefiReportLike = aefiReportLike; + } + + public String getInvestigationCaseId() { + return investigationCaseId; + } + + public void setInvestigationCaseId(String investigationCaseId) { + this.investigationCaseId = investigationCaseId; + } + + public Disease getDisease() { + return disease; + } + + public void setDisease(Disease disease) { + this.disease = disease; + } + + public String getPersonLike() { + return personLike; + } + + public void setPersonLike(String personLike) { + this.personLike = personLike; + } + + public AefiType getAefiType() { + return aefiType; + } + + public void setAefiType(AefiType aefiType) { + this.aefiType = aefiType; + } + + public Vaccine getVaccineName() { + return vaccineName; + } + + public void setVaccineName(Vaccine vaccineName) { + this.vaccineName = vaccineName; + } + + public VaccineManufacturer getVaccineManufacturer() { + return vaccineManufacturer; + } + + public void setVaccineManufacturer(VaccineManufacturer vaccineManufacturer) { + this.vaccineManufacturer = vaccineManufacturer; + } + + public RegionReferenceDto getRegion() { + return region; + } + + public void setRegion(RegionReferenceDto region) { + this.region = region; + } + + public DistrictReferenceDto getDistrict() { + return district; + } + + public void setDistrict(DistrictReferenceDto district) { + this.district = district; + } + + public CommunityReferenceDto getCommunity() { + return community; + } + + public void setCommunity(CommunityReferenceDto community) { + this.community = community; + } + + public PatientStatusAtAefiInvestigation getStatusAtAefiInvestigation() { + return statusAtAefiInvestigation; + } + + public void setStatusAtAefiInvestigation(PatientStatusAtAefiInvestigation statusAtAefiInvestigation) { + this.statusAtAefiInvestigation = statusAtAefiInvestigation; + } + + public AefiClassification getAefiClassification() { + return aefiClassification; + } + + public void setAefiClassification(AefiClassification aefiClassification) { + this.aefiClassification = aefiClassification; + } + + public FacilityTypeGroup getFacilityTypeGroup() { + return facilityTypeGroup; + } + + public void setFacilityTypeGroup(FacilityTypeGroup facilityTypeGroup) { + this.facilityTypeGroup = facilityTypeGroup; + } + + public FacilityType getFacilityType() { + return facilityType; + } + + public void setFacilityType(FacilityType facilityType) { + this.facilityType = facilityType; + } + + public FacilityReferenceDto getHealthFacility() { + return healthFacility; + } + + public void setHealthFacility(FacilityReferenceDto healthFacility) { + this.healthFacility = healthFacility; + } + + public DateFilterOption getDateFilterOption() { + return dateFilterOption; + } + + public void setDateFilterOption(DateFilterOption dateFilterOption) { + this.dateFilterOption = dateFilterOption; + } + + public AefiInvestigationDateType getAefiInvestigationDateType() { + return aefiInvestigationDateType; + } + + public void setAefiInvestigationDateType(AefiInvestigationDateType aefiInvestigationDateType) { + this.aefiInvestigationDateType = aefiInvestigationDateType; + } + + public Date getFromDate() { + return fromDate; + } + + public void setFromDate(Date fromDate) { + this.fromDate = fromDate; + } + + public Date getToDate() { + return toDate; + } + + public void setToDate(Date toDate) { + this.toDate = toDate; + } + + public EntityRelevanceStatus getRelevanceStatus() { + return relevanceStatus; + } + + public void setRelevanceStatus(EntityRelevanceStatus relevanceStatus) { + this.relevanceStatus = relevanceStatus; + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationDateType.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationDateType.java new file mode 100644 index 00000000000..7d1fb23e605 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationDateType.java @@ -0,0 +1,30 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum AefiInvestigationDateType { + + REPORT_DATE, + INVESTIGATION_DATE, + VACCINATION_DATE; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationDto.java new file mode 100644 index 00000000000..29e8ddd4cb4 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationDto.java @@ -0,0 +1,1684 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Set; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import de.symeda.sormas.api.common.DeletionReason; +import de.symeda.sormas.api.feature.FeatureType; +import de.symeda.sormas.api.i18n.Validations; +import de.symeda.sormas.api.infrastructure.community.CommunityReferenceDto; +import de.symeda.sormas.api.infrastructure.country.CountryReferenceDto; +import de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto; +import de.symeda.sormas.api.infrastructure.facility.FacilityReferenceDto; +import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto; +import de.symeda.sormas.api.location.LocationDto; +import de.symeda.sormas.api.user.UserReferenceDto; +import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.api.utils.DependingOnFeatureType; +import de.symeda.sormas.api.utils.FieldConstraints; +import de.symeda.sormas.api.utils.YesNoUnknown; +import de.symeda.sormas.api.utils.pseudonymization.PseudonymizableDto; +import de.symeda.sormas.api.vaccination.VaccinationDto; + +@DependingOnFeatureType(featureType = { + FeatureType.IMMUNIZATION_MANAGEMENT, + FeatureType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_MANAGEMENT }) +public class AefiInvestigationDto extends PseudonymizableDto { + + private static final long serialVersionUID = 7811960334585576774L; + + public static final long APPROXIMATE_JSON_SIZE_IN_BYTES = 25455; + + public static final String I18N_PREFIX = "AefiInvestigation"; + + public static final String AEFI_REPORT = "aefiReport"; + public static final String ADDRESS = "address"; + public static final String VACCINATIONS = "vaccinations"; + public static final String PRIMARY_SUSPECT_VACCINE = "primarySuspectVaccine"; + public static final String REPORT_DATE = "reportDate"; + public static final String REPORTING_USER = "reportingUser"; + public static final String EXTERNAL_ID = "externalId"; + public static final String RESPONSIBLE_REGION = "responsibleRegion"; + public static final String RESPONSIBLE_DISTRICT = "responsibleDistrict"; + public static final String RESPONSIBLE_COMMUNITY = "responsibleCommunity"; + public static final String COUNTRY = "country"; + public static final String INVESTIGATION_CASE_ID = "investigationCaseId"; + public static final String PLACE_OF_VACCINATION = "placeOfVaccination"; + public static final String PLACE_OF_VACCINATION_DETAILS = "placeOfVaccinationDetails"; + public static final String VACCINATION_ACTIVITY = "vaccinationActivity"; + public static final String VACCINATION_ACTIVITY_DETAILS = "vaccinationActivityDetails"; + public static final String VACCINATION_FACILITY = "vaccinationFacility"; + public static final String VACCINATION_FACILITY_DETAILS = "vaccinationFacilityDetails"; + public static final String REPORTING_OFFICER_NAME = "reportingOfficerName"; + public static final String REPORTING_OFFICER_FACILITY = "reportingOfficerFacility"; + public static final String REPORTING_OFFICER_FACILITY_DETAILS = "reportingOfficerFacilityDetails"; + public static final String REPORTING_OFFICER_DESIGNATION = "reportingOfficerDesignation"; + public static final String REPORTING_OFFICER_DEPARTMENT = "reportingOfficerDepartment"; + public static final String REPORTING_OFFICER_ADDRESS = "reportingOfficerAddress"; + public static final String REPORTING_OFFICER_LANDLINE_PHONE_NUMBER = "reportingOfficerLandlinePhoneNumber"; + public static final String REPORTING_OFFICER_MOBILE_PHONE_NUMBER = "reportingOfficerMobilePhoneNumber"; + public static final String REPORTING_OFFICER_EMAIL = "reportingOfficerEmail"; + public static final String INVESTIGATION_DATE = "investigationDate"; + public static final String FORM_COMPLETION_DATE = "formCompletionDate"; + public static final String INVESTIGATION_STAGE = "investigationStage"; + public static final String TYPE_OF_SITE = "typeOfSite"; + public static final String TYPE_OF_SITE_DETAILS = "typeOfSiteDetails"; + public static final String KEY_SYMPTOM_DATE_TIME = "keySymptomDateTime"; + public static final String HOSPITALIZATION_DATE = "hospitalizationDate"; + public static final String REPORTED_TO_HEALTH_AUTHORITY_DATE = "reportedToHealthAuthorityDate"; + public static final String STATUS_ON_DATE_OF_INVESTIGATION = "statusOnDateOfInvestigation"; + public static final String DEATH_DATE_TIME = "deathDateTime"; + public static final String AUTOPSY_DONE = "autopsyDone"; + public static final String AUTOPSY_DATE = "autopsyDate"; + public static final String AUTOPSY_PLANNED_DATE_TIME = "autopsyPlannedDateTime"; + public static final String PAST_HISTORY_OF_SIMILAR_EVENT = "pastHistoryOfSimilarEvent"; + public static final String PAST_HISTORY_OF_SIMILAR_EVENT_DETAILS = "pastHistoryOfSimilarEventDetails"; + public static final String ADVERSE_EVENT_AFTER_PREVIOUS_VACCINATIONS = "adverseEventAfterPreviousVaccinations"; + public static final String ADVERSE_EVENT_AFTER_PREVIOUS_VACCINATIONS_DETAILS = "adverseEventAfterPreviousVaccinationsDetails"; + public static final String HISTORY_OF_ALLERGY_TO_VACCINE_DRUG_OR_FOOD = "historyOfAllergyToVaccineDrugOrFood"; + public static final String HISTORY_OF_ALLERGY_TO_VACCINE_DRUG_OR_FOOD_DETAILS = "historyOfAllergyToVaccineDrugOrFoodDetails"; + public static final String PRE_EXISTING_ILLNESS_THIRTY_DAYS_OR_CONGENITAL_DISORDER = "preExistingIllnessThirtyDaysOrCongenitalDisorder"; + public static final String PRE_EXISTING_ILLNESS_THIRTY_DAYS_OR_CONGENITAL_DISORDER_DETAILS = + "preExistingIllnessThirtyDaysOrCongenitalDisorderDetails"; + public static final String HISTORY_OF_HOSPITALIZATION_IN_LAST_THIRTY_DAYS_WITH_CAUSE = "historyOfHospitalizationInLastThirtyDaysWithCause"; + public static final String HISTORY_OF_HOSPITALIZATION_IN_LAST_THIRTY_DAYS_WITH_CAUSE_DETAILS = + "historyOfHospitalizationInLastThirtyDaysWithCauseDetails"; + public static final String CURRENTLY_ON_CONCOMITANT_MEDICATION = "currentlyOnConcomitantMedication"; + public static final String CURRENTLY_ON_CONCOMITANT_MEDICATION_DETAILS = "currentlyOnConcomitantMedicationDetails"; + public static final String FAMILY_HISTORY_OF_DISEASE_OR_ALLERGY = "familyHistoryOfDiseaseOrAllergy"; + public static final String FAMILY_HISTORY_OF_DISEASE_OR_ALLERGY_DETAILS = "familyHistoryOfDiseaseOrAllergyDetails"; + public static final String NUMBER_OF_WEEKS_PREGNANT = "numberOfWeeksPregnant"; + public static final String BIRTH_TERM = "birthTerm"; + public static final String BIRTH_WEIGHT = "birthWeight"; + public static final String DELIVERY_PROCEDURE = "deliveryProcedure"; + public static final String DELIVERY_PROCEDURE_DETAILS = "deliveryProcedureDetails"; + public static final String SERIOUS_AEFI_INFO_SOURCE = "seriousAefiInfoSource"; + public static final String SERIOUS_AEFI_INFO_SOURCE_DETAILS = "seriousAefiInfoSourceDetails"; + public static final String SERIOUS_AEFI_VERBAL_AUTOPSY_INFO_SOURCE_DETAILS = "seriousAefiVerbalAutopsyInfoSourceDetails"; + public static final String FIRST_CAREGIVERS_NAME = "firstCaregiversName"; + public static final String OTHER_CAREGIVERS_NAMES = "otherCaregiversNames"; + public static final String OTHER_SOURCES_WHO_PROVIDED_INFO = "otherSourcesWhoProvidedInfo"; + public static final String SIGNS_AND_SYMPTOMS_FROM_TIME_OF_VACCINATION = "signsAndSymptomsFromTimeOfVaccination"; + public static final String CLINICAL_DETAILS_OFFICER_NAME = "clinicalDetailsOfficerName"; + public static final String CLINICAL_DETAILS_OFFICER_PHONE_NUMBER = "clinicalDetailsOfficerPhoneNumber"; + public static final String CLINICAL_DETAILS_OFFICER_EMAIL = "clinicalDetailsOfficerEmail"; + public static final String CLINICAL_DETAILS_OFFICER_DESIGNATION = "clinicalDetailsOfficerDesignation"; + public static final String CLINICAL_DETAILS_DATE_TIME = "clinicalDetailsDateTime"; + public static final String PATIENT_RECEIVED_MEDICAL_CARE = "patientReceivedMedicalCare"; + public static final String PATIENT_RECEIVED_MEDICAL_CARE_DETAILS = "patientReceivedMedicalCareDetails"; + public static final String PROVISIONAL_OR_FINAL_DIAGNOSIS = "provisionalOrFinalDiagnosis"; + public static final String PATIENT_IMMUNIZED_PERIOD = "patientImmunizedPeriod"; + public static final String PATIENT_IMMUNIZED_PERIOD_DETAILS = "patientImmunizedPeriodDetails"; + public static final String VACCINE_GIVEN_PERIOD = "vaccineGivenPeriod"; + public static final String VACCINE_GIVEN_PERIOD_DETAILS = "vaccineGivenPeriodDetails"; + public static final String ERROR_PRESCRIBING_VACCINE = "errorPrescribingVaccine"; + public static final String ERROR_PRESCRIBING_VACCINE_DETAILS = "errorPrescribingVaccineDetails"; + public static final String VACCINE_COULD_HAVE_BEEN_UNSTERILE = "vaccineCouldHaveBeenUnSterile"; + public static final String VACCINE_COULD_HAVE_BEEN_UNSTERILE_DETAILS = "vaccineCouldHaveBeenUnSterileDetails"; + public static final String VACCINE_PHYSICAL_CONDITION_ABNORMAL = "vaccinePhysicalConditionAbnormal"; + public static final String VACCINE_PHYSICAL_CONDITION_ABNORMAL_DETAILS = "vaccinePhysicalConditionAbnormalDetails"; + public static final String ERROR_IN_VACCINE_RECONSTITUTION = "errorInVaccineReconstitution"; + public static final String ERROR_IN_VACCINE_RECONSTITUTION_DETAILS = "errorInVaccineReconstitutionDetails"; + public static final String ERROR_IN_VACCINE_HANDLING = "errorInVaccineHandling"; + public static final String ERROR_IN_VACCINE_HANDLING_DETAILS = "errorInVaccineHandlingDetails"; + public static final String VACCINE_ADMINISTERED_INCORRECTLY = "vaccineAdministeredIncorrectly"; + public static final String VACCINE_ADMINISTERED_INCORRECTLY_DETAILS = "vaccineAdministeredIncorrectlyDetails"; + public static final String NUMBER_IMMUNIZED_FROM_CONCERNED_VACCINE_VIAL = "numberImmunizedFromConcernedVaccineVial"; + public static final String NUMBER_IMMUNIZED_WITH_CONCERNED_VACCINE_IN_SAME_SESSION = "numberImmunizedWithConcernedVaccineInSameSession"; + public static final String NUMBER_IMMUNIZED_CONCERNED_VACCINE_SAME_BATCH_NUMBER_OTHER_LOCATIONS = + "numberImmunizedConcernedVaccineSameBatchNumberOtherLocations"; + public static final String NUMBER_IMMUNIZED_CONCERNED_VACCINE_SAME_BATCH_NUMBER_LOCATION_DETAILS = + "numberImmunizedConcernedVaccineSameBatchNumberLocationDetails"; + public static final String VACCINE_HAS_QUALITY_DEFECT = "vaccineHasQualityDefect"; + public static final String VACCINE_HAS_QUALITY_DEFECT_DETAILS = "vaccineHasQualityDefectDetails"; + public static final String EVENT_IS_A_STRESS_RESPONSE_RELATED_TO_IMMUNIZATION = "eventIsAStressResponseRelatedToImmunization"; + public static final String EVENT_IS_A_STRESS_RESPONSE_RELATED_TO_IMMUNIZATION_DETAILS = "eventIsAStressResponseRelatedToImmunizationDetails"; + public static final String CASE_IS_PART_OF_A_CLUSTER = "caseIsPartOfACluster"; + public static final String CASE_IS_PART_OF_A_CLUSTER_DETAILS = "caseIsPartOfAClusterDetails"; + public static final String NUMBER_OF_CASES_DETECTED_IN_CLUSTER = "numberOfCasesDetectedInCluster"; + public static final String ALL_CASES_IN_CLUSTER_RECEIVED_VACCINE_FROM_SAME_VIAL = "allCasesInClusterReceivedVaccineFromSameVial"; + public static final String ALL_CASES_IN_CLUSTER_RECEIVED_VACCINE_FROM_SAME_VIAL_DETAILS = "allCasesInClusterReceivedVaccineFromSameVialDetails"; + public static final String NUMBER_OF_VIALS_USED_IN_CLUSTER = "numberOfVialsUsedInCluster"; + public static final String NUMBER_OF_VIALS_USED_IN_CLUSTER_DETAILS = "numberOfVialsUsedInClusterDetails"; + public static final String AD_SYRINGES_USED_FOR_IMMUNIZATION = "adSyringesUsedForImmunization"; + public static final String TYPE_OF_SYRINGES_USED = "typeOfSyringesUsed"; + public static final String TYPE_OF_SYRINGES_USED_DETAILS = "typeOfSyringesUsedDetails"; + public static final String SYRINGES_USED_ADDITIONAL_DETAILS = "syringesUsedAdditionalDetails"; + public static final String SAME_RECONSTITUTION_SYRINGE_USED_FOR_MULTIPLE_VIALS_OF_SAME_VACCINE = + "sameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine"; + public static final String SAME_RECONSTITUTION_SYRINGE_USED_FOR_RECONSTITUTING_DIFFERENT_VACCINES = + "sameReconstitutionSyringeUsedForReconstitutingDifferentVaccines"; + public static final String SAME_RECONSTITUTION_SYRINGE_FOR_EACH_VACCINE_VIAL = "sameReconstitutionSyringeForEachVaccineVial"; + public static final String SAME_RECONSTITUTION_SYRINGE_FOR_EACH_VACCINATION = "sameReconstitutionSyringeForEachVaccination"; + public static final String VACCINES_AND_DILUENTS_USED_RECOMMENDED_BY_MANUFACTURER = "vaccinesAndDiluentsUsedRecommendedByManufacturer"; + public static final String RECONSTITUTION_ADDITIONAL_DETAILS = "reconstitutionAdditionalDetails"; + public static final String CORRECT_DOSE_OR_ROUTE = "correctDoseOrRoute"; + public static final String TIME_OF_RECONSTITUTION_MENTIONED_ON_THE_VIAL = "timeOfReconstitutionMentionedOnTheVial"; + public static final String NON_TOUCH_TECHNIQUE_FOLLOWED = "nonTouchTechniqueFollowed"; + public static final String CONTRAINDICATION_SCREENED_PRIOR_TO_VACCINATION = "contraIndicationScreenedPriorToVaccination"; + public static final String NUMBER_OF_AEFI_REPORTED_FROM_VACCINE_DISTRIBUTION_CENTER_LAST_THIRTY_DAYS = + "numberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays"; + public static final String TRAINING_RECEIVED_BY_VACCINATOR = "trainingReceivedByVaccinator"; + public static final String LAST_TRAINING_RECEIVED_BY_VACCINATOR_DATE = "lastTrainingReceivedByVaccinatorDate"; + public static final String INJECTION_TECHNIQUE_ADDITIONAL_DETAILS = "injectionTechniqueAdditionalDetails"; + public static final String VACCINE_STORAGE_REFRIGERATOR_TEMPERATURE_MONITORED = "vaccineStorageRefrigeratorTemperatureMonitored"; + public static final String ANY_STORAGE_TEMPERATURE_DEVIATION_OUTSIDE_TWO_TO_EIGHT_DEGREES = + "anyStorageTemperatureDeviationOutsideTwoToEightDegrees"; + public static final String STORAGE_TEMPERATURE_MONITORING_ADDITIONAL_DETAILS = "storageTemperatureMonitoringAdditionalDetails"; + public static final String CORRECT_PROCEDURE_FOR_STORAGE_FOLLOWED = "correctProcedureForStorageFollowed"; + public static final String ANY_OTHER_ITEM_IN_REFRIGERATOR = "anyOtherItemInRefrigerator"; + public static final String PARTIALLY_USED_RECONSTITUTED_VACCINES_IN_REFRIGERATOR = "partiallyUsedReconstitutedVaccinesInRefrigerator"; + public static final String UNUSABLE_VACCINES_IN_REFRIGERATOR = "unusableVaccinesInRefrigerator"; + public static final String UNUSABLE_DILUENTS_IN_STORE = "unusableDiluentsInStore"; + public static final String VACCINE_STORAGE_POINT_ADDITIONAL_DETAILS = "vaccineStoragePointAdditionalDetails"; + public static final String VACCINE_CARRIER_TYPE = "vaccineCarrierType"; + public static final String VACCINE_CARRIER_TYPE_DETAILS = "vaccineCarrierTypeDetails"; + public static final String VACCINE_CARRIER_SENT_TO_SITE_ON_SAME_DATE_AS_VACCINATION = "vaccineCarrierSentToSiteOnSameDateAsVaccination"; + public static final String VACCINE_CARRIER_RETURNED_FROM_SITE_ON_SAME_DATE_AS_VACCINATION = + "vaccineCarrierReturnedFromSiteOnSameDateAsVaccination"; + public static final String CONDITIONED_ICE_PACK_USED = "conditionedIcepackUsed"; + public static final String VACCINE_TRANSPORTATION_ADDITIONAL_DETAILS = "vaccineTransportationAdditionalDetails"; + public static final String SIMILAR_EVENTS_REPORTED_SAME_PERIOD_AND_LOCALITY = "similarEventsReportedSamePeriodAndLocality"; + public static final String SIMILAR_EVENTS_REPORTED_SAME_PERIOD_AND_LOCALITY_DETAILS = "similarEventsReportedSamePeriodAndLocalityDetails"; + public static final String NUMBER_OF_SIMILAR_EVENTS_REPORTED_SAME_PERIOD_AND_LOCALITY = "numberOfSimilarEventsReportedSamePeriodAndLocality"; + public static final String NUMBER_OF_THOSE_AFFECTED_VACCINATED = "numberOfThoseAffectedVaccinated"; + public static final String NUMBER_OF_THOSE_AFFECTED_NOT_VACCINATED = "numberOfThoseAffectedNotVaccinated"; + public static final String NUMBER_OF_THOSE_AFFECTED_VACCINATED_UNKNOWN = "numberOfThoseAffectedVaccinatedUnknown"; + public static final String COMMUNITY_INVESTIGATION_ADDITIONAL_DETAILS = "communityInvestigationAdditionalDetails"; + public static final String OTHER_INVESTIGATION_FINDINGS = "otherInvestigationFindings"; + public static final String INVESTIGATION_STATUS = "investigationStatus"; + public static final String INVESTIGATION_STATUS_DETAILS = "investigationStatusDetails"; + public static final String AEFI_CLASSIFICATION = "aefiClassification"; + public static final String AEFI_CLASSIFICATION_SUB_TYPE = "aefiClassificationSubType"; + public static final String AEFI_CLASSIFICATION_DETAILS = "aefiClassificationDetails"; + public static final String CAUSALITY = "causality"; + public static final String CAUSALITY_DETAILS = "causalityDetails"; + public static final String INVESTIGATION_COMPLETION_DATE = "investigationCompletionDate"; + public static final String DELETION_REASON = "deletionReason"; + public static final String OTHER_DELETION_REASON = "otherDeletionReason"; + + @NotNull(message = Validations.validAefiReport) + private AefiReferenceDto aefiReport; + private LocationDto address; + @NotEmpty(message = Validations.aefiInvestigationWithoutSuspectVaccines) + private List vaccinations = new ArrayList<>(); + private VaccinationDto primarySuspectVaccine; + private Date reportDate; + private UserReferenceDto reportingUser; + private String externalId; + private RegionReferenceDto responsibleRegion; + private DistrictReferenceDto responsibleDistrict; + private CommunityReferenceDto responsibleCommunity; + private CountryReferenceDto country; + private String investigationCaseId; + private PlaceOfVaccination placeOfVaccination; + private String placeOfVaccinationDetails; + private VaccinationActivity vaccinationActivity; + private String vaccinationActivityDetails; + private FacilityReferenceDto vaccinationFacility; + private String vaccinationFacilityDetails; + private String reportingOfficerName; + private FacilityReferenceDto reportingOfficerFacility; + private String reportingOfficerFacilityDetails; + private String reportingOfficerDesignation; + private String reportingOfficerDepartment; + private LocationDto reportingOfficerAddress; + private String reportingOfficerLandlinePhoneNumber; + private String reportingOfficerMobilePhoneNumber; + private String reportingOfficerEmail; + private Date investigationDate; + private Date formCompletionDate; + private AefiInvestigationStage investigationStage; + private VaccinationSite typeOfSite; + private String typeOfSiteDetails; + private Date keySymptomDateTime; + private Date hospitalizationDate; + private Date reportedToHealthAuthorityDate; + private PatientStatusAtAefiInvestigation statusOnDateOfInvestigation; + private Date deathDateTime; + private YesNoUnknown autopsyDone; + private Date autopsyDate; + private Date autopsyPlannedDateTime; + private YesNoUnknown pastHistoryOfSimilarEvent; + private String pastHistoryOfSimilarEventDetails; + private YesNoUnknown adverseEventAfterPreviousVaccinations; + private String adverseEventAfterPreviousVaccinationsDetails; + private YesNoUnknown historyOfAllergyToVaccineDrugOrFood; + private String historyOfAllergyToVaccineDrugOrFoodDetails; + private YesNoUnknown preExistingIllnessThirtyDaysOrCongenitalDisorder; + private String preExistingIllnessThirtyDaysOrCongenitalDisorderDetails; + private YesNoUnknown historyOfHospitalizationInLastThirtyDaysWithCause; + private String historyOfHospitalizationInLastThirtyDaysWithCauseDetails; + private YesNoUnknown currentlyOnConcomitantMedication; + private String currentlyOnConcomitantMedicationDetails; + private YesNoUnknown familyHistoryOfDiseaseOrAllergy; + private String familyHistoryOfDiseaseOrAllergyDetails; + private Integer numberOfWeeksPregnant; + private BirthTerm birthTerm; + private Float birthWeight; + private DeliveryProcedure deliveryProcedure; + private String deliveryProcedureDetails; + private Set seriousAefiInfoSource; + private String seriousAefiInfoSourceDetails; + private String seriousAefiVerbalAutopsyInfoSourceDetails; + private String firstCaregiversName; + private String otherCaregiversNames; + private String otherSourcesWhoProvidedInfo; + private String signsAndSymptomsFromTimeOfVaccination; + private String clinicalDetailsOfficerName; + private String clinicalDetailsOfficerPhoneNumber; + private String clinicalDetailsOfficerEmail; + private String clinicalDetailsOfficerDesignation; + private Date clinicalDetailsDateTime; + private YesNoUnknown patientReceivedMedicalCare; + private String patientReceivedMedicalCareDetails; + private String provisionalOrFinalDiagnosis; + private AefiImmunizationPeriod patientImmunizedPeriod; + private String patientImmunizedPeriodDetails; + private AefiVaccinationPeriod vaccineGivenPeriod; + private String vaccineGivenPeriodDetails; + private YesNoUnknown errorPrescribingVaccine; + private String errorPrescribingVaccineDetails; + private YesNoUnknown vaccineCouldHaveBeenUnSterile; + private String vaccineCouldHaveBeenUnSterileDetails; + private YesNoUnknown vaccinePhysicalConditionAbnormal; + private String vaccinePhysicalConditionAbnormalDetails; + private YesNoUnknown errorInVaccineReconstitution; + private String errorInVaccineReconstitutionDetails; + private YesNoUnknown errorInVaccineHandling; + private String errorInVaccineHandlingDetails; + private YesNoUnknown vaccineAdministeredIncorrectly; + private String vaccineAdministeredIncorrectlyDetails; + private Integer numberImmunizedFromConcernedVaccineVial; + private Integer numberImmunizedWithConcernedVaccineInSameSession; + private Integer numberImmunizedConcernedVaccineSameBatchNumberOtherLocations; + private String numberImmunizedConcernedVaccineSameBatchNumberLocationDetails; + private YesNoUnknown vaccineHasQualityDefect; + private String vaccineHasQualityDefectDetails; + private YesNoUnknown eventIsAStressResponseRelatedToImmunization; + private String eventIsAStressResponseRelatedToImmunizationDetails; + private YesNoUnknown caseIsPartOfACluster; + private String caseIsPartOfAClusterDetails; + private Integer numberOfCasesDetectedInCluster; + private YesNoUnknown allCasesInClusterReceivedVaccineFromSameVial; + private String allCasesInClusterReceivedVaccineFromSameVialDetails; + private Integer numberOfVialsUsedInCluster; + private String numberOfVialsUsedInClusterDetails; + private YesNoUnknown adSyringesUsedForImmunization; + private SyringeType typeOfSyringesUsed; + private String typeOfSyringesUsedDetails; + private String syringesUsedAdditionalDetails; + private YesNoUnknown sameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine; + private YesNoUnknown sameReconstitutionSyringeUsedForReconstitutingDifferentVaccines; + private YesNoUnknown sameReconstitutionSyringeForEachVaccineVial; + private YesNoUnknown sameReconstitutionSyringeForEachVaccination; + private YesNoUnknown vaccinesAndDiluentsUsedRecommendedByManufacturer; + private String reconstitutionAdditionalDetails; + private YesNoUnknown correctDoseOrRoute; + private YesNoUnknown timeOfReconstitutionMentionedOnTheVial; + private YesNoUnknown nonTouchTechniqueFollowed; + private YesNoUnknown contraIndicationScreenedPriorToVaccination; + private Integer numberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays; + private YesNoUnknown trainingReceivedByVaccinator; + private Date lastTrainingReceivedByVaccinatorDate; + private String injectionTechniqueAdditionalDetails; + private YesNoUnknown vaccineStorageRefrigeratorTemperatureMonitored; + private YesNoUnknown anyStorageTemperatureDeviationOutsideTwoToEightDegrees; + private String storageTemperatureMonitoringAdditionalDetails; + private YesNoUnknown correctProcedureForStorageFollowed; + private YesNoUnknown anyOtherItemInRefrigerator; + private YesNoUnknown partiallyUsedReconstitutedVaccinesInRefrigerator; + private YesNoUnknown unusableVaccinesInRefrigerator; + private YesNoUnknown unusableDiluentsInStore; + private String vaccineStoragePointAdditionalDetails; + private VaccineCarrier vaccineCarrierType; + private String vaccineCarrierTypeDetails; + private YesNoUnknown vaccineCarrierSentToSiteOnSameDateAsVaccination; + private YesNoUnknown vaccineCarrierReturnedFromSiteOnSameDateAsVaccination; + private YesNoUnknown conditionedIcepackUsed; + private String vaccineTransportationAdditionalDetails; + private YesNoUnknown similarEventsReportedSamePeriodAndLocality; + private String similarEventsReportedSamePeriodAndLocalityDetails; + private Integer numberOfSimilarEventsReportedSamePeriodAndLocality; + private Integer numberOfThoseAffectedVaccinated; + private Integer numberOfThoseAffectedNotVaccinated; + private Integer numberOfThoseAffectedVaccinatedUnknown; + private String communityInvestigationAdditionalDetails; + private String otherInvestigationFindings; + private AefiInvestigationStatus investigationStatus; + private String investigationStatusDetails; + private AefiClassification aefiClassification; + private AefiClassificationSubType aefiClassificationSubType; + private String aefiClassificationDetails; + private AefiCausality causality; + private String causalityDetails; + private Date investigationCompletionDate; + private boolean archived; + private boolean deleted; + private DeletionReason deletionReason; + @Size(max = FieldConstraints.CHARACTER_LIMIT_TEXT, message = Validations.textTooLong) + private String otherDeletionReason; + + public static AefiInvestigationDto build(UserReferenceDto user) { + + final AefiInvestigationDto aefiInvestigationDto = new AefiInvestigationDto(); + aefiInvestigationDto.setUuid(DataHelper.createUuid()); + aefiInvestigationDto.setReportingUser(user); + aefiInvestigationDto.setReportDate(new Date()); + + return aefiInvestigationDto; + } + + public static AefiInvestigationDto build(AefiReferenceDto aefiReferenceDto) { + + final AefiInvestigationDto aefiInvestigationDto = new AefiInvestigationDto(); + aefiInvestigationDto.setUuid(DataHelper.createUuid()); + aefiInvestigationDto.setAefiReport(aefiReferenceDto); + aefiInvestigationDto.setReportDate(new Date()); + + return aefiInvestigationDto; + } + + public static AefiInvestigationDto build(AefiInvestigationReferenceDto aefiInvestigationReferenceDto) { + + final AefiInvestigationDto aefiInvestigationDto = new AefiInvestigationDto(); + aefiInvestigationDto.setUuid(aefiInvestigationReferenceDto.getUuid()); + aefiInvestigationDto.setReportDate(new Date()); + + return aefiInvestigationDto; + } + + public AefiInvestigationReferenceDto toReference() { + return new AefiInvestigationReferenceDto(getUuid(), getExternalId()); + } + + public AefiReferenceDto getAefiReport() { + return aefiReport; + } + + public void setAefiReport(AefiReferenceDto aefiReport) { + this.aefiReport = aefiReport; + } + + public LocationDto getAddress() { + return address; + } + + public void setAddress(LocationDto address) { + this.address = address; + } + + public List getVaccinations() { + return vaccinations; + } + + public void setVaccinations(List vaccinations) { + this.vaccinations = vaccinations; + } + + public VaccinationDto getPrimarySuspectVaccine() { + return primarySuspectVaccine; + } + + public void setPrimarySuspectVaccine(VaccinationDto primarySuspectVaccine) { + this.primarySuspectVaccine = primarySuspectVaccine; + } + + public Date getReportDate() { + return reportDate; + } + + public void setReportDate(Date reportDate) { + this.reportDate = reportDate; + } + + public UserReferenceDto getReportingUser() { + return reportingUser; + } + + public void setReportingUser(UserReferenceDto reportingUser) { + this.reportingUser = reportingUser; + } + + public String getExternalId() { + return externalId; + } + + public void setExternalId(String externalId) { + this.externalId = externalId; + } + + public RegionReferenceDto getResponsibleRegion() { + return responsibleRegion; + } + + public void setResponsibleRegion(RegionReferenceDto responsibleRegion) { + this.responsibleRegion = responsibleRegion; + } + + public DistrictReferenceDto getResponsibleDistrict() { + return responsibleDistrict; + } + + public void setResponsibleDistrict(DistrictReferenceDto responsibleDistrict) { + this.responsibleDistrict = responsibleDistrict; + } + + public CommunityReferenceDto getResponsibleCommunity() { + return responsibleCommunity; + } + + public void setResponsibleCommunity(CommunityReferenceDto responsibleCommunity) { + this.responsibleCommunity = responsibleCommunity; + } + + public CountryReferenceDto getCountry() { + return country; + } + + public void setCountry(CountryReferenceDto country) { + this.country = country; + } + + public String getInvestigationCaseId() { + return investigationCaseId; + } + + public void setInvestigationCaseId(String investigationCaseId) { + this.investigationCaseId = investigationCaseId; + } + + public PlaceOfVaccination getPlaceOfVaccination() { + return placeOfVaccination; + } + + public void setPlaceOfVaccination(PlaceOfVaccination placeOfVaccination) { + this.placeOfVaccination = placeOfVaccination; + } + + public String getPlaceOfVaccinationDetails() { + return placeOfVaccinationDetails; + } + + public void setPlaceOfVaccinationDetails(String placeOfVaccinationDetails) { + this.placeOfVaccinationDetails = placeOfVaccinationDetails; + } + + public VaccinationActivity getVaccinationActivity() { + return vaccinationActivity; + } + + public void setVaccinationActivity(VaccinationActivity vaccinationActivity) { + this.vaccinationActivity = vaccinationActivity; + } + + public String getVaccinationActivityDetails() { + return vaccinationActivityDetails; + } + + public void setVaccinationActivityDetails(String vaccinationActivityDetails) { + this.vaccinationActivityDetails = vaccinationActivityDetails; + } + + public FacilityReferenceDto getVaccinationFacility() { + return vaccinationFacility; + } + + public void setVaccinationFacility(FacilityReferenceDto vaccinationFacility) { + this.vaccinationFacility = vaccinationFacility; + } + + public String getVaccinationFacilityDetails() { + return vaccinationFacilityDetails; + } + + public void setVaccinationFacilityDetails(String vaccinationFacilityDetails) { + this.vaccinationFacilityDetails = vaccinationFacilityDetails; + } + + public String getReportingOfficerName() { + return reportingOfficerName; + } + + public void setReportingOfficerName(String reportingOfficerName) { + this.reportingOfficerName = reportingOfficerName; + } + + public FacilityReferenceDto getReportingOfficerFacility() { + return reportingOfficerFacility; + } + + public void setReportingOfficerFacility(FacilityReferenceDto reportingOfficerFacility) { + this.reportingOfficerFacility = reportingOfficerFacility; + } + + public String getReportingOfficerFacilityDetails() { + return reportingOfficerFacilityDetails; + } + + public void setReportingOfficerFacilityDetails(String reportingOfficerFacilityDetails) { + this.reportingOfficerFacilityDetails = reportingOfficerFacilityDetails; + } + + public String getReportingOfficerDesignation() { + return reportingOfficerDesignation; + } + + public void setReportingOfficerDesignation(String reportingOfficerDesignation) { + this.reportingOfficerDesignation = reportingOfficerDesignation; + } + + public String getReportingOfficerDepartment() { + return reportingOfficerDepartment; + } + + public void setReportingOfficerDepartment(String reportingOfficerDepartment) { + this.reportingOfficerDepartment = reportingOfficerDepartment; + } + + public LocationDto getReportingOfficerAddress() { + return reportingOfficerAddress; + } + + public void setReportingOfficerAddress(LocationDto reportingOfficerAddress) { + this.reportingOfficerAddress = reportingOfficerAddress; + } + + public String getReportingOfficerLandlinePhoneNumber() { + return reportingOfficerLandlinePhoneNumber; + } + + public void setReportingOfficerLandlinePhoneNumber(String reportingOfficerLandlinePhoneNumber) { + this.reportingOfficerLandlinePhoneNumber = reportingOfficerLandlinePhoneNumber; + } + + public String getReportingOfficerMobilePhoneNumber() { + return reportingOfficerMobilePhoneNumber; + } + + public void setReportingOfficerMobilePhoneNumber(String reportingOfficerMobilePhoneNumber) { + this.reportingOfficerMobilePhoneNumber = reportingOfficerMobilePhoneNumber; + } + + public String getReportingOfficerEmail() { + return reportingOfficerEmail; + } + + public void setReportingOfficerEmail(String reportingOfficerEmail) { + this.reportingOfficerEmail = reportingOfficerEmail; + } + + public Date getInvestigationDate() { + return investigationDate; + } + + public void setInvestigationDate(Date investigationDate) { + this.investigationDate = investigationDate; + } + + public Date getFormCompletionDate() { + return formCompletionDate; + } + + public void setFormCompletionDate(Date formCompletionDate) { + this.formCompletionDate = formCompletionDate; + } + + public AefiInvestigationStage getInvestigationStage() { + return investigationStage; + } + + public void setInvestigationStage(AefiInvestigationStage investigationStage) { + this.investigationStage = investigationStage; + } + + public VaccinationSite getTypeOfSite() { + return typeOfSite; + } + + public void setTypeOfSite(VaccinationSite typeOfSite) { + this.typeOfSite = typeOfSite; + } + + public String getTypeOfSiteDetails() { + return typeOfSiteDetails; + } + + public void setTypeOfSiteDetails(String typeOfSiteDetails) { + this.typeOfSiteDetails = typeOfSiteDetails; + } + + public Date getKeySymptomDateTime() { + return keySymptomDateTime; + } + + public void setKeySymptomDateTime(Date keySymptomDateTime) { + this.keySymptomDateTime = keySymptomDateTime; + } + + public Date getHospitalizationDate() { + return hospitalizationDate; + } + + public void setHospitalizationDate(Date hospitalizationDate) { + this.hospitalizationDate = hospitalizationDate; + } + + public Date getReportedToHealthAuthorityDate() { + return reportedToHealthAuthorityDate; + } + + public void setReportedToHealthAuthorityDate(Date reportedToHealthAuthorityDate) { + this.reportedToHealthAuthorityDate = reportedToHealthAuthorityDate; + } + + public PatientStatusAtAefiInvestigation getStatusOnDateOfInvestigation() { + return statusOnDateOfInvestigation; + } + + public void setStatusOnDateOfInvestigation(PatientStatusAtAefiInvestigation statusOnDateOfInvestigation) { + this.statusOnDateOfInvestigation = statusOnDateOfInvestigation; + } + + public Date getDeathDateTime() { + return deathDateTime; + } + + public void setDeathDateTime(Date deathDateTime) { + this.deathDateTime = deathDateTime; + } + + public YesNoUnknown getAutopsyDone() { + return autopsyDone; + } + + public void setAutopsyDone(YesNoUnknown autopsyDone) { + this.autopsyDone = autopsyDone; + } + + public Date getAutopsyDate() { + return autopsyDate; + } + + public void setAutopsyDate(Date autopsyDate) { + this.autopsyDate = autopsyDate; + } + + public Date getAutopsyPlannedDateTime() { + return autopsyPlannedDateTime; + } + + public void setAutopsyPlannedDateTime(Date autopsyPlannedDateTime) { + this.autopsyPlannedDateTime = autopsyPlannedDateTime; + } + + public YesNoUnknown getPastHistoryOfSimilarEvent() { + return pastHistoryOfSimilarEvent; + } + + public void setPastHistoryOfSimilarEvent(YesNoUnknown pastHistoryOfSimilarEvent) { + this.pastHistoryOfSimilarEvent = pastHistoryOfSimilarEvent; + } + + public String getPastHistoryOfSimilarEventDetails() { + return pastHistoryOfSimilarEventDetails; + } + + public void setPastHistoryOfSimilarEventDetails(String pastHistoryOfSimilarEventDetails) { + this.pastHistoryOfSimilarEventDetails = pastHistoryOfSimilarEventDetails; + } + + public YesNoUnknown getAdverseEventAfterPreviousVaccinations() { + return adverseEventAfterPreviousVaccinations; + } + + public void setAdverseEventAfterPreviousVaccinations(YesNoUnknown adverseEventAfterPreviousVaccinations) { + this.adverseEventAfterPreviousVaccinations = adverseEventAfterPreviousVaccinations; + } + + public String getAdverseEventAfterPreviousVaccinationsDetails() { + return adverseEventAfterPreviousVaccinationsDetails; + } + + public void setAdverseEventAfterPreviousVaccinationsDetails(String adverseEventAfterPreviousVaccinationsDetails) { + this.adverseEventAfterPreviousVaccinationsDetails = adverseEventAfterPreviousVaccinationsDetails; + } + + public YesNoUnknown getHistoryOfAllergyToVaccineDrugOrFood() { + return historyOfAllergyToVaccineDrugOrFood; + } + + public void setHistoryOfAllergyToVaccineDrugOrFood(YesNoUnknown historyOfAllergyToVaccineDrugOrFood) { + this.historyOfAllergyToVaccineDrugOrFood = historyOfAllergyToVaccineDrugOrFood; + } + + public String getHistoryOfAllergyToVaccineDrugOrFoodDetails() { + return historyOfAllergyToVaccineDrugOrFoodDetails; + } + + public void setHistoryOfAllergyToVaccineDrugOrFoodDetails(String historyOfAllergyToVaccineDrugOrFoodDetails) { + this.historyOfAllergyToVaccineDrugOrFoodDetails = historyOfAllergyToVaccineDrugOrFoodDetails; + } + + public YesNoUnknown getPreExistingIllnessThirtyDaysOrCongenitalDisorder() { + return preExistingIllnessThirtyDaysOrCongenitalDisorder; + } + + public void setPreExistingIllnessThirtyDaysOrCongenitalDisorder(YesNoUnknown preExistingIllnessThirtyDaysOrCongenitalDisorder) { + this.preExistingIllnessThirtyDaysOrCongenitalDisorder = preExistingIllnessThirtyDaysOrCongenitalDisorder; + } + + public String getPreExistingIllnessThirtyDaysOrCongenitalDisorderDetails() { + return preExistingIllnessThirtyDaysOrCongenitalDisorderDetails; + } + + public void setPreExistingIllnessThirtyDaysOrCongenitalDisorderDetails(String preExistingIllnessThirtyDaysOrCongenitalDisorderDetails) { + this.preExistingIllnessThirtyDaysOrCongenitalDisorderDetails = preExistingIllnessThirtyDaysOrCongenitalDisorderDetails; + } + + public YesNoUnknown getHistoryOfHospitalizationInLastThirtyDaysWithCause() { + return historyOfHospitalizationInLastThirtyDaysWithCause; + } + + public void setHistoryOfHospitalizationInLastThirtyDaysWithCause(YesNoUnknown historyOfHospitalizationInLastThirtyDaysWithCause) { + this.historyOfHospitalizationInLastThirtyDaysWithCause = historyOfHospitalizationInLastThirtyDaysWithCause; + } + + public String getHistoryOfHospitalizationInLastThirtyDaysWithCauseDetails() { + return historyOfHospitalizationInLastThirtyDaysWithCauseDetails; + } + + public void setHistoryOfHospitalizationInLastThirtyDaysWithCauseDetails(String historyOfHospitalizationInLastThirtyDaysWithCauseDetails) { + this.historyOfHospitalizationInLastThirtyDaysWithCauseDetails = historyOfHospitalizationInLastThirtyDaysWithCauseDetails; + } + + public YesNoUnknown getCurrentlyOnConcomitantMedication() { + return currentlyOnConcomitantMedication; + } + + public void setCurrentlyOnConcomitantMedication(YesNoUnknown currentlyOnConcomitantMedication) { + this.currentlyOnConcomitantMedication = currentlyOnConcomitantMedication; + } + + public String getCurrentlyOnConcomitantMedicationDetails() { + return currentlyOnConcomitantMedicationDetails; + } + + public void setCurrentlyOnConcomitantMedicationDetails(String currentlyOnConcomitantMedicationDetails) { + this.currentlyOnConcomitantMedicationDetails = currentlyOnConcomitantMedicationDetails; + } + + public YesNoUnknown getFamilyHistoryOfDiseaseOrAllergy() { + return familyHistoryOfDiseaseOrAllergy; + } + + public void setFamilyHistoryOfDiseaseOrAllergy(YesNoUnknown familyHistoryOfDiseaseOrAllergy) { + this.familyHistoryOfDiseaseOrAllergy = familyHistoryOfDiseaseOrAllergy; + } + + public String getFamilyHistoryOfDiseaseOrAllergyDetails() { + return familyHistoryOfDiseaseOrAllergyDetails; + } + + public void setFamilyHistoryOfDiseaseOrAllergyDetails(String familyHistoryOfDiseaseOrAllergyDetails) { + this.familyHistoryOfDiseaseOrAllergyDetails = familyHistoryOfDiseaseOrAllergyDetails; + } + + public Integer getNumberOfWeeksPregnant() { + return numberOfWeeksPregnant; + } + + public void setNumberOfWeeksPregnant(Integer numberOfWeeksPregnant) { + this.numberOfWeeksPregnant = numberOfWeeksPregnant; + } + + public BirthTerm getBirthTerm() { + return birthTerm; + } + + public void setBirthTerm(BirthTerm birthTerm) { + this.birthTerm = birthTerm; + } + + public Float getBirthWeight() { + return birthWeight; + } + + public void setBirthWeight(Float birthWeight) { + this.birthWeight = birthWeight; + } + + public DeliveryProcedure getDeliveryProcedure() { + return deliveryProcedure; + } + + public void setDeliveryProcedure(DeliveryProcedure deliveryProcedure) { + this.deliveryProcedure = deliveryProcedure; + } + + public String getDeliveryProcedureDetails() { + return deliveryProcedureDetails; + } + + public void setDeliveryProcedureDetails(String deliveryProcedureDetails) { + this.deliveryProcedureDetails = deliveryProcedureDetails; + } + + public Set getSeriousAefiInfoSource() { + return seriousAefiInfoSource; + } + + public void setSeriousAefiInfoSource(Set seriousAefiInfoSource) { + this.seriousAefiInfoSource = seriousAefiInfoSource; + } + + public String getSeriousAefiInfoSourceDetails() { + return seriousAefiInfoSourceDetails; + } + + public void setSeriousAefiInfoSourceDetails(String seriousAefiInfoSourceDetails) { + this.seriousAefiInfoSourceDetails = seriousAefiInfoSourceDetails; + } + + public String getSeriousAefiVerbalAutopsyInfoSourceDetails() { + return seriousAefiVerbalAutopsyInfoSourceDetails; + } + + public void setSeriousAefiVerbalAutopsyInfoSourceDetails(String seriousAefiVerbalAutopsyInfoSourceDetails) { + this.seriousAefiVerbalAutopsyInfoSourceDetails = seriousAefiVerbalAutopsyInfoSourceDetails; + } + + public String getFirstCaregiversName() { + return firstCaregiversName; + } + + public void setFirstCaregiversName(String firstCaregiversName) { + this.firstCaregiversName = firstCaregiversName; + } + + public String getOtherCaregiversNames() { + return otherCaregiversNames; + } + + public void setOtherCaregiversNames(String otherCaregiversNames) { + this.otherCaregiversNames = otherCaregiversNames; + } + + public String getOtherSourcesWhoProvidedInfo() { + return otherSourcesWhoProvidedInfo; + } + + public void setOtherSourcesWhoProvidedInfo(String otherSourcesWhoProvidedInfo) { + this.otherSourcesWhoProvidedInfo = otherSourcesWhoProvidedInfo; + } + + public String getSignsAndSymptomsFromTimeOfVaccination() { + return signsAndSymptomsFromTimeOfVaccination; + } + + public void setSignsAndSymptomsFromTimeOfVaccination(String signsAndSymptomsFromTimeOfVaccination) { + this.signsAndSymptomsFromTimeOfVaccination = signsAndSymptomsFromTimeOfVaccination; + } + + public String getClinicalDetailsOfficerName() { + return clinicalDetailsOfficerName; + } + + public void setClinicalDetailsOfficerName(String clinicalDetailsOfficerName) { + this.clinicalDetailsOfficerName = clinicalDetailsOfficerName; + } + + public String getClinicalDetailsOfficerPhoneNumber() { + return clinicalDetailsOfficerPhoneNumber; + } + + public void setClinicalDetailsOfficerPhoneNumber(String clinicalDetailsOfficerPhoneNumber) { + this.clinicalDetailsOfficerPhoneNumber = clinicalDetailsOfficerPhoneNumber; + } + + public String getClinicalDetailsOfficerEmail() { + return clinicalDetailsOfficerEmail; + } + + public void setClinicalDetailsOfficerEmail(String clinicalDetailsOfficerEmail) { + this.clinicalDetailsOfficerEmail = clinicalDetailsOfficerEmail; + } + + public String getClinicalDetailsOfficerDesignation() { + return clinicalDetailsOfficerDesignation; + } + + public void setClinicalDetailsOfficerDesignation(String clinicalDetailsOfficerDesignation) { + this.clinicalDetailsOfficerDesignation = clinicalDetailsOfficerDesignation; + } + + public Date getClinicalDetailsDateTime() { + return clinicalDetailsDateTime; + } + + public void setClinicalDetailsDateTime(Date clinicalDetailsDateTime) { + this.clinicalDetailsDateTime = clinicalDetailsDateTime; + } + + public YesNoUnknown getPatientReceivedMedicalCare() { + return patientReceivedMedicalCare; + } + + public void setPatientReceivedMedicalCare(YesNoUnknown patientReceivedMedicalCare) { + this.patientReceivedMedicalCare = patientReceivedMedicalCare; + } + + public String getPatientReceivedMedicalCareDetails() { + return patientReceivedMedicalCareDetails; + } + + public void setPatientReceivedMedicalCareDetails(String patientReceivedMedicalCareDetails) { + this.patientReceivedMedicalCareDetails = patientReceivedMedicalCareDetails; + } + + public String getProvisionalOrFinalDiagnosis() { + return provisionalOrFinalDiagnosis; + } + + public void setProvisionalOrFinalDiagnosis(String provisionalOrFinalDiagnosis) { + this.provisionalOrFinalDiagnosis = provisionalOrFinalDiagnosis; + } + + public AefiImmunizationPeriod getPatientImmunizedPeriod() { + return patientImmunizedPeriod; + } + + public void setPatientImmunizedPeriod(AefiImmunizationPeriod patientImmunizedPeriod) { + this.patientImmunizedPeriod = patientImmunizedPeriod; + } + + public String getPatientImmunizedPeriodDetails() { + return patientImmunizedPeriodDetails; + } + + public void setPatientImmunizedPeriodDetails(String patientImmunizedPeriodDetails) { + this.patientImmunizedPeriodDetails = patientImmunizedPeriodDetails; + } + + public AefiVaccinationPeriod getVaccineGivenPeriod() { + return vaccineGivenPeriod; + } + + public void setVaccineGivenPeriod(AefiVaccinationPeriod vaccineGivenPeriod) { + this.vaccineGivenPeriod = vaccineGivenPeriod; + } + + public String getVaccineGivenPeriodDetails() { + return vaccineGivenPeriodDetails; + } + + public void setVaccineGivenPeriodDetails(String vaccineGivenPeriodDetails) { + this.vaccineGivenPeriodDetails = vaccineGivenPeriodDetails; + } + + public YesNoUnknown getErrorPrescribingVaccine() { + return errorPrescribingVaccine; + } + + public void setErrorPrescribingVaccine(YesNoUnknown errorPrescribingVaccine) { + this.errorPrescribingVaccine = errorPrescribingVaccine; + } + + public String getErrorPrescribingVaccineDetails() { + return errorPrescribingVaccineDetails; + } + + public void setErrorPrescribingVaccineDetails(String errorPrescribingVaccineDetails) { + this.errorPrescribingVaccineDetails = errorPrescribingVaccineDetails; + } + + public YesNoUnknown getVaccineCouldHaveBeenUnSterile() { + return vaccineCouldHaveBeenUnSterile; + } + + public void setVaccineCouldHaveBeenUnSterile(YesNoUnknown vaccineCouldHaveBeenUnSterile) { + this.vaccineCouldHaveBeenUnSterile = vaccineCouldHaveBeenUnSterile; + } + + public String getVaccineCouldHaveBeenUnSterileDetails() { + return vaccineCouldHaveBeenUnSterileDetails; + } + + public void setVaccineCouldHaveBeenUnSterileDetails(String vaccineCouldHaveBeenUnSterileDetails) { + this.vaccineCouldHaveBeenUnSterileDetails = vaccineCouldHaveBeenUnSterileDetails; + } + + public YesNoUnknown getVaccinePhysicalConditionAbnormal() { + return vaccinePhysicalConditionAbnormal; + } + + public void setVaccinePhysicalConditionAbnormal(YesNoUnknown vaccinePhysicalConditionAbnormal) { + this.vaccinePhysicalConditionAbnormal = vaccinePhysicalConditionAbnormal; + } + + public String getVaccinePhysicalConditionAbnormalDetails() { + return vaccinePhysicalConditionAbnormalDetails; + } + + public void setVaccinePhysicalConditionAbnormalDetails(String vaccinePhysicalConditionAbnormalDetails) { + this.vaccinePhysicalConditionAbnormalDetails = vaccinePhysicalConditionAbnormalDetails; + } + + public YesNoUnknown getErrorInVaccineReconstitution() { + return errorInVaccineReconstitution; + } + + public void setErrorInVaccineReconstitution(YesNoUnknown errorInVaccineReconstitution) { + this.errorInVaccineReconstitution = errorInVaccineReconstitution; + } + + public String getErrorInVaccineReconstitutionDetails() { + return errorInVaccineReconstitutionDetails; + } + + public void setErrorInVaccineReconstitutionDetails(String errorInVaccineReconstitutionDetails) { + this.errorInVaccineReconstitutionDetails = errorInVaccineReconstitutionDetails; + } + + public YesNoUnknown getErrorInVaccineHandling() { + return errorInVaccineHandling; + } + + public void setErrorInVaccineHandling(YesNoUnknown errorInVaccineHandling) { + this.errorInVaccineHandling = errorInVaccineHandling; + } + + public String getErrorInVaccineHandlingDetails() { + return errorInVaccineHandlingDetails; + } + + public void setErrorInVaccineHandlingDetails(String errorInVaccineHandlingDetails) { + this.errorInVaccineHandlingDetails = errorInVaccineHandlingDetails; + } + + public YesNoUnknown getVaccineAdministeredIncorrectly() { + return vaccineAdministeredIncorrectly; + } + + public void setVaccineAdministeredIncorrectly(YesNoUnknown vaccineAdministeredIncorrectly) { + this.vaccineAdministeredIncorrectly = vaccineAdministeredIncorrectly; + } + + public String getVaccineAdministeredIncorrectlyDetails() { + return vaccineAdministeredIncorrectlyDetails; + } + + public void setVaccineAdministeredIncorrectlyDetails(String vaccineAdministeredIncorrectlyDetails) { + this.vaccineAdministeredIncorrectlyDetails = vaccineAdministeredIncorrectlyDetails; + } + + public Integer getNumberImmunizedFromConcernedVaccineVial() { + return numberImmunizedFromConcernedVaccineVial; + } + + public void setNumberImmunizedFromConcernedVaccineVial(Integer numberImmunizedFromConcernedVaccineVial) { + this.numberImmunizedFromConcernedVaccineVial = numberImmunizedFromConcernedVaccineVial; + } + + public Integer getNumberImmunizedWithConcernedVaccineInSameSession() { + return numberImmunizedWithConcernedVaccineInSameSession; + } + + public void setNumberImmunizedWithConcernedVaccineInSameSession(Integer numberImmunizedWithConcernedVaccineInSameSession) { + this.numberImmunizedWithConcernedVaccineInSameSession = numberImmunizedWithConcernedVaccineInSameSession; + } + + public Integer getNumberImmunizedConcernedVaccineSameBatchNumberOtherLocations() { + return numberImmunizedConcernedVaccineSameBatchNumberOtherLocations; + } + + public void setNumberImmunizedConcernedVaccineSameBatchNumberOtherLocations( + Integer numberImmunizedConcernedVaccineSameBatchNumberOtherLocations) { + this.numberImmunizedConcernedVaccineSameBatchNumberOtherLocations = numberImmunizedConcernedVaccineSameBatchNumberOtherLocations; + } + + public String getNumberImmunizedConcernedVaccineSameBatchNumberLocationDetails() { + return numberImmunizedConcernedVaccineSameBatchNumberLocationDetails; + } + + public void setNumberImmunizedConcernedVaccineSameBatchNumberLocationDetails( + String numberImmunizedConcernedVaccineSameBatchNumberLocationDetails) { + this.numberImmunizedConcernedVaccineSameBatchNumberLocationDetails = numberImmunizedConcernedVaccineSameBatchNumberLocationDetails; + } + + public YesNoUnknown getVaccineHasQualityDefect() { + return vaccineHasQualityDefect; + } + + public void setVaccineHasQualityDefect(YesNoUnknown vaccineHasQualityDefect) { + this.vaccineHasQualityDefect = vaccineHasQualityDefect; + } + + public String getVaccineHasQualityDefectDetails() { + return vaccineHasQualityDefectDetails; + } + + public void setVaccineHasQualityDefectDetails(String vaccineHasQualityDefectDetails) { + this.vaccineHasQualityDefectDetails = vaccineHasQualityDefectDetails; + } + + public YesNoUnknown getEventIsAStressResponseRelatedToImmunization() { + return eventIsAStressResponseRelatedToImmunization; + } + + public void setEventIsAStressResponseRelatedToImmunization(YesNoUnknown eventIsAStressResponseRelatedToImmunization) { + this.eventIsAStressResponseRelatedToImmunization = eventIsAStressResponseRelatedToImmunization; + } + + public String getEventIsAStressResponseRelatedToImmunizationDetails() { + return eventIsAStressResponseRelatedToImmunizationDetails; + } + + public void setEventIsAStressResponseRelatedToImmunizationDetails(String eventIsAStressResponseRelatedToImmunizationDetails) { + this.eventIsAStressResponseRelatedToImmunizationDetails = eventIsAStressResponseRelatedToImmunizationDetails; + } + + public YesNoUnknown getCaseIsPartOfACluster() { + return caseIsPartOfACluster; + } + + public void setCaseIsPartOfACluster(YesNoUnknown caseIsPartOfACluster) { + this.caseIsPartOfACluster = caseIsPartOfACluster; + } + + public String getCaseIsPartOfAClusterDetails() { + return caseIsPartOfAClusterDetails; + } + + public void setCaseIsPartOfAClusterDetails(String caseIsPartOfAClusterDetails) { + this.caseIsPartOfAClusterDetails = caseIsPartOfAClusterDetails; + } + + public Integer getNumberOfCasesDetectedInCluster() { + return numberOfCasesDetectedInCluster; + } + + public void setNumberOfCasesDetectedInCluster(Integer numberOfCasesDetectedInCluster) { + this.numberOfCasesDetectedInCluster = numberOfCasesDetectedInCluster; + } + + public YesNoUnknown getAllCasesInClusterReceivedVaccineFromSameVial() { + return allCasesInClusterReceivedVaccineFromSameVial; + } + + public void setAllCasesInClusterReceivedVaccineFromSameVial(YesNoUnknown allCasesInClusterReceivedVaccineFromSameVial) { + this.allCasesInClusterReceivedVaccineFromSameVial = allCasesInClusterReceivedVaccineFromSameVial; + } + + public String getAllCasesInClusterReceivedVaccineFromSameVialDetails() { + return allCasesInClusterReceivedVaccineFromSameVialDetails; + } + + public void setAllCasesInClusterReceivedVaccineFromSameVialDetails(String allCasesInClusterReceivedVaccineFromSameVialDetails) { + this.allCasesInClusterReceivedVaccineFromSameVialDetails = allCasesInClusterReceivedVaccineFromSameVialDetails; + } + + public Integer getNumberOfVialsUsedInCluster() { + return numberOfVialsUsedInCluster; + } + + public void setNumberOfVialsUsedInCluster(Integer numberOfVialsUsedInCluster) { + this.numberOfVialsUsedInCluster = numberOfVialsUsedInCluster; + } + + public String getNumberOfVialsUsedInClusterDetails() { + return numberOfVialsUsedInClusterDetails; + } + + public void setNumberOfVialsUsedInClusterDetails(String numberOfVialsUsedInClusterDetails) { + this.numberOfVialsUsedInClusterDetails = numberOfVialsUsedInClusterDetails; + } + + public YesNoUnknown getAdSyringesUsedForImmunization() { + return adSyringesUsedForImmunization; + } + + public void setAdSyringesUsedForImmunization(YesNoUnknown adSyringesUsedForImmunization) { + this.adSyringesUsedForImmunization = adSyringesUsedForImmunization; + } + + public SyringeType getTypeOfSyringesUsed() { + return typeOfSyringesUsed; + } + + public void setTypeOfSyringesUsed(SyringeType typeOfSyringesUsed) { + this.typeOfSyringesUsed = typeOfSyringesUsed; + } + + public String getTypeOfSyringesUsedDetails() { + return typeOfSyringesUsedDetails; + } + + public void setTypeOfSyringesUsedDetails(String typeOfSyringesUsedDetails) { + this.typeOfSyringesUsedDetails = typeOfSyringesUsedDetails; + } + + public String getSyringesUsedAdditionalDetails() { + return syringesUsedAdditionalDetails; + } + + public void setSyringesUsedAdditionalDetails(String syringesUsedAdditionalDetails) { + this.syringesUsedAdditionalDetails = syringesUsedAdditionalDetails; + } + + public YesNoUnknown getSameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine() { + return sameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine; + } + + public void setSameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine( + YesNoUnknown sameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine) { + this.sameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine = sameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine; + } + + public YesNoUnknown getSameReconstitutionSyringeUsedForReconstitutingDifferentVaccines() { + return sameReconstitutionSyringeUsedForReconstitutingDifferentVaccines; + } + + public void setSameReconstitutionSyringeUsedForReconstitutingDifferentVaccines( + YesNoUnknown sameReconstitutionSyringeUsedForReconstitutingDifferentVaccines) { + this.sameReconstitutionSyringeUsedForReconstitutingDifferentVaccines = sameReconstitutionSyringeUsedForReconstitutingDifferentVaccines; + } + + public YesNoUnknown getSameReconstitutionSyringeForEachVaccineVial() { + return sameReconstitutionSyringeForEachVaccineVial; + } + + public void setSameReconstitutionSyringeForEachVaccineVial(YesNoUnknown sameReconstitutionSyringeForEachVaccineVial) { + this.sameReconstitutionSyringeForEachVaccineVial = sameReconstitutionSyringeForEachVaccineVial; + } + + public YesNoUnknown getSameReconstitutionSyringeForEachVaccination() { + return sameReconstitutionSyringeForEachVaccination; + } + + public void setSameReconstitutionSyringeForEachVaccination(YesNoUnknown sameReconstitutionSyringeForEachVaccination) { + this.sameReconstitutionSyringeForEachVaccination = sameReconstitutionSyringeForEachVaccination; + } + + public YesNoUnknown getVaccinesAndDiluentsUsedRecommendedByManufacturer() { + return vaccinesAndDiluentsUsedRecommendedByManufacturer; + } + + public void setVaccinesAndDiluentsUsedRecommendedByManufacturer(YesNoUnknown vaccinesAndDiluentsUsedRecommendedByManufacturer) { + this.vaccinesAndDiluentsUsedRecommendedByManufacturer = vaccinesAndDiluentsUsedRecommendedByManufacturer; + } + + public String getReconstitutionAdditionalDetails() { + return reconstitutionAdditionalDetails; + } + + public void setReconstitutionAdditionalDetails(String reconstitutionAdditionalDetails) { + this.reconstitutionAdditionalDetails = reconstitutionAdditionalDetails; + } + + public YesNoUnknown getCorrectDoseOrRoute() { + return correctDoseOrRoute; + } + + public void setCorrectDoseOrRoute(YesNoUnknown correctDoseOrRoute) { + this.correctDoseOrRoute = correctDoseOrRoute; + } + + public YesNoUnknown getTimeOfReconstitutionMentionedOnTheVial() { + return timeOfReconstitutionMentionedOnTheVial; + } + + public void setTimeOfReconstitutionMentionedOnTheVial(YesNoUnknown timeOfReconstitutionMentionedOnTheVial) { + this.timeOfReconstitutionMentionedOnTheVial = timeOfReconstitutionMentionedOnTheVial; + } + + public YesNoUnknown getNonTouchTechniqueFollowed() { + return nonTouchTechniqueFollowed; + } + + public void setNonTouchTechniqueFollowed(YesNoUnknown nonTouchTechniqueFollowed) { + this.nonTouchTechniqueFollowed = nonTouchTechniqueFollowed; + } + + public YesNoUnknown getContraIndicationScreenedPriorToVaccination() { + return contraIndicationScreenedPriorToVaccination; + } + + public void setContraIndicationScreenedPriorToVaccination(YesNoUnknown contraIndicationScreenedPriorToVaccination) { + this.contraIndicationScreenedPriorToVaccination = contraIndicationScreenedPriorToVaccination; + } + + public Integer getNumberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays() { + return numberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays; + } + + public void setNumberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays( + Integer numberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays) { + this.numberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays = numberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays; + } + + public YesNoUnknown getTrainingReceivedByVaccinator() { + return trainingReceivedByVaccinator; + } + + public void setTrainingReceivedByVaccinator(YesNoUnknown trainingReceivedByVaccinator) { + this.trainingReceivedByVaccinator = trainingReceivedByVaccinator; + } + + public Date getLastTrainingReceivedByVaccinatorDate() { + return lastTrainingReceivedByVaccinatorDate; + } + + public void setLastTrainingReceivedByVaccinatorDate(Date lastTrainingReceivedByVaccinatorDate) { + this.lastTrainingReceivedByVaccinatorDate = lastTrainingReceivedByVaccinatorDate; + } + + public String getInjectionTechniqueAdditionalDetails() { + return injectionTechniqueAdditionalDetails; + } + + public void setInjectionTechniqueAdditionalDetails(String injectionTechniqueAdditionalDetails) { + this.injectionTechniqueAdditionalDetails = injectionTechniqueAdditionalDetails; + } + + public YesNoUnknown getVaccineStorageRefrigeratorTemperatureMonitored() { + return vaccineStorageRefrigeratorTemperatureMonitored; + } + + public void setVaccineStorageRefrigeratorTemperatureMonitored(YesNoUnknown vaccineStorageRefrigeratorTemperatureMonitored) { + this.vaccineStorageRefrigeratorTemperatureMonitored = vaccineStorageRefrigeratorTemperatureMonitored; + } + + public YesNoUnknown getAnyStorageTemperatureDeviationOutsideTwoToEightDegrees() { + return anyStorageTemperatureDeviationOutsideTwoToEightDegrees; + } + + public void setAnyStorageTemperatureDeviationOutsideTwoToEightDegrees(YesNoUnknown anyStorageTemperatureDeviationOutsideTwoToEightDegrees) { + this.anyStorageTemperatureDeviationOutsideTwoToEightDegrees = anyStorageTemperatureDeviationOutsideTwoToEightDegrees; + } + + public String getStorageTemperatureMonitoringAdditionalDetails() { + return storageTemperatureMonitoringAdditionalDetails; + } + + public void setStorageTemperatureMonitoringAdditionalDetails(String storageTemperatureMonitoringAdditionalDetails) { + this.storageTemperatureMonitoringAdditionalDetails = storageTemperatureMonitoringAdditionalDetails; + } + + public YesNoUnknown getCorrectProcedureForStorageFollowed() { + return correctProcedureForStorageFollowed; + } + + public void setCorrectProcedureForStorageFollowed(YesNoUnknown correctProcedureForStorageFollowed) { + this.correctProcedureForStorageFollowed = correctProcedureForStorageFollowed; + } + + public YesNoUnknown getAnyOtherItemInRefrigerator() { + return anyOtherItemInRefrigerator; + } + + public void setAnyOtherItemInRefrigerator(YesNoUnknown anyOtherItemInRefrigerator) { + this.anyOtherItemInRefrigerator = anyOtherItemInRefrigerator; + } + + public YesNoUnknown getPartiallyUsedReconstitutedVaccinesInRefrigerator() { + return partiallyUsedReconstitutedVaccinesInRefrigerator; + } + + public void setPartiallyUsedReconstitutedVaccinesInRefrigerator(YesNoUnknown partiallyUsedReconstitutedVaccinesInRefrigerator) { + this.partiallyUsedReconstitutedVaccinesInRefrigerator = partiallyUsedReconstitutedVaccinesInRefrigerator; + } + + public YesNoUnknown getUnusableVaccinesInRefrigerator() { + return unusableVaccinesInRefrigerator; + } + + public void setUnusableVaccinesInRefrigerator(YesNoUnknown unusableVaccinesInRefrigerator) { + this.unusableVaccinesInRefrigerator = unusableVaccinesInRefrigerator; + } + + public YesNoUnknown getUnusableDiluentsInStore() { + return unusableDiluentsInStore; + } + + public void setUnusableDiluentsInStore(YesNoUnknown unusableDiluentsInStore) { + this.unusableDiluentsInStore = unusableDiluentsInStore; + } + + public String getVaccineStoragePointAdditionalDetails() { + return vaccineStoragePointAdditionalDetails; + } + + public void setVaccineStoragePointAdditionalDetails(String vaccineStoragePointAdditionalDetails) { + this.vaccineStoragePointAdditionalDetails = vaccineStoragePointAdditionalDetails; + } + + public VaccineCarrier getVaccineCarrierType() { + return vaccineCarrierType; + } + + public void setVaccineCarrierType(VaccineCarrier vaccineCarrierType) { + this.vaccineCarrierType = vaccineCarrierType; + } + + public String getVaccineCarrierTypeDetails() { + return vaccineCarrierTypeDetails; + } + + public void setVaccineCarrierTypeDetails(String vaccineCarrierTypeDetails) { + this.vaccineCarrierTypeDetails = vaccineCarrierTypeDetails; + } + + public YesNoUnknown getVaccineCarrierSentToSiteOnSameDateAsVaccination() { + return vaccineCarrierSentToSiteOnSameDateAsVaccination; + } + + public void setVaccineCarrierSentToSiteOnSameDateAsVaccination(YesNoUnknown vaccineCarrierSentToSiteOnSameDateAsVaccination) { + this.vaccineCarrierSentToSiteOnSameDateAsVaccination = vaccineCarrierSentToSiteOnSameDateAsVaccination; + } + + public YesNoUnknown getVaccineCarrierReturnedFromSiteOnSameDateAsVaccination() { + return vaccineCarrierReturnedFromSiteOnSameDateAsVaccination; + } + + public void setVaccineCarrierReturnedFromSiteOnSameDateAsVaccination(YesNoUnknown vaccineCarrierReturnedFromSiteOnSameDateAsVaccination) { + this.vaccineCarrierReturnedFromSiteOnSameDateAsVaccination = vaccineCarrierReturnedFromSiteOnSameDateAsVaccination; + } + + public YesNoUnknown getConditionedIcepackUsed() { + return conditionedIcepackUsed; + } + + public void setConditionedIcepackUsed(YesNoUnknown conditionedIcepackUsed) { + this.conditionedIcepackUsed = conditionedIcepackUsed; + } + + public String getVaccineTransportationAdditionalDetails() { + return vaccineTransportationAdditionalDetails; + } + + public void setVaccineTransportationAdditionalDetails(String vaccineTransportationAdditionalDetails) { + this.vaccineTransportationAdditionalDetails = vaccineTransportationAdditionalDetails; + } + + public YesNoUnknown getSimilarEventsReportedSamePeriodAndLocality() { + return similarEventsReportedSamePeriodAndLocality; + } + + public void setSimilarEventsReportedSamePeriodAndLocality(YesNoUnknown similarEventsReportedSamePeriodAndLocality) { + this.similarEventsReportedSamePeriodAndLocality = similarEventsReportedSamePeriodAndLocality; + } + + public String getSimilarEventsReportedSamePeriodAndLocalityDetails() { + return similarEventsReportedSamePeriodAndLocalityDetails; + } + + public void setSimilarEventsReportedSamePeriodAndLocalityDetails(String similarEventsReportedSamePeriodAndLocalityDetails) { + this.similarEventsReportedSamePeriodAndLocalityDetails = similarEventsReportedSamePeriodAndLocalityDetails; + } + + public Integer getNumberOfSimilarEventsReportedSamePeriodAndLocality() { + return numberOfSimilarEventsReportedSamePeriodAndLocality; + } + + public void setNumberOfSimilarEventsReportedSamePeriodAndLocality(Integer numberOfSimilarEventsReportedSamePeriodAndLocality) { + this.numberOfSimilarEventsReportedSamePeriodAndLocality = numberOfSimilarEventsReportedSamePeriodAndLocality; + } + + public Integer getNumberOfThoseAffectedVaccinated() { + return numberOfThoseAffectedVaccinated; + } + + public void setNumberOfThoseAffectedVaccinated(Integer numberOfThoseAffectedVaccinated) { + this.numberOfThoseAffectedVaccinated = numberOfThoseAffectedVaccinated; + } + + public Integer getNumberOfThoseAffectedNotVaccinated() { + return numberOfThoseAffectedNotVaccinated; + } + + public void setNumberOfThoseAffectedNotVaccinated(Integer numberOfThoseAffectedNotVaccinated) { + this.numberOfThoseAffectedNotVaccinated = numberOfThoseAffectedNotVaccinated; + } + + public Integer getNumberOfThoseAffectedVaccinatedUnknown() { + return numberOfThoseAffectedVaccinatedUnknown; + } + + public void setNumberOfThoseAffectedVaccinatedUnknown(Integer numberOfThoseAffectedVaccinatedUnknown) { + this.numberOfThoseAffectedVaccinatedUnknown = numberOfThoseAffectedVaccinatedUnknown; + } + + public String getCommunityInvestigationAdditionalDetails() { + return communityInvestigationAdditionalDetails; + } + + public void setCommunityInvestigationAdditionalDetails(String communityInvestigationAdditionalDetails) { + this.communityInvestigationAdditionalDetails = communityInvestigationAdditionalDetails; + } + + public String getOtherInvestigationFindings() { + return otherInvestigationFindings; + } + + public void setOtherInvestigationFindings(String otherInvestigationFindings) { + this.otherInvestigationFindings = otherInvestigationFindings; + } + + public AefiInvestigationStatus getInvestigationStatus() { + return investigationStatus; + } + + public void setInvestigationStatus(AefiInvestigationStatus investigationStatus) { + this.investigationStatus = investigationStatus; + } + + public String getInvestigationStatusDetails() { + return investigationStatusDetails; + } + + public void setInvestigationStatusDetails(String investigationStatusDetails) { + this.investigationStatusDetails = investigationStatusDetails; + } + + public AefiClassification getAefiClassification() { + return aefiClassification; + } + + public void setAefiClassification(AefiClassification aefiClassification) { + this.aefiClassification = aefiClassification; + } + + public AefiClassificationSubType getAefiClassificationSubType() { + return aefiClassificationSubType; + } + + public void setAefiClassificationSubType(AefiClassificationSubType aefiClassificationSubType) { + this.aefiClassificationSubType = aefiClassificationSubType; + } + + public String getAefiClassificationDetails() { + return aefiClassificationDetails; + } + + public void setAefiClassificationDetails(String aefiClassificationDetails) { + this.aefiClassificationDetails = aefiClassificationDetails; + } + + public AefiCausality getCausality() { + return causality; + } + + public void setCausality(AefiCausality causality) { + this.causality = causality; + } + + public String getCausalityDetails() { + return causalityDetails; + } + + public void setCausalityDetails(String causalityDetails) { + this.causalityDetails = causalityDetails; + } + + public Date getInvestigationCompletionDate() { + return investigationCompletionDate; + } + + public void setInvestigationCompletionDate(Date investigationCompletionDate) { + this.investigationCompletionDate = investigationCompletionDate; + } + + public boolean isArchived() { + return archived; + } + + public void setArchived(boolean archived) { + this.archived = archived; + } + + public boolean isDeleted() { + return deleted; + } + + public void setDeleted(boolean deleted) { + this.deleted = deleted; + } + + public DeletionReason getDeletionReason() { + return deletionReason; + } + + public void setDeletionReason(DeletionReason deletionReason) { + this.deletionReason = deletionReason; + } + + public String getOtherDeletionReason() { + return otherDeletionReason; + } + + public void setOtherDeletionReason(String otherDeletionReason) { + this.otherDeletionReason = otherDeletionReason; + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationFacade.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationFacade.java new file mode 100644 index 00000000000..1fff4591f78 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationFacade.java @@ -0,0 +1,29 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import java.util.List; + +import javax.ejb.Remote; + +import de.symeda.sormas.api.CoreFacade; + +@Remote +public interface AefiInvestigationFacade + extends CoreFacade { + + List getEntriesList(AefiInvestigationListCriteria criteria, Integer first, Integer max); +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationIndexDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationIndexDto.java new file mode 100644 index 00000000000..635e82c75da --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationIndexDto.java @@ -0,0 +1,372 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import java.io.Serializable; +import java.util.Date; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.caze.AgeAndBirthDateDto; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.common.DeletionReason; +import de.symeda.sormas.api.person.Sex; +import de.symeda.sormas.api.utils.PersonalData; +import de.symeda.sormas.api.utils.SensitiveData; +import de.symeda.sormas.api.utils.pseudonymization.PseudonymizableIndexDto; + +public class AefiInvestigationIndexDto extends PseudonymizableIndexDto implements Serializable, Cloneable { + + private static final long serialVersionUID = 5659752736289073666L; + + public static final String I18N_PREFIX = "AefiInvestigationIndex"; + + public static final String UUID = "uuid"; + public static final String AEFI_REPORT_UUID = "aefiReportUuid"; + public static final String INVESTIGATION_CASE_ID = "investigationCaseId"; + public static final String DISEASE = "disease"; + public static final String PERSON_FIRST_NAME = "personFirstName"; + public static final String PERSON_LAST_NAME = "personLastName"; + public static final String AGE_AND_BIRTH_DATE = "ageAndBirthDate"; + public static final String SEX = "sex"; + public static final String REGION = "region"; + public static final String DISTRICT = "district"; + public static final String PLACE_OF_VACCINATION = "placeOfVaccination"; + public static final String VACCINATION_ACTIVITY = "vaccinationActivity"; + public static final String ADVERSE_EVENT_REPORT_DATE = "adverseEventReportDate"; + public static final String REPORT_DATE = "reportDate"; + public static final String INVESTIGATION_DATE = "investigationDate"; + public static final String INVESTIGATION_STAGE = "investigationStage"; + public static final String TYPE_OF_SITE = "typeOfSite"; + public static final String KEY_SYMPTOM_DATE_TIME = "keySymptomDateTime"; + public static final String HOSPITALIZATION_DATE = "hospitalizationDate"; + public static final String REPORTED_TO_HEALTH_AUTHORITY_DATE = "reportedToHealthAuthorityDate"; + public static final String STATUS_ON_DATE_OF_INVESTIGATION = "statusOnDateOfInvestigation"; + public static final String PRIMARY_VACCINE_NAME = "primaryVaccine"; + public static final String PRIMARY_VACCINE_DETAILS = "primaryVaccineDetails"; + public static final String INVESTIGATION_STATUS = "investigationStatus"; + public static final String AEFI_CLASSIFICATION = "aefiClassification"; + public static final String DELETION_REASON = "deletionReason"; + + private String aefiReportUuid; + private String investigationCaseId; + private Disease disease; + @PersonalData + @SensitiveData + private String personFirstName; + @PersonalData + @SensitiveData + private String personLastName; + private AgeAndBirthDateDto ageAndBirthDate; + private Sex sex; + private String region; + private String district; + private PlaceOfVaccination placeOfVaccination; + private VaccinationActivity vaccinationActivity; + private Date aefiReportDate; + private Date reportDate; + private Date investigationDate; + private AefiInvestigationStage investigationStage; + private VaccinationSite typeOfSite; + private Date keySymptomDateTime; + private Date hospitalizationDate; + private Date reportedToHealthAuthorityDate; + private PatientStatusAtAefiInvestigation statusOnDateOfInvestigation; + private Vaccine primaryVaccine; + private String primaryVaccineDetails; + private AefiInvestigationStatus investigationStatus; + private AefiClassification aefiClassification; + private DeletionReason deletionReason; + private String otherDeletionReason; + private boolean isInJurisdiction; + + public AefiInvestigationIndexDto( + String uuid, + String aefiReportUuid, + String investigationCaseId, + Disease disease, + String personFirstName, + String personLastName, + AgeAndBirthDateDto ageAndBirthDate, + Sex sex, + String region, + String district, + PlaceOfVaccination placeOfVaccination, + VaccinationActivity vaccinationActivity, + Date aefiReportDate, + Date reportDate, + Date investigationDate, + AefiInvestigationStage investigationStage, + VaccinationSite typeOfSite, + Date keySymptomDateTime, + Date hospitalizationDate, + Date reportedToHealthAuthorityDate, + PatientStatusAtAefiInvestigation statusOnDateOfInvestigation, + Vaccine primaryVaccine, + String primaryVaccineDetails, + AefiInvestigationStatus investigationStatus, + AefiClassification aefiClassification, + DeletionReason deletionReason, + String otherDeletionReason, + boolean isInJurisdiction) { + + super(uuid); + this.aefiReportUuid = aefiReportUuid; + this.investigationCaseId = investigationCaseId; + this.disease = disease; + this.personFirstName = personFirstName; + this.personLastName = personLastName; + this.ageAndBirthDate = ageAndBirthDate; + this.sex = sex; + this.region = region; + this.district = district; + this.placeOfVaccination = placeOfVaccination; + this.vaccinationActivity = vaccinationActivity; + this.aefiReportDate = aefiReportDate; + this.reportDate = reportDate; + this.investigationDate = investigationDate; + this.investigationStage = investigationStage; + this.typeOfSite = typeOfSite; + this.keySymptomDateTime = keySymptomDateTime; + this.hospitalizationDate = hospitalizationDate; + this.reportedToHealthAuthorityDate = reportedToHealthAuthorityDate; + this.statusOnDateOfInvestigation = statusOnDateOfInvestigation; + this.primaryVaccine = primaryVaccine; + this.primaryVaccineDetails = primaryVaccineDetails; + this.investigationStatus = investigationStatus; + this.aefiClassification = aefiClassification; + this.deletionReason = deletionReason; + this.otherDeletionReason = otherDeletionReason; + this.isInJurisdiction = isInJurisdiction; + } + + public String getAefiReportUuid() { + return aefiReportUuid; + } + + public void setAefiReportUuid(String aefiReportUuid) { + this.aefiReportUuid = aefiReportUuid; + } + + public String getInvestigationCaseId() { + return investigationCaseId; + } + + public void setInvestigationCaseId(String investigationCaseId) { + this.investigationCaseId = investigationCaseId; + } + + public Disease getDisease() { + return disease; + } + + public void setDisease(Disease disease) { + this.disease = disease; + } + + public String getPersonFirstName() { + return personFirstName; + } + + public void setPersonFirstName(String personFirstName) { + this.personFirstName = personFirstName; + } + + public String getPersonLastName() { + return personLastName; + } + + public void setPersonLastName(String personLastName) { + this.personLastName = personLastName; + } + + public AgeAndBirthDateDto getAgeAndBirthDate() { + return ageAndBirthDate; + } + + public void setAgeAndBirthDate(AgeAndBirthDateDto ageAndBirthDate) { + this.ageAndBirthDate = ageAndBirthDate; + } + + public Sex getSex() { + return sex; + } + + public void setSex(Sex sex) { + this.sex = sex; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public String getDistrict() { + return district; + } + + public void setDistrict(String district) { + this.district = district; + } + + public PlaceOfVaccination getPlaceOfVaccination() { + return placeOfVaccination; + } + + public void setPlaceOfVaccination(PlaceOfVaccination placeOfVaccination) { + this.placeOfVaccination = placeOfVaccination; + } + + public VaccinationActivity getVaccinationActivity() { + return vaccinationActivity; + } + + public void setVaccinationActivity(VaccinationActivity vaccinationActivity) { + this.vaccinationActivity = vaccinationActivity; + } + + public Date getAefiReportDate() { + return aefiReportDate; + } + + public void setAefiReportDate(Date aefiReportDate) { + this.aefiReportDate = aefiReportDate; + } + + public Date getReportDate() { + return reportDate; + } + + public void setReportDate(Date reportDate) { + this.reportDate = reportDate; + } + + public Date getInvestigationDate() { + return investigationDate; + } + + public void setInvestigationDate(Date investigationDate) { + this.investigationDate = investigationDate; + } + + public AefiInvestigationStage getInvestigationStage() { + return investigationStage; + } + + public void setInvestigationStage(AefiInvestigationStage investigationStage) { + this.investigationStage = investigationStage; + } + + public VaccinationSite getTypeOfSite() { + return typeOfSite; + } + + public void setTypeOfSite(VaccinationSite typeOfSite) { + this.typeOfSite = typeOfSite; + } + + public Date getKeySymptomDateTime() { + return keySymptomDateTime; + } + + public void setKeySymptomDateTime(Date keySymptomDateTime) { + this.keySymptomDateTime = keySymptomDateTime; + } + + public Date getHospitalizationDate() { + return hospitalizationDate; + } + + public void setHospitalizationDate(Date hospitalizationDate) { + this.hospitalizationDate = hospitalizationDate; + } + + public Date getReportedToHealthAuthorityDate() { + return reportedToHealthAuthorityDate; + } + + public void setReportedToHealthAuthorityDate(Date reportedToHealthAuthorityDate) { + this.reportedToHealthAuthorityDate = reportedToHealthAuthorityDate; + } + + public PatientStatusAtAefiInvestigation getStatusOnDateOfInvestigation() { + return statusOnDateOfInvestigation; + } + + public void setStatusOnDateOfInvestigation(PatientStatusAtAefiInvestigation statusOnDateOfInvestigation) { + this.statusOnDateOfInvestigation = statusOnDateOfInvestigation; + } + + public Vaccine getPrimaryVaccine() { + return primaryVaccine; + } + + public void setPrimaryVaccine(Vaccine primaryVaccine) { + this.primaryVaccine = primaryVaccine; + } + + public String getPrimaryVaccineDetails() { + return primaryVaccineDetails; + } + + public void setPrimaryVaccineDetails(String primaryVaccineDetails) { + this.primaryVaccineDetails = primaryVaccineDetails; + } + + public AefiInvestigationStatus getInvestigationStatus() { + return investigationStatus; + } + + public void setInvestigationStatus(AefiInvestigationStatus investigationStatus) { + this.investigationStatus = investigationStatus; + } + + public AefiClassification getAefiClassification() { + return aefiClassification; + } + + public void setAefiClassification(AefiClassification aefiClassification) { + this.aefiClassification = aefiClassification; + } + + public DeletionReason getDeletionReason() { + return deletionReason; + } + + public void setDeletionReason(DeletionReason deletionReason) { + this.deletionReason = deletionReason; + } + + public String getOtherDeletionReason() { + return otherDeletionReason; + } + + public void setOtherDeletionReason(String otherDeletionReason) { + this.otherDeletionReason = otherDeletionReason; + } + + @Override + public boolean isInJurisdiction() { + return isInJurisdiction; + } + + @Override + public void setInJurisdiction(boolean inJurisdiction) { + isInJurisdiction = inJurisdiction; + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationListCriteria.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationListCriteria.java new file mode 100644 index 00000000000..c150fb25e81 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationListCriteria.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.api.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.utils.criteria.BaseCriteria; + +public class AefiInvestigationListCriteria extends BaseCriteria { + + private final AefiReferenceDto aefiReport; + + public static class Builder { + + private final AefiReferenceDto aefiReferenceDto; + + public Builder(AefiReferenceDto aefiReferenceDto) { + this.aefiReferenceDto = aefiReferenceDto; + } + + public AefiInvestigationListCriteria build() { + return new AefiInvestigationListCriteria(this); + } + } + + private AefiInvestigationListCriteria(AefiInvestigationListCriteria.Builder builder) { + this.aefiReport = builder.aefiReferenceDto; + } + + public AefiReferenceDto getAefiReport() { + return aefiReport; + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationListEntryDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationListEntryDto.java new file mode 100644 index 00000000000..7282075e79a --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationListEntryDto.java @@ -0,0 +1,156 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import java.io.Serializable; +import java.util.Date; + +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.utils.pseudonymization.PseudonymizableIndexDto; + +public class AefiInvestigationListEntryDto extends PseudonymizableIndexDto implements Serializable, Cloneable { + + public static final String I18N_PREFIX = "AefiInvestigationListEntry"; + + public static final String UUID = "uuid"; + public static final String INVESTIGATION_CASE_ID = "investigationCaseId"; + public static final String INVESTIGATION_DATE = "investigationDate"; + public static final String INVESTIGATION_STAGE = "investigationStage"; + public static final String STATUS_ON_DATE_OF_INVESTIGATION = "statusOnDateOfInvestigation"; + public static final String PRIMARY_VACCINE_NAME = "primaryVaccine"; + public static final String PRIMARY_VACCINE_DETAILS = "primaryVaccineDetails"; + public static final String PRIMARY_VACCINE_DOSE = "primaryVaccineDose"; + public static final String PRIMARY_VACCINE_VACCINATION_DATE = "primaryVaccineVaccinationDate"; + public static final String INVESTIGATION_STATUS = "investigationStatus"; + public static final String AEFI_CLASSIFICATION = "aefiClassification"; + + private String investigationCaseId; + private Date investigationDate; + private AefiInvestigationStage investigationStage; + private PatientStatusAtAefiInvestigation statusOnDateOfInvestigation; + private Vaccine primaryVaccine; + private String primaryVaccineDetails; + private String primaryVaccineDose; + private Date primaryVaccineVaccinationDate; + private AefiInvestigationStatus investigationStatus; + private AefiClassification aefiClassification; + + public AefiInvestigationListEntryDto( + String uuid, + String investigationCaseId, + Date investigationDate, + AefiInvestigationStage investigationStage, + PatientStatusAtAefiInvestigation statusOnDateOfInvestigation, + Vaccine primaryVaccine, + String primaryVaccineDetails, + String primaryVaccineDose, + Date primaryVaccineVaccinationDate, + AefiInvestigationStatus investigationStatus, + AefiClassification aefiClassification) { + + super(uuid); + this.investigationCaseId = investigationCaseId; + this.investigationDate = investigationDate; + this.investigationStage = investigationStage; + this.statusOnDateOfInvestigation = statusOnDateOfInvestigation; + this.primaryVaccine = primaryVaccine; + this.primaryVaccineDetails = primaryVaccineDetails; + this.primaryVaccineDose = primaryVaccineDose; + this.primaryVaccineVaccinationDate = primaryVaccineVaccinationDate; + this.investigationStatus = investigationStatus; + this.aefiClassification = aefiClassification; + } + + public String getInvestigationCaseId() { + return investigationCaseId; + } + + public void setInvestigationCaseId(String investigationCaseId) { + this.investigationCaseId = investigationCaseId; + } + + public Date getInvestigationDate() { + return investigationDate; + } + + public void setInvestigationDate(Date investigationDate) { + this.investigationDate = investigationDate; + } + + public AefiInvestigationStage getInvestigationStage() { + return investigationStage; + } + + public void setInvestigationStage(AefiInvestigationStage investigationStage) { + this.investigationStage = investigationStage; + } + + public PatientStatusAtAefiInvestigation getStatusOnDateOfInvestigation() { + return statusOnDateOfInvestigation; + } + + public void setStatusOnDateOfInvestigation(PatientStatusAtAefiInvestigation statusOnDateOfInvestigation) { + this.statusOnDateOfInvestigation = statusOnDateOfInvestigation; + } + + public Vaccine getPrimaryVaccine() { + return primaryVaccine; + } + + public void setPrimaryVaccine(Vaccine primaryVaccine) { + this.primaryVaccine = primaryVaccine; + } + + public String getPrimaryVaccineDetails() { + return primaryVaccineDetails; + } + + public void setPrimaryVaccineDetails(String primaryVaccineDetails) { + this.primaryVaccineDetails = primaryVaccineDetails; + } + + public String getPrimaryVaccineDose() { + return primaryVaccineDose; + } + + public void setPrimaryVaccineDose(String primaryVaccineDose) { + this.primaryVaccineDose = primaryVaccineDose; + } + + public Date getPrimaryVaccineVaccinationDate() { + return primaryVaccineVaccinationDate; + } + + public void setPrimaryVaccineVaccinationDate(Date primaryVaccineVaccinationDate) { + this.primaryVaccineVaccinationDate = primaryVaccineVaccinationDate; + } + + public AefiInvestigationStatus getInvestigationStatus() { + return investigationStatus; + } + + public void setInvestigationStatus(AefiInvestigationStatus investigationStatus) { + this.investigationStatus = investigationStatus; + } + + public AefiClassification getAefiClassification() { + return aefiClassification; + } + + public void setAefiClassification(AefiClassification aefiClassification) { + this.aefiClassification = aefiClassification; + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationReferenceDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationReferenceDto.java new file mode 100644 index 00000000000..10d9c77a3a5 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationReferenceDto.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.api.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.ReferenceDto; +import de.symeda.sormas.api.feature.FeatureType; +import de.symeda.sormas.api.utils.DependingOnFeatureType; + +@DependingOnFeatureType(featureType = FeatureType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_MANAGEMENT) +public class AefiInvestigationReferenceDto extends ReferenceDto { + + private String externalId; + + public AefiInvestigationReferenceDto() { + } + + public AefiInvestigationReferenceDto(String uuid, String externalId) { + super(uuid); + this.externalId = externalId; + } + + public String getExternalId() { + return externalId; + } + + public void setExternalId(String externalId) { + this.externalId = externalId; + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationStage.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationStage.java new file mode 100644 index 00000000000..e6a8d26526e --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationStage.java @@ -0,0 +1,30 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum AefiInvestigationStage { + + FIRST, + INTERIM, + FINAL; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationStatus.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationStatus.java new file mode 100644 index 00000000000..1506a3c1138 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiInvestigationStatus.java @@ -0,0 +1,33 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum AefiInvestigationStatus { + + DONE, + DISCARDED; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } + + public String toShortString() { + return I18nProperties.getEnumCaptionShort(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiReferenceDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiReferenceDto.java index 51acac53ec1..9f992ad8963 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiReferenceDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiReferenceDto.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -30,8 +27,8 @@ public class AefiReferenceDto extends ReferenceDto { public AefiReferenceDto() { } - public AefiReferenceDto(String uuid, String caption, String externalId) { - super(uuid, caption); + public AefiReferenceDto(String uuid, String externalId) { + super(uuid); this.externalId = externalId; } diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiVaccinationPeriod.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiVaccinationPeriod.java new file mode 100644 index 00000000000..67bee292daa --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/AefiVaccinationPeriod.java @@ -0,0 +1,30 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum AefiVaccinationPeriod { + + WITHIN_FIRST_FEW_DOSES, + WITHIN_LAST_DOSES, + UNKNOWN; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/BirthTerm.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/BirthTerm.java new file mode 100644 index 00000000000..11abb53e8d8 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/BirthTerm.java @@ -0,0 +1,30 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum BirthTerm { + + FULL_TERM, + PRE_TERM, + POST_TERM; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/DeliveryProcedure.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/DeliveryProcedure.java new file mode 100644 index 00000000000..998861a1e6a --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/DeliveryProcedure.java @@ -0,0 +1,31 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum DeliveryProcedure { + + NORMAL, + CAESAREAN, + ASSISTED, + WITH_COMPLICATION; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/PatientStatusAtAefiInvestigation.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/PatientStatusAtAefiInvestigation.java new file mode 100644 index 00000000000..6067cb39260 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/PatientStatusAtAefiInvestigation.java @@ -0,0 +1,32 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum PatientStatusAtAefiInvestigation { + + DIED, + DISABLED, + RECOVERED, + RECOVERED_COMPLETELY, + UNKNOWN; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/PlaceOfVaccination.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/PlaceOfVaccination.java new file mode 100644 index 00000000000..772ca5641a1 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/PlaceOfVaccination.java @@ -0,0 +1,30 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum PlaceOfVaccination { + + GOVERNMENT_HEALTH_FACILITY, + PRIVATE_HEALTH_FACILITY, + OTHER; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/SeriousAefiInfoSource.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/SeriousAefiInfoSource.java new file mode 100644 index 00000000000..aa21ff6588d --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/SeriousAefiInfoSource.java @@ -0,0 +1,31 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum SeriousAefiInfoSource { + + EXAMINATION, + DOCUMENTS, + VERBAL_AUTOPSY, + OTHER; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/SyringeType.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/SyringeType.java new file mode 100644 index 00000000000..a8161b6c21a --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/SyringeType.java @@ -0,0 +1,31 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum SyringeType { + + GLASS, + DISPOSABLE, + RECYCLED_DISPOSABLE, + OTHER; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/VaccinationActivity.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/VaccinationActivity.java new file mode 100644 index 00000000000..d7724fb2fc8 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/VaccinationActivity.java @@ -0,0 +1,30 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum VaccinationActivity { + + CAMPAIGN, + ROUTINE, + OTHER; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/VaccinationSite.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/VaccinationSite.java new file mode 100644 index 00000000000..c4625e1ceed --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/VaccinationSite.java @@ -0,0 +1,32 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum VaccinationSite { + + FIXED, + MOBILE, + OUTREACH, + OTHER; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } + +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/VaccineCarrier.java b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/VaccineCarrier.java new file mode 100644 index 00000000000..86ebe5d47ab --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/adverseeventsfollowingimmunization/VaccineCarrier.java @@ -0,0 +1,30 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import de.symeda.sormas.api.i18n.I18nProperties; + +public enum VaccineCarrier { + + SHORT_RANGE, + LONG_RANGE, + OTHER; + + @Override + public String toString() { + return I18nProperties.getEnumCaption(this); + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/caze/Vaccine.java b/sormas-api/src/main/java/de/symeda/sormas/api/caze/Vaccine.java index d1a41a5e01b..9071192bc8d 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/caze/Vaccine.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/caze/Vaccine.java @@ -59,6 +59,18 @@ public enum Vaccine { @Diseases(value = { Disease.CORONAVIRUS }) SANOFI_GSK(VaccineManufacturer.SANOFI_GSK), + @Diseases(value = { + Disease.CSM }) + MenABCWY(VaccineManufacturer.PFIZER), + @Diseases(value = { + Disease.MONKEYPOX }) + ACAM2000(VaccineManufacturer.SANOFI_PASTEUR_BIOLOGICS), + @Diseases(value = { + Disease.MONKEYPOX }) + LC_16(VaccineManufacturer.KM_BIOLOGICS), + @Diseases(value = { + Disease.MONKEYPOX }) + MVA_BN(VaccineManufacturer.BAVARIAN_NORDIC), UNKNOWN, OTHER; diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/caze/VaccineManufacturer.java b/sormas-api/src/main/java/de/symeda/sormas/api/caze/VaccineManufacturer.java index 9d384da94a7..286293d076b 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/caze/VaccineManufacturer.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/caze/VaccineManufacturer.java @@ -24,6 +24,12 @@ public enum VaccineManufacturer { @Diseases(value = { Disease.CORONAVIRUS }) BIONTECH_PFIZER, + @Diseases(value = { + Disease.CSM }) + PFIZER, + @Diseases(value = { + Disease.MONKEYPOX }) + BAVARIAN_NORDIC, @Diseases(value = { Disease.CORONAVIRUS }) MODERNA, @@ -33,12 +39,18 @@ public enum VaccineManufacturer { @Diseases(value = { Disease.CORONAVIRUS }) JOHNSON_JOHNSON, + @Diseases(value = { + Disease.MONKEYPOX }) + KM_BIOLOGICS, @Diseases(value = { Disease.CORONAVIRUS }) NOVAVAX, @Diseases(value = { Disease.CORONAVIRUS }) SANOFI_GSK, + @Diseases(value = { + Disease.MONKEYPOX }) + SANOFI_PASTEUR_BIOLOGICS, VALNEVA, UNKNOWN, OTHER; diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiDashboardFacade.java b/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiDashboardFacade.java index 2e61f221bc5..2e6e9c7a087 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiDashboardFacade.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiDashboardFacade.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -23,6 +20,8 @@ import javax.ejb.Remote; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiClassification; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationStatus; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; import de.symeda.sormas.api.caze.Vaccine; import de.symeda.sormas.api.dashboard.AefiDashboardCriteria; @@ -32,6 +31,10 @@ public interface AefiDashboardFacade { Map getAefiCountsByType(AefiDashboardCriteria dashboardCriteria); + Map> getAefiInvestigationCountsByInvestigationStatus(AefiDashboardCriteria dashboardCriteria); + + Map> getAefiInvestigationCountsByAefiClassification(AefiDashboardCriteria dashboardCriteria); + Map> getAefiCountsByVaccine(AefiDashboardCriteria dashboardCriteria); AefiChartData getAefiByVaccineDoseChartData(AefiDashboardCriteria dashboardCriteria); 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 ac9fd632af3..233647e5b4f 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 @@ -237,15 +237,26 @@ public interface Captions { String Aefi_uuid = "Aefi.uuid"; String Aefi_worldwideId = "Aefi.worldwideId"; String aefiActiveAdverseEvents = "aefiActiveAdverseEvents"; + String aefiActiveInvestigations = "aefiActiveInvestigations"; String aefiAefiDataView = "aefiAefiDataView"; + String aefiAefiInvestigationDataView = "aefiAefiInvestigationDataView"; + String aefiAefiInvestigationList = "aefiAefiInvestigationList"; String aefiAefiList = "aefiAefiList"; String aefiAllActiveAndArchivedAdverseEvents = "aefiAllActiveAndArchivedAdverseEvents"; + String aefiAllActiveAndArchivedInvestigations = "aefiAllActiveAndArchivedInvestigations"; String aefiArchivedAdverseEvents = "aefiArchivedAdverseEvents"; + String aefiArchivedInvestigations = "aefiArchivedInvestigations"; String AefiCriteria_aefiType = "AefiCriteria.aefiType"; String AefiCriteria_outcome = "AefiCriteria.outcome"; String AefiCriteria_vaccineManufacturer = "AefiCriteria.vaccineManufacturer"; String AefiCriteria_vaccineName = "AefiCriteria.vaccineName"; + String aefiDashboardAefiClassificationCoincidentalAdverseEvent = "aefiDashboardAefiClassificationCoincidentalAdverseEvent"; + String aefiDashboardAefiClassificationRelatedToVaccination = "aefiDashboardAefiClassificationRelatedToVaccination"; + String aefiDashboardAefiClassificationUndetermined = "aefiDashboardAefiClassificationUndetermined"; + String aefiDashboardAefiInvestigationDiscarded = "aefiDashboardAefiInvestigationDiscarded"; + String aefiDashboardAefiInvestigationDone = "aefiDashboardAefiInvestigationDone"; String aefiDashboardAllAefi = "aefiDashboardAllAefi"; + String aefiDashboardAllAefiInvestigation = "aefiDashboardAllAefiInvestigation"; String aefiDashboardNonSerious = "aefiDashboardNonSerious"; String aefiDashboardNonSeriousAefi = "aefiDashboardNonSeriousAefi"; String aefiDashboardSerious = "aefiDashboardSerious"; @@ -253,6 +264,50 @@ public interface Captions { String aefiDashboardShowNonSeriousAefi = "aefiDashboardShowNonSeriousAefi"; String aefiDashboardShowSeriousAefi = "aefiDashboardShowSeriousAefi"; String aefiDeletedAdverseEvents = "aefiDeletedAdverseEvents"; + String aefiDeletedInvestigations = "aefiDeletedInvestigations"; + String AefiExport_aefiDescription = "AefiExport.aefiDescription"; + String AefiExport_birthDate = "AefiExport.birthDate"; + String AefiExport_firstName = "AefiExport.firstName"; + String AefiExport_lastName = "AefiExport.lastName"; + String AefiExport_nationalLevelComment = "AefiExport.nationalLevelComment"; + String AefiExport_onsetAgeDays = "AefiExport.onsetAgeDays"; + String AefiExport_onsetAgeGroup = "AefiExport.onsetAgeGroup"; + String AefiExport_onsetAgeMonths = "AefiExport.onsetAgeMonths"; + String AefiExport_onsetAgeYears = "AefiExport.onsetAgeYears"; + String AefiExport_outcome = "AefiExport.outcome"; + String AefiExport_patientAddressCommunity = "AefiExport.patientAddressCommunity"; + String AefiExport_patientAddressDetails = "AefiExport.patientAddressDetails"; + String AefiExport_patientAddressDistrict = "AefiExport.patientAddressDistrict"; + String AefiExport_patientAddressRegion = "AefiExport.patientAddressRegion"; + String AefiExport_primarySuspectVaccineBatchNumber = "AefiExport.primarySuspectVaccineBatchNumber"; + String AefiExport_primarySuspectVaccineBrand = "AefiExport.primarySuspectVaccineBrand"; + String AefiExport_primarySuspectVaccineDiluentBatchNumber = "AefiExport.primarySuspectVaccineDiluentBatchNumber"; + String AefiExport_primarySuspectVaccineDose = "AefiExport.primarySuspectVaccineDose"; + String AefiExport_primarySuspectVaccineManufacturer = "AefiExport.primarySuspectVaccineManufacturer"; + String AefiExport_primarySuspectVaccineName = "AefiExport.primarySuspectVaccineName"; + String AefiExport_primarySuspectVaccineOtherName = "AefiExport.primarySuspectVaccineOtherName"; + String AefiExport_primarySuspectVaccineVaccinationDate = "AefiExport.primarySuspectVaccineVaccinationDate"; + String AefiExport_receivedAtNationalLevelDate = "AefiExport.receivedAtNationalLevelDate"; + String AefiExport_reportDate = "AefiExport.reportDate"; + String AefiExport_reportingIdNumber = "AefiExport.reportingIdNumber"; + String AefiExport_reportingOfficerAddressCountryName = "AefiExport.reportingOfficerAddressCountryName"; + String AefiExport_reportingOfficerDepartment = "AefiExport.reportingOfficerDepartment"; + String AefiExport_reportingOfficerDesignation = "AefiExport.reportingOfficerDesignation"; + String AefiExport_reportingOfficerEmail = "AefiExport.reportingOfficerEmail"; + String AefiExport_reportingOfficerFacilityCommunity = "AefiExport.reportingOfficerFacilityCommunity"; + String AefiExport_reportingOfficerFacilityDistrict = "AefiExport.reportingOfficerFacilityDistrict"; + String AefiExport_reportingOfficerFacilityName = "AefiExport.reportingOfficerFacilityName"; + String AefiExport_reportingOfficerFacilityRegion = "AefiExport.reportingOfficerFacilityRegion"; + String AefiExport_reportingOfficerName = "AefiExport.reportingOfficerName"; + String AefiExport_reportingOfficerPhoneNumber = "AefiExport.reportingOfficerPhoneNumber"; + String AefiExport_serious = "AefiExport.serious"; + String AefiExport_sex = "AefiExport.sex"; + String AefiExport_startDateTime = "AefiExport.startDateTime"; + String AefiExport_vaccinationFacilityCommunity = "AefiExport.vaccinationFacilityCommunity"; + String AefiExport_vaccinationFacilityDistrict = "AefiExport.vaccinationFacilityDistrict"; + String AefiExport_vaccinationFacilityName = "AefiExport.vaccinationFacilityName"; + String AefiExport_vaccinationFacilityRegion = "AefiExport.vaccinationFacilityRegion"; + String AefiExport_worldWideId = "AefiExport.worldWideId"; String AefiIndex_adverseEvents = "AefiIndex.adverseEvents"; String AefiIndex_ageAndBirthDate = "AefiIndex.ageAndBirthDate"; String AefiIndex_disease = "AefiIndex.disease"; @@ -270,7 +325,195 @@ public interface Captions { String AefiIndex_startDateTime = "AefiIndex.startDateTime"; String AefiIndex_uuid = "AefiIndex.uuid"; String AefiIndex_vaccinationDate = "AefiIndex.vaccinationDate"; + String AefiInvestigation_adSyringesUsedForImmunization = "AefiInvestigation.adSyringesUsedForImmunization"; + String AefiInvestigation_adverseEventAfterPreviousVaccinations = "AefiInvestigation.adverseEventAfterPreviousVaccinations"; + String AefiInvestigation_adverseEventAfterPreviousVaccinationsDetails = "AefiInvestigation.adverseEventAfterPreviousVaccinationsDetails"; + String AefiInvestigation_aefiClassification = "AefiInvestigation.aefiClassification"; + String AefiInvestigation_aefiClassificationDetails = "AefiInvestigation.aefiClassificationDetails"; + String AefiInvestigation_aefiClassificationSubType = "AefiInvestigation.aefiClassificationSubType"; + String AefiInvestigation_allCasesInClusterReceivedVaccineFromSameVial = "AefiInvestigation.allCasesInClusterReceivedVaccineFromSameVial"; + String AefiInvestigation_allCasesInClusterReceivedVaccineFromSameVialDetails = "AefiInvestigation.allCasesInClusterReceivedVaccineFromSameVialDetails"; + String AefiInvestigation_anyOtherItemInRefrigerator = "AefiInvestigation.anyOtherItemInRefrigerator"; + String AefiInvestigation_anyStorageTemperatureDeviationOutsideTwoToEightDegrees = "AefiInvestigation.anyStorageTemperatureDeviationOutsideTwoToEightDegrees"; + String AefiInvestigation_autopsyDate = "AefiInvestigation.autopsyDate"; + String AefiInvestigation_autopsyDone = "AefiInvestigation.autopsyDone"; + String AefiInvestigation_autopsyPlannedDateTime = "AefiInvestigation.autopsyPlannedDateTime"; + String AefiInvestigation_birthTerm = "AefiInvestigation.birthTerm"; + String AefiInvestigation_birthWeight = "AefiInvestigation.birthWeight"; + String AefiInvestigation_caseIsPartOfACluster = "AefiInvestigation.caseIsPartOfACluster"; + String AefiInvestigation_caseIsPartOfAClusterDetails = "AefiInvestigation.caseIsPartOfAClusterDetails"; + String AefiInvestigation_causality = "AefiInvestigation.causality"; + String AefiInvestigation_causalityDetails = "AefiInvestigation.causalityDetails"; + String AefiInvestigation_changeDate = "AefiInvestigation.changeDate"; + String AefiInvestigation_clinicalDetailsDateTime = "AefiInvestigation.clinicalDetailsDateTime"; + String AefiInvestigation_clinicalDetailsOfficerDesignation = "AefiInvestigation.clinicalDetailsOfficerDesignation"; + String AefiInvestigation_clinicalDetailsOfficerEmail = "AefiInvestigation.clinicalDetailsOfficerEmail"; + String AefiInvestigation_clinicalDetailsOfficerName = "AefiInvestigation.clinicalDetailsOfficerName"; + String AefiInvestigation_clinicalDetailsOfficerPhoneNumber = "AefiInvestigation.clinicalDetailsOfficerPhoneNumber"; + String AefiInvestigation_communityInvestigationAdditionalDetails = "AefiInvestigation.communityInvestigationAdditionalDetails"; + String AefiInvestigation_conditionedIcepackUsed = "AefiInvestigation.conditionedIcepackUsed"; + String AefiInvestigation_contraIndicationScreenedPriorToVaccination = "AefiInvestigation.contraIndicationScreenedPriorToVaccination"; + String AefiInvestigation_correctDoseOrRoute = "AefiInvestigation.correctDoseOrRoute"; + String AefiInvestigation_correctProcedureForStorageFollowed = "AefiInvestigation.correctProcedureForStorageFollowed"; + String AefiInvestigation_country = "AefiInvestigation.country"; + String AefiInvestigation_creationDate = "AefiInvestigation.creationDate"; + String AefiInvestigation_currentlyOnConcomitantMedication = "AefiInvestigation.currentlyOnConcomitantMedication"; + String AefiInvestigation_currentlyOnConcomitantMedicationDetails = "AefiInvestigation.currentlyOnConcomitantMedicationDetails"; + String AefiInvestigation_deathDateTime = "AefiInvestigation.deathDateTime"; + String AefiInvestigation_deletionReason = "AefiInvestigation.deletionReason"; + String AefiInvestigation_deliveryProcedure = "AefiInvestigation.deliveryProcedure"; + String AefiInvestigation_deliveryProcedureDetails = "AefiInvestigation.deliveryProcedureDetails"; + String AefiInvestigation_errorInVaccineHandling = "AefiInvestigation.errorInVaccineHandling"; + String AefiInvestigation_errorInVaccineHandlingDetails = "AefiInvestigation.errorInVaccineHandlingDetails"; + String AefiInvestigation_errorInVaccineReconstitution = "AefiInvestigation.errorInVaccineReconstitution"; + String AefiInvestigation_errorInVaccineReconstitutionDetails = "AefiInvestigation.errorInVaccineReconstitutionDetails"; + String AefiInvestigation_errorPrescribingVaccine = "AefiInvestigation.errorPrescribingVaccine"; + String AefiInvestigation_errorPrescribingVaccineDetails = "AefiInvestigation.errorPrescribingVaccineDetails"; + String AefiInvestigation_eventIsAStressResponseRelatedToImmunization = "AefiInvestigation.eventIsAStressResponseRelatedToImmunization"; + String AefiInvestigation_eventIsAStressResponseRelatedToImmunizationDetails = "AefiInvestigation.eventIsAStressResponseRelatedToImmunizationDetails"; + String AefiInvestigation_externalId = "AefiInvestigation.externalId"; + String AefiInvestigation_familyHistoryOfDiseaseOrAllergy = "AefiInvestigation.familyHistoryOfDiseaseOrAllergy"; + String AefiInvestigation_familyHistoryOfDiseaseOrAllergyDetails = "AefiInvestigation.familyHistoryOfDiseaseOrAllergyDetails"; + String AefiInvestigation_firstCaregiversName = "AefiInvestigation.firstCaregiversName"; + String AefiInvestigation_formCompletionDate = "AefiInvestigation.formCompletionDate"; + String AefiInvestigation_historyOfAllergyToVaccineDrugOrFood = "AefiInvestigation.historyOfAllergyToVaccineDrugOrFood"; + String AefiInvestigation_historyOfAllergyToVaccineDrugOrFoodDetails = "AefiInvestigation.historyOfAllergyToVaccineDrugOrFoodDetails"; + String AefiInvestigation_historyOfHospitalizationInLastThirtyDaysWithCause = "AefiInvestigation.historyOfHospitalizationInLastThirtyDaysWithCause"; + String AefiInvestigation_historyOfHospitalizationInLastThirtyDaysWithCauseDetails = "AefiInvestigation.historyOfHospitalizationInLastThirtyDaysWithCauseDetails"; + String AefiInvestigation_hospitalizationDate = "AefiInvestigation.hospitalizationDate"; + String AefiInvestigation_injectionTechniqueAdditionalDetails = "AefiInvestigation.injectionTechniqueAdditionalDetails"; + String AefiInvestigation_investigationCaseId = "AefiInvestigation.investigationCaseId"; + String AefiInvestigation_investigationCompletionDate = "AefiInvestigation.investigationCompletionDate"; + String AefiInvestigation_investigationDate = "AefiInvestigation.investigationDate"; + String AefiInvestigation_investigationStage = "AefiInvestigation.investigationStage"; + String AefiInvestigation_investigationStatus = "AefiInvestigation.investigationStatus"; + String AefiInvestigation_investigationStatusDetails = "AefiInvestigation.investigationStatusDetails"; + String AefiInvestigation_keySymptomDateTime = "AefiInvestigation.keySymptomDateTime"; + String AefiInvestigation_lastTrainingReceivedByVaccinatorDate = "AefiInvestigation.lastTrainingReceivedByVaccinatorDate"; + String AefiInvestigation_nonTouchTechniqueFollowed = "AefiInvestigation.nonTouchTechniqueFollowed"; + String AefiInvestigation_numberImmunizedConcernedVaccineSameBatchNumberLocationDetails = "AefiInvestigation.numberImmunizedConcernedVaccineSameBatchNumberLocationDetails"; + String AefiInvestigation_numberImmunizedConcernedVaccineSameBatchNumberOtherLocations = "AefiInvestigation.numberImmunizedConcernedVaccineSameBatchNumberOtherLocations"; + String AefiInvestigation_numberImmunizedFromConcernedVaccineVial = "AefiInvestigation.numberImmunizedFromConcernedVaccineVial"; + String AefiInvestigation_numberImmunizedWithConcernedVaccineInSameSession = "AefiInvestigation.numberImmunizedWithConcernedVaccineInSameSession"; + String AefiInvestigation_numberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays = "AefiInvestigation.numberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays"; + String AefiInvestigation_numberOfCasesDetectedInCluster = "AefiInvestigation.numberOfCasesDetectedInCluster"; + String AefiInvestigation_numberOfSimilarEventsReportedSamePeriodAndLocality = "AefiInvestigation.numberOfSimilarEventsReportedSamePeriodAndLocality"; + String AefiInvestigation_numberOfThoseAffectedNotVaccinated = "AefiInvestigation.numberOfThoseAffectedNotVaccinated"; + String AefiInvestigation_numberOfThoseAffectedVaccinated = "AefiInvestigation.numberOfThoseAffectedVaccinated"; + String AefiInvestigation_numberOfThoseAffectedVaccinatedUnknown = "AefiInvestigation.numberOfThoseAffectedVaccinatedUnknown"; + String AefiInvestigation_numberOfVialsUsedInCluster = "AefiInvestigation.numberOfVialsUsedInCluster"; + String AefiInvestigation_numberOfVialsUsedInClusterDetails = "AefiInvestigation.numberOfVialsUsedInClusterDetails"; + String AefiInvestigation_numberOfWeeksPregnant = "AefiInvestigation.numberOfWeeksPregnant"; + String AefiInvestigation_otherCaregiversNames = "AefiInvestigation.otherCaregiversNames"; + String AefiInvestigation_otherDeletionReason = "AefiInvestigation.otherDeletionReason"; + String AefiInvestigation_otherInvestigationFindings = "AefiInvestigation.otherInvestigationFindings"; + String AefiInvestigation_otherSourcesWhoProvidedInfo = "AefiInvestigation.otherSourcesWhoProvidedInfo"; + String AefiInvestigation_partiallyUsedReconstitutedVaccinesInRefrigerator = "AefiInvestigation.partiallyUsedReconstitutedVaccinesInRefrigerator"; + String AefiInvestigation_pastHistoryOfSimilarEvent = "AefiInvestigation.pastHistoryOfSimilarEvent"; + String AefiInvestigation_pastHistoryOfSimilarEventDetails = "AefiInvestigation.pastHistoryOfSimilarEventDetails"; + String AefiInvestigation_patientImmunizedPeriod = "AefiInvestigation.patientImmunizedPeriod"; + String AefiInvestigation_patientImmunizedPeriodDetails = "AefiInvestigation.patientImmunizedPeriodDetails"; + String AefiInvestigation_patientReceivedMedicalCare = "AefiInvestigation.patientReceivedMedicalCare"; + String AefiInvestigation_patientReceivedMedicalCareDetails = "AefiInvestigation.patientReceivedMedicalCareDetails"; + String AefiInvestigation_placeOfVaccination = "AefiInvestigation.placeOfVaccination"; + String AefiInvestigation_placeOfVaccinationDetails = "AefiInvestigation.placeOfVaccinationDetails"; + String AefiInvestigation_preExistingIllnessThirtyDaysOrCongenitalDisorder = "AefiInvestigation.preExistingIllnessThirtyDaysOrCongenitalDisorder"; + String AefiInvestigation_preExistingIllnessThirtyDaysOrCongenitalDisorderDetails = "AefiInvestigation.preExistingIllnessThirtyDaysOrCongenitalDisorderDetails"; + String AefiInvestigation_provisionalOrFinalDiagnosis = "AefiInvestigation.provisionalOrFinalDiagnosis"; + String AefiInvestigation_reconstitutionAdditionalDetails = "AefiInvestigation.reconstitutionAdditionalDetails"; + String AefiInvestigation_reportDate = "AefiInvestigation.reportDate"; + String AefiInvestigation_reportedToHealthAuthorityDate = "AefiInvestigation.reportedToHealthAuthorityDate"; + String AefiInvestigation_reportingOfficerAddress = "AefiInvestigation.reportingOfficerAddress"; + String AefiInvestigation_reportingOfficerDepartment = "AefiInvestigation.reportingOfficerDepartment"; + String AefiInvestigation_reportingOfficerDesignation = "AefiInvestigation.reportingOfficerDesignation"; + String AefiInvestigation_reportingOfficerEmail = "AefiInvestigation.reportingOfficerEmail"; + String AefiInvestigation_reportingOfficerFacility = "AefiInvestigation.reportingOfficerFacility"; + String AefiInvestigation_reportingOfficerFacilityDetails = "AefiInvestigation.reportingOfficerFacilityDetails"; + String AefiInvestigation_reportingOfficerLandlinePhoneNumber = "AefiInvestigation.reportingOfficerLandlinePhoneNumber"; + String AefiInvestigation_reportingOfficerMobilePhoneNumber = "AefiInvestigation.reportingOfficerMobilePhoneNumber"; + String AefiInvestigation_reportingOfficerName = "AefiInvestigation.reportingOfficerName"; + String AefiInvestigation_reportingUser = "AefiInvestigation.reportingUser"; + String AefiInvestigation_responsibleCommunity = "AefiInvestigation.responsibleCommunity"; + String AefiInvestigation_responsibleDistrict = "AefiInvestigation.responsibleDistrict"; + String AefiInvestigation_responsibleRegion = "AefiInvestigation.responsibleRegion"; + String AefiInvestigation_sameReconstitutionSyringeForEachVaccination = "AefiInvestigation.sameReconstitutionSyringeForEachVaccination"; + String AefiInvestigation_sameReconstitutionSyringeForEachVaccineVial = "AefiInvestigation.sameReconstitutionSyringeForEachVaccineVial"; + String AefiInvestigation_sameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine = "AefiInvestigation.sameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine"; + String AefiInvestigation_sameReconstitutionSyringeUsedForReconstitutingDifferentVaccines = "AefiInvestigation.sameReconstitutionSyringeUsedForReconstitutingDifferentVaccines"; + String AefiInvestigation_seriousAefiInfoSource = "AefiInvestigation.seriousAefiInfoSource"; + String AefiInvestigation_seriousAefiInfoSourceDetails = "AefiInvestigation.seriousAefiInfoSourceDetails"; + String AefiInvestigation_seriousAefiVerbalAutopsyInfoSourceDetails = "AefiInvestigation.seriousAefiVerbalAutopsyInfoSourceDetails"; + String AefiInvestigation_signsAndSymptomsFromTimeOfVaccination = "AefiInvestigation.signsAndSymptomsFromTimeOfVaccination"; + String AefiInvestigation_similarEventsReportedSamePeriodAndLocality = "AefiInvestigation.similarEventsReportedSamePeriodAndLocality"; + String AefiInvestigation_similarEventsReportedSamePeriodAndLocalityDetails = "AefiInvestigation.similarEventsReportedSamePeriodAndLocalityDetails"; + String AefiInvestigation_statusOnDateOfInvestigation = "AefiInvestigation.statusOnDateOfInvestigation"; + String AefiInvestigation_storageTemperatureMonitoringAdditionalDetails = "AefiInvestigation.storageTemperatureMonitoringAdditionalDetails"; + String AefiInvestigation_syringesUsedAdditionalDetails = "AefiInvestigation.syringesUsedAdditionalDetails"; + String AefiInvestigation_timeOfReconstitutionMentionedOnTheVial = "AefiInvestigation.timeOfReconstitutionMentionedOnTheVial"; + String AefiInvestigation_trainingReceivedByVaccinator = "AefiInvestigation.trainingReceivedByVaccinator"; + String AefiInvestigation_typeOfSite = "AefiInvestigation.typeOfSite"; + String AefiInvestigation_typeOfSiteDetails = "AefiInvestigation.typeOfSiteDetails"; + String AefiInvestigation_typeOfSyringesUsed = "AefiInvestigation.typeOfSyringesUsed"; + String AefiInvestigation_typeOfSyringesUsedDetails = "AefiInvestigation.typeOfSyringesUsedDetails"; + String AefiInvestigation_unusableDiluentsInStore = "AefiInvestigation.unusableDiluentsInStore"; + String AefiInvestigation_unusableVaccinesInRefrigerator = "AefiInvestigation.unusableVaccinesInRefrigerator"; + String AefiInvestigation_uuid = "AefiInvestigation.uuid"; + String AefiInvestigation_vaccinationActivity = "AefiInvestigation.vaccinationActivity"; + String AefiInvestigation_vaccinationActivityDetails = "AefiInvestigation.vaccinationActivityDetails"; + String AefiInvestigation_vaccinationFacility = "AefiInvestigation.vaccinationFacility"; + String AefiInvestigation_vaccinationFacilityDetails = "AefiInvestigation.vaccinationFacilityDetails"; + String AefiInvestigation_vaccineAdministeredIncorrectly = "AefiInvestigation.vaccineAdministeredIncorrectly"; + String AefiInvestigation_vaccineAdministeredIncorrectlyDetails = "AefiInvestigation.vaccineAdministeredIncorrectlyDetails"; + String AefiInvestigation_vaccineCarrierReturnedFromSiteOnSameDateAsVaccination = "AefiInvestigation.vaccineCarrierReturnedFromSiteOnSameDateAsVaccination"; + String AefiInvestigation_vaccineCarrierSentToSiteOnSameDateAsVaccination = "AefiInvestigation.vaccineCarrierSentToSiteOnSameDateAsVaccination"; + String AefiInvestigation_vaccineCarrierType = "AefiInvestigation.vaccineCarrierType"; + String AefiInvestigation_vaccineCarrierTypeDetails = "AefiInvestigation.vaccineCarrierTypeDetails"; + String AefiInvestigation_vaccineCouldHaveBeenUnSterile = "AefiInvestigation.vaccineCouldHaveBeenUnSterile"; + String AefiInvestigation_vaccineCouldHaveBeenUnSterileDetails = "AefiInvestigation.vaccineCouldHaveBeenUnSterileDetails"; + String AefiInvestigation_vaccineGivenPeriod = "AefiInvestigation.vaccineGivenPeriod"; + String AefiInvestigation_vaccineGivenPeriodDetails = "AefiInvestigation.vaccineGivenPeriodDetails"; + String AefiInvestigation_vaccineHasQualityDefect = "AefiInvestigation.vaccineHasQualityDefect"; + String AefiInvestigation_vaccineHasQualityDefectDetails = "AefiInvestigation.vaccineHasQualityDefectDetails"; + String AefiInvestigation_vaccinePhysicalConditionAbnormal = "AefiInvestigation.vaccinePhysicalConditionAbnormal"; + String AefiInvestigation_vaccinePhysicalConditionAbnormalDetails = "AefiInvestigation.vaccinePhysicalConditionAbnormalDetails"; + String AefiInvestigation_vaccinesAndDiluentsUsedRecommendedByManufacturer = "AefiInvestigation.vaccinesAndDiluentsUsedRecommendedByManufacturer"; + String AefiInvestigation_vaccineStoragePointAdditionalDetails = "AefiInvestigation.vaccineStoragePointAdditionalDetails"; + String AefiInvestigation_vaccineStorageRefrigeratorTemperatureMonitored = "AefiInvestigation.vaccineStorageRefrigeratorTemperatureMonitored"; + String AefiInvestigation_vaccineTransportationAdditionalDetails = "AefiInvestigation.vaccineTransportationAdditionalDetails"; + String aefiInvestigationClinicalDetailsOfficer = "aefiInvestigationClinicalDetailsOfficer"; + String AefiInvestigationCriteria_aefiClassification = "AefiInvestigationCriteria.aefiClassification"; + String AefiInvestigationCriteria_statusAtAefiInvestigation = "AefiInvestigationCriteria.statusAtAefiInvestigation"; + String AefiInvestigationCriteria_vaccineManufacturer = "AefiInvestigationCriteria.vaccineManufacturer"; + String AefiInvestigationCriteria_vaccineName = "AefiInvestigationCriteria.vaccineName"; + String aefiInvestigationForAdultWomen = "aefiInvestigationForAdultWomen"; + String aefiInvestigationForInfants = "aefiInvestigationForInfants"; + String AefiInvestigationIndex_aefiClassification = "AefiInvestigationIndex.aefiClassification"; + String AefiInvestigationIndex_aefiReportUuid = "AefiInvestigationIndex.aefiReportUuid"; + String AefiInvestigationIndex_ageAndBirthDate = "AefiInvestigationIndex.ageAndBirthDate"; + String AefiInvestigationIndex_disease = "AefiInvestigationIndex.disease"; + String AefiInvestigationIndex_district = "AefiInvestigationIndex.district"; + String AefiInvestigationIndex_investigationCaseId = "AefiInvestigationIndex.investigationCaseId"; + String AefiInvestigationIndex_investigationDate = "AefiInvestigationIndex.investigationDate"; + String AefiInvestigationIndex_investigationStatus = "AefiInvestigationIndex.investigationStatus"; + String AefiInvestigationIndex_personFirstName = "AefiInvestigationIndex.personFirstName"; + String AefiInvestigationIndex_personLastName = "AefiInvestigationIndex.personLastName"; + String AefiInvestigationIndex_primaryVaccine = "AefiInvestigationIndex.primaryVaccine"; + String AefiInvestigationIndex_region = "AefiInvestigationIndex.region"; + String AefiInvestigationIndex_reportDate = "AefiInvestigationIndex.reportDate"; + String AefiInvestigationIndex_sex = "AefiInvestigationIndex.sex"; + String AefiInvestigationIndex_statusOnDateOfInvestigation = "AefiInvestigationIndex.statusOnDateOfInvestigation"; + String AefiInvestigationIndex_uuid = "AefiInvestigationIndex.uuid"; + String AefiInvestigationListEntry_aefiClassification = "AefiInvestigationListEntry.aefiClassification"; + String AefiInvestigationListEntry_investigationDate = "AefiInvestigationListEntry.investigationDate"; + String AefiInvestigationListEntry_investigationStage = "AefiInvestigationListEntry.investigationStage"; + String AefiInvestigationListEntry_statusOnDateOfInvestigation = "AefiInvestigationListEntry.statusOnDateOfInvestigation"; + String aefiInvestigationMedicalCareDetailsInstruction = "aefiInvestigationMedicalCareDetailsInstruction"; + String aefiInvestigationOfThoseAffected = "aefiInvestigationOfThoseAffected"; + String aefiInvestigationReconstitutionProcedure = "aefiInvestigationReconstitutionProcedure"; + String aefiInvestigationSourceOfInformation = "aefiInvestigationSourceOfInformation"; String aefiNewAdverseEvent = "aefiNewAdverseEvent"; + String aefiNewAefiInvestigation = "aefiNewAefiInvestigation"; + String aefiNewAefiInvestigationStageTitle = "aefiNewAefiInvestigationStageTitle"; String aefiVaccinationsDiluentBatchLotNumber = "aefiVaccinationsDiluentBatchLotNumber"; String aefiVaccinationsDiluentExpiryDate = "aefiVaccinationsDiluentExpiryDate"; String aefiVaccinationsDiluentInformation = "aefiVaccinationsDiluentInformation"; @@ -2694,6 +2937,23 @@ public interface Captions { String TestReport_testLabPostalCode = "TestReport.testLabPostalCode"; String TestReport_testResult = "TestReport.testResult"; String TestReport_testType = "TestReport.testType"; + String titleAefiInvestigationBasicDetails = "titleAefiInvestigationBasicDetails"; + String titleAefiInvestigationColdChainAndTransport = "titleAefiInvestigationColdChainAndTransport"; + String titleAefiInvestigationColdChainAndTransportLastVaccineStoragePoint = "titleAefiInvestigationColdChainAndTransportLastVaccineStoragePoint"; + String titleAefiInvestigationColdChainAndTransportSubTitle = "titleAefiInvestigationColdChainAndTransportSubTitle"; + String titleAefiInvestigationColdChainAndTransportVaccineTransportation = "titleAefiInvestigationColdChainAndTransportVaccineTransportation"; + String titleAefiInvestigationCommunityInvestigation = "titleAefiInvestigationCommunityInvestigation"; + String titleAefiInvestigationCommunityInvestigationThoseAffected = "titleAefiInvestigationCommunityInvestigationThoseAffected"; + String titleAefiInvestigationFirstExaminationDetails = "titleAefiInvestigationFirstExaminationDetails"; + String titleAefiInvestigationImmunizationPractices = "titleAefiInvestigationImmunizationPractices"; + String titleAefiInvestigationImmunizationPracticesInjectionTechnique = "titleAefiInvestigationImmunizationPracticesInjectionTechnique"; + String titleAefiInvestigationImmunizationPracticesReconstitution = "titleAefiInvestigationImmunizationPracticesReconstitution"; + String titleAefiInvestigationImmunizationPracticesSubTitle = "titleAefiInvestigationImmunizationPracticesSubTitle"; + String titleAefiInvestigationImmunizationPracticesSyringesAndNeedlesUsed = "titleAefiInvestigationImmunizationPracticesSyringesAndNeedlesUsed"; + String titleAefiInvestigationInvestigationStatus = "titleAefiInvestigationInvestigationStatus"; + String titleAefiInvestigationOtherFindings = "titleAefiInvestigationOtherFindings"; + String titleAefiInvestigationRelevantPatientInformation = "titleAefiInvestigationRelevantPatientInformation"; + String titleAefiInvestigationVaccinesDetails = "titleAefiInvestigationVaccinesDetails"; String to = "to"; String total = "total"; String travelEntriesNoTravelEntriesForPerson = "travelEntriesNoTravelEntriesForPerson"; @@ -2852,6 +3112,7 @@ public interface Captions { String versionIsMissing = "versionIsMissing"; String view = "view"; String View_actions = "View.actions"; + String View_adverseeventinvestigations = "View.adverseeventinvestigations"; String View_adverseevents = "View.adverseevents"; String View_aggregatereports = "View.aggregatereports"; String View_aggregatereports_aggregatereporting = "View.aggregatereports.aggregatereporting"; 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 42c2dd68365..f6c1ce4c730 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 @@ -54,6 +54,7 @@ public interface Strings { String comparedTo = "comparedTo"; String confirmationAlsoAdjustQuarantine = "confirmationAlsoAdjustQuarantine"; String confirmationArchiveAdverseEvent = "confirmationArchiveAdverseEvent"; + String confirmationArchiveAdverseEventInvestigation = "confirmationArchiveAdverseEventInvestigation"; String confirmationArchiveArea = "confirmationArchiveArea"; String confirmationArchiveAreas = "confirmationArchiveAreas"; String confirmationArchiveCampaign = "confirmationArchiveCampaign"; @@ -98,6 +99,7 @@ public interface Strings { String confirmationChangeCaseDisease = "confirmationChangeCaseDisease"; String confirmationContactSourceCaseDiscardUnsavedChanges = "confirmationContactSourceCaseDiscardUnsavedChanges"; String confirmationDearchiveAdverseEvent = "confirmationDearchiveAdverseEvent"; + String confirmationDearchiveAdverseEventInvestigation = "confirmationDearchiveAdverseEventInvestigation"; String confirmationDearchiveArea = "confirmationDearchiveArea"; String confirmationDearchiveAreas = "confirmationDearchiveAreas"; String confirmationDearchiveCampaign = "confirmationDearchiveCampaign"; @@ -220,6 +222,8 @@ public interface Strings { String entityAdditionalTest = "entityAdditionalTest"; String entityAdditionalTests = "entityAdditionalTests"; String entityAdverseEvent = "entityAdverseEvent"; + String entityAdverseEventInvestigation = "entityAdverseEventInvestigation"; + String entityAdverseEventInvestigations = "entityAdverseEventInvestigations"; String entityAdverseEvents = "entityAdverseEvents"; String entityAggregateReports = "entityAggregateReports"; String entityAreas = "entityAreas"; @@ -302,6 +306,7 @@ public interface Strings { String entityWeeklyReports = "entityWeeklyReports"; String epiWeek = "epiWeek"; String errorAccessDenied = "errorAccessDenied"; + String errorAdverseEventInvestigationNotEditable = "errorAdverseEventInvestigationNotEditable"; String errorAdverseEventNotEditable = "errorAdverseEventNotEditable"; String errorCampaignDiagramTotalsCalculationError = "errorCampaignDiagramTotalsCalculationError"; String errorCampaignNotEditable = "errorCampaignNotEditable"; @@ -421,17 +426,21 @@ public interface Strings { String headingAefiDashboardEpiCurve = "headingAefiDashboardEpiCurve"; String headingAefiDashboardMap = "headingAefiDashboardMap"; String headingAefiFirstDecisionLevel = "headingAefiFirstDecisionLevel"; + String headingAefiInvestigationFormSubHeading = "headingAefiInvestigationFormSubHeading"; + String headingAefiInvestigationSelectConcernedVaccine = "headingAefiInvestigationSelectConcernedVaccine"; String headingAefiNationalDecisionLevel = "headingAefiNationalDecisionLevel"; String headingAefiPatientsAgeAtOnset = "headingAefiPatientsAgeAtOnset"; String headingAefiPatientsIdentification = "headingAefiPatientsIdentification"; - String headingAefiPickPrimarySuspectVaccine = "headingAefiPickPrimarySuspectVaccine"; String headingAefiReportersInformation = "headingAefiReportersInformation"; String headingAefiReportingInformation = "headingAefiReportingInformation"; + String headingAefiReportInvestigations = "headingAefiReportInvestigations"; + String headingAefiSelectPrimarySuspectVaccine = "headingAefiSelectPrimarySuspectVaccine"; String headingAefiVaccinations = "headingAefiVaccinations"; String headingAllContacts = "headingAllContacts"; String headingAnimalContactDetails = "headingAnimalContactDetails"; String headingAnimalContacts = "headingAnimalContacts"; String headingArchiveAdverseEvent = "headingArchiveAdverseEvent"; + String headingArchiveAdverseEventInvestigation = "headingArchiveAdverseEventInvestigation"; String headingArchiveCampaign = "headingArchiveCampaign"; String headingArchiveCase = "headingArchiveCase"; String headingArchiveContact = "headingArchiveContact"; @@ -553,6 +562,7 @@ public interface Strings { String headingDatabaseExportFailed = "headingDatabaseExportFailed"; String headingDataImport = "headingDataImport"; String headingDearchiveAdverseEvent = "headingDearchiveAdverseEvent"; + String headingDearchiveAdverseEventInvestigation = "headingDearchiveAdverseEventInvestigation"; String headingDearchiveCampaign = "headingDearchiveCampaign"; String headingDearchiveCase = "headingDearchiveCase"; String headingDearchiveContact = "headingDearchiveContact"; @@ -950,6 +960,7 @@ public interface Strings { String infoCountryNotEditableEventParticipantsWithoutJurisdiction = "infoCountryNotEditableEventParticipantsWithoutJurisdiction"; String infoCreateEntry = "infoCreateEntry"; String infoCreateNewContactDiscardsChanges = "infoCreateNewContactDiscardsChanges"; + String infoCreateNewSampleDiscardsChangesCase = "infoCreateNewSampleDiscardsChangesCase"; String infoCreateNewSampleDiscardsChangesContact = "infoCreateNewSampleDiscardsChangesContact"; String infoCreateNewSampleDiscardsChangesEventParticipant = "infoCreateNewSampleDiscardsChangesEventParticipant"; String infoCustomExport = "infoCustomExport"; @@ -1015,6 +1026,7 @@ public interface Strings { String infoMoreDetailsAboutHospitalization = "infoMoreDetailsAboutHospitalization"; String infoNoAccessToPersonEntities = "infoNoAccessToPersonEntities"; String infoNoAdditionalTests = "infoNoAdditionalTests"; + String infoNoAefiInvestigations = "infoNoAefiInvestigations"; String infoNoCasesFoundStatistics = "infoNoCasesFoundStatistics"; String infoNoCustomizableEnumTranslations = "infoNoCustomizableEnumTranslations"; String infoNoDiseaseSelected = "infoNoDiseaseSelected"; @@ -1120,6 +1132,9 @@ public interface Strings { String messageAdditionalTestSaved = "messageAdditionalTestSaved"; String messageAdverseEventArchived = "messageAdverseEventArchived"; String messageAdverseEventDearchived = "messageAdverseEventDearchived"; + String messageAdverseEventInvestigationArchived = "messageAdverseEventInvestigationArchived"; + String messageAdverseEventInvestigationDearchived = "messageAdverseEventInvestigationDearchived"; + String messageAdverseEventInvestigationSaved = "messageAdverseEventInvestigationSaved"; String messageAdverseEventSaved = "messageAdverseEventSaved"; String messageAggregatedReportEpiWeekFilterNotFilled = "messageAggregatedReportEpiWeekFilterNotFilled"; String messageAggregateReportDelete = "messageAggregateReportDelete"; @@ -1650,6 +1665,12 @@ public interface Strings { String promptAefiDateType = "promptAefiDateType"; String promptAefiEpiWeekFrom = "promptAefiEpiWeekFrom"; String promptAefiEpiWeekTo = "promptAefiEpiWeekTo"; + String promptAefiInvestigationDateFrom = "promptAefiInvestigationDateFrom"; + String promptAefiInvestigationDateTo = "promptAefiInvestigationDateTo"; + String promptAefiInvestigationDateType = "promptAefiInvestigationDateType"; + String promptAefiInvestigationEpiWeekFrom = "promptAefiInvestigationEpiWeekFrom"; + String promptAefiInvestigationEpiWeekTo = "promptAefiInvestigationEpiWeekTo"; + String promptAefiInvestigationValidFrom = "promptAefiInvestigationValidFrom"; String promptAefiValidFrom = "promptAefiValidFrom"; String promptAllAreas = "promptAllAreas"; String promptAllCommunities = "promptAllCommunities"; @@ -1676,6 +1697,7 @@ public interface Strings { String promptDateTo = "promptDateTo"; String promptDisease = "promptDisease"; String promptDistrict = "promptDistrict"; + String promptEmail = "promptEmail"; String promptEnvironmentDateFrom = "promptEnvironmentDateFrom"; String promptEnvironmentDateTo = "promptEnvironmentDateTo"; String promptEnvironmentEpiWeekFrom = "promptEnvironmentEpiWeekFrom"; @@ -1738,6 +1760,7 @@ public interface Strings { String promptPrescriptionTextFilter = "promptPrescriptionTextFilter"; String promptRegion = "promptRegion"; String promptRelatedPersonLikeField = "promptRelatedPersonLikeField"; + String promptRemarks = "promptRemarks"; String promptSampleDashboardFilterDateType = "promptSampleDashboardFilterDateType"; String promptSampleDateFrom = "promptSampleDateFrom"; String promptSampleDateTo = "promptSampleDateTo"; @@ -1757,6 +1780,7 @@ public interface Strings { String promptTaskEpiWeekFrom = "promptTaskEpiWeekFrom"; String promptTaskEpiWeekTo = "promptTaskEpiWeekTo"; String promptTaskSearchField = "promptTaskSearchField"; + String promptTelephoneNumber = "promptTelephoneNumber"; String promptTravelEntryDateFrom = "promptTravelEntryDateFrom"; String promptTravelEntryDateTo = "promptTravelEntryDateTo"; String promptTravelEntryEpiWeekFrom = "promptTravelEntryEpiWeekFrom"; 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 68a9fbe69a4..acf04abd059 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 @@ -10,9 +10,11 @@ public interface Validations { * 1. java:S115: Violation of name convention for constants of this class is accepted: Close as false positive. */ + String aefiInvestigationWithoutPrimarySuspectVaccine = "aefiInvestigationWithoutPrimarySuspectVaccine"; + String aefiInvestigationWithoutSuspectVaccines = "aefiInvestigationWithoutSuspectVaccines"; String aefiWithoutAdverseEvents = "aefiWithoutAdverseEvents"; String aefiWithoutPrimarySuspectVaccine = "aefiWithoutPrimarySuspectVaccine"; - String aefiWithoutSuspectVaccine = "aefiWithoutSuspectVaccine"; + String aefiWithoutSuspectVaccines = "aefiWithoutSuspectVaccines"; String afterDate = "afterDate"; String afterDateSoft = "afterDateSoft"; String afterDateWithDate = "afterDateWithDate"; @@ -266,6 +268,7 @@ public interface Validations { String userNameNotUnique = "userNameNotUnique"; String uuidPatternNotMatching = "uuidPatternNotMatching"; String vaccineDosesFormat = "vaccineDosesFormat"; + String validAefiReport = "validAefiReport"; String validCaseContactOrEventParticipant = "validCaseContactOrEventParticipant"; String validCommunity = "validCommunity"; String validDateOfArrival = "validDateOfArrival"; 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 64684f3a800..806a73d1cb6 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 @@ -68,6 +68,7 @@ public enum UserRight { ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT(UserRightGroup.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION), ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE(UserRightGroup.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION), ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE(UserRightGroup.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION), + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT(UserRightGroup.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION), PERSON_VIEW(UserRightGroup.PERSON), PERSON_EDIT(UserRightGroup.PERSON, UserRight._PERSON_VIEW), @@ -336,6 +337,7 @@ public enum UserRight { public static final String _ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT = "ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT"; public static final String _ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE = "ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE"; public static final String _ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE = "ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE"; + public static final String _ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT = "ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT"; public static final String _PERSON_VIEW = "PERSON_VIEW"; public static final String _PERSON_EDIT = "PERSON_EDIT"; public static final String _PERSON_DELETE = "PERSON_DELETE"; diff --git a/sormas-api/src/main/resources/captions.properties b/sormas-api/src/main/resources/captions.properties index 70623db15e1..6c5a3bfde2c 100644 --- a/sormas-api/src/main/resources/captions.properties +++ b/sormas-api/src/main/resources/captions.properties @@ -1022,13 +1022,19 @@ sampleDashboardShowContactSamples=Show Contact Samples sampleDashboardShowEventParticipantSamples=Show Event Participant Samples sampleDashboardShowEnvironmentSamples=Show Environment Samples #AefiDashboard -aefiDashboardAllAefi=All AEFI +aefiDashboardAllAefi=AEFI aefiDashboardSerious=Serious aefiDashboardNonSerious=Non Serious aefiDashboardSeriousAefi=Serious AEFI aefiDashboardNonSeriousAefi=Non-Serious AEFI aefiDashboardShowSeriousAefi=Show Serious AEFI aefiDashboardShowNonSeriousAefi=Show Non-Serious AEFI +aefiDashboardAllAefiInvestigation=Investigations +aefiDashboardAefiInvestigationDone=Investigation Done +aefiDashboardAefiInvestigationDiscarded=Investigation Discarded +aefiDashboardAefiClassificationRelatedToVaccination=Related to vaccine or vaccination +aefiDashboardAefiClassificationCoincidentalAdverseEvent=Coincidental adverse event +aefiDashboardAefiClassificationUndetermined=Undetermined captionDefault=Default defaultRegion=Default Region @@ -2333,11 +2339,270 @@ AefiIndex.outcome=Outcome AefiIndex.vaccinationDate=Date of vaccination AefiIndex.startDateTime=Date of AEFI onset AefiIndex.adverseEvents=Adverse events -# Advers Events Criteria +# Adverse Events Export +AefiExport.receivedAtNationalLevelDate=Date AEFI report first received at national centre +AefiExport.vaccinationFacilityName=Place of vaccination +AefiExport.vaccinationFacilityRegion=Place of vaccination region +AefiExport.vaccinationFacilityDistrict=Place of vaccination district +AefiExport.vaccinationFacilityCommunity=Place of vaccination community +AefiExport.reportingOfficerAddressCountryName=Country where this AEFI reported +AefiExport.patientAddressRegion=Location (address) region +AefiExport.patientAddressDistrict=Location (address) district +AefiExport.patientAddressCommunity=Location (address) community +AefiExport.patientAddressDetails=Location (address) +AefiExport.reportingIdNumber=AEFI reporting id number +AefiExport.worldWideId=Worldwide unique number +AefiExport.firstName=Patient identifier (First Name) +AefiExport.lastName=Patient identifier (Last Name) +AefiExport.birthDate=Date of birth +AefiExport.onsetAgeYears=Age (years) at time of onset +AefiExport.onsetAgeMonths=Age (months) at time of onset +AefiExport.onsetAgeDays=Age (days) at time of onset +AefiExport.onsetAgeGroup=Age group at onset +AefiExport.sex=Sex +AefiExport.aefiDescription=History of Event +AefiExport.primarySuspectVaccineName=Primary suspect vaccine name (generic) +AefiExport.primarySuspectVaccineOtherName=Other primary suspect vaccine name (generic) +AefiExport.primarySuspectVaccineBrand=Primary suspect vaccine name (brand) +AefiExport.primarySuspectVaccineManufacturer=Primary suspect vaccine name (manufacturer) +AefiExport.primarySuspectVaccineBatchNumber=Primary supect vaccine batch number +AefiExport.primarySuspectVaccineDose=Primary suspect vaccine dose number for this particular vaccinee +AefiExport.primarySuspectVaccineDiluentBatchNumber=Diluent batch/ lot number +AefiExport.primarySuspectVaccineVaccinationDate=Date and time of primary vaccination +AefiExport.startDateTime=Date and time of AEFI onset +AefiExport.outcome=Outcome of AEFI +AefiExport.serious=Serious +AefiExport.reportingOfficerName=Name of first reporter of AEFI +AefiExport.reportingOfficerFacilityName=Institution/location +AefiExport.reportingOfficerFacilityRegion=Reporter institution/location region +AefiExport.reportingOfficerFacilityDistrict=Reporter institution/location district +AefiExport.reportingOfficerFacilityCommunity=Reporter institution/location community +AefiExport.reportingOfficerDesignation=Position +AefiExport.reportingOfficerDepartment=Department +AefiExport.reportingOfficerEmail=E-mail Id +AefiExport.reportingOfficerPhoneNumber=Telephone number +AefiExport.reportDate=Date of report +AefiExport.nationalLevelComment=Comments (if any) +# Adverse Events Criteria AefiCriteria.aefiType=AEFI Type AefiCriteria.outcome=Outcome AefiCriteria.vaccineName=Vaccine AefiCriteria.vaccineManufacturer=Manufacturer +# Adverse Events List Entry +AefiInvestigationListEntry.investigationDate=Investigation Date +AefiInvestigationListEntry.investigationStage=Stage +AefiInvestigationListEntry.statusOnDateOfInvestigation=Status +AefiInvestigationListEntry.aefiClassification=Classification +# Adverse Events Following Immunization Investigations +AefiInvestigation.uuid=AEFI Investigation UUID +AefiInvestigation.reportDate=Date of report +AefiInvestigation.reportingUser=Reporting user +AefiInvestigation.externalId=External ID +AefiInvestigation.responsibleRegion=Responsible region +AefiInvestigation.responsibleDistrict=Responsible district +AefiInvestigation.responsibleCommunity=Responsible community +AefiInvestigation.country=Country +AefiInvestigation.investigationCaseId=Investigation Case ID +AefiInvestigation.placeOfVaccination=Place of vaccination +AefiInvestigation.placeOfVaccinationDetails=Place of vaccination details +AefiInvestigation.vaccinationActivity=Vaccination in +AefiInvestigation.vaccinationActivityDetails=Vaccination activity details +AefiInvestigation.vaccinationFacility=Facility +AefiInvestigation.vaccinationFacilityDetails=Facility name & description +AefiInvestigation.reportingOfficerName=Name of reporting officer +AefiInvestigation.reportingOfficerFacility=Facility +AefiInvestigation.reportingOfficerFacilityDetails=Facility name & description +AefiInvestigation.reportingOfficerDesignation=Designation / Position +AefiInvestigation.reportingOfficerDepartment=Department +AefiInvestigation.reportingOfficerAddress=Address of reporting officer +AefiInvestigation.reportingOfficerLandlinePhoneNumber=Telephone # landline (with code): +AefiInvestigation.reportingOfficerMobilePhoneNumber=Mobile +AefiInvestigation.reportingOfficerEmail=E-mail +AefiInvestigation.investigationDate=Date of investigation +AefiInvestigation.formCompletionDate=Date of filling this form +AefiInvestigation.investigationStage=This report is +AefiInvestigation.typeOfSite=Type of site +AefiInvestigation.typeOfSiteDetails=Type of site details +AefiInvestigation.keySymptomDateTime=Date & time of first/key symptom +AefiInvestigation.hospitalizationDate=Date of hospitalization +AefiInvestigation.reportedToHealthAuthorityDate=Date first reported to the health authority +AefiInvestigation.statusOnDateOfInvestigation=Status on the date of investigation +AefiInvestigation.deathDateTime=Date and time of death +AefiInvestigation.autopsyDone=Autopsy done? +AefiInvestigation.autopsyDate=Autopsy date +AefiInvestigation.autopsyPlannedDateTime=Autopsy planned on +AefiInvestigation.pastHistoryOfSimilarEvent=Past history of similar event +AefiInvestigation.pastHistoryOfSimilarEventDetails=Additional information +AefiInvestigation.adverseEventAfterPreviousVaccinations=Adverse event after previous vaccination(s) +AefiInvestigation.adverseEventAfterPreviousVaccinationsDetails=Additional information +AefiInvestigation.historyOfAllergyToVaccineDrugOrFood=History of allergy to vaccine, drug or food +AefiInvestigation.historyOfAllergyToVaccineDrugOrFoodDetails=Additional information +AefiInvestigation.preExistingIllnessThirtyDaysOrCongenitalDisorder=Pre-existing illness (30 days) / congenital disorder +AefiInvestigation.preExistingIllnessThirtyDaysOrCongenitalDisorderDetails=Additional information +AefiInvestigation.historyOfHospitalizationInLastThirtyDaysWithCause=History of hospitalization in last 30 days, with cause +AefiInvestigation.historyOfHospitalizationInLastThirtyDaysWithCauseDetails=Additional information +AefiInvestigation.currentlyOnConcomitantMedication=Patient currently on concomitant medication? +AefiInvestigation.currentlyOnConcomitantMedicationDetails=Additional information +AefiInvestigation.familyHistoryOfDiseaseOrAllergy=Family history of any disease (relevant to AEFI) or allergy +AefiInvestigation.familyHistoryOfDiseaseOrAllergyDetails=Additional information +AefiInvestigation.numberOfWeeksPregnant=Number of weeks pregnant +AefiInvestigation.birthTerm=The birth was +AefiInvestigation.birthWeight=Birth weight: +AefiInvestigation.deliveryProcedure=Delivery procedure +AefiInvestigation.deliveryProcedureDetails=Delivery procedure details +AefiInvestigation.seriousAefiInfoSource=Source of information +AefiInvestigation.seriousAefiInfoSourceDetails=Other source of information details +AefiInvestigation.seriousAefiVerbalAutopsyInfoSourceDetails=Please mention verbal autopsy source +AefiInvestigation.firstCaregiversName=Name of the person who first examined/treated the patient +AefiInvestigation.otherCaregiversNames=Name of other persons treating the patient +AefiInvestigation.otherSourcesWhoProvidedInfo=Other sources who provided information +AefiInvestigation.signsAndSymptomsFromTimeOfVaccination=Signs and symptoms in chronological order from the time of vaccination +AefiInvestigation.clinicalDetailsOfficerName=Name of person completing these clinical details +AefiInvestigation.clinicalDetailsOfficerPhoneNumber=Phone number +AefiInvestigation.clinicalDetailsOfficerEmail=E-mail +AefiInvestigation.clinicalDetailsOfficerDesignation=Designation +AefiInvestigation.clinicalDetailsDateTime=Date/time +AefiInvestigation.patientReceivedMedicalCare=Patient has received medical care +AefiInvestigation.patientReceivedMedicalCareDetails=Complete additional medical care information NOT AVAILABLE in existing documents +AefiInvestigation.provisionalOrFinalDiagnosis=Provisional / Final diagnosis +AefiInvestigation.patientImmunizedPeriod=When was the patient immunized? +AefiInvestigation.patientImmunizedPeriodDetails=Additional information +AefiInvestigation.vaccineGivenPeriod=In case of multidose vials, was the vaccine given +AefiInvestigation.vaccineGivenPeriodDetails=Additional information +AefiInvestigation.errorPrescribingVaccine=Was there an error in prescribing or non-adherence to recommendations for use of this vaccine? +AefiInvestigation.errorPrescribingVaccineDetails=Additional information +AefiInvestigation.vaccineCouldHaveBeenUnSterile=Based on your investigation, do you feel that the vaccine (ingredients) administered could have been unsterile? +AefiInvestigation.vaccineCouldHaveBeenUnSterileDetails=Additional information +AefiInvestigation.vaccinePhysicalConditionAbnormal=Based on your investigation, do you feel that the vaccine's physical condition (e.g. colour, turbidity, foreign substances etc.) was abnormal at the time of administration? +AefiInvestigation.vaccinePhysicalConditionAbnormalDetails=Additional information +AefiInvestigation.errorInVaccineReconstitution=Based on your investigation, do you feel that there was an error in vaccine reconstitution/preparation by the vaccinator (e.g. wrong product, wrong diluent, improper mixing, improper syringe filling etc.)? +AefiInvestigation.errorInVaccineReconstitutionDetails=Additional information +AefiInvestigation.errorInVaccineHandling=Based on your investigation, do you feel that there was an error in vaccine handling (e.g. break in cold chain during transport, storage and/or immunization session etc.)? +AefiInvestigation.errorInVaccineHandlingDetails=Additional information +AefiInvestigation.vaccineAdministeredIncorrectly=Based on your investigation, do you feel that the vaccine was administered incorrectly (e.g. wrong dose, site or route of administration, wrong needle size, not following good injection practice etc.)? +AefiInvestigation.vaccineAdministeredIncorrectlyDetails=Additional information +AefiInvestigation.numberImmunizedFromConcernedVaccineVial=Number immunized from the concerned vaccine vial/ampoule +AefiInvestigation.numberImmunizedWithConcernedVaccineInSameSession=Number immunized with the concerned vaccine in the same session +AefiInvestigation.numberImmunizedConcernedVaccineSameBatchNumberOtherLocations=Number immunized with the concerned vaccine having the same batch number in other locations +AefiInvestigation.numberImmunizedConcernedVaccineSameBatchNumberLocationDetails=Specify locations +AefiInvestigation.vaccineHasQualityDefect=Could the vaccine given to this patient have a quality defect or is substandard or falsified? +AefiInvestigation.vaccineHasQualityDefectDetails=Additional information +AefiInvestigation.eventIsAStressResponseRelatedToImmunization=Could this event be a stress response related to immunization (e.g. acute stress response, vasovagal reaction, hyperventilation, dissociative neurological symptom reaction etc.)? +AefiInvestigation.eventIsAStressResponseRelatedToImmunizationDetails=Additional information +AefiInvestigation.caseIsPartOfACluster=Is this case a part of a cluster? +AefiInvestigation.caseIsPartOfAClusterDetails=Additional information +AefiInvestigation.numberOfCasesDetectedInCluster=How many other cases have been detected in the cluster? +AefiInvestigation.allCasesInClusterReceivedVaccineFromSameVial=Did all the cases in the cluster receive vaccine from the same vial? +AefiInvestigation.allCasesInClusterReceivedVaccineFromSameVialDetails=Additional information +AefiInvestigation.numberOfVialsUsedInCluster=Number of vials used in the cluster +AefiInvestigation.numberOfVialsUsedInClusterDetails=Number of vials used in the cluster details +AefiInvestigation.adSyringesUsedForImmunization=Are AD syringes used for immunization? +AefiInvestigation.typeOfSyringesUsed=Type of syringes used +AefiInvestigation.typeOfSyringesUsedDetails=Additional information +AefiInvestigation.syringesUsedAdditionalDetails=Specific key findings/additional observations and comments +AefiInvestigation.sameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine=Same reconstitution syringe used for multiple vials of same vaccine? +AefiInvestigation.sameReconstitutionSyringeUsedForReconstitutingDifferentVaccines=Same reconstitution syringe used for reconstituting different vaccines? +AefiInvestigation.sameReconstitutionSyringeForEachVaccineVial=Separate reconstitution syringe for each vaccine vial? +AefiInvestigation.sameReconstitutionSyringeForEachVaccination=Separate reconstitution syringe for each vaccination? +AefiInvestigation.vaccinesAndDiluentsUsedRecommendedByManufacturer=Are the vaccines and diluents used the same as those recommended by the manufacturer? +AefiInvestigation.reconstitutionAdditionalDetails=Specific key findings/additional observations and comments +AefiInvestigation.correctDoseOrRoute=Correct dose and route? +AefiInvestigation.timeOfReconstitutionMentionedOnTheVial=Time of reconstitution mentioned on the vial? (in case of freeze dried vaccines) +AefiInvestigation.nonTouchTechniqueFollowed=Non-touch technique followed? +AefiInvestigation.contraIndicationScreenedPriorToVaccination=Contraindications screened prior to vaccination? +AefiInvestigation.numberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays=How many AEFI were reported from the centre that distributed the vaccine in the last 30 days? +AefiInvestigation.trainingReceivedByVaccinator=Training received by the vaccinator? +AefiInvestigation.lastTrainingReceivedByVaccinatorDate=Date of last training +AefiInvestigation.injectionTechniqueAdditionalDetails=Specific key findings/ additional observations and comments? +AefiInvestigation.vaccineStorageRefrigeratorTemperatureMonitored=Is the temperature of the vaccine storage refrigerator monitored? +AefiInvestigation.anyStorageTemperatureDeviationOutsideTwoToEightDegrees=Was there any deviation outside of 2-8 (degrees C) after the vaccine was placed inside? +AefiInvestigation.storageTemperatureMonitoringAdditionalDetails=Provide details of monitoring separately +AefiInvestigation.correctProcedureForStorageFollowed=Was the correct procedure for storing vaccines, diluents and syringes followed? +AefiInvestigation.anyOtherItemInRefrigerator=Was any other item (other than EPI vaccines and diluents) in the refrigerator or freezer? +AefiInvestigation.partiallyUsedReconstitutedVaccinesInRefrigerator=Were any partially used reconstituted vaccines in the refrigerator? +AefiInvestigation.unusableVaccinesInRefrigerator=Were any unusable vaccines (expired, no label, VVM at stages 3 or 4, frozen) in the refrigerator? +AefiInvestigation.unusableDiluentsInStore=Were any unusable diluents (expired, manufacturer not matched, cracked, dirty ampoule) in the store? +AefiInvestigation.vaccineStoragePointAdditionalDetails=Specific key findings/additional observations and comments: +AefiInvestigation.vaccineCarrierType=Type of vaccine carrier used +AefiInvestigation.vaccineCarrierTypeDetails=Additional information +AefiInvestigation.vaccineCarrierSentToSiteOnSameDateAsVaccination=Was the vaccine carrier sent to the site on the same day as vaccination? +AefiInvestigation.vaccineCarrierReturnedFromSiteOnSameDateAsVaccination=Was the vaccine carrier returned from the site on the same day as vaccination? +AefiInvestigation.conditionedIcepackUsed=Was a conditioned ice-pack used? +AefiInvestigation.vaccineTransportationAdditionalDetails=Specific key findings/additional observations and comments +AefiInvestigation.similarEventsReportedSamePeriodAndLocality=Were any similar events reported within a time period similar to when the adverse event occurred and in the same locality? +AefiInvestigation.similarEventsReportedSamePeriodAndLocalityDetails=Additional information +AefiInvestigation.numberOfSimilarEventsReportedSamePeriodAndLocality=How many events/episodes? +AefiInvestigation.numberOfThoseAffectedVaccinated=Vaccinated +AefiInvestigation.numberOfThoseAffectedNotVaccinated=Not vaccinated +AefiInvestigation.numberOfThoseAffectedVaccinatedUnknown=Unknown +AefiInvestigation.communityInvestigationAdditionalDetails=Other comments: +AefiInvestigation.otherInvestigationFindings=Other findings/observations/comments +AefiInvestigation.investigationStatus=Investigation status +AefiInvestigation.investigationStatusDetails=Investigation status details +AefiInvestigation.aefiClassification=Classification of AEFI +AefiInvestigation.aefiClassificationSubType=Reason for classification +AefiInvestigation.aefiClassificationDetails=Classification of AEFI details +AefiInvestigation.causality=Causality +AefiInvestigation.causalityDetails=Causality details +AefiInvestigation.investigationCompletionDate=Date investigation completed +AefiInvestigation.deletionReason=Reason for deletion +AefiInvestigation.otherDeletionReason=Reason for deletion details +AefiInvestigation.creationDate=Creation date +AefiInvestigation.changeDate=Date of last change +aefiInvestigationForAdultWomen=For adult women +aefiInvestigationForInfants=For infants +aefiInvestigationSourceOfInformation=Source of information +aefiInvestigationClinicalDetailsOfficer=Clinical Details Officer +aefiInvestigationMedicalCareDetailsInstruction=**Instructions ? Attach copies of ALL available documents (including case sheet, discharge summary, case notes, laboratory reports and autopsy reports) and then complete additional information NOT AVAILABLE in existing documents, +aefiInvestigationReconstitutionProcedure=Reconstitution procedure +aefiInvestigationOfThoseAffected=Of those effected, how many are +aefiAefiInvestigationList=Adverse Event Investigations +aefiNewAefiInvestigation = New Investigation +aefiAefiInvestigationDataView=Adverse Event Investigation +aefiNewAefiInvestigationStageTitle=Investigation +aefiActiveInvestigations = Active AEFI investigations +aefiArchivedInvestigations = Archived AEFI investigations +aefiAllActiveAndArchivedInvestigations = All active and archived AEFI investigations +aefiDeletedInvestigations = Deleted AEFI investigations +titleAefiInvestigationBasicDetails=Section A: Basic details +titleAefiInvestigationRelevantPatientInformation=Section B: Relevant patient information prior to immunization +titleAefiInvestigationFirstExaminationDetails=Section C: Details of first examination** of serious AEFI case +titleAefiInvestigationVaccinesDetails=Section D: Details of vaccines provided at the site linked to AEFI on the corresponding day +titleAefiInvestigationImmunizationPractices=Section E: Immunization practices at the place(s) where concerned vaccine was used +titleAefiInvestigationImmunizationPracticesSubTitle=(Complete this section by asking and/or observing practice) +titleAefiInvestigationImmunizationPracticesSyringesAndNeedlesUsed=Syringes and needles used +titleAefiInvestigationImmunizationPracticesReconstitution=Reconstitution: (complete only if applicable) +titleAefiInvestigationImmunizationPracticesInjectionTechnique=Injection technique in vaccinator(s): (Observe another session in the same locality ? same or different place) +titleAefiInvestigationColdChainAndTransport=Section F: Cold chain and transport +titleAefiInvestigationColdChainAndTransportSubTitle=(Complete this section by asking and/or observing practice) +titleAefiInvestigationColdChainAndTransportLastVaccineStoragePoint=Last vaccine storage point +titleAefiInvestigationColdChainAndTransportVaccineTransportation=Vaccine transportation +titleAefiInvestigationCommunityInvestigation=Section G: Community investigation (Please visit locality and interview parents/others) +titleAefiInvestigationCommunityInvestigationThoseAffected=Of those effected, how many are +titleAefiInvestigationOtherFindings=Section H: Other findings/observations/comments +titleAefiInvestigationInvestigationStatus=Section I: Investigation Status +# Adverse Events Investigation Criteria +AefiInvestigationCriteria.statusAtAefiInvestigation=Patient status +AefiInvestigationCriteria.aefiClassification=Classification +AefiInvestigationCriteria.vaccineName=Vaccine +AefiInvestigationCriteria.vaccineManufacturer=Manufacturer +# Adverse Events Investigation Index +AefiInvestigationIndex.uuid=Investigation ID +AefiInvestigationIndex.aefiReportUuid=AEFI ID +AefiInvestigationIndex.investigationCaseId=Case ID +AefiInvestigationIndex.personFirstName=First Name +AefiInvestigationIndex.personLastName=Last Name +AefiInvestigationIndex.reportDate=Date of report +AefiInvestigationIndex.investigationDate=Date of investigation +AefiInvestigationIndex.disease=Disease +AefiInvestigationIndex.ageAndBirthDate=Age and birth date +AefiInvestigationIndex.sex=Sex +AefiInvestigationIndex.region=Region +AefiInvestigationIndex.district=District +AefiInvestigationIndex.primaryVaccine=Concerned Vaccine +AefiInvestigationIndex.statusOnDateOfInvestigation=Patient Status +AefiInvestigationIndex.investigationStatus=Status +AefiInvestigationIndex.aefiClassification=Classification # Statistics statisticsAddFilter=Add filter statisticsAttribute=Attribute @@ -2840,6 +3105,7 @@ View.samples.sub= View.travelEntries=Travel Entries Directory View.immunizations=Immunization Directory View.adverseevents=Adverse Events Directory +View.adverseeventinvestigations=AEFI Investigations Directory View.statistics=Statistics View.statistics.database-export=Database export View.tasks=Task Management diff --git a/sormas-api/src/main/resources/enum.properties b/sormas-api/src/main/resources/enum.properties index 5880c9e0f00..4bf5a3190d5 100644 --- a/sormas-api/src/main/resources/enum.properties +++ b/sormas-api/src/main/resources/enum.properties @@ -1556,6 +1556,7 @@ UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE = Create new adverse even UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT = Edit existing adverse event following immunization UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE = Delete adverse events following immunization from the system UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE = Archive adverse events following immunization +UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT = Export adverse events following immunization UserRight.PERSON_EXPORT = Export persons UserRight.CONTACT_MERGE = Merge contacts UserRight.EVENTGROUP_CREATE = Create new event groups @@ -1779,6 +1780,7 @@ UserRight.Desc.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE = Able to create new UserRight.Desc.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT = Able to edit existing adverse events following immunization UserRight.Desc.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE = Able to delete adverse events following immunization from the system UserRight.Desc.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE = Able to archive adverse events following immunization +UserRight.Desc.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT = Able to export adverse events following immunization UserRight.Desc.PERSON_EXPORT = Able to export persons UserRight.Desc.CONTACT_MERGE = Able to merge contacts UserRight.Desc.EVENTGROUP_CREATE = Able to create new event groups @@ -2073,16 +2075,24 @@ Vaccine.VALNEVA=inactivated (Valneva) Vaccine.NUVAXOVID=protein-based, recombinant (Novavax) Vaccine.MRNA_BIVALENT_BA_4_5_BIONTECH_PFIZER=mRNA/bivalent BA.4/5 (BioNTech/Pfizer) Vaccine.MRNA_BIVALENT_BA_4_5_MODERNA=mRNA/bivalent BA.4/5 (Moderna) +Vaccine.MenABCWY=PENBRAYA +Vaccine.ACAM2000=ACAM2000 +Vaccine.LC_16=LC-16 +Vaccine.MVA_BN=JYNNEOS Vaccine.UNKNOWN=Unknown Vaccine.OTHER=Other # VaccineManufacturer VaccineManufacturer.BIONTECH_PFIZER=BioNTech/Pfizer +VaccineManufacturer.PFIZER=Pfizer +VaccineManufacturer.BAVARIAN_NORDIC=Bavarian Nordic VaccineManufacturer.MODERNA=Moderna VaccineManufacturer.ASTRA_ZENECA=AstraZeneca VaccineManufacturer.JOHNSON_JOHNSON=Johnson & Johnson +VaccineManufacturer.KM_BIOLOGICS=KM Biologics VaccineManufacturer.NOVAVAX=Novavax VaccineManufacturer.SANOFI_GSK=Sanofi-GSK +VaccineManufacturer.SANOFI_PASTEUR_BIOLOGICS=Sanofi Pasteur Biologics VaccineManufacturer.ASTRA_ZENECA_BIONTECH_PFIZER=AstraZeneca & BioNTech/Pfizer VaccineManufacturer.ASTRA_ZENECA_MODERNA=AstraZeneca & Moderna VaccineManufacturer.VALNEVA=Valneva @@ -2384,4 +2394,94 @@ AefiDateType.VACCINATION_DATE=Date of vaccination # AefiDashboardFilterDateType AefiDashboardFilterDateType.REPORT_DATE=Date of report -AefiDashboardFilterDateType.START_DATE=Date of onset \ No newline at end of file +AefiDashboardFilterDateType.START_DATE=Date of onset + +# AefiInvestigationDateType +AefiInvestigationDateType.REPORT_DATE=Date of report +AefiInvestigationDateType.INVESTIGATION_DATE=Date of investigation +AefiInvestigationDateType.VACCINATION_DATE=Date of vaccination + +# PlaceOfVaccination +PlaceOfVaccination.GOVERNMENT_HEALTH_FACILITY=Government health facility +PlaceOfVaccination.PRIVATE_HEALTH_FACILITY=Private health facility +PlaceOfVaccination.OTHER=Other + +# VaccinationActivity +VaccinationActivity.CAMPAIGN=Campaign +VaccinationActivity.ROUTINE=Routine +VaccinationActivity.OTHER=Other + +# AefiInvestigationStage +AefiInvestigationStage.FIRST=First +AefiInvestigationStage.INTERIM=Interim +AefiInvestigationStage.FINAL=Final + +# VaccinationSite +VaccinationSite.FIXED=Fixed +VaccinationSite.MOBILE=Mobile +VaccinationSite.OUTREACH=Outreach +VaccinationSite.OTHER=Other + +# PatientStatusAtAefiInvestigation +PatientStatusAtAefiInvestigation.DIED=Died +PatientStatusAtAefiInvestigation.DISABLED=Disabled +PatientStatusAtAefiInvestigation.RECOVERED=Recovering +PatientStatusAtAefiInvestigation.RECOVERED_COMPLETELY=Recovered completely +PatientStatusAtAefiInvestigation.UNKNOWN=Unknown + +# BirthTerm +BirthTerm.FULL_TERM=Full-term +BirthTerm.PRE_TERM=Pre-term +BirthTerm.POST_TERM=Post-term + +# DeliveryProcedure +DeliveryProcedure.NORMAL=Normal +DeliveryProcedure.CAESAREAN=Caesarean +DeliveryProcedure.ASSISTED=Assisted (forceps, vacuum etc.) +DeliveryProcedure.WITH_COMPLICATION=with complication + +# SeriousAefiInfoSource +SeriousAefiInfoSource.EXAMINATION=Examination by the investigator +SeriousAefiInfoSource.DOCUMENTS=Documents +SeriousAefiInfoSource.VERBAL_AUTOPSY=Verbal autopsy +SeriousAefiInfoSource.OTHER=Other + +# AefiImmunizationPeriod +AefiImmunizationPeriod.WITHIN_FIRST_VACCINATIONS=Within the first vaccinations of the session +AefiImmunizationPeriod.WITHIN_LAST_VACCINATIONS=Within the last vaccinations of the session +AefiImmunizationPeriod.UNKNOWN=Unknown + +# AefiVaccinationPeriod +AefiVaccinationPeriod.WITHIN_FIRST_FEW_DOSES=Within the first few doses of the vial administered +AefiVaccinationPeriod.WITHIN_LAST_DOSES=Within the last doses of the vial administered +AefiVaccinationPeriod.UNKNOWN=Unknown + +# SyringeType +SyringeType.GLASS=Glass +SyringeType.DISPOSABLE=Disposable +SyringeType.RECYCLED_DISPOSABLE=Recycled disposable +SyringeType.OTHER=Other + +# VaccineCarrier +VaccineCarrier.SHORT_RANGE=Short range +VaccineCarrier.LONG_RANGE=Long range +VaccineCarrier.OTHER=Other + +# AefiInvestigationStatus +AefiInvestigationStatus.DONE=Done +AefiInvestigationStatus.DISCARDED=Discarded + +# AefiCausality +AefiCausality.CONFIRMED=Confirmed +AefiCausality.INCONCLUSIVE=Inconclusive + +# AefiClassification +AefiClassification.RELATED_TO_VACCINE_OR_VACCINATION=Related to vaccine or vaccination +AefiClassification.COINCIDENTAL_ADVERSE_EVENT=Coincidental adverse event +AefiClassification.UNDETERMINED=Undetermined + +# AefiClassificationSubType +AefiClassificationSubType.VACCINE_PRODUCT_RELATED=Vaccine product related +AefiClassificationSubType.VACCINE_QUALITY_DEFECT_RELATED=Vaccine quality defect related +AefiClassificationSubType.IMMUNIZATION_ERROR_RELATED=Immunization error related +AefiClassificationSubType.IMMUNIZATION_ANXIETY_RELATED=Immunization anxiety related \ No newline at end of file diff --git a/sormas-api/src/main/resources/strings.properties b/sormas-api/src/main/resources/strings.properties index 845fd0c6f1f..ea0e48ed95c 100644 --- a/sormas-api/src/main/resources/strings.properties +++ b/sormas-api/src/main/resources/strings.properties @@ -137,6 +137,7 @@ confirmationArchiveEvents = Are you sure you want to archive all %d selected eve confirmationArchiveEventParticipant = Are you sure you want to archive this event participant? This will not remove it from the system or any statistics, but only hide it from the list of event participants. confirmationArchiveImmunization = Are you sure you want to archive this immunization? This will not remove it from the system or any statistics, but only hide it from the normal immunization directory. confirmationArchiveAdverseEvent = Are you sure you want to archive this adverse event? This will not remove it from the system or any statistics, but only hide it from the normal adverse events directory. +confirmationArchiveAdverseEventInvestigation = Are you sure you want to archive this adverse event investigation? This will not remove it from the system or any statistics, but only hide it from the normal adverse events investigation directory. confirmationArchiveTask = Are you sure you want to archive this task? This will not remove it from the system or any statistics, but only hide it from the normal task management. confirmationArchiveTasks = Are you sure you want to archive all %d selected tasks? confirmationArchiveTravelEntry = Are you sure you want to archive this travel entry? This will not remove it from the system or any statistics, but only hide it from the normal travel entry directory. @@ -219,6 +220,7 @@ confirmationArchiveFacilities = Are you sure you want to archive all %d selected confirmationDearchiveFacilities = Are you sure you want to de-archive all %d selected facilities? confirmationDearchiveImmunization = Are you sure you want to de-archive this immunization? This will make it appear in the normal immunization directory again. confirmationDearchiveAdverseEvent = Are you sure you want to de-archive this adverse event? This will make it appear in the normal adverse events directory again. +confirmationDearchiveAdverseEventInvestigation = Are you sure you want to de-archive this adverse event investigation? This will make it appear in the normal adverse events investigation directory again. confirmationArchiveLaboratories = Are you sure you want to archive all %d selected laboratories? confirmationDearchiveLaboratories = Are you sure you want to de-archive all %d selected laboratories? confirmationDearchiveTask = Are you sure you want to de-archive this task? This will make it appear in the normal task directory again. @@ -347,6 +349,8 @@ entityCampaignFormMeta = Campaign form meta entityCampaignFormData = Campaign form data entityAdverseEvent = Adverse event entityAdverseEvents = Adverse events +entityAdverseEventInvestigation = Adverse event investigation +entityAdverseEventInvestigations = Adverse event investigations # Error Messages errorAccessDenied=You do not have the required rights to view this page. @@ -435,6 +439,7 @@ errorEnvironmentSampleNoReceivalRight = You do not have the necessary user right errorSendingExternalEmail = Email could not be sent. Please contact an admin and notify them about this problem. errorExternalEmailAttachmentCannotEncrypt=Can't send email with attachments. The person has no national health id or primary phone number to send the password to or the SMS service is not set up in the system. errorAdverseEventNotEditable = This adverse event is not editable anymore +errorAdverseEventInvestigationNotEditable = This adverse event investigation is not editable anymore errorExternalEmailMissingPersonEmailAddress=This person does not have an email address # headings @@ -452,6 +457,7 @@ headingArchiveEventParticipant = Archive event participant headingArchiveEventGroup = Archive event group headingArchiveImmunization = Archive immunization headingArchiveAdverseEvent = Archive adverse event +headingArchiveAdverseEventInvestigation = Archive adverse event investigation headingArchiveTravelEntry = Archive travel entry headingCampaignBasics = Campaign basics headingCampaignData = Campaign data @@ -527,6 +533,8 @@ headingDearchiveEvent = De-Archive event headingDearchiveEventParticipant = De-Archive event participant headingDearchiveEventGroup = De-Archive event group headingDearchiveImmunization = De-Archive immunization +headingDearchiveAdverseEvent = De-Archive adverse event +headingDearchiveAdverseEventInvestigation = De-Archive adverse event investigation headingDearchiveTravelEntry = De-Archive travel entry headingDefineOutbreakDistricts = Define which districts currently are affected by an outbreak. headingDeleteConfirmation = Confirm deletion @@ -884,6 +892,8 @@ headingExternalEmailSend=Send email headingExternalEmailDetails=Email details headingCustomizableEnumConfigurationInfo=Customizable enum configuration headingImmunizationAdverseEvents=Adverse events +headingAefiDashboardEpiCurve=Adverse Events Type Chart +headingAefiDashboardMap=Adverse Events Status Map headingAefiReportingInformation=Reporting information headingAefiPatientsIdentification=Patients identification headingAefiPatientsAgeAtOnset=Age at onset @@ -892,7 +902,10 @@ headingAefiAdverseEvents=Adverse events headingAefiFirstDecisionLevel=First decision Level headingAefiNationalDecisionLevel=National Decision Level headingAefiReportersInformation=Reporter's information -headingAefiPickPrimarySuspectVaccine=Select primary suspect vaccine +headingAefiSelectPrimarySuspectVaccine=Select primary suspect vaccine +headingAefiReportInvestigations=Investigations +headingAefiInvestigationSelectConcernedVaccine=Select concerned vaccine +headingAefiInvestigationFormSubHeading=(Only for Serious Adverse Events Following Immunization ? Death / Disability / Hospitalization / Cluster) # Info texts infoActivityAsCaseInvestigation = Please document ALL relevant activities after infection: @@ -1098,6 +1111,8 @@ infoCustomizableEnumConfigurationInfo = Customizable enums are value sets that c infoNoImmunizationAdverseEvents = No adverse events have been created for this immunization infoAefiSelectPrimarySuspectVaccine = The list below contains all vaccinations of the immunization. Please select the suspect vaccination related to this adverse event. infoArchivedAefiEntries = Adverse event entries are automatically archived after %d days without changes to the data. +infoNoAefiInvestigations = No investigations have been created for this adverse event +infoHeadingAefiDashboardMap=Adverse events are shown using the GPS coordinate of the facility or person's home address. # Messages messageActionOutsideJurisdictionDeletionDenied = The action outside user's jurisdiction cannot be deleted @@ -1281,6 +1296,8 @@ messageImmunizationSaved = Immunization data saved. messageImmunizationSavedVaccinationStatusUpdated = Immunization data saved. The vaccination status of matching cases, contacts, and event participants of the immunization person has been updated to vaccinated. messageAdverseEventArchived = Adverse event has been archived messageAdverseEventDearchived = Adverse event has been de-archived +messageAdverseEventInvestigationArchived = Adverse event investigation has been archived +messageAdverseEventInvestigationDearchived = Adverse event investigation has been de-archived messageImportCanceled = Import canceled!
The import has been canceled. All already processed rows have been successfully imported. You can now close this window. messageImportCanceledErrors = Import canceled!
The import has been canceled. Some of the already processed rows could not be imported due to malformed data.
Please close this window and download the error report. messageImportError = Could not import file. @@ -1547,6 +1564,7 @@ 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. messageAdverseEventSaved=Adverse event saved +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. @@ -1715,12 +1733,20 @@ promptAllCommunities=All communities promptExternalIdExternalSurveillanceTool=Will adopt external reporting tool GUID promptExternalJournalForceDeletion=Do you want to force the cancellation in SORMAS? This would mark the person as deleted from the external journal in SORMAS, while there is a high probability of personal data still remaining in the external journal. promptPersonDuplicateSearchIdExternalId=First Name, Last Name, ID, External ID, External token +promptAefiDashboardFilterDateType=AEFI reference date promptAefiDateType = Aefi reference date promptAefiValidFrom = New adverse events valid from... promptAefiDateFrom = New adverse events from... promptAefiDateTo = ... to promptAefiEpiWeekFrom = New adverse events from epi week... promptAefiEpiWeekTo = ... to epi week +promptAefiInvestigationDateType = Aefi investigation reference date +promptAefiInvestigationValidFrom = New Aefi investigations valid from... +promptAefiInvestigationDateFrom = New Aefi investigations from... +promptAefiInvestigationDateTo = ... to +promptAefiInvestigationEpiWeekFrom = New Aefi investigations from epi week... +promptAefiInvestigationEpiWeekTo = ... to epi week +promptRemarks = Remarks #DiseaseNetworkDiagram DiseaseNetworkDiagram.Classification.HEALTHY = Healthy DiseaseNetworkDiagram.heading = Disease network diagram @@ -1833,11 +1859,6 @@ headingSampleDashboardMap=Sample Status Map infoHeadingSampleDashboardMap=Samples are shown using the GPS coordinate of the person's home address. infoHeadingEnvironmentSampleDashboardMap=Environment samples are shown using the GPS coordinates of those samples or, if not available, their associated environment. -promptAefiDashboardFilterDateType=AEFI reference date -headingAefiDashboardEpiCurve=Adverse Events Type Chart -headingAefiDashboardMap=Adverse Events Status Map -infoHeadingAefiDashboardMap=Adverse events are shown using the GPS coordinate of the facility or person's home address. - headingSpecailCaseAccess = Grant special access headingCreateSpecailCaseAccess = Create new special access headingEditSpecailCaseAccess = Edit special access diff --git a/sormas-api/src/main/resources/validations.properties b/sormas-api/src/main/resources/validations.properties index ac49b31d7e3..f1030a60038 100644 --- a/sormas-api/src/main/resources/validations.properties +++ b/sormas-api/src/main/resources/validations.properties @@ -297,9 +297,12 @@ customizableEnumValueEmptyTranslations = Please select languages and enter capti 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. -aefiWithoutSuspectVaccine=You have to select at least one suspect vaccine +aefiWithoutSuspectVaccines=You have to select at least one suspect vaccine aefiWithoutPrimarySuspectVaccine=You have to select the primary suspect vaccine aefiWithoutAdverseEvents=You have to select at least one adverse event +validAefiReport=You have to link a valid adverse event report +aefiInvestigationWithoutSuspectVaccines=You have to select at least one suspect vaccine +aefiInvestigationWithoutPrimarySuspectVaccine=You have to select the concerned suspect vaccine invalidNationalHealthId=This value does not seem to be a correct national health ID invalidSelfReportType = Invalid SelfReport type selfReportAlreadyProcessedError = The self report was processed by another user in the meantime. diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiFacadeEjb.java index 0d91053215e..672edfd0f34 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiFacadeEjb.java @@ -16,6 +16,7 @@ package de.symeda.sormas.backend.adverseeventsfollowingimmunization; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; import java.util.List; @@ -34,6 +35,7 @@ import de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiCriteria; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiExportDto; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiFacade; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiIndexDto; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiListCriteria; @@ -173,6 +175,15 @@ public List getIndexList(AefiCriteria criteria, Integer first, Int return resultsList; } + @Override + @RightsAllowed(UserRight._ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT) + public List getExportList(AefiCriteria criteria, Collection selectedRows, int first, int max) { + List resultsList = service.getExportList(criteria, selectedRows, first, max); + Pseudonymizer pseudonymizer = createGenericPlaceholderPseudonymizer(); + pseudonymizer.pseudonymizeDtoCollection(AefiExportDto.class, resultsList, AefiExportDto::getInJurisdiction, null); + return resultsList; + } + @Override public List getEntriesList(AefiListCriteria criteria, Integer first, Integer max) { Long immunizationId = immunizationService.getIdByUuid(criteria.getImmunization().getUuid()); @@ -295,13 +306,14 @@ protected Aefi fillOrBuildEntity(@NotNull AefiDto source, Aefi target, boolean c target.setAgeGroup(source.getAgeGroup()); target.setHealthFacility(facilityService.getByReferenceDto(source.getHealthFacility())); target.setHealthFacilityDetails(source.getHealthFacilityDetails()); - target.setReporterName(source.getReporterName()); - target.setReporterInstitution(facilityService.getByReferenceDto(source.getReporterInstitution())); - target.setReporterDesignation(source.getReporterDesignation()); - target.setReporterDepartment(source.getReporterDepartment()); - target.setReporterAddress(locationFacade.fillOrBuildEntity(source.getReporterAddress(), target.getReporterAddress(), checkChangeDate)); - target.setReporterPhone(source.getReporterPhone()); - target.setReporterEmail(source.getReporterEmail()); + target.setReportingOfficerName(source.getReportingOfficerName()); + target.setReportingOfficerFacility(facilityService.getByReferenceDto(source.getReportingOfficerFacility())); + target.setReportingOfficerDesignation(source.getReportingOfficerDesignation()); + target.setReportingOfficerDepartment(source.getReportingOfficerDepartment()); + target.setReportingOfficerAddress( + locationFacade.fillOrBuildEntity(source.getReportingOfficerAddress(), target.getReportingOfficerAddress(), checkChangeDate)); + target.setReportingOfficerPhoneNumber(source.getReportingOfficerPhoneNumber()); + target.setReportingOfficerEmail(source.getReportingOfficerEmail()); target.setTodaysDate(source.getTodaysDate()); target.setStartDateTime(source.getStartDateTime()); target.setAefiDescription(source.getAefiDescription()); @@ -369,13 +381,13 @@ public static AefiDto toAefiDto(Aefi entity) { dto.setAgeGroup(entity.getAgeGroup()); dto.setHealthFacility(FacilityFacadeEjb.toReferenceDto(entity.getHealthFacility())); dto.setHealthFacilityDetails(entity.getHealthFacilityDetails()); - dto.setReporterName(entity.getReporterName()); - dto.setReporterInstitution(FacilityFacadeEjb.toReferenceDto(entity.getReporterInstitution())); - dto.setReporterDesignation(entity.getReporterDesignation()); - dto.setReporterDepartment(entity.getReporterDepartment()); - dto.setReporterAddress(LocationFacadeEjb.toDto(entity.getReporterAddress())); - dto.setReporterPhone(entity.getReporterPhone()); - dto.setReporterEmail(entity.getReporterEmail()); + dto.setReportingOfficerName(entity.getReportingOfficerName()); + dto.setReportingOfficerFacility(FacilityFacadeEjb.toReferenceDto(entity.getReportingOfficerFacility())); + dto.setReportingOfficerDesignation(entity.getReportingOfficerDesignation()); + dto.setReportingOfficerDepartment(entity.getReportingOfficerDepartment()); + dto.setReportingOfficerAddress(LocationFacadeEjb.toDto(entity.getReportingOfficerAddress())); + dto.setReportingOfficerPhoneNumber(entity.getReportingOfficerPhoneNumber()); + dto.setReportingOfficerEmail(entity.getReportingOfficerEmail()); dto.setTodaysDate(entity.getTodaysDate()); dto.setStartDateTime(entity.getStartDateTime()); dto.setAefiDescription(entity.getAefiDescription()); @@ -410,7 +422,7 @@ public static AefiReferenceDto toReferenceDto(Aefi entity) { return null; } - return new AefiReferenceDto(entity.getUuid(), "", ""); + return new AefiReferenceDto(entity.getUuid(), ""); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiInvestigationFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiInvestigationFacadeEjb.java new file mode 100644 index 00000000000..8cef80f6506 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiInvestigationFacadeEjb.java @@ -0,0 +1,641 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import javax.ejb.EJB; +import javax.ejb.LocalBean; +import javax.ejb.Stateless; +import javax.inject.Inject; +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationCriteria; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationFacade; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationIndexDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationListCriteria; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationListEntryDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationReferenceDto; +import de.symeda.sormas.api.common.DeletableEntityType; +import de.symeda.sormas.api.common.DeletionDetails; +import de.symeda.sormas.api.common.progress.ProcessedEntity; +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.immunization.ImmunizationDto; +import de.symeda.sormas.api.user.UserRight; +import de.symeda.sormas.api.utils.AccessDeniedException; +import de.symeda.sormas.api.utils.DateHelper; +import de.symeda.sormas.api.utils.SortProperty; +import de.symeda.sormas.api.utils.ValidationRuntimeException; +import de.symeda.sormas.api.vaccination.VaccinationDto; +import de.symeda.sormas.backend.FacadeHelper; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AefiInvestigation; +import de.symeda.sormas.backend.common.AbstractCoreFacadeEjb; +import de.symeda.sormas.backend.infrastructure.community.CommunityFacadeEjb; +import de.symeda.sormas.backend.infrastructure.community.CommunityService; +import de.symeda.sormas.backend.infrastructure.country.CountryFacadeEjb; +import de.symeda.sormas.backend.infrastructure.country.CountryService; +import de.symeda.sormas.backend.infrastructure.district.DistrictFacadeEjb; +import de.symeda.sormas.backend.infrastructure.district.DistrictService; +import de.symeda.sormas.backend.infrastructure.facility.FacilityFacadeEjb; +import de.symeda.sormas.backend.infrastructure.facility.FacilityService; +import de.symeda.sormas.backend.infrastructure.region.RegionFacadeEjb; +import de.symeda.sormas.backend.infrastructure.region.RegionService; +import de.symeda.sormas.backend.location.LocationFacadeEjb; +import de.symeda.sormas.backend.user.User; +import de.symeda.sormas.backend.user.UserFacadeEjb; +import de.symeda.sormas.backend.util.DtoHelper; +import de.symeda.sormas.backend.util.Pseudonymizer; +import de.symeda.sormas.backend.util.RightsAllowed; +import de.symeda.sormas.backend.vaccination.Vaccination; +import de.symeda.sormas.backend.vaccination.VaccinationFacadeEjb; +import de.symeda.sormas.backend.vaccination.VaccinationService; + +@Stateless(name = "AefiInvestigationFacade") +@RightsAllowed(UserRight._ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW) +public class AefiInvestigationFacadeEjb + extends + AbstractCoreFacadeEjb + implements AefiInvestigationFacade { + + private final Logger logger = LoggerFactory.getLogger(AefiInvestigationFacadeEjb.class); + + @EJB + private AefiService aefiService; + @EJB + private LocationFacadeEjb.LocationFacadeEjbLocal locationFacade; + @EJB + private VaccinationFacadeEjb.VaccinationFacadeEjbLocal vaccinationFacade; + @EJB + private VaccinationService vaccinationService; + @EJB + private RegionService regionService; + @EJB + private DistrictService districtService; + @EJB + private CommunityService communityService; + @EJB + private FacilityService facilityService; + @EJB + private CountryService countryService; + + public AefiInvestigationFacadeEjb() { + } + + @Inject + public AefiInvestigationFacadeEjb(AefiInvestigationService service) { + super(AefiInvestigation.class, AefiInvestigationDto.class, service); + } + + @Override + @RightsAllowed({ + UserRight._ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE, + UserRight._ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT }) + public AefiInvestigationDto save(@Valid @NotNull AefiInvestigationDto dto) { + return save(dto, true, true); + } + + @RightsAllowed({ + UserRight._ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE, + UserRight._ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT }) + public AefiInvestigationDto save(@Valid @NotNull AefiInvestigationDto dto, boolean checkChangeDate, boolean internal) { + AefiInvestigation existingAefiInvestigation = service.getByUuid(dto.getUuid()); + + FacadeHelper.checkCreateAndEditRights( + existingAefiInvestigation, + userService, + UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE, + UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT); + + if (internal && existingAefiInvestigation != null && !service.isEditAllowed(existingAefiInvestigation)) { + throw new AccessDeniedException(I18nProperties.getString(Strings.errorAdverseEventInvestigationNotEditable)); + } + + AefiInvestigationDto existingDto = toDto(existingAefiInvestigation); + + Pseudonymizer pseudonymizer = createPseudonymizer(existingAefiInvestigation); + restorePseudonymizedDto(dto, existingDto, existingAefiInvestigation, pseudonymizer); + + validate(dto); + + AefiInvestigation aefiInvestigation = fillOrBuildEntity(dto, existingAefiInvestigation, checkChangeDate); + + service.ensurePersisted(aefiInvestigation); + + return toPseudonymizedDto(aefiInvestigation, pseudonymizer); + } + + @Override + public long count(AefiInvestigationCriteria criteria) { + return service.count(criteria); + } + + @Override + public List getIndexList( + AefiInvestigationCriteria criteria, + Integer first, + Integer max, + List sortProperties) { + List resultsList = service.getIndexList(criteria, first, max, sortProperties); + Pseudonymizer pseudonymizer = createGenericPlaceholderPseudonymizer(); + pseudonymizer.pseudonymizeDtoCollection(AefiInvestigationIndexDto.class, resultsList, AefiInvestigationIndexDto::isInJurisdiction, null); + return resultsList; + } + + @Override + public List getEntriesList(AefiInvestigationListCriteria criteria, Integer first, Integer max) { + Long aefiId = aefiService.getIdByUuid(criteria.getAefiReport().getUuid()); + return service.getEntriesList(aefiId, first, max); + } + + @Override + public void validate(AefiInvestigationDto aefiInvestigationDto) throws ValidationRuntimeException { + if (DateHelper.isDateAfter(aefiInvestigationDto.getInvestigationDate(), aefiInvestigationDto.getReportDate())) { + String validationError = String.format( + I18nProperties.getValidationError(Validations.afterDate), + I18nProperties.getPrefixCaption(ImmunizationDto.I18N_PREFIX, AefiInvestigationDto.INVESTIGATION_DATE), + I18nProperties.getPrefixCaption(ImmunizationDto.I18N_PREFIX, AefiInvestigationDto.REPORT_DATE)); + throw new ValidationRuntimeException(validationError); + } + + // Check whether any required field that does not have a not null constraint in the database is empty + if (aefiInvestigationDto.getAefiReport() == null) { + throw new ValidationRuntimeException(I18nProperties.getValidationError(Validations.validAefiReport)); + } + + /* + * if (aefiInvestigationDto.getPrimarySuspectVaccine() == null) { + * throw new + * ValidationRuntimeException(I18nProperties.getValidationError(Validations.aefiInvestigationWithoutPrimarySuspectVaccine)); + * } + */ + + if (aefiInvestigationDto.getReportingUser() == null && !aefiInvestigationDto.isPseudonymized()) { + throw new ValidationRuntimeException(I18nProperties.getValidationError(Validations.validReportingUser)); + } + } + + @Override + public List getArchivedUuidsSince(Date since) { + return null; + } + + @Override + public List delete(List uuids, DeletionDetails deletionDetails) { + return null; + } + + @Override + public List restore(List uuids) { + return null; + } + + @Override + protected AefiInvestigation fillOrBuildEntity(AefiInvestigationDto source, AefiInvestigation target, boolean checkChangeDate) { + return fillOrBuildEntity(source, target, checkChangeDate, false); + } + + protected AefiInvestigation fillOrBuildEntity( + @NotNull AefiInvestigationDto source, + AefiInvestigation target, + boolean checkChangeDate, + boolean includeVaccinations) { + + target = DtoHelper.fillOrBuildEntity(source, target, AefiInvestigation::build, checkChangeDate); + + target.setAefiReport(aefiService.getByReferenceDto(source.getAefiReport())); + target.setAddress(locationFacade.fillOrBuildEntity(source.getAddress(), target.getAddress(), checkChangeDate)); + + if (includeVaccinations) { + List vaccinationEntities = new ArrayList<>(); + for (VaccinationDto vaccinationDto : source.getVaccinations()) { + Vaccination vaccination = vaccinationService.getByUuid(vaccinationDto.getUuid()); + vaccination = vaccinationFacade.fillOrBuildEntity(vaccinationDto, vaccination, checkChangeDate); + vaccinationEntities.add(vaccination); + } + target.getVaccinations().clear(); + target.getVaccinations().addAll(vaccinationEntities); + } + + if (source.getPrimarySuspectVaccine() != null) { + target.setPrimarySuspectVaccine(vaccinationService.getByUuid(source.getPrimarySuspectVaccine().getUuid())); + } + + target.setReportDate(source.getReportDate()); + target.setReportingUser(userService.getByReferenceDto(source.getReportingUser())); + target.setExternalId(source.getExternalId()); + target.setResponsibleRegion(regionService.getByReferenceDto(source.getResponsibleRegion())); + target.setResponsibleDistrict(districtService.getByReferenceDto(source.getResponsibleDistrict())); + target.setResponsibleCommunity(communityService.getByReferenceDto(source.getResponsibleCommunity())); + target.setCountry(countryService.getByReferenceDto(source.getCountry())); + target.setInvestigationCaseId(source.getInvestigationCaseId()); + target.setPlaceOfVaccination(source.getPlaceOfVaccination()); + target.setPlaceOfVaccinationDetails(source.getPlaceOfVaccinationDetails()); + target.setVaccinationActivity(source.getVaccinationActivity()); + target.setVaccinationActivityDetails(source.getVaccinationActivityDetails()); + target.setVaccinationFacility(facilityService.getByReferenceDto(source.getVaccinationFacility())); + target.setVaccinationFacilityDetails(source.getVaccinationFacilityDetails()); + target.setReportingOfficerName(source.getReportingOfficerName()); + target.setReportingOfficerFacility(facilityService.getByReferenceDto(source.getReportingOfficerFacility())); + target.setReportingOfficerFacilityDetails(source.getReportingOfficerFacilityDetails()); + target.setReportingOfficerDesignation(source.getReportingOfficerDesignation()); + target.setReportingOfficerDepartment(source.getReportingOfficerDepartment()); + target.setReportingOfficerAddress( + locationFacade.fillOrBuildEntity(source.getReportingOfficerAddress(), target.getReportingOfficerAddress(), checkChangeDate)); + target.setReportingOfficerLandlinePhoneNumber(source.getReportingOfficerLandlinePhoneNumber()); + target.setReportingOfficerEmail(source.getReportingOfficerEmail()); + target.setReportingOfficerEmail(source.getReportingOfficerEmail()); + target.setInvestigationDate(source.getInvestigationDate()); + target.setFormCompletionDate(source.getFormCompletionDate()); + target.setInvestigationStage(source.getInvestigationStage()); + target.setTypeOfSite(source.getTypeOfSite()); + target.setTypeOfSiteDetails(source.getTypeOfSiteDetails()); + target.setKeySymptomDateTime(source.getKeySymptomDateTime()); + target.setHospitalizationDate(source.getHospitalizationDate()); + target.setReportedToHealthAuthorityDate(source.getReportedToHealthAuthorityDate()); + target.setStatusOnDateOfInvestigation(source.getStatusOnDateOfInvestigation()); + target.setDeathDateTime(source.getDeathDateTime()); + target.setAutopsyDone(source.getAutopsyDone()); + target.setAutopsyPlannedDateTime(source.getAutopsyPlannedDateTime()); + target.setPastHistoryOfSimilarEvent(source.getPastHistoryOfSimilarEvent()); + target.setPastHistoryOfSimilarEventDetails(source.getPastHistoryOfSimilarEventDetails()); + target.setAdverseEventAfterPreviousVaccinations(source.getAdverseEventAfterPreviousVaccinations()); + target.setAdverseEventAfterPreviousVaccinationsDetails(source.getAdverseEventAfterPreviousVaccinationsDetails()); + target.setHistoryOfAllergyToVaccineDrugOrFood(source.getHistoryOfAllergyToVaccineDrugOrFood()); + target.setHistoryOfAllergyToVaccineDrugOrFoodDetails(source.getHistoryOfAllergyToVaccineDrugOrFoodDetails()); + target.setPreExistingIllnessThirtyDaysOrCongenitalDisorder(source.getPreExistingIllnessThirtyDaysOrCongenitalDisorder()); + target.setPreExistingIllnessThirtyDaysOrCongenitalDisorderDetails(source.getPreExistingIllnessThirtyDaysOrCongenitalDisorderDetails()); + target.setHistoryOfHospitalizationInLastThirtyDaysWithCause(source.getHistoryOfHospitalizationInLastThirtyDaysWithCause()); + target.setHistoryOfHospitalizationInLastThirtyDaysWithCauseDetails(source.getHistoryOfHospitalizationInLastThirtyDaysWithCauseDetails()); + target.setCurrentlyOnConcomitantMedication(source.getCurrentlyOnConcomitantMedication()); + target.setCurrentlyOnConcomitantMedicationDetails(source.getCurrentlyOnConcomitantMedicationDetails()); + target.setFamilyHistoryOfDiseaseOrAllergy(source.getFamilyHistoryOfDiseaseOrAllergy()); + target.setFamilyHistoryOfDiseaseOrAllergyDetails(source.getFamilyHistoryOfDiseaseOrAllergyDetails()); + target.setBirthTerm(source.getBirthTerm()); + target.setBirthWeight(source.getBirthWeight()); + target.setDeliveryProcedure(source.getDeliveryProcedure()); + target.setDeliveryProcedureDetails(source.getDeliveryProcedureDetails()); + target.setSeriousAefiInfoSource(source.getSeriousAefiInfoSource()); + target.setSeriousAefiInfoSourceDetails(source.getSeriousAefiInfoSourceDetails()); + target.setSeriousAefiVerbalAutopsyInfoSourceDetails(source.getSeriousAefiVerbalAutopsyInfoSourceDetails()); + target.setFirstCaregiversName(source.getFirstCaregiversName()); + target.setOtherCaregiversNames(source.getOtherCaregiversNames()); + target.setOtherSourcesWhoProvidedInfo(source.getOtherSourcesWhoProvidedInfo()); + target.setSignsAndSymptomsFromTimeOfVaccination(source.getSignsAndSymptomsFromTimeOfVaccination()); + target.setClinicalDetailsOfficerName(source.getClinicalDetailsOfficerName()); + target.setClinicalDetailsOfficerPhoneNumber(source.getClinicalDetailsOfficerPhoneNumber()); + target.setClinicalDetailsOfficerEmail(source.getClinicalDetailsOfficerEmail()); + target.setClinicalDetailsOfficerDesignation(source.getClinicalDetailsOfficerDesignation()); + target.setClinicalDetailsDateTime(source.getClinicalDetailsDateTime()); + target.setPatientReceivedMedicalCare(source.getPatientReceivedMedicalCare()); + target.setPatientReceivedMedicalCareDetails(source.getPatientReceivedMedicalCareDetails()); + target.setProvisionalOrFinalDiagnosis(source.getProvisionalOrFinalDiagnosis()); + target.setPatientImmunizedPeriod(source.getPatientImmunizedPeriod()); + target.setPatientImmunizedPeriodDetails(source.getPatientImmunizedPeriodDetails()); + target.setVaccineGivenPeriod(source.getVaccineGivenPeriod()); + target.setVaccineGivenPeriodDetails(source.getVaccineGivenPeriodDetails()); + target.setErrorPrescribingVaccine(source.getErrorPrescribingVaccine()); + target.setErrorPrescribingVaccineDetails(source.getErrorPrescribingVaccineDetails()); + target.setVaccineCouldHaveBeenUnSterile(source.getVaccineCouldHaveBeenUnSterile()); + target.setVaccineCouldHaveBeenUnSterileDetails(source.getVaccineCouldHaveBeenUnSterileDetails()); + target.setVaccinePhysicalConditionAbnormal(source.getVaccinePhysicalConditionAbnormal()); + target.setVaccinePhysicalConditionAbnormalDetails(source.getVaccinePhysicalConditionAbnormalDetails()); + target.setErrorInVaccineReconstitution(source.getErrorInVaccineReconstitution()); + target.setErrorInVaccineReconstitutionDetails(source.getErrorInVaccineReconstitutionDetails()); + target.setErrorInVaccineHandling(source.getErrorInVaccineHandling()); + target.setErrorInVaccineHandlingDetails(source.getErrorInVaccineHandlingDetails()); + target.setVaccineAdministeredIncorrectly(source.getVaccineAdministeredIncorrectly()); + target.setVaccineAdministeredIncorrectlyDetails(source.getVaccineAdministeredIncorrectlyDetails()); + target.setNumberImmunizedFromConcernedVaccineVial(source.getNumberImmunizedFromConcernedVaccineVial()); + target.setNumberImmunizedWithConcernedVaccineInSameSession(source.getNumberImmunizedWithConcernedVaccineInSameSession()); + target.setNumberImmunizedConcernedVaccineSameBatchNumberOtherLocations( + source.getNumberImmunizedConcernedVaccineSameBatchNumberOtherLocations()); + target.setNumberImmunizedConcernedVaccineSameBatchNumberLocationDetails( + source.getNumberImmunizedConcernedVaccineSameBatchNumberLocationDetails()); + target.setVaccineHasQualityDefect(source.getVaccineHasQualityDefect()); + target.setVaccineHasQualityDefectDetails(source.getVaccineHasQualityDefectDetails()); + target.setEventIsAStressResponseRelatedToImmunization(source.getEventIsAStressResponseRelatedToImmunization()); + target.setEventIsAStressResponseRelatedToImmunizationDetails(source.getEventIsAStressResponseRelatedToImmunizationDetails()); + target.setCaseIsPartOfACluster(source.getCaseIsPartOfACluster()); + target.setCaseIsPartOfAClusterDetails(source.getCaseIsPartOfAClusterDetails()); + target.setNumberOfCasesDetectedInCluster(source.getNumberOfCasesDetectedInCluster()); + target.setAllCasesInClusterReceivedVaccineFromSameVial(source.getAllCasesInClusterReceivedVaccineFromSameVial()); + target.setAllCasesInClusterReceivedVaccineFromSameVialDetails(source.getAllCasesInClusterReceivedVaccineFromSameVialDetails()); + target.setNumberOfVialsUsedInCluster(source.getNumberOfVialsUsedInCluster()); + target.setNumberOfVialsUsedInClusterDetails(source.getNumberOfVialsUsedInClusterDetails()); + target.setAdSyringesUsedForImmunization(source.getAdSyringesUsedForImmunization()); + target.setTypeOfSyringesUsed(source.getTypeOfSyringesUsed()); + target.setTypeOfSyringesUsedDetails(source.getTypeOfSyringesUsedDetails()); + target.setSyringesUsedAdditionalDetails(source.getSyringesUsedAdditionalDetails()); + target.setSameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine(source.getSameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine()); + target.setSameReconstitutionSyringeUsedForReconstitutingDifferentVaccines( + source.getSameReconstitutionSyringeUsedForReconstitutingDifferentVaccines()); + target.setSameReconstitutionSyringeForEachVaccineVial(source.getSameReconstitutionSyringeForEachVaccineVial()); + target.setSameReconstitutionSyringeForEachVaccination(source.getSameReconstitutionSyringeForEachVaccination()); + target.setVaccinesAndDiluentsUsedRecommendedByManufacturer(source.getVaccinesAndDiluentsUsedRecommendedByManufacturer()); + target.setReconstitutionAdditionalDetails(source.getReconstitutionAdditionalDetails()); + target.setCorrectDoseOrRoute(source.getCorrectDoseOrRoute()); + target.setTimeOfReconstitutionMentionedOnTheVial(source.getTimeOfReconstitutionMentionedOnTheVial()); + target.setNonTouchTechniqueFollowed(source.getNonTouchTechniqueFollowed()); + target.setContraIndicationScreenedPriorToVaccination(source.getContraIndicationScreenedPriorToVaccination()); + target.setNumberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays( + source.getNumberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays()); + target.setTrainingReceivedByVaccinator(source.getTrainingReceivedByVaccinator()); + target.setLastTrainingReceivedByVaccinatorDate(source.getLastTrainingReceivedByVaccinatorDate()); + target.setInjectionTechniqueAdditionalDetails(source.getInjectionTechniqueAdditionalDetails()); + target.setVaccineStorageRefrigeratorTemperatureMonitored(source.getVaccineStorageRefrigeratorTemperatureMonitored()); + target.setAnyStorageTemperatureDeviationOutsideTwoToEightDegrees(source.getAnyStorageTemperatureDeviationOutsideTwoToEightDegrees()); + target.setStorageTemperatureMonitoringAdditionalDetails(source.getStorageTemperatureMonitoringAdditionalDetails()); + target.setCorrectProcedureForStorageFollowed(source.getCorrectProcedureForStorageFollowed()); + target.setAnyOtherItemInRefrigerator(source.getAnyOtherItemInRefrigerator()); + target.setPartiallyUsedReconstitutedVaccinesInRefrigerator(source.getPartiallyUsedReconstitutedVaccinesInRefrigerator()); + target.setUnusableVaccinesInRefrigerator(source.getUnusableVaccinesInRefrigerator()); + target.setUnusableDiluentsInStore(source.getUnusableDiluentsInStore()); + target.setVaccineStoragePointAdditionalDetails(source.getVaccineStoragePointAdditionalDetails()); + target.setVaccineCarrierType(source.getVaccineCarrierType()); + target.setVaccineCarrierTypeDetails(source.getVaccineCarrierTypeDetails()); + target.setVaccineCarrierSentToSiteOnSameDateAsVaccination(source.getVaccineCarrierSentToSiteOnSameDateAsVaccination()); + target.setVaccineCarrierReturnedFromSiteOnSameDateAsVaccination(source.getVaccineCarrierReturnedFromSiteOnSameDateAsVaccination()); + target.setConditionedIcepackUsed(source.getConditionedIcepackUsed()); + target.setVaccineTransportationAdditionalDetails(source.getVaccineTransportationAdditionalDetails()); + target.setSimilarEventsReportedSamePeriodAndLocality(source.getSimilarEventsReportedSamePeriodAndLocality()); + target.setSimilarEventsReportedSamePeriodAndLocalityDetails(source.getSimilarEventsReportedSamePeriodAndLocalityDetails()); + target.setNumberOfSimilarEventsReportedSamePeriodAndLocality(source.getNumberOfSimilarEventsReportedSamePeriodAndLocality()); + target.setNumberOfThoseAffectedVaccinated(source.getNumberOfThoseAffectedVaccinated()); + target.setNumberOfThoseAffectedNotVaccinated(source.getNumberOfThoseAffectedNotVaccinated()); + target.setNumberOfThoseAffectedVaccinatedUnknown(source.getNumberOfThoseAffectedVaccinatedUnknown()); + target.setCommunityInvestigationAdditionalDetails(source.getCommunityInvestigationAdditionalDetails()); + target.setOtherInvestigationFindings(source.getOtherInvestigationFindings()); + target.setInvestigationStatus(source.getInvestigationStatus()); + target.setAefiClassification(source.getAefiClassification()); + target.setArchived(source.isArchived()); + target.setDeleted(source.isDeleted()); + target.setDeletionReason(source.getDeletionReason()); + target.setOtherDeletionReason(source.getOtherDeletionReason()); + + return target; + } + + @Override + protected AefiInvestigationDto toDto(AefiInvestigation entity) { + return toAefiInvestigationDto(entity); + } + + public static AefiInvestigationDto toAefiInvestigationDto(AefiInvestigation entity) { + + if (entity == null) { + return null; + } + AefiInvestigationDto dto = new AefiInvestigationDto(); + DtoHelper.fillDto(dto, entity); + + dto.setAefiReport(AefiFacadeEjb.toReferenceDto(entity.getAefiReport())); + dto.setAddress(LocationFacadeEjb.toDto(entity.getAddress())); + + List vaccinationDtos = new ArrayList<>(); + for (Vaccination vaccination : entity.getAefiReport().getImmunization().getVaccinations()) { + VaccinationDto vaccinationDto = VaccinationFacadeEjb.toVaccinationDto(vaccination); + vaccinationDtos.add(vaccinationDto); + } + dto.setVaccinations(vaccinationDtos); + + if (entity.getPrimarySuspectVaccine() != null) { + dto.setPrimarySuspectVaccine(VaccinationFacadeEjb.toVaccinationDto(entity.getPrimarySuspectVaccine())); + } + + dto.setReportDate(entity.getReportDate()); + dto.setReportingUser(UserFacadeEjb.toReferenceDto(entity.getReportingUser())); + dto.setExternalId(entity.getExternalId()); + dto.setResponsibleRegion(RegionFacadeEjb.toReferenceDto(entity.getResponsibleRegion())); + dto.setResponsibleDistrict(DistrictFacadeEjb.toReferenceDto(entity.getResponsibleDistrict())); + dto.setResponsibleCommunity(CommunityFacadeEjb.toReferenceDto(entity.getResponsibleCommunity())); + dto.setCountry(CountryFacadeEjb.toReferenceDto(entity.getCountry())); + dto.setInvestigationCaseId(entity.getInvestigationCaseId()); + dto.setPlaceOfVaccination(entity.getPlaceOfVaccination()); + dto.setPlaceOfVaccinationDetails(entity.getPlaceOfVaccinationDetails()); + dto.setVaccinationActivity(entity.getVaccinationActivity()); + dto.setVaccinationActivityDetails(entity.getVaccinationActivityDetails()); + dto.setVaccinationFacility(FacilityFacadeEjb.toReferenceDto(entity.getVaccinationFacility())); + dto.setVaccinationFacilityDetails(entity.getVaccinationFacilityDetails()); + dto.setReportingOfficerName(entity.getReportingOfficerName()); + dto.setReportingOfficerFacility(FacilityFacadeEjb.toReferenceDto(entity.getReportingOfficerFacility())); + dto.setReportingOfficerFacilityDetails(entity.getReportingOfficerFacilityDetails()); + dto.setReportingOfficerDesignation(entity.getReportingOfficerDesignation()); + dto.setReportingOfficerDepartment(entity.getReportingOfficerDepartment()); + dto.setReportingOfficerAddress(LocationFacadeEjb.toDto(entity.getReportingOfficerAddress())); + dto.setReportingOfficerLandlinePhoneNumber(entity.getReportingOfficerLandlinePhoneNumber()); + dto.setReportingOfficerEmail(entity.getReportingOfficerEmail()); + dto.setReportingOfficerEmail(entity.getReportingOfficerEmail()); + dto.setInvestigationDate(entity.getInvestigationDate()); + dto.setFormCompletionDate(entity.getFormCompletionDate()); + dto.setInvestigationStage(entity.getInvestigationStage()); + dto.setTypeOfSite(entity.getTypeOfSite()); + dto.setTypeOfSiteDetails(entity.getTypeOfSiteDetails()); + dto.setKeySymptomDateTime(entity.getKeySymptomDateTime()); + dto.setHospitalizationDate(entity.getHospitalizationDate()); + dto.setReportedToHealthAuthorityDate(entity.getReportedToHealthAuthorityDate()); + dto.setStatusOnDateOfInvestigation(entity.getStatusOnDateOfInvestigation()); + dto.setDeathDateTime(entity.getDeathDateTime()); + dto.setAutopsyDone(entity.getAutopsyDone()); + dto.setAutopsyPlannedDateTime(entity.getAutopsyPlannedDateTime()); + dto.setPastHistoryOfSimilarEvent(entity.getPastHistoryOfSimilarEvent()); + dto.setPastHistoryOfSimilarEventDetails(entity.getPastHistoryOfSimilarEventDetails()); + dto.setAdverseEventAfterPreviousVaccinations(entity.getAdverseEventAfterPreviousVaccinations()); + dto.setAdverseEventAfterPreviousVaccinationsDetails(entity.getAdverseEventAfterPreviousVaccinationsDetails()); + dto.setHistoryOfAllergyToVaccineDrugOrFood(entity.getHistoryOfAllergyToVaccineDrugOrFood()); + dto.setHistoryOfAllergyToVaccineDrugOrFoodDetails(entity.getHistoryOfAllergyToVaccineDrugOrFoodDetails()); + dto.setPreExistingIllnessThirtyDaysOrCongenitalDisorder(entity.getPreExistingIllnessThirtyDaysOrCongenitalDisorder()); + dto.setPreExistingIllnessThirtyDaysOrCongenitalDisorderDetails(entity.getPreExistingIllnessThirtyDaysOrCongenitalDisorderDetails()); + dto.setHistoryOfHospitalizationInLastThirtyDaysWithCause(entity.getHistoryOfHospitalizationInLastThirtyDaysWithCause()); + dto.setHistoryOfHospitalizationInLastThirtyDaysWithCauseDetails(entity.getHistoryOfHospitalizationInLastThirtyDaysWithCauseDetails()); + dto.setCurrentlyOnConcomitantMedication(entity.getCurrentlyOnConcomitantMedication()); + dto.setCurrentlyOnConcomitantMedicationDetails(entity.getCurrentlyOnConcomitantMedicationDetails()); + dto.setFamilyHistoryOfDiseaseOrAllergy(entity.getFamilyHistoryOfDiseaseOrAllergy()); + dto.setFamilyHistoryOfDiseaseOrAllergyDetails(entity.getFamilyHistoryOfDiseaseOrAllergyDetails()); + dto.setBirthTerm(entity.getBirthTerm()); + dto.setBirthWeight(entity.getBirthWeight()); + dto.setDeliveryProcedure(entity.getDeliveryProcedure()); + dto.setDeliveryProcedureDetails(entity.getDeliveryProcedureDetails()); + dto.setSeriousAefiInfoSource(entity.getSeriousAefiInfoSource()); + dto.setSeriousAefiInfoSourceDetails(entity.getSeriousAefiInfoSourceDetails()); + dto.setSeriousAefiVerbalAutopsyInfoSourceDetails(entity.getSeriousAefiVerbalAutopsyInfoSourceDetails()); + dto.setFirstCaregiversName(entity.getFirstCaregiversName()); + dto.setOtherCaregiversNames(entity.getOtherCaregiversNames()); + dto.setOtherSourcesWhoProvidedInfo(entity.getOtherSourcesWhoProvidedInfo()); + dto.setSignsAndSymptomsFromTimeOfVaccination(entity.getSignsAndSymptomsFromTimeOfVaccination()); + dto.setClinicalDetailsOfficerName(entity.getClinicalDetailsOfficerName()); + dto.setClinicalDetailsOfficerPhoneNumber(entity.getClinicalDetailsOfficerPhoneNumber()); + dto.setClinicalDetailsOfficerEmail(entity.getClinicalDetailsOfficerEmail()); + dto.setClinicalDetailsOfficerDesignation(entity.getClinicalDetailsOfficerDesignation()); + dto.setClinicalDetailsDateTime(entity.getClinicalDetailsDateTime()); + dto.setPatientReceivedMedicalCare(entity.getPatientReceivedMedicalCare()); + dto.setPatientReceivedMedicalCareDetails(entity.getPatientReceivedMedicalCareDetails()); + dto.setProvisionalOrFinalDiagnosis(entity.getProvisionalOrFinalDiagnosis()); + dto.setPatientImmunizedPeriod(entity.getPatientImmunizedPeriod()); + dto.setPatientImmunizedPeriodDetails(entity.getPatientImmunizedPeriodDetails()); + dto.setVaccineGivenPeriod(entity.getVaccineGivenPeriod()); + dto.setVaccineGivenPeriodDetails(entity.getVaccineGivenPeriodDetails()); + dto.setErrorPrescribingVaccine(entity.getErrorPrescribingVaccine()); + dto.setErrorPrescribingVaccineDetails(entity.getErrorPrescribingVaccineDetails()); + dto.setVaccineCouldHaveBeenUnSterile(entity.getVaccineCouldHaveBeenUnSterile()); + dto.setVaccineCouldHaveBeenUnSterileDetails(entity.getVaccineCouldHaveBeenUnSterileDetails()); + dto.setVaccinePhysicalConditionAbnormal(entity.getVaccinePhysicalConditionAbnormal()); + dto.setVaccinePhysicalConditionAbnormalDetails(entity.getVaccinePhysicalConditionAbnormalDetails()); + dto.setErrorInVaccineReconstitution(entity.getErrorInVaccineReconstitution()); + dto.setErrorInVaccineReconstitutionDetails(entity.getErrorInVaccineReconstitutionDetails()); + dto.setErrorInVaccineHandling(entity.getErrorInVaccineHandling()); + dto.setErrorInVaccineHandlingDetails(entity.getErrorInVaccineHandlingDetails()); + dto.setVaccineAdministeredIncorrectly(entity.getVaccineAdministeredIncorrectly()); + dto.setVaccineAdministeredIncorrectlyDetails(entity.getVaccineAdministeredIncorrectlyDetails()); + dto.setNumberImmunizedFromConcernedVaccineVial(entity.getNumberImmunizedFromConcernedVaccineVial()); + dto.setNumberImmunizedWithConcernedVaccineInSameSession(entity.getNumberImmunizedWithConcernedVaccineInSameSession()); + dto.setNumberImmunizedConcernedVaccineSameBatchNumberOtherLocations(entity.getNumberImmunizedConcernedVaccineSameBatchNumberOtherLocations()); + dto.setNumberImmunizedConcernedVaccineSameBatchNumberLocationDetails( + entity.getNumberImmunizedConcernedVaccineSameBatchNumberLocationDetails()); + dto.setVaccineHasQualityDefect(entity.getVaccineHasQualityDefect()); + dto.setVaccineHasQualityDefectDetails(entity.getVaccineHasQualityDefectDetails()); + dto.setEventIsAStressResponseRelatedToImmunization(entity.getEventIsAStressResponseRelatedToImmunization()); + dto.setEventIsAStressResponseRelatedToImmunizationDetails(entity.getEventIsAStressResponseRelatedToImmunizationDetails()); + dto.setCaseIsPartOfACluster(entity.getCaseIsPartOfACluster()); + dto.setCaseIsPartOfAClusterDetails(entity.getCaseIsPartOfAClusterDetails()); + dto.setNumberOfCasesDetectedInCluster(entity.getNumberOfCasesDetectedInCluster()); + dto.setAllCasesInClusterReceivedVaccineFromSameVial(entity.getAllCasesInClusterReceivedVaccineFromSameVial()); + dto.setAllCasesInClusterReceivedVaccineFromSameVialDetails(entity.getAllCasesInClusterReceivedVaccineFromSameVialDetails()); + dto.setNumberOfVialsUsedInCluster(entity.getNumberOfVialsUsedInCluster()); + dto.setNumberOfVialsUsedInClusterDetails(entity.getNumberOfVialsUsedInClusterDetails()); + dto.setAdSyringesUsedForImmunization(entity.getAdSyringesUsedForImmunization()); + dto.setTypeOfSyringesUsed(entity.getTypeOfSyringesUsed()); + dto.setTypeOfSyringesUsedDetails(entity.getTypeOfSyringesUsedDetails()); + dto.setSyringesUsedAdditionalDetails(entity.getSyringesUsedAdditionalDetails()); + dto.setSameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine(entity.getSameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine()); + dto.setSameReconstitutionSyringeUsedForReconstitutingDifferentVaccines( + entity.getSameReconstitutionSyringeUsedForReconstitutingDifferentVaccines()); + dto.setSameReconstitutionSyringeForEachVaccineVial(entity.getSameReconstitutionSyringeForEachVaccineVial()); + dto.setSameReconstitutionSyringeForEachVaccination(entity.getSameReconstitutionSyringeForEachVaccination()); + dto.setVaccinesAndDiluentsUsedRecommendedByManufacturer(entity.getVaccinesAndDiluentsUsedRecommendedByManufacturer()); + dto.setReconstitutionAdditionalDetails(entity.getReconstitutionAdditionalDetails()); + dto.setCorrectDoseOrRoute(entity.getCorrectDoseOrRoute()); + dto.setTimeOfReconstitutionMentionedOnTheVial(entity.getTimeOfReconstitutionMentionedOnTheVial()); + dto.setNonTouchTechniqueFollowed(entity.getNonTouchTechniqueFollowed()); + dto.setContraIndicationScreenedPriorToVaccination(entity.getContraIndicationScreenedPriorToVaccination()); + dto.setNumberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays( + entity.getNumberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays()); + dto.setTrainingReceivedByVaccinator(entity.getTrainingReceivedByVaccinator()); + dto.setLastTrainingReceivedByVaccinatorDate(entity.getLastTrainingReceivedByVaccinatorDate()); + dto.setInjectionTechniqueAdditionalDetails(entity.getInjectionTechniqueAdditionalDetails()); + dto.setVaccineStorageRefrigeratorTemperatureMonitored(entity.getVaccineStorageRefrigeratorTemperatureMonitored()); + dto.setAnyStorageTemperatureDeviationOutsideTwoToEightDegrees(entity.getAnyStorageTemperatureDeviationOutsideTwoToEightDegrees()); + dto.setStorageTemperatureMonitoringAdditionalDetails(entity.getStorageTemperatureMonitoringAdditionalDetails()); + dto.setCorrectProcedureForStorageFollowed(entity.getCorrectProcedureForStorageFollowed()); + dto.setAnyOtherItemInRefrigerator(entity.getAnyOtherItemInRefrigerator()); + dto.setPartiallyUsedReconstitutedVaccinesInRefrigerator(entity.getPartiallyUsedReconstitutedVaccinesInRefrigerator()); + dto.setUnusableVaccinesInRefrigerator(entity.getUnusableVaccinesInRefrigerator()); + dto.setUnusableDiluentsInStore(entity.getUnusableDiluentsInStore()); + dto.setVaccineStoragePointAdditionalDetails(entity.getVaccineStoragePointAdditionalDetails()); + dto.setVaccineCarrierType(entity.getVaccineCarrierType()); + dto.setVaccineCarrierTypeDetails(entity.getVaccineCarrierTypeDetails()); + dto.setVaccineCarrierSentToSiteOnSameDateAsVaccination(entity.getVaccineCarrierSentToSiteOnSameDateAsVaccination()); + dto.setVaccineCarrierReturnedFromSiteOnSameDateAsVaccination(entity.getVaccineCarrierReturnedFromSiteOnSameDateAsVaccination()); + dto.setConditionedIcepackUsed(entity.getConditionedIcepackUsed()); + dto.setVaccineTransportationAdditionalDetails(entity.getVaccineTransportationAdditionalDetails()); + dto.setSimilarEventsReportedSamePeriodAndLocality(entity.getSimilarEventsReportedSamePeriodAndLocality()); + dto.setSimilarEventsReportedSamePeriodAndLocalityDetails(entity.getSimilarEventsReportedSamePeriodAndLocalityDetails()); + dto.setNumberOfSimilarEventsReportedSamePeriodAndLocality(entity.getNumberOfSimilarEventsReportedSamePeriodAndLocality()); + dto.setNumberOfThoseAffectedVaccinated(entity.getNumberOfThoseAffectedVaccinated()); + dto.setNumberOfThoseAffectedNotVaccinated(entity.getNumberOfThoseAffectedNotVaccinated()); + dto.setNumberOfThoseAffectedVaccinatedUnknown(entity.getNumberOfThoseAffectedVaccinatedUnknown()); + dto.setCommunityInvestigationAdditionalDetails(entity.getCommunityInvestigationAdditionalDetails()); + dto.setOtherInvestigationFindings(entity.getOtherInvestigationFindings()); + dto.setInvestigationStatus(entity.getInvestigationStatus()); + dto.setAefiClassification(entity.getAefiClassification()); + dto.setArchived(entity.isArchived()); + dto.setDeleted(entity.isDeleted()); + dto.setDeletionReason(entity.getDeletionReason()); + dto.setOtherDeletionReason(entity.getOtherDeletionReason()); + + return dto; + } + + @Override + protected AefiInvestigationReferenceDto toRefDto(AefiInvestigation aefiInvestigation) { + return toReferenceDto(aefiInvestigation); + } + + public static AefiInvestigationReferenceDto toReferenceDto(AefiInvestigation entity) { + + if (entity == null) { + return null; + } + + return new AefiInvestigationReferenceDto(entity.getUuid(), ""); + } + + @Override + protected void pseudonymizeDto( + AefiInvestigation source, + AefiInvestigationDto dto, + Pseudonymizer pseudonymizer, + boolean inJurisdiction) { + + if (dto != null) { + pseudonymizer.pseudonymizeDto(AefiInvestigationDto.class, dto, inJurisdiction, c -> { + pseudonymizer.pseudonymizeUser(source.getReportingUser(), userService.getCurrentUser(), dto::setReportingUser, dto); + }); + } + } + + @Override + protected void restorePseudonymizedDto( + AefiInvestigationDto dto, + AefiInvestigationDto existingDto, + AefiInvestigation entity, + Pseudonymizer pseudonymizer) { + + if (existingDto != null) { + final boolean inJurisdiction = service.inJurisdictionOrOwned(entity); + final User currentUser = userService.getCurrentUser(); + pseudonymizer.restoreUser(entity.getReportingUser(), currentUser, dto, dto::setReportingUser); + pseudonymizer.restorePseudonymizedValues(AefiInvestigationDto.class, dto, existingDto, inJurisdiction); + } + } + + @Override + protected DeletableEntityType getDeletableEntityType() { + return null; + } + + @LocalBean + @Stateless + public static class AefiInvestigationFacadeEjbLocal extends AefiInvestigationFacadeEjb { + + public AefiInvestigationFacadeEjbLocal() { + super(); + } + + @Inject + public AefiInvestigationFacadeEjbLocal(AefiInvestigationService service) { + super(service); + } + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiInvestigationJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiInvestigationJurisdictionPredicateValidator.java new file mode 100644 index 00000000000..bf377ed8fb7 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiInvestigationJurisdictionPredicateValidator.java @@ -0,0 +1,116 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import java.util.List; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.Path; +import javax.persistence.criteria.Predicate; + +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.Aefi; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AefiInvestigation; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AefiInvestigationJoins; +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.user.User; +import de.symeda.sormas.backend.util.PredicateJurisdictionValidator; + +public class AefiInvestigationJurisdictionPredicateValidator extends PredicateJurisdictionValidator { + + private final AefiInvestigationJoins joins; + + public AefiInvestigationJurisdictionPredicateValidator( + CriteriaBuilder cb, + AefiInvestigationJoins joins, + User user, + List jurisdictionValidators) { + super(cb, user, null, jurisdictionValidators); + this.joins = joins; + } + + public static AefiInvestigationJurisdictionPredicateValidator of(AefiInvestigationQueryContext qc, User user) { + return new AefiInvestigationJurisdictionPredicateValidator(qc.getCriteriaBuilder(), qc.getJoins(), user, null); + } + + @Override + public Predicate isRootInJurisdiction() { + return isInJurisdictionByJurisdictionLevel(user.getJurisdictionLevel()); + } + + @Override + public Predicate isRootInJurisdictionOrOwned() { + final Path reportingUserPath = joins.getRoot().get(AefiInvestigation.REPORTING_USER); + final Predicate reportedByCurrentUser = cb.and(cb.isNotNull(reportingUserPath), cb.equal(reportingUserPath.get(User.ID), user.getId())); + return cb.or(reportedByCurrentUser, this.isRootInJurisdiction()); + } + + @Override + public Predicate isRootInJurisdictionForRestrictedAccess() { + return null; + } + + @Override + protected Predicate whenNotAllowed() { + return cb.disjunction(); + } + + @Override + protected Predicate whenNationalLevel() { + return cb.conjunction(); + } + + @Override + protected Predicate whenRegionalLevel() { + return cb.equal( + joins.getRoot().get(AefiInvestigation.AEFI_REPORT).get(Aefi.IMMUNIZATION).get(Immunization.RESPONSIBLE_REGION).get(Region.ID), + user.getRegion().getId()); + } + + @Override + protected Predicate whenDistrictLevel() { + return cb.equal( + joins.getRoot().get(AefiInvestigation.AEFI_REPORT).get(Aefi.IMMUNIZATION).get(Immunization.RESPONSIBLE_DISTRICT).get(District.ID), + user.getDistrict().getId()); + } + + @Override + protected Predicate whenCommunityLevel() { + return cb.equal( + joins.getRoot().get(AefiInvestigation.AEFI_REPORT).get(Aefi.IMMUNIZATION).get(Immunization.RESPONSIBLE_COMMUNITY).get(Community.ID), + user.getCommunity().getId()); + } + + @Override + protected Predicate whenFacilityLevel() { + return cb.equal( + joins.getRoot().get(AefiInvestigation.AEFI_REPORT).get(Aefi.IMMUNIZATION).get(Immunization.HEALTH_FACILITY).get(Facility.ID), + user.getHealthFacility().getId()); + } + + @Override + protected Predicate whenPointOfEntryLevel() { + return cb.disjunction(); + } + + @Override + protected Predicate whenLaboratoryLevel() { + return cb.disjunction(); + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiInvestigationQueryContext.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiInvestigationQueryContext.java new file mode 100644 index 00000000000..81defa6406f --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiInvestigationQueryContext.java @@ -0,0 +1,45 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Expression; +import javax.persistence.criteria.From; + +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AefiInvestigation; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AefiInvestigationJoins; +import de.symeda.sormas.backend.common.QueryContext; + +public class AefiInvestigationQueryContext extends QueryContext { + + public AefiInvestigationQueryContext(CriteriaBuilder cb, CriteriaQuery query, From root) { + super(cb, query, root, new AefiInvestigationJoins(root)); + } + + public AefiInvestigationQueryContext(CriteriaBuilder cb, CriteriaQuery query, AefiInvestigationJoins joins) { + super(cb, query, joins.getRoot(), joins); + } + + public AefiInvestigationQueryContext(CriteriaBuilder cb, CriteriaQuery query, From root, AefiInvestigationJoins joins) { + super(cb, query, root, joins); + } + + @Override + protected Expression createExpression(String name) { + return null; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiInvestigationService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiInvestigationService.java new file mode 100644 index 00000000000..dfa5f010a5f --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiInvestigationService.java @@ -0,0 +1,548 @@ +/* + * 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.adverseeventsfollowingimmunization; + +import static de.symeda.sormas.backend.common.CriteriaBuilderHelper.andEquals; + +import java.util.ArrayList; +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.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; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import javax.persistence.criteria.Selection; + +import org.apache.commons.collections4.CollectionUtils; + +import de.symeda.sormas.api.EntityRelevanceStatus; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationCriteria; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationDateType; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationIndexDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationListEntryDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; +import de.symeda.sormas.api.common.DeletableEntityType; +import de.symeda.sormas.api.feature.FeatureType; +import de.symeda.sormas.api.feature.FeatureTypeProperty; +import de.symeda.sormas.api.person.PersonIndexDto; +import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.api.utils.SortProperty; +import de.symeda.sormas.api.utils.YesNoUnknown; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.Aefi; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AefiInvestigation; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AefiInvestigationJoins; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.transformers.AefiInvestigationIndexDtoResultTransformer; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.transformers.AefiInvestigationListEntryDtoResultTransformer; +import de.symeda.sormas.backend.common.AbstractCoreAdoService; +import de.symeda.sormas.backend.common.CriteriaBuilderHelper; +import de.symeda.sormas.backend.feature.FeatureConfigurationFacadeEjb; +import de.symeda.sormas.backend.immunization.entity.Immunization; +import de.symeda.sormas.backend.infrastructure.district.District; +import de.symeda.sormas.backend.infrastructure.region.Region; +import de.symeda.sormas.backend.location.Location; +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.user.User; +import de.symeda.sormas.backend.user.UserService; +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.vaccination.Vaccination; + +@Stateless +@LocalBean +public class AefiInvestigationService extends AbstractCoreAdoService { + + @EJB + private PersonService personService; + @EJB + private UserService userService; + @EJB + private FeatureConfigurationFacadeEjb.FeatureConfigurationFacadeEjbLocal featureConfigurationFacade; + + public AefiInvestigationService() { + super(AefiInvestigation.class, DeletableEntityType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION); + } + + public List getEntriesList(Long aefiReportId, Integer first, Integer max) { + final CriteriaBuilder cb = em.getCriteriaBuilder(); + final CriteriaQuery cq = cb.createQuery(Tuple.class); + final Root aefiInvestigation = cq.from(AefiInvestigation.class); + + AefiInvestigationQueryContext queryContext = new AefiInvestigationQueryContext(cb, cq, aefiInvestigation); + AefiInvestigationJoins joins = queryContext.getJoins(); + + Join primarySuspectVaccine = joins.getPrimarySuspectVaccination(); + + cq.multiselect( + aefiInvestigation.get(AefiInvestigation.UUID), + aefiInvestigation.get(AefiInvestigation.INVESTIGATION_CASE_ID), + aefiInvestigation.get(AefiInvestigation.INVESTIGATION_DATE), + aefiInvestigation.get(AefiInvestigation.INVESTIGATION_STAGE), + aefiInvestigation.get(AefiInvestigation.STATUS_ON_DATE_OF_INVESTIGATION), + primarySuspectVaccine.get(Vaccination.VACCINE_NAME), + primarySuspectVaccine.get(Vaccination.OTHER_VACCINE_NAME), + primarySuspectVaccine.get(Vaccination.VACCINE_DOSE), + primarySuspectVaccine.get(Vaccination.VACCINATION_DATE), + aefiInvestigation.get(AefiInvestigation.INVESTIGATION_STATUS), + aefiInvestigation.get(AefiInvestigation.AEFI_CLASSIFICATION), + aefiInvestigation.get(Aefi.CHANGE_DATE), + JurisdictionHelper.booleanSelector(cb, isInJurisdictionOrOwned(queryContext))); + + final Predicate criteriaFilter = buildCriteriaFilter(aefiReportId, queryContext); + if (criteriaFilter != null) { + cq.where(criteriaFilter); + } + + cq.orderBy(cb.desc(aefiInvestigation.get(AefiInvestigation.CHANGE_DATE))); + + cq.distinct(true); + + return QueryHelper.getResultList(em, cq, new AefiInvestigationListEntryDtoResultTransformer(), first, max); + } + + private Predicate buildCriteriaFilter(Long aefiReportId, AefiInvestigationQueryContext queryContext) { + + final CriteriaBuilder cb = queryContext.getCriteriaBuilder(); + final From from = queryContext.getRoot(); + + Predicate filter = cb.equal(from.get(AefiInvestigation.AEFI_REPORT_ID), aefiReportId); + + filter = CriteriaBuilderHelper.and(cb, filter, cb.isFalse(from.get(AefiInvestigation.DELETED))); + + return filter; + } + + public long count(AefiInvestigationCriteria criteria) { + final CriteriaBuilder cb = em.getCriteriaBuilder(); + final CriteriaQuery cq = cb.createQuery(Long.class); + final Root aefiInvestigation = cq.from(AefiInvestigation.class); + + AefiInvestigationQueryContext queryContext = new AefiInvestigationQueryContext(cb, cq, aefiInvestigation); + + buildWhereCondition(criteria, cb, cq, queryContext, null); + + cq.select(cb.countDistinct(aefiInvestigation)); + return em.createQuery(cq).getSingleResult(); + } + + public List getIndexList( + AefiInvestigationCriteria criteria, + Integer first, + Integer max, + List sortProperties) { + + List indexListIds = getIndexListIds(criteria, first, max, sortProperties); + List aefiInvestigationIndexDtos = new ArrayList<>(); + + IterableHelper.executeBatched(indexListIds, ModelConstants.PARAMETER_LIMIT, batchedIds -> { + + final CriteriaBuilder cb = em.getCriteriaBuilder(); + final CriteriaQuery cq = cb.createQuery(Tuple.class); + final Root aefiInvestigation = cq.from(AefiInvestigation.class); + + AefiInvestigationQueryContext queryContext = new AefiInvestigationQueryContext(cb, cq, aefiInvestigation); + AefiInvestigationJoins joins = queryContext.getJoins(); + + final Join aefi = joins.getAefi(); + final Join immunization = joins.getAefiJoins().getImmunization(); + final Join person = joins.getAefiJoins().getImmunizationJoins().getPerson(); + + final Join responsibleRegion = joins.getAefiJoins().getImmunizationJoins().getResponsibleRegion(); + final Join responsibleDistrict = joins.getAefiJoins().getImmunizationJoins().getResponsibleDistrict(); + + final Join primarySuspectVaccine = joins.getPrimarySuspectVaccination(); + + cq.multiselect( + Stream + .concat( + Stream.of( + aefiInvestigation.get(AefiInvestigation.UUID), + aefi.get(Aefi.UUID), + aefiInvestigation.get(AefiInvestigation.INVESTIGATION_CASE_ID), + immunization.get(Immunization.DISEASE), + 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), + responsibleRegion.get(Region.NAME), + responsibleDistrict.get(District.NAME), + aefiInvestigation.get(AefiInvestigation.PLACE_OF_VACCINATION), + aefiInvestigation.get(AefiInvestigation.VACCINATION_ACTIVITY), + aefi.get(Aefi.REPORT_DATE), + aefiInvestigation.get(Aefi.REPORT_DATE), + aefiInvestigation.get(AefiInvestigation.INVESTIGATION_DATE), + aefiInvestigation.get(AefiInvestigation.INVESTIGATION_STAGE), + aefiInvestigation.get(AefiInvestigation.TYPE_OF_SITE), + aefiInvestigation.get(AefiInvestigation.KEY_SYMPTOM_DATE_TIME), + aefiInvestigation.get(AefiInvestigation.HOSPITALIZATION_DATE), + aefiInvestigation.get(AefiInvestigation.REPORTED_TO_HEALTH_AUTHORITY_DATE), + aefiInvestigation.get(AefiInvestigation.STATUS_ON_DATE_OF_INVESTIGATION), + primarySuspectVaccine.get(Vaccination.VACCINE_NAME), + primarySuspectVaccine.get(Vaccination.OTHER_VACCINE_NAME), + aefiInvestigation.get(AefiInvestigation.INVESTIGATION_STATUS), + aefiInvestigation.get(AefiInvestigation.AEFI_CLASSIFICATION), + aefiInvestigation.get(AefiInvestigation.DELETION_REASON), + aefiInvestigation.get(AefiInvestigation.OTHER_DELETION_REASON), + JurisdictionHelper.booleanSelector(cb, isInJurisdictionOrOwned(queryContext)), + aefiInvestigation.get(AefiInvestigation.CHANGE_DATE)), + // add sort properties to select + sortBy(sortProperties, queryContext).stream()) + .collect(Collectors.toList())); + + buildWhereCondition(criteria, cb, cq, queryContext, aefiInvestigation.get(AefiInvestigation.ID).in(batchedIds)); + cq.distinct(true); + + aefiInvestigationIndexDtos.addAll(QueryHelper.getResultList(em, cq, new AefiInvestigationIndexDtoResultTransformer(), null, null)); + }); + + return aefiInvestigationIndexDtos; + } + + private List getIndexListIds(AefiInvestigationCriteria criteria, Integer first, Integer max, List sortProperties) { + + final CriteriaBuilder cb = em.getCriteriaBuilder(); + final CriteriaQuery cq = cb.createTupleQuery(); + final Root aefiInvestigation = cq.from(AefiInvestigation.class); + + AefiInvestigationQueryContext queryContext = new AefiInvestigationQueryContext(cb, cq, aefiInvestigation); + + List> selections = new ArrayList<>(); + selections.add(aefiInvestigation.get(AefiInvestigation.ID)); + selections.addAll(sortBy(sortProperties, queryContext)); + + cq.multiselect(selections); + + buildWhereCondition(criteria, cb, cq, queryContext, null); + cq.distinct(true); + + List aefiInvestigationsResultList = QueryHelper.getResultList(em, cq, first, max); + return aefiInvestigationsResultList.stream().map(t -> t.get(0, Long.class)).collect(Collectors.toList()); + } + + private List> sortBy(List sortProperties, AefiInvestigationQueryContext queryContext) { + + List> selections = new ArrayList<>(); + CriteriaBuilder cb = queryContext.getCriteriaBuilder(); + CriteriaQuery cq = queryContext.getQuery(); + + if (CollectionUtils.isNotEmpty(sortProperties)) { + List order = new ArrayList<>(sortProperties.size()); + for (SortProperty sortProperty : sortProperties) { + Expression expression; + switch (sortProperty.propertyName) { + case AefiInvestigationIndexDto.UUID: + case AefiInvestigationIndexDto.DISEASE: + case AefiInvestigationIndexDto.INVESTIGATION_DATE: + case AefiInvestigationIndexDto.STATUS_ON_DATE_OF_INVESTIGATION: + case AefiInvestigationIndexDto.AEFI_CLASSIFICATION: + expression = queryContext.getRoot().get(sortProperty.propertyName); + break; + case AefiInvestigationIndexDto.AEFI_REPORT_UUID: + expression = queryContext.getJoins().getAefi().get(Aefi.UUID); + break; + case AefiInvestigationIndexDto.PERSON_FIRST_NAME: + expression = cb.lower(queryContext.getJoins().getAefiJoins().getImmunizationJoins().getPerson().get(Person.FIRST_NAME)); + break; + case AefiInvestigationIndexDto.PERSON_LAST_NAME: + expression = cb.lower(queryContext.getJoins().getAefiJoins().getImmunizationJoins().getPerson().get(Person.LAST_NAME)); + break; + case AefiInvestigationIndexDto.AGE_AND_BIRTH_DATE: + expression = queryContext.getJoins().getAefiJoins().getImmunizationJoins().getPerson().get(Person.APPROXIMATE_AGE); + break; + case AefiInvestigationIndexDto.SEX: + expression = queryContext.getJoins().getAefiJoins().getImmunizationJoins().getPerson().get(Person.SEX); + break; + case AefiInvestigationIndexDto.REGION: + expression = cb.lower( + queryContext.getJoins() + .getAefiJoins() + .getImmunizationJoins() + .getPersonJoins() + .getAddressJoins() + .getRegion() + .get(Region.NAME)); + break; + case AefiInvestigationIndexDto.DISTRICT: + expression = cb.lower( + queryContext.getJoins() + .getAefiJoins() + .getImmunizationJoins() + .getPersonJoins() + .getAddressJoins() + .getDistrict() + .get(District.NAME)); + break; + case AefiInvestigationIndexDto.PRIMARY_VACCINE_NAME: + expression = queryContext.getJoins().getPrimarySuspectVaccination().get(Vaccination.VACCINE_NAME); + break; + default: + throw new IllegalArgumentException(sortProperty.propertyName); + } + order.add(sortProperty.ascending ? cb.asc(expression) : cb.desc(expression)); + selections.add(expression); + } + cq.orderBy(order); + } else { + Path changeDate = queryContext.getRoot().get(AefiInvestigation.CHANGE_DATE); + cq.orderBy(cb.desc(changeDate)); + selections.add(changeDate); + } + + return selections; + } + + private void buildWhereCondition( + AefiInvestigationCriteria criteria, + CriteriaBuilder cb, + CriteriaQuery cq, + AefiInvestigationQueryContext queryContext, + Predicate additionalFilter) { + + Predicate filter = createUserFilter(queryContext); + if (additionalFilter != null) { + filter = CriteriaBuilderHelper.and(cb, additionalFilter, filter); + } + + if (criteria != null) { + final Predicate criteriaFilter = buildCriteriaFilter(criteria, queryContext); + filter = CriteriaBuilderHelper.and(cb, filter, criteriaFilter); + } + + if (filter != null) { + cq.where(filter); + } + } + + public Predicate buildCriteriaFilter(AefiInvestigationCriteria criteria, AefiInvestigationQueryContext queryContext) { + + final AefiInvestigationJoins joins = queryContext.getJoins(); + final CriteriaBuilder cb = queryContext.getCriteriaBuilder(); + final From from = queryContext.getRoot(); + final Join aefi = joins.getAefi(); + final Join immunization = joins.getAefiJoins().getImmunization(); + final Join person = joins.getAefiJoins().getImmunizationJoins().getPerson(); + final Join primarySuspectVaccine = joins.getPrimarySuspectVaccination(); + + final Join location = joins.getAefiJoins().getImmunizationJoins().getPersonJoins().getAddress(); + + Predicate filter = null; + if (criteria.getDisease() != null) { + filter = CriteriaBuilderHelper.and(cb, null, cb.equal(immunization.get(Immunization.DISEASE), criteria.getDisease())); + } + + if (!DataHelper.isNullOrEmpty(criteria.getAefiReportLike())) { + + String[] textFilters = criteria.getAefiReportLike().split("\\s+"); + + for (String textFilter : textFilters) { + if (DataHelper.isNullOrEmpty(textFilter)) { + continue; + } + + Predicate likeFilters = cb.or(CriteriaBuilderHelper.ilike(cb, aefi.get(Aefi.UUID), textFilter)); + filter = CriteriaBuilderHelper.and(cb, filter, likeFilters); + } + } + + if (!DataHelper.isNullOrEmpty(criteria.getPersonLike())) { + final CriteriaQuery cq = cb.createQuery(PersonIndexDto.class); + final PersonQueryContext personQueryContext = + new PersonQueryContext(cb, cq, joins.getAefiJoins().getImmunizationJoins().getPersonJoins()); + + String[] textFilters = criteria.getPersonLike().split("\\s+"); + + for (String textFilter : textFilters) { + if (DataHelper.isNullOrEmpty(textFilter)) { + continue; + } + + Predicate likeFilters = cb.or( + CriteriaBuilderHelper.ilike(cb, from.get(AefiInvestigation.UUID), textFilter), + CriteriaBuilderHelper.unaccentedIlike(cb, person.get(Person.FIRST_NAME), textFilter), + CriteriaBuilderHelper.unaccentedIlike(cb, person.get(Person.LAST_NAME), textFilter), + CriteriaBuilderHelper.ilike(cb, person.get(Person.UUID), textFilter), + CriteriaBuilderHelper.ilike(cb, personQueryContext.getSubqueryExpression(PersonQueryContext.PERSON_EMAIL_SUBQUERY), textFilter), + phoneNumberPredicate(cb, personQueryContext.getSubqueryExpression(PersonQueryContext.PERSON_PHONE_SUBQUERY), textFilter), + CriteriaBuilderHelper + .ilike(cb, personQueryContext.getSubqueryExpression(PersonQueryContext.PERSON_PRIMARY_OTHER_SUBQUERY), textFilter), + CriteriaBuilderHelper.unaccentedIlike(cb, location.get(Location.STREET), textFilter), + CriteriaBuilderHelper.unaccentedIlike(cb, location.get(Location.CITY), textFilter), + CriteriaBuilderHelper.ilike(cb, location.get(Location.POSTAL_CODE), textFilter), + CriteriaBuilderHelper.ilike(cb, person.get(Person.INTERNAL_TOKEN), textFilter), + CriteriaBuilderHelper.ilike(cb, person.get(Person.EXTERNAL_ID), textFilter), + CriteriaBuilderHelper.ilike(cb, person.get(Person.EXTERNAL_TOKEN), textFilter)); + filter = CriteriaBuilderHelper.and(cb, filter, likeFilters); + } + } + if (criteria.getAefiType() != null) { + if (criteria.getAefiType() == AefiType.SERIOUS) { + filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(aefi.get(Aefi.SERIOUS), YesNoUnknown.YES)); + } else { + filter = CriteriaBuilderHelper.and(cb, filter, cb.notEqual(aefi.get(Aefi.SERIOUS), YesNoUnknown.YES)); + } + } + if (criteria.getStatusAtAefiInvestigation() != null) { + filter = CriteriaBuilderHelper + .and(cb, filter, cb.equal(from.get(AefiInvestigation.STATUS_ON_DATE_OF_INVESTIGATION), criteria.getStatusAtAefiInvestigation())); + } + if (criteria.getAefiClassification() != null) { + filter = + CriteriaBuilderHelper.and(cb, filter, cb.equal(from.get(AefiInvestigation.AEFI_CLASSIFICATION), criteria.getAefiClassification())); + } + if (criteria.getVaccineName() != null) { + filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(primarySuspectVaccine.get(Vaccination.VACCINE_NAME), criteria.getVaccineName())); + } + if (criteria.getVaccineManufacturer() != null) { + filter = CriteriaBuilderHelper + .and(cb, filter, cb.equal(primarySuspectVaccine.get(Vaccination.VACCINE_MANUFACTURER), criteria.getVaccineManufacturer())); + } + filter = andEquals(cb, () -> joins.getAefiJoins().getImmunizationJoins().getResponsibleRegion(), filter, criteria.getRegion()); + filter = andEquals(cb, () -> joins.getAefiJoins().getImmunizationJoins().getResponsibleDistrict(), filter, criteria.getDistrict()); + filter = andEquals(cb, () -> joins.getAefiJoins().getImmunizationJoins().getResponsibleCommunity(), filter, criteria.getCommunity()); + if (criteria.getFacilityType() != null) { + filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(immunization.get(Immunization.FACILITY_TYPE), criteria.getFacilityType())); + } + filter = andEquals(cb, () -> joins.getAefiJoins().getImmunizationJoins().getHealthFacility(), filter, criteria.getHealthFacility()); + if (criteria.getAefiInvestigationDateType() != null) { + Path path = buildPathForDateFilter(criteria.getAefiInvestigationDateType(), queryContext); + if (path != null) { + filter = CriteriaBuilderHelper.applyDateFilter(cb, filter, path, criteria.getFromDate(), criteria.getToDate()); + } + } + + if (criteria.getRelevanceStatus() != null) { + if (criteria.getRelevanceStatus() == EntityRelevanceStatus.ACTIVE) { + filter = CriteriaBuilderHelper + .and(cb, filter, cb.or(cb.equal(from.get(AefiInvestigation.ARCHIVED), false), cb.isNull(from.get(AefiInvestigation.ARCHIVED)))); + } else if (criteria.getRelevanceStatus() == EntityRelevanceStatus.ARCHIVED) { + filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(from.get(AefiInvestigation.ARCHIVED), true)); + } else if (criteria.getRelevanceStatus() == EntityRelevanceStatus.DELETED) { + filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(from.get(AefiInvestigation.DELETED), true)); + } + } + if (criteria.getRelevanceStatus() != EntityRelevanceStatus.DELETED) { + filter = CriteriaBuilderHelper.and(cb, filter, cb.isFalse(from.get(AefiInvestigation.DELETED))); + } + + return filter; + } + + private Path buildPathForDateFilter(AefiInvestigationDateType aefiInvestigationDateType, AefiInvestigationQueryContext queryContext) { + Path path = null; + String dateField = getDateFieldFromDateType(aefiInvestigationDateType); + if (dateField != null) { + if (Vaccination.VACCINATION_DATE.equals(dateField)) { + final Join primarySuspectVaccination = queryContext.getJoins().getPrimarySuspectVaccination(); + path = primarySuspectVaccination.get(Vaccination.VACCINATION_DATE); + } else { + path = queryContext.getRoot().get(dateField); + } + } + return path; + } + + private String getDateFieldFromDateType(AefiInvestigationDateType aefiInvestigationDateType) { + switch (aefiInvestigationDateType) { + case REPORT_DATE: + return AefiInvestigation.REPORT_DATE; + case INVESTIGATION_DATE: + return AefiInvestigation.INVESTIGATION_DATE; + case VACCINATION_DATE: + return Vaccination.VACCINATION_DATE; + } + return null; + } + + public Predicate createUserFilter(AefiInvestigationQueryContext qc) { + + User currentUser = getCurrentUser(); + if (currentUser == null) { + return null; + } + final CriteriaBuilder cb = qc.getCriteriaBuilder(); + + Predicate filter = isInJurisdictionOrOwned(qc); + + filter = CriteriaBuilderHelper.and( + cb, + filter, + CriteriaBuilderHelper.limitedDiseasePredicate( + cb, + currentUser, + qc.getRoot().get(AefiInvestigation.AEFI_REPORT).get(Aefi.IMMUNIZATION).get(Immunization.DISEASE))); + + return filter; + } + + private Predicate isInJurisdictionOrOwned(AefiInvestigationQueryContext qc) { + + final User currentUser = userService.getCurrentUser(); + CriteriaBuilder cb = qc.getCriteriaBuilder(); + Predicate filter; + if (!featureConfigurationFacade + .isPropertyValueTrue(FeatureType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_MANAGEMENT, FeatureTypeProperty.REDUCED)) { + filter = AefiInvestigationJurisdictionPredicateValidator.of(qc, currentUser).inJurisdictionOrOwned(); + } else { + filter = CriteriaBuilderHelper.or( + cb, + cb.equal(qc.getRoot().get(AefiInvestigation.REPORTING_USER), currentUser), + PersonJurisdictionPredicateValidator + .of( + qc.getQuery(), + cb, + new PersonJoins(qc.getJoins().getAefiJoins().getImmunizationJoins().getPerson()), + currentUser, + personService.getPermittedAssociations()) + .inJurisdictionOrOwned()); + } + return filter; + } + + @Override + protected Predicate createUserFilterInternal(CriteriaBuilder cb, CriteriaQuery cq, From from) { + return createUserFilter(new AefiInvestigationQueryContext(cb, cq, from)); + } + + @Override + protected AefiInvestigationJoins toJoins(From adoPath) { + return new AefiInvestigationJoins(adoPath); + } + + @Override + public Predicate inJurisdictionOrOwned(CriteriaBuilder cb, CriteriaQuery query, From from) { + return isInJurisdictionOrOwned(new AefiInvestigationQueryContext(cb, query, from)); + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiJurisdictionPredicateValidator.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiJurisdictionPredicateValidator.java index 215572a9d48..776d84268c9 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiJurisdictionPredicateValidator.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiJurisdictionPredicateValidator.java @@ -55,7 +55,7 @@ public Predicate isRootInJurisdiction() { @Override public Predicate isRootInJurisdictionOrOwned() { - final Path reportingUserPath = joins.getRoot().get(Immunization.REPORTING_USER); + final Path reportingUserPath = joins.getRoot().get(Aefi.REPORTING_USER); final Predicate reportedByCurrentUser = cb.and(cb.isNotNull(reportingUserPath), cb.equal(reportingUserPath.get(User.ID), user.getId())); return cb.or(reportedByCurrentUser, this.isRootInJurisdiction()); } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiService.java index 5d18a99795b..62736e5f1b5 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/AefiService.java @@ -18,6 +18,7 @@ import static de.symeda.sormas.backend.common.CriteriaBuilderHelper.andEquals; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -26,22 +27,27 @@ 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; import javax.persistence.criteria.From; import javax.persistence.criteria.Join; +import javax.persistence.criteria.JoinType; import javax.persistence.criteria.Order; +import javax.persistence.criteria.ParameterExpression; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import javax.persistence.criteria.Selection; +import javax.validation.constraints.NotNull; import org.apache.commons.collections4.CollectionUtils; import de.symeda.sormas.api.EntityRelevanceStatus; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiCriteria; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDateType; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiExportDto; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiIndexDto; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiListEntryDto; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; @@ -58,10 +64,14 @@ import de.symeda.sormas.backend.adverseeventsfollowingimmunization.transformers.AefiIndexDtoResultTransformer; import de.symeda.sormas.backend.adverseeventsfollowingimmunization.transformers.AefiListEntryDtoResultTransformer; import de.symeda.sormas.backend.common.AbstractCoreAdoService; +import de.symeda.sormas.backend.common.AbstractDomainObject; import de.symeda.sormas.backend.common.CriteriaBuilderHelper; import de.symeda.sormas.backend.feature.FeatureConfigurationFacadeEjb; import de.symeda.sormas.backend.immunization.entity.Immunization; +import de.symeda.sormas.backend.infrastructure.community.Community; +import de.symeda.sormas.backend.infrastructure.country.Country; 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.location.Location; import de.symeda.sormas.backend.person.Person; @@ -92,6 +102,24 @@ public AefiService() { super(Aefi.class, DeletableEntityType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION); } + public Long getIdByUuid(@NotNull String uuid) { + + if (uuid == null) { + return null; + } + + CriteriaBuilder cb = em.getCriteriaBuilder(); + ParameterExpression uuidParam = cb.parameter(String.class, AbstractDomainObject.UUID); + CriteriaQuery cq = cb.createQuery(Long.class); + Root from = cq.from(Aefi.class); + cq.select(from.get(AbstractDomainObject.ID)); + cq.where(cb.equal(from.get(AbstractDomainObject.UUID), uuidParam)); + + TypedQuery q = em.createQuery(cq).setParameter(uuidParam, uuid); + + return q.getResultList().stream().findFirst().orElse(null); + } + public List getEntriesList(Long immunizationId, Integer first, Integer max) { final CriteriaBuilder cb = em.getCriteriaBuilder(); final CriteriaQuery cq = cb.createQuery(Tuple.class); @@ -205,6 +233,7 @@ public List getIndexList(AefiCriteria criteria, Integer first, Int responsibleDistrict.get(District.NAME), aefi.get(Aefi.SERIOUS), primarySuspectVaccine.get(Vaccination.VACCINE_NAME), + primarySuspectVaccine.get(Vaccination.OTHER_VACCINE_NAME), aefi.get(Aefi.OUTCOME), primarySuspectVaccine.get(Vaccination.VACCINATION_DATE), aefi.get(Aefi.REPORT_DATE), @@ -260,6 +289,121 @@ private List getIndexListIds(AefiCriteria criteria, Integer first, Integer return aefiResultList.stream().map(t -> t.get(0, Long.class)).collect(Collectors.toList()); } + public List getExportList(AefiCriteria criteria, Collection selectedRows, int first, int max) { + + final CriteriaBuilder cb = em.getCriteriaBuilder(); + final CriteriaQuery cq = cb.createQuery(AefiExportDto.class); + final Root aefi = cq.from(Aefi.class); + + final AefiQueryContext aefiQueryContext = new AefiQueryContext(cb, cq, aefi); + AefiJoins joins = aefiQueryContext.getJoins(); + + final Join immunization = joins.getImmunization(); + final Join person = joins.getImmunizationJoins().getPerson(); + final Join immunizationFacility = joins.getImmunizationJoins().getHealthFacility(); + final Join immunizationFacilityRegion = immunizationFacility.join(Facility.REGION, JoinType.LEFT); + final Join immunizationFacilityDistrict = immunizationFacility.join(Facility.DISTRICT, JoinType.LEFT); + final Join immunizationFacilityCommunity = immunizationFacility.join(Facility.COMMUNITY, JoinType.LEFT); + + final Join personLocation = person.join(Person.ADDRESS, JoinType.LEFT); + final Join personLocationRegion = personLocation.join(Location.REGION, JoinType.LEFT); + final Join personLocationDistrict = personLocation.join(Location.DISTRICT, JoinType.LEFT); + final Join personLocationCommunity = personLocation.join(Location.COMMUNITY, JoinType.LEFT); + + final Join responsibleRegion = joins.getImmunizationJoins().getResponsibleRegion(); + final Join responsibleDistrict = joins.getImmunizationJoins().getResponsibleDistrict(); + + final Join primarySuspectVaccine = joins.getPrimarySuspectVaccination(); + final Join adverseEvents = joins.getAdverseEvents(); + + final Join reportingUser = joins.getReportingUser(); + final Join reportingUserLocation = reportingUser.join(User.ADDRESS, JoinType.LEFT); + final Join reportingUserLocationCountry = reportingUserLocation.join(Location.COUNTRY, JoinType.LEFT); + final Join reportingUserFacility = reportingUser.join(User.HEALTH_FACILITY, JoinType.LEFT); + final Join reportingUserFacilityRegion = reportingUserFacility.join(Facility.REGION, JoinType.LEFT); + final Join reportingUserFacilityDistrict = reportingUserFacility.join(Facility.DISTRICT, JoinType.LEFT); + final Join reportingUserFacilityCommunity = reportingUserFacility.join(Facility.COMMUNITY, JoinType.LEFT); + + cq.multiselect( + aefi.get(Aefi.UUID), + aefi.get(Aefi.RECEIVED_AT_NATIONAL_LEVEL_DATE), + immunizationFacility.get(Facility.NAME), + immunizationFacilityRegion.get(Region.NAME), + immunizationFacilityDistrict.get(District.NAME), + immunizationFacilityCommunity.get(Community.NAME), + reportingUserLocationCountry.get(Country.DEFAULT_NAME), + personLocationRegion.get(Region.NAME), + personLocationDistrict.get(District.NAME), + personLocationCommunity.get(Community.NAME), + personLocation.get(Location.STREET), + personLocation.get(Location.HOUSE_NUMBER), + personLocation.get(Location.POSTAL_CODE), + personLocation.get(Location.CITY), + aefi.get(Aefi.REPORTINGID_NUMBER), + aefi.get(Aefi.WORLD_WIDE_ID), + person.get(Person.FIRST_NAME), + person.get(Person.LAST_NAME), + person.get(Person.BIRTHDATE_DD), + person.get(Person.BIRTHDATE_MM), + person.get(Person.BIRTHDATE_YYYY), + aefi.get(Aefi.ONSET_AGE_YEARS), + aefi.get(Aefi.ONSET_AGE_MONTHS), + aefi.get(Aefi.ONSET_AGE_DAYS), + aefi.get(Aefi.AGE_GROUP), + person.get(Person.SEX), + aefi.get(Aefi.AEFI_DESCRIPTION), + primarySuspectVaccine.get(Vaccination.VACCINE_NAME), + primarySuspectVaccine.get(Vaccination.OTHER_VACCINE_NAME), + primarySuspectVaccine.get(Vaccination.VACCINE_MANUFACTURER), + primarySuspectVaccine.get(Vaccination.VACCINE_BATCH_NUMBER), + primarySuspectVaccine.get(Vaccination.VACCINE_DOSE), + primarySuspectVaccine.get(Vaccination.VACCINATION_DATE), + aefi.get(Aefi.START_DATE_TIME), + adverseEvents.get(AdverseEvents.SEVERE_LOCAL_REACTION), + adverseEvents.get(AdverseEvents.SEVERE_LOCAL_REACTION_MORE_THAN_THREE_DAYS), + adverseEvents.get(AdverseEvents.SEVERE_LOCAL_REACTION_BEYOND_NEAREST_JOINT), + adverseEvents.get(AdverseEvents.SEIZURES), + adverseEvents.get(AdverseEvents.SEIZURE_TYPE), + adverseEvents.get(AdverseEvents.ABSCESS), + adverseEvents.get(AdverseEvents.SEPSIS), + adverseEvents.get(AdverseEvents.ENCEPHALOPATHY), + adverseEvents.get(AdverseEvents.TOXIC_SHOCK_SYNDROME), + adverseEvents.get(AdverseEvents.THROMBOCYTOPENIA), + adverseEvents.get(AdverseEvents.ANAPHYLAXIS), + adverseEvents.get(AdverseEvents.FEVERISH_FEELING), + adverseEvents.get(AdverseEvents.OTHER_ADVERSE_EVENT_DETAILS), + aefi.get(Aefi.OUTCOME), + aefi.get(Aefi.SERIOUS), + reportingUser.get(User.FIRST_NAME), + reportingUser.get(User.LAST_NAME), + reportingUserFacility.get(Facility.NAME), + reportingUserFacilityRegion.get(Region.NAME), + reportingUserFacilityDistrict.get(District.NAME), + reportingUserFacilityCommunity.get(Community.NAME), + reportingUser.get(User.USER_EMAIL), + reportingUser.get(User.PHONE), + aefi.get((Aefi.REPORT_DATE)), + aefi.get((Aefi.NATIONAL_LEVEL_COMMENT)), + JurisdictionHelper.booleanSelector(cb, isInJurisdictionOrOwned(aefiQueryContext))); + + /* + * buildWhereCondition(criteria, cb, cq, aefiQueryContext, null); + * cq.distinct(true); + */ + + Predicate filter = buildExportListWhereCondition(criteria, cb, cq, aefiQueryContext); + if (selectedRows != null && !selectedRows.isEmpty()) { + filter = CriteriaBuilderHelper.andInValues(selectedRows, filter, cb, aefi.get(Aefi.UUID)); + } + + if (filter != null) { + cq.where(filter); + } + cq.distinct(true); + + return QueryHelper.getResultList(em, cq, first, max); + } + private List> sortBy(List sortProperties, AefiQueryContext aefiQueryContext) { List> selections = new ArrayList<>(); @@ -349,6 +493,22 @@ private void buildWhereCondition( } } + private Predicate buildExportListWhereCondition( + AefiCriteria criteria, + CriteriaBuilder cb, + CriteriaQuery cq, + AefiQueryContext aefiQueryContext) { + + Predicate filter = createUserFilter(aefiQueryContext); + + if (criteria != null) { + final Predicate criteriaFilter = buildCriteriaFilter(criteria, aefiQueryContext); + filter = CriteriaBuilderHelper.and(cb, filter, criteriaFilter); + } + + return filter; + } + public Predicate buildCriteriaFilter(AefiCriteria criteria, AefiQueryContext aefiQueryContext) { final AefiJoins joins = aefiQueryContext.getJoins(); @@ -365,11 +525,11 @@ public Predicate buildCriteriaFilter(AefiCriteria criteria, AefiQueryContext aef filter = CriteriaBuilderHelper.and(cb, null, cb.equal(immunization.get(Immunization.DISEASE), criteria.getDisease())); } - if (!DataHelper.isNullOrEmpty(criteria.getNameAddressPhoneEmailLike())) { + if (!DataHelper.isNullOrEmpty(criteria.getPersonLike())) { final CriteriaQuery cq = cb.createQuery(PersonIndexDto.class); final PersonQueryContext personQueryContext = new PersonQueryContext(cb, cq, joins.getImmunizationJoins().getPersonJoins()); - String[] textFilters = criteria.getNameAddressPhoneEmailLike().split("\\s+"); + String[] textFilters = criteria.getPersonLike().split("\\s+"); for (String textFilter : textFilters) { if (DataHelper.isNullOrEmpty(textFilter)) { @@ -496,7 +656,7 @@ private Predicate isInJurisdictionOrOwned(AefiQueryContext qc) { } else { filter = CriteriaBuilderHelper.or( cb, - cb.equal(qc.getRoot().get(Immunization.REPORTING_USER), currentUser), + cb.equal(qc.getRoot().get(Aefi.REPORTING_USER), currentUser), PersonJurisdictionPredicateValidator .of(qc.getQuery(), cb, new PersonJoins(qc.getJoins().getPerson()), currentUser, personService.getPermittedAssociations()) .inJurisdictionOrOwned()); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/Aefi.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/Aefi.java index 1b62575f5e4..92b65406c2b 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/Aefi.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/Aefi.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -91,13 +88,13 @@ public class Aefi extends CoreAdo { public static final String AGE_GROUP = "ageGroup"; public static final String HEALTH_FACILITY = "healthFacility"; public static final String HEALTH_FACILITY_DETAILS = "healthFacilityDetails"; - public static final String REPORTER_NAME = "reporterName"; - public static final String REPORTER_INSTITUTION = "reporterInstitution"; - public static final String REPORTER_DESIGNATION = "reporterDesignation"; - public static final String REPORTER_DEPARTMENT = "reporterDepartment"; - public static final String REPORTER_ADDRESS = "reporterAddress"; - public static final String REPORTER_PHONE = "reporterPhone"; - public static final String REPORTER_EMAIL = "reporterEmail"; + public static final String REPORTING_OFFICER_NAME = "reportingOfficerName"; + public static final String REPORTING_OFFICER_FACILITY = "reportingOfficerFacility"; + public static final String REPORTING_OFFICER_DESIGNATION = "reportingOfficerDesignation"; + public static final String REPORTING_OFFICER_DEPARTMENT = "reportingOfficerDepartment"; + public static final String REPORTING_OFFICER_ADDRESS = "reportingOfficerAddress"; + public static final String REPORTING_OFFICER_PHONE_NUMBER = "reportingOfficerPhoneNumber"; + public static final String REPORTING_OFFICER_EMAIL = "reportingOfficerEmail"; public static final String TODAYS_DATE = "todaysDate"; public static final String START_DATE_TIME = "startDateTime"; public static final String AEFI_DESCRIPTION = "aefiDescription"; @@ -140,13 +137,13 @@ public class Aefi extends CoreAdo { private AefiAgeGroup ageGroup; private Facility healthFacility; private String healthFacilityDetails; - private String reporterName; - private Facility reporterInstitution; - private String reporterDesignation; - private String reporterDepartment; - private Location reporterAddress; - private String reporterPhone; - private String reporterEmail; + private String reportingOfficerName; + private Facility reportingOfficerFacility; + private String reportingOfficerDesignation; + private String reportingOfficerDepartment; + private Location reportingOfficerAddress; + private String reportingOfficerPhoneNumber; + private String reportingOfficerEmail; private Date todaysDate; private Date startDateTime; private String aefiDescription; @@ -323,6 +320,7 @@ public void setReportingIdNumber(String reportingIdNumber) { this.reportingIdNumber = reportingIdNumber; } + @Column public String getPhoneNumber() { return phoneNumber; } @@ -358,6 +356,7 @@ public void setLactating(YesNoUnknown lactating) { this.lactating = lactating; } + @Column public Integer getOnsetAgeYears() { return onsetAgeYears; } @@ -366,6 +365,7 @@ public void setOnsetAgeYears(Integer onsetAgeYears) { this.onsetAgeYears = onsetAgeYears; } + @Column public Integer getOnsetAgeMonths() { return onsetAgeMonths; } @@ -374,6 +374,7 @@ public void setOnsetAgeMonths(Integer onsetAgeMonths) { this.onsetAgeMonths = onsetAgeMonths; } + @Column public Integer getOnsetAgeDays() { return onsetAgeDays; } @@ -409,63 +410,68 @@ public void setHealthFacilityDetails(String healthFacilityDetails) { this.healthFacilityDetails = healthFacilityDetails; } - public String getReporterName() { - return reporterName; + @Column + public String getReportingOfficerName() { + return reportingOfficerName; } - public void setReporterName(String reporterName) { - this.reporterName = reporterName; + public void setReportingOfficerName(String reporterName) { + this.reportingOfficerName = reporterName; } @ManyToOne(fetch = FetchType.LAZY) - public Facility getReporterInstitution() { - return reporterInstitution; + public Facility getReportingOfficerFacility() { + return reportingOfficerFacility; } - public void setReporterInstitution(Facility reporterInstitution) { - this.reporterInstitution = reporterInstitution; + public void setReportingOfficerFacility(Facility reporterInstitution) { + this.reportingOfficerFacility = reporterInstitution; } - public String getReporterDesignation() { - return reporterDesignation; + @Column + public String getReportingOfficerDesignation() { + return reportingOfficerDesignation; } - public void setReporterDesignation(String reporterDesignation) { - this.reporterDesignation = reporterDesignation; + public void setReportingOfficerDesignation(String reporterDesignation) { + this.reportingOfficerDesignation = reporterDesignation; } - public String getReporterDepartment() { - return reporterDepartment; + @Column + public String getReportingOfficerDepartment() { + return reportingOfficerDepartment; } - public void setReporterDepartment(String reporterDepartment) { - this.reporterDepartment = reporterDepartment; + public void setReportingOfficerDepartment(String reporterDepartment) { + this.reportingOfficerDepartment = reporterDepartment; } @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) - @JoinColumn(name = "reporteraddress_id") - public Location getReporterAddress() { - return reporterAddress; + @JoinColumn(name = "reportingofficeraddress_id") + public Location getReportingOfficerAddress() { + return reportingOfficerAddress; } - public void setReporterAddress(Location reporterAddress) { - this.reporterAddress = reporterAddress; + public void setReportingOfficerAddress(Location reporterAddress) { + this.reportingOfficerAddress = reporterAddress; } - public String getReporterPhone() { - return reporterPhone; + @Column + public String getReportingOfficerPhoneNumber() { + return reportingOfficerPhoneNumber; } - public void setReporterPhone(String reporterPhone) { - this.reporterPhone = reporterPhone; + public void setReportingOfficerPhoneNumber(String reporterPhone) { + this.reportingOfficerPhoneNumber = reporterPhone; } - public String getReporterEmail() { - return reporterEmail; + @Column + public String getReportingOfficerEmail() { + return reportingOfficerEmail; } - public void setReporterEmail(String reporterEmail) { - this.reporterEmail = reporterEmail; + public void setReportingOfficerEmail(String reporterEmail) { + this.reportingOfficerEmail = reporterEmail; } @Temporal(TemporalType.TIMESTAMP) @@ -587,6 +593,7 @@ public void setReceivedAtNationalLevelDate(Date receivedAtNationalLevelDate) { this.receivedAtNationalLevelDate = receivedAtNationalLevelDate; } + @Column public String getWorldwideId() { return worldwideId; } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiInvestigation.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiInvestigation.java new file mode 100644 index 00000000000..e4157a4c6c0 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiInvestigation.java @@ -0,0 +1,1832 @@ +/* + * 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.adverseeventsfollowingimmunization.entity; + +import java.util.Arrays; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; +import javax.persistence.OneToOne; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.Transient; + +import org.apache.commons.lang3.StringUtils; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiCausality; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiClassification; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiClassificationSubType; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiImmunizationPeriod; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationStage; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationStatus; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiVaccinationPeriod; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.BirthTerm; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.DeliveryProcedure; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.PatientStatusAtAefiInvestigation; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.PlaceOfVaccination; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.SeriousAefiInfoSource; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.SyringeType; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.VaccinationActivity; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.VaccinationSite; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.VaccineCarrier; +import de.symeda.sormas.api.utils.YesNoUnknown; +import de.symeda.sormas.backend.common.CoreAdo; +import de.symeda.sormas.backend.infrastructure.community.Community; +import de.symeda.sormas.backend.infrastructure.country.Country; +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.location.Location; +import de.symeda.sormas.backend.user.User; +import de.symeda.sormas.backend.vaccination.Vaccination; + +@Entity +@Table(name = "adverseeventsfollowingimmunizationinvestigation") +public class AefiInvestigation extends CoreAdo { + + private static final long serialVersionUID = 6128204752074963848L; + + public static final String TABLE_NAME = "adverseeventsfollowingimmunizationinvestigation"; + public static final String AEFI_INVESTIGATION_VACCINATIONS_TABLE_NAME = "adverseeventsfollowingimmunizationinvestigation_vaccinations"; + + public static final String AEFI_REPORT = "aefiReport"; + public static final String AEFI_REPORT_ID = "aefiReportId"; + public static final String ADDRESS = "address"; + public static final String VACCINATIONS = "vaccinations"; + public static final String PRIMARY_SUSPECT_VACCINE = "primarySuspectVaccine"; + public static final String REPORT_DATE = "reportDate"; + public static final String REPORTING_USER = "reportingUser"; + public static final String EXTERNAL_ID = "externalId"; + public static final String RESPONSIBLE_REGION = "responsibleRegion"; + public static final String RESPONSIBLE_DISTRICT = "responsibleDistrict"; + public static final String RESPONSIBLE_COMMUNITY = "responsibleCommunity"; + public static final String COUNTRY = "country"; + public static final String INVESTIGATION_CASE_ID = "investigationCaseId"; + public static final String PLACE_OF_VACCINATION = "placeOfVaccination"; + public static final String PLACE_OF_VACCINATION_DETAILS = "placeOfVaccinationDetails"; + public static final String VACCINATION_ACTIVITY = "vaccinationActivity"; + public static final String VACCINATION_ACTIVITY_DETAILS = "vaccinationActivityDetails"; + public static final String VACCINATION_FACILITY = "vaccinationFacility"; + public static final String VACCINATION_FACILITY_DETAILS = "vaccinationFacilityDetails"; + public static final String REPORTING_OFFICER_NAME = "reportingOfficerName"; + public static final String REPORTING_OFFICER_FACILITY = "reportingOfficerFacility"; + public static final String REPORTING_OFFICER_FACILITY_DETAILS = "reportingOfficerFacilityDetails"; + public static final String REPORTING_OFFICER_DESIGNATION = "reportingOfficerDesignation"; + public static final String REPORTING_OFFICER_DEPARTMENT = "reportingOfficerDepartment"; + public static final String REPORTING_OFFICER_ADDRESS = "reportingOfficerAddress"; + public static final String REPORTING_OFFICER_LANDLINE_PHONE_NUMBER = "reportingOfficerLandlinePhoneNumber"; + public static final String REPORTING_OFFICER_MOBILE_PHONE_NUMBER = "reportingOfficerMobilePhoneNumber"; + public static final String REPORTING_OFFICER_EMAIL = "reportingOfficerEmail"; + public static final String INVESTIGATION_DATE = "investigationDate"; + public static final String FORM_COMPLETION_DATE = "formCompletionDate"; + public static final String INVESTIGATION_STAGE = "investigationStage"; + public static final String TYPE_OF_SITE = "typeOfSite"; + public static final String TYPE_OF_SITE_DETAILS = "typeOfSiteDetails"; + public static final String KEY_SYMPTOM_DATE_TIME = "keySymptomDateTime"; + public static final String HOSPITALIZATION_DATE = "hospitalizationDate"; + public static final String REPORTED_TO_HEALTH_AUTHORITY_DATE = "reportedToHealthAuthorityDate"; + public static final String STATUS_ON_DATE_OF_INVESTIGATION = "statusOnDateOfInvestigation"; + public static final String DEATH_DATE_TIME = "deathDateTime"; + public static final String AUTOPSY_DONE = "autopsyDone"; + public static final String AUTOPSY_DATE = "autopsyDate"; + public static final String AUTOPSY_PLANNED_DATE_TIME = "autopsyPlannedDateTime"; + public static final String PAST_HISTORY_OF_SIMILAR_EVENT = "pastHistoryOfSimilarEvent"; + public static final String PAST_HISTORY_OF_SIMILAR_EVENT_DETAILS = "pastHistoryOfSimilarEventDetails"; + public static final String ADVERSE_EVENT_AFTER_PREVIOUS_VACCINATIONS = "adverseEventAfterPreviousVaccinations"; + public static final String ADVERSE_EVENT_AFTER_PREVIOUS_VACCINATIONS_DETAILS = "adverseEventAfterPreviousVaccinationsDetails"; + public static final String HISTORY_OF_ALLERGY_TO_VACCINE_DRUG_OR_FOOD = "historyOfAllergyToVaccineDrugOrFood"; + public static final String HISTORY_OF_ALLERGY_TO_VACCINE_DRUG_OR_FOOD_DETAILS = "historyOfAllergyToVaccineDrugOrFoodDetails"; + public static final String PRE_EXISTING_ILLNESS_THIRTY_DAYS_OR_CONGENITAL_DISORDER = "preExistingIllnessThirtyDaysOrCongenitalDisorder"; + public static final String PRE_EXISTING_ILLNESS_THIRTY_DAYS_OR_CONGENITAL_DISORDER_DETAILS = + "preExistingIllnessThirtyDaysOrCongenitalDisorderDetails"; + public static final String HISTORY_OF_HOSPITALIZATION_IN_LAST_THIRTY_DAYS_WITH_CAUSE = "historyOfHospitalizationInLastThirtyDaysWithCause"; + public static final String HISTORY_OF_HOSPITALIZATION_IN_LAST_THIRTY_DAYS_WITH_CAUSE_DETAILS = + "historyOfHospitalizationInLastThirtyDaysWithCauseDetails"; + public static final String CURRENTLY_ON_CONCOMITANT_MEDICATION = "currentlyOnConcomitantMedication"; + public static final String CURRENTLY_ON_CONCOMITANT_MEDICATION_DETAILS = "currentlyOnConcomitantMedicationDetails"; + public static final String FAMILY_HISTORY_OF_DISEASE_OR_ALLERGY = "familyHistoryOfDiseaseOrAllergy"; + public static final String FAMILY_HISTORY_OF_DISEASE_OR_ALLERGY_DETAILS = "familyHistoryOfDiseaseOrAllergyDetails"; + public static final String NUMBER_OF_WEEKS_PREGNANT = "numberOfWeeksPregnant"; + public static final String BIRTH_TERM = "birthTerm"; + public static final String BIRTH_WEIGHT = "birthWeight"; + public static final String DELIVERY_PROCEDURE = "deliveryProcedure"; + public static final String DELIVERY_PROCEDURE_DETAILS = "deliveryProcedureDetails"; + public static final String SERIOUS_AEFI_INFO_SOURCE_STRING = "seriousAefiInfoSourceString"; + public static final String SERIOUS_AEFI_INFO_SOURCE_DETAILS = "seriousAefiInfoSourceDetails"; + public static final String SERIOUS_AEFI_VERBAL_AUTOPSY_INFO_SOURCE_DETAILS = "seriousAefiVerbalAutopsyInfoSourceDetails"; + public static final String FIRST_CAREGIVERS_NAME = "firstCaregiversName"; + public static final String OTHER_CAREGIVERS_NAMES = "otherCaregiversNames"; + public static final String OTHER_SOURCES_WHO_PROVIDED_INFO = "otherSourcesWhoProvidedInfo"; + public static final String SIGNS_AND_SYMPTOMS_FROM_TIME_OF_VACCINATION = "signsAndSymptomsFromTimeOfVaccination"; + public static final String CLINICAL_DETAILS_OFFICER_NAME = "clinicalDetailsOfficerName"; + public static final String CLINICAL_DETAILS_OFFICER_PHONE_NUMBER = "clinicalDetailsOfficerPhoneNumber"; + public static final String CLINICAL_DETAILS_OFFICER_EMAIL = "clinicalDetailsOfficerEmail"; + public static final String CLINICAL_DETAILS_OFFICER_DESIGNATION = "clinicalDetailsOfficerDesignation"; + public static final String CLINICAL_DETAILS_DATE_TIME = "clinicalDetailsDateTime"; + public static final String PATIENT_RECEIVED_MEDICAL_CARE = "patientReceivedMedicalCare"; + public static final String PATIENT_RECEIVED_MEDICAL_CARE_DETAILS = "patientReceivedMedicalCareDetails"; + public static final String PROVISIONAL_OR_FINAL_DIAGNOSIS = "provisionalOrFinalDiagnosis"; + public static final String PATIENT_IMMUNIZED_PERIOD = "patientImmunizedPeriod"; + public static final String PATIENT_IMMUNIZED_PERIOD_DETAILS = "patientImmunizedPeriodDetails"; + public static final String VACCINE_GIVEN_PERIOD = "vaccineGivenPeriod"; + public static final String VACCINE_GIVEN_PERIOD_DETAILS = "vaccineGivenPeriodDetails"; + public static final String ERROR_PRESCRIBING_VACCINE = "errorPrescribingVaccine"; + public static final String ERROR_PRESCRIBING_VACCINE_DETAILS = "errorPrescribingVaccineDetails"; + public static final String VACCINE_COULD_HAVE_BEEN_UNSTERILE = "vaccineCouldHaveBeenUnSterile"; + public static final String VACCINE_COULD_HAVE_BEEN_UNSTERILE_DETAILS = "vaccineCouldHaveBeenUnSterileDetails"; + public static final String VACCINE_PHYSICAL_CONDITION_ABNORMAL = "vaccinePhysicalConditionAbnormal"; + public static final String VACCINE_PHYSICAL_CONDITION_ABNORMAL_DETAILS = "vaccinePhysicalConditionAbnormalDetails"; + public static final String ERROR_IN_VACCINE_RECONSTITUTION = "errorInVaccineReconstitution"; + public static final String ERROR_IN_VACCINE_RECONSTITUTION_DETAILS = "errorInVaccineReconstitutionDetails"; + public static final String ERROR_IN_VACCINE_HANDLING = "errorInVaccineHandling"; + public static final String ERROR_IN_VACCINE_HANDLING_DETAILS = "errorInVaccineHandlingDetails"; + public static final String VACCINE_ADMINISTERED_INCORRECTLY = "vaccineAdministeredIncorrectly"; + public static final String VACCINE_ADMINISTERED_INCORRECTLY_DETAILS = "vaccineAdministeredIncorrectlyDetails"; + public static final String NUMBER_IMMUNIZED_FROM_CONCERNED_VACCINE_VIAL = "numberImmunizedFromConcernedVaccineVial"; + public static final String NUMBER_IMMUNIZED_WITH_CONCERNED_VACCINE_IN_SAME_SESSION = "numberImmunizedWithConcernedVaccineInSameSession"; + public static final String NUMBER_IMMUNIZED_CONCERNED_VACCINE_SAME_BATCH_NUMBER_OTHER_LOCATIONS = + "numberImmunizedConcernedVaccineSameBatchNumberOtherLocations"; + public static final String NUMBER_IMMUNIZED_CONCERNED_VACCINE_SAME_BATCH_NUMBER_LOCATION_DETAILS = + "numberImmunizedConcernedVaccineSameBatchNumberLocationDetails"; + public static final String VACCINE_HAS_QUALITY_DEFECT = "vaccineHasQualityDefect"; + public static final String VACCINE_HAS_QUALITY_DEFECT_DETAILS = "vaccineHasQualityDefectDetails"; + public static final String EVENT_IS_A_STRESS_RESPONSE_RELATED_TO_IMMUNIZATION = "eventIsAStressResponseRelatedToImmunization"; + public static final String EVENT_IS_A_STRESS_RESPONSE_RELATED_TO_IMMUNIZATION_DETAILS = "eventIsAStressResponseRelatedToImmunizationDetails"; + public static final String CASE_IS_PART_OF_A_CLUSTER = "caseIsPartOfACluster"; + public static final String CASE_IS_PART_OF_A_CLUSTER_DETAILS = "caseIsPartOfAClusterDetails"; + public static final String NUMBER_OF_CASES_DETECTED_IN_CLUSTER = "numberOfCasesDetectedInCluster"; + public static final String ALL_CASES_IN_CLUSTER_RECEIVED_VACCINE_FROM_SAME_VIAL = "allCasesInClusterReceivedVaccineFromSameVial"; + public static final String ALL_CASES_IN_CLUSTER_RECEIVED_VACCINE_FROM_SAME_VIAL_DETAILS = "allCasesInClusterReceivedVaccineFromSameVialDetails"; + public static final String NUMBER_OF_VIALS_USED_IN_CLUSTER = "numberOfVialsUsedInCluster"; + public static final String NUMBER_OF_VIALS_USED_IN_CLUSTER_DETAILS = "numberOfVialsUsedInClusterDetails"; + public static final String AD_SYRINGES_USED_FOR_IMMUNIZATION = "adSyringesUsedForImmunization"; + public static final String TYPE_OF_SYRINGES_USED = "typeOfSyringesUsed"; + public static final String TYPE_OF_SYRINGES_USED_DETAILS = "typeOfSyringesUsedDetails"; + public static final String SYRINGES_USED_ADDITIONAL_DETAILS = "syringesUsedAdditionalDetails"; + public static final String SAME_RECONSTITUTION_SYRINGE_USED_FOR_MULTIPLE_VIALS_OF_SAME_VACCINE = + "sameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine"; + public static final String SAME_RECONSTITUTION_SYRINGE_USED_FOR_RECONSTITUTING_DIFFERENT_VACCINES = + "sameReconstitutionSyringeUsedForReconstitutingDifferentVaccines"; + public static final String SAME_RECONSTITUTION_SYRINGE_FOR_EACH_VACCINE_VIAL = "sameReconstitutionSyringeForEachVaccineVial"; + public static final String SAME_RECONSTITUTION_SYRINGE_FOR_EACH_VACCINATION = "sameReconstitutionSyringeForEachVaccination"; + public static final String VACCINES_AND_DILUENTS_USED_RECOMMENDED_BY_MANUFACTURER = "vaccinesAndDiluentsUsedRecommendedByManufacturer"; + public static final String RECONSTITUTION_ADDITIONAL_DETAILS = "reconstitutionAdditionalDetails"; + public static final String CORRECT_DOSE_OR_ROUTE = "correctDoseOrRoute"; + public static final String TIME_OF_RECONSTITUTION_MENTIONED_ON_THE_VIAL = "timeOfReconstitutionMentionedOnTheVial"; + public static final String NON_TOUCH_TECHNIQUE_FOLLOWED = "nonTouchTechniqueFollowed"; + public static final String CONTRAINDICATION_SCREENED_PRIOR_TO_VACCINATION = "contraIndicationScreenedPriorToVaccination"; + public static final String NUMBER_OF_AEFI_REPORTED_FROM_VACCINE_DISTRIBUTION_CENTER_LAST_THIRTY_DAYS = + "numberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays"; + public static final String TRAINING_RECEIVED_BY_VACCINATOR = "trainingReceivedByVaccinator"; + public static final String LAST_TRAINING_RECEIVED_BY_VACCINATOR_DATE = "lastTrainingReceivedByVaccinatorDate"; + public static final String INJECTION_TECHNIQUE_ADDITIONAL_DETAILS = "injectionTechniqueAdditionalDetails"; + public static final String VACCINE_STORAGE_REFRIGERATOR_TEMPERATURE_MONITORED = "vaccineStorageRefrigeratorTemperatureMonitored"; + public static final String ANY_STORAGE_TEMPERATURE_DEVIATION_OUTSIDE_TWO_TO_EIGHT_DEGREES = + "anyStorageTemperatureDeviationOutsideTwoToEightDegrees"; + public static final String STORAGE_TEMPERATURE_MONITORING_ADDITIONAL_DETAILS = "storageTemperatureMonitoringAdditionalDetails"; + public static final String CORRECT_PROCEDURE_FOR_STORAGE_FOLLOWED = "correctProcedureForStorageFollowed"; + public static final String ANY_OTHER_ITEM_IN_REFRIGERATOR = "anyOtherItemInRefrigerator"; + public static final String PARTIALLY_USED_RECONSTITUTED_VACCINES_IN_REFRIGERATOR = "partiallyUsedReconstitutedVaccinesInRefrigerator"; + public static final String UNUSABLE_VACCINES_IN_REFRIGERATOR = "unusableVaccinesInRefrigerator"; + public static final String UNUSABLE_DILUENTS_IN_STORE = "unusableDiluentsInStore"; + public static final String VACCINE_STORAGE_POINT_ADDITIONAL_DETAILS = "vaccineStoragePointAdditionalDetails"; + public static final String VACCINE_CARRIER_TYPE = "vaccineCarrierType"; + public static final String VACCINE_CARRIER_TYPE_DETAILS = "vaccineCarrierTypeDetails"; + public static final String VACCINE_CARRIER_SENT_TO_SITE_ON_SAME_DATE_AS_VACCINATION = "vaccineCarrierSentToSiteOnSameDateAsVaccination"; + public static final String VACCINE_CARRIER_RETURNED_FROM_SITE_ON_SAME_DATE_AS_VACCINATION = + "vaccineCarrierReturnedFromSiteOnSameDateAsVaccination"; + public static final String CONDITIONED_ICE_PACK_USED = "conditionedIcepackUsed"; + public static final String VACCINE_TRANSPORTATION_ADDITIONAL_DETAILS = "vaccineTransportationAdditionalDetails"; + public static final String SIMILAR_EVENTS_REPORTED_SAME_PERIOD_AND_LOCALITY = "similarEventsReportedSamePeriodAndLocality"; + public static final String SIMILAR_EVENTS_REPORTED_SAME_PERIOD_AND_LOCALITY_DETAILS = "similarEventsReportedSamePeriodAndLocalityDetails"; + public static final String NUMBER_OF_SIMILAR_EVENTS_REPORTED_SAME_PERIOD_AND_LOCALITY = "numberOfSimilarEventsReportedSamePeriodAndLocality"; + public static final String NUMBER_OF_THOSE_AFFECTED_VACCINATED = "numberOfThoseAffectedVaccinated"; + public static final String NUMBER_OF_THOSE_AFFECTED_NOT_VACCINATED = "numberOfThoseAffectedNotVaccinated"; + public static final String NUMBER_OF_THOSE_AFFECTED_VACCINATED_UNKNOWN = "numberOfThoseAffectedVaccinatedUnknown"; + public static final String COMMUNITY_INVESTIGATION_ADDITIONAL_DETAILS = "communityInvestigationAdditionalDetails"; + public static final String OTHER_INVESTIGATION_FINDINGS = "otherInvestigationFindings"; + public static final String INVESTIGATION_STATUS = "investigationStatus"; + public static final String INVESTIGATION_STATUS_DETAILS = "investigationStatusDetails"; + public static final String AEFI_CLASSIFICATION = "aefiClassification"; + public static final String AEFI_CLASSIFICATION_SUB_TYPE = "aefiClassificationSubType"; + public static final String AEFI_CLASSIFICATION_DETAILS = "aefiClassificationDetails"; + public static final String CAUSALITY = "causality"; + public static final String CAUSALITY_DETAILS = "causalityDetails"; + public static final String INVESTIGATION_COMPLETION_DATE = "investigationCompletionDate"; + + private Aefi aefiReport; + private Long aefiReportId; + private Location address; + private Set vaccinations; + private Vaccination primarySuspectVaccine; + private Date reportDate; + private User reportingUser; + private String externalId; + private Region responsibleRegion; + private District responsibleDistrict; + private Community responsibleCommunity; + private Country country; + private String investigationCaseId; + private PlaceOfVaccination placeOfVaccination; + private String placeOfVaccinationDetails; + private VaccinationActivity vaccinationActivity; + private String vaccinationActivityDetails; + private Facility vaccinationFacility; + private String vaccinationFacilityDetails; + private String reportingOfficerName; + private Facility reportingOfficerFacility; + private String reportingOfficerFacilityDetails; + private String reportingOfficerDesignation; + private String reportingOfficerDepartment; + private Location reportingOfficerAddress; + private String reportingOfficerLandlinePhoneNumber; + private String reportingOfficerMobilePhoneNumber; + private String reportingOfficerEmail; + private Date investigationDate; + private Date formCompletionDate; + private AefiInvestigationStage investigationStage; + private VaccinationSite typeOfSite; + private String typeOfSiteDetails; + private Date keySymptomDateTime; + private Date hospitalizationDate; + private Date reportedToHealthAuthorityDate; + private PatientStatusAtAefiInvestigation statusOnDateOfInvestigation; + private Date deathDateTime; + private YesNoUnknown autopsyDone; + private Date autopsyDate; + private Date autopsyPlannedDateTime; + private YesNoUnknown pastHistoryOfSimilarEvent; + private String pastHistoryOfSimilarEventDetails; + private YesNoUnknown adverseEventAfterPreviousVaccinations; + private String adverseEventAfterPreviousVaccinationsDetails; + private YesNoUnknown historyOfAllergyToVaccineDrugOrFood; + private String historyOfAllergyToVaccineDrugOrFoodDetails; + private YesNoUnknown preExistingIllnessThirtyDaysOrCongenitalDisorder; + private String preExistingIllnessThirtyDaysOrCongenitalDisorderDetails; + private YesNoUnknown historyOfHospitalizationInLastThirtyDaysWithCause; + private String historyOfHospitalizationInLastThirtyDaysWithCauseDetails; + private YesNoUnknown currentlyOnConcomitantMedication; + private String currentlyOnConcomitantMedicationDetails; + private YesNoUnknown familyHistoryOfDiseaseOrAllergy; + private String familyHistoryOfDiseaseOrAllergyDetails; + private Integer numberOfWeeksPregnant; + private BirthTerm birthTerm; + private Float birthWeight; + private DeliveryProcedure deliveryProcedure; + private String deliveryProcedureDetails; + private Set seriousAefiInfoSource; + private String seriousAefiInfoSourceString; + private String seriousAefiInfoSourceDetails; + private String seriousAefiVerbalAutopsyInfoSourceDetails; + private String firstCaregiversName; + private String otherCaregiversNames; + private String otherSourcesWhoProvidedInfo; + private String signsAndSymptomsFromTimeOfVaccination; + private String clinicalDetailsOfficerName; + private String clinicalDetailsOfficerPhoneNumber; + private String clinicalDetailsOfficerEmail; + private String clinicalDetailsOfficerDesignation; + private Date clinicalDetailsDateTime; + private YesNoUnknown patientReceivedMedicalCare; + private String patientReceivedMedicalCareDetails; + private String provisionalOrFinalDiagnosis; + private AefiImmunizationPeriod patientImmunizedPeriod; + private String patientImmunizedPeriodDetails; + private AefiVaccinationPeriod vaccineGivenPeriod; + private String vaccineGivenPeriodDetails; + private YesNoUnknown errorPrescribingVaccine; + private String errorPrescribingVaccineDetails; + private YesNoUnknown vaccineCouldHaveBeenUnSterile; + private String vaccineCouldHaveBeenUnSterileDetails; + private YesNoUnknown vaccinePhysicalConditionAbnormal; + private String vaccinePhysicalConditionAbnormalDetails; + private YesNoUnknown errorInVaccineReconstitution; + private String errorInVaccineReconstitutionDetails; + private YesNoUnknown errorInVaccineHandling; + private String errorInVaccineHandlingDetails; + private YesNoUnknown vaccineAdministeredIncorrectly; + private String vaccineAdministeredIncorrectlyDetails; + private Integer numberImmunizedFromConcernedVaccineVial; + private Integer numberImmunizedWithConcernedVaccineInSameSession; + private Integer numberImmunizedConcernedVaccineSameBatchNumberOtherLocations; + private String numberImmunizedConcernedVaccineSameBatchNumberLocationDetails; + private YesNoUnknown vaccineHasQualityDefect; + private String vaccineHasQualityDefectDetails; + private YesNoUnknown eventIsAStressResponseRelatedToImmunization; + private String eventIsAStressResponseRelatedToImmunizationDetails; + private YesNoUnknown caseIsPartOfACluster; + private String caseIsPartOfAClusterDetails; + private Integer numberOfCasesDetectedInCluster; + private YesNoUnknown allCasesInClusterReceivedVaccineFromSameVial; + private String allCasesInClusterReceivedVaccineFromSameVialDetails; + private Integer numberOfVialsUsedInCluster; + private String numberOfVialsUsedInClusterDetails; + private YesNoUnknown adSyringesUsedForImmunization; + private SyringeType typeOfSyringesUsed; + private String typeOfSyringesUsedDetails; + private String syringesUsedAdditionalDetails; + private YesNoUnknown sameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine; + private YesNoUnknown sameReconstitutionSyringeUsedForReconstitutingDifferentVaccines; + private YesNoUnknown sameReconstitutionSyringeForEachVaccineVial; + private YesNoUnknown sameReconstitutionSyringeForEachVaccination; + private YesNoUnknown vaccinesAndDiluentsUsedRecommendedByManufacturer; + private String reconstitutionAdditionalDetails; + private YesNoUnknown correctDoseOrRoute; + private YesNoUnknown timeOfReconstitutionMentionedOnTheVial; + private YesNoUnknown nonTouchTechniqueFollowed; + private YesNoUnknown contraIndicationScreenedPriorToVaccination; + private Integer numberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays; + private YesNoUnknown trainingReceivedByVaccinator; + private Date lastTrainingReceivedByVaccinatorDate; + private String injectionTechniqueAdditionalDetails; + private YesNoUnknown vaccineStorageRefrigeratorTemperatureMonitored; + private YesNoUnknown anyStorageTemperatureDeviationOutsideTwoToEightDegrees; + private String storageTemperatureMonitoringAdditionalDetails; + private YesNoUnknown correctProcedureForStorageFollowed; + private YesNoUnknown anyOtherItemInRefrigerator; + private YesNoUnknown partiallyUsedReconstitutedVaccinesInRefrigerator; + private YesNoUnknown unusableVaccinesInRefrigerator; + private YesNoUnknown unusableDiluentsInStore; + private String vaccineStoragePointAdditionalDetails; + private VaccineCarrier vaccineCarrierType; + private String vaccineCarrierTypeDetails; + private YesNoUnknown vaccineCarrierSentToSiteOnSameDateAsVaccination; + private YesNoUnknown vaccineCarrierReturnedFromSiteOnSameDateAsVaccination; + private YesNoUnknown conditionedIcepackUsed; + private String vaccineTransportationAdditionalDetails; + private YesNoUnknown similarEventsReportedSamePeriodAndLocality; + private String similarEventsReportedSamePeriodAndLocalityDetails; + private Integer numberOfSimilarEventsReportedSamePeriodAndLocality; + private Integer numberOfThoseAffectedVaccinated; + private Integer numberOfThoseAffectedNotVaccinated; + private Integer numberOfThoseAffectedVaccinatedUnknown; + private String communityInvestigationAdditionalDetails; + private String otherInvestigationFindings; + private AefiInvestigationStatus investigationStatus; + private String investigationStatusDetails; + private AefiClassification aefiClassification; + private AefiClassificationSubType aefiClassificationSubType; + private String aefiClassificationDetails; + private AefiCausality causality; + private String causalityDetails; + private Date investigationCompletionDate; + + public static AefiInvestigation build() { + AefiInvestigation aefiInvestigation = new AefiInvestigation(); + return aefiInvestigation; + } + + @ManyToOne + @JoinColumn(name = "adverseeventsfollowingimmunization_id", nullable = false) + public Aefi getAefiReport() { + return aefiReport; + } + + public void setAefiReport(Aefi aefiReport) { + this.aefiReport = aefiReport; + } + + @Column(name = "adverseeventsfollowingimmunization_id", updatable = false, insertable = false) + public Long getAefiReportId() { + return aefiReportId; + } + + public void setAefiReportId(Long aefiReportId) { + this.aefiReportId = aefiReportId; + } + + @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) + public Location getAddress() { + return address; + } + + public void setAddress(Location address) { + this.address = address; + } + + @ManyToMany(fetch = FetchType.LAZY) + @JoinTable(name = AEFI_INVESTIGATION_VACCINATIONS_TABLE_NAME, + joinColumns = @JoinColumn(name = "adverseeventsfollowingimmunizationinvestigation_id"), + inverseJoinColumns = @JoinColumn(name = "vaccination_id")) + public Set getVaccinations() { + return vaccinations; + } + + public void setVaccinations(Set vaccinations) { + this.vaccinations = vaccinations; + } + + @OneToOne + public Vaccination getPrimarySuspectVaccine() { + return primarySuspectVaccine; + } + + public void setPrimarySuspectVaccine(Vaccination primarySuspectVaccine) { + this.primarySuspectVaccine = primarySuspectVaccine; + } + + @Temporal(TemporalType.TIMESTAMP) + @Column(nullable = false) + public Date getReportDate() { + return reportDate; + } + + public void setReportDate(Date reportDate) { + this.reportDate = reportDate; + } + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(nullable = false) + public User getReportingUser() { + return reportingUser; + } + + public void setReportingUser(User reportingUser) { + this.reportingUser = reportingUser; + } + + public String getExternalId() { + return externalId; + } + + public void setExternalId(String externalId) { + this.externalId = externalId; + } + + @ManyToOne(fetch = FetchType.LAZY) + public Region getResponsibleRegion() { + return responsibleRegion; + } + + public void setResponsibleRegion(Region responsibleRegion) { + this.responsibleRegion = responsibleRegion; + } + + @ManyToOne(fetch = FetchType.LAZY) + public District getResponsibleDistrict() { + return responsibleDistrict; + } + + public void setResponsibleDistrict(District responsibleDistrict) { + this.responsibleDistrict = responsibleDistrict; + } + + @ManyToOne(fetch = FetchType.LAZY) + public Community getResponsibleCommunity() { + return responsibleCommunity; + } + + public void setResponsibleCommunity(Community responsibleCommunity) { + this.responsibleCommunity = responsibleCommunity; + } + + @ManyToOne(fetch = FetchType.LAZY) + public Country getCountry() { + return country; + } + + public void setCountry(Country country) { + this.country = country; + } + + public String getInvestigationCaseId() { + return investigationCaseId; + } + + public void setInvestigationCaseId(String investigationCaseId) { + this.investigationCaseId = investigationCaseId; + } + + @Enumerated(EnumType.STRING) + public PlaceOfVaccination getPlaceOfVaccination() { + return placeOfVaccination; + } + + public void setPlaceOfVaccination(PlaceOfVaccination placeOfVaccination) { + this.placeOfVaccination = placeOfVaccination; + } + + public String getPlaceOfVaccinationDetails() { + return placeOfVaccinationDetails; + } + + public void setPlaceOfVaccinationDetails(String placeOfVaccinationDetails) { + this.placeOfVaccinationDetails = placeOfVaccinationDetails; + } + + @Enumerated(EnumType.STRING) + public VaccinationActivity getVaccinationActivity() { + return vaccinationActivity; + } + + public void setVaccinationActivity(VaccinationActivity vaccinationActivity) { + this.vaccinationActivity = vaccinationActivity; + } + + public String getVaccinationActivityDetails() { + return vaccinationActivityDetails; + } + + public void setVaccinationActivityDetails(String vaccinationActivityDetails) { + this.vaccinationActivityDetails = vaccinationActivityDetails; + } + + @ManyToOne(fetch = FetchType.LAZY) + public Facility getVaccinationFacility() { + return vaccinationFacility; + } + + public void setVaccinationFacility(Facility vaccinationFacility) { + this.vaccinationFacility = vaccinationFacility; + } + + public String getVaccinationFacilityDetails() { + return vaccinationFacilityDetails; + } + + public void setVaccinationFacilityDetails(String vaccinationFacilityDetails) { + this.vaccinationFacilityDetails = vaccinationFacilityDetails; + } + + public String getReportingOfficerName() { + return reportingOfficerName; + } + + public void setReportingOfficerName(String reportingOfficerName) { + this.reportingOfficerName = reportingOfficerName; + } + + @ManyToOne(fetch = FetchType.LAZY) + public Facility getReportingOfficerFacility() { + return reportingOfficerFacility; + } + + public void setReportingOfficerFacility(Facility reportingOfficerFacility) { + this.reportingOfficerFacility = reportingOfficerFacility; + } + + public String getReportingOfficerFacilityDetails() { + return reportingOfficerFacilityDetails; + } + + public void setReportingOfficerFacilityDetails(String reportingOfficerFacilityDetails) { + this.reportingOfficerFacilityDetails = reportingOfficerFacilityDetails; + } + + public String getReportingOfficerDesignation() { + return reportingOfficerDesignation; + } + + public void setReportingOfficerDesignation(String reportingOfficerDesignation) { + this.reportingOfficerDesignation = reportingOfficerDesignation; + } + + public String getReportingOfficerDepartment() { + return reportingOfficerDepartment; + } + + public void setReportingOfficerDepartment(String reportingOfficerDepartment) { + this.reportingOfficerDepartment = reportingOfficerDepartment; + } + + @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @JoinColumn(name = "reportingofficeraddress_id") + public Location getReportingOfficerAddress() { + return reportingOfficerAddress; + } + + public void setReportingOfficerAddress(Location reportingOfficerAddress) { + this.reportingOfficerAddress = reportingOfficerAddress; + } + + public String getReportingOfficerLandlinePhoneNumber() { + return reportingOfficerLandlinePhoneNumber; + } + + public void setReportingOfficerLandlinePhoneNumber(String reportingOfficerLandlinePhoneNumber) { + this.reportingOfficerLandlinePhoneNumber = reportingOfficerLandlinePhoneNumber; + } + + public String getReportingOfficerMobilePhoneNumber() { + return reportingOfficerMobilePhoneNumber; + } + + public void setReportingOfficerMobilePhoneNumber(String reportingOfficerMobilePhoneNumber) { + this.reportingOfficerMobilePhoneNumber = reportingOfficerMobilePhoneNumber; + } + + public String getReportingOfficerEmail() { + return reportingOfficerEmail; + } + + public void setReportingOfficerEmail(String reportingOfficerEmail) { + this.reportingOfficerEmail = reportingOfficerEmail; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getInvestigationDate() { + return investigationDate; + } + + public void setInvestigationDate(Date investigationDate) { + this.investigationDate = investigationDate; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getFormCompletionDate() { + return formCompletionDate; + } + + public void setFormCompletionDate(Date formCompletionDate) { + this.formCompletionDate = formCompletionDate; + } + + @Enumerated(EnumType.STRING) + public AefiInvestigationStage getInvestigationStage() { + return investigationStage; + } + + public void setInvestigationStage(AefiInvestigationStage investigationStage) { + this.investigationStage = investigationStage; + } + + @Enumerated(EnumType.STRING) + public VaccinationSite getTypeOfSite() { + return typeOfSite; + } + + public void setTypeOfSite(VaccinationSite typeOfSite) { + this.typeOfSite = typeOfSite; + } + + @Column + public String getTypeOfSiteDetails() { + return typeOfSiteDetails; + } + + public void setTypeOfSiteDetails(String typeOfSiteDetails) { + this.typeOfSiteDetails = typeOfSiteDetails; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getKeySymptomDateTime() { + return keySymptomDateTime; + } + + public void setKeySymptomDateTime(Date keySymptomDateTime) { + this.keySymptomDateTime = keySymptomDateTime; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getHospitalizationDate() { + return hospitalizationDate; + } + + public void setHospitalizationDate(Date hospitalizationDate) { + this.hospitalizationDate = hospitalizationDate; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getReportedToHealthAuthorityDate() { + return reportedToHealthAuthorityDate; + } + + public void setReportedToHealthAuthorityDate(Date reportedToHealthAuthorityDate) { + this.reportedToHealthAuthorityDate = reportedToHealthAuthorityDate; + } + + @Enumerated(EnumType.STRING) + public PatientStatusAtAefiInvestigation getStatusOnDateOfInvestigation() { + return statusOnDateOfInvestigation; + } + + public void setStatusOnDateOfInvestigation(PatientStatusAtAefiInvestigation statusOnDateOfInvestigation) { + this.statusOnDateOfInvestigation = statusOnDateOfInvestigation; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getDeathDateTime() { + return deathDateTime; + } + + public void setDeathDateTime(Date deathDateTime) { + this.deathDateTime = deathDateTime; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getAutopsyDone() { + return autopsyDone; + } + + public void setAutopsyDone(YesNoUnknown autopsyDone) { + this.autopsyDone = autopsyDone; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getAutopsyDate() { + return autopsyDate; + } + + public void setAutopsyDate(Date autopsyDate) { + this.autopsyDate = autopsyDate; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getAutopsyPlannedDateTime() { + return autopsyPlannedDateTime; + } + + public void setAutopsyPlannedDateTime(Date autopsyPlannedDateTime) { + this.autopsyPlannedDateTime = autopsyPlannedDateTime; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getPastHistoryOfSimilarEvent() { + return pastHistoryOfSimilarEvent; + } + + public void setPastHistoryOfSimilarEvent(YesNoUnknown pastHistoryOfSimilarEvent) { + this.pastHistoryOfSimilarEvent = pastHistoryOfSimilarEvent; + } + + @Column + public String getPastHistoryOfSimilarEventDetails() { + return pastHistoryOfSimilarEventDetails; + } + + public void setPastHistoryOfSimilarEventDetails(String pastHistoryOfSimilarEventDetails) { + this.pastHistoryOfSimilarEventDetails = pastHistoryOfSimilarEventDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getAdverseEventAfterPreviousVaccinations() { + return adverseEventAfterPreviousVaccinations; + } + + public void setAdverseEventAfterPreviousVaccinations(YesNoUnknown adverseEventAfterPreviousVaccinations) { + this.adverseEventAfterPreviousVaccinations = adverseEventAfterPreviousVaccinations; + } + + @Column + public String getAdverseEventAfterPreviousVaccinationsDetails() { + return adverseEventAfterPreviousVaccinationsDetails; + } + + public void setAdverseEventAfterPreviousVaccinationsDetails(String adverseEventAfterPreviousVaccinationsDetails) { + this.adverseEventAfterPreviousVaccinationsDetails = adverseEventAfterPreviousVaccinationsDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getHistoryOfAllergyToVaccineDrugOrFood() { + return historyOfAllergyToVaccineDrugOrFood; + } + + public void setHistoryOfAllergyToVaccineDrugOrFood(YesNoUnknown historyOfAllergyToVaccineDrugOrFood) { + this.historyOfAllergyToVaccineDrugOrFood = historyOfAllergyToVaccineDrugOrFood; + } + + @Column + public String getHistoryOfAllergyToVaccineDrugOrFoodDetails() { + return historyOfAllergyToVaccineDrugOrFoodDetails; + } + + public void setHistoryOfAllergyToVaccineDrugOrFoodDetails(String historyOfAllergyToVaccineDrugOrFoodDetails) { + this.historyOfAllergyToVaccineDrugOrFoodDetails = historyOfAllergyToVaccineDrugOrFoodDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getPreExistingIllnessThirtyDaysOrCongenitalDisorder() { + return preExistingIllnessThirtyDaysOrCongenitalDisorder; + } + + public void setPreExistingIllnessThirtyDaysOrCongenitalDisorder(YesNoUnknown preExistingIllnessThirtyDaysOrCongenitalDisorder) { + this.preExistingIllnessThirtyDaysOrCongenitalDisorder = preExistingIllnessThirtyDaysOrCongenitalDisorder; + } + + @Column + public String getPreExistingIllnessThirtyDaysOrCongenitalDisorderDetails() { + return preExistingIllnessThirtyDaysOrCongenitalDisorderDetails; + } + + public void setPreExistingIllnessThirtyDaysOrCongenitalDisorderDetails(String preExistingIllnessThirtyDaysOrCongenitalDisorderDetails) { + this.preExistingIllnessThirtyDaysOrCongenitalDisorderDetails = preExistingIllnessThirtyDaysOrCongenitalDisorderDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getHistoryOfHospitalizationInLastThirtyDaysWithCause() { + return historyOfHospitalizationInLastThirtyDaysWithCause; + } + + public void setHistoryOfHospitalizationInLastThirtyDaysWithCause(YesNoUnknown historyOfHospitalizationInLastThirtyDaysWithCause) { + this.historyOfHospitalizationInLastThirtyDaysWithCause = historyOfHospitalizationInLastThirtyDaysWithCause; + } + + @Column + public String getHistoryOfHospitalizationInLastThirtyDaysWithCauseDetails() { + return historyOfHospitalizationInLastThirtyDaysWithCauseDetails; + } + + public void setHistoryOfHospitalizationInLastThirtyDaysWithCauseDetails(String historyOfHospitalizationInLastThirtyDaysWithCauseDetails) { + this.historyOfHospitalizationInLastThirtyDaysWithCauseDetails = historyOfHospitalizationInLastThirtyDaysWithCauseDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getCurrentlyOnConcomitantMedication() { + return currentlyOnConcomitantMedication; + } + + public void setCurrentlyOnConcomitantMedication(YesNoUnknown currentlyOnConcomitantMedication) { + this.currentlyOnConcomitantMedication = currentlyOnConcomitantMedication; + } + + @Column + public String getCurrentlyOnConcomitantMedicationDetails() { + return currentlyOnConcomitantMedicationDetails; + } + + public void setCurrentlyOnConcomitantMedicationDetails(String currentlyOnConcomitantMedicationDetails) { + this.currentlyOnConcomitantMedicationDetails = currentlyOnConcomitantMedicationDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getFamilyHistoryOfDiseaseOrAllergy() { + return familyHistoryOfDiseaseOrAllergy; + } + + public void setFamilyHistoryOfDiseaseOrAllergy(YesNoUnknown familyHistoryOfDiseaseOrAllergy) { + this.familyHistoryOfDiseaseOrAllergy = familyHistoryOfDiseaseOrAllergy; + } + + @Column + public String getFamilyHistoryOfDiseaseOrAllergyDetails() { + return familyHistoryOfDiseaseOrAllergyDetails; + } + + public void setFamilyHistoryOfDiseaseOrAllergyDetails(String familyHistoryOfDiseaseOrAllergyDetails) { + this.familyHistoryOfDiseaseOrAllergyDetails = familyHistoryOfDiseaseOrAllergyDetails; + } + + @Column + public Integer getNumberOfWeeksPregnant() { + return numberOfWeeksPregnant; + } + + public void setNumberOfWeeksPregnant(Integer numberOfWeeksPregnant) { + this.numberOfWeeksPregnant = numberOfWeeksPregnant; + } + + @Enumerated(EnumType.STRING) + public BirthTerm getBirthTerm() { + return birthTerm; + } + + public void setBirthTerm(BirthTerm birthTerm) { + this.birthTerm = birthTerm; + } + + @Column + public Float getBirthWeight() { + return birthWeight; + } + + public void setBirthWeight(Float birthWeight) { + this.birthWeight = birthWeight; + } + + @Enumerated(EnumType.STRING) + public DeliveryProcedure getDeliveryProcedure() { + return deliveryProcedure; + } + + public void setDeliveryProcedure(DeliveryProcedure deliveryProcedure) { + this.deliveryProcedure = deliveryProcedure; + } + + @Column + public String getDeliveryProcedureDetails() { + return deliveryProcedureDetails; + } + + public void setDeliveryProcedureDetails(String deliveryProcedureDetails) { + this.deliveryProcedureDetails = deliveryProcedureDetails; + } + + @Transient + public Set getSeriousAefiInfoSource() { + if (seriousAefiInfoSource == null) { + if (StringUtils.isEmpty(seriousAefiInfoSourceString)) { + seriousAefiInfoSource = new HashSet<>(); + } else { + seriousAefiInfoSource = + Arrays.stream(seriousAefiInfoSourceString.split(",")).map(SeriousAefiInfoSource::valueOf).collect(Collectors.toSet()); + } + } + return seriousAefiInfoSource; + } + + public void setSeriousAefiInfoSource(Set seriousAefiInfoSource) { + this.seriousAefiInfoSource = seriousAefiInfoSource; + + if (this.seriousAefiInfoSource == null) { + return; + } + + StringBuilder sb = new StringBuilder(); + seriousAefiInfoSource.stream().forEach(t -> { + sb.append(t.name()); + sb.append(","); + }); + if (sb.length() > 0) { + sb.substring(0, sb.lastIndexOf(",")); + } + seriousAefiInfoSourceString = sb.toString(); + } + + @Column + public String getSeriousAefiInfoSourceString() { + return seriousAefiInfoSourceString; + } + + public void setSeriousAefiInfoSourceString(String seriousAefiInfoSourceString) { + this.seriousAefiInfoSourceString = seriousAefiInfoSourceString; + } + + @Column + public String getSeriousAefiInfoSourceDetails() { + return seriousAefiInfoSourceDetails; + } + + public void setSeriousAefiInfoSourceDetails(String seriousAefiInfoSourceDetails) { + this.seriousAefiInfoSourceDetails = seriousAefiInfoSourceDetails; + } + + @Column + public String getSeriousAefiVerbalAutopsyInfoSourceDetails() { + return seriousAefiVerbalAutopsyInfoSourceDetails; + } + + public void setSeriousAefiVerbalAutopsyInfoSourceDetails(String seriousAefiVerbalAutopsyInfoSourceDetails) { + this.seriousAefiVerbalAutopsyInfoSourceDetails = seriousAefiVerbalAutopsyInfoSourceDetails; + } + + @Column + public String getFirstCaregiversName() { + return firstCaregiversName; + } + + public void setFirstCaregiversName(String firstCaregiversName) { + this.firstCaregiversName = firstCaregiversName; + } + + @Column + public String getOtherCaregiversNames() { + return otherCaregiversNames; + } + + public void setOtherCaregiversNames(String otherCaregiversNames) { + this.otherCaregiversNames = otherCaregiversNames; + } + + @Column + public String getOtherSourcesWhoProvidedInfo() { + return otherSourcesWhoProvidedInfo; + } + + public void setOtherSourcesWhoProvidedInfo(String otherSourcesWhoProvidedInfo) { + this.otherSourcesWhoProvidedInfo = otherSourcesWhoProvidedInfo; + } + + @Column + public String getSignsAndSymptomsFromTimeOfVaccination() { + return signsAndSymptomsFromTimeOfVaccination; + } + + public void setSignsAndSymptomsFromTimeOfVaccination(String signsAndSymptomsFromTimeOfVaccination) { + this.signsAndSymptomsFromTimeOfVaccination = signsAndSymptomsFromTimeOfVaccination; + } + + @Column + public String getClinicalDetailsOfficerName() { + return clinicalDetailsOfficerName; + } + + public void setClinicalDetailsOfficerName(String clinicalDetailsOfficerName) { + this.clinicalDetailsOfficerName = clinicalDetailsOfficerName; + } + + @Column + public String getClinicalDetailsOfficerPhoneNumber() { + return clinicalDetailsOfficerPhoneNumber; + } + + public void setClinicalDetailsOfficerPhoneNumber(String clinicalDetailsOfficerPhoneNumber) { + this.clinicalDetailsOfficerPhoneNumber = clinicalDetailsOfficerPhoneNumber; + } + + @Column + public String getClinicalDetailsOfficerEmail() { + return clinicalDetailsOfficerEmail; + } + + public void setClinicalDetailsOfficerEmail(String clinicalDetailsOfficerEmail) { + this.clinicalDetailsOfficerEmail = clinicalDetailsOfficerEmail; + } + + @Column + public String getClinicalDetailsOfficerDesignation() { + return clinicalDetailsOfficerDesignation; + } + + public void setClinicalDetailsOfficerDesignation(String clinicalDetailsOfficerDesignation) { + this.clinicalDetailsOfficerDesignation = clinicalDetailsOfficerDesignation; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getClinicalDetailsDateTime() { + return clinicalDetailsDateTime; + } + + public void setClinicalDetailsDateTime(Date clinicalDetailsDateTime) { + this.clinicalDetailsDateTime = clinicalDetailsDateTime; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getPatientReceivedMedicalCare() { + return patientReceivedMedicalCare; + } + + public void setPatientReceivedMedicalCare(YesNoUnknown patientReceivedMedicalCare) { + this.patientReceivedMedicalCare = patientReceivedMedicalCare; + } + + @Column + public String getPatientReceivedMedicalCareDetails() { + return patientReceivedMedicalCareDetails; + } + + public void setPatientReceivedMedicalCareDetails(String patientReceivedMedicalCareDetails) { + this.patientReceivedMedicalCareDetails = patientReceivedMedicalCareDetails; + } + + @Column + public String getProvisionalOrFinalDiagnosis() { + return provisionalOrFinalDiagnosis; + } + + public void setProvisionalOrFinalDiagnosis(String provisionalOrFinalDiagnosis) { + this.provisionalOrFinalDiagnosis = provisionalOrFinalDiagnosis; + } + + @Enumerated(EnumType.STRING) + public AefiImmunizationPeriod getPatientImmunizedPeriod() { + return patientImmunizedPeriod; + } + + public void setPatientImmunizedPeriod(AefiImmunizationPeriod patientImmunizedPeriod) { + this.patientImmunizedPeriod = patientImmunizedPeriod; + } + + @Column + public String getPatientImmunizedPeriodDetails() { + return patientImmunizedPeriodDetails; + } + + public void setPatientImmunizedPeriodDetails(String patientImmunizedPeriodDetails) { + this.patientImmunizedPeriodDetails = patientImmunizedPeriodDetails; + } + + @Enumerated(EnumType.STRING) + public AefiVaccinationPeriod getVaccineGivenPeriod() { + return vaccineGivenPeriod; + } + + public void setVaccineGivenPeriod(AefiVaccinationPeriod vaccineGivenPeriod) { + this.vaccineGivenPeriod = vaccineGivenPeriod; + } + + @Column + public String getVaccineGivenPeriodDetails() { + return vaccineGivenPeriodDetails; + } + + public void setVaccineGivenPeriodDetails(String vaccineGivenPeriodDetails) { + this.vaccineGivenPeriodDetails = vaccineGivenPeriodDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getErrorPrescribingVaccine() { + return errorPrescribingVaccine; + } + + public void setErrorPrescribingVaccine(YesNoUnknown errorPrescribingVaccine) { + this.errorPrescribingVaccine = errorPrescribingVaccine; + } + + @Column + public String getErrorPrescribingVaccineDetails() { + return errorPrescribingVaccineDetails; + } + + public void setErrorPrescribingVaccineDetails(String errorPrescribingVaccineDetails) { + this.errorPrescribingVaccineDetails = errorPrescribingVaccineDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getVaccineCouldHaveBeenUnSterile() { + return vaccineCouldHaveBeenUnSterile; + } + + public void setVaccineCouldHaveBeenUnSterile(YesNoUnknown vaccineCouldHaveBeenUnSterile) { + this.vaccineCouldHaveBeenUnSterile = vaccineCouldHaveBeenUnSterile; + } + + @Column + public String getVaccineCouldHaveBeenUnSterileDetails() { + return vaccineCouldHaveBeenUnSterileDetails; + } + + public void setVaccineCouldHaveBeenUnSterileDetails(String vaccineCouldHaveBeenUnSterileDetails) { + this.vaccineCouldHaveBeenUnSterileDetails = vaccineCouldHaveBeenUnSterileDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getVaccinePhysicalConditionAbnormal() { + return vaccinePhysicalConditionAbnormal; + } + + public void setVaccinePhysicalConditionAbnormal(YesNoUnknown vaccinePhysicalConditionAbnormal) { + this.vaccinePhysicalConditionAbnormal = vaccinePhysicalConditionAbnormal; + } + + @Column + public String getVaccinePhysicalConditionAbnormalDetails() { + return vaccinePhysicalConditionAbnormalDetails; + } + + public void setVaccinePhysicalConditionAbnormalDetails(String vaccinePhysicalConditionAbnormalDetails) { + this.vaccinePhysicalConditionAbnormalDetails = vaccinePhysicalConditionAbnormalDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getErrorInVaccineReconstitution() { + return errorInVaccineReconstitution; + } + + public void setErrorInVaccineReconstitution(YesNoUnknown errorInVaccineReconstitution) { + this.errorInVaccineReconstitution = errorInVaccineReconstitution; + } + + @Column + public String getErrorInVaccineReconstitutionDetails() { + return errorInVaccineReconstitutionDetails; + } + + public void setErrorInVaccineReconstitutionDetails(String errorInVaccineReconstitutionDetails) { + this.errorInVaccineReconstitutionDetails = errorInVaccineReconstitutionDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getErrorInVaccineHandling() { + return errorInVaccineHandling; + } + + public void setErrorInVaccineHandling(YesNoUnknown errorInVaccineHandling) { + this.errorInVaccineHandling = errorInVaccineHandling; + } + + @Column + public String getErrorInVaccineHandlingDetails() { + return errorInVaccineHandlingDetails; + } + + public void setErrorInVaccineHandlingDetails(String errorInVaccineHandlingDetails) { + this.errorInVaccineHandlingDetails = errorInVaccineHandlingDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getVaccineAdministeredIncorrectly() { + return vaccineAdministeredIncorrectly; + } + + public void setVaccineAdministeredIncorrectly(YesNoUnknown vaccineAdministeredIncorrectly) { + this.vaccineAdministeredIncorrectly = vaccineAdministeredIncorrectly; + } + + @Column + public String getVaccineAdministeredIncorrectlyDetails() { + return vaccineAdministeredIncorrectlyDetails; + } + + public void setVaccineAdministeredIncorrectlyDetails(String vaccineAdministeredIncorrectlyDetails) { + this.vaccineAdministeredIncorrectlyDetails = vaccineAdministeredIncorrectlyDetails; + } + + @Column + public Integer getNumberImmunizedFromConcernedVaccineVial() { + return numberImmunizedFromConcernedVaccineVial; + } + + public void setNumberImmunizedFromConcernedVaccineVial(Integer numberImmunizedFromConcernedVaccineVial) { + this.numberImmunizedFromConcernedVaccineVial = numberImmunizedFromConcernedVaccineVial; + } + + @Column + public Integer getNumberImmunizedWithConcernedVaccineInSameSession() { + return numberImmunizedWithConcernedVaccineInSameSession; + } + + public void setNumberImmunizedWithConcernedVaccineInSameSession(Integer numberImmunizedWithConcernedVaccineInSameSession) { + this.numberImmunizedWithConcernedVaccineInSameSession = numberImmunizedWithConcernedVaccineInSameSession; + } + + @Column + public Integer getNumberImmunizedConcernedVaccineSameBatchNumberOtherLocations() { + return numberImmunizedConcernedVaccineSameBatchNumberOtherLocations; + } + + public void setNumberImmunizedConcernedVaccineSameBatchNumberOtherLocations( + Integer numberImmunizedConcernedVaccineSameBatchNumberOtherLocations) { + this.numberImmunizedConcernedVaccineSameBatchNumberOtherLocations = numberImmunizedConcernedVaccineSameBatchNumberOtherLocations; + } + + @Column + public String getNumberImmunizedConcernedVaccineSameBatchNumberLocationDetails() { + return numberImmunizedConcernedVaccineSameBatchNumberLocationDetails; + } + + public void setNumberImmunizedConcernedVaccineSameBatchNumberLocationDetails( + String numberImmunizedConcernedVaccineSameBatchNumberLocationDetails) { + this.numberImmunizedConcernedVaccineSameBatchNumberLocationDetails = numberImmunizedConcernedVaccineSameBatchNumberLocationDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getVaccineHasQualityDefect() { + return vaccineHasQualityDefect; + } + + public void setVaccineHasQualityDefect(YesNoUnknown vaccineHasQualityDefect) { + this.vaccineHasQualityDefect = vaccineHasQualityDefect; + } + + @Column + public String getVaccineHasQualityDefectDetails() { + return vaccineHasQualityDefectDetails; + } + + public void setVaccineHasQualityDefectDetails(String vaccineHasQualityDefectDetails) { + this.vaccineHasQualityDefectDetails = vaccineHasQualityDefectDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getEventIsAStressResponseRelatedToImmunization() { + return eventIsAStressResponseRelatedToImmunization; + } + + public void setEventIsAStressResponseRelatedToImmunization(YesNoUnknown eventIsAStressResponseRelatedToImmunization) { + this.eventIsAStressResponseRelatedToImmunization = eventIsAStressResponseRelatedToImmunization; + } + + @Column + public String getEventIsAStressResponseRelatedToImmunizationDetails() { + return eventIsAStressResponseRelatedToImmunizationDetails; + } + + public void setEventIsAStressResponseRelatedToImmunizationDetails(String eventIsAStressResponseRelatedToImmunizationDetails) { + this.eventIsAStressResponseRelatedToImmunizationDetails = eventIsAStressResponseRelatedToImmunizationDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getCaseIsPartOfACluster() { + return caseIsPartOfACluster; + } + + public void setCaseIsPartOfACluster(YesNoUnknown caseIsPartOfACluster) { + this.caseIsPartOfACluster = caseIsPartOfACluster; + } + + @Column + public String getCaseIsPartOfAClusterDetails() { + return caseIsPartOfAClusterDetails; + } + + public void setCaseIsPartOfAClusterDetails(String caseIsPartOfAClusterDetails) { + this.caseIsPartOfAClusterDetails = caseIsPartOfAClusterDetails; + } + + @Column + public Integer getNumberOfCasesDetectedInCluster() { + return numberOfCasesDetectedInCluster; + } + + public void setNumberOfCasesDetectedInCluster(Integer numberOfCasesDetectedInCluster) { + this.numberOfCasesDetectedInCluster = numberOfCasesDetectedInCluster; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getAllCasesInClusterReceivedVaccineFromSameVial() { + return allCasesInClusterReceivedVaccineFromSameVial; + } + + public void setAllCasesInClusterReceivedVaccineFromSameVial(YesNoUnknown allCasesInClusterReceivedVaccineFromSameVial) { + this.allCasesInClusterReceivedVaccineFromSameVial = allCasesInClusterReceivedVaccineFromSameVial; + } + + @Column + public String getAllCasesInClusterReceivedVaccineFromSameVialDetails() { + return allCasesInClusterReceivedVaccineFromSameVialDetails; + } + + public void setAllCasesInClusterReceivedVaccineFromSameVialDetails(String allCasesInClusterReceivedVaccineFromSameVialDetails) { + this.allCasesInClusterReceivedVaccineFromSameVialDetails = allCasesInClusterReceivedVaccineFromSameVialDetails; + } + + @Column + public Integer getNumberOfVialsUsedInCluster() { + return numberOfVialsUsedInCluster; + } + + public void setNumberOfVialsUsedInCluster(Integer numberOfVialsUsedInCluster) { + this.numberOfVialsUsedInCluster = numberOfVialsUsedInCluster; + } + + @Column + public String getNumberOfVialsUsedInClusterDetails() { + return numberOfVialsUsedInClusterDetails; + } + + public void setNumberOfVialsUsedInClusterDetails(String numberOfVialsUsedInClusterDetails) { + this.numberOfVialsUsedInClusterDetails = numberOfVialsUsedInClusterDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getAdSyringesUsedForImmunization() { + return adSyringesUsedForImmunization; + } + + public void setAdSyringesUsedForImmunization(YesNoUnknown adSyringesUsedForImmunization) { + this.adSyringesUsedForImmunization = adSyringesUsedForImmunization; + } + + @Enumerated(EnumType.STRING) + public SyringeType getTypeOfSyringesUsed() { + return typeOfSyringesUsed; + } + + public void setTypeOfSyringesUsed(SyringeType typeOfSyringesUsed) { + this.typeOfSyringesUsed = typeOfSyringesUsed; + } + + @Column + public String getTypeOfSyringesUsedDetails() { + return typeOfSyringesUsedDetails; + } + + public void setTypeOfSyringesUsedDetails(String typeOfSyringesUsedDetails) { + this.typeOfSyringesUsedDetails = typeOfSyringesUsedDetails; + } + + @Column + public String getSyringesUsedAdditionalDetails() { + return syringesUsedAdditionalDetails; + } + + public void setSyringesUsedAdditionalDetails(String syringesUsedAdditionalDetails) { + this.syringesUsedAdditionalDetails = syringesUsedAdditionalDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getSameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine() { + return sameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine; + } + + public void setSameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine( + YesNoUnknown sameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine) { + this.sameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine = sameReconstitutionSyringeUsedForMultipleVialsOfSameVaccine; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getSameReconstitutionSyringeUsedForReconstitutingDifferentVaccines() { + return sameReconstitutionSyringeUsedForReconstitutingDifferentVaccines; + } + + public void setSameReconstitutionSyringeUsedForReconstitutingDifferentVaccines( + YesNoUnknown sameReconstitutionSyringeUsedForReconstitutingDifferentVaccines) { + this.sameReconstitutionSyringeUsedForReconstitutingDifferentVaccines = sameReconstitutionSyringeUsedForReconstitutingDifferentVaccines; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getSameReconstitutionSyringeForEachVaccineVial() { + return sameReconstitutionSyringeForEachVaccineVial; + } + + public void setSameReconstitutionSyringeForEachVaccineVial(YesNoUnknown sameReconstitutionSyringeForEachVaccineVial) { + this.sameReconstitutionSyringeForEachVaccineVial = sameReconstitutionSyringeForEachVaccineVial; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getSameReconstitutionSyringeForEachVaccination() { + return sameReconstitutionSyringeForEachVaccination; + } + + public void setSameReconstitutionSyringeForEachVaccination(YesNoUnknown sameReconstitutionSyringeForEachVaccination) { + this.sameReconstitutionSyringeForEachVaccination = sameReconstitutionSyringeForEachVaccination; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getVaccinesAndDiluentsUsedRecommendedByManufacturer() { + return vaccinesAndDiluentsUsedRecommendedByManufacturer; + } + + public void setVaccinesAndDiluentsUsedRecommendedByManufacturer(YesNoUnknown vaccinesAndDiluentsUsedRecommendedByManufacturer) { + this.vaccinesAndDiluentsUsedRecommendedByManufacturer = vaccinesAndDiluentsUsedRecommendedByManufacturer; + } + + @Column + public String getReconstitutionAdditionalDetails() { + return reconstitutionAdditionalDetails; + } + + public void setReconstitutionAdditionalDetails(String reconstitutionAdditionalDetails) { + this.reconstitutionAdditionalDetails = reconstitutionAdditionalDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getCorrectDoseOrRoute() { + return correctDoseOrRoute; + } + + public void setCorrectDoseOrRoute(YesNoUnknown correctDoseOrRoute) { + this.correctDoseOrRoute = correctDoseOrRoute; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getTimeOfReconstitutionMentionedOnTheVial() { + return timeOfReconstitutionMentionedOnTheVial; + } + + public void setTimeOfReconstitutionMentionedOnTheVial(YesNoUnknown timeOfReconstitutionMentionedOnTheVial) { + this.timeOfReconstitutionMentionedOnTheVial = timeOfReconstitutionMentionedOnTheVial; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getNonTouchTechniqueFollowed() { + return nonTouchTechniqueFollowed; + } + + public void setNonTouchTechniqueFollowed(YesNoUnknown nonTouchTechniqueFollowed) { + this.nonTouchTechniqueFollowed = nonTouchTechniqueFollowed; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getContraIndicationScreenedPriorToVaccination() { + return contraIndicationScreenedPriorToVaccination; + } + + public void setContraIndicationScreenedPriorToVaccination(YesNoUnknown contraIndicationScreenedPriorToVaccination) { + this.contraIndicationScreenedPriorToVaccination = contraIndicationScreenedPriorToVaccination; + } + + @Column + public Integer getNumberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays() { + return numberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays; + } + + public void setNumberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays( + Integer numberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays) { + this.numberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays = numberOfAefiReportedFromVaccineDistributionCenterLastThirtyDays; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getTrainingReceivedByVaccinator() { + return trainingReceivedByVaccinator; + } + + public void setTrainingReceivedByVaccinator(YesNoUnknown trainingReceivedByVaccinator) { + this.trainingReceivedByVaccinator = trainingReceivedByVaccinator; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getLastTrainingReceivedByVaccinatorDate() { + return lastTrainingReceivedByVaccinatorDate; + } + + public void setLastTrainingReceivedByVaccinatorDate(Date lastTrainingReceivedByVaccinatorDate) { + this.lastTrainingReceivedByVaccinatorDate = lastTrainingReceivedByVaccinatorDate; + } + + @Column + public String getInjectionTechniqueAdditionalDetails() { + return injectionTechniqueAdditionalDetails; + } + + public void setInjectionTechniqueAdditionalDetails(String injectionTechniqueAdditionalDetails) { + this.injectionTechniqueAdditionalDetails = injectionTechniqueAdditionalDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getVaccineStorageRefrigeratorTemperatureMonitored() { + return vaccineStorageRefrigeratorTemperatureMonitored; + } + + public void setVaccineStorageRefrigeratorTemperatureMonitored(YesNoUnknown vaccineStorageRefrigeratorTemperatureMonitored) { + this.vaccineStorageRefrigeratorTemperatureMonitored = vaccineStorageRefrigeratorTemperatureMonitored; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getAnyStorageTemperatureDeviationOutsideTwoToEightDegrees() { + return anyStorageTemperatureDeviationOutsideTwoToEightDegrees; + } + + public void setAnyStorageTemperatureDeviationOutsideTwoToEightDegrees(YesNoUnknown anyStorageTemperatureDeviationOutsideTwoToEightDegrees) { + this.anyStorageTemperatureDeviationOutsideTwoToEightDegrees = anyStorageTemperatureDeviationOutsideTwoToEightDegrees; + } + + @Column + public String getStorageTemperatureMonitoringAdditionalDetails() { + return storageTemperatureMonitoringAdditionalDetails; + } + + public void setStorageTemperatureMonitoringAdditionalDetails(String storageTemperatureMonitoringAdditionalDetails) { + this.storageTemperatureMonitoringAdditionalDetails = storageTemperatureMonitoringAdditionalDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getCorrectProcedureForStorageFollowed() { + return correctProcedureForStorageFollowed; + } + + public void setCorrectProcedureForStorageFollowed(YesNoUnknown correctProcedureForStorageFollowed) { + this.correctProcedureForStorageFollowed = correctProcedureForStorageFollowed; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getAnyOtherItemInRefrigerator() { + return anyOtherItemInRefrigerator; + } + + public void setAnyOtherItemInRefrigerator(YesNoUnknown anyOtherItemInRefrigerator) { + this.anyOtherItemInRefrigerator = anyOtherItemInRefrigerator; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getPartiallyUsedReconstitutedVaccinesInRefrigerator() { + return partiallyUsedReconstitutedVaccinesInRefrigerator; + } + + public void setPartiallyUsedReconstitutedVaccinesInRefrigerator(YesNoUnknown partiallyUsedReconstitutedVaccinesInRefrigerator) { + this.partiallyUsedReconstitutedVaccinesInRefrigerator = partiallyUsedReconstitutedVaccinesInRefrigerator; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getUnusableVaccinesInRefrigerator() { + return unusableVaccinesInRefrigerator; + } + + public void setUnusableVaccinesInRefrigerator(YesNoUnknown unusableVaccinesInRefrigerator) { + this.unusableVaccinesInRefrigerator = unusableVaccinesInRefrigerator; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getUnusableDiluentsInStore() { + return unusableDiluentsInStore; + } + + public void setUnusableDiluentsInStore(YesNoUnknown unusableDiluentsInStore) { + this.unusableDiluentsInStore = unusableDiluentsInStore; + } + + @Column + public String getVaccineStoragePointAdditionalDetails() { + return vaccineStoragePointAdditionalDetails; + } + + public void setVaccineStoragePointAdditionalDetails(String vaccineStoragePointAdditionalDetails) { + this.vaccineStoragePointAdditionalDetails = vaccineStoragePointAdditionalDetails; + } + + @Enumerated(EnumType.STRING) + public VaccineCarrier getVaccineCarrierType() { + return vaccineCarrierType; + } + + public void setVaccineCarrierType(VaccineCarrier vaccineCarrierType) { + this.vaccineCarrierType = vaccineCarrierType; + } + + @Column + public String getVaccineCarrierTypeDetails() { + return vaccineCarrierTypeDetails; + } + + public void setVaccineCarrierTypeDetails(String vaccineCarrierTypeDetails) { + this.vaccineCarrierTypeDetails = vaccineCarrierTypeDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getVaccineCarrierSentToSiteOnSameDateAsVaccination() { + return vaccineCarrierSentToSiteOnSameDateAsVaccination; + } + + public void setVaccineCarrierSentToSiteOnSameDateAsVaccination(YesNoUnknown vaccineCarrierSentToSiteOnSameDateAsVaccination) { + this.vaccineCarrierSentToSiteOnSameDateAsVaccination = vaccineCarrierSentToSiteOnSameDateAsVaccination; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getVaccineCarrierReturnedFromSiteOnSameDateAsVaccination() { + return vaccineCarrierReturnedFromSiteOnSameDateAsVaccination; + } + + public void setVaccineCarrierReturnedFromSiteOnSameDateAsVaccination(YesNoUnknown vaccineCarrierReturnedFromSiteOnSameDateAsVaccination) { + this.vaccineCarrierReturnedFromSiteOnSameDateAsVaccination = vaccineCarrierReturnedFromSiteOnSameDateAsVaccination; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getConditionedIcepackUsed() { + return conditionedIcepackUsed; + } + + public void setConditionedIcepackUsed(YesNoUnknown conditionedIcepackUsed) { + this.conditionedIcepackUsed = conditionedIcepackUsed; + } + + @Column + public String getVaccineTransportationAdditionalDetails() { + return vaccineTransportationAdditionalDetails; + } + + public void setVaccineTransportationAdditionalDetails(String vaccineTransportationAdditionalDetails) { + this.vaccineTransportationAdditionalDetails = vaccineTransportationAdditionalDetails; + } + + @Enumerated(EnumType.STRING) + public YesNoUnknown getSimilarEventsReportedSamePeriodAndLocality() { + return similarEventsReportedSamePeriodAndLocality; + } + + public void setSimilarEventsReportedSamePeriodAndLocality(YesNoUnknown similarEventsReportedSamePeriodAndLocality) { + this.similarEventsReportedSamePeriodAndLocality = similarEventsReportedSamePeriodAndLocality; + } + + @Column + public String getSimilarEventsReportedSamePeriodAndLocalityDetails() { + return similarEventsReportedSamePeriodAndLocalityDetails; + } + + public void setSimilarEventsReportedSamePeriodAndLocalityDetails(String similarEventsReportedSamePeriodAndLocalityDetails) { + this.similarEventsReportedSamePeriodAndLocalityDetails = similarEventsReportedSamePeriodAndLocalityDetails; + } + + @Column + public Integer getNumberOfSimilarEventsReportedSamePeriodAndLocality() { + return numberOfSimilarEventsReportedSamePeriodAndLocality; + } + + public void setNumberOfSimilarEventsReportedSamePeriodAndLocality(Integer numberOfSimilarEventsReportedSamePeriodAndLocality) { + this.numberOfSimilarEventsReportedSamePeriodAndLocality = numberOfSimilarEventsReportedSamePeriodAndLocality; + } + + @Column + public Integer getNumberOfThoseAffectedVaccinated() { + return numberOfThoseAffectedVaccinated; + } + + public void setNumberOfThoseAffectedVaccinated(Integer numberOfThoseAffectedVaccinated) { + this.numberOfThoseAffectedVaccinated = numberOfThoseAffectedVaccinated; + } + + @Column + public Integer getNumberOfThoseAffectedNotVaccinated() { + return numberOfThoseAffectedNotVaccinated; + } + + public void setNumberOfThoseAffectedNotVaccinated(Integer numberOfThoseAffectedNotVaccinated) { + this.numberOfThoseAffectedNotVaccinated = numberOfThoseAffectedNotVaccinated; + } + + @Column + public Integer getNumberOfThoseAffectedVaccinatedUnknown() { + return numberOfThoseAffectedVaccinatedUnknown; + } + + public void setNumberOfThoseAffectedVaccinatedUnknown(Integer numberOfThoseAffectedVaccinatedUnknown) { + this.numberOfThoseAffectedVaccinatedUnknown = numberOfThoseAffectedVaccinatedUnknown; + } + + @Column + public String getCommunityInvestigationAdditionalDetails() { + return communityInvestigationAdditionalDetails; + } + + public void setCommunityInvestigationAdditionalDetails(String communityInvestigationAdditionalDetails) { + this.communityInvestigationAdditionalDetails = communityInvestigationAdditionalDetails; + } + + @Column + public String getOtherInvestigationFindings() { + return otherInvestigationFindings; + } + + public void setOtherInvestigationFindings(String otherInvestigationFindings) { + this.otherInvestigationFindings = otherInvestigationFindings; + } + + @Enumerated(EnumType.STRING) + public AefiInvestigationStatus getInvestigationStatus() { + return investigationStatus; + } + + public void setInvestigationStatus(AefiInvestigationStatus investigationStatus) { + this.investigationStatus = investigationStatus; + } + + @Column + public String getInvestigationStatusDetails() { + return investigationStatusDetails; + } + + public void setInvestigationStatusDetails(String investigationStatusDetails) { + this.investigationStatusDetails = investigationStatusDetails; + } + + @Enumerated(EnumType.STRING) + @Column(name = "adverseeventfollowingimmunizationclassification") + public AefiClassification getAefiClassification() { + return aefiClassification; + } + + public void setAefiClassification(AefiClassification aefiClassification) { + this.aefiClassification = aefiClassification; + } + + @Enumerated(EnumType.STRING) + @Column(name = "adverseeventfollowingimmunizationclassificationsubtype") + public AefiClassificationSubType getAefiClassificationSubType() { + return aefiClassificationSubType; + } + + public void setAefiClassificationSubType(AefiClassificationSubType aefiClassificationSubType) { + this.aefiClassificationSubType = aefiClassificationSubType; + } + + @Column(name = "adverseeventfollowingimmunizationclassificationdetails") + public String getAefiClassificationDetails() { + return aefiClassificationDetails; + } + + public void setAefiClassificationDetails(String aefiClassificationDetails) { + this.aefiClassificationDetails = aefiClassificationDetails; + } + + @Column + public AefiCausality getCausality() { + return causality; + } + + public void setCausality(AefiCausality causality) { + this.causality = causality; + } + + @Column + public String getCausalityDetails() { + return causalityDetails; + } + + public void setCausalityDetails(String causalityDetails) { + this.causalityDetails = causalityDetails; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getInvestigationCompletionDate() { + return investigationCompletionDate; + } + + public void setInvestigationCompletionDate(Date investigationCompletionDate) { + this.investigationCompletionDate = investigationCompletionDate; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiInvestigationJoins.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiInvestigationJoins.java new file mode 100644 index 00000000000..03495959759 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiInvestigationJoins.java @@ -0,0 +1,138 @@ +/* + * 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.adverseeventsfollowingimmunization.entity; + +import javax.persistence.criteria.From; +import javax.persistence.criteria.Join; +import javax.persistence.criteria.JoinType; + +import de.symeda.sormas.backend.common.QueryJoins; +import de.symeda.sormas.backend.infrastructure.community.Community; +import de.symeda.sormas.backend.infrastructure.country.Country; +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.location.Location; +import de.symeda.sormas.backend.user.User; +import de.symeda.sormas.backend.vaccination.Vaccination; + +public class AefiInvestigationJoins extends QueryJoins { + + private Join aefi; + + private AefiJoins aefiJoins; + private Join address; + private Join primarySuspectVaccination; + private Join reportingUser; + private Join responsibleRegion; + private Join responsibleDistrict; + private Join responsibleCommunity; + private Join country; + private Join vaccinationFacility; + private Join reportingOfficerFacility; + + public AefiInvestigationJoins(From root) { + super(root); + } + + public Join getAefi() { + return getOrCreate(aefi, AefiInvestigation.AEFI_REPORT, JoinType.LEFT, this::setAefi); + } + + public void setAefi(Join aefi) { + this.aefi = aefi; + } + + public AefiJoins getAefiJoins() { + return getOrCreate(aefiJoins, () -> new AefiJoins(getAefi()), this::setAefiJoins); + } + + public void setAefiJoins(AefiJoins aefiJoins) { + this.aefiJoins = aefiJoins; + } + + public Join getAddress() { + return getOrCreate(address, AefiInvestigation.ADDRESS, JoinType.LEFT, this::setAddress); + } + + public void setAddress(Join address) { + this.address = address; + } + + public Join getPrimarySuspectVaccination() { + return getOrCreate(primarySuspectVaccination, AefiInvestigation.PRIMARY_SUSPECT_VACCINE, JoinType.LEFT, this::setPrimarySuspectVaccination); + } + + public void setPrimarySuspectVaccination(Join primarySuspectVaccination) { + this.primarySuspectVaccination = primarySuspectVaccination; + } + + public Join getReportingUser() { + return getOrCreate(reportingUser, AefiInvestigation.REPORTING_USER, JoinType.LEFT, this::setReportingUser); + } + + public void setReportingUser(Join reportingUser) { + this.reportingUser = reportingUser; + } + + public Join getResponsibleRegion() { + return getOrCreate(responsibleRegion, AefiInvestigation.RESPONSIBLE_REGION, JoinType.LEFT, this::setResponsibleRegion); + } + + public void setResponsibleRegion(Join responsibleRegion) { + this.responsibleRegion = responsibleRegion; + } + + public Join getResponsibleDistrict() { + return getOrCreate(responsibleDistrict, AefiInvestigation.RESPONSIBLE_DISTRICT, JoinType.LEFT, this::setResponsibleDistrict); + } + + public void setResponsibleDistrict(Join responsibleDistrict) { + this.responsibleDistrict = responsibleDistrict; + } + + public Join getResponsibleCommunity() { + return getOrCreate(responsibleCommunity, AefiInvestigation.RESPONSIBLE_COMMUNITY, JoinType.LEFT, this::setResponsibleCommunity); + } + + public void setResponsibleCommunity(Join responsibleCommunity) { + this.responsibleCommunity = responsibleCommunity; + } + + public Join getCountry() { + return getOrCreate(country, AefiInvestigation.COUNTRY, JoinType.LEFT, this::setCountry); + } + + public void setCountry(Join country) { + this.country = country; + } + + public Join getVaccinationFacility() { + return getOrCreate(vaccinationFacility, AefiInvestigation.VACCINATION_FACILITY, JoinType.LEFT, this::setVaccinationFacility); + } + + public void setVaccinationFacility(Join vaccinationFacility) { + this.vaccinationFacility = vaccinationFacility; + } + + public Join getReportingOfficerFacility() { + return getOrCreate(reportingOfficerFacility, AefiInvestigation.REPORTING_OFFICER_FACILITY, JoinType.LEFT, this::setReportingOfficerFacility); + } + + public void setReportingOfficerFacility(Join reportingOfficerFacility) { + this.reportingOfficerFacility = reportingOfficerFacility; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiJoins.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiJoins.java index 33f71570b4f..e1f29ef65fd 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiJoins.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiJoins.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -153,7 +150,7 @@ public void setHealthFacility(Join healthFacility) { } public Join getReporterInstitution() { - return getOrCreate(reporterInstitution, Aefi.REPORTER_INSTITUTION, JoinType.LEFT, this::setReporterInstitution); + return getOrCreate(reporterInstitution, Aefi.REPORTING_OFFICER_FACILITY, JoinType.LEFT, this::setReporterInstitution); } public void setReporterInstitution(Join reporterInstitution) { diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiIndexDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiIndexDtoResultTransformer.java index 73594a78f5f..c2173e84654 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiIndexDtoResultTransformer.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiIndexDtoResultTransformer.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -49,11 +46,11 @@ public Object transformTuple(Object[] objects, String[] strings) { //@formatter:off String adverseEvents = AefiHelper - .buildAdverseEventsString((AdverseEventState) objects[20], (boolean) objects[21], (boolean) objects[22], - (AdverseEventState) objects[23], (SeizureType) objects[24], (AdverseEventState) objects[25], - (AdverseEventState) objects[26], (AdverseEventState) objects[27], (AdverseEventState) objects[28], - (AdverseEventState) objects[29], (AdverseEventState) objects[30], (AdverseEventState) objects[31], - (String) objects[32]); + .buildAdverseEventsString((AdverseEventState) objects[21], (boolean) objects[22], (boolean) objects[23], + (AdverseEventState) objects[24], (SeizureType) objects[25], (AdverseEventState) objects[26], + (AdverseEventState) objects[27], (AdverseEventState) objects[28], (AdverseEventState) objects[29], + (AdverseEventState) objects[30], (AdverseEventState) objects[31], (AdverseEventState) objects[32], + (String) objects[33]); //@formatter:on return new AefiIndexDto( @@ -69,14 +66,15 @@ public Object transformTuple(Object[] objects, String[] strings) { (String) objects[13], (YesNoUnknown) objects[14], (Vaccine) objects[15], - (AefiOutcome) objects[16], - (Date) objects[17], + (String) objects[16], + (AefiOutcome) objects[17], (Date) objects[18], (Date) objects[19], + (Date) objects[20], adverseEvents, - (DeletionReason) objects[33], - (String) objects[34], - (boolean) objects[35]); + (DeletionReason) objects[34], + (String) objects[35], + (boolean) objects[36]); } @Override diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiInvestigationIndexDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiInvestigationIndexDtoResultTransformer.java new file mode 100644 index 00000000000..51e2e29fa19 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiInvestigationIndexDtoResultTransformer.java @@ -0,0 +1,84 @@ +/* + * 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.adverseeventsfollowingimmunization.transformers; + +import java.util.Date; +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiClassification; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationIndexDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationStage; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationStatus; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.PatientStatusAtAefiInvestigation; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.PlaceOfVaccination; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.VaccinationActivity; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.VaccinationSite; +import de.symeda.sormas.api.caze.AgeAndBirthDateDto; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.common.DeletionReason; +import de.symeda.sormas.api.person.ApproximateAgeType; +import de.symeda.sormas.api.person.Sex; + +public class AefiInvestigationIndexDtoResultTransformer implements ResultTransformer { + + @Override + public Object transformTuple(Object[] objects, String[] strings) { + + Integer age = objects[6] != null ? (int) objects[6] : null; + ApproximateAgeType approximateAgeType = (ApproximateAgeType) objects[7]; + Integer birthdateDD = objects[8] != null ? (int) objects[8] : null; + Integer birthdateMM = objects[9] != null ? (int) objects[9] : null; + Integer birthdateYYYY = objects[10] != null ? (int) objects[10] : null; + + return new AefiInvestigationIndexDto( + (String) objects[0], + (String) objects[1], + (String) objects[2], + (Disease) objects[3], + (String) objects[4], + (String) objects[5], + new AgeAndBirthDateDto(age, approximateAgeType, birthdateDD, birthdateMM, birthdateYYYY), + (Sex) objects[11], + (String) objects[12], + (String) objects[13], + (PlaceOfVaccination) objects[14], + (VaccinationActivity) objects[15], + (Date) objects[16], + (Date) objects[17], + (Date) objects[18], + (AefiInvestigationStage) objects[19], + (VaccinationSite) objects[20], + (Date) objects[21], + (Date) objects[22], + (Date) objects[23], + (PatientStatusAtAefiInvestigation) objects[24], + (Vaccine) objects[25], + (String) objects[26], + (AefiInvestigationStatus) objects[27], + (AefiClassification) objects[28], + (DeletionReason) objects[29], + (String) objects[30], + (boolean) objects[31]); + } + + @Override + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiInvestigationListEntryDtoResultTransformer.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiInvestigationListEntryDtoResultTransformer.java new file mode 100644 index 00000000000..e22f380b2d7 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/transformers/AefiInvestigationListEntryDtoResultTransformer.java @@ -0,0 +1,53 @@ +/* + * 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.adverseeventsfollowingimmunization.transformers; + +import java.util.Date; +import java.util.List; + +import org.hibernate.transform.ResultTransformer; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiClassification; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationListEntryDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationStage; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationStatus; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.PatientStatusAtAefiInvestigation; +import de.symeda.sormas.api.caze.Vaccine; + +public class AefiInvestigationListEntryDtoResultTransformer implements ResultTransformer { + + @Override + public Object transformTuple(Object[] objects, String[] strings) { + + return new AefiInvestigationListEntryDto( + (String) objects[0], + (String) objects[1], + (Date) objects[2], + (AefiInvestigationStage) objects[3], + (PatientStatusAtAefiInvestigation) objects[4], + (Vaccine) objects[5], + (String) objects[6], + (String) objects[7], + (Date) objects[8], + (AefiInvestigationStatus) objects[9], + (AefiClassification) objects[10]); + } + + @Override + public List transformList(List list) { + return list; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/dashboard/adverseeventsfollowingimmunization/AefiDashboardFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/dashboard/adverseeventsfollowingimmunization/AefiDashboardFacadeEjb.java index 91471089e92..9a3fc77ec3f 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/dashboard/adverseeventsfollowingimmunization/AefiDashboardFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/dashboard/adverseeventsfollowingimmunization/AefiDashboardFacadeEjb.java @@ -22,6 +22,8 @@ import javax.ejb.LocalBean; import javax.ejb.Stateless; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiClassification; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationStatus; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; import de.symeda.sormas.api.caze.Vaccine; import de.symeda.sormas.api.dashboard.AefiDashboardCriteria; @@ -43,6 +45,17 @@ public Map getAefiCountsByType(AefiDashboardCriteria dashboardCr return aefiDashboardService.getAefiCountsByType(dashboardCriteria); } + @Override + public Map> getAefiInvestigationCountsByInvestigationStatus( + AefiDashboardCriteria dashboardCriteria) { + return aefiDashboardService.getAefiInvestigationCountsByInvestigationStatus(dashboardCriteria); + } + + @Override + public Map> getAefiInvestigationCountsByAefiClassification(AefiDashboardCriteria dashboardCriteria) { + return aefiDashboardService.getAefiInvestigationCountsByAefiClassification(dashboardCriteria); + } + @Override public Map> getAefiCountsByVaccine(AefiDashboardCriteria dashboardCriteria) { return aefiDashboardService.getAefiCountsByVaccine(dashboardCriteria); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/dashboard/adverseeventsfollowingimmunization/AefiDashboardService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/dashboard/adverseeventsfollowingimmunization/AefiDashboardService.java index 41a50bed7a5..213655e0049 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/dashboard/adverseeventsfollowingimmunization/AefiDashboardService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/dashboard/adverseeventsfollowingimmunization/AefiDashboardService.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -49,8 +46,10 @@ import org.slf4j.LoggerFactory; import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiClassification; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiCriteria; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDashboardFilterDateType; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationStatus; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; import de.symeda.sormas.api.caze.Vaccine; import de.symeda.sormas.api.dashboard.AefiDashboardCriteria; @@ -62,6 +61,7 @@ import de.symeda.sormas.api.person.Sex; import de.symeda.sormas.api.utils.DateHelper; import de.symeda.sormas.api.utils.YesNoUnknown; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.AefiInvestigationService; import de.symeda.sormas.backend.adverseeventsfollowingimmunization.AefiQueryContext; import de.symeda.sormas.backend.adverseeventsfollowingimmunization.AefiService; import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AdverseEvents; @@ -97,6 +97,8 @@ public class AefiDashboardService { @EJB private AefiService aefiService; @EJB + private AefiInvestigationService aefiInvestigationService; + @EJB private RegionService regionService; @EJB private DistrictService districtService; @@ -113,6 +115,167 @@ public Map getAefiCountsByType(AefiDashboardCriteria dashboardCr return result; } + public Map> getAefiInvestigationCountsByInvestigationStatus( + AefiDashboardCriteria dashboardCriteria) { + + Map> countsByInvestigationStatus = new HashMap<>(); + + Map defaultValuesMap = new HashMap<>(); + defaultValuesMap.put("total", "0"); + defaultValuesMap.put("percent", "0"); + + for (AefiInvestigationStatus investigationStatus : AefiInvestigationStatus.values()) { + countsByInvestigationStatus.put(investigationStatus, new HashMap<>(defaultValuesMap)); + } + + Disease disease = dashboardCriteria.getDisease(); + RegionReferenceDto regionReference = dashboardCriteria.getRegion(); + DistrictReferenceDto districtReference = dashboardCriteria.getDistrict(); + + String whereConditions = createAefiNativeQueryFilter(dashboardCriteria); + if (StringUtils.isBlank(whereConditions)) { + whereConditions = " aefininvestigation.investigationstatus is not null"; + } else { + whereConditions = whereConditions + " AND aefininvestigation.investigationstatus is not null"; + } + + //@formatter:off + String queryString = "select aefininvestigation.investigationstatus, count(*) as total_status " + + " from adverseeventsfollowingimmunizationinvestigation aefininvestigation" + + " join adverseeventsfollowingimmunization aefi on aefininvestigation.adverseeventsfollowingimmunization_id = aefi.id" + + " join immunization on aefi.immunization_id = immunization.id" + + " where " + whereConditions + + " group by aefininvestigation.investigationstatus"; + //@formatter:on + + Query dataQuery = em.createNativeQuery(queryString); + + if (disease != null) { + dataQuery.setParameter("disease", disease.name()); + } + + if (regionReference != null) { + Region region = regionService.getByReferenceDto(regionReference); + dataQuery.setParameter("responsibleregion_id", region.getId()); + } + + if (districtReference != null) { + District district = districtService.getByReferenceDto(districtReference); + dataQuery.setParameter("responsibledistrict_id", district.getId()); + } + + if (dashboardCriteria.getDateFrom() != null && dashboardCriteria.getDateTo() != null) { + Date dateFrom = DateHelper.getStartOfDay(dashboardCriteria.getDateFrom()); + Date dateTo = DateHelper.getEndOfDay(dashboardCriteria.getDateTo()); + + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + String dateFromStr = DateHelper.formatLocalDate(dateFrom, simpleDateFormat); + String dateToStr = DateHelper.formatLocalDate(dateTo, simpleDateFormat); + + dataQuery.setParameter("dateFrom", dateFromStr); + dataQuery.setParameter("dateTo", dateToStr); + } + + @SuppressWarnings("unchecked") + List resultList = dataQuery.getResultList(); + + int totalInvestigations = 0; + for (Object[] result : resultList) { + totalInvestigations += ((BigInteger) result[1]).intValue(); + } + + int statusTotal; + int statusPercent; + for (Object[] result : resultList) { + statusTotal = ((BigInteger) result[1]).intValue(); + statusPercent = (totalInvestigations == 0) ? 0 : ((int) ((statusTotal * 100.0f) / totalInvestigations)); + countsByInvestigationStatus.get(AefiInvestigationStatus.valueOf((String) result[0])).put("total", String.valueOf(statusTotal)); + countsByInvestigationStatus.get(AefiInvestigationStatus.valueOf((String) result[0])).put("percent", String.valueOf(statusPercent)); + } + + return countsByInvestigationStatus; + } + + public Map> getAefiInvestigationCountsByAefiClassification(AefiDashboardCriteria dashboardCriteria) { + + Map> countsByAefiClassitication = new HashMap<>(); + + Map defaultValuesMap = new HashMap<>(); + defaultValuesMap.put("total", "0"); + defaultValuesMap.put("percent", "0"); + + for (AefiClassification aefiClassification : AefiClassification.values()) { + countsByAefiClassitication.put(aefiClassification, new HashMap<>(defaultValuesMap)); + } + + Disease disease = dashboardCriteria.getDisease(); + RegionReferenceDto regionReference = dashboardCriteria.getRegion(); + DistrictReferenceDto districtReference = dashboardCriteria.getDistrict(); + + String whereConditions = createAefiNativeQueryFilter(dashboardCriteria); + if (StringUtils.isBlank(whereConditions)) { + whereConditions = " aefininvestigation.adverseeventfollowingimmunizationclassification is not null"; + } else { + whereConditions = whereConditions + " AND aefininvestigation.adverseeventfollowingimmunizationclassification is not null"; + } + + //@formatter:off + String queryString = "select aefininvestigation.adverseeventfollowingimmunizationclassification, count(*) as total_classification " + + " from adverseeventsfollowingimmunizationinvestigation aefininvestigation" + + " join adverseeventsfollowingimmunization aefi on aefininvestigation.adverseeventsfollowingimmunization_id = aefi.id" + + " join immunization on aefi.immunization_id = immunization.id" + + " where " + whereConditions + + " group by aefininvestigation.adverseeventfollowingimmunizationclassification"; + //@formatter:on + + Query dataQuery = em.createNativeQuery(queryString); + + if (disease != null) { + dataQuery.setParameter("disease", disease.name()); + } + + if (regionReference != null) { + Region region = regionService.getByReferenceDto(regionReference); + dataQuery.setParameter("responsibleregion_id", region.getId()); + } + + if (districtReference != null) { + District district = districtService.getByReferenceDto(districtReference); + dataQuery.setParameter("responsibledistrict_id", district.getId()); + } + + if (dashboardCriteria.getDateFrom() != null && dashboardCriteria.getDateTo() != null) { + Date dateFrom = DateHelper.getStartOfDay(dashboardCriteria.getDateFrom()); + Date dateTo = DateHelper.getEndOfDay(dashboardCriteria.getDateTo()); + + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + String dateFromStr = DateHelper.formatLocalDate(dateFrom, simpleDateFormat); + String dateToStr = DateHelper.formatLocalDate(dateTo, simpleDateFormat); + + dataQuery.setParameter("dateFrom", dateFromStr); + dataQuery.setParameter("dateTo", dateToStr); + } + + @SuppressWarnings("unchecked") + List resultList = dataQuery.getResultList(); + + int totalInvestigations = 0; + for (Object[] result : resultList) { + totalInvestigations += ((BigInteger) result[1]).intValue(); + } + + int classificationTotal; + int classificationPercent; + for (Object[] result : resultList) { + classificationTotal = ((BigInteger) result[1]).intValue(); + classificationPercent = (totalInvestigations == 0) ? 0 : ((int) ((classificationTotal * 100.0f) / totalInvestigations)); + countsByAefiClassitication.get(AefiClassification.valueOf((String) result[0])).put("total", String.valueOf(classificationTotal)); + countsByAefiClassitication.get(AefiClassification.valueOf((String) result[0])).put("percent", String.valueOf(classificationPercent)); + } + + return countsByAefiClassitication; + } + public Map> getAefiCountsByVaccine(AefiDashboardCriteria dashboardCriteria) { Map> countsByVaccine = new HashMap<>(); @@ -349,7 +512,7 @@ public AefiChartData getAefiEventsByGenderChartData(AefiDashboardCriteria dashbo if (!resultList.isEmpty()) { Object[] firstResult = resultList.get(0); - maleSeries.addData(firstResult[1].toString()); + maleSeries.addData("-" + firstResult[1].toString()); femaleSeries.addData(firstResult[2].toString()); } else { maleSeries.addData("0"); @@ -500,10 +663,12 @@ private String createAefiNativeQueryFilter(AefiDashboardCriteria criteria) { switch (aefiDashboardFilterDateType) { case REPORT_DATE: - whereConditions.add("(aefi.reportdate >= cast(:dateFrom as timestamp) and aefi.reportdate <= cast(:dateTo as timestamp))"); + whereConditions + .add("(cast(aefi.reportdate as date) >= cast(:dateFrom as date) and cast(aefi.reportdate as date) <= cast(:dateTo as date))"); break; case START_DATE: - whereConditions.add("(aefi.startdatetime >= cast(:dateFrom as timestamp) and aefi.startdatetime <= cast(:dateTo as timestamp))"); + whereConditions.add( + "(cast(aefi.startdatetime as date) >= cast(:dateFrom as date) and cast(aefi.startdatetime as date) <= cast(:dateTo as date))"); break; default: throw new RuntimeException("Unhandled date type [" + aefiDashboardFilterDateType + "]"); diff --git a/sormas-backend/src/main/resources/META-INF/persistence.xml b/sormas-backend/src/main/resources/META-INF/persistence.xml index e0dd26ad9b2..002827d82d3 100644 --- a/sormas-backend/src/main/resources/META-INF/persistence.xml +++ b/sormas-backend/src/main/resources/META-INF/persistence.xml @@ -88,12 +88,12 @@ de.symeda.sormas.backend.externalmessage.labmessage.SampleReport de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.Aefi de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AdverseEvents - de.symeda.sormas.backend.specialcaseaccess.SpecialCaseAccess + de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AefiInvestigation de.symeda.sormas.backend.specialcaseaccess.SpecialCaseAccess de.symeda.sormas.backend.selfreport.SelfReport - true + true ENABLE_SELECTIVE CALLBACK diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/ControllerProvider.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/ControllerProvider.java index 7e2f4581fc1..1e8db100332 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/ControllerProvider.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/ControllerProvider.java @@ -19,6 +19,7 @@ import de.symeda.sormas.ui.action.ActionController; import de.symeda.sormas.ui.adverseeventsfollowingimmunization.AefiController; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.AefiInvestigationController; import de.symeda.sormas.ui.campaign.CampaignController; import de.symeda.sormas.ui.caze.CaseController; import de.symeda.sormas.ui.caze.surveillancereport.SurveillanceReportController; @@ -91,6 +92,7 @@ public class ControllerProvider extends BaseControllerProvider { private final TravelEntryController travelEntryController; private final ImmunizationController immunizationController; private final AefiController aefiController; + private final AefiInvestigationController aefiInvestigationController; private final VaccinationController vaccinationController; private final ArchivingController archivingController; private final DeleteRestoreController deleteRestoreController; @@ -135,6 +137,7 @@ public ControllerProvider() { travelEntryController = new TravelEntryController(); immunizationController = new ImmunizationController(); aefiController = new AefiController(); + aefiInvestigationController = new AefiInvestigationController(); vaccinationController = new VaccinationController(); archivingController = new ArchivingController(); deleteRestoreController = new DeleteRestoreController(); @@ -271,6 +274,10 @@ public static AefiController getAefiController() { return get().aefiController; } + public static AefiInvestigationController getAefiInvestigationController() { + return get().aefiInvestigationController; + } + public static VaccinationController getVaccinationController() { return get().vaccinationController; } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiDataView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiDataView.java new file mode 100644 index 00000000000..d021b2ac3b0 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiDataView.java @@ -0,0 +1,113 @@ +/* + * 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.ui.adverseeventsfollowingimmunization; + +import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; + +import de.symeda.sormas.api.EditPermissionFacade; +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiReferenceDto; +import de.symeda.sormas.api.i18n.Captions; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.immunization.ImmunizationDto; +import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.SubMenu; +import de.symeda.sormas.ui.immunization.ImmunizationDataView; +import de.symeda.sormas.ui.immunization.ImmunizationPersonView; +import de.symeda.sormas.ui.utils.AbstractEditAllowedDetailView; + +public abstract class AbstractAefiDataView extends AbstractEditAllowedDetailView { + + public static final String ROOT_VIEW_NAME = AefiView.VIEW_NAME; + + protected AbstractAefiDataView(String viewName) { + super(viewName); + } + + @Override + protected AefiReferenceDto getReferenceByUuid(String uuid) { + + final AefiReferenceDto reference; + + boolean isCreateAction = ControllerProvider.getAefiController().isCreateAction(uuid); + + if (isCreateAction) { + reference = new AefiReferenceDto(); + reference.setUuid(DataHelper.createUuid()); + } else { + if (FacadeProvider.getAefiFacade().exists(uuid)) { + reference = FacadeProvider.getAefiFacade().getReferenceByUuid(uuid); + } else { + reference = null; + } + } + return reference; + } + + @Override + protected String getRootViewName() { + return ROOT_VIEW_NAME; + } + + @Override + protected void initView(String params) { + + } + + @Override + protected EditPermissionFacade getEditPermissionFacade() { + return FacadeProvider.getAefiFacade(); + } + + @Override + public void enter(ViewChangeEvent event) { + + super.enter(event); + initOrRedirect(event); + } + + @Override + public void refreshMenu(SubMenu menu, String params) { + + if (!findReferenceByParams(params)) { + return; + } + + boolean isCreateAction = ControllerProvider.getAefiController().isCreateAction(params); + + String immunizationUuid = ""; + if (isCreateAction) { + immunizationUuid = ControllerProvider.getAefiController().getCreateActionImmunizationUuid(params); + } else { + AefiDto aefiDto = FacadeProvider.getAefiFacade().getByUuid(params); + immunizationUuid = aefiDto.getImmunization().getUuid(); + } + + menu.removeAllViews(); + menu.addView(AefiView.VIEW_NAME, I18nProperties.getCaption(Captions.aefiAefiList)); + menu.addView(ImmunizationDataView.VIEW_NAME, I18nProperties.getCaption(ImmunizationDto.I18N_PREFIX), immunizationUuid); + menu.addView( + ImmunizationPersonView.VIEW_NAME, + I18nProperties.getPrefixCaption(ImmunizationDto.I18N_PREFIX, ImmunizationDto.PERSON), + immunizationUuid); + menu.addView(AefiDataView.VIEW_NAME, I18nProperties.getCaption(Captions.aefiAefiDataView), params); + + setMainHeaderComponent( + ControllerProvider.getAefiController().getAefiViewTitleLayout(getReference().getUuid(), immunizationUuid, isCreateAction)); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiInvestigationDataView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiInvestigationDataView.java new file mode 100644 index 00000000000..3b2ffe2cb7b --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiInvestigationDataView.java @@ -0,0 +1,122 @@ +/* + * 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.ui.adverseeventsfollowingimmunization; + +import com.vaadin.navigator.ViewChangeListener; + +import de.symeda.sormas.api.EditPermissionFacade; +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationReferenceDto; +import de.symeda.sormas.api.i18n.Captions; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.immunization.ImmunizationDto; +import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.SubMenu; +import de.symeda.sormas.ui.immunization.ImmunizationDataView; +import de.symeda.sormas.ui.immunization.ImmunizationPersonView; +import de.symeda.sormas.ui.utils.AbstractEditAllowedDetailView; + +public class AbstractAefiInvestigationDataView extends AbstractEditAllowedDetailView { + + public static final String ROOT_VIEW_NAME = AefiInvestigationView.VIEW_NAME; + + protected AbstractAefiInvestigationDataView(String viewName) { + super(viewName); + } + + @Override + protected AefiInvestigationReferenceDto getReferenceByUuid(String uuid) { + + final AefiInvestigationReferenceDto reference; + + boolean isCreateAction = ControllerProvider.getAefiInvestigationController().isCreateAction(uuid); + + if (isCreateAction) { + reference = new AefiInvestigationReferenceDto(); + reference.setUuid(DataHelper.createUuid()); + } else { + if (FacadeProvider.getAefiInvestigationFacade().exists(uuid)) { + reference = FacadeProvider.getAefiInvestigationFacade().getReferenceByUuid(uuid); + } else { + reference = null; + } + } + return reference; + } + + @Override + protected String getRootViewName() { + return ROOT_VIEW_NAME; + } + + @Override + protected void initView(String params) { + + } + + @Override + protected EditPermissionFacade getEditPermissionFacade() { + return FacadeProvider.getAefiInvestigationFacade(); + } + + @Override + public void enter(ViewChangeListener.ViewChangeEvent event) { + + super.enter(event); + initOrRedirect(event); + } + + @Override + public void refreshMenu(SubMenu menu, String params) { + + if (!findReferenceByParams(params)) { + return; + } + + boolean isCreateAction = ControllerProvider.getAefiInvestigationController().isCreateAction(params); + + String aefiReportUuid = ""; + String immunizationUuid = ""; + if (isCreateAction) { + aefiReportUuid = ControllerProvider.getAefiInvestigationController().getCreateActionAefiReportUuid(params); + AefiDto aefiDto = FacadeProvider.getAefiFacade().getByUuid(aefiReportUuid); + immunizationUuid = aefiDto.getImmunization().getUuid(); + } else { + AefiInvestigationDto aefiInvestigationDto = FacadeProvider.getAefiInvestigationFacade().getByUuid(params); + aefiReportUuid = aefiInvestigationDto.getAefiReport().getUuid(); + + AefiDto aefiDto = FacadeProvider.getAefiFacade().getByUuid(aefiReportUuid); + immunizationUuid = aefiDto.getImmunization().getUuid(); + } + + menu.removeAllViews(); + menu.addView(AefiView.VIEW_NAME, I18nProperties.getCaption(Captions.aefiAefiList)); + menu.addView(ImmunizationDataView.VIEW_NAME, I18nProperties.getCaption(ImmunizationDto.I18N_PREFIX), immunizationUuid); + menu.addView( + ImmunizationPersonView.VIEW_NAME, + I18nProperties.getPrefixCaption(ImmunizationDto.I18N_PREFIX, ImmunizationDto.PERSON), + immunizationUuid); + menu.addView(AefiDataView.VIEW_NAME, I18nProperties.getCaption(Captions.aefiAefiDataView), aefiReportUuid); + menu.addView(AefiInvestigationDataView.VIEW_NAME, I18nProperties.getCaption(Captions.aefiAefiInvestigationDataView), params); + + setMainHeaderComponent( + ControllerProvider.getAefiInvestigationController() + .getAefiInvestigationViewTitleLayout(getReference().getUuid(), aefiReportUuid, immunizationUuid, isCreateAction)); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiView.java index 3e082e0657a..4499d4a7278 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiView.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiView.java @@ -1,115 +1,38 @@ /* * 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.ui.adverseeventsfollowingimmunization; -import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; +import com.vaadin.ui.Component; -import de.symeda.sormas.api.EditPermissionFacade; -import de.symeda.sormas.api.FacadeProvider; -import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; -import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiReferenceDto; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; -import de.symeda.sormas.api.immunization.ImmunizationDto; -import de.symeda.sormas.api.utils.DataHelper; -import de.symeda.sormas.ui.ControllerProvider; import de.symeda.sormas.ui.SubMenu; -import de.symeda.sormas.ui.immunization.ImmunizationDataView; -import de.symeda.sormas.ui.immunization.ImmunizationPersonView; -import de.symeda.sormas.ui.utils.AbstractEditAllowedDetailView; +import de.symeda.sormas.ui.utils.AbstractSubNavigationView; -public abstract class AbstractAefiView extends AbstractEditAllowedDetailView { - - public static final String ROOT_VIEW_NAME = AefiView.VIEW_NAME; +public class AbstractAefiView extends AbstractSubNavigationView { protected AbstractAefiView(String viewName) { super(viewName); } - @Override - protected AefiReferenceDto getReferenceByUuid(String uuid) { - - final AefiReferenceDto reference; - - boolean isCreateAction = ControllerProvider.getAefiController().isCreateAction(uuid); - - if (isCreateAction) { - reference = new AefiReferenceDto(); - reference.setUuid(DataHelper.createUuid()); - } else { - if (FacadeProvider.getAefiFacade().exists(uuid)) { - reference = FacadeProvider.getAefiFacade().getReferenceByUuid(uuid); - } else { - reference = null; - } - } - return reference; - } - - @Override - protected String getRootViewName() { - return ROOT_VIEW_NAME; - } - - @Override - protected void initView(String params) { - - } - - @Override - protected EditPermissionFacade getEditPermissionFacade() { - return FacadeProvider.getAefiFacade(); - } - - @Override - public void enter(ViewChangeEvent event) { - - super.enter(event); - initOrRedirect(event); - } - @Override public void refreshMenu(SubMenu menu, String params) { - - if (!findReferenceByParams(params)) { - return; - } - - boolean isCreateAction = ControllerProvider.getAefiController().isCreateAction(params); - - String immunizationUuid = ""; - if (isCreateAction) { - immunizationUuid = ControllerProvider.getAefiController().getCreateActionImmunizationUuid(params); - } else { - AefiDto aefiDto = FacadeProvider.getAefiFacade().getByUuid(params); - immunizationUuid = aefiDto.getImmunization().getUuid(); - } - menu.removeAllViews(); - menu.addView(AefiView.VIEW_NAME, I18nProperties.getCaption(Captions.aefiAefiList)); - menu.addView(ImmunizationDataView.VIEW_NAME, I18nProperties.getCaption(ImmunizationDto.I18N_PREFIX), immunizationUuid); - menu.addView( - ImmunizationPersonView.VIEW_NAME, - I18nProperties.getPrefixCaption(ImmunizationDto.I18N_PREFIX, ImmunizationDto.PERSON), - immunizationUuid); - menu.addView(AefiDataView.VIEW_NAME, I18nProperties.getCaption(Captions.aefiAefiDataView), params); - setMainHeaderComponent(ControllerProvider.getAefiController().getAefiViewTitleLayout(params, immunizationUuid, isCreateAction)); + menu.addView(AefiView.VIEW_NAME, I18nProperties.getCaption(Captions.aefiAefiList), params); + menu.addView(AefiInvestigationView.VIEW_NAME, I18nProperties.getCaption(Captions.aefiAefiInvestigationList), params); } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiController.java index a3200c25c27..7a6f3ef13fe 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiController.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiController.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -28,6 +25,7 @@ import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; import de.symeda.sormas.api.common.DeletionReason; import de.symeda.sormas.api.deletionconfiguration.DeletionInfoDto; import de.symeda.sormas.api.i18n.I18nProperties; @@ -36,6 +34,7 @@ import de.symeda.sormas.api.person.PersonDto; import de.symeda.sormas.api.user.UserRight; import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.api.utils.YesNoUnknown; import de.symeda.sormas.api.vaccination.VaccinationDto; import de.symeda.sormas.ui.ControllerProvider; import de.symeda.sormas.ui.SormasUI; @@ -44,8 +43,10 @@ import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.form.AefiDataForm; import de.symeda.sormas.ui.utils.ArchiveHandlers; import de.symeda.sormas.ui.utils.CommitDiscardWrapperComponent; +import de.symeda.sormas.ui.utils.CssStyles; import de.symeda.sormas.ui.utils.VaadinUiUtil; import de.symeda.sormas.ui.utils.components.automaticdeletion.DeletionLabel; +import de.symeda.sormas.ui.utils.components.page.title.RowLayout; import de.symeda.sormas.ui.utils.components.page.title.TitleLayout; import de.symeda.sormas.ui.utils.components.page.title.TitleLayoutHelper; @@ -53,9 +54,9 @@ public class AefiController { public void registerViews(Navigator navigator) { navigator.addView(AefiView.VIEW_NAME, AefiView.class); - //navigator.addView(ImmunizationDataView.VIEW_NAME, ImmunizationDataView.class); - //navigator.addView(ImmunizationPersonView.VIEW_NAME, ImmunizationPersonView.class); navigator.addView(AefiDataView.VIEW_NAME, AefiDataView.class); + navigator.addView(AefiInvestigationView.VIEW_NAME, AefiInvestigationView.class); + navigator.addView(AefiInvestigationDataView.VIEW_NAME, AefiInvestigationDataView.class); } public void selectPrimarySuspectVaccination(AefiDto aefiDto, Consumer commitCallback) { @@ -67,6 +68,7 @@ public void selectPrimarySuspectVaccination(AefiDto aefiDto, Consumer component = new CommitDiscardWrapperComponent<>(selectionField); component.addCommitListener(() -> { + VaccinationDto selectedVaccination = selectionField.getValue(); if (selectedVaccination != null) { aefiDto.setPrimarySuspectVaccine(selectedVaccination); @@ -78,7 +80,7 @@ public void selectPrimarySuspectVaccination(AefiDto aefiDto, Consumer component.getCommitButton().setEnabled(commitAllowed)); - VaadinUiUtil.showModalPopupWindow(component, I18nProperties.getString(Strings.headingAefiPickPrimarySuspectVaccine)); + VaadinUiUtil.showModalPopupWindow(component, I18nProperties.getString(Strings.headingAefiSelectPrimarySuspectVaccine)); } public void navigateToAefi(String uuid) { @@ -162,18 +164,30 @@ public CommitDiscardWrapperComponent getAefiDataEditComponent( public TitleLayout getAefiViewTitleLayout(String aefiUuid, String immunizationUuid, boolean isCreateAction) { + TitleLayout titleLayout = new TitleLayout(); + if (!isCreateAction) { AefiDto aefiDto = findAefi(aefiUuid); immunizationUuid = aefiDto.getImmunization().getUuid(); - } - TitleLayout titleLayout = new TitleLayout(); + if (aefiDto.getSerious() == YesNoUnknown.YES) { + RowLayout aefiTypeLayout = new RowLayout(); + aefiTypeLayout.addToLayout(AefiType.SERIOUS.toString(), CssStyles.LABEL_CRITICAL); + titleLayout.addRow(aefiTypeLayout); + } else { + titleLayout.addRow(AefiType.NON_SERIOUS.toString()); + } + } - String shortUuid = DataHelper.getShortUuid(immunizationUuid); + String shortUuid = DataHelper.getShortUuid(aefiUuid); ImmunizationDto immunizationDto = FacadeProvider.getImmunizationFacade().getByUuid(immunizationUuid); PersonDto person = FacadeProvider.getPersonFacade().getByUuid(immunizationDto.getPerson().getUuid()); StringBuilder mainRowText = TitleLayoutHelper.buildPersonString(person); - mainRowText.append(mainRowText.length() > 0 ? " (" + shortUuid + ")" : shortUuid); + + if (!StringUtils.isBlank(shortUuid)) { + mainRowText.append(mainRowText.length() > 0 ? " (" + shortUuid + ")" : shortUuid); + } + titleLayout.addMainRow(mainRowText.toString()); return titleLayout; @@ -189,7 +203,7 @@ public boolean isCreateAction(String params) { public String getCreateActionImmunizationUuid(String params) { return StringUtils.contains(params, "/") - ? StringUtils.substringBetween(params, "/", "/") - : StringUtils.substringBetween(params, "immunization", "create"); + ? StringUtils.substringBetween(params, "immunization/", "/adverseevent/create") + : StringUtils.substringBetween(params, "immunization", "adverseeventcreate"); } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiDataView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiDataView.java index adc07afc106..44444a3b191 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiDataView.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiDataView.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -24,13 +21,16 @@ import de.symeda.sormas.api.EditPermissionType; import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationListCriteria; 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.person.PersonDto; import de.symeda.sormas.api.user.UserRight; +import de.symeda.sormas.api.utils.YesNoUnknown; import de.symeda.sormas.ui.ControllerProvider; import de.symeda.sormas.ui.UserProvider; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.aefiinvestigationlink.AefiInvestigationListComponent; import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.form.AefiDataForm; import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.information.AefiImmunizationInfo; import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.information.AefiPersonInfo; @@ -39,11 +39,10 @@ import de.symeda.sormas.ui.utils.DetailSubComponentWrapper; import de.symeda.sormas.ui.utils.LayoutWithSidePanel; -public class AefiDataView extends AbstractAefiView { +public class AefiDataView extends AbstractAefiDataView { public static final String VIEW_NAME = ROOT_VIEW_NAME + "/data"; - public static final String ADVERSE_EVENT_LOC = "adverseEventLoc"; public static final String PERSON_LOC = "personLoc"; public static final String IMMUNIZATION_LOC = "immunizationLoc"; public static final String INVESTIGATIONS_LOC = "investigationsLoc"; @@ -118,6 +117,18 @@ protected void initView(String params) { } } + if (!isCreateAction + && (aefi.getSerious() == YesNoUnknown.YES) + && currentUser.hasAllUserRights(UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW)) { + + AefiInvestigationListCriteria listCriteria = new AefiInvestigationListCriteria.Builder(getReference()).build(); + AefiInvestigationListComponent aefiInvestigationListComponent = + new AefiInvestigationListComponent(listCriteria, this::showUnsavedChangesPopup, isEditAllowed(), isCreateAction); + CssStyles.style(aefiInvestigationListComponent, CssStyles.VIEW_SECTION, CssStyles.VSPACE_TOP_3); + + layout.addSidePanelComponent(aefiInvestigationListComponent, INVESTIGATIONS_LOC); + } + if (!isCreateAction) { final String uuid = aefi.getUuid(); final EditPermissionType aefiEditAllowed = FacadeProvider.getAefiFacade().getEditPermissionType(uuid); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationController.java new file mode 100644 index 00000000000..0c44bb7a702 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationController.java @@ -0,0 +1,229 @@ +/* + * 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.ui.adverseeventsfollowingimmunization; + +import java.util.function.Consumer; + +import org.apache.commons.lang3.StringUtils; + +import com.vaadin.navigator.Navigator; +import com.vaadin.server.Sizeable; +import com.vaadin.ui.Notification; + +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; +import de.symeda.sormas.api.common.DeletionReason; +import de.symeda.sormas.api.deletionconfiguration.DeletionInfoDto; +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.immunization.ImmunizationDto; +import de.symeda.sormas.api.person.PersonDto; +import de.symeda.sormas.api.user.UserRight; +import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.api.utils.YesNoUnknown; +import de.symeda.sormas.api.vaccination.VaccinationDto; +import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.SormasUI; +import de.symeda.sormas.ui.UserProvider; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.fields.vaccines.AefiPrimarySuspectVaccinationSelectionField; +import de.symeda.sormas.ui.utils.ArchiveHandlers; +import de.symeda.sormas.ui.utils.CommitDiscardWrapperComponent; +import de.symeda.sormas.ui.utils.CssStyles; +import de.symeda.sormas.ui.utils.VaadinUiUtil; +import de.symeda.sormas.ui.utils.components.automaticdeletion.DeletionLabel; +import de.symeda.sormas.ui.utils.components.page.title.RowLayout; +import de.symeda.sormas.ui.utils.components.page.title.TitleLayout; +import de.symeda.sormas.ui.utils.components.page.title.TitleLayoutHelper; + +public class AefiInvestigationController { + + public void registerViews(Navigator navigator) { + } + + public void selectPrimarySuspectVaccination(AefiInvestigationDto aefiInvestigationDto, Consumer commitCallback) { + + AefiPrimarySuspectVaccinationSelectionField selectionField = + new AefiPrimarySuspectVaccinationSelectionField(aefiInvestigationDto.getVaccinations(), aefiInvestigationDto.getPrimarySuspectVaccine()); + selectionField.setWidth(1024, Sizeable.Unit.PIXELS); + + final CommitDiscardWrapperComponent component = + new CommitDiscardWrapperComponent<>(selectionField); + component.addCommitListener(() -> { + VaccinationDto selectedVaccination = selectionField.getValue(); + if (selectedVaccination != null) { + aefiInvestigationDto.setPrimarySuspectVaccine(selectedVaccination); + + if (commitCallback != null) { + commitCallback.accept(selectedVaccination); + } + } + }); + + selectionField.setSelectionChangeCallback((commitAllowed) -> component.getCommitButton().setEnabled(commitAllowed)); + VaadinUiUtil.showModalPopupWindow(component, I18nProperties.getString(Strings.headingAefiInvestigationSelectConcernedVaccine)); + } + + public void navigateToAefiInvestigation(String uuid) { + navigateToView(AefiInvestigationDataView.VIEW_NAME, uuid); + } + + public void navigateToView(String viewName, String uuid) { + final String navigationState = viewName + "/" + uuid; + SormasUI.get().getNavigator().navigateTo(navigationState); + } + + public CommitDiscardWrapperComponent getAefiInvestigationDataEditComponent( + boolean isCreateAction, + AefiInvestigationDto aefiInvestigationDto, + Consumer actionCallback) { + + AefiInvestigationDataForm aefiInvestigationDataForm = new AefiInvestigationDataForm( + isCreateAction, + aefiInvestigationDto.isPseudonymized(), + aefiInvestigationDto.isInJurisdiction(), + actionCallback); + aefiInvestigationDataForm.setValue(aefiInvestigationDto); + + CommitDiscardWrapperComponent editComponent = + new CommitDiscardWrapperComponent<>(aefiInvestigationDataForm, true, aefiInvestigationDataForm.getFieldGroup()); + + if (!isCreateAction) { + DeletionInfoDto automaticDeletionInfoDto = + FacadeProvider.getAefiInvestigationFacade().getAutomaticDeletionInfo(aefiInvestigationDto.getUuid()); + DeletionInfoDto manuallyDeletionInfoDto = + FacadeProvider.getAefiInvestigationFacade().getManuallyDeletionInfo(aefiInvestigationDto.getUuid()); + + editComponent.getButtonsPanel() + .addComponentAsFirst( + new DeletionLabel( + automaticDeletionInfoDto, + manuallyDeletionInfoDto, + aefiInvestigationDto.isDeleted(), + AefiInvestigationDto.I18N_PREFIX)); + + if (aefiInvestigationDto.isDeleted()) { + editComponent.getWrappedComponent().getField(AefiInvestigationDto.DELETION_REASON).setVisible(true); + if (editComponent.getWrappedComponent().getField(AefiInvestigationDto.DELETION_REASON).getValue() == DeletionReason.OTHER_REASON) { + editComponent.getWrappedComponent().getField(AefiInvestigationDto.OTHER_DELETION_REASON).setVisible(true); + } + } + } + + editComponent.addCommitListener(() -> { + if (!aefiInvestigationDataForm.getFieldGroup().isModified()) { + AefiInvestigationDto aefiInvestigationDataFormValue = aefiInvestigationDataForm.getValue(); + + AefiInvestigationDto savedAefiInvestigationDto = FacadeProvider.getAefiInvestigationFacade().save(aefiInvestigationDataFormValue); + Notification.show(I18nProperties.getString(Strings.messageAdverseEventInvestigationSaved), Notification.Type.WARNING_MESSAGE); + + if (isCreateAction) { + navigateToAefiInvestigation(savedAefiInvestigationDto.getUuid()); + } else { + SormasUI.refreshView(); + } + } + }); + + if (!isCreateAction) { + // Initialize 'Delete' button + if (UserProvider.getCurrent().hasUserRight(UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE)) { + editComponent.addDeleteWithReasonOrRestoreListener( + AefiInvestigationView.VIEW_NAME, + null, + I18nProperties.getString(Strings.entityAdverseEventInvestigation), + aefiInvestigationDto.getUuid(), + FacadeProvider.getAefiInvestigationFacade()); + } + + // Initialize 'Archive' button + if (UserProvider.getCurrent().hasUserRight(UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE)) { + ControllerProvider.getArchiveController() + .addArchivingButton( + aefiInvestigationDto, + ArchiveHandlers.forAefiInvestigation(), + editComponent, + () -> navigateToAefiInvestigation(aefiInvestigationDto.getUuid())); + } + + editComponent.restrictEditableComponentsOnEditView( + UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT, + null, + UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE, + UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE, + FacadeProvider.getAefiInvestigationFacade().getEditPermissionType(aefiInvestigationDto.getUuid()), + aefiInvestigationDto.isInJurisdiction()); + } + + return editComponent; + } + + public TitleLayout getAefiInvestigationViewTitleLayout( + String aefiInvestigationUuid, + String aefiUuid, + String immunizationUuid, + boolean isCreateAction) { + + TitleLayout titleLayout = new TitleLayout(); + + String investigationStage = ""; + + if (isCreateAction) { + investigationStage = I18nProperties.getCaption(Captions.aefiNewAefiInvestigationStageTitle); + } else { + AefiInvestigationDto aefiInvestigationDto = findAefiInvestigation(aefiInvestigationUuid); + investigationStage = aefiInvestigationDto.getInvestigationStage().toString(); + } + + AefiDto aefiDto = FacadeProvider.getAefiFacade().getByUuid(aefiUuid); + if (aefiDto.getSerious() == YesNoUnknown.YES) { + RowLayout aefiTypeLayout = new RowLayout(); + aefiTypeLayout.addToLayout(investigationStage + ", "); + aefiTypeLayout.addToLayout(AefiType.SERIOUS.toString(), CssStyles.LABEL_CRITICAL); + titleLayout.addRow(aefiTypeLayout); + } else { + titleLayout.addRow(investigationStage + ", " + AefiType.NON_SERIOUS); + } + + String shortUuid = DataHelper.getShortUuid(aefiInvestigationUuid); + ImmunizationDto immunizationDto = FacadeProvider.getImmunizationFacade().getByUuid(immunizationUuid); + PersonDto person = FacadeProvider.getPersonFacade().getByUuid(immunizationDto.getPerson().getUuid()); + StringBuilder mainRowText = TitleLayoutHelper.buildPersonString(person); + + if (!StringUtils.isBlank(shortUuid)) { + mainRowText.append(mainRowText.length() > 0 ? " (" + shortUuid + ")" : shortUuid); + } + titleLayout.addMainRow(mainRowText.toString()); + + return titleLayout; + } + + private AefiInvestigationDto findAefiInvestigation(String uuid) { + return FacadeProvider.getAefiInvestigationFacade().getByUuid(uuid); + } + + public boolean isCreateAction(String params) { + return StringUtils.startsWith(params, "adverseevent") && StringUtils.endsWith(params, "create"); + } + + public String getCreateActionAefiReportUuid(String params) { + return StringUtils.contains(params, "/") + ? StringUtils.substringBetween(params, "adverseevent/", "/investigation/create") + : StringUtils.substringBetween(params, "adverseevent", "investigationcreate"); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationDataForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationDataForm.java new file mode 100644 index 00000000000..1ba7beb0475 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationDataForm.java @@ -0,0 +1,950 @@ +/* + * 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.ui.adverseeventsfollowingimmunization; + +import static de.symeda.sormas.ui.utils.CssStyles.H3; +import static de.symeda.sormas.ui.utils.LayoutUtil.fluidColumnLocCss; +import static de.symeda.sormas.ui.utils.LayoutUtil.fluidRow; +import static de.symeda.sormas.ui.utils.LayoutUtil.fluidRowCss; +import static de.symeda.sormas.ui.utils.LayoutUtil.fluidRowLocs; +import static de.symeda.sormas.ui.utils.LayoutUtil.loc; +import static de.symeda.sormas.ui.utils.LayoutUtil.locCss; + +import java.util.Arrays; +import java.util.function.Consumer; + +import com.vaadin.ui.CustomLayout; +import com.vaadin.ui.Label; +import com.vaadin.v7.data.util.converter.Converter; +import com.vaadin.v7.ui.DateField; +import com.vaadin.v7.ui.OptionGroup; +import com.vaadin.v7.ui.PasswordField; +import com.vaadin.v7.ui.TextArea; +import com.vaadin.v7.ui.TextField; + +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.DeliveryProcedure; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.PatientStatusAtAefiInvestigation; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.PlaceOfVaccination; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.SeriousAefiInfoSource; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.SyringeType; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.VaccinationActivity; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.VaccinationSite; +import de.symeda.sormas.api.i18n.Captions; +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.i18n.Validations; +import de.symeda.sormas.api.immunization.ImmunizationDto; +import de.symeda.sormas.api.utils.YesNoUnknown; +import de.symeda.sormas.api.utils.fieldaccess.UiFieldAccessCheckers; +import de.symeda.sormas.api.utils.fieldvisibility.FieldVisibilityCheckers; +import de.symeda.sormas.ui.UserProvider; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.fields.vaccines.AefiVaccinationsField; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.form.FormSectionAccordion; +import de.symeda.sormas.ui.utils.AbstractEditForm; +import de.symeda.sormas.ui.utils.CssStyles; +import de.symeda.sormas.ui.utils.DateTimeField; +import de.symeda.sormas.ui.utils.FieldHelper; +import de.symeda.sormas.ui.utils.NullableOptionGroup; +import de.symeda.sormas.ui.utils.UserField; + +@SuppressWarnings("deprecation") +public class AefiInvestigationDataForm extends AbstractEditForm { + + public static final String FORM_HEADING_LOC = "formHeadingLoc"; + public static final String MAIN_ACCORDION_LOC = "mainAccordionLoc"; + public static final String FOR_INFANTS_HEADING_LOC = "forInfantsHeadingLoc"; + public static final String SOURCE_OF_INFORMATION_HEADING_LOC = "sourceOfInformationHeadingLoc"; + public static final String CLINICAL_DETAILS_OFFICER_HEADING_LOC = "clinicalDetailsOfficerHeadingLoc"; + public static final String SYRINGES_AND_NEEDLES_HEADING_LOC = "syringesAndNeedlesHeadingLoc"; + public static final String RECONSTITUTION_HEADING_LOC = "reconstitutionHeadingLoc"; + public static final String INJECTION_TECHNIQUE_HEADING_LOC = "injectionTechniqueHeadingLoc"; + public static final String VACCINE_STORAGE_POINT_HEADING_LOC = "vaccineStoragePointHeadingLoc"; + public static final String VACCINE_TRANSPORTATION_HEADING_LOC = "vaccineTransportationHeadingLoc"; + public static final String THOSE_AFFECTED_HEADING_LOC = "thoseAffectedHeadingLoc"; + + //@formatter:off + public static final String HTML_LAYOUT = + locCss(CssStyles.VSPACE_3, FORM_HEADING_LOC) + + fluidRowLocs(MAIN_ACCORDION_LOC); + //@formatter:on + + //@formatter:off + public static final String BASIC_DETAILS_HTML_LAYOUT = + fluidRowLocs(4, AefiInvestigationDto.UUID, 4, AefiInvestigationDto.REPORT_DATE, 3, AefiInvestigationDto.REPORTING_USER) + + fluidRowLocs(4, AefiInvestigationDto.RESPONSIBLE_REGION, 4, AefiInvestigationDto.RESPONSIBLE_DISTRICT, 3, AefiInvestigationDto.RESPONSIBLE_COMMUNITY) + + fluidRowLocs(4, AefiInvestigationDto.INVESTIGATION_CASE_ID) + + fluidRowLocs(8, AefiInvestigationDto.PLACE_OF_VACCINATION, 4, AefiInvestigationDto.PLACE_OF_VACCINATION_DETAILS) + + fluidRowLocs(4, AefiInvestigationDto.VACCINATION_ACTIVITY, 4, AefiInvestigationDto.VACCINATION_ACTIVITY_DETAILS) + + fluidRowLocs(AefiInvestigationDto.INVESTIGATION_DATE, AefiInvestigationDto.FORM_COMPLETION_DATE, AefiInvestigationDto.INVESTIGATION_STAGE) + + fluidRowLocs(AefiInvestigationDto.VACCINATIONS) + + fluidRowLocs(8, AefiInvestigationDto.TYPE_OF_SITE, 4, AefiInvestigationDto.TYPE_OF_SITE_DETAILS) + + fluidRowLocs(4, AefiInvestigationDto.KEY_SYMPTOM_DATE_TIME, 3, AefiInvestigationDto.HOSPITALIZATION_DATE, 5, AefiInvestigationDto.REPORTED_TO_HEALTH_AUTHORITY_DATE) + + fluidRowLocs(AefiInvestigationDto.STATUS_ON_DATE_OF_INVESTIGATION) + + fluidRowLocs(4, AefiInvestigationDto.DEATH_DATE_TIME, 3, AefiInvestigationDto.AUTOPSY_DONE, 5, AefiInvestigationDto.AUTOPSY_DATE) + + fluidRowLocs(4, "", 5, AefiInvestigationDto.AUTOPSY_PLANNED_DATE_TIME); + //@formatter:on + + //@formatter:off + public static final String RELEVANT_PATIENT_INFO_HTML_LAYOUT = + fluidRowLocs(8, AefiInvestigationDto.PAST_HISTORY_OF_SIMILAR_EVENT, 4, AefiInvestigationDto.PAST_HISTORY_OF_SIMILAR_EVENT_DETAILS) + + fluidRowLocs(8, AefiInvestigationDto.ADVERSE_EVENT_AFTER_PREVIOUS_VACCINATIONS, 4, AefiInvestigationDto.ADVERSE_EVENT_AFTER_PREVIOUS_VACCINATIONS_DETAILS) + + fluidRowLocs(8, AefiInvestigationDto.HISTORY_OF_ALLERGY_TO_VACCINE_DRUG_OR_FOOD, 4, AefiInvestigationDto.HISTORY_OF_ALLERGY_TO_VACCINE_DRUG_OR_FOOD_DETAILS) + + fluidRowLocs(8, AefiInvestigationDto.PRE_EXISTING_ILLNESS_THIRTY_DAYS_OR_CONGENITAL_DISORDER, 4, AefiInvestigationDto.PRE_EXISTING_ILLNESS_THIRTY_DAYS_OR_CONGENITAL_DISORDER_DETAILS) + + fluidRowLocs(8, AefiInvestigationDto.HISTORY_OF_HOSPITALIZATION_IN_LAST_THIRTY_DAYS_WITH_CAUSE, 4, AefiInvestigationDto.HISTORY_OF_HOSPITALIZATION_IN_LAST_THIRTY_DAYS_WITH_CAUSE_DETAILS) + + fluidRowLocs(8, AefiInvestigationDto.CURRENTLY_ON_CONCOMITANT_MEDICATION, 4, AefiInvestigationDto.CURRENTLY_ON_CONCOMITANT_MEDICATION_DETAILS) + + fluidRowLocs(8, AefiInvestigationDto.FAMILY_HISTORY_OF_DISEASE_OR_ALLERGY, 4, AefiInvestigationDto.FAMILY_HISTORY_OF_DISEASE_OR_ALLERGY_DETAILS) + + loc(FOR_INFANTS_HEADING_LOC) + + fluidRowLocs(8, AefiInvestigationDto.BIRTH_TERM, 4, AefiInvestigationDto.BIRTH_WEIGHT) + + fluidRowLocs(8, AefiInvestigationDto.DELIVERY_PROCEDURE, 4, AefiInvestigationDto.DELIVERY_PROCEDURE_DETAILS); + //@formatter:on + + //@formatter:off + public static final String FIRST_EXAMINATION_HTML_LAYOUT = + loc(SOURCE_OF_INFORMATION_HEADING_LOC) + + fluidRowLocs(AefiInvestigationDto.SERIOUS_AEFI_INFO_SOURCE) + + fluidRowLocs(AefiInvestigationDto.SERIOUS_AEFI_INFO_SOURCE_DETAILS, AefiInvestigationDto.SERIOUS_AEFI_VERBAL_AUTOPSY_INFO_SOURCE_DETAILS) + + fluidRowLocs(AefiInvestigationDto.FIRST_CAREGIVERS_NAME, AefiInvestigationDto.OTHER_CAREGIVERS_NAMES) + + fluidRowLocs(6, AefiInvestigationDto.OTHER_SOURCES_WHO_PROVIDED_INFO) + + fluidRowLocs(AefiInvestigationDto.SIGNS_AND_SYMPTOMS_FROM_TIME_OF_VACCINATION) + + loc(CLINICAL_DETAILS_OFFICER_HEADING_LOC) + + fluidRowLocs(5, AefiInvestigationDto.CLINICAL_DETAILS_OFFICER_NAME, 4, AefiInvestigationDto.CLINICAL_DETAILS_OFFICER_PHONE_NUMBER, 3, AefiInvestigationDto.CLINICAL_DETAILS_OFFICER_EMAIL) + + fluidRowLocs(5, AefiInvestigationDto.CLINICAL_DETAILS_OFFICER_DESIGNATION, 4, AefiInvestigationDto.CLINICAL_DETAILS_DATE_TIME) + + fluidRowLocs(4, AefiInvestigationDto.PATIENT_RECEIVED_MEDICAL_CARE) + + fluidRowLocs(AefiInvestigationDto.PATIENT_RECEIVED_MEDICAL_CARE_DETAILS) + + fluidRowLocs(AefiInvestigationDto.PROVISIONAL_OR_FINAL_DIAGNOSIS); + //@formatter:on + + //@formatter:off + public static final String VACCINES_DETAILS_HTML_LAYOUT = + fluidRowLocs(AefiInvestigationDto.PATIENT_IMMUNIZED_PERIOD) + + fluidRowLocs(AefiInvestigationDto.VACCINE_GIVEN_PERIOD) + + fluidRowCss(CssStyles.VSPACE_TOP_4, + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.ERROR_PRESCRIBING_VACCINE), + fluidColumnLocCss("", 4, 0, AefiInvestigationDto.ERROR_PRESCRIBING_VACCINE_DETAILS) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.VACCINE_COULD_HAVE_BEEN_UNSTERILE), + fluidColumnLocCss("", 4, 0, AefiInvestigationDto.VACCINE_COULD_HAVE_BEEN_UNSTERILE_DETAILS) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.VACCINE_PHYSICAL_CONDITION_ABNORMAL), + fluidColumnLocCss("", 4, 0, AefiInvestigationDto.VACCINE_PHYSICAL_CONDITION_ABNORMAL_DETAILS) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.ERROR_IN_VACCINE_RECONSTITUTION), + fluidColumnLocCss("", 4, 0, AefiInvestigationDto.ERROR_IN_VACCINE_RECONSTITUTION_DETAILS) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.ERROR_IN_VACCINE_HANDLING), + fluidColumnLocCss("", 4, 0, AefiInvestigationDto.ERROR_IN_VACCINE_HANDLING_DETAILS) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.VACCINE_ADMINISTERED_INCORRECTLY), + fluidColumnLocCss("", 4, 0, AefiInvestigationDto.VACCINE_ADMINISTERED_INCORRECTLY_DETAILS) + ) + + fluidRowLocs(8, AefiInvestigationDto.NUMBER_IMMUNIZED_FROM_CONCERNED_VACCINE_VIAL) + + fluidRowLocs(8, AefiInvestigationDto.NUMBER_IMMUNIZED_WITH_CONCERNED_VACCINE_IN_SAME_SESSION) + + fluidRowLocs(12, AefiInvestigationDto.NUMBER_IMMUNIZED_CONCERNED_VACCINE_SAME_BATCH_NUMBER_OTHER_LOCATIONS) + + fluidRowLocs(12, AefiInvestigationDto.NUMBER_IMMUNIZED_CONCERNED_VACCINE_SAME_BATCH_NUMBER_LOCATION_DETAILS) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.VACCINE_HAS_QUALITY_DEFECT), + fluidColumnLocCss("", 4, 0, AefiInvestigationDto.VACCINE_HAS_QUALITY_DEFECT_DETAILS) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.EVENT_IS_A_STRESS_RESPONSE_RELATED_TO_IMMUNIZATION), + fluidColumnLocCss("", 4, 0, AefiInvestigationDto.EVENT_IS_A_STRESS_RESPONSE_RELATED_TO_IMMUNIZATION_DETAILS) + ) + + fluidRowLocs(4, AefiInvestigationDto.CASE_IS_PART_OF_A_CLUSTER, 8, AefiInvestigationDto.CASE_IS_PART_OF_A_CLUSTER_DETAILS) + + fluidRowLocs(8, AefiInvestigationDto.NUMBER_OF_CASES_DETECTED_IN_CLUSTER) + + fluidRowLocs(8, AefiInvestigationDto.ALL_CASES_IN_CLUSTER_RECEIVED_VACCINE_FROM_SAME_VIAL, 4, AefiInvestigationDto.ALL_CASES_IN_CLUSTER_RECEIVED_VACCINE_FROM_SAME_VIAL_DETAILS) + + fluidRowLocs(8, AefiInvestigationDto.NUMBER_OF_VIALS_USED_IN_CLUSTER); + //@formatter:on + + //@formatter:off + public static final String IMMUNIZATION_PRACTICES_HTML_LAYOUT = + loc(SYRINGES_AND_NEEDLES_HEADING_LOC) + + fluidRowLocs(6, AefiInvestigationDto.AD_SYRINGES_USED_FOR_IMMUNIZATION) + + fluidRowLocs(8, AefiInvestigationDto.TYPE_OF_SYRINGES_USED, 4, AefiInvestigationDto.TYPE_OF_SYRINGES_USED_DETAILS) + + fluidRowLocs(AefiInvestigationDto.SYRINGES_USED_ADDITIONAL_DETAILS) + + loc(RECONSTITUTION_HEADING_LOC) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.SAME_RECONSTITUTION_SYRINGE_USED_FOR_MULTIPLE_VIALS_OF_SAME_VACCINE) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.SAME_RECONSTITUTION_SYRINGE_USED_FOR_RECONSTITUTING_DIFFERENT_VACCINES) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.SAME_RECONSTITUTION_SYRINGE_FOR_EACH_VACCINE_VIAL) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.SAME_RECONSTITUTION_SYRINGE_FOR_EACH_VACCINATION) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.VACCINES_AND_DILUENTS_USED_RECOMMENDED_BY_MANUFACTURER) + ) + + fluidRowLocs(AefiInvestigationDto.RECONSTITUTION_ADDITIONAL_DETAILS) + + loc(INJECTION_TECHNIQUE_HEADING_LOC) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.CORRECT_DOSE_OR_ROUTE) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.TIME_OF_RECONSTITUTION_MENTIONED_ON_THE_VIAL) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.NON_TOUCH_TECHNIQUE_FOLLOWED) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.CONTRAINDICATION_SCREENED_PRIOR_TO_VACCINATION) + ) + + fluidRowLocs(AefiInvestigationDto.NUMBER_OF_AEFI_REPORTED_FROM_VACCINE_DISTRIBUTION_CENTER_LAST_THIRTY_DAYS) + + fluidRowLocs(4, AefiInvestigationDto.TRAINING_RECEIVED_BY_VACCINATOR, 4, AefiInvestigationDto.LAST_TRAINING_RECEIVED_BY_VACCINATOR_DATE) + + fluidRowLocs(AefiInvestigationDto.INJECTION_TECHNIQUE_ADDITIONAL_DETAILS); + //@formatter:on + + //@formatter:off + public static final String COLD_CHAIN_AND_TRANSPORT_HTML_LAYOUT = + loc(VACCINE_STORAGE_POINT_HEADING_LOC) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.VACCINE_STORAGE_REFRIGERATOR_TEMPERATURE_MONITORED) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.ANY_STORAGE_TEMPERATURE_DEVIATION_OUTSIDE_TWO_TO_EIGHT_DEGREES) + ) + + fluidRowLocs(AefiInvestigationDto.STORAGE_TEMPERATURE_MONITORING_ADDITIONAL_DETAILS) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.CORRECT_PROCEDURE_FOR_STORAGE_FOLLOWED) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.ANY_OTHER_ITEM_IN_REFRIGERATOR) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.PARTIALLY_USED_RECONSTITUTED_VACCINES_IN_REFRIGERATOR) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.UNUSABLE_VACCINES_IN_REFRIGERATOR) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.UNUSABLE_DILUENTS_IN_STORE) + ) + + fluidRowLocs(AefiInvestigationDto.VACCINE_STORAGE_POINT_ADDITIONAL_DETAILS) + + loc(VACCINE_TRANSPORTATION_HEADING_LOC) + + fluidRowLocs(4, AefiInvestigationDto.VACCINE_CARRIER_TYPE) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.VACCINE_CARRIER_SENT_TO_SITE_ON_SAME_DATE_AS_VACCINATION) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.VACCINE_CARRIER_RETURNED_FROM_SITE_ON_SAME_DATE_AS_VACCINATION) + ) + + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.CONDITIONED_ICE_PACK_USED) + ) + + fluidRowLocs(AefiInvestigationDto.VACCINE_TRANSPORTATION_ADDITIONAL_DETAILS); + //@formatter:on + + //@formatter:off + public static final String COMMUNITY_INVESTIGATION_HTML_LAYOUT = + fluidRow( + fluidColumnLocCss(CssStyles.OPTIONGROUP_CAPTION_FLEX, 8, 0, AefiInvestigationDto.SIMILAR_EVENTS_REPORTED_SAME_PERIOD_AND_LOCALITY) + ) + + fluidRowLocs(AefiInvestigationDto.SIMILAR_EVENTS_REPORTED_SAME_PERIOD_AND_LOCALITY_DETAILS, AefiInvestigationDto.NUMBER_OF_SIMILAR_EVENTS_REPORTED_SAME_PERIOD_AND_LOCALITY) + + loc(THOSE_AFFECTED_HEADING_LOC) + + fluidRowLocs(AefiInvestigationDto.NUMBER_OF_THOSE_AFFECTED_VACCINATED, AefiInvestigationDto.NUMBER_OF_THOSE_AFFECTED_NOT_VACCINATED, AefiInvestigationDto.NUMBER_OF_THOSE_AFFECTED_VACCINATED_UNKNOWN) + + fluidRowLocs(AefiInvestigationDto.COMMUNITY_INVESTIGATION_ADDITIONAL_DETAILS); + //@formatter:on + + //@formatter:off + public static final String OTHER_FINDINGS_HTML_LAYOUT = + fluidRowLocs(AefiInvestigationDto.OTHER_INVESTIGATION_FINDINGS); + //@formatter:on + + //@formatter:off + public static final String INVESTIGATION_STATUS_HTML_LAYOUT = + fluidRowLocs(4, AefiInvestigationDto.INVESTIGATION_STATUS, 8, AefiInvestigationDto.INVESTIGATION_STATUS_DETAILS) + + fluidRowLocs(AefiInvestigationDto.AEFI_CLASSIFICATION) + + fluidRowLocs(AefiInvestigationDto.AEFI_CLASSIFICATION_DETAILS); + //@formatter:on + + private boolean isCreateAction; + private final Consumer actionCallback; + private TextField responsibleRegion; + private TextField responsibleDistrict; + private TextField responsibleCommunity; + private AefiVaccinationsField vaccinationsField; + + public AefiInvestigationDataForm(boolean isCreateAction, boolean isPseudonymized, boolean inJurisdiction, Consumer actionCallback) { + super( + AefiInvestigationDto.class, + AefiInvestigationDto.I18N_PREFIX, + false, + FieldVisibilityCheckers.withCountry(FacadeProvider.getConfigFacade().getCountryLocale()), + UiFieldAccessCheckers.forDataAccessLevel(UserProvider.getCurrent().getPseudonymizableDataAccessLevel(inJurisdiction), isPseudonymized)); + + this.isCreateAction = isCreateAction; + this.actionCallback = actionCallback; + + if (isCreateAction) { + hideValidationUntilNextCommit(); + } + + addFields(); + } + + @Override + protected String createHtmlLayout() { + return HTML_LAYOUT; + } + + @Override + protected void addFields() { + + Label formHeadingLabel = new Label(I18nProperties.getString(Strings.headingAefiInvestigationFormSubHeading)); + formHeadingLabel.addStyleNames(H3, CssStyles.LABEL_CRITICAL, CssStyles.VSPACE_NONE, CssStyles.VSPACE_TOP_NONE); + getContent().addComponent(formHeadingLabel, FORM_HEADING_LOC); + + FormSectionAccordion accordion = new FormSectionAccordion(); + + //Basic details + CustomLayout basicDetailsLayout = new CustomLayout(); + basicDetailsLayout.setTemplateContents(BASIC_DETAILS_HTML_LAYOUT); + + if (isCreateAction) { + addField(basicDetailsLayout, AefiInvestigationDto.UUID, PasswordField.class); + } else { + addField(basicDetailsLayout, AefiInvestigationDto.UUID); + } + addField(basicDetailsLayout, AefiInvestigationDto.REPORT_DATE, DateField.class); + addField(basicDetailsLayout, AefiInvestigationDto.REPORTING_USER, UserField.class); + + responsibleRegion = new TextField(I18nProperties.getPrefixCaption(AefiInvestigationDto.I18N_PREFIX, AefiInvestigationDto.RESPONSIBLE_REGION)); + basicDetailsLayout.addComponent(responsibleRegion, AefiInvestigationDto.RESPONSIBLE_REGION); + responsibleDistrict = + new TextField(I18nProperties.getPrefixCaption(AefiInvestigationDto.I18N_PREFIX, AefiInvestigationDto.RESPONSIBLE_DISTRICT)); + basicDetailsLayout.addComponent(responsibleDistrict, AefiInvestigationDto.RESPONSIBLE_DISTRICT); + responsibleCommunity = + new TextField(I18nProperties.getPrefixCaption(AefiInvestigationDto.I18N_PREFIX, AefiInvestigationDto.RESPONSIBLE_COMMUNITY)); + basicDetailsLayout.addComponent(responsibleCommunity, AefiInvestigationDto.RESPONSIBLE_COMMUNITY); + + addField(basicDetailsLayout, AefiInvestigationDto.INVESTIGATION_CASE_ID); + addField(basicDetailsLayout, AefiInvestigationDto.PLACE_OF_VACCINATION, NullableOptionGroup.class); + addField(basicDetailsLayout, AefiInvestigationDto.PLACE_OF_VACCINATION_DETAILS); + addField(basicDetailsLayout, AefiInvestigationDto.VACCINATION_ACTIVITY, NullableOptionGroup.class); + addField(basicDetailsLayout, AefiInvestigationDto.VACCINATION_ACTIVITY_DETAILS); + addField(basicDetailsLayout, AefiInvestigationDto.INVESTIGATION_DATE, DateField.class); + addField(basicDetailsLayout, AefiInvestigationDto.FORM_COMPLETION_DATE, DateField.class); + addField(basicDetailsLayout, AefiInvestigationDto.INVESTIGATION_STAGE, NullableOptionGroup.class); + vaccinationsField = addField(basicDetailsLayout, AefiInvestigationDto.VACCINATIONS, AefiVaccinationsField.class); + addField(basicDetailsLayout, AefiInvestigationDto.TYPE_OF_SITE, NullableOptionGroup.class); + addField(basicDetailsLayout, AefiInvestigationDto.TYPE_OF_SITE_DETAILS); + addField(basicDetailsLayout, AefiInvestigationDto.KEY_SYMPTOM_DATE_TIME, DateTimeField.class); + addField(basicDetailsLayout, AefiInvestigationDto.HOSPITALIZATION_DATE, DateField.class); + addField(basicDetailsLayout, AefiInvestigationDto.REPORTED_TO_HEALTH_AUTHORITY_DATE, DateField.class); + addField(basicDetailsLayout, AefiInvestigationDto.STATUS_ON_DATE_OF_INVESTIGATION, NullableOptionGroup.class); + addField(basicDetailsLayout, AefiInvestigationDto.DEATH_DATE_TIME, DateTimeField.class); + addField(basicDetailsLayout, AefiInvestigationDto.AUTOPSY_DONE, NullableOptionGroup.class); + addField(basicDetailsLayout, AefiInvestigationDto.AUTOPSY_DATE, DateField.class); + addField(basicDetailsLayout, AefiInvestigationDto.AUTOPSY_PLANNED_DATE_TIME, DateTimeField.class); + + accordion.addFormSectionPanel(Captions.titleAefiInvestigationBasicDetails, true, basicDetailsLayout); + + CustomLayout relevantPatientInformationLayout = new CustomLayout(); + relevantPatientInformationLayout.setTemplateContents(RELEVANT_PATIENT_INFO_HTML_LAYOUT); + + addField(relevantPatientInformationLayout, AefiInvestigationDto.PAST_HISTORY_OF_SIMILAR_EVENT); + TextField pastHistoryOfSimilarEventDetails = + addField(relevantPatientInformationLayout, AefiInvestigationDto.PAST_HISTORY_OF_SIMILAR_EVENT_DETAILS); + pastHistoryOfSimilarEventDetails.setCaption(null); + pastHistoryOfSimilarEventDetails.setInputPrompt(I18nProperties.getString(Strings.promptRemarks)); + + addField(relevantPatientInformationLayout, AefiInvestigationDto.ADVERSE_EVENT_AFTER_PREVIOUS_VACCINATIONS); + TextField adverseEventAfterPreviousVaccinationsDetails = + addField(relevantPatientInformationLayout, AefiInvestigationDto.ADVERSE_EVENT_AFTER_PREVIOUS_VACCINATIONS_DETAILS); + adverseEventAfterPreviousVaccinationsDetails.setCaption(null); + adverseEventAfterPreviousVaccinationsDetails.setInputPrompt(I18nProperties.getString(Strings.promptRemarks)); + + addField(relevantPatientInformationLayout, AefiInvestigationDto.HISTORY_OF_ALLERGY_TO_VACCINE_DRUG_OR_FOOD); + TextField historyOfAllergyDetails = + addField(relevantPatientInformationLayout, AefiInvestigationDto.HISTORY_OF_ALLERGY_TO_VACCINE_DRUG_OR_FOOD_DETAILS); + historyOfAllergyDetails.setCaption(null); + historyOfAllergyDetails.setInputPrompt(I18nProperties.getString(Strings.promptRemarks)); + + addField(relevantPatientInformationLayout, AefiInvestigationDto.PRE_EXISTING_ILLNESS_THIRTY_DAYS_OR_CONGENITAL_DISORDER); + TextField preExistingIllnessDetails = + addField(relevantPatientInformationLayout, AefiInvestigationDto.PRE_EXISTING_ILLNESS_THIRTY_DAYS_OR_CONGENITAL_DISORDER_DETAILS); + preExistingIllnessDetails.setCaption(null); + preExistingIllnessDetails.setInputPrompt(I18nProperties.getString(Strings.promptRemarks)); + + addField(relevantPatientInformationLayout, AefiInvestigationDto.HISTORY_OF_HOSPITALIZATION_IN_LAST_THIRTY_DAYS_WITH_CAUSE); + TextField historyOfHospitalizationDetails = + addField(relevantPatientInformationLayout, AefiInvestigationDto.HISTORY_OF_HOSPITALIZATION_IN_LAST_THIRTY_DAYS_WITH_CAUSE_DETAILS); + historyOfHospitalizationDetails.setCaption(null); + historyOfHospitalizationDetails.setInputPrompt(I18nProperties.getString(Strings.promptRemarks)); + + addField(relevantPatientInformationLayout, AefiInvestigationDto.CURRENTLY_ON_CONCOMITANT_MEDICATION); + TextField currentlyOnConcomitantMedicationDetails = + addField(relevantPatientInformationLayout, AefiInvestigationDto.CURRENTLY_ON_CONCOMITANT_MEDICATION_DETAILS); + currentlyOnConcomitantMedicationDetails.setCaption(null); + currentlyOnConcomitantMedicationDetails.setInputPrompt(I18nProperties.getString(Strings.promptRemarks)); + + addField(relevantPatientInformationLayout, AefiInvestigationDto.FAMILY_HISTORY_OF_DISEASE_OR_ALLERGY); + TextField familyHistoryOfDiseaseDetails = + addField(relevantPatientInformationLayout, AefiInvestigationDto.FAMILY_HISTORY_OF_DISEASE_OR_ALLERGY_DETAILS); + familyHistoryOfDiseaseDetails.setCaption(null); + familyHistoryOfDiseaseDetails.setInputPrompt(I18nProperties.getString(Strings.promptRemarks)); + + Label forInfantsLabel = new Label(I18nProperties.getCaption(Captions.aefiInvestigationForInfants)); + forInfantsLabel.addStyleName(CssStyles.H4); + relevantPatientInformationLayout.addComponent(forInfantsLabel, FOR_INFANTS_HEADING_LOC); + + addField(relevantPatientInformationLayout, AefiInvestigationDto.BIRTH_TERM, NullableOptionGroup.class); + addField(relevantPatientInformationLayout, AefiInvestigationDto.BIRTH_WEIGHT); + addField(relevantPatientInformationLayout, AefiInvestigationDto.DELIVERY_PROCEDURE, NullableOptionGroup.class); + addField(relevantPatientInformationLayout, AefiInvestigationDto.DELIVERY_PROCEDURE_DETAILS); + + accordion.addFormSectionPanel(Captions.titleAefiInvestigationRelevantPatientInformation, false, relevantPatientInformationLayout); + + //First examination + CustomLayout firstExaminationDetailsLayout = new CustomLayout(); + firstExaminationDetailsLayout.setTemplateContents(FIRST_EXAMINATION_HTML_LAYOUT); + + Label sourceOfInformationLabel = new Label(I18nProperties.getCaption(Captions.aefiInvestigationSourceOfInformation)); + sourceOfInformationLabel.addStyleName(CssStyles.H4); + firstExaminationDetailsLayout.addComponent(sourceOfInformationLabel, SOURCE_OF_INFORMATION_HEADING_LOC); + + OptionGroup seriousAefiSourcesOfInformation = + addField(firstExaminationDetailsLayout, AefiInvestigationDto.SERIOUS_AEFI_INFO_SOURCE, OptionGroup.class); + CssStyles.style(seriousAefiSourcesOfInformation, CssStyles.OPTIONGROUP_CHECKBOXES_HORIZONTAL); + seriousAefiSourcesOfInformation.setMultiSelect(true); + seriousAefiSourcesOfInformation.addItems((Object[]) SeriousAefiInfoSource.values()); + seriousAefiSourcesOfInformation.setCaption(null); + + addField(firstExaminationDetailsLayout, AefiInvestigationDto.SERIOUS_AEFI_INFO_SOURCE_DETAILS); + addField(firstExaminationDetailsLayout, AefiInvestigationDto.SERIOUS_AEFI_VERBAL_AUTOPSY_INFO_SOURCE_DETAILS); + + addField(firstExaminationDetailsLayout, AefiInvestigationDto.FIRST_CAREGIVERS_NAME); + addField(firstExaminationDetailsLayout, AefiInvestigationDto.OTHER_CAREGIVERS_NAMES); + addField(firstExaminationDetailsLayout, AefiInvestigationDto.OTHER_SOURCES_WHO_PROVIDED_INFO); + + TextArea signsAndSymptomsFromTimeOfVaccination = + addField(firstExaminationDetailsLayout, AefiInvestigationDto.SIGNS_AND_SYMPTOMS_FROM_TIME_OF_VACCINATION, TextArea.class); + signsAndSymptomsFromTimeOfVaccination.setRows(6); + signsAndSymptomsFromTimeOfVaccination.setDescription( + I18nProperties + .getPrefixDescription(AefiInvestigationDto.I18N_PREFIX, AefiInvestigationDto.SIGNS_AND_SYMPTOMS_FROM_TIME_OF_VACCINATION, "") + "\n" + + I18nProperties.getDescription(Descriptions.descGdpr)); + + Label clinicalDetailsOfficerLabel = new Label(I18nProperties.getCaption(Captions.aefiInvestigationClinicalDetailsOfficer)); + clinicalDetailsOfficerLabel.addStyleName(CssStyles.H4); + firstExaminationDetailsLayout.addComponent(clinicalDetailsOfficerLabel, CLINICAL_DETAILS_OFFICER_HEADING_LOC); + + addField(firstExaminationDetailsLayout, AefiInvestigationDto.CLINICAL_DETAILS_OFFICER_NAME); + addField(firstExaminationDetailsLayout, AefiInvestigationDto.CLINICAL_DETAILS_OFFICER_PHONE_NUMBER); + addField(firstExaminationDetailsLayout, AefiInvestigationDto.CLINICAL_DETAILS_OFFICER_EMAIL); + addField(firstExaminationDetailsLayout, AefiInvestigationDto.CLINICAL_DETAILS_OFFICER_DESIGNATION); + addField(firstExaminationDetailsLayout, AefiInvestigationDto.CLINICAL_DETAILS_DATE_TIME, DateTimeField.class); + addField(firstExaminationDetailsLayout, AefiInvestigationDto.PATIENT_RECEIVED_MEDICAL_CARE, NullableOptionGroup.class); + + TextArea patientReceivedMedicalCareDetails = + addField(firstExaminationDetailsLayout, AefiInvestigationDto.PATIENT_RECEIVED_MEDICAL_CARE_DETAILS, TextArea.class); + patientReceivedMedicalCareDetails.setRows(6); + patientReceivedMedicalCareDetails.setDescription( + I18nProperties.getPrefixDescription(AefiInvestigationDto.I18N_PREFIX, AefiInvestigationDto.PATIENT_RECEIVED_MEDICAL_CARE_DETAILS, "") + + "\n" + I18nProperties.getDescription(Descriptions.descGdpr)); + + TextArea provisionalOrFinalDiagnosis = + addField(firstExaminationDetailsLayout, AefiInvestigationDto.PROVISIONAL_OR_FINAL_DIAGNOSIS, TextArea.class); + provisionalOrFinalDiagnosis.setRows(6); + provisionalOrFinalDiagnosis.setDescription( + I18nProperties.getPrefixDescription(AefiInvestigationDto.I18N_PREFIX, AefiInvestigationDto.PROVISIONAL_OR_FINAL_DIAGNOSIS, "") + "\n" + + I18nProperties.getDescription(Descriptions.descGdpr)); + + accordion.addFormSectionPanel(Captions.titleAefiInvestigationFirstExaminationDetails, false, firstExaminationDetailsLayout); + + //Vaccines details + CustomLayout vaccinesDetailsLayout = new CustomLayout(); + vaccinesDetailsLayout.setTemplateContents(VACCINES_DETAILS_HTML_LAYOUT); + + addField(vaccinesDetailsLayout, AefiInvestigationDto.PATIENT_IMMUNIZED_PERIOD, NullableOptionGroup.class); + /* + * TextField patientImmunizedPeriodDetails = addField(vaccinesDetailsLayout, AefiInvestigationDto.PATIENT_IMMUNIZED_PERIOD_DETAILS); + * patientImmunizedPeriodDetails.setCaption(null); + * patientImmunizedPeriodDetails.setInputPrompt(I18nProperties.getString(Strings.promptRemarks)); + */ + + addField(vaccinesDetailsLayout, AefiInvestigationDto.VACCINE_GIVEN_PERIOD, NullableOptionGroup.class); + /* + * TextField vaccineGivenPeriodDetails = addField(vaccinesDetailsLayout, AefiInvestigationDto.VACCINE_GIVEN_PERIOD_DETAILS); + * vaccineGivenPeriodDetails.setCaption(null); + * vaccineGivenPeriodDetails.setInputPrompt(I18nProperties.getString(Strings.promptRemarks)); + */ + + addField(vaccinesDetailsLayout, AefiInvestigationDto.ERROR_PRESCRIBING_VACCINE); + TextField errorPrescribingVaccineDetails = addField(vaccinesDetailsLayout, AefiInvestigationDto.ERROR_PRESCRIBING_VACCINE_DETAILS); + errorPrescribingVaccineDetails.setCaption(null); + errorPrescribingVaccineDetails.setInputPrompt(I18nProperties.getString(Strings.promptRemarks)); + + addField(vaccinesDetailsLayout, AefiInvestigationDto.VACCINE_COULD_HAVE_BEEN_UNSTERILE); + TextField vaccineCouldBeUnsterileDetails = addField(vaccinesDetailsLayout, AefiInvestigationDto.VACCINE_COULD_HAVE_BEEN_UNSTERILE_DETAILS); + vaccineCouldBeUnsterileDetails.setCaption(null); + vaccineCouldBeUnsterileDetails.setInputPrompt(I18nProperties.getString(Strings.promptRemarks)); + + addField(vaccinesDetailsLayout, AefiInvestigationDto.VACCINE_PHYSICAL_CONDITION_ABNORMAL); + TextField vaccinePhysicalConditionAbnormalDetails = + addField(vaccinesDetailsLayout, AefiInvestigationDto.VACCINE_PHYSICAL_CONDITION_ABNORMAL_DETAILS); + vaccinePhysicalConditionAbnormalDetails.setCaption(null); + vaccinePhysicalConditionAbnormalDetails.setInputPrompt(I18nProperties.getString(Strings.promptRemarks)); + + addField(vaccinesDetailsLayout, AefiInvestigationDto.ERROR_IN_VACCINE_RECONSTITUTION); + TextField errorInVaccineReconstitutionAbnormalDetails = + addField(vaccinesDetailsLayout, AefiInvestigationDto.ERROR_IN_VACCINE_RECONSTITUTION_DETAILS); + errorInVaccineReconstitutionAbnormalDetails.setCaption(null); + errorInVaccineReconstitutionAbnormalDetails.setInputPrompt(I18nProperties.getString(Strings.promptRemarks)); + + addField(vaccinesDetailsLayout, AefiInvestigationDto.ERROR_IN_VACCINE_HANDLING); + TextField errorInVaccineHandlingDetails = addField(vaccinesDetailsLayout, AefiInvestigationDto.ERROR_IN_VACCINE_HANDLING_DETAILS); + errorInVaccineHandlingDetails.setCaption(null); + errorInVaccineHandlingDetails.setInputPrompt(I18nProperties.getString(Strings.promptRemarks)); + + addField(vaccinesDetailsLayout, AefiInvestigationDto.VACCINE_ADMINISTERED_INCORRECTLY); + TextField vaccineAdministeredIncorrectlyDetails = + addField(vaccinesDetailsLayout, AefiInvestigationDto.VACCINE_ADMINISTERED_INCORRECTLY_DETAILS); + vaccineAdministeredIncorrectlyDetails.setCaption(null); + vaccineAdministeredIncorrectlyDetails.setInputPrompt(I18nProperties.getString(Strings.promptRemarks)); + + TextField numberImmunizedFromConcernedVaccineVial = + addField(vaccinesDetailsLayout, AefiInvestigationDto.NUMBER_IMMUNIZED_FROM_CONCERNED_VACCINE_VIAL, TextField.class); + numberImmunizedFromConcernedVaccineVial.setConversionError( + I18nProperties.getValidationError(Validations.onlyIntegerNumbersAllowed, numberImmunizedFromConcernedVaccineVial.getCaption())); + + TextField numberImmunizedFromConcernedVaccineInSameSession = + addField(vaccinesDetailsLayout, AefiInvestigationDto.NUMBER_IMMUNIZED_WITH_CONCERNED_VACCINE_IN_SAME_SESSION, TextField.class); + numberImmunizedFromConcernedVaccineInSameSession.setConversionError( + I18nProperties.getValidationError(Validations.onlyIntegerNumbersAllowed, numberImmunizedFromConcernedVaccineInSameSession.getCaption())); + + TextField numberImmunizedFromConcernedVaccineSameBatchNumberOtherLocationsSession = addField( + vaccinesDetailsLayout, + AefiInvestigationDto.NUMBER_IMMUNIZED_CONCERNED_VACCINE_SAME_BATCH_NUMBER_OTHER_LOCATIONS, + TextField.class); + numberImmunizedFromConcernedVaccineSameBatchNumberOtherLocationsSession.setConversionError( + I18nProperties.getValidationError( + Validations.onlyIntegerNumbersAllowed, + numberImmunizedFromConcernedVaccineSameBatchNumberOtherLocationsSession.getCaption())); + + addField(vaccinesDetailsLayout, AefiInvestigationDto.NUMBER_IMMUNIZED_CONCERNED_VACCINE_SAME_BATCH_NUMBER_LOCATION_DETAILS); + + addField(vaccinesDetailsLayout, AefiInvestigationDto.VACCINE_HAS_QUALITY_DEFECT); + TextField vaccineHasQualityDefectDetails = addField(vaccinesDetailsLayout, AefiInvestigationDto.VACCINE_HAS_QUALITY_DEFECT_DETAILS); + vaccineHasQualityDefectDetails.setCaption(null); + vaccineHasQualityDefectDetails.setInputPrompt(I18nProperties.getString(Strings.promptRemarks)); + + addField(vaccinesDetailsLayout, AefiInvestigationDto.EVENT_IS_A_STRESS_RESPONSE_RELATED_TO_IMMUNIZATION); + TextField eventIsStressResponseRelatedToImmunizationDetails = + addField(vaccinesDetailsLayout, AefiInvestigationDto.EVENT_IS_A_STRESS_RESPONSE_RELATED_TO_IMMUNIZATION_DETAILS); + eventIsStressResponseRelatedToImmunizationDetails.setCaption(null); + eventIsStressResponseRelatedToImmunizationDetails.setInputPrompt(I18nProperties.getString(Strings.promptRemarks)); + + addField(vaccinesDetailsLayout, AefiInvestigationDto.CASE_IS_PART_OF_A_CLUSTER, NullableOptionGroup.class); + addField(vaccinesDetailsLayout, AefiInvestigationDto.CASE_IS_PART_OF_A_CLUSTER_DETAILS); + + TextField numberOfCasesDetectedInCluster = + addField(vaccinesDetailsLayout, AefiInvestigationDto.NUMBER_OF_CASES_DETECTED_IN_CLUSTER, TextField.class); + numberOfCasesDetectedInCluster.setConversionError( + I18nProperties.getValidationError(Validations.onlyIntegerNumbersAllowed, numberOfCasesDetectedInCluster.getCaption())); + + addField(vaccinesDetailsLayout, AefiInvestigationDto.ALL_CASES_IN_CLUSTER_RECEIVED_VACCINE_FROM_SAME_VIAL, NullableOptionGroup.class); + addField(vaccinesDetailsLayout, AefiInvestigationDto.ALL_CASES_IN_CLUSTER_RECEIVED_VACCINE_FROM_SAME_VIAL_DETAILS); + + TextField numberOfVialsUsedInCluster = addField(vaccinesDetailsLayout, AefiInvestigationDto.NUMBER_OF_VIALS_USED_IN_CLUSTER, TextField.class); + numberOfVialsUsedInCluster + .setConversionError(I18nProperties.getValidationError(Validations.onlyIntegerNumbersAllowed, numberOfVialsUsedInCluster.getCaption())); + + accordion.addFormSectionPanel(Captions.titleAefiInvestigationVaccinesDetails, false, vaccinesDetailsLayout); + + //Immunization practices + CustomLayout immunizationPracticesLayout = new CustomLayout(); + immunizationPracticesLayout.setTemplateContents(IMMUNIZATION_PRACTICES_HTML_LAYOUT); + + Label syringesAndNeedlesUsedLabel = + new Label(I18nProperties.getCaption(Captions.titleAefiInvestigationImmunizationPracticesSyringesAndNeedlesUsed)); + syringesAndNeedlesUsedLabel.addStyleName(CssStyles.H4); + immunizationPracticesLayout.addComponent(syringesAndNeedlesUsedLabel, SYRINGES_AND_NEEDLES_HEADING_LOC); + + addField(immunizationPracticesLayout, AefiInvestigationDto.AD_SYRINGES_USED_FOR_IMMUNIZATION, NullableOptionGroup.class); + addField(immunizationPracticesLayout, AefiInvestigationDto.TYPE_OF_SYRINGES_USED, NullableOptionGroup.class); + addField(immunizationPracticesLayout, AefiInvestigationDto.TYPE_OF_SYRINGES_USED_DETAILS); + + TextArea syringesUsedAdditionalDetails = + addField(immunizationPracticesLayout, AefiInvestigationDto.SYRINGES_USED_ADDITIONAL_DETAILS, TextArea.class); + syringesUsedAdditionalDetails.setRows(6); + syringesUsedAdditionalDetails.setDescription( + I18nProperties.getPrefixDescription(AefiInvestigationDto.I18N_PREFIX, AefiInvestigationDto.SYRINGES_USED_ADDITIONAL_DETAILS, "") + "\n" + + I18nProperties.getDescription(Descriptions.descGdpr)); + + Label reconstitutionLabel = new Label(I18nProperties.getCaption(Captions.titleAefiInvestigationImmunizationPracticesReconstitution)); + reconstitutionLabel.addStyleName(CssStyles.H4); + immunizationPracticesLayout.addComponent(reconstitutionLabel, RECONSTITUTION_HEADING_LOC); + + addField(immunizationPracticesLayout, AefiInvestigationDto.SAME_RECONSTITUTION_SYRINGE_USED_FOR_MULTIPLE_VIALS_OF_SAME_VACCINE); + addField(immunizationPracticesLayout, AefiInvestigationDto.SAME_RECONSTITUTION_SYRINGE_USED_FOR_RECONSTITUTING_DIFFERENT_VACCINES); + addField(immunizationPracticesLayout, AefiInvestigationDto.SAME_RECONSTITUTION_SYRINGE_FOR_EACH_VACCINE_VIAL); + addField(immunizationPracticesLayout, AefiInvestigationDto.SAME_RECONSTITUTION_SYRINGE_FOR_EACH_VACCINATION); + addField(immunizationPracticesLayout, AefiInvestigationDto.VACCINES_AND_DILUENTS_USED_RECOMMENDED_BY_MANUFACTURER); + + TextArea reconstitutionAdditionalDetails = + addField(immunizationPracticesLayout, AefiInvestigationDto.RECONSTITUTION_ADDITIONAL_DETAILS, TextArea.class); + reconstitutionAdditionalDetails.setRows(6); + reconstitutionAdditionalDetails.setDescription( + I18nProperties.getPrefixDescription(AefiInvestigationDto.I18N_PREFIX, AefiInvestigationDto.RECONSTITUTION_ADDITIONAL_DETAILS, "") + "\n" + + I18nProperties.getDescription(Descriptions.descGdpr)); + + Label injectionTechniqueLabel = new Label(I18nProperties.getCaption(Captions.titleAefiInvestigationImmunizationPracticesInjectionTechnique)); + injectionTechniqueLabel.addStyleName(CssStyles.H4); + immunizationPracticesLayout.addComponent(injectionTechniqueLabel, INJECTION_TECHNIQUE_HEADING_LOC); + + addField(immunizationPracticesLayout, AefiInvestigationDto.CORRECT_DOSE_OR_ROUTE); + addField(immunizationPracticesLayout, AefiInvestigationDto.TIME_OF_RECONSTITUTION_MENTIONED_ON_THE_VIAL); + addField(immunizationPracticesLayout, AefiInvestigationDto.NON_TOUCH_TECHNIQUE_FOLLOWED); + addField(immunizationPracticesLayout, AefiInvestigationDto.CONTRAINDICATION_SCREENED_PRIOR_TO_VACCINATION); + + TextField numberOfAefiFromDistributionCenter = addField( + immunizationPracticesLayout, + AefiInvestigationDto.NUMBER_OF_AEFI_REPORTED_FROM_VACCINE_DISTRIBUTION_CENTER_LAST_THIRTY_DAYS, + TextField.class); + numberOfAefiFromDistributionCenter.setConversionError( + I18nProperties.getValidationError(Validations.onlyIntegerNumbersAllowed, numberOfAefiFromDistributionCenter.getCaption())); + + addField(immunizationPracticesLayout, AefiInvestigationDto.TRAINING_RECEIVED_BY_VACCINATOR, NullableOptionGroup.class); + addField(immunizationPracticesLayout, AefiInvestigationDto.LAST_TRAINING_RECEIVED_BY_VACCINATOR_DATE, DateField.class); + + TextArea injectionTechniqueAdditionalDetails = + addField(immunizationPracticesLayout, AefiInvestigationDto.INJECTION_TECHNIQUE_ADDITIONAL_DETAILS, TextArea.class); + injectionTechniqueAdditionalDetails.setRows(6); + injectionTechniqueAdditionalDetails.setDescription( + I18nProperties.getPrefixDescription(AefiInvestigationDto.I18N_PREFIX, AefiInvestigationDto.INJECTION_TECHNIQUE_ADDITIONAL_DETAILS, "") + + "\n" + I18nProperties.getDescription(Descriptions.descGdpr)); + + accordion.addFormSectionPanel(Captions.titleAefiInvestigationImmunizationPractices, false, immunizationPracticesLayout); + + //Cold chain and transport + CustomLayout coldChainAndTransportLayout = new CustomLayout(); + coldChainAndTransportLayout.setTemplateContents(COLD_CHAIN_AND_TRANSPORT_HTML_LAYOUT); + + Label lastVaccineStoragePointLabel = + new Label(I18nProperties.getCaption(Captions.titleAefiInvestigationColdChainAndTransportLastVaccineStoragePoint)); + lastVaccineStoragePointLabel.addStyleName(CssStyles.H4); + coldChainAndTransportLayout.addComponent(lastVaccineStoragePointLabel, VACCINE_STORAGE_POINT_HEADING_LOC); + + addField(coldChainAndTransportLayout, AefiInvestigationDto.VACCINE_STORAGE_REFRIGERATOR_TEMPERATURE_MONITORED); + addField(coldChainAndTransportLayout, AefiInvestigationDto.ANY_STORAGE_TEMPERATURE_DEVIATION_OUTSIDE_TWO_TO_EIGHT_DEGREES); + + TextArea storageTemperatureMonitoringDetails = + addField(coldChainAndTransportLayout, AefiInvestigationDto.STORAGE_TEMPERATURE_MONITORING_ADDITIONAL_DETAILS, TextArea.class); + storageTemperatureMonitoringDetails.setRows(6); + storageTemperatureMonitoringDetails.setDescription( + I18nProperties + .getPrefixDescription(AefiInvestigationDto.I18N_PREFIX, AefiInvestigationDto.STORAGE_TEMPERATURE_MONITORING_ADDITIONAL_DETAILS, "") + + "\n" + I18nProperties.getDescription(Descriptions.descGdpr)); + + addField(coldChainAndTransportLayout, AefiInvestigationDto.CORRECT_PROCEDURE_FOR_STORAGE_FOLLOWED); + addField(coldChainAndTransportLayout, AefiInvestigationDto.ANY_OTHER_ITEM_IN_REFRIGERATOR); + addField(coldChainAndTransportLayout, AefiInvestigationDto.PARTIALLY_USED_RECONSTITUTED_VACCINES_IN_REFRIGERATOR); + addField(coldChainAndTransportLayout, AefiInvestigationDto.UNUSABLE_VACCINES_IN_REFRIGERATOR); + addField(coldChainAndTransportLayout, AefiInvestigationDto.UNUSABLE_DILUENTS_IN_STORE); + + TextArea vaccineStoragePointAdditionalDetails = + addField(coldChainAndTransportLayout, AefiInvestigationDto.VACCINE_STORAGE_POINT_ADDITIONAL_DETAILS, TextArea.class); + vaccineStoragePointAdditionalDetails.setRows(6); + vaccineStoragePointAdditionalDetails.setDescription( + I18nProperties.getPrefixDescription(AefiInvestigationDto.I18N_PREFIX, AefiInvestigationDto.VACCINE_STORAGE_POINT_ADDITIONAL_DETAILS, "") + + "\n" + I18nProperties.getDescription(Descriptions.descGdpr)); + + Label vaccineTransportationLabel = + new Label(I18nProperties.getCaption(Captions.titleAefiInvestigationColdChainAndTransportVaccineTransportation)); + vaccineTransportationLabel.addStyleName(CssStyles.H4); + coldChainAndTransportLayout.addComponent(vaccineTransportationLabel, VACCINE_TRANSPORTATION_HEADING_LOC); + + addField(coldChainAndTransportLayout, AefiInvestigationDto.VACCINE_CARRIER_TYPE, NullableOptionGroup.class); + addField(coldChainAndTransportLayout, AefiInvestigationDto.VACCINE_CARRIER_SENT_TO_SITE_ON_SAME_DATE_AS_VACCINATION); + addField(coldChainAndTransportLayout, AefiInvestigationDto.VACCINE_CARRIER_RETURNED_FROM_SITE_ON_SAME_DATE_AS_VACCINATION); + addField(coldChainAndTransportLayout, AefiInvestigationDto.CONDITIONED_ICE_PACK_USED); + + TextArea vaccineTransportationAdditionalDetails = + addField(coldChainAndTransportLayout, AefiInvestigationDto.VACCINE_TRANSPORTATION_ADDITIONAL_DETAILS, TextArea.class); + vaccineTransportationAdditionalDetails.setRows(6); + vaccineTransportationAdditionalDetails.setDescription( + I18nProperties.getPrefixDescription(AefiInvestigationDto.I18N_PREFIX, AefiInvestigationDto.VACCINE_TRANSPORTATION_ADDITIONAL_DETAILS, "") + + "\n" + I18nProperties.getDescription(Descriptions.descGdpr)); + + accordion.addFormSectionPanel(Captions.titleAefiInvestigationColdChainAndTransport, false, coldChainAndTransportLayout); + + //Community investigation + CustomLayout communityInvestigationLayout = new CustomLayout(); + communityInvestigationLayout.setTemplateContents(COMMUNITY_INVESTIGATION_HTML_LAYOUT); + + addField(communityInvestigationLayout, AefiInvestigationDto.SIMILAR_EVENTS_REPORTED_SAME_PERIOD_AND_LOCALITY); + + TextArea similarEventsReportedSamePeriodDetails = + addField(communityInvestigationLayout, AefiInvestigationDto.SIMILAR_EVENTS_REPORTED_SAME_PERIOD_AND_LOCALITY_DETAILS, TextArea.class); + similarEventsReportedSamePeriodDetails.setRows(6); + similarEventsReportedSamePeriodDetails.setDescription( + I18nProperties.getPrefixDescription( + AefiInvestigationDto.I18N_PREFIX, + AefiInvestigationDto.SIMILAR_EVENTS_REPORTED_SAME_PERIOD_AND_LOCALITY_DETAILS, + "") + "\n" + I18nProperties.getDescription(Descriptions.descGdpr)); + + TextField numberOfSimilarEventsReportedInSamePeriod = + addField(communityInvestigationLayout, AefiInvestigationDto.NUMBER_OF_SIMILAR_EVENTS_REPORTED_SAME_PERIOD_AND_LOCALITY, TextField.class); + numberOfSimilarEventsReportedInSamePeriod.setConversionError( + I18nProperties.getValidationError(Validations.onlyIntegerNumbersAllowed, numberOfSimilarEventsReportedInSamePeriod.getCaption())); + + Label thoseAffectedLabelLabel = new Label(I18nProperties.getCaption(Captions.titleAefiInvestigationCommunityInvestigationThoseAffected)); + thoseAffectedLabelLabel.addStyleName(CssStyles.H4); + communityInvestigationLayout.addComponent(thoseAffectedLabelLabel, THOSE_AFFECTED_HEADING_LOC); + + TextField numberOfThoseAffectedVaccinated = + addField(communityInvestigationLayout, AefiInvestigationDto.NUMBER_OF_THOSE_AFFECTED_VACCINATED, TextField.class); + numberOfThoseAffectedVaccinated.setConversionError( + I18nProperties.getValidationError(Validations.onlyIntegerNumbersAllowed, numberOfThoseAffectedVaccinated.getCaption())); + + TextField numberOfThoseAffectedNotVaccinated = + addField(communityInvestigationLayout, AefiInvestigationDto.NUMBER_OF_THOSE_AFFECTED_NOT_VACCINATED, TextField.class); + numberOfThoseAffectedNotVaccinated.setConversionError( + I18nProperties.getValidationError(Validations.onlyIntegerNumbersAllowed, numberOfThoseAffectedNotVaccinated.getCaption())); + + TextField numberOfThoseAffectedVaccinatedUnknown = + addField(communityInvestigationLayout, AefiInvestigationDto.NUMBER_OF_THOSE_AFFECTED_VACCINATED_UNKNOWN, TextField.class); + numberOfThoseAffectedVaccinatedUnknown.setConversionError( + I18nProperties.getValidationError(Validations.onlyIntegerNumbersAllowed, numberOfThoseAffectedVaccinatedUnknown.getCaption())); + + TextArea communityInvestigationAdditionalDetails = + addField(communityInvestigationLayout, AefiInvestigationDto.COMMUNITY_INVESTIGATION_ADDITIONAL_DETAILS, TextArea.class); + communityInvestigationAdditionalDetails.setRows(6); + communityInvestigationAdditionalDetails.setDescription( + I18nProperties.getPrefixDescription(AefiInvestigationDto.I18N_PREFIX, AefiInvestigationDto.COMMUNITY_INVESTIGATION_ADDITIONAL_DETAILS, "") + + "\n" + I18nProperties.getDescription(Descriptions.descGdpr)); + + accordion.addFormSectionPanel(Captions.titleAefiInvestigationCommunityInvestigation, false, communityInvestigationLayout); + + //Other findings + CustomLayout otherFindingsLayout = new CustomLayout(); + otherFindingsLayout.setTemplateContents(OTHER_FINDINGS_HTML_LAYOUT); + + TextArea otherInvestigationFindingsDetails = addField(otherFindingsLayout, AefiInvestigationDto.OTHER_INVESTIGATION_FINDINGS, TextArea.class); + otherInvestigationFindingsDetails.setRows(6); + otherInvestigationFindingsDetails.setDescription( + I18nProperties.getPrefixDescription(AefiInvestigationDto.I18N_PREFIX, AefiInvestigationDto.OTHER_INVESTIGATION_FINDINGS, "") + "\n" + + I18nProperties.getDescription(Descriptions.descGdpr)); + + accordion.addFormSectionPanel(Captions.titleAefiInvestigationOtherFindings, true, otherFindingsLayout); + + //Investigation status + CustomLayout investigationStatusLayout = new CustomLayout(); + investigationStatusLayout.setTemplateContents(INVESTIGATION_STATUS_HTML_LAYOUT); + + addField(investigationStatusLayout, AefiInvestigationDto.INVESTIGATION_STATUS, NullableOptionGroup.class); + addField(investigationStatusLayout, AefiInvestigationDto.INVESTIGATION_STATUS_DETAILS); + addField(investigationStatusLayout, AefiInvestigationDto.AEFI_CLASSIFICATION, NullableOptionGroup.class); + TextArea aefiClassificationDetails = addField(investigationStatusLayout, AefiInvestigationDto.AEFI_CLASSIFICATION_DETAILS, TextArea.class); + aefiClassificationDetails.setRows(6); + aefiClassificationDetails.setDescription( + I18nProperties.getPrefixDescription(AefiInvestigationDto.I18N_PREFIX, AefiInvestigationDto.AEFI_CLASSIFICATION_DETAILS, "") + "\n" + + I18nProperties.getDescription(Descriptions.descGdpr)); + + accordion.addFormSectionPanel(Captions.titleAefiInvestigationInvestigationStatus, true, investigationStatusLayout); + + getContent().addComponent(accordion, MAIN_ACCORDION_LOC); + + //set visibility, read only and required status + FieldHelper.setVisibleWhen( + getFieldGroup(), + AefiInvestigationDto.PLACE_OF_VACCINATION_DETAILS, + AefiInvestigationDto.PLACE_OF_VACCINATION, + Arrays.asList(PlaceOfVaccination.OTHER), + true); + + FieldHelper.setVisibleWhen( + getFieldGroup(), + AefiInvestigationDto.VACCINATION_ACTIVITY_DETAILS, + AefiInvestigationDto.VACCINATION_ACTIVITY, + Arrays.asList(VaccinationActivity.OTHER), + true); + + FieldHelper.setVisibleWhen( + getFieldGroup(), + AefiInvestigationDto.TYPE_OF_SITE_DETAILS, + AefiInvestigationDto.TYPE_OF_SITE, + Arrays.asList(VaccinationSite.OTHER), + true); + + FieldHelper.setVisibleWhen( + getFieldGroup(), + Arrays.asList(AefiInvestigationDto.DEATH_DATE_TIME, AefiInvestigationDto.AUTOPSY_DONE), + AefiInvestigationDto.STATUS_ON_DATE_OF_INVESTIGATION, + Arrays.asList(PatientStatusAtAefiInvestigation.DIED), + true); + + FieldHelper.setVisibleWhen( + getFieldGroup(), + AefiInvestigationDto.AUTOPSY_DATE, + AefiInvestigationDto.AUTOPSY_DONE, + Arrays.asList(YesNoUnknown.YES), + true); + + FieldHelper.setVisibleWhen( + getFieldGroup(), + AefiInvestigationDto.AUTOPSY_PLANNED_DATE_TIME, + AefiInvestigationDto.AUTOPSY_DONE, + Arrays.asList(YesNoUnknown.NO), + true); + + FieldHelper.setVisibleWhen( + getFieldGroup(), + AefiInvestigationDto.PAST_HISTORY_OF_SIMILAR_EVENT_DETAILS, + AefiInvestigationDto.PAST_HISTORY_OF_SIMILAR_EVENT, + Arrays.asList(YesNoUnknown.YES), + true); + + FieldHelper.setVisibleWhen( + getFieldGroup(), + AefiInvestigationDto.ADVERSE_EVENT_AFTER_PREVIOUS_VACCINATIONS_DETAILS, + AefiInvestigationDto.ADVERSE_EVENT_AFTER_PREVIOUS_VACCINATIONS, + Arrays.asList(YesNoUnknown.YES), + true); + + FieldHelper.setVisibleWhen( + getFieldGroup(), + AefiInvestigationDto.HISTORY_OF_ALLERGY_TO_VACCINE_DRUG_OR_FOOD_DETAILS, + AefiInvestigationDto.HISTORY_OF_ALLERGY_TO_VACCINE_DRUG_OR_FOOD, + Arrays.asList(YesNoUnknown.YES), + true); + + FieldHelper.setVisibleWhen( + getFieldGroup(), + AefiInvestigationDto.PRE_EXISTING_ILLNESS_THIRTY_DAYS_OR_CONGENITAL_DISORDER_DETAILS, + AefiInvestigationDto.PRE_EXISTING_ILLNESS_THIRTY_DAYS_OR_CONGENITAL_DISORDER, + Arrays.asList(YesNoUnknown.YES), + true); + + FieldHelper.setVisibleWhen( + getFieldGroup(), + AefiInvestigationDto.HISTORY_OF_HOSPITALIZATION_IN_LAST_THIRTY_DAYS_WITH_CAUSE_DETAILS, + AefiInvestigationDto.HISTORY_OF_HOSPITALIZATION_IN_LAST_THIRTY_DAYS_WITH_CAUSE, + Arrays.asList(YesNoUnknown.YES), + true); + + FieldHelper.setVisibleWhen( + getFieldGroup(), + AefiInvestigationDto.CURRENTLY_ON_CONCOMITANT_MEDICATION_DETAILS, + AefiInvestigationDto.CURRENTLY_ON_CONCOMITANT_MEDICATION, + Arrays.asList(YesNoUnknown.YES), + true); + + FieldHelper.setVisibleWhen( + getFieldGroup(), + AefiInvestigationDto.FAMILY_HISTORY_OF_DISEASE_OR_ALLERGY_DETAILS, + AefiInvestigationDto.FAMILY_HISTORY_OF_DISEASE_OR_ALLERGY, + Arrays.asList(YesNoUnknown.YES), + true); + + FieldHelper.setVisibleWhen( + getFieldGroup(), + AefiInvestigationDto.DELIVERY_PROCEDURE_DETAILS, + AefiInvestigationDto.DELIVERY_PROCEDURE, + Arrays.asList(DeliveryProcedure.WITH_COMPLICATION), + true); + + FieldHelper.setVisibleWhen( + getFieldGroup(), + AefiInvestigationDto.TYPE_OF_SYRINGES_USED_DETAILS, + AefiInvestigationDto.TYPE_OF_SYRINGES_USED, + Arrays.asList(SyringeType.OTHER), + true); + + FieldHelper.setVisibleWhen( + getFieldGroup(), + AefiInvestigationDto.LAST_TRAINING_RECEIVED_BY_VACCINATOR_DATE, + AefiInvestigationDto.TRAINING_RECEIVED_BY_VACCINATOR, + Arrays.asList(YesNoUnknown.YES), + true); + + FieldHelper.setVisibleWhen( + getFieldGroup(), + Arrays.asList( + AefiInvestigationDto.SIMILAR_EVENTS_REPORTED_SAME_PERIOD_AND_LOCALITY_DETAILS, + AefiInvestigationDto.NUMBER_OF_SIMILAR_EVENTS_REPORTED_SAME_PERIOD_AND_LOCALITY), + AefiInvestigationDto.SIMILAR_EVENTS_REPORTED_SAME_PERIOD_AND_LOCALITY, + Arrays.asList(YesNoUnknown.YES), + true); + + setReadOnly(true, AefiDto.UUID, AefiDto.REPORTING_USER); + + setRequired(true, AefiInvestigationDto.REPORT_DATE, AefiInvestigationDto.INVESTIGATION_CASE_ID); + setRequired(true, AefiInvestigationDto.PLACE_OF_VACCINATION, AefiInvestigationDto.VACCINATION_ACTIVITY); + setRequired( + true, + AefiInvestigationDto.INVESTIGATION_DATE, + AefiInvestigationDto.FORM_COMPLETION_DATE, + AefiInvestigationDto.INVESTIGATION_STAGE); + setRequired(true, AefiInvestigationDto.TYPE_OF_SITE); + setRequired(true, AefiInvestigationDto.KEY_SYMPTOM_DATE_TIME); + setRequired(true, AefiInvestigationDto.STATUS_ON_DATE_OF_INVESTIGATION); + setRequired(true, AefiInvestigationDto.INVESTIGATION_STATUS, AefiInvestigationDto.AEFI_CLASSIFICATION); + } + + @Override + public void attach() { + super.attach(); + + AefiInvestigationDto dataFormValue = getValue(); + + AefiDto aefiDto = FacadeProvider.getAefiFacade().getByUuid(dataFormValue.getAefiReport().getUuid()); + ImmunizationDto immunizationDto = FacadeProvider.getImmunizationFacade().getByUuid(aefiDto.getImmunization().getUuid()); + + responsibleRegion.setValue(immunizationDto.getResponsibleRegion().getCaption()); + responsibleDistrict.setValue(immunizationDto.getResponsibleDistrict().getCaption()); + if (immunizationDto.getResponsibleCommunity() != null) { + responsibleCommunity.setValue(immunizationDto.getResponsibleCommunity().getCaption()); + } + + responsibleRegion.setReadOnly(true); + responsibleDistrict.setReadOnly(true); + responsibleCommunity.setReadOnly(true); + + vaccinationsField.applyAefiInvestigationContext(dataFormValue); + if (dataFormValue.getPrimarySuspectVaccine() != null) { + vaccinationsField.selectPrimarySuspectVaccination(dataFormValue.getPrimarySuspectVaccine()); + } + } + + @Override + public void setValue(AefiInvestigationDto newFieldValue) throws ReadOnlyException, Converter.ConversionException { + super.setValue(newFieldValue); + + getValue(); + + // 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(); + } + + @Override + public void discard() throws SourceException { + super.discard(); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationDataView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationDataView.java new file mode 100644 index 00000000000..30979b59ca1 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationDataView.java @@ -0,0 +1,132 @@ +/* + * 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.ui.adverseeventsfollowingimmunization; + +import java.util.ArrayList; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.EditPermissionType; +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationDto; +import de.symeda.sormas.api.immunization.ImmunizationDto; +import de.symeda.sormas.api.person.PersonDto; +import de.symeda.sormas.api.user.UserRight; +import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.UserProvider; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.information.AefiImmunizationInfo; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.information.AefiInfo; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.information.AefiPersonInfo; +import de.symeda.sormas.ui.utils.CommitDiscardWrapperComponent; +import de.symeda.sormas.ui.utils.CssStyles; +import de.symeda.sormas.ui.utils.DetailSubComponentWrapper; +import de.symeda.sormas.ui.utils.LayoutWithSidePanel; + +public class AefiInvestigationDataView extends AbstractAefiInvestigationDataView { + + public static final String VIEW_NAME = ROOT_VIEW_NAME + "/data"; + + public static final String ADVERSE_EVENT_LOC = "adverseEventLoc"; + public static final String PERSON_LOC = "personLoc"; + public static final String IMMUNIZATION_LOC = "immunizationLoc"; + + private CommitDiscardWrapperComponent editComponent; + + public AefiInvestigationDataView() { + super(VIEW_NAME); + } + + @Override + protected String getRootViewName() { + return super.getRootViewName(); + } + + @Override + protected void initView(String params) { + setHeightUndefined(); + + AefiInvestigationDto aefiInvestigationDto; + AefiDto aefiReport; + ImmunizationDto immunization; + + boolean isCreateAction = ControllerProvider.getAefiInvestigationController().isCreateAction(params); + if (isCreateAction) { + aefiInvestigationDto = AefiInvestigationDto.build(getReference()); + + String aefiReportUuid = ControllerProvider.getAefiInvestigationController().getCreateActionAefiReportUuid(params); + aefiReport = FacadeProvider.getAefiFacade().getByUuid(aefiReportUuid); + immunization = FacadeProvider.getImmunizationFacade().getByUuid(aefiReport.getImmunization().getUuid()); + + aefiInvestigationDto.setAefiReport(aefiReport.toReference()); + aefiInvestigationDto.setVaccinations(new ArrayList<>(immunization.getVaccinations())); + aefiInvestigationDto.setReportingUser(UserProvider.getCurrent().getUserReference()); + } else { + aefiInvestigationDto = FacadeProvider.getAefiInvestigationFacade().getByUuid(getReference().getUuid()); + aefiReport = FacadeProvider.getAefiFacade().getByUuid(aefiInvestigationDto.getAefiReport().getUuid()); + immunization = FacadeProvider.getImmunizationFacade().getByUuid(aefiReport.getImmunization().getUuid()); + } + + editComponent = ControllerProvider.getAefiInvestigationController() + .getAefiInvestigationDataEditComponent(isCreateAction, aefiInvestigationDto, this::showUnsavedChangesPopup); + + DetailSubComponentWrapper container = new DetailSubComponentWrapper(() -> editComponent); + container.setWidth(100, Unit.PERCENTAGE); + container.setMargin(true); + setSubComponent(container); + container.setEnabled(true); + + LayoutWithSidePanel layout = new LayoutWithSidePanel(editComponent, PERSON_LOC, ADVERSE_EVENT_LOC, IMMUNIZATION_LOC); + + container.addComponent(layout); + + UserProvider currentUser = UserProvider.getCurrent(); + if (currentUser.hasAllUserRights(UserRight.PERSON_VIEW)) { + + PersonDto personDto = FacadeProvider.getPersonFacade().getByUuid(immunization.getPerson().getUuid()); + Disease disease = immunization.getDisease(); + + AefiPersonInfo aefiPersonInfo = new AefiPersonInfo(personDto, disease); + CssStyles.style(aefiPersonInfo, CssStyles.VIEW_SECTION); + + layout.addSidePanelComponent(aefiPersonInfo, PERSON_LOC); + } + + if (currentUser.hasUserRight(UserRight.IMMUNIZATION_VIEW)) { + + AefiImmunizationInfo aefiImmunizationInfo = new AefiImmunizationInfo(immunization, (r) -> { + }); + CssStyles.style(aefiImmunizationInfo, CssStyles.VIEW_SECTION, CssStyles.VSPACE_TOP_3); + + layout.addSidePanelComponent(aefiImmunizationInfo, IMMUNIZATION_LOC); + } + + if (currentUser.hasUserRight(UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW)) { + + AefiInfo aefiInfo = new AefiInfo(aefiReport, (r) -> { + }); + CssStyles.style(aefiInfo, CssStyles.VIEW_SECTION, CssStyles.VSPACE_TOP_3); + + layout.addSidePanelComponent(aefiInfo, ADVERSE_EVENT_LOC); + } + + if (!isCreateAction) { + final String uuid = aefiInvestigationDto.getUuid(); + final EditPermissionType aefiInvestigationEditAllowed = FacadeProvider.getAefiInvestigationFacade().getEditPermissionType(uuid); + final boolean deleted = FacadeProvider.getAefiInvestigationFacade().isDeleted(uuid); + layout.disableIfNecessary(deleted, aefiInvestigationEditAllowed); + } + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationView.java new file mode 100644 index 00000000000..ebc4814cfd8 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationView.java @@ -0,0 +1,244 @@ +/* + * 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.ui.adverseeventsfollowingimmunization; + +import java.util.Collections; +import java.util.Objects; + +import org.vaadin.hene.popupbutton.PopupButton; + +import com.vaadin.icons.VaadinIcons; +import com.vaadin.navigator.ViewChangeListener; +import com.vaadin.server.FileDownloader; +import com.vaadin.server.StreamResource; +import com.vaadin.shared.ui.ContentMode; +import com.vaadin.shared.ui.MarginInfo; +import com.vaadin.ui.Alignment; +import com.vaadin.ui.Button; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.themes.ValoTheme; +import com.vaadin.v7.ui.ComboBox; + +import de.symeda.sormas.api.EntityRelevanceStatus; +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationCriteria; +import de.symeda.sormas.api.common.DeletableEntityType; +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; +import de.symeda.sormas.api.user.UserRight; +import de.symeda.sormas.ui.UserProvider; +import de.symeda.sormas.ui.ViewModelProviders; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.directory.AefiInvestigationDataLayout; +import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.directory.AefiInvestigationFilterFormLayout; +import de.symeda.sormas.ui.utils.ButtonHelper; +import de.symeda.sormas.ui.utils.ComboBoxHelper; +import de.symeda.sormas.ui.utils.CssStyles; +import de.symeda.sormas.ui.utils.ExportEntityName; +import de.symeda.sormas.ui.utils.GridExportStreamResource; +import de.symeda.sormas.ui.utils.ViewConfiguration; + +public class AefiInvestigationView extends AbstractAefiView { + + public static final String VIEW_NAME = "adverseeventinvestigations"; + + private final AefiInvestigationCriteria criteria; + + private AefiInvestigationFilterFormLayout filterFormLayout; + private final AefiInvestigationDataLayout dataLayout; + + // Filters + private Label relevanceStatusInfoLabel; + private ComboBox relevanceStatusFilter; + private ViewConfiguration viewConfiguration; + + public AefiInvestigationView() { + super(VIEW_NAME); + + CssStyles.style(getViewTitleLabel(), CssStyles.PAGE_TITLE); + + viewConfiguration = ViewModelProviders.of(getClass()).get(ViewConfiguration.class); + + criteria = ViewModelProviders.of(AefiInvestigationView.class).get(AefiInvestigationCriteria.class); + if (criteria.getRelevanceStatus() == null) { + criteria.setRelevanceStatus(EntityRelevanceStatus.ACTIVE); + } + dataLayout = new AefiInvestigationDataLayout(criteria); + + if (UserProvider.getCurrent().hasUserRight(UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT)) { + VerticalLayout exportLayout = new VerticalLayout(); + exportLayout.setSpacing(true); + exportLayout.setMargin(true); + exportLayout.addStyleName(CssStyles.LAYOUT_MINIMAL); + exportLayout.setWidth(200, Unit.PIXELS); + + PopupButton exportButton = ButtonHelper.createIconPopupButton(Captions.export, VaadinIcons.DOWNLOAD, exportLayout); + addHeaderComponent(exportButton); + + Button basicExportButton = ButtonHelper.createIconButton(Captions.exportBasic, VaadinIcons.TABLE, null, ValoTheme.BUTTON_PRIMARY); + basicExportButton.setDescription(I18nProperties.getString(Strings.infoBasicExport)); + basicExportButton.setWidth(100, Unit.PERCENTAGE); + exportLayout.addComponent(basicExportButton); + StreamResource streamResource = GridExportStreamResource.createStreamResourceWithSelectedItems( + dataLayout.getGrid(), + () -> viewConfiguration.isInEagerMode() ? dataLayout.getGrid().asMultiSelect().getSelectedItems() : Collections.emptySet(), + ExportEntityName.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_INVESTIGATION); + FileDownloader fileDownloader = new FileDownloader(streamResource); + fileDownloader.extend(basicExportButton); + } + + final VerticalLayout mainLayout = new VerticalLayout(); + mainLayout.addComponent(createFilterBar()); + + final VerticalLayout gridLayout = new VerticalLayout(); + gridLayout.setMargin(false); + gridLayout.setSpacing(false); + gridLayout.setSizeFull(); + CssStyles.style(gridLayout, CssStyles.VIEW_SECTION, CssStyles.VSPACE_TOP_3); + + gridLayout.addComponent(createStatusFilterBar()); + gridLayout.addComponent(dataLayout); + gridLayout.setExpandRatio(dataLayout, 1); + + mainLayout.addComponent(gridLayout); + + mainLayout.setMargin(new MarginInfo(false, true, true, true)); + mainLayout.setSpacing(false); + mainLayout.setSizeFull(); + mainLayout.setExpandRatio(gridLayout, 1); + mainLayout.addStyleNames("crud-main-layout", CssStyles.VSPACE_TOP_4); + + addComponent(mainLayout); + } + + private void updateFilterComponents() { + // TODO replace with Vaadin 8 databinding + applyingCriteria = true; + + if (relevanceStatusFilter != null) { + relevanceStatusFilter.setValue(criteria.getRelevanceStatus()); + } + + filterFormLayout.setValue(criteria); + + applyingCriteria = false; + } + + private AefiInvestigationFilterFormLayout createFilterBar() { + filterFormLayout = new AefiInvestigationFilterFormLayout(); + + filterFormLayout.addResetHandler(clickEvent -> { + ViewModelProviders.of(AefiInvestigationView.class).remove(AefiInvestigationCriteria.class); + navigateTo(null, true); + }); + + filterFormLayout.addApplyHandler(clickEvent -> { + dataLayout.refreshGrid(); + }); + + return filterFormLayout; + } + + public HorizontalLayout createStatusFilterBar() { + HorizontalLayout statusFilterLayout = new HorizontalLayout(); + statusFilterLayout.setSpacing(true); + statusFilterLayout.setMargin(false); + statusFilterLayout.setWidth(100, Unit.PERCENTAGE); + statusFilterLayout.addStyleName(CssStyles.VSPACE_3); + + HorizontalLayout actionButtonsLayout = new HorizontalLayout(); + actionButtonsLayout.setSpacing(true); + + // Show active/archived/all dropdown + if (Objects.nonNull(UserProvider.getCurrent()) + && UserProvider.getCurrent().hasUserRight(UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW)) { + + if (FacadeProvider.getFeatureConfigurationFacade() + .isFeatureEnabled(FeatureType.AUTOMATIC_ARCHIVING, DeletableEntityType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION)) { + + int daysAfterAefiEntryGetsArchived = FacadeProvider.getFeatureConfigurationFacade() + .getProperty( + FeatureType.AUTOMATIC_ARCHIVING, + DeletableEntityType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION, + FeatureTypeProperty.THRESHOLD_IN_DAYS, + Integer.class); + if (daysAfterAefiEntryGetsArchived > 0) { + relevanceStatusInfoLabel = new Label( + VaadinIcons.INFO_CIRCLE.getHtml() + " " + + String.format(I18nProperties.getString(Strings.infoArchivedAefiEntries), daysAfterAefiEntryGetsArchived), + ContentMode.HTML); + relevanceStatusInfoLabel.setVisible(false); + relevanceStatusInfoLabel.addStyleName(CssStyles.LABEL_VERTICAL_ALIGN_SUPER); + actionButtonsLayout.addComponent(relevanceStatusInfoLabel); + actionButtonsLayout.setComponentAlignment(relevanceStatusInfoLabel, Alignment.MIDDLE_RIGHT); + } + } + relevanceStatusFilter = ComboBoxHelper.createComboBoxV7(); + relevanceStatusFilter.setId("relevanceStatus"); + relevanceStatusFilter.setWidth(260, Unit.PIXELS); + relevanceStatusFilter.setNullSelectionAllowed(false); + relevanceStatusFilter.setTextInputAllowed(false); + relevanceStatusFilter.addItems((Object[]) EntityRelevanceStatus.values()); + relevanceStatusFilter.setItemCaption(EntityRelevanceStatus.ACTIVE, I18nProperties.getCaption(Captions.aefiActiveInvestigations)); + relevanceStatusFilter.setItemCaption(EntityRelevanceStatus.ARCHIVED, I18nProperties.getCaption(Captions.aefiArchivedInvestigations)); + relevanceStatusFilter.setItemCaption( + EntityRelevanceStatus.ACTIVE_AND_ARCHIVED, + I18nProperties.getCaption(Captions.aefiAllActiveAndArchivedInvestigations)); + relevanceStatusFilter.setCaption(null); + relevanceStatusFilter.addStyleName(CssStyles.VSPACE_NONE); + + if (UserProvider.getCurrent().hasUserRight(UserRight.IMMUNIZATION_DELETE)) { + relevanceStatusFilter.setItemCaption(EntityRelevanceStatus.DELETED, I18nProperties.getCaption(Captions.aefiDeletedInvestigations)); + } else { + relevanceStatusFilter.removeItem(EntityRelevanceStatus.DELETED); + } + + relevanceStatusFilter.addValueChangeListener(e -> { + if (relevanceStatusInfoLabel != null) { + relevanceStatusInfoLabel.setVisible(EntityRelevanceStatus.ARCHIVED.equals(e.getProperty().getValue())); + } + criteria.setRelevanceStatus((EntityRelevanceStatus) e.getProperty().getValue()); + navigateTo(criteria); + }); + actionButtonsLayout.addComponent(relevanceStatusFilter); + } + + if (actionButtonsLayout.getComponentCount() > 0) { + statusFilterLayout.addComponent(actionButtonsLayout); + statusFilterLayout.setComponentAlignment(actionButtonsLayout, Alignment.TOP_RIGHT); + statusFilterLayout.setExpandRatio(actionButtonsLayout, 1); + } + + return statusFilterLayout; + } + + @Override + public void enter(ViewChangeListener.ViewChangeEvent event) { + + String params = event.getParameters().trim(); + if (params.startsWith("?")) { + params = params.substring(1); + criteria.fromUrlParams(params); + } + updateFilterComponents(); + + super.enter(event); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiView.java index daa30665c50..ef58c7bc968 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiView.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiView.java @@ -1,37 +1,45 @@ /* * 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.ui.adverseeventsfollowingimmunization; +import java.util.Collections; import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import org.vaadin.hene.popupbutton.PopupButton; import com.vaadin.icons.VaadinIcons; import com.vaadin.navigator.ViewChangeListener; +import com.vaadin.server.FileDownloader; +import com.vaadin.server.StreamResource; import com.vaadin.shared.ui.ContentMode; +import com.vaadin.shared.ui.MarginInfo; import com.vaadin.ui.Alignment; +import com.vaadin.ui.Button; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.themes.ValoTheme; import com.vaadin.v7.ui.ComboBox; import de.symeda.sormas.api.EntityRelevanceStatus; import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiCriteria; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiIndexDto; import de.symeda.sormas.api.common.DeletableEntityType; import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.feature.FeatureTypeProperty; @@ -43,11 +51,15 @@ import de.symeda.sormas.ui.ViewModelProviders; import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.directory.AefiDataLayout; import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.directory.AefiFilterFormLayout; -import de.symeda.sormas.ui.utils.AbstractView; +import de.symeda.sormas.ui.utils.AefiDownloadUtil; +import de.symeda.sormas.ui.utils.ButtonHelper; import de.symeda.sormas.ui.utils.ComboBoxHelper; import de.symeda.sormas.ui.utils.CssStyles; +import de.symeda.sormas.ui.utils.ExportEntityName; +import de.symeda.sormas.ui.utils.GridExportStreamResource; +import de.symeda.sormas.ui.utils.ViewConfiguration; -public class AefiView extends AbstractView { +public class AefiView extends AbstractAefiView { public static final String VIEW_NAME = "adverseevents"; @@ -59,18 +71,53 @@ public class AefiView extends AbstractView { // Filters private Label relevanceStatusInfoLabel; private ComboBox relevanceStatusFilter; + private ViewConfiguration viewConfiguration; public AefiView() { super(VIEW_NAME); CssStyles.style(getViewTitleLabel(), CssStyles.PAGE_TITLE); + viewConfiguration = ViewModelProviders.of(getClass()).get(ViewConfiguration.class); + criteria = ViewModelProviders.of(AefiView.class).get(AefiCriteria.class); if (criteria.getRelevanceStatus() == null) { criteria.setRelevanceStatus(EntityRelevanceStatus.ACTIVE); } dataLayout = new AefiDataLayout(criteria); + if (UserProvider.getCurrent().hasUserRight(UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT)) { + VerticalLayout exportLayout = new VerticalLayout(); + exportLayout.setSpacing(true); + exportLayout.setMargin(true); + exportLayout.addStyleName(CssStyles.LAYOUT_MINIMAL); + exportLayout.setWidth(200, Unit.PIXELS); + + PopupButton exportButton = ButtonHelper.createIconPopupButton(Captions.export, VaadinIcons.DOWNLOAD, exportLayout); + addHeaderComponent(exportButton); + + Button basicExportButton = ButtonHelper.createIconButton(Captions.exportBasic, VaadinIcons.TABLE, null, ValoTheme.BUTTON_PRIMARY); + basicExportButton.setDescription(I18nProperties.getString(Strings.infoBasicExport)); + basicExportButton.setWidth(100, Unit.PERCENTAGE); + exportLayout.addComponent(basicExportButton); + StreamResource streamResource = GridExportStreamResource.createStreamResourceWithSelectedItems( + dataLayout.getGrid(), + () -> viewConfiguration.isInEagerMode() ? dataLayout.getGrid().asMultiSelect().getSelectedItems() : Collections.emptySet(), + ExportEntityName.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION); + FileDownloader fileDownloader = new FileDownloader(streamResource); + fileDownloader.extend(basicExportButton); + + StreamResource extendedExportStreamResource = + AefiDownloadUtil.createAefiExportResource(dataLayout.getGrid().getCriteria(), this::getSelectedRowUuids, null); + addExportButton( + extendedExportStreamResource, + exportButton, + exportLayout, + VaadinIcons.FILE_TEXT, + Captions.exportDetailed, + Strings.infoDetailedExport); + } + final VerticalLayout mainLayout = new VerticalLayout(); mainLayout.addComponent(createFilterBar()); @@ -86,11 +133,11 @@ public AefiView() { mainLayout.addComponent(gridLayout); - mainLayout.setMargin(true); + mainLayout.setMargin(new MarginInfo(false, true, true, true)); mainLayout.setSpacing(false); mainLayout.setSizeFull(); mainLayout.setExpandRatio(gridLayout, 1); - mainLayout.setStyleName("crud-main-layout"); + mainLayout.addStyleNames("crud-main-layout", CssStyles.VSPACE_TOP_4); addComponent(mainLayout); } @@ -195,6 +242,12 @@ public HorizontalLayout createStatusFilterBar() { return statusFilterLayout; } + private Set getSelectedRowUuids() { + return viewConfiguration.isInEagerMode() + ? dataLayout.getGrid().asMultiSelect().getSelectedItems().stream().map(AefiIndexDto::getUuid).collect(Collectors.toSet()) + : Collections.emptySet(); + } + @Override public void enter(ViewChangeListener.ViewChangeEvent event) { @@ -204,5 +257,7 @@ public void enter(ViewChangeListener.ViewChangeEvent event) { criteria.fromUrlParams(params); } updateFilterComponents(); + + super.enter(event); } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefiinvestigationlink/AefiInvestigationList.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefiinvestigationlink/AefiInvestigationList.java new file mode 100644 index 00000000000..7a78c37b890 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefiinvestigationlink/AefiInvestigationList.java @@ -0,0 +1,88 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.aefiinvestigationlink; + +import java.util.List; +import java.util.function.Consumer; + +import org.apache.commons.collections.CollectionUtils; + +import com.vaadin.ui.Button; +import com.vaadin.ui.Label; + +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationListCriteria; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationListEntryDto; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.i18n.Strings; +import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.utils.PaginationList; + +@SuppressWarnings("serial") +public class AefiInvestigationList extends PaginationList { + + private static final int MAX_DISPLAYED_ENTRIES = 5; + + private final AefiInvestigationListCriteria listCriteria; + private final Consumer actionCallback; + private final boolean isEditable; + private final Label noInvestigationsLabel; + + public AefiInvestigationList(AefiInvestigationListCriteria listCriteria, Consumer actionCallback, boolean isEditable) { + + super(MAX_DISPLAYED_ENTRIES); + + this.listCriteria = listCriteria; + this.actionCallback = actionCallback; + this.isEditable = isEditable; + + noInvestigationsLabel = new Label(I18nProperties.getString(Strings.infoNoAefiInvestigations)); + } + + @Override + public void reload() { + + List listEntries = + FacadeProvider.getAefiInvestigationFacade().getEntriesList(listCriteria, 0, maxDisplayedEntries * 20); + + setEntries(listEntries); + if (CollectionUtils.isNotEmpty(listEntries)) { + showPage(1); + } else { + listLayout.removeAllComponents(); + updatePaginationLayout(); + listLayout.addComponent(noInvestigationsLabel); + } + } + + @Override + protected void drawDisplayedEntries() { + + List displayedEntries = getDisplayedEntries(); + for (AefiInvestigationListEntryDto listEntryDto : displayedEntries) { + AefiInvestigationListEntry listEntry = new AefiInvestigationListEntry(listEntryDto); + + String aefiInvestigationUuid = listEntryDto.getUuid(); + listEntry.addEditButton( + "edit-aefiinvestigation-" + aefiInvestigationUuid, + (Button.ClickListener) event -> ControllerProvider.getAefiInvestigationController() + .navigateToAefiInvestigation(aefiInvestigationUuid)); + + listEntry.setEnabled(isEditable); + listLayout.addComponent(listEntry); + } + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefiinvestigationlink/AefiInvestigationListComponent.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefiinvestigationlink/AefiInvestigationListComponent.java new file mode 100644 index 00000000000..9faf3780c03 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefiinvestigationlink/AefiInvestigationListComponent.java @@ -0,0 +1,57 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.aefiinvestigationlink; + +import java.util.function.Consumer; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationListCriteria; +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.user.UserRight; +import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.utils.components.sidecomponent.SideComponent; + +@SuppressWarnings("serial") +public class AefiInvestigationListComponent extends SideComponent { + + public AefiInvestigationListComponent( + AefiInvestigationListCriteria listCriteria, + Consumer actionCallback, + boolean isEditAllowed, + boolean isCreateAction) { + super(I18nProperties.getString(Strings.headingAefiReportInvestigations), actionCallback); + + setMargin(false); + setWidth(100, Unit.PERCENTAGE); + + if (isEditAllowed) { + addCreateButton( + I18nProperties.getCaption(Captions.aefiNewAefiInvestigation), + () -> ControllerProvider.getAefiInvestigationController() + .navigateToAefiInvestigation("adverseevent/" + listCriteria.getAefiReport().getUuid() + "/investigation/create"), + UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE); + + if (isCreateAction) { + createButton.setEnabled(false); + } + } + + AefiInvestigationList aefiInvestigationList = new AefiInvestigationList(listCriteria, actionCallback, isEditAllowed); + addComponent(aefiInvestigationList); + aefiInvestigationList.reload(); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefiinvestigationlink/AefiInvestigationListEntry.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefiinvestigationlink/AefiInvestigationListEntry.java new file mode 100644 index 00000000000..74e571ef1cd --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefiinvestigationlink/AefiInvestigationListEntry.java @@ -0,0 +1,76 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.aefiinvestigationlink; + +import org.apache.commons.lang3.StringUtils; + +import com.vaadin.ui.Label; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationListEntryDto; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.ui.utils.CssStyles; +import de.symeda.sormas.ui.utils.DateFormatHelper; +import de.symeda.sormas.ui.utils.components.sidecomponent.SideComponentField; + +@SuppressWarnings("serial") +public class AefiInvestigationListEntry extends SideComponentField { + + public static final String SEPARATOR = ": "; + + private final AefiInvestigationListEntryDto listEntry; + + public AefiInvestigationListEntry(AefiInvestigationListEntryDto listEntry) { + + this.listEntry = listEntry; + + if (!StringUtils.isBlank(listEntry.getInvestigationCaseId())) { + Label labelCaseId = new Label(listEntry.getInvestigationCaseId()); + CssStyles.style(labelCaseId, CssStyles.LABEL_BOLD, CssStyles.LABEL_UPPERCASE); + addComponentToField(labelCaseId); + } + + Label labelInvestigationDate = new Label( + I18nProperties.getPrefixCaption(AefiInvestigationListEntryDto.I18N_PREFIX, AefiInvestigationListEntryDto.INVESTIGATION_DATE) + + SEPARATOR + + DateFormatHelper.formatLocalDate(listEntry.getInvestigationDate())); + addComponentToField(labelInvestigationDate); + + Label labelInvestigationStage = new Label( + I18nProperties.getPrefixCaption(AefiInvestigationListEntryDto.I18N_PREFIX, AefiInvestigationListEntryDto.INVESTIGATION_STAGE) + + SEPARATOR + + listEntry.getInvestigationStage()); + CssStyles.style(labelInvestigationStage, CssStyles.LABEL_BOLD, CssStyles.LABEL_UPPERCASE); + addComponentToField(labelInvestigationStage); + + Label labelStatusOnInvestigation = new Label( + I18nProperties.getPrefixCaption(AefiInvestigationListEntryDto.I18N_PREFIX, AefiInvestigationListEntryDto.STATUS_ON_DATE_OF_INVESTIGATION) + + SEPARATOR + + listEntry.getStatusOnDateOfInvestigation()); + CssStyles.style(labelStatusOnInvestigation, CssStyles.LABEL_BOLD, CssStyles.LABEL_UPPERCASE); + addComponentToField(labelStatusOnInvestigation); + + Label labelAefiClassification = new Label( + I18nProperties.getPrefixCaption(AefiInvestigationListEntryDto.I18N_PREFIX, AefiInvestigationListEntryDto.AEFI_CLASSIFICATION) + + SEPARATOR + + ((listEntry.getAefiClassification() != null) ? listEntry.getAefiClassification() : "")); + CssStyles.style(labelAefiClassification, CssStyles.LABEL_BOLD, CssStyles.LABEL_UPPERCASE); + addComponentToField(labelAefiClassification); + } + + public AefiInvestigationListEntryDto getListEntry() { + return listEntry; + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiListComponent.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiListComponent.java index 400715182cb..3503f05bbde 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiListComponent.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiListComponent.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -41,7 +38,7 @@ public AefiListComponent(AefiListCriteria aefiListCriteria, Consumer a addCreateButton( I18nProperties.getCaption(Captions.aefiNewAdverseEvent), () -> ControllerProvider.getAefiController() - .navigateToAefi("immunization/" + aefiListCriteria.getImmunization().getUuid() + "/create"), + .navigateToAefi("immunization/" + aefiListCriteria.getImmunization().getUuid() + "/adverseevent/create"), UserRight.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE); if (totalVaccinations == 0) { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiDataLayout.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiDataLayout.java index fa96538ee1e..8b96dd8bc29 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiDataLayout.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiDataLayout.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -36,6 +33,10 @@ public AefiDataLayout(AefiCriteria criteria) { setExpandRatio(grid, 1); } + public AefiGrid getGrid() { + return grid; + } + public void refreshGrid() { grid.reload(); } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiFilterForm.java index 3f83e93210e..5f1f4a47288 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiFilterForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiFilterForm.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -77,7 +74,7 @@ public AefiFilterForm() { @Override protected String createHtmlLayout() { return divCss( - CssStyles.VIEW_SECTION, + "", filterLocs(ArrayUtils.addAll(getMainFilterLocators(), ACTION_BUTTONS_ID)) + locCss(CssStyles.VSPACE_TOP_NONE, MORE_FILTERS_ID)); } @@ -86,7 +83,7 @@ protected String createHtmlLayout() { protected String[] getMainFilterLocators() { return new String[] { AefiCriteria.DISEASE, - AefiCriteria.NAME_ADDRESS_PHONE_EMAIL_LIKE, + AefiCriteria.PERSON_LIKE, AefiCriteria.AEFI_TYPE, AefiCriteria.VACCINE_NAME, AefiCriteria.REGION, @@ -105,10 +102,7 @@ protected void addFields() { addField(FieldConfiguration.pixelSized(AefiCriteria.DISEASE, 140)); final TextField searchField = addField( - FieldConfiguration.withCaptionAndPixelSized( - AefiCriteria.NAME_ADDRESS_PHONE_EMAIL_LIKE, - I18nProperties.getString(Strings.promptPersonsSearchField), - 200)); + FieldConfiguration.withCaptionAndPixelSized(AefiCriteria.PERSON_LIKE, I18nProperties.getString(Strings.promptPersonsSearchField), 200)); searchField.setNullRepresentation(""); addFields(FieldConfiguration.pixelSized(AefiCriteria.AEFI_TYPE, 140), FieldConfiguration.pixelSized(AefiCriteria.VACCINE_NAME, 140)); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiGrid.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiGrid.java index 8a27926187e..f89c5d7f240 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiGrid.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiGrid.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -20,6 +17,8 @@ import java.util.Date; +import org.apache.commons.lang3.StringUtils; + import com.vaadin.ui.renderers.DateRenderer; import com.vaadin.ui.renderers.TextRenderer; @@ -27,6 +26,7 @@ import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiCriteria; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiIndexDto; import de.symeda.sormas.api.caze.AgeAndBirthDateDto; +import de.symeda.sormas.api.caze.Vaccine; import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; @@ -42,12 +42,30 @@ public class AefiGrid extends FilteredGrid { + public static final String PRIMARY_VACCINE_COLUMN = "primaryVaccineColumn"; + public AefiGrid(AefiCriteria criteria) { super(AefiIndexDto.class); setSizeFull(); setLazyDataProvider(); setCriteria(criteria); + Column primaryVaccineColumn = addColumn(entry -> { + if (entry.getPrimaryVaccine() != null) { + if (entry.getPrimaryVaccine() != Vaccine.OTHER) { + return entry.getPrimaryVaccine().toString(); + } else { + return StringUtils.isBlank(entry.getPrimaryVaccineDetails()) + ? entry.getPrimaryVaccine().toString() + : (entry.getPrimaryVaccine() + " (" + entry.getPrimaryVaccineDetails() + ")"); + } + } else { + return "-"; + } + }); + primaryVaccineColumn.setId(PRIMARY_VACCINE_COLUMN); + primaryVaccineColumn.setCaption(I18nProperties.getPrefixCaption(AefiIndexDto.I18N_PREFIX, AefiIndexDto.PRIMARY_VACCINE_NAME)); + Column deleteColumn = addColumn(entry -> { if (entry.getDeletionReason() != null) { return entry.getDeletionReason() + (entry.getOtherDeletionReason() != null ? ": " + entry.getOtherDeletionReason() : ""); @@ -87,7 +105,7 @@ private void initColumns() { AefiIndexDto.REGION, AefiIndexDto.DISTRICT, AefiIndexDto.SERIOUS, - AefiIndexDto.PRIMARY_VACCINE_NAME, + PRIMARY_VACCINE_COLUMN, AefiIndexDto.OUTCOME, AefiIndexDto.VACCINATION_DATE, AefiIndexDto.REPORT_DATE, diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiInvestigationDataLayout.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiInvestigationDataLayout.java new file mode 100644 index 00000000000..e649ebc0473 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiInvestigationDataLayout.java @@ -0,0 +1,43 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.components.directory; + +import com.vaadin.ui.VerticalLayout; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationCriteria; + +public class AefiInvestigationDataLayout extends VerticalLayout { + + private final AefiInvestigationGrid grid; + + public AefiInvestigationDataLayout(AefiInvestigationCriteria criteria) { + grid = new AefiInvestigationGrid(criteria); + addComponent(grid); + + setMargin(false); + setSpacing(false); + setSizeFull(); + setExpandRatio(grid, 1); + } + + public AefiInvestigationGrid getGrid() { + return grid; + } + + public void refreshGrid() { + grid.reload(); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiInvestigationFilterForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiInvestigationFilterForm.java new file mode 100644 index 00000000000..c10376e2785 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiInvestigationFilterForm.java @@ -0,0 +1,418 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.components.directory; + +import static de.symeda.sormas.ui.utils.LayoutUtil.divCss; +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.Date; +import java.util.stream.Stream; + +import org.apache.commons.lang3.ArrayUtils; + +import com.vaadin.ui.CustomLayout; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.v7.data.Property; +import com.vaadin.v7.ui.ComboBox; +import com.vaadin.v7.ui.Field; +import com.vaadin.v7.ui.TextField; + +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationCriteria; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationDateType; +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.infrastructure.community.CommunityReferenceDto; +import de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto; +import de.symeda.sormas.api.infrastructure.facility.FacilityType; +import de.symeda.sormas.api.infrastructure.facility.FacilityTypeGroup; +import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto; +import de.symeda.sormas.api.user.JurisdictionLevel; +import de.symeda.sormas.api.user.UserDto; +import de.symeda.sormas.api.utils.DataHelper; +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.UserProvider; +import de.symeda.sormas.ui.utils.AbstractFilterForm; +import de.symeda.sormas.ui.utils.CssStyles; +import de.symeda.sormas.ui.utils.EpiWeekAndDateFilterComponent; +import de.symeda.sormas.ui.utils.FieldConfiguration; +import de.symeda.sormas.ui.utils.FieldHelper; + +public class AefiInvestigationFilterForm extends AbstractFilterForm { + + private static final String ACTION_BUTTONS_ID = "actionButtons"; + private static final String MORE_FILTERS_ID = "moreFilters"; + private static final String WEEK_AND_DATE_FILTER = "weekAndDateFilter"; + + private static final String MORE_FILTERS_HTML = loc(WEEK_AND_DATE_FILTER); + + public AefiInvestigationFilterForm() { + super( + AefiInvestigationCriteria.class, + AefiInvestigationCriteria.I18N_PREFIX, + JurisdictionFieldConfig.of(AefiInvestigationCriteria.REGION, AefiInvestigationCriteria.DISTRICT, AefiInvestigationCriteria.COMMUNITY)); + } + + @Override + protected String createHtmlLayout() { + return divCss( + "", + filterLocs(ArrayUtils.addAll(getMainFilterLocators(), ACTION_BUTTONS_ID)) + locCss(CssStyles.VSPACE_TOP_NONE, MORE_FILTERS_ID)); + + } + + @Override + protected String[] getMainFilterLocators() { + return new String[] { + AefiInvestigationCriteria.DISEASE, + AefiInvestigationCriteria.PERSON_LIKE, + AefiInvestigationCriteria.VACCINE_NAME, + AefiInvestigationCriteria.REGION, + AefiInvestigationCriteria.DISTRICT, + AefiInvestigationCriteria.COMMUNITY, + AefiInvestigationCriteria.STATUS_ON_DATE_OF_INVESTIGATION, + AefiInvestigationCriteria.AEFI_CLASSIFICATION }; + } + + @Override + protected String createMoreFiltersHtmlLayout() { + return MORE_FILTERS_HTML; + } + + @Override + protected void addFields() { + addField(FieldConfiguration.pixelSized(AefiInvestigationCriteria.DISEASE, 140)); + + final TextField searchField = addField( + FieldConfiguration + .withCaptionAndPixelSized(AefiInvestigationCriteria.PERSON_LIKE, I18nProperties.getString(Strings.promptPersonsSearchField), 200)); + searchField.setNullRepresentation(""); + + addFields( + FieldConfiguration.pixelSized(AefiInvestigationCriteria.AEFI_TYPE, 140), + FieldConfiguration.pixelSized(AefiInvestigationCriteria.VACCINE_NAME, 140)); + + if (currentUserDto().getRegion() == null) { + ComboBox regionFilter = addField(getContent(), FieldConfiguration.pixelSized(AefiInvestigationCriteria.REGION, 140)); + regionFilter.addItems(FacadeProvider.getRegionFacade().getAllActiveByServerCountry()); + } + + ComboBox districtFilter = addField(getContent(), FieldConfiguration.pixelSized(AefiInvestigationCriteria.DISTRICT, 140)); + districtFilter.setDescription(I18nProperties.getDescription(Descriptions.descDistrictFilter)); + if (currentUserDto().getDistrict() != null) { + districtFilter.setVisible(false); + } + + addField(getContent(), FieldConfiguration.pixelSized(AefiInvestigationCriteria.COMMUNITY, 140)); + + addField(FieldConfiguration.pixelSized(AefiInvestigationCriteria.STATUS_ON_DATE_OF_INVESTIGATION, 140)); + addField(FieldConfiguration.pixelSized(AefiInvestigationCriteria.AEFI_CLASSIFICATION, 140)); + } + + @Override + public void addMoreFilters(CustomLayout moreFiltersContainer) { + moreFiltersContainer.addComponent(buildWeekAndDateFilter(), WEEK_AND_DATE_FILTER); + } + + @Override + protected void applyDependenciesOnFieldChange(String propertyId, Property.ValueChangeEvent event) { + + super.applyDependenciesOnFieldChange(propertyId, event); + + final AefiInvestigationCriteria criteria = getValue(); + + final ComboBox facilityTypeGroupField = getField(AefiInvestigationCriteria.FACILITY_TYPE_GROUP); + final ComboBox facilityTypeField = getField(AefiInvestigationCriteria.FACILITY_TYPE); + final ComboBox facilityField = getField(AefiInvestigationCriteria.HEALTH_FACILITY); + + final UserDto user = currentUserDto(); + final DistrictReferenceDto currentDistrict = + user.getDistrict() != null ? user.getDistrict() : (DistrictReferenceDto) districtFilter.getValue(); + + switch (propertyId) { + case AefiInvestigationCriteria.REGION: { + final RegionReferenceDto region = user.getRegion() != null ? user.getRegion() : (RegionReferenceDto) event.getProperty().getValue(); + + if (!DataHelper.equal(region, criteria.getRegion())) { + if (region != null) { + enableFields(districtFilter); + FieldHelper.updateItems(districtFilter, FacadeProvider.getDistrictFacade().getAllActiveByRegion(region.getUuid())); + } else { + clearAndDisableFields(districtFilter); + } + clearAndDisableFields(communityFilter, facilityField, facilityTypeField, facilityTypeGroupField); + } + + break; + } + case AefiInvestigationCriteria.DISTRICT: { + final DistrictReferenceDto newDistrict = (DistrictReferenceDto) event.getProperty().getValue(); + + if (!DataHelper.equal(newDistrict, criteria.getDistrict())) { + if (newDistrict != null) { + enableFields(communityFilter, facilityTypeGroupField); + + clearAndDisableFields(facilityField); + if (facilityTypeGroupField != null) { + if (facilityTypeGroupField.getValue() != null && facilityTypeField.getValue() != null) { + FieldHelper.updateItems( + facilityField, + FacadeProvider.getFacilityFacade() + .getActiveFacilitiesByDistrictAndType(newDistrict, (FacilityType) facilityTypeField.getValue(), true, false)); + enableFields(facilityField); + } else { + FieldHelper.updateEnumData(facilityTypeGroupField, FacilityTypeGroup.getAccomodationGroups()); + } + } + + FieldHelper.updateItems(communityFilter, FacadeProvider.getCommunityFacade().getAllActiveByDistrict(newDistrict.getUuid())); + } else { + clearAndDisableFields(communityFilter, facilityField, facilityTypeField, facilityTypeGroupField); + } + } + + break; + } + case AefiInvestigationCriteria.COMMUNITY: { + CommunityReferenceDto community = (CommunityReferenceDto) event.getProperty().getValue(); + if (!DataHelper.equal(community, criteria.getCommunity())) { + if (facilityField != null) { + facilityField.setValue(null); + } + + final FacilityType facilityType = facilityTypeField != null ? (FacilityType) facilityTypeField.getValue() : null; + + if (facilityType == null && facilityField != null) { + facilityField.removeAllItems(); + } else if (facilityField != null) { + if (community == null) { + FieldHelper.updateItems( + facilityField, + FacadeProvider.getFacilityFacade().getActiveFacilitiesByDistrictAndType(currentDistrict, facilityType, true, false)); + } else { + FieldHelper.updateItems( + facilityField, + FacadeProvider.getFacilityFacade().getActiveFacilitiesByCommunityAndType(community, facilityType, true, false)); + } + } + } + break; + } + case AefiInvestigationCriteria.FACILITY_TYPE_GROUP: { + FacilityTypeGroup typeGroup = (FacilityTypeGroup) event.getProperty().getValue(); + if (!DataHelper.equal(typeGroup, criteria.getFacilityTypeGroup())) { + if (typeGroup != null) { + enableFields(AefiInvestigationCriteria.FACILITY_TYPE); + FieldHelper.updateEnumData(facilityTypeField, FacilityType.getAccommodationTypes(typeGroup)); + facilityField.setValue(null); + } else { + clearAndDisableFields(facilityTypeField, facilityField); + } + } + + break; + } + case AefiInvestigationCriteria.FACILITY_TYPE: { + FacilityType facilityType = (FacilityType) event.getProperty().getValue(); + if (!DataHelper.equal(facilityType, criteria.getFacilityType())) { + if (facilityType == null) { + clearAndDisableFields(facilityField); + } else { + enableFields(facilityField); + facilityField.setValue(null); + + CommunityReferenceDto community = (CommunityReferenceDto) communityFilter.getValue(); + if (community != null) { + FieldHelper.updateItems( + facilityField, + FacadeProvider.getFacilityFacade().getActiveFacilitiesByCommunityAndType(community, facilityType, true, false)); + } else if (currentDistrict != null) { + FieldHelper.updateItems( + facilityField, + FacadeProvider.getFacilityFacade().getActiveFacilitiesByDistrictAndType(currentDistrict, facilityType, true, false)); + } + } + } + break; + } + } + } + + @Override + protected void applyDependenciesOnNewValue(AefiInvestigationCriteria criteria) { + + final UserDto user = currentUserDto(); + + UserProvider currentUserProvider = UserProvider.getCurrent(); + final JurisdictionLevel userJurisdictionLevel = currentUserProvider != null ? UserProvider.getCurrent().getJurisdictionLevel() : null; + + final ComboBox facilityTypeGroupField = getField(AefiInvestigationCriteria.FACILITY_TYPE_GROUP); + final ComboBox facilityTypeField = getField(AefiInvestigationCriteria.FACILITY_TYPE); + final ComboBox facilityField = getField(AefiInvestigationCriteria.HEALTH_FACILITY); + + // Disable all fields + clearAndDisableFields(districtFilter, communityFilter, facilityTypeGroupField, facilityTypeField, facilityField); + + // Get initial field values according to user and criteria + final RegionReferenceDto region = user.getRegion() == null ? criteria.getRegion() : user.getRegion(); + final DistrictReferenceDto district = user.getDistrict() == null ? criteria.getDistrict() : user.getDistrict(); + final CommunityReferenceDto community = user.getCommunity() == null ? criteria.getCommunity() : user.getCommunity(); + final FacilityTypeGroup facilityTypeGroup = criteria.getFacilityTypeGroup(); + final FacilityType facilityType = criteria.getFacilityType(); + + // district + if (region != null) { + enableFields(districtFilter); + districtFilter.addItems(FacadeProvider.getDistrictFacade().getAllActiveByRegion(region.getUuid())); + // community + if (district != null) { + districtFilter.setValue(district); + communityFilter.addItems(FacadeProvider.getCommunityFacade().getAllActiveByDistrict(district.getUuid())); + enableFields(communityFilter); + if (community != null) { + communityFilter.setValue(community); + } + } else { + clearAndDisableFields(communityFilter); + } + } else { + clearAndDisableFields(districtFilter, communityFilter); + } + + // facility + if (userJurisdictionLevel == JurisdictionLevel.HEALTH_FACILITY) { + facilityField.setValue(user.getHealthFacility()); + disableFields(facilityTypeGroupField, facilityTypeField, facilityField); + } else if (facilityTypeGroupField != null && district != null) { + enableFields(facilityTypeGroupField); + FieldHelper.updateEnumData(facilityTypeGroupField, FacilityTypeGroup.getAccomodationGroups()); + if (facilityTypeGroup != null) { + facilityTypeGroupField.setValue(facilityTypeGroup); + enableFields(facilityTypeField); + FieldHelper.updateEnumData(facilityTypeField, FacilityType.getAccommodationTypes(facilityTypeGroup)); + if (facilityType != null) { + facilityTypeField.setValue(facilityType); + enableFields(facilityField); + if (community != null) { + facilityField + .addItems(FacadeProvider.getFacilityFacade().getActiveFacilitiesByCommunityAndType(community, facilityType, true, false)); + } else { + facilityField + .addItems(FacadeProvider.getFacilityFacade().getActiveFacilitiesByDistrictAndType(district, facilityType, true, false)); + } + } else { + disableFields(facilityField); + } + } else { + disableFields(facilityTypeField); + } + } + + // Disable fields according to user & jurisdiction + if (userJurisdictionLevel == JurisdictionLevel.DISTRICT) { + clearAndDisableFields(districtFilter); + } else if (userJurisdictionLevel == JurisdictionLevel.COMMUNITY) { + clearAndDisableFields(districtFilter, communityFilter); + } else if (userJurisdictionLevel == JurisdictionLevel.HEALTH_FACILITY) { + clearAndDisableFields(districtFilter, communityFilter, facilityTypeGroupField, facilityTypeField, facilityField); + } + + // Date/Epi week filter + HorizontalLayout dateFilterLayout = (HorizontalLayout) getMoreFiltersContainer().getComponent(WEEK_AND_DATE_FILTER); + @SuppressWarnings("unchecked") + EpiWeekAndDateFilterComponent weekAndDateFilter = + (EpiWeekAndDateFilterComponent) dateFilterLayout.getComponent(0); + + AefiInvestigationDateType aefiInvestigationDateType = criteria.getAefiInvestigationDateType(); + weekAndDateFilter.getDateTypeSelector().setValue(aefiInvestigationDateType); + weekAndDateFilter.getDateFilterOptionFilter().setValue(criteria.getDateFilterOption()); + Date dateFrom = criteria.getFromDate(); + Date dateTo = criteria.getToDate(); + + if (DateFilterOption.EPI_WEEK.equals(criteria.getDateFilterOption())) { + weekAndDateFilter.getWeekFromFilter().setValue(dateFrom == null ? null : DateHelper.getEpiWeek(dateFrom)); + weekAndDateFilter.getWeekToFilter().setValue(dateTo == null ? null : DateHelper.getEpiWeek(dateTo)); + } else { + weekAndDateFilter.getDateFromFilter().setValue(dateFrom); + weekAndDateFilter.getDateToFilter().setValue(dateTo); + } + } + + @Override + protected Stream streamFieldsForEmptyCheck(CustomLayout layout) { + HorizontalLayout dateFilterLayout = (HorizontalLayout) getMoreFiltersContainer().getComponent(WEEK_AND_DATE_FILTER); + EpiWeekAndDateFilterComponent weekAndDateFilter = + (EpiWeekAndDateFilterComponent) dateFilterLayout.getComponent(0); + + return super.streamFieldsForEmptyCheck(layout).filter(f -> f != weekAndDateFilter.getDateFilterOptionFilter()); + } + + private HorizontalLayout buildWeekAndDateFilter() { + + EpiWeekAndDateFilterComponent weekAndDateFilter = new EpiWeekAndDateFilterComponent<>( + false, + false, + null, + AefiInvestigationDateType.values(), + I18nProperties.getString(Strings.promptAefiInvestigationDateType), + null, + this); + weekAndDateFilter.getWeekFromFilter().setInputPrompt(I18nProperties.getString(Strings.promptAefiInvestigationEpiWeekFrom)); + weekAndDateFilter.getWeekToFilter().setInputPrompt(I18nProperties.getString(Strings.promptAefiInvestigationEpiWeekTo)); + weekAndDateFilter.getDateFromFilter().setInputPrompt(I18nProperties.getString(Strings.promptAefiInvestigationDateFrom)); + weekAndDateFilter.getDateToFilter().setInputPrompt(I18nProperties.getString(Strings.promptAefiInvestigationDateTo)); + + addApplyHandler(e -> onApplyClick(weekAndDateFilter)); + + HorizontalLayout dateFilterRowLayout = new HorizontalLayout(); + dateFilterRowLayout.setSpacing(true); + dateFilterRowLayout.setSizeUndefined(); + + dateFilterRowLayout.addComponent(weekAndDateFilter); + + return dateFilterRowLayout; + } + + private void onApplyClick(EpiWeekAndDateFilterComponent weekAndDateFilter) { + AefiInvestigationCriteria criteria = getValue(); + + DateFilterOption dateFilterOption = (DateFilterOption) weekAndDateFilter.getDateFilterOptionFilter().getValue(); + Date fromDate, toDate; + if (dateFilterOption == DateFilterOption.DATE) { + Date dateFrom = weekAndDateFilter.getDateFromFilter().getValue(); + fromDate = dateFrom != null ? DateHelper.getStartOfDay(dateFrom) : null; + Date dateTo = weekAndDateFilter.getDateToFilter().getValue(); + toDate = dateFrom != null ? DateHelper.getEndOfDay(dateTo) : null; + } else { + fromDate = DateHelper.getEpiWeekStart((EpiWeek) weekAndDateFilter.getWeekFromFilter().getValue()); + toDate = DateHelper.getEpiWeekEnd((EpiWeek) weekAndDateFilter.getWeekToFilter().getValue()); + } + if ((fromDate != null && toDate != null) || (fromDate == null && toDate == null)) { + criteria.setDateFilterOption(dateFilterOption); + AefiInvestigationDateType aefiInvestigationDateType = (AefiInvestigationDateType) weekAndDateFilter.getDateTypeSelector().getValue(); + criteria.setAefiInvestigationDateType(aefiInvestigationDateType); + criteria.setFromDate(fromDate); + criteria.setToDate(toDate); + } else { + weekAndDateFilter.setNotificationsForMissingFilters(); + } + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiInvestigationFilterFormLayout.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiInvestigationFilterFormLayout.java new file mode 100644 index 00000000000..eddd5ee5c8b --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiInvestigationFilterFormLayout.java @@ -0,0 +1,53 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.components.directory; + +import com.vaadin.ui.Button; +import com.vaadin.ui.VerticalLayout; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationCriteria; + +public class AefiInvestigationFilterFormLayout extends VerticalLayout { + + private static final float PERCENTAGE_WIDTH = 100; + + private final AefiInvestigationFilterForm filterForm; + + public AefiInvestigationFilterFormLayout() { + setSpacing(false); + setMargin(false); + setWidth(PERCENTAGE_WIDTH, Unit.PERCENTAGE); + + filterForm = new AefiInvestigationFilterForm(); + addComponent(filterForm); + } + + public AefiInvestigationCriteria getValue() { + return filterForm.getValue(); + } + + public void setValue(AefiInvestigationCriteria criteria) { + filterForm.setValue(criteria); + } + + public void addResetHandler(Button.ClickListener listener) { + filterForm.addResetHandler(listener); + } + + public void addApplyHandler(Button.ClickListener listener) { + filterForm.addApplyHandler(listener); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiInvestigationGrid.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiInvestigationGrid.java new file mode 100644 index 00000000000..a0575b79a3f --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/directory/AefiInvestigationGrid.java @@ -0,0 +1,151 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.components.directory; + +import java.util.Date; + +import org.apache.commons.lang3.StringUtils; + +import com.vaadin.ui.renderers.DateRenderer; +import com.vaadin.ui.renderers.TextRenderer; + +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationCriteria; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationIndexDto; +import de.symeda.sormas.api.caze.AgeAndBirthDateDto; +import de.symeda.sormas.api.caze.Vaccine; +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.person.PersonHelper; +import de.symeda.sormas.ui.ControllerProvider; +import de.symeda.sormas.ui.UiUtil; +import de.symeda.sormas.ui.utils.DateFormatHelper; +import de.symeda.sormas.ui.utils.FieldAccessColumnStyleGenerator; +import de.symeda.sormas.ui.utils.FilteredGrid; +import de.symeda.sormas.ui.utils.ShowDetailsListener; +import de.symeda.sormas.ui.utils.UuidRenderer; + +public class AefiInvestigationGrid extends FilteredGrid { + + public static final String PRIMARY_VACCINE_COLUMN = "primaryVaccineColumn"; + + public AefiInvestigationGrid(AefiInvestigationCriteria criteria) { + super(AefiInvestigationIndexDto.class); + setSizeFull(); + setLazyDataProvider(); + setCriteria(criteria); + + Column primaryVaccineColumn = addColumn(entry -> { + if (entry.getPrimaryVaccine() != null) { + if (entry.getPrimaryVaccine() != Vaccine.OTHER) { + return entry.getPrimaryVaccine().toString(); + } else { + return StringUtils.isBlank(entry.getPrimaryVaccineDetails()) + ? entry.getPrimaryVaccine().toString() + : (entry.getPrimaryVaccine() + " (" + entry.getPrimaryVaccineDetails() + ")"); + } + } else { + return "-"; + } + }); + primaryVaccineColumn.setId(PRIMARY_VACCINE_COLUMN); + primaryVaccineColumn + .setCaption(I18nProperties.getPrefixCaption(AefiInvestigationIndexDto.I18N_PREFIX, AefiInvestigationIndexDto.PRIMARY_VACCINE_NAME)); + + Column deleteColumn = addColumn(entry -> { + if (entry.getDeletionReason() != null) { + return entry.getDeletionReason() + (entry.getOtherDeletionReason() != null ? ": " + entry.getOtherDeletionReason() : ""); + } else { + return "-"; + } + }); + deleteColumn.setId(DELETE_REASON_COLUMN); + deleteColumn.setSortable(false); + deleteColumn.setCaption(I18nProperties.getCaption(Captions.deletionReason)); + + initColumns(); + + addItemClickListener( + new ShowDetailsListener<>( + AefiInvestigationIndexDto.UUID, + e -> ControllerProvider.getAefiInvestigationController().navigateToAefiInvestigation(e.getUuid()))); + addItemClickListener(new ShowDetailsListener<>(AefiInvestigationIndexDto.AEFI_REPORT_UUID, e -> { + ControllerProvider.getAefiController().navigateToAefi(e.getAefiReportUuid()); + })); + } + + public void reload() { + getDataProvider().refreshAll(); + } + + private void initColumns() { + setColumns( + AefiInvestigationIndexDto.UUID, + AefiInvestigationIndexDto.INVESTIGATION_CASE_ID, + AefiInvestigationIndexDto.AEFI_REPORT_UUID, + AefiInvestigationIndexDto.PERSON_FIRST_NAME, + AefiInvestigationIndexDto.PERSON_LAST_NAME, + AefiInvestigationIndexDto.DISEASE, + AefiInvestigationIndexDto.AGE_AND_BIRTH_DATE, + AefiInvestigationIndexDto.SEX, + AefiInvestigationIndexDto.REGION, + AefiInvestigationIndexDto.DISTRICT, + PRIMARY_VACCINE_COLUMN, + AefiInvestigationIndexDto.STATUS_ON_DATE_OF_INVESTIGATION, + AefiInvestigationIndexDto.INVESTIGATION_STATUS, + AefiInvestigationIndexDto.AEFI_CLASSIFICATION, + AefiInvestigationIndexDto.REPORT_DATE, + AefiInvestigationIndexDto.INVESTIGATION_DATE, + AefiInvestigationIndexDto.INVESTIGATION_STAGE, + DELETE_REASON_COLUMN); + + ((Column) getColumn(AefiInvestigationIndexDto.UUID)).setRenderer(new UuidRenderer()); + ((Column) getColumn(AefiInvestigationIndexDto.AEFI_REPORT_UUID)).setRenderer(new UuidRenderer()); + + ((Column) getColumn(AefiInvestigationIndexDto.AGE_AND_BIRTH_DATE)).setRenderer( + value -> value == null + ? "" + : PersonHelper.getAgeAndBirthdateString( + value.getAge(), + value.getAgeType(), + value.getDateOfBirthDD(), + value.getDateOfBirthMM(), + value.getDateOfBirthYYYY()), + new TextRenderer()); + + ((Column) getColumn(AefiInvestigationIndexDto.REPORT_DATE)) + .setRenderer(new DateRenderer(DateFormatHelper.getDateFormat())); + ((Column) getColumn(AefiInvestigationIndexDto.INVESTIGATION_DATE)) + .setRenderer(new DateRenderer(DateFormatHelper.getDateFormat())); + + for (Column column : getColumns()) { + column + .setCaption(I18nProperties.findPrefixCaptionWithDefault(column.getId(), column.getCaption(), AefiInvestigationIndexDto.I18N_PREFIX)); + column.setStyleGenerator(FieldAccessColumnStyleGenerator.getDefault(getBeanType(), column.getId())); + } + + if (UiUtil.enabled(FeatureType.HIDE_JURISDICTION_FIELDS)) { + getColumn(AefiInvestigationIndexDto.REGION).setHidden(true); + getColumn(AefiInvestigationIndexDto.DISTRICT).setHidden(true); + } + } + + private void setLazyDataProvider() { + + setLazyDataProvider(FacadeProvider.getAefiInvestigationFacade()::getIndexList, FacadeProvider.getAefiInvestigationFacade()::count); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiVaccinationsField.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiVaccinationsField.java index 03742120e3a..8597fdac53a 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiVaccinationsField.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiVaccinationsField.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -29,6 +26,7 @@ import com.vaadin.v7.ui.Table; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationDto; import de.symeda.sormas.api.caze.Vaccine; import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; @@ -41,7 +39,10 @@ public class AefiVaccinationsField extends AbstractTableField { private AefiDto aefiDto; + private AefiInvestigationDto aefiInvestigationDto; private VaccinationDto primarySuspectVaccination; + private boolean aefiReportContext; + private boolean aefiInvestigationContext; private final UiFieldAccessCheckers fieldAccessCheckers; public AefiVaccinationsField(UiFieldAccessCheckers fieldAccessCheckers) { @@ -60,7 +61,12 @@ public Class getEntryType() { protected void editEntry(VaccinationDto entry, boolean create, Consumer commitCallback) { if (create) { - ControllerProvider.getAefiController().selectPrimarySuspectVaccination(aefiDto, this::selectPrimarySuspectVaccination); + if (aefiReportContext) { + ControllerProvider.getAefiController().selectPrimarySuspectVaccination(aefiDto, this::selectPrimarySuspectVaccination); + } else if (aefiInvestigationContext) { + ControllerProvider.getAefiInvestigationController() + .selectPrimarySuspectVaccination(aefiInvestigationDto, this::selectPrimarySuspectVaccination); + } } } @@ -68,30 +74,6 @@ public void updateAddButtonCaption() { getAddButton().setCaption(I18nProperties.getCaption(Captions.actionAefiSelectPrimarySuspectVaccination)); } - /* - * @Override - * protected VaccinationDto createEntry() { - * UserDto user = UserProvider.getCurrent().getUser(); - * return VaccinationDto.build(user.toReference()); - * } - */ - - /* - * @Override - * protected Table createTable() { - * Table table = super.createTable(); - * table.addGeneratedColumn(VaccinationDto.UUID, (Table.ColumnGenerator) (source, itemId, columnId) -> { - * Label textField = new Label(DataHelper.getShortUuid(((EntityDto) itemId).getUuid())); - * return textField; - * }); - * table.addGeneratedColumn(VaccinationDto.VACCINATION_DATE, (Table.ColumnGenerator) (source, itemId, columnId) -> { - * Label textField = new Label(DateFormatHelper.formatDate(((VaccinationDto) itemId).getVaccinationDate())); - * return textField; - * }); - * return table; - * } - */ - @Override protected void updateColumns() { Table table = getTable(); @@ -175,12 +157,22 @@ public void refreshTable() { } container.removeAllItems(); - container.addAll(aefiDto.getVaccinations()); + if (aefiReportContext) { + container.addAll(aefiDto.getVaccinations()); + } else { + container.addAll(aefiInvestigationDto.getVaccinations()); + } table.refreshRowCache(); } - public void setAefiDto(AefiDto aefiDto) { + public void applyAefiReportContext(AefiDto aefiDto) { this.aefiDto = aefiDto; + aefiReportContext = true; + } + + public void applyAefiInvestigationContext(AefiInvestigationDto aefiInvestigationDto) { + this.aefiInvestigationDto = aefiInvestigationDto; + aefiInvestigationContext = true; } public void selectPrimarySuspectVaccination(VaccinationDto vaccinationDto) { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiVaccinationsField_2.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiVaccinationsField_2.java deleted file mode 100644 index 659ae920839..00000000000 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/fields/vaccines/AefiVaccinationsField_2.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * 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.ui.adverseeventsfollowingimmunization.components.fields.vaccines; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.vaadin.ui.Alignment; -import com.vaadin.ui.Button; -import com.vaadin.ui.Component; -import com.vaadin.ui.Grid; -import com.vaadin.ui.HorizontalLayout; -import com.vaadin.ui.Label; -import com.vaadin.ui.VerticalLayout; -import com.vaadin.ui.themes.ValoTheme; -import com.vaadin.v7.data.Property; -import com.vaadin.v7.data.util.converter.Converter; -import com.vaadin.v7.ui.CustomField; - -import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; -import de.symeda.sormas.api.caze.Vaccine; -import de.symeda.sormas.api.caze.VaccineManufacturer; -import de.symeda.sormas.api.i18n.Captions; -import de.symeda.sormas.api.i18n.I18nProperties; -import de.symeda.sormas.api.utils.fieldaccess.UiFieldAccessCheckers; -import de.symeda.sormas.api.vaccination.VaccinationDto; -import de.symeda.sormas.ui.ControllerProvider; -import de.symeda.sormas.ui.utils.ButtonHelper; -import de.symeda.sormas.ui.utils.CssStyles; -import de.symeda.sormas.ui.utils.DateFormatHelper; - -@SuppressWarnings({ - "serial", - "rawtypes" }) -public class AefiVaccinationsField_2 extends CustomField { - - private final Logger logger = LoggerFactory.getLogger(getClass()); - - private VerticalLayout mainLayout; - private Label captionLabel; - private Button addButton; - private Grid vaccinationGrid; - private List value = new ArrayList<>(); - private AefiDto aefiDto; - private VaccinationDto primarySuspectVaccination; - protected UiFieldAccessCheckers fieldAccessCheckers; - - public AefiVaccinationsField_2(UiFieldAccessCheckers fieldAccessCheckers) { - this.fieldAccessCheckers = fieldAccessCheckers; - - getContent(); - //setValue(value); - } - - public void initializeGrid() { - - vaccinationGrid = new Grid<>(); - vaccinationGrid.setSizeFull(); - vaccinationGrid.setSelectionMode(Grid.SelectionMode.SINGLE); - /* vaccinationGrid.setHeightMode(HeightMode.ROW); */ - - vaccinationGrid.addColumn(vaccinationDto -> DateFormatHelper.formatDate(vaccinationDto.getVaccinationDate())) - .setCaption(I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, VaccinationDto.VACCINATION_DATE)); - - vaccinationGrid - .addColumn( - vaccinationDto -> Vaccine.OTHER.equals(vaccinationDto.getVaccineName()) - ? vaccinationDto.getOtherVaccineName() - : vaccinationDto.getVaccineName()) - .setCaption(I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, VaccinationDto.VACCINE_NAME)); - - vaccinationGrid - .addColumn( - vaccinationDto -> VaccineManufacturer.OTHER.equals(vaccinationDto.getVaccineManufacturer()) - ? vaccinationDto.getOtherVaccineManufacturer() - : vaccinationDto.getVaccineManufacturer()) - .setCaption(I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, VaccinationDto.VACCINE_MANUFACTURER)); - - vaccinationGrid.addColumn(VaccinationDto::getVaccineType) - .setCaption(I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, VaccinationDto.VACCINE_TYPE)); - - vaccinationGrid.addColumn(VaccinationDto::getVaccineDose) - .setCaption(I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, VaccinationDto.VACCINE_DOSE)); - - vaccinationGrid.setStyleGenerator(vaccinationDto -> { - if (primarySuspectVaccination != null) { - return vaccinationDto.getUuid().equals(primarySuspectVaccination.getUuid()) ? CssStyles.GRID_ROW_SELECTED : null; - } - return null; - }); - } - - @Override - protected Component initContent() { - mainLayout = new VerticalLayout(); - mainLayout.setSpacing(false); - mainLayout.setMargin(false); - - HorizontalLayout headerLayout = new HorizontalLayout(); - { - headerLayout.setWidth(100, Unit.PERCENTAGE); - - captionLabel = new Label(getCaption()); - captionLabel.setSizeUndefined(); - headerLayout.addComponent(captionLabel); - headerLayout.setComponentAlignment(captionLabel, Alignment.BOTTOM_LEFT); - headerLayout.setExpandRatio(captionLabel, 0); - - addButton = ButtonHelper.createButton(Captions.actionAefiSelectPrimarySuspectVaccination, (event) -> { - ControllerProvider.getAefiController().selectPrimarySuspectVaccination(aefiDto, this::selectPrimarySuspectVaccination); - }, ValoTheme.BUTTON_LINK); - headerLayout.addComponent(addButton); - headerLayout.setComponentAlignment(addButton, Alignment.BOTTOM_RIGHT); - headerLayout.setExpandRatio(addButton, 1); - } - mainLayout.addComponent(headerLayout); - - initializeGrid(); - mainLayout.addComponent(vaccinationGrid); - - return mainLayout; - } - - @Override - public Class getType() { - return Collection.class; - } - - @Override - public void setPropertyDataSource(Property newDataSource) { - super.setPropertyDataSource(newDataSource); - } - - /* - * @Override - * protected void setValue(Collection newFieldValue, boolean repaintIsNotNeeded, boolean ignoreReadOnly) - * throws ReadOnlyException, Converter.ConversionException, Validator.InvalidValueException { - * super.setValue(newFieldValue, repaintIsNotNeeded, ignoreReadOnly); - * value = new ArrayList<>(newFieldValue); - * vaccinationGrid.setItems(newFieldValue); - * fireValueChange(repaintIsNotNeeded); - * } - */ - - @Override - public void setValue(Collection newFieldValue) throws ReadOnlyException, Converter.ConversionException { - value = new ArrayList<>(newFieldValue); - vaccinationGrid.setItems(newFieldValue); - - super.setValue(newFieldValue); - } - - /* - * @Override - * protected void doSetValue(Collection collection) { - * value = new ArrayList<>(collection); - * vaccinationGrid.setItems(collection); - * } - */ - - @Override - public Collection getValue() { - return value; - } - - public void setAefiDto(AefiDto aefiDto) { - this.aefiDto = aefiDto; - } - - public void setPrimarySuspectVaccination(VaccinationDto primarySuspectVaccination) { - this.primarySuspectVaccination = primarySuspectVaccination; - } - - public void selectPrimarySuspectVaccination(VaccinationDto vaccinationDto) { - primarySuspectVaccination = vaccinationDto; - vaccinationGrid.select(primarySuspectVaccination); - } -} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/AdverseEventsForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/AdverseEventsForm.java index 4eade7d908a..48181c91253 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/AdverseEventsForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/AdverseEventsForm.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -44,6 +41,7 @@ import com.vaadin.ui.CustomLayout; import com.vaadin.ui.Label; +import com.vaadin.ui.themes.ValoTheme; import com.vaadin.v7.ui.CheckBox; import com.vaadin.v7.ui.Field; import com.vaadin.v7.ui.TextArea; @@ -58,7 +56,9 @@ import de.symeda.sormas.ui.utils.AbstractEditForm; import de.symeda.sormas.ui.utils.CssStyles; import de.symeda.sormas.ui.utils.FieldHelper; +import de.symeda.sormas.ui.utils.NullableOptionGroup; +@SuppressWarnings("deprecation") public class AdverseEventsForm extends AbstractEditForm { private static final long serialVersionUID = 5081846814610543073L; @@ -119,7 +119,8 @@ protected void addFields() { emptyLabel.addStyleName(H3); getContent().addComponent(emptyLabel, EMPTY_LABEL_LOC); - addField(SEIZURE_TYPE); + NullableOptionGroup seizureType = addField(SEIZURE_TYPE, NullableOptionGroup.class); + CssStyles.style(seizureType, ValoTheme.OPTIONGROUP_HORIZONTAL, CssStyles.OPTIONGROUP_CAPTION_INLINE); TextArea otherAdverseEvents = addField(OTHER_ADVERSE_EVENT_DETAILS, TextArea.class); otherAdverseEvents.setRows(6); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/AefiDataForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/AefiDataForm.java index 3bbd3e2e4c0..78ee9dcb888 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/AefiDataForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/AefiDataForm.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -79,7 +76,8 @@ public class AefiDataForm extends AbstractEditForm { private static final String HTML_LAYOUT = divCss(CssStyles.VIEW_SECTION_MARGIN_TOP_4_MARGIN_X_4, loc(REPORTING_INFORMATION_HEADING_LOC) - + fluidRowLocs(4, AefiDto.UUID, 3, AefiDto.REPORT_DATE, 3, AefiDto.REPORTING_USER, 2, "") + + fluidRowLocs(4, AefiDto.UUID, 4, AefiDto.REPORT_DATE, 3, AefiDto.REPORTING_USER) + + fluidRowLocs(4, AefiDto.RESPONSIBLE_REGION, 4, AefiDto.RESPONSIBLE_DISTRICT, 3, AefiDto.RESPONSIBLE_COMMUNITY) + fluidRowLocs(4, AefiDto.REPORTING_ID_NUMBER, 3, ASSIGN_NEW_AEFI_ID_LOC) ) + divCss(CssStyles.VIEW_SECTION_MARGIN_X_4 + " " + CssStyles.VSPACE_TOP_3, @@ -118,6 +116,9 @@ public class AefiDataForm extends AbstractEditForm { private boolean isCreateAction; private final Consumer actionCallback; + private TextField responsibleRegion; + private TextField responsibleDistrict; + private TextField responsibleCommunity; private AefiVaccinationsField vaccinationsField; public AefiDataForm(boolean isCreateAction, boolean isPseudonymized, boolean inJurisdiction, Consumer actionCallback) { @@ -156,7 +157,14 @@ protected void addFields() { addField(AefiDto.UUID); } addField(AefiDto.REPORT_DATE, DateField.class); - addField(ImmunizationDto.REPORTING_USER, UserField.class); + addField(AefiDto.REPORTING_USER, UserField.class); + + responsibleRegion = new TextField(I18nProperties.getPrefixCaption(AefiDto.I18N_PREFIX, AefiDto.RESPONSIBLE_REGION)); + getContent().addComponent(responsibleRegion, AefiDto.RESPONSIBLE_REGION); + responsibleDistrict = new TextField(I18nProperties.getPrefixCaption(AefiDto.I18N_PREFIX, AefiDto.RESPONSIBLE_DISTRICT)); + getContent().addComponent(responsibleDistrict, AefiDto.RESPONSIBLE_DISTRICT); + responsibleCommunity = new TextField(I18nProperties.getPrefixCaption(AefiDto.I18N_PREFIX, AefiDto.RESPONSIBLE_COMMUNITY)); + getContent().addComponent(responsibleCommunity, AefiDto.RESPONSIBLE_COMMUNITY); TextField reportIdField = addField(AefiDto.REPORTING_ID_NUMBER, TextField.class); /* @@ -272,18 +280,25 @@ protected void addFields() { public void attach() { super.attach(); - vaccinationsField.setAefiDto(getValue()); - if (getValue().getPrimarySuspectVaccine() != null) { - vaccinationsField.selectPrimarySuspectVaccination(getValue().getPrimarySuspectVaccine()); + AefiDto dataFormValue = getValue(); + + ImmunizationDto immunizationDto = FacadeProvider.getImmunizationFacade().getByUuid(dataFormValue.getImmunization().getUuid()); + + responsibleRegion.setValue(immunizationDto.getResponsibleRegion().getCaption()); + responsibleDistrict.setValue(immunizationDto.getResponsibleDistrict().getCaption()); + if (immunizationDto.getResponsibleCommunity() != null) { + responsibleCommunity.setValue(immunizationDto.getResponsibleCommunity().getCaption()); } - } - /* - * @Override - * public AefiDto getValue() { - * return super.getValue(); - * } - */ + responsibleRegion.setReadOnly(true); + responsibleDistrict.setReadOnly(true); + responsibleCommunity.setReadOnly(true); + + vaccinationsField.applyAefiReportContext(dataFormValue); + if (dataFormValue.getPrimarySuspectVaccine() != null) { + vaccinationsField.selectPrimarySuspectVaccination(dataFormValue.getPrimarySuspectVaccine()); + } + } @Override public void setValue(AefiDto newFieldValue) throws ReadOnlyException, Converter.ConversionException { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/FormSectionAccordion.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/FormSectionAccordion.java new file mode 100644 index 00000000000..ce435e84443 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/FormSectionAccordion.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.ui.adverseeventsfollowingimmunization.components.form; + +import java.util.ArrayList; +import java.util.List; + +import com.vaadin.ui.Component; +import com.vaadin.ui.VerticalLayout; + +public class FormSectionAccordion extends VerticalLayout { + + private final List formSectionAccordionPanelList = new ArrayList<>(); + + public FormSectionAccordion() { + setMargin(false); + setSpacing(false); + setWidth(100, Unit.PERCENTAGE); + } + + public void addFormSectionPanel(String sectionTitleCaption, boolean expanded, Component component) { + + FormSectionAccordionPanel formSectionAccordionPanel = new FormSectionAccordionPanel(sectionTitleCaption, expanded, FormSectionAccordion.this); + formSectionAccordionPanel.addComponentToMainLayout(component); + + formSectionAccordionPanelList.add(formSectionAccordionPanel); + + addComponent(formSectionAccordionPanel); + } + + public void toggleFormSection(FormSectionAccordionPanel formSectionAccordionPanel) { + formSectionAccordionPanel.getMainLayout().setVisible(!formSectionAccordionPanel.isExpanded()); + formSectionAccordionPanel.setExpanded(!formSectionAccordionPanel.isExpanded()); + } + + public void toggleAllFormSections(boolean expanded) { + for (FormSectionAccordionPanel formSectionAccordionPanel : formSectionAccordionPanelList) { + formSectionAccordionPanel.getMainLayout().setVisible(!expanded); + formSectionAccordionPanel.setExpanded(!expanded); + } + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/FormSectionAccordionPanel.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/FormSectionAccordionPanel.java new file mode 100644 index 00000000000..6e8cc33ef79 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/form/FormSectionAccordionPanel.java @@ -0,0 +1,77 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.components.form; + +import com.vaadin.ui.Button; +import com.vaadin.ui.Component; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.themes.ValoTheme; + +import de.symeda.sormas.ui.utils.ButtonHelper; +import de.symeda.sormas.ui.utils.CssStyles; + +public class FormSectionAccordionPanel extends VerticalLayout { + + private final Button titleButton; + private final VerticalLayout mainLayout; + private final FormSectionAccordion formSectionAccordion; + private boolean expanded; + + public FormSectionAccordionPanel(String titleButtonCaption, boolean expanded, FormSectionAccordion formSectionAccordion) { + + this.expanded = expanded; + this.formSectionAccordion = formSectionAccordion; + + setMargin(false); + setSpacing(false); + setWidth(99, Unit.PERCENTAGE); + addStyleNames(CssStyles.VIEW_SECTION_MARGIN_X_4, CssStyles.VSPACE_3); + + titleButton = ButtonHelper.createButton(titleButtonCaption, (event) -> { + formSectionAccordion.toggleFormSection(FormSectionAccordionPanel.this); + }, ValoTheme.BUTTON_LINK, CssStyles.FORM_SECTION_ACCORDION_PANEL_TITLE_BUTTON); + addComponent(titleButton); + + mainLayout = new VerticalLayout(); + mainLayout.setMargin(false); + mainLayout.setSpacing(false); + //mainLayout.setWidth(100, Unit.PERCENTAGE); + mainLayout.setVisible(expanded); + mainLayout.addStyleNames(CssStyles.VSPACE_TOP_3); + + addComponent(mainLayout); + } + + public void addComponentToMainLayout(Component component) { + mainLayout.addComponent(component); + } + + public Button getTitleButton() { + return titleButton; + } + + public VerticalLayout getMainLayout() { + return mainLayout; + } + + public boolean isExpanded() { + return expanded; + } + + public void setExpanded(boolean expanded) { + this.expanded = expanded; + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/information/AefiInfo.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/information/AefiInfo.java new file mode 100644 index 00000000000..43824207209 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/components/information/AefiInfo.java @@ -0,0 +1,89 @@ +/* + * 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.ui.adverseeventsfollowingimmunization.components.information; + +import java.util.function.Consumer; + +import org.apache.commons.lang3.StringUtils; + +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; + +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiHelper; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiListEntryDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.i18n.Strings; +import de.symeda.sormas.api.utils.YesNoUnknown; +import de.symeda.sormas.api.vaccination.VaccinationDto; +import de.symeda.sormas.ui.utils.CssStyles; +import de.symeda.sormas.ui.utils.DateFormatHelper; +import de.symeda.sormas.ui.utils.components.sidecomponent.SideComponent; + +public class AefiInfo extends SideComponent { + + public static final String SEPARATOR = ": "; + + private AefiDto aefi; + private final VerticalLayout mainLayout; + + public AefiInfo(AefiDto aefi, Consumer actionCallback) { + super(I18nProperties.getString(Strings.entityAdverseEvent), actionCallback); + + this.aefi = aefi; + mainLayout = new VerticalLayout(); + mainLayout.setWidth(100, Unit.PERCENTAGE); + mainLayout.setMargin(false); + mainLayout.setSpacing(false); + + buildMainLayout(); + addComponent(mainLayout); + } + + public void buildMainLayout() { + + Label labelAefiType = new Label(AefiType.toString(aefi.getSerious())); + CssStyles.style(labelAefiType, CssStyles.LABEL_BOLD, CssStyles.LABEL_UPPERCASE); + if (aefi.getSerious() == YesNoUnknown.YES) { + CssStyles.style(labelAefiType, CssStyles.LABEL_CRITICAL); + } + mainLayout.addComponent(labelAefiType); + + Label labelVaccineName = new Label(aefi.getPrimarySuspectVaccine().getVaccineName().toString()); + CssStyles.style(labelVaccineName, CssStyles.LABEL_BOLD, CssStyles.LABEL_UPPERCASE); + mainLayout.addComponent(labelVaccineName); + + if (!StringUtils.isBlank(aefi.getPrimarySuspectVaccine().getVaccineDose())) { + Label labelVaccineDose = new Label( + I18nProperties.getPrefixCaption(VaccinationDto.I18N_PREFIX, VaccinationDto.VACCINE_DOSE) + + SEPARATOR + + aefi.getPrimarySuspectVaccine().getVaccineDose()); + CssStyles.style(labelVaccineDose, CssStyles.LABEL_BOLD, CssStyles.LABEL_UPPERCASE); + mainLayout.addComponent(labelVaccineDose); + } + + Label labelVaccineDate = new Label( + I18nProperties.getPrefixCaption(AefiListEntryDto.I18N_PREFIX, AefiListEntryDto.PRIMARY_VACCINE_VACCINATION_DATE) + + SEPARATOR + + DateFormatHelper.formatLocalDate(aefi.getPrimarySuspectVaccine().getVaccinationDate())); + mainLayout.addComponent(labelVaccineDate); + + Label labelAdverseEvents = new Label(StringUtils.abbreviate(AefiHelper.buildAdverseEventsString(aefi.getAdverseEvents()), 56)); + CssStyles.style(labelAdverseEvents, CssStyles.LABEL_BOLD, CssStyles.LABEL_UPPERCASE); + mainLayout.addComponent(labelAdverseEvents); + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardDataProvider.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardDataProvider.java index fb6a77afc5a..2945bb8f54f 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardDataProvider.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardDataProvider.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -21,7 +18,9 @@ import java.util.Map; import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiClassification; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDashboardFilterDateType; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationStatus; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; import de.symeda.sormas.api.caze.Vaccine; import de.symeda.sormas.api.dashboard.AefiDashboardCriteria; @@ -33,6 +32,9 @@ public class AefiDashboardDataProvider extends AbstractDashboardDataProvider aefiCountsByType; + private int totalAefiInvestigations; + private Map> aefiInvestigationCountsByInvestigationStatus; + private Map> aefiInvestigationCountsByAefiClassification; private Map> aefiCountsByVaccine; private AefiChartData aefiByVaccineDoseChartData; private AefiChartData aefiEventsByGenderChartData; @@ -40,6 +42,16 @@ public class AefiDashboardDataProvider extends AbstractDashboardDataProvider investigationStatusValue : aefiInvestigationCountsByInvestigationStatus.values()) { + totalAefiInvestigations += Integer.parseInt(investigationStatusValue.get("total")); + } + + aefiInvestigationCountsByAefiClassification = + FacadeProvider.getAefiDashboardFacade().getAefiInvestigationCountsByAefiClassification(buildDashboardCriteriaWithDates()); aefiCountsByVaccine = FacadeProvider.getAefiDashboardFacade().getAefiCountsByVaccine(buildDashboardCriteriaWithDates()); aefiByVaccineDoseChartData = FacadeProvider.getAefiDashboardFacade().getAefiByVaccineDoseChartData(buildDashboardCriteriaWithDates()); aefiEventsByGenderChartData = FacadeProvider.getAefiDashboardFacade().getAefiEventsByGenderChartData(buildDashboardCriteriaWithDates()); @@ -67,6 +79,18 @@ public Map getAefiCountsByType() { return aefiCountsByType; } + public int getTotalAefiInvestigations() { + return totalAefiInvestigations; + } + + public Map> getAefiInvestigationCountsByInvestigationStatus() { + return aefiInvestigationCountsByInvestigationStatus; + } + + public Map> getAefiInvestigationCountsByAefiClassification() { + return aefiInvestigationCountsByAefiClassification; + } + public Map> getAefiCountsByVaccine() { return aefiCountsByVaccine; } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardFilterLayout.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardFilterLayout.java index 0c4df88ccf6..c4f2cc2ff1a 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardFilterLayout.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardFilterLayout.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -78,7 +75,7 @@ private void createDiseaseFilter() { diseaseFilter.setWidth(200, Unit.PIXELS); diseaseFilter.setInputPrompt(I18nProperties.getString(Strings.promptDisease)); diseaseFilter.setDescription(I18nProperties.getDescription(Descriptions.aefiDashboardDiseaseFilter)); - List availableDisease = FacadeProvider.getDiseaseConfigurationFacade().getAllDiseasesWithFollowUp(true, true, true); + List availableDisease = FacadeProvider.getDiseaseConfigurationFacade().getAllDiseases(true, true, true); diseaseFilter .addItems(Stream.concat(availableDisease.stream(), Stream.of(AefiDashboardCustomDiseaseFilter.values())).collect(Collectors.toList())); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardView.java index 15bc987c333..b114177e007 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardView.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardView.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -23,13 +20,19 @@ import static de.symeda.sormas.ui.utils.LayoutUtil.fluidRowCss; import static de.symeda.sormas.ui.utils.LayoutUtil.locCss; +import java.util.Map; + +import com.vaadin.shared.ui.MarginInfo; import com.vaadin.ui.Component; import com.vaadin.ui.CustomLayout; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.VerticalLayout; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiClassification; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationStatus; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiType; import de.symeda.sormas.api.i18n.Captions; +import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.ui.dashboard.AbstractDashboardView; import de.symeda.sormas.ui.dashboard.DashboardCssStyles; import de.symeda.sormas.ui.dashboard.DashboardType; @@ -39,6 +42,7 @@ import de.symeda.sormas.ui.dashboard.adverseeventsfollowingimmunization.components.AefiReactionsByGenderChart; import de.symeda.sormas.ui.dashboard.adverseeventsfollowingimmunization.components.AefiTypeStatisticsGroupComponent; import de.symeda.sormas.ui.dashboard.components.DashboardHeadingComponent; +import de.symeda.sormas.ui.dashboard.statistics.DashboardStatisticsPercentageElement; import de.symeda.sormas.ui.utils.CssStyles; public class AefiDashboardView extends AbstractDashboardView { @@ -47,8 +51,11 @@ public class AefiDashboardView extends AbstractDashboardView { private static final int EPI_CURVE_AND_MAP_HEIGHT = 555; - private static final String HEADING_LOC = "headingLoc"; + private static final String ALL_AEFI_HEADING_LOC = "allAefiHeadingLoc"; private static final String AEFI_TYPE_LOC = "aefiTypeLoc"; + private static final String ALL_AEFI_INVESTIGATION_HEADING_LOC = "allAefiInvestigationHeadingLoc"; + private static final String INVESTIGATION_STATUS_LOC = "investigationStatusLoc"; + private static final String AEFI_CLASSIFICATION_LOC = "aefiClassificationLoc"; private static final String VACCINES_LOC = "vaccinesLoc"; private static final String VACCINE_DOSE_LOC = "vaccineDoseLoc"; private static final String REACTIONS_LOC = "reactionsLoc"; @@ -60,8 +67,14 @@ public class AefiDashboardView extends AbstractDashboardView { private final VerticalLayout epiCurveLayout; private final VerticalLayout mapLayout; - private final DashboardHeadingComponent heading; + private final DashboardHeadingComponent allAefiHeading; private final AefiCountTilesComponent aefiCountsByType; + private final DashboardHeadingComponent allAefiInvestigationHeading; + private DashboardStatisticsPercentageElement investigationStatusDone; + private DashboardStatisticsPercentageElement investigationStatusDiscarded; + private DashboardStatisticsPercentageElement aefiClassificationVaccineRelated; + private DashboardStatisticsPercentageElement aefiClassificationConincidentalAefi; + private DashboardStatisticsPercentageElement aefiClassificationUndetermined; private final AefiTypeStatisticsGroupComponent aefiCountsByVaccine; private final AefiByVaccineDoseChart vaccineDoseChart; private final AefiReactionsByGenderChart reactionsByGenderChart; @@ -89,8 +102,11 @@ public AefiDashboardView() { aefiCountsLayout.setTemplateContents( fluidRowCss( CssStyles.PADDING_X_20 + " " + CssStyles.VSPACE_TOP_2, - fluidColumn(6, 0, locCss("", HEADING_LOC)), - fluidColumn(4, 0, locCss("", AEFI_TYPE_LOC)) + fluidColumn(1, 0, locCss("", ALL_AEFI_HEADING_LOC)), + fluidColumn(3, 0, locCss("", AEFI_TYPE_LOC)), + fluidColumn(2, 0, locCss("", ALL_AEFI_INVESTIGATION_HEADING_LOC)), + fluidColumn(3, 0, locCss("", INVESTIGATION_STATUS_LOC)), + fluidColumn(3, 0, locCss("", AEFI_CLASSIFICATION_LOC)) ) + fluidRowCss( CssStyles.VSPACE_TOP_2, @@ -105,15 +121,53 @@ public AefiDashboardView() { //@formatter:on dashboardLayout.addComponent(aefiCountsLayout); - heading = new DashboardHeadingComponent(Captions.aefiDashboardAllAefi, null); - heading.setMargin(false); - aefiCountsLayout.addComponent(heading, HEADING_LOC); + allAefiHeading = new DashboardHeadingComponent(Captions.aefiDashboardAllAefi, null); + allAefiHeading.setMargin(false); + aefiCountsLayout.addComponent(allAefiHeading, ALL_AEFI_HEADING_LOC); aefiCountsByType = new AefiCountTilesComponent<>(AefiType.class, "", this::getBackgroundStyleForAefiCountByType, null); aefiCountsByType.setTitleStyleNames(CssStyles.H3, CssStyles.VSPACE_TOP_5); aefiCountsByType.setGroupLabelStyle(CssStyles.LABEL_LARGE + " " + CssStyles.LABEL_WHITE_SPACE_NORMAL); aefiCountsLayout.addComponent(aefiCountsByType, AEFI_TYPE_LOC); + allAefiInvestigationHeading = new DashboardHeadingComponent(Captions.aefiDashboardAllAefiInvestigation, null); + allAefiInvestigationHeading.setMargin(false); + aefiCountsLayout.addComponent(allAefiInvestigationHeading, ALL_AEFI_INVESTIGATION_HEADING_LOC); + + VerticalLayout investigationStatusLayout = new VerticalLayout(); + investigationStatusLayout.setMargin(new MarginInfo(false, true, false, true)); + investigationStatusLayout.setSpacing(false); + + investigationStatusDone = new DashboardStatisticsPercentageElement( + I18nProperties.getCaption(Captions.aefiDashboardAefiInvestigationDone), + CssStyles.SVG_FILL_POSITIVE); + investigationStatusDiscarded = new DashboardStatisticsPercentageElement( + I18nProperties.getCaption(Captions.aefiDashboardAefiInvestigationDiscarded), + CssStyles.SVG_FILL_NEUTRAL); + + investigationStatusLayout.addComponent(investigationStatusDone); + investigationStatusLayout.addComponent(investigationStatusDiscarded); + aefiCountsLayout.addComponent(investigationStatusLayout, INVESTIGATION_STATUS_LOC); + + VerticalLayout aefiClassificationLayout = new VerticalLayout(); + aefiClassificationLayout.setMargin(new MarginInfo(false, true, false, true)); + aefiClassificationLayout.setSpacing(false); + + aefiClassificationVaccineRelated = new DashboardStatisticsPercentageElement( + I18nProperties.getCaption(Captions.aefiDashboardAefiClassificationRelatedToVaccination), + CssStyles.SVG_FILL_POSITIVE); + aefiClassificationConincidentalAefi = new DashboardStatisticsPercentageElement( + I18nProperties.getCaption(Captions.aefiDashboardAefiClassificationCoincidentalAdverseEvent), + CssStyles.SVG_FILL_IMPORTANT); + aefiClassificationUndetermined = new DashboardStatisticsPercentageElement( + I18nProperties.getCaption(Captions.aefiDashboardAefiClassificationUndetermined), + CssStyles.SVG_FILL_NEUTRAL); + + aefiClassificationLayout.addComponent(aefiClassificationVaccineRelated); + aefiClassificationLayout.addComponent(aefiClassificationConincidentalAefi); + aefiClassificationLayout.addComponent(aefiClassificationUndetermined); + aefiCountsLayout.addComponent(aefiClassificationLayout, AEFI_CLASSIFICATION_LOC); + aefiCountsByVaccine = new AefiTypeStatisticsGroupComponent(); aefiCountsByVaccine.addStyleNames(CssStyles.PADDING_X_20); aefiCountsLayout.addComponent(aefiCountsByVaccine, VACCINES_LOC); @@ -140,9 +194,30 @@ public AefiDashboardView() { public void refreshDashboard() { dataProvider.refreshData(); - heading.updateTotalLabel(String.valueOf(dataProvider.getAefiCountsByType().values().stream().mapToLong(Long::longValue).sum())); - + allAefiHeading.updateTotalLabel(String.valueOf(dataProvider.getAefiCountsByType().values().stream().mapToLong(Long::longValue).sum())); aefiCountsByType.update(dataProvider.getAefiCountsByType()); + + allAefiInvestigationHeading.updateTotalLabel(String.valueOf(dataProvider.getTotalAefiInvestigations())); + Map> investigationStatusCountMap = + dataProvider.getAefiInvestigationCountsByInvestigationStatus(); + investigationStatusDone.updatePercentageValueWithCount( + Integer.parseInt(investigationStatusCountMap.get(AefiInvestigationStatus.DONE).get("total")), + Integer.parseInt(investigationStatusCountMap.get(AefiInvestigationStatus.DONE).get("percent"))); + investigationStatusDiscarded.updatePercentageValueWithCount( + Integer.parseInt(investigationStatusCountMap.get(AefiInvestigationStatus.DISCARDED).get("total")), + Integer.parseInt(investigationStatusCountMap.get(AefiInvestigationStatus.DISCARDED).get("percent"))); + + Map> aefiClassificationCountMap = dataProvider.getAefiInvestigationCountsByAefiClassification(); + aefiClassificationVaccineRelated.updatePercentageValueWithCount( + Integer.parseInt(aefiClassificationCountMap.get(AefiClassification.RELATED_TO_VACCINE_OR_VACCINATION).get("total")), + Integer.parseInt(aefiClassificationCountMap.get(AefiClassification.RELATED_TO_VACCINE_OR_VACCINATION).get("percent"))); + aefiClassificationConincidentalAefi.updatePercentageValueWithCount( + Integer.parseInt(aefiClassificationCountMap.get(AefiClassification.COINCIDENTAL_ADVERSE_EVENT).get("total")), + Integer.parseInt(aefiClassificationCountMap.get(AefiClassification.COINCIDENTAL_ADVERSE_EVENT).get("percent"))); + aefiClassificationUndetermined.updatePercentageValueWithCount( + Integer.parseInt(aefiClassificationCountMap.get(AefiClassification.UNDETERMINED).get("total")), + Integer.parseInt(aefiClassificationCountMap.get(AefiClassification.UNDETERMINED).get("percent"))); + aefiCountsByVaccine.update(dataProvider.getAefiCountsByVaccine()); vaccineDoseChart.update(dataProvider.getAefiByVaccineDoseChartData()); reactionsByGenderChart.update(dataProvider.getAefiEventsByGenderChartData()); @@ -206,7 +281,7 @@ private VerticalLayout createMapLayout(AefiDashboardMapComponent mapComponent) { private void setExpanded(Boolean expanded, Component componentToExpand, Component componentToRemove, int removedComponentIndex) { if (expanded) { - dashboardLayout.removeComponent(heading); + dashboardLayout.removeComponent(allAefiHeading); dashboardLayout.removeComponent(aefiCountsLayout); epiCurveAndMapLayout.removeComponent(componentToRemove); setHeight(100, Unit.PERCENTAGE); @@ -216,7 +291,7 @@ private void setExpanded(Boolean expanded, Component componentToExpand, Componen componentToExpand.setSizeFull(); dashboardLayout.setHeightFull(); } else { - dashboardLayout.addComponent(heading, 1); + dashboardLayout.addComponent(allAefiHeading, 1); dashboardLayout.addComponent(aefiCountsLayout, 2); epiCurveAndMapLayout.addComponent(componentToRemove, removedComponentIndex); mapComponent.refreshMap(); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiCountTilesComponent.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiCountTilesComponent.java index a3308e23824..7a08ff88730 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiCountTilesComponent.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiCountTilesComponent.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -84,6 +81,8 @@ public AefiCountTilesComponent( titleLayout.addComponent(infoIcon); } + titleLayout.setVisible(false); + countsLayout = new HorizontalLayout(); countsLayout.setWidthFull(); addComponent(countsLayout); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiReactionsByGenderChart.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiReactionsByGenderChart.java index 464872634f0..b44a29b613d 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiReactionsByGenderChart.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiReactionsByGenderChart.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -127,6 +124,11 @@ public void update(AefiChartData chartData) { " fontWeight: 'bold'" + " }" + " }," + + " labels: {" + + " formatter: function() {" + + " return Math.abs(this.value);" + + " }" + + " }" + " }," + " plotOptions: {" + " series: {" + @@ -135,7 +137,12 @@ public void update(AefiChartData chartData) { " }," + " credits: {" + " enabled: false" + - " },"); + " }," + + " tooltip: {" + + " formatter: function() {" + + " return this.point.category + ': ' + this.series.name + ' ' + Math.abs(this.y);" + + " }" + + " },"); //@formatter:on hcjs.append("series: ["); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiTypeStatisticsGroupComponent.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiTypeStatisticsGroupComponent.java index 45e459ac760..aed7bba874e 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiTypeStatisticsGroupComponent.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiTypeStatisticsGroupComponent.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -39,10 +36,8 @@ public AefiTypeStatisticsGroupComponent() { public void update(Map> countsByVaccineData) { //temporary fix: re-use stored components and hide/unhide if not in new update - if (countsByVaccineData.isEmpty()) { - removeAllComponents(); - componentMap.clear(); - } + removeAllComponents(); + componentMap.clear(); AefiTypeStatisticsComponent statisticsComponent; @@ -54,7 +49,7 @@ public void update(Map> countsByVaccineData) { //statisticsComponent.getHeading().getTitleLabel().setValue(entry.getKey().toString()); statisticsComponent.hideHeading(); statisticsComponent.update(entry.getValue()); - statisticsComponent.addStyleNames(CssStyles.VIEW_SECTION, CssStyles.PADDING_X_8, CssStyles.HSPACE_RIGHT_3); + statisticsComponent.addStyleNames(CssStyles.VIEW_SECTION, CssStyles.PADDING_X_8, CssStyles.HSPACE_RIGHT_3, CssStyles.VSPACE_4); componentMap.put(entry.getKey(), statisticsComponent); addComponent(statisticsComponent); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AefiDownloadUtil.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AefiDownloadUtil.java new file mode 100644 index 00000000000..1f8174ec575 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AefiDownloadUtil.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.ui.utils; + +import java.util.Collection; +import java.util.Date; +import java.util.function.Supplier; + +import com.vaadin.server.StreamResource; + +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventsDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiCriteria; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiExportDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiIndexDto; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.importexport.ExportConfigurationDto; + +public class AefiDownloadUtil { + + private AefiDownloadUtil() { + } + + public static StreamResource createAefiExportResource( + AefiCriteria aefiCriteria, + Supplier> selectedRows, + ExportConfigurationDto exportConfiguration) { + return DownloadUtil.createCsvExportStreamResource( + AefiExportDto.class, + null, + (Integer start, Integer max) -> FacadeProvider.getAefiFacade().getExportList(aefiCriteria, selectedRows.get(), start, max), + AefiDownloadUtil::captionProvider, + ExportEntityName.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION, + exportConfiguration); + } + + public static String getPropertyCaption(String propertyId, String prefixId) { + if (prefixId != null) { + return I18nProperties.getPrefixCaption(prefixId, propertyId); + } + + return I18nProperties.findPrefixCaption(propertyId, AefiExportDto.I18N_PREFIX, AefiIndexDto.I18N_PREFIX, AdverseEventsDto.I18N_PREFIX); + } + + private static String captionProvider(String propertyId, Class type) { + String caption = getPropertyCaption(propertyId, null); + + if (Date.class.isAssignableFrom(type)) { + caption += " (" + DateFormatHelper.getDateFormatPattern() + ")"; + } + + return caption; + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ArchiveHandlers.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ArchiveHandlers.java index 5bfa1ac1249..ae367e005a7 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ArchiveHandlers.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ArchiveHandlers.java @@ -32,6 +32,8 @@ import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiDto; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiFacade; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationDto; +import de.symeda.sormas.api.adverseeventsfollowingimmunization.AefiInvestigationFacade; import de.symeda.sormas.api.campaign.CampaignDto; import de.symeda.sormas.api.campaign.CampaignFacade; import de.symeda.sormas.api.caze.CaseDataDto; @@ -99,6 +101,12 @@ public static CoreEntityArchiveHandler forAefi() { return new CoreEntityArchiveHandler<>(FacadeProvider.getAefiFacade(), ArchiveMessages.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION); } + public static CoreEntityArchiveHandler forAefiInvestigation() { + return new CoreEntityArchiveHandler<>( + FacadeProvider.getAefiInvestigationFacade(), + ArchiveMessages.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_INVESTIGATION); + } + public static CoreEntityArchiveHandler forTravelEntry() { return new CoreEntityArchiveHandler<>(FacadeProvider.getTravelEntryFacade(), ArchiveMessages.TRAVEL_ENTRY); } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ArchiveMessages.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ArchiveMessages.java index 079f167ae09..f7504095812 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ArchiveMessages.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ArchiveMessages.java @@ -106,14 +106,30 @@ public enum ArchiveMessages { null, null), - ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION(Strings.headingArchiveImmunization, - Strings.confirmationArchiveImmunization, + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION(Strings.headingArchiveAdverseEvent, + Strings.confirmationArchiveAdverseEvent, null, - Strings.messageImmunizationArchived, - Strings.headingDearchiveImmunization, - Strings.confirmationDearchiveImmunization, + Strings.messageAdverseEventArchived, + Strings.headingDearchiveAdverseEvent, + Strings.confirmationDearchiveAdverseEvent, null, - Strings.messageImmunizationDearchived, + Strings.messageAdverseEventDearchived, + null, + null, + null, + null, + null, + null, + null, + null), + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_INVESTIGATION(Strings.headingArchiveAdverseEventInvestigation, + Strings.confirmationArchiveAdverseEventInvestigation, + null, + Strings.messageAdverseEventInvestigationArchived, + Strings.headingDearchiveAdverseEventInvestigation, + Strings.confirmationDearchiveAdverseEventInvestigation, + null, + Strings.messageAdverseEventInvestigationDearchived, null, null, null, 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 1c82e66f59f..a1bee68b7c0 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 @@ -323,6 +323,8 @@ private CssStyles() { public static final String MARGIN_TOP_4 = "margin-top-4"; public static final String PADDING_X_8 = "padding-x-8"; public static final String PADDING_X_20 = "padding-x-20"; + public static final String FORM_SECTION_ACCORDION_PANEL_TITLE_BUTTON = "form-section-accordion-panel-title-button"; + public static final String OPTIONGROUP_CAPTION_FLEX = "optiongroup-caption-flex"; public static final String VIEW_SECTION_MARGIN_X_4 = VIEW_SECTION + " " + MARGIN_X_4; public static final String VIEW_SECTION_MARGIN_TOP_4_MARGIN_X_4 = VIEW_SECTION + " " + MARGIN_X_4 + " " + MARGIN_TOP_4; diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ExportEntityName.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ExportEntityName.java index fd9ad184630..ca2b6e7b088 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ExportEntityName.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ExportEntityName.java @@ -43,6 +43,9 @@ public enum ExportEntityName { ENVIRONMENTS("entityEnvironments", "environments"), ENVIRONMENT_SAMPLES("entityEnvironmentSamples", "environment samples"), SELF_REPORTS("entitySelfReports", "self reports"); + ENVIRONMENT_SAMPLES("entityEnvironmentSamples", "environment samples"), + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION("entityAdverseEvents", "adverse events following immunization"), + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_INVESTIGATION("entityAdverseEventInvestigations", "aefi investigations"); private final String languageKey; private final String defaultName; diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/SormasFieldGroupFieldFactory.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/SormasFieldGroupFieldFactory.java index 6e0290496cd..22b80d05097 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/SormasFieldGroupFieldFactory.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/SormasFieldGroupFieldFactory.java @@ -20,8 +20,6 @@ import de.symeda.sormas.api.FacadeProvider; import de.symeda.sormas.api.ReferenceDto; import de.symeda.sormas.api.adverseeventsfollowingimmunization.AdverseEventState; -import de.symeda.sormas.api.adverseeventsfollowingimmunization.SeizureType; -import de.symeda.sormas.api.caze.Trimester; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.symptoms.SymptomState; import de.symeda.sormas.api.utils.FieldConstraints; @@ -30,7 +28,6 @@ import de.symeda.sormas.api.utils.fieldvisibility.FieldVisibilityCheckers; import de.symeda.sormas.ui.ActivityAsCase.ActivityAsCaseField; import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.fields.vaccines.AefiVaccinationsField; -import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.fields.vaccines.AefiVaccinationsField_2; import de.symeda.sormas.ui.adverseeventsfollowingimmunization.components.form.AdverseEventsForm; import de.symeda.sormas.ui.clinicalcourse.HealthConditionsForm; import de.symeda.sormas.ui.exposure.ExposuresField; @@ -80,9 +77,7 @@ public T createField(Class type, Class fieldType) { if (fieldType.isAssignableFrom(Field.class) // no specific fieldType defined? && (SymptomState.class.isAssignableFrom(type) || YesNoUnknown.class.isAssignableFrom(type) - || AdverseEventState.class.isAssignableFrom(type) - || SeizureType.class.isAssignableFrom(type) - || Trimester.class.isAssignableFrom(type))) { + || AdverseEventState.class.isAssignableFrom(type))) { NullableOptionGroup field = new NullableOptionGroup(); field.setImmediate(true); populateWithEnumData(field, (Class) type); @@ -191,7 +186,7 @@ public T createField(Class type, Class fieldType) { return (T) new AefiVaccinationsField(fieldAccessCheckers); } else if (AdverseEventsForm.class.isAssignableFrom(fieldType)) { return (T) new AdverseEventsForm(fieldVisibilityCheckers, fieldAccessCheckers); - }else if (CheckBoxTree.class.isAssignableFrom(fieldType)){ + } else if (CheckBoxTree.class.isAssignableFrom(fieldType)) { return (T) new CheckBoxTree<>(); } return super.createField(type, fieldType); From 6e516b6d0f95c744f5c2b00bec917e57fe7acd76 Mon Sep 17 00:00:00 2001 From: Obinna Henry <55580796+obinna-h-n@users.noreply.github.com> Date: Sat, 30 Mar 2024 19:56:12 +0100 Subject: [PATCH 3/5] #12976 - AEFI dashboard - Change "gender" to "sex" on the dashboard --- .../AefiDashboardView.java | 10 +++++----- ...ByGenderChart.java => AefiReactionsBySexChart.java} | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) rename sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/{AefiReactionsByGenderChart.java => AefiReactionsBySexChart.java} (96%) diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardView.java index b114177e007..f21df5a8aaf 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardView.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/AefiDashboardView.java @@ -39,7 +39,7 @@ import de.symeda.sormas.ui.dashboard.adverseeventsfollowingimmunization.components.AefiByVaccineDoseChart; import de.symeda.sormas.ui.dashboard.adverseeventsfollowingimmunization.components.AefiCountTilesComponent; import de.symeda.sormas.ui.dashboard.adverseeventsfollowingimmunization.components.AefiDashboardMapComponent; -import de.symeda.sormas.ui.dashboard.adverseeventsfollowingimmunization.components.AefiReactionsByGenderChart; +import de.symeda.sormas.ui.dashboard.adverseeventsfollowingimmunization.components.AefiReactionsBySexChart; import de.symeda.sormas.ui.dashboard.adverseeventsfollowingimmunization.components.AefiTypeStatisticsGroupComponent; import de.symeda.sormas.ui.dashboard.components.DashboardHeadingComponent; import de.symeda.sormas.ui.dashboard.statistics.DashboardStatisticsPercentageElement; @@ -77,7 +77,7 @@ public class AefiDashboardView extends AbstractDashboardView { private DashboardStatisticsPercentageElement aefiClassificationUndetermined; private final AefiTypeStatisticsGroupComponent aefiCountsByVaccine; private final AefiByVaccineDoseChart vaccineDoseChart; - private final AefiReactionsByGenderChart reactionsByGenderChart; + private final AefiReactionsBySexChart reactionsBySexChart; private final AefiEpiCurveComponent epiCurveComponent; private final AefiDashboardMapComponent mapComponent; @@ -175,8 +175,8 @@ public AefiDashboardView() { vaccineDoseChart = new AefiByVaccineDoseChart(); aefiCountsLayout.addComponent(vaccineDoseChart, VACCINE_DOSE_LOC); - reactionsByGenderChart = new AefiReactionsByGenderChart(); - aefiCountsLayout.addComponent(reactionsByGenderChart, REACTIONS_LOC); + reactionsBySexChart = new AefiReactionsBySexChart(); + aefiCountsLayout.addComponent(reactionsBySexChart, REACTIONS_LOC); epiCurveComponent = new AefiEpiCurveComponent(dataProvider); epiCurveLayout = createEpiCurveLayout(); @@ -220,7 +220,7 @@ public void refreshDashboard() { aefiCountsByVaccine.update(dataProvider.getAefiCountsByVaccine()); vaccineDoseChart.update(dataProvider.getAefiByVaccineDoseChartData()); - reactionsByGenderChart.update(dataProvider.getAefiEventsByGenderChartData()); + reactionsBySexChart.update(dataProvider.getAefiEventsByGenderChartData()); epiCurveComponent.clearAndFillEpiCurveChart(); mapComponent.refreshMap(); } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiReactionsByGenderChart.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiReactionsBySexChart.java similarity index 96% rename from sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiReactionsByGenderChart.java rename to sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiReactionsBySexChart.java index b44a29b613d..8b923778206 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiReactionsByGenderChart.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/adverseeventsfollowingimmunization/components/AefiReactionsBySexChart.java @@ -27,11 +27,11 @@ import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.ui.highcharts.HighChart; -public class AefiReactionsByGenderChart extends VerticalLayout { +public class AefiReactionsBySexChart extends VerticalLayout { protected final HighChart chart; - public AefiReactionsByGenderChart() { + public AefiReactionsBySexChart() { setMargin(false); setSpacing(false); @@ -56,7 +56,7 @@ public void update(AefiChartData chartData) { " borderRadius: '8px'" + " }," + " title: {" + - " text: 'Proportion of AEFI reactions (events) by gender'," + + " text: 'Proportion of AEFI reactions (events) by sex'," + " align: 'left'," + " style: {" + " fontSize: '15px'," + From 6efd99da13f749a421bf4c008212accb86de75aa Mon Sep 17 00:00:00 2001 From: Obinna Henry <55580796+obinna-h-n@users.noreply.github.com> Date: Sun, 14 Jul 2024 19:35:51 +0100 Subject: [PATCH 4/5] #12774 - aefi export entity configuration --- .../main/java/de/symeda/sormas/ui/utils/ExportEntityName.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ExportEntityName.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ExportEntityName.java index ca2b6e7b088..e00f41dfe45 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ExportEntityName.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/ExportEntityName.java @@ -42,8 +42,7 @@ public enum ExportEntityName { PERSONS("entityPersons", "persons"), ENVIRONMENTS("entityEnvironments", "environments"), ENVIRONMENT_SAMPLES("entityEnvironmentSamples", "environment samples"), - SELF_REPORTS("entitySelfReports", "self reports"); - ENVIRONMENT_SAMPLES("entityEnvironmentSamples", "environment samples"), + SELF_REPORTS("entitySelfReports", "self reports"), ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION("entityAdverseEvents", "adverse events following immunization"), ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_INVESTIGATION("entityAdverseEventInvestigations", "aefi investigations"); From 8a9119a3e771a6cc8fd06b6f45a5b0a0b61a1ab3 Mon Sep 17 00:00:00 2001 From: Obinna Henry <55580796+obinna-h-n@users.noreply.github.com> Date: Wed, 16 Oct 2024 14:40:16 +0100 Subject: [PATCH 5/5] update sormas_schema.sql for aefi module, fix tests, update user rights in web descriptors --- .../AefiChartData.java | 6 +- .../api/importexport/DatabaseTable.java | 8 + .../sormas/api/user/DefaultUserRole.java | 14 + .../entity/Aefi.java | 4 +- .../entity/AefiInvestigation.java | 4 +- .../resources/META-INF/glassfish-ejb-jar.xml | 35 ++ .../src/main/resources/sql/sormas_schema.sql | 411 ++++++++++++++++++ .../backend/common/HistoryTablesTest.java | 7 + .../DatabaseExportServiceTest.java | 12 +- .../src/test/resources/checkHistoryTables.sql | 4 +- .../src/main/webapp/WEB-INF/glassfish-web.xml | 35 ++ sormas-rest/src/main/webapp/WEB-INF/web.xml | 28 ++ .../AbstractAefiView.java | 2 + .../AefiInvestigationView.java | 4 +- .../AefiView.java | 4 +- .../AefiInvestigationList.java | 4 +- .../aefilink/AefiList.java | 11 +- .../webapp/VAADIN/themes/sormas/global.scss | 8 + .../src/main/webapp/WEB-INF/glassfish-web.xml | 35 ++ sormas-ui/src/main/webapp/WEB-INF/web.xml | 28 ++ 20 files changed, 637 insertions(+), 27 deletions(-) diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiChartData.java b/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiChartData.java index 0ba1d2093bc..b6190530a39 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiChartData.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/dashboard/adverseeventsfollowingimmunization/AefiChartData.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -22,6 +19,9 @@ import java.util.ArrayList; import java.util.List; +import de.symeda.sormas.api.audit.AuditedClass; + +@AuditedClass public class AefiChartData implements Serializable { private static final long serialVersionUID = 3538219674050390425L; diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/importexport/DatabaseTable.java b/sormas-api/src/main/java/de/symeda/sormas/api/importexport/DatabaseTable.java index 63f15937443..171ad6e8303 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/importexport/DatabaseTable.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/importexport/DatabaseTable.java @@ -68,6 +68,14 @@ public enum DatabaseTable { IMMUNIZATIONS(DatabaseTableType.SORMAS, "immunizations", dependingOnFeature(FeatureType.IMMUNIZATION_MANAGEMENT)), VACCINATIONS(DatabaseTableType.SORMAS, IMMUNIZATIONS, "vaccinations"), + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATIONS(DatabaseTableType.SORMAS, + "adverse_events_following_immunizations", + dependingOnFeature(FeatureType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_MANAGEMENT)), + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_INVESTIGATIONS(DatabaseTableType.SORMAS, + "adverse_events_following_immunization_investigations", + dependingOnFeature(FeatureType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_MANAGEMENT)), + ADVERSE_EVENTS(DatabaseTableType.SORMAS, "adverse_events", dependingOnFeature(FeatureType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_MANAGEMENT)), + SAMPLES(DatabaseTableType.SORMAS, "samples", dependingOnFeature(FeatureType.SAMPLES_LAB)), PATHOGEN_TESTS(DatabaseTableType.SORMAS, SAMPLES, "pathogen_tests"), ADDITIONAL_TESTS(DatabaseTableType.SORMAS, SAMPLES, "additional_tests", dependingOnFeature(FeatureType.ADDITIONAL_TESTS)), 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 5e7a2fc06ab..b91d28b515b 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 @@ -304,6 +304,13 @@ public Set getDefaultUserRights() { IMMUNIZATION_DELETE, IMMUNIZATION_ARCHIVE, IMMUNIZATION_VIEW_ARCHIVED, + DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW, + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE, + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW, + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT, + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE, + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE, + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT, PERSON_VIEW, PERSON_EDIT, PERSON_DELETE, @@ -1315,6 +1322,13 @@ public Set getDefaultUserRights() { IMMUNIZATION_CREATE, IMMUNIZATION_EDIT, IMMUNIZATION_DELETE, + DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW, + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE, + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW, + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT, + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE, + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE, + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT, PERSON_VIEW, PERSON_EDIT, PERSON_DELETE, diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/Aefi.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/Aefi.java index 92b65406c2b..63df6410c97 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/Aefi.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/Aefi.java @@ -32,7 +32,6 @@ import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.OneToOne; -import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; @@ -53,8 +52,7 @@ import de.symeda.sormas.backend.user.User; import de.symeda.sormas.backend.vaccination.Vaccination; -@Entity -@Table(name = "adverseeventsfollowingimmunization") +@Entity(name = "adverseeventsfollowingimmunization") public class Aefi extends CoreAdo { private static final long serialVersionUID = -7845660472641846292L; diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiInvestigation.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiInvestigation.java index e4157a4c6c0..be0e4de6af1 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiInvestigation.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/adverseeventsfollowingimmunization/entity/AefiInvestigation.java @@ -32,7 +32,6 @@ import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.OneToOne; -import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; import javax.persistence.Transient; @@ -66,8 +65,7 @@ import de.symeda.sormas.backend.user.User; import de.symeda.sormas.backend.vaccination.Vaccination; -@Entity -@Table(name = "adverseeventsfollowingimmunizationinvestigation") +@Entity(name = "adverseeventsfollowingimmunizationinvestigation") public class AefiInvestigation extends CoreAdo { private static final long serialVersionUID = 6128204752074963848L; 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 584b2fa6fd6..c907e3669f4 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 @@ -122,6 +122,36 @@ IMMUNIZATION_ARCHIVE + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT + + PERSON_VIEW PERSON_VIEW @@ -607,6 +637,11 @@ DASHBOARD_SAMPLES_VIEW + + DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW + DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW + + CASE_CLINICIAN_VIEW CASE_CLINICIAN_VIEW diff --git a/sormas-backend/src/main/resources/sql/sormas_schema.sql b/sormas-backend/src/main/resources/sql/sormas_schema.sql index f08ecaec095..fb32127ab77 100644 --- a/sormas-backend/src/main/resources/sql/sormas_schema.sql +++ b/sormas-backend/src/main/resources/sql/sormas_schema.sql @@ -13257,4 +13257,415 @@ ALTER TABLE externalmessage_history ADD COLUMN personadditionaldetails text; INSERT INTO schema_version (version_number, comment) VALUES (551, '#13147 Phone Number Validation for E-Santé Reports – Remove and Store Non-Numeric Text'); + +-- 2024-10-16 Adverse Events Following Immunization (AEFI) - Entities #12634 +-- adverse events +create table adverseevents +( + id bigint not null, + uuid varchar(36) not null, + changedate timestamp(3) not null, + creationdate timestamp(3) not null, + severelocalreaction varchar(255), + severelocalreactionmorethanthreedays boolean, + severelocalreactionbeyondnearestjoint boolean, + seizures varchar(255), + seizuretype varchar(255), + abscess varchar(255), + sepsis varchar(255), + encephalopathy varchar(255), + toxicshocksyndrome varchar(255), + thrombocytopenia varchar(255), + anaphylaxis varchar(255), + feverishfeeling varchar(255), + otheradverseeventdetails varchar(255), + sys_period tstzrange not null, + change_user_id bigint +); + +alter table adverseevents owner to sormas_user; + +alter table adverseevents add primary key (id); +alter table adverseevents add unique (uuid); +alter table adverseevents add constraint fk_adverseevents_change_user_id foreign key (change_user_id) references users; + +-- adverse events history +CREATE TABLE adverseevents_history (LIKE adverseevents); +DROP TRIGGER IF EXISTS versioning_trigger ON adverseevents; +CREATE TRIGGER versioning_trigger + BEFORE INSERT OR UPDATE ON adverseevents + FOR EACH ROW EXECUTE PROCEDURE versioning('sys_period', 'adverseevents_history', true); +DROP TRIGGER IF EXISTS delete_history_trigger ON adverseevents; +CREATE TRIGGER delete_history_trigger + AFTER DELETE ON adverseevents + FOR EACH ROW EXECUTE PROCEDURE delete_history_trigger('adverseevents_history', 'id'); +ALTER TABLE adverseevents_history OWNER TO sormas_user; + +-- adverse events following immunization (AEFI) +create table adverseeventsfollowingimmunization +( + id bigint not null, + uuid varchar(36) not null, + changedate timestamp(3) not null, + creationdate timestamp(3) not null, + immunization_id bigint not null, + address_id bigint, + primarysuspectvaccine_id bigint not null, + adverseevents_id bigint not null, + person_id bigint, + reportdate timestamp not null, + reportinguser_id bigint not null, + externalid varchar(512), + responsibleregion_id bigint, + responsibledistrict_id bigint, + responsiblecommunity_id bigint, + country_id bigint, + reportingidnumber varchar(512) not null, + firstname varchar(255), + lastname varchar(255), + phonenumber varchar(255), + pregnant varchar(255), + trimester varchar(255), + lactating varchar(255), + onsetageyears integer, + onsetagemonths integer, + onsetagedays integer, + agegroup varchar(255), + healthfacility_id bigint, + healthfacilitydetails varchar(512), + reportingofficername varchar(255), + reportingofficerfacility_id bigint, + reportingofficerfacilitydetails varchar(512), + reportingofficerdesignation varchar(255), + reportingofficerdepartment varchar(255), + reportingofficeraddress_id bigint, + reportingofficerphonenumber varchar(255), + reportingofficeremail varchar(255), + healthsystemnotifieddate timestamp, + todaysdate timestamp, + startdatetime timestamp, + aefidescription text, + serious varchar(255) not null, + seriousreason varchar(255), + seriousreasondetails text, + outcome varchar(255) not null, + deathdate timestamp, + autopsydone varchar(255), + pastmedicalhistory text, + investigationneeded varchar(255), + investigationplanneddate timestamp, + receivedatnationalleveldate timestamp, + worldwideid varchar(255), + nationallevelcomment text, + archived boolean default false, + endofprocessingdate timestamp, + archiveundonereason varchar(255), + deleted boolean default false, + deletionreason varchar(255), + otherdeletionreason text, + sys_period tstzrange not null, + change_user_id bigint +); + +alter table adverseeventsfollowingimmunization owner to sormas_user; + +alter table adverseeventsfollowingimmunization add primary key (id); +alter table adverseeventsfollowingimmunization add unique (uuid); +alter table adverseeventsfollowingimmunization add constraint fk_aefi_address_id foreign key (address_id) references location; +alter table adverseeventsfollowingimmunization add constraint fk_aefi_adverseevents_id foreign key (adverseevents_id) references adverseevents; +alter table adverseeventsfollowingimmunization add constraint fk_aefi_change_user_id foreign key (change_user_id) references users; +alter table adverseeventsfollowingimmunization add constraint fk_aefi_country_id foreign key (country_id) references country; +alter table adverseeventsfollowingimmunization add constraint fk_aefi_healthfacility_id foreign key (healthfacility_id) references facility; +alter table adverseeventsfollowingimmunization add constraint fk_aefi_immunization_id foreign key (immunization_id) references immunization; +alter table adverseeventsfollowingimmunization add constraint fk_aefi_person_id foreign key (person_id) references person; +alter table adverseeventsfollowingimmunization add constraint fk_aefi_primarysuspectvaccine_id foreign key (primarysuspectvaccine_id) references vaccination; +alter table adverseeventsfollowingimmunization add constraint fk_aefi_reporting_user_id foreign key (reportinguser_id) references users; +alter table adverseeventsfollowingimmunization add constraint fk_aefi_reportingofficeraddress_id foreign key (reportingofficeraddress_id) references location; +alter table adverseeventsfollowingimmunization add constraint fk_aefi_reportingofficerfacility_id foreign key (reportingofficerfacility_id) references facility; +alter table adverseeventsfollowingimmunization add constraint fk_aefi_responsiblecommunity_id foreign key (responsiblecommunity_id) references community; +alter table adverseeventsfollowingimmunization add constraint fk_aefi_responsibledistrict_id foreign key (responsibledistrict_id) references district; +alter table adverseeventsfollowingimmunization add constraint fk_aefi_responsibleregion_id foreign key (responsibleregion_id) references region; + +-- AEFI history +CREATE TABLE adverseeventsfollowingimmunization_history (LIKE adverseeventsfollowingimmunization); +DROP TRIGGER IF EXISTS versioning_trigger ON adverseeventsfollowingimmunization; +CREATE TRIGGER versioning_trigger + BEFORE INSERT OR UPDATE ON adverseeventsfollowingimmunization + FOR EACH ROW EXECUTE PROCEDURE versioning('sys_period', 'adverseeventsfollowingimmunization_history', true); +DROP TRIGGER IF EXISTS delete_history_trigger ON adverseeventsfollowingimmunization; +CREATE TRIGGER delete_history_trigger + AFTER DELETE ON adverseeventsfollowingimmunization + FOR EACH ROW EXECUTE PROCEDURE delete_history_trigger('adverseeventsfollowingimmunization_history', 'id'); +ALTER TABLE adverseeventsfollowingimmunization_history OWNER TO sormas_user; + +-- AEFI vaccination +create table adverseeventsfollowingimmunization_vaccinations +( + adverseeventsfollowingimmunization_id bigint not null, + vaccination_id bigint not null, + sys_period tstzrange not null +); + +alter table adverseeventsfollowingimmunization_vaccinations owner to sormas_user; + +alter table adverseeventsfollowingimmunization_vaccinations add constraint aefi_vaccinations_pkey primary key (adverseeventsfollowingimmunization_id, vaccination_id); +alter table adverseeventsfollowingimmunization_vaccinations add constraint fk_aefi_vaccinations_aefi_id foreign key (adverseeventsfollowingimmunization_id) references adverseeventsfollowingimmunization; +alter table adverseeventsfollowingimmunization_vaccinations add constraint fk_aefi_vaccinations_vaccination_id foreign key (vaccination_id) references vaccination; + +-- AEFI vaccination history +CREATE TABLE adverseeventsfollowingimmunization_vaccinations_history (LIKE adverseeventsfollowingimmunization_vaccinations); +DROP TRIGGER IF EXISTS versioning_trigger ON adverseeventsfollowingimmunization_vaccinations; +CREATE TRIGGER versioning_trigger + BEFORE INSERT OR UPDATE ON adverseeventsfollowingimmunization_vaccinations + FOR EACH ROW EXECUTE PROCEDURE versioning('sys_period', 'adverseeventsfollowingimmunization_vaccinations_history', true); +DROP TRIGGER IF EXISTS delete_history_trigger ON adverseeventsfollowingimmunization_vaccinations; +CREATE TRIGGER delete_history_trigger + AFTER DELETE ON adverseeventsfollowingimmunization_vaccinations + FOR EACH ROW EXECUTE PROCEDURE delete_history_trigger('adverseeventsfollowingimmunization_vaccinations_history', 'id'); +ALTER TABLE adverseeventsfollowingimmunization_vaccinations_history OWNER TO sormas_user; + +-- AEFI investigation +create table adverseeventsfollowingimmunizationinvestigation +( + id bigint not null, + uuid varchar(36) not null, + changedate timestamp(3) not null, + creationdate timestamp(3) not null, + adverseeventsfollowingimmunization_id bigint not null, + address_id bigint, + primarysuspectvaccine_id bigint, + reportdate timestamp not null, + reportinguser_id bigint not null, + externalid varchar(512), + responsibleregion_id bigint, + responsibledistrict_id bigint, + responsiblecommunity_id bigint, + country_id bigint, + investigationcaseid varchar(255), + placeofvaccination varchar(255) not null, + placeofvaccinationdetails varchar(512), + vaccinationactivity varchar(255) not null, + vaccinationactivitydetails varchar(512), + vaccinationfacility_id bigint, + vaccinationfacilitydetails varchar(512), + reportingofficername varchar(255), + reportingofficerfacility_id bigint, + reportingofficerfacilitydetails varchar(512), + reportingofficerdesignation varchar(255), + reportingofficerdepartment varchar(255), + reportingofficeraddress_id bigint, + reportingofficerlandlinephonenumber varchar(255), + reportingofficermobilephonenumber varchar(255), + reportingofficeremail varchar(255), + investigationdate timestamp not null, + formcompletiondate timestamp not null, + investigationstage varchar(255), + onsetageyears integer, + onsetagemonths integer, + onsetagedays integer, + agegroup varchar(255), + typeofsite varchar(255) not null, + typeofsitedetails varchar(255), + keysymptomdatetime timestamp, + hospitalizationdate timestamp, + reportedtohealthauthoritydate timestamp, + statusondateofinvestigation varchar(255), + deathdatetime timestamp, + autopsydone varchar(255), + autopsydate timestamp, + autopsyplanneddatetime timestamp, + autopsyreportname varchar(255), + pasthistoryofsimilarevent varchar(255), + pasthistoryofsimilareventdetails varchar(512), + adverseeventafterpreviousvaccinations varchar(255), + adverseeventafterpreviousvaccinationsdetails varchar(512), + historyofallergytovaccinedrugorfood varchar(255), + historyofallergytovaccinedrugorfooddetails varchar(512), + preexistingillnessthirtydaysorcongenitaldisorder varchar(255), + preexistingillnessthirtydaysorcongenitaldisorderdetails varchar(512), + historyofhospitalizationinlastthirtydayswithcause varchar(255), + historyofhospitalizationinlastthirtydayswithcausedetails varchar(512), + currentlyonconcomitantmedication varchar(255), + currentlyonconcomitantmedicationdetails varchar(255), + familyhistoryofdiseaseorallergy varchar(255), + familyhistoryofdiseaseorallergydetails varchar(512), + pregnant varchar(255), + numberofweekspregnant integer, + breastfeeding varchar(255), + birthterm varchar(255), + birthweight real, + deliveryprocedure varchar(255), + deliveryproceduredetails varchar(512), + seriousaefiinfosourcestring varchar(512), + seriousaefiinfosourcedetails varchar(512), + seriousaefiverbalautopsyinfosourcedetails varchar(512), + firstcaregiversname varchar(255), + othercaregiversnames varchar(512), + othersourceswhoprovidedinfo varchar(512), + signsandsymptomsfromtimeofvaccination text, + clinicaldetailsofficername varchar(255), + clinicaldetailsofficerphonenumber varchar(255), + clinicaldetailsofficeremail varchar(255), + clinicaldetailsofficerdesignation varchar(255), + clinicaldetailsdatetime timestamp, + patientreceivedmedicalcare varchar(255), + patientreceivedmedicalcaredetails text, + provisionalorfinaldiagnosis text, + patientimmunizedperiod varchar(255), + patientimmunizedperioddetails varchar(512), + vaccinegivenperiod varchar(255), + vaccinegivenperioddetails varchar(512), + errorprescribingvaccine varchar(255), + errorprescribingvaccinedetails varchar(512), + vaccinecouldhavebeenunsterile varchar(255), + vaccinecouldhavebeenunsteriledetails varchar(512), + vaccinephysicalconditionabnormal varchar(255), + vaccinephysicalconditionabnormaldetails varchar(255), + errorinvaccinereconstitution varchar(255), + errorinvaccinereconstitutiondetails varchar(512), + errorinvaccinehandling varchar(255), + errorinvaccinehandlingdetails varchar(512), + vaccineadministeredincorrectly varchar(255), + vaccineadministeredincorrectlydetails varchar(255), + numberimmunizedfromconcernedvaccinevial integer, + numberimmunizedwithconcernedvaccineinsamesession integer, + numberimmunizedconcernedvaccinesamebatchnumberotherlocations integer, + numberimmunizedconcernedvaccinesamebatchnumberlocationdetails varchar(512), + vaccinehasqualitydefect varchar(255), + vaccinehasqualitydefectdetails varchar(512), + eventisastressresponserelatedtoimmunization varchar(255), + eventisastressresponserelatedtoimmunizationdetails varchar(255), + caseispartofacluster varchar(255), + caseispartofaclusterdetails varchar(255), + numberofcasesdetectedincluster integer, + allcasesinclusterreceivedvaccinefromsamevial varchar(255), + allcasesinclusterreceivedvaccinefromsamevialdetails varchar(512), + numberofvialsusedincluster integer, + numberofvialsusedinclusterdetails varchar(255), + adsyringesusedforimmunization varchar(255), + typeofsyringesused varchar(255), + typeofsyringesuseddetails varchar(512), + syringesusedadditionaldetails text, + samereconstitutionsyringeusedformultiplevialsofsamevaccine varchar(255), + samereconstitutionsyringeusedforreconstitutingdifferentvaccines varchar(255), + samereconstitutionsyringeforeachvaccinevial varchar(255), + samereconstitutionsyringeforeachvaccination varchar(255), + vaccinesanddiluentsusedrecommendedbymanufacturer varchar(255), + reconstitutionadditionaldetails text, + correctdoseorroute varchar(255), + timeofreconstitutionmentionedonthevial varchar(255), + nontouchtechniquefollowed varchar(255), + contraindicationscreenedpriortovaccination varchar(255), + numberofaefireportedfromvaccinedistributioncenterlastthirtydays integer, + trainingreceivedbyvaccinator varchar(255), + lasttrainingreceivedbyvaccinatordate timestamp, + injectiontechniqueadditionaldetails text, + vaccinestoragerefrigeratortemperaturemonitored varchar(255), + anystoragetemperaturedeviationoutsidetwotoeightdegrees varchar(255), + storagetemperaturemonitoringadditionaldetails text, + correctprocedureforstoragefollowed varchar(255), + anyotheriteminrefrigerator varchar(255), + partiallyusedreconstitutedvaccinesinrefrigerator varchar(255), + unusablevaccinesinrefrigerator varchar(255), + unusablediluentsinstore varchar(255), + vaccinestoragepointadditionaldetails text, + vaccinecarriertype varchar(255), + vaccinecarriertypedetails varchar(512), + vaccinecarriersenttositeonsamedateasvaccination varchar(255), + vaccinecarrierreturnedfromsiteonsamedateasvaccination varchar(255), + conditionedicepackused varchar(255), + vaccinetransportationadditionaldetails text, + similareventsreportedsameperiodandlocality varchar(255), + similareventsreportedsameperiodandlocalitydetails varchar(512), + numberofsimilareventsreportedsameperiodandlocality integer, + numberofthoseaffectedvaccinated integer, + numberofthoseaffectednotvaccinated integer, + numberofthoseaffectedvaccinatedunknown integer, + communityinvestigationadditionaldetails text, + otherinvestigationfindings text, + investigationstatus varchar(255), + investigationstatusdetails text, + adverseeventfollowingimmunizationclassification varchar(255), + adverseeventfollowingimmunizationclassificationsubtype varchar(255), + adverseeventfollowingimmunizationclassificationdetails varchar(512), + causality varchar(255), + causalitydetails text, + investigationcompletiondate timestamp, + archived boolean, + endofprocessingdate timestamp, + archiveundonereason varchar(255), + deleted boolean, + deletionreason varchar(255), + otherdeletionreason text, + sys_period tstzrange not null, + change_user_id bigint +); + +alter table adverseeventsfollowingimmunizationinvestigation owner to sormas_user; + +alter table adverseeventsfollowingimmunizationinvestigation add primary key (id); +alter table adverseeventsfollowingimmunizationinvestigation add unique (uuid); +alter table adverseeventsfollowingimmunizationinvestigation add constraint fk_aefiinvestigation_address_id foreign key (address_id) references location; +alter table adverseeventsfollowingimmunizationinvestigation add constraint fk_aefiinvestigation_aefi_id foreign key (adverseeventsfollowingimmunization_id) references adverseeventsfollowingimmunization; +alter table adverseeventsfollowingimmunizationinvestigation add constraint fk_aefiinvestigation_change_user_id foreign key (change_user_id) references users; +alter table adverseeventsfollowingimmunizationinvestigation add constraint fk_aefiinvestigation_country_id foreign key (country_id) references country; +alter table adverseeventsfollowingimmunizationinvestigation add constraint fk_aefiinvestigation_primarysuspectvaccine_id foreign key (primarysuspectvaccine_id) references vaccination; +alter table adverseeventsfollowingimmunizationinvestigation add constraint fk_aefiinvestigation_reportingofficeraddress_id foreign key (reportingofficeraddress_id) references location; +alter table adverseeventsfollowingimmunizationinvestigation add constraint fk_aefiinvestigation_reportingofficerfacility_id foreign key (reportingofficerfacility_id) references facility; +alter table adverseeventsfollowingimmunizationinvestigation add constraint fk_aefiinvestigation_reportinguser_id foreign key (reportinguser_id) references users; +alter table adverseeventsfollowingimmunizationinvestigation add constraint fk_aefiinvestigation_responsiblecommunity_id foreign key (responsiblecommunity_id) references community; +alter table adverseeventsfollowingimmunizationinvestigation add constraint fk_aefiinvestigation_responsibledistrict_id foreign key (responsibledistrict_id) references district; +alter table adverseeventsfollowingimmunizationinvestigation add constraint fk_aefiinvestigation_responsibleregion_id foreign key (responsibleregion_id) references region; +alter table adverseeventsfollowingimmunizationinvestigation add constraint fk_aefiinvestigation_vaccinationfacility_id foreign key (vaccinationfacility_id) references facility; + +-- AEFI investigation history +CREATE TABLE adverseeventsfollowingimmunizationinvestigation_history (LIKE adverseeventsfollowingimmunizationinvestigation); + +DROP TRIGGER IF EXISTS versioning_trigger ON adverseeventsfollowingimmunizationinvestigation; +CREATE TRIGGER versioning_trigger + BEFORE INSERT OR UPDATE ON adverseeventsfollowingimmunizationinvestigation + FOR EACH ROW EXECUTE PROCEDURE versioning('sys_period', 'adverseeventsfollowingimmunizationinvestigation_history', true); +DROP TRIGGER IF EXISTS delete_history_trigger ON adverseeventsfollowingimmunizationinvestigation; +CREATE TRIGGER delete_history_trigger + AFTER DELETE ON adverseeventsfollowingimmunizationinvestigation + FOR EACH ROW EXECUTE PROCEDURE delete_history_trigger('adverseeventsfollowingimmunizationinvestigation_history', 'id'); + +ALTER TABLE adverseeventsfollowingimmunizationinvestigation_history OWNER TO sormas_user; + +-- AEFI investigation vaccination +create table adverseeventsfollowingimmunizationinvestigation_vaccinations +( + adverseeventsfollowingimmunizationinvestigation_id bigint not null, + vaccination_id bigint not null, + sys_period tstzrange not null +); + +alter table adverseeventsfollowingimmunizationinvestigation_vaccinations owner to sormas_user; + +alter table adverseeventsfollowingimmunizationinvestigation_vaccinations add constraint aefi_investigation_vaccinations_pkey primary key (adverseeventsfollowingimmunizationinvestigation_id, vaccination_id); +alter table adverseeventsfollowingimmunizationinvestigation_vaccinations add constraint fk_aefiinvestigation_vaccinations_aefiinvestigation_id foreign key (adverseeventsfollowingimmunizationinvestigation_id) references adverseeventsfollowingimmunizationinvestigation; +alter table adverseeventsfollowingimmunizationinvestigation_vaccinations add constraint fk_aefiinvestigation_vaccinations_vaccination_id foreign key (vaccination_id) references vaccination; + +-- AEFI investigation vaccination history +CREATE TABLE aefiinvestigation_vaccinations_history (LIKE adverseeventsfollowingimmunizationinvestigation_vaccinations); +DROP TRIGGER IF EXISTS versioning_trigger ON adverseeventsfollowingimmunizationinvestigation_vaccinations; +CREATE TRIGGER versioning_trigger + BEFORE INSERT OR UPDATE ON adverseeventsfollowingimmunizationinvestigation_vaccinations + FOR EACH ROW EXECUTE PROCEDURE versioning('sys_period', 'aefiinvestigation_vaccinations_history', true); +DROP TRIGGER IF EXISTS delete_history_trigger ON adverseeventsfollowingimmunizationinvestigation_vaccinations; +CREATE TRIGGER delete_history_trigger + AFTER DELETE ON adverseeventsfollowingimmunizationinvestigation_vaccinations + FOR EACH ROW EXECUTE PROCEDURE delete_history_trigger('aefiinvestigation_vaccinations_history', 'id'); +ALTER TABLE aefiinvestigation_vaccinations_history OWNER TO sormas_user; + +-- Assign AEFI user rights to default admin and national_user user roles +INSERT INTO userroles_userrights (userrole_id, userright) SELECT id, 'DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW' FROM public.userroles WHERE userroles.linkeddefaultuserrole in ('ADMIN','NATIONAL_USER'); +INSERT INTO userroles_userrights (userrole_id, userright) SELECT id, 'ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE' FROM public.userroles WHERE userroles.linkeddefaultuserrole in ('ADMIN','NATIONAL_USER'); +INSERT INTO userroles_userrights (userrole_id, userright) SELECT id, 'ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW' FROM public.userroles WHERE userroles.linkeddefaultuserrole in ('ADMIN','NATIONAL_USER'); +INSERT INTO userroles_userrights (userrole_id, userright) SELECT id, 'ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT' FROM public.userroles WHERE userroles.linkeddefaultuserrole in ('ADMIN','NATIONAL_USER'); +INSERT INTO userroles_userrights (userrole_id, userright) SELECT id, 'ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE' FROM public.userroles WHERE userroles.linkeddefaultuserrole in ('ADMIN','NATIONAL_USER'); +INSERT INTO userroles_userrights (userrole_id, userright) SELECT id, 'ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE' FROM public.userroles WHERE userroles.linkeddefaultuserrole in ('ADMIN','NATIONAL_USER'); +INSERT INTO userroles_userrights (userrole_id, userright) SELECT id, 'ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT' FROM public.userroles WHERE userroles.linkeddefaultuserrole in ('ADMIN','NATIONAL_USER'); + +INSERT INTO schema_version (version_number, comment) VALUES (552, 'Adverse Events Following Immunization (AEFI) - Entities #12634'); -- *** 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/common/HistoryTablesTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/common/HistoryTablesTest.java index ecaba04ef41..725e266a9ed 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/common/HistoryTablesTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/common/HistoryTablesTest.java @@ -27,13 +27,19 @@ import org.testcontainers.containers.JdbcDatabaseContainer; import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; import org.testcontainers.images.builder.ImageFromDockerfile; +import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils; import de.hilling.junit.cdi.CdiTestJunitExtension; import de.hilling.junit.cdi.annotations.BypassTestInterceptor; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.Aefi; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AefiInvestigation; @ExtendWith(CdiTestJunitExtension.class) public class HistoryTablesTest { + private static final List NO_HISTORY_REQUIRED_TABLES = + Arrays.asList(Aefi.AEFI_VACCINATIONS_TABLE_NAME, AefiInvestigation.AEFI_INVESTIGATION_VACCINATIONS_TABLE_NAME); + /** * Test that the *_history tables have the same columns as the corresponding production tables * @@ -71,6 +77,7 @@ public void testHistoryTablesMatch() throws IOException, URISyntaxException { Files.readAllBytes(Paths.get(Objects.requireNonNull(getClass().getClassLoader().getResource("checkHistoryTables.sql")).toURI()))); @SuppressWarnings("unchecked") List results = (List) em.createNativeQuery(checkHistoryTablesSql).getResultList(); + results.removeIf(o -> StringUtils.containsAny(o[1].toString(), NO_HISTORY_REQUIRED_TABLES.toArray(String[]::new))); StringBuilder result = new StringBuilder(); results.forEach(objects -> { result.append("\n"); diff --git a/sormas-backend/src/test/java/de/symeda/sormas/backend/importexport/DatabaseExportServiceTest.java b/sormas-backend/src/test/java/de/symeda/sormas/backend/importexport/DatabaseExportServiceTest.java index afcc4faf9bf..e6b42ec468c 100644 --- a/sormas-backend/src/test/java/de/symeda/sormas/backend/importexport/DatabaseExportServiceTest.java +++ b/sormas-backend/src/test/java/de/symeda/sormas/backend/importexport/DatabaseExportServiceTest.java @@ -23,6 +23,9 @@ import com.tngtech.archunit.core.importer.ClassFileImporter; import de.symeda.sormas.api.importexport.DatabaseTable; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AdverseEvents; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.Aefi; +import de.symeda.sormas.backend.adverseeventsfollowingimmunization.entity.AefiInvestigation; import de.symeda.sormas.backend.environment.Environment; import de.symeda.sormas.backend.environment.environmentsample.EnvironmentSample; import de.symeda.sormas.backend.immunization.entity.DirectoryImmunization; @@ -64,7 +67,10 @@ public void testGetConfigFullyDefined() { FirstVaccinationDate.class, Environment.class, EnvironmentSample.class, - SelfReport.class); + SelfReport.class, + Aefi.class, + AdverseEvents.class, + AefiInvestigation.class); @Test public void test_all_entities_have_export_configuration() { @@ -107,6 +113,10 @@ public void test_all_entities_have_export_configuration() { // remove not exported entities from the list of missing ones NOT_EXPORTED_ENTITIES.forEach(e -> missingEntities.remove(e.getSimpleName())); + //remove aefi join tables + missingJoinTables.remove(Aefi.AEFI_VACCINATIONS_TABLE_NAME); + missingJoinTables.remove(AefiInvestigation.AEFI_INVESTIGATION_VACCINATIONS_TABLE_NAME); + assertThat("Missing export configuration for entities [" + String.join(", ", missingEntities) + "]", missingEntities, hasSize(0)); assertThat( "Export configuration not wanted for entities [" + String.join(", ", exportedButNotWantedEntity) + "]", diff --git a/sormas-backend/src/test/resources/checkHistoryTables.sql b/sormas-backend/src/test/resources/checkHistoryTables.sql index 7d0a5860b3a..9f8056274ef 100644 --- a/sormas-backend/src/test/resources/checkHistoryTables.sql +++ b/sormas-backend/src/test/resources/checkHistoryTables.sql @@ -23,11 +23,11 @@ AND c_hist.column_name IS NULL AND c.table_name NOT IN (SELECT t.table_name FROM information_schema."tables" t WHERE t.table_schema = 'public' AND t.table_name NOT LIKE '%_history' - AND (SELECT COUNT(t_hist.table_name) FROM information_schema."tables" t_hist WHERE concat(t.table_name,'_history') = t_hist .table_name) = 0) + AND (SELECT COUNT(t_hist.table_name) FROM information_schema."tables" t_hist WHERE concat(t.table_name,'_history') = t_hist.table_name) = 0) UNION SELECT 'no history table' as remark, t.table_name, null as column_name, null as data_type FROM information_schema."tables" t WHERE t.table_schema = 'public' AND t.table_name NOT LIKE '%_history' AND t.table_name NOT IN ('schema_version', 'systemevent') AND t.table_name NOT like 'pg_%' -AND (SELECT COUNT(t_hist.table_name) FROM information_schema."tables" t_hist WHERE concat(t.table_name,'_history') = t_hist .table_name) = 0 +AND (SELECT COUNT(t_hist.table_name) FROM information_schema."tables" t_hist WHERE concat(t.table_name,'_history') = t_hist.table_name) = 0 UNION SELECT 'missing delete history trigger' as remark, t.table_name, null as column_name, null as data_type FROM information_schema."tables" t WHERE t.table_schema = 'public' 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 c78da1af03b..d9f6a362c55 100644 --- a/sormas-rest/src/main/webapp/WEB-INF/glassfish-web.xml +++ b/sormas-rest/src/main/webapp/WEB-INF/glassfish-web.xml @@ -115,6 +115,36 @@ IMMUNIZATION_ARCHIVE + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT + + PERSON_VIEW PERSON_VIEW @@ -590,6 +620,11 @@ DASHBOARD_SAMPLES_VIEW + + DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW + DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW + + CASE_CLINICIAN_VIEW CASE_CLINICIAN_VIEW diff --git a/sormas-rest/src/main/webapp/WEB-INF/web.xml b/sormas-rest/src/main/webapp/WEB-INF/web.xml index 3decccae6a9..dc2a67e6b83 100644 --- a/sormas-rest/src/main/webapp/WEB-INF/web.xml +++ b/sormas-rest/src/main/webapp/WEB-INF/web.xml @@ -100,6 +100,30 @@ IMMUNIZATION_ARCHIVE + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT + + PERSON_VIEW @@ -480,6 +504,10 @@ DASHBOARD_SAMPLES_VIEW + + DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW + + CASE_CLINICIAN_VIEW diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiView.java index 4499d4a7278..66cff5e28c8 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiView.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AbstractAefiView.java @@ -24,6 +24,8 @@ public class AbstractAefiView extends AbstractSubNavigationView { + public static final String ROOT_VIEW_NAME = "adverseevents"; + protected AbstractAefiView(String viewName) { super(viewName); } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationView.java index ebc4814cfd8..5dccd5e14cb 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationView.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiInvestigationView.java @@ -57,7 +57,7 @@ public class AefiInvestigationView extends AbstractAefiView { - public static final String VIEW_NAME = "adverseeventinvestigations"; + public static final String VIEW_NAME = ROOT_VIEW_NAME + "/investigations"; private final AefiInvestigationCriteria criteria; @@ -111,7 +111,7 @@ public AefiInvestigationView() { gridLayout.setMargin(false); gridLayout.setSpacing(false); gridLayout.setSizeFull(); - CssStyles.style(gridLayout, CssStyles.VIEW_SECTION, CssStyles.VSPACE_TOP_3); + //CssStyles.style(gridLayout, CssStyles.VIEW_SECTION, CssStyles.VSPACE_TOP_3); gridLayout.addComponent(createStatusFilterBar()); gridLayout.addComponent(dataLayout); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiView.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiView.java index ef58c7bc968..c68ab2828be 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiView.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/AefiView.java @@ -61,7 +61,7 @@ public class AefiView extends AbstractAefiView { - public static final String VIEW_NAME = "adverseevents"; + public static final String VIEW_NAME = ROOT_VIEW_NAME; private final AefiCriteria criteria; @@ -125,7 +125,7 @@ public AefiView() { gridLayout.setMargin(false); gridLayout.setSpacing(false); gridLayout.setSizeFull(); - CssStyles.style(gridLayout, CssStyles.VIEW_SECTION, CssStyles.VSPACE_TOP_3); + //CssStyles.style(gridLayout, CssStyles.VIEW_SECTION, CssStyles.VSPACE_TOP_3); gridLayout.addComponent(createStatusFilterBar()); gridLayout.addComponent(dataLayout); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefiinvestigationlink/AefiInvestigationList.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefiinvestigationlink/AefiInvestigationList.java index 7a78c37b890..b063ad4f542 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefiinvestigationlink/AefiInvestigationList.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefiinvestigationlink/AefiInvestigationList.java @@ -18,8 +18,6 @@ import java.util.List; import java.util.function.Consumer; -import org.apache.commons.collections.CollectionUtils; - import com.vaadin.ui.Button; import com.vaadin.ui.Label; @@ -59,7 +57,7 @@ public void reload() { FacadeProvider.getAefiInvestigationFacade().getEntriesList(listCriteria, 0, maxDisplayedEntries * 20); setEntries(listEntries); - if (CollectionUtils.isNotEmpty(listEntries)) { + if (!listEntries.isEmpty()) { showPage(1); } else { listLayout.removeAllComponents(); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiList.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiList.java index 1c88db1072b..d4c8a1dd8ef 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiList.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/adverseeventsfollowingimmunization/aefilink/AefiList.java @@ -1,17 +1,14 @@ /* * 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 . */ @@ -21,8 +18,6 @@ import java.util.List; import java.util.function.Consumer; -import org.apache.commons.collections.CollectionUtils; - import com.vaadin.ui.Button; import com.vaadin.ui.Label; @@ -58,10 +53,10 @@ public AefiList(AefiListCriteria aefiListCriteria, Consumer actionCall @Override public void reload() { - List aefiListEntries = FacadeProvider.getAefiFacade().getEntriesList(aefiListCriteria, 0, maxDisplayedEntries * 20); + List listEntries = FacadeProvider.getAefiFacade().getEntriesList(aefiListCriteria, 0, maxDisplayedEntries * 20); - setEntries(aefiListEntries); - if (CollectionUtils.isNotEmpty(aefiListEntries)) { + setEntries(listEntries); + if (!listEntries.isEmpty()) { showPage(1); } else { listLayout.removeAllComponents(); 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 a84710ea9e3..aaa7a9eea7e 100644 --- a/sormas-ui/src/main/webapp/VAADIN/themes/sormas/global.scss +++ b/sormas-ui/src/main/webapp/VAADIN/themes/sormas/global.scss @@ -410,6 +410,14 @@ border-bottom-right-radius: 4px; } + .form-section-accordion-panel-title-button{ + font-size: 16px !important; + font-weight: 600; + color: #6591C4; + text-decoration: none !important; + padding-left: 0; + } + .spacing-small { .v-spacing { width: 4px; 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 99b99fa4b15..cc6f9e6ccf8 100644 --- a/sormas-ui/src/main/webapp/WEB-INF/glassfish-web.xml +++ b/sormas-ui/src/main/webapp/WEB-INF/glassfish-web.xml @@ -115,6 +115,36 @@ IMMUNIZATION_ARCHIVE + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT + + PERSON_VIEW PERSON_VIEW @@ -590,6 +620,11 @@ DASHBOARD_SAMPLES_VIEW + + DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW + DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW + + CASE_CLINICIAN_VIEW CASE_CLINICIAN_VIEW diff --git a/sormas-ui/src/main/webapp/WEB-INF/web.xml b/sormas-ui/src/main/webapp/WEB-INF/web.xml index 998d7088943..b62eb6a327a 100644 --- a/sormas-ui/src/main/webapp/WEB-INF/web.xml +++ b/sormas-ui/src/main/webapp/WEB-INF/web.xml @@ -105,6 +105,30 @@ IMMUNIZATION_ARCHIVE + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_CREATE + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EDIT + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_ARCHIVE + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_DELETE + + + + ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_EXPORT + + PERSON_VIEW @@ -485,6 +509,10 @@ DASHBOARD_SAMPLES_VIEW + + DASHBOARD_ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_VIEW + + CASE_CLINICIAN_VIEW