Skip to content

Commit

Permalink
Merge pull request #55 from kairos-fhir/FNUSA-enhancements
Browse files Browse the repository at this point in the history
Fnusa enhancements
  • Loading branch information
kairosjonas authored Apr 5, 2024
2 parents 00ec776 + 447a2d3 commit b56f53a
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 3 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.compiler.level>1.8</java.compiler.level>
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
<kairos-fhir-dsl.version>1.30.0</kairos-fhir-dsl.version>
<kairos-fhir-dsl.version>1.31.0-SNAPSHOT</kairos-fhir-dsl.version>
<junit-jupiter.version>5.8.2</junit-jupiter.version>
<maven-surefire-plugin.version>3.1.2</maven-surefire-plugin.version>
<gmavenplus-plugin.version>1.9.1</gmavenplus-plugin.version>
Expand Down
144 changes: 144 additions & 0 deletions src/main/groovy/projects/patientfinder/procedureWithMapping.groovy
Original file line number Diff line number Diff line change
@@ -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
}
34 changes: 32 additions & 2 deletions src/main/groovy/projects/patientfinder/specimen.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,27 @@ 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
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) {
Expand All @@ -28,6 +38,7 @@ specimen {
}
}


type {
coding {
system = FhirUrls.System.Sample.SampleKind.BASE_URL
Expand All @@ -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()]
Expand All @@ -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]
}
}
}
}
}
}

0 comments on commit b56f53a

Please sign in to comment.