From 901026025af12c23ab4c42d5974882757fd86e07 Mon Sep 17 00:00:00 2001 From: leventegal-she <62599627+leventegal-she@users.noreply.github.com> Date: Fri, 5 Feb 2021 16:08:17 +0200 Subject: [PATCH] 4137 covid vaccine (#4270) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * #4137 enabled and extended covid vaccination info on cases (BE + WEB) * #4137 extend vaccination info in the android app * #4137 - Added lazy loading for sample properties Necessary because too many columns were loaded when trying to fetch all pathogen tests for cases: Caused by: org.postgresql.util.PSQLException: FEHLER: target lists can have at most 1664 entries * #4137 fixed labels and added the new field to detailed export * #4137 fixed vaccine name/manufacturer logic * #4137 WIP new vaccination info entity added to contacts end event participants * #4137 generate vaccination info for existing contacts and event participants + handle missing vaccination info coming from mobile app * #4137 disabled vaccination onf for contacts and event participant in the mobile app * #4137 added vaccination info history table + fixed tests * #4137 fix DateHelper test Co-authored-by: lgal Co-authored-by: Maté Strysewske --- .../symeda/sormas/api/caze/CaseExportDto.java | 2 + .../symeda/sormas/api/contact/ContactDto.java | 14 + .../sormas/api/contact/ContactExportDto.java | 151 ++++++++- .../sormas/api/event/EventParticipantDto.java | 12 + .../api/event/EventParticipantExportDto.java | 152 +++++++-- .../de/symeda/sormas/api/i18n/Captions.java | 13 + .../vaccinationinfo/VaccinationInfoDto.java | 306 ++++++++++++++++++ .../VaccinationInfoFacade.java | 22 ++ .../src/main/resources/captions.properties | 14 + .../sormas/api/utils/DataHelperTest.java | 6 +- .../de/symeda/sormas/app/BaseFragment.java | 4 +- .../app/backend/common/DatabaseHelper.java | 32 +- .../sormas/app/backend/contact/Contact.java | 21 +- .../app/backend/contact/ContactDtoHelper.java | 12 + .../app/backend/event/EventParticipant.java | 13 + .../event/EventParticipantDtoHelper.java | 12 + .../vaccinationinfo/VaccinationInfo.java | 176 ++++++++++ .../vaccinationinfo/VaccinationInfoDao.java | 22 ++ .../VaccinationInfoDtoHelper.java | 71 ++++ .../app/caze/edit/CaseEditFragment.java | 10 +- .../app/contact/edit/ContactEditFragment.java | 9 + .../app/contact/read/ContactReadFragment.java | 7 + .../edit/VaccinationInfoEditFragment.java | 80 +++++ .../read/VaccinationInfoReadFragment.java | 33 ++ .../layout/fragment_contact_edit_layout.xml | 15 + .../layout/fragment_contact_read_layout.xml | 15 + .../fragment_vaccination_info_edit_layout.xml | 163 ++++++++++ .../fragment_vaccination_info_read_layout.xml | 156 +++++++++ .../sormas/backend/contact/Contact.java | 14 + .../backend/contact/ContactFacadeEjb.java | 33 +- .../sormas/backend/contact/ContactJoins.java | 11 + .../backend/contact/ContactService.java | 4 + .../backend/event/EventParticipant.java | 16 + .../event/EventParticipantFacadeEjb.java | 33 +- .../event/EventParticipantService.java | 12 + .../vaccinationinfo/VaccinationInfo.java | 184 +++++++++++ .../VaccinationInfoFacadeEjb.java | 89 +++++ .../VaccinationInfoService.java | 30 ++ .../main/resources/META-INF/persistence.xml | 1 + .../src/main/resources/sql/sormas_schema.sql | 65 +++- .../test/resources/META-INF/persistence.xml | 1 + .../sormas/ui/contact/ContactDataForm.java | 14 +- .../ui/events/EventParticipantEditForm.java | 27 +- .../sormas/ui/utils/AbstractEditForm.java | 10 +- .../utils/SormasFieldGroupFieldFactory.java | 3 + .../ui/vaccination/VaccinationInfoForm.java | 196 +++++++++++ .../test/resources/META-INF/persistence.xml | 1 + 47 files changed, 2237 insertions(+), 50 deletions(-) create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/vaccinationinfo/VaccinationInfoDto.java create mode 100644 sormas-api/src/main/java/de/symeda/sormas/api/vaccinationinfo/VaccinationInfoFacade.java create mode 100644 sormas-app/app/src/main/java/de/symeda/sormas/app/backend/vaccinationinfo/VaccinationInfo.java create mode 100644 sormas-app/app/src/main/java/de/symeda/sormas/app/backend/vaccinationinfo/VaccinationInfoDao.java create mode 100644 sormas-app/app/src/main/java/de/symeda/sormas/app/backend/vaccinationinfo/VaccinationInfoDtoHelper.java create mode 100644 sormas-app/app/src/main/java/de/symeda/sormas/app/vaccinationinfo/edit/VaccinationInfoEditFragment.java create mode 100644 sormas-app/app/src/main/java/de/symeda/sormas/app/vaccinationinfo/read/VaccinationInfoReadFragment.java create mode 100644 sormas-app/app/src/main/res/layout/fragment_vaccination_info_edit_layout.xml create mode 100644 sormas-app/app/src/main/res/layout/fragment_vaccination_info_read_layout.xml create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/vaccinationinfo/VaccinationInfo.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/vaccinationinfo/VaccinationInfoFacadeEjb.java create mode 100644 sormas-backend/src/main/java/de/symeda/sormas/backend/vaccinationinfo/VaccinationInfoService.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/vaccination/VaccinationInfoForm.java diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseExportDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseExportDto.java index a1637053740..51ed2106f29 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseExportDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseExportDto.java @@ -294,9 +294,11 @@ public CaseExportDto(long id, long personId, long personAddressId, long epiDataI String phone, String phoneOwner, String emailAddress, EducationType educationType, String educationDetails, OccupationType occupationType, String occupationDetails, ArmedForcesRelationType ArmedForcesRelationType, YesNoUnknown contactWithSourceCaseKnown, //Date onsetDate, + // vaccination info Vaccination vaccination, String vaccinationDoses, VaccinationInfoSource vaccinationInfoSource, Date firstVaccinationDate, Date lastVaccinationDate, Vaccine vaccineName, String otherVaccineName, VaccineManufacturer vaccineManufacturer, String otherVaccineManufacturer, String vaccineInn, String vaccineBatchNumber, String vaccineUniiCode, String vaccineAtcCode, + YesNoUnknown postpartum, Trimester trimester, long eventCount, String externalID, String externalToken, String birthName, String birthCountryIsoCode, String birthCountryName, String citizenshipIsoCode, String citizenshipCountryName, diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/contact/ContactDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/contact/ContactDto.java index 6ff316d70eb..f50e4bb96cf 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/contact/ContactDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/contact/ContactDto.java @@ -44,6 +44,7 @@ import de.symeda.sormas.api.utils.pseudonymization.Pseudonymizer; import de.symeda.sormas.api.utils.pseudonymization.valuepseudonymizers.LatitudePseudonymizer; import de.symeda.sormas.api.utils.pseudonymization.valuepseudonymizers.LongitudePseudonymizer; +import de.symeda.sormas.api.vaccinationinfo.VaccinationInfoDto; public class ContactDto extends PseudonymizableDto { @@ -123,6 +124,8 @@ public class ContactDto extends PseudonymizableDto { public static final String REPORTING_DISTRICT = "reportingDistrict"; + public static final String VACCINATION_INFO = "vaccinationInfo"; + private CaseReferenceDto caze; private String caseIdExternalSystem; @SensitiveData @@ -273,6 +276,8 @@ public class ContactDto extends PseudonymizableDto { @HideForCountriesExcept private DistrictReferenceDto reportingDistrict; + private VaccinationInfoDto vaccinationInfo; + public static ContactDto build() { final ContactDto contact = new ContactDto(); contact.setUuid(DataHelper.createUuid()); @@ -282,6 +287,7 @@ public static ContactDto build() { contact.setContactStatus(ContactStatus.ACTIVE); contact.setEpiData(EpiDataDto.build()); contact.setHealthConditions(HealthConditionsDto.build()); + contact.setVaccinationInfo(VaccinationInfoDto.build()); return contact; } @@ -888,4 +894,12 @@ public YesNoUnknown getReturningTraveler() { public void setReturningTraveler(YesNoUnknown returningTraveler) { this.returningTraveler = returningTraveler; } + + public VaccinationInfoDto getVaccinationInfo() { + return vaccinationInfo; + } + + public void setVaccinationInfo(VaccinationInfoDto vaccinationInfo) { + this.vaccinationInfo = vaccinationInfo; + } } diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/contact/ContactExportDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/contact/ContactExportDto.java index bc966b01175..3b5f487a4c7 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/contact/ContactExportDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/contact/ContactExportDto.java @@ -26,6 +26,10 @@ import de.symeda.sormas.api.caze.CaseClassification; import de.symeda.sormas.api.caze.CaseDataDto; import de.symeda.sormas.api.caze.CaseJurisdictionDto; +import de.symeda.sormas.api.caze.Vaccination; +import de.symeda.sormas.api.caze.VaccinationInfoSource; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.caze.VaccineManufacturer; import de.symeda.sormas.api.epidata.EpiDataDto; import de.symeda.sormas.api.facility.FacilityHelper; import de.symeda.sormas.api.i18n.I18nProperties; @@ -50,6 +54,7 @@ import de.symeda.sormas.api.utils.YesNoUnknown; import de.symeda.sormas.api.utils.pseudonymization.Pseudonymizer; import de.symeda.sormas.api.utils.pseudonymization.valuepseudonymizers.PostalCodePseudonymizer; +import de.symeda.sormas.api.vaccinationinfo.VaccinationInfoDto; public class ContactExportDto implements Serializable { @@ -166,7 +171,19 @@ public class ContactExportDto implements Serializable { private Date quarantineOfficialOrderSentDate; private YesNoUnknown returningTraveler; - private ContactJurisdictionDto jurisdiction; + private Vaccination vaccination; + private String vaccinationDoses; + private VaccinationInfoSource vaccinationInfoSource; + private Date firstVaccinationDate; + private Date lastVaccinationDate; + private Vaccine vaccineName; + private String otherVaccineName; + private VaccineManufacturer vaccineManufacturer; + private String otherVaccineManufacturer; + private String vaccineInn; + private String vaccineBatchNumber; + private String vaccineUniiCode; + private String vaccineAtcCode; private Long eventCount; private String latestEventId; @@ -182,6 +199,8 @@ public class ContactExportDto implements Serializable { private String reportingDistrict; + private ContactJurisdictionDto jurisdiction; + //@formatter:off public ContactExportDto(long id, long personId, String uuid, String sourceCaseUuid, CaseClassification caseClassification, Disease disease, String diseaseDetails, ContactClassification contactClassification, Boolean multiDayContact, Date firstContactDate, Date lastContactDate, @@ -199,7 +218,13 @@ public ContactExportDto(long id, long personId, String uuid, String sourceCaseUu String facility, String facilityUuid, String facilityDetails, String phone, String phoneOwner, String emailAddress, OccupationType occupationType, String occupationDetails, ArmedForcesRelationType armedForcesRelationType, String region, String district, String community, - long epiDataId, YesNoUnknown contactWithSourceCaseKnown, YesNoUnknown returningTraveler, String externalID, String externalToken, + long epiDataId, YesNoUnknown contactWithSourceCaseKnown, YesNoUnknown returningTraveler, + // vaccination info + Vaccination vaccination, String vaccinationDoses, VaccinationInfoSource vaccinationInfoSource, Date firstVaccinationDate, Date lastVaccinationDate, + Vaccine vaccineName, String otherVaccineName, VaccineManufacturer vaccineManufacturer, String otherVaccineManufacturer, + String vaccineInn, String vaccineBatchNumber, String vaccineUniiCode, String vaccineAtcCode, + + String externalID, String externalToken, String birthName, String birthCountryIsoCode, String birthCountryName, String citizenshipIsoCode, String citizenshipCountryName, String reportingDistrict, String reportingUserUuid, String regionUuid, String districtUuid, String communityUuid, @@ -267,6 +292,21 @@ public ContactExportDto(long id, long personId, String uuid, String sourceCaseUu this.epiDataId = epiDataId; this.contactWithSourceCaseKnown = contactWithSourceCaseKnown; this.returningTraveler = returningTraveler; + + this.vaccination = vaccination; + this.vaccinationDoses = vaccinationDoses; + this.vaccinationInfoSource = vaccinationInfoSource; + this.firstVaccinationDate = firstVaccinationDate; + this.lastVaccinationDate = lastVaccinationDate; + this.vaccineName = vaccineName; + this.otherVaccineName = otherVaccineName; + this.vaccineManufacturer = vaccineManufacturer; + this.otherVaccineManufacturer = otherVaccineManufacturer; + this.vaccineInn = vaccineInn; + this.vaccineBatchNumber = vaccineBatchNumber; + this.vaccineUniiCode = vaccineUniiCode; + this.vaccineAtcCode = vaccineAtcCode; + this.externalID = externalID; this.externalToken = externalToken; this.birthName = birthName; @@ -793,7 +833,98 @@ public void setReturningTraveler(YesNoUnknown returningTraveler) { this.returningTraveler = returningTraveler; } - @Order(71) + @Order(80) + @ExportProperty(VaccinationInfoDto.VACCINATION) + @ExportGroup(ExportGroupType.VACCINATION) + public Vaccination getVaccination() { + return vaccination; + } + + @Order(81) + @ExportProperty(VaccinationInfoDto.VACCINATION_DOSES) + @ExportGroup(ExportGroupType.VACCINATION) + public String getVaccinationDoses() { + return vaccinationDoses; + } + + @Order(82) + @ExportProperty(VaccinationInfoDto.VACCINATION_INFO_SOURCE) + @ExportGroup(ExportGroupType.VACCINATION) + public VaccinationInfoSource getVaccinationInfoSource() { + return vaccinationInfoSource; + } + + @Order(83) + @ExportProperty(VaccinationInfoDto.FIRST_VACCINATION_DATE) + @ExportGroup(ExportGroupType.VACCINATION) + public Date getFirstVaccinationDate() { + return firstVaccinationDate; + } + + @Order(84) + @ExportProperty(VaccinationInfoDto.LAST_VACCINATION_DATE) + @ExportGroup(ExportGroupType.VACCINATION) + public Date getLastVaccinationDate() { + return lastVaccinationDate; + } + + @Order(85) + @ExportProperty(VaccinationInfoDto.VACCINE_NAME) + @ExportGroup(ExportGroupType.VACCINATION) + public Vaccine getVaccineName() { + return vaccineName; + } + + @Order(86) + @ExportProperty(VaccinationInfoDto.OTHER_VACCINE_NAME) + @ExportGroup(ExportGroupType.VACCINATION) + public String getOtherVaccineName() { + return otherVaccineName; + } + + @Order(87) + @ExportProperty(VaccinationInfoDto.VACCINE_MANUFACTURER) + @ExportGroup(ExportGroupType.VACCINATION) + public VaccineManufacturer getVaccineManufacturer() { + return vaccineManufacturer; + } + + @Order(88) + @ExportProperty(VaccinationInfoDto.OTHER_VACCINE_MANUFACTURER) + @ExportGroup(ExportGroupType.VACCINATION) + public String getOtherVaccineManufacturer() { + return otherVaccineManufacturer; + } + + @Order(89) + @ExportProperty(VaccinationInfoDto.VACCINE_INN) + @ExportGroup(ExportGroupType.VACCINATION) + public String getVaccineInn() { + return vaccineInn; + } + + @Order(90) + @ExportProperty(VaccinationInfoDto.VACCINE_BATCH_NUMBER) + @ExportGroup(ExportGroupType.VACCINATION) + public String getVaccineBatchNumber() { + return vaccineBatchNumber; + } + + @Order(91) + @ExportProperty(VaccinationInfoDto.VACCINE_UNII_CODE) + @ExportGroup(ExportGroupType.VACCINATION) + public String getVaccineUniiCode() { + return vaccineUniiCode; + } + + @Order(92) + @ExportProperty(VaccinationInfoDto.VACCINE_ATC_CODE) + @ExportGroup(ExportGroupType.VACCINATION) + public String getVaccineAtcCode() { + return vaccineAtcCode; + } + + @Order(100) @ExportProperty(LATEST_EVENT_ID) @ExportGroup(ExportGroupType.EVENT) public String getLatestEventId() { @@ -804,7 +935,7 @@ public void setLatestEventId(String latestEventId) { this.latestEventId = latestEventId; } - @Order(72) + @Order(101) @ExportProperty(LATEST_EVENT_TITLE) @ExportGroup(ExportGroupType.EVENT) public String getLatestEventTitle() { @@ -815,14 +946,14 @@ public void setLatestEventTitle(String latestEventTitle) { this.latestEventTitle = latestEventTitle; } - @Order(73) + @Order(102) @ExportProperty(EVENT_COUNT) @ExportGroup(ExportGroupType.EVENT) public Long getEventCount() { return eventCount; } - @Order(80) + @Order(103) @ExportProperty(PersonDto.BIRTH_NAME) @ExportGroup(ExportGroupType.SENSITIVE) @HideForCountriesExcept @@ -830,7 +961,7 @@ public String getBirthName() { return birthName; } - @Order(81) + @Order(104) @ExportProperty(PersonDto.BIRTH_COUNTRY) @ExportGroup(ExportGroupType.SENSITIVE) @HideForCountriesExcept @@ -838,7 +969,7 @@ public String getBirthCountry() { return birthCountry; } - @Order(82) + @Order(105) @ExportProperty(PersonDto.CITIZENSHIP) @ExportGroup(ExportGroupType.SENSITIVE) @HideForCountriesExcept @@ -846,7 +977,7 @@ public String getCitizenship() { return citizenship; } - @Order(83) + @Order(106) @ExportProperty(ContactDto.REPORTING_DISTRICT) @ExportGroup(ExportGroupType.ADDITIONAL) @HideForCountriesExcept @@ -854,7 +985,7 @@ public String getReportingDistrict() { return reportingDistrict; } - @Order(84) + @Order(107) @ExportProperty(ContactDto.EXTERNAL_TOKEN) @ExportGroup(ExportGroupType.CORE) public String getExternalToken() { diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/event/EventParticipantDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/event/EventParticipantDto.java index 454ee2ff37c..86f4dadee7a 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/event/EventParticipantDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/event/EventParticipantDto.java @@ -27,6 +27,7 @@ import de.symeda.sormas.api.utils.Required; import de.symeda.sormas.api.utils.SensitiveData; import de.symeda.sormas.api.utils.pseudonymization.PseudonymizableDto; +import de.symeda.sormas.api.vaccinationinfo.VaccinationInfoDto; public class EventParticipantDto extends PseudonymizableDto { @@ -41,6 +42,7 @@ public class EventParticipantDto extends PseudonymizableDto { public static final String REPORTING_USER = "reportingUser"; public static final String REGION = "region"; public static final String DISTRICT = "district"; + public static final String VACCINATION_INFO = "vaccinationInfo"; private UserReferenceDto reportingUser; @Required @@ -54,6 +56,8 @@ public class EventParticipantDto extends PseudonymizableDto { private RegionReferenceDto region; private DistrictReferenceDto district; + private VaccinationInfoDto vaccinationInfo; + public static EventParticipantDto build(EventReferenceDto event, UserReferenceDto reportingUser) { EventParticipantDto eventParticipant = new EventParticipantDto(); eventParticipant.setUuid(DataHelper.createUuid()); @@ -146,4 +150,12 @@ public DistrictReferenceDto getDistrict() { public void setDistrict(DistrictReferenceDto district) { this.district = district; } + + public VaccinationInfoDto getVaccinationInfo() { + return vaccinationInfo; + } + + public void setVaccinationInfo(VaccinationInfoDto vaccinationInfo) { + this.vaccinationInfo = vaccinationInfo; + } } diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/event/EventParticipantExportDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/event/EventParticipantExportDto.java index bba4a37f92c..f349af30ddb 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/event/EventParticipantExportDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/event/EventParticipantExportDto.java @@ -29,6 +29,10 @@ import de.symeda.sormas.api.caze.BirthDateDto; import de.symeda.sormas.api.caze.BurialInfoDto; import de.symeda.sormas.api.caze.EmbeddedSampleExportDto; +import de.symeda.sormas.api.caze.Vaccination; +import de.symeda.sormas.api.caze.VaccinationInfoSource; +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.importexport.ExportProperty; import de.symeda.sormas.api.person.ApproximateAgeType; @@ -44,6 +48,7 @@ import de.symeda.sormas.api.utils.SensitiveData; import de.symeda.sormas.api.utils.pseudonymization.Pseudonymizer; import de.symeda.sormas.api.utils.pseudonymization.valuepseudonymizers.PostalCodePseudonymizer; +import de.symeda.sormas.api.vaccinationinfo.VaccinationInfoDto; public class EventParticipantExportDto implements Serializable { @@ -148,6 +153,20 @@ public class EventParticipantExportDto implements Serializable { private String birthCountry; private String citizenship; + private Vaccination vaccination; + private String vaccinationDoses; + private VaccinationInfoSource vaccinationInfoSource; + private Date firstVaccinationDate; + private Date lastVaccinationDate; + private Vaccine vaccineName; + private String otherVaccineName; + private VaccineManufacturer vaccineManufacturer; + private String otherVaccineManufacturer; + private String vaccineInn; + private String vaccineBatchNumber; + private String vaccineUniiCode; + private String vaccineAtcCode; + private String caseUuid; private List eventParticipantSamples = new ArrayList<>(); @@ -165,7 +184,12 @@ public EventParticipantExportDto(long id, long personId, String personUuid, Stri Integer birthdateDD, Integer birthdateMM, Integer birthdateYYYY, PresentCondition presentCondition, Date deathDate, Date burialDate, BurialConductor burialConductor, String burialPlaceDescription, String addressRegion, String addressDistrict, String addressCommunity, String city, String street, String houseNumber, String additionalInformation, String postalCode, String phone, String emailAddress, String caseUuid, - String birthName, String birthCountryIsoCode, String birthCountryName, String citizenshipIsoCode, String citizenshipCountryName) { + String birthName, String birthCountryIsoCode, String birthCountryName, String citizenshipIsoCode, String citizenshipCountryName, + // vaccination info + Vaccination vaccination, String vaccinationDoses, VaccinationInfoSource vaccinationInfoSource, Date firstVaccinationDate, Date lastVaccinationDate, + Vaccine vaccineName, String otherVaccineName, VaccineManufacturer vaccineManufacturer, String otherVaccineManufacturer, + String vaccineInn, String vaccineBatchNumber, String vaccineUniiCode, String vaccineAtcCode + ) { //@formatter:on this.id = id; @@ -217,6 +241,20 @@ public EventParticipantExportDto(long id, long personId, String personUuid, Stri this.birthCountry = I18nProperties.getCountryName(birthCountryIsoCode, birthCountryName); this.citizenship = I18nProperties.getCountryName(citizenshipIsoCode, citizenshipCountryName); + this.vaccination = vaccination; + this.vaccinationDoses = vaccinationDoses; + this.vaccinationInfoSource = vaccinationInfoSource; + this.firstVaccinationDate = firstVaccinationDate; + this.lastVaccinationDate = lastVaccinationDate; + this.vaccineName = vaccineName; + this.otherVaccineName = otherVaccineName; + this.vaccineManufacturer = vaccineManufacturer; + this.otherVaccineManufacturer = otherVaccineManufacturer; + this.vaccineInn = vaccineInn; + this.vaccineBatchNumber = vaccineBatchNumber; + this.vaccineUniiCode = vaccineUniiCode; + this.vaccineAtcCode = vaccineAtcCode; + jurisdiction = new EventParticipantJurisdictionDto(reportingUserUuid); } @@ -379,6 +417,84 @@ public String getCitizenship() { } @Order(45) + @ExportProperty(VaccinationInfoDto.VACCINATION) + public Vaccination getVaccination() { + return vaccination; + } + + @Order(46) + @ExportProperty(VaccinationInfoDto.VACCINATION_DOSES) + public String getVaccinationDoses() { + return vaccinationDoses; + } + + @Order(45) + @ExportProperty(VaccinationInfoDto.VACCINATION_INFO_SOURCE) + public VaccinationInfoSource getVaccinationInfoSource() { + return vaccinationInfoSource; + } + + @Order(46) + @ExportProperty(VaccinationInfoDto.FIRST_VACCINATION_DATE) + public Date getFirstVaccinationDate() { + return firstVaccinationDate; + } + + @Order(47) + @ExportProperty(VaccinationInfoDto.LAST_VACCINATION_DATE) + public Date getLastVaccinationDate() { + return lastVaccinationDate; + } + + @Order(48) + @ExportProperty(VaccinationInfoDto.VACCINE_NAME) + public Vaccine getVaccineName() { + return vaccineName; + } + + @Order(49) + @ExportProperty(VaccinationInfoDto.OTHER_VACCINE_NAME) + public String getOtherVaccineName() { + return otherVaccineName; + } + + @Order(50) + @ExportProperty(VaccinationInfoDto.VACCINE_MANUFACTURER) + public VaccineManufacturer getVaccineManufacturer() { + return vaccineManufacturer; + } + + @Order(51) + @ExportProperty(VaccinationInfoDto.OTHER_VACCINE_MANUFACTURER) + public String getOtherVaccineManufacturer() { + return otherVaccineManufacturer; + } + + @Order(52) + @ExportProperty(VaccinationInfoDto.VACCINE_INN) + public String getVaccineInn() { + return vaccineInn; + } + + @Order(53) + @ExportProperty(VaccinationInfoDto.VACCINE_BATCH_NUMBER) + public String getVaccineBatchNumber() { + return vaccineBatchNumber; + } + + @Order(54) + @ExportProperty(VaccinationInfoDto.VACCINE_UNII_CODE) + public String getVaccineUniiCode() { + return vaccineUniiCode; + } + + @Order(55) + @ExportProperty(VaccinationInfoDto.VACCINE_ATC_CODE) + public String getVaccineAtcCode() { + return vaccineAtcCode; + } + + @Order(60) @ExportProperty(EventParticipantExportDto.SAMPLE_INFORMATION) public String getOtherSamplesString() { StringBuilder samples = new StringBuilder(); @@ -391,103 +507,103 @@ public String getOtherSamplesString() { return samples.length() > 0 ? samples.substring(0, samples.length() - separator.length()) : ""; } - @Order(46) + @Order(61) @ExportProperty(EventParticipantExportDto.EVENT_PARTICIPANT_INVOLVMENT_DESCRIPTION) public String getInvolvmentDescription() { return involvmentDescription; } - @Order(50) + @Order(62) @ExportProperty(EventDto.UUID) public String getEventUuid() { return eventUuid; } - @Order(51) + @Order(63) @ExportProperty(EventDto.EVENT_STATUS) public EventStatus getEventStatus() { return eventStatus; } - @Order(52) + @Order(64) @ExportProperty(EventDto.EVENT_INVESTIGATION_STATUS) public EventInvestigationStatus getEventInvestigationStatus() { return eventInvestigationStatus; } - @Order(53) + @Order(65) @ExportProperty(EventParticipantExportDto.EVENT_DISEASE) public Disease getEventDisease() { return eventDisease; } - @Order(54) + @Order(66) @ExportProperty(EventParticipantExportDto.EVENT_TYPE_OF_PLACE) public TypeOfPlace getTypeOfPlace() { return typeOfPlace; } - @Order(55) + @Order(67) @ExportProperty(EventParticipantExportDto.EVENT_START_DATE) public Date getEventStartDate() { return eventStartDate; } - @Order(56) + @Order(68) @ExportProperty(EventParticipantExportDto.EVENT_END_DATE) public Date getEventEndDate() { return eventEndDate; } - @Order(57) + @Order(69) @ExportProperty(EventParticipantExportDto.EVENT_TITLE) public String getEventTitle() { return eventTitle; } - @Order(58) + @Order(70) @ExportProperty(EventParticipantExportDto.EVENT_DESCRIPTION) public String getEventDesc() { return eventDesc; } - @Order(59) + @Order(71) @ExportProperty(EventParticipantExportDto.EVENT_REGION) public String getEventRegion() { return eventRegion; } - @Order(60) + @Order(72) @ExportProperty(EventParticipantExportDto.EVENT_DISTRICT) public String getEventDistrict() { return eventDistrict; } - @Order(61) + @Order(73) @ExportProperty(EventParticipantExportDto.EVENT_COMMUNITY) public String getEventCommunity() { return eventCommunity; } - @Order(62) + @Order(74) @ExportProperty(EventParticipantExportDto.EVENT_CITY) public String getEventCity() { return eventCity; } - @Order(63) + @Order(75) @ExportProperty(EventParticipantExportDto.EVENT_STREET) public String getEventStreet() { return eventStreet; } - @Order(64) + @Order(76) @ExportProperty(EventParticipantExportDto.EVENT_HOUSE_NUMBER) public String getEventHouseNumber() { return eventHouseNumber; } - @Order(65) + @Order(77) @ExportProperty(EventParticipantExportDto.CONTACT_COUNT) public Long getContactCount() { return contactCount; 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 0edb78c78ff..87474a554dd 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 @@ -1820,6 +1820,19 @@ public interface Captions { String userNewUser = "userNewUser"; String userResetPassword = "userResetPassword"; String userUpdatePasswordConfirmation = "userUpdatePasswordConfirmation"; + String VaccinationInfo_firstVaccinationDate = "VaccinationInfo.firstVaccinationDate"; + String VaccinationInfo_lastVaccinationDate = "VaccinationInfo.lastVaccinationDate"; + String VaccinationInfo_otherVaccineManufacturer = "VaccinationInfo.otherVaccineManufacturer"; + String VaccinationInfo_otherVaccineName = "VaccinationInfo.otherVaccineName"; + String VaccinationInfo_vaccination = "VaccinationInfo.vaccination"; + String VaccinationInfo_vaccinationDoses = "VaccinationInfo.vaccinationDoses"; + String VaccinationInfo_vaccinationInfoSource = "VaccinationInfo.vaccinationInfoSource"; + String VaccinationInfo_vaccineAtcCode = "VaccinationInfo.vaccineAtcCode"; + String VaccinationInfo_vaccineBatchNumber = "VaccinationInfo.vaccineBatchNumber"; + String VaccinationInfo_vaccineInn = "VaccinationInfo.vaccineInn"; + String VaccinationInfo_vaccineManufacturer = "VaccinationInfo.vaccineManufacturer"; + String VaccinationInfo_vaccineName = "VaccinationInfo.vaccineName"; + String VaccinationInfo_vaccineUniiCode = "VaccinationInfo.vaccineUniiCode"; String View_actions = "View.actions"; String View_aggregatereports = "View.aggregatereports"; String View_aggregatereports_sub = "View.aggregatereports.sub"; diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/vaccinationinfo/VaccinationInfoDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/vaccinationinfo/VaccinationInfoDto.java new file mode 100644 index 00000000000..fde1b2b0ac2 --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/vaccinationinfo/VaccinationInfoDto.java @@ -0,0 +1,306 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2021 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.vaccinationinfo; + +import java.util.Date; + +import de.symeda.sormas.api.Disease; +import de.symeda.sormas.api.EntityDto; +import de.symeda.sormas.api.caze.Vaccination; +import de.symeda.sormas.api.caze.VaccinationInfoSource; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.caze.VaccineManufacturer; +import de.symeda.sormas.api.utils.DataHelper; +import de.symeda.sormas.api.utils.Diseases; +import de.symeda.sormas.api.utils.Outbreaks; + +public class VaccinationInfoDto extends EntityDto { + + public static final String I18N_PREFIX = "VaccinationInfo"; + + public static final String VACCINATION = "vaccination"; + public static final String VACCINATION_DOSES = "vaccinationDoses"; + public static final String VACCINATION_INFO_SOURCE = "vaccinationInfoSource"; + public static final String FIRST_VACCINATION_DATE = "firstVaccinationDate"; + public static final String LAST_VACCINATION_DATE = "lastVaccinationDate"; + public static final String VACCINE_NAME = "vaccineName"; + public static final String OTHER_VACCINE_NAME = "otherVaccineName"; + public static final String VACCINE_MANUFACTURER = "vaccineManufacturer"; + public static final String OTHER_VACCINE_MANUFACTURER = "otherVaccineManufacturer"; + public static final String VACCINE_INN = "vaccineInn"; + public static final String VACCINE_BATCH_NUMBER = "vaccineBatchNumber"; + public static final String VACCINE_UNII_CODE = "vaccineUniiCode"; + public static final String VACCINE_ATC_CODE = "vaccineAtcCode"; + + @Diseases({ + Disease.AFP, + Disease.GUINEA_WORM, + Disease.MEASLES, + Disease.POLIO, + Disease.YELLOW_FEVER, + Disease.CSM, + Disease.RABIES, + Disease.UNSPECIFIED_VHF, + Disease.ANTHRAX, + Disease.CORONAVIRUS, + Disease.OTHER }) + @Outbreaks + private Vaccination vaccination; + + @Diseases({ + Disease.AFP, + Disease.GUINEA_WORM, + Disease.MEASLES, + Disease.POLIO, + Disease.CSM, + Disease.YELLOW_FEVER, + Disease.RABIES, + Disease.UNSPECIFIED_VHF, + Disease.ANTHRAX, + Disease.CORONAVIRUS, + Disease.OTHER }) + @Outbreaks + private String vaccinationDoses; + + @Diseases({ + Disease.AFP, + Disease.GUINEA_WORM, + Disease.MEASLES, + Disease.POLIO, + Disease.YELLOW_FEVER, + Disease.CSM, + Disease.MONKEYPOX, + Disease.UNSPECIFIED_VHF, + Disease.RABIES, + Disease.ANTHRAX, + Disease.CORONAVIRUS, + Disease.OTHER }) + @Outbreaks + private Date firstVaccinationDate; + + @Diseases({ + Disease.AFP, + Disease.GUINEA_WORM, + Disease.MEASLES, + Disease.POLIO, + Disease.YELLOW_FEVER, + Disease.CSM, + Disease.MONKEYPOX, + Disease.UNSPECIFIED_VHF, + Disease.RABIES, + Disease.ANTHRAX, + Disease.CORONAVIRUS, + Disease.OTHER }) + @Outbreaks + private Date lastVaccinationDate; + + @Diseases({ + Disease.AFP, + Disease.GUINEA_WORM, + Disease.MEASLES, + Disease.POLIO, + Disease.YELLOW_FEVER, + Disease.CSM, + Disease.RABIES, + Disease.UNSPECIFIED_VHF, + Disease.ANTHRAX, + Disease.CORONAVIRUS, + Disease.OTHER }) + private VaccinationInfoSource vaccinationInfoSource; + + @Diseases({ + Disease.CORONAVIRUS }) + private Vaccine vaccineName; + + @Diseases({ + Disease.CORONAVIRUS }) + private String otherVaccineName; + + @Diseases({ + Disease.CORONAVIRUS, }) + private VaccineManufacturer vaccineManufacturer; + + @Diseases({ + Disease.CORONAVIRUS, }) + private String otherVaccineManufacturer; + + @Diseases({ + Disease.AFP, + Disease.GUINEA_WORM, + Disease.MEASLES, + Disease.POLIO, + Disease.YELLOW_FEVER, + Disease.CSM, + Disease.RABIES, + Disease.UNSPECIFIED_VHF, + Disease.ANTHRAX, + Disease.CORONAVIRUS, + Disease.OTHER }) + private String vaccineInn; + + @Diseases({ + Disease.AFP, + Disease.GUINEA_WORM, + Disease.MEASLES, + Disease.POLIO, + Disease.YELLOW_FEVER, + Disease.CSM, + Disease.RABIES, + Disease.UNSPECIFIED_VHF, + Disease.ANTHRAX, + Disease.CORONAVIRUS, + Disease.OTHER }) + private String vaccineBatchNumber; + + @Diseases({ + Disease.AFP, + Disease.GUINEA_WORM, + Disease.MEASLES, + Disease.POLIO, + Disease.YELLOW_FEVER, + Disease.CSM, + Disease.RABIES, + Disease.UNSPECIFIED_VHF, + Disease.ANTHRAX, + Disease.CORONAVIRUS, + Disease.OTHER }) + private String vaccineUniiCode; + + @Diseases({ + Disease.AFP, + Disease.GUINEA_WORM, + Disease.MEASLES, + Disease.POLIO, + Disease.YELLOW_FEVER, + Disease.CSM, + Disease.RABIES, + Disease.UNSPECIFIED_VHF, + Disease.ANTHRAX, + Disease.CORONAVIRUS, + Disease.OTHER }) + private String vaccineAtcCode; + + public static VaccinationInfoDto build() { + VaccinationInfoDto vaccinationInfo = new VaccinationInfoDto(); + vaccinationInfo.setUuid(DataHelper.createUuid()); + + return vaccinationInfo; + } + + public Vaccination getVaccination() { + return vaccination; + } + + public void setVaccination(Vaccination vaccination) { + this.vaccination = vaccination; + } + + public String getVaccinationDoses() { + return vaccinationDoses; + } + + public void setVaccinationDoses(String vaccinationDoses) { + this.vaccinationDoses = vaccinationDoses; + } + + public Date getFirstVaccinationDate() { + return firstVaccinationDate; + } + + public void setFirstVaccinationDate(Date firstVaccinationDate) { + this.firstVaccinationDate = firstVaccinationDate; + } + + public Date getLastVaccinationDate() { + return lastVaccinationDate; + } + + public void setLastVaccinationDate(Date lastVaccinationDate) { + this.lastVaccinationDate = lastVaccinationDate; + } + + public VaccinationInfoSource getVaccinationInfoSource() { + return vaccinationInfoSource; + } + + public void setVaccinationInfoSource(VaccinationInfoSource vaccinationInfoSource) { + this.vaccinationInfoSource = vaccinationInfoSource; + } + + public Vaccine getVaccineName() { + return vaccineName; + } + + public void setVaccineName(Vaccine vaccineName) { + this.vaccineName = vaccineName; + } + + public String getOtherVaccineName() { + return otherVaccineName; + } + + public void setOtherVaccineName(String otherVaccineName) { + this.otherVaccineName = otherVaccineName; + } + + public VaccineManufacturer getVaccineManufacturer() { + return vaccineManufacturer; + } + + public void setVaccineManufacturer(VaccineManufacturer vaccineManufacturer) { + this.vaccineManufacturer = vaccineManufacturer; + } + + public String getOtherVaccineManufacturer() { + return otherVaccineManufacturer; + } + + public void setOtherVaccineManufacturer(String otherVaccineManufacturer) { + this.otherVaccineManufacturer = otherVaccineManufacturer; + } + + public String getVaccineInn() { + return vaccineInn; + } + + public void setVaccineInn(String vaccineInn) { + this.vaccineInn = vaccineInn; + } + + public String getVaccineBatchNumber() { + return vaccineBatchNumber; + } + + public void setVaccineBatchNumber(String vaccineBatchNumber) { + this.vaccineBatchNumber = vaccineBatchNumber; + } + + public String getVaccineUniiCode() { + return vaccineUniiCode; + } + + public void setVaccineUniiCode(String vaccineUniiCode) { + this.vaccineUniiCode = vaccineUniiCode; + } + + public String getVaccineAtcCode() { + return vaccineAtcCode; + } + + public void setVaccineAtcCode(String vaccineAtcCode) { + this.vaccineAtcCode = vaccineAtcCode; + } +} diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/vaccinationinfo/VaccinationInfoFacade.java b/sormas-api/src/main/java/de/symeda/sormas/api/vaccinationinfo/VaccinationInfoFacade.java new file mode 100644 index 00000000000..9ecf0efc43f --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/vaccinationinfo/VaccinationInfoFacade.java @@ -0,0 +1,22 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2021 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.vaccinationinfo; + +import javax.ejb.Remote; + +@Remote +public interface VaccinationInfoFacade { +} diff --git a/sormas-api/src/main/resources/captions.properties b/sormas-api/src/main/resources/captions.properties index d0d3cefec42..ee55658ad3c 100644 --- a/sormas-api/src/main/resources/captions.properties +++ b/sormas-api/src/main/resources/captions.properties @@ -2132,3 +2132,17 @@ patientDiaryPersonNotExportable=Cannot export the person to the patient diary. T showPlacesOnMap=Show changeUserEmail=Change user email + +VaccinationInfo.vaccination=Vaccination status for this disease +VaccinationInfo.firstVaccinationDate=Date of first vaccination +VaccinationInfo.lastVaccinationDate=Date of last vaccination +VaccinationInfo.vaccinationDoses=Vaccine dose +VaccinationInfo.vaccinationInfoSource=Source of vaccination information +VaccinationInfo.vaccineName=Vaccine name +VaccinationInfo.otherVaccineName=Other vaccine name +VaccinationInfo.vaccineManufacturer=Manufacturer +VaccinationInfo.otherVaccineManufacturer=Other manufacturer +VaccinationInfo.vaccineInn=INN +VaccinationInfo.vaccineBatchNumber=Batch number +VaccinationInfo.vaccineUniiCode=UNII code +VaccinationInfo.vaccineAtcCode=ATC code diff --git a/sormas-api/src/test/java/de/symeda/sormas/api/utils/DataHelperTest.java b/sormas-api/src/test/java/de/symeda/sormas/api/utils/DataHelperTest.java index d099898383c..a8dee7d0733 100644 --- a/sormas-api/src/test/java/de/symeda/sormas/api/utils/DataHelperTest.java +++ b/sormas-api/src/test/java/de/symeda/sormas/api/utils/DataHelperTest.java @@ -2,6 +2,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import org.junit.Test; @@ -63,11 +64,14 @@ public void testShortUuid() { assertEquals("UZOUEH", DataHelper.getShortUuid("UZOUEH-HP7DRG-YOJ74F-PXWL2JZ4")); assertNull(DataHelper.getShortUuid((String) null)); + boolean exceptionThrown = false; try { assertEquals("A", DataHelper.getShortUuid("A")); fail("getShortUuid should not be graceful on Uuids that are too short."); } catch (StringIndexOutOfBoundsException e) { - assertEquals("begin 0, end 6, length 1", e.getMessage()); + exceptionThrown = true; } + + assertTrue("getShortUuid should throw StringIndexOutOfBoundsException on Uuids that are too short.", exceptionThrown); } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/BaseFragment.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/BaseFragment.java index f17e86cecf1..50e3e067a5e 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/BaseFragment.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/BaseFragment.java @@ -95,7 +95,7 @@ public void setFieldVisibilitiesAndAccesses(Class dtoClass, ViewGroup viewGro FieldVisibilityAndAccessHelper.setFieldVisibilitiesAndAccesses(dtoClass, viewGroup, fieldVisibilityCheckers, fieldAccessCheckers); } - protected boolean isVisibleAllowed(Class dtoClass, ControlPropertyField field) { + public boolean isVisibleAllowed(Class dtoClass, ControlPropertyField field) { String propertyId = field.getSubPropertyId(); return FieldVisibilityAndAccessHelper.isVisibleAllowed(dtoClass, propertyId, fieldVisibilityCheckers); } @@ -106,7 +106,7 @@ protected boolean isFieldAccessible(Class dtoClass, ControlPropertyField fiel return FieldVisibilityAndAccessHelper.isFieldAccessible(dtoClass, propertyId, fieldAccessCheckers); } - protected void setVisibleWhen(final ControlPropertyField targetField, ControlPropertyField sourceField, final Object sourceValue) { + public void setVisibleWhen(final ControlPropertyField targetField, ControlPropertyField sourceField, final Object sourceValue) { if (sourceField.getValue() != null && sourceField.getValue().equals(sourceValue)) { targetField.setVisibility(VISIBLE); } else { diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/common/DatabaseHelper.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/common/DatabaseHelper.java index 1439f125a21..ce5b582e6dc 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/common/DatabaseHelper.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/common/DatabaseHelper.java @@ -219,6 +219,8 @@ public static void clearTables(boolean clearInfrastructure) { TableUtils.clearTable(connectionSource, SyncLog.class); TableUtils.clearTable(connectionSource, DiseaseClassificationCriteria.class); TableUtils.clearTable(connectionSource, CampaignFormData.class); + // TODO [vaccination info] integrate vaccination info +// TableUtils.clearTable(connectionSource, VaccinationInfo.class); if (clearInfrastructure) { TableUtils.clearTable(connectionSource, User.class); @@ -302,6 +304,8 @@ public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) { TableUtils.createTable(connectionSource, Campaign.class); TableUtils.createTable(connectionSource, CampaignFormData.class); TableUtils.createTable(connectionSource, CampaignFormMeta.class); + // TODO [vaccination info] integrate vaccination info +// TableUtils.createTable(connectionSource, VaccinationInfo.class); } catch (SQLException e) { Log.e(DatabaseHelper.class.getName(), "Can't build database", e); throw new RuntimeException(e); @@ -1910,6 +1914,20 @@ public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int currentVersion = 268; getDao(Exposure.class).executeRaw("ALTER TABLE exposures ADD COLUMN exposureRole varchar(255);"); + // TODO [vaccination info] integrate vaccination info +// case 269: +// +// currentVersion = 269; +// +// getDao(VaccinationInfo.class).executeRaw( +// "CREATE TABLE vaccinationInfo(vaccination VARCHAR(255), vaccinationDoses TEXT, vaccinationInfoSource VARCHAR(255), firstVaccinationDate TIMESTAMP, lastVaccinationDate TIMESTAMP, vaccineName VARCHAR(255), otherVaccineName TEXT, " +// + "vaccineManufacturer VARCHAR(255), otherVaccineManufacturer TEXT, vaccineInn TEXT, vaccineBatchNumber TEXT, vaccineUniiCode TEXT, vaccineAtcCode TEXT, " +// + "changeDate BIGINT NOT NULL, creationDate BIGINT NOT NULL, id INTEGER, lastOpenedDate BIGINT, localChangeDate BIGINT NOT NULL, modified SMALLINT, snapshot SMALLINT, uuid VARCHAR NOT NULL, PRIMARY KEY(id AUTOINCREMENT), UNIQUE(snapshot, uuid));"); +// +// getDao(Contact.class).executeRaw("ALTER TABLE contacts ADD COLUMN vaccinationInfo_id references vaccinationInfo(id)"); +// getDao(EventParticipant.class) +// .executeRaw("ALTER TABLE eventParticipants ADD COLUMN vaccinationInfo_id references vaccinationInfo(id)"); + // ATTENTION: break should only be done after last version break; @@ -2245,6 +2263,8 @@ private void upgradeFromUnupgradableVersion(SQLiteDatabase db, ConnectionSource TableUtils.dropTable(connectionSource, Campaign.class, true); TableUtils.dropTable(connectionSource, CampaignFormMeta.class, true); TableUtils.dropTable(connectionSource, CampaignFormData.class, true); + // TODO [vaccination info] integrate vaccination info +// TableUtils.dropTable(connectionSource, VaccinationInfo.class, true); if (oldVersion < 30) { TableUtils.dropTable(connectionSource, Config.class, true); @@ -2356,7 +2376,12 @@ public AbstractAdoDao getAdoDaoInner(Cla dao = (AbstractAdoDao) new CampaignFormMetaDao((Dao) innerDao); } else if (type.equals(CampaignFormData.class)) { dao = (AbstractAdoDao) new CampaignFormDataDao((Dao) innerDao); - } else { + } + // TODO [vaccination info] integrate vaccination info +// else if (type.equals(VaccinationInfo.class)) { +// dao = (AbstractAdoDao) new VaccinationInfoDao((Dao) innerDao); +// } + else { throw new UnsupportedOperationException(type.toString()); } @@ -2585,6 +2610,11 @@ public static CampaignFormDataDao getCampaignFormDataDao() { return (CampaignFormDataDao) getAdoDao(CampaignFormData.class); } + // TODO [vaccination info] integrate vaccination info +// public static VaccinationInfoDao getVaccinationInfoDao() { +// return (VaccinationInfoDao) getAdoDao(VaccinationInfo.class); +// } + /** * Close the database connections and clear any cached DAOs. */ diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/Contact.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/Contact.java index a859bad95eb..0b6c1d87e76 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/Contact.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/Contact.java @@ -247,6 +247,10 @@ public class Contact extends PseudonymizableAdo { @DatabaseField(foreign = true, foreignAutoRefresh = true) private District reportingDistrict; + // TODO [vaccination info] integrate vaccination info +// @DatabaseField(foreign = true, foreignAutoRefresh = true) +// private VaccinationInfo vaccinationInfo; + public Person getPerson() { return person; } @@ -501,7 +505,9 @@ public void setExternalID(String externalID) { this.externalID = externalID; } - public String getExternalToken() { return externalToken; } + public String getExternalToken() { + return externalToken; + } public void setExternalToken(String externalToken) { this.externalToken = externalToken; @@ -771,8 +777,8 @@ public YesNoUnknown getReturningTraveler() { public void setReturningTraveler(YesNoUnknown returningTraveler) { this.returningTraveler = returningTraveler; - } - + } + public SormasToSormasOriginInfo getSormasToSormasOriginInfo() { return sormasToSormasOriginInfo; } @@ -836,4 +842,13 @@ public District getReportingDistrict() { public void setReportingDistrict(District reportingDistrict) { this.reportingDistrict = reportingDistrict; } + + // TODO [vaccination info] integrate vaccination info +// public VaccinationInfo getVaccinationInfo() { +// return vaccinationInfo; +// } +// +// public void setVaccinationInfo(VaccinationInfo vaccinationInfo) { +// this.vaccinationInfo = vaccinationInfo; +// } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactDtoHelper.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactDtoHelper.java index daa18d8bf7c..7e1078b0376 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactDtoHelper.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/contact/ContactDtoHelper.java @@ -47,6 +47,8 @@ public class ContactDtoHelper extends AdoDtoHelper { private EpiDataDtoHelper epiDataDtoHelper = new EpiDataDtoHelper(); private HealthConditionsDtoHelper healthConditionsDtoHelper = new HealthConditionsDtoHelper(); private SormasToSormasOriginInfoDtoHelper sormasToSormasOriginInfoDtoHelper = new SormasToSormasOriginInfoDtoHelper(); + // TODO [vaccination info] integrate vaccination info + // private VaccinationInfoDtoHelper vaccinationInfoDtoHelper = new VaccinationInfoDtoHelper(); public ContactDtoHelper() { } @@ -164,6 +166,9 @@ public void fillInnerFromDto(Contact target, ContactDto source) { target.setProhibitionToWorkUntil(source.getProhibitionToWorkUntil()); target.setReportingDistrict(DatabaseHelper.getDistrictDao().getByReferenceDto(source.getReportingDistrict())); + + // TODO [vaccination info] integrate vaccination info +// target.setVaccinationInfo(vaccinationInfoDtoHelper.fillOrCreateFromDto(target.getVaccinationInfo(), source.getVaccinationInfo())); } @Override @@ -307,6 +312,13 @@ public void fillInnerFromAdo(ContactDto target, Contact source) { } else { target.setReportingDistrict(null); } + + // TODO [vaccination info] integrate vaccination info +// if (source.getVaccinationInfo() != null) { +// target.setVaccinationInfo(vaccinationInfoDtoHelper.adoToDto(source.getVaccinationInfo())); +// } else { +// target.setVaccinationInfo(null); +// } } public static ContactReferenceDto toReferenceDto(Contact ado) { diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipant.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipant.java index e04abb62f08..1deaff306c1 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipant.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipant.java @@ -56,6 +56,10 @@ public class EventParticipant extends PseudonymizableAdo { @DatabaseField private String resultingCaseUuid; + // TODO [vaccination info] integrate vaccination info +// @DatabaseField(foreign = true, foreignAutoRefresh = true) +// private VaccinationInfo vaccinationInfo; + public User getReportingUser() { return reportingUser; } @@ -117,4 +121,13 @@ public String getResultingCaseUuid() { public void setResultingCaseUuid(String resultingCaseUuid) { this.resultingCaseUuid = resultingCaseUuid; } + + // TODO [vaccination info] integrate vaccination info +// public VaccinationInfo getVaccinationInfo() { +// return vaccinationInfo; +// } +// +// public void setVaccinationInfo(VaccinationInfo vaccinationInfo) { +// this.vaccinationInfo = vaccinationInfo; +// } } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantDtoHelper.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantDtoHelper.java index 66f16a38ba0..f15ff883129 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantDtoHelper.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantDtoHelper.java @@ -33,6 +33,8 @@ public class EventParticipantDtoHelper extends AdoDtoHelper { private PersonDtoHelper personHelper = new PersonDtoHelper(); + // TODO [vaccination info] integrate vaccination info +// private VaccinationInfoDtoHelper vaccinationInfoDtoHelper = new VaccinationInfoDtoHelper(); @Override protected Class getAdoClass() { @@ -82,6 +84,9 @@ public void fillInnerFromDto(EventParticipant target, EventParticipantDto source target.setInvolvementDescription(source.getInvolvementDescription()); target.setResultingCaseUuid(source.getResultingCase() != null ? source.getResultingCase().getUuid() : null); + // TODO [vaccination info] integrate vaccination info +// target.setVaccinationInfo(vaccinationInfoDtoHelper.fillOrCreateFromDto(target.getVaccinationInfo(), source.getVaccinationInfo())); + target.setPseudonymized(source.isPseudonymized()); } @@ -117,6 +122,13 @@ public void fillInnerFromAdo(EventParticipantDto target, EventParticipant source target.setInvolvementDescription(source.getInvolvementDescription()); + // TODO [vaccination info] integrate vaccination info +// if (source.getVaccinationInfo() != null) { +// target.setVaccinationInfo(vaccinationInfoDtoHelper.adoToDto(source.getVaccinationInfo())); +// } else { +// target.setVaccinationInfo(null); +// } + target.setPseudonymized(source.isPseudonymized()); } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/vaccinationinfo/VaccinationInfo.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/vaccinationinfo/VaccinationInfo.java new file mode 100644 index 00000000000..3af0d80fc10 --- /dev/null +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/vaccinationinfo/VaccinationInfo.java @@ -0,0 +1,176 @@ +package de.symeda.sormas.app.backend.vaccinationinfo; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; + +import com.j256.ormlite.field.DataType; +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +import de.symeda.sormas.api.caze.Vaccination; +import de.symeda.sormas.api.caze.VaccinationInfoSource; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.caze.VaccineManufacturer; +import de.symeda.sormas.app.backend.common.AbstractDomainObject; +import de.symeda.sormas.app.backend.common.EmbeddedAdo; + +@Entity(name = VaccinationInfo.TABLE_NAME) +@DatabaseTable(tableName = VaccinationInfo.TABLE_NAME) +@EmbeddedAdo +public class VaccinationInfo extends AbstractDomainObject { + + public static final String TABLE_NAME = "vaccinationInfo"; + public static final String I18N_PREFIX = "VaccinationInfo"; + + @Enumerated(EnumType.STRING) + private Vaccination vaccination; + + @Column(columnDefinition = "text") + private String vaccinationDoses; + + @Enumerated(EnumType.STRING) + private VaccinationInfoSource vaccinationInfoSource; + + @DatabaseField(dataType = DataType.DATE_LONG) + private Date firstVaccinationDate; + + @DatabaseField(dataType = DataType.DATE_LONG) + private Date lastVaccinationDate; + + @Enumerated(EnumType.STRING) + private Vaccine vaccineName; + + @Column(columnDefinition = "text") + private String otherVaccineName; + + @Enumerated(EnumType.STRING) + private VaccineManufacturer vaccineManufacturer; + + @Column(columnDefinition = "text") + private String otherVaccineManufacturer; + + @Column(columnDefinition = "text") + private String vaccineInn; + + @Column(columnDefinition = "text") + private String vaccineBatchNumber; + + @Column(columnDefinition = "text") + private String vaccineUniiCode; + + @Column(columnDefinition = "text") + private String vaccineAtcCode; + + public Vaccination getVaccination() { + return vaccination; + } + + public void setVaccination(Vaccination vaccination) { + this.vaccination = vaccination; + } + + public String getVaccinationDoses() { + return vaccinationDoses; + } + + public void setVaccinationDoses(String vaccinationDoses) { + this.vaccinationDoses = vaccinationDoses; + } + + public VaccinationInfoSource getVaccinationInfoSource() { + return vaccinationInfoSource; + } + + public void setVaccinationInfoSource(VaccinationInfoSource vaccinationInfoSource) { + this.vaccinationInfoSource = vaccinationInfoSource; + } + + public Date getFirstVaccinationDate() { + return firstVaccinationDate; + } + + public void setFirstVaccinationDate(Date firstVaccinationDate) { + this.firstVaccinationDate = firstVaccinationDate; + } + + public Date getLastVaccinationDate() { + return lastVaccinationDate; + } + + public void setLastVaccinationDate(Date lastVaccinationDate) { + this.lastVaccinationDate = lastVaccinationDate; + } + + public Vaccine getVaccineName() { + return vaccineName; + } + + public void setVaccineName(Vaccine vaccineName) { + this.vaccineName = vaccineName; + } + + public String getOtherVaccineName() { + return otherVaccineName; + } + + public void setOtherVaccineName(String otherVaccineName) { + this.otherVaccineName = otherVaccineName; + } + + public VaccineManufacturer getVaccineManufacturer() { + return vaccineManufacturer; + } + + public void setVaccineManufacturer(VaccineManufacturer vaccineManufacturer) { + this.vaccineManufacturer = vaccineManufacturer; + } + + public String getOtherVaccineManufacturer() { + return otherVaccineManufacturer; + } + + public void setOtherVaccineManufacturer(String otherVaccineManufacturer) { + this.otherVaccineManufacturer = otherVaccineManufacturer; + } + + public String getVaccineInn() { + return vaccineInn; + } + + public void setVaccineInn(String vaccineInn) { + this.vaccineInn = vaccineInn; + } + + public String getVaccineBatchNumber() { + return vaccineBatchNumber; + } + + public void setVaccineBatchNumber(String vaccineBatchNumber) { + this.vaccineBatchNumber = vaccineBatchNumber; + } + + public String getVaccineUniiCode() { + return vaccineUniiCode; + } + + public void setVaccineUniiCode(String vaccineUniiCode) { + this.vaccineUniiCode = vaccineUniiCode; + } + + public String getVaccineAtcCode() { + return vaccineAtcCode; + } + + public void setVaccineAtcCode(String vaccineAtcCode) { + this.vaccineAtcCode = vaccineAtcCode; + } + + @Override + public String getI18nPrefix() { + return I18N_PREFIX; + } +} diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/vaccinationinfo/VaccinationInfoDao.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/vaccinationinfo/VaccinationInfoDao.java new file mode 100644 index 00000000000..9b4c8c555d7 --- /dev/null +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/vaccinationinfo/VaccinationInfoDao.java @@ -0,0 +1,22 @@ +package de.symeda.sormas.app.backend.vaccinationinfo; + +import com.j256.ormlite.dao.Dao; + +import de.symeda.sormas.app.backend.common.AbstractAdoDao; + +public class VaccinationInfoDao extends AbstractAdoDao { + + public VaccinationInfoDao(Dao innerDao) { + super(innerDao); + } + + @Override + protected Class getAdoClass() { + return VaccinationInfo.class; + } + + @Override + public String getTableName() { + return VaccinationInfo.TABLE_NAME; + } +} diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/vaccinationinfo/VaccinationInfoDtoHelper.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/vaccinationinfo/VaccinationInfoDtoHelper.java new file mode 100644 index 00000000000..c7ca9630212 --- /dev/null +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/vaccinationinfo/VaccinationInfoDtoHelper.java @@ -0,0 +1,71 @@ +package de.symeda.sormas.app.backend.vaccinationinfo; + +import java.util.List; + +import de.symeda.sormas.api.PushResult; +import de.symeda.sormas.api.vaccinationinfo.VaccinationInfoDto; +import de.symeda.sormas.app.backend.common.AdoDtoHelper; +import de.symeda.sormas.app.rest.NoConnectionException; +import retrofit2.Call; + +public class VaccinationInfoDtoHelper extends AdoDtoHelper { + + @Override + protected Class getAdoClass() { + return VaccinationInfo.class; + } + + @Override + protected Class getDtoClass() { + return VaccinationInfoDto.class; + } + + @Override + protected Call> pullAllSince(long since) throws NoConnectionException { + throw new UnsupportedOperationException("Entity is embedded"); + } + + @Override + protected Call> pullByUuids(List uuids) throws NoConnectionException { + throw new UnsupportedOperationException("Entity is embedded"); + } + + @Override + protected Call> pushAll(List vaccinationInfoDtos) throws NoConnectionException { + throw new UnsupportedOperationException("Entity is embedded"); + } + + @Override + protected void fillInnerFromDto(VaccinationInfo target, VaccinationInfoDto source) { + target.setVaccination(source.getVaccination()); + target.setVaccinationDoses(source.getVaccinationDoses()); + target.setVaccinationInfoSource(source.getVaccinationInfoSource()); + target.setFirstVaccinationDate(source.getFirstVaccinationDate()); + target.setLastVaccinationDate(source.getLastVaccinationDate()); + target.setVaccineName(source.getVaccineName()); + target.setOtherVaccineName(source.getOtherVaccineName()); + target.setVaccineManufacturer(source.getVaccineManufacturer()); + target.setOtherVaccineManufacturer(source.getOtherVaccineManufacturer()); + target.setVaccineInn(source.getVaccineInn()); + target.setVaccineBatchNumber(source.getVaccineBatchNumber()); + target.setVaccineUniiCode(source.getVaccineUniiCode()); + target.setVaccineAtcCode(source.getVaccineAtcCode()); + } + + @Override + protected void fillInnerFromAdo(VaccinationInfoDto target, VaccinationInfo source) { + target.setVaccination(source.getVaccination()); + target.setVaccinationDoses(source.getVaccinationDoses()); + target.setVaccinationInfoSource(source.getVaccinationInfoSource()); + target.setFirstVaccinationDate(source.getFirstVaccinationDate()); + target.setLastVaccinationDate(source.getLastVaccinationDate()); + target.setVaccineName(source.getVaccineName()); + target.setOtherVaccineName(source.getOtherVaccineName()); + target.setVaccineManufacturer(source.getVaccineManufacturer()); + target.setOtherVaccineManufacturer(source.getOtherVaccineManufacturer()); + target.setVaccineInn(source.getVaccineInn()); + target.setVaccineBatchNumber(source.getVaccineBatchNumber()); + target.setVaccineUniiCode(source.getVaccineUniiCode()); + target.setVaccineAtcCode(source.getVaccineAtcCode()); + } +} diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditFragment.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditFragment.java index cea26349022..9371dba9be0 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditFragment.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditFragment.java @@ -43,7 +43,6 @@ import de.symeda.sormas.api.caze.ReportingType; import de.symeda.sormas.api.caze.Trimester; import de.symeda.sormas.api.caze.Vaccination; -import de.symeda.sormas.api.caze.VaccinationInfoSource; import de.symeda.sormas.api.caze.Vaccine; import de.symeda.sormas.api.caze.VaccineManufacturer; import de.symeda.sormas.api.contact.QuarantineType; @@ -90,7 +89,8 @@ public class CaseEditFragment extends BaseEditFragment caseClassificationList; private List caseOutcomeList; - private List vaccinationInfoSourceList; + // TODO [vaccination info] integrate vaccination info +// private List vaccinationInfoSourceList; private List diseaseList; private List diseaseVariantList; private List plagueTypeList; @@ -274,7 +274,8 @@ record = getActivityRootData(); .remove(new Item<>(CaseClassification.CONFIRMED_UNKNOWN_SYMPTOMS.toString(), CaseClassification.CONFIRMED_UNKNOWN_SYMPTOMS)); } caseOutcomeList = DataUtils.getEnumItems(CaseOutcome.class, true); - vaccinationInfoSourceList = DataUtils.getEnumItems(VaccinationInfoSource.class, true); + // TODO [vaccination info] integrate vaccination info +// vaccinationInfoSourceList = DataUtils.getEnumItems(VaccinationInfoSource.class, true); plagueTypeList = DataUtils.getEnumItems(PlagueType.class, true); dengueFeverTypeList = DataUtils.getEnumItems(DengueFeverType.class, true); humanRabiesTypeList = DataUtils.getEnumItems(RabiesType.class, true); @@ -513,7 +514,8 @@ public void onAfterLayoutBinding(final FragmentCaseEditLayoutBinding contentBind contentBinding.caseDataDengueFeverType.initializeSpinner(dengueFeverTypeList); contentBinding.caseDataRabiesType.initializeSpinner(humanRabiesTypeList); contentBinding.caseDataNotifyingClinic.initializeSpinner(hospitalWardTypeList); - contentBinding.caseDataVaccinationInfoSource.initializeSpinner(vaccinationInfoSourceList); + // TODO [vaccination info] integrate vaccination info +// contentBinding.caseDataVaccinationInfoSource.initializeSpinner(vaccinationInfoSourceList); contentBinding.caseDataQuarantine.initializeSpinner(quarantineList); contentBinding.caseDataReportingDistrict.initializeSpinner(allDistricts); diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/contact/edit/ContactEditFragment.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/contact/edit/ContactEditFragment.java index be6c99d2aec..85199a7ce63 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/contact/edit/ContactEditFragment.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/contact/edit/ContactEditFragment.java @@ -96,6 +96,8 @@ private void setUpControlListeners(FragmentContactEditLayoutBinding contentBindi private void setUpFieldVisibilities(FragmentContactEditLayoutBinding contentBinding) { setFieldVisibilitiesAndAccesses(ContactDto.class, contentBinding.mainContent); + // TODO [vaccination info] integrate vaccination info +// setFieldVisibilitiesAndAccesses(VaccinationInfoDto.class, contentBinding.vaccinationInfoEditLayout.mainContent); if (record.getResultingCaseUuid() != null) { contentBinding.createCase.setVisibility(GONE); @@ -142,6 +144,11 @@ private void setUpFieldVisibilities(FragmentContactEditLayoutBinding contentBind contentBinding.contactQuarantineExtended.setVisibility(record.isQuarantineExtended() ? VISIBLE : GONE); contentBinding.contactQuarantineReduced.setVisibility(record.isQuarantineReduced() ? VISIBLE : GONE); + + // TODO [vaccination info] integrate vaccination info +// if (!isVisibleAllowed(VaccinationInfoDto.class, contentBinding.vaccinationInfoEditLayout.vaccinationInfoVaccination)) { +// contentBinding.medicalInformationHeader.setVisibility(GONE); +// } } // Overrides @@ -394,6 +401,8 @@ private void updateContactCategory(FragmentContactEditLayoutBinding contentBindi @Override public void onAfterLayoutBinding(FragmentContactEditLayoutBinding contentBinding) { + // TODO [vaccination info] integrate vaccination info +// VaccinationInfoEditFragment.setUpLayoutBinding(this, record.getVaccinationInfo(), contentBinding.vaccinationInfoEditLayout); setUpFieldVisibilities(contentBinding); // Initialize ControlSpinnerFields diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/contact/read/ContactReadFragment.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/contact/read/ContactReadFragment.java index 70a597f225a..198a739e783 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/contact/read/ContactReadFragment.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/contact/read/ContactReadFragment.java @@ -55,6 +55,8 @@ private void setUpControlListeners(FragmentContactReadLayoutBinding contentBindi private void setUpFieldVisibilities(FragmentContactReadLayoutBinding contentBinding) { setFieldVisibilitiesAndAccesses(ContactDto.class, contentBinding.mainContent); + // TODO [vaccination info] integrate vaccination info +// setFieldVisibilitiesAndAccesses(VaccinationInfoDto.class, contentBinding.vaccinationInfoLayout.mainContent); if (record.getResultingCaseUuid() == null || DatabaseHelper.getCaseDao().queryUuidBasic(record.getResultingCaseUuid()) == null) { contentBinding.openResultingCase.setVisibility(GONE); @@ -87,6 +89,11 @@ private void setUpFieldVisibilities(FragmentContactReadLayoutBinding contentBind contentBinding.contactQuarantineExtended.setVisibility(record.isQuarantineExtended() ? VISIBLE : GONE); contentBinding.contactQuarantineReduced.setVisibility(record.isQuarantineReduced() ? VISIBLE : GONE); + + // TODO [vaccination info] integrate vaccination info +// if (!isVisibleAllowed(VaccinationInfoDto.class, contentBinding.vaccinationInfoLayout.vaccinationInfoVaccination)) { +// contentBinding.medicalInformationHeader.setVisibility(GONE); +// } } // Overrides diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/vaccinationinfo/edit/VaccinationInfoEditFragment.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/vaccinationinfo/edit/VaccinationInfoEditFragment.java new file mode 100644 index 00000000000..2f76ecd9998 --- /dev/null +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/vaccinationinfo/edit/VaccinationInfoEditFragment.java @@ -0,0 +1,80 @@ +package de.symeda.sormas.app.vaccinationinfo.edit; + +import de.symeda.sormas.api.caze.Vaccination; +import de.symeda.sormas.api.caze.VaccinationInfoSource; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.caze.VaccineManufacturer; +import de.symeda.sormas.app.BaseEditFragment; +import de.symeda.sormas.app.R; +import de.symeda.sormas.app.backend.vaccinationinfo.VaccinationInfo; +import de.symeda.sormas.app.contact.edit.ContactEditFragment; +import de.symeda.sormas.app.databinding.FragmentVaccinationInfoEditLayoutBinding; +import de.symeda.sormas.app.util.DataUtils; + +public class VaccinationInfoEditFragment extends BaseEditFragment { + + private VaccinationInfo record; + + public static void setUpLayoutBinding( + ContactEditFragment contactEditFragment, + VaccinationInfo vaccinationInfo, + FragmentVaccinationInfoEditLayoutBinding vaccinationInfoEditLayout) { + vaccinationInfoEditLayout.setData(vaccinationInfo); + vaccinationInfoEditLayout.setVaccinationClass(Vaccination.class); + + vaccinationInfoEditLayout.vaccinationInfoVaccinationInfoSource.initializeSpinner(DataUtils.getEnumItems(VaccinationInfoSource.class, true)); + vaccinationInfoEditLayout.vaccinationInfoVaccineName.initializeSpinner(DataUtils.getEnumItems(Vaccine.class, true)); + vaccinationInfoEditLayout.vaccinationInfoVaccineManufacturer.initializeSpinner(DataUtils.getEnumItems(VaccineManufacturer.class, true)); + vaccinationInfoEditLayout.vaccinationInfoFirstVaccinationDate.initializeDateField(contactEditFragment.getChildFragmentManager()); + vaccinationInfoEditLayout.vaccinationInfoLastVaccinationDate.initializeDateField(contactEditFragment.getChildFragmentManager()); + +// vaccinationInfoEditLayout.vaccinationInfoVaccineName.addValueChangedListener(new ValueChangeListener() { +// +// private Vaccine currentVaccine = vaccinationInfo.getVaccineName(); +// +// @Override +// public void onChange(ControlPropertyField e) { +// Vaccine vaccine = (Vaccine) e.getValue(); +// +// if (currentVaccine != vaccine) { +// vaccinationInfoEditLayout.vaccinationInfoVaccineManufacturer.setValue(vaccine != null ? vaccine.getManufacturer() : null); +// currentVaccine = vaccine; +// } +// } +// }); +// +// ValidationHelper.initIntegerValidator( +// vaccinationInfoEditLayout.vaccinationInfoVaccinationDoses, +// I18nProperties.getValidationError(Validations.vaccineDosesFormat), +// 1, +// 10); +// +// if (contactEditFragment.isVisibleAllowed(VaccinationInfoDto.class, vaccinationInfoEditLayout.vaccinationInfoVaccineName)) { +// contactEditFragment.setVisibleWhen(vaccinationInfoEditLayout.vaccinationInfoVaccineName, vaccinationInfoEditLayout.vaccinationInfoVaccination, Vaccination.VACCINATED); +// } +// if (contactEditFragment.isVisibleAllowed(VaccinationInfoDto.class, vaccinationInfoEditLayout.vaccinationInfoVaccineManufacturer)) { +// contactEditFragment.setVisibleWhen(vaccinationInfoEditLayout.vaccinationInfoVaccineManufacturer, vaccinationInfoEditLayout.vaccinationInfoVaccination, Vaccination.VACCINATED); +// } + } + + @Override + public int getEditLayout() { + return R.layout.fragment_vaccination_info_edit_layout; + } + + @Override + public VaccinationInfo getPrimaryData() { + return record; + } + + @Override + protected void prepareFragmentData() { + record = getActivityRootData(); + } + + @Override + protected void onLayoutBinding(FragmentVaccinationInfoEditLayoutBinding contentBinding) { + contentBinding.setData(record); + contentBinding.setVaccinationClass(Vaccination.class); + } +} diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/vaccinationinfo/read/VaccinationInfoReadFragment.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/vaccinationinfo/read/VaccinationInfoReadFragment.java new file mode 100644 index 00000000000..44fe7b45f7d --- /dev/null +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/vaccinationinfo/read/VaccinationInfoReadFragment.java @@ -0,0 +1,33 @@ +package de.symeda.sormas.app.vaccinationinfo.read; + +import android.os.Bundle; + +import de.symeda.sormas.app.BaseReadFragment; +import de.symeda.sormas.app.R; +import de.symeda.sormas.app.backend.vaccinationinfo.VaccinationInfo; +import de.symeda.sormas.app.databinding.FragmentVaccinationInfoReadLayoutBinding; + +public class VaccinationInfoReadFragment extends BaseReadFragment { + + private VaccinationInfo record; + + @Override + protected void prepareFragmentData(Bundle savedInstanceState) { + record = getActivityRootData(); + } + + @Override + public void onLayoutBinding(FragmentVaccinationInfoReadLayoutBinding contentBinding) { + contentBinding.setData(record); + } + + @Override + public int getReadLayout() { + return R.layout.fragment_vaccination_info_read_layout; + } + + @Override + public VaccinationInfo getPrimaryData() { + return record; + } +} diff --git a/sormas-app/app/src/main/res/layout/fragment_contact_edit_layout.xml b/sormas-app/app/src/main/res/layout/fragment_contact_edit_layout.xml index 1e4fa56bdb3..14364c1574a 100644 --- a/sormas-app/app/src/main/res/layout/fragment_contact_edit_layout.xml +++ b/sormas-app/app/src/main/res/layout/fragment_contact_edit_layout.xml @@ -444,6 +444,21 @@ app:value="@={data.highPriority}" style="@style/ControlSingleColumnStyle" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sormas-app/app/src/main/res/layout/fragment_vaccination_info_read_layout.xml b/sormas-app/app/src/main/res/layout/fragment_vaccination_info_read_layout.xml new file mode 100644 index 00000000000..207f14f4dd9 --- /dev/null +++ b/sormas-app/app/src/main/res/layout/fragment_vaccination_info_read_layout.xml @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/Contact.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/Contact.java index 3ed60fab158..f4d021d527d 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/Contact.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/Contact.java @@ -68,6 +68,7 @@ import de.symeda.sormas.backend.sormastosormas.SormasToSormasShareInfo; import de.symeda.sormas.backend.task.Task; import de.symeda.sormas.backend.user.User; +import de.symeda.sormas.backend.vaccinationinfo.VaccinationInfo; import de.symeda.sormas.backend.visit.Visit; @Entity @@ -147,6 +148,7 @@ public class Contact extends CoreAdo { public static final String END_OF_QUARANTINE_REASON = "endOfQuarantineReason"; public static final String END_OF_QUARANTINE_REASON_DETAILS = "endOfQuarantineReasonDetails"; public static final String REPORTING_DISTRICT = "reportingDistrict"; + public static final String VACCINATION_INFO = "vaccinationInfo"; private Date reportDateTime; private User reportingUser; @@ -233,6 +235,8 @@ public class Contact extends CoreAdo { private District reportingDistrict; + private VaccinationInfo vaccinationInfo; + private SormasToSormasOriginInfo sormasToSormasOriginInfo; private List sormasToSormasShares = new ArrayList<>(0); @@ -934,4 +938,14 @@ public YesNoUnknown getReturningTraveler() { public void setReturningTraveler(YesNoUnknown returningTraveler) { this.returningTraveler = returningTraveler; } + + @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @AuditedIgnore + public VaccinationInfo getVaccinationInfo() { + return vaccinationInfo; + } + + public void setVaccinationInfo(VaccinationInfo vaccinationInfo) { + this.vaccinationInfo = vaccinationInfo; + } } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactFacadeEjb.java index bd69e017618..c97b601cae6 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactFacadeEjb.java @@ -58,7 +58,6 @@ import javax.persistence.criteria.Root; import javax.validation.constraints.NotNull; -import de.symeda.sormas.api.person.JournalPersonDto; import org.apache.commons.collections.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -96,6 +95,7 @@ import de.symeda.sormas.api.i18n.Validations; import de.symeda.sormas.api.importexport.ExportConfigurationDto; import de.symeda.sormas.api.location.LocationDto; +import de.symeda.sormas.api.person.JournalPersonDto; import de.symeda.sormas.api.person.PersonReferenceDto; import de.symeda.sormas.api.region.DistrictReferenceDto; import de.symeda.sormas.api.region.RegionReferenceDto; @@ -112,6 +112,7 @@ import de.symeda.sormas.api.utils.SortProperty; import de.symeda.sormas.api.utils.ValidationRuntimeException; import de.symeda.sormas.api.utils.YesNoUnknown; +import de.symeda.sormas.api.vaccinationinfo.VaccinationInfoDto; import de.symeda.sormas.api.visit.VisitResultDto; import de.symeda.sormas.api.visit.VisitStatus; import de.symeda.sormas.api.visit.VisitSummaryExportDetailsDto; @@ -163,6 +164,9 @@ import de.symeda.sormas.backend.util.IterableHelper; import de.symeda.sormas.backend.util.ModelConstants; import de.symeda.sormas.backend.util.Pseudonymizer; +import de.symeda.sormas.backend.vaccinationinfo.VaccinationInfo; +import de.symeda.sormas.backend.vaccinationinfo.VaccinationInfoFacadeEjb; +import de.symeda.sormas.backend.vaccinationinfo.VaccinationInfoFacadeEjb.VaccinationInfoFacadeEjbLocal; import de.symeda.sormas.backend.visit.Visit; import de.symeda.sormas.backend.visit.VisitService; @@ -214,6 +218,8 @@ public class ContactFacadeEjb implements ContactFacade { private EventService eventService; @EJB private PersonFacadeEjb.PersonFacadeEjbLocal personFacade; + @EJB + private VaccinationInfoFacadeEjbLocal vaccinationInfoFacade; @Override public List getAllActiveUuids() { @@ -511,6 +517,19 @@ public List getExportList( joins.getEpiData().get(EpiData.ID), joins.getEpiData().get(EpiData.CONTACT_WITH_SOURCE_CASE_KNOWN), contact.get(Contact.RETURNING_TRAVELER), + joins.getVaccinationInfo().get(VaccinationInfo.VACCINATION), + joins.getVaccinationInfo().get(VaccinationInfo.VACCINATION_DOSES), + joins.getVaccinationInfo().get(VaccinationInfo.VACCINATION_INFO_SOURCE), + joins.getVaccinationInfo().get(VaccinationInfo.FIRST_VACCINATION_DATE), + joins.getVaccinationInfo().get(VaccinationInfo.LAST_VACCINATION_DATE), + joins.getVaccinationInfo().get(VaccinationInfo.VACCINE_NAME), + joins.getVaccinationInfo().get(VaccinationInfo.OTHER_VACCINE_NAME), + joins.getVaccinationInfo().get(VaccinationInfo.VACCINE_MANUFACTURER), + joins.getVaccinationInfo().get(VaccinationInfo.OTHER_VACCINE_MANUFACTURER), + joins.getVaccinationInfo().get(VaccinationInfo.VACCINE_INN), + joins.getVaccinationInfo().get(VaccinationInfo.VACCINE_BATCH_NUMBER), + joins.getVaccinationInfo().get(VaccinationInfo.VACCINE_UNII_CODE), + joins.getVaccinationInfo().get(VaccinationInfo.VACCINE_ATC_CODE), contact.get(Contact.EXTERNAL_ID), contact.get(Contact.EXTERNAL_TOKEN), joins.getPerson().get(Person.BIRTH_NAME), @@ -1162,6 +1181,16 @@ public Contact fromDto(@NotNull ContactDto source, boolean checkChangeDate) { target.setReportingDistrict(districtService.getByReferenceDto(source.getReportingDistrict())); + // create new vaccination info in case it is created in the mobile app + // TODO [vaccination info] no VaccinationInfoDto.build() will be needed after integrating vaccination info into the app + VaccinationInfoDto vaccinationInfo = source.getVaccinationInfo(); + if (vaccinationInfo == null && target.getVaccinationInfo() == null) { + vaccinationInfo = VaccinationInfoDto.build(); + } + if (vaccinationInfo != null) { + target.setVaccinationInfo(vaccinationInfoFacade.fromDto(vaccinationInfo, checkChangeDate)); + } + if (source.getSormasToSormasOriginInfo() != null) { target.setSormasToSormasOriginInfo(originInfoFacade.toDto(source.getSormasToSormasOriginInfo(), checkChangeDate)); } @@ -1410,6 +1439,8 @@ public static ContactDto toDto(Contact source) { target.setSormasToSormasOriginInfo(SormasToSormasOriginInfoFacadeEjb.toDto(source.getSormasToSormasOriginInfo())); target.setOwnershipHandedOver(source.getSormasToSormasShares().stream().anyMatch(SormasToSormasShareInfo::isOwnershipHandedOver)); + target.setVaccinationInfo(VaccinationInfoFacadeEjb.toDto(source.getVaccinationInfo())); + return target; } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactJoins.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactJoins.java index 6a97b3b23af..41e85d401ee 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactJoins.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactJoins.java @@ -35,6 +35,7 @@ import de.symeda.sormas.backend.symptoms.Symptoms; import de.symeda.sormas.backend.user.User; import de.symeda.sormas.backend.util.AbstractDomainObjectJoins; +import de.symeda.sormas.backend.vaccinationinfo.VaccinationInfo; import de.symeda.sormas.backend.visit.Visit; public class ContactJoins extends AbstractDomainObjectJoins { @@ -77,6 +78,8 @@ public class ContactJoins extends AbstractDomainObjectJoins { private Join reportingDistrict; + private Join vaccinationInfo; + public ContactJoins(Root contact) { super(contact); @@ -338,4 +341,12 @@ public Join getReportingDistrict() { private void setReportingDistrict(Join reportingDistrict) { this.reportingDistrict = reportingDistrict; } + + public Join getVaccinationInfo() { + return getOrCreate(vaccinationInfo, Contact.VACCINATION_INFO, JoinType.LEFT, this::setVaccinationInfo); + } + + private void setVaccinationInfo(Join vaccinationInfo) { + this.vaccinationInfo = vaccinationInfo; + } } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactService.java index d3c4cf13a43..08b74b0a061 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/contact/ContactService.java @@ -92,6 +92,7 @@ import de.symeda.sormas.backend.task.TaskService; import de.symeda.sormas.backend.user.User; import de.symeda.sormas.backend.util.DateHelper8; +import de.symeda.sormas.backend.vaccinationinfo.VaccinationInfoService; import de.symeda.sormas.backend.visit.Visit; import de.symeda.sormas.backend.visit.VisitService; import de.symeda.sormas.utils.CaseJoins; @@ -120,6 +121,8 @@ public class ContactService extends AbstractCoreAdoService { private ContactJurisdictionChecker contactJurisdictionChecker; @EJB private ExposureService exposureService; + @EJB + private VaccinationInfoService vaccinationInfoService; public ContactService() { super(Contact.class); @@ -181,6 +184,7 @@ public Predicate createChangeDateFilter(CriteriaBuilder cb, From fro Predicate dateFilter = changeDateFilter(cb, date, from); dateFilter = cb.or(dateFilter, epiDataService.createChangeDateFilter(cb, from.join(Contact.EPI_DATA, JoinType.LEFT), date)); dateFilter = cb.or(dateFilter, healthConditionsService.createChangeDateFilter(cb, from.join(Contact.HEALTH_CONDITIONS, JoinType.LEFT), date)); + dateFilter = cb.or(dateFilter, vaccinationInfoService.createChangeDateFilter(cb, from.join(Contact.VACCINATION_INFO, JoinType.LEFT), date)); dateFilter = cb.or(dateFilter, changeDateFilter(cb, date, from, Contact.SORMAS_TO_SORMAS_SHARES)); return dateFilter; diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipant.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipant.java index bbe5e7f8170..e101a65a645 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipant.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipant.java @@ -19,14 +19,17 @@ import java.util.Set; +import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; +import javax.persistence.OneToOne; import de.symeda.auditlog.api.Audited; +import de.symeda.auditlog.api.AuditedIgnore; import de.symeda.sormas.backend.caze.Case; import de.symeda.sormas.backend.common.CoreAdo; import de.symeda.sormas.backend.person.Person; @@ -34,6 +37,7 @@ import de.symeda.sormas.backend.region.Region; import de.symeda.sormas.backend.sample.Sample; import de.symeda.sormas.backend.user.User; +import de.symeda.sormas.backend.vaccinationinfo.VaccinationInfo; @Entity @Audited @@ -48,6 +52,7 @@ public class EventParticipant extends CoreAdo { public static final String PERSON = "person"; public static final String INVOLVEMENT_DESCRIPTION = "involvementDescription"; public static final String RESULTING_CASE = "resultingCase"; + public static final String VACCINATION_INFO = "vaccinationInfo"; private User reportingUser; private Event event; @@ -57,6 +62,7 @@ public class EventParticipant extends CoreAdo { private Set samples; private Region region; private District district; + private VaccinationInfo vaccinationInfo; @ManyToOne(cascade = {}) public User getReportingUser() { @@ -136,4 +142,14 @@ public District getDistrict() { public void setDistrict(District district) { this.district = district; } + + @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @AuditedIgnore + public VaccinationInfo getVaccinationInfo() { + return vaccinationInfo; + } + + public void setVaccinationInfo(VaccinationInfo vaccinationInfo) { + this.vaccinationInfo = vaccinationInfo; + } } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjb.java index 7fc37624e5d..93914bf301f 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantFacadeEjb.java @@ -66,6 +66,7 @@ import de.symeda.sormas.api.user.UserRight; import de.symeda.sormas.api.utils.SortProperty; import de.symeda.sormas.api.utils.ValidationRuntimeException; +import de.symeda.sormas.api.vaccinationinfo.VaccinationInfoDto; import de.symeda.sormas.backend.caze.Case; import de.symeda.sormas.backend.caze.CaseFacadeEjb; import de.symeda.sormas.backend.caze.CaseService; @@ -90,6 +91,8 @@ import de.symeda.sormas.backend.util.IterableHelper; import de.symeda.sormas.backend.util.ModelConstants; import de.symeda.sormas.backend.util.Pseudonymizer; +import de.symeda.sormas.backend.vaccinationinfo.VaccinationInfo; +import de.symeda.sormas.backend.vaccinationinfo.VaccinationInfoFacadeEjb.VaccinationInfoFacadeEjbLocal; @Stateless(name = "EventParticipantFacade") public class EventParticipantFacadeEjb implements EventParticipantFacade { @@ -117,6 +120,8 @@ public class EventParticipantFacadeEjb implements EventParticipantFacade { private DistrictService districtService; @EJB private EventJurisdictionChecker eventJurisdictionChecker; + @EJB + private VaccinationInfoFacadeEjbLocal vaccinationInfoFacade; @Override public List getAllEventParticipantsByEventAfter(Date date, String eventUuid) { @@ -353,6 +358,7 @@ public List getExportList( Join eventLocation = event.join(Event.EVENT_LOCATION, JoinType.LEFT); Join resultingCase = eventParticipant.join(EventParticipant.RESULTING_CASE, JoinType.LEFT); + Join vaccinationInfo = eventParticipant.join(EventParticipant.VACCINATION_INFO, JoinType.LEFT); cq.multiselect( eventParticipant.get(EventParticipant.ID), @@ -414,7 +420,21 @@ public List getExportList( birthCountry.get(Country.ISO_CODE), birthCountry.get(Country.DEFAULT_NAME), citizenship.get(Country.ISO_CODE), - citizenship.get(Country.DEFAULT_NAME)); + citizenship.get(Country.DEFAULT_NAME), + + vaccinationInfo.get(VaccinationInfo.VACCINATION), + vaccinationInfo.get(VaccinationInfo.VACCINATION_DOSES), + vaccinationInfo.get(VaccinationInfo.VACCINATION_INFO_SOURCE), + vaccinationInfo.get(VaccinationInfo.FIRST_VACCINATION_DATE), + vaccinationInfo.get(VaccinationInfo.LAST_VACCINATION_DATE), + vaccinationInfo.get(VaccinationInfo.VACCINE_NAME), + vaccinationInfo.get(VaccinationInfo.OTHER_VACCINE_NAME), + vaccinationInfo.get(VaccinationInfo.VACCINE_MANUFACTURER), + vaccinationInfo.get(VaccinationInfo.OTHER_VACCINE_MANUFACTURER), + vaccinationInfo.get(VaccinationInfo.VACCINE_INN), + vaccinationInfo.get(VaccinationInfo.VACCINE_BATCH_NUMBER), + vaccinationInfo.get(VaccinationInfo.VACCINE_UNII_CODE), + vaccinationInfo.get(VaccinationInfo.VACCINE_ATC_CODE)); Predicate filter = eventParticipantService.buildCriteriaFilter(eventParticipantCriteria, cb, eventParticipant); cq.where(filter); @@ -669,6 +689,16 @@ public EventParticipant fromDto(@NotNull EventParticipantDto source, boolean che target.setRegion(regionService.getByReferenceDto(source.getRegion())); target.setDistrict(districtService.getByReferenceDto(source.getDistrict())); + // create new vaccination info in case it is created in the mobile app + // TODO [vaccination info] no VaccinationInfoDto.build() will be needed after integrating vaccination info into the app + VaccinationInfoDto vaccinationInfo = source.getVaccinationInfo(); + if (vaccinationInfo == null && target.getVaccinationInfo() == null) { + vaccinationInfo = VaccinationInfoDto.build(); + } + if (vaccinationInfo != null) { + target.setVaccinationInfo(vaccinationInfoFacade.fromDto(vaccinationInfo, checkChangeDate)); + } + return target; } @@ -733,6 +763,7 @@ public static EventParticipantDto toDto(EventParticipant source) { target.setResultingCase(CaseFacadeEjb.toReferenceDto(source.getResultingCase())); target.setRegion(RegionFacadeEjb.toReferenceDto(source.getRegion())); target.setDistrict(DistrictFacadeEjb.toReferenceDto(source.getDistrict())); + target.setVaccinationInfo(VaccinationInfoFacadeEjbLocal.toDto(source.getVaccinationInfo())); return target; } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantService.java index 279f2ab12d8..1d001da9fb2 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/event/EventParticipantService.java @@ -17,6 +17,7 @@ *******************************************************************************/ package de.symeda.sormas.backend.event; +import java.sql.Timestamp; import java.util.Date; import java.util.List; import java.util.Optional; @@ -42,6 +43,7 @@ import de.symeda.sormas.backend.person.Person; import de.symeda.sormas.backend.sample.SampleService; import de.symeda.sormas.backend.user.User; +import de.symeda.sormas.backend.vaccinationinfo.VaccinationInfoService; @Stateless @LocalBean @@ -51,6 +53,8 @@ public class EventParticipantService extends AbstractCoreAdoService getByEventUuids(List eventUuids) { return em.createQuery(cq).getResultList(); } + @Override + public Predicate createChangeDateFilter(CriteriaBuilder cb, From from, Timestamp date) { + Predicate dateFilter = super.createChangeDateFilter(cb, from, date); + dateFilter = + cb.or(dateFilter, vaccinationInfoService.createChangeDateFilter(cb, from.join(EventParticipant.VACCINATION_INFO, JoinType.LEFT), date)); + + return dateFilter; + } } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/vaccinationinfo/VaccinationInfo.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/vaccinationinfo/VaccinationInfo.java new file mode 100644 index 00000000000..6bcbe477fe1 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/vaccinationinfo/VaccinationInfo.java @@ -0,0 +1,184 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2021 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.vaccinationinfo; + +import static de.symeda.sormas.api.EntityDto.COLUMN_LENGTH_DEFAULT; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import de.symeda.sormas.api.caze.Vaccination; +import de.symeda.sormas.api.caze.VaccinationInfoSource; +import de.symeda.sormas.api.caze.Vaccine; +import de.symeda.sormas.api.caze.VaccineManufacturer; +import de.symeda.sormas.backend.common.AbstractDomainObject; + +@Entity +public class VaccinationInfo extends AbstractDomainObject { + + private static final long serialVersionUID = 110758935266105730L; + + public static final String VACCINATION = "vaccination"; + public static final String VACCINATION_DOSES = "vaccinationDoses"; + public static final String VACCINATION_INFO_SOURCE = "vaccinationInfoSource"; + public static final String FIRST_VACCINATION_DATE = "firstVaccinationDate"; + public static final String LAST_VACCINATION_DATE = "lastVaccinationDate"; + public static final String VACCINE_NAME = "vaccineName"; + public static final String OTHER_VACCINE_NAME = "otherVaccineName"; + public static final String VACCINE_MANUFACTURER = "vaccineManufacturer"; + public static final String OTHER_VACCINE_MANUFACTURER = "otherVaccineManufacturer"; + public static final String VACCINE_INN = "vaccineInn"; + public static final String VACCINE_BATCH_NUMBER = "vaccineBatchNumber"; + public static final String VACCINE_UNII_CODE = "vaccineUniiCode"; + public static final String VACCINE_ATC_CODE = "vaccineAtcCode"; + + private Vaccination vaccination; + private String vaccinationDoses; + private VaccinationInfoSource vaccinationInfoSource; + private Date firstVaccinationDate; + private Date lastVaccinationDate; + private Vaccine vaccineName; + private String otherVaccineName; + private VaccineManufacturer vaccineManufacturer; + private String otherVaccineManufacturer; + private String vaccineInn; + private String vaccineBatchNumber; + private String vaccineUniiCode; + private String vaccineAtcCode; + + @Enumerated(EnumType.STRING) + public Vaccination getVaccination() { + return vaccination; + } + + public void setVaccination(Vaccination vaccination) { + this.vaccination = vaccination; + } + + @Column(length = COLUMN_LENGTH_DEFAULT) + public String getVaccinationDoses() { + return vaccinationDoses; + } + + public void setVaccinationDoses(String vaccinationDoses) { + this.vaccinationDoses = vaccinationDoses; + } + + @Enumerated(EnumType.STRING) + public VaccinationInfoSource getVaccinationInfoSource() { + return vaccinationInfoSource; + } + + public void setVaccinationInfoSource(VaccinationInfoSource vaccinationInfoSource) { + this.vaccinationInfoSource = vaccinationInfoSource; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getFirstVaccinationDate() { + return firstVaccinationDate; + } + + public void setFirstVaccinationDate(Date firstVaccinationDate) { + this.firstVaccinationDate = firstVaccinationDate; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getLastVaccinationDate() { + return lastVaccinationDate; + } + + public void setLastVaccinationDate(Date vaccinationDate) { + this.lastVaccinationDate = vaccinationDate; + } + + @Enumerated(EnumType.STRING) + public Vaccine getVaccineName() { + return vaccineName; + } + + public void setVaccineName(Vaccine vaccineName) { + this.vaccineName = vaccineName; + } + + @Column(columnDefinition = "text") + public String getOtherVaccineName() { + return otherVaccineName; + } + + public void setOtherVaccineName(String otherVaccineName) { + this.otherVaccineName = otherVaccineName; + } + + @Enumerated(EnumType.STRING) + public VaccineManufacturer getVaccineManufacturer() { + return vaccineManufacturer; + } + + public void setVaccineManufacturer(VaccineManufacturer vaccineManufacturer) { + this.vaccineManufacturer = vaccineManufacturer; + } + + @Column(columnDefinition = "text") + public String getOtherVaccineManufacturer() { + return otherVaccineManufacturer; + } + + public void setOtherVaccineManufacturer(String otherVaccineManufacturer) { + this.otherVaccineManufacturer = otherVaccineManufacturer; + } + + @Column(columnDefinition = "text") + public String getVaccineInn() { + return vaccineInn; + } + + public void setVaccineInn(String vaccineInn) { + this.vaccineInn = vaccineInn; + } + + @Column(columnDefinition = "text") + public String getVaccineBatchNumber() { + return vaccineBatchNumber; + } + + public void setVaccineBatchNumber(String vaccineBatchNumber) { + this.vaccineBatchNumber = vaccineBatchNumber; + } + + @Column(columnDefinition = "text") + public String getVaccineUniiCode() { + return vaccineUniiCode; + } + + public void setVaccineUniiCode(String vaccineUniiCode) { + this.vaccineUniiCode = vaccineUniiCode; + } + + @Column(columnDefinition = "text") + public String getVaccineAtcCode() { + return vaccineAtcCode; + } + + public void setVaccineAtcCode(String vaccineAtcCode) { + this.vaccineAtcCode = vaccineAtcCode; + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/vaccinationinfo/VaccinationInfoFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/vaccinationinfo/VaccinationInfoFacadeEjb.java new file mode 100644 index 00000000000..100cffb2b1a --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/vaccinationinfo/VaccinationInfoFacadeEjb.java @@ -0,0 +1,89 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2021 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.vaccinationinfo; + +import javax.ejb.EJB; +import javax.ejb.LocalBean; +import javax.ejb.Stateless; + +import de.symeda.sormas.api.vaccinationinfo.VaccinationInfoDto; +import de.symeda.sormas.api.vaccinationinfo.VaccinationInfoFacade; +import de.symeda.sormas.backend.util.DtoHelper; + +@Stateless(name = "VaccinationInfoFacade") +public class VaccinationInfoFacadeEjb implements VaccinationInfoFacade { + + @EJB + private VaccinationInfoService service; + + public static VaccinationInfoDto toDto(VaccinationInfo source) { + if (source == null) { + return null; + } + + VaccinationInfoDto target = new VaccinationInfoDto(); + + DtoHelper.fillDto(target, source); + + target.setVaccination(source.getVaccination()); + target.setVaccinationDoses(source.getVaccinationDoses()); + target.setVaccinationInfoSource(source.getVaccinationInfoSource()); + target.setFirstVaccinationDate(source.getFirstVaccinationDate()); + target.setLastVaccinationDate(source.getLastVaccinationDate()); + target.setVaccineName(source.getVaccineName()); + target.setOtherVaccineName(source.getOtherVaccineName()); + target.setVaccineManufacturer(source.getVaccineManufacturer()); + target.setOtherVaccineManufacturer(source.getOtherVaccineManufacturer()); + target.setVaccineInn(source.getVaccineInn()); + target.setVaccineBatchNumber(source.getVaccineBatchNumber()); + target.setVaccineUniiCode(source.getVaccineUniiCode()); + target.setVaccineAtcCode(source.getVaccineAtcCode()); + + return target; + } + + public VaccinationInfo fromDto(VaccinationInfoDto source, boolean checkChangeDate) { + if (source == null) { + return null; + } + + String uuid = source.getUuid(); + VaccinationInfo target = + DtoHelper.fillOrBuildEntity(source, uuid != null ? service.getByUuid(uuid) : null, VaccinationInfo::new, checkChangeDate); + + target.setVaccination(source.getVaccination()); + target.setVaccinationDoses(source.getVaccinationDoses()); + target.setVaccinationInfoSource(source.getVaccinationInfoSource()); + target.setFirstVaccinationDate(source.getFirstVaccinationDate()); + target.setLastVaccinationDate(source.getLastVaccinationDate()); + target.setVaccineName(source.getVaccineName()); + target.setOtherVaccineName(source.getOtherVaccineName()); + target.setVaccineManufacturer(source.getVaccineManufacturer()); + target.setOtherVaccineManufacturer(source.getOtherVaccineManufacturer()); + target.setVaccineInn(source.getVaccineInn()); + target.setVaccineBatchNumber(source.getVaccineBatchNumber()); + target.setVaccineUniiCode(source.getVaccineUniiCode()); + target.setVaccineAtcCode(source.getVaccineAtcCode()); + + return target; + } + + @LocalBean + @Stateless + public static class VaccinationInfoFacadeEjbLocal extends VaccinationInfoFacadeEjb { + + } +} diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/vaccinationinfo/VaccinationInfoService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/vaccinationinfo/VaccinationInfoService.java new file mode 100644 index 00000000000..be0e7a719b6 --- /dev/null +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/vaccinationinfo/VaccinationInfoService.java @@ -0,0 +1,30 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2021 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.vaccinationinfo; + +import javax.ejb.LocalBean; +import javax.ejb.Stateless; + +import de.symeda.sormas.backend.common.BaseAdoService; + +@Stateless +@LocalBean +public class VaccinationInfoService extends BaseAdoService { + + public VaccinationInfoService() { + super(VaccinationInfo.class); + } +} diff --git a/sormas-backend/src/main/resources/META-INF/persistence.xml b/sormas-backend/src/main/resources/META-INF/persistence.xml index 7443fa087df..d616437af5f 100644 --- a/sormas-backend/src/main/resources/META-INF/persistence.xml +++ b/sormas-backend/src/main/resources/META-INF/persistence.xml @@ -62,6 +62,7 @@ de.symeda.sormas.backend.common.messaging.ManualMessageLog de.symeda.sormas.backend.systemevent.SystemEvent de.symeda.sormas.backend.labmessage.LabMessage + de.symeda.sormas.backend.vaccinationinfo.VaccinationInfo true diff --git a/sormas-backend/src/main/resources/sql/sormas_schema.sql b/sormas-backend/src/main/resources/sql/sormas_schema.sql index 8bc5e17e130..c758aa16446 100644 --- a/sormas-backend/src/main/resources/sql/sormas_schema.sql +++ b/sormas-backend/src/main/resources/sql/sormas_schema.sql @@ -6355,7 +6355,7 @@ ALTER TABLE cases_history ADD COLUMN diseasevariant_id bigint; ALTER TABLE cases ADD CONSTRAINT fk_cases_diseasevariant_id FOREIGN KEY (diseasevariant_id) REFERENCES diseasevariant(id); INSERT INTO schema_version (version_number, comment) VALUES (316, 'Add DiseaseVariant entity #4042'); - + -- 2020-02-03 ALTER TABLE pathogentest ADD COLUMN typingId text; ALTER TABLE pathogentest_history ADD COLUMN typingId text; @@ -6378,4 +6378,67 @@ UPDATE exposures SET exposureRole = 'GUEST' WHERE exposureRole = 'ACCOMMODATED_I UPDATE exposures SET exposureRole = 'PATIENT' WHERE exposureRole = 'CARED_FOR'; INSERT INTO schema_version (version_number, comment) VALUES (319, '[SurvNet Interface] Change title of role field in exposures and add new field #4036'); +-- 2021-02-04 Add vaccination for contacts and event participant #4137 + +CREATE TABLE vaccinationinfo ( + id bigint NOT NULL, + changedate timestamp without time zone NOT NULL, + creationdate timestamp without time zone NOT NULL, + uuid character varying(36) NOT NULL, + vaccination varchar(255), + vaccinationdoses varchar(512), + vaccinationinfosource varchar(255), + firstvaccinationdate timestamp, + lastvaccinationdate timestamp, + vaccinename varchar(255), + othervaccinename text, + vaccinemanufacturer varchar(255), + othervaccinemanufacturer text, + vaccineinn text, + vaccinebatchnumber text, + vaccineuniicode text, + vaccineatccode text, + sys_period tstzrange not null, + primary key (id) +); + +ALTER TABLE vaccinationinfo OWNER TO sormas_user; + +CREATE TABLE vaccinationinfo_history (LIKE vaccinationinfo); +CREATE TRIGGER versioning_trigger + BEFORE INSERT OR UPDATE OR DELETE ON vaccinationinfo + FOR EACH ROW EXECUTE PROCEDURE versioning('sys_period', 'vaccinationinfo_history', true); +ALTER TABLE vaccinationinfo_history OWNER TO sormas_user; + +ALTER TABLE contact + ADD COLUMN vaccinationinfo_id bigint; + +ALTER TABLE contact ADD CONSTRAINT fk_contact_vaccinationinfo_id FOREIGN KEY (vaccinationinfo_id) REFERENCES vaccinationinfo(id); + +ALTER TABLE eventparticipant + ADD COLUMN vaccinationinfo_id bigint; + +ALTER TABLE eventparticipant ADD CONSTRAINT fk_eventparticipant_vaccinationinfo_id FOREIGN KEY (vaccinationinfo_id) REFERENCES vaccinationinfo(id); + +DO $$ + DECLARE rec RECORD; + DECLARE new_vaccination_info_id INTEGER; + BEGIN + FOR rec IN SELECT id FROM public.contact WHERE contact.vaccinationinfo_id IS NULL + LOOP + INSERT INTO vaccinationinfo(id, uuid, creationdate, changedate) VALUES (nextval('entity_seq'), upper(substring(CAST(CAST(md5(CAST(random() AS text) || CAST(clock_timestamp() AS text)) AS uuid) AS text), 3, 29)), now(), now()) RETURNING id INTO new_vaccination_info_id; + UPDATE contact SET vaccinationinfo_id = new_vaccination_info_id WHERE id = rec.id; + END LOOP; + + FOR rec IN SELECT id FROM public.eventparticipant WHERE eventparticipant.vaccinationinfo_id IS NULL + LOOP + INSERT INTO vaccinationinfo(id, uuid, creationdate, changedate) VALUES (nextval('entity_seq'), upper(substring(CAST(CAST(md5(CAST(random() AS text) || CAST(clock_timestamp() AS text)) AS uuid) AS text), 3, 29)), now(), now()) RETURNING id INTO new_vaccination_info_id; + UPDATE eventparticipant SET vaccinationinfo_id = new_vaccination_info_id WHERE id = rec.id; + END LOOP; + END; +$$ LANGUAGE plpgsql; + +INSERT INTO schema_version (version_number, comment) VALUES (320, 'Add vaccination for contacts and event participant #4137'); + + -- *** Insert new sql commands BEFORE this line *** diff --git a/sormas-backend/src/test/resources/META-INF/persistence.xml b/sormas-backend/src/test/resources/META-INF/persistence.xml index 4cd4c1cea35..e47fb0a0b60 100644 --- a/sormas-backend/src/test/resources/META-INF/persistence.xml +++ b/sormas-backend/src/test/resources/META-INF/persistence.xml @@ -61,6 +61,7 @@ de.symeda.sormas.backend.common.messaging.ManualMessageLog de.symeda.sormas.backend.systemevent.SystemEvent de.symeda.sormas.backend.labmessage.LabMessage + de.symeda.sormas.backend.vaccinationinfo.VaccinationInfo true diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactDataForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactDataForm.java index ae556a66822..c9ae8f77e19 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactDataForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactDataForm.java @@ -77,6 +77,7 @@ 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.api.utils.fieldvisibility.checkers.DiseaseFieldVisibilityChecker; import de.symeda.sormas.ui.ControllerProvider; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.clinicalcourse.HealthConditionsForm; @@ -89,6 +90,7 @@ import de.symeda.sormas.ui.utils.NullableOptionGroup; import de.symeda.sormas.ui.utils.VaadinUiUtil; import de.symeda.sormas.ui.utils.ViewMode; +import de.symeda.sormas.ui.vaccination.VaccinationInfoForm; public class ContactDataForm extends AbstractEditForm { @@ -100,6 +102,7 @@ public class ContactDataForm extends AbstractEditForm { private static final String CANCEL_OR_RESUME_FOLLOW_UP_BTN_LOC = "cancelOrResumeFollowUpBtnLoc"; private static final String LOST_FOLLOW_UP_BTN_LOC = "lostFollowUpBtnLoc"; private static final String GENERAL_COMMENT_LOC = "generalCommentLoc"; + private static final String MEDICAL_INFORMATION_LOC = "medicalInformationLoc"; //@formatter:off private static final String HTML_LAYOUT = @@ -140,6 +143,8 @@ public class ContactDataForm extends AbstractEditForm { fluidRowLocs(ContactDto.END_OF_QUARANTINE_REASON, ContactDto.END_OF_QUARANTINE_REASON_DETAILS) + locCss(VSPACE_3, ContactDto.HIGH_PRIORITY) + fluidRowLocs(ContactDto.HEALTH_CONDITIONS) + + loc(MEDICAL_INFORMATION_LOC) + + loc(ContactDto.VACCINATION_INFO) + fluidRowLocs(ContactDto.IMMUNOSUPPRESSIVE_THERAPY_BASIC_DISEASE, ContactDto.IMMUNOSUPPRESSIVE_THERAPY_BASIC_DISEASE_DETAILS) + loc(ContactDto.CARE_FOR_PEOPLE_OVER_60) + loc(FOLLOW_UP_STATUS_HEADING_LOC) + @@ -169,7 +174,7 @@ public ContactDataForm(Disease disease, ViewMode viewMode, boolean isPseudonymiz ContactDto.class, ContactDto.I18N_PREFIX, false, - FieldVisibilityCheckers.withCountry(FacadeProvider.getConfigFacade().getCountryLocale()), + FieldVisibilityCheckers.withCountry(FacadeProvider.getConfigFacade().getCountryLocale()).add(new DiseaseFieldVisibilityChecker(disease)), UiFieldAccessCheckers.forSensitiveData(isPseudonymized)); this.viewMode = viewMode; @@ -425,6 +430,13 @@ protected void addFields() { HealthConditionsForm clinicalCourseForm = addField(ContactDto.HEALTH_CONDITIONS, HealthConditionsForm.class); clinicalCourseForm.setCaption(null); + VaccinationInfoForm vaccinationForm = addField(ContactDto.VACCINATION_INFO, VaccinationInfoForm.class); + if (vaccinationForm.isVisibleAllowed()) { + Label medicalInformationCaptionLabel = new Label(I18nProperties.getString(Strings.headingMedicalInformation)); + medicalInformationCaptionLabel.addStyleName(H3); + getContent().addComponent(medicalInformationCaptionLabel, MEDICAL_INFORMATION_LOC); + } + Label generalCommentLabel = new Label(I18nProperties.getPrefixCaption(ContactDto.I18N_PREFIX, ContactDto.ADDITIONAL_DETAILS)); generalCommentLabel.addStyleName(H3); getContent().addComponent(generalCommentLabel, GENERAL_COMMENT_LOC); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventParticipantEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventParticipantEditForm.java index 386471c82db..1b30e8144fb 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventParticipantEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/events/EventParticipantEditForm.java @@ -17,15 +17,20 @@ *******************************************************************************/ package de.symeda.sormas.ui.events; +import static de.symeda.sormas.ui.utils.CssStyles.H3; import static de.symeda.sormas.ui.utils.LayoutUtil.fluidRowLocs; +import static de.symeda.sormas.ui.utils.LayoutUtil.loc; +import com.vaadin.ui.Label; import com.vaadin.v7.ui.ComboBox; import com.vaadin.v7.ui.TextField; import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.contact.ContactDto; import de.symeda.sormas.api.event.EventDto; import de.symeda.sormas.api.event.EventParticipantDto; import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.i18n.Strings; import de.symeda.sormas.api.person.PersonContext; import de.symeda.sormas.api.person.PersonDto; import de.symeda.sormas.api.region.RegionReferenceDto; @@ -34,33 +39,37 @@ import de.symeda.sormas.ui.person.PersonEditForm; import de.symeda.sormas.ui.utils.AbstractEditForm; import de.symeda.sormas.ui.utils.FieldHelper; +import de.symeda.sormas.ui.vaccination.VaccinationInfoForm; public class EventParticipantEditForm extends AbstractEditForm { private static final long serialVersionUID = 1L; + private static final String MEDICAL_INFORMATION_LOC = "medicalInformationLoc"; + private static final String HTML_LAYOUT = fluidRowLocs(EventParticipantDto.REGION, EventParticipantDto.DISTRICT) + fluidRowLocs(EventParticipantDto.REPORTING_USER) + fluidRowLocs(EventParticipantDto.INVOLVEMENT_DESCRIPTION) - + fluidRowLocs(EventParticipantDto.PERSON); + + fluidRowLocs(EventParticipantDto.PERSON) + + loc(MEDICAL_INFORMATION_LOC) + + fluidRowLocs(EventParticipantDto.VACCINATION_INFO); private final EventDto event; private final boolean isPseudonymized; + private VaccinationInfoForm vaccinationForm; + public EventParticipantEditForm(EventDto event, boolean isPseudonymized) { super( EventParticipantDto.class, EventParticipantDto.I18N_PREFIX, false, - new FieldVisibilityCheckers(), + FieldVisibilityCheckers.withDisease(event.getDisease()), UiFieldAccessCheckers.getDefault(isPseudonymized)); this.event = event; this.isPseudonymized = isPseudonymized; - if (event == null) { - throw new IllegalArgumentException("Event cannot be null"); - } addFields(); } @@ -97,7 +106,15 @@ protected void addFields() { addField(EventParticipantDto.REPORTING_USER, ComboBox.class); setReadOnly(true, EventParticipantDto.REPORTING_USER); + initializeVisibilitiesAndAllowedVisibilities(); initializeAccessAndAllowedAccesses(); + + vaccinationForm = addField(ContactDto.VACCINATION_INFO, VaccinationInfoForm.class); + if (vaccinationForm.isVisibleAllowed()) { + Label medicalInformationCaptionLabel = new Label(I18nProperties.getString(Strings.headingMedicalInformation)); + medicalInformationCaptionLabel.addStyleName(H3); + getContent().addComponent(medicalInformationCaptionLabel, MEDICAL_INFORMATION_LOC); + } } public String getPersonFirstName() { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java index 502b7d27d33..ac34ae37a55 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java @@ -51,7 +51,9 @@ public abstract class AbstractEditForm extends AbstractForm implements private boolean hideValidationUntilNextCommit = false; private List> visibleAllowedFields = new ArrayList<>(); + private boolean visibilitiesInitialized; private List> editableAllowedFields = new ArrayList<>(); + private boolean fieldAccessesInitialized; protected AbstractEditForm(Class type, String propertyI18nPrefix) { this(type, propertyI18nPrefix, true, null, null); @@ -410,6 +412,8 @@ protected void initializeVisibilitiesAndAllowedVisibilities() { field.setVisible(false); } } + + visibilitiesInitialized = true; } /** @@ -417,7 +421,7 @@ protected void initializeVisibilitiesAndAllowedVisibilities() { * the given field. This needs to be called before EVERY setVisible or setVisibleWhen call. */ protected boolean isVisibleAllowed(Field field) { - return visibleAllowedFields.isEmpty() || visibleAllowedFields.contains(field); + return !visibilitiesInitialized || visibleAllowedFields.contains(field); } protected boolean isVisibleAllowed(String propertyId) { @@ -453,6 +457,8 @@ protected void initializeAccessAndAllowedAccesses() { } } } + + fieldAccessesInitialized = true; } /** @@ -460,7 +466,7 @@ protected void initializeAccessAndAllowedAccesses() { * the given field. This needs to be called before EVERY setEnabled or setEnabledWhen call. */ protected boolean isEditableAllowed(Field field) { - return editableAllowedFields.isEmpty() || editableAllowedFields.contains(field); + return !fieldAccessesInitialized || editableAllowedFields.contains(field); } protected boolean isEditableAllowed(String propertyId) { 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 e55f40f2b8b..19fcc31ac48 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 @@ -30,6 +30,7 @@ import de.symeda.sormas.ui.hospitalization.PreviousHospitalizationsField; import de.symeda.sormas.ui.location.LocationEditForm; import de.symeda.sormas.ui.person.LocationsField; +import de.symeda.sormas.ui.vaccination.VaccinationInfoForm; public class SormasFieldGroupFieldFactory extends DefaultFieldGroupFieldFactory { @@ -123,6 +124,8 @@ public T createField(Class type, Class fieldType) { return (T) new ExposuresField(fieldVisibilityCheckers, fieldAccessCheckers); } else if (LocationsField.class.isAssignableFrom(fieldType)) { return (T) new LocationsField(fieldVisibilityCheckers, fieldAccessCheckers); + } else if (VaccinationInfoForm.class.isAssignableFrom(fieldType)) { + return (T) new VaccinationInfoForm(fieldVisibilityCheckers, fieldAccessCheckers); } else if (fieldType.equals(Field.class)) { // no specific field type defined -> fallbacks if (Date.class.isAssignableFrom(type)) { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/vaccination/VaccinationInfoForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/vaccination/VaccinationInfoForm.java new file mode 100644 index 00000000000..c3862a2611c --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/vaccination/VaccinationInfoForm.java @@ -0,0 +1,196 @@ +/* + * SORMAS® - Surveillance Outbreak Response Management & Analysis System + * Copyright © 2016-2021 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.vaccination; + +import static de.symeda.sormas.ui.utils.LayoutUtil.fluidRowLocs; + +import java.util.Collections; + +import com.vaadin.v7.ui.ComboBox; + +import de.symeda.sormas.api.caze.Vaccination; +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.Validations; +import de.symeda.sormas.api.utils.fieldaccess.UiFieldAccessCheckers; +import de.symeda.sormas.api.utils.fieldvisibility.FieldVisibilityCheckers; +import de.symeda.sormas.api.vaccinationinfo.VaccinationInfoDto; +import de.symeda.sormas.ui.utils.AbstractEditForm; +import de.symeda.sormas.ui.utils.FieldHelper; +import de.symeda.sormas.ui.utils.NumberValidator; + +public class VaccinationInfoForm extends AbstractEditForm { + + private static final String HTML_LAYOUT = fluidRowLocs(VaccinationInfoDto.VACCINATION, VaccinationInfoDto.VACCINATION_DOSES) + + fluidRowLocs( + VaccinationInfoDto.FIRST_VACCINATION_DATE, + VaccinationInfoDto.LAST_VACCINATION_DATE, + VaccinationInfoDto.VACCINATION_INFO_SOURCE) + + fluidRowLocs(VaccinationInfoDto.VACCINE_NAME, VaccinationInfoDto.OTHER_VACCINE_NAME) + + fluidRowLocs(VaccinationInfoDto.VACCINE_MANUFACTURER, VaccinationInfoDto.OTHER_VACCINE_MANUFACTURER) + + fluidRowLocs(VaccinationInfoDto.VACCINE_INN, VaccinationInfoDto.VACCINE_BATCH_NUMBER) + + fluidRowLocs(VaccinationInfoDto.VACCINE_UNII_CODE, VaccinationInfoDto.VACCINE_ATC_CODE); + + public VaccinationInfoForm(FieldVisibilityCheckers fieldVisibilityCheckers, UiFieldAccessCheckers fieldAccessCheckers) { + super(VaccinationInfoDto.class, VaccinationInfoDto.I18N_PREFIX, true, fieldVisibilityCheckers, fieldAccessCheckers); + } + + @Override + protected String createHtmlLayout() { + return HTML_LAYOUT; + } + + @Override + protected void addFields() { + addField(VaccinationInfoDto.VACCINATION); + addField(VaccinationInfoDto.VACCINATION_DOSES) + .addValidator(new NumberValidator(I18nProperties.getValidationError(Validations.vaccineDosesFormat), 1, 10)); + addFields(VaccinationInfoDto.VACCINATION_INFO_SOURCE, VaccinationInfoDto.FIRST_VACCINATION_DATE, VaccinationInfoDto.LAST_VACCINATION_DATE); + + ComboBox vaccineName = addField(VaccinationInfoDto.VACCINE_NAME); + ComboBox vaccineManufacturer = addField(VaccinationInfoDto.VACCINE_MANUFACTURER); + vaccineName.addValueChangeListener(e -> { + Vaccine vaccine = (Vaccine) e.getProperty().getValue(); + if (vaccine != null) { + vaccineManufacturer.setValue(vaccine.getManufacturer()); + } + }); + + addFields( + VaccinationInfoDto.OTHER_VACCINE_NAME, + VaccinationInfoDto.OTHER_VACCINE_MANUFACTURER, + VaccinationInfoDto.VACCINE_INN, + VaccinationInfoDto.VACCINE_BATCH_NUMBER, + VaccinationInfoDto.VACCINE_UNII_CODE, + VaccinationInfoDto.VACCINE_ATC_CODE); + + initializeVisibilitiesAndAllowedVisibilities(); + initializeAccessAndAllowedAccesses(); + + if (isVisibleAllowed(VaccinationInfoDto.VACCINATION_DOSES)) { + FieldHelper.setVisibleWhen( + getFieldGroup(), + VaccinationInfoDto.VACCINATION_DOSES, + VaccinationInfoDto.VACCINATION, + Collections.singletonList(Vaccination.VACCINATED), + true); + } + + if (isVisibleAllowed(VaccinationInfoDto.FIRST_VACCINATION_DATE)) { + FieldHelper.setVisibleWhen( + getFieldGroup(), + VaccinationInfoDto.FIRST_VACCINATION_DATE, + VaccinationInfoDto.VACCINATION, + Collections.singletonList(Vaccination.VACCINATED), + true); + } + + if (isVisibleAllowed(VaccinationInfoDto.LAST_VACCINATION_DATE)) { + FieldHelper.setVisibleWhen( + getFieldGroup(), + VaccinationInfoDto.LAST_VACCINATION_DATE, + VaccinationInfoDto.VACCINATION, + Collections.singletonList(Vaccination.VACCINATED), + true); + } + + if (isVisibleAllowed(VaccinationInfoDto.VACCINE_NAME)) { + FieldHelper.setVisibleWhen( + getFieldGroup(), + VaccinationInfoDto.VACCINE_NAME, + VaccinationInfoDto.VACCINATION, + Collections.singletonList(Vaccination.VACCINATED), + true); + FieldHelper.setVisibleWhen( + getFieldGroup(), + VaccinationInfoDto.OTHER_VACCINE_NAME, + VaccinationInfoDto.VACCINE_NAME, + Collections.singletonList(Vaccine.OTHER), + true); + } + + if (isVisibleAllowed(VaccinationInfoDto.VACCINATION_INFO_SOURCE)) { + FieldHelper.setVisibleWhen( + getFieldGroup(), + VaccinationInfoDto.VACCINATION_INFO_SOURCE, + VaccinationInfoDto.VACCINATION, + Collections.singletonList(Vaccination.VACCINATED), + true); + } + + if (isVisibleAllowed(VaccinationInfoDto.VACCINE_MANUFACTURER)) { + FieldHelper.setVisibleWhen( + getFieldGroup(), + VaccinationInfoDto.VACCINE_MANUFACTURER, + VaccinationInfoDto.VACCINATION, + Collections.singletonList(Vaccination.VACCINATED), + true); + FieldHelper.setVisibleWhen( + getFieldGroup(), + VaccinationInfoDto.OTHER_VACCINE_MANUFACTURER, + VaccinationInfoDto.VACCINE_MANUFACTURER, + Collections.singletonList(VaccineManufacturer.OTHER), + true); + } + + if (isVisibleAllowed(VaccinationInfoDto.VACCINE_INN)) { + FieldHelper.setVisibleWhen( + getFieldGroup(), + VaccinationInfoDto.VACCINE_INN, + VaccinationInfoDto.VACCINATION, + Collections.singletonList(Vaccination.VACCINATED), + true); + } + + if (isVisibleAllowed(VaccinationInfoDto.VACCINE_BATCH_NUMBER)) { + FieldHelper.setVisibleWhen( + getFieldGroup(), + VaccinationInfoDto.VACCINE_BATCH_NUMBER, + VaccinationInfoDto.VACCINATION, + Collections.singletonList(Vaccination.VACCINATED), + true); + } + + if (isVisibleAllowed(VaccinationInfoDto.VACCINE_UNII_CODE)) { + FieldHelper.setVisibleWhen( + getFieldGroup(), + VaccinationInfoDto.VACCINE_UNII_CODE, + VaccinationInfoDto.VACCINATION, + Collections.singletonList(Vaccination.VACCINATED), + true); + } + + if (isVisibleAllowed(VaccinationInfoDto.VACCINE_ATC_CODE)) { + FieldHelper.setVisibleWhen( + getFieldGroup(), + VaccinationInfoDto.VACCINE_ATC_CODE, + VaccinationInfoDto.VACCINATION, + Collections.singletonList(Vaccination.VACCINATED), + true); + } + } + + public boolean isVisibleAllowed() { + return isVisibleAllowed(VaccinationInfoDto.VACCINATION); + } + + @Override + public String getCaption() { + // never render caption + return null; + } +} diff --git a/sormas-ui/src/test/resources/META-INF/persistence.xml b/sormas-ui/src/test/resources/META-INF/persistence.xml index 959f6a5ce0e..bbac17f19c7 100644 --- a/sormas-ui/src/test/resources/META-INF/persistence.xml +++ b/sormas-ui/src/test/resources/META-INF/persistence.xml @@ -61,6 +61,7 @@ de.symeda.sormas.backend.common.messaging.ManualMessageLog de.symeda.sormas.backend.systemevent.SystemEvent de.symeda.sormas.backend.labmessage.LabMessage + de.symeda.sormas.backend.vaccinationinfo.VaccinationInfo true