diff --git a/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryController.java b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryController.java index 00608686a3b8f95ad7c2c5eb934851b39d62365a..51fe575160c222b53e06325d106216edcd3e8e89 100644 --- a/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryController.java +++ b/enterprise-adapter/src/main/java/de/ozgcloud/eingang/enterprise/entry/EntryController.java @@ -6,6 +6,7 @@ import java.time.ZonedDateTime; import java.util.Collection; import java.util.Objects; +import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; import org.springframework.http.HttpStatus; @@ -22,6 +23,7 @@ import de.ozgcloud.common.binaryfile.TempFileUtils; import de.ozgcloud.common.errorhandling.TechnicalException; import de.ozgcloud.eingang.common.formdata.FormData; 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.enterprise.entry.EntryResponse.ResponseVorgang; import de.ozgcloud.eingang.semantik.SemantikAdapter; @@ -32,6 +34,7 @@ import de.ozgcloud.eingang.semantik.SemantikAdapter; public class EntryController { private static final String STARTING_STATUS = "NEU"; + private static final String OTHER_FILE_GROUP_NAME = "Sonstige"; @Autowired private EntryDataMapper mapper; @@ -44,10 +47,13 @@ public class EntryController { @ResponseStatus(HttpStatus.ACCEPTED) @PostMapping(consumes = "multipart/form-data", produces = MediaType.APPLICATION_JSON_VALUE) 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()); mapped = addVorgangNummer(mapped); mapped = addRepresentations(representations, mapped); + mapped = addAttachments(attachment, mapped); var vorgangId = semantikAdapter.processFormData(mapped); @@ -71,6 +77,21 @@ public class EntryController { 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) { InputStream inStream = getInputStream(multipartFile); diff --git a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EnterpriseEntryITCase.java b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EnterpriseEntryITCase.java index c2ae1da091e76e6d909ab796473f30a4b86a40f5..bf583f15fffcb0ed87e003c40243277ba1a57a26 100644 --- a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EnterpriseEntryITCase.java +++ b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EnterpriseEntryITCase.java @@ -13,6 +13,7 @@ import org.mockito.Captor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; @@ -45,7 +46,8 @@ class EnterpriseEntryITCase { @SneakyThrows private ResultActions doPostRequest() { 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()); } @@ -78,11 +80,9 @@ class EnterpriseEntryITCase { @SneakyThrows private FormData doPostRequest() { mockMvc.perform(multipart("/antrag") - .file(new MockMultipartFile("formData", TestUtils.loadTextFile("request/a12_entry.json").getBytes())) - .file(new MockMultipartFile("representation", "document_JaS.json", "application/json", - TestUtils.loadTextFile("request/document_JaS.json").getBytes())) - .file(new MockMultipartFile("representation", - TestUtils.loadTextFile("request/jugendsozialarbeit_an_schulen-DM.json").getBytes()))) + .file(buildJsonFileMock("formData", "a12_entry.json")) + .file(buildJsonFileMock("representation", "document_JaS.json")) + .file(buildJsonFileMock("representation", "jugendsozialarbeit_an_schulen-DM.json"))) .andExpect(status().is2xxSuccessful()); verify(vorgangService).createVorgang(formDataCaptor.capture()); @@ -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()); + } } diff --git a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryControllerTest.java b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryControllerTest.java index a6f47cf6aa98f06f12d6c1bbe2408ba7091492bc..97518cade79823016fbf2349955a8fe1d5062d2b 100644 --- a/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryControllerTest.java +++ b/enterprise-adapter/src/test/java/de/ozgcloud/eingang/enterprise/entry/EntryControllerTest.java @@ -1,6 +1,7 @@ package de.ozgcloud.eingang.enterprise.entry; import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.InstanceOfAssertFactories.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; @@ -8,6 +9,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import java.io.InputStream; import java.util.Collections; +import java.util.List; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.BeforeEach; @@ -29,6 +31,7 @@ import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; import de.ozgcloud.eingang.common.formdata.FormHeader; 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.semantik.SemantikAdapter; import lombok.SneakyThrows; @@ -57,7 +60,7 @@ class EntryControllerTest { class ReceiveAntrag { 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 private ArgumentCaptor<InputStream> streamCaptor; @@ -109,7 +112,7 @@ class EntryControllerTest { @Test @SneakyThrows 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); } @@ -131,7 +134,7 @@ class EntryControllerTest { void shouldAddRepresentations() { var formData = doPostRequest(); - assertThat(formData.getRepresentations()).hasSize(3); + assertThat(formData.getRepresentations()).hasSize(2); } @SneakyThrows @@ -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 diff --git a/enterprise-adapter/src/test/resources/request/a12_entry.json b/enterprise-adapter/src/test/resources/request/a12_entry.json index bb1702d2f5a660a31424740822a8dd4eb2f10468..553b82dc2c082291705ae961c432a89e351e9ded 100644 --- a/enterprise-adapter/src/test/resources/request/a12_entry.json +++ b/enterprise-adapter/src/test/resources/request/a12_entry.json @@ -12,10 +12,10 @@ "formId": "KFAS_LIVE_KI_10_Haltverbot_befristet", "name": "Anmeldung zur Einrichtung einer zeitlich befristeten Haltverbotszone gem. § 45 Abs. 1 Straßenverkehrsordnung (StVO)", "serviceKonto": { - "type": "BayernId", + "type": "MUK", "postfachAddress": { - "identifier": "76f1ae54-1cf1-4ae1-c0b4-08d950d6cfc0", - "type": "privat" + "identifier": "e155fcdc-a73e-4ae2-b148-b02e02331ebb", + "type": "unternehmen" } }, "representations": {