Skip to content

Commit

Permalink
adding test ordered code to bulk upload api (#6166)
Browse files Browse the repository at this point in the history
* adding test ordered code to bulk upload api

* adding test ordered code to the bulk upload guide
  • Loading branch information
DanielSass authored Jul 25, 2023
1 parent 9def755 commit a3bc03f
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public class TestResultRow implements FileRow {
final ValueOrError orderingFacilityPhoneNumber;
final ValueOrError comment;
final ValueOrError testResultStatus;
final ValueOrError testOrderedCode;

static final String PATIENT_LAST_NAME = "patient_last_name";
static final String PATIENT_FIRST_NAME = "patient_first_name";
Expand Down Expand Up @@ -351,6 +352,7 @@ public TestResultRow(Map<String, String> rawRow) {
rawRow, "ordering_facility_phone_number", isRequired("ordering_facility_phone_number"));
comment = getValue(rawRow, "comment", isRequired("comment"));
testResultStatus = getValue(rawRow, "test_result_status", isRequired("test_result_status"));
testOrderedCode = getValue(rawRow, "test_ordered_code", isRequired("test_ordered_code"));
}

private List<FeedbackMessage> validateDeviceModelAndTestPerformedCode(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ private Bundle convertRowToFhirBundle(TestResultRow row, UUID orgId) {
String testKitNameId = null;
String manufacturer = null;
String diseaseName = null;
String testOrderLoinc = null;
String testOrderedCode = row.getTestOrderedCode().getValue();

UUID deviceId = uuidGenerator.randomUUID();
var testPerformedCode = row.getTestPerformedCode().getValue();
Expand Down Expand Up @@ -317,7 +317,10 @@ private Bundle convertRowToFhirBundle(TestResultRow row, UUID orgId) {
.map(SupportedDisease::getName)
.orElse(null);

testOrderLoinc = MultiplexUtils.inferMultiplexTestOrderLoinc(deviceTypeDiseaseEntries);
testOrderedCode =
StringUtils.isEmpty(testOrderedCode)
? MultiplexUtils.inferMultiplexTestOrderLoinc(deviceTypeDiseaseEntries)
: testOrderedCode;
} else {
log.info(
"No device found for model ("
Expand All @@ -327,6 +330,9 @@ private Bundle convertRowToFhirBundle(TestResultRow row, UUID orgId) {
+ ")");
}

// code was not passed via api or inferred above: defaulting to the test performed code.
testOrderedCode = StringUtils.isEmpty(testOrderedCode) ? testPerformedCode : testOrderedCode;

var device = fhirConverter.convertToDevice(manufacturer, modelName, deviceId.toString());

var specimen =
Expand Down Expand Up @@ -385,7 +391,7 @@ private Bundle convertRowToFhirBundle(TestResultRow row, UUID orgId) {
var serviceRequest =
fhirConverter.convertToServiceRequest(
ServiceRequest.ServiceRequestStatus.COMPLETED,
testOrderLoinc,
testOrderedCode,
uuidGenerator.randomUUID().toString(),
orderTestDate);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ void uploadService_processCsv_translatesSpecimenNameToSNOMED() {
var headerCount = Arrays.stream(rows[0].split(",")).toList().size();
var row = rows[1];

// if the last column is optional and empty/null this fails when it shouldn't
assertThat(row.split(",")).hasSize(headerCount);
assertThat(rows[1]).contains("000111222");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gov.cdc.usds.simplereport.utils;

import static gov.cdc.usds.simplereport.test_util.JsonTestUtils.assertJsonNodesEqual;
import static gov.cdc.usds.simplereport.validators.CsvValidatorUtils.getIteratorForCsv;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
Expand All @@ -17,6 +18,7 @@
import gov.cdc.usds.simplereport.service.ResultsUploaderCachingService;
import gov.cdc.usds.simplereport.test_util.TestDataBuilder;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
Expand All @@ -31,6 +33,7 @@
import org.hl7.fhir.r4.model.DiagnosticReport;
import org.hl7.fhir.r4.model.Observation;
import org.hl7.fhir.r4.model.Organization;
import org.hl7.fhir.r4.model.ServiceRequest;
import org.hl7.fhir.r4.model.Specimen;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
Expand Down Expand Up @@ -92,9 +95,77 @@ void convertExistingCsv_success() {
assertThat(resourceUrls).hasSize(14);
}

@Test
void allFieldsCsv_TestOrderedCodeMapped() throws IOException {
byte[] input = loadCsv("testResultUpload/test-results-upload-all-fields.csv").readAllBytes();

var serializedBundles =
sut.convertToFhirBundles(new ByteArrayInputStream(input), UUID.randomUUID());
var mappingIterator = getIteratorForCsv(new ByteArrayInputStream(input));

int index = 0;
while (mappingIterator.hasNext()) {
var csvRow = mappingIterator.next();
var inputOrderedCode = csvRow.get("test_ordered_code");
var inputPerformedCode = csvRow.get("test_performed_code");

var bundle = serializedBundles.get(index++);
var deserializedBundle = (Bundle) parser.parseResource(bundle);

var serviceRequestEntry =
deserializedBundle.getEntry().stream()
.filter(entry -> entry.getFullUrl().contains("ServiceRequest/"))
.findFirst()
.orElseThrow(
() -> new AssertionError("Expected to find ServiceRequest, but not found"));
var serviceRequest = (ServiceRequest) serviceRequestEntry.getResource();

var mappedCode = serviceRequest.getCode().getCoding().stream().findFirst().get().getCode();

// value is mapped
assertThat(mappedCode).isEqualTo(inputOrderedCode);
// value is not defaulted to performed code
assertThat(inputOrderedCode).isNotEqualTo(inputPerformedCode);
}
}

@Test
void validCsv_TestOrderedCodeDefaultedToPerformedCode() throws IOException {
byte[] input = loadCsv("testResultUpload/test-results-upload-valid.csv").readAllBytes();

var serializedBundles =
sut.convertToFhirBundles(new ByteArrayInputStream(input), UUID.randomUUID());
var mappingIterator = getIteratorForCsv(new ByteArrayInputStream(input));

int index = 0;
while (mappingIterator.hasNext()) {
var csvRow = mappingIterator.next();
var inputOrderedCode = csvRow.get("test_ordered_code");
var inputPerformedCode = csvRow.get("test_performed_code");

var bundle = serializedBundles.get(index++);
var deserializedBundle = (Bundle) parser.parseResource(bundle);

var serviceRequestEntry =
deserializedBundle.getEntry().stream()
.filter(entry -> entry.getFullUrl().contains("ServiceRequest/"))
.findFirst()
.orElseThrow(
() -> new AssertionError("Expected to find ServiceRequest, but not found"));
var serviceRequest = (ServiceRequest) serviceRequestEntry.getResource();

var mappedCode = serviceRequest.getCode().getCoding().stream().findFirst().get().getCode();

// when supplied orderedCode is empty
assertThat(inputOrderedCode).isEmpty();
// value is defaulted to performed code
assertThat(mappedCode).isEqualTo(inputPerformedCode);
}
}

@Test
void convertExistingCsv_aoeQuestionsMapped() {
InputStream input = loadCsv("testResultUpload/test-results-upload-aoe.csv");
InputStream input = loadCsv("testResultUpload/test-results-upload-all-fields.csv");
var serializedBundles = sut.convertToFhirBundles(input, UUID.randomUUID());

var asymptomaticEntry = serializedBundles.get(0);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
patient_id,patient_last_name,patient_first_name,patient_middle_name,patient_street,patient_street2,patient_city,patient_state,patient_zip_code,patient_county,patient_phone_number,patient_dob,patient_gender,patient_race,patient_ethnicity,patient_preferred_language,patient_email,accession_number,equipment_model_name,test_performed_code,test_result,order_test_date,specimen_collection_date,testing_lab_specimen_received_date,test_result_date,date_result_released,specimen_type,ordering_provider_id,ordering_provider_last_name,ordering_provider_first_name,ordering_provider_middle_name,ordering_provider_street,ordering_provider_street2,ordering_provider_city,ordering_provider_state,ordering_provider_zip_code,ordering_provider_phone_number,testing_lab_clia,testing_lab_name,testing_lab_street,testing_lab_street2,testing_lab_city,testing_lab_state,testing_lab_zip_code,testing_lab_phone_number,pregnant,employed_in_healthcare,symptomatic_for_disease,illness_onset_date,resident_congregate_setting,residence_type,hospitalized,icu,ordering_facility_name,ordering_facility_street,ordering_facility_street2,ordering_facility_city,ordering_facility_state,ordering_facility_zip_code,ordering_facility_phone_number,comment,test_result_status,test_ordered_code
1234,Doe,Jane,Jingleheimer,123 Main St,Suite 401,Birmingham,AL,35226,Jefferson,205-999-2800,1/20/1962,F,White,Not Hispanic or Latino,Eng,test@test.com,123,ID NOW,94534-5,Detected,12/20/2021 14:00,12/20/2021 14:00,12/20/2021 14:00,12/20/2021 14:00,12/20/2021 14:00,Nasal Swab,1013012657,Smith MD,John,Smitty,400 Main Street,Suite 401,Birmingham,AL,35228,205-888-2000,01D1058442,My Urgent Care,400 Main Street,Suite 401,Birmingham,AL,35228,205-888-2000,N,N,N,01/01/1901,N,22232009,N,N,My Urgent Care,400 Main Street,Suite 100,Birmingham,AL,35228,205-888-2000,Test Comment,C,94534-1
5678,Doe,John,Jingleheimer,333 Elm St,Suite 401,Hoover,AL,35244,Shelby,205-222-2000,11/1/2001,MALE,BLACK OR AFRICAN AMERICAN,NOT HISPANIC OR LATINO,Spa,myemail@email.com,05be96ef-949f-4f46-9c07-2675e8abf412,BD Veritor System for Rapid Detection of SARS-CoV-2*,94558-4,NOT DETECTED,12/21/2021 17:00,12/21/2021 17:00,12/21/2021 17:00,12/21/2021 17:00,12/21/2021 17:00,ANTERIOR NARES SWAB,1013012657,Smith MD,John,Smitty,400 Main Street,Suite 401,Birmingham,AL,35228,205-888-2000,01D1058442,My Urgent Care,400 Main Street,Suite 401,Birmingham,AL,35228,205-888-2000,NO,YES,Y,01/01/2020,Y,HOSTEL,NO,NO,My Urgent Care,400 Main Street,Suite 100,Birmingham,AL,35228,205-888-2000,testy mctesterson,F,94534-2

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
patient_id,patient_last_name,patient_first_name,patient_middle_name,patient_street,patient_street2,patient_city,patient_state,patient_zip_code,patient_county,patient_phone_number,patient_dob,patient_gender,patient_race,patient_ethnicity,patient_preferred_language,patient_email,accession_number,equipment_model_name,test_performed_code,test_result,order_test_date,specimen_collection_date,testing_lab_specimen_received_date,test_result_date,date_result_released,specimen_type,ordering_provider_id,ordering_provider_last_name,ordering_provider_first_name,ordering_provider_middle_name,ordering_provider_street,ordering_provider_street2,ordering_provider_city,ordering_provider_state,ordering_provider_zip_code,ordering_provider_phone_number,testing_lab_clia,testing_lab_name,testing_lab_street,testing_lab_street2,testing_lab_city,testing_lab_state,testing_lab_zip_code,testing_lab_phone_number,pregnant,employed_in_healthcare,symptomatic_for_disease,illness_onset_date,resident_congregate_setting,residence_type,hospitalized,icu,ordering_facility_name,ordering_facility_street,ordering_facility_street2,ordering_facility_city,ordering_facility_state,ordering_facility_zip_code,ordering_facility_phone_number,comment,test_result_status
1234,Doe,Jane,,123 Main St,,Birmingham,AL,35226,Jefferson,205-999-2800,1/20/1962,F,White,Not Hispanic or Latino,,,123,ID NOW,94534-5,Detected,12/20/2021 14:00,12/21/2021 14:00,12/22/2021 14:00,12/23/2021 14:00,12/24/2021 14:00,Nasal Swab,1013012657,Smith MD,John,,400 Main Street,,Birmingham,AL,35228,205-888-2000,01D1058442,My Testing Lab,300 North Street,,Birmingham,AL,35228,205-888-2000,N,N,N,,N,,N,N,My Urgent Care,400 Main Street,Suite 100,Birmingham,AL,35228,205-888-2000,Test Comment,F
patient_id,patient_last_name,patient_first_name,patient_middle_name,patient_street,patient_street2,patient_city,patient_state,patient_zip_code,patient_county,patient_phone_number,patient_dob,patient_gender,patient_race,patient_ethnicity,patient_preferred_language,patient_email,accession_number,equipment_model_name,test_performed_code,test_result,order_test_date,specimen_collection_date,testing_lab_specimen_received_date,test_result_date,date_result_released,specimen_type,ordering_provider_id,ordering_provider_last_name,ordering_provider_first_name,ordering_provider_middle_name,ordering_provider_street,ordering_provider_street2,ordering_provider_city,ordering_provider_state,ordering_provider_zip_code,ordering_provider_phone_number,testing_lab_clia,testing_lab_name,testing_lab_street,testing_lab_street2,testing_lab_city,testing_lab_state,testing_lab_zip_code,testing_lab_phone_number,pregnant,employed_in_healthcare,symptomatic_for_disease,illness_onset_date,resident_congregate_setting,residence_type,hospitalized,icu,ordering_facility_name,ordering_facility_street,ordering_facility_street2,ordering_facility_city,ordering_facility_state,ordering_facility_zip_code,ordering_facility_phone_number,comment,test_ordered_code,test_result_status
1234,Doe,Jane,,123 Main St,,Birmingham,AL,35226,Jefferson,205-999-2800,1/20/1962,F,White,Not Hispanic or Latino,,,123,ID NOW,94534-5,Detected,12/20/2021 14:00,12/21/2021 14:00,12/22/2021 14:00,12/23/2021 14:00,12/24/2021 14:00,Nasal Swab,1013012657,Smith MD,John,,400 Main Street,,Birmingham,AL,35228,205-888-2000,01D1058442,My Testing Lab,300 North Street,,Birmingham,AL,35228,205-888-2000,N,N,N,,N,,N,N,My Urgent Care,400 Main Street,Suite 100,Birmingham,AL,35228,205-888-2000,Test Comment,,F
Original file line number Diff line number Diff line change
Expand Up @@ -2210,6 +2210,108 @@ exports[`CsvSchemaDocumentation tests CsvSchemaDocumentation matches snapshot 1`
</ul>
</div>
</div>
<div
class="rs-documentation__values margin-top-6"
>
<h5
class="margin-bottom-2"
data-testid="header"
id="test_ordered_code"
>
Test ordered LOINC code
<span
class="text-normal bg-white border-1px border-base font-body-3xs padding-x-1 padding-y-05 text-base margin-left-2 text-bottom"
>
Optional
</span>
</h5>
<div
class="margin-bottom-3"
data-testid="subheader"
/>
<div
class="grid-row margin-bottom-05"
data-testid="column-header"
>
<div
class="grid-col-4 text-base"
>
Column header
</div>
<div
class="grid-col-auto"
>
<code>
test_ordered_code
</code>
</div>
</div>
<div
class="grid-row margin-bottom-05 border-base-lighter border-top-1px padding-top-1"
data-testid="format"
>
<div
class="grid-col-4 text-base"
>
Format
</div>
<div
class="grid-col-8 prime-ul margin-top-0"
>
00000-0
</div>
</div>
<div
class="grid-row margin-bottom-05 border-base-lighter border-top-1px padding-top-1"
data-testid="examples"
>
<div
class="grid-col-4 text-base"
>
Example
s
</div>
<ul
class="grid-col-8 prime-ul margin-top-0"
>
<li
class="bullet-list"
>
<em>
94534-5
</em>
</li>
<li
class="bullet-list"
>
<em>
94558-4
</em>
</li>
<li
class="bullet-list"
>
<em>
97097-0
</em>
</li>
<li
class="bullet-list"
>
<em>
94507-1
</em>
</li>
<li
class="bullet-list"
>
<em>
94508-9
</em>
</li>
</ul>
</div>
</div>
<div
class="rs-documentation__values margin-top-6"
>
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/app/testResults/uploads/schemaBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,21 @@ export const schemaBuilder = (facilityId: string | null) => {
`Find your device on the ${deviceCodeLookupLink}, then copy the value for this field.`,
],
},
{
name: "Test ordered LOINC code",
colHeader: "test_ordered_code",
required: false,
requested: false,
format: "00000-0",
examples: [
"94534-5",
"94558-4",
"97097-0",
"94507-1",
"94508-9",
],
description: [],
},
{
name: "Test result",
colHeader: "test_result",
Expand Down

0 comments on commit a3bc03f

Please sign in to comment.