Skip to content
Snippets Groups Projects
Commit be773a08 authored by OZGCloud's avatar OZGCloud
Browse files

OZG-5835 log warning if attachments uploaded in the form were not included in the form data

parent 1e77fc13
No related branches found
No related tags found
No related merge requests found
......@@ -15,7 +15,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Version of FORMCYCLE to built against. -->
<xfc.version>8.1.0</xfc.version>
<xfc.version>8.1.2</xfc.version>
<fc-server-maven-plugin.version>8.0.3</fc-server-maven-plugin.version>
<fc-deploy-plugin-maven-plugin.version>8.0.1</fc-deploy-plugin-maven-plugin.version>
......
# Version 2.5.0
- Wenn im Formular Anhänge hochgeladen wurden, aber keine Dateien gefunden wurden, wird eine Warnung mit dem Fehlercode
MISSING_ATTACHMENTS und einer entsprechenden Nachricht protokolliert.
# Version 2.4.0
- Flexibles Einbetten des AKDB-Templates in die OZG Cloud Plugin. Ab diese Version kann das AKDB-Template, das zur
......
......@@ -22,23 +22,24 @@
*/
package de.ozgcloud.formcycle;
import static java.util.Objects.*;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.ozgcloud.eingang.formcycle.FormCycleConfirmationResponse;
import de.ozgcloud.formcycle.attachment.AttachmentMapper;
import de.ozgcloud.formcycle.attachment.AttachmentType;
import de.ozgcloud.formcycle.attachment.FormcycleAttachment;
import de.ozgcloud.formcycle.errorhandling.OzgPluginSoftError;
import de.ozgcloud.formcycle.errorhandling.Warning;
import de.ozgcloud.formcycle.formdata.FormData;
import de.ozgcloud.formcycle.formdata.OzgCloudFormDataMapper;
import de.ozgcloud.formcycle.formdata.PluginFormDataAdapter;
import de.xima.fc.entities.Attachment;
......@@ -58,35 +59,43 @@ public final class OzgPluginExecutor {
public ExecutionResult execute() {
LOG.debug("Executing plugin WorkflowElementNodePlugin");
var formData = pluginFormDataAdapter.readFormData();
var resultBuilder = ExecutionResult.builder();
formData.getWarnings().forEach(resultBuilder::warning);
var attachments = getAttachedFiles(formData.getAttachmentUuids());
if (isNull(attachments.get(AttachmentType.REPRESENTATION))) {
resultBuilder.warning(
buildWarning("Representation is missing. Ensure workflow is configured to attach form view to form data."));
return buildExecutionResult(sendFormData(addAttachedFiles(formData)), formData);
}
var formcycleFormData = ozgCloudFormDataMapper.map(formData);
var formCycleConfirmationResponse = ozgHttpClient.send(formcycleFormData, attachments.get(AttachmentType.ATTACHMENT),
attachments.get(AttachmentType.REPRESENTATION));
LOG.debug("Formcycle adapter response: {}", formCycleConfirmationResponse);
FormCycleConfirmationResponse sendFormData(FormData formData) {
return ozgHttpClient.send(ozgCloudFormDataMapper.map(formData), formData.getAttachments(), formData.getRepresentations());
}
return resultBuilder.vorgangnummer(formCycleConfirmationResponse.getVorgangNummer()).build();
FormData addAttachedFiles(FormData formData) {
var formDataBuilder = formData.toBuilder();
var attachedFiles = getAttachedFiles(formData.getAttachmentUuids());
Optional.ofNullable(attachedFiles.get(AttachmentType.REPRESENTATION)).ifPresentOrElse(formDataBuilder::representations,
() -> formDataBuilder.warning(buildWarning(OzgPluginSoftError.MISSING_REPRESENTATION,
"Representation is missing. Ensure workflow is configured to attach form view to form data.")));
Optional.ofNullable(attachedFiles.get(AttachmentType.ATTACHMENT)).ifPresentOrElse(formDataBuilder::attachments,
() -> formDataBuilder.warning(
buildWarning(OzgPluginSoftError.MISSING_ATTACHMENTS, "Attachments were found in form data, but files are missing.")));
return formDataBuilder.build();
}
Map<AttachmentType, Set<FormcycleAttachment>> getAttachedFiles(Set<String> uploadFieldUuids) {
var resultMap = new EnumMap<AttachmentType, Set<FormcycleAttachment>>(AttachmentType.class);
Map<AttachmentType, List<FormcycleAttachment>> getAttachedFiles(Set<String> uploadFieldUuids) {
var resultMap = new EnumMap<AttachmentType, List<FormcycleAttachment>>(AttachmentType.class);
for (Attachment attachment : attachmentsSupplier.get()) {
if (uploadFieldUuids.contains(attachment.getUUID())) {
resultMap.computeIfAbsent(AttachmentType.ATTACHMENT, e -> new HashSet<>()).add(attachmentMapper.map(attachment));
resultMap.computeIfAbsent(AttachmentType.ATTACHMENT, e -> new ArrayList<>()).add(attachmentMapper.map(attachment));
continue;
}
resultMap.computeIfAbsent(AttachmentType.REPRESENTATION, e -> new HashSet<>()).add(attachmentMapper.map(attachment));
resultMap.computeIfAbsent(AttachmentType.REPRESENTATION, e -> new ArrayList<>()).add(attachmentMapper.map(attachment));
}
return resultMap;
}
Warning buildWarning(String message) {
return Warning.builder().errorCode(OzgPluginSoftError.MISSING_REPRESENTATION).message(message).build();
Warning buildWarning(OzgPluginSoftError warningCode, String message) {
return Warning.builder().errorCode(warningCode).message(message).build();
}
ExecutionResult buildExecutionResult(FormCycleConfirmationResponse response, FormData formData) {
LOG.debug("Formcycle adapter response: {}", response);
return ExecutionResult.builder().vorgangnummer(response.getVorgangNummer()).warnings(formData.getWarnings()).build();
}
}
......@@ -33,6 +33,8 @@ public enum OzgPluginSoftError {
/** Indicates that representation of a formular was not attached to form data */
MISSING_REPRESENTATION,
/** Indicates that the attachments uploaded in the form were not included in the form data. */
MISSING_ATTACHMENTS,
/** Indicates that user connected the formular with a service konto and it supply an unexpected trust level value */
UNEXPECTED_TRUST_LEVEL
......
......@@ -27,13 +27,14 @@ import java.util.List;
import java.util.Optional;
import java.util.Set;
import de.ozgcloud.formcycle.attachment.FormcycleAttachment;
import de.ozgcloud.formcycle.errorhandling.Warning;
import lombok.Builder;
import lombok.Getter;
import lombok.Singular;
@Getter
@Builder
@Builder(toBuilder = true)
public class FormData {
......@@ -48,6 +49,11 @@ public class FormData {
private List<FormNode> fieldData;
@Singular
private List<FormcycleAttachment> attachments;
@Singular
private List<FormcycleAttachment> representations;
@Singular
private List<Warning> warnings;
......
......@@ -13,6 +13,7 @@ de.ozgcloud.formcycle.OzgCloudPlugin.errVal.OZGCLOUD_REQUEST_FAILED.exceptionId
# Soft Errors
de.ozgcloud.formcycle.OzgCloudPlugin.softerrcode.MISSING_REPRESENTATION = Warnung Code, wenn Formular Representation nicht angehngt werden konnte.
de.ozgcloud.formcycle.OzgCloudPlugin.softerrcode.MISSING_ATTACHMENTS=Warnung Code, wenn im Formular hochgeladene Anhnge nicht gefunden worden sind.
de.ozgcloud.formcycle.OzgCloudPlugin.softerrcode.UNEXPECTED_TRUST_LEVEL = Warnung Code, wenn das Vertrauensniveau der BayernID Verbindung einen unerwarteten Wert hat oder leer ist.
OzgPluginWorkflowNodeProperties.section_settings = Einstellungen
......
......@@ -52,6 +52,7 @@ import de.ozgcloud.formcycle.errorhandling.NodeThrewExceptionFactory;
import de.ozgcloud.formcycle.errorhandling.OzgPluginSoftError;
import de.ozgcloud.formcycle.errorhandling.Warning;
import de.ozgcloud.formcycle.formdata.FormData;
import de.ozgcloud.formcycle.formdata.FormDataTestFactory;
import de.ozgcloud.formcycle.formdata.OzgCloudFormDataMapper;
import de.ozgcloud.formcycle.formdata.PluginFormDataAdapter;
import de.xima.fc.entities.Attachment;
......@@ -59,6 +60,8 @@ import lombok.SneakyThrows;
class OzgPluginExecutorTest {
private final static FormData FORM_DATA = FormDataTestFactory.create();
@Spy
@InjectMocks
private OzgPluginExecutor executor;
......@@ -81,57 +84,53 @@ class OzgPluginExecutorTest {
@Nested
class TestExecution {
private static final String VORGANGS_NUMMER = "12345";
@Mock
private FormCycleConfirmationResponse response;
@Mock
private FormData formData;
@Mock
private Warning warning;
@Captor
private ArgumentCaptor<List<FormcycleAttachment>> attachmentsCapture;
private ExecutionResult executionResult;
@SneakyThrows
@BeforeEach
void setup() {
when(response.getVorgangNummer()).thenReturn(VORGANGS_NUMMER);
when(ozgHttpClient.send(any(), any(), any())).thenReturn(response);
when(pluginFormDataAdapter.readFormData()).thenReturn(formData);
when(pluginFormDataAdapter.readFormData()).thenReturn(FORM_DATA);
doReturn(FORM_DATA).when(executor).addAttachedFiles(any());
doReturn(executionResult).when(executor).buildExecutionResult(any(), any());
}
@Nested
class TestMapping {
@Test
void shouldCallPluginFormDataAdapter() {
executor.execute();
@BeforeEach
void setup() {
when(attachmentSupplier.get()).thenReturn(List.of());
verify(pluginFormDataAdapter).readFormData();
}
@SneakyThrows
@Test
void shouldExtractAsGrpc() {
void shouldCallAddAttachedFiles() {
executor.execute();
verify(ozgCloudFormDataMapper).map(formData);
verify(executor).addAttachedFiles(FORM_DATA);
}
@SneakyThrows
@Test
void shouldCreateSuccessResult() {
var executionResult = executor.execute();
void shouldCallSendFormData() {
executor.execute();
assertThat(executionResult.getVorgangnummer()).isEqualTo(VORGANGS_NUMMER);
verify(executor).sendFormData(FORM_DATA);
}
@Test
void shouldAddWarnings() {
when(formData.getWarnings()).thenReturn(List.of(warning));
void shouldCallBuildExecutionResult() {
executor.execute();
verify(executor).buildExecutionResult(response, FORM_DATA);
}
var executionResult = executor.execute();
@Test
void shouldReturnExecutionResult() {
var result = executor.execute();
assertThat(executionResult.getWarnings()).contains(warning);
assertThat(result).isSameAs(executionResult);
}
}
......@@ -141,54 +140,160 @@ class OzgPluginExecutorTest {
@Mock
private FormCycleFormData formcycleFormData;
@Mock
private FormCycleConfirmationResponse response;
@Captor
private ArgumentCaptor<Set<FormcycleAttachment>> attachmentsCapture;
private ArgumentCaptor<List<FormcycleAttachment>> attachmentsCapture;
@Captor
private ArgumentCaptor<List<FormcycleAttachment>> representationsCapture;
@SneakyThrows
@BeforeEach
void setup() {
when(ozgCloudFormDataMapper.map(any())).thenReturn(formcycleFormData);
@Test
void shouldCallMapper() {
sendFormData();
verify(ozgCloudFormDataMapper).map(FORM_DATA);
}
@SneakyThrows
@Test
void shouldSendFormData() {
when(attachmentSupplier.get()).thenReturn(List.of());
when(ozgCloudFormDataMapper.map(any())).thenReturn(formcycleFormData);
executor.execute();
sendFormData();
verify(ozgHttpClient).send(eq(formcycleFormData), any(), any());
}
@SneakyThrows
@Test
void shouldSendAttachments() {
var expectedAttachment = FormcycleAttachmentTestFactory.create();
doReturn(Map.of(
AttachmentType.ATTACHMENT, Set.of(expectedAttachment),
AttachmentType.REPRESENTATION, Set.of(FormcycleAttachmentTestFactory.create()))).when(executor).getAttachedFiles(any());
executor.execute();
sendFormData();
verify(ozgHttpClient).send(any(), attachmentsCapture.capture(), any());
assertThat(attachmentsCapture.getValue()).containsExactlyInAnyOrder(expectedAttachment);
assertThat(attachmentsCapture.getValue()).hasSize(1).first().extracting("uuid").isEqualTo(FormDataTestFactory.ATTACHMENT_UUID);
}
@SneakyThrows
@Test
void shouldSendRepresentations() {
var expectedRepresentations = FormcycleAttachmentTestFactory.create();
doReturn(Map.of(
AttachmentType.ATTACHMENT, Set.of(FormcycleAttachmentTestFactory.create()),
AttachmentType.REPRESENTATION, Set.of(expectedRepresentations))).when(executor).getAttachedFiles(any());
sendFormData();
executor.execute();
verify(ozgHttpClient).send(any(), any(), representationsCapture.capture());
assertThat(representationsCapture.getValue()).hasSize(1).first().extracting("uuid").isEqualTo(FormDataTestFactory.REPRESENTATION_UUID);
}
@Test
void shouldReturnResponse() {
when(ozgHttpClient.send(any(), any(), any())).thenReturn(response);
var result = sendFormData();
verify(ozgHttpClient).send(any(), any(), attachmentsCapture.capture());
assertThat(attachmentsCapture.getValue()).containsExactlyInAnyOrder(expectedRepresentations);
assertThat(result).isSameAs(response);
}
private FormCycleConfirmationResponse sendFormData() {
return executor.sendFormData(FORM_DATA);
}
}
@Nested
class TestAddAttachedFiles {
@Captor
private ArgumentCaptor<Set<String>> attachmentUuidsCapture;
private final FormData formData = FormDataTestFactory.createBuilder().clearAttachments().clearRepresentations().clearWarnings().build();
@Test
void shouldCallGetAttachedFiles() {
mockGetAttachedFiles();
executor.addAttachedFiles(formData);
verify(executor).getAttachedFiles(attachmentUuidsCapture.capture());
assertThat(attachmentUuidsCapture.getValue()).containsExactly(FormDataTestFactory.ATTACHMENT_UUID);
}
@Test
void shouldSetRepresentations() {
mockGetAttachedFiles();
var result = executor.addAttachedFiles(formData);
assertThat(result.getRepresentations()).hasSize(1).first().extracting("uuid").isEqualTo(FormDataTestFactory.REPRESENTATION_UUID);
}
@Test
void shouldSetAttachments() {
mockGetAttachedFiles();
var result = executor.addAttachedFiles(formData);
assertThat(result.getAttachments()).hasSize(1).first().extracting("uuid").isEqualTo(FormDataTestFactory.ATTACHMENT_UUID);
}
@Test
void shouldNotAddAnyWarnings() {
mockGetAttachedFiles();
var result = executor.addAttachedFiles(formData);
assertThat(result.getWarnings()).isEmpty();
}
private void mockGetAttachedFiles() {
var attachedFiles = Map.of(
AttachmentType.ATTACHMENT,
List.of(FormcycleAttachmentTestFactory.createBuilder().uuid(FormDataTestFactory.ATTACHMENT_UUID).build()),
AttachmentType.REPRESENTATION,
List.of(FormcycleAttachmentTestFactory.createBuilder().uuid(FormDataTestFactory.REPRESENTATION_UUID).build()));
doReturn(attachedFiles).when(executor).getAttachedFiles(any());
}
@Nested
class TestAddWarnings {
@BeforeEach
void setup() {
}
@Test
void shouldAddWhenMissingRepresentations() {
doReturn(Map.of(AttachmentType.ATTACHMENT, List.of(FormcycleAttachmentTestFactory.create()))).when(executor).getAttachedFiles(any());
var result = executor.addAttachedFiles(formData);
assertThat(result.getWarnings()).hasSize(1).first().extracting(Warning::getErrorCode)
.isEqualTo(OzgPluginSoftError.MISSING_REPRESENTATION.name());
}
@Test
void shouldAddNotAddRepresentations() {
doReturn(Map.of(AttachmentType.ATTACHMENT, List.of(FormcycleAttachmentTestFactory.create()))).when(executor).getAttachedFiles(any());
var result = executor.addAttachedFiles(formData);
assertThat(result.getRepresentations()).isEmpty();
}
@Test
void shouldAddWhenMissingAttachments() {
doReturn(Map.of(AttachmentType.REPRESENTATION, List.of(FormcycleAttachmentTestFactory.create()))).when(executor)
.getAttachedFiles(any());
var result = executor.addAttachedFiles(formData);
assertThat(result.getWarnings()).hasSize(1).first().extracting(Warning::getErrorCode)
.isEqualTo(OzgPluginSoftError.MISSING_ATTACHMENTS.name());
}
@Test
void shouldNotAddAttachments() {
doReturn(Map.of(AttachmentType.REPRESENTATION, List.of(FormcycleAttachmentTestFactory.create()))).when(executor)
.getAttachedFiles(any());
var result = executor.addAttachedFiles(formData);
assertThat(result.getAttachments()).isEmpty();
}
}
}
......@@ -216,7 +321,7 @@ class OzgPluginExecutorTest {
var attachedFiles = getAttachedFiles(Set.of(FormcycleAttachmentTestFactory.UUID));
assertThat(attachedFiles).hasSize(1).containsOnly(Map.entry(AttachmentType.ATTACHMENT, Set.of(expectedAttachment)));
assertThat(attachedFiles).hasSize(1).containsOnly(Map.entry(AttachmentType.ATTACHMENT, List.of(expectedAttachment)));
}
@Test
......@@ -225,7 +330,7 @@ class OzgPluginExecutorTest {
var attachedFiles = getAttachedFiles(Set.of(FormcycleAttachmentTestFactory.UUID));
assertThat(attachedFiles).hasSize(1).containsOnly(Map.entry(AttachmentType.ATTACHMENT, Set.of(expectedAttachment)));
assertThat(attachedFiles).hasSize(1).containsOnly(Map.entry(AttachmentType.ATTACHMENT, List.of(expectedAttachment)));
}
@Test
......@@ -251,7 +356,7 @@ class OzgPluginExecutorTest {
}
@SneakyThrows
private Map<AttachmentType, Set<FormcycleAttachment>> getAttachedFiles(Set<String> ids) {
private Map<AttachmentType, List<FormcycleAttachment>> getAttachedFiles(Set<String> ids) {
return executor.getAttachedFiles(ids);
}
}
......@@ -263,16 +368,39 @@ class OzgPluginExecutorTest {
@Test
void shouldSetErrorCode() {
var warning = executor.buildWarning(MESSAGE);
var warning = executor.buildWarning(OzgPluginSoftError.MISSING_REPRESENTATION, MESSAGE);
assertThat(warning.getErrorCode()).isEqualTo(OzgPluginSoftError.MISSING_REPRESENTATION.toString());
}
@Test
void shouldSetMessage() {
var warning = executor.buildWarning(MESSAGE);
var warning = executor.buildWarning(OzgPluginSoftError.MISSING_REPRESENTATION, MESSAGE);
assertThat(warning.getMessage()).isEqualTo(MESSAGE);
}
}
@Nested
class TestBuildExecutionResults {
@Mock
private Warning warning;
@Test
void shouldSetVorgangNummer() {
var result = executor.buildExecutionResult(FormCycleConfirmationResponseTestFactory.create(), FORM_DATA);
assertThat(result.getVorgangnummer()).isEqualTo(FormCycleConfirmationResponseTestFactory.VORGANG_NUMMER);
}
@Test
void shouldSetWarnings() {
var formData = FormDataTestFactory.createBuilder().clearWarnings().warning(warning).build();
var result = executor.buildExecutionResult(FormCycleConfirmationResponseTestFactory.create(), formData);
assertThat(result.getWarnings()).containsExactly(warning);
}
}
}
\ No newline at end of file
......@@ -19,7 +19,7 @@ public class FormcycleAttachmentTestFactory {
return createBuilder().build();
}
static FormcycleAttachmentBuilder createBuilder() {
public static FormcycleAttachmentBuilder createBuilder() {
return FormcycleAttachment.builder()
.uuid(UUID)
.fileName(FILE_NAME)
......
......@@ -24,12 +24,17 @@ package de.ozgcloud.formcycle.formdata;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import de.ozgcloud.formcycle.attachment.FormcycleAttachmentTestFactory;
public class FormDataTestFactory {
public static final String FORM_NAME = "formular";
public static final String ORGANISATIONS_EINHEIT_ID = "12345";
public static final String ATTACHMENT_ID = "file.pdf";
public static final String ATTACHMENT_UUID = UUID.randomUUID().toString();
public static final String REPRESENTATION_UUID = UUID.randomUUID().toString();
public static final String FIELD_VALUE_1 = "on";
public static final List<FormNode> FIELD_DATA = List.of(FormNodeTestFactory.create());
......@@ -43,6 +48,9 @@ public class FormDataTestFactory {
.organisationsEinheitId(ORGANISATIONS_EINHEIT_ID)
.fieldData(FIELD_DATA)
.attachmentNames(Set.of(ATTACHMENT_ID))
.attachmentUuids(Set.of(ATTACHMENT_UUID))
.representation(FormcycleAttachmentTestFactory.createBuilder().uuid(REPRESENTATION_UUID).build())
.attachment(FormcycleAttachmentTestFactory.createBuilder().uuid(ATTACHMENT_UUID).build())
.serviceKonto(ServiceKontoTestFactory.create());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment