diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/sample/PathogenTestDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/sample/PathogenTestDto.java index 1b73b1df961..df46ffdb50f 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/sample/PathogenTestDto.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/sample/PathogenTestDto.java @@ -155,7 +155,6 @@ public class PathogenTestDto extends PseudonymizableDto { @SensitiveData @Size(max = FieldConstraints.CHARACTER_LIMIT_BIG, message = Validations.textTooLong) private String testResultText; - @NotNull(message = Validations.requiredField) private Boolean testResultVerified; private boolean fourFoldIncreaseAntibodyTiter; @SensitiveData diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/pathogentest/edit/PathogenTestEditActivity.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/pathogentest/edit/PathogenTestEditActivity.java index 9145a5023e3..880b2f68df5 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/pathogentest/edit/PathogenTestEditActivity.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/pathogentest/edit/PathogenTestEditActivity.java @@ -23,7 +23,6 @@ import android.os.AsyncTask; import android.util.Log; import android.view.Menu; - import de.symeda.sormas.api.disease.DiseaseVariant; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; @@ -100,7 +99,7 @@ public void saveData() { DiseaseVariant caseDiseaseVariant = associatedCase.getDiseaseVariant(); DiseaseVariant newDiseaseVariant = pathogenTestToSave.getTestedDiseaseVariant(); if (pathogenTestToSave.getTestResult() == PathogenTestResultType.POSITIVE - && pathogenTestToSave.getTestResultVerified() + && Boolean.TRUE.equals(pathogenTestToSave.getTestResultVerified()) && !DataHelper.equal(newDiseaseVariant, caseDiseaseVariant)) { String heading = I18nProperties.getString(Strings.headingUpdateCaseWithNewDiseaseVariant); @@ -155,7 +154,7 @@ protected void onPostExecute(AsyncTaskResult taskResult) { if (taskResult.getResultStatus().isSuccess()) { Sample sampleOfPathogenTestToSave = pathogenTestToSave.getSample(); if (sampleOfPathogenTestToSave != null - && Boolean.TRUE == pathogenTestToSave.getTestResultVerified() + && Boolean.TRUE.equals(pathogenTestToSave.getTestResultVerified()) && pathogenTestToSave.getTestedDisease() == associatedCase.getDisease() && pathogenTestToSave.getTestResult() != sampleOfPathogenTestToSave.getPathogenTestResult()) { final ConfirmationDialog confirmationDialog = new ConfirmationDialog( diff --git a/sormas-app/app/src/main/java/de/symeda/sormas/app/pathogentest/edit/PathogenTestNewActivity.java b/sormas-app/app/src/main/java/de/symeda/sormas/app/pathogentest/edit/PathogenTestNewActivity.java index 5d6690f763f..16f1d3c2dcd 100644 --- a/sormas-app/app/src/main/java/de/symeda/sormas/app/pathogentest/edit/PathogenTestNewActivity.java +++ b/sormas-app/app/src/main/java/de/symeda/sormas/app/pathogentest/edit/PathogenTestNewActivity.java @@ -156,7 +156,7 @@ public void saveData() { DiseaseVariant caseDiseaseVariant = associatedCase.getDiseaseVariant(); DiseaseVariant newDiseaseVariant = pathogenTestToSave.getTestedDiseaseVariant(); if (pathogenTestToSave.getTestResult() == PathogenTestResultType.POSITIVE - && pathogenTestToSave.getTestResultVerified() + && Boolean.TRUE.equals(pathogenTestToSave.getTestResultVerified()) && !DataHelper.equal(newDiseaseVariant, caseDiseaseVariant)) { String heading = I18nProperties.getString(Strings.headingUpdateCaseWithNewDiseaseVariant); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/PathogenTest.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/PathogenTest.java index 2793bc31116..c6184eab1e5 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/PathogenTest.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/PathogenTest.java @@ -366,7 +366,7 @@ public void setTestResultText(String testResultText) { this.testResultText = testResultText; } - @Column(nullable = false) + @Column public Boolean getTestResultVerified() { return testResultVerified; } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/PathogenTestFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/PathogenTestFacadeEjb.java index 0cdb7288b91..a3a8257ae30 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/PathogenTestFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/sample/PathogenTestFacadeEjb.java @@ -490,7 +490,8 @@ public void validate(PathogenTestDto pathogenTest) throws ValidationRuntimeExcep Validations.required, I18nProperties.getPrefixCaption(PathogenTestDto.I18N_PREFIX, PathogenTestDto.TEST_RESULT))); } - if (pathogenTest.getTestResultVerified() == null) { + // Validate testResultVerified is required when test comes via LIMS (laboratory is directly connected) + if (pathogenTest.isViaLims() && pathogenTest.getTestResultVerified() == null) { throw new ValidationRuntimeException( I18nProperties.getValidationError( Validations.required, diff --git a/sormas-backend/src/main/resources/sql/sormas_schema.sql b/sormas-backend/src/main/resources/sql/sormas_schema.sql index 3b941bd6e76..d9f7bbd2a51 100644 --- a/sormas-backend/src/main/resources/sql/sormas_schema.sql +++ b/sormas-backend/src/main/resources/sql/sormas_schema.sql @@ -15062,4 +15062,10 @@ ALTER TABLE testreport_history ADD COLUMN serotype character varying(255); ALTER TABLE testreport_history ADD COLUMN straincallstatus character varying(255); INSERT INTO schema_version (version_number, comment) VALUES (602, 'External message additional fields'); + +-- 2025-12-18 Make testResultVerified optional in pathogentest #13557 +ALTER TABLE pathogentest ALTER COLUMN testresultverified DROP NOT NULL; +ALTER TABLE pathogentest_history ALTER COLUMN testresultverified DROP NOT NULL; + +INSERT INTO schema_version (version_number, comment) VALUES (603, 'Make testResultVerified optional in pathogentest #13557'); -- *** Insert new sql commands BEFORE this line. Remember to always consider _history tables. *** diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/PathogenTestController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/PathogenTestController.java index 87c1aa6b0fd..e20473fbd3e 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/PathogenTestController.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/PathogenTestController.java @@ -372,12 +372,12 @@ private void handleAssociatedCase(List pathogenTests, CaseRefer Map> testsByDisease = pathogenTests.stream().collect(Collectors.groupingBy(PathogenTestDto::getTestedDisease)); Optional positiveWithSameDisease = testsByDisease.getOrDefault(caze.getDisease(), Collections.emptyList()) .stream() - .filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && t.getTestResultVerified()) + .filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && Boolean.TRUE.equals(t.getTestResultVerified())) .findFirst(); Optional negativeWithSameDisease = testsByDisease.getOrDefault(caze.getDisease(), Collections.emptyList()) .stream() - .filter(t -> t.getTestResult() == PathogenTestResultType.NEGATIVE && t.getTestResultVerified()) + .filter(t -> t.getTestResult() == PathogenTestResultType.NEGATIVE && Boolean.TRUE.equals(t.getTestResultVerified())) .findFirst(); PathogenTestDto resultedPathogenTest; @@ -401,7 +401,7 @@ private void handleAssociatedCase(List pathogenTests, CaseRefer List tests = testsByDisease.get(disease); Optional positiveWithOtherDisease = - tests.stream().filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && t.getTestResultVerified()).findFirst(); + tests.stream().filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && Boolean.TRUE.equals(t.getTestResultVerified())).findFirst(); if (positiveWithOtherDisease.isPresent()) { List duplicatedCases = @@ -441,12 +441,12 @@ private void handleAssociatedContact(List pathogenTests, Contac Map> testsByDisease = pathogenTests.stream().collect(Collectors.groupingBy(PathogenTestDto::getTestedDisease)); Optional positiveWithSameDisease = testsByDisease.getOrDefault(contact.getDisease(), Collections.emptyList()) .stream() - .filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && t.getTestResultVerified()) + .filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && Boolean.TRUE.equals(t.getTestResultVerified())) .findFirst(); Optional negativeWithSameDisease = testsByDisease.getOrDefault(contact.getDisease(), Collections.emptyList()) .stream() - .filter(t -> t.getTestResult() == PathogenTestResultType.NEGATIVE && t.getTestResultVerified()) + .filter(t -> t.getTestResult() == PathogenTestResultType.NEGATIVE && Boolean.TRUE.equals(t.getTestResultVerified())) .findFirst(); final boolean caseCreationPossible = UiUtil.permitted(FeatureType.CASE_SURVEILANCE, UserRight.CASE_CREATE); @@ -467,7 +467,7 @@ private void handleAssociatedContact(List pathogenTests, Contac List tests = testsByDisease.get(disease); Optional positiveWithOtherDisease = - tests.stream().filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && t.getTestResultVerified()).findFirst(); + tests.stream().filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && Boolean.TRUE.equals(t.getTestResultVerified())).findFirst(); if (positiveWithOtherDisease.isPresent()) { List duplicatedCases = FacadeProvider.getCaseFacade().getDuplicatesWithPathogenTest(contact.getPerson(), positiveWithOtherDisease.get()); @@ -504,12 +504,12 @@ private void handleAssociatedEventParticipant(List pathogenTest Map> testsByDisease = pathogenTests.stream().collect(Collectors.groupingBy(PathogenTestDto::getTestedDisease)); Optional positiveWithSameDisease = testsByDisease.getOrDefault(eventDisease, Collections.emptyList()) .stream() - .filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && t.getTestResultVerified()) + .filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && Boolean.TRUE.equals(t.getTestResultVerified())) .findFirst(); Optional negativeWithSameDisease = testsByDisease.getOrDefault(eventDisease, Collections.emptyList()) .stream() - .filter(t -> t.getTestResult() == PathogenTestResultType.NEGATIVE && t.getTestResultVerified()) + .filter(t -> t.getTestResult() == PathogenTestResultType.NEGATIVE && Boolean.TRUE.equals(t.getTestResultVerified())) .findFirst(); final boolean caseCreationPossible = UiUtil.permitted(FeatureType.CASE_SURVEILANCE, UserRight.CASE_CREATE); @@ -531,7 +531,7 @@ private void handleAssociatedEventParticipant(List pathogenTest List tests = testsByDisease.get(disease); Optional positiveWithOtherDisease = - tests.stream().filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && t.getTestResultVerified()).findFirst(); + tests.stream().filter(t -> t.getTestResult() == PathogenTestResultType.POSITIVE && Boolean.TRUE.equals(t.getTestResultVerified())).findFirst(); if (positiveWithOtherDisease.isPresent() && UiUtil.enabled(FeatureType.CASE_SURVEILANCE)) { List duplicatedCases = FacadeProvider.getCaseFacade() .getDuplicatesWithPathogenTest(eventParticipant.getPerson().toReference(), positiveWithOtherDisease.get()); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/PathogenTestForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/PathogenTestForm.java index 0b6414b28e0..c0eb6e660fa 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/PathogenTestForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/samples/PathogenTestForm.java @@ -429,7 +429,7 @@ protected void addFields() { getContent().addComponent(pathogenTestHeadingLabel, PATHOGEN_TEST_HEADING_LOC); addDateField(PathogenTestDto.REPORT_DATE, DateField.class, 0); - addField(PathogenTestDto.VIA_LIMS); + CheckBox viaLimsField = addField(PathogenTestDto.VIA_LIMS); addField(PathogenTestDto.EXTERNAL_ID); addField(PathogenTestDto.EXTERNAL_ORDER_ID); testTypeField = addField(PathogenTestDto.TEST_TYPE, ComboBox.class); @@ -951,9 +951,17 @@ protected void addFields() { PathogenTestDto.TUBE_MITOGENE_GT10); NullableOptionGroup testResultVerifiedField = addField(PathogenTestDto.TEST_RESULT_VERIFIED, NullableOptionGroup.class); - testResultVerifiedField.setRequired(true); addField(PathogenTestDto.PRELIMINARY).addStyleName(CssStyles.VSPACE_4); + // Make TEST_RESULT_VERIFIED required only when the test comes via LIMS (laboratory is directly connected) + viaLimsField.addValueChangeListener(e -> { + boolean isViaLims = Boolean.TRUE.equals(e.getProperty().getValue()); + testResultVerifiedField.setRequired(isViaLims); + }); + + // Set initial required state based on current viaLims value + testResultVerifiedField.setRequired(Boolean.TRUE.equals(viaLimsField.getValue())); + CheckBox fourFoldIncrease = addField(PathogenTestDto.FOUR_FOLD_INCREASE_ANTIBODY_TITER, CheckBox.class); CssStyles.style(fourFoldIncrease, VSPACE_3, VSPACE_TOP_4); fourFoldIncrease.setVisible(false);