Skip to content

Commit f27172d

Browse files
committed
#13793 - Disabled classification popup for pathogen tests that are negative
The behaviour was introduced it seems by a requirement to display the case classification popup for verified pathogen tests (positive and negative). While the behaviour might have beed desired, the actual logic in the code and popup text is not. The popup text and the logic in other blocks of the code lead us to the conclusion that only positive results trigger the popup.
1 parent fcb1f01 commit f27172d

1 file changed

Lines changed: 79 additions & 28 deletions

File tree

sormas-ui/src/main/java/de/symeda/sormas/ui/samples/PathogenTestController.java

Lines changed: 79 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,33 @@ public void savePathogenTests(List<PathogenTestDto> pathogenTests, SampleReferen
351351
TRAY_NOTIFICATION);
352352
}
353353

354+
/**
355+
* Handles the association of a pathogen test with a case.
356+
* Based on pathogen test results the following logic is applied:
357+
*
358+
* <p>Negative test result AND test result verified
359+
* <ol>
360+
* <li>Tested disease == case disease AND test result != sample pathogen test result: Ask user whether to update the sample pathogen test result</li>
361+
* <li>Tested disease != case disease: Do nothing</li>
362+
* </ol>
363+
* </p>
364+
* <p>Positive test result AND test result verified
365+
* <ol>
366+
* <li>Tested disease == case disease: Ask user whether to update the sample pathogen test result
367+
* <ol>
368+
* <li>Tested disease variant != case disease variant: Ask user to change the case disease variant</li>
369+
* <li>Case classification != confirmed: Ask user whether to confirm the case</li>
370+
* </ol>
371+
* </li>
372+
* <li>Tested disease != case disease: Ask user to create a new case for the tested disease</li>
373+
* </ol>
374+
* </p>
375+
*
376+
* @param pathogenTests the pathogen tests
377+
* @param associatedCase the associated case
378+
* @param suppressNavigateToCase whether to suppress navigation to the case
379+
*
380+
*/
354381
private void handleAssociatedCase(List<PathogenTestDto> pathogenTests, CaseReferenceDto associatedCase, boolean suppressNavigateToCase) {
355382

356383
if (!UiUtil.permitted(UserRight.CASE_EDIT)) {
@@ -367,46 +394,68 @@ private void handleAssociatedCase(List<PathogenTestDto> pathogenTests, CaseRefer
367394
// a.2) Case classification != confirmed: Ask user whether to confirm the case
368395
// b) Tested disease != case disease: Ask user to create a new case for the tested disease
369396

370-
CaseDataDto caze = FacadeProvider.getCaseFacade().getCaseDataByUuid(associatedCase.getUuid());
397+
final CaseDataDto caze = FacadeProvider.getCaseFacade().getCaseDataByUuid(associatedCase.getUuid());
371398

372-
Map<Disease, List<PathogenTestDto>> testsByDisease = pathogenTests.stream().collect(Collectors.groupingBy(PathogenTestDto::getTestedDisease));
373-
Optional<PathogenTestDto> positiveWithSameDisease = testsByDisease.getOrDefault(caze.getDisease(), Collections.emptyList())
399+
final Map<Disease, List<PathogenTestDto>> testsByDisease =
400+
pathogenTests.stream().collect(Collectors.groupingBy(PathogenTestDto::getTestedDisease));
401+
final Optional<PathogenTestDto> positiveWithSameDisease = testsByDisease.getOrDefault(caze.getDisease(), Collections.emptyList())
374402
.stream()
375403
.filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && Boolean.TRUE.equals(t.getTestResultVerified()))
376404
.findFirst();
377405

378-
Optional<PathogenTestDto> negativeWithSameDisease = testsByDisease.getOrDefault(caze.getDisease(), Collections.emptyList())
406+
final Optional<PathogenTestDto> negativeWithSameDisease = testsByDisease.getOrDefault(caze.getDisease(), Collections.emptyList())
379407
.stream()
380408
.filter(t -> t.getTestResult() == PathogenTestResultType.NEGATIVE && Boolean.TRUE.equals(t.getTestResultVerified()))
381409
.findFirst();
382410

383-
PathogenTestDto resultedPathogenTest;
384-
if (positiveWithSameDisease.isPresent()) {
385-
resultedPathogenTest = positiveWithSameDisease.get();
386-
} else if (negativeWithSameDisease.isPresent()) {
387-
resultedPathogenTest = negativeWithSameDisease.get();
388-
} else {
389-
resultedPathogenTest = null;
390-
}
411+
final boolean hasVerifiedPositiveTest = positiveWithSameDisease.isPresent();
412+
final boolean hasVerifiedNegativeTest = negativeWithSameDisease.isPresent();
413+
414+
final boolean hasVerifiedTests = hasVerifiedPositiveTest || hasVerifiedNegativeTest;
415+
416+
417+
// 1. Ask user to update sample overall result if latest test result is different
418+
// 2. Ask user to update disease variant if case variant is different
419+
// 3. Ask user if they want to confirm the case only if any of the tests are verified either positive or negative (not pending or other)
420+
421+
// We need to display popups if any of the tests are verified either positive or negative
422+
if (hasVerifiedTests) {
423+
// get either the positive or negative test
424+
final PathogenTestDto resultedPathogenTest = hasVerifiedPositiveTest ? positiveWithSameDisease.get() : negativeWithSameDisease.get();
425+
426+
// just a sanity check
427+
if (resultedPathogenTest == null) {
428+
throw new IllegalStateException("No verified test found for disease " + caze.getDisease());
429+
}
391430

392-
if (resultedPathogenTest != null) {
393-
showChangeAssociatedSampleResultDialog(resultedPathogenTest, (accepted) -> {
394-
if (accepted) {
395-
checkForDiseaseVariantUpdate(resultedPathogenTest, caze, suppressNavigateToCase, this::showConfirmCaseDialog);
431+
showChangeAssociatedSampleResultDialog(resultedPathogenTest, accepted -> { // Change sample result
432+
// Accepted SR may have changed
433+
if (Boolean.TRUE.equals(accepted)) {
434+
checkForDiseaseVariantUpdate(resultedPathogenTest, caze, suppressNavigateToCase, c -> { // Update disease variant
435+
// Only show the confirmation dialog if there are verified positive tests
436+
// We decided this based on the intented text in the dialog but based on the test results instead of the sample overall result
437+
if (hasVerifiedPositiveTest) {
438+
// The final laboratory result of the sample the saved pathogen test belongs to is positive. <-- sample overall result
439+
// However, the case cannot be automatically classified as a confirmed case because it is missing some information.
440+
// Do you want to set the case classification to confirmed anyway?
441+
this.showConfirmCaseDialog(c); // Case classification
442+
}
443+
});
396444
}
397445
});
398446
}
399447

400448
testsByDisease.keySet().stream().filter(disease -> disease != caze.getDisease()).forEach((disease) -> {
401449
List<PathogenTestDto> tests = testsByDisease.get(disease);
402450

403-
Optional<PathogenTestDto> positiveWithOtherDisease =
404-
tests.stream().filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && Boolean.TRUE.equals(t.getTestResultVerified())).findFirst();
451+
Optional<PathogenTestDto> positiveWithOtherDisease = tests.stream()
452+
.filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && Boolean.TRUE.equals(t.getTestResultVerified()))
453+
.findFirst();
405454

406455
if (positiveWithOtherDisease.isPresent()) {
407456
List<CaseDataDto> duplicatedCases =
408457
FacadeProvider.getCaseFacade().getDuplicatesWithPathogenTest(caze.getPerson(), positiveWithOtherDisease.get());
409-
if (duplicatedCases == null || duplicatedCases.size() == 0) {
458+
if (duplicatedCases == null || duplicatedCases.isEmpty()) {
410459
PathogenTestDto positiveTestWithOtherDisease = positiveWithOtherDisease.get();
411460

412461
showCaseCloningWithNewDiseaseDialog(
@@ -466,8 +515,9 @@ private void handleAssociatedContact(List<PathogenTestDto> pathogenTests, Contac
466515
testsByDisease.keySet().stream().filter(disease -> disease != contact.getDisease()).forEach((disease) -> {
467516
List<PathogenTestDto> tests = testsByDisease.get(disease);
468517

469-
Optional<PathogenTestDto> positiveWithOtherDisease =
470-
tests.stream().filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && Boolean.TRUE.equals(t.getTestResultVerified())).findFirst();
518+
Optional<PathogenTestDto> positiveWithOtherDisease = tests.stream()
519+
.filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && Boolean.TRUE.equals(t.getTestResultVerified()))
520+
.findFirst();
471521
if (positiveWithOtherDisease.isPresent()) {
472522
List<CaseDataDto> duplicatedCases =
473523
FacadeProvider.getCaseFacade().getDuplicatesWithPathogenTest(contact.getPerson(), positiveWithOtherDisease.get());
@@ -530,8 +580,9 @@ private void handleAssociatedEventParticipant(List<PathogenTestDto> pathogenTest
530580
testsByDisease.keySet().stream().filter(disease -> disease != eventDisease).forEach((disease) -> {
531581
List<PathogenTestDto> tests = testsByDisease.get(disease);
532582

533-
Optional<PathogenTestDto> positiveWithOtherDisease =
534-
tests.stream().filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && Boolean.TRUE.equals(t.getTestResultVerified())).findFirst();
583+
Optional<PathogenTestDto> positiveWithOtherDisease = tests.stream()
584+
.filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && Boolean.TRUE.equals(t.getTestResultVerified()))
585+
.findFirst();
535586
if (positiveWithOtherDisease.isPresent() && UiUtil.enabled(FeatureType.CASE_SURVEILANCE)) {
536587
List<CaseDataDto> duplicatedCases = FacadeProvider.getCaseFacade()
537588
.getDuplicatesWithPathogenTest(eventParticipant.getPerson().toReference(), positiveWithOtherDisease.get());
@@ -616,7 +667,7 @@ public void showConvertEventParticipantToCaseDialog(EventParticipantDto eventPar
616667
I18nProperties.getString(Strings.no),
617668
800,
618669
confirmed -> {
619-
if (confirmed) {
670+
if (Boolean.TRUE.equals(confirmed)) {
620671
if (differentDiseases) {
621672
ControllerProvider.getCaseController().createFromEventParticipantDifferentDisease(eventParticipant, testedDisease);
622673
} else {
@@ -635,7 +686,7 @@ public void showConvertContactToCaseDialog(ContactDto contact, Consumer<Boolean>
635686
I18nProperties.getString(Strings.no),
636687
800,
637688
confirmed -> {
638-
if (confirmed) {
689+
if (Boolean.TRUE.equals(confirmed)) {
639690
ControllerProvider.getCaseController().createFromContact(contact);
640691
}
641692
callback.accept(confirmed);
@@ -650,7 +701,7 @@ public void showCreateContactCaseDialog(ContactDto contact, Disease disease) {
650701
I18nProperties.getString(Strings.no),
651702
800,
652703
confirmed -> {
653-
if (confirmed) {
704+
if (Boolean.TRUE.equals(confirmed)) {
654705
ControllerProvider.getCaseController().createFromUnrelatedContact(contact, disease);
655706
}
656707
});
@@ -670,7 +721,7 @@ public static void showCaseCloningWithNewDiseaseDialog(
670721
I18nProperties.getString(Strings.no),
671722
800,
672723
confirmed -> {
673-
if (confirmed) {
724+
if (Boolean.TRUE.equals(confirmed)) {
674725
existingCaseDto.setCaseClassification(CaseClassification.NOT_CLASSIFIED);
675726
existingCaseDto.setClassificationUser(null);
676727
existingCaseDto.setDisease(disease);
@@ -702,7 +753,7 @@ public void showConfirmCaseDialog(CaseDataDto caze) {
702753
I18nProperties.getString(Strings.no),
703754
800,
704755
confirmed -> {
705-
if (confirmed) {
756+
if (Boolean.TRUE.equals(confirmed)) {
706757
CaseDataDto caseDataByUuid = FacadeProvider.getCaseFacade().getCaseDataByUuid(caze.getUuid());
707758
caseDataByUuid.setCaseClassification(CaseClassification.CONFIRMED);
708759
FacadeProvider.getCaseFacade().save(caseDataByUuid);

0 commit comments

Comments
 (0)