summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul-Christian Volkmer2025-10-22 13:09:50 +0200
committerGitHub2025-10-22 13:09:50 +0200
commit004e1021c8156bf81f85ac5ad1ef6d260392dc6f (patch)
tree9b448c286e5023440a60633e5dc58a25545aac2b
parent8ccda539b1923dd793744467b780ffc4c2897e71 (diff)
Merge pull request #154
-rw-r--r--src/main/java/dev/dnpm/etl/processor/consent/GicsConsentService.java226
-rw-r--r--src/test/java/dev/dnpm/etl/processor/consent/GicsConsentServiceTest.java177
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt2
-rw-r--r--src/test/resources/fake_broadConsent_mii_response_permit.json513
4 files changed, 760 insertions, 158 deletions
diff --git a/src/main/java/dev/dnpm/etl/processor/consent/GicsConsentService.java b/src/main/java/dev/dnpm/etl/processor/consent/GicsConsentService.java
index 95e8e8f..de722e6 100644
--- a/src/main/java/dev/dnpm/etl/processor/consent/GicsConsentService.java
+++ b/src/main/java/dev/dnpm/etl/processor/consent/GicsConsentService.java
@@ -4,6 +4,8 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.parser.DataFormatException;
import dev.dnpm.etl.processor.config.AppFhirConfig;
import dev.dnpm.etl.processor.config.GIcsConfigProperties;
+import kotlin.random.Random;
+import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.Parameters.ParametersParameterComponent;
@@ -34,6 +36,8 @@ public class GicsConsentService implements IConsentService {
public static final String IS_CONSENTED_ENDPOINT = "/$isConsented";
public static final String IS_POLICY_STATES_FOR_PERSON_ENDPOINT = "/$currentPolicyStatesForPerson";
+ private static final String BROAD_CONSENT_PROFILE_URI = "https://www.medizininformatik-initiative.de/fhir/modul-consent/StructureDefinition/mii-pr-consent-einwilligung";
+ private static final String BROAD_CONSENT_POLICY = "urn:oid:2.16.840.1.113883.3.1937.777.24.2.1791";
private final RetryTemplate retryTemplate;
private final RestTemplate restTemplate;
@@ -41,10 +45,10 @@ public class GicsConsentService implements IConsentService {
private final GIcsConfigProperties gIcsConfigProperties;
public GicsConsentService(
- GIcsConfigProperties gIcsConfigProperties,
- RetryTemplate retryTemplate,
- RestTemplate restTemplate,
- AppFhirConfig appFhirConfig
+ GIcsConfigProperties gIcsConfigProperties,
+ RetryTemplate retryTemplate,
+ RestTemplate restTemplate,
+ AppFhirConfig appFhirConfig
) {
this.retryTemplate = retryTemplate;
this.restTemplate = restTemplate;
@@ -54,34 +58,34 @@ public class GicsConsentService implements IConsentService {
}
protected Parameters getFhirRequestParameters(
- String personIdentifierValue
+ String personIdentifierValue
) {
var result = new Parameters();
result.addParameter(
- new ParametersParameterComponent()
- .setName("personIdentifier")
- .setValue(
- new Identifier()
- .setValue(personIdentifierValue)
- .setSystem(this.gIcsConfigProperties.getPersonIdentifierSystem())
- )
+ new ParametersParameterComponent()
+ .setName("personIdentifier")
+ .setValue(
+ new Identifier()
+ .setValue(personIdentifierValue)
+ .setSystem(this.gIcsConfigProperties.getPersonIdentifierSystem())
+ )
);
result.addParameter(
- new ParametersParameterComponent()
- .setName("domain")
- .setValue(
- new StringType()
- .setValue(this.gIcsConfigProperties.getBroadConsentDomainName())
- )
+ new ParametersParameterComponent()
+ .setName("domain")
+ .setValue(
+ new StringType()
+ .setValue(this.gIcsConfigProperties.getBroadConsentDomainName())
+ )
);
result.addParameter(
- new ParametersParameterComponent()
- .setName("policy")
- .setValue(
- new Coding()
- .setCode(this.gIcsConfigProperties.getBroadConsentPolicyCode())
- .setSystem(this.gIcsConfigProperties.getBroadConsentPolicySystem())
- )
+ new ParametersParameterComponent()
+ .setName("policy")
+ .setValue(
+ new Coding()
+ .setCode(this.gIcsConfigProperties.getBroadConsentPolicyCode())
+ .setSystem(this.gIcsConfigProperties.getBroadConsentPolicySystem())
+ )
);
/*
@@ -89,10 +93,10 @@ public class GicsConsentService implements IConsentService {
* 'ignoreVersionNumber'.
*/
result.addParameter(
- new ParametersParameterComponent()
- .setName("version")
- .setValue(new StringType().setValue("1.1")
- )
+ new ParametersParameterComponent()
+ .setName("version")
+ .setValue(new StringType().setValue("1.1")
+ )
);
/* add config parameter with:
@@ -101,17 +105,17 @@ public class GicsConsentService implements IConsentService {
* unknownStateIsConsideredAsDecline -> true
*/
var config = new ParametersParameterComponent()
- .setName("config")
- .addPart(
- new ParametersParameterComponent()
- .setName("ignoreVersionNumber")
- .setValue(new BooleanType().setValue(true))
- )
- .addPart(
- new ParametersParameterComponent()
- .setName("unknownStateIsConsideredAsDecline")
- .setValue(new BooleanType().setValue(false))
- );
+ .setName("config")
+ .addPart(
+ new ParametersParameterComponent()
+ .setName("ignoreVersionNumber")
+ .setValue(new BooleanType().setValue(true))
+ )
+ .addPart(
+ new ParametersParameterComponent()
+ .setName("unknownStateIsConsideredAsDecline")
+ .setValue(new BooleanType().setValue(false))
+ );
result.addParameter(config);
@@ -130,8 +134,8 @@ public class GicsConsentService implements IConsentService {
headers.setContentType(MediaType.APPLICATION_XML);
if (
- StringUtils.isBlank(this.gIcsConfigProperties.getUsername())
- || StringUtils.isBlank(this.gIcsConfigProperties.getPassword())
+ StringUtils.isBlank(this.gIcsConfigProperties.getUsername())
+ || StringUtils.isBlank(this.gIcsConfigProperties.getPassword())
) {
return headers;
}
@@ -145,28 +149,28 @@ public class GicsConsentService implements IConsentService {
HttpEntity<String> requestEntity = new HttpEntity<>(parameterAsXml, this.headersWithHttpBasicAuth());
try {
var responseEntity = retryTemplate.execute(
- ctx -> restTemplate.exchange(endpointUri(endpoint), HttpMethod.POST, requestEntity, String.class)
+ ctx -> restTemplate.exchange(endpointUri(endpoint), HttpMethod.POST, requestEntity, String.class)
);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
return responseEntity.getBody();
} else {
var msg = String.format(
- "Trusted party system reached but request failed! code: '%s' response: '%s'",
- responseEntity.getStatusCode(), responseEntity.getBody());
+ "Trusted party system reached but request failed! code: '%s' response: '%s'",
+ responseEntity.getStatusCode(), responseEntity.getBody());
log.error(msg);
return null;
}
} catch (RestClientException e) {
var msg = String.format("Get consents status request failed reason: '%s",
- e.getMessage());
+ e.getMessage());
log.error(msg);
return null;
} catch (TerminatedRetryException terminatedRetryException) {
var msg = String.format(
- "Get consents status process has been terminated. termination reason: '%s",
- terminatedRetryException.getMessage());
+ "Get consents status process has been terminated. termination reason: '%s",
+ terminatedRetryException.getMessage());
log.error(msg);
return null;
}
@@ -175,45 +179,45 @@ public class GicsConsentService implements IConsentService {
@Override
public TtpConsentStatus getTtpBroadConsentStatus(String personIdentifierValue) {
var consentStatusResponse = callGicsApi(
- getFhirRequestParameters(personIdentifierValue),
- GicsConsentService.IS_CONSENTED_ENDPOINT
+ getFhirRequestParameters(personIdentifierValue),
+ GicsConsentService.IS_CONSENTED_ENDPOINT
);
return evaluateConsentResponse(consentStatusResponse);
}
protected Bundle currentConsentForPersonAndTemplate(
- String personIdentifierValue,
- ConsentDomain consentDomain,
- Date requestDate
+ String personIdentifierValue,
+ ConsentDomain consentDomain,
+ Date requestDate
) {
var requestParameter = buildRequestParameterCurrentPolicyStatesForPerson(
- personIdentifierValue,
- requestDate,
- consentDomain
+ personIdentifierValue,
+ requestDate,
+ consentDomain
);
var consentDataSerialized = callGicsApi(requestParameter,
- GicsConsentService.IS_POLICY_STATES_FOR_PERSON_ENDPOINT);
+ GicsConsentService.IS_POLICY_STATES_FOR_PERSON_ENDPOINT);
if (consentDataSerialized == null) {
// error occurred - should not process further!
throw new IllegalStateException(
- "consent data request failed - stopping processing! - try again or fix other problems first.");
+ "consent data request failed - stopping processing! - try again or fix other problems first.");
}
var iBaseResource = fhirContext.newJsonParser()
- .parseResource(consentDataSerialized);
+ .parseResource(consentDataSerialized);
if (iBaseResource instanceof OperationOutcome) {
// log error - very likely a configuration error
String errorMessage =
- "Consent request failed! Check outcome:\n " + consentDataSerialized;
+ "Consent request failed! Check outcome:\n " + consentDataSerialized;
log.error(errorMessage);
throw new IllegalStateException(errorMessage);
} else if (iBaseResource instanceof Bundle bundle) {
return bundle;
} else {
String errorMessage = "Consent request failed! Unexpected response received! -> "
- + consentDataSerialized;
+ + consentDataSerialized;
log.error(errorMessage);
throw new IllegalStateException(errorMessage);
}
@@ -228,43 +232,43 @@ public class GicsConsentService implements IConsentService {
}
protected Parameters buildRequestParameterCurrentPolicyStatesForPerson(
- String personIdentifierValue,
- Date requestDate,
- ConsentDomain consentDomain
+ String personIdentifierValue,
+ Date requestDate,
+ ConsentDomain consentDomain
) {
var requestParameter = new Parameters();
requestParameter.addParameter(
- new ParametersParameterComponent()
- .setName("personIdentifier")
- .setValue(
- new Identifier()
- .setValue(personIdentifierValue)
- .setSystem(this.gIcsConfigProperties.getPersonIdentifierSystem())
- )
+ new ParametersParameterComponent()
+ .setName("personIdentifier")
+ .setValue(
+ new Identifier()
+ .setValue(personIdentifierValue)
+ .setSystem(this.gIcsConfigProperties.getPersonIdentifierSystem())
+ )
);
requestParameter.addParameter(
- new ParametersParameterComponent()
- .setName("domain")
- .setValue(new StringType().setValue(getConsentDomainName(consentDomain)))
+ new ParametersParameterComponent()
+ .setName("domain")
+ .setValue(new StringType().setValue(getConsentDomainName(consentDomain)))
);
Parameters nestedConfigParameters = new Parameters();
nestedConfigParameters
- .addParameter(
- new ParametersParameterComponent()
- .setName("idMatchingType")
- .setValue(new Coding()
- .setSystem("https://ths-greifswald.de/fhir/CodeSystem/gics/IdMatchingType")
- .setCode("AT_LEAST_ONE")
- )
- )
- .addParameter("ignoreVersionNumber", false)
- .addParameter("unknownStateIsConsideredAsDecline", false)
- .addParameter("requestDate", new DateType().setValue(requestDate));
+ .addParameter(
+ new ParametersParameterComponent()
+ .setName("idMatchingType")
+ .setValue(new Coding()
+ .setSystem("https://ths-greifswald.de/fhir/CodeSystem/gics/IdMatchingType")
+ .setCode("AT_LEAST_ONE")
+ )
+ )
+ .addParameter("ignoreVersionNumber", false)
+ .addParameter("unknownStateIsConsideredAsDecline", false)
+ .addParameter("requestDate", new DateType().setValue(requestDate));
requestParameter.addParameter(
- new ParametersParameterComponent().setName("config").addPart().setResource(nestedConfigParameters)
+ new ParametersParameterComponent().setName("config").addPart().setResource(nestedConfigParameters)
);
return requestParameter;
@@ -291,7 +295,7 @@ public class GicsConsentService implements IConsentService {
}
} else if (response instanceof OperationOutcome outcome) {
log.error("failed to get consent status from ttp. probably configuration error. "
- + "outcome: '{}'", fhirContext.newJsonParser().encodeToString(outcome));
+ + "outcome: '{}'", fhirContext.newJsonParser().encodeToString(outcome));
}
} catch (DataFormatException dfe) {
@@ -302,6 +306,52 @@ public class GicsConsentService implements IConsentService {
@Override
public Bundle getConsent(String patientId, Date requestDate, ConsentDomain consentDomain) {
- return currentConsentForPersonAndTemplate(patientId, consentDomain, requestDate);
+ Bundle gIcsResultBundle = currentConsentForPersonAndTemplate(patientId, consentDomain, requestDate);
+ if (ConsentDomain.BROAD_CONSENT == consentDomain) {
+ return anonymizeBroadConsent(convertGicsResultToMiiBroadConsent(gIcsResultBundle));
+ }
+ return gIcsResultBundle;
+ }
+
+ protected Bundle convertGicsResultToMiiBroadConsent(Bundle gIcsResultBundle) {
+ if (gIcsResultBundle == null
+ || gIcsResultBundle.getEntry().isEmpty()
+ || !(gIcsResultBundle.getEntry().getFirst().getResource() instanceof Consent))
+ return gIcsResultBundle;
+
+ Bundle.BundleEntryComponent bundleEntryComponent = gIcsResultBundle.getEntry().getFirst();
+
+ var consentAsOne = (Consent) bundleEntryComponent.getResource();
+ if (consentAsOne.getPolicy().stream().noneMatch(p -> p.getUri().equals(BROAD_CONSENT_POLICY))) {
+ consentAsOne.addPolicy(new Consent.ConsentPolicyComponent().setUri(BROAD_CONSENT_POLICY));
+ }
+
+ if (consentAsOne.getMeta().getProfile().stream().noneMatch(p -> p.getValue().equals(BROAD_CONSENT_PROFILE_URI))) {
+ consentAsOne.getMeta().addProfile(BROAD_CONSENT_PROFILE_URI);
+ }
+
+ consentAsOne.setPolicyRule(null);
+
+ gIcsResultBundle.getEntry().stream().skip(1).forEach(c -> consentAsOne.getProvision().addProvision(((Consent) c.getResource()).getProvision().getProvisionFirstRep()));
+
+ gIcsResultBundle.getEntry().clear();
+ gIcsResultBundle.addEntry(bundleEntryComponent);
+ return gIcsResultBundle;
+ }
+
+ protected Bundle anonymizeBroadConsent(Bundle bundle) {
+ Bundle.BundleEntryComponent bundleEntryComponent = bundle.getEntry().getFirst();
+ hashBundleEntry(bundleEntryComponent);
+ return bundle;
+ }
+
+ private static void hashBundleEntry(Bundle.BundleEntryComponent entry) {
+ String id = entry.getResource().getIdPart();
+ var hash = DigestUtils.sha256Hex("%s_%s".formatted(Random.Default.toString(), id));
+
+ entry.getResource().setId(hash);
+ entry.setFullUrl(entry.getFullUrl().replace(id, hash));
+ var consent = (Consent) entry.getResource();
+ consent.getSource().setProperty("reference", new StringType("QuestionnaireResponse/%s".formatted(hash)));
}
}
diff --git a/src/test/java/dev/dnpm/etl/processor/consent/GicsConsentServiceTest.java b/src/test/java/dev/dnpm/etl/processor/consent/GicsConsentServiceTest.java
index 6fa8f08..02b4d37 100644
--- a/src/test/java/dev/dnpm/etl/processor/consent/GicsConsentServiceTest.java
+++ b/src/test/java/dev/dnpm/etl/processor/consent/GicsConsentServiceTest.java
@@ -1,9 +1,11 @@
package dev.dnpm.etl.processor.consent;
+import ca.uhn.fhir.context.FhirContext;
import com.fasterxml.jackson.databind.ObjectMapper;
import dev.dnpm.etl.processor.config.AppConfiguration;
import dev.dnpm.etl.processor.config.AppFhirConfig;
import dev.dnpm.etl.processor.config.GIcsConfigProperties;
+import org.apache.commons.io.IOUtils;
import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.OperationOutcome.IssueSeverity;
import org.hl7.fhir.r4.model.OperationOutcome.IssueType;
@@ -20,18 +22,21 @@ import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.RestTemplate;
+import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Date;
+import java.util.Objects;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withServerError;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
@ContextConfiguration(classes = {AppConfiguration.class, ObjectMapper.class})
@TestPropertySource(properties = {
- "app.consent.service=gics",
- "app.consent.gics.uri=http://localhost:8090/ttp-fhir/fhir/gics"
+ "app.consent.service=gics",
+ "app.consent.gics.uri=http://localhost:8090/ttp-fhir/fhir/gics"
})
@RestClientTest
class GicsConsentServiceTest {
@@ -46,8 +51,8 @@ class GicsConsentServiceTest {
@BeforeEach
void setUp(
- @Autowired AppFhirConfig appFhirConfig,
- @Autowired GIcsConfigProperties gIcsConfigProperties
+ @Autowired AppFhirConfig appFhirConfig,
+ @Autowired GIcsConfigProperties gIcsConfigProperties
) {
this.appFhirConfig = appFhirConfig;
this.gIcsConfigProperties = gIcsConfigProperties;
@@ -56,33 +61,33 @@ class GicsConsentServiceTest {
this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate);
this.gicsConsentService = new GicsConsentService(
- this.gIcsConfigProperties,
- RetryTemplate.builder().maxAttempts(1).build(),
- restTemplate,
- this.appFhirConfig
+ this.gIcsConfigProperties,
+ RetryTemplate.builder().maxAttempts(1).build(),
+ restTemplate,
+ this.appFhirConfig
);
}
@Test
void shouldReturnTtpBroadConsentStatus() {
final Parameters consentedResponse = new Parameters()
- .addParameter(
- new ParametersParameterComponent()
- .setName("consented")
- .setValue(new BooleanType().setValue(true))
- );
+ .addParameter(
+ new ParametersParameterComponent()
+ .setName("consented")
+ .setValue(new BooleanType().setValue(true))
+ );
mockRestServiceServer
- .expect(
- requestTo(
- "http://localhost:8090/ttp-fhir/fhir/gics" + GicsConsentService.IS_CONSENTED_ENDPOINT)
- )
- .andRespond(
- withSuccess(
- appFhirConfig.fhirContext().newJsonParser().encodeResourceToString(consentedResponse),
- MediaType.APPLICATION_JSON
+ .expect(
+ requestTo(
+ "http://localhost:8090/ttp-fhir/fhir/gics" + GicsConsentService.IS_CONSENTED_ENDPOINT)
)
- );
+ .andRespond(
+ withSuccess(
+ appFhirConfig.fhirContext().newJsonParser().encodeResourceToString(consentedResponse),
+ MediaType.APPLICATION_JSON
+ )
+ );
var consentStatus = gicsConsentService.getTtpBroadConsentStatus("123456");
assertThat(consentStatus).isEqualTo(TtpConsentStatus.BROAD_CONSENT_GIVEN);
@@ -91,22 +96,22 @@ class GicsConsentServiceTest {
@Test
void shouldReturnRevokedConsent() {
final Parameters revokedResponse = new Parameters()
- .addParameter(
- new ParametersParameterComponent()
- .setName("consented")
- .setValue(new BooleanType().setValue(false))
- );
+ .addParameter(
+ new ParametersParameterComponent()
+ .setName("consented")
+ .setValue(new BooleanType().setValue(false))
+ );
mockRestServiceServer
- .expect(
- requestTo(
- "http://localhost:8090/ttp-fhir/fhir/gics" + GicsConsentService.IS_CONSENTED_ENDPOINT)
- )
- .andRespond(
- withSuccess(
- appFhirConfig.fhirContext().newJsonParser().encodeResourceToString(revokedResponse),
- MediaType.APPLICATION_JSON)
- );
+ .expect(
+ requestTo(
+ "http://localhost:8090/ttp-fhir/fhir/gics" + GicsConsentService.IS_CONSENTED_ENDPOINT)
+ )
+ .andRespond(
+ withSuccess(
+ appFhirConfig.fhirContext().newJsonParser().encodeResourceToString(revokedResponse),
+ MediaType.APPLICATION_JSON)
+ );
var consentStatus = gicsConsentService.getTtpBroadConsentStatus("123456");
assertThat(consentStatus).isEqualTo(TtpConsentStatus.BROAD_CONSENT_MISSING_OR_REJECTED);
@@ -116,23 +121,23 @@ class GicsConsentServiceTest {
@Test
void shouldReturnInvalidParameterResponse() {
final OperationOutcome responseWithErrorOutcome = new OperationOutcome()
- .addIssue(
- new OperationOutcomeIssueComponent()
- .setSeverity(IssueSeverity.ERROR)
- .setCode(IssueType.PROCESSING)
- .setDiagnostics("Invalid policy parameter...")
- );
+ .addIssue(
+ new OperationOutcomeIssueComponent()
+ .setSeverity(IssueSeverity.ERROR)
+ .setCode(IssueType.PROCESSING)
+ .setDiagnostics("Invalid policy parameter...")
+ );
mockRestServiceServer
- .expect(
- requestTo(GICS_BASE_URI + GicsConsentService.IS_CONSENTED_ENDPOINT)
- )
- .andRespond(
- withSuccess(
- appFhirConfig.fhirContext().newJsonParser().encodeResourceToString(responseWithErrorOutcome),
- MediaType.APPLICATION_JSON
+ .expect(
+ requestTo(GICS_BASE_URI + GicsConsentService.IS_CONSENTED_ENDPOINT)
)
- );
+ .andRespond(
+ withSuccess(
+ appFhirConfig.fhirContext().newJsonParser().encodeResourceToString(responseWithErrorOutcome),
+ MediaType.APPLICATION_JSON
+ )
+ );
var consentStatus = gicsConsentService.getTtpBroadConsentStatus("123456");
assertThat(consentStatus).isEqualTo(TtpConsentStatus.FAILED_TO_ASK);
@@ -141,12 +146,12 @@ class GicsConsentServiceTest {
@Test
void shouldReturnRequestError() {
mockRestServiceServer
- .expect(
- requestTo(GICS_BASE_URI + GicsConsentService.IS_CONSENTED_ENDPOINT)
- )
- .andRespond(
- withServerError()
- );
+ .expect(
+ requestTo(GICS_BASE_URI + GicsConsentService.IS_CONSENTED_ENDPOINT)
+ )
+ .andRespond(
+ withServerError()
+ );
var consentStatus = gicsConsentService.getTtpBroadConsentStatus("123456");
assertThat(consentStatus).isEqualTo(TtpConsentStatus.FAILED_TO_ASK);
@@ -156,26 +161,60 @@ class GicsConsentServiceTest {
void buildRequestParameterCurrentPolicyStatesForPersonTest() {
String pid = "12345678";
var result = gicsConsentService
- .buildRequestParameterCurrentPolicyStatesForPerson(
- pid,
- Date.from(Instant.now()),
- ConsentDomain.MODELLVORHABEN_64E
- );
+ .buildRequestParameterCurrentPolicyStatesForPerson(
+ pid,
+ Date.from(Instant.now()),
+ ConsentDomain.MODELLVORHABEN_64E
+ );
assertThat(result.getParameter())
- .as("should contain 3 parameter resources")
- .hasSize(3);
+ .as("should contain 3 parameter resources")
+ .hasSize(3);
assertThat(((StringType) result.getParameter("domain").getValue()).getValue())
- .isEqualTo(
- gIcsConfigProperties.getGenomDeConsentDomainName()
- );
+ .isEqualTo(
+ gIcsConfigProperties.getGenomDeConsentDomainName()
+ );
assertThat(((Identifier) result.getParameter("personIdentifier").getValue()).getValue())
- .isEqualTo(
- pid
- );
+ .isEqualTo(
+ pid
+ );
+ }
+
+ @Test
+ void convertGicsResultToMiiBroadConsent() throws Exception {
+ var fhirJsonParser = FhirContext.forR4().newJsonParser();
+ fhirJsonParser.setPrettyPrint(true);
+
+ var gicsInputStream = Objects.requireNonNull(
+ this.getClass().getClassLoader().getResourceAsStream("fake_broadConsent_gics_response_permit.json")
+ );
+ var gicsConsentBundle = (Bundle) fhirJsonParser.parseResource(IOUtils.toString(gicsInputStream, StandardCharsets.UTF_8));
+
+ var miiInputStream = Objects.requireNonNull(
+ this.getClass().getClassLoader().getResourceAsStream("fake_broadConsent_mii_response_permit.json")
+ );
+ var miiConsent = IOUtils.toString(miiInputStream, StandardCharsets.UTF_8);
+
+ var actual = gicsConsentService.convertGicsResultToMiiBroadConsent(gicsConsentBundle);
+
+ assertThat(fhirJsonParser.encodeToString(actual)).isEqualTo(miiConsent);
}
+ @Test
+ void convertedMiiBroadConsentShouldNotContainPatientId() throws Exception {
+ var fhirJsonParser = FhirContext.forR4().newJsonParser();
+ fhirJsonParser.setPrettyPrint(true);
+
+ var miiInputStream = Objects.requireNonNull(
+ this.getClass().getClassLoader().getResourceAsStream("fake_broadConsent_mii_response_permit.json")
+ );
+ var miiConsentBundle = (Bundle) fhirJsonParser.parseResource(IOUtils.toString(miiInputStream, StandardCharsets.UTF_8));
+
+ var currentPatientId = miiConsentBundle.getEntry().getFirst().getResource().getIdPart();
+ var actual = gicsConsentService.anonymizeBroadConsent(miiConsentBundle);
+ assertThat(fhirJsonParser.encodeToString(actual)).doesNotContain(currentPatientId);
+ }
}
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt
index 4d414c5..bbc8b1a 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/ConsentProcessorTest.kt
@@ -80,7 +80,7 @@ class ConsentProcessorTest {
val checkResult = consentProcessor.consentGatedCheckAndTryEmbedding(inputMtb)
assertThat(checkResult).isTrue
- assertThat(inputMtb.metadata.researchConsents).hasSize(26)
+ assertThat(inputMtb.metadata.researchConsents).isNotEmpty
}
companion object {
diff --git a/src/test/resources/fake_broadConsent_mii_response_permit.json b/src/test/resources/fake_broadConsent_mii_response_permit.json
new file mode 100644
index 0000000..e7bea5a
--- /dev/null
+++ b/src/test/resources/fake_broadConsent_mii_response_permit.json
@@ -0,0 +1,513 @@
+{
+ "resourceType": "Bundle",
+ "type": "collection",
+ "total": 26,
+ "entry": [ {
+ "fullUrl": "http://localhost:8080/ttp-fhir/fhir/gics/Consent/7d3456c2-79b1-11f0-ab27-6ed0ed82d0fd",
+ "resource": {
+ "resourceType": "Consent",
+ "id": "7d3456c2-79b1-11f0-ab27-6ed0ed82d0fd",
+ "meta": {
+ "lastUpdated": "2025-08-15T11:13:59.143+02:00",
+ "profile": [ "http://fhir.de/ConsentManagement/StructureDefinition/Consent", "https://www.medizininformatik-initiative.de/fhir/modul-consent/StructureDefinition/mii-pr-consent-einwilligung" ]
+ },
+ "extension": [ {
+ "url": "http://fhir.de/ConsentManagement/StructureDefinition/DomainReference",
+ "extension": [ {
+ "url": "domain",
+ "valueReference": {
+ "reference": "ResearchStudy/3c3ffec5-79b1-11f0-ab27-6ed0ed82d0fd"
+ }
+ }, {
+ "url": "status",
+ "valueCoding": {
+ "system": "http://hl7.org/fhir/publication-status",
+ "code": "active"
+ }
+ } ]
+ } ],
+ "status": "active",
+ "scope": {
+ "coding": [ {
+ "system": "http://terminology.hl7.org/CodeSystem/consentscope",
+ "code": "research"
+ } ]
+ },
+ "category": [ {
+ "coding": [ {
+ "system": "http://loinc.org",
+ "code": "57016-8"
+ } ]
+ }, {
+ "coding": [ {
+ "system": "http://fhir.de/ConsentManagement/CodeSystem/ResultType",
+ "code": "policy"
+ } ]
+ } ],
+ "patient": {
+ "reference": "Patient/7d2da57f-79b1-11f0-ab27-6ed0ed82d0fd",
+ "display": "Patienten-ID 644bae7a-56f6-4ee8-b02f-c532e65af5b1"
+ },
+ "dateTime": "2025-08-15T00:00:00+02:00",
+ "organization": [ {
+ "display": "MII"
+ } ],
+ "sourceReference": {
+ "reference": "QuestionnaireResponse/7d314bc5-79b1-11f0-ab27-6ed0ed82d0fd"
+ },
+ "policy": [ {
+ "uri": "urn:oid:2.16.840.1.113883.3.1937.777.24.2.1791"
+ } ],
+ "provision": {
+ "type": "deny",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "provision": [ {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy",
+ "code": "IDAT_erheben",
+ "display": "Erfassung neuer identifizierender Daten (IDAT)"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.2",
+ "display": "IDAT erheben"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy/MII",
+ "code": "KKDAT_5J_retro_speichern_verarbeiten",
+ "display": "Retrospektive Krankenkassendaten (KKDAT) aus fünf Jahren vor Einwilligung speichern und codiert verarbeiten zu Zwecken med. Forschung in der verantwortlichen Stelle"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.12",
+ "display": "KKDAT 5J retrospektiv speichern verarbeiten"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy/MII",
+ "code": "BIOMAT_wissenschaftlich_nutzen_EU_DSGVO_konform",
+ "display": "Bereitstellung umcodierter Biomaterialien (BIOMAT) für wissenschaftliche Nutzung und Analysen zu Zwecken med. Forschung an ext. Forscher"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.22",
+ "display": "BIOMAT wissenschaftlich nutzen EU DSGVO NIVEAU"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy/MII",
+ "code": "KKDAT_5J_retro_wissenschaftlich_nutzen",
+ "display": "Bereitstellung umcodierter retrospektiver Krankenkassendaten (KKDAT) für wissenschaftliche Nutzung zu Zwecken med. Forschung an externe Forscher"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.13",
+ "display": "KKDAT 5J retrospektiv wissenschaftlich nutzen"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy",
+ "code": "BIOMAT_Analysedaten_zusammenfuehren_Dritte",
+ "display": "Zusammenführen von auf Biomaterialien (BIOMAT) basierenden Analysedaten mit Analysedaten Dritter, sofern dort ebenfalls eine Einwilligung vorliegt"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.23",
+ "display": "BIOMAT Analysedaten zusammenfuehren Dritte"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy/MII",
+ "code": "Rekontaktierung_Zusatzbefund",
+ "display": "Rekontaktierung bezüglich Zusatzbefund im Rahmen der am Standort dafür entwickelten Prozesse und der im Nutzungsantrag angegebenen Bedingungen"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.31",
+ "display": "Rekontaktierung Zusatzbefund"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy/MII",
+ "code": "KKDAT_5J_pro_wissenschaftlich_nutzen",
+ "display": "Bereitstellung umcodierter prospektiver Krankenkassendaten (KKDAT) aus fünf Jahren ab Einwilligung zu Zwecken med. Forschung an ext. Forscher"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.17",
+ "display": "KKDAT 5J prospektiv wissenschaftlich nutzen"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy",
+ "code": "BIOMAT_lagern_verarbeiten",
+ "display": "Lagerung und Verarbeitung von Biomaterialien innerhalb der verantwortlichen Stelle (BIOMAT)"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.20",
+ "display": "BIOMAT lagern verarbeiten"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy/MII",
+ "code": "KKDAT_5J_retro_uebertragen",
+ "display": "Krankenkassendaten (KKDAT) der letzten fünf Kalenderjahre vor Datum Unterschrift übertragen"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.11",
+ "display": "KKDAT 5J retrospektiv uebertragen"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy/MII",
+ "code": "KKDAT_KVNR_5J_retro_uebertragen",
+ "display": "Erlaubnis zur retrospektiven Übermittlung der KVNr., MII-Pseudonym und Zeitraum Datenübermittlung (von:5 Jahre vor Datum Unterschrift; bis: Datum Unterschrift) an zuständige Stelle"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.38",
+ "display": "KKDAT 5J retrospektiv uebertragen KVNR"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2030-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy",
+ "code": "MDAT_erheben",
+ "display": "Erfassung medizinischer Daten (MDAT)"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.6",
+ "display": "MDAT erheben"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy/MII",
+ "code": "KKDAT_5J_pro_speichern_verarbeiten",
+ "display": "Prospektive Krankenkassendaten (KKDAT) aus fünf Jahren ab Einwilligung speichern und codiert verarbeiten zu Zwecken der med. Forschung in der verantwortlichen Stelle"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.16",
+ "display": "KKDAT 5J prospektiv speichern verarbeiten"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy/MII",
+ "code": "MDAT_wissenschaftlich_nutzen_EU_DSGVO_konform",
+ "display": "Bereitstellung umcodierter medizinischer Daten (MDAT) für wissenschaftliche Nutzung zu Zwecken med. Forschung an externe Forscher"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.8",
+ "display": "MDAT wissenschaftlich nutzen EU DSGVO NIVEAU"
+ } ]
+ } ]
+ }, {
+ "type": "deny",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy",
+ "code": "Rekontaktierung_Verknuepfung_Datenbanken",
+ "display": "Rekontaktierung zur Verknüpfung von Patientendaten mit Daten anderer Datenbanken"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.27",
+ "display": "Rekontaktierung Verknüpfung Datenbanken"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy",
+ "code": "Rekontaktierung_weitere_Studien",
+ "display": "Rekontaktierung bezüglich Information zu neuen Forschungsvorhaben oder Studien"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.29",
+ "display": "Rekontaktierung weitere Studien"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy/MII",
+ "code": "IDAT_bereitstellen_EU_DSGVO_konform",
+ "display": "Herausgabe identifizierender Daten (IDAT) an unabhängige Treuhandstelle zur weiteren Verarbeitung"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.5",
+ "display": "IDAT bereitstellen EU DSGVO NIVEAU"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy",
+ "code": "IDAT_speichern_verarbeiten",
+ "display": "Speicherung und Verarbeitung identifizierender Daten (IDAT) zu Zwecken med. Forschung in der verantwortlichen Stelle"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.3",
+ "display": "IDAT speichern, verarbeiten"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy",
+ "code": "MDAT_speichern_verarbeiten",
+ "display": "Speicherung und Verarbeitung von medizinischen codierten Daten zu Zwecken med. Forschung innerhalb der verantwortlichen Stelle (MDAT)"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.7",
+ "display": "MDAT speichern, verarbeiten"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2030-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy",
+ "code": "BIOMAT_erheben",
+ "display": "Gewinnung von Biomaterialien (BIOMAT)"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.19",
+ "display": "BIOMAT erheben"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy/MII",
+ "code": "Rekontaktierung_Ergebnisse_erheblicher_Bedeutung",
+ "display": "Rekontaktierung des Betroffenen bei Ergebnissen von erheblicher Bedeutung"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.37",
+ "display": "Rekontaktierung Ergebnisse erheblicher Bedeutung"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2030-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy/MII",
+ "code": "KKDAT_KVNR_5J_pro_uebertragen",
+ "display": "Erlaubnis zur prospektiven Übermittlung der KVNr., MII-Pseudonym und Zeitraum Datenübermittlung (von: Datum Unterschrift; bis: max. 5 Kalenderjahre nach Unterschrift) an zuständige Stelle"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.39",
+ "display": "KKDAT 5J prospektiv uebertragen KVNR"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2030-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy",
+ "code": "BIOMAT_Zusatzmengen_entnehmen",
+ "display": "Entnahme zusätzlicher Mengen von Biomaterialien (BIOMAT) in den in der Einwilligung beschriebenen Grenzen"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.25",
+ "display": "BIOMAT Zusatzmengen entnehmen"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy",
+ "code": "Rekontaktierung_weitere_Erhebung",
+ "display": "Rekontaktierung bezüglich Erhebung zusätzlicher Daten"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.28",
+ "display": "Rekontaktierung weitere Erhebung"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy",
+ "code": "IDAT_zusammenfuehren_Dritte",
+ "display": "Zusammenführung identifizierender Daten (IDAT) über die unabhängige Treuhandstelle mit Dritten Forschungspartnern, sofern dort eine Einwilligung vorliegt"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.4",
+ "display": "IDAT zusammenfuehren Dritte"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2055-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy",
+ "code": "MDAT_zusammenfuehren_Dritte",
+ "display": "Zusammenführung medizinischer Daten (MDAT) mit Dritten Forschungspartnern, sofern dort eine Einwilligung vorliegt"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.9",
+ "display": "MDAT zusammenfuehren Dritte"
+ } ]
+ } ]
+ }, {
+ "type": "permit",
+ "period": {
+ "start": "2025-08-15T00:00:00+02:00",
+ "end": "2030-08-15T00:00:00+02:00"
+ },
+ "code": [ {
+ "coding": [ {
+ "system": "https://ths-greifswald.de/fhir/CodeSystem/gics/Policy/MII",
+ "code": "KKDAT_5J_pro_uebertragen",
+ "display": "Prospektive Krankenkassendaten (KKDAT) für fünf Kalenderjahre nach Datum Unterschrift übertragen"
+ }, {
+ "system": "urn:oid:2.16.840.1.113883.3.1937.777.24.5.3",
+ "code": "2.16.840.1.113883.3.1937.777.24.5.3.15",
+ "display": "KKDAT 5J prospektiv uebertragen"
+ } ]
+ } ]
+ } ]
+ }
+ }
+ } ]
+} \ No newline at end of file