Skip to content
This repository was archived by the owner on May 5, 2021. It is now read-only.

Commit 2599f0a

Browse files
Feature 4058 sample selection (SORMAS-Foundation#4144)
* SORMAS-Foundation#4058: Add sample selection
1 parent 050e0b9 commit 2599f0a

12 files changed

Lines changed: 281 additions & 13 deletions

File tree

sormas-api/src/main/java/de/symeda/sormas/api/i18n/Captions.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,6 +1397,7 @@ public interface Captions {
13971397
String sampleAllSamples = "sampleAllSamples";
13981398
String sampleArchivedSamples = "sampleArchivedSamples";
13991399
String sampleAssociationType = "sampleAssociationType";
1400+
String sampleCreateNew = "sampleCreateNew";
14001401
String SampleExport_additionalTestingRequested = "SampleExport.additionalTestingRequested";
14011402
String SampleExport_altSgpt = "SampleExport.altSgpt";
14021403
String SampleExport_arterialVenousBloodGas = "SampleExport.arterialVenousBloodGas";
@@ -1481,6 +1482,7 @@ public interface Captions {
14811482
String sampleReferredTo = "sampleReferredTo";
14821483
String sampleReferredToInternal = "sampleReferredToInternal";
14831484
String sampleSamplesList = "sampleSamplesList";
1485+
String sampleSelect = "sampleSelect";
14841486
String sampleShipped = "sampleShipped";
14851487
String sampleSpecimenNotAdequate = "sampleSpecimenNotAdequate";
14861488
String sex = "sex";

sormas-api/src/main/java/de/symeda/sormas/api/i18n/Strings.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ public interface Strings {
409409
String headingPickOrCreateEntry = "headingPickOrCreateEntry";
410410
String headingPickOrCreateEvent = "headingPickOrCreateEvent";
411411
String headingPickOrCreatePerson = "headingPickOrCreatePerson";
412+
String headingPickOrCreateSample = "headingPickOrCreateSample";
412413
String headingPointOfEntryImport = "headingPointOfEntryImport";
413414
String headingPointOfEntryInformation = "headingPointOfEntryInformation";
414415
String headingPrescriptionsDeleted = "headingPrescriptionsDeleted";
@@ -524,6 +525,7 @@ public interface Strings {
524525
String infoPickOrCreateCaseNewCase = "infoPickOrCreateCaseNewCase";
525526
String infoPickOrCreateEventForCase = "infoPickOrCreateEventForCase";
526527
String infoPickOrCreateEventForContact = "infoPickOrCreateEventForContact";
528+
String infoPickOrCreateSample = "infoPickOrCreateSample";
527529
String infoPickOrCreateSuperordinateEventForEvent = "infoPickOrCreateSuperordinateEventForEvent";
528530
String infoPopulationCollectionDate = "infoPopulationCollectionDate";
529531
String infoPopulationDataView = "infoPopulationDataView";

sormas-api/src/main/java/de/symeda/sormas/api/sample/SampleFacade.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,7 @@ public interface SampleFacade {
6666

6767
Boolean isSampleEditAllowed(String sampleUuid);
6868

69+
List<SampleDto> getByContactUuids(List<String> contactUuids);
70+
6971
boolean exists(String uuid);
7072
}

sormas-api/src/main/resources/captions.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1482,6 +1482,7 @@ Region.population=Population
14821482
Region.externalID=External ID
14831483

14841484
# Sample
1485+
sampleCreateNew=Create new sample
14851486
sampleIncludeTestOnCreation=Create test result for this sample now
14861487
sampleNewSample=New sample
14871488
sampleNoSamplesForCase=There are no samples for this case
@@ -1499,6 +1500,7 @@ sampleReferredShort=Referred
14991500
sampleReferredTo=Referred to
15001501
sampleReferredToInternal=Referred to internal sample
15011502
sampleSamplesList=Samples list
1503+
sampleSelect=Select sample
15021504
sampleShipped=Shipped
15031505
sampleSpecimenNotAdequate=Specimen not adequate
15041506
sampleActiveSamples=Active samples

sormas-api/src/main/resources/strings.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ headingPickOrCreateCase = Pick or Create a Case
416416
headingPickOrCreatePerson = Pick or create person
417417
headingPickOrCreateEvent = Pick or create event
418418
headingPickOrCreateEntry = Pick or create entry
419+
headingPickOrCreateSample = Pick or create sample
419420
headingPointOfEntryInformation = Point of entry information
420421
headingPrescriptionsDeleted = Prescriptions deleted
421422
headingReferSample = Refer sample to another laboratory
@@ -540,6 +541,7 @@ infoCaseIncidenceIncompatible = No population data is available for communities
540541
infoNoPathogenTests = No pathogen tests have been created for this sample
541542
infoPickOrCreateCase = There are existing cases in the database that seem very similar to the one you are about to create. Please have a look at the list of existing cases and verify that the case you want to create is not a duplicate of one of them. If you find a case that is most likely the same as yours, please <b>click on it in the list</b> and confirm.
542543
infoPickOrCreateCaseNewCase = Newly added case information
544+
infoPickOrCreateSample = The database already contains at least one sample that seems to be very similar to the details of the lab message.<br/><br/>Please look through the lists of samples. If you feel certain that one matches the lab message details, select it and click on the <i>Save</i> button. Otherwise, click on <i>Create new sample</i> to create a new sample for the entry.<br/><br/>If you are unsure, you can discard this window and cancel the process.
543545
infoSampleAdditionalTesting = Please tick every type of additional test you would like to be performed on this sample.
544546
infoSampleExport = Export the samples of all cases displayed in the table rows with an extended set of columns. This may take a while.
545547
infoSamplePathogenTesting = Please tick every type of pathogen test you would like to be performed on this sample.

sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleFacadeEjb.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,12 @@ public List<SampleDto> getByCaseUuids(List<String> caseUuids) {
210210
return sampleService.getByCaseUuids(caseUuids).stream().map(c -> convertToDto(c, pseudonymizer)).collect(Collectors.toList());
211211
}
212212

213+
@Override
214+
public List<SampleDto> getByContactUuids(List<String> contactUuids) {
215+
Pseudonymizer pseudonymizer = Pseudonymizer.getDefault(userService::hasRight);
216+
return sampleService.getByContactUuids(contactUuids).stream().map(c -> convertToDto(c, pseudonymizer)).collect(Collectors.toList());
217+
}
218+
213219
@Override
214220
public boolean exists(String uuid) {
215221
return sampleService.exists(uuid);

sormas-backend/src/main/java/de/symeda/sormas/backend/sample/SampleService.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,19 @@ public List<Sample> getByCaseUuids(List<String> caseUuids) {
235235
return em.createQuery(cq).getResultList();
236236
}
237237

238+
public List<Sample> getByContactUuids(List<String> contactUuids) {
239+
240+
CriteriaBuilder cb = em.getCriteriaBuilder();
241+
CriteriaQuery<Sample> cq = cb.createQuery(Sample.class);
242+
Root<Sample> sampleRoot = cq.from(Sample.class);
243+
Join<Sample, Contact> contactJoin = sampleRoot.join(Sample.ASSOCIATED_CONTACT, JoinType.LEFT);
244+
245+
Predicate filter = cb.and(createDefaultFilter(cb, sampleRoot), contactJoin.get(AbstractDomainObject.UUID).in(contactUuids));
246+
247+
cq.where(filter);
248+
return em.createQuery(cq).getResultList();
249+
}
250+
238251
public Map<PathogenTestResultType, Long> getNewTestResultCountByResultType(List<Long> caseIds) {
239252

240253
if (CollectionUtils.isEmpty(caseIds)) {

sormas-ui/src/main/java/de/symeda/sormas/ui/labmessage/LabMessageController.java

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package de.symeda.sormas.ui.labmessage;
22

3+
import java.util.Arrays;
34
import java.util.List;
45

56
import com.vaadin.server.Sizeable;
@@ -28,14 +29,17 @@
2829
import de.symeda.sormas.api.labmessage.SimilarEntriesDto;
2930
import de.symeda.sormas.api.person.PersonDto;
3031
import de.symeda.sormas.api.sample.PathogenTestDto;
32+
import de.symeda.sormas.api.sample.SampleCriteria;
3133
import de.symeda.sormas.api.sample.SampleDto;
34+
import de.symeda.sormas.api.utils.pseudonymization.PseudonymizableDto;
3235
import de.symeda.sormas.ui.ControllerProvider;
3336
import de.symeda.sormas.ui.SormasUI;
3437
import de.symeda.sormas.ui.UserProvider;
3538
import de.symeda.sormas.ui.caze.CaseCreateForm;
3639
import de.symeda.sormas.ui.contact.ContactCreateForm;
3740
import de.symeda.sormas.ui.samples.PathogenTestForm;
3841
import de.symeda.sormas.ui.samples.SampleCreateForm;
42+
import de.symeda.sormas.ui.samples.SampleSelectionField;
3943
import de.symeda.sormas.ui.utils.CommitDiscardWrapperComponent;
4044
import de.symeda.sormas.ui.utils.DateTimeField;
4145
import de.symeda.sormas.ui.utils.VaadinUiUtil;
@@ -112,6 +116,7 @@ private void pickOrCreateEntry(
112116
EntrySelectionField selectField = new EntrySelectionField(labMessageDto, cases, contacts, eventParticipants);
113117

114118
final CommitDiscardWrapperComponent<EntrySelectionField> selectionField = new CommitDiscardWrapperComponent<>(selectField);
119+
selectionField.getCommitButton().setCaption(I18nProperties.getCaption(Captions.actionConfirm));
115120
selectionField.setWidth(1280, Sizeable.Unit.PIXELS);
116121
selectionField.addCommitListener(() -> {
117122
SimilarEntriesDto similarEntriesDto = selectField.getValue();
@@ -120,9 +125,27 @@ private void pickOrCreateEntry(
120125
} else if (similarEntriesDto.isNewContact()) {
121126
createContact(labMessageDto, person);
122127
} else if (similarEntriesDto.getCaze() != null) {
123-
createSample(FacadeProvider.getCaseFacade().getCaseDataByUuid(similarEntriesDto.getCaze().getUuid()), labMessageDto);
128+
CaseDataDto caseDto = FacadeProvider.getCaseFacade().getCaseDataByUuid(similarEntriesDto.getCaze().getUuid());
129+
SampleCriteria criteria = new SampleCriteria();
130+
criteria.caze(caseDto.toReference());
131+
criteria.setDisease(caseDto.getDisease());
132+
List<SampleDto> samples = FacadeProvider.getSampleFacade().getByCaseUuids(Arrays.asList(caseDto.getUuid()));
133+
if (samples.isEmpty()) {
134+
createSample(caseDto, labMessageDto);
135+
} else {
136+
pickOrCreateSample(caseDto, labMessageDto, samples);
137+
}
124138
} else if (similarEntriesDto.getContact() != null) {
125-
createSample(FacadeProvider.getContactFacade().getContactByUuid(similarEntriesDto.getContact().getUuid()), labMessageDto);
139+
ContactDto contactDto = FacadeProvider.getContactFacade().getContactByUuid(similarEntriesDto.getContact().getUuid());
140+
SampleCriteria criteria = new SampleCriteria();
141+
criteria.contact(contactDto.toReference());
142+
criteria.setDisease(contactDto.getDisease());
143+
List<SampleDto> samples = FacadeProvider.getSampleFacade().getByContactUuids(Arrays.asList(contactDto.getUuid()));
144+
if (samples.isEmpty()) {
145+
createSample(contactDto, labMessageDto);
146+
} else {
147+
pickOrCreateSample(contactDto, labMessageDto, samples);
148+
}
126149
}
127150
});
128151

@@ -134,6 +157,34 @@ private void pickOrCreateEntry(
134157
VaadinUiUtil.showModalPopupWindow(selectionField, I18nProperties.getString(Strings.headingPickOrCreateEntry));
135158
}
136159

160+
private void pickOrCreateSample(PseudonymizableDto dto, LabMessageDto labMessageDto, List<SampleDto> samples) {
161+
SampleSelectionField selectField = new SampleSelectionField(samples, I18nProperties.getString(Strings.infoPickOrCreateSample));
162+
163+
Window window = VaadinUiUtil.createPopupWindow();
164+
165+
final CommitDiscardWrapperComponent<EntrySelectionField> selectionField = new CommitDiscardWrapperComponent(selectField);
166+
selectionField.getCommitButton().setCaption(I18nProperties.getCaption(Captions.actionConfirm));
167+
selectionField.setWidth(1280, Sizeable.Unit.PIXELS);
168+
selectionField.addCommitListener(() -> {
169+
SampleDto sampleDto = selectField.getValue();
170+
if (sampleDto != null) {
171+
createPathogenTest(sampleDto, labMessageDto);
172+
} else if (CaseDataDto.class.equals(dto.getClass())) {
173+
createSample((CaseDataDto) dto, labMessageDto);
174+
} else if (ContactDto.class.equals(dto.getClass())) {
175+
createSample((ContactDto) dto, labMessageDto);
176+
}
177+
window.close();
178+
});
179+
selectField.setSelectionChangeCallback((commitAllowed) -> {
180+
selectionField.getCommitButton().setEnabled(commitAllowed);
181+
});
182+
selectionField.getCommitButton().setEnabled(false);
183+
selectionField.addDiscardListener(() -> window.close());
184+
185+
showFormWithLabMessage(labMessageDto, selectionField, window, I18nProperties.getString(Strings.headingPickOrCreateSample));
186+
}
187+
137188
private void createCase(LabMessageDto labMessageDto, PersonDto person) {
138189
CommitDiscardWrapperComponent<CaseCreateForm> caseCreateComponent =
139190
ControllerProvider.getCaseController().getCaseCreateComponent(null, null, null, true);
@@ -161,7 +212,7 @@ private void createCase(LabMessageDto labMessageDto, PersonDto person) {
161212
caseCreateComponent.getWrappedComponent().setValue(caseDto);
162213
caseCreateComponent.getWrappedComponent().setPerson(person);
163214

164-
showCreateForm(labMessageDto, caseCreateComponent, window, I18nProperties.getString(Strings.headingCreateNewCase));
215+
showFormWithLabMessage(labMessageDto, caseCreateComponent, window, I18nProperties.getString(Strings.headingCreateNewCase));
165216
}
166217

167218
private void createContact(LabMessageDto labMessageDto, PersonDto person) {
@@ -191,12 +242,13 @@ private void createContact(LabMessageDto labMessageDto, PersonDto person) {
191242
contactCreateComponent.getWrappedComponent().setValue(contactDto);
192243
contactCreateComponent.getWrappedComponent().setPerson(person);
193244

194-
showCreateForm(labMessageDto, contactCreateComponent, window, I18nProperties.getString(Strings.headingCreateNewContact));
245+
showFormWithLabMessage(labMessageDto, contactCreateComponent, window, I18nProperties.getString(Strings.headingCreateNewContact));
195246
}
196247

197-
private void showCreateForm(LabMessageDto labMessageDto, CommitDiscardWrapperComponent createComponent, Window window, String heading) {
248+
private void showFormWithLabMessage(LabMessageDto labMessageDto, CommitDiscardWrapperComponent createComponent, Window window, String heading) {
198249
LabMessageEditForm form = new LabMessageEditForm(true);
199250
form.setValue(labMessageDto);
251+
form.setWidth(550, Sizeable.Unit.PIXELS);
200252
HorizontalLayout layout = new HorizontalLayout(form, createComponent);
201253
layout.setMargin(true);
202254
window.setContent(layout);
@@ -252,7 +304,7 @@ private void createSample(SampleDto sampleDto, LabMessageDto labMessageDto) {
252304
});
253305
sampleCreateComponent.addDiscardListener(() -> window.close());
254306

255-
showCreateForm(labMessageDto, sampleCreateComponent, window, I18nProperties.getString(Strings.headingCreateNewSample));
307+
showFormWithLabMessage(labMessageDto, sampleCreateComponent, window, I18nProperties.getString(Strings.headingCreateNewSample));
256308
}
257309

258310
private void createPathogenTest(SampleDto sampleDto, LabMessageDto labMessageDto) {
@@ -274,6 +326,6 @@ private void createPathogenTest(SampleDto sampleDto, LabMessageDto labMessageDto
274326
pathogenTestCreateComponent.addDiscardListener(() -> window.close());
275327
pathogenTestCreateComponent.getWrappedComponent().setValue(pathogenTestDto);
276328

277-
showCreateForm(labMessageDto, pathogenTestCreateComponent, window, I18nProperties.getString(Strings.headingCreatePathogenTestResult));
329+
showFormWithLabMessage(labMessageDto, pathogenTestCreateComponent, window, I18nProperties.getString(Strings.headingCreatePathogenTestResult));
278330
}
279331
}

sormas-ui/src/main/java/de/symeda/sormas/ui/labmessage/LabMessageEditForm.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,10 @@ public class LabMessageEditForm extends AbstractEditForm<LabMessageDto> {
2121
private final boolean readOnly;
2222
private Label labMessageDetails;
2323

24-
public LabMessageEditForm() {
25-
this(false);
26-
}
27-
2824
public LabMessageEditForm(boolean readOnly) {
2925

3026
super(LabMessageDto.class, LabMessageDto.I18N_PREFIX);
3127

32-
setWidth(800, Unit.PIXELS);
33-
3428
this.readOnly = readOnly;
3529
}
3630

sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonController.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import de.symeda.sormas.api.FacadeProvider;
3131
import de.symeda.sormas.api.caze.CaseClassification;
3232
import de.symeda.sormas.api.caze.CaseDataDto;
33+
import de.symeda.sormas.api.i18n.Captions;
3334
import de.symeda.sormas.api.i18n.I18nProperties;
3435
import de.symeda.sormas.api.i18n.Strings;
3536
import de.symeda.sormas.api.person.PersonContext;
@@ -62,6 +63,9 @@ public void selectOrCreatePerson(final PersonDto person, String infoText, Consum
6263
// TODO add user right parameter
6364
final CommitDiscardWrapperComponent<PersonSelectionField> component =
6465
new CommitDiscardWrapperComponent<PersonSelectionField>(personSelect);
66+
if (!saveNewPerson) {
67+
component.getCommitButton().setCaption(I18nProperties.getCaption(Captions.actionConfirm));
68+
}
6569
component.addCommitListener(new CommitListener() {
6670

6771
@Override

0 commit comments

Comments
 (0)