Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add patient gender identity to bulk upload #8270

Merged
merged 1 commit into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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. <br>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding this note!

*
* <p>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;
Expand Down Expand Up @@ -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";
Expand Down Expand Up @@ -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<String, String> diseaseSpecificLoincMap =
new ImmutableMap.Builder<String, String>()
Expand Down Expand Up @@ -456,6 +469,8 @@ public TestResultRow(Map<String, String> 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<FeedbackMessage> validateDeviceModelAndTestPerformedCode(
Expand Down Expand Up @@ -612,6 +627,8 @@ public List<FeedbackMessage> validateIndividualValues() {

errors.addAll(validateGendersOfSexualPartners(gendersOfSexualPartners));

errors.addAll(validatePatientGenderIdentity(patientGenderIdentity));

if (isHivResult()) {
errors.addAll(
validateRequiredFieldsForPositiveResult(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,7 @@ public static Map<String, String> 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,16 @@ private Bundle convertRowToFhirBundle(TestResultRow row, UUID orgId) {
fhirConverter.convertToAOEGenderOfSexualPartnersObservation(abbrConvertedGenders));
}

String patientGenderIdentity = row.getPatientGenderIdentity().getValue();
if (StringUtils.isNotBlank(patientGenderIdentity)) {
Map<String, String> genderAbbreviationMap = getGenderIdentityAbbreviationMap();
String abbrConvertedGenderIdentity =
genderAbbreviationMap.get(patientGenderIdentity.toUpperCase());
aoeObservations.addAll(
fhirConverter.convertToAOEGenderIdentityObservation(
testEventId, abbrConvertedGenderIdentity));
}

var serviceRequest =
fhirConverter.convertToServiceRequest(
ServiceRequest.ServiceRequestStatus.COMPLETED,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,26 @@ public static List<FeedbackMessage> validateGendersOfSexualPartners(ValueOrError
return errors;
}

public static List<FeedbackMessage> validatePatientGenderIdentity(ValueOrError input) {
List<FeedbackMessage> 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<FeedbackMessage> validateRequiredFieldsForPositiveResult(
ValueOrError testResult, String diseaseName, List<ValueOrError> fields) {
List<FeedbackMessage> errors = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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,[email protected],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,[email protected],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,[email protected],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,[email protected],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
Loading