diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/collaboration/CollaborationVorgangProcessor.java b/alfa-service/src/main/java/de/ozgcloud/alfa/collaboration/CollaborationVorgangProcessor.java index 2f75114f05193871bb4c78621f119d912075065f..919b64ed9a0281c46620de22ff49c1c1761de22d 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/collaboration/CollaborationVorgangProcessor.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/collaboration/CollaborationVorgangProcessor.java @@ -25,7 +25,6 @@ package de.ozgcloud.alfa.collaboration; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; -import java.util.List; import java.util.Objects; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -47,7 +46,6 @@ import lombok.RequiredArgsConstructor; class CollaborationVorgangProcessor implements RepresentationModelProcessor<EntityModel<VorgangWithEingang>> { static final LinkRelation REL_COLLABORATIONS = LinkRelation.of("collaborations"); - static final LinkRelation REL_SEARCH_ORGANISATIONS_EINHEIT = LinkRelation.of("searchOrganisationsEinheit"); static final LinkRelation REL_SEARCH_FACHSTELLE = LinkRelation.of("searchFachstelle"); private final CurrentUserService currentUserService; @@ -60,17 +58,11 @@ class CollaborationVorgangProcessor implements RepresentationModelProcessor<Enti if (Objects.isNull(vorgang) || !currentUserService.hasRole(UserRole.VERWALTUNG_USER)) { return model; } - model.addAllIf(!collaborationService.hasCollaboration(vorgang.getId()), - () -> List.of(buildSearchOrganisationsEinheitLink(), buildSearchFachstelleLink())) + model.addIf(!collaborationService.hasCollaboration(vorgang.getId()), this::buildSearchFachstelleLink) .add(linkTo(methodOn(CollaborationByVorgangController.class).getAllByVorgangId(vorgang.getId())).withRel(REL_COLLABORATIONS)); return model; } - private Link buildSearchOrganisationsEinheitLink() { - return linkTo(methodOn(OrganisationsEinheitController.class).search(null)).withRel( - REL_SEARCH_ORGANISATIONS_EINHEIT); - } - private Link buildSearchFachstelleLink() { return linkTo(methodOn(FachstelleController.class).search(null)).withRel(REL_SEARCH_FACHSTELLE); } diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/collaboration/OrganisationsEinheitVorgangWithEingangProcessor.java b/alfa-service/src/main/java/de/ozgcloud/alfa/collaboration/OrganisationsEinheitVorgangWithEingangProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..301f5947d030298e8ddb941de5507aef2da4085f --- /dev/null +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/collaboration/OrganisationsEinheitVorgangWithEingangProcessor.java @@ -0,0 +1,57 @@ +package de.ozgcloud.alfa.collaboration; + +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; + +import java.util.Optional; + +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.Link; +import org.springframework.hateoas.LinkRelation; +import org.springframework.hateoas.server.RepresentationModelProcessor; +import org.springframework.stereotype.Component; + +import de.ozgcloud.alfa.common.FeatureToggleProperties; +import de.ozgcloud.alfa.common.user.CurrentUserService; +import de.ozgcloud.alfa.common.user.UserRole; +import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus; +import de.ozgcloud.alfa.vorgang.VorgangWithEingang; +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +class OrganisationsEinheitVorgangWithEingangProcessor implements RepresentationModelProcessor<EntityModel<VorgangWithEingang>> { + + static final LinkRelation REL_SEARCH_ORGANISATIONS_EINHEIT = LinkRelation.of("searchOrganisationsEinheit"); + + private final FeatureToggleProperties featureToggleProperties; + private final CurrentUserService userService; + + @Override + public EntityModel<VorgangWithEingang> process(EntityModel<VorgangWithEingang> model) { + Optional.ofNullable(model.getContent()) + .ifPresent(vorgang -> model.addIf(this.isSearchNeeded(vorgang), + this::buildSearchOrganisationsEinheitLink)); + return model; + } + + boolean isSearchNeeded(VorgangWithEingang vorgang) { + return this.isForwardable(vorgang) || this.isCollaborationCreateable(); + } + + boolean isForwardable(VorgangWithEingang vorgang) { + return featureToggleProperties.isForwardByOzgCloudEnabled() && isStatusNeu(vorgang); + } + + boolean isCollaborationCreateable() { + return featureToggleProperties.isCollaborationEnabled() && this.userService.hasRole(UserRole.VERWALTUNG_USER); + } + + private boolean isStatusNeu(VorgangWithEingang vorgang) { + return vorgang.getStatus() == VorgangStatus.NEU; + } + + private Link buildSearchOrganisationsEinheitLink() { + return linkTo(methodOn(OrganisationsEinheitController.class).search(null)).withRel( + REL_SEARCH_ORGANISATIONS_EINHEIT); + } +} \ No newline at end of file diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/collaboration/CollaborationVorgangProcessorTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/collaboration/CollaborationVorgangProcessorTest.java index 97079a883a639e1844028ab2356403866462f7f5..9f245c3c6a9c4b31c29e3459c148862d467bc1a7 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/collaboration/CollaborationVorgangProcessorTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/collaboration/CollaborationVorgangProcessorTest.java @@ -103,20 +103,6 @@ class CollaborationVorgangProcessorTest { when(collaborationService.hasCollaboration(VorgangHeaderTestFactory.ID)).thenReturn(true); } - @Test - void shouldHaveOneLink() { - var model = callProcessor(); - - assertThat(model.getLinks()).hasSize(1); - } - - @Test - void shouldNotAddSearchOrganisationsEinheitLink() { - var model = callProcessor(); - - assertThat(model.getLink(CollaborationVorgangProcessor.REL_SEARCH_ORGANISATIONS_EINHEIT)).isEmpty(); - } - @Test void shouldAddCollaborationsLink() { var model = callProcessor(); @@ -135,26 +121,6 @@ class CollaborationVorgangProcessorTest { when(collaborationService.hasCollaboration(VorgangHeaderTestFactory.ID)).thenReturn(false); } - @Test - void shouldHaveThreeLinks() { - var model = callProcessor(); - - assertThat(model.getLinks()).hasSize(3); - } - - @Test - void shouldAddSearchOrganisationsEinheitLink() { - var expectedHref = UriComponentsBuilder.fromUriString(OrganisationsEinheitController.PATH) - .queryParam(OrganisationsEinheitController.SEARCH_BY_PARAM, "{" + OrganisationsEinheitController.SEARCH_BY_PARAM + "}") - .build().toString(); - - var model = callProcessor(); - - assertThat(model.getLink(CollaborationVorgangProcessor.REL_SEARCH_ORGANISATIONS_EINHEIT)).get() - .extracting(Link::getHref) - .isEqualTo(expectedHref); - } - @Test void shouldAddSearchFachstelleLink() { var expectedHref = UriComponentsBuilder.fromUriString(FachstelleController.PATH) diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/collaboration/OrganisationsEinheitVorgangWithEingangProcessorTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/collaboration/OrganisationsEinheitVorgangWithEingangProcessorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b3832f8cbb24f9b5bc57d5b5ca0b72bc6d78dae8 --- /dev/null +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/collaboration/OrganisationsEinheitVorgangWithEingangProcessorTest.java @@ -0,0 +1,387 @@ +package de.ozgcloud.alfa.collaboration; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.EnumSource.Mode; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.Link; +import org.springframework.web.util.UriComponentsBuilder; + +import de.ozgcloud.alfa.common.FeatureToggleProperties; +import de.ozgcloud.alfa.common.user.CurrentUserService; +import de.ozgcloud.alfa.common.user.UserRole; +import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus; +import de.ozgcloud.alfa.vorgang.VorgangWithEingang; +import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory; + +public class OrganisationsEinheitVorgangWithEingangProcessorTest { + + @InjectMocks + @Spy + private OrganisationsEinheitVorgangWithEingangProcessor processor; + + @Mock + private CurrentUserService userService; + @Mock + private FeatureToggleProperties featureToggleProperties; + + @DisplayName("Process") + @Nested + class TestProcess { + + private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create(); + + private final EntityModel<VorgangWithEingang> model = EntityModel.of(vorgang); + + @SuppressWarnings("unchecked") + @Test + void shouldReturnSameModelOnNullContent() { + var entityModel = mock(EntityModel.class); + when(entityModel.getContent()).thenReturn(null); + + var processedModel = processor.process(entityModel); + + assertThat(processedModel).isSameAs(entityModel); + } + + @DisplayName("entity model links") + @Nested + class TestEntityModelLinks { + + @Test + void shouldContainsSearchLinkIfNeeded() { + doReturn(true).when(processor).isSearchNeeded(any()); + + var processedModel = processor.process(model); + + var expectedHref = UriComponentsBuilder.fromUriString(OrganisationsEinheitController.PATH).build().toString(); + + assertThat(processedModel.getLink(OrganisationsEinheitVorgangWithEingangProcessor.REL_SEARCH_ORGANISATIONS_EINHEIT)).get() + .extracting(Link::getHref) + .isEqualTo(OrganisationsEinheitController.PATH + "?searchBy={searchBy}"); + } + } + } + + @DisplayName("is search needed") + @Nested + class TestIsSearchNeeded { + + private VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create(); + + @Test + void shouldReturnTrueIfForwardable() { + doReturn(true).when(processor).isForwardable(any()); + + var isSearchNeeded = processor.isSearchNeeded(vorgang); + + assertThat(isSearchNeeded).isTrue(); + } + + @Test + void shouldReturnFalseIfCollaborationCreateable() { + doReturn(true).when(processor).isCollaborationCreateable(); + + var isSearchNeeded = processor.isSearchNeeded(vorgang); + + assertThat(isSearchNeeded).isTrue(); + } + } + + @DisplayName("is forwardable") + @Nested + class TestIsForwardable { + + @DisplayName("on feature disabled") + @Nested + class TestOnFeatureDisabled { + + @BeforeEach + void mockFeatureToggle() { + when(featureToggleProperties.isForwardByOzgCloudEnabled()).thenReturn(false); + } + + @ParameterizedTest + @EnumSource + void shouldReturnFalse(VorgangStatus status) { + var vorgang = VorgangWithEingangTestFactory.createBuilder().status(status).build(); + + var forwardableByOzgCloud = processor.isForwardable(vorgang); + + assertThat(forwardableByOzgCloud).isFalse(); + } + } + + @DisplayName("on feature enabled") + @Nested + class TestOnFeatureEnabled { + + @BeforeEach + void mockFeatureToggle() { + when(featureToggleProperties.isForwardByOzgCloudEnabled()).thenReturn(true); + } + + @ParameterizedTest(name = "{0}") + @EnumSource(mode = Mode.EXCLUDE, names = { "NEU" }) + void shouldReturnFalseOnVorgangStatus(VorgangStatus status) { + var forwardableByOzgCloud = processor.isForwardable(VorgangWithEingangTestFactory.createBuilder().status(status).build()); + + assertThat(forwardableByOzgCloud).isFalse(); + } + + @Test + void shouldReturnTrueOnVorgangStatusNeu() { + var forwardable = processor.isForwardable(VorgangWithEingangTestFactory.createBuilder().status(VorgangStatus.NEU).build()); + + assertThat(forwardable).isTrue(); + } + } + } + + @DisplayName("is collaboration createable") + @Nested + class TestIsCollaborationCreateable { + + @DisplayName("on feature disabled") + @Nested + class TestOnFeatureDisabled { + + @BeforeEach + void mockFeatureToggle() { + when(featureToggleProperties.isCollaborationEnabled()).thenReturn(false); + } + + void shouldReturnFalse() { + var isCollaborationEnabled = processor.isCollaborationCreateable(); + + assertThat(isCollaborationEnabled).isFalse(); + } + } + + @DisplayName("on feature enabled") + @Nested + class TestOnFeatureEnabled { + + @BeforeEach + void mockFeatureToggle() { + when(featureToggleProperties.isCollaborationEnabled()).thenReturn(true); + } + + @Test + void shouldVerifyRole() { + processor.isCollaborationCreateable(); + + verify(userService).hasRole(UserRole.VERWALTUNG_USER); + } + + @Test + void shouldReturnFalseMissingRole() { + when(userService.hasRole(any())).thenReturn(false); + + var isCollaborationEnabled = processor.isCollaborationCreateable(); + + assertThat(isCollaborationEnabled).isFalse(); + } + + @Test + void shouldReturnTrueOnAssignedRole() { + when(userService.hasRole(any())).thenReturn(true); + + var isCollaborationEnabled = processor.isCollaborationCreateable(); + + assertThat(isCollaborationEnabled).isTrue(); + } + } + } + +// @Nested +// class TestForwardByOzgCloudLink { +// +// @Test +// void shouldCallIsForwardableByOzgCloud() { +// doReturn(false).when(processor).isForwardableByOzgCloud(any()); +// +// processor.process(EntityModel.of(vorgang)); +// +// verify(processor).isForwardableByOzgCloud(vorgang); +// } +// +// @Nested +// class TestOnIsNotForwardableByOzgCloud { +// +// @BeforeEach +// void givenIsNotForwardableByOzgCloud() { +// doReturn(false).when(processor).isForwardableByOzgCloud(any()); +// } +// +// @Test +// void shouldNotAddLink() { +// var model = processor.process(EntityModel.of(vorgang)); +// +// assertThat(model.getLink(ForwardingVorgangWithEingangProcessor.REL_FORWARD_BY_OZGCLOUD)).isEmpty(); +// } +// } +// +// @Nested +// class TestOnIsForwardableByOzgCloud { +// +// @BeforeEach +// void givenIsNotForwardableByOzgCloud() { +// doReturn(true).when(processor).isForwardableByOzgCloud(any()); +// } +// +// @Test +// void shouldAddForwardByOzgCloudLink() { +// var expectedHref = UriComponentsBuilder.fromUriString(ForwardByVorgangCommandController.PATH) +// .buildAndExpand(VorgangHeaderTestFactory.ID, VorgangHeaderTestFactory.VERSION).toString(); +// +// var model = processor.process(EntityModel.of(vorgang)); +// +// assertThat(model.getLink(ForwardingVorgangWithEingangProcessor.REL_FORWARD_BY_OZGCLOUD)).get() +// .extracting(Link::getHref) +// .isEqualTo(expectedHref); +// } +// } +// } +// +// @Nested +// class TestForwardByEmailLink { +// +// @Test +// void shouldCallIsForwardableByEmail() { +// doReturn(false).when(processor).isForwardableByEmail(); +// +// processor.process(EntityModel.of(vorgang)); +// +// verify(processor).isForwardableByEmail(); +// } +// +// @Nested +// class TestOnIsNotForwardableByEmail { +// +// @BeforeEach +// void givenIsNotForwardableByEmail() { +// doReturn(false).when(processor).isForwardableByEmail(); +// } +// +// @Test +// void shouldNotAddLink() { +// var model = processor.process(EntityModel.of(vorgang)); +// +// assertThat(model.getLink(ForwardingVorgangWithEingangProcessor.REL_FORWARD_BY_EMAIL)).isEmpty(); +// } +// } +// +// @Nested +// class TestOnIsForwardableByEmail { +// +// @BeforeEach +// void givenIsForwardableByEmail() { +// doReturn(true).when(processor).isForwardableByEmail(); +// } +// +// @Test +// void shouldAddLink() { +// var expectedHref = UriComponentsBuilder.fromUriString(ForwardingController.LIST_PATH) +// .queryParam(ForwardingController.PARAM_VORGANG_ID, VorgangHeaderTestFactory.ID).build().toString(); +// +// var model = processor.process(EntityModel.of(vorgang)); +// +// assertThat(model.getLink(ForwardingVorgangWithEingangProcessor.REL_FORWARD_BY_EMAIL)).get() +// .extracting(Link::getHref) +// .isEqualTo(expectedHref); +// } +// } +// } +// } +// +// @Nested +// class TestIsForwardableByOzgCloud { +// +// @Nested +// class TestOnFeatureDisabled { +// +// @BeforeEach +// void givenFeatureDisabled() { +// when(featureToggleProperties.isForwardByOzgCloudEnabled()).thenReturn(false); +// } +// +// @ParameterizedTest +// @EnumSource +// void shouldReturnFalse(VorgangStatus status) { +// var vorgang = VorgangWithEingangTestFactory.createBuilder().status(status).build(); +// +// var forwardableByOzgCloud = processor.isForwardableByOzgCloud(vorgang); +// +// assertThat(forwardableByOzgCloud).isFalse(); +// } +// } +// +// @Nested +// class TestOnFeatureEnabled { +// +// @BeforeEach +// void givenFeatureEnabled() { +// when(featureToggleProperties.isForwardByOzgCloudEnabled()).thenReturn(true); +// } +// +// @Nested +// class TestOnVorgangNotNeu { +// @ParameterizedTest +// @EnumSource(mode = Mode.EXCLUDE, names = { "NEU" }) +// void shouldReturnFalseOnVorgangStatusNotNeu(VorgangStatus status) { +// var vorgang = VorgangWithEingangTestFactory.createBuilder().status(status).build(); +// +// var forwardableByOzgCloud = processor.isForwardableByOzgCloud(vorgang); +// +// assertThat(forwardableByOzgCloud).isFalse(); +// } +// } +// +// @Nested +// class TestOnVorgangIsNeu { +// +// private final VorgangWithEingang newVorgang = VorgangWithEingangTestFactory.createBuilder().status(VorgangStatus.NEU).build(); +// +// @Test +// void shouldReturnTrue() { +// var forwardableByOzgCloud = processor.isForwardableByOzgCloud(newVorgang); +// +// assertThat(forwardableByOzgCloud).isTrue(); +// } +// } +// } +// } +// +// @Nested +// class TestIsForwardableByEmail { +// +// @Test +// void shouldCallUserServiceForCurrentRole() { +// processor.isForwardableByEmail(); +// +// verify(userService).hasRole(UserRole.EINHEITLICHER_ANSPRECHPARTNER); +// } +// +// @ParameterizedTest +// @ValueSource(booleans = { true, false }) +// void shouldReturnIsEinheitlicherAnsprechpartner(boolean isEinheitlicherAnsprechpartner) { +// when(userService.hasRole(any())).thenReturn(isEinheitlicherAnsprechpartner); +// +// var isForwardableByEmail = processor.isForwardableByEmail(); +// +// assertThat(isForwardableByEmail).isEqualTo(isEinheitlicherAnsprechpartner); +// } +// } +}