From a7c1ed2d366e193280cfd9b0ed924ae48ebaa923 Mon Sep 17 00:00:00 2001 From: Carina Paul Date: Thu, 21 Dec 2023 17:48:25 +0200 Subject: [PATCH 1/5] #12794 - The same event participant should not be allowed to be selected --- .../backend/event/EventParticipantDao.java | 22 ++++++++++ .../sormas/app/caze/edit/CaseNewActivity.java | 2 +- .../app/contact/edit/ContactNewActivity.java | 2 +- .../edit/EventParticipantNewActivity.java | 5 ++- .../edit/ImmunizationNewActivity.java | 2 +- .../person/SelectOrCreatePersonDialog.java | 40 +++++++++++++++++-- 6 files changed, 64 insertions(+), 9 deletions(-) diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantDao.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantDao.java index 9e53fb24180..78a2930f4ff 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantDao.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/backend/event/EventParticipantDao.java @@ -26,6 +26,7 @@ import de.symeda.sormas.app.backend.common.AbstractAdoDao; import de.symeda.sormas.app.backend.common.AbstractDomainObject; import de.symeda.sormas.app.backend.config.ConfigProvider; +import de.symeda.sormas.app.backend.person.Person; public class EventParticipantDao extends AbstractAdoDao { @@ -66,6 +67,27 @@ public List getByEvent(Event event) { } } + public boolean eventParticipantAlreadyExists(Event event, Person person) { + + if (event.isSnapshot()) { + throw new IllegalArgumentException("Does not support snapshot entities"); + } + + try { + List eventParticipants = queryBuilder().where() + .eq(EventParticipant.EVENT + "_id", event) + .and() + .eq(AbstractDomainObject.SNAPSHOT, false) + .and() + .eq(EventParticipant.PERSON + "_id", person) + .query(); + return eventParticipants.size() > 0; + } catch (SQLException e) { + Log.e(getTableName(), "Could not perform getByEvent on EventParticipant"); + throw new RuntimeException(e); + } + } + public Long countByEvent(Event event) { if (event.isSnapshot()) { throw new IllegalArgumentException("Does not support snapshot entities"); diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseNewActivity.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseNewActivity.java index 86b7bac1a83..05223153c56 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseNewActivity.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseNewActivity.java @@ -227,7 +227,7 @@ public void saveData() { // Person selection can be skipped if the case was created from a contact or event participant if (contactUuid == null && eventParticipantUuid == null) { - SelectOrCreatePersonDialog.selectOrCreatePerson(caze.getPerson(), person -> { + SelectOrCreatePersonDialog.selectOrCreatePerson(caze.getPerson(), caze, person -> { if (person != null) { caze.setPerson(person); pickOrCreateCaseAndSave(caze, fragment); diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/contact/edit/ContactNewActivity.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/contact/edit/ContactNewActivity.java index 0610f469e51..6db81a6d4bd 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/contact/edit/ContactNewActivity.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/contact/edit/ContactNewActivity.java @@ -177,7 +177,7 @@ public void saveData() { return; } - SelectOrCreatePersonDialog.selectOrCreatePerson(contactToSave.getPerson(), new Consumer() { + SelectOrCreatePersonDialog.selectOrCreatePerson(contactToSave.getPerson(), contactToSave, new Consumer() { @Override public void accept(Person person) { diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/event/eventparticipant/edit/EventParticipantNewActivity.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/event/eventparticipant/edit/EventParticipantNewActivity.java index 07a3c1e1711..1a2e2e77980 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/event/eventparticipant/edit/EventParticipantNewActivity.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/event/eventparticipant/edit/EventParticipantNewActivity.java @@ -135,7 +135,9 @@ public void saveData() { return; } - SelectOrCreatePersonDialog.selectOrCreatePerson(eventParticipantToSave.getPerson(), new Consumer() { + final Event event = DatabaseHelper.getEventDao().queryUuid(eventUuid); + + SelectOrCreatePersonDialog.selectOrCreatePerson(eventParticipantToSave.getPerson(), event, new Consumer() { @Override public void accept(Person person) { @@ -151,7 +153,6 @@ protected void onPreExecute() { @Override protected void doInBackground(TaskResultHolder resultHolder) throws Exception { DatabaseHelper.getPersonDao().saveAndSnapshot(eventParticipantToSave.getPerson()); - final Event event = DatabaseHelper.getEventDao().queryUuid(eventUuid); eventParticipantToSave.setEvent(event); DatabaseHelper.getEventParticipantDao().saveAndSnapshot(eventParticipantToSave); } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/immunization/edit/ImmunizationNewActivity.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/immunization/edit/ImmunizationNewActivity.java index 6a83ddd6e4f..d022496404c 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/immunization/edit/ImmunizationNewActivity.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/immunization/edit/ImmunizationNewActivity.java @@ -182,7 +182,7 @@ public void saveData() { if (caseUuid != null || contactUuid != null || eventParticipantUuid != null) { pickOrCreateImmunizationAndSave(immunization, fragment); } else { - SelectOrCreatePersonDialog.selectOrCreatePerson(immunization.getPerson(), person -> { + SelectOrCreatePersonDialog.selectOrCreatePerson(immunization.getPerson(), immunization, person -> { if (person != null) { immunization.setPerson(person); pickOrCreateImmunizationAndSave(immunization, fragment); diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/person/SelectOrCreatePersonDialog.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/person/SelectOrCreatePersonDialog.java index 87caa38f439..cecbeee037a 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/person/SelectOrCreatePersonDialog.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/person/SelectOrCreatePersonDialog.java @@ -21,20 +21,22 @@ import android.content.Context; import android.view.View; - import androidx.databinding.Observable; import androidx.databinding.ObservableArrayList; import androidx.databinding.ObservableField; import androidx.databinding.ViewDataBinding; import androidx.databinding.library.baseAdapters.BR; import androidx.fragment.app.FragmentActivity; - +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.i18n.Strings; import de.symeda.sormas.api.person.PersonHelper; import de.symeda.sormas.api.person.PersonNameDto; import de.symeda.sormas.api.person.PersonSimilarityCriteria; import de.symeda.sormas.app.BaseActivity; import de.symeda.sormas.app.R; import de.symeda.sormas.app.backend.common.DatabaseHelper; +import de.symeda.sormas.app.backend.common.PseudonymizableAdo; +import de.symeda.sormas.app.backend.event.Event; import de.symeda.sormas.app.backend.person.Person; import de.symeda.sormas.app.component.controls.ControlButton; import de.symeda.sormas.app.component.dialog.AbstractDialog; @@ -61,9 +63,11 @@ public class SelectOrCreatePersonDialog extends AbstractDialog { private Callback createCallback; private final ObservableField selectedPerson = new ObservableField<>(); + private View selectedPersonItemView; + // Static methods - public static void selectOrCreatePerson(final Person person, final Consumer resultConsumer) { + public static void selectOrCreatePerson(final Person person, PseudonymizableAdo ado, final Consumer resultConsumer) { final SelectOrCreatePersonDialog personDialog = new SelectOrCreatePersonDialog(BaseActivity.getActiveActivity(), person); if (!personDialog.hasSimilarPersons()) { @@ -73,7 +77,24 @@ public static void selectOrCreatePerson(final Person person, final Consumer { if (personDialog.getSelectedPerson() != null) { - resultConsumer.accept(personDialog.getSelectedPerson()); + if (ado instanceof Event) { + boolean eventParticipantAlreadyExists = + DatabaseHelper.getEventParticipantDao().eventParticipantAlreadyExists((Event) ado, personDialog.getSelectedPerson()); + + if (eventParticipantAlreadyExists) { + personDialog.suppressNextDismiss(); + + personDialog.setSelectedPerson(null); + personDialog.setSelectedPersonItemView(null); + + NotificationHelper.showDialogNotification( + personDialog, + NotificationType.WARNING, + I18nProperties.getString(Strings.messageAlreadyEventParticipant)); + } else { + resultConsumer.accept(personDialog.getSelectedPerson()); + } + } } else { personDialog.suppressNextDismiss(); NotificationHelper.showDialogNotification(personDialog, NotificationType.ERROR, R.string.info_select_create_person); @@ -150,8 +171,10 @@ private void setUpControlListeners() { if (itemViewId == vId && v.isSelected()) { itemView.setSelected(false); + setSelectedPerson(personItem); } else if (itemViewId == vId && !v.isSelected()) { itemView.setSelected(true); + setSelectedPersonItemView(itemView); setSelectedPerson(personItem); } else { itemView.setSelected(false); @@ -193,6 +216,11 @@ public void onPropertyChanged(Observable observable, int i) { if (getSelectedPerson() == null) { btnCreate.setVisibility(View.VISIBLE); btnSelect.setVisibility(View.GONE); + + //TODO: View based on tag and the item will be set to false + if (selectedPersonItemView != null) { + selectedPersonItemView.setSelected(false); + } } else { btnCreate.setVisibility(View.GONE); btnSelect.setVisibility(View.VISIBLE); @@ -229,4 +257,8 @@ private Person getSelectedPerson() { private void setSelectedPerson(Person selectedPerson) { this.selectedPerson.set(selectedPerson); } + + public void setSelectedPersonItemView(View selectedPersonItemView) { + this.selectedPersonItemView = selectedPersonItemView; + } } From bfc98c6ab32e17f3273cfe9001b2746463bd03e4 Mon Sep 17 00:00:00 2001 From: Carina Paul Date: Fri, 5 Jan 2024 17:57:03 +0200 Subject: [PATCH 2/5] #12794- Fix linking an event to a case bug --- .../de/symeda/sormas/app/caze/edit/CaseEditActivity.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditActivity.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditActivity.java index 2e4c69c19fb..8a3c86a6886 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditActivity.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditActivity.java @@ -352,7 +352,10 @@ private void linkEventToCase() { eventParticipantToSave.setResultingCaseUuid(caze.getUuid()); EventParticipantSaver eventParticipantSaver = new EventParticipantSaver(this); - if (!isEventLinkedToCase(caze, event)) { + boolean eventParticipantAlreadyExists = + DatabaseHelper.getEventParticipantDao().eventParticipantAlreadyExists(event, caze.getPerson()); + + if (!isEventLinkedToCase(caze, event) && !eventParticipantAlreadyExists) { eventParticipantSaver.saveEventParticipantLinkedToCase(eventParticipantToSave); } else { NotificationHelper From 0e7382b2498f6e25c927c6a7cd59b5724bb53f52 Mon Sep 17 00:00:00 2001 From: Carina Paul Date: Mon, 8 Jan 2024 12:56:22 +0200 Subject: [PATCH 3/5] #12794 - fix --- .../de/symeda/sormas/app/person/SelectOrCreatePersonDialog.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/person/SelectOrCreatePersonDialog.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/person/SelectOrCreatePersonDialog.java index cecbeee037a..9bd20bbc703 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/person/SelectOrCreatePersonDialog.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/person/SelectOrCreatePersonDialog.java @@ -94,6 +94,8 @@ public static void selectOrCreatePerson(final Person person, PseudonymizableAdo } else { resultConsumer.accept(personDialog.getSelectedPerson()); } + } else { + resultConsumer.accept(personDialog.getSelectedPerson()); } } else { personDialog.suppressNextDismiss(); From 932e054aa597755b3495470d6e5093085caed12c Mon Sep 17 00:00:00 2001 From: Carina Paul Date: Mon, 8 Jan 2024 18:38:36 +0200 Subject: [PATCH 4/5] #12794 - changes after review --- .../app/caze/edit/CaseEditActivity.java | 7 ++---- .../person/SelectOrCreatePersonDialog.java | 25 +++++++------------ 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditActivity.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditActivity.java index 8a3c86a6886..179e2b7205d 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditActivity.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditActivity.java @@ -23,7 +23,6 @@ import android.content.Context; import android.os.AsyncTask; import android.view.Menu; - import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.caze.CaseClassification; import de.symeda.sormas.api.caze.CaseOrigin; @@ -352,10 +351,8 @@ private void linkEventToCase() { eventParticipantToSave.setResultingCaseUuid(caze.getUuid()); EventParticipantSaver eventParticipantSaver = new EventParticipantSaver(this); - boolean eventParticipantAlreadyExists = - DatabaseHelper.getEventParticipantDao().eventParticipantAlreadyExists(event, caze.getPerson()); - - if (!isEventLinkedToCase(caze, event) && !eventParticipantAlreadyExists) { + if (!isEventLinkedToCase(caze, event) + && !DatabaseHelper.getEventParticipantDao().eventParticipantAlreadyExists(event, caze.getPerson())) { eventParticipantSaver.saveEventParticipantLinkedToCase(eventParticipantToSave); } else { NotificationHelper diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/person/SelectOrCreatePersonDialog.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/person/SelectOrCreatePersonDialog.java index 9bd20bbc703..361b26142c0 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/person/SelectOrCreatePersonDialog.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/person/SelectOrCreatePersonDialog.java @@ -77,23 +77,17 @@ public static void selectOrCreatePerson(final Person person, PseudonymizableAdo personDialog.setPositiveCallback(() -> { if (personDialog.getSelectedPerson() != null) { - if (ado instanceof Event) { - boolean eventParticipantAlreadyExists = - DatabaseHelper.getEventParticipantDao().eventParticipantAlreadyExists((Event) ado, personDialog.getSelectedPerson()); + if (ado instanceof Event + && DatabaseHelper.getEventParticipantDao().eventParticipantAlreadyExists((Event) ado, personDialog.getSelectedPerson())) { + personDialog.suppressNextDismiss(); + personDialog.setSelectedPerson(null); + personDialog.setSelectedPersonItemView(null); - if (eventParticipantAlreadyExists) { - personDialog.suppressNextDismiss(); + NotificationHelper.showDialogNotification( + personDialog, + NotificationType.WARNING, + I18nProperties.getString(Strings.messageAlreadyEventParticipant)); - personDialog.setSelectedPerson(null); - personDialog.setSelectedPersonItemView(null); - - NotificationHelper.showDialogNotification( - personDialog, - NotificationType.WARNING, - I18nProperties.getString(Strings.messageAlreadyEventParticipant)); - } else { - resultConsumer.accept(personDialog.getSelectedPerson()); - } } else { resultConsumer.accept(personDialog.getSelectedPerson()); } @@ -219,7 +213,6 @@ public void onPropertyChanged(Observable observable, int i) { btnCreate.setVisibility(View.VISIBLE); btnSelect.setVisibility(View.GONE); - //TODO: View based on tag and the item will be set to false if (selectedPersonItemView != null) { selectedPersonItemView.setSelected(false); } From afccd9f9531c298e06ff25d7511e03b9fff63e1e Mon Sep 17 00:00:00 2001 From: Carina Paul Date: Thu, 11 Jan 2024 16:54:44 +0200 Subject: [PATCH 5/5] #12794 - Display proper message if only the event participant was linked not the event --- .../sormas/app/caze/edit/CaseEditActivity.java | 15 ++++++++++++--- .../sormas/app/event/edit/EventNewActivity.java | 2 +- .../eventparticipant/EventParticipantSaver.java | 8 ++++++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditActivity.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditActivity.java index 179e2b7205d..2f3c62ca52e 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditActivity.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/caze/edit/CaseEditActivity.java @@ -23,12 +23,15 @@ import android.content.Context; import android.os.AsyncTask; import android.view.Menu; + import de.symeda.sormas.api.Disease; import de.symeda.sormas.api.caze.CaseClassification; import de.symeda.sormas.api.caze.CaseOrigin; import de.symeda.sormas.api.caze.CaseReferenceDto; import de.symeda.sormas.api.feature.FeatureType; import de.symeda.sormas.api.feature.FeatureTypeProperty; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.i18n.Strings; import de.symeda.sormas.api.user.UserRight; import de.symeda.sormas.api.utils.DataHelper; import de.symeda.sormas.api.utils.ValidationException; @@ -351,9 +354,15 @@ private void linkEventToCase() { eventParticipantToSave.setResultingCaseUuid(caze.getUuid()); EventParticipantSaver eventParticipantSaver = new EventParticipantSaver(this); - if (!isEventLinkedToCase(caze, event) - && !DatabaseHelper.getEventParticipantDao().eventParticipantAlreadyExists(event, caze.getPerson())) { - eventParticipantSaver.saveEventParticipantLinkedToCase(eventParticipantToSave); + if (!isEventLinkedToCase(caze, event)) { + boolean eventParticipantAlreadyExists = + DatabaseHelper.getEventParticipantDao().eventParticipantAlreadyExists(event, caze.getPerson()); + eventParticipantSaver.saveEventParticipantLinkedToCase(eventParticipantToSave, eventParticipantAlreadyExists); + + if (eventParticipantAlreadyExists) { + NotificationHelper.showNotification(this, WARNING, I18nProperties.getString(Strings.messagePersonAlreadyEventParticipant)); + } + } else { NotificationHelper .showNotification(this, WARNING, getString(R.string.message_Event_already_linked_to_Case) + " " + caze.getUuid()); diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/event/edit/EventNewActivity.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/event/edit/EventNewActivity.java index b024977ac19..bb275c23ca8 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/event/edit/EventNewActivity.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/event/edit/EventNewActivity.java @@ -175,7 +175,7 @@ protected void onPostExecute(AsyncTaskResult taskResult) { eventParticipantToSave.setEvent(eventToSave); eventParticipantToSave.setResultingCaseUuid(linkedCase.getUuid()); EventParticipantSaver eventParticipantSaver = new EventParticipantSaver(EventNewActivity.this); - eventParticipantSaver.saveEventParticipantLinkedToCase(eventParticipantToSave); + eventParticipantSaver.saveEventParticipantLinkedToCase(eventParticipantToSave, false); } else { EventEditActivity.startActivity(getContext(), eventToSave.getUuid(), EventSection.EVENT_PARTICIPANTS); } diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/event/eventparticipant/EventParticipantSaver.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/event/eventparticipant/EventParticipantSaver.java index 0e39523a2b3..d4a8ccbd1d0 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/event/eventparticipant/EventParticipantSaver.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/event/eventparticipant/EventParticipantSaver.java @@ -15,7 +15,7 @@ public EventParticipantSaver(BaseActivity parentActivity) { this.parentActivity = parentActivity; } - public void saveEventParticipantLinkedToCase(EventParticipant eventParticipantToSave) { + public void saveEventParticipantLinkedToCase(EventParticipant eventParticipantToSave, boolean eventParticipantAlreadyExists) { new SavingAsyncTask(parentActivity.getRootView(), eventParticipantToSave) { @@ -32,7 +32,11 @@ protected void doInBackground(TaskResultHolder resultHolder) throws Exception { @Override protected void onPostExecute(AsyncTaskResult taskResult) { parentActivity.hidePreloader(); - super.onPostExecute(taskResult); + + if (!eventParticipantAlreadyExists) { + super.onPostExecute(taskResult); + } + if (taskResult.getResultStatus().isSuccess()) { parentActivity.finish(); }