diff --git a/backend/src/main/java/gov/cdc/usds/simplereport/api/model/filerow/TestResultRow.java b/backend/src/main/java/gov/cdc/usds/simplereport/api/model/filerow/TestResultRow.java index dfc0617e1d..2405e12028 100644 --- a/backend/src/main/java/gov/cdc/usds/simplereport/api/model/filerow/TestResultRow.java +++ b/backend/src/main/java/gov/cdc/usds/simplereport/api/model/filerow/TestResultRow.java @@ -502,6 +502,18 @@ private boolean isSyphilisResult() { equipmentModelName.getValue(), testPerformedCode.getValue())); } + private boolean isHepatitisCResult() { + if (equipmentModelName.getValue() == null || testPerformedCode.getValue() == null) { + return false; + } + + return resultsUploaderCachingService + .getHepatitisCEquipmentModelAndTestPerformedCodeSet() + .contains( + ResultsUploaderCachingService.getKey( + equipmentModelName.getValue(), testPerformedCode.getValue())); + } + private List generateInvalidDataErrorMessages() { String errorMessage = "Invalid " + EQUIPMENT_MODEL_NAME + " and " + TEST_PERFORMED_CODE + " combination"; @@ -627,6 +639,14 @@ public List validateIndividualValues() { List.of(gendersOfSexualPartners, pregnant, syphilisHistory, symptomaticForDisease))); } + if (isHepatitisCResult()) { + errors.addAll( + validateRequiredFieldsForPositiveResult( + testResult, + DiseaseService.HEPATITIS_C_NAME, + List.of(gendersOfSexualPartners, pregnant, symptomaticForDisease))); + } + return errors; } } diff --git a/backend/src/main/java/gov/cdc/usds/simplereport/config/CachingConfig.java b/backend/src/main/java/gov/cdc/usds/simplereport/config/CachingConfig.java index 051b1591dc..e10cd493f7 100644 --- a/backend/src/main/java/gov/cdc/usds/simplereport/config/CachingConfig.java +++ b/backend/src/main/java/gov/cdc/usds/simplereport/config/CachingConfig.java @@ -12,6 +12,8 @@ public class CachingConfig { public static final String COVID_EQUIPMENT_MODEL_AND_TEST_PERFORMED_CODE_SET = "covidEquipmentModelAndTestPerformedCodeSet"; + public static final String HEPATITIS_C_EQUIPMENT_MODEL_AND_TEST_PERFORMED_CODE_SET = + "hepatitisCEquipmentModelAndTestPerformedCodeSet"; public static final String HIV_EQUIPMENT_MODEL_AND_TEST_PERFORMED_CODE_SET = "hivEquipmentModelAndTestPerformedCodeSet"; public static final String SYPHILIS_EQUIPMENT_MODEL_AND_TEST_PERFORMED_CODE_SET = @@ -27,6 +29,7 @@ public class CachingConfig { public CacheManager cacheManager() { return new ConcurrentMapCacheManager( COVID_EQUIPMENT_MODEL_AND_TEST_PERFORMED_CODE_SET, + HEPATITIS_C_EQUIPMENT_MODEL_AND_TEST_PERFORMED_CODE_SET, HIV_EQUIPMENT_MODEL_AND_TEST_PERFORMED_CODE_SET, SYPHILIS_EQUIPMENT_MODEL_AND_TEST_PERFORMED_CODE_SET, DEVICE_MODEL_AND_TEST_PERFORMED_CODE_MAP, diff --git a/backend/src/main/java/gov/cdc/usds/simplereport/service/DiseaseService.java b/backend/src/main/java/gov/cdc/usds/simplereport/service/DiseaseService.java index 8f88368197..98c916a09e 100644 --- a/backend/src/main/java/gov/cdc/usds/simplereport/service/DiseaseService.java +++ b/backend/src/main/java/gov/cdc/usds/simplereport/service/DiseaseService.java @@ -21,6 +21,7 @@ public class DiseaseService { public static final String FLU_B_NAME = "Flu B"; public static final String FLU_A_AND_B_NAME = "Flu A and B"; public static final String FLU_RNA_NAME = "Flu RNA"; + public static final String HEPATITIS_C_NAME = "Hepatitis C"; public static final String RSV_NAME = "RSV"; public static final String HIV_NAME = "HIV"; public static final String SYPHILIS_NAME = "Syphilis"; @@ -60,6 +61,10 @@ public SupportedDisease fluB() { return getDiseaseByName(FLU_B_NAME); } + public SupportedDisease hepatitisC() { + return getDiseaseByName(HEPATITIS_C_NAME); + } + public SupportedDisease rsv() { return getDiseaseByName(RSV_NAME); } diff --git a/backend/src/main/java/gov/cdc/usds/simplereport/service/ResultsUploaderCachingService.java b/backend/src/main/java/gov/cdc/usds/simplereport/service/ResultsUploaderCachingService.java index 80bf60deb2..1ec1fb37cd 100644 --- a/backend/src/main/java/gov/cdc/usds/simplereport/service/ResultsUploaderCachingService.java +++ b/backend/src/main/java/gov/cdc/usds/simplereport/service/ResultsUploaderCachingService.java @@ -3,6 +3,7 @@ import static gov.cdc.usds.simplereport.config.CachingConfig.ADDRESS_TIMEZONE_LOOKUP_MAP; import static gov.cdc.usds.simplereport.config.CachingConfig.COVID_EQUIPMENT_MODEL_AND_TEST_PERFORMED_CODE_SET; import static gov.cdc.usds.simplereport.config.CachingConfig.DEVICE_MODEL_AND_TEST_PERFORMED_CODE_MAP; +import static gov.cdc.usds.simplereport.config.CachingConfig.HEPATITIS_C_EQUIPMENT_MODEL_AND_TEST_PERFORMED_CODE_SET; import static gov.cdc.usds.simplereport.config.CachingConfig.HIV_EQUIPMENT_MODEL_AND_TEST_PERFORMED_CODE_SET; import static gov.cdc.usds.simplereport.config.CachingConfig.SNOMED_TO_SPECIMEN_NAME_MAP; import static gov.cdc.usds.simplereport.config.CachingConfig.SPECIMEN_NAME_TO_SNOMED_MAP; @@ -163,6 +164,12 @@ public Set getCovidEquipmentModelAndTestPerformedCodeSet() { return getDiseaseSpecificEquipmentModelAndTestPerformedCodeSet(DiseaseService.COVID19_NAME); } + @Cacheable(HEPATITIS_C_EQUIPMENT_MODEL_AND_TEST_PERFORMED_CODE_SET) + public Set getHepatitisCEquipmentModelAndTestPerformedCodeSet() { + log.info("generating hepatitisCEquipmentModelAndTestPerformedCodeSet cache"); + return getDiseaseSpecificEquipmentModelAndTestPerformedCodeSet(DiseaseService.HEPATITIS_C_NAME); + } + @Scheduled(fixedRate = 1, timeUnit = TimeUnit.HOURS) @Caching( evict = { @@ -183,6 +190,18 @@ public void cacheHivEquipmentModelAndTestPerformedCodeSet() { getHivEquipmentModelAndTestPerformedCodeSet(); } + @Scheduled(fixedRate = 1, timeUnit = TimeUnit.HOURS) + @Caching( + evict = { + @CacheEvict( + value = HEPATITIS_C_EQUIPMENT_MODEL_AND_TEST_PERFORMED_CODE_SET, + allEntries = true) + }) + public void cacheHepatitisCEquipmentModelAndTestPerformedCodeSet() { + log.info("clear and generate hepatitisCEquipmentModelAndTestPerformedCodeSet cache"); + getHepatitisCEquipmentModelAndTestPerformedCodeSet(); + } + @Cacheable(SNOMED_TO_SPECIMEN_NAME_MAP) public Map getSNOMEDToSpecimenTypeNameMap() { log.info("generating SNOMEDToSpecimenTypeNameMap cache"); diff --git a/backend/src/test/java/gov/cdc/usds/simplereport/service/DiseaseServiceTest.java b/backend/src/test/java/gov/cdc/usds/simplereport/service/DiseaseServiceTest.java index afc26533b9..dea8300424 100644 --- a/backend/src/test/java/gov/cdc/usds/simplereport/service/DiseaseServiceTest.java +++ b/backend/src/test/java/gov/cdc/usds/simplereport/service/DiseaseServiceTest.java @@ -58,6 +58,13 @@ void getFluB_successful() { assertEquals("Flu B", _service.fluB().getName()); } + @Test + void getHepatitisC_successful() { + SupportedDisease hepC = _service.hepatitisC(); + assertNotNull(hepC); + assertEquals(DiseaseService.HEPATITIS_C_NAME, hepC.getName()); + } + @Test void getByName_successful() { SupportedDisease covidByName = _service.getDiseaseByName(COVID19_NAME); @@ -77,7 +84,9 @@ void getSupportedDiseasesMap_successful() { .containsEntry(_service.covid().getInternalId(), _service.covid()) .containsEntry(_service.fluA().getInternalId(), _service.fluA()) .containsEntry(_service.fluB().getInternalId(), _service.fluB()) - .containsEntry(_service.rsv().getInternalId(), _service.rsv()); + .containsEntry(_service.rsv().getInternalId(), _service.rsv()) + .containsEntry(_service.hiv().getInternalId(), _service.hiv()) + .containsEntry(_service.hepatitisC().getInternalId(), _service.hepatitisC()); } @Test @@ -90,6 +99,8 @@ void getSupportedDiseasesList_successful() { .contains(_service.covid()) .contains(_service.fluA()) .contains(_service.fluB()) - .contains(_service.rsv()); + .contains(_service.rsv()) + .contains(_service.hiv()) + .contains(_service.hepatitisC()); } } diff --git a/backend/src/test/java/gov/cdc/usds/simplereport/validators/TestResultRowTest.java b/backend/src/test/java/gov/cdc/usds/simplereport/validators/TestResultRowTest.java index 50dd28244a..2de94c9468 100644 --- a/backend/src/test/java/gov/cdc/usds/simplereport/validators/TestResultRowTest.java +++ b/backend/src/test/java/gov/cdc/usds/simplereport/validators/TestResultRowTest.java @@ -17,6 +17,7 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -432,11 +433,8 @@ void validateIndividualFields() { @Test void validatePositiveHivRequiredAoeFields() { - var missingHivRequiredAoeFields = validRowMap; - missingHivRequiredAoeFields.put("equipment_model_name", "HIV model"); - missingHivRequiredAoeFields.put("test_performed_code", "80387-4"); - missingHivRequiredAoeFields.put("specimen_type", "123456789"); - missingHivRequiredAoeFields.put("test_result", "Detected"); + Map missingHivRequiredAoeFields = + getPositiveResultRowMap("HIV model", "80387-4"); missingHivRequiredAoeFields.put("pregnant", ""); missingHivRequiredAoeFields.put("genders_of_sexual_partners", ""); @@ -463,11 +461,8 @@ void validatePositiveHivRequiredAoeFields() { @Test void validatePositiveSyphilisRequiredAoeFields() { - var missingSyphilisRequiredAoeFields = validRowMap; - missingSyphilisRequiredAoeFields.put("equipment_model_name", "Syphilis model"); - missingSyphilisRequiredAoeFields.put("test_performed_code", "80387-4"); - missingSyphilisRequiredAoeFields.put("specimen_type", "123456789"); - missingSyphilisRequiredAoeFields.put("test_result", "Detected"); + Map missingSyphilisRequiredAoeFields = + getPositiveResultRowMap("Syphilis model", "80387-4"); missingSyphilisRequiredAoeFields.put("pregnant", ""); missingSyphilisRequiredAoeFields.put("genders_of_sexual_partners", ""); missingSyphilisRequiredAoeFields.put("previous_syphilis_diagnosis", ""); @@ -495,6 +490,48 @@ void validatePositiveSyphilisRequiredAoeFields() { "This is required because the row contains a positive Syphilis test result.")); } + @Test + void validatePositiveHepatitisCRequiredAoeFields() { + Map missingHepCRequiredAoeFields = + getPositiveResultRowMap("Hepatitis C Model", "40726-2"); + missingHepCRequiredAoeFields.put("pregnant", ""); + missingHepCRequiredAoeFields.put("genders_of_sexual_partners", ""); + missingHepCRequiredAoeFields.put("symptomatic_for_disease", ""); + + ResultsUploaderCachingService resultsUploaderCachingService = + mock(ResultsUploaderCachingService.class); + when(resultsUploaderCachingService.getModelAndTestPerformedCodeToDeviceMap()) + .thenReturn(Map.of("hepatitis c model|40726-2", TestDataBuilder.createDeviceType())); + when(resultsUploaderCachingService.getHepatitisCEquipmentModelAndTestPerformedCodeSet()) + .thenReturn(Set.of("hepatitis c model|40726-2")); + + TestResultRow testResultRow = + new TestResultRow( + missingHepCRequiredAoeFields, + resultsUploaderCachingService, + mock(FeatureFlagsConfig.class)); + + List actual = testResultRow.validateIndividualValues(); + + assertThat(actual).hasSize(3); + actual.forEach( + message -> + assertThat(message.getMessage()) + .contains( + "This is required because the row contains a positive Hepatitis C test result.")); + } + + @NotNull + private Map getPositiveResultRowMap( + String deviceModelName, String testPerformedCode) { + Map positiveResultRowMap = validRowMap; + positiveResultRowMap.put("equipment_model_name", deviceModelName); + positiveResultRowMap.put("test_performed_code", testPerformedCode); + positiveResultRowMap.put("specimen_type", "123456789"); + positiveResultRowMap.put("test_result", "Detected"); + return positiveResultRowMap; + } + private ResultsUploaderCachingService mockResultsUploaderCachingService() { var resultsUploaderCachingService = mock(ResultsUploaderCachingService.class); when(resultsUploaderCachingService.getModelAndTestPerformedCodeToDeviceMap())