Skip to content

Commit

Permalink
allowing for column headers and enum values to be case-insensitive in…
Browse files Browse the repository at this point in the history
… CSV. Still not allowed for JSON
  • Loading branch information
shaselton-usds committed Jan 12, 2024
1 parent 1318c7f commit 480a89c
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/csv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export async function validateCsv(
resolve: (result: ValidationResult | PromiseLike<ValidationResult>) => void,
parser: Papa.Parser
) => {
const row: string[] = step.data
const row: string[] = step.data.map((item) => item.toLowerCase())
// Ignore empty lines
if (rowIsEmpty(row)) {
++index
Expand Down
20 changes: 13 additions & 7 deletions src/versions/1.1/csv.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CsvValidationError, StateCode, STATE_CODES } from "../../types.js"

import {
csvErr,
sepColumnsEqual,
Expand All @@ -18,6 +19,11 @@ import {
DrugUnit,
} from "./types.js"

// CSV is being allowed to have case insensitive values...
const STATE_CODES_CSV = STATE_CODES.map((state) => state.toLowerCase())
const BILLING_CODE_TYPES_CSV = BILLING_CODE_TYPES.map((code) => code.toLowerCase())
const DRUG_UNITS_CSV = DRUG_UNITS.map((unit) => unit.toLowerCase())

export const HEADER_COLUMNS = [
"hospital_name",
"last_updated_on",
Expand Down Expand Up @@ -201,7 +207,7 @@ export function validateRow(
)
)

if (!BILLING_CODE_TYPES.includes(row["code | 1 | type"] as BillingCodeType)) {
if (!BILLING_CODE_TYPES_CSV.includes(row["code | 1 | type"] as BillingCodeType)) {
errors.push(
csvErr(
index,
Expand All @@ -210,7 +216,7 @@ export function validateRow(
ERRORS.ALLOWED_VALUES(
"code | 1 | type",
row["code | 1 | type"],
BILLING_CODE_TYPES as unknown as string[]
BILLING_CODE_TYPES_CSV as unknown as string[]
),
true
)
Expand All @@ -220,7 +226,7 @@ export function validateRow(
// TODO: Code itself is required, need to check all of those, not all checked here
if (
row["code | 2"] &&
!BILLING_CODE_TYPES.includes(row["code | 2 | type"] as BillingCodeType)
!BILLING_CODE_TYPES_CSV.includes(row["code | 2 | type"] as BillingCodeType)
) {
errors.push(
csvErr(
Expand All @@ -230,7 +236,7 @@ export function validateRow(
ERRORS.ALLOWED_VALUES(
"code | 2 | type",
row["code | 2 | type"],
BILLING_CODE_TYPES as unknown as string[]
BILLING_CODE_TYPES_CSV as unknown as string[]
)
)
)
Expand Down Expand Up @@ -282,7 +288,7 @@ export function validateRow(
)
)
}
if (!DRUG_UNITS.includes(row["drug_type_of_measurement"] as DrugUnit)) {
if (!DRUG_UNITS_CSV.includes(row["drug_type_of_measurement"] as DrugUnit)) {
errors.push(
csvErr(
index,
Expand All @@ -291,7 +297,7 @@ export function validateRow(
ERRORS.ALLOWED_VALUES(
"drug_type_of_measurement",
row["drug_type_of_measurement"],
DRUG_UNITS as unknown as string[]
DRUG_UNITS_CSV as unknown as string[]
)
)
)
Expand Down Expand Up @@ -379,7 +385,7 @@ function validateLicenseStateColumn(
return [csvErr(rowIndex, columnIndex, LICENSE_STATE, invalidMessage)]
}
const stateCode = column.split("|").slice(-1)[0].trim()
if (!STATE_CODES.includes(stateCode as StateCode)) {
if (!STATE_CODES_CSV.includes(stateCode as StateCode)) {
return [
csvErr(
rowIndex,
Expand Down
16 changes: 2 additions & 14 deletions test/csv.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,10 @@ test("sample-1", async (t) => {
{
field: "code | 1 | type",
message:
'"code | 1 | type" value "C" is not one of the allowed values: "CPT", "HCPCS", "ICD", "MS-DRG", "R-DRG", "S-DRG", "APS-DRG", "AP-DRG", "APR-DRG", "APC", "NDC", "HIPPS", "LOCAL", "EAPG", "CDT", "RC", "CDM"',
'"code | 1 | type" value "c" is not one of the allowed values: "cpt", "hcpcs", "icd", "ms-drg", "r-drg", "s-drg", "aps-drg", "ap-drg", "apr-drg", "apc", "ndc", "hipps", "local", "eapg", "cdt", "rc", "cdm"',
path: "C4",
warning: true,
},
{
field: "billing_class",
message:
'"billing_class" value "Facility" is not one of the allowed values: "professional", "facility"',
path: "F4",
},
{
field: "setting",
message:
Expand All @@ -40,7 +34,7 @@ test("sample-1 maxErrors", async (t) => {
{
field: "code | 1 | type",
message:
'"code | 1 | type" value "C" is not one of the allowed values: "CPT", "HCPCS", "ICD", "MS-DRG", "R-DRG", "S-DRG", "APS-DRG", "AP-DRG", "APR-DRG", "APC", "NDC", "HIPPS", "LOCAL", "EAPG", "CDT", "RC", "CDM"',
'"code | 1 | type" value "c" is not one of the allowed values: "cpt", "hcpcs", "icd", "ms-drg", "r-drg", "s-drg", "aps-drg", "ap-drg", "apr-drg", "apc", "ndc", "hipps", "local", "eapg", "cdt", "rc", "cdm"',
path: "C4",
warning: true,
},
Expand All @@ -52,12 +46,6 @@ test("sample-2", async (t) => {
t.deepEqual(
(await validateCsv(loadFixtureStream("sample-2.csv"), "v1.1")).errors,
[
{
field: "billing_class",
message:
'"billing_class" value "Facility" is not one of the allowed values: "professional", "facility"',
path: "F4",
},
{
field: "setting",
message:
Expand Down
2 changes: 1 addition & 1 deletion test/csv.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
import { CONTRACTING_METHODS } from "../src/versions/1.1/types.js"

const VALID_HEADER_COLUMNS = HEADER_COLUMNS.map((c) =>
c === "license_number | state" ? "license_number | MD" : c
c === "license_number | state" ? "license_number | md" : c
)

test("validateHeaderColumns", (t) => {
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/sample-1.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
hospital_name,last_updated_on,version,hospital_location,financial_aid_policy,license_number | MD,,,,,,,,,,,,,,
Hospital_name,last_updated_on,version,hospital_location,financial_aid_policy,license_number | MD,,,,,,,,,,,,,,
Example Hospital,2/1/23,1.0.0,Woodlawn,See aid policy on site,12345678,,,,,,,,,,,,,,
description,code | 1,code | 1 | type,code | 2,code | 2 | type,billing_class,setting,drug_unit_of_measurement,drug_type_of_measurement,modifiers,standard_charge | gross,standard_charge | discounted_cash,payer_name,plan_name,standard_charge | negotiated_dollar,standard_charge | negotiated_percent,standard_charge | min,standard_charge | max,standard_charge | contracting_method,additional_generic_notes
Code 1,A123,C,,,Facility,ipatient,1,ML,,100,90,Payer,Plan,80,20,60,80,other,

0 comments on commit 480a89c

Please sign in to comment.