diff --git a/README.md b/README.md index 7483d92..2e359cf 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ The HSK was built and tested with the following prerequisites: - [MarkLogic Data Hub Central v5.5.1](http://developer.marklogic.com/download/binaries/dhf/marklogic-data-hub-central-5.5.1.war) - MarkLogic Server >= v10.0-7 -### Installation Steps: +### Installation Steps > Note: Installation steps assume a MarkLogic Server user/role with sufficient privileges is specified. Refer to the MarkLogic Data Hub documentation if needed. diff --git a/build.gradle b/build.gradle index efb07e9..810c8f9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ buildscript { repositories { mavenLocal() - maven {url 'http://developer.marklogic.com/maven2/'} + maven {url 'https://developer.marklogic.com/maven2/'} jcenter() } @@ -20,7 +20,7 @@ plugins { id 'net.saliman.properties' version '1.4.6' // Data Hub plugin - id 'com.marklogic.ml-data-hub' version '5.5.1' + id 'com.marklogic.ml-data-hub' version '5.7.0' //Data services needs these id 'com.marklogic.ml-development-tools' version '5.4.0' @@ -30,7 +30,7 @@ repositories { maven {url "https://plugins.gradle.org/m2/"} mavenCentral() jcenter() - maven {url 'http://developer.marklogic.com/maven2/'} + maven {url 'https://developer.marklogic.com/maven2/'} if (project.hasProperty("testing")) { mavenLocal() } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4c5803d..6043638 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-bin.zip -zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/hub-internal-config/security/amps/deleteProvenance.json b/src/main/hub-internal-config/security/amps/deleteProvenance.json new file mode 100644 index 0000000..974f28e --- /dev/null +++ b/src/main/hub-internal-config/security/amps/deleteProvenance.json @@ -0,0 +1,6 @@ +{ + "local-name" : "deleteProvenance", + "document-uri" : "/data-hub/5/provenance/prov-lib.sjs", + "modules-database" : "%%mlModulesDbName%%", + "role" : [ "ps-internal" ] +} diff --git a/src/main/hub-internal-config/security/amps/migrate-provenance-record.json b/src/main/hub-internal-config/security/amps/migrate-provenance-record.json new file mode 100644 index 0000000..9717f6d --- /dev/null +++ b/src/main/hub-internal-config/security/amps/migrate-provenance-record.json @@ -0,0 +1,7 @@ +{ + "namespace" : "http://marklogic.com/datahub/migrate-prov", + "local-name" : "migrate-provenance", + "document-uri" : "/data-hub/5/provenance/migrate-provenance.xqy", + "modules-database" : "%%mlModulesDbName%%", + "role" : [ "ps-internal" ] +} \ No newline at end of file diff --git a/src/main/hub-internal-config/security/amps/update-provenance-record.json b/src/main/hub-internal-config/security/amps/update-provenance-record.json new file mode 100644 index 0000000..d81c0b3 --- /dev/null +++ b/src/main/hub-internal-config/security/amps/update-provenance-record.json @@ -0,0 +1,7 @@ +{ + "namespace" : "http://marklogic.com/data-hub/dh-provenance-services", + "local-name" : "dhps-document-update", + "document-uri" : "/data-hub/5/provenance/dh-provenance.xqy", + "modules-database" : "%%mlModulesDbName%%", + "role" : [ "ps-internal" ] +} diff --git a/src/main/hub-internal-config/security/amps/write-provenance-record.json b/src/main/hub-internal-config/security/amps/write-provenance-record.json new file mode 100644 index 0000000..4bb3a2d --- /dev/null +++ b/src/main/hub-internal-config/security/amps/write-provenance-record.json @@ -0,0 +1,7 @@ +{ + "namespace" : "http://marklogic.com/data-hub/dh-provenance-services", + "local-name" : "dhps-document-insert", + "document-uri" : "/data-hub/5/provenance/dh-provenance.xqy", + "modules-database" : "%%mlModulesDbName%%", + "role" : [ "ps-internal" ] +} diff --git a/src/main/hub-internal-config/security/privileges/data-hub-delete-provenance.json b/src/main/hub-internal-config/security/privileges/data-hub-delete-provenance.json new file mode 100644 index 0000000..cf0ad56 --- /dev/null +++ b/src/main/hub-internal-config/security/privileges/data-hub-delete-provenance.json @@ -0,0 +1,5 @@ +{ + "privilege-name": "data-hub-delete-provenance", + "action": "http://marklogic.com/data-hub/privileges/delete-provenance", + "kind": "execute" +} diff --git a/src/main/hub-internal-config/security/roles/data-hub-admin.json b/src/main/hub-internal-config/security/roles/data-hub-admin.json index 0cd42ac..f3ffe74 100644 --- a/src/main/hub-internal-config/security/roles/data-hub-admin.json +++ b/src/main/hub-internal-config/security/roles/data-hub-admin.json @@ -1,6 +1,6 @@ { "role-name": "data-hub-admin", - "description": "5.5.1: Permits actions pertaining to administering a Data Hub application", + "description": "5.7.0: Permits actions pertaining to administering a Data Hub application", "role": [ "data-hub-developer" ], diff --git a/src/main/hub-internal-config/security/roles/data-hub-common.json b/src/main/hub-internal-config/security/roles/data-hub-common.json index 39bb48e..3bba8fa 100644 --- a/src/main/hub-internal-config/security/roles/data-hub-common.json +++ b/src/main/hub-internal-config/security/roles/data-hub-common.json @@ -111,6 +111,11 @@ "privilege-name": "xdmp:xslt-invoke", "action": "http://marklogic.com/xdmp/privileges/xslt-invoke", "kind": "execute" + }, + { + "privilege-name": "xdmp:xslt-eval", + "action": "http://marklogic.com/xdmp/privileges/xslt-eval", + "kind": "execute" } ] } diff --git a/src/main/hub-internal-config/security/roles/data-hub-operator.json b/src/main/hub-internal-config/security/roles/data-hub-operator.json index 5fa11ad..374d67c 100644 --- a/src/main/hub-internal-config/security/roles/data-hub-operator.json +++ b/src/main/hub-internal-config/security/roles/data-hub-operator.json @@ -83,8 +83,8 @@ "kind": "execute" }, { - "privilege-name": "data-hub-prune-provenance", - "action": "http://marklogic.com/data-hub/privileges/prune-provenance", + "privilege-name": "data-hub-delete-provenance", + "action": "http://marklogic.com/data-hub/privileges/delete-provenance", "kind": "execute" } ] diff --git a/src/main/hub-internal-config/security/roles/hub-central-entity-model-reader.json b/src/main/hub-internal-config/security/roles/hub-central-entity-model-reader.json index 122a576..4d40e12 100644 --- a/src/main/hub-internal-config/security/roles/hub-central-entity-model-reader.json +++ b/src/main/hub-internal-config/security/roles/hub-central-entity-model-reader.json @@ -3,6 +3,7 @@ "description": "Permits reading entity models in Hub Central", "role": [ "hub-central-user", + "data-hub-common-writer", "data-hub-entity-model-reader" ] } diff --git a/src/main/hub-internal-config/security/roles/hub-central-mapping-reader.json b/src/main/hub-internal-config/security/roles/hub-central-mapping-reader.json index f9eedda..4390920 100644 --- a/src/main/hub-internal-config/security/roles/hub-central-mapping-reader.json +++ b/src/main/hub-internal-config/security/roles/hub-central-mapping-reader.json @@ -4,7 +4,8 @@ "role": [ "hub-central-user", "data-hub-entity-model-reader", - "data-hub-mapping-reader" + "data-hub-mapping-reader", + "data-hub-step-definition-reader" ], "privilege": [ { diff --git a/src/main/hub-internal-config/triggers/ml-dh-draft-entity-validate-create.json b/src/main/hub-internal-config/triggers/ml-dh-draft-entity-validate-create.json new file mode 100644 index 0000000..fb5c80b --- /dev/null +++ b/src/main/hub-internal-config/triggers/ml-dh-draft-entity-validate-create.json @@ -0,0 +1,39 @@ +{ + "name": "ml-dh-draft-entity-validate-create", + "description": "MarkLogic Data Hub draft entity model creation validation pre-commit trigger", + "event": { + "data-event": { + "collection-scope": { + "uri": "http://marklogic.com/entity-services/models/draft" + }, + "document-content": { + "update-kind": "create" + }, + "when": "pre-commit" + } + }, + "module": "data-hub/4/triggers/entity-model-validate-trigger.xqy", + "module-db": "%%mlModulesDbName%%", + "module-root": "/", + "enabled": true, + "recursive": true, + "task-priority": "normal", + "permission": [ + { + "role-name": "%%mlFlowDeveloperRole%%", + "capability": "update" + }, + { + "role-name": "%%mlFlowOperatorRole%%", + "capability": "read" + }, + { + "role-name": "data-hub-developer", + "capability": "update" + }, + { + "role-name": "data-hub-common", + "capability": "read" + } + ] +} diff --git a/src/main/hub-internal-config/triggers/ml-dh-draft-entity-validate-modify.json b/src/main/hub-internal-config/triggers/ml-dh-draft-entity-validate-modify.json new file mode 100644 index 0000000..d516437 --- /dev/null +++ b/src/main/hub-internal-config/triggers/ml-dh-draft-entity-validate-modify.json @@ -0,0 +1,39 @@ +{ + "name": "ml-dh-draft-entity-validate-modify", + "description": "MarkLogic Data Hub draft entity model update validation pre-commit trigger", + "event": { + "data-event": { + "collection-scope": { + "uri": "http://marklogic.com/entity-services/models/draft" + }, + "document-content": { + "update-kind": "modify" + }, + "when": "pre-commit" + } + }, + "module": "data-hub/4/triggers/entity-model-validate-trigger.xqy", + "module-db": "%%mlModulesDbName%%", + "module-root": "/", + "enabled": true, + "recursive": true, + "task-priority": "normal", + "permission": [ + { + "role-name": "%%mlFlowDeveloperRole%%", + "capability": "update" + }, + { + "role-name": "%%mlFlowOperatorRole%%", + "capability": "read" + }, + { + "role-name": "data-hub-developer", + "capability": "update" + }, + { + "role-name": "data-hub-common", + "capability": "read" + } + ] +} diff --git a/src/main/hub-internal-config/triggers/ml-dh-entity-validate-create.json b/src/main/hub-internal-config/triggers/ml-dh-entity-validate-create.json index 818912d..228ad1a 100644 --- a/src/main/hub-internal-config/triggers/ml-dh-entity-validate-create.json +++ b/src/main/hub-internal-config/triggers/ml-dh-entity-validate-create.json @@ -17,7 +17,7 @@ "module-root": "/", "enabled": true, "recursive": true, - "task-priority": "normal", + "task-priority": "higher", "permission": [ { "role-name": "%%mlFlowDeveloperRole%%", diff --git a/src/main/hub-internal-config/triggers/ml-dh-entity-validate-modify.json b/src/main/hub-internal-config/triggers/ml-dh-entity-validate-modify.json index c4cd3bd..5b84ad9 100644 --- a/src/main/hub-internal-config/triggers/ml-dh-entity-validate-modify.json +++ b/src/main/hub-internal-config/triggers/ml-dh-entity-validate-modify.json @@ -17,7 +17,7 @@ "module-root": "/", "enabled": true, "recursive": true, - "task-priority": "normal", + "task-priority": "higher", "permission": [ { "role-name": "%%mlFlowDeveloperRole%%", diff --git a/src/main/ml-config/database-fields/final-database.xml b/src/main/ml-config/database-fields/final-database.xml index 5c8b4c9..b861552 100644 --- a/src/main/ml-config/database-fields/final-database.xml +++ b/src/main/ml-config/database-fields/final-database.xml @@ -1,3 +1,4 @@ + %%mlFinalDbName%% @@ -9,7 +10,7 @@ datahubCreatedOn - + off false true @@ -17,14 +18,14 @@ false false false - - - - + + + + datahubCreatedByJob - + off true true @@ -32,9 +33,9 @@ false false false - - - + + + - @@ -44,7 +45,7 @@ datahubCreatedByStep - + off true true @@ -52,9 +53,9 @@ false false false - - - + + + _ @@ -68,7 +69,7 @@ datahubCreatedInFlow - + off true true @@ -76,10 +77,10 @@ false false false - - - - + + + + datahubSourceName @@ -94,10 +95,10 @@ false false false - - - - + + + + datahubSourceType @@ -112,16 +113,16 @@ false false false - - - - + + + + dateTime - + datahubCreatedOn false reject diff --git a/src/main/ml-modules/root/lib/interceptors/flat-to-multiple.sjs b/src/main/ml-modules/root/lib/interceptors/flat-to-multiple.sjs new file mode 100644 index 0000000..8165730 --- /dev/null +++ b/src/main/ml-modules/root/lib/interceptors/flat-to-multiple.sjs @@ -0,0 +1,51 @@ +'use strict'; +const { getTraceHelpers } = require('/lib/util/trace-helpers.sjs'); + +var contentArray; +var options; + +var entireRecord; +var entries; + +const { trace, traceObject } = getTraceHelpers('flat-to-multiple'); + +traceObject(contentArray); +traceObject(options); +traceObject(entries); + +// Add default values to variables +entireRecord = entireRecord || false; + +function flatToMultipleEntries(nodes, breakouts) { + return nodes.reduce( + (nodesAcc, node) => nodesAcc.concat(breakouts.reduce( + (acc, breakout) => acc.concat(node.xpath(breakout.xpath).toArray().map(source => ({ type: breakout.type, source }))), + [], + )), + [], + ); +} + +/** + * Wraps `flatToMultipleEntries` in a way where DHF users can provide multiple specs for unflattening fields in a single + * call to this pre-step interceptor. + */ +contentArray.forEach(content => { + const doc = content.value; + const envelope = (doc.root || doc.toObject()).envelope; + const instance = envelope.instance; + + const record = entireRecord ? doc : fn.head(doc.xpath('envelope/instance')); + const results = {}; + + for (const { dest, sourcedFrom, breakouts } of entries) { + results[dest] = flatToMultipleEntries(sourcedFrom ? record.xpath(sourcedFrom).toArray() : [record], breakouts); + } + + const newInstance = { + ...instance, + ...results, + }; + + content.value = new NodeBuilder().addNode(entireRecord ? { envelope: { ...envelope, instance: newInstance } } : newInstance).toNode(); +}); diff --git a/src/main/ml-modules/root/lib/interceptors/insert-claim-lines.sjs b/src/main/ml-modules/root/lib/interceptors/insert-claim-lines.sjs new file mode 100644 index 0000000..c221ab7 --- /dev/null +++ b/src/main/ml-modules/root/lib/interceptors/insert-claim-lines.sjs @@ -0,0 +1,79 @@ +'use strict'; +const { getTraceHelpers } = require('/lib/util/trace-helpers.sjs'); + +var contentArray; +var options; + +var claimIdPath; +var placeOfServiceIdPath; +var linesDestination; +var linesTotalAmountDestination; + +const { trace, traceObject } = getTraceHelpers('insert-claim-lines'); + +traceObject(contentArray); +traceObject(options); + +function claimGetOrganizationLocation(placeOfServiceId) { + // Performance note: we use a path index to avoid building a larger index with every Id in the system. But a simple jsonPropertyRangeQuery on an Id will also work + // It is NOT a best practice to use jsonPropertyValueQuery for Id values in a batch; that accesses many different index structures + // By using a range index, a single range index structure is memory mapped and available without excessive I/O + const search = cts.search( + cts.andQuery([ + cts.jsonPropertyValueQuery("Id", placeOfServiceId), + cts.collectionQuery("OrganizationIngest") + ]) + ); + + return search.toArray().map(hit => hit.root.envelope.instance); +} + +function claimGetLines(claimId) { + const lines = []; + const amounts = []; + + const search = cts.search( + cts.andQuery([ + cts.jsonPropertyValueQuery("CLAIMID", claimId), + cts.collectionQuery("ClaimTransactionIngest") + ]) + ); + + for (const hit of search) { + const claimLine = { + ...hit.root.envelope.instance, + + locations: claimGetOrganizationLocation(hit.xpath(['envelope/instance', placeOfServiceIdPath].join('/')).toArray()[0]) + }; + + lines.push(claimLine); + + const amt = claimLine.AMOUNT; + if (fn.stringLength(amt) > 0 && xs.decimal(amt)) { + amounts.push(amt); + } + } + + return { + [linesDestination]: lines, + [linesTotalAmountDestination]: fn.sum(amounts), + }; +} + +/** + * Performs all mapping for claim lines, claim line total amount, and claim line location for a given claim and inserts + * it into the instance provided to the mapping step + */ +contentArray.forEach(content => { + const doc = content.value; + + const claimId = doc.xpath(['envelope/instance', claimIdPath].join('/')).toArray()[0]; + + const result = { + ...doc.root.envelope.instance, + + ...claimGetLines(claimId), + }; + + content.value = new NodeBuilder().addNode(result).toNode(); +}); diff --git a/src/test/ml-modules/root/test/suites/EsToTrueFhirSuite/removeSanctions.sjs b/src/test/ml-modules/root/test/suites/EsToTrueFhirSuite/removeSanctions.sjs index 5df5083..11ab7bd 100644 --- a/src/test/ml-modules/root/test/suites/EsToTrueFhirSuite/removeSanctions.sjs +++ b/src/test/ml-modules/root/test/suites/EsToTrueFhirSuite/removeSanctions.sjs @@ -13,10 +13,10 @@ let contentArray = [{ const flowName = "Provider"; const runtimeOptions = {}; -const result = flowApi.runFlowStepOnContent(flowName, "2", contentArray, runtimeOptions); +const result = flowApi.runFlowStepOnContent(flowName, "3", contentArray, runtimeOptions); const assertions = [ - test.assertEqual("completed step 2", result.stepResponse.status), + test.assertEqual("completed step 3", result.stepResponse.status), test.assertEqual(1, result.contentArray.length) ]; @@ -38,4 +38,4 @@ assertions.push( test.assertFalse('custom__sanction' in fhirPractitioner) ); -assertions \ No newline at end of file +assertions diff --git a/src/test/ml-modules/root/test/suites/PractitionerRoleSuite/test.sjs b/src/test/ml-modules/root/test/suites/PractitionerRoleSuite/test.sjs index b993439..0f31272 100644 --- a/src/test/ml-modules/root/test/suites/PractitionerRoleSuite/test.sjs +++ b/src/test/ml-modules/root/test/suites/PractitionerRoleSuite/test.sjs @@ -45,10 +45,10 @@ const contentArray = [{ const flowName = "Provider"; const runtimeOptions = {}; -const result = flowApi.runFlowStepOnContent(flowName, "3", contentArray, runtimeOptions); +const result = flowApi.runFlowStepOnContent(flowName, "4", contentArray, runtimeOptions); const assertions = [ - test.assertEqual("completed step 3", result.stepResponse.status), + test.assertEqual("completed step 4", result.stepResponse.status), test.assertEqual(1, result.contentArray.length) ]; @@ -62,4 +62,4 @@ assertions.push( test.assertEqual("doctor", providerRole.code__code, "General Practice -> doctor") ); -assertions \ No newline at end of file +assertions diff --git a/src/test/ml-modules/root/test/suites/PractitionerSuite/test.sjs b/src/test/ml-modules/root/test/suites/PractitionerSuite/test.sjs index 09d6aff..f2dc610 100644 --- a/src/test/ml-modules/root/test/suites/PractitionerSuite/test.sjs +++ b/src/test/ml-modules/root/test/suites/PractitionerSuite/test.sjs @@ -45,10 +45,10 @@ const contentArray = [{ const flowName = "Provider"; const runtimeOptions = {}; -const result = flowApi.runFlowStepOnContent(flowName, "2", contentArray, runtimeOptions); +const result = flowApi.runFlowStepOnContent(flowName, "3", contentArray, runtimeOptions); const assertions = [ - test.assertEqual("completed step 2", result.stepResponse.status), + test.assertEqual("completed step 3", result.stepResponse.status), test.assertEqual(1, result.contentArray.length) ]; diff --git a/src/test/ml-modules/root/test/suites/ProviderLocationSuite/test.sjs b/src/test/ml-modules/root/test/suites/ProviderLocationSuite/test.sjs index c61fac4..bd5444c 100644 --- a/src/test/ml-modules/root/test/suites/ProviderLocationSuite/test.sjs +++ b/src/test/ml-modules/root/test/suites/ProviderLocationSuite/test.sjs @@ -45,10 +45,10 @@ const contentArray = [{ const flowName = "Provider"; const runtimeOptions = {}; -const result = flowApi.runFlowStepOnContent(flowName, "4", contentArray, runtimeOptions); +const result = flowApi.runFlowStepOnContent(flowName, "5", contentArray, runtimeOptions); const assertions = [ - test.assertEqual("completed step 4", result.stepResponse.status), + test.assertEqual("completed step 5", result.stepResponse.status), test.assertEqual(1, result.contentArray.length) ]; diff --git a/src/test/ml-modules/root/test/suites/SanctionSuite/test.sjs b/src/test/ml-modules/root/test/suites/SanctionSuite/test.sjs index a143849..3d9cb88 100644 --- a/src/test/ml-modules/root/test/suites/SanctionSuite/test.sjs +++ b/src/test/ml-modules/root/test/suites/SanctionSuite/test.sjs @@ -14,10 +14,10 @@ let contentArray = [{ const flowName = "Provider"; const runtimeOptions = {}; -const result = flowApi.runFlowStepOnContent(flowName, "2", contentArray, runtimeOptions); +const result = flowApi.runFlowStepOnContent(flowName, "3", contentArray, runtimeOptions); const assertions = [ - test.assertEqual("completed step 2", result.stepResponse.status), + test.assertEqual("completed step 3", result.stepResponse.status), test.assertEqual(1, result.contentArray.length) ]; diff --git a/steps/mapping/ClaimMapping.step.json b/steps/mapping/ClaimMapping.step.json index 7a04a25..158819f 100644 --- a/steps/mapping/ClaimMapping.step.json +++ b/steps/mapping/ClaimMapping.step.json @@ -18,6 +18,16 @@ "targetDatabase": "data-hub-FINAL", "headers": { }, "interceptors": [ + { + "path": "/lib/interceptors/insert-claim-lines.sjs", + "when": "beforeMain", + "vars": { + "claimIdPath": "Id/normalize-space()", + "placeOfServiceIdPath": "PLACEOFSERVICE/normalize-space()", + "linesDestination": "claimLines", + "linesTotalAmountDestination": "claimLinesTotalAmount" + } + }, { "path": "/lib/interceptors/claim-mapping.sjs", "when": "beforeContentPersisted" @@ -178,7 +188,7 @@ "targetEntityType": "#/definitions/Diagnosis" }, "procedure": { - "sourcedFrom": "claimGetLines(Id/normalize-space())", + "sourcedFrom": "claimLines", "properties": { "sequence": { "sourcedFrom": "position()" @@ -187,10 +197,10 @@ "sourcedFrom": "\"primary\"" }, "date": { - "sourcedFrom": "substring-before(./claimLine/TODATE, \"T\")" + "sourcedFrom": "substring-before(./TODATE, \"T\")" }, "code__procedureCodeableConcept__SNOMED": { - "sourcedFrom": "./claimLine/PROCEDURECODE" + "sourcedFrom": "./PROCEDURECODE" } }, "targetEntityType": "#/definitions/Procedure" @@ -223,10 +233,10 @@ "targetEntityType": "#/definitions/Insurance" }, "total": { - "sourcedFrom": "claimGetLinesTotalAmount(Id/normalize-space())", + "sourcedFrom": "claimLinesTotalAmount", "properties": { "value": { - "sourcedFrom": "./claimAmountTotal/data()" + "sourcedFrom": "./data()" }, "currency": { "sourcedFrom": "valueSetLookup(\"USD\", \"currencies\", '')/code" @@ -235,7 +245,7 @@ "targetEntityType": "#/definitions/Money" }, "item": { - "sourcedFrom": "claimGetLines(Id/normalize-space())", + "sourcedFrom": "claimLines", "properties": { "sequence": { "sourcedFrom": "position()" @@ -247,22 +257,22 @@ "sourcedFrom": "position()" }, "diagnosisSequence": { - "sourcedFrom": "./claimLine/(DIAGNOSISREF1|DIAGNOSISREF2|DIAGNOSISREF3|DIAGNOSISREF4)[string-length(./normalize-space()) > 0]" + "sourcedFrom": "./(DIAGNOSISREF1|DIAGNOSISREF2|DIAGNOSISREF3|DIAGNOSISREF4)[string-length(./normalize-space()) > 0]" }, "informationSequence": { "sourcedFrom": "1" }, "servicedDate": { - "sourcedFrom": "substring-before(./claimLine/TODATE/normalize-space(), \"T\")" + "sourcedFrom": "substring-before(./TODATE/normalize-space(), \"T\")" }, "servicedPeriod": { "sourcedFrom": ".", "properties": { "start": { - "sourcedFrom": "./claimLine/FROMDATE/normalize-space()" + "sourcedFrom": "./FROMDATE/normalize-space()" }, "end": { - "sourcedFrom": "./claimLine/TODATE/normalize-space()" + "sourcedFrom": "./TODATE/normalize-space()" } }, "targetEntityType": "#/definitions/Period" @@ -274,25 +284,25 @@ "sourcedFrom": "\"99555\"" }, "locationAddress": { - "sourcedFrom": "claimGetOrganizationLocation(./claimLine/PLACEOFSERVICE/normalize-space())", + "sourcedFrom": "./locations", "properties": { "city": { - "sourcedFrom": "./organization/CITY/normalize-space()" + "sourcedFrom": "./CITY/normalize-space()" }, "state": { - "sourcedFrom": "./organization/STATE/normalize-space()" + "sourcedFrom": "./STATE/normalize-space()" }, "postalCode": { - "sourcedFrom": "./organization/ZIP/normalize-space()" + "sourcedFrom": "./ZIP/normalize-space()" }, "country": { "sourcedFrom": "\"US\"" }, "line": { - "sourcedFrom": "./organization/ADDRESS/normalize-space()" + "sourcedFrom": "./ADDRESS/normalize-space()" }, "text": { - "sourcedFrom": "string-join((./organization/NAME/normalize-space(), ./organization/ADDRESS/normalize-space(), ./organization/CITY/normalize-space(), ./organization/STATE/normalize-space(), ./organization/ZIP/normalize-space()), \", \")" + "sourcedFrom": "string-join((./NAME/normalize-space(), ./ADDRESS/normalize-space(), ./CITY/normalize-space(), ./STATE/normalize-space(), ./ZIP/normalize-space()), \", \")" }, "use": { "sourcedFrom": "valueSetLookup(\"work\", \"address-use\", '')/code" @@ -307,7 +317,7 @@ "sourcedFrom": ".", "properties": { "reference": { - "sourcedFrom": "concat(\"Location/\", ./claimLine/PLACEOFSERVICE/normalize-space())" + "sourcedFrom": "concat(\"Location/\", ./PLACEOFSERVICE/normalize-space())" }, "type": { "sourcedFrom": "\"Location\"" @@ -319,7 +329,7 @@ "sourcedFrom": ".", "properties": { "value": { - "sourcedFrom": "./claimLine/UNITS[./normalize-space() ne \"\"]" + "sourcedFrom": "./UNITS[./normalize-space() ne \"\"]" }, "unit": { "sourcedFrom": "" @@ -334,7 +344,7 @@ "sourcedFrom": "valueSetLookup(\"USD\", \"currencies\", '')/code" }, "value": { - "sourcedFrom": "if (./claimLine/UNITAMOUNT[./normalize-space() ne \"\"]) then ./claimLine/UNITAMOUNT/normalize-space() else 0" + "sourcedFrom": "if (./UNITAMOUNT[./normalize-space() ne \"\"]) then ./UNITAMOUNT/normalize-space() else 0" } }, "targetEntityType": "#/definitions/Money" @@ -343,7 +353,7 @@ "sourcedFrom": ".", "properties": { "value": { - "sourcedFrom": "if (./claimLine/AMOUNT[./normalize-space() ne \"\"]) then ./claimLine/AMOUNT/normalize-space() else 0" + "sourcedFrom": "if (./AMOUNT[./normalize-space() ne \"\"]) then ./AMOUNT/normalize-space() else 0" }, "currency": { "sourcedFrom": "valueSetLookup(\"USD\", \"currencies\", '')/code" diff --git a/steps/mapping/PatientMapping.step.json b/steps/mapping/PatientMapping.step.json index 14eea78..e1c1979 100644 --- a/steps/mapping/PatientMapping.step.json +++ b/steps/mapping/PatientMapping.step.json @@ -20,6 +20,29 @@ "targetDatabase": "data-hub-FINAL", "headers": { }, "interceptors": [ + { + "path": "/lib/interceptors/flat-to-multiple.sjs", + "when": "beforeMain", + "vars": { + "entireRecord": false, + "entries": [ + { + "dest": "names", + "sourcedFrom": ".", + "breakouts": [ + { + "type": "official", + "xpath": "LAST[string-length(normalize-space(.)) gt 0]" + }, + { + "type": "maiden", + "xpath": "MAIDEN[string-length(normalize-space(.)) gt 0]" + } + ] + } + ] + } + }, { "path": "/lib/interceptors/patient-mapping.sjs", "when": "beforeContentPersisted" @@ -36,19 +59,19 @@ "uriExpression": "$URI", "properties": { "name": { - "sourcedFrom": "flatToMultipleEntries(/,'{\"breakout\": [{\"type\": \"official\", \"xpath\": \"./LAST[string-length(normalize-space(.)) gt 0]\"}, {\"type\": \"maiden\", \"xpath\": \"./MAIDEN[string-length(normalize-space(.)) gt 0]\"}]}')", + "sourcedFrom": "names", "properties": { "family": { "sourcedFrom": "source/normalize-space()" }, "given": { - "sourcedFrom": "//FIRST/normalize-space()" + "sourcedFrom": "/FIRST/normalize-space()" }, "suffix": { - "sourcedFrom": "//SUFFIX/normalize-space()" + "sourcedFrom": "/SUFFIX/normalize-space()" }, "prefix": { - "sourcedFrom": "//PREFIX/normalize-space()" + "sourcedFrom": "/PREFIX/normalize-space()" }, "use": { "sourcedFrom": "type/normalize-space()"