diff --git a/pom.xml b/pom.xml
index 5c017bef..451cb04d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,7 +16,7 @@
UTF-8
1.8
3.11.0
- 1.30.0
+ 1.31.0-SNAPSHOT
5.8.2
3.1.2
1.9.1
diff --git a/src/main/groovy/projects/patientfinder/procedureWithMapping.groovy b/src/main/groovy/projects/patientfinder/procedureWithMapping.groovy
new file mode 100644
index 00000000..74e3a98b
--- /dev/null
+++ b/src/main/groovy/projects/patientfinder/procedureWithMapping.groovy
@@ -0,0 +1,144 @@
+package projects.patientfinder
+
+import ca.uhn.fhir.model.api.TemporalPrecisionEnum
+import de.kairos.fhir.centraxx.metamodel.CrfTemplateField
+import de.kairos.fhir.centraxx.metamodel.Episode
+import de.kairos.fhir.centraxx.metamodel.LaborFinding
+import de.kairos.fhir.centraxx.metamodel.LaborFindingLaborValue
+import de.kairos.fhir.centraxx.metamodel.LaborMapping
+import de.kairos.fhir.centraxx.metamodel.OrganisationUnit
+import de.kairos.fhir.centraxx.metamodel.ValueReference
+import org.hl7.fhir.r4.model.Procedure
+
+import static de.kairos.fhir.centraxx.metamodel.AbstractCode.CODE
+import static de.kairos.fhir.centraxx.metamodel.AbstractIdContainer.PSN
+import static de.kairos.fhir.centraxx.metamodel.MultilingualEntry.LANG
+import static de.kairos.fhir.centraxx.metamodel.MultilingualEntry.VALUE
+import static de.kairos.fhir.centraxx.metamodel.RootEntities.medProcedure
+
+/**
+ * Represented by CXX MedProcedure
+ * Exports extra data that is documented in a measurement profile with code ADDITIONAL_PROCEDURE_DATA
+ * The measurement profile 2 parameters:
+ * 1. Code: "DEPARTMENT", Type: SingleChoice on MasterDataCatalog of all OrgUnits
+ * 2. Code: "IS_SURGICAL_PROCEDURE", Type: boolean
+ *
+ */
+procedure {
+ id = "Procedure/" + context.source[medProcedure().id()]
+
+ status = Procedure.ProcedureStatus.UNKNOWN
+ //println(context.source)
+
+ final def mapping = context.source[medProcedure().laborMappings()].find {
+ it[LaborMapping.LABOR_FINDING][LaborFinding.LABOR_METHOD][CODE] == "ADDITIONAL_PROCEDURE_DATA"
+ }
+
+ if (mapping != null) {
+ final def departmentValue = mapping[LaborMapping.LABOR_FINDING][LaborFinding.LABOR_FINDING_LABOR_VALUES].find {
+ it[LaborFindingLaborValue.CRF_TEMPLATE_FIELD][CrfTemplateField.LABOR_VALUE][CODE] == "DEPARTMENT"
+ }
+
+ final def procedureType = mapping[LaborMapping.LABOR_FINDING][LaborFinding.LABOR_FINDING_LABOR_VALUES].find {
+ it[LaborFindingLaborValue.CRF_TEMPLATE_FIELD][CrfTemplateField.LABOR_VALUE][CODE] == "IS_SURGICAL_PROCEDURE"
+ }
+
+ println(departmentValue)
+ println(procedureType)
+
+
+ if (departmentValue != null) {
+ println(departmentValue[LaborFindingLaborValue.MULTI_VALUE_REFERENCES])
+ departmentValue[LaborFindingLaborValue.MULTI_VALUE_REFERENCES].each { final def valRef ->
+ performer {
+ onBehalfOf {
+ reference = "Organization/" + valRef[ValueReference.ORGANIZATION_VALUE][OrganisationUnit.ID]
+ }
+ }
+ }
+ }
+
+ if (procedureType != null && procedureType[LaborFindingLaborValue.BOOLEAN_VALUE] == true) {
+ category {
+ coding {
+ system = "http://hl7.org/fhir/ValueSet/procedure-category"
+ code = "387713003"
+ display = "Surgical procedure (procedure)"
+ }
+ }
+ }
+ }
+
+ code {
+ if (context.source[medProcedure().opsEntry()]) {
+ coding {
+ system = "https://fhir.centraxx.de/system/" + context.source[medProcedure().opsEntry().catalogue().name()]
+ version = context.source[medProcedure().opsEntry().catalogue().catalogueVersion()]
+ code = context.source[medProcedure().opsEntry().code()] as String
+ display = context.source[medProcedure().opsEntry().preferredLong()] as String
+ }
+ }
+
+ if (context.source[medProcedure().userDefinedCatalogEntry()]) {
+ coding {
+ system = "https://fhir.centraxx.de/system/" + context.source[medProcedure().userDefinedCatalogEntry().catalog().code()]
+ version = context.source[medProcedure().userDefinedCatalogEntry().catalog().version()]
+ code = context.source[medProcedure().userDefinedCatalogEntry().code()] as String
+ display = context.source[medProcedure().userDefinedCatalogEntry().nameMultilingualEntries()]?.find { it[LANG] == "en" }?.getAt(VALUE)
+ }
+ }
+
+ if (context.source[medProcedure().procedureCode()]) {
+ coding {
+ code = context.source[medProcedure().procedureCode()] as String
+ display = context.source[medProcedure().procedureText()] as String
+ }
+ }
+ }
+
+ if (context.source[medProcedure().procedureDate().date()]) {
+ performedDateTime {
+ date = normalizeDate(context.source[medProcedure().procedureDate().date()] as String)
+ precision = TemporalPrecisionEnum.DAY.toString()
+ }
+ }
+
+ final String opsNote = context.source[medProcedure().comments()] as String
+ if (opsNote) {
+ note {
+ text = opsNote
+ }
+ }
+
+ subject {
+ reference = "Patient/" + context.source[medProcedure().patientContainer().id()]
+ }
+
+ if (!isFakeEpisode(context.source[medProcedure().episode()])) {
+ encounter {
+ reference = "Encounter/" + context.source[medProcedure().episode().id()]
+ }
+ }
+}
+
+static boolean isFakeEpisode(final def episode) {
+ if (episode == null) {
+ return true
+ }
+
+ if (["SACT", "COSD"].contains(episode[Episode.ENTITY_SOURCE])) {
+ return true
+ }
+
+ final def fakeId = episode[Episode.ID_CONTAINER]?.find { (it[PSN] as String).toUpperCase().startsWith("FAKE") }
+ return fakeId != null
+}
+
+/**
+ * removes milli seconds and time zone.
+ * @param dateTimeString the date time string
+ * @return the result might be something like "1989-01-15T00:00:00"
+ */
+static String normalizeDate(final String dateTimeString) {
+ return dateTimeString != null ? dateTimeString.substring(0, 19) : null
+}
diff --git a/src/main/groovy/projects/patientfinder/specimen.groovy b/src/main/groovy/projects/patientfinder/specimen.groovy
index 571c813b..80eca1fe 100644
--- a/src/main/groovy/projects/patientfinder/specimen.groovy
+++ b/src/main/groovy/projects/patientfinder/specimen.groovy
@@ -2,6 +2,10 @@ package projects.patientfinder
import de.kairos.centraxx.fhir.r4.utils.FhirUrls
import de.kairos.fhir.centraxx.metamodel.AbstractSample
+import de.kairos.fhir.centraxx.metamodel.CrfTemplateField
+import de.kairos.fhir.centraxx.metamodel.LaborFinding
+import de.kairos.fhir.centraxx.metamodel.LaborFindingLaborValue
+import de.kairos.fhir.centraxx.metamodel.LaborMapping
import static de.kairos.fhir.centraxx.metamodel.AbstractCode.CODE
import static de.kairos.fhir.centraxx.metamodel.AbstractIdContainer.ID_CONTAINER_TYPE
@@ -9,10 +13,16 @@ import static de.kairos.fhir.centraxx.metamodel.AbstractIdContainer.PSN
import static de.kairos.fhir.centraxx.metamodel.IdContainerType.DECISIVE
import static de.kairos.fhir.centraxx.metamodel.RootEntities.sample
+/**
+ * Export additional data via a SAMPLETYPELABORMAPPING that links to a finding
+ * with LABORMETHOD code "ADDITIONAL_SAMPLE_DATA". If that finding
+ * contains a value for a parameter with code "COLLECTION_METHOD", the value
+ * is exported to collection.method.coding.code
+ */
specimen {
id = "Specimen/" + context.source[sample().id()]
-
+ println(context.source)
context.source[sample().idContainer()].each { final idContainer ->
final boolean isDecisive = idContainer[ID_CONTAINER_TYPE]?.getAt(DECISIVE)
if (isDecisive) {
@@ -28,6 +38,7 @@ specimen {
}
}
+
type {
coding {
system = FhirUrls.System.Sample.SampleKind.BASE_URL
@@ -41,12 +52,17 @@ specimen {
final def parentSample = context.source[sample().parent()]
- if (parentSample != null){
+ if (parentSample != null) {
parent {
reference = "Specimen/" + parentSample[AbstractSample.ID]
}
}
+ final def finding = context.source[sample().laborMappings()].find {
+ it[LaborMapping.LABOR_FINDING][LaborFinding.LABOR_METHOD][CODE] == "ADDITIONAL_SAMPLE_DATA"
+ }
+
+
collection {
collectedDateTime {
date = context.source[sample().samplingDate().date()]
@@ -55,5 +71,19 @@ specimen {
unit = context.source[sample().initialAmount().unit()]
}
}
+
+ if (finding != null) {
+ final def collectionMethod = finding[LaborMapping.LABOR_FINDING][LaborFinding.LABOR_FINDING_LABOR_VALUES].find {
+ it[LaborFindingLaborValue.CRF_TEMPLATE_FIELD][CrfTemplateField.LABOR_VALUE][CODE] == "COLLECTION_METHOD"
+ }
+
+ if (collectionMethod != null) {
+ method {
+ coding {
+ code = collectionMethod[LaborFindingLaborValue.STRING_VALUE]
+ }
+ }
+ }
+ }
}
}
\ No newline at end of file