Skip to content

Commit d857a84

Browse files
committed
Add Permit Type and Consent Status in Consent Calculation
1 parent 6a36034 commit d857a84

File tree

4 files changed

+87
-8
lines changed

4 files changed

+87
-8
lines changed

src/main/java/de/medizininformatikinitiative/torch/consent/ConsentFetcher.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ public Mono<PatientBatchWithConsent> buildConsentInfo(String key, PatientBatch b
106106
return dataStore.search(getConsentQuery(batch), Consent.class)
107107
.doOnSubscribe(subscription -> logger.trace("Fetching resources for batch: {}", batch.ids()))
108108
.doOnNext(resource -> logger.trace("Consent resource with id {} fetched for ConsentBuild", resource.getIdPart()))
109+
.filter(consent -> consent.getStatus() == Consent.ConsentState.ACTIVE)
109110
.concatMap(consent -> {
110111
try {
111112
String patientId = ResourceUtils.patientId(consent);

src/main/java/de/medizininformatikinitiative/torch/consent/ConsentProcessor.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,17 @@ public Provisions transformToConsentPeriodByCode(Consent consent, Set<String> re
7272
List<Base> provisionPeriodList = extractConsentProvisions(consent);
7373
for (Base provisionBase : provisionPeriodList) {
7474
Consent.ProvisionComponent provision = (Consent.ProvisionComponent) provisionBase;
75-
String code = provision.getCode().getFirst().getCoding().getFirst().getCode();
76-
if (requiredCodes.contains(code)) {
77-
Period period = provision.getPeriod();
78-
DateTimeType start = period.hasStart() ? period.getStartElement() : null;
79-
DateTimeType end = period.hasEnd() ? period.getEndElement() : null;
75+
if (provision.getType().equals(Consent.ConsentProvisionType.PERMIT)) {
76+
String code = provision.getCode().getFirst().getCoding().getFirst().getCode();
77+
if (requiredCodes.contains(code)) {
78+
Period period = provision.getPeriod();
79+
DateTimeType start = period.hasStart() ? period.getStartElement() : null;
80+
DateTimeType end = period.hasEnd() ? period.getEndElement() : null;
8081

81-
// If no start or end period is present, skip to the next provision
82-
if (start != null && end != null) {
83-
consentPeriodMap.computeIfAbsent(code, k -> new ArrayList<>()).add(de.medizininformatikinitiative.torch.model.consent.Period.fromHapi(period));
82+
// If no start or end period is present, skip to the next provision
83+
if (start != null && end != null) {
84+
consentPeriodMap.computeIfAbsent(code, k -> new ArrayList<>()).add(de.medizininformatikinitiative.torch.model.consent.Period.fromHapi(period));
85+
}
8486
}
8587
}
8688

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package de.medizininformatikinitiative.torch.consent;
2+
3+
import ca.uhn.fhir.context.FhirContext;
4+
import de.medizininformatikinitiative.torch.exceptions.ConsentViolatedException;
5+
import de.medizininformatikinitiative.torch.model.management.PatientBatch;
6+
import de.medizininformatikinitiative.torch.service.DataStore;
7+
import org.hl7.fhir.r4.model.Consent;
8+
import org.junit.jupiter.api.Test;
9+
import org.junit.jupiter.api.extension.ExtendWith;
10+
import org.mockito.InjectMocks;
11+
import org.mockito.Mock;
12+
import org.mockito.junit.jupiter.MockitoExtension;
13+
import reactor.core.publisher.Flux;
14+
import reactor.test.StepVerifier;
15+
16+
import java.util.List;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.mockito.ArgumentMatchers.any;
20+
import static org.mockito.Mockito.when;
21+
22+
@ExtendWith(MockitoExtension.class)
23+
class ConsentFetcherTest {
24+
25+
@Mock
26+
private DataStore dataStore;
27+
28+
@Mock
29+
private ConsentCodeMapper mapper;
30+
31+
@Mock
32+
private FhirContext fhirContext;
33+
34+
35+
@InjectMocks
36+
private ConsentFetcher consentFetcher;
37+
38+
39+
@Test
40+
void failsOnInactiveConsent() {
41+
Consent consent = new Consent();
42+
consent.setStatus(Consent.ConsentState.INACTIVE);
43+
when(dataStore.search(any(), any())).thenReturn(Flux.just(consent));
44+
45+
var resultBatch = consentFetcher.buildConsentInfo("validCode", new PatientBatch(List.of("123")));
46+
47+
48+
StepVerifier.create(resultBatch)
49+
.expectErrorSatisfies(error -> assertThat(error)
50+
.isInstanceOf(ConsentViolatedException.class)
51+
.hasMessageContaining("No valid provisions found for any patients in batch"))
52+
.verify();
53+
}
54+
55+
}

src/test/java/de/medizininformatikinitiative/torch/util/ConsentProcessorTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ void testTransformToConsentPeriodByCodeValid() throws ConsentViolatedException {
7878

7979

8080
when(mockProvision.getPeriod()).thenReturn(mockPeriod);
81+
when(mockProvision.getType()).thenReturn(Consent.ConsentProvisionType.PERMIT);
8182
when(mockProvision.getCode()).thenReturn(Collections.singletonList(new CodeableConcept().addCoding(mockCoding)));
8283

8384

@@ -110,6 +111,25 @@ void testTransformToConsentPeriodByCodeNoPeriods() {
110111
assertThrows(ConsentViolatedException.class, () -> consentProcessor.transformToConsentPeriodByCode(consent, validCodes));
111112
}
112113

114+
@Test
115+
@DisplayName("Test transformToConsentPeriodByCode - some codes are missing and should throw ConsentViolatedException")
116+
void failsOnDeny() {
117+
Consent consent = mock(Consent.class);
118+
119+
// Assume we are requesting two valid codes, but only one will be found
120+
Set<String> validCodes = Set.of("VALID_CODE_1", "VALID_CODE_2");
121+
122+
// Mock provision for VALID_CODE_1
123+
Consent.ProvisionComponent invalidProvision = mock(Consent.ProvisionComponent.class);
124+
when(invalidProvision.getType()).thenReturn(Consent.ConsentProvisionType.DENY);
125+
// Only VALID_CODE_1 is provided, VALID_CODE_2 is missing
126+
when(fhirPath.evaluate(any(), anyString(), eq(Base.class))).thenReturn(List.of(invalidProvision)); // Only one valid provision
127+
128+
// Since VALID_CODE_2 is missing, an exception should be thrown
129+
assertThrows(ConsentViolatedException.class, () -> consentProcessor.transformToConsentPeriodByCode(consent, validCodes));
130+
131+
}
132+
113133

114134
@Test
115135
@DisplayName("Test transformToConsentPeriodByCode - some codes are missing and should throw ConsentViolatedException")
@@ -121,6 +141,7 @@ void testTransformToConsentPeriodByCodePartialValidButOneMissing() {
121141

122142
// Mock provision for VALID_CODE_1
123143
Consent.ProvisionComponent validProvision1 = mock(Consent.ProvisionComponent.class);
144+
when(validProvision1.getType()).thenReturn(Consent.ConsentProvisionType.PERMIT);
124145
Period validPeriod1 = mock(Period.class);
125146
when(validProvision1.getPeriod()).thenReturn(validPeriod1);
126147
when(validProvision1.getCode()).thenReturn(Collections.singletonList(new CodeableConcept().addCoding(new Coding().setCode("VALID_CODE_1"))));

0 commit comments

Comments
 (0)