diff options
Diffstat (limited to 'src/test')
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 |
