diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidGrpcService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidGrpcService.java index fb1cce79ca8b440566661cede1b0ff50cc4036d8..84d0d11a5d44d852abf7d4e2ea7c027a8cc946be 100644 --- a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidGrpcService.java +++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidGrpcService.java @@ -17,7 +17,7 @@ class BescheidGrpcService extends BescheidServiceImplBase { @Override public void getBescheidDraft(GrpcGetBescheidDraftRequest request, StreamObserver<GrpcGetBescheidDraftResponse> responseObserver) { - var response = attachedItemService.getBescheidItem(request.getVorgangId()) + var response = attachedItemService.findBescheidItem(request.getVorgangId()) .map(this::buildResponse) .orElseGet(GrpcGetBescheidDraftResponse::getDefaultInstance); diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/attacheditem/AttachedItemService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/attacheditem/AttachedItemService.java index 5362b2a489b9616f9ecb606446ea1f713e9ecb7e..cf8d8bf0e80e6a905b5e2c5097382462744acf74 100644 --- a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/attacheditem/AttachedItemService.java +++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/attacheditem/AttachedItemService.java @@ -48,7 +48,6 @@ import lombok.extern.log4j.Log4j2; public class AttachedItemService { static final String BESCHEID_ITEM_NAME = "Bescheid"; - static final String BESCHEID_DRAFT_STATUS = "DRAFT"; static final String CREATE_ATTACHED_ITEM_ORDER = "CREATE_ATTACHED_ITEM"; static final String UPDATE_ATTACHED_ITEM_ORDER = "UPDATE_ATTACHED_ITEM"; static final String DELETE_ATTACHED_ITEM = "DELETE_ATTACHED_ITEM"; @@ -59,10 +58,14 @@ public class AttachedItemService { private final VorgangAttachedItemRemoteService remoteService; private final CommandMapper commandMapper; - public Optional<BescheidItem> getBescheidItem(String vorgangId) { + public Optional<BescheidItem> findBescheidItem(String vorgangId) { return remoteService.findBescheidDraft(vorgangId); } + public BescheidItem getBescheidItem(String id) { + return remoteService.getBescheid(id); + } + public String createBescheidDraft(Command command) { validateBescheidData(command.getBodyObject()); return remoteService.findBescheidDraft(command.getVorgangId()) @@ -129,7 +132,7 @@ public class AttachedItemService { Map<String, Object> buildItemMapWithExistingBescheidFields(Command command) { var result = new HashMap<String, Object>(); - result.put(BescheidItem.FIELD_STATUS, BESCHEID_DRAFT_STATUS); + result.put(BescheidItem.FIELD_STATUS, BescheidItem.Status.DRAFT.name()); addValueFromMapIfExists(command.getBodyObject(), BescheidItem.FIELD_BESCHIEDEN_AM, result); addValueFromMapIfExists(command.getBodyObject(), BescheidItem.FIELD_BEWILLIGT, result); addValueFromMapIfExists(command.getBodyObject(), BescheidItem.FIELD_BESCHEID_DOCUMENT, result); @@ -168,7 +171,7 @@ public class AttachedItemService { void validateBescheidStatus(BescheidItem bescheid) { var bescheidStatus = MapUtils.getString(bescheid.getBescheidData(), BescheidItem.FIELD_STATUS); - if (!BESCHEID_DRAFT_STATUS.equals(bescheidStatus)) { + if (BescheidItem.Status.DRAFT.not(bescheidStatus)) { throw new TechnicalException("Bescheid draft with ID '%s' has an unexpected status: '%s'".formatted(bescheid.getId(), bescheidStatus)); } } diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/attacheditem/BescheidItem.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/attacheditem/BescheidItem.java index 57d6eac58ed8fe7681dbf4e28500d8ca53871205..84b6f8aff6a040ab619ccaed13d19c08c7d3b4f7 100644 --- a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/attacheditem/BescheidItem.java +++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/attacheditem/BescheidItem.java @@ -60,4 +60,16 @@ public class BescheidItem { private String itemName; private Map<String, Object> bescheidData; + + public enum Status { + DRAFT, BESCHEID; + + public boolean not(String value) { + return !hasValue(value); + } + + public boolean hasValue(String value) { + return this.name().equalsIgnoreCase(value); + } + } } diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/attacheditem/VorgangAttachedItemRemoteService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/attacheditem/VorgangAttachedItemRemoteService.java index 192f16e46ab7308c6230b208e88bbdb8093674ce..e0ee53970c6e8b22f1e66b9060e7cd505847b987 100644 --- a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/attacheditem/VorgangAttachedItemRemoteService.java +++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/attacheditem/VorgangAttachedItemRemoteService.java @@ -72,14 +72,17 @@ class VorgangAttachedItemRemoteService { Optional<BescheidItem> findBescheidDraft(GrpcFindVorgangAttachedItemRequest request) { var grpcResponse = getServiceStub().find(request); - var bescheidItems = bescheidItemMapper.fromFindVorgangAttachedItemResponse(grpcResponse) - .filter(item -> BESCHEID_DRAFT_STATUS.equals(MapUtils.getString(item.getBescheidData(), BescheidItem.FIELD_STATUS))) + var bescheidItems = bescheidItemMapper.fromFindVorgangAttachedItemResponse(grpcResponse).filter(this::hasStatusDraft) .sorted(BY_BESCHIEDEN_AM_DESC).toList(); if (bescheidItems.size() > 1) { LOG.error("Found more than one ({}) draft bescheid for vorgangId: {}. Return one with last beschiedenAm date", bescheidItems.size(), - bescheidItems.get(0).getVorgangId()); + bescheidItems.getFirst().getVorgangId()); } - return bescheidItems.isEmpty() ? Optional.empty() : Optional.of(bescheidItems.get(0)); + return bescheidItems.isEmpty() ? Optional.empty() : Optional.of(bescheidItems.getFirst()); + } + + boolean hasStatusDraft(BescheidItem bescheidItem) { + return BescheidItem.Status.DRAFT.hasValue(MapUtils.getString(bescheidItem.getBescheidData(), BescheidItem.FIELD_STATUS)); } public BescheidItem getBescheid(String bescheidId) { diff --git a/bescheid-manager/src/main/java/de/ozgcloud/document/DocumentService.java b/bescheid-manager/src/main/java/de/ozgcloud/document/DocumentService.java index 1846fb93799c2b8dedffc2f3baa2c57f1e2d587a..0a4e4090ec4f656f47d34d612a1cd72ef3474c56 100644 --- a/bescheid-manager/src/main/java/de/ozgcloud/document/DocumentService.java +++ b/bescheid-manager/src/main/java/de/ozgcloud/document/DocumentService.java @@ -27,12 +27,14 @@ import java.util.HashMap; import java.util.Map; import java.util.Optional; +import org.apache.commons.collections.MapUtils; import org.springframework.stereotype.Service; import de.ozgcloud.apilib.common.command.OzgCloudCommand; import de.ozgcloud.apilib.common.command.OzgCloudCommandService; import de.ozgcloud.apilib.common.command.grpc.CommandMapper; import de.ozgcloud.bescheid.BescheidCallContextAttachingInterceptor; +import de.ozgcloud.bescheid.attacheditem.AttachedItemService; import de.ozgcloud.bescheid.attacheditem.BescheidItem; import de.ozgcloud.command.Command; import de.ozgcloud.common.errorhandling.TechnicalException; @@ -48,20 +50,30 @@ public class DocumentService { static final String DOCUMENT_TYPE = "BESCHEID"; static final String FIELD_DOCUMENT_FILE = "documentFile"; + private final AttachedItemService attachedItemService; private final OzgCloudCommandService commandService; private final CommandMapper commandMapper; public String createBescheidDocument(Command command) { + validateBescheidItem(command.getRelationId()); var ozgCloudCommand = buildCreateDocumentOzgCommand(command); var executedCommand = commandService.createAndWaitUntilDone(ozgCloudCommand); return executedCommand.getCreatedResource(); } + void validateBescheidItem(String bescheidId) { + var bescheidData = attachedItemService.getBescheidItem(bescheidId).getBescheidData(); + var status = MapUtils.getString(bescheidData, BescheidItem.FIELD_STATUS); + if (BescheidItem.Status.DRAFT.not(status)) { + throw new TechnicalException("Bescheid is not in draft status"); + } + } + OzgCloudCommand buildCreateDocumentOzgCommand(Command command) { return OzgCloudCommand.builder() .order(CREATE_ATTACHED_ITEM_ORDER) .vorgangId(commandMapper.toOzgCloudVorgangId(command.getVorgangId())) - .relationId(commandMapper.mapRelationId(command.getRelationId())) + .relationId(commandMapper.mapRelationId(command.getVorgangId())) .bodyObject(buildAttachedItem(command)) .build(); } diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidGrpcServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidGrpcServiceTest.java index 9cb416ff02f582ac1b8d6e535ab583fb704a661f..4d965a689be4c55ce1a9909c85fa8e013eb2da7e 100644 --- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidGrpcServiceTest.java +++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidGrpcServiceTest.java @@ -45,7 +45,7 @@ class BescheidGrpcServiceTest { @Test void shouldBuildResponse() { when(mapper.toBescheid(any())).thenReturn(GrpcBescheidTestFactory.create()); - when(attachedItemService.getBescheidItem(any())).thenReturn(Optional.of(BescheidItemTestFactory.create())); + when(attachedItemService.findBescheidItem(any())).thenReturn(Optional.of(BescheidItemTestFactory.create())); service.getBescheidDraft(request, responseObserver); @@ -56,7 +56,7 @@ class BescheidGrpcServiceTest { void shouldCallNext() { when(mapper.toBescheid(any())).thenReturn(GrpcBescheidTestFactory.create()); when(service.buildResponse(any())).thenReturn(response); - when(attachedItemService.getBescheidItem(any())).thenReturn(Optional.of(BescheidItemTestFactory.create())); + when(attachedItemService.findBescheidItem(any())).thenReturn(Optional.of(BescheidItemTestFactory.create())); service.getBescheidDraft(request, responseObserver); diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/attacheditem/AttachedItemServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/attacheditem/AttachedItemServiceTest.java index d81c4212494dea994091fafc85cc78f8d1b56ee7..3c10b5cdb070f9c0cbd60590cf805170c0491632 100644 --- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/attacheditem/AttachedItemServiceTest.java +++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/attacheditem/AttachedItemServiceTest.java @@ -72,7 +72,7 @@ class AttachedItemServiceTest { @Test void shouldCallGetBescheidDraft() { - service.getBescheidItem(CommandTestFactory.VORGANG_ID); + service.findBescheidItem(CommandTestFactory.VORGANG_ID); verify(remoteService).findBescheidDraft(CommandTestFactory.VORGANG_ID); } @@ -82,12 +82,33 @@ class AttachedItemServiceTest { var expected = BescheidItemTestFactory.create(); when(remoteService.findBescheidDraft(anyString())).thenReturn(Optional.of(expected)); - var actual = service.getBescheidItem(CommandTestFactory.VORGANG_ID); + var actual = service.findBescheidItem(CommandTestFactory.VORGANG_ID); assertThat(actual).contains(expected); } } + @Nested + class TestGetBescheidItem { + + @Test + void shouldCallGetBescheid() { + service.getBescheidItem(BescheidItemTestFactory.ID); + + verify(remoteService).getBescheid(BescheidItemTestFactory.ID); + } + + @Test + void shouldReturnBescheidItem() { + var expected = BescheidItemTestFactory.create(); + when(remoteService.getBescheid(anyString())).thenReturn(expected); + + var actual = service.getBescheidItem(BescheidItemTestFactory.ID); + + assertThat(actual).isEqualTo(expected); + } + } + @Nested class TestCreateBescheidDraft { @@ -484,7 +505,7 @@ class AttachedItemServiceTest { void shouldSetStatus() { var bescheidMap = service.buildItemMapWithExistingBescheidFields(command); - assertThat(bescheidMap).containsEntry(BescheidItem.FIELD_STATUS, AttachedItemService.BESCHEID_DRAFT_STATUS); + assertThat(bescheidMap).containsEntry(BescheidItem.FIELD_STATUS, BescheidItem.Status.DRAFT.name()); } @Test diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/attacheditem/BescheidItemTestFactory.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/attacheditem/BescheidItemTestFactory.java index b053862753311d75651238ead6f5ae4492b6a124..1299edf5394b1d9a8ec0d804663dbd450b3d741c 100644 --- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/attacheditem/BescheidItemTestFactory.java +++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/attacheditem/BescheidItemTestFactory.java @@ -58,7 +58,7 @@ public class BescheidItemTestFactory { public static Map<String, Object> createBescheidBody() { return Map.of( - BescheidItem.FIELD_STATUS, AttachedItemService.BESCHEID_DRAFT_STATUS, + BescheidItem.FIELD_STATUS, BescheidItem.Status.DRAFT, BescheidItem.FIELD_BESCHIEDEN_AM, BESCHEIDEN_AM, BescheidItem.FIELD_BEWILLIGT, true, BescheidItem.FIELD_BESCHEID_DOCUMENT, BESCHEID_DOCUMENT, diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/attacheditem/VorgangAttachedItemRemoteServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/attacheditem/VorgangAttachedItemRemoteServiceTest.java index 257cbc65ee52e8660fa93be4912f321e01d8089e..88259ab1300ec4b86712144b5c196f761c7a231a 100644 --- a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/attacheditem/VorgangAttachedItemRemoteServiceTest.java +++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/attacheditem/VorgangAttachedItemRemoteServiceTest.java @@ -130,11 +130,40 @@ class VorgangAttachedItemRemoteServiceTest { verify(bescheidItemMapper).fromFindVorgangAttachedItemResponse(response); } + @Test + void shouldCallHasStatusDraft() { + var item = BescheidItemTestFactory.create(); + when(bescheidItemMapper.fromFindVorgangAttachedItemResponse(any())).thenReturn(Stream.of(item)); + + service.findBescheidDraft(request); + + verify(service).hasStatusDraft(item); + } + @Test void shouldFilterDraftItems() { - var item1 = BescheidItemTestFactory.createBuilder().bescheidData(Map.of( - BescheidItem.FIELD_STATUS, "other")).build(); - when(bescheidItemMapper.fromFindVorgangAttachedItemResponse(any())).thenReturn(Stream.of(item1)); + var item = BescheidItemTestFactory.create(); + when(bescheidItemMapper.fromFindVorgangAttachedItemResponse(any())).thenReturn(Stream.of(item)); + doReturn(true).when(service).hasStatusDraft(any()); + + var result = service.findBescheidDraft(request); + + assertThat(result).contains(item); + } + + @Test + void shouldReturnEmptyWhenNotFound() { + when(bescheidItemMapper.fromFindVorgangAttachedItemResponse(any())).thenReturn(Stream.empty()); + + var result = service.findBescheidDraft(request); + + assertThat(result).isEmpty(); + } + + @Test + void shouldReturnEmptyWhenNotDraft() { + when(bescheidItemMapper.fromFindVorgangAttachedItemResponse(any())).thenReturn(Stream.of(BescheidItemTestFactory.create())); + doReturn(false).when(service).hasStatusDraft(any()); var result = service.findBescheidDraft(request); @@ -144,10 +173,10 @@ class VorgangAttachedItemRemoteServiceTest { @Test void shouldReturnLastBescheid() { var item1 = BescheidItemTestFactory.createBuilder().bescheidData(Map.of( - BescheidItem.FIELD_BESCHIEDEN_AM, "2021-01-01", - BescheidItem.FIELD_STATUS, AttachedItemService.BESCHEID_DRAFT_STATUS)).build(); + BescheidItem.FIELD_BESCHIEDEN_AM, "2021-01-01")).build(); var item2 = BescheidItemTestFactory.create(); when(bescheidItemMapper.fromFindVorgangAttachedItemResponse(any())).thenReturn(Stream.of(item1, item2)); + doReturn(true).when(service).hasStatusDraft(any()); var result = service.findBescheidDraft(request); @@ -191,6 +220,30 @@ class VorgangAttachedItemRemoteServiceTest { } } + @Nested + class TestHasStatusDraft { + + @Test + void shouldReturnTrueIfDraft() { + var item = BescheidItemTestFactory.createBuilder().bescheidData(Map.of(BescheidItem.FIELD_STATUS, BescheidItem.Status.DRAFT.name())) + .build(); + + var result = service.hasStatusDraft(item); + + assertThat(result).isTrue(); + } + + @Test + void shouldReturnFalseIfNotDraft() { + var item = BescheidItemTestFactory.createBuilder().bescheidData(Map.of(BescheidItem.FIELD_STATUS, BescheidItem.Status.BESCHEID.name())) + .build(); + + var result = service.hasStatusDraft(item); + + assertThat(result).isFalse(); + } + } + @Nested class TestGetBescheid { diff --git a/bescheid-manager/src/test/java/de/ozgcloud/document/DocumentEventListenerITCase.java b/bescheid-manager/src/test/java/de/ozgcloud/document/DocumentEventListenerITCase.java deleted file mode 100644 index a7f40a347744785b1be6cee7580c7efe9cfceddd..0000000000000000000000000000000000000000 --- a/bescheid-manager/src/test/java/de/ozgcloud/document/DocumentEventListenerITCase.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den - * Ministerpräsidenten des Landes Schleswig-Holstein - * Staatskanzlei - * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung - * - * Lizenziert unter der EUPL, Version 1.2 oder - sobald - * diese von der Europäischen Kommission genehmigt wurden - - * Folgeversionen der EUPL ("Lizenz"); - * Sie dürfen dieses Werk ausschließlich gemäß - * dieser Lizenz nutzen. - * Eine Kopie der Lizenz finden Sie hier: - * - * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 - * - * Sofern nicht durch anwendbare Rechtsvorschriften - * gefordert oder in schriftlicher Form vereinbart, wird - * die unter der Lizenz verbreitete Software "so wie sie - * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - - * ausdrücklich oder stillschweigend - verbreitet. - * Die sprachspezifischen Genehmigungen und Beschränkungen - * unter der Lizenz sind dem Lizenztext zu entnehmen. - */ -package de.ozgcloud.document; - -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; - -import java.util.Map; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.Spy; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; -import org.springframework.context.ApplicationEventPublisher; - -import de.ozgcloud.apilib.common.command.OzgCloudCommand; -import de.ozgcloud.apilib.common.command.OzgCloudCommandService; -import de.ozgcloud.apilib.common.command.grpc.CommandMapper; -import de.ozgcloud.bescheid.common.callcontext.CurrentUserService; -import de.ozgcloud.bescheid.common.callcontext.UserProfile; -import de.ozgcloud.command.Command; -import de.ozgcloud.command.CommandCreatedEventTestFactory; -import de.ozgcloud.command.CommandTestFactory; -import de.ozgcloud.common.test.ITCase; - -@SpringBootTest(classes = DocumentTestApplication.class) -@ITCase -class DocumentEventListenerITCase { - - @Spy - @Autowired - private ApplicationEventPublisher eventPublisher; - - @SpyBean - private DocumentEventListener documentEventListener; - - @MockBean - private OzgCloudCommandService ozgCloudCommandService; - @MockBean - private CommandMapper commandMapper; - @MockBean - private CurrentUserService userService; - - @Mock - private UserProfile userProfile; - - @BeforeEach - void init() { - when(userService.getUserProfile()).thenReturn(userProfile); - } - - @Nested - class TestCreateBescheidDocument { - - private static final String CREATED_RESOURCE_ID = "created-resource-id"; - - @Mock - private OzgCloudCommand executedCommand; - - @Captor - private ArgumentCaptor<BescheidDocumentCreatedEvent> documentCreatedEventCaptor; - - private Command command = CommandTestFactory.createBuilder() - .order(DocumentEventListener.CREATE_BESCHEID_DOCUMENT_FROM_FILE_ORDER) - .bodyObject(Map.of(DocumentService.FIELD_DOCUMENT_FILE, "file-id")) - .build(); - - @Test - void shouldPublishBescheidDocumentCreatedEvent() { - when(executedCommand.getCreatedResource()).thenReturn(CREATED_RESOURCE_ID); - when(ozgCloudCommandService.createAndWaitUntilDone(any())).thenReturn(executedCommand); - - eventPublisher.publishEvent(CommandCreatedEventTestFactory.withCommand(command)); - - verify(documentEventListener, timeout(60000)).publishEvent(documentCreatedEventCaptor.capture()); - assertThat(documentCreatedEventCaptor.getValue()).satisfies(event -> { - assertThat(event.getCommand()).isEqualTo(command); - assertThat(event.getCreatedResource()).isEqualTo(CREATED_RESOURCE_ID); - }); - } - } -} \ No newline at end of file diff --git a/bescheid-manager/src/test/java/de/ozgcloud/document/DocumentServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/document/DocumentServiceTest.java index 559c3bc73436f3d87fd4df9e07b12f29d3eb74ef..9ade6417382b7da3c7968fb1b994f2c568fd51eb 100644 --- a/bescheid-manager/src/test/java/de/ozgcloud/document/DocumentServiceTest.java +++ b/bescheid-manager/src/test/java/de/ozgcloud/document/DocumentServiceTest.java @@ -35,6 +35,7 @@ import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; +import org.springframework.web.server.ResponseStatusException; import de.ozgcloud.apilib.common.command.OzgCloudCommand; import de.ozgcloud.apilib.common.command.OzgCloudCommandService; @@ -42,7 +43,9 @@ import de.ozgcloud.apilib.common.command.grpc.CommandMapper; import de.ozgcloud.apilib.common.datatypes.GenericId; import de.ozgcloud.apilib.vorgang.OzgCloudVorgangId; import de.ozgcloud.bescheid.BescheidCallContextAttachingInterceptor; +import de.ozgcloud.bescheid.attacheditem.AttachedItemService; import de.ozgcloud.bescheid.attacheditem.BescheidItem; +import de.ozgcloud.bescheid.attacheditem.BescheidItemTestFactory; import de.ozgcloud.command.Command; import de.ozgcloud.command.CommandTestFactory; import de.ozgcloud.common.errorhandling.TechnicalException; @@ -60,6 +63,8 @@ class DocumentServiceTest { private OzgCloudCommandService commandService; @Mock private CommandMapper commandMapper; + @Mock + private AttachedItemService attachedItemService; private Command command = CommandTestFactory.createBuilder() .relationId(RELATION_ID) @@ -76,6 +81,14 @@ class DocumentServiceTest { @BeforeEach void init() { when(commandService.createAndWaitUntilDone(any())).thenReturn(ozgCommand); + doNothing().when(service).validateBescheidItem(any()); + } + + @Test + void shouldCallValidateBescheidItem() { + service.createBescheidDocument(command); + + verify(service).validateBescheidItem(RELATION_ID); } @Test @@ -104,6 +117,44 @@ class DocumentServiceTest { } } + @Nested + class TestValidateBescheidItem { + + @Test + void shouldCallGetBescheidItem() { + when(attachedItemService.getBescheidItem(any())).thenReturn(BescheidItemTestFactory.create()); + + validateBescheidItem(); + + verify(attachedItemService).getBescheidItem(BescheidItemTestFactory.ID); + } + + @Test + void shouldThrowExceptionWhenNoBescheidDraft() { + when(attachedItemService.getBescheidItem(any())).thenThrow(ResponseStatusException.class); + + assertThrows(ResponseStatusException.class, this::validateBescheidItem); + } + + @Test + void shouldNotThrowExceptionIfNotDraft() { + when(attachedItemService.getBescheidItem(any())).thenReturn( + BescheidItemTestFactory.createBuilder().bescheidData(Map.of(BescheidItem.FIELD_STATUS, "not-draft")).build()); + + assertThrows(TechnicalException.class, this::validateBescheidItem); + } + + @Test + void shouldValidateBescheidItem() { + when(attachedItemService.getBescheidItem(any())).thenReturn(BescheidItemTestFactory.create()); + + assertDoesNotThrow(this::validateBescheidItem); + } + void validateBescheidItem() { + service.validateBescheidItem(BescheidItemTestFactory.ID); + } + } + @Nested class TestBuildCreateDocumentOzgCommand { @@ -135,7 +186,7 @@ class DocumentServiceTest { void shouldCallRelationIdMapper() { service.buildCreateDocumentOzgCommand(command); - verify(commandMapper).mapRelationId(RELATION_ID); + verify(commandMapper).mapRelationId(CommandTestFactory.VORGANG_ID); } @Test diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/document/DocumentEventListenerITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/document/DocumentEventListenerITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..bdbcf04f6d8bb24fdfb319fdd45a57c0bcbf9835 --- /dev/null +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/document/DocumentEventListenerITCase.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.document; + +import static org.assertj.core.api.Assertions.*; +import static org.awaitility.Awaitility.*; +import static org.mockito.Mockito.*; + +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.test.annotation.DirtiesContext; + +import de.ozgcloud.apilib.common.command.grpc.CommandMapper; +import de.ozgcloud.bescheid.common.callcontext.CallContextUser; +import de.ozgcloud.bescheid.common.callcontext.CurrentUserService; +import de.ozgcloud.command.Command; +import de.ozgcloud.command.CommandCreatedEvent; +import de.ozgcloud.command.CommandFailedEvent; +import de.ozgcloud.common.test.DataITCase; +import de.ozgcloud.vorgang.VorgangManagerServerApplication; +import de.ozgcloud.vorgang.attached_item.VorgangAttachedItem; +import de.ozgcloud.vorgang.attached_item.VorgangAttachedItemTestFactory; +import de.ozgcloud.vorgang.command.CommandTestFactory; + +@SpringBootTest(classes = VorgangManagerServerApplication.class, properties = { + "grpc.server.inProcessName=test", + "grpc.server.port=-1", + "grpc.client.ozgcloud-command-manager.address=in-process:test", + "grpc.client.vorgang-manager.address=in-process:test" +}) +@DataITCase +@DirtiesContext +class DocumentEventListenerITCase { + + private static final String FILE_ID = "file-id"; + + @Autowired + private ApplicationEventPublisher eventPublisher; + @SpyBean + private DocumentEventListener eventListener; + @Autowired + private CommandMapper mapper; + @Autowired + private MongoOperations mongoOperations; + + @MockBean + private CurrentUserService currentUserService; + @Mock + private CallContextUser callContextUser; + + @Captor + private ArgumentCaptor<BescheidDocumentCreatedEvent> bescheidDocumentCreatedEventCaptor; + @Captor + private ArgumentCaptor<CommandFailedEvent> commandFailedEventCaptor; + + @BeforeEach + void init() { + mongoOperations.dropCollection(VorgangAttachedItem.COLLECTION_NAME); + when(currentUserService.getUser()).thenReturn(callContextUser); + } + + @Test + void shouldCreateDocument() { + var bescheidItem = mongoOperations.save(createBescheidItem("DRAFT")); + var command = createCommand(bescheidItem.getId()); + + eventPublisher.publishEvent(new CommandCreatedEvent(command)); + + assertThat(loadBescheidDocument()).containsEntry(DocumentService.FIELD_DOCUMENT_FILE, FILE_ID); + } + + @Test + void shouldFailWhenNoBescheidFound() { + var command = createCommand("non-existing-id"); + + eventPublisher.publishEvent(new CommandCreatedEvent(command)); + + await().atMost(60, TimeUnit.SECONDS).untilAsserted(() -> { + verify(eventListener, timeout(5000)).publishEvent(commandFailedEventCaptor.capture()); + assertThat(commandFailedEventCaptor.getValue().getSource()).isEqualTo(command.getId()); + }); + } + + @Test + void shouldFailWhenNotDraft() { + var bescheidItem = mongoOperations.save(createBescheidItem("BESCHEID")); + var command = createCommand(bescheidItem.getId()); + + eventPublisher.publishEvent(new CommandCreatedEvent(command)); + + await().atMost(60, TimeUnit.SECONDS).untilAsserted(() -> { + verify(eventListener, timeout(5000)).publishEvent(commandFailedEventCaptor.capture()); + assertThat(commandFailedEventCaptor.getValue().getSource()).isEqualTo(command.getId()); + }); + } + + private VorgangAttachedItem createBescheidItem(String status) { + return VorgangAttachedItemTestFactory.createBuilder().id(null).version(0) + .item(Map.of("status", status)) + .build(); + } + + private Map<String, Object> loadBescheidDocument() { + verify(eventListener, timeout(5000)).publishEvent(bescheidDocumentCreatedEventCaptor.capture()); + var bescheidDocumentId = bescheidDocumentCreatedEventCaptor.getValue().getCreatedResource(); + return mongoOperations.findById(bescheidDocumentId, VorgangAttachedItem.class).getItem(); + } + + private Command createCommand(String relationId) { + return CommandTestFactory.createBuilder() + .relationId(relationId) + .order(DocumentEventListener.CREATE_BESCHEID_DOCUMENT_FROM_FILE_ORDER) + .bodyObject(Map.of(DocumentService.FIELD_DOCUMENT_FILE, FILE_ID)) + .build(); + } +} \ No newline at end of file