feat: implement http request

This commit is contained in:
2025-07-13 15:29:59 +02:00
parent da526a39af
commit 628f011404
4 changed files with 165 additions and 18 deletions

View File

@@ -6,12 +6,19 @@ import de.itc.onkostar.api.Procedure;
import de.itc.onkostar.api.analysis.AnalyzerRequirement;
import de.itc.onkostar.api.analysis.IProcedureAnalyzer;
import de.itc.onkostar.api.analysis.OnkostarPluginType;
import dev.pcvolkmer.mv64e.mtb.Mtb;
import dev.pcvolkmer.onco.datamapper.mapper.MtbDataMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import javax.sql.DataSource;
import java.net.URI;
import java.util.Base64;
/**
* Analyzer to start export if DNPM Klinik/Anamnese or DNPM Therapieplan form gets locked
@@ -26,11 +33,16 @@ public class ExportAnalyzer implements IProcedureAnalyzer {
private final IOnkostarApi onkostarApi;
private final MtbDataMapper mtbDataMapper;
private final RestTemplate restTemplate;
public ExportAnalyzer(final IOnkostarApi onkostarApi, final DataSource dataSource) {
public ExportAnalyzer(
final IOnkostarApi onkostarApi,
final MtbDataMapper mtbDataMapper,
final RestTemplate restTemplate
) {
this.onkostarApi = onkostarApi;
// Reuse default Onkostar DataSource for MtbDataMapper
this.mtbDataMapper = MtbDataMapper.create(dataSource);
this.mtbDataMapper = mtbDataMapper;
this.restTemplate = restTemplate;
}
@Override
@@ -79,28 +91,55 @@ public class ExportAnalyzer implements IProcedureAnalyzer {
logger.info("Starting export for procedure {}", procedure.getId());
try {
String caseId = "";
String caseId;
switch (procedure.getFormName()) {
case "DNPM Klinik/Anamnese":
caseId = procedure.getValue("FallnummrMV").getString();
caseId = procedure.getValue("FallnummerMV").getString();
break;
case "DNPM Therapieplan":
var kpaProcedure = onkostarApi.getProcedure(
procedure.getValue("ref_dnpm_klinikanamnese").getInt()
);
caseId = kpaProcedure.getValue("FallnummrMV").getString();
caseId = kpaProcedure.getValue("FallnummerMV").getString();
break;
default:
logger.info("Cannot handle procedure form {}", procedure.getFormName());
return;
}
var mtb = mtbDataMapper.getByCaseId(caseId);
// TODO: Send MTB data to remote application
var mtb = mtbDataMapper.getByCaseId(caseId);
sendMtbFileRequest(mtb);
} catch (Exception e) {
logger.error("Could export mtb data for procedure {}", procedure.getId(), e);
}
}
private void sendMtbFileRequest(Mtb mtb) {
var exportUrl = onkostarApi.getGlobalSetting("dnpmexport_url");
try {
var uri = URI.create(exportUrl);
var headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
if (uri.getUserInfo() != null) {
headers.set(HttpHeaders.AUTHORIZATION, "Basic " + Base64.getEncoder().encodeToString(uri.getUserInfo().getBytes()));
}
var entityReq = new HttpEntity<>(mtb, headers);
var r = restTemplate.postForEntity(uri, entityReq, String.class);
if (!r.getStatusCode().is2xxSuccessful()) {
logger.warn("Error sending to remote system: {}", r.getBody());
throw new RuntimeException("Kann Daten nicht an das externe System senden");
}
} catch (IllegalArgumentException e) {
logger.error("Not a valid URI to export to: '{}'", exportUrl);
throw new RuntimeException("Keine gültige Adresse für das externe System");
} catch (RestClientException e) {
logger.error("Cannot send data to remote system", e);
throw new RuntimeException("Kann Daten nicht an das externe System senden");
}
}
}

View File

@@ -0,0 +1,18 @@
package dev.pcvolkmer.onco.dnpmexport;
import dev.pcvolkmer.onco.datamapper.mapper.MtbDataMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class ExportAnalyzerConfig {
@Bean
public MtbDataMapper mtbDataMapper(final DataSource dataSource) {
// Reuse default Onkostar DataSource for MtbDataMapper
return MtbDataMapper.create(dataSource);
}
}

View File

@@ -1,34 +1,121 @@
package dev.pcvolkmer.onco.dnpmexport;
import de.itc.onkostar.api.IOnkostarApi;
import de.itc.onkostar.api.Item;
import de.itc.onkostar.api.Procedure;
import dev.pcvolkmer.mv64e.mtb.Mtb;
import dev.pcvolkmer.onco.datamapper.mapper.MtbDataMapper;
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.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import javax.sql.DataSource;
import java.net.URI;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class ExportAnalyzerTest {
private IOnkostarApi onkostarApi;
private DataSource dataSource;
private MtbDataMapper mtbDataMapper;
private RestTemplate restTemplate;
private ExportAnalyzer analyzer;
@BeforeEach
void setup(
@Mock IOnkostarApi onkostarApi,
@Mock DataSource dataSource
@Mock MtbDataMapper mtbDataMapper,
@Mock RestTemplate restTemplate
) {
this.onkostarApi = onkostarApi;
this.dataSource = dataSource;
this.analyzer = new ExportAnalyzer(onkostarApi, dataSource);
this.mtbDataMapper = mtbDataMapper;
this.restTemplate = restTemplate;
this.analyzer = new ExportAnalyzer(onkostarApi, mtbDataMapper, restTemplate);
doAnswer(invocationOnMock -> {
var name = invocationOnMock.getArgument(0, String.class);
return defaultSetting(name);
}).when(this.onkostarApi).getGlobalSetting(anyString());
}
private static String defaultSetting(String name) {
switch (name) {
case "dnpmexport_url":
return "http://localhost:9000/mtb/etl/patient-record";
case "dnpmexport_prefix":
return "TEST";
default:
return null;
}
}
@Test
void testShouldTestSomeAnalyzerImplementation() {
// Implement your first test
void shouldExtractMtbDataForKlinikAnamnese() {
when(mtbDataMapper.getByCaseId(anyString())).thenReturn(Mtb.builder().build());
when(this.restTemplate.postForEntity(any(URI.class), any(), any())).thenReturn(ResponseEntity.accepted().build());
var procedure = new Procedure(onkostarApi);
procedure.setId(1);
procedure.setFormName("DNPM Klinik/Anamnese");
procedure.setValue("FallnummerMV", new Item("FallnummerMV", "1600012345"));
this.analyzer.analyze(procedure, null);
var caseIdCaptor = ArgumentCaptor.forClass(String.class);
verify(mtbDataMapper, times(1)).getByCaseId(caseIdCaptor.capture());
assertThat(caseIdCaptor.getValue()).isEqualTo("1600012345");
}
@Test
void shouldExtractMtbDataForTherapieplan() {
doAnswer(invocationOnMock -> {
var procedure = new Procedure(onkostarApi);
procedure.setId(1);
procedure.setFormName("DNPM Klinik/Anamnese");
procedure.setValue("FallnummerMV", new Item("FallnummerMV", "1600012345"));
return procedure;
}).when(this.onkostarApi).getProcedure(anyInt());
when(mtbDataMapper.getByCaseId(anyString())).thenReturn(Mtb.builder().build());
when(this.restTemplate.postForEntity(any(URI.class), any(), any())).thenReturn(ResponseEntity.accepted().build());
var procedure = new Procedure(onkostarApi);
procedure.setId(2);
procedure.setFormName("DNPM Therapieplan");
procedure.setValue("ref_dnpm_klinikanamnese", new Item("ref_dnpm_klinikanamnese", 1));
this.analyzer.analyze(procedure, null);
var kpaIdCaptor = ArgumentCaptor.forClass(Integer.class);
verify(onkostarApi, times(1)).getProcedure(kpaIdCaptor.capture());
assertThat(kpaIdCaptor.getValue()).isEqualTo(1);
var caseIdCaptor = ArgumentCaptor.forClass(String.class);
verify(mtbDataMapper, times(1)).getByCaseId(caseIdCaptor.capture());
assertThat(caseIdCaptor.getValue()).isEqualTo("1600012345");
}
@Test
void shouldSendHttpRequestWithMtbData() {
when(mtbDataMapper.getByCaseId(anyString())).thenReturn(Mtb.builder().build());
when(this.restTemplate.postForEntity(any(URI.class), any(), any())).thenReturn(ResponseEntity.accepted().build());
var procedure = new Procedure(onkostarApi);
procedure.setId(1);
procedure.setFormName("DNPM Klinik/Anamnese");
procedure.setValue("FallnummerMV", new Item("FallnummerMV", "1600012345"));
this.analyzer.analyze(procedure, null);
verify(restTemplate, times(1)).postForEntity(any(URI.class), any(), any());
}
}