diff --git a/.github/workflows/ci-java.yml b/.github/workflows/ci-java.yml
index 3742e3f48b..2f29e43489 100644
--- a/.github/workflows/ci-java.yml
+++ b/.github/workflows/ci-java.yml
@@ -10,7 +10,7 @@ env:
# NOTE: The expression below can be extended to multi-line
# using a '\' as a continuation character.
# https://stackoverflow.com/questions/6268391/is-there-a-way-to-represent-a-long-string-that-doesnt-have-any-whitespace-on-mul
- workflow_files_re: "^apps/(?!bfd-pipeline/bfd-pipeline-idr|utils).+$|^.github/workflows/ci-java.yml$"
+ workflow_files_re: "^apps/(?!bfd-pipeline/bfd-pipeline-idr|bfd-model/bfd-model-idr|utils).+$|^.github/workflows/ci-java.yml$"
jobs:
workflow:
diff --git a/apps/bfd-model/bfd-model-idr/README.md b/apps/bfd-model/bfd-model-idr/README.md
new file mode 100644
index 0000000000..401a901cc5
--- /dev/null
+++ b/apps/bfd-model/bfd-model-idr/README.md
@@ -0,0 +1,38 @@
+Placeholder directories + structures for mapping between IDR and FHIR.
+
+To download the FHIR Validator:
+https://github.com/hapifhir/org.hl7.fhir.core/releases/latest/download/validator_cli.jar
+
+To execute FHIR Mapping language transforms against the sample data.
+To compile the StructureMap:
+```sh
+java -jar validator_cli.jar -ig maps/patient.map \
+ -compile https://bfd.cms.gov/MappingLanguage/Resources/Patient \
+ -version 4.0.1 -output StructureMaps/bfd_patient_structuremap.json
+```
+
+To execute:
+```sh
+java -jar validator_cli.jar sample-data/BeneficiarySample.json \
+ -output outputs/Patient.json \
+ -transform https://bfd.cms.gov/MappingLanguage/Resources/Patient \
+ -version 4.0.1 \
+ -ig StructureMaps/bfd_patient_structuremap.json \
+ -ig StructureDefinitions/Source/Bene-MBI.json \
+ -ig StructureDefinitions/Source/Bene.json \
+ -ig hl7.fhir.us.carin-bb#2.0.0 \
+ -ig maps/Patient-Helper.map
+```
+
+
+Validating sample resources against self-defined StructureDefinitions:
+```sh
+java -jar validator_cli.jar sample-data/.json \
+ -ig StructureDefinitions/Source/.json
+```
+
+Validate against C4BB:
+```sh
+java -jar validator_cli.jar outputs/.json \
+ -ig hl7.fhir.us.carin-bb#2.0.0
+```
diff --git a/apps/bfd-model/bfd-model-idr/StructureDefinitions/Source/Bene-MBI.json b/apps/bfd-model/bfd-model-idr/StructureDefinitions/Source/Bene-MBI.json
new file mode 100644
index 0000000000..e6435da00d
--- /dev/null
+++ b/apps/bfd-model/bfd-model-idr/StructureDefinitions/Source/Bene-MBI.json
@@ -0,0 +1,64 @@
+{
+ "resourceType": "StructureDefinition",
+ "id": "BENE_MBI",
+ "url": "http://hl7.org/fhir/StructureDefinition/BeneficiaryMBIIdentifier",
+ "name": "BENE_MBI",
+ "status": "draft",
+ "fhirVersion": "4.0.1",
+ "kind": "logical",
+ "abstract": true,
+ "type": "BeneficiaryMBIIdentifier",
+ "baseDefinition": "http://hl7.org/fhir/StructureDefinition/Base",
+ "derivation": "specialization",
+ "differential": {
+ "element": [
+ {
+ "id": "BeneficiaryMBIIdentifier",
+ "path": "BeneficiaryMBIIdentifier",
+ "label": "IDR MBI Base Resource. Ignore in DD Generation",
+ "definition": "BeneficiaryMBIIdentifier definition",
+ "min": 1,
+ "max": "1"
+ },
+ {
+ "id": "BeneficiaryMBIIdentifier.BENE_MBI_ID",
+ "path": "BeneficiaryMBIIdentifier.BENE_MBI_ID",
+ "label": "MBI ID",
+ "definition": "Medicare Beneficiary Identifier",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "BeneficiaryMBIIdentifier.BENE_MBI_EFCTV_DT",
+ "path": "BeneficiaryMBIIdentifier.BENE_MBI_EFCTV_DT",
+ "label": "MBI Effective Date",
+ "definition": "Effective date of this MBI.",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "dateTime"
+ }
+ ]
+ },
+ {
+ "id": "BeneficiaryMBIIdentifier.BENE_MBI_OBSLT_DT",
+ "path": "BeneficiaryMBIIdentifier.BENE_MBI_OBSLT_DT",
+ "label": "MBI Obsolete Date",
+ "definition": "Date this MBI was marked obsolete.",
+ "min": 0,
+ "max": "1",
+ "type": [
+ {
+ "code": "dateTime"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/apps/bfd-model/bfd-model-idr/StructureDefinitions/Source/Bene.json b/apps/bfd-model/bfd-model-idr/StructureDefinitions/Source/Bene.json
new file mode 100644
index 0000000000..1e9dfaaaa1
--- /dev/null
+++ b/apps/bfd-model/bfd-model-idr/StructureDefinitions/Source/Bene.json
@@ -0,0 +1,338 @@
+{
+ "resourceType": "StructureDefinition",
+ "id": "BENE",
+ "url": "https://bfd.cms.gov/fhir/StructureDefinition/BENE",
+ "name": "BENE",
+ "status": "draft",
+ "fhirVersion": "4.0.1",
+ "kind": "logical",
+ "abstract": true,
+ "type": "Beneficiary",
+ "baseDefinition": "http://hl7.org/fhir/StructureDefinition/Base",
+ "derivation": "specialization",
+ "differential": {
+ "element": [
+ {
+ "id": "Beneficiary",
+ "path": "Beneficiary",
+ "label": "IDR Beneficiary Base. Ignore in DD Generation",
+ "definition": "Beneficiary definition",
+ "min": 1,
+ "max": "1"
+ },
+ {
+ "id": "Beneficiary.BENE_1ST_NAME",
+ "path": "Beneficiary.BENE_1ST_NAME",
+ "label": "First Name",
+ "definition": "First name from IDR",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.BENE_LAST_NAME",
+ "path": "Beneficiary.BENE_LAST_NAME",
+ "label": "Last Name",
+ "definition": "Last name from IDR",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.BENE_MIDL_NAME",
+ "path": "Beneficiary.BENE_MIDL_NAME",
+ "label": "Last Name",
+ "definition": "Last name from IDR",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.BENE_DOB",
+ "path": "Beneficiary.BENE_DOB",
+ "label": "Date of Birth",
+ "definition": "Date of birth for beneficiary",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "date"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.BENE_DEATH_DT",
+ "path": "Beneficiary.BENE_DEATH_DT",
+ "label": "Date of Death",
+ "definition": "Date of death for beneficiary. Only populated if BENE_VRFY_DEATH_DAY_SW is true",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "dateTime"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.BENE_VRFY_DEATH_DAY_SW",
+ "path": "Beneficiary.BENE_VRFY_DEATH_DAY_SW",
+ "label": "Date of Death Verification Switch",
+ "definition": "Don't trust the date of death unless this is 'true'.",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "boolean"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.mbi",
+ "path": "Beneficiary.mbi",
+ "label": "Medicare Beneficiary Identifier (MBI)",
+ "definition": "Medicare Beneficiary Identifier (MBI) for beneficiary",
+ "min": 1,
+ "max": "*",
+ "type": [
+ {
+ "code": "BeneficiaryMBIIdentifier",
+ "targetProfile" : ["https://bfd.cms.gov/fhir/StructureDefinition/BENE_MBI"]
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.XREF_EFCTV_BENE_SK",
+ "path": "Beneficiary.XREF_EFCTV_BENE_SK",
+ "label": "Effective Beneficiary SK ",
+ "definition": "Effective BENE_SK for the individual, representing the XREF_EFCTV_SK",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.BENE_SK",
+ "path": "Beneficiary.BENE_SK",
+ "label": "Effective Beneficiary SK ",
+ "definition": "BENE_SK for the individual.",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.ALL_BENE_SKs",
+ "path": "Beneficiary.ALL_BENE_SKs",
+ "label": "Beneficiary SK List.",
+ "definition": "A list of all BENE_SKs for the beneficiary. This list is to be used when querying the claims table.",
+ "min": 1,
+ "max": "*",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.lastUpdated",
+ "path": "Beneficiary.lastUpdated",
+ "label": "Last Updated time",
+ "definition": "The time the data utilized from IDR was inserted/updated",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "date"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.GEO_USPS_STATE_CD",
+ "path": "Beneficiary.GEO_USPS_STATE_CD",
+ "label": "USPS State Code",
+ "definition": "USPS State Code",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.BENE_ZIP_CD",
+ "path": "Beneficiary.BENE_ZIP_CD",
+ "label": "Beneficiary Zip Code",
+ "definition": "Beneficiary Zip Code",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.BENE_LINE_1_ADR",
+ "path": "Beneficiary.BENE_LINE_1_ADR",
+ "label": "Line 1 of address",
+ "definition": "Line 1 of address",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.BENE_LINE_2_ADR",
+ "path": "Beneficiary.BENE_LINE_2_ADR",
+ "label": "Line 2 of address",
+ "definition": "Line 2 of address",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.BENE_LINE_3_ADR",
+ "path": "Beneficiary.BENE_LINE_3_ADR",
+ "label": "Line 3 of address",
+ "definition": "Line 3 of address",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.BENE_LINE_4_ADR",
+ "path": "Beneficiary.BENE_LINE_4_ADR",
+ "label": "Line 4 of address",
+ "definition": "Line 4 of address",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.BENE_LINE_5_ADR",
+ "path": "Beneficiary.BENE_LINE_5_ADR",
+ "label": "Line 5 of address",
+ "definition": "Line 5 of address",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.BENE_LINE_6_ADR",
+ "path": "Beneficiary.BENE_LINE_6_ADR",
+ "label": "Line 6 of Address",
+ "definition": "Line 6 of address",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.GEO_ZIP_PLC_NAME",
+ "path": "Beneficiary.GEO_ZIP_PLC_NAME",
+ "label": "City Name",
+ "definition": "City Name of Beneficiary.",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.CNTCT_LANG_CD",
+ "path": "Beneficiary.CNTCT_LANG_CD",
+ "label": "Contact Language Code",
+ "definition": "Contact Language Code for beneficiary. Either English or Spanish. Used for Medicare Handbook today.",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.BENE_PHNE_NUM",
+ "path": "Beneficiary.BENE_PHNE_NUM",
+ "label": "Beneficiary Phone Number",
+ "definition": "Beneficiary Phone Number from BENE_HISTRY.",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.BENE_SEX_CD",
+ "path": "Beneficiary.BENE_SEX_CD",
+ "label": "Beneficiary Sex Code",
+ "definition": "Beneficiary Sex Code, as recorded by CMS in IDR.",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ },
+ {
+ "id": "Beneficiary.BENE_RACE_CD",
+ "path": "Beneficiary.BENE_RACE_CD",
+ "label": "Beneficiary Race Code",
+ "definition": "Beneficiary Race Code, as recorded by CMS in IDR.",
+ "min": 1,
+ "max": "1",
+ "type": [
+ {
+ "code": "string"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/apps/bfd-model/bfd-model-idr/dictionary-support-yamls/patient.yaml b/apps/bfd-model/bfd-model-idr/dictionary-support-yamls/patient.yaml
new file mode 100644
index 0000000000..186ef7f914
--- /dev/null
+++ b/apps/bfd-model/bfd-model-idr/dictionary-support-yamls/patient.yaml
@@ -0,0 +1,135 @@
+#of note, BENE_SSN_NUM will be consumed by BFD and should be in here, but not as part of the mapping to FHIR. It should only be used for matching, eventually.
+- inputPath: Beneficiary.BENE_1ST_NAME
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.name.given
+ expectedFHIRPath: Patient.name.given[0]
+- inputPath: Beneficiary.BENE_LAST_NAME
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.name.family
+ expectedFHIRPath: Patient.name.family
+- inputPath: Beneficiary.BENE_MIDL_NAME
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.name.given
+ expectedFHIRPath: Patient.name.given[1]
+- inputPath: Beneficiary.BENE_DOB
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.birthDate
+ expectedFHIRPath: Patient.birthDate
+- inputPath: Beneficiary.BENE_DEATH_DT
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.deceasedDateTime
+ expectedFHIRPath: Patient.deceasedDateTime
+- inputPath: Beneficiary.BENE_VRFY_DEATH_DAY_SW
+ appliesTo:
+ - Patient
+- inputPath: Beneficiary.mbi
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.identifier
+ expectedFHIRPath: Patient.identifier.where(system='http://hl7.org/fhir/sid/us-mbi')
+- inputPath: Beneficiary.XREF_EFCTV_BENE_SK
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.id XOR BFDPatient.link.other.display
+ expectedFHIRPath: iif(Patient.link.where(type = 'replaced-by').other.exists(),Patient.link.where(type = 'replaced-by').other.reference.substring(8),Patient.id)
+- inputPath: Beneficiary.ALL_BENE_SKs
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.link.other.display OR Patient.id
+ expectedFHIRPath: Patient.link.other.display.union(Patient.id)
+- inputPath: Beneficiary.BENE_SK
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.id
+ expectedFHIRPath: Patient.id
+- inputPath: Beneficiary.lastUpdated
+ appliesTo:
+ - Patient
+ targetElement: Patient.meta.lastUpdated
+ expectedFHIRPath: Patient.meta.lastUpdated
+- inputPath: Beneficiary.GEO_USPS_STATE_CD
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.
+ expectedFHIRPath: Patient.address[0].state
+- inputPath: Beneficiary.BENE_ZIP_CD
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.address.postalCode
+ expectedFHIRPath: Patient.address[0].postalCode
+- inputPath: Beneficiary.BENE_LINE_1_ADR
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.address.line
+ expectedFHIRPath: Patient.address[0].line[0]
+- inputPath: Beneficiary.BENE_LINE_2_ADR
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.address.line
+ expectedFHIRPath: Patient.address[0].line[1]
+- inputPath: Beneficiary.BENE_LINE_3_ADR
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.address.line
+ expectedFHIRPath: Patient.address[0].line[2]
+- inputPath: Beneficiary.BENE_LINE_4_ADR
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.address.line
+ expectedFHIRPath: Patient.address[0].line[3]
+- inputPath: Beneficiary.BENE_LINE_5_ADR
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.address.line
+ expectedFHIRPath: Patient.address[0].line[4]
+- inputPath: Beneficiary.BENE_LINE_6_ADR
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.address.line
+ expectedFHIRPath: Patient.address[0].line[5]
+- inputPath: Beneficiary.GEO_ZIP_PLC_NAME
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.address.city
+ expectedFHIRPath: Patient.address[0].city
+- inputPath: Beneficiary.CNTCT_LANG_CD
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.communication.language.coding.code
+ expectedFHIRPath: Patient.communication.language.coding.where(system='urn:ietf:bcp:47').code
+- inputPath: Beneficiary.BENE_PHNE_NUM
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.telecom.value
+ expectedFHIRPath: Patient.telecom.where(system='phone').value
+- inputPath: Beneficiary.BENE_SEX_CD
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.gender
+ expectedFHIRPath: Patient.gender
+- inputPath: Beneficiary.BENE_RACE_CD
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.extension.extension.valueString
+ expectedFHIRPath: Patient.extension.where(url='http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity' or url='http://hl7.org/fhir/us/core/StructureDefinition/us-core-race')
+- inputPath: BeneficiaryMBIIdentifier.BENE_MBI_ID
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.identifier.value
+ expectedFHIRPath: Patient.identifier.where(system='http://hl7.org/fhir/sid/us-mbi').value
+- inputPath: BeneficiaryMBIIdentifier.BENE_MBI_EFCTV_DT
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.identifier.period.start
+ expectedFHIRPath: Patient.identifier.where(system='http://hl7.org/fhir/sid/us-mbi').period.start
+- inputPath: BeneficiaryMBIIdentifier.BENE_MBI_OBSLT_DT
+ appliesTo:
+ - Patient
+ targetElement: BFDPatient.identifier.period.end
+ expectedFHIRPath: Patient.identifier.where(system='http://hl7.org/fhir/sid/us-mbi').period.end
+
diff --git a/apps/bfd-model/bfd-model-idr/idr-queries/temp-patient-queries.txt b/apps/bfd-model/bfd-model-idr/idr-queries/temp-patient-queries.txt
new file mode 100644
index 0000000000..a9dd5f398e
--- /dev/null
+++ b/apps/bfd-model/bfd-model-idr/idr-queries/temp-patient-queries.txt
@@ -0,0 +1,51 @@
+Query 1:
+Gets the current beneficiary information, along with a list of BENE_SKs that are applicable, as well as a list of all of their MBIs
+
+with
+ bene_filtered as (
+ SELECT
+ bene.*,
+ bene_history.bene_vrfy_death_day_sw,
+ ARRAY_AGG (bene.BENE_SK) OVER () AS ALL_BENE_SKs,
+ ARRAY_AGG (DISTINCT bene.BENE_MBI_ID) OVER () AS ALL_BENE_MBIs,
+ COALESCE(bene.IDR_UPDT_TS,bene.IDR_INSRT_TS) AS lastUpdated
+ FROM
+ IDRC_PRD.CMS_VDM_VIEW_MDCR_PRD.V2_MDCR_BENE bene
+ JOIN IDRC_PRD.CMS_VDM_VIEW_MDCR_PRD.V2_MDCR_BENE_HSTRY AS bene_history ON bene_history.BENE_SK = bene.BENE_XREF_EFCTV_SK
+ WHERE
+ bene.BENE_XREF_EFCTV_SK IN (
+ SELECT
+ bene.BENE_XREF_EFCTV_SK
+ FROM
+ IDRC_PRD.CMS_VDM_VIEW_MDCR_PRD.V2_MDCR_BENE bene
+ WHERE
+ bene.BENE_MBI_ID = 'mbi'
+ )
+ and bene_history.idr_trans_obslt_ts > '9999-12-30'
+ )
+SELECT
+ *
+FROM
+ bene_filtered
+WHERE
+ BENE_XREF_EFCTV_SK = BENE_SK;
+
+
+
+Query 2:
+Gets the effective dates of each MBI.
+WITH latest_bene_mbi AS (
+ SELECT
+ *,
+ ROW_NUMBER() OVER (PARTITION BY BENE_MBI_ID ORDER BY IDR_TRANS_EFCTV_TS DESC) AS rn
+ FROM
+ IDRC_PRD.CMS_VDM_VIEW_MDCR_PRD.V2_MDCR_BENE_MBI_ID
+ WHERE
+ BENE_MBI_ID IN ('mbi1', 'mbi2') --ALL_BENE_MBIs from above.
+)
+SELECT
+ *
+FROM
+ latest_bene_mbi
+WHERE
+ rn = 1;
diff --git a/apps/bfd-model/bfd-model-idr/maps/Patient-Helper.map b/apps/bfd-model/bfd-model-idr/maps/Patient-Helper.map
new file mode 100644
index 0000000000..3ec874b916
--- /dev/null
+++ b/apps/bfd-model/bfd-model-idr/maps/Patient-Helper.map
@@ -0,0 +1,43 @@
+map "https://bfd.cms.gov/MappingLanguage/Maps/Patient-Helper" = "patient-support-map"
+
+//Eventually these should be sourced automagically from IDR on startup. But until then!
+
+conceptmap "AdministrativeGender" {
+ prefix s = "https://hl7.org/fhir/string"
+ prefix t = "http://hl7.org/fhir/4.0/administrative-gender"
+
+ s:0 = t:unknown
+ s:1 = t:male
+ s:2 = t:female
+}
+
+conceptmap "PreferredContactLanguage" {
+ prefix s = "https://hl7.org/fhir/string"
+ prefix t = "urn:ietf:bcp:47"
+
+ s:"~" = t:unknown
+ s:ENG = t:en
+ s:SPA = t:es
+}
+
+conceptmap "USCDIRaceCode" {
+ prefix s = "https://hl7.org/fhir/string"
+ prefix t = "https://hl7.org/fhir/string"
+
+ s:1 = t:"2106-3"
+ s:2 = t:"2054-5"
+ s:3 = t:"2131-1"
+ s:4 = t:"2028-9"
+ s:6 = t:"1002-5"
+}
+
+conceptmap "USCDIRaceDisplay" {
+ prefix s = "https://hl7.org/fhir/string"
+ prefix t = "https://hl7.org/fhir/string"
+
+ s:1 = t:"White"
+ s:2 = t:"Black or African American"
+ s:3 = t:"Other Race"
+ s:4 = t:"Asian"
+ s:6 = t:"American Indian or Alaska Native"
+}
diff --git a/apps/bfd-model/bfd-model-idr/maps/patient.map b/apps/bfd-model/bfd-model-idr/maps/patient.map
new file mode 100644
index 0000000000..cc5cb633dd
--- /dev/null
+++ b/apps/bfd-model/bfd-model-idr/maps/patient.map
@@ -0,0 +1,136 @@
+//See this link for lexer order -> https://github.com/hapifhir/org.hl7.fhir.core/blob/c06051838f9bcd5fc0b552df960f5bf2fcf2dbb4/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/StructureMapUtilities.java#L757
+//Must appear in order map -> conceptmap -> uses -> imports -> groups
+map "https://bfd.cms.gov/MappingLanguage/Resources/Patient" = "BFD-Patient-Map"
+
+
+uses "https://bfd.cms.gov/fhir/StructureDefinition/BENE" alias Bene as source
+uses "http://hl7.org/fhir/StructureDefinition/BeneficiaryMBIIdentifier" alias BeneMBI as source
+//The first specified target is what the default output will output as the ResourceType
+uses "http://hl7.org/fhir/StructureDefinition/Patient" alias BFDPatient as target
+
+
+imports "https://bfd.cms.gov/MappingLanguage/Maps/Patient-Helper"
+
+//This refers to a patient where XREF_BENE_EFCTV_SK == BENE_SK. See notes for the other identity use case.
+
+group createPatient(source src: Bene, target patient: BFDPatient){
+
+ src -> patient.name = create('HumanName') as tgtName then{
+ src.BENE_1ST_NAME as firstName -> tgtName.given = firstName "Populate first name";
+ src.BENE_MIDL_NAME as middleName -> tgtName.given = middleName "Populate middle name";
+ src.BENE_LAST_NAME as lastName -> tgtName.family = lastName "Populate last name";
+ } "add name";
+ src.BENE_DOB as dob -> patient.birthDate = dob "set dob";
+ src.BENE_DEATH_DT as dod where (src.BENE_VRFY_DEATH_DAY_SW = "true") -> patient.deceased = dod "Set death date";
+ src.BENE_SEX_CD as gender -> patient.gender = translate(gender, 'https://bfd.cms.gov/MappingLanguage/Maps/Patient-Helper#AdministrativeGender', 'code');
+
+ //All except Unknown, Missing, or Hispanic
+ src.BENE_RACE_CD as race where (race != "~" and race != "0" and race != "5") -> patient.extension = create('Extension') as raceExtension then {
+ src -> raceExtension.url = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race" "Set race extension url";
+ src -> raceExtension.extension = create('Extension') as raceExtensionExtended then {
+ src -> raceExtensionExtended.url = "ombCategory" "Set race extension url";
+ src -> raceExtensionExtended.value = create('Coding') as valueCoding then{
+ src -> valueCoding.system = "urn:oid:2.16.840.1.113883.6.238" "Set race system urn";
+ src -> valueCoding.code = translate(race, 'https://bfd.cms.gov/MappingLanguage/Maps/Patient-Helper#USCDIRaceCode', "code") "Set code";
+ src -> valueCoding.display = translate(race, 'https://bfd.cms.gov/MappingLanguage/Maps/Patient-Helper#USCDIRaceDisplay', "code") "Set display";
+ } "Create Coding within sub-extension";
+ } "Create sub-extension for ombCategory";
+ src -> raceExtension.extension = create('Extension') as raceExtensionExtended then {
+ src -> raceExtensionExtended.url = "text" "Set race extension text url";
+ src -> raceExtensionExtended.valueString = translate(race, 'https://bfd.cms.gov/MappingLanguage/Maps/Patient-Helper#USCDIRaceDisplay','code') "set value string";
+ } "Create sub-extension for text display";
+ } "Create race extension";
+
+ //Missing or unknown
+ src.BENE_RACE_CD as race where (race = "~" or race = "0") -> patient.extension = create('Extension') as raceExtension then {
+ src -> raceExtension.url = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race" "Set race extension url";
+ src -> raceExtension.extension = create('Extension') as raceExtensionExtended then {
+ src -> raceExtensionExtended.url = "ombCategory" "Set race extension url";
+ src -> raceExtensionExtended.value = create('Coding') as valueCoding then{
+ src -> valueCoding.system = "http://terminology.hl7.org/CodeSystem/v3-NullFlavor" "Set race system urn";
+ src -> valueCoding.code = "UNK" "Set code";
+ src -> valueCoding.display = "Unknown" "Set display";
+ } "Create Coding within sub-extension";
+ } "Create sub-extension for ombCategory";
+ src -> raceExtension.extension = create('Extension') as raceExtensionExtended then {
+ src -> raceExtensionExtended.url = "text" "Set race extension text url";
+ src -> raceExtensionExtended.valueString = "Unknown" "Set display";
+ } "Create sub-extension for text display";
+ } "Create race extension";
+
+
+ src.BENE_RACE_CD as race where (race = "5") -> patient.extension = create('Extension') as ethnicityExtension then {
+ src -> ethnicityExtension.url="http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity" "Set ethnicity extension url";
+ src -> ethnicityExtension.extension = create('Extension') as ethnicityExtensionExtended then {
+ src -> ethnicityExtensionExtended.url = "ombCategory" "Set ethnicity extension url";
+ src -> ethnicityExtensionExtended.value = create('Coding') as valueCoding then{
+ src -> valueCoding.system = "urn:oid:2.16.840.1.113883.6.238" "Set ethnicity system urn";
+ src -> valueCoding.code = "2135-2" "Set code";
+ src -> valueCoding.display = "Hispanic or Latino" "Set display";
+ } "Create Coding within sub-extension";
+ } "Create sub-extension for ombCategory";
+ src -> ethnicityExtension.extension = create('Extension') as ethnicityExtensionExtended then {
+ src -> ethnicityExtensionExtended.url = "text" "Set ethnicity extension text url";
+ src -> ethnicityExtensionExtended.valueString = "Hispanic or Latino" "Set display";
+ } "Create sub-extension for text display";
+ } "create ethnicity extension";
+
+
+ src.BENE_SK as bene_sk -> patient.id = bene_sk "Assign BENE_SK as identifier.";
+
+ src.ALL_BENE_SKs as bene_sks where (bene_sks != src.XREF_EFCTV_BENE_SK) -> patient.link = create('BackboneElement') as patientLink then{
+ src -> patientLink.type = "replaces" "replaces type";
+ src -> patientLink.other = create('Reference') as tgtReference,
+ tgtReference.reference = append("Patient/",bene_sks),
+ tgtReference.display = bene_sks "Set BENE_SK";
+ } "Create Patient links";
+
+
+ src.mbi as bene_mbis -> patient.identifier = create('Identifier') as ptIdentifier then SetMBI(bene_mbis,ptIdentifier) "Set Bene MBIs";
+
+
+ src -> patient.meta = create('Meta') as tgtMeta then{
+ src.lastUpdated as lastUpdated -> tgtMeta.lastUpdated = lastUpdated "Set lastUpdated";
+ src -> tgtMeta.profile = "http://hl7.org/fhir/us/carin-bb/StructureDefinition/C4BB-Patient|2.0.0" "Set C4BB profile";
+ src -> tgtMeta.profile = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient|3.1.1" "Set US Core profile";
+ } "add metadata";
+
+ src -> patient.address = create('Address') as ptAddress then {
+ src.GEO_USPS_STATE_CD as stateCode -> ptAddress.state = stateCode "Set state code";
+ src.BENE_ZIP_CD as zipCode -> ptAddress.postalCode = zipCode "Set zip code";
+ src.BENE_LINE_1_ADR as addrLine where (addrLine.length()>0) -> ptAddress.line = addrLine "Set address line 1";
+ src.BENE_LINE_2_ADR as addrLine where (addrLine.length()>0) -> ptAddress.line = addrLine "Set address line 2";
+ src.BENE_LINE_3_ADR as addrLine where (addrLine.length()>0) -> ptAddress.line = addrLine "Set address line 3";
+ src.BENE_LINE_4_ADR as addrLine where (addrLine.length()>0) -> ptAddress.line = addrLine "Set address line 4";
+ src.BENE_LINE_5_ADR as addrLine where (addrLine.length()>0) -> ptAddress.line = addrLine "Set address line 5";
+ src.BENE_LINE_6_ADR as addrLine where (addrLine.length()>0) -> ptAddress.line = addrLine "Set address line 6";
+ src.GEO_ZIP_PLC_NAME as cityName -> ptAddress.city = cityName "Set city name";
+ } "Set patient address";
+
+ src -> patient.telecom = create('ContactPoint') as ptTele then{
+ src.BENE_PHNE_NUM as phoneNumber -> ptTele.value = phoneNumber "Set phone number";
+ src -> ptTele.use = "home" "Set phone number use";
+ src -> ptTele.system = "phone" "Set phone as system";
+ } "Set beneficary contact info";
+
+ src -> patient.communication = create('BackboneElement') as commsBackbone then{
+ src -> commsBackbone.language = create('CodeableConcept') as langCC then{
+ src.CNTCT_LANG_CD as langCode -> langCC.coding = translate(langCode,'https://bfd.cms.gov/MappingLanguage/Maps/Patient-Helper#PreferredContactLanguage','coding') "set coding";
+
+ }"Create CodeableConcept for Language.";
+ src -> commsBackbone.preferred=true "set preference as true";
+ } "Create backbone element for communication";
+}
+
+group SetMBI(source src : BeneMBI, target tgt : Identifier) {
+ src -> tgt.type = create('CodeableConcept') as idCC,
+ idCC.coding = create('Coding') as tempCode,
+ tempCode.system = "http://terminology.hl7.org/CodeSystem/v2-0203",
+ tempCode.code = "MB",
+ tgt.system = "http://hl7.org/fhir/sid/us-mbi" "Set identifier system and value";
+ src.BENE_MBI_ID as mbi -> tgt.value = mbi "Set identifier Value";
+ src -> tgt.period = create('Period') as tgtPeriod then {
+ src.BENE_MBI_EFCTV_DT as start-> tgtPeriod.start = start "Add MBI start date";
+ src.BENE_MBI_OBSLT_DT as end -> tgtPeriod.end = end "Add MBI end date.";
+ } "Mark start and end dates of MBI";
+}
diff --git a/apps/bfd-model/bfd-model-idr/sample-data/BeneficiarySample.json b/apps/bfd-model/bfd-model-idr/sample-data/BeneficiarySample.json
new file mode 100644
index 0000000000..7788575706
--- /dev/null
+++ b/apps/bfd-model/bfd-model-idr/sample-data/BeneficiarySample.json
@@ -0,0 +1,29 @@
+{
+ "resourceType": "Beneficiary",
+ "BENE_1ST_NAME": "Frankie",
+ "BENE_LAST_NAME": "Sheep",
+ "BENE_MIDL_NAME": "Le Petit Prince",
+ "BENE_DOB": "1995-03-11",
+ "BENE_DEATH_DT": "2024-03-11",
+ "BENE_VRFY_DEATH_DAY_SW": "true",
+ "mbi": [
+ {"BENE_MBI_ID":"AAA1AA0AA11","BENE_MBI_EFCTV_DT":"2017-05-11","BENE_MBI_OBSLT_DT":"2017-07-01"},
+ {"BENE_MBI_ID":"ABB2BB0BB22","BENE_MBI_EFCTV_DT":"2017-07-02"}],
+ "XREF_EFCTV_BENE_SK": "123456789",
+ "BENE_SK": "123456789",
+ "ALL_BENE_SKs": ["123456789","234567891"],
+ "lastUpdated": "2020-01-07T03:02:28.000000Z",
+ "GEO_USPS_STATE_CD": "TX",
+ "BENE_ZIP_CD": "77843",
+ "BENE_LINE_1_ADR": "600 John Kimbrough Blvd",
+ "BENE_LINE_2_ADR": "TEST for line 2",
+ "BENE_LINE_3_ADR": "",
+ "BENE_LINE_4_ADR": "",
+ "BENE_LINE_5_ADR": "",
+ "BENE_LINE_6_ADR": "",
+ "GEO_ZIP_PLC_NAME": "College Station",
+ "CNTCT_LANG_CD": "ENG",
+ "BENE_PHNE_NUM": "1-800-MEDICARE",
+ "BENE_SEX_CD": "2",
+ "BENE_RACE_CD": "5"
+}