Skip to content
Snippets Groups Projects
Commit b8c5fa04 authored by OZG-Cloud Team's avatar OZG-Cloud Team
Browse files

OZG-5286 add handling of attachments

parent 71e2c215
No related branches found
No related tags found
No related merge requests found
...@@ -6,6 +6,7 @@ import java.time.ZonedDateTime; ...@@ -6,6 +6,7 @@ import java.time.ZonedDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.Objects; import java.util.Objects;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
...@@ -22,6 +23,7 @@ import de.ozgcloud.common.binaryfile.TempFileUtils; ...@@ -22,6 +23,7 @@ import de.ozgcloud.common.binaryfile.TempFileUtils;
import de.ozgcloud.common.errorhandling.TechnicalException; import de.ozgcloud.common.errorhandling.TechnicalException;
import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormData;
import de.ozgcloud.eingang.common.formdata.IncomingFile; import de.ozgcloud.eingang.common.formdata.IncomingFile;
import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier; import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier;
import de.ozgcloud.eingang.enterprise.entry.EntryResponse.ResponseVorgang; import de.ozgcloud.eingang.enterprise.entry.EntryResponse.ResponseVorgang;
import de.ozgcloud.eingang.semantik.SemantikAdapter; import de.ozgcloud.eingang.semantik.SemantikAdapter;
...@@ -32,6 +34,7 @@ import de.ozgcloud.eingang.semantik.SemantikAdapter; ...@@ -32,6 +34,7 @@ import de.ozgcloud.eingang.semantik.SemantikAdapter;
public class EntryController { public class EntryController {
private static final String STARTING_STATUS = "NEU"; private static final String STARTING_STATUS = "NEU";
private static final String OTHER_FILE_GROUP_NAME = "Sonstige";
@Autowired @Autowired
private EntryDataMapper mapper; private EntryDataMapper mapper;
...@@ -44,10 +47,13 @@ public class EntryController { ...@@ -44,10 +47,13 @@ public class EntryController {
@ResponseStatus(HttpStatus.ACCEPTED) @ResponseStatus(HttpStatus.ACCEPTED)
@PostMapping(consumes = "multipart/form-data", produces = MediaType.APPLICATION_JSON_VALUE) @PostMapping(consumes = "multipart/form-data", produces = MediaType.APPLICATION_JSON_VALUE)
public EntryResponse receiveAntrag(@RequestPart("formData") Resource formData, public EntryResponse receiveAntrag(@RequestPart("formData") Resource formData,
@RequestPart(name = "representation", required = false) Collection<MultipartFile> representations) throws IOException { @RequestPart(name = "representation", required = false) Collection<MultipartFile> representations,
@RequestPart(name = "attachment", required = false) Collection<MultipartFile> attachment)
throws IOException {
var mapped = mapper.mapEntryData(formData.getInputStream()); var mapped = mapper.mapEntryData(formData.getInputStream());
mapped = addVorgangNummer(mapped); mapped = addVorgangNummer(mapped);
mapped = addRepresentations(representations, mapped); mapped = addRepresentations(representations, mapped);
mapped = addAttachments(attachment, mapped);
var vorgangId = semantikAdapter.processFormData(mapped); var vorgangId = semantikAdapter.processFormData(mapped);
...@@ -71,6 +77,21 @@ public class EntryController { ...@@ -71,6 +77,21 @@ public class EntryController {
return result.toBuilder().numberOfRepresentations(result.getRepresentations().size()).build(); return result.toBuilder().numberOfRepresentations(result.getRepresentations().size()).build();
} }
FormData addAttachments(Collection<MultipartFile> attachments, FormData formData) {
if (CollectionUtils.isEmpty(attachments)) {
return formData;
}
IncomingFileGroup group = buildSonstigeGroup(attachments);
return formData.toBuilder().attachment(group).numberOfAttachments(group.getFiles().size()).build();
}
private IncomingFileGroup buildSonstigeGroup(Collection<MultipartFile> attachments) {
var builder = IncomingFileGroup.builder().name(OTHER_FILE_GROUP_NAME);
attachments.stream().map(this::buildIncomingFile).forEach(builder::file);
return builder.build();
}
private IncomingFile buildIncomingFile(MultipartFile multipartFile) { private IncomingFile buildIncomingFile(MultipartFile multipartFile) {
InputStream inStream = getInputStream(multipartFile); InputStream inStream = getInputStream(multipartFile);
......
...@@ -13,6 +13,7 @@ import org.mockito.Captor; ...@@ -13,6 +13,7 @@ import org.mockito.Captor;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile; import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
...@@ -45,7 +46,8 @@ class EnterpriseEntryITCase { ...@@ -45,7 +46,8 @@ class EnterpriseEntryITCase {
@SneakyThrows @SneakyThrows
private ResultActions doPostRequest() { private ResultActions doPostRequest() {
return mockMvc.perform(multipart("/antrag") return mockMvc.perform(multipart("/antrag")
.file(new MockMultipartFile("formData", TestUtils.loadTextFile("request/simple.json").getBytes()))) .file(new MockMultipartFile("formData", "simple.json", MediaType.APPLICATION_JSON.toString(),
TestUtils.loadTextFile("request/simple.json").getBytes())))
.andExpect(status().is2xxSuccessful()); .andExpect(status().is2xxSuccessful());
} }
...@@ -78,11 +80,9 @@ class EnterpriseEntryITCase { ...@@ -78,11 +80,9 @@ class EnterpriseEntryITCase {
@SneakyThrows @SneakyThrows
private FormData doPostRequest() { private FormData doPostRequest() {
mockMvc.perform(multipart("/antrag") mockMvc.perform(multipart("/antrag")
.file(new MockMultipartFile("formData", TestUtils.loadTextFile("request/a12_entry.json").getBytes())) .file(buildJsonFileMock("formData", "a12_entry.json"))
.file(new MockMultipartFile("representation", "document_JaS.json", "application/json", .file(buildJsonFileMock("representation", "document_JaS.json"))
TestUtils.loadTextFile("request/document_JaS.json").getBytes())) .file(buildJsonFileMock("representation", "jugendsozialarbeit_an_schulen-DM.json")))
.file(new MockMultipartFile("representation",
TestUtils.loadTextFile("request/jugendsozialarbeit_an_schulen-DM.json").getBytes())))
.andExpect(status().is2xxSuccessful()); .andExpect(status().is2xxSuccessful());
verify(vorgangService).createVorgang(formDataCaptor.capture()); verify(vorgangService).createVorgang(formDataCaptor.capture());
...@@ -90,4 +90,9 @@ class EnterpriseEntryITCase { ...@@ -90,4 +90,9 @@ class EnterpriseEntryITCase {
} }
} }
private MockMultipartFile buildJsonFileMock(String name, String origName) {
var fileToLoad = "request/%s".formatted(origName);
return new MockMultipartFile(name, origName, MediaType.APPLICATION_JSON.toString(), TestUtils.loadTextFile(fileToLoad).getBytes());
}
} }
package de.ozgcloud.eingang.enterprise.entry; package de.ozgcloud.eingang.enterprise.entry;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.InstanceOfAssertFactories.*;
import static org.mockito.ArgumentMatchers.*; import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
...@@ -8,6 +9,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. ...@@ -8,6 +9,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import java.io.InputStream; import java.io.InputStream;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
...@@ -29,6 +31,7 @@ import de.ozgcloud.eingang.common.formdata.FormData; ...@@ -29,6 +31,7 @@ import de.ozgcloud.eingang.common.formdata.FormData;
import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; import de.ozgcloud.eingang.common.formdata.FormDataTestFactory;
import de.ozgcloud.eingang.common.formdata.FormHeader; import de.ozgcloud.eingang.common.formdata.FormHeader;
import de.ozgcloud.eingang.common.formdata.FormHeaderTestFactory; import de.ozgcloud.eingang.common.formdata.FormHeaderTestFactory;
import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier; import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier;
import de.ozgcloud.eingang.semantik.SemantikAdapter; import de.ozgcloud.eingang.semantik.SemantikAdapter;
import lombok.SneakyThrows; import lombok.SneakyThrows;
...@@ -57,7 +60,7 @@ class EntryControllerTest { ...@@ -57,7 +60,7 @@ class EntryControllerTest {
class ReceiveAntrag { class ReceiveAntrag {
private final FormHeader header = FormHeaderTestFactory.createBuilder().vorgangNummer(null).build(); private final FormHeader header = FormHeaderTestFactory.createBuilder().vorgangNummer(null).build();
private final FormData formData = FormDataTestFactory.createBuilder().header(header).build(); private final FormData formData = FormDataTestFactory.createBuilder().header(header).clearAttachments().clearRepresentations().build();
@Captor @Captor
private ArgumentCaptor<InputStream> streamCaptor; private ArgumentCaptor<InputStream> streamCaptor;
...@@ -109,7 +112,7 @@ class EntryControllerTest { ...@@ -109,7 +112,7 @@ class EntryControllerTest {
@Test @Test
@SneakyThrows @SneakyThrows
void shouldReturnResponse() { void shouldReturnResponse() {
var response = controller.receiveAntrag(mock(Resource.class), Collections.emptyList()); var response = controller.receiveAntrag(mock(Resource.class), Collections.emptyList(), Collections.emptyList());
assertThat(response).isSameAs(this.response); assertThat(response).isSameAs(this.response);
} }
...@@ -131,7 +134,7 @@ class EntryControllerTest { ...@@ -131,7 +134,7 @@ class EntryControllerTest {
void shouldAddRepresentations() { void shouldAddRepresentations() {
var formData = doPostRequest(); var formData = doPostRequest();
assertThat(formData.getRepresentations()).hasSize(3); assertThat(formData.getRepresentations()).hasSize(2);
} }
@SneakyThrows @SneakyThrows
...@@ -148,6 +151,77 @@ class EntryControllerTest { ...@@ -148,6 +151,77 @@ class EntryControllerTest {
} }
} }
@Nested
class WithAttachments {
@Test
void shouldAddAttachments() {
var formData = doPostRequest();
assertThat(formData.getAttachments()).hasSize(1).first().extracting(IncomingFileGroup::getFiles).asInstanceOf(LIST).hasSize(1);
}
@Test
void shouldSetNumberOfAttachments() {
var formData = doPostRequest();
assertThat(formData.getNumberOfAttachments()).isEqualTo(1);
}
@SneakyThrows
private FormData doPostRequest() {
mockMvc.perform(multipart("/antrag")
.file(new MockMultipartFile("formData", TestUtils.loadTextFile("request/a12_entry.json").getBytes()))
.file(new MockMultipartFile("attachment", TestUtils.loadTextFile("request/document_JaS.json").getBytes())))
.andExpect(status().is2xxSuccessful());
verify(semantikAdapter).processFormData(formDataCaptor.capture());
return formDataCaptor.getValue();
}
}
}
@Nested
class TestAddAttachments {
private MockMultipartFile file = new MockMultipartFile("attachment", TestUtils.loadTextFile("request/document_JaS.json").getBytes());
@Test
void shouldIgnoreNullCollection() {
var formData = FormDataTestFactory.create();
var result = controller.addAttachments(null, formData);
assertThat(result).isSameAs(formData);
}
@Test
void shouldIgnoreEmptyCollection() {
var formData = FormDataTestFactory.create();
var result = controller.addAttachments(Collections.emptyList(), formData);
assertThat(result).isSameAs(formData);
}
@Test
void shouldAddToSonstigeGroup() {
var formData = FormDataTestFactory.createBuilder().clearAttachments().build();
var result = controller.addAttachments(List.of(file), formData);
assertThat(result.getAttachments()).hasSize(1).first().extracting(IncomingFileGroup::getName).isEqualTo("Sonstige");
}
@Test
void shouldAddFiles() {
var formData = FormDataTestFactory.createBuilder().clearAttachments().build();
var result = controller.addAttachments(List.of(file), formData);
assertThat(result.getAttachments()).hasSize(1).first().extracting(IncomingFileGroup::getFiles).asInstanceOf(LIST).hasSize(1);
}
} }
@Nested @Nested
......
...@@ -12,10 +12,10 @@ ...@@ -12,10 +12,10 @@
"formId": "KFAS_LIVE_KI_10_Haltverbot_befristet", "formId": "KFAS_LIVE_KI_10_Haltverbot_befristet",
"name": "Anmeldung zur Einrichtung einer zeitlich befristeten Haltverbotszone gem. § 45 Abs. 1 Straßenverkehrsordnung (StVO)", "name": "Anmeldung zur Einrichtung einer zeitlich befristeten Haltverbotszone gem. § 45 Abs. 1 Straßenverkehrsordnung (StVO)",
"serviceKonto": { "serviceKonto": {
"type": "BayernId", "type": "MUK",
"postfachAddress": { "postfachAddress": {
"identifier": "76f1ae54-1cf1-4ae1-c0b4-08d950d6cfc0", "identifier": "e155fcdc-a73e-4ae2-b148-b02e02331ebb",
"type": "privat" "type": "unternehmen"
} }
}, },
"representations": { "representations": {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment