diff --git a/alfa-client/libs/design-system/src/index.ts b/alfa-client/libs/design-system/src/index.ts index c4553cf30882baa5265e0189b4ac320dafee551b..9f7b60a883c3ad40fc3bb29b3bd56d8a058d9197 100644 --- a/alfa-client/libs/design-system/src/index.ts +++ b/alfa-client/libs/design-system/src/index.ts @@ -13,7 +13,7 @@ export * from './lib/icons/attachment-icon/attachment-icon.component'; export * from './lib/icons/bescheid-generate-icon/bescheid-generate-icon.component'; export * from './lib/icons/bescheid-upload-icon/bescheid-upload-icon.component'; export * from './lib/icons/close-icon/close-icon.component'; -export * from './lib/icons/exclamate-icon/exclamate-icon.component'; +export * from './lib/icons/exclamation-icon/exclamation-icon.component'; export * from './lib/icons/file-icon/file-icon.component'; export * from './lib/icons/save-icon/save-icon.component'; export * from './lib/icons/send-icon/send-icon.component'; diff --git a/alfa-client/libs/design-system/src/lib/form/error-message/error-message.component.spec.ts b/alfa-client/libs/design-system/src/lib/form/error-message/error-message.component.spec.ts index 2ca00ff49bcf029d32498a692af9368217ac19f2..b89607a810b4bc7bd67c136edce54c4a65b28cb4 100644 --- a/alfa-client/libs/design-system/src/lib/form/error-message/error-message.component.spec.ts +++ b/alfa-client/libs/design-system/src/lib/form/error-message/error-message.component.spec.ts @@ -1,5 +1,5 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { ExclamateIconComponent } from '../../icons/exclamate-icon/exclamate-icon.component'; +import { ExclamationIconComponent } from '../../icons/exclamation-icon/exclamation-icon.component'; import { ErrorMessageComponent } from './error-message.component'; describe('ErrorMessageComponent', () => { @@ -8,7 +8,7 @@ describe('ErrorMessageComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [ErrorMessageComponent, ExclamateIconComponent], + imports: [ErrorMessageComponent, ExclamationIconComponent], }).compileComponents(); fixture = TestBed.createComponent(ErrorMessageComponent); diff --git a/alfa-client/libs/design-system/src/lib/form/error-message/error-message.component.ts b/alfa-client/libs/design-system/src/lib/form/error-message/error-message.component.ts index 8fc3456345c220e957ee99aaf370dd2cb21b172f..45c7dc662666e8456d1ba736da8a094d8d0538c0 100644 --- a/alfa-client/libs/design-system/src/lib/form/error-message/error-message.component.ts +++ b/alfa-client/libs/design-system/src/lib/form/error-message/error-message.component.ts @@ -1,13 +1,13 @@ import { CommonModule } from '@angular/common'; import { Component, Input } from '@angular/core'; -import { ExclamateIconComponent } from '../../icons/exclamate-icon/exclamate-icon.component'; +import { ExclamationIconComponent } from '../../icons/exclamation-icon/exclamation-icon.component'; @Component({ selector: 'ods-error-message', standalone: true, - imports: [CommonModule, ExclamateIconComponent], + imports: [CommonModule, ExclamationIconComponent], styles: [':host {@apply flex text-error my-2 text-sm items-center font-medium}'], - template: `<ods-exclamate-icon class="mr-1"></ods-exclamate-icon> + template: `<ods-exclamation-icon class="mr-1"></ods-exclamation-icon> <div class="flex-grow break-all"> {{ text }} <br *ngIf="subText" aria-hidden="true" /> diff --git a/alfa-client/libs/design-system/src/lib/icons/exclamate-icon/exclamate-icon.component.spec.ts b/alfa-client/libs/design-system/src/lib/icons/exclamate-icon/exclamate-icon.component.spec.ts deleted file mode 100644 index 26417da63df4fe5d7d59b0ffcbf3e5a712a17410..0000000000000000000000000000000000000000 --- a/alfa-client/libs/design-system/src/lib/icons/exclamate-icon/exclamate-icon.component.spec.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { ExclamateIconComponent } from './exclamate-icon.component'; - -describe('ExclamateIconComponent', () => { - let component: ExclamateIconComponent; - let fixture: ComponentFixture<ExclamateIconComponent>; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ExclamateIconComponent], - }).compileComponents(); - - fixture = TestBed.createComponent(ExclamateIconComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/alfa-client/libs/design-system/src/lib/icons/exclamation-icon/exclamation-icon.component.spec.ts b/alfa-client/libs/design-system/src/lib/icons/exclamation-icon/exclamation-icon.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..7e580ce2831f1785a20905def5533243991722d0 --- /dev/null +++ b/alfa-client/libs/design-system/src/lib/icons/exclamation-icon/exclamation-icon.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ExclamationIconComponent } from './exclamation-icon.component'; + +describe('ExclamationIconComponent', () => { + let component: ExclamationIconComponent; + let fixture: ComponentFixture<ExclamationIconComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ExclamationIconComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(ExclamationIconComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/design-system/src/lib/icons/exclamate-icon/exclamate-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/exclamation-icon/exclamation-icon.component.ts similarity index 96% rename from alfa-client/libs/design-system/src/lib/icons/exclamate-icon/exclamate-icon.component.ts rename to alfa-client/libs/design-system/src/lib/icons/exclamation-icon/exclamation-icon.component.ts index dec6b285ff6324df13d45bd1cfca115843b524af..9dda95ea08ca28bee431be67e9400e6ccaa6f0ec 100644 --- a/alfa-client/libs/design-system/src/lib/icons/exclamate-icon/exclamate-icon.component.ts +++ b/alfa-client/libs/design-system/src/lib/icons/exclamation-icon/exclamation-icon.component.ts @@ -5,7 +5,7 @@ import { twMerge } from 'tailwind-merge'; import { IconVariants, iconVariants } from '../IconClasses'; @Component({ - selector: 'ods-exclamate-icon', + selector: 'ods-exclamation-icon', standalone: true, imports: [NgClass], template: `<svg @@ -20,7 +20,7 @@ import { IconVariants, iconVariants } from '../IconClasses'; /> </svg>`, }) -export class ExclamateIconComponent { +export class ExclamationIconComponent { @Input() size: IconVariants['size'] = 'medium'; @Input() class: string = undefined; diff --git a/alfa-client/libs/design-system/src/lib/icons/exclamate-icon/exclamate-icon.stories.ts b/alfa-client/libs/design-system/src/lib/icons/exclamation-icon/exclamation-icon.stories.ts similarity index 65% rename from alfa-client/libs/design-system/src/lib/icons/exclamate-icon/exclamate-icon.stories.ts rename to alfa-client/libs/design-system/src/lib/icons/exclamation-icon/exclamation-icon.stories.ts index 502a70571ec5c26bcfbc9f4121a1b0dfbd761cfd..7fbca7f8bf95db9d3d40528470aa67186235f2cf 100644 --- a/alfa-client/libs/design-system/src/lib/icons/exclamate-icon/exclamate-icon.stories.ts +++ b/alfa-client/libs/design-system/src/lib/icons/exclamation-icon/exclamation-icon.stories.ts @@ -1,16 +1,16 @@ import type { Meta, StoryObj } from '@storybook/angular'; -import { ExclamateIconComponent } from './exclamate-icon.component'; +import { ExclamationIconComponent } from './exclamation-icon.component'; -const meta: Meta<ExclamateIconComponent> = { - title: 'Icons/Exclamate icon', - component: ExclamateIconComponent, +const meta: Meta<ExclamationIconComponent> = { + title: 'Icons/Exclamation icon', + component: ExclamationIconComponent, excludeStories: /.*Data$/, tags: ['autodocs'], }; export default meta; -type Story = StoryObj<ExclamateIconComponent>; +type Story = StoryObj<ExclamationIconComponent>; export const Default: Story = { args: { size: 'medium' }, diff --git a/alfa-client/libs/test-utils/src/lib/helper.ts b/alfa-client/libs/test-utils/src/lib/helper.ts index a4fcbd913f24c54d8f195ebe96edf4a73811a488..ed3e6fa137f9399a1ce428b627c13b47a70947f9 100644 --- a/alfa-client/libs/test-utils/src/lib/helper.ts +++ b/alfa-client/libs/test-utils/src/lib/helper.ts @@ -74,6 +74,19 @@ function getDebugElementFromFixtureByDirective( return fixture.debugElement.query(By.directive(query)); } +function getAllDebugElementsFromFixtureByDirective( + fixture: ComponentFixture<any>, + query: Type<any>, +): DebugElement[] { + return fixture.debugElement.queryAll(By.directive(query)); +} + export function getMockComponent<T>(fixture: ComponentFixture<unknown>, component: Type<T>): T { return <T>getDebugElementFromFixtureByDirective(fixture, component).componentInstance; } + +export function getMockComponents<T>(fixture: ComponentFixture<unknown>, component: Type<T>): T[] { + return getAllDebugElementsFromFixtureByDirective(fixture, component).map( + (debugElement) => <T>debugElement.componentInstance, + ); +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.html index 6ca2dbaa357252cc367ef1109f7a506ecc9c278e..f85e710ee281b6db31597be88ad3a669455cbe14 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.html @@ -9,7 +9,6 @@ </button> <ozgcloud-menu #moreMenu data-test-id="more-menu"> <ozgcloud-menu-item - *ngIf="vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.EXPORT" data-test-id="vorgang-exportieren-button" headline="Vorgang exportieren" text="Alle Informationen und Anhänge des Vorgangs zur Archivierung im DMS." diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.spec.ts index ccc2742029338f17a3ce3d1aa5a67535dde60af3..7b41960423afe4a55ed7f91b44d58adbf000fa89 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.spec.ts @@ -2,6 +2,7 @@ import { getElementFromDomRoot, getElementFromFixture, getMockComponent, + getMockComponents, } from '@alfa-client/test-utils'; import { MenuItemComponent, OzgcloudIconComponent, UiModule } from '@alfa-client/ui'; import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; @@ -122,7 +123,7 @@ describe('VorgangDetailMoreMenuComponent', () => { fixture.detectChanges(); }); - it('should be visible if link exists', () => { + it('should be visible', () => { component.vorgangWithEingang = vorgangWithEingang; fixture.detectChanges(); getElementFromFixture(fixture, moreMenuButton).click(); @@ -132,16 +133,6 @@ describe('VorgangDetailMoreMenuComponent', () => { expect(element).toBeInTheDocument(); }); - it('should NOT be visible if link is missing', () => { - component.vorgangWithEingang = createVorgangWithEingangResource(); - fixture.detectChanges(); - getElementFromFixture(fixture, moreMenuButton).click(); - - const element = getElementFromDomRoot(fixture, exportMenuItem); - - expect(element).not.toBeInTheDocument(); - }); - describe('input property', () => { beforeEach(() => { component.vorgangWithEingang = vorgangWithEingang; @@ -236,7 +227,7 @@ describe('VorgangDetailMoreMenuComponent', () => { it('should contains headline', () => { getElementFromFixture(fixture, moreMenuButton).click(); - const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); + const menuItem: MenuItemComponent = getMockComponents(fixture, MenuItemComponent)[1]; expect(menuItem.headline).toBe('Vorgang automatisiert vorprüfen'); }); @@ -244,7 +235,7 @@ describe('VorgangDetailMoreMenuComponent', () => { it('should contains text', () => { getElementFromFixture(fixture, moreMenuButton).click(); - const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); + const menuItem: MenuItemComponent = getMockComponents(fixture, MenuItemComponent)[1]; expect(menuItem.text).toBe( 'Eine Vorprüfung wird durchgeführt. Das Ergebnis wird als Kommentar hinzugefügt.', @@ -254,7 +245,7 @@ describe('VorgangDetailMoreMenuComponent', () => { it('should contains icon', () => { getElementFromFixture(fixture, moreMenuButton).click(); - const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); + const menuItem: MenuItemComponent = getMockComponents(fixture, MenuItemComponent)[1]; expect(menuItem.icon).toBe('vorgang_vorpruefen'); }); @@ -262,7 +253,7 @@ describe('VorgangDetailMoreMenuComponent', () => { it('should contains iconSizeBig', () => { getElementFromFixture(fixture, moreMenuButton).click(); - const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); + const menuItem: MenuItemComponent = getMockComponents(fixture, MenuItemComponent)[1]; expect(menuItem.iconSizeBig).toBeTruthy(); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.html index 8af626e25c56a8500686ece7d085e7bee3a1f6f3..4fbe39f39937a006977709e805d4d05ea4d1c534 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.html @@ -1,8 +1,17 @@ -<ozgcloud-button-with-spinner - dataTestId="export-vorgang" - [showSpinner]="(exportStateResource$ | async)?.loading" - (clickEmitter)="export()" - text="Herunterladen" - icon="save_alt" -> -</ozgcloud-button-with-spinner> +<ng-container> + <ozgcloud-button-with-spinner + *ngIf="canExport" + dataTestId="export-vorgang" + [showSpinner]="(exportStateResource$ | async)?.loading" + (clickEmitter)="export()" + text="Herunterladen" + icon="save_alt" + /> + <div *ngIf="!canExport" class="flex gap-2 items-start" data-test-id="cannot-export-vorgang"> + <ods-exclamation-icon /> + <div> + <p class="text-error font-medium text-sm">Vorgang exportieren nicht möglich.</p> + <p class="text-sm">Die xdomea-Datei kann nur im <strong class="font-medium">Status Abgeschlossen</strong> heruntergeladen werden.</p> + </div> + </div> +</ng-container> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.spec.ts index 23b7002028757884d9700ccc7eca370207b1427a..04d921568b9e3c72e0ad109f238e1c1edca3ba80 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.spec.ts @@ -1,8 +1,11 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; import { StateResource, createStateResource } from '@alfa-client/tech-shared'; -import { dispatchEventFromFixture, mock } from '@alfa-client/test-utils'; +import { getElementFromFixture, mock } from '@alfa-client/test-utils'; import { OzgcloudButtonWithSpinnerComponent } from '@alfa-client/ui'; -import { VorgangService } from '@alfa-client/vorgang-shared'; +import { VorgangService, VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ExclamationIconComponent } from '@ods/system'; +import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; +import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; import { MockComponent } from 'ng-mocks'; import { of } from 'rxjs'; import { VorgangExportContainerComponent } from './vorgang-export-container.component'; @@ -15,12 +18,14 @@ describe('VorgangExportContainerComponent', () => { const vorgangService = mock(VorgangService); const buttonWithSpinner: string = '[dataTestId="export-vorgang"]'; + const cannotExportMessageDataTestId: string = getDataTestIdOf('cannot-export-vorgang'); beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [ VorgangExportContainerComponent, MockComponent(OzgcloudButtonWithSpinnerComponent), + MockComponent(ExclamationIconComponent), ], providers: [ { @@ -60,9 +65,49 @@ describe('VorgangExportContainerComponent', () => { describe('export', () => { it('should call vorgangService.export', () => { - dispatchEventFromFixture(fixture, buttonWithSpinner, 'clickEmitter'); + component.export(); expect(vorgangService.export).toHaveBeenCalled(); }); }); + + describe('set vorgang with eingang property', () => { + it('should set canExport to true', () => { + const vorgangResourceWithExportLink = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.EXPORT, + ]); + + component.vorgangWithEingang = vorgangResourceWithExportLink; + + expect(component.canExport).toBeTruthy(); + }); + + it('should set canExport to false', () => { + const vorgangResource = createVorgangWithEingangResource(); + + component.vorgangWithEingang = vorgangResource; + + expect(component.canExport).toBeFalsy(); + }); + }); + + describe('show export button or message', () => { + it('should show button, if canExport is true', () => { + component.canExport = true; + fixture.detectChanges(); + + const element = getElementFromFixture(fixture, buttonWithSpinner); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should show message, if canExport is false', () => { + component.canExport = false; + fixture.detectChanges(); + + const element = getElementFromFixture(fixture, cannotExportMessageDataTestId); + + expect(element).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.ts index 76499065c513750bf5528c8d335471a1382c57f4..a6d201ed49cd80f88d9b09219720ed6742ee7695 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.ts @@ -1,6 +1,11 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { StateResource } from '@alfa-client/tech-shared'; -import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangService, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { hasLink } from '@ngxp/rest'; import { Observable, tap } from 'rxjs'; @Component({ @@ -9,11 +14,14 @@ import { Observable, tap } from 'rxjs'; styleUrls: ['./vorgang-export-container.component.scss'], }) export class VorgangExportContainerComponent implements OnInit { - @Input() vorgangWithEingang: VorgangWithEingangResource; + @Input() set vorgangWithEingang(vorgang: VorgangWithEingangResource) { + this.canExport = hasLink(vorgang, VorgangWithEingangLinkRel.EXPORT); + } @Output() public closeMenu: EventEmitter<void> = new EventEmitter(); public exportStateResource$: Observable<StateResource<boolean>>; + public canExport: boolean = false; constructor(private vorgangService: VorgangService) {} diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts index 756a87e840c127ae44ec8199bb63bc53c0332063..910757039e1fdfe3e1b5ff885a2491687d92cfa2 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts @@ -57,6 +57,7 @@ import { ButtonComponent, CloseIconComponent, ErrorMessageComponent, + ExclamationIconComponent, RadioButtonCardComponent, SaveIconComponent, SendIconComponent, @@ -146,6 +147,7 @@ const routes: Routes = [ ButtonComponent, ButtonCardComponent, CloseIconComponent, + ExclamationIconComponent, SaveIconComponent, SendIconComponent, StampIconComponent, diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/Vorgang.java b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/Vorgang.java index 4168fcf828056858862d0e1a0dae1c92e499aefa..876f7e229e65ba95d27254ed895aea7d361755b5 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/Vorgang.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/Vorgang.java @@ -35,7 +35,7 @@ public interface Vorgang { enum VorgangStatus { NEU, ANGENOMMEN, VERWORFEN, IN_BEARBEITUNG, BESCHIEDEN, ABGESCHLOSSEN, WEITERGELEITET, ZU_LOESCHEN; - private Map<String, Set<VorgangStatus>> allowedFollowStatusByRole = new HashMap<>(); + private final Map<String, Set<VorgangStatus>> allowedFollowStatusByRole = new HashMap<>(); static { NEU.allowedFollowStatusByRole.put(UserRole.EINHEITLICHER_ANSPRECHPARTNER, Set.of(WEITERGELEITET, VERWORFEN)); diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportVorgangProcessor.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportVorgangProcessor.java index 28184ab2ecfec34797cee5261605f1cde264d7b4..cd93a4d4c15df7e7f57bcc02668076f4c2efdd15 100644 --- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportVorgangProcessor.java +++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportVorgangProcessor.java @@ -3,6 +3,7 @@ package de.ozgcloud.alfa.export; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; import java.util.Objects; +import java.util.function.Predicate; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.LinkRelation; @@ -11,6 +12,7 @@ import org.springframework.stereotype.Component; import de.ozgcloud.alfa.common.FeatureToggleProperties; import de.ozgcloud.alfa.common.ModelBuilder; +import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus; import de.ozgcloud.alfa.vorgang.VorgangWithEingang; import lombok.RequiredArgsConstructor; @@ -18,6 +20,9 @@ import lombok.RequiredArgsConstructor; @Component class ExportVorgangProcessor implements RepresentationModelProcessor<EntityModel<VorgangWithEingang>> { + private final Predicate<VorgangWithEingang> isExportEnabled = vorgang -> isExportEnabled(); + private static final Predicate<VorgangWithEingang> IS_VORGANG_ABGESCHLOSSEN = vorgang -> vorgang.getStatus() == VorgangStatus.ABGESCHLOSSEN; + static final LinkRelation REL_EXPORT = LinkRelation.of("export"); private final FeatureToggleProperties featureToggleProperties; @@ -31,9 +36,12 @@ class ExportVorgangProcessor implements RepresentationModelProcessor<EntityModel } return ModelBuilder.fromModel(model) - .ifMatch(featureToggleProperties::isVorgangExport) + .ifMatch(isExportEnabled.and(IS_VORGANG_ABGESCHLOSSEN)) .addLink(linkTo(methodOn(ExportVorgangController.class).exportToXdomea(vorgang.getId())).withRel(REL_EXPORT)) .buildModel(); + } + private boolean isExportEnabled() { + return featureToggleProperties.isVorgangExport(); } } diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportVorgangProcessorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportVorgangProcessorTest.java index 9fe2304b79c6b655a580e83df8df91218ed6802c..27ed62377f845026eb3265b2a23f0694188c2579 100644 --- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportVorgangProcessorTest.java +++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportVorgangProcessorTest.java @@ -8,6 +8,8 @@ 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.mockito.InjectMocks; import org.mockito.Mock; import org.springframework.hateoas.EntityModel; @@ -15,7 +17,9 @@ import org.springframework.hateoas.Link; import de.ozgcloud.alfa.common.FeatureToggleProperties; import de.ozgcloud.alfa.common.UserProfileUrlProvider; +import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus; import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory; +import de.ozgcloud.alfa.vorgang.VorgangWithEingang; import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory; class ExportVorgangProcessorTest { @@ -26,7 +30,7 @@ class ExportVorgangProcessorTest { @Mock private FeatureToggleProperties featureToggleProperties; - private UserProfileUrlProvider urlProvider = new UserProfileUrlProvider(); + private final UserProfileUrlProvider urlProvider = new UserProfileUrlProvider(); @Nested class TestProcess { @@ -41,23 +45,40 @@ class ExportVorgangProcessorTest { } @Test - void shouldAddLink() { + void shouldAddLinkWhenExportIsEnabledAndVorgangIsAbgeschlossen() { when(featureToggleProperties.isVorgangExport()).thenReturn(true); + var vorgang = vorgangInStatus(VorgangStatus.ABGESCHLOSSEN); - var model = processor.process(EntityModel.of(VorgangWithEingangTestFactory.create())); + var model = processor.process(EntityModel.of(vorgang)); assertThat(model.getLink(ExportVorgangProcessor.REL_EXPORT)).isPresent().get().extracting(Link::getHref) .isEqualTo(ExportVorgangController.PATH + "/" + VorgangHeaderTestFactory.ID); } + @ParameterizedTest + @EnumSource(mode = EnumSource.Mode.EXCLUDE, names = "ABGESCHLOSSEN") + void shouldNotAddLinkWhenVorgangIsNotAbgeschlossen(VorgangStatus status) { + when(featureToggleProperties.isVorgangExport()).thenReturn(true); + var vorgang = vorgangInStatus(status); + + var model = processor.process(EntityModel.of(vorgang)); + + assertThat(model.getLink(ExportVorgangProcessor.REL_EXPORT)).isEmpty(); + } + @Test - void shouldNotAddLink() { + void shouldNotAddLinkWhenExportIsDisabled() { when(featureToggleProperties.isVorgangExport()).thenReturn(false); + var vorgang = vorgangInStatus(VorgangStatus.ABGESCHLOSSEN); - var model = processor.process(EntityModel.of(VorgangWithEingangTestFactory.create())); + var model = processor.process(EntityModel.of(vorgang)); assertThat(model.getLink(ExportVorgangProcessor.REL_EXPORT)).isEmpty(); } + + private VorgangWithEingang vorgangInStatus(VorgangStatus status) { + return VorgangWithEingangTestFactory.createBuilder().status(status).build(); + } } }