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..d3fb918fb6 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
@@ -14,6 +14,7 @@
import static gov.cdc.usds.simplereport.validators.CsvValidatorUtils.validateEmail;
import static gov.cdc.usds.simplereport.validators.CsvValidatorUtils.validateEthnicity;
import static gov.cdc.usds.simplereport.validators.CsvValidatorUtils.validateGendersOfSexualPartners;
+import static gov.cdc.usds.simplereport.validators.CsvValidatorUtils.validatePatientGenderIdentity;
import static gov.cdc.usds.simplereport.validators.CsvValidatorUtils.validatePhoneNumber;
import static gov.cdc.usds.simplereport.validators.CsvValidatorUtils.validateRace;
import static gov.cdc.usds.simplereport.validators.CsvValidatorUtils.validateRequiredFieldsForPositiveResult;
@@ -54,7 +55,17 @@ public class TestResultRow implements FileRow {
final ValueOrError patientCounty;
final ValueOrError patientPhoneNumber;
final ValueOrError patientDob;
+
+ /**
+ * This field "patient_gender" refers to the patient's sex assigned at birth.
+ *
+ *
When "patient_gender_identity" was added as a field in 2024, the team decided to keep this
+ * current column name of "patient_gender" instead of changing the header to something like
+ * "patient_sex_assigned_at_birth". This decision was made to maintain compatibility for existing
+ * bulk upload users.
+ */
final ValueOrError patientGender;
+
final ValueOrError patientRace;
final ValueOrError patientEthnicity;
final ValueOrError patientPreferredLanguage;
@@ -107,6 +118,7 @@ public class TestResultRow implements FileRow {
final ValueOrError testOrderedCode;
final ValueOrError gendersOfSexualPartners;
final ValueOrError syphilisHistory;
+ final ValueOrError patientGenderIdentity;
static final String PATIENT_LAST_NAME = "patient_last_name";
static final String PATIENT_FIRST_NAME = "patient_first_name";
@@ -152,6 +164,7 @@ public class TestResultRow implements FileRow {
public static final String ORDERING_FACILITY_PHONE_NUMBER = "ordering_facility_phone_number";
public static final String GENDERS_OF_SEXUAL_PARTNERS = "genders_of_sexual_partners";
public static final String SYPHILIS_HISTORY = "syphilis_history";
+ public static final String PATIENT_GENDER_IDENTITY = "patient_gender_identity";
public static final ImmutableMap diseaseSpecificLoincMap =
new ImmutableMap.Builder()
@@ -456,6 +469,8 @@ public TestResultRow(Map rawRow) {
gendersOfSexualPartners =
getValue(rawRow, GENDERS_OF_SEXUAL_PARTNERS, isRequired(GENDERS_OF_SEXUAL_PARTNERS));
syphilisHistory = getValue(rawRow, SYPHILIS_HISTORY, isRequired(SYPHILIS_HISTORY));
+ patientGenderIdentity =
+ getValue(rawRow, PATIENT_GENDER_IDENTITY, isRequired(PATIENT_GENDER_IDENTITY));
}
private List validateDeviceModelAndTestPerformedCode(
@@ -612,6 +627,8 @@ public List validateIndividualValues() {
errors.addAll(validateGendersOfSexualPartners(gendersOfSexualPartners));
+ errors.addAll(validatePatientGenderIdentity(patientGenderIdentity));
+
if (isHivResult()) {
errors.addAll(
validateRequiredFieldsForPositiveResult(
diff --git a/backend/src/main/java/gov/cdc/usds/simplereport/db/model/PersonUtils.java b/backend/src/main/java/gov/cdc/usds/simplereport/db/model/PersonUtils.java
index 9dfac6e823..d5d8f549e8 100644
--- a/backend/src/main/java/gov/cdc/usds/simplereport/db/model/PersonUtils.java
+++ b/backend/src/main/java/gov/cdc/usds/simplereport/db/model/PersonUtils.java
@@ -843,6 +843,7 @@ public static Map getGenderIdentityAbbreviationMap() {
genderMap.put("M", MALE);
genderMap.put("MALE", MALE);
genderMap.put("NB", NON_BINARY);
+ genderMap.put("NON BINARY", NON_BINARY);
genderMap.put("NONBINARY", NON_BINARY);
genderMap.put("TM", TRANS_MAN);
genderMap.put("TRANS MAN", TRANS_MAN);
diff --git a/backend/src/main/java/gov/cdc/usds/simplereport/utils/BulkUploadResultsToFhir.java b/backend/src/main/java/gov/cdc/usds/simplereport/utils/BulkUploadResultsToFhir.java
index 0a8997e076..7df1d232d9 100644
--- a/backend/src/main/java/gov/cdc/usds/simplereport/utils/BulkUploadResultsToFhir.java
+++ b/backend/src/main/java/gov/cdc/usds/simplereport/utils/BulkUploadResultsToFhir.java
@@ -528,6 +528,16 @@ private Bundle convertRowToFhirBundle(TestResultRow row, UUID orgId) {
fhirConverter.convertToAOEGenderOfSexualPartnersObservation(abbrConvertedGenders));
}
+ String patientGenderIdentity = row.getPatientGenderIdentity().getValue();
+ if (StringUtils.isNotBlank(patientGenderIdentity)) {
+ Map genderAbbreviationMap = getGenderIdentityAbbreviationMap();
+ String abbrConvertedGenderIdentity =
+ genderAbbreviationMap.get(patientGenderIdentity.toUpperCase());
+ aoeObservations.addAll(
+ fhirConverter.convertToAOEGenderIdentityObservation(
+ testEventId, abbrConvertedGenderIdentity));
+ }
+
var serviceRequest =
fhirConverter.convertToServiceRequest(
ServiceRequest.ServiceRequestStatus.COMPLETED,
diff --git a/backend/src/main/java/gov/cdc/usds/simplereport/validators/CsvValidatorUtils.java b/backend/src/main/java/gov/cdc/usds/simplereport/validators/CsvValidatorUtils.java
index 3556caf950..902c793ffe 100644
--- a/backend/src/main/java/gov/cdc/usds/simplereport/validators/CsvValidatorUtils.java
+++ b/backend/src/main/java/gov/cdc/usds/simplereport/validators/CsvValidatorUtils.java
@@ -660,6 +660,26 @@ public static List validateGendersOfSexualPartners(ValueOrError
return errors;
}
+ public static List validatePatientGenderIdentity(ValueOrError input) {
+ List errors = new ArrayList<>();
+ String value = parseString(input.getValue());
+ if (value == null) {
+ return errors;
+ }
+ if (!getGenderIdentityAbbreviationMap().containsKey(value.toUpperCase())) {
+ errors.add(
+ FeedbackMessage.builder()
+ .scope(ITEM_SCOPE)
+ .fieldHeader(input.getHeader())
+ .source(ResultUploadErrorSource.SIMPLE_REPORT)
+ .message(getInvalidValueErrorMessage(input.getValue(), input.getHeader()))
+ .errorType(ResultUploadErrorType.INVALID_DATA)
+ .fieldRequired(input.isRequired())
+ .build());
+ }
+ return errors;
+ }
+
public static List validateRequiredFieldsForPositiveResult(
ValueOrError testResult, String diseaseName, List fields) {
List errors = new ArrayList<>();
diff --git a/backend/src/test/java/gov/cdc/usds/simplereport/utils/BulkUploadResultsToFhirTest.java b/backend/src/test/java/gov/cdc/usds/simplereport/utils/BulkUploadResultsToFhirTest.java
index 6cfd895011..e70cbb8c6a 100644
--- a/backend/src/test/java/gov/cdc/usds/simplereport/utils/BulkUploadResultsToFhirTest.java
+++ b/backend/src/test/java/gov/cdc/usds/simplereport/utils/BulkUploadResultsToFhirTest.java
@@ -214,7 +214,7 @@ void convertExistingCsv_aoeQuestionsMapped() {
.filter(
observation -> observation.getResource().getNamedProperty("identifier").hasValues())
.toList();
- assertThat(asymptomaticNotCongregateAOE).hasSize(11);
+ assertThat(asymptomaticNotCongregateAOE).hasSize(12);
var symptomaticCongregateSettingEntry = serializedBundles.get(1);
var deserializedSymptomaticCongregateEntry =
@@ -227,7 +227,7 @@ void convertExistingCsv_aoeQuestionsMapped() {
symptomaticCongregateObservations.stream()
.filter(obs -> obs.getResource().getNamedProperty("identifier").hasValues())
.toList();
- assertThat(symptomaticCongregateAOE).hasSize(10);
+ assertThat(symptomaticCongregateAOE).hasSize(11);
}
private InputStream loadCsv(String csvFile) {
diff --git a/backend/src/test/java/gov/cdc/usds/simplereport/validators/CsvValidatorUtilsTest.java b/backend/src/test/java/gov/cdc/usds/simplereport/validators/CsvValidatorUtilsTest.java
index af37d86296..c5cdcb703d 100644
--- a/backend/src/test/java/gov/cdc/usds/simplereport/validators/CsvValidatorUtilsTest.java
+++ b/backend/src/test/java/gov/cdc/usds/simplereport/validators/CsvValidatorUtilsTest.java
@@ -10,6 +10,7 @@
import static gov.cdc.usds.simplereport.validators.CsvValidatorUtils.validateFlexibleDate;
import static gov.cdc.usds.simplereport.validators.CsvValidatorUtils.validateGendersOfSexualPartners;
import static gov.cdc.usds.simplereport.validators.CsvValidatorUtils.validatePartialUnkAddress;
+import static gov.cdc.usds.simplereport.validators.CsvValidatorUtils.validatePatientGenderIdentity;
import static gov.cdc.usds.simplereport.validators.CsvValidatorUtils.validatePhoneNumber;
import static gov.cdc.usds.simplereport.validators.CsvValidatorUtils.validateRequiredFieldsForPositiveResult;
import static gov.cdc.usds.simplereport.validators.CsvValidatorUtils.validateSpecimenType;
@@ -290,6 +291,61 @@ void invalidGendersOfSexualPartners() {
assertThat(validateGendersOfSexualPartners(genders)).hasSize(1);
}
+ @Test
+ void validPatientGenderIdentity() {
+ assertThat(validatePatientGenderIdentity(new ValueOrError("f", "patient_gender_identity")))
+ .isEmpty();
+ assertThat(validatePatientGenderIdentity(new ValueOrError("m", "patient_gender_identity")))
+ .isEmpty();
+ assertThat(validatePatientGenderIdentity(new ValueOrError("nb", "patient_gender_identity")))
+ .isEmpty();
+ assertThat(validatePatientGenderIdentity(new ValueOrError("tm", "patient_gender_identity")))
+ .isEmpty();
+ assertThat(validatePatientGenderIdentity(new ValueOrError("tw", "patient_gender_identity")))
+ .isEmpty();
+ assertThat(validatePatientGenderIdentity(new ValueOrError("o", "patient_gender_identity")))
+ .isEmpty();
+ assertThat(validatePatientGenderIdentity(new ValueOrError("r", "patient_gender_identity")))
+ .isEmpty();
+ assertThat(validatePatientGenderIdentity(new ValueOrError("female", "patient_gender_identity")))
+ .isEmpty();
+ assertThat(validatePatientGenderIdentity(new ValueOrError("male", "patient_gender_identity")))
+ .isEmpty();
+ assertThat(
+ validatePatientGenderIdentity(
+ new ValueOrError("non binary", "patient_gender_identity")))
+ .isEmpty();
+ assertThat(
+ validatePatientGenderIdentity(new ValueOrError("nonbinary", "patient_gender_identity")))
+ .isEmpty();
+ assertThat(
+ validatePatientGenderIdentity(new ValueOrError("trans man", "patient_gender_identity")))
+ .isEmpty();
+ assertThat(
+ validatePatientGenderIdentity(
+ new ValueOrError("trans woman", "patient_gender_identity")))
+ .isEmpty();
+ assertThat(validatePatientGenderIdentity(new ValueOrError("other", "patient_gender_identity")))
+ .isEmpty();
+ assertThat(
+ validatePatientGenderIdentity(new ValueOrError("refused", "patient_gender_identity")))
+ .isEmpty();
+ }
+
+ @Test
+ void invalidPatientGenderIdentity() {
+ assertThat(validatePatientGenderIdentity(new ValueOrError("t", "patient_gender_identity")))
+ .hasSize(1);
+ assertThat(validatePatientGenderIdentity(new ValueOrError("n", "patient_gender_identity")))
+ .hasSize(1);
+ assertThat(validatePatientGenderIdentity(new ValueOrError("ma", "patient_gender_identity")))
+ .hasSize(1);
+ assertThat(validatePatientGenderIdentity(new ValueOrError("fe", "patient_gender_identity")))
+ .hasSize(1);
+ assertThat(validatePatientGenderIdentity(new ValueOrError(" ", "patient_gender_identity")))
+ .hasSize(1);
+ }
+
@Test
void validNegativeHIVNoRequiredAOEFields() {
ValueOrError testResult = new ValueOrError("negative", "test_result");
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..236b851891 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
@@ -96,7 +96,8 @@ class TestResultRowTest {
"test_result_status",
"specimen_type",
"testing_lab_clia",
- "genders_of_sexual_partners");
+ "genders_of_sexual_partners",
+ "patient_gender_identity");
@BeforeEach
public void init() {
@@ -164,6 +165,7 @@ public void init() {
validRowMap.put("comment", "Test Comment");
validRowMap.put("test_result_status", "");
validRowMap.put("genders_of_sexual_partners", "M, F, TM, TW");
+ validRowMap.put("patient_gender_identity", "F");
}
@Test
@@ -358,7 +360,10 @@ void processRowSetsAllValues() {
from(TestResultRow::getTestResultStatus).andThen(ValueOrError::getValue))
.returns(
validRowMap.get("genders_of_sexual_partners"),
- from(TestResultRow::getGendersOfSexualPartners).andThen(ValueOrError::getValue));
+ from(TestResultRow::getGendersOfSexualPartners).andThen(ValueOrError::getValue))
+ .returns(
+ validRowMap.get("patient_gender_identity"),
+ from(TestResultRow::getPatientGenderIdentity).andThen(ValueOrError::getValue));
}
@Test
@@ -412,6 +417,7 @@ void validateIndividualFields() {
invalidIndividualFields.put("specimen_type", "100");
invalidIndividualFields.put("testing_lab_clia", "à");
invalidIndividualFields.put("genders_of_sexual_partners", "ma, f");
+ invalidIndividualFields.put("patient_gender_identity", "fe");
var testResultRow =
new TestResultRow(
invalidIndividualFields,
diff --git a/backend/src/test/resources/testResultUpload/test-results-upload-all-fields.csv b/backend/src/test/resources/testResultUpload/test-results-upload-all-fields.csv
index 21c4ac4419..d3db9052bf 100644
--- a/backend/src/test/resources/testResultUpload/test-results-upload-all-fields.csv
+++ b/backend/src/test/resources/testResultUpload/test-results-upload-all-fields.csv
@@ -1,3 +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,genders_of_sexual_partners,syphilis_history
-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,"M, F, trans man, TW, nonbinary",""
-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,"Male, NB",""
+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,genders_of_sexual_partners,syphilis_history,patient_gender_identity
+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,"M, F, trans man, TW, nonbinary","",m
+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,"Male, NB","",f