1
0
mirror of https://github.com/pcvolkmer/mv64e-onkostar-data.git synced 2025-09-13 16:02:52 +00:00

feat: add germline diagnosis codes

This commit is contained in:
2025-07-26 21:32:47 +02:00
parent a6ba6c54e2
commit ed1d6a9dab
6 changed files with 220 additions and 3 deletions

View File

@@ -103,6 +103,8 @@ public class DataCatalogueFactory {
return ConsentMvCatalogue.create(jdbcTemplate); return ConsentMvCatalogue.create(jdbcTemplate);
} else if (c == ConsentMvVerlaufCatalogue.class) { } else if (c == ConsentMvVerlaufCatalogue.class) {
return ConsentMvVerlaufCatalogue.create(jdbcTemplate); return ConsentMvVerlaufCatalogue.create(jdbcTemplate);
} else if (c == KeimbahndiagnoseCatalogue.class) {
return KeimbahndiagnoseCatalogue.create(jdbcTemplate);
} }
throw new DataCatalogueCreationException(clazz); throw new DataCatalogueCreationException(clazz);
}); });

View File

@@ -0,0 +1,46 @@
/*
* This file is part of mv64e-onkostar-data
*
* Copyright (C) 2025 Paul-Christian Volkmer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package dev.pcvolkmer.onco.datamapper.datacatalogues;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* Load raw result sets from database table 'dk_dnpm_uf_keimbahndiagnose'
*
* @author Paul-Christian Volkmer
* @since 0.1
*/
public class KeimbahndiagnoseCatalogue extends AbstractSubformDataCatalogue {
private KeimbahndiagnoseCatalogue(JdbcTemplate jdbcTemplate) {
super(jdbcTemplate);
}
@Override
protected String getTableName() {
return "dk_dnpm_uf_keimbahndiagnose";
}
public static KeimbahndiagnoseCatalogue create(JdbcTemplate jdbcTemplate) {
return new KeimbahndiagnoseCatalogue(jdbcTemplate);
}
}

View File

@@ -23,6 +23,7 @@ package dev.pcvolkmer.onco.datamapper.mapper;
import dev.pcvolkmer.mv64e.mtb.*; import dev.pcvolkmer.mv64e.mtb.*;
import dev.pcvolkmer.onco.datamapper.PropertyCatalogue; import dev.pcvolkmer.onco.datamapper.PropertyCatalogue;
import dev.pcvolkmer.onco.datamapper.ResultSet; import dev.pcvolkmer.onco.datamapper.ResultSet;
import dev.pcvolkmer.onco.datamapper.datacatalogues.KeimbahndiagnoseCatalogue;
import dev.pcvolkmer.onco.datamapper.datacatalogues.KpaCatalogue; import dev.pcvolkmer.onco.datamapper.datacatalogues.KpaCatalogue;
import dev.pcvolkmer.onco.datamapper.datacatalogues.TumorausbreitungCatalogue; import dev.pcvolkmer.onco.datamapper.datacatalogues.TumorausbreitungCatalogue;
import dev.pcvolkmer.onco.datamapper.datacatalogues.TumorgradingCatalogue; import dev.pcvolkmer.onco.datamapper.datacatalogues.TumorgradingCatalogue;
@@ -44,17 +45,20 @@ public class KpaDiagnosisDataMapper implements DataMapper<MtbDiagnosis> {
private final KpaCatalogue kpaCatalogue; private final KpaCatalogue kpaCatalogue;
private final TumorausbreitungCatalogue tumorausbreitungCatalogue; private final TumorausbreitungCatalogue tumorausbreitungCatalogue;
private final TumorgradingCatalogue tumorgradingCatalogue; private final TumorgradingCatalogue tumorgradingCatalogue;
private final KeimbahndiagnoseCatalogue keimbahndiagnoseCatalogue;
private final PropertyCatalogue propertyCatalogue; private final PropertyCatalogue propertyCatalogue;
public KpaDiagnosisDataMapper( public KpaDiagnosisDataMapper(
final KpaCatalogue kpaCatalogue, final KpaCatalogue kpaCatalogue,
final TumorausbreitungCatalogue tumorausbreitungCatalogue, final TumorausbreitungCatalogue tumorausbreitungCatalogue,
final TumorgradingCatalogue tumorgradingCatalogue, final TumorgradingCatalogue tumorgradingCatalogue,
final KeimbahndiagnoseCatalogue keimbahndiagnoseCatalogue,
final PropertyCatalogue propertyCatalogue final PropertyCatalogue propertyCatalogue
) { ) {
this.kpaCatalogue = kpaCatalogue; this.kpaCatalogue = kpaCatalogue;
this.tumorausbreitungCatalogue = tumorausbreitungCatalogue; this.tumorausbreitungCatalogue = tumorausbreitungCatalogue;
this.tumorgradingCatalogue = tumorgradingCatalogue; this.tumorgradingCatalogue = tumorgradingCatalogue;
this.keimbahndiagnoseCatalogue = keimbahndiagnoseCatalogue;
this.propertyCatalogue = propertyCatalogue; this.propertyCatalogue = propertyCatalogue;
} }
@@ -83,13 +87,12 @@ public class KpaDiagnosisDataMapper implements DataMapper<MtbDiagnosis> {
.recordedOn(data.getDate("datumerstdiagnose")) .recordedOn(data.getDate("datumerstdiagnose"))
.topography(Coding.builder().code(data.getString("icdo3lokalisation")).build()) .topography(Coding.builder().code(data.getString("icdo3lokalisation")).build())
.type(getType(data)) .type(getType(data))
// Nicht in Onkostar erfasst
//.germlineCodes()
.guidelineTreatmentStatus( .guidelineTreatmentStatus(
getMtbDiagnosisGuidelineTreatmentStatusCoding(data.getString("leitlinienstatus"), data.getInteger("leitlinienstatus_propcat_version")) getMtbDiagnosisGuidelineTreatmentStatusCoding(data.getString("leitlinienstatus"), data.getInteger("leitlinienstatus_propcat_version"))
) )
.grading(getGrading(id)) .grading(getGrading(id))
.staging(getStaging(id)) .staging(getStaging(id))
.germlineCodes(getGermlineCodes(id))
; ;
return builder.build(); return builder.build();
} }
@@ -172,6 +175,19 @@ public class KpaDiagnosisDataMapper implements DataMapper<MtbDiagnosis> {
return Staging.builder().history(all).build(); return Staging.builder().history(all).build();
} }
private List<Coding> getGermlineCodes(final int id) {
return keimbahndiagnoseCatalogue.getAllByParentId(id).stream()
.map(it ->
Coding.builder()
.code(it.getString("icd10"))
.system("http://fhir.de/CodeSystem/bfarm/icd-10-gm")
.display(propertyCatalogue.getByCodeAndVersion(it.getString("icd10"), it.getInteger("icd10_propcat_version")).getShortdesc())
.version(propertyCatalogue.getByCodeAndVersion(it.getString("icd10"), it.getInteger("icd10_propcat_version")).getVersionDescription())
.build()
)
.collect(Collectors.toList());
}
private Type getType(final ResultSet resultSet) { private Type getType(final ResultSet resultSet) {
var diagnosisCoding = MtbDiagnosisCoding.builder(); var diagnosisCoding = MtbDiagnosisCoding.builder();
var code = resultSet.getString("diagnosetyp"); var code = resultSet.getString("diagnosetyp");

View File

@@ -85,6 +85,7 @@ public class MtbDataMapper implements DataMapper<Mtb> {
kpaCatalogue, kpaCatalogue,
catalogueFactory.catalogue(TumorausbreitungCatalogue.class), catalogueFactory.catalogue(TumorausbreitungCatalogue.class),
catalogueFactory.catalogue(TumorgradingCatalogue.class), catalogueFactory.catalogue(TumorgradingCatalogue.class),
catalogueFactory.catalogue(KeimbahndiagnoseCatalogue.class),
propertyCatalogue propertyCatalogue
); );
var mtbEpisodeDataMapper = new MtbEpisodeDataMapper(kpaCatalogue, propertyCatalogue); var mtbEpisodeDataMapper = new MtbEpisodeDataMapper(kpaCatalogue, propertyCatalogue);

View File

@@ -0,0 +1,126 @@
/*
* This file is part of mv64e-onkostar-data
*
* Copyright (C) 2025 Paul-Christian Volkmer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package dev.pcvolkmer.onco.datamapper.datacatalogues;
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.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class KeimbahndiagnoseCatalogueTest {
JdbcTemplate jdbcTemplate;
KeimbahndiagnoseCatalogue catalogue;
@BeforeEach
void setUp(@Mock JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
this.catalogue = KeimbahndiagnoseCatalogue.create(jdbcTemplate);
}
@Test
void shouldUseCorrectQuery(@Mock Map<String, Object> resultSet) {
doAnswer(invocationOnMock -> List.of(resultSet))
.when(jdbcTemplate)
.queryForList(anyString(), anyInt());
this.catalogue.getById(1);
var captor = ArgumentCaptor.forClass(String.class);
verify(this.jdbcTemplate).queryForList(captor.capture(), anyInt());
assertThat(captor.getValue())
.isEqualTo("SELECT patient.patienten_id, dk_dnpm_uf_keimbahndiagnose.*, prozedur.patient_id, prozedur.hauptprozedur_id FROM dk_dnpm_uf_keimbahndiagnose JOIN prozedur ON (prozedur.id = dk_dnpm_uf_keimbahndiagnose.id) JOIN patient ON (patient.id = prozedur.patient_id) WHERE geloescht = 0 AND prozedur.id = ?");
}
@Test
void shouldUseCorrectSubformQuery(@Mock Map<String, Object> resultSet) {
doAnswer(invocationOnMock -> List.of(resultSet))
.when(jdbcTemplate)
.queryForList(anyString(), anyInt());
this.catalogue.getAllByParentId(1);
var captor = ArgumentCaptor.forClass(String.class);
verify(this.jdbcTemplate).queryForList(captor.capture(), anyInt());
assertThat(captor.getValue())
.isEqualTo("SELECT patient.patienten_id, dk_dnpm_uf_keimbahndiagnose.*, prozedur.patient_id, prozedur.hauptprozedur_id FROM dk_dnpm_uf_keimbahndiagnose JOIN prozedur ON (prozedur.id = dk_dnpm_uf_keimbahndiagnose.id) JOIN patient ON (patient.id = prozedur.patient_id) WHERE geloescht = 0 AND hauptprozedur_id = ?");
}
@Test
void shouldUseCorrectMerkmalQuery(@Mock Map<String, Object> resultSet) {
when(resultSet.get(anyString()))
.thenReturn(Map.of("feldname", "name", "feldwert", "wert"));
doAnswer(invocationOnMock -> List.of(resultSet))
.when(jdbcTemplate)
.queryForList(anyString(), anyInt());
this.catalogue.getMerkmaleById(1);
var captor = ArgumentCaptor.forClass(String.class);
verify(this.jdbcTemplate).queryForList(captor.capture(), anyInt());
assertThat(captor.getValue())
.isEqualTo("SELECT feldname, feldwert FROM dk_dnpm_uf_keimbahndiagnose_merkmale WHERE eintrag_id = ?");
}
@Test
void shouldUseMerkmalList() {
doAnswer(invocationOnMock -> {
var sql = invocationOnMock.getArgument(0, String.class);
ArrayList<Map<String, Object>> result = new ArrayList<>();
if (sql.startsWith("SELECT feldname")) {
result.add(Map.of("feldname", "name", "feldwert", "wert1"));
result.add(Map.of("feldname", "name", "feldwert", "wert2"));
} else {
var map = new HashMap<String, Object>();
map.put("id", 1);
map.put("name", "x");
result.add(map);
}
return result;
})
.when(jdbcTemplate)
.queryForList(anyString(), anyInt());
var result = this.catalogue.getById(1);
assertThat(result.getInteger("id")).isEqualTo(1);
assertThat(result.getMerkmalList("name")).isEqualTo(List.of("wert1", "wert2"));
}
}

View File

@@ -24,6 +24,7 @@ import dev.pcvolkmer.mv64e.mtb.MtbDiagnosis;
import dev.pcvolkmer.mv64e.mtb.Reference; import dev.pcvolkmer.mv64e.mtb.Reference;
import dev.pcvolkmer.onco.datamapper.PropertyCatalogue; import dev.pcvolkmer.onco.datamapper.PropertyCatalogue;
import dev.pcvolkmer.onco.datamapper.ResultSet; import dev.pcvolkmer.onco.datamapper.ResultSet;
import dev.pcvolkmer.onco.datamapper.datacatalogues.KeimbahndiagnoseCatalogue;
import dev.pcvolkmer.onco.datamapper.datacatalogues.KpaCatalogue; import dev.pcvolkmer.onco.datamapper.datacatalogues.KpaCatalogue;
import dev.pcvolkmer.onco.datamapper.datacatalogues.TumorausbreitungCatalogue; import dev.pcvolkmer.onco.datamapper.datacatalogues.TumorausbreitungCatalogue;
import dev.pcvolkmer.onco.datamapper.datacatalogues.TumorgradingCatalogue; import dev.pcvolkmer.onco.datamapper.datacatalogues.TumorgradingCatalogue;
@@ -34,6 +35,7 @@ import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import javax.sql.DataSource; import javax.sql.DataSource;
import java.util.List;
import java.util.Map; import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@@ -47,6 +49,7 @@ class KpaDiagnosisDataMapperTest {
KpaCatalogue kpaCatalogue; KpaCatalogue kpaCatalogue;
TumorausbreitungCatalogue tumorausbreitungCatalogue; TumorausbreitungCatalogue tumorausbreitungCatalogue;
TumorgradingCatalogue tumorgradingCatalogue; TumorgradingCatalogue tumorgradingCatalogue;
KeimbahndiagnoseCatalogue keimbahndiagnoseCatalogue;
PropertyCatalogue propertyCatalogue; PropertyCatalogue propertyCatalogue;
KpaDiagnosisDataMapper dataMapper; KpaDiagnosisDataMapper dataMapper;
@@ -56,13 +59,21 @@ class KpaDiagnosisDataMapperTest {
@Mock KpaCatalogue kpaCatalogue, @Mock KpaCatalogue kpaCatalogue,
@Mock TumorausbreitungCatalogue tumorausbreitungCatalogue, @Mock TumorausbreitungCatalogue tumorausbreitungCatalogue,
@Mock TumorgradingCatalogue tumorgradingCatalogue, @Mock TumorgradingCatalogue tumorgradingCatalogue,
@Mock KeimbahndiagnoseCatalogue keimbahndiagnoseCatalogue,
@Mock PropertyCatalogue propertyCatalogue @Mock PropertyCatalogue propertyCatalogue
) { ) {
this.kpaCatalogue = kpaCatalogue; this.kpaCatalogue = kpaCatalogue;
this.tumorausbreitungCatalogue = tumorausbreitungCatalogue; this.tumorausbreitungCatalogue = tumorausbreitungCatalogue;
this.tumorgradingCatalogue = tumorgradingCatalogue; this.tumorgradingCatalogue = tumorgradingCatalogue;
this.keimbahndiagnoseCatalogue = keimbahndiagnoseCatalogue;
this.propertyCatalogue = propertyCatalogue; this.propertyCatalogue = propertyCatalogue;
this.dataMapper = new KpaDiagnosisDataMapper(kpaCatalogue, tumorausbreitungCatalogue, tumorgradingCatalogue, propertyCatalogue); this.dataMapper = new KpaDiagnosisDataMapper(
kpaCatalogue,
tumorausbreitungCatalogue,
tumorgradingCatalogue,
keimbahndiagnoseCatalogue,
propertyCatalogue
);
} }
@Test @Test
@@ -88,12 +99,27 @@ class KpaDiagnosisDataMapperTest {
new PropertyCatalogue.Entry("C00.0", "Bösartige Neubildung: Äußere Oberlippe", "Bösartige Neubildung: Äußere Oberlippe") new PropertyCatalogue.Entry("C00.0", "Bösartige Neubildung: Äußere Oberlippe", "Bösartige Neubildung: Äußere Oberlippe")
).when(propertyCatalogue).getByCodeAndVersion(anyString(), anyInt()); ).when(propertyCatalogue).getByCodeAndVersion(anyString(), anyInt());
doAnswer(invocationOnMock ->
List.of(
ResultSet.from(
Map.of(
"id", 1,
"icd10", "C00.0",
"icd10_propcat_version", 42
)
)
)
).when(keimbahndiagnoseCatalogue).getAllByParentId(anyInt());
var actual = this.dataMapper.getById(1); var actual = this.dataMapper.getById(1);
assertThat(actual).isInstanceOf(MtbDiagnosis.class); assertThat(actual).isInstanceOf(MtbDiagnosis.class);
assertThat(actual.getId()).isEqualTo("1"); assertThat(actual.getId()).isEqualTo("1");
assertThat(actual.getPatient()) assertThat(actual.getPatient())
.isEqualTo(Reference.builder().id("42").type("Patient").build()); .isEqualTo(Reference.builder().id("42").type("Patient").build());
assertThat(actual.getCode().getCode()).isEqualTo("F79.9"); assertThat(actual.getCode().getCode()).isEqualTo("F79.9");
assertThat(actual.getGermlineCodes()).hasSize(1);
assertThat(actual.getGermlineCodes().get(0).getCode()).isEqualTo("C00.0");
} }
private static Map<String, Object> testData() { private static Map<String, Object> testData() {