summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/helpers.kt20
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt8
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt11
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt23
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/output/RestBwhcMtbFileSenderTest.kt (renamed from src/test/kotlin/dev/dnpm/etl/processor/output/RestMtbFileSenderTest.kt)85
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt262
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt10
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/security/TokenServiceTest.kt (renamed from src/test/kotlin/dev/dnpm/etl/processor/services/TokenServiceTest.kt)15
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/security/UserRoleServiceTest.kt202
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt126
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt178
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt37
-rw-r--r--src/test/resources/fake_MTBFile.json2
13 files changed, 736 insertions, 243 deletions
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/helpers.kt b/src/test/kotlin/dev/dnpm/etl/processor/helpers.kt
new file mode 100644
index 0000000..8caa908
--- /dev/null
+++ b/src/test/kotlin/dev/dnpm/etl/processor/helpers.kt
@@ -0,0 +1,20 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package dev.dnpm.etl.processor \ No newline at end of file
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt
index 1157644..b54a02e 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/input/KafkaInputListenerTest.kt
@@ -31,10 +31,10 @@ import org.apache.kafka.common.record.TimestampType
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
-import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.kotlin.any
+import org.mockito.kotlin.anyValueClass
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import java.util.*
@@ -77,7 +77,7 @@ class KafkaInputListenerTest {
kafkaInputListener.onMessage(ConsumerRecord("testtopic", 0, 0, "", this.objectMapper.writeValueAsString(mtbFile)))
- verify(requestProcessor, times(1)).processDeletion(anyString())
+ verify(requestProcessor, times(1)).processDeletion(anyValueClass())
}
@Test
@@ -92,7 +92,7 @@ class KafkaInputListenerTest {
ConsumerRecord("testtopic", 0, 0, -1L, TimestampType.NO_TIMESTAMP_TYPE, -1, -1, "", this.objectMapper.writeValueAsString(mtbFile), headers, Optional.empty())
)
- verify(requestProcessor, times(1)).processMtbFile(any(), anyString())
+ verify(requestProcessor, times(1)).processMtbFile(any(), anyValueClass())
}
@Test
@@ -106,7 +106,7 @@ class KafkaInputListenerTest {
kafkaInputListener.onMessage(
ConsumerRecord("testtopic", 0, 0, -1L, TimestampType.NO_TIMESTAMP_TYPE, -1, -1, "", this.objectMapper.writeValueAsString(mtbFile), headers, Optional.empty())
)
- verify(requestProcessor, times(1)).processDeletion(anyString(), anyString())
+ verify(requestProcessor, times(1)).processDeletion(anyValueClass(), anyValueClass())
}
} \ No newline at end of file
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt
index 0b076a1..3e5b53a 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/input/MtbFileRestControllerTest.kt
@@ -22,7 +22,6 @@ package dev.dnpm.etl.processor.input
import com.fasterxml.jackson.databind.ObjectMapper
import de.ukw.ccc.bwhc.dto.*
import dev.dnpm.etl.processor.services.RequestProcessor
-import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@@ -31,7 +30,7 @@ import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.kotlin.any
-import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.anyValueClass
import org.springframework.http.MediaType
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.delete
@@ -129,9 +128,7 @@ class MtbFileRestControllerTest {
}
}
- val captor = argumentCaptor<String>()
- verify(requestProcessor, times(1)).processDeletion(captor.capture())
- assertThat(captor.firstValue).isEqualTo("TEST_12345678")
+ verify(requestProcessor, times(1)).processDeletion(anyValueClass())
}
@Test
@@ -142,9 +139,7 @@ class MtbFileRestControllerTest {
}
}
- val captor = argumentCaptor<String>()
- verify(requestProcessor, times(1)).processDeletion(captor.capture())
- assertThat(captor.firstValue).isEqualTo("TEST_12345678")
+ verify(requestProcessor, times(1)).processDeletion(anyValueClass())
}
} \ No newline at end of file
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt
index 411c51e..655e29e 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSenderTest.kt
@@ -21,6 +21,8 @@ package dev.dnpm.etl.processor.output
import com.fasterxml.jackson.databind.ObjectMapper
import de.ukw.ccc.bwhc.dto.*
+import dev.dnpm.etl.processor.PatientPseudonym
+import dev.dnpm.etl.processor.RequestId
import dev.dnpm.etl.processor.config.KafkaProperties
import dev.dnpm.etl.processor.monitoring.RequestStatus
import org.assertj.core.api.Assertions.assertThat
@@ -72,7 +74,7 @@ class KafkaMtbFileSenderTest {
completedFuture(SendResult<String, String>(null, null))
}.whenever(kafkaTemplate).send(anyString(), anyString(), anyString())
- val response = kafkaMtbFileSender.send(MtbFileSender.MtbFileRequest("TestID", mtbFile(Consent.Status.ACTIVE)))
+ val response = kafkaMtbFileSender.send(MtbFileSender.MtbFileRequest(TEST_REQUEST_ID, mtbFile(Consent.Status.ACTIVE)))
assertThat(response.status).isEqualTo(testData.requestStatus)
}
@@ -86,7 +88,7 @@ class KafkaMtbFileSenderTest {
completedFuture(SendResult<String, String>(null, null))
}.whenever(kafkaTemplate).send(anyString(), anyString(), anyString())
- val response = kafkaMtbFileSender.send(MtbFileSender.DeleteRequest("TestID", "PID"))
+ val response = kafkaMtbFileSender.send(MtbFileSender.DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
assertThat(response.status).isEqualTo(testData.requestStatus)
}
@@ -96,14 +98,14 @@ class KafkaMtbFileSenderTest {
completedFuture(SendResult<String, String>(null, null))
}.whenever(kafkaTemplate).send(anyString(), anyString(), anyString())
- kafkaMtbFileSender.send(MtbFileSender.MtbFileRequest("TestID", mtbFile(Consent.Status.ACTIVE)))
+ kafkaMtbFileSender.send(MtbFileSender.MtbFileRequest(TEST_REQUEST_ID, mtbFile(Consent.Status.ACTIVE)))
val captor = argumentCaptor<String>()
verify(kafkaTemplate, times(1)).send(anyString(), captor.capture(), captor.capture())
assertThat(captor.firstValue).isNotNull
assertThat(captor.firstValue).isEqualTo("{\"pid\": \"PID\"}")
assertThat(captor.secondValue).isNotNull
- assertThat(captor.secondValue).isEqualTo(objectMapper.writeValueAsString(kafkaRecordData("TestID", Consent.Status.ACTIVE)))
+ assertThat(captor.secondValue).isEqualTo(objectMapper.writeValueAsString(kafkaRecordData(TEST_REQUEST_ID, Consent.Status.ACTIVE)))
}
@Test
@@ -112,14 +114,14 @@ class KafkaMtbFileSenderTest {
completedFuture(SendResult<String, String>(null, null))
}.whenever(kafkaTemplate).send(anyString(), anyString(), anyString())
- kafkaMtbFileSender.send(MtbFileSender.DeleteRequest("TestID", "PID"))
+ kafkaMtbFileSender.send(MtbFileSender.DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
val captor = argumentCaptor<String>()
verify(kafkaTemplate, times(1)).send(anyString(), captor.capture(), captor.capture())
assertThat(captor.firstValue).isNotNull
assertThat(captor.firstValue).isEqualTo("{\"pid\": \"PID\"}")
assertThat(captor.secondValue).isNotNull
- assertThat(captor.secondValue).isEqualTo(objectMapper.writeValueAsString(kafkaRecordData("TestID", Consent.Status.REJECTED)))
+ assertThat(captor.secondValue).isEqualTo(objectMapper.writeValueAsString(kafkaRecordData(TEST_REQUEST_ID, Consent.Status.REJECTED)))
}
@ParameterizedTest
@@ -136,7 +138,7 @@ class KafkaMtbFileSenderTest {
completedFuture(SendResult<String, String>(null, null))
}.whenever(kafkaTemplate).send(anyString(), anyString(), anyString())
- kafkaMtbFileSender.send(MtbFileSender.MtbFileRequest("TestID", mtbFile(Consent.Status.ACTIVE)))
+ kafkaMtbFileSender.send(MtbFileSender.MtbFileRequest(TEST_REQUEST_ID, mtbFile(Consent.Status.ACTIVE)))
val expectedCount = when (testData.exception) {
// OK - No Retry
@@ -162,7 +164,7 @@ class KafkaMtbFileSenderTest {
completedFuture(SendResult<String, String>(null, null))
}.whenever(kafkaTemplate).send(anyString(), anyString(), anyString())
- kafkaMtbFileSender.send(MtbFileSender.DeleteRequest("TestID", "PID"))
+ kafkaMtbFileSender.send(MtbFileSender.DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
val expectedCount = when (testData.exception) {
// OK - No Retry
@@ -175,6 +177,9 @@ class KafkaMtbFileSenderTest {
}
companion object {
+ val TEST_REQUEST_ID = RequestId("TestId")
+ val TEST_PATIENT_PSEUDONYM = PatientPseudonym("PID")
+
fun mtbFile(consentStatus: Consent.Status): MtbFile {
return if (consentStatus == Consent.Status.ACTIVE) {
MtbFile.builder()
@@ -210,7 +215,7 @@ class KafkaMtbFileSenderTest {
}.build()
}
- fun kafkaRecordData(requestId: String, consentStatus: Consent.Status): KafkaMtbFileSender.Data {
+ fun kafkaRecordData(requestId: RequestId, consentStatus: Consent.Status): KafkaMtbFileSender.Data {
return KafkaMtbFileSender.Data(requestId, mtbFile(consentStatus))
}
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/output/RestMtbFileSenderTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/output/RestBwhcMtbFileSenderTest.kt
index df19ddb..5063a97 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/output/RestMtbFileSenderTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/output/RestBwhcMtbFileSenderTest.kt
@@ -1,7 +1,7 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -20,6 +20,8 @@
package dev.dnpm.etl.processor.output
import de.ukw.ccc.bwhc.dto.*
+import dev.dnpm.etl.processor.PatientPseudonym
+import dev.dnpm.etl.processor.RequestId
import dev.dnpm.etl.processor.config.RestTargetProperties
import dev.dnpm.etl.processor.monitoring.RequestStatus
import org.assertj.core.api.Assertions.assertThat
@@ -37,7 +39,7 @@ import org.springframework.test.web.client.match.MockRestRequestMatchers.request
import org.springframework.test.web.client.response.MockRestResponseCreators.withStatus
import org.springframework.web.client.RestTemplate
-class RestMtbFileSenderTest {
+class RestBwhcMtbFileSenderTest {
private lateinit var mockRestServiceServer: MockRestServiceServer
@@ -46,25 +48,25 @@ class RestMtbFileSenderTest {
@BeforeEach
fun setup() {
val restTemplate = RestTemplate()
- val restTargetProperties = RestTargetProperties("http://localhost:9000/mtbfile")
+ val restTargetProperties = RestTargetProperties("http://localhost:9000/mtbfile", null, null)
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
- this.restMtbFileSender = RestMtbFileSender(restTemplate, restTargetProperties, retryTemplate)
+ this.restMtbFileSender = RestBwhcMtbFileSender(restTemplate, restTargetProperties, retryTemplate)
}
@ParameterizedTest
@MethodSource("deleteRequestWithResponseSource")
fun shouldReturnExpectedResponseForDelete(requestWithResponse: RequestWithResponse) {
- this.mockRestServiceServer.expect {
- method(HttpMethod.DELETE)
- requestTo("/mtbfile")
- }.andRespond {
- withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
- }
+ this.mockRestServiceServer
+ .expect(method(HttpMethod.DELETE))
+ .andExpect(requestTo("http://localhost:9000/mtbfile/Patient/${TEST_PATIENT_PSEUDONYM.value}"))
+ .andRespond {
+ withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
+ }
- val response = restMtbFileSender.send(MtbFileSender.DeleteRequest("TestID", "PID"))
+ val response = restMtbFileSender.send(MtbFileSender.DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
assertThat(response.status).isEqualTo(requestWithResponse.response.status)
assertThat(response.body).isEqualTo(requestWithResponse.response.body)
}
@@ -72,14 +74,14 @@ class RestMtbFileSenderTest {
@ParameterizedTest
@MethodSource("mtbFileRequestWithResponseSource")
fun shouldReturnExpectedResponseForMtbFilePost(requestWithResponse: RequestWithResponse) {
- this.mockRestServiceServer.expect {
- method(HttpMethod.POST)
- requestTo("/mtbfile")
- }.andRespond {
- withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
- }
+ this.mockRestServiceServer
+ .expect(method(HttpMethod.POST))
+ .andExpect(requestTo("http://localhost:9000/mtbfile/MTBFile"))
+ .andRespond {
+ withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
+ }
- val response = restMtbFileSender.send(MtbFileSender.MtbFileRequest("TestID", mtbFile))
+ val response = restMtbFileSender.send(MtbFileSender.MtbFileRequest(TEST_REQUEST_ID, mtbFile))
assertThat(response.status).isEqualTo(requestWithResponse.response.status)
assertThat(response.body).isEqualTo(requestWithResponse.response.body)
}
@@ -88,11 +90,11 @@ class RestMtbFileSenderTest {
@MethodSource("mtbFileRequestWithResponseSource")
fun shouldRetryOnMtbFileHttpRequestError(requestWithResponse: RequestWithResponse) {
val restTemplate = RestTemplate()
- val restTargetProperties = RestTargetProperties("http://localhost:9000/mtbfile")
+ val restTargetProperties = RestTargetProperties("http://localhost:9000/mtbfile", null, null)
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(3)).build()
this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
- this.restMtbFileSender = RestMtbFileSender(restTemplate, restTargetProperties, retryTemplate)
+ this.restMtbFileSender = RestBwhcMtbFileSender(restTemplate, restTargetProperties, retryTemplate)
val expectedCount = when (requestWithResponse.httpStatus) {
// OK - No Retry
@@ -101,14 +103,14 @@ class RestMtbFileSenderTest {
else -> ExpectedCount.max(3)
}
- this.mockRestServiceServer.expect(expectedCount) {
- method(HttpMethod.POST)
- requestTo("/mtbfile")
- }.andRespond {
- withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
- }
+ this.mockRestServiceServer
+ .expect(expectedCount, method(HttpMethod.POST))
+ .andExpect(requestTo("http://localhost:9000/mtbfile/MTBFile"))
+ .andRespond {
+ withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
+ }
- val response = restMtbFileSender.send(MtbFileSender.MtbFileRequest("TestID", mtbFile))
+ val response = restMtbFileSender.send(MtbFileSender.MtbFileRequest(TEST_REQUEST_ID, mtbFile))
assertThat(response.status).isEqualTo(requestWithResponse.response.status)
assertThat(response.body).isEqualTo(requestWithResponse.response.body)
}
@@ -117,11 +119,11 @@ class RestMtbFileSenderTest {
@MethodSource("deleteRequestWithResponseSource")
fun shouldRetryOnDeleteHttpRequestError(requestWithResponse: RequestWithResponse) {
val restTemplate = RestTemplate()
- val restTargetProperties = RestTargetProperties("http://localhost:9000/mtbfile")
+ val restTargetProperties = RestTargetProperties("http://localhost:9000/mtbfile", null, null)
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(3)).build()
this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
- this.restMtbFileSender = RestMtbFileSender(restTemplate, restTargetProperties, retryTemplate)
+ this.restMtbFileSender = RestBwhcMtbFileSender(restTemplate, restTargetProperties, retryTemplate)
val expectedCount = when (requestWithResponse.httpStatus) {
// OK - No Retry
@@ -130,14 +132,14 @@ class RestMtbFileSenderTest {
else -> ExpectedCount.max(3)
}
- this.mockRestServiceServer.expect(expectedCount) {
- method(HttpMethod.DELETE)
- requestTo("/mtbfile")
- }.andRespond {
- withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
- }
+ this.mockRestServiceServer
+ .expect(expectedCount, method(HttpMethod.DELETE))
+ .andExpect(requestTo("http://localhost:9000/mtbfile/Patient/${TEST_PATIENT_PSEUDONYM.value}"))
+ .andRespond {
+ withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
+ }
- val response = restMtbFileSender.send(MtbFileSender.DeleteRequest("TestID", "PID"))
+ val response = restMtbFileSender.send(MtbFileSender.DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
assertThat(response.status).isEqualTo(requestWithResponse.response.status)
assertThat(response.body).isEqualTo(requestWithResponse.response.body)
}
@@ -149,6 +151,9 @@ class RestMtbFileSenderTest {
val response: MtbFileSender.Response
)
+ val TEST_REQUEST_ID = RequestId("TestId")
+ val TEST_PATIENT_PSEUDONYM = PatientPseudonym("PID")
+
private val warningBody = """
{
"patient_id": "PID",
@@ -208,23 +213,23 @@ class RestMtbFileSenderTest {
),
RequestWithResponse(
HttpStatus.BAD_REQUEST,
- "??",
+ ERROR_RESPONSE_BODY,
MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY)
),
RequestWithResponse(
HttpStatus.UNPROCESSABLE_ENTITY,
errorBody,
- MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY)
+ MtbFileSender.Response(RequestStatus.ERROR, errorBody)
),
// Some more errors not mentioned in documentation
RequestWithResponse(
HttpStatus.NOT_FOUND,
- "what????",
+ ERROR_RESPONSE_BODY,
MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY)
),
RequestWithResponse(
HttpStatus.INTERNAL_SERVER_ERROR,
- "what????",
+ ERROR_RESPONSE_BODY,
MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY)
)
)
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt
new file mode 100644
index 0000000..dac6496
--- /dev/null
+++ b/src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt
@@ -0,0 +1,262 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package dev.dnpm.etl.processor.output
+
+import de.ukw.ccc.bwhc.dto.*
+import dev.dnpm.etl.processor.PatientPseudonym
+import dev.dnpm.etl.processor.RequestId
+import dev.dnpm.etl.processor.config.RestTargetProperties
+import dev.dnpm.etl.processor.monitoring.RequestStatus
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.MethodSource
+import org.springframework.http.HttpMethod
+import org.springframework.http.HttpStatus
+import org.springframework.retry.policy.SimpleRetryPolicy
+import org.springframework.retry.support.RetryTemplateBuilder
+import org.springframework.test.web.client.ExpectedCount
+import org.springframework.test.web.client.MockRestServiceServer
+import org.springframework.test.web.client.match.MockRestRequestMatchers.method
+import org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo
+import org.springframework.test.web.client.response.MockRestResponseCreators.withStatus
+import org.springframework.web.client.RestTemplate
+
+class RestDipMtbFileSenderTest {
+
+ private lateinit var mockRestServiceServer: MockRestServiceServer
+
+ private lateinit var restMtbFileSender: RestMtbFileSender
+
+ @BeforeEach
+ fun setup() {
+ val restTemplate = RestTemplate()
+ val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null, false)
+ val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
+
+ this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
+
+ this.restMtbFileSender = RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate)
+ }
+
+ @ParameterizedTest
+ @MethodSource("deleteRequestWithResponseSource")
+ fun shouldReturnExpectedResponseForDelete(requestWithResponse: RequestWithResponse) {
+ this.mockRestServiceServer
+ .expect(method(HttpMethod.DELETE))
+ .andExpect(requestTo("http://localhost:9000/api/mtb/etl/patient/${TEST_PATIENT_PSEUDONYM.value}"))
+ .andRespond {
+ withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
+ }
+
+ val response = restMtbFileSender.send(MtbFileSender.DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
+ assertThat(response.status).isEqualTo(requestWithResponse.response.status)
+ assertThat(response.body).isEqualTo(requestWithResponse.response.body)
+ }
+
+ @ParameterizedTest
+ @MethodSource("mtbFileRequestWithResponseSource")
+ fun shouldReturnExpectedResponseForMtbFilePost(requestWithResponse: RequestWithResponse) {
+ this.mockRestServiceServer
+ .expect(method(HttpMethod.POST))
+ .andExpect(requestTo("http://localhost:9000/api/mtb/etl/patient-record"))
+ .andRespond {
+ withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
+ }
+
+ val response = restMtbFileSender.send(MtbFileSender.MtbFileRequest(TEST_REQUEST_ID, mtbFile))
+ assertThat(response.status).isEqualTo(requestWithResponse.response.status)
+ assertThat(response.body).isEqualTo(requestWithResponse.response.body)
+ }
+
+ @ParameterizedTest
+ @MethodSource("mtbFileRequestWithResponseSource")
+ fun shouldRetryOnMtbFileHttpRequestError(requestWithResponse: RequestWithResponse) {
+ val restTemplate = RestTemplate()
+ val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null, false)
+ val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(3)).build()
+
+ this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
+ this.restMtbFileSender = RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate)
+
+ val expectedCount = when (requestWithResponse.httpStatus) {
+ // OK - No Retry
+ HttpStatus.OK, HttpStatus.CREATED -> ExpectedCount.max(1)
+ // Request failed - Retry max 3 times
+ else -> ExpectedCount.max(3)
+ }
+
+ this.mockRestServiceServer
+ .expect(expectedCount, method(HttpMethod.POST))
+ .andExpect(requestTo("http://localhost:9000/api/mtb/etl/patient-record"))
+ .andRespond {
+ withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
+ }
+
+ val response = restMtbFileSender.send(MtbFileSender.MtbFileRequest(TEST_REQUEST_ID, mtbFile))
+ assertThat(response.status).isEqualTo(requestWithResponse.response.status)
+ assertThat(response.body).isEqualTo(requestWithResponse.response.body)
+ }
+
+ @ParameterizedTest
+ @MethodSource("deleteRequestWithResponseSource")
+ fun shouldRetryOnDeleteHttpRequestError(requestWithResponse: RequestWithResponse) {
+ val restTemplate = RestTemplate()
+ val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null, false)
+ val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(3)).build()
+
+ this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate)
+ this.restMtbFileSender = RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate)
+
+ val expectedCount = when (requestWithResponse.httpStatus) {
+ // OK - No Retry
+ HttpStatus.OK, HttpStatus.CREATED -> ExpectedCount.max(1)
+ // Request failed - Retry max 3 times
+ else -> ExpectedCount.max(3)
+ }
+
+ this.mockRestServiceServer
+ .expect(expectedCount, method(HttpMethod.DELETE))
+ .andExpect(requestTo("http://localhost:9000/api/mtb/etl/patient/${TEST_PATIENT_PSEUDONYM.value}"))
+ .andRespond {
+ withStatus(requestWithResponse.httpStatus).body(requestWithResponse.body).createResponse(it)
+ }
+
+ val response = restMtbFileSender.send(MtbFileSender.DeleteRequest(TEST_REQUEST_ID, TEST_PATIENT_PSEUDONYM))
+ assertThat(response.status).isEqualTo(requestWithResponse.response.status)
+ assertThat(response.body).isEqualTo(requestWithResponse.response.body)
+ }
+
+ companion object {
+ data class RequestWithResponse(
+ val httpStatus: HttpStatus,
+ val body: String,
+ val response: MtbFileSender.Response
+ )
+
+ val TEST_REQUEST_ID = RequestId("TestId")
+ val TEST_PATIENT_PSEUDONYM = PatientPseudonym("PID")
+
+ private val warningBody = """
+ {
+ "patient_id": "PID",
+ "issues": [
+ { "severity": "warning", "message": "Something is not right" }
+ ]
+ }
+ """.trimIndent()
+
+ private val errorBody = """
+ {
+ "patient_id": "PID",
+ "issues": [
+ { "severity": "error", "message": "Something is very bad" }
+ ]
+ }
+ """.trimIndent()
+
+ val mtbFile: MtbFile = MtbFile.builder()
+ .withPatient(
+ Patient.builder()
+ .withId("PID")
+ .withBirthDate("2000-08-08")
+ .withGender(Patient.Gender.MALE)
+ .build()
+ )
+ .withConsent(
+ Consent.builder()
+ .withId("1")
+ .withStatus(Consent.Status.ACTIVE)
+ .withPatient("PID")
+ .build()
+ )
+ .withEpisode(
+ Episode.builder()
+ .withId("1")
+ .withPatient("PID")
+ .withPeriod(PeriodStart("2023-08-08"))
+ .build()
+ )
+ .build()
+
+ private const val ERROR_RESPONSE_BODY = "Sonstiger Fehler bei der Übertragung"
+
+ /**
+ * Synthetic http responses with related request status
+ * Also see: https://ibmi-intra.cs.uni-tuebingen.de/display/ZPM/bwHC+REST+API
+ */
+ @JvmStatic
+ fun mtbFileRequestWithResponseSource(): Set<RequestWithResponse> {
+ return setOf(
+ RequestWithResponse(HttpStatus.OK, "{}", MtbFileSender.Response(RequestStatus.SUCCESS, "{}")),
+ RequestWithResponse(
+ HttpStatus.CREATED,
+ warningBody,
+ MtbFileSender.Response(RequestStatus.WARNING, warningBody)
+ ),
+ RequestWithResponse(
+ HttpStatus.BAD_REQUEST,
+ ERROR_RESPONSE_BODY,
+ MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY)
+ ),
+ RequestWithResponse(
+ HttpStatus.UNPROCESSABLE_ENTITY,
+ errorBody,
+ MtbFileSender.Response(RequestStatus.ERROR, errorBody)
+ ),
+ // Some more errors not mentioned in documentation
+ RequestWithResponse(
+ HttpStatus.NOT_FOUND,
+ ERROR_RESPONSE_BODY,
+ MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY)
+ ),
+ RequestWithResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ ERROR_RESPONSE_BODY,
+ MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY)
+ )
+ )
+ }
+
+ /**
+ * Synthetic http responses with related request status
+ * Also see: https://ibmi-intra.cs.uni-tuebingen.de/display/ZPM/bwHC+REST+API
+ */
+ @JvmStatic
+ fun deleteRequestWithResponseSource(): Set<RequestWithResponse> {
+ return setOf(
+ RequestWithResponse(HttpStatus.OK, "", MtbFileSender.Response(RequestStatus.SUCCESS)),
+ // Some more errors not mentioned in documentation
+ RequestWithResponse(
+ HttpStatus.NOT_FOUND,
+ "what????",
+ MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY)
+ ),
+ RequestWithResponse(
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ "what????",
+ MtbFileSender.Response(RequestStatus.ERROR, ERROR_RESPONSE_BODY)
+ )
+ )
+ }
+ }
+
+
+} \ No newline at end of file
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt
index d8c7813..0acf7db 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/pseudonym/ExtensionsTest.kt
@@ -25,9 +25,9 @@ import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.extension.ExtendWith
-import org.mockito.ArgumentMatchers
import org.mockito.Mock
import org.mockito.junit.jupiter.MockitoExtension
+import org.mockito.kotlin.anyValueClass
import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.whenever
import org.springframework.core.io.ClassPathResource
@@ -52,7 +52,7 @@ class ExtensionsTest {
doAnswer {
it.arguments[0]
"PSEUDO-ID"
- }.whenever(pseudonymizeService).patientPseudonym(ArgumentMatchers.anyString())
+ }.whenever(pseudonymizeService).patientPseudonym(anyValueClass())
val mtbFile = fakeMtbFile()
@@ -67,7 +67,7 @@ class ExtensionsTest {
doAnswer {
it.arguments[0]
"PSEUDO-ID"
- }.whenever(pseudonymizeService).patientPseudonym(ArgumentMatchers.anyString())
+ }.whenever(pseudonymizeService).patientPseudonym(anyValueClass())
doAnswer {
"TESTDOMAIN"
@@ -95,7 +95,7 @@ class ExtensionsTest {
doAnswer {
it.arguments[0]
"PSEUDO-ID"
- }.whenever(pseudonymizeService).patientPseudonym(ArgumentMatchers.anyString())
+ }.whenever(pseudonymizeService).patientPseudonym(anyValueClass())
doAnswer {
"TESTDOMAIN"
@@ -139,7 +139,7 @@ class ExtensionsTest {
doAnswer {
it.arguments[0]
"PSEUDO-ID"
- }.whenever(pseudonymizeService).patientPseudonym(ArgumentMatchers.anyString())
+ }.whenever(pseudonymizeService).patientPseudonym(anyValueClass())
doAnswer {
"TESTDOMAIN"
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/TokenServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/security/TokenServiceTest.kt
index 1fdc3d9..b93e9f5 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/TokenServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/security/TokenServiceTest.kt
@@ -17,13 +17,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package dev.dnpm.etl.processor.services
+package dev.dnpm.etl.processor.security
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
-import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.anyLong
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
@@ -96,11 +95,11 @@ class TokenServiceTest {
val actual = this.tokenService.addToken("Test Token")
- val captor = ArgumentCaptor.forClass(Token::class.java)
+ val captor = argumentCaptor<Token>()
verify(tokenRepository, times(1)).save(captor.capture())
assertThat(actual).satisfies(Consumer { assertThat(it.isSuccess).isTrue() })
- assertThat(captor.value).satisfies(
+ assertThat(captor.firstValue).satisfies(
Consumer { assertThat(it.name).isEqualTo("Test Token") },
Consumer { assertThat(it.username).isEqualTo("testtoken") },
Consumer { assertThat(it.password).isEqualTo("{test}verysecret") }
@@ -116,13 +115,13 @@ class TokenServiceTest {
this.tokenService.deleteToken(42)
- val stringCaptor = ArgumentCaptor.forClass(String::class.java)
+ val stringCaptor = argumentCaptor<String>()
verify(userDetailsManager, times(1)).deleteUser(stringCaptor.capture())
- assertThat(stringCaptor.value).isEqualTo("testtoken")
+ assertThat(stringCaptor.firstValue).isEqualTo("testtoken")
- val tokenCaptor = ArgumentCaptor.forClass(Token::class.java)
+ val tokenCaptor = argumentCaptor<Token>()
verify(tokenRepository, times(1)).delete(tokenCaptor.capture())
- assertThat(tokenCaptor.value.id).isEqualTo(42)
+ assertThat(tokenCaptor.firstValue.id).isEqualTo(42)
}
@Test
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/security/UserRoleServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/security/UserRoleServiceTest.kt
new file mode 100644
index 0000000..39ba7c0
--- /dev/null
+++ b/src/test/kotlin/dev/dnpm/etl/processor/security/UserRoleServiceTest.kt
@@ -0,0 +1,202 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package dev.dnpm.etl.processor.security
+
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Nested
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+import org.mockito.Mock
+import org.mockito.junit.jupiter.MockitoExtension
+import org.mockito.kotlin.*
+import org.springframework.security.core.session.SessionInformation
+import org.springframework.security.core.session.SessionRegistry
+import org.springframework.security.oauth2.core.oidc.OidcIdToken
+import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser
+import org.springframework.security.oauth2.core.oidc.user.OidcUser
+import java.time.Instant
+import java.util.*
+
+@ExtendWith(MockitoExtension::class)
+class UserRoleServiceTest {
+
+ private lateinit var userRoleRepository: UserRoleRepository
+ private lateinit var sessionRegistry: SessionRegistry
+
+ private lateinit var userRoleService: UserRoleService
+
+ @BeforeEach
+ fun setup(
+ @Mock userRoleRepository: UserRoleRepository,
+ @Mock sessionRegistry: SessionRegistry
+ ) {
+ this.userRoleRepository = userRoleRepository
+ this.sessionRegistry = sessionRegistry
+
+ this.userRoleService = UserRoleService(userRoleRepository, sessionRegistry)
+ }
+
+ @Test
+ fun shouldDelegateFindAllToRepository() {
+ userRoleService.findAll()
+
+ verify(userRoleRepository, times(1)).findAll()
+ }
+
+ @Nested
+ inner class WithExistingUserRole {
+
+ @BeforeEach
+ fun setup() {
+ doAnswer { invocation ->
+ Optional.of(
+ UserRole(invocation.getArgument(0), "patrick.tester", Role.USER)
+ )
+ }.whenever(userRoleRepository).findById(any<Long>())
+
+ doAnswer { _ ->
+ listOf(
+ dummyPrincipal()
+ )
+ }.whenever(sessionRegistry).allPrincipals
+ }
+
+ @Test
+ fun shouldUpdateUserRole() {
+ userRoleService.updateUserRole(1, Role.ADMIN)
+
+ val userRoleCaptor = argumentCaptor<UserRole>()
+ verify(userRoleRepository, times(1)).save(userRoleCaptor.capture())
+
+ assertThat(userRoleCaptor.firstValue.id).isEqualTo(1L)
+ assertThat(userRoleCaptor.firstValue.role).isEqualTo(Role.ADMIN)
+ }
+
+ @Test
+ fun shouldExpireSessionOnUpdate() {
+ val dummySessions = dummySessions()
+ whenever(sessionRegistry.getAllSessions(any(), any<Boolean>())).thenReturn(
+ dummySessions
+ )
+
+ assertThat(dummySessions.filter { it.isExpired }).hasSize(0)
+
+ userRoleService.updateUserRole(1, Role.ADMIN)
+
+ verify(sessionRegistry, times(1)).getAllSessions(any<OidcUser>(), any<Boolean>())
+
+ assertThat(dummySessions.filter { it.isExpired }).hasSize(2)
+ }
+
+ @Test
+ fun shouldDeleteUserRole() {
+ userRoleService.deleteUserRole(1)
+
+ val userRoleCaptor = argumentCaptor<UserRole>()
+ verify(userRoleRepository, times(1)).delete(userRoleCaptor.capture())
+
+ assertThat(userRoleCaptor.firstValue.id).isEqualTo(1L)
+ assertThat(userRoleCaptor.firstValue.role).isEqualTo(Role.USER)
+ }
+
+ @Test
+ fun shouldExpireSessionOnDelete() {
+ val dummySessions = dummySessions()
+ whenever(sessionRegistry.getAllSessions(any(), any<Boolean>())).thenReturn(
+ dummySessions
+ )
+
+ assertThat(dummySessions.filter { it.isExpired }).hasSize(0)
+
+ userRoleService.deleteUserRole(1)
+
+ verify(sessionRegistry, times(1)).getAllSessions(any<OidcUser>(), any<Boolean>())
+
+ assertThat(dummySessions.filter { it.isExpired }).hasSize(2)
+ }
+ }
+
+ @Nested
+ inner class WithoutExistingUserRole {
+
+ @BeforeEach
+ fun setup() {
+ doAnswer { _ ->
+ Optional.empty<UserRole>()
+ }.whenever(userRoleRepository).findById(any<Long>())
+ }
+
+ @Test
+ fun shouldNotUpdateUserRole() {
+ userRoleService.updateUserRole(1, Role.ADMIN)
+
+ verify(userRoleRepository, never()).save(any<UserRole>())
+ }
+
+ @Test
+ fun shouldNotExpireSessionOnUpdate() {
+ userRoleService.updateUserRole(1, Role.ADMIN)
+
+ verify(sessionRegistry, never()).getAllSessions(any<OidcUser>(), any<Boolean>())
+ }
+
+ @Test
+ fun shouldNotDeleteUserRole() {
+ userRoleService.deleteUserRole(1)
+
+ verify(userRoleRepository, never()).delete(any<UserRole>())
+ }
+
+ @Test
+ fun shouldNotExpireSessionOnDelete() {
+ userRoleService.deleteUserRole(1)
+
+ verify(sessionRegistry, never()).getAllSessions(any<OidcUser>(), any<Boolean>())
+ }
+
+ }
+
+
+ companion object {
+ private fun dummyPrincipal() = DefaultOidcUser(
+ listOf(),
+ OidcIdToken(
+ "anytokenvalue",
+ Instant.now(),
+ Instant.now().plusSeconds(10),
+ mapOf("sub" to "testsub", "preferred_username" to "patrick.tester")
+ )
+ )
+
+ private fun dummySessions() = listOf(
+ SessionInformation(
+ dummyPrincipal(),
+ "SESSIONID1",
+ Date.from(Instant.now()),
+ ),
+ SessionInformation(
+ dummyPrincipal(),
+ "SESSIONID2",
+ Date.from(Instant.now()),
+ )
+ )
+ }
+} \ No newline at end of file
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt
index 611c0ff..5578c7b 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt
@@ -21,6 +21,7 @@ package dev.dnpm.etl.processor.services
import com.fasterxml.jackson.databind.ObjectMapper
import de.ukw.ccc.bwhc.dto.*
+import dev.dnpm.etl.processor.*
import dev.dnpm.etl.processor.config.AppConfigProperties
import dev.dnpm.etl.processor.monitoring.Request
import dev.dnpm.etl.processor.monitoring.RequestStatus
@@ -32,16 +33,15 @@ import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
-import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.Mockito.*
import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.kotlin.any
+import org.mockito.kotlin.anyValueClass
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.whenever
import org.springframework.context.ApplicationEventPublisher
import java.time.Instant
-import java.util.*
@ExtendWith(MockitoExtension::class)
@@ -88,24 +88,24 @@ class RequestProcessorTest {
fun testShouldSendMtbFileDuplicationAndSaveUnknownRequestStatusAtFirst() {
doAnswer {
Request(
- id = 1L,
- uuid = UUID.randomUUID().toString(),
- patientId = "TEST_12345678901",
- pid = "P1",
- fingerprint = "zdlzv5s5ydmd4ktw2v5piohegc4jcyrm6j66bq6tv2uxuerndmga",
- type = RequestType.MTB_FILE,
- status = RequestStatus.SUCCESS,
- processedAt = Instant.parse("2023-08-08T02:00:00Z")
+ 1L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("zdlzv5s5ydmd4ktw2v5piohegc4jcyrm6j66bq6tv2uxuerndmga"),
+ RequestType.MTB_FILE,
+ RequestStatus.SUCCESS,
+ Instant.parse("2023-08-08T02:00:00Z")
)
- }.`when`(requestService).lastMtbFileRequestForPatientPseudonym(anyString())
+ }.whenever(requestService).lastMtbFileRequestForPatientPseudonym(anyValueClass())
doAnswer {
false
- }.`when`(requestService).isLastRequestWithKnownStatusDeletion(anyString())
+ }.whenever(requestService).isLastRequestWithKnownStatusDeletion(anyValueClass())
doAnswer {
it.arguments[0] as String
- }.`when`(pseudonymizeService).patientPseudonym(any())
+ }.whenever(pseudonymizeService).patientPseudonym(anyValueClass())
doAnswer {
it.arguments[0]
@@ -147,24 +147,24 @@ class RequestProcessorTest {
fun testShouldDetectMtbFileDuplicationAndSendDuplicationEvent() {
doAnswer {
Request(
- id = 1L,
- uuid = UUID.randomUUID().toString(),
- patientId = "TEST_12345678901",
- pid = "P1",
- fingerprint = "zdlzv5s5ydmd4ktw2v5piohegc4jcyrm6j66bq6tv2uxuerndmga",
- type = RequestType.MTB_FILE,
- status = RequestStatus.SUCCESS,
- processedAt = Instant.parse("2023-08-08T02:00:00Z")
+ 1L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("zdlzv5s5ydmd4ktw2v5piohegc4jcyrm6j66bq6tv2uxuerndmga"),
+ RequestType.MTB_FILE,
+ RequestStatus.SUCCESS,
+ Instant.parse("2023-08-08T02:00:00Z")
)
- }.`when`(requestService).lastMtbFileRequestForPatientPseudonym(anyString())
+ }.whenever(requestService).lastMtbFileRequestForPatientPseudonym(anyValueClass())
doAnswer {
false
- }.`when`(requestService).isLastRequestWithKnownStatusDeletion(anyString())
+ }.whenever(requestService).isLastRequestWithKnownStatusDeletion(anyValueClass())
doAnswer {
it.arguments[0] as String
- }.`when`(pseudonymizeService).patientPseudonym(any())
+ }.whenever(pseudonymizeService).patientPseudonym(anyValueClass())
doAnswer {
it.arguments[0]
@@ -206,28 +206,28 @@ class RequestProcessorTest {
fun testShouldSendMtbFileAndSendSuccessEvent() {
doAnswer {
Request(
- id = 1L,
- uuid = UUID.randomUUID().toString(),
- patientId = "TEST_12345678901",
- pid = "P1",
- fingerprint = "different",
- type = RequestType.MTB_FILE,
- status = RequestStatus.SUCCESS,
- processedAt = Instant.parse("2023-08-08T02:00:00Z")
+ 1L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("different"),
+ RequestType.MTB_FILE,
+ RequestStatus.SUCCESS,
+ Instant.parse("2023-08-08T02:00:00Z")
)
- }.`when`(requestService).lastMtbFileRequestForPatientPseudonym(anyString())
+ }.whenever(requestService).lastMtbFileRequestForPatientPseudonym(anyValueClass())
doAnswer {
false
- }.`when`(requestService).isLastRequestWithKnownStatusDeletion(anyString())
+ }.whenever(requestService).isLastRequestWithKnownStatusDeletion(anyValueClass())
doAnswer {
MtbFileSender.Response(status = RequestStatus.SUCCESS)
- }.`when`(sender).send(any<MtbFileSender.MtbFileRequest>())
+ }.whenever(sender).send(any<MtbFileSender.MtbFileRequest>())
doAnswer {
it.arguments[0] as String
- }.`when`(pseudonymizeService).patientPseudonym(any())
+ }.whenever(pseudonymizeService).patientPseudonym(anyValueClass())
doAnswer {
it.arguments[0]
@@ -269,28 +269,28 @@ class RequestProcessorTest {
fun testShouldSendMtbFileAndSendErrorEvent() {
doAnswer {
Request(
- id = 1L,
- uuid = UUID.randomUUID().toString(),
- patientId = "TEST_12345678901",
- pid = "P1",
- fingerprint = "different",
- type = RequestType.MTB_FILE,
- status = RequestStatus.SUCCESS,
- processedAt = Instant.parse("2023-08-08T02:00:00Z")
+ 1L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("different"),
+ RequestType.MTB_FILE,
+ RequestStatus.SUCCESS,
+ Instant.parse("2023-08-08T02:00:00Z")
)
- }.`when`(requestService).lastMtbFileRequestForPatientPseudonym(anyString())
+ }.whenever(requestService).lastMtbFileRequestForPatientPseudonym(anyValueClass())
doAnswer {
false
- }.`when`(requestService).isLastRequestWithKnownStatusDeletion(anyString())
+ }.whenever(requestService).isLastRequestWithKnownStatusDeletion(anyValueClass())
doAnswer {
MtbFileSender.Response(status = RequestStatus.ERROR)
- }.`when`(sender).send(any<MtbFileSender.MtbFileRequest>())
+ }.whenever(sender).send(any<MtbFileSender.MtbFileRequest>())
doAnswer {
it.arguments[0] as String
- }.`when`(pseudonymizeService).patientPseudonym(any())
+ }.whenever(pseudonymizeService).patientPseudonym(anyValueClass())
doAnswer {
it.arguments[0]
@@ -332,13 +332,13 @@ class RequestProcessorTest {
fun testShouldSendDeleteRequestAndSaveUnknownRequestStatusAtFirst() {
doAnswer {
"PSEUDONYM"
- }.`when`(pseudonymizeService).patientPseudonym(anyString())
+ }.whenever(pseudonymizeService).patientPseudonym(anyValueClass())
doAnswer {
MtbFileSender.Response(status = RequestStatus.UNKNOWN)
- }.`when`(sender).send(any<MtbFileSender.DeleteRequest>())
+ }.whenever(sender).send(any<MtbFileSender.DeleteRequest>())
- this.requestProcessor.processDeletion("TEST_12345678901")
+ this.requestProcessor.processDeletion(TEST_PATIENT_ID)
val requestCaptor = argumentCaptor<Request>()
verify(requestService, times(1)).save(requestCaptor.capture())
@@ -350,13 +350,13 @@ class RequestProcessorTest {
fun testShouldSendDeleteRequestAndSendSuccessEvent() {
doAnswer {
"PSEUDONYM"
- }.`when`(pseudonymizeService).patientPseudonym(anyString())
+ }.whenever(pseudonymizeService).patientPseudonym(anyValueClass())
doAnswer {
MtbFileSender.Response(status = RequestStatus.SUCCESS)
- }.`when`(sender).send(any<MtbFileSender.DeleteRequest>())
+ }.whenever(sender).send(any<MtbFileSender.DeleteRequest>())
- this.requestProcessor.processDeletion("TEST_12345678901")
+ this.requestProcessor.processDeletion(TEST_PATIENT_ID)
val eventCaptor = argumentCaptor<ResponseEvent>()
verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
@@ -368,13 +368,13 @@ class RequestProcessorTest {
fun testShouldSendDeleteRequestAndSendErrorEvent() {
doAnswer {
"PSEUDONYM"
- }.`when`(pseudonymizeService).patientPseudonym(anyString())
+ }.whenever(pseudonymizeService).patientPseudonym(anyValueClass())
doAnswer {
MtbFileSender.Response(status = RequestStatus.ERROR)
- }.`when`(sender).send(any<MtbFileSender.DeleteRequest>())
+ }.whenever(sender).send(any<MtbFileSender.DeleteRequest>())
- this.requestProcessor.processDeletion("TEST_12345678901")
+ this.requestProcessor.processDeletion(TEST_PATIENT_ID)
val eventCaptor = argumentCaptor<ResponseEvent>()
verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
@@ -384,9 +384,9 @@ class RequestProcessorTest {
@Test
fun testShouldSendDeleteRequestWithPseudonymErrorAndSaveErrorRequestStatus() {
- doThrow(RuntimeException()).`when`(pseudonymizeService).patientPseudonym(anyString())
+ doThrow(RuntimeException()).whenever(pseudonymizeService).patientPseudonym(anyValueClass())
- this.requestProcessor.processDeletion("TEST_12345678901")
+ this.requestProcessor.processDeletion(TEST_PATIENT_ID)
val requestCaptor = argumentCaptor<Request>()
verify(requestService, times(1)).save(requestCaptor.capture())
@@ -400,7 +400,7 @@ class RequestProcessorTest {
doAnswer {
it.arguments[0] as String
- }.`when`(pseudonymizeService).patientPseudonym(any())
+ }.whenever(pseudonymizeService).patientPseudonym(anyValueClass())
doAnswer {
it.arguments[0]
@@ -408,7 +408,7 @@ class RequestProcessorTest {
doAnswer {
MtbFileSender.Response(status = RequestStatus.SUCCESS)
- }.`when`(sender).send(any<MtbFileSender.MtbFileRequest>())
+ }.whenever(sender).send(any<MtbFileSender.MtbFileRequest>())
val mtbFile = MtbFile.builder()
.withPatient(
@@ -442,4 +442,8 @@ class RequestProcessorTest {
assertThat(eventCaptor.firstValue.status).isEqualTo(RequestStatus.SUCCESS)
}
+ companion object {
+ val TEST_PATIENT_ID = PatientId("TEST_12345678901")
+ }
+
} \ No newline at end of file
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt
index 3cf8804..c0e4400 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt
@@ -19,6 +19,7 @@
package dev.dnpm.etl.processor.services
+import dev.dnpm.etl.processor.*
import dev.dnpm.etl.processor.monitoring.Request
import dev.dnpm.etl.processor.monitoring.RequestRepository
import dev.dnpm.etl.processor.monitoring.RequestStatus
@@ -30,8 +31,9 @@ import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.Mock
import org.mockito.Mockito.*
import org.mockito.junit.jupiter.MockitoExtension
+import org.mockito.kotlin.anyValueClass
+import org.mockito.kotlin.whenever
import java.time.Instant
-import java.util.*
@ExtendWith(MockitoExtension::class)
class RequestServiceTest {
@@ -41,14 +43,14 @@ class RequestServiceTest {
private lateinit var requestService: RequestService
private fun anyRequest() = any(Request::class.java) ?: Request(
- id = 0L,
- uuid = UUID.randomUUID().toString(),
- patientId = "TEST_dummy",
- pid = "PX",
- fingerprint = "dummy",
- type = RequestType.MTB_FILE,
- status = RequestStatus.SUCCESS,
- processedAt = Instant.parse("2023-08-08T02:00:00Z")
+ 0L,
+ randomRequestId(),
+ PatientPseudonym("TEST_dummy"),
+ PatientId("PX"),
+ Fingerprint("dummy"),
+ RequestType.MTB_FILE,
+ RequestStatus.SUCCESS,
+ Instant.parse("2023-08-08T02:00:00Z")
)
@BeforeEach
@@ -63,34 +65,34 @@ class RequestServiceTest {
fun shouldIndicateLastRequestIsDeleteRequest() {
val requests = listOf(
Request(
- id = 1L,
- uuid = UUID.randomUUID().toString(),
- patientId = "TEST_12345678901",
- pid = "P1",
- fingerprint = "0123456789abcdef1",
- type = RequestType.MTB_FILE,
- status = RequestStatus.WARNING,
- processedAt = Instant.parse("2023-07-07T00:00:00Z")
+ 1L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("0123456789abcdef1"),
+ RequestType.MTB_FILE,
+ RequestStatus.WARNING,
+ Instant.parse("2023-07-07T00:00:00Z")
),
Request(
- id = 2L,
- uuid = UUID.randomUUID().toString(),
- patientId = "TEST_12345678901",
- pid = "P1",
- fingerprint = "0123456789abcdefd",
- type = RequestType.DELETE,
- status = RequestStatus.WARNING,
- processedAt = Instant.parse("2023-07-07T02:00:00Z")
+ 2L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("0123456789abcdefd"),
+ RequestType.DELETE,
+ RequestStatus.WARNING,
+ Instant.parse("2023-07-07T02:00:00Z")
),
Request(
- id = 3L,
- uuid = UUID.randomUUID().toString(),
- patientId = "TEST_12345678901",
- pid = "P1",
- fingerprint = "0123456789abcdef1",
- type = RequestType.MTB_FILE,
- status = RequestStatus.UNKNOWN,
- processedAt = Instant.parse("2023-08-11T00:00:00Z")
+ 3L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("0123456789abcdef1"),
+ RequestType.MTB_FILE,
+ RequestStatus.UNKNOWN,
+ Instant.parse("2023-08-11T00:00:00Z")
)
)
@@ -103,34 +105,34 @@ class RequestServiceTest {
fun shouldIndicateLastRequestIsNotDeleteRequest() {
val requests = listOf(
Request(
- id = 1L,
- uuid = UUID.randomUUID().toString(),
- patientId = "TEST_12345678901",
- pid = "P1",
- fingerprint = "0123456789abcdef1",
- type = RequestType.MTB_FILE,
- status = RequestStatus.WARNING,
- processedAt = Instant.parse("2023-07-07T00:00:00Z")
+ 1L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("0123456789abcdef1"),
+ RequestType.MTB_FILE,
+ RequestStatus.WARNING,
+ Instant.parse("2023-07-07T00:00:00Z")
),
Request(
- id = 2L,
- uuid = UUID.randomUUID().toString(),
- patientId = "TEST_12345678901",
- pid = "P1",
- fingerprint = "0123456789abcdef1",
- type = RequestType.MTB_FILE,
- status = RequestStatus.WARNING,
- processedAt = Instant.parse("2023-07-07T02:00:00Z")
+ 2L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("0123456789abcdef1"),
+ RequestType.MTB_FILE,
+ RequestStatus.WARNING,
+ Instant.parse("2023-07-07T02:00:00Z")
),
Request(
- id = 3L,
- uuid = UUID.randomUUID().toString(),
- patientId = "TEST_12345678901",
- pid = "P1",
- fingerprint = "0123456789abcdef1",
- type = RequestType.MTB_FILE,
- status = RequestStatus.UNKNOWN,
- processedAt = Instant.parse("2023-08-11T00:00:00Z")
+ 3L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("0123456789abcdef1"),
+ RequestType.MTB_FILE,
+ RequestStatus.UNKNOWN,
+ Instant.parse("2023-08-11T00:00:00Z")
)
)
@@ -143,31 +145,31 @@ class RequestServiceTest {
fun shouldReturnPatientsLastRequest() {
val requests = listOf(
Request(
- id = 1L,
- uuid = UUID.randomUUID().toString(),
- patientId = "TEST_12345678901",
- pid = "P1",
- fingerprint = "0123456789abcdef1",
- type = RequestType.DELETE,
- status = RequestStatus.SUCCESS,
- processedAt = Instant.parse("2023-07-07T02:00:00Z")
+ 1L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("0123456789abcdef1"),
+ RequestType.DELETE,
+ RequestStatus.SUCCESS,
+ Instant.parse("2023-07-07T02:00:00Z")
),
Request(
- id = 1L,
- uuid = UUID.randomUUID().toString(),
- patientId = "TEST_12345678902",
- pid = "P2",
- fingerprint = "0123456789abcdef2",
- type = RequestType.MTB_FILE,
- status = RequestStatus.WARNING,
- processedAt = Instant.parse("2023-08-08T00:00:00Z")
+ 1L,
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678902"),
+ PatientId("P2"),
+ Fingerprint("0123456789abcdef2"),
+ RequestType.MTB_FILE,
+ RequestStatus.WARNING,
+ Instant.parse("2023-08-08T00:00:00Z")
)
)
val actual = RequestService.lastMtbFileRequestForPatientPseudonym(requests)
assertThat(actual).isInstanceOf(Request::class.java)
- assertThat(actual?.fingerprint).isEqualTo("0123456789abcdef2")
+ assertThat(actual?.fingerprint).isEqualTo(Fingerprint("0123456789abcdef2"))
}
@Test
@@ -184,16 +186,16 @@ class RequestServiceTest {
doAnswer {
val obj = it.arguments[0] as Request
obj.copy(id = 1L)
- }.`when`(requestRepository).save(anyRequest())
+ }.whenever(requestRepository).save(anyRequest())
val request = Request(
- uuid = UUID.randomUUID().toString(),
- patientId = "TEST_12345678901",
- pid = "P1",
- fingerprint = "0123456789abcdef1",
- type = RequestType.DELETE,
- status = RequestStatus.SUCCESS,
- processedAt = Instant.parse("2023-07-07T02:00:00Z")
+ randomRequestId(),
+ PatientPseudonym("TEST_12345678901"),
+ PatientId("P1"),
+ Fingerprint("0123456789abcdef1"),
+ RequestType.DELETE,
+ RequestStatus.SUCCESS,
+ Instant.parse("2023-07-07T02:00:00Z")
)
requestService.save(request)
@@ -203,23 +205,23 @@ class RequestServiceTest {
@Test
fun allRequestsByPatientPseudonymShouldRequestAllRequestsForPatientPseudonym() {
- requestService.allRequestsByPatientPseudonym("TEST_12345678901")
+ requestService.allRequestsByPatientPseudonym(PatientPseudonym("TEST_12345678901"))
- verify(requestRepository, times(1)).findAllByPatientIdOrderByProcessedAtDesc(anyString())
+ verify(requestRepository, times(1)).findAllByPatientPseudonymOrderByProcessedAtDesc(anyValueClass())
}
@Test
fun lastMtbFileRequestForPatientPseudonymShouldRequestAllRequestsForPatientPseudonym() {
- requestService.lastMtbFileRequestForPatientPseudonym("TEST_12345678901")
+ requestService.lastMtbFileRequestForPatientPseudonym(PatientPseudonym("TEST_12345678901"))
- verify(requestRepository, times(1)).findAllByPatientIdOrderByProcessedAtDesc(anyString())
+ verify(requestRepository, times(1)).findAllByPatientPseudonymOrderByProcessedAtDesc(anyValueClass())
}
@Test
fun isLastRequestDeletionShouldRequestAllRequestsForPatientPseudonym() {
- requestService.isLastRequestWithKnownStatusDeletion("TEST_12345678901")
+ requestService.isLastRequestWithKnownStatusDeletion(PatientPseudonym("TEST_12345678901"))
- verify(requestRepository, times(1)).findAllByPatientIdOrderByProcessedAtDesc(anyString())
+ verify(requestRepository, times(1)).findAllByPatientPseudonymOrderByProcessedAtDesc(anyValueClass())
}
} \ No newline at end of file
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt
index b9e4b7f..465d8b8 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt
@@ -19,8 +19,8 @@
package dev.dnpm.etl.processor.services
+import dev.dnpm.etl.processor.*
import dev.dnpm.etl.processor.monitoring.Request
-import dev.dnpm.etl.processor.monitoring.RequestRepository
import dev.dnpm.etl.processor.monitoring.RequestStatus
import dev.dnpm.etl.processor.monitoring.RequestType
import org.assertj.core.api.Assertions.assertThat
@@ -29,7 +29,6 @@ import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.MethodSource
-import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.kotlin.*
@@ -40,64 +39,64 @@ import java.util.*
@ExtendWith(MockitoExtension::class)
class ResponseProcessorTest {
- private lateinit var requestRepository: RequestRepository
+ private lateinit var requestService: RequestService
private lateinit var statisticsUpdateProducer: Sinks.Many<Any>
private lateinit var responseProcessor: ResponseProcessor
private val testRequest = Request(
1L,
- "TestID1234",
- "PSEUDONYM-A",
- "1",
- "dummyfingerprint",
+ RequestId("TestID1234"),
+ PatientPseudonym("PSEUDONYM-A"),
+ PatientId("1"),
+ Fingerprint("dummyfingerprint"),
RequestType.MTB_FILE,
RequestStatus.UNKNOWN
)
@BeforeEach
fun setup(
- @Mock requestRepository: RequestRepository,
+ @Mock requestService: RequestService,
@Mock statisticsUpdateProducer: Sinks.Many<Any>
) {
- this.requestRepository = requestRepository
+ this.requestService = requestService
this.statisticsUpdateProducer = statisticsUpdateProducer
- this.responseProcessor = ResponseProcessor(requestRepository, statisticsUpdateProducer)
+ this.responseProcessor = ResponseProcessor(requestService, statisticsUpdateProducer)
}
@Test
fun shouldNotSaveStatusForUnknownRequest() {
doAnswer {
Optional.empty<Request>()
- }.whenever(requestRepository).findByUuidEquals(anyString())
+ }.whenever(requestService).findByUuid(anyValueClass())
val event = ResponseEvent(
- "TestID1234",
+ RequestId("TestID1234"),
Instant.parse("2023-09-09T00:00:00Z"),
RequestStatus.SUCCESS
)
this.responseProcessor.handleResponseEvent(event)
- verify(requestRepository, never()).save(any())
+ verify(requestService, never()).save(any())
}
@Test
fun shouldNotSaveStatusWithUnknownState() {
doAnswer {
Optional.of(testRequest)
- }.whenever(requestRepository).findByUuidEquals(anyString())
+ }.whenever(requestService).findByUuid(anyValueClass())
val event = ResponseEvent(
- "TestID1234",
+ RequestId("TestID1234"),
Instant.parse("2023-09-09T00:00:00Z"),
RequestStatus.UNKNOWN
)
this.responseProcessor.handleResponseEvent(event)
- verify(requestRepository, never()).save(any())
+ verify(requestService, never()).save(any<Request>())
}
@ParameterizedTest
@@ -105,10 +104,10 @@ class ResponseProcessorTest {
fun shouldSaveStatusForKnownRequest(requestStatus: RequestStatus) {
doAnswer {
Optional.of(testRequest)
- }.whenever(requestRepository).findByUuidEquals(anyString())
+ }.whenever(requestService).findByUuid(anyValueClass())
val event = ResponseEvent(
- "TestID1234",
+ RequestId("TestID1234"),
Instant.parse("2023-09-09T00:00:00Z"),
requestStatus
)
@@ -116,7 +115,7 @@ class ResponseProcessorTest {
this.responseProcessor.handleResponseEvent(event)
val captor = argumentCaptor<Request>()
- verify(requestRepository, times(1)).save(captor.capture())
+ verify(requestService, times(1)).save(captor.capture())
assertThat(captor.firstValue).isNotNull
assertThat(captor.firstValue.status).isEqualTo(requestStatus)
}
diff --git a/src/test/resources/fake_MTBFile.json b/src/test/resources/fake_MTBFile.json
index 3f4e8a3..cdf8d75 100644
--- a/src/test/resources/fake_MTBFile.json
+++ b/src/test/resources/fake_MTBFile.json
@@ -1 +1 @@
-{"patient":{"id":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","gender":"female","birthDate":"1971-03","insurance":"Barmer"},"consent":{"id":"b93e4717-7b0e-4ca5-a5d6-cf8d0f7b14cf","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","status":"active"},"episode":{"id":"8ddb893f-0d55-412f-a257-9bc8bb054549","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","period":{"start":"2021-12-29"}},"diagnoses":[{"id":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","recordedOn":"2023-12-14","icd10":{"code":"C16.0","display":"Bösartige Neubildung: Kardia","version":"2023","system":"ICD-10-GM"},"whoGrade":{"code":"III","system":"WHO-Grading-CNS-Tumors"},"histologyResults":["385926d9-51f2-4a3a-96b6-57c5effefd84"],"statusHistory":[{"status":"local","date":"2023-12-14"},{"status":"unknown","date":"2023-12-14"}],"guidelineTreatmentStatus":"no-guidelines-available"}],"familyMemberDiagnoses":[{"id":"c434f063-76d9-4a7f-8ff2-34cd55fc56b2","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","relationship":{"code":"EXT","system":"http://terminology.hl7.org/ValueSet/v3-FamilyMember"}},{"id":"b07a73a8-70ed-48f8-a745-e82e7a5907a8","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","relationship":{"code":"EXT","system":"http://terminology.hl7.org/ValueSet/v3-FamilyMember"}}],"previousGuidelineTherapies":[{"id":"6435d684-18e3-45ad-b063-cdc303f61aa2","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","diagnosis":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","therapyLine":4,"medication":[{"code":"L01XC18","system":"ATC","display":"Pembrolizumab","version":"2020"},{"code":"L01XE21","system":"ATC","display":"Regorafenib","version":"2020"},{"code":"L01XC17","system":"ATC","display":"Nivolumab","version":"2020"}]},{"id":"e35731db-7447-4c4b-896a-0e90f1e68c67","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","diagnosis":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","therapyLine":4,"medication":[{"code":"L01XX46","system":"ATC","display":"Olaparib","version":"2020"},{"code":"L01XX32","system":"ATC","display":"Bortezomib","version":"2020"},{"code":"L01XE02","system":"ATC","display":"Gefitinib","version":"2020"}]},{"id":"d8a46cf9-cdc9-4f0d-b106-5aa57e08c4d0","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","diagnosis":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","therapyLine":1,"medication":[{"code":"L01XC28","system":"ATC","display":"Durvalumab","version":"2020"},{"code":"L01XC06","system":"ATC","display":"Cetuximab","version":"2020"},{"code":"L01XE47","system":"ATC","display":"Dacomitinib","version":"2020"}]}],"lastGuidelineTherapies":[{"id":"9152b20d-ac04-406c-b18b-5b6f7f4d1911","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","diagnosis":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","therapyLine":1,"period":{"start":"2023-12-14","end":"2024-01-04"},"medication":[{"code":"L01DB01","system":"ATC","display":"Doxorubicin","version":"2020"}],"reasonStopped":{"code":"toxicity","system":"MTB-CDS:GuidelineTherapy-StopReason"}}],"ecogStatus":[{"id":"51589dd2-f48d-4c41-8740-292b88d63b30","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","effectiveDate":"2023-12-14","value":{"code":"2","system":"ECOG-Performance-Status"}},{"id":"30caf153-a30a-4a1c-9056-fd4eae2a55da","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","effectiveDate":"2023-12-14","value":{"code":"4","system":"ECOG-Performance-Status"}}],"specimens":[{"id":"40043ae5-d4cb-48e4-85c6-b34266b7693f","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","icd10":{"code":"C16.0","display":"Bösartige Neubildung: Kardia","version":"2023","system":"ICD-10-GM"},"type":"liquid-biopsy","collection":{"date":"2023-12-14","localization":"unknown","method":"liquid-biopsy"}}],"molecularPathologyFindings":[{"id":"c7622342-3297-489e-850a-26aaf1225b36","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","specimen":"40043ae5-d4cb-48e4-85c6-b34266b7693f","performingInstitute":"TESTINSTITUTE","issuedOn":"2023-12-14","note":"MolecularPathologyFinding notes..."}],"histologyReports":[{"id":"385926d9-51f2-4a3a-96b6-57c5effefd84","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","specimen":"40043ae5-d4cb-48e4-85c6-b34266b7693f","issuedOn":"2023-12-14","tumorMorphology":{"id":"592b13c7-9507-4f31-a544-5cff90e35581","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","specimen":"40043ae5-d4cb-48e4-85c6-b34266b7693f","value":{"code":"8851/3","display":"Gut differenziertes Liposarkom","version":"Zweite Revision","system":"ICD-O-3-M"},"note":"Histology finding notes..."},"tumorCellContent":{"id":"f6af339c-415c-4682-b700-499e392b4558","specimen":"40043ae5-d4cb-48e4-85c6-b34266b7693f","method":"histologic","value":0.38164}}],"ngsReports":[{"id":"223e3e6e-d99b-415e-83c0-18bcfc5729ca","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","specimen":"40043ae5-d4cb-48e4-85c6-b34266b7693f","issueDate":"2023-12-14","sequencingType":"WGS","metadata":[{"kitType":"Agilent ExomV6","kitManufacturer":"Agilent","sequencer":"Sequencer-XYZ","referenceGenome":"HG19","pipeline":"dummy/uri/to/pipeline"}],"tumorCellContent":{"id":"e865f20a-1307-4ca3-b2ef-3a863b8afde0","specimen":"40043ae5-d4cb-48e4-85c6-b34266b7693f","method":"bioinformatic","value":0.74991},"brcaness":0.39,"msi":0.35,"tmb":594349.91,"simpleVariants":[{"id":"SNV_599c38d4-af9f-416c-ad38-eb2fee8159e1","chromosome":"chr6","gene":{"ensemblId":"ENSENSG00000242908","hgncId":"HGNC:50301","symbol":"AADACL2-AS1","name":"AADACL2 antisense RNA 1"},"startEnd":{"start":6736035388467870105},"refAllele":"A","altAllele":"G","dnaChange":{"code":"A>G","system":"HGVS.c"},"aminoAcidChange":{"code":"Amino acid change code...","system":"HGVS.p"},"readDepth":19,"allelicFrequency":0.75,"cosmicId":"COSMICf106c745-dbaa-453f-8dca-2f584bc1e6cb","dbSNPId":"DBSNPIDc3f51fb2-31f3-4b27-bbcc-aac52736986f","interpretation":{"code":"Probably Inactivating","system":"ClinVAR"}},{"id":"SNV_963a3ea1-a1d5-4a52-b8d4-2e969be74b7b","chromosome":"chr2","gene":{"ensemblId":"ENSENSG00000141338","hgncId":"HGNC:38","symbol":"ABCA8","name":"ATP binding cassette subfamily A member 8"},"startEnd":{"start":1672464855319477743},"refAllele":"T","altAllele":"C","dnaChange":{"code":"T>C","system":"HGVS.c"},"aminoAcidChange":{"code":"Amino acid change code...","system":"HGVS.p"},"readDepth":23,"allelicFrequency":0.36,"cosmicId":"COSMICbcbc96bb-0428-48c9-8c64-7d2fd884528d","dbSNPId":"DBSNPIDc4904618-819c-4af1-b793-ca9d820371dc","interpretation":{"code":"Ambiguous","system":"ClinVAR"}},{"id":"SNV_7f35df9d-d8b1-4421-9ec7-35cf8d3c4546","chromosome":"chr5","gene":{"ensemblId":"ENSENSG00000149313","hgncId":"HGNC:14235","symbol":"AASDHPPT","name":"aminoadipate-semialdehyde dehydrogenase-phosphopantetheinyl transferase"},"startEnd":{"start":4251323878559029469},"refAllele":"A","altAllele":"C","dnaChange":{"code":"A>C","system":"HGVS.c"},"aminoAcidChange":{"code":"Amino acid change code...","system":"HGVS.p"},"readDepth":37,"allelicFrequency":0.48,"cosmicId":"COSMICc3c67469-2303-4cba-9b45-424d62a0d3db","dbSNPId":"DBSNPIDd94cb5ce-250a-471f-a571-015fe8a711c9","interpretation":{"code":"Function Changed","system":"ClinVAR"}},{"id":"SNV_22f943fd-ad99-48af-a61e-42679e851b71","chromosome":"chr2","gene":{"ensemblId":"ENSENSG00000167972","hgncId":"HGNC:33","symbol":"ABCA3","name":"ATP binding cassette subfamily A member 3"},"startEnd":{"start":7454627449124699972},"refAllele":"A","altAllele":"C","dnaChange":{"code":"A>C","system":"HGVS.c"},"aminoAcidChange":{"code":"Amino acid change code...","system":"HGVS.p"},"readDepth":22,"allelicFrequency":0.37,"cosmicId":"COSMICa6074760-ce24-4075-ab11-f5ab4cd6c497","dbSNPId":"DBSNPID3578fa1b-eb03-423c-929d-6705cd8e805c","interpretation":{"code":"Function Changed","system":"ClinVAR"}},{"id":"SNV_fe346bed-74ac-4b84-843b-7490a5823364","chromosome":"chr14","gene":{"ensemblId":"ENSENSG00000125257","hgncId":"HGNC:55","symbol":"ABCC4","name":"ATP binding cassette subfamily C member 4"},"startEnd":{"start":6478613836523717707},"refAllele":"G","altAllele":"T","dnaChange":{"code":"G>T","system":"HGVS.c"},"aminoAcidChange":{"code":"Amino acid change code...","system":"HGVS.p"},"readDepth":30,"allelicFrequency":0.47,"cosmicId":"COSMIC14d8842e-6af9-434f-a993-32fae87a84be","dbSNPId":"DBSNPID1a97211e-a6f6-44be-a909-3620f34b01e2","interpretation":{"code":"Ambiguous","system":"ClinVAR"}}],"copyNumberVariants":[{"id":"CNV_ABALON_ABCA17P_high-level-gain","chromosome":"chr8","startRange":{"start":969911792064545275,"end":969911792064546084},"endRange":{"start":4404138220928659257,"end":4404138220928659925},"totalCopyNumber":2,"relativeCopyNumber":0.18,"cnA":0.87,"cnB":0.49,"reportedAffectedGenes":[{"ensemblId":"ENSENSG00000281376","hgncId":"HGNC:49667","symbol":"ABALON","name":"apoptotic BCL2L1-antisense long non-coding RNA"},{"ensemblId":"ENSENSG00000238098","hgncId":"HGNC:32972","symbol":"ABCA17P","name":"ATP binding cassette subfamily A member 17, pseudogene"}],"reportedFocality":"reported-focality...","type":"high-level-gain","copyNumberNeutralLoH":[{"ensemblId":"ENSENSG00000115657","hgncId":"HGNC:47","symbol":"ABCB6","name":"ATP binding cassette subfamily B member 6 (Langereis blood group)"},{"ensemblId":"ENSENSG00000184389","hgncId":"HGNC:30005","symbol":"A3GALT2","name":"alpha 1,3-galactosyltransferase 2"},{"ensemblId":"ENSENSG00000023839","hgncId":"HGNC:53","symbol":"ABCC2","name":"ATP binding cassette subfamily C member 2"},{"ensemblId":"ENSENSG00000127837","hgncId":"HGNC:18","symbol":"AAMP","name":"angio associated migratory cell protein"}]},{"id":"CNV_AAGAB_ABCA6_high-level-gain","chromosome":"chr3","startRange":{"start":6843968935032545040,"end":6843968935032545924},"endRange":{"start":3583631517115538627,"end":3583631517115539281},"totalCopyNumber":4,"relativeCopyNumber":0.11,"cnA":0.15,"cnB":0.29,"reportedAffectedGenes":[{"ensemblId":"ENSENSG00000103591","hgncId":"HGNC:25662","symbol":"AAGAB","name":"alpha and gamma adaptin binding protein"},{"ensemblId":"ENSENSG00000154262","hgncId":"HGNC:36","symbol":"ABCA6","name":"ATP binding cassette subfamily A member 6"}],"reportedFocality":"reported-focality...","type":"high-level-gain","copyNumberNeutralLoH":[{"ensemblId":"ENSENSG00000231749","hgncId":"HGNC:39983","symbol":"ABCA9-AS1","name":"ABCA9 antisense RNA 1"},{"ensemblId":"ENSENSG00000154265","hgncId":"HGNC:35","symbol":"ABCA5","name":"ATP binding cassette subfamily A member 5"},{"ensemblId":"ENSENSG00000081760","hgncId":"HGNC:21298","symbol":"AACS","name":"acetoacetyl-CoA synthetase"}]},{"id":"CNV_ABCA12_AASDHPPT_ABCC2_AARS1P1_high-level-gain","chromosome":"chr5","startRange":{"start":8487172994898555456,"end":8487172994898556127},"endRange":{"start":2329045896118581347,"end":2329045896118581894},"totalCopyNumber":3,"relativeCopyNumber":0.67,"cnA":0.47,"cnB":0.46,"reportedAffectedGenes":[{"ensemblId":"ENSENSG00000144452","hgncId":"HGNC:14637","symbol":"ABCA12","name":"ATP binding cassette subfamily A member 12"},{"ensemblId":"ENSENSG00000149313","hgncId":"HGNC:14235","symbol":"AASDHPPT","name":"aminoadipate-semialdehyde dehydrogenase-phosphopantetheinyl transferase"},{"ensemblId":"ENSENSG00000023839","hgncId":"HGNC:53","symbol":"ABCC2","name":"ATP binding cassette subfamily C member 2"},{"ensemblId":"ENSENSG00000249038","hgncId":"HGNC:49894","symbol":"AARS1P1","name":"alanyl-tRNA synthetase 1 pseudogene 1"}],"reportedFocality":"reported-focality...","type":"high-level-gain","copyNumberNeutralLoH":[{"ensemblId":"ENSENSG00000141338","hgncId":"HGNC:38","symbol":"ABCA8","name":"ATP binding cassette subfamily A member 8"},{"ensemblId":"ENSENSG00000129673","hgncId":"HGNC:19","symbol":"AANAT","name":"aralkylamine N-acetyltransferase"},{"ensemblId":"ENSENSG00000242908","hgncId":"HGNC:50301","symbol":"AADACL2-AS1","name":"AADACL2 antisense RNA 1"}]},{"id":"CNV_AAAS_AADAT_high-level-gain","chromosome":"chr10","startRange":{"start":1954565432038993495,"end":1954565432038994133},"endRange":{"start":442085989067090995,"end":442085989067091164},"totalCopyNumber":4,"relativeCopyNumber":0.37,"cnA":0.98,"cnB":0.18,"reportedAffectedGenes":[{"ensemblId":"ENSENSG00000094914","hgncId":"HGNC:13666","symbol":"AAAS","name":"aladin WD repeat nucleoporin"},{"ensemblId":"ENSENSG00000109576","hgncId":"HGNC:17929","symbol":"AADAT","name":"aminoadipate aminotransferase"}],"reportedFocality":"reported-focality...","type":"high-level-gain","copyNumberNeutralLoH":[{"ensemblId":"ENSENSG00000023839","hgncId":"HGNC:53","symbol":"ABCC2","name":"ATP binding cassette subfamily C member 2"},{"ensemblId":"ENSENSG00000150967","hgncId":"HGNC:50","symbol":"ABCB9","name":"ATP binding cassette subfamily B member 9"},{"ensemblId":"ENSENSG00000149313","hgncId":"HGNC:14235","symbol":"AASDHPPT","name":"aminoadipate-semialdehyde dehydrogenase-phosphopantetheinyl transferase"}]},{"id":"CNV_A3GALT2_ABCB10P4_low-level-gain","chromosome":"chr8","startRange":{"start":1779205446909981075,"end":1779205446909981845},"endRange":{"start":3151805846500148631,"end":3151805846500149455},"totalCopyNumber":4,"relativeCopyNumber":0.94,"cnA":0.3,"cnB":0.66,"reportedAffectedGenes":[{"ensemblId":"ENSENSG00000184389","hgncId":"HGNC:30005","symbol":"A3GALT2","name":"alpha 1,3-galactosyltransferase 2"},{"ensemblId":"ENSENSG00000260053","hgncId":"HGNC:31130","symbol":"ABCB10P4","name":"ABCB10 pseudogene 4"}],"reportedFocality":"reported-focality...","type":"low-level-gain","copyNumberNeutralLoH":[{"ensemblId":"ENSENSG00000167972","hgncId":"HGNC:33","symbol":"ABCA3","name":"ATP binding cassette subfamily A member 3"},{"ensemblId":"ENSENSG00000231749","hgncId":"HGNC:39983","symbol":"ABCA9-AS1","name":"ABCA9 antisense RNA 1"},{"ensemblId":"ENSENSG00000108846","hgncId":"HGNC:54","symbol":"ABCC3","name":"ATP binding cassette subfamily C member 3"},{"ensemblId":"ENSENSG00000197953","hgncId":"HGNC:24427","symbol":"AADACL2","name":"arylacetamide deacetylase like 2"}]},{"id":"CNV_ABCA10_AADACL2_high-level-gain","chromosome":"chrX","startRange":{"start":165156786091954061,"end":165156786091954176},"endRange":{"start":5591033364020511004,"end":5591033364020511607},"totalCopyNumber":4,"relativeCopyNumber":0.69,"cnA":0.56,"cnB":0.12,"reportedAffectedGenes":[{"ensemblId":"ENSENSG00000154263","hgncId":"HGNC:30","symbol":"ABCA10","name":"ATP binding cassette subfamily A member 10"},{"ensemblId":"ENSENSG00000197953","hgncId":"HGNC:24427","symbol":"AADACL2","name":"arylacetamide deacetylase like 2"}],"reportedFocality":"reported-focality...","type":"high-level-gain","copyNumberNeutralLoH":[{"ensemblId":"ENSENSG00000215458","hgncId":"HGNC:51526","symbol":"AATBC","name":"apoptosis associated transcript in bladder cancer"},{"ensemblId":"ENSENSG00000249038","hgncId":"HGNC:49894","symbol":"AARS1P1","name":"alanyl-tRNA synthetase 1 pseudogene 1"},{"ensemblId":"ENSENSG00000261524","hgncId":"HGNC:31129","symbol":"ABCB10P3","name":"ABCB10 pseudogene 3"}]},{"id":"CNV_AAMP_AADACL3_low-level-gain","chromosome":"chrX","startRange":{"start":7552444878262806955,"end":7552444878262807187},"endRange":{"start":140089034030783731,"end":140089034030784407},"totalCopyNumber":2,"relativeCopyNumber":0.57,"cnA":0.26,"cnB":0.82,"reportedAffectedGenes":[{"ensemblId":"ENSENSG00000127837","hgncId":"HGNC:18","symbol":"AAMP","name":"angio associated migratory cell protein"},{"ensemblId":"ENSENSG00000188984","hgncId":"HGNC:32037","symbol":"AADACL3","name":"arylacetamide deacetylase like 3"}],"reportedFocality":"reported-focality...","type":"low-level-gain","copyNumberNeutralLoH":[{"ensemblId":"ENSENSG00000121410","hgncId":"HGNC:5","symbol":"A1BG","name":"alpha-1-B glycoprotein"},{"ensemblId":"ENSENSG00000175899","hgncId":"HGNC:7","symbol":"A2M","name":"alpha-2-macroglobulin"},{"ensemblId":"ENSENSG00000257408","hgncId":"HGNC:55707","symbol":"ABCA3P1","name":"ABCA3 pseudogene 1"},{"ensemblId":"ENSENSG00000005471","hgncId":"HGNC:45","symbol":"ABCB4","name":"ATP binding cassette subfamily B member 4"}]}],"dnaFusions":[{"id":"DNAFusion_A3GALT2_AAGAB","fusionPartner5prime":{"chromosome":"chr16","position":569568638299166051,"gene":{"ensemblId":"ENSENSG00000184389","hgncId":"HGNC:30005","symbol":"A3GALT2","name":"alpha 1,3-galactosyltransferase 2"}},"fusionPartner3prime":{"chromosome":"chr1","position":1728963273084125905,"gene":{"ensemblId":"ENSENSG00000103591","hgncId":"HGNC:25662","symbol":"AAGAB","name":"alpha and gamma adaptin binding protein"}},"reportedNumReads":25},{"id":"DNAFusion_ABCA3_AASDHPPT","fusionPartner5prime":{"chromosome":"chr12","position":4142955940382701892,"gene":{"ensemblId":"ENSENSG00000167972","hgncId":"HGNC:33","symbol":"ABCA3","name":"ATP binding cassette subfamily A member 3"}},"fusionPartner3prime":{"chromosome":"chr13","position":2530447494476677762,"gene":{"ensemblId":"ENSENSG00000149313","hgncId":"HGNC:14235","symbol":"AASDHPPT","name":"aminoadipate-semialdehyde dehydrogenase-phosphopantetheinyl transferase"}},"reportedNumReads":29},{"id":"DNAFusion_ABCB10P3_AAAS","fusionPartner5prime":{"chromosome":"chr19","position":216619303235013143,"gene":{"ensemblId":"ENSENSG00000261524","hgncId":"HGNC:31129","symbol":"ABCB10P3","name":"ABCB10 pseudogene 3"}},"fusionPartner3prime":{"chromosome":"chr20","position":7983660439294503113,"gene":{"ensemblId":"ENSENSG00000094914","hgncId":"HGNC:13666","symbol":"AAAS","name":"aladin WD repeat nucleoporin"}},"reportedNumReads":30},{"id":"DNAFusion_A1BG_AADACL4","fusionPartner5prime":{"chromosome":"chr19","position":2761782759714541191,"gene":{"ensemblId":"ENSENSG00000121410","hgncId":"HGNC:5","symbol":"A1BG","name":"alpha-1-B glycoprotein"}},"fusionPartner3prime":{"chromosome":"chr15","position":2381966877469433813,"gene":{"ensemblId":"ENSENSG00000204518","hgncId":"HGNC:32038","symbol":"AADACL4","name":"arylacetamide deacetylase like 4"}},"reportedNumReads":22},{"id":"DNAFusion_AAMP_ABCB9","fusionPartner5prime":{"chromosome":"chr12","position":2738282492147015127,"gene":{"ensemblId":"ENSENSG00000127837","hgncId":"HGNC:18","symbol":"AAMP","name":"angio associated migratory cell protein"}},"fusionPartner3prime":{"chromosome":"chr18","position":4689414126579295665,"gene":{"ensemblId":"ENSENSG00000150967","hgncId":"HGNC:50","symbol":"ABCB9","name":"ATP binding cassette subfamily B member 9"}},"reportedNumReads":44},{"id":"DNAFusion_AACS_ABCB10","fusionPartner5prime":{"chromosome":"chr19","position":5162788528310959454,"gene":{"ensemblId":"ENSENSG00000081760","hgncId":"HGNC:21298","symbol":"AACS","name":"acetoacetyl-CoA synthetase"}},"fusionPartner3prime":{"chromosome":"chr2","position":281250493569316672,"gene":{"ensemblId":"ENSENSG00000135776","hgncId":"HGNC:41","symbol":"ABCB10","name":"ATP binding cassette subfamily B member 10"}},"reportedNumReads":28},{"id":"DNAFusion_ABCA3_ABCA8","fusionPartner5prime":{"chromosome":"chr17","position":7239027143174816791,"gene":{"ensemblId":"ENSENSG00000167972","hgncId":"HGNC:33","symbol":"ABCA3","name":"ATP binding cassette subfamily A member 3"}},"fusionPartner3prime":{"chromosome":"chr20","position":3415200056745807403,"gene":{"ensemblId":"ENSENSG00000141338","hgncId":"HGNC:38","symbol":"ABCA8","name":"ATP binding cassette subfamily A member 8"}},"reportedNumReads":47},{"id":"DNAFusion_AATF_AASS","fusionPartner5prime":{"chromosome":"chr14","position":6207520478306983467,"gene":{"ensemblId":"ENSENSG00000275700","hgncId":"HGNC:19235","symbol":"AATF","name":"apoptosis antagonizing transcription factor"}},"fusionPartner3prime":{"chromosome":"chr7","position":966733822586135931,"gene":{"ensemblId":"ENSENSG00000008311","hgncId":"HGNC:17366","symbol":"AASS","name":"aminoadipate-semialdehyde synthase"}},"reportedNumReads":32},{"id":"DNAFusion_AATBC_AARD","fusionPartner5prime":{"chromosome":"chr9","position":6948858453904558539,"gene":{"ensemblId":"ENSENSG00000215458","hgncId":"HGNC:51526","symbol":"AATBC","name":"apoptosis associated transcript in bladder cancer"}},"fusionPartner3prime":{"chromosome":"chr21","position":5188489683141511746,"gene":{"ensemblId":"ENSENSG00000205002","hgncId":"HGNC:33842","symbol":"AARD","name":"alanine and arginine rich domain containing protein"}},"reportedNumReads":21}],"rnaFusions":[{"id":"RNAFusion_A3GALT2_ABCB6","fusionPartner5prime":{"gene":{"ensemblId":"ENSENSG00000184389","hgncId":"HGNC:30005","symbol":"A3GALT2","name":"alpha 1,3-galactosyltransferase 2"},"transcriptId":"TIDf283c026-41bf-41c6-afd5-1980bd408a06","exon":"EXONc9f963b3-4e55-4f1f-9ad1-e79b86e6e751","position":1009212469473862062,"strand":"+"},"fusionPartner3prime":{"gene":{"ensemblId":"ENSENSG00000115657","hgncId":"HGNC:47","symbol":"ABCB6","name":"ATP binding cassette subfamily B member 6 (Langereis blood group)"},"transcriptId":"TID97eabd37-cf0e-44f3-a1f1-d21543eb3b5d","exon":"EXONc9077d54-f82f-42bb-8bc8-e79e46204085","position":6271859040431005877,"strand":"-"},"effect":"RNA Fusion effect...","cosmicId":"COSMIC28f0a2f7-a923-4622-a9e4-52ecd5806066","reportedNumReads":29},{"id":"RNAFusion_ABCB10P4_A2ML1-AS1","fusionPartner5prime":{"gene":{"ensemblId":"ENSENSG00000260053","hgncId":"HGNC:31130","symbol":"ABCB10P4","name":"ABCB10 pseudogene 4"},"transcriptId":"TID2cd74611-6960-455f-9946-3962aadbbd56","exon":"EXONf7f8f171-248f-44de-9408-37a3bfa75b4f","position":9124790507143722597,"strand":"+"},"fusionPartner3prime":{"gene":{"ensemblId":"ENSENSG00000256661","hgncId":"HGNC:41022","symbol":"A2ML1-AS1","name":"A2ML1 antisense RNA 1"},"transcriptId":"TIDb16fc5d0-e8ed-40e4-9798-216ad6d4aade","exon":"EXON1bd1a002-966b-4c1d-bb0a-7f331038e5ae","position":461028552708332541,"strand":"-"},"effect":"RNA Fusion effect...","cosmicId":"COSMIC89d4c113-ca01-4804-ad46-ac20a4762389","reportedNumReads":22},{"id":"RNAFusion_A2ML1-AS2_AARS1P1","fusionPartner5prime":{"gene":{"ensemblId":"ENSENSG00000256904","hgncId":"HGNC:41523","symbol":"A2ML1-AS2","name":"A2ML1 antisense RNA 2"},"transcriptId":"TID40d495d1-f498-4b7d-8e71-e3c90af68e58","exon":"EXON23c9ccaa-ea43-444c-8340-f18365c32e4e","position":6743012027657999130,"strand":"+"},"fusionPartner3prime":{"gene":{"ensemblId":"ENSENSG00000249038","hgncId":"HGNC:49894","symbol":"AARS1P1","name":"alanyl-tRNA synthetase 1 pseudogene 1"},"transcriptId":"TIDb4337aef-0a69-483c-a603-9e3d6beefff6","exon":"EXON6980165c-6f85-4fd3-8c66-4349187f6382","position":4014336725221699201,"strand":"-"},"effect":"RNA Fusion effect...","cosmicId":"COSMICb82c4810-5629-4ea3-b569-3fd9c7167752","reportedNumReads":25},{"id":"RNAFusion_ABCA9_ABCB10P1","fusionPartner5prime":{"gene":{"ensemblId":"ENSENSG00000154258","hgncId":"HGNC:39","symbol":"ABCA9","name":"ATP binding cassette subfamily A member 9"},"transcriptId":"TIDfbbc5ac0-1d3f-476a-a1ac-4ed1456528ba","exon":"EXONf97da06b-9d7d-48c0-b202-d58a92d57e22","position":7451485235432246024,"strand":"-"},"fusionPartner3prime":{"gene":{"ensemblId":"ENSENSG00000274099","hgncId":"HGNC:14114","symbol":"ABCB10P1","name":"ABCB10 pseudogene 1"},"transcriptId":"TID3154eb7b-4364-4394-a128-75d7eb7174a0","exon":"EXON22661f53-bfb7-4b8a-9e5f-ca0b05cda801","position":2144193097707360397,"strand":"+"},"effect":"RNA Fusion effect...","cosmicId":"COSMIC42bebec2-a56e-4b55-9dc6-986d1b421404","reportedNumReads":36},{"id":"RNAFusion_A2M-AS1_AAR2","fusionPartner5prime":{"gene":{"ensemblId":"ENSENSG00000245105","hgncId":"HGNC:27057","symbol":"A2M-AS1","name":"A2M antisense RNA 1"},"transcriptId":"TID9a631927-221f-455b-b3af-b7ed8204f8ce","exon":"EXON1ae4eead-6101-4f79-b09e-2289476ec75e","position":8438088205780109333,"strand":"-"},"fusionPartner3prime":{"gene":{"ensemblId":"ENSENSG00000131043","hgncId":"HGNC:15886","symbol":"AAR2","name":"AAR2 splicing factor"},"transcriptId":"TIDe66203bb-2b54-432c-8eb9-41b81f712602","exon":"EXONfe1ed045-ddfa-4a7d-b0c8-6f08a2bc7249","position":4758763569629035168,"strand":"+"},"effect":"RNA Fusion effect...","cosmicId":"COSMIC6f5c8a08-fa74-41da-9a3e-c5965a8d6978","reportedNumReads":32},{"id":"RNAFusion_ABCB7_AADAT","fusionPartner5prime":{"gene":{"ensemblId":"ENSENSG00000131269","hgncId":"HGNC:48","symbol":"ABCB7","name":"ATP binding cassette subfamily B member 7"},"transcriptId":"TID78736fa2-71a0-4dc3-9675-e497da53a019","exon":"EXON6cd359fc-87e1-41b8-90be-9ca397aff1af","position":7631148909251407357,"strand":"+"},"fusionPartner3prime":{"gene":{"ensemblId":"ENSENSG00000109576","hgncId":"HGNC:17929","symbol":"AADAT","name":"aminoadipate aminotransferase"},"transcriptId":"TIDf79fa95a-c199-4568-959f-14f3baaea274","exon":"EXON98a11577-0325-4199-8b6f-1c8207b4d3d4","position":5619672559603971,"strand":"-"},"effect":"RNA Fusion effect...","cosmicId":"COSMIC8a43fd3b-3df4-414d-8520-571c3ad2cf77","reportedNumReads":49}],"rnaSeqs":[{"id":"RNASeq_8a6e6d50-bfd8-4c29-9003-1937ba3cc9b3","entrezId":"EID8a6e6d50-bfd8-4c29-9003-1937ba3cc9b3","ensemblId":"ENS0fcf6c3b-6389-42a8-a8d3-3e724feb302c","gene":{"ensemblId":"ENSENSG00000129673","hgncId":"HGNC:19","symbol":"AANAT","name":"aralkylamine N-acetyltransferase"},"transcriptId":"TID16c9f024-d10b-48fc-b3eb-fe21455f2016","fragmentsPerKilobaseMillion":0.52,"fromNGS":false,"tissueCorrectedExpression":true,"rawCounts":393,"librarySize":97,"cohortRanking":2},{"id":"RNASeq_0ae924be-d9c2-42e2-b9eb-c946bf768da4","entrezId":"EID0ae924be-d9c2-42e2-b9eb-c946bf768da4","ensemblId":"ENS347f84b9-6147-4336-bba8-bb5e8f32091d","gene":{"ensemblId":"ENSENSG00000260053","hgncId":"HGNC:31130","symbol":"ABCB10P4","name":"ABCB10 pseudogene 4"},"transcriptId":"TID68d3f08f-68c5-4c4e-a868-2a91bf6a74ef","fragmentsPerKilobaseMillion":0.5,"fromNGS":true,"tissueCorrectedExpression":false,"rawCounts":410,"librarySize":82,"cohortRanking":5},{"id":"RNASeq_4d00e0d0-76be-4071-ab10-2d1b6fd2bf32","entrezId":"EID4d00e0d0-76be-4071-ab10-2d1b6fd2bf32","ensemblId":"ENS7b768481-e129-4f87-8bff-815dc5449f58","gene":{"ensemblId":"ENSENSG00000256661","hgncId":"HGNC:41022","symbol":"A2ML1-AS1","name":"A2ML1 antisense RNA 1"},"transcriptId":"TID488b86f2-668b-4d75-a784-8267757b5cdd","fragmentsPerKilobaseMillion":0.55,"fromNGS":true,"tissueCorrectedExpression":false,"rawCounts":968,"librarySize":47,"cohortRanking":2},{"id":"RNASeq_ceeb241f-6dbd-4e55-9c34-666c44e46405","entrezId":"EIDceeb241f-6dbd-4e55-9c34-666c44e46405","ensemblId":"ENS5a0783cb-48ff-4cde-98b1-e2b8ea31a9f4","gene":{"ensemblId":"ENSENSG00000141338","hgncId":"HGNC:38","symbol":"ABCA8","name":"ATP binding cassette subfamily A member 8"},"transcriptId":"TID972fda4e-a47b-43b0-b574-9dc688d668f5","fragmentsPerKilobaseMillion":0.71,"fromNGS":true,"tissueCorrectedExpression":true,"rawCounts":294,"librarySize":35,"cohortRanking":3},{"id":"RNASeq_475d891e-030f-490e-b741-030b965877c0","entrezId":"EID475d891e-030f-490e-b741-030b965877c0","ensemblId":"ENS66d9d63f-8b6e-4de7-baa3-e6be55497c77","gene":{"ensemblId":"ENSENSG00000197150","hgncId":"HGNC:49","symbol":"ABCB8","name":"ATP binding cassette subfamily B member 8"},"transcriptId":"TID7af2745c-811f-481a-a288-81456117a9fa","fragmentsPerKilobaseMillion":0.04,"fromNGS":true,"tissueCorrectedExpression":false,"rawCounts":371,"librarySize":68,"cohortRanking":8}]}],"carePlans":[{"id":"6a3601ea-8fba-437d-8add-bf4f4cce469e","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","diagnosis":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","issuedOn":"2023-12-14","description":"MTB conference protocol...","recommendations":["df376556-df45-41c3-8bae-af1fe3fb7418","08234e1e-105c-4362-87e8-4f20bf87ed0b"],"geneticCounsellingRequest":"65344fca-0028-4129-a530-dd36fd984bd3","rebiopsyRequests":["5f54fb43-92a5-4f62-ae48-081d428ff2e8"],"studyInclusionRequests":["d49b41ff-e2df-499f-938f-8fb7136366b2"]}],"recommendations":[{"id":"df376556-df45-41c3-8bae-af1fe3fb7418","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","diagnosis":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","issuedOn":"2023-12-14","medication":[{"code":"L01XE39","system":"ATC","display":"Midostaurin","version":"2020"},{"code":"L01XX42","system":"ATC","display":"Panobinostat","version":"2020"}],"priority":"4","levelOfEvidence":{"grading":{"code":"m1B","system":"MTB-CDS:Level-of-Evidence:Grading"},"addendums":[{"code":"R","system":"MTB-CDS:Level-of-Evidence:Addendum"},{"code":"is","system":"MTB-CDS:Level-of-Evidence:Addendum"}]},"ngsReport":"223e3e6e-d99b-415e-83c0-18bcfc5729ca","supportingVariants":["CNV_AAGAB_ABCA6_high-level-gain","CNV_AAMP_AADACL3_low-level-gain","SNV_7f35df9d-d8b1-4421-9ec7-35cf8d3c4546"]},{"id":"08234e1e-105c-4362-87e8-4f20bf87ed0b","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","diagnosis":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","issuedOn":"2023-12-14","medication":[{"code":"L01XX42","system":"ATC","display":"Panobinostat","version":"2020"},{"code":"L01XE12","system":"ATC","display":"Vandetanib","version":"2020"}],"priority":"4","levelOfEvidence":{"grading":{"code":"m1A","system":"MTB-CDS:Level-of-Evidence:Grading"},"addendums":[{"code":"R","system":"MTB-CDS:Level-of-Evidence:Addendum"},{"code":"is","system":"MTB-CDS:Level-of-Evidence:Addendum"},{"code":"iv","system":"MTB-CDS:Level-of-Evidence:Addendum"}]},"ngsReport":"223e3e6e-d99b-415e-83c0-18bcfc5729ca","supportingVariants":["CNV_AAGAB_ABCA6_high-level-gain","CNV_ABCA12_AASDHPPT_ABCC2_AARS1P1_high-level-gain","SNV_963a3ea1-a1d5-4a52-b8d4-2e969be74b7b","SNV_7f35df9d-d8b1-4421-9ec7-35cf8d3c4546","CNV_AAAS_AADAT_high-level-gain","CNV_ABALON_ABCA17P_high-level-gain","CNV_AAMP_AADACL3_low-level-gain","SNV_22f943fd-ad99-48af-a61e-42679e851b71","SNV_599c38d4-af9f-416c-ad38-eb2fee8159e1"]}],"geneticCounsellingRequests":[{"id":"65344fca-0028-4129-a530-dd36fd984bd3","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","issuedOn":"2023-12-14","reason":"Some reason for genetic counselling..."}],"rebiopsyRequests":[{"id":"5f54fb43-92a5-4f62-ae48-081d428ff2e8","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","specimen":"40043ae5-d4cb-48e4-85c6-b34266b7693f","issuedOn":"2023-12-14"}],"histologyReevaluationRequests":[{"id":"b76dfb95-13e8-4acb-9ab8-364bc5215d63","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","specimen":"40043ae5-d4cb-48e4-85c6-b34266b7693f","issuedOn":"2023-12-14"}],"studyInclusionRequests":[{"id":"d49b41ff-e2df-499f-938f-8fb7136366b2","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","reason":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","nctNumber":"NCT84044685","issuedOn":"2023-12-14"}],"claims":[{"id":"2280a457-c5b8-4541-b6ca-86de385d789f","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","issuedOn":"2023-12-14","therapy":"df376556-df45-41c3-8bae-af1fe3fb7418"},{"id":"061fde0a-935c-4e2f-a54a-531679b2f8d5","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","issuedOn":"2023-12-14","therapy":"08234e1e-105c-4362-87e8-4f20bf87ed0b"}],"claimResponses":[{"id":"1177f670-cf44-4886-b9b3-a4dd25271dcb","claim":"2280a457-c5b8-4541-b6ca-86de385d789f","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","issuedOn":"2023-12-14","status":"accepted","reason":"standard-therapy-not-exhausted"},{"id":"c85d365d-e3c1-474b-aaa3-0e3e051d4223","claim":"061fde0a-935c-4e2f-a54a-531679b2f8d5","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","issuedOn":"2023-12-14","status":"rejected","reason":"other"}],"molecularTherapies":[{"history":[{"id":"88801f10-9f77-4a5d-adc1-47dd97b7e9ea","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","recordedOn":"2023-12-14","basedOn":"df376556-df45-41c3-8bae-af1fe3fb7418","period":{"start":"2023-12-14","end":"2023-12-14"},"medication":[{"code":"L01XE39","system":"ATC","display":"Midostaurin","version":"2020"},{"code":"L01XX42","system":"ATC","display":"Panobinostat","version":"2020"}],"dosage":">=50%","reasonStopped":{"code":"medical-reason","system":"MTB-CDS:MolecularTherapy:StopReason"},"note":"Notes on the Therapy...","status":"stopped"}]},{"history":[{"id":"660813fd-a42d-492a-8522-9c4aa3b3e162","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","recordedOn":"2023-12-14","basedOn":"08234e1e-105c-4362-87e8-4f20bf87ed0b","period":{"start":"2023-12-14","end":"2023-12-14"},"medication":[{"code":"L01XX42","system":"ATC","display":"Panobinostat","version":"2020"},{"code":"L01XE12","system":"ATC","display":"Vandetanib","version":"2020"}],"dosage":"<50%","note":"Notes on the Therapy...","status":"completed"}]}],"responses":[{"id":"267cddc7-50fd-43e6-90e6-a7f2806c7da2","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","therapy":"88801f10-9f77-4a5d-adc1-47dd97b7e9ea","effectiveDate":"2023-12-14","value":{"code":"SD","system":"RECIST"}},{"id":"8b2af33e-afee-450b-b947-3370d89603f8","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","therapy":"660813fd-a42d-492a-8522-9c4aa3b3e162","effectiveDate":"2023-12-14","value":{"code":"CR","system":"RECIST"}}]} \ No newline at end of file
+{"patient":{"id":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","gender":"female","birthDate":"1971-03","insurance":"Barmer"},"consent":{"id":"b93e4717-7b0e-4ca5-a5d6-cf8d0f7b14cf","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","status":"active"},"episode":{"id":"8ddb893f-0d55-412f-a257-9bc8bb054549","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","period":{"start":"2021-12-29"}},"diagnoses":[{"id":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","recordedOn":"2023-12-14","icd10":{"code":"C16.0","display":"Bösartige Neubildung: Kardia","version":"2023","system":"ICD-10-GM"},"whoGrade":{"code":"3", "version":"2021", "system":"WHO-Grading-CNS-Tumors"},"histologyResults":["385926d9-51f2-4a3a-96b6-57c5effefd84"],"statusHistory":[{"status":"local","date":"2023-12-14"},{"status":"unknown","date":"2023-12-14"}],"guidelineTreatmentStatus":"no-guidelines-available"}],"familyMemberDiagnoses":[{"id":"c434f063-76d9-4a7f-8ff2-34cd55fc56b2","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","relationship":{"code":"EXT","system":"http://terminology.hl7.org/ValueSet/v3-FamilyMember"}},{"id":"b07a73a8-70ed-48f8-a745-e82e7a5907a8","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","relationship":{"code":"EXT","system":"http://terminology.hl7.org/ValueSet/v3-FamilyMember"}}],"previousGuidelineTherapies":[{"id":"6435d684-18e3-45ad-b063-cdc303f61aa2","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","diagnosis":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","therapyLine":4,"medication":[{"code":"L01XC18","system":"ATC","display":"Pembrolizumab","version":"2020"},{"code":"L01XE21","system":"ATC","display":"Regorafenib","version":"2020"},{"code":"L01XC17","system":"ATC","display":"Nivolumab","version":"2020"}]},{"id":"e35731db-7447-4c4b-896a-0e90f1e68c67","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","diagnosis":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","therapyLine":4,"medication":[{"code":"L01XX46","system":"ATC","display":"Olaparib","version":"2020"},{"code":"L01XX32","system":"ATC","display":"Bortezomib","version":"2020"},{"code":"L01XE02","system":"ATC","display":"Gefitinib","version":"2020"}]},{"id":"d8a46cf9-cdc9-4f0d-b106-5aa57e08c4d0","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","diagnosis":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","therapyLine":1,"medication":[{"code":"L01XC28","system":"ATC","display":"Durvalumab","version":"2020"},{"code":"L01XC06","system":"ATC","display":"Cetuximab","version":"2020"},{"code":"L01XE47","system":"ATC","display":"Dacomitinib","version":"2020"}]}],"lastGuidelineTherapies":[{"id":"9152b20d-ac04-406c-b18b-5b6f7f4d1911","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","diagnosis":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","therapyLine":1,"period":{"start":"2023-12-14","end":"2024-01-04"},"medication":[{"code":"L01DB01","system":"ATC","display":"Doxorubicin","version":"2020"}],"reasonStopped":{"code":"toxicity","system":"MTB-CDS:GuidelineTherapy-StopReason"}}],"ecogStatus":[{"id":"51589dd2-f48d-4c41-8740-292b88d63b30","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","effectiveDate":"2023-12-14","value":{"code":"2","system":"ECOG-Performance-Status"}},{"id":"30caf153-a30a-4a1c-9056-fd4eae2a55da","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","effectiveDate":"2023-12-14","value":{"code":"4","system":"ECOG-Performance-Status"}}],"specimens":[{"id":"40043ae5-d4cb-48e4-85c6-b34266b7693f","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","icd10":{"code":"C16.0","display":"Bösartige Neubildung: Kardia","version":"2023","system":"ICD-10-GM"},"type":"liquid-biopsy","collection":{"date":"2023-12-14","localization":"unknown","method":"liquid-biopsy"}}],"molecularPathologyFindings":[{"id":"c7622342-3297-489e-850a-26aaf1225b36","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","specimen":"40043ae5-d4cb-48e4-85c6-b34266b7693f","performingInstitute":"TESTINSTITUTE","issuedOn":"2023-12-14","note":"MolecularPathologyFinding notes..."}],"histologyReports":[{"id":"385926d9-51f2-4a3a-96b6-57c5effefd84","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","specimen":"40043ae5-d4cb-48e4-85c6-b34266b7693f","issuedOn":"2023-12-14","tumorMorphology":{"id":"592b13c7-9507-4f31-a544-5cff90e35581","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","specimen":"40043ae5-d4cb-48e4-85c6-b34266b7693f","value":{"code":"8851/3","display":"Gut differenziertes Liposarkom","version":"Zweite Revision","system":"ICD-O-3-M"},"note":"Histology finding notes..."},"tumorCellContent":{"id":"f6af339c-415c-4682-b700-499e392b4558","specimen":"40043ae5-d4cb-48e4-85c6-b34266b7693f","method":"histologic","value":0.38164}}],"ngsReports":[{"id":"223e3e6e-d99b-415e-83c0-18bcfc5729ca","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","specimen":"40043ae5-d4cb-48e4-85c6-b34266b7693f","issueDate":"2023-12-14","sequencingType":"WGS","metadata":[{"kitType":"Agilent ExomV6","kitManufacturer":"Agilent","sequencer":"Sequencer-XYZ","referenceGenome":"HG19","pipeline":"dummy/uri/to/pipeline"}],"tumorCellContent":{"id":"e865f20a-1307-4ca3-b2ef-3a863b8afde0","specimen":"40043ae5-d4cb-48e4-85c6-b34266b7693f","method":"bioinformatic","value":0.74991},"brcaness":0.39,"msi":0.35,"tmb":594349.91,"simpleVariants":[{"id":"SNV_599c38d4-af9f-416c-ad38-eb2fee8159e1","chromosome":"chr6","gene":{"ensemblId":"ENSENSG00000242908","hgncId":"HGNC:50301","symbol":"AADACL2-AS1","name":"AADACL2 antisense RNA 1"},"startEnd":{"start":6736035388467870105},"refAllele":"A","altAllele":"G","dnaChange":{"code":"A>G","system":"HGVS.c"},"aminoAcidChange":{"code":"Tyr","system":"HGVS.p"},"readDepth":19,"allelicFrequency":0.75,"cosmicId":"COSMICf106c745-dbaa-453f-8dca-2f584bc1e6cb","dbSNPId":"DBSNPIDc3f51fb2-31f3-4b27-bbcc-aac52736986f","interpretation":{"code":"Probably Inactivating","system":"ClinVAR"}},{"id":"SNV_963a3ea1-a1d5-4a52-b8d4-2e969be74b7b","chromosome":"chr2","gene":{"ensemblId":"ENSENSG00000141338","hgncId":"HGNC:38","symbol":"ABCA8","name":"ATP binding cassette subfamily A member 8"},"startEnd":{"start":1672464855319477743},"refAllele":"T","altAllele":"C","dnaChange":{"code":"Tyr","system":"HGVS.c"},"aminoAcidChange":{"code":"Tyr","system":"HGVS.p"},"readDepth":23,"allelicFrequency":0.36,"cosmicId":"COSMICbcbc96bb-0428-48c9-8c64-7d2fd884528d","dbSNPId":"DBSNPIDc4904618-819c-4af1-b793-ca9d820371dc","interpretation":{"code":"Ambiguous","system":"ClinVAR"}},{"id":"SNV_7f35df9d-d8b1-4421-9ec7-35cf8d3c4546","chromosome":"chr5","gene":{"ensemblId":"ENSENSG00000149313","hgncId":"HGNC:14235","symbol":"AASDHPPT","name":"aminoadipate-semialdehyde dehydrogenase-phosphopantetheinyl transferase"},"startEnd":{"start":4251323878559029469},"refAllele":"A","altAllele":"C","dnaChange":{"code":"A>C","system":"HGVS.c"},"aminoAcidChange":{"code":"Tyr","system":"HGVS.p"},"readDepth":37,"allelicFrequency":0.48,"cosmicId":"COSMICc3c67469-2303-4cba-9b45-424d62a0d3db","dbSNPId":"DBSNPIDd94cb5ce-250a-471f-a571-015fe8a711c9","interpretation":{"code":"Function Changed","system":"ClinVAR"}},{"id":"SNV_22f943fd-ad99-48af-a61e-42679e851b71","chromosome":"chr2","gene":{"ensemblId":"ENSENSG00000167972","hgncId":"HGNC:33","symbol":"ABCA3","name":"ATP binding cassette subfamily A member 3"},"startEnd":{"start":7454627449124699972},"refAllele":"A","altAllele":"C","dnaChange":{"code":"A>C","system":"HGVS.c"},"aminoAcidChange":{"code":"Tyr","system":"HGVS.p"},"readDepth":22,"allelicFrequency":0.37,"cosmicId":"COSMICa6074760-ce24-4075-ab11-f5ab4cd6c497","dbSNPId":"DBSNPID3578fa1b-eb03-423c-929d-6705cd8e805c","interpretation":{"code":"Function Changed","system":"ClinVAR"}},{"id":"SNV_fe346bed-74ac-4b84-843b-7490a5823364","chromosome":"chr14","gene":{"ensemblId":"ENSENSG00000125257","hgncId":"HGNC:55","symbol":"ABCC4","name":"ATP binding cassette subfamily C member 4"},"startEnd":{"start":6478613836523717707},"refAllele":"G","altAllele":"T","dnaChange":{"code":"G>T","system":"HGVS.c"},"aminoAcidChange":{"code":"Tyr","system":"HGVS.p"},"readDepth":30,"allelicFrequency":0.47,"cosmicId":"COSMIC14d8842e-6af9-434f-a993-32fae87a84be","dbSNPId":"DBSNPID1a97211e-a6f6-44be-a909-3620f34b01e2","interpretation":{"code":"Ambiguous","system":"ClinVAR"}}],"copyNumberVariants":[{"id":"CNV_ABALON_ABCA17P_high-level-gain","chromosome":"chr8","startRange":{"start":969911792064545275,"end":969911792064546084},"endRange":{"start":4404138220928659257,"end":4404138220928659925},"totalCopyNumber":2,"relativeCopyNumber":0.18,"cnA":0.87,"cnB":0.49,"reportedAffectedGenes":[{"ensemblId":"ENSENSG00000281376","hgncId":"HGNC:49667","symbol":"ABALON","name":"apoptotic BCL2L1-antisense long non-coding RNA"},{"ensemblId":"ENSENSG00000238098","hgncId":"HGNC:32972","symbol":"ABCA17P","name":"ATP binding cassette subfamily A member 17, pseudogene"}],"reportedFocality":"reported-focality...","type":"high-level-gain","copyNumberNeutralLoH":[{"ensemblId":"ENSENSG00000115657","hgncId":"HGNC:47","symbol":"ABCB6","name":"ATP binding cassette subfamily B member 6 (Langereis blood group)"},{"ensemblId":"ENSENSG00000184389","hgncId":"HGNC:30005","symbol":"A3GALT2","name":"alpha 1,3-galactosyltransferase 2"},{"ensemblId":"ENSENSG00000023839","hgncId":"HGNC:53","symbol":"ABCC2","name":"ATP binding cassette subfamily C member 2"},{"ensemblId":"ENSENSG00000127837","hgncId":"HGNC:18","symbol":"AAMP","name":"angio associated migratory cell protein"}]},{"id":"CNV_AAGAB_ABCA6_high-level-gain","chromosome":"chr3","startRange":{"start":6843968935032545040,"end":6843968935032545924},"endRange":{"start":3583631517115538627,"end":3583631517115539281},"totalCopyNumber":4,"relativeCopyNumber":0.11,"cnA":0.15,"cnB":0.29,"reportedAffectedGenes":[{"ensemblId":"ENSENSG00000103591","hgncId":"HGNC:25662","symbol":"AAGAB","name":"alpha and gamma adaptin binding protein"},{"ensemblId":"ENSENSG00000154262","hgncId":"HGNC:36","symbol":"ABCA6","name":"ATP binding cassette subfamily A member 6"}],"reportedFocality":"reported-focality...","type":"high-level-gain","copyNumberNeutralLoH":[{"ensemblId":"ENSENSG00000231749","hgncId":"HGNC:39983","symbol":"ABCA9-AS1","name":"ABCA9 antisense RNA 1"},{"ensemblId":"ENSENSG00000154265","hgncId":"HGNC:35","symbol":"ABCA5","name":"ATP binding cassette subfamily A member 5"},{"ensemblId":"ENSENSG00000081760","hgncId":"HGNC:21298","symbol":"AACS","name":"acetoacetyl-CoA synthetase"}]},{"id":"CNV_ABCA12_AASDHPPT_ABCC2_AARS1P1_high-level-gain","chromosome":"chr5","startRange":{"start":8487172994898555456,"end":8487172994898556127},"endRange":{"start":2329045896118581347,"end":2329045896118581894},"totalCopyNumber":3,"relativeCopyNumber":0.67,"cnA":0.47,"cnB":0.46,"reportedAffectedGenes":[{"ensemblId":"ENSENSG00000144452","hgncId":"HGNC:14637","symbol":"ABCA12","name":"ATP binding cassette subfamily A member 12"},{"ensemblId":"ENSENSG00000149313","hgncId":"HGNC:14235","symbol":"AASDHPPT","name":"aminoadipate-semialdehyde dehydrogenase-phosphopantetheinyl transferase"},{"ensemblId":"ENSENSG00000023839","hgncId":"HGNC:53","symbol":"ABCC2","name":"ATP binding cassette subfamily C member 2"},{"ensemblId":"ENSENSG00000249038","hgncId":"HGNC:49894","symbol":"AARS1P1","name":"alanyl-tRNA synthetase 1 pseudogene 1"}],"reportedFocality":"reported-focality...","type":"high-level-gain","copyNumberNeutralLoH":[{"ensemblId":"ENSENSG00000141338","hgncId":"HGNC:38","symbol":"ABCA8","name":"ATP binding cassette subfamily A member 8"},{"ensemblId":"ENSENSG00000129673","hgncId":"HGNC:19","symbol":"AANAT","name":"aralkylamine N-acetyltransferase"},{"ensemblId":"ENSENSG00000242908","hgncId":"HGNC:50301","symbol":"AADACL2-AS1","name":"AADACL2 antisense RNA 1"}]},{"id":"CNV_AAAS_AADAT_high-level-gain","chromosome":"chr10","startRange":{"start":1954565432038993495,"end":1954565432038994133},"endRange":{"start":442085989067090995,"end":442085989067091164},"totalCopyNumber":4,"relativeCopyNumber":0.37,"cnA":0.98,"cnB":0.18,"reportedAffectedGenes":[{"ensemblId":"ENSENSG00000094914","hgncId":"HGNC:13666","symbol":"AAAS","name":"aladin WD repeat nucleoporin"},{"ensemblId":"ENSENSG00000109576","hgncId":"HGNC:17929","symbol":"AADAT","name":"aminoadipate aminotransferase"}],"reportedFocality":"reported-focality...","type":"high-level-gain","copyNumberNeutralLoH":[{"ensemblId":"ENSENSG00000023839","hgncId":"HGNC:53","symbol":"ABCC2","name":"ATP binding cassette subfamily C member 2"},{"ensemblId":"ENSENSG00000150967","hgncId":"HGNC:50","symbol":"ABCB9","name":"ATP binding cassette subfamily B member 9"},{"ensemblId":"ENSENSG00000149313","hgncId":"HGNC:14235","symbol":"AASDHPPT","name":"aminoadipate-semialdehyde dehydrogenase-phosphopantetheinyl transferase"}]},{"id":"CNV_A3GALT2_ABCB10P4_low-level-gain","chromosome":"chr8","startRange":{"start":1779205446909981075,"end":1779205446909981845},"endRange":{"start":3151805846500148631,"end":3151805846500149455},"totalCopyNumber":4,"relativeCopyNumber":0.94,"cnA":0.3,"cnB":0.66,"reportedAffectedGenes":[{"ensemblId":"ENSENSG00000184389","hgncId":"HGNC:30005","symbol":"A3GALT2","name":"alpha 1,3-galactosyltransferase 2"},{"ensemblId":"ENSENSG00000260053","hgncId":"HGNC:31130","symbol":"ABCB10P4","name":"ABCB10 pseudogene 4"}],"reportedFocality":"reported-focality...","type":"low-level-gain","copyNumberNeutralLoH":[{"ensemblId":"ENSENSG00000167972","hgncId":"HGNC:33","symbol":"ABCA3","name":"ATP binding cassette subfamily A member 3"},{"ensemblId":"ENSENSG00000231749","hgncId":"HGNC:39983","symbol":"ABCA9-AS1","name":"ABCA9 antisense RNA 1"},{"ensemblId":"ENSENSG00000108846","hgncId":"HGNC:54","symbol":"ABCC3","name":"ATP binding cassette subfamily C member 3"},{"ensemblId":"ENSENSG00000197953","hgncId":"HGNC:24427","symbol":"AADACL2","name":"arylacetamide deacetylase like 2"}]},{"id":"CNV_ABCA10_AADACL2_high-level-gain","chromosome":"chrX","startRange":{"start":165156786091954061,"end":165156786091954176},"endRange":{"start":5591033364020511004,"end":5591033364020511607},"totalCopyNumber":4,"relativeCopyNumber":0.69,"cnA":0.56,"cnB":0.12,"reportedAffectedGenes":[{"ensemblId":"ENSENSG00000154263","hgncId":"HGNC:30","symbol":"ABCA10","name":"ATP binding cassette subfamily A member 10"},{"ensemblId":"ENSENSG00000197953","hgncId":"HGNC:24427","symbol":"AADACL2","name":"arylacetamide deacetylase like 2"}],"reportedFocality":"reported-focality...","type":"high-level-gain","copyNumberNeutralLoH":[{"ensemblId":"ENSENSG00000215458","hgncId":"HGNC:51526","symbol":"AATBC","name":"apoptosis associated transcript in bladder cancer"},{"ensemblId":"ENSENSG00000249038","hgncId":"HGNC:49894","symbol":"AARS1P1","name":"alanyl-tRNA synthetase 1 pseudogene 1"},{"ensemblId":"ENSENSG00000261524","hgncId":"HGNC:31129","symbol":"ABCB10P3","name":"ABCB10 pseudogene 3"}]},{"id":"CNV_AAMP_AADACL3_low-level-gain","chromosome":"chrX","startRange":{"start":7552444878262806955,"end":7552444878262807187},"endRange":{"start":140089034030783731,"end":140089034030784407},"totalCopyNumber":2,"relativeCopyNumber":0.57,"cnA":0.26,"cnB":0.82,"reportedAffectedGenes":[{"ensemblId":"ENSENSG00000127837","hgncId":"HGNC:18","symbol":"AAMP","name":"angio associated migratory cell protein"},{"ensemblId":"ENSENSG00000188984","hgncId":"HGNC:32037","symbol":"AADACL3","name":"arylacetamide deacetylase like 3"}],"reportedFocality":"reported-focality...","type":"low-level-gain","copyNumberNeutralLoH":[{"ensemblId":"ENSENSG00000121410","hgncId":"HGNC:5","symbol":"A1BG","name":"alpha-1-B glycoprotein"},{"ensemblId":"ENSENSG00000175899","hgncId":"HGNC:7","symbol":"A2M","name":"alpha-2-macroglobulin"},{"ensemblId":"ENSENSG00000257408","hgncId":"HGNC:55707","symbol":"ABCA3P1","name":"ABCA3 pseudogene 1"},{"ensemblId":"ENSENSG00000005471","hgncId":"HGNC:45","symbol":"ABCB4","name":"ATP binding cassette subfamily B member 4"}]}],"dnaFusions":[{"id":"DNAFusion_A3GALT2_AAGAB","fusionPartner5prime":{"chromosome":"chr16","position":569568638299166051,"gene":{"ensemblId":"ENSENSG00000184389","hgncId":"HGNC:30005","symbol":"A3GALT2","name":"alpha 1,3-galactosyltransferase 2"}},"fusionPartner3prime":{"chromosome":"chr1","position":1728963273084125905,"gene":{"ensemblId":"ENSENSG00000103591","hgncId":"HGNC:25662","symbol":"AAGAB","name":"alpha and gamma adaptin binding protein"}},"reportedNumReads":25},{"id":"DNAFusion_ABCA3_AASDHPPT","fusionPartner5prime":{"chromosome":"chr12","position":4142955940382701892,"gene":{"ensemblId":"ENSENSG00000167972","hgncId":"HGNC:33","symbol":"ABCA3","name":"ATP binding cassette subfamily A member 3"}},"fusionPartner3prime":{"chromosome":"chr13","position":2530447494476677762,"gene":{"ensemblId":"ENSENSG00000149313","hgncId":"HGNC:14235","symbol":"AASDHPPT","name":"aminoadipate-semialdehyde dehydrogenase-phosphopantetheinyl transferase"}},"reportedNumReads":29},{"id":"DNAFusion_ABCB10P3_AAAS","fusionPartner5prime":{"chromosome":"chr19","position":216619303235013143,"gene":{"ensemblId":"ENSENSG00000261524","hgncId":"HGNC:31129","symbol":"ABCB10P3","name":"ABCB10 pseudogene 3"}},"fusionPartner3prime":{"chromosome":"chr20","position":7983660439294503113,"gene":{"ensemblId":"ENSENSG00000094914","hgncId":"HGNC:13666","symbol":"AAAS","name":"aladin WD repeat nucleoporin"}},"reportedNumReads":30},{"id":"DNAFusion_A1BG_AADACL4","fusionPartner5prime":{"chromosome":"chr19","position":2761782759714541191,"gene":{"ensemblId":"ENSENSG00000121410","hgncId":"HGNC:5","symbol":"A1BG","name":"alpha-1-B glycoprotein"}},"fusionPartner3prime":{"chromosome":"chr15","position":2381966877469433813,"gene":{"ensemblId":"ENSENSG00000204518","hgncId":"HGNC:32038","symbol":"AADACL4","name":"arylacetamide deacetylase like 4"}},"reportedNumReads":22},{"id":"DNAFusion_AAMP_ABCB9","fusionPartner5prime":{"chromosome":"chr12","position":2738282492147015127,"gene":{"ensemblId":"ENSENSG00000127837","hgncId":"HGNC:18","symbol":"AAMP","name":"angio associated migratory cell protein"}},"fusionPartner3prime":{"chromosome":"chr18","position":4689414126579295665,"gene":{"ensemblId":"ENSENSG00000150967","hgncId":"HGNC:50","symbol":"ABCB9","name":"ATP binding cassette subfamily B member 9"}},"reportedNumReads":44},{"id":"DNAFusion_AACS_ABCB10","fusionPartner5prime":{"chromosome":"chr19","position":5162788528310959454,"gene":{"ensemblId":"ENSENSG00000081760","hgncId":"HGNC:21298","symbol":"AACS","name":"acetoacetyl-CoA synthetase"}},"fusionPartner3prime":{"chromosome":"chr2","position":281250493569316672,"gene":{"ensemblId":"ENSENSG00000135776","hgncId":"HGNC:41","symbol":"ABCB10","name":"ATP binding cassette subfamily B member 10"}},"reportedNumReads":28},{"id":"DNAFusion_ABCA3_ABCA8","fusionPartner5prime":{"chromosome":"chr17","position":7239027143174816791,"gene":{"ensemblId":"ENSENSG00000167972","hgncId":"HGNC:33","symbol":"ABCA3","name":"ATP binding cassette subfamily A member 3"}},"fusionPartner3prime":{"chromosome":"chr20","position":3415200056745807403,"gene":{"ensemblId":"ENSENSG00000141338","hgncId":"HGNC:38","symbol":"ABCA8","name":"ATP binding cassette subfamily A member 8"}},"reportedNumReads":47},{"id":"DNAFusion_AATF_AASS","fusionPartner5prime":{"chromosome":"chr14","position":6207520478306983467,"gene":{"ensemblId":"ENSENSG00000275700","hgncId":"HGNC:19235","symbol":"AATF","name":"apoptosis antagonizing transcription factor"}},"fusionPartner3prime":{"chromosome":"chr7","position":966733822586135931,"gene":{"ensemblId":"ENSENSG00000008311","hgncId":"HGNC:17366","symbol":"AASS","name":"aminoadipate-semialdehyde synthase"}},"reportedNumReads":32},{"id":"DNAFusion_AATBC_AARD","fusionPartner5prime":{"chromosome":"chr9","position":6948858453904558539,"gene":{"ensemblId":"ENSENSG00000215458","hgncId":"HGNC:51526","symbol":"AATBC","name":"apoptosis associated transcript in bladder cancer"}},"fusionPartner3prime":{"chromosome":"chr21","position":5188489683141511746,"gene":{"ensemblId":"ENSENSG00000205002","hgncId":"HGNC:33842","symbol":"AARD","name":"alanine and arginine rich domain containing protein"}},"reportedNumReads":21}],"rnaFusions":[{"id":"RNAFusion_A3GALT2_ABCB6","fusionPartner5prime":{"gene":{"ensemblId":"ENSENSG00000184389","hgncId":"HGNC:30005","symbol":"A3GALT2","name":"alpha 1,3-galactosyltransferase 2"},"transcriptId":"TIDf283c026-41bf-41c6-afd5-1980bd408a06","exon":"EXONc9f963b3-4e55-4f1f-9ad1-e79b86e6e751","position":1009212469473862062,"strand":"+"},"fusionPartner3prime":{"gene":{"ensemblId":"ENSENSG00000115657","hgncId":"HGNC:47","symbol":"ABCB6","name":"ATP binding cassette subfamily B member 6 (Langereis blood group)"},"transcriptId":"TID97eabd37-cf0e-44f3-a1f1-d21543eb3b5d","exon":"EXONc9077d54-f82f-42bb-8bc8-e79e46204085","position":6271859040431005877,"strand":"-"},"effect":"RNA Fusion effect...","cosmicId":"COSMIC28f0a2f7-a923-4622-a9e4-52ecd5806066","reportedNumReads":29},{"id":"RNAFusion_ABCB10P4_A2ML1-AS1","fusionPartner5prime":{"gene":{"ensemblId":"ENSENSG00000260053","hgncId":"HGNC:31130","symbol":"ABCB10P4","name":"ABCB10 pseudogene 4"},"transcriptId":"TID2cd74611-6960-455f-9946-3962aadbbd56","exon":"EXONf7f8f171-248f-44de-9408-37a3bfa75b4f","position":9124790507143722597,"strand":"+"},"fusionPartner3prime":{"gene":{"ensemblId":"ENSENSG00000256661","hgncId":"HGNC:41022","symbol":"A2ML1-AS1","name":"A2ML1 antisense RNA 1"},"transcriptId":"TIDb16fc5d0-e8ed-40e4-9798-216ad6d4aade","exon":"EXON1bd1a002-966b-4c1d-bb0a-7f331038e5ae","position":461028552708332541,"strand":"-"},"effect":"RNA Fusion effect...","cosmicId":"COSMIC89d4c113-ca01-4804-ad46-ac20a4762389","reportedNumReads":22},{"id":"RNAFusion_A2ML1-AS2_AARS1P1","fusionPartner5prime":{"gene":{"ensemblId":"ENSENSG00000256904","hgncId":"HGNC:41523","symbol":"A2ML1-AS2","name":"A2ML1 antisense RNA 2"},"transcriptId":"TID40d495d1-f498-4b7d-8e71-e3c90af68e58","exon":"EXON23c9ccaa-ea43-444c-8340-f18365c32e4e","position":6743012027657999130,"strand":"+"},"fusionPartner3prime":{"gene":{"ensemblId":"ENSENSG00000249038","hgncId":"HGNC:49894","symbol":"AARS1P1","name":"alanyl-tRNA synthetase 1 pseudogene 1"},"transcriptId":"TIDb4337aef-0a69-483c-a603-9e3d6beefff6","exon":"EXON6980165c-6f85-4fd3-8c66-4349187f6382","position":4014336725221699201,"strand":"-"},"effect":"RNA Fusion effect...","cosmicId":"COSMICb82c4810-5629-4ea3-b569-3fd9c7167752","reportedNumReads":25},{"id":"RNAFusion_ABCA9_ABCB10P1","fusionPartner5prime":{"gene":{"ensemblId":"ENSENSG00000154258","hgncId":"HGNC:39","symbol":"ABCA9","name":"ATP binding cassette subfamily A member 9"},"transcriptId":"TIDfbbc5ac0-1d3f-476a-a1ac-4ed1456528ba","exon":"EXONf97da06b-9d7d-48c0-b202-d58a92d57e22","position":7451485235432246024,"strand":"-"},"fusionPartner3prime":{"gene":{"ensemblId":"ENSENSG00000274099","hgncId":"HGNC:14114","symbol":"ABCB10P1","name":"ABCB10 pseudogene 1"},"transcriptId":"TID3154eb7b-4364-4394-a128-75d7eb7174a0","exon":"EXON22661f53-bfb7-4b8a-9e5f-ca0b05cda801","position":2144193097707360397,"strand":"+"},"effect":"RNA Fusion effect...","cosmicId":"COSMIC42bebec2-a56e-4b55-9dc6-986d1b421404","reportedNumReads":36},{"id":"RNAFusion_A2M-AS1_AAR2","fusionPartner5prime":{"gene":{"ensemblId":"ENSENSG00000245105","hgncId":"HGNC:27057","symbol":"A2M-AS1","name":"A2M antisense RNA 1"},"transcriptId":"TID9a631927-221f-455b-b3af-b7ed8204f8ce","exon":"EXON1ae4eead-6101-4f79-b09e-2289476ec75e","position":8438088205780109333,"strand":"-"},"fusionPartner3prime":{"gene":{"ensemblId":"ENSENSG00000131043","hgncId":"HGNC:15886","symbol":"AAR2","name":"AAR2 splicing factor"},"transcriptId":"TIDe66203bb-2b54-432c-8eb9-41b81f712602","exon":"EXONfe1ed045-ddfa-4a7d-b0c8-6f08a2bc7249","position":4758763569629035168,"strand":"+"},"effect":"RNA Fusion effect...","cosmicId":"COSMIC6f5c8a08-fa74-41da-9a3e-c5965a8d6978","reportedNumReads":32},{"id":"RNAFusion_ABCB7_AADAT","fusionPartner5prime":{"gene":{"ensemblId":"ENSENSG00000131269","hgncId":"HGNC:48","symbol":"ABCB7","name":"ATP binding cassette subfamily B member 7"},"transcriptId":"TID78736fa2-71a0-4dc3-9675-e497da53a019","exon":"EXON6cd359fc-87e1-41b8-90be-9ca397aff1af","position":7631148909251407357,"strand":"+"},"fusionPartner3prime":{"gene":{"ensemblId":"ENSENSG00000109576","hgncId":"HGNC:17929","symbol":"AADAT","name":"aminoadipate aminotransferase"},"transcriptId":"TIDf79fa95a-c199-4568-959f-14f3baaea274","exon":"EXON98a11577-0325-4199-8b6f-1c8207b4d3d4","position":5619672559603971,"strand":"-"},"effect":"RNA Fusion effect...","cosmicId":"COSMIC8a43fd3b-3df4-414d-8520-571c3ad2cf77","reportedNumReads":49}],"rnaSeqs":[{"id":"RNASeq_8a6e6d50-bfd8-4c29-9003-1937ba3cc9b3","entrezId":"EID8a6e6d50-bfd8-4c29-9003-1937ba3cc9b3","ensemblId":"ENS0fcf6c3b-6389-42a8-a8d3-3e724feb302c","gene":{"ensemblId":"ENSENSG00000129673","hgncId":"HGNC:19","symbol":"AANAT","name":"aralkylamine N-acetyltransferase"},"transcriptId":"TID16c9f024-d10b-48fc-b3eb-fe21455f2016","fragmentsPerKilobaseMillion":0.52,"fromNGS":false,"tissueCorrectedExpression":true,"rawCounts":393,"librarySize":97,"cohortRanking":2},{"id":"RNASeq_0ae924be-d9c2-42e2-b9eb-c946bf768da4","entrezId":"EID0ae924be-d9c2-42e2-b9eb-c946bf768da4","ensemblId":"ENS347f84b9-6147-4336-bba8-bb5e8f32091d","gene":{"ensemblId":"ENSENSG00000260053","hgncId":"HGNC:31130","symbol":"ABCB10P4","name":"ABCB10 pseudogene 4"},"transcriptId":"TID68d3f08f-68c5-4c4e-a868-2a91bf6a74ef","fragmentsPerKilobaseMillion":0.5,"fromNGS":true,"tissueCorrectedExpression":false,"rawCounts":410,"librarySize":82,"cohortRanking":5},{"id":"RNASeq_4d00e0d0-76be-4071-ab10-2d1b6fd2bf32","entrezId":"EID4d00e0d0-76be-4071-ab10-2d1b6fd2bf32","ensemblId":"ENS7b768481-e129-4f87-8bff-815dc5449f58","gene":{"ensemblId":"ENSENSG00000256661","hgncId":"HGNC:41022","symbol":"A2ML1-AS1","name":"A2ML1 antisense RNA 1"},"transcriptId":"TID488b86f2-668b-4d75-a784-8267757b5cdd","fragmentsPerKilobaseMillion":0.55,"fromNGS":true,"tissueCorrectedExpression":false,"rawCounts":968,"librarySize":47,"cohortRanking":2},{"id":"RNASeq_ceeb241f-6dbd-4e55-9c34-666c44e46405","entrezId":"EIDceeb241f-6dbd-4e55-9c34-666c44e46405","ensemblId":"ENS5a0783cb-48ff-4cde-98b1-e2b8ea31a9f4","gene":{"ensemblId":"ENSENSG00000141338","hgncId":"HGNC:38","symbol":"ABCA8","name":"ATP binding cassette subfamily A member 8"},"transcriptId":"TID972fda4e-a47b-43b0-b574-9dc688d668f5","fragmentsPerKilobaseMillion":0.71,"fromNGS":true,"tissueCorrectedExpression":true,"rawCounts":294,"librarySize":35,"cohortRanking":3},{"id":"RNASeq_475d891e-030f-490e-b741-030b965877c0","entrezId":"EID475d891e-030f-490e-b741-030b965877c0","ensemblId":"ENS66d9d63f-8b6e-4de7-baa3-e6be55497c77","gene":{"ensemblId":"ENSENSG00000197150","hgncId":"HGNC:49","symbol":"ABCB8","name":"ATP binding cassette subfamily B member 8"},"transcriptId":"TID7af2745c-811f-481a-a288-81456117a9fa","fragmentsPerKilobaseMillion":0.04,"fromNGS":true,"tissueCorrectedExpression":false,"rawCounts":371,"librarySize":68,"cohortRanking":8}]}],"carePlans":[{"id":"6a3601ea-8fba-437d-8add-bf4f4cce469e","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","diagnosis":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","issuedOn":"2023-12-14","description":"MTB conference protocol...","recommendations":["df376556-df45-41c3-8bae-af1fe3fb7418","08234e1e-105c-4362-87e8-4f20bf87ed0b"],"geneticCounsellingRequest":"65344fca-0028-4129-a530-dd36fd984bd3","rebiopsyRequests":["5f54fb43-92a5-4f62-ae48-081d428ff2e8"],"studyInclusionRequests":["d49b41ff-e2df-499f-938f-8fb7136366b2"]}],"recommendations":[{"id":"df376556-df45-41c3-8bae-af1fe3fb7418","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","diagnosis":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","issuedOn":"2023-12-14","medication":[{"code":"L01XE39","system":"ATC","display":"Midostaurin","version":"2020"},{"code":"L01XX42","system":"ATC","display":"Panobinostat","version":"2020"}],"priority":"4","levelOfEvidence":{"grading":{"code":"m1B","system":"MTB-CDS:Level-of-Evidence:Grading"},"addendums":[{"code":"R","system":"MTB-CDS:Level-of-Evidence:Addendum"},{"code":"is","system":"MTB-CDS:Level-of-Evidence:Addendum"}]},"ngsReport":"223e3e6e-d99b-415e-83c0-18bcfc5729ca","supportingVariants":["CNV_AAGAB_ABCA6_high-level-gain","CNV_AAMP_AADACL3_low-level-gain","SNV_7f35df9d-d8b1-4421-9ec7-35cf8d3c4546"]},{"id":"08234e1e-105c-4362-87e8-4f20bf87ed0b","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","diagnosis":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","issuedOn":"2023-12-14","medication":[{"code":"L01XX42","system":"ATC","display":"Panobinostat","version":"2020"},{"code":"L01XE12","system":"ATC","display":"Vandetanib","version":"2020"}],"priority":"4","levelOfEvidence":{"grading":{"code":"m1A","system":"MTB-CDS:Level-of-Evidence:Grading"},"addendums":[{"code":"R","system":"MTB-CDS:Level-of-Evidence:Addendum"},{"code":"is","system":"MTB-CDS:Level-of-Evidence:Addendum"},{"code":"iv","system":"MTB-CDS:Level-of-Evidence:Addendum"}]},"ngsReport":"223e3e6e-d99b-415e-83c0-18bcfc5729ca","supportingVariants":["CNV_AAGAB_ABCA6_high-level-gain","CNV_ABCA12_AASDHPPT_ABCC2_AARS1P1_high-level-gain","SNV_963a3ea1-a1d5-4a52-b8d4-2e969be74b7b","SNV_7f35df9d-d8b1-4421-9ec7-35cf8d3c4546","CNV_AAAS_AADAT_high-level-gain","CNV_ABALON_ABCA17P_high-level-gain","CNV_AAMP_AADACL3_low-level-gain","SNV_22f943fd-ad99-48af-a61e-42679e851b71","SNV_599c38d4-af9f-416c-ad38-eb2fee8159e1"]}],"geneticCounsellingRequests":[{"id":"65344fca-0028-4129-a530-dd36fd984bd3","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","issuedOn":"2023-12-14","reason":"Some reason for genetic counselling..."}],"rebiopsyRequests":[{"id":"5f54fb43-92a5-4f62-ae48-081d428ff2e8","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","specimen":"40043ae5-d4cb-48e4-85c6-b34266b7693f","issuedOn":"2023-12-14"}],"histologyReevaluationRequests":[{"id":"b76dfb95-13e8-4acb-9ab8-364bc5215d63","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","specimen":"40043ae5-d4cb-48e4-85c6-b34266b7693f","issuedOn":"2023-12-14"}],"studyInclusionRequests":[{"id":"d49b41ff-e2df-499f-938f-8fb7136366b2","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","reason":"ed1f151c-0707-4bbf-bb02-9654310ac1f8","nctNumber":"NCT84044685","issuedOn":"2023-12-14"}],"claims":[{"id":"2280a457-c5b8-4541-b6ca-86de385d789f","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","issuedOn":"2023-12-14","therapy":"df376556-df45-41c3-8bae-af1fe3fb7418"},{"id":"061fde0a-935c-4e2f-a54a-531679b2f8d5","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","issuedOn":"2023-12-14","therapy":"08234e1e-105c-4362-87e8-4f20bf87ed0b"}],"claimResponses":[{"id":"1177f670-cf44-4886-b9b3-a4dd25271dcb","claim":"2280a457-c5b8-4541-b6ca-86de385d789f","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","issuedOn":"2023-12-14","status":"accepted","reason":"standard-therapy-not-exhausted"},{"id":"c85d365d-e3c1-474b-aaa3-0e3e051d4223","claim":"061fde0a-935c-4e2f-a54a-531679b2f8d5","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","issuedOn":"2023-12-14","status":"rejected","reason":"other"}],"molecularTherapies":[{"history":[{"id":"660813fd-a42d-492a-8522-9c4aa3b3e162","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","recordedOn":"2023-12-31","basedOn":"08234e1e-105c-4362-87e8-4f20bf87ed0b","period":{"start":"2023-12-16","end":"2023-12-31"},"medication":[{"code":"L01XX42","system":"ATC","display":"Panobinostat","version":"2020"},{"code":"L01XE12","system":"ATC","display":"Vandetanib","version":"2020"}],"dosage":"<50%","note":"Notes on the Therapy...","status":"completed"}]}],"responses":[{"id":"8b2af33e-afee-450b-b947-3370d89603f8","patient":"5dad2f0b-49c6-47d8-a952-7b9e9e0f7549","therapy":"660813fd-a42d-492a-8522-9c4aa3b3e162","effectiveDate":"2023-12-16","value":{"code":"CR","system":"RECIST"}}]} \ No newline at end of file