diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.linkrel.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.linkrel.ts new file mode 100644 index 0000000000000000000000000000000000000000..0ad5c47c6d511e25d658ecc06634ec393fd7aa16 --- /dev/null +++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.linkrel.ts @@ -0,0 +1,3 @@ +export enum BescheidLinkRel { + DELETE = 'delete', +} diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.model.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.model.ts index 4c05bd47b57fa99637c1ca250fce6105363dfa46..c7dc8db99cd709ae5909a5b10db662801357276e 100644 --- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.model.ts +++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.model.ts @@ -1,7 +1,6 @@ import { Resource } from '@ngxp/rest'; export interface Bescheid { - id?: string; beschiedenAm: string; bewilligt: boolean; bescheidDocument?: string; diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts index c6739a72de18543668ff4c2b18b18b052611247d..972537e77f7862ce5da10ffd868c3ffa529d2060 100644 --- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts +++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts @@ -1,5 +1,6 @@ import { mock, Mock, useFromMock } from '@alfa-client/test-utils'; import { + VorgangCommandService, VorgangService, VorgangWithEingangLinkRel, VorgangWithEingangResource, @@ -7,16 +8,20 @@ import { import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; import { BescheidFacade } from './+state/bescheid.facade'; import { BescheidService } from './bescheid.service'; -import { buildCreateBescheidCommand } from './bescheid.util'; import { Observable, of } from 'rxjs'; import { createEmptyStateResource, createStateResource, + EMPTY_STRING, StateResource, } from '@alfa-client/tech-shared'; import { ResourceRepository } from '../../../tech-shared/src/lib/resource/resource.repository'; -import { CommandOrder, CommandService, CreateCommand } from '@alfa-client/command-shared'; -import faker from '@faker-js/faker'; +import { + CommandOrder, + CommandResource, + CommandService, + CreateCommandProps, +} from '@alfa-client/command-shared'; import { createBescheidResource } from '../test/bescheid'; import { createCommandResource, @@ -26,6 +31,7 @@ import { singleCold } from '../../../tech-shared/src/lib/resource/marbles'; import { BescheidResource } from './bescheid.model'; import { cold } from 'jest-marbles'; import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; +import { BescheidLinkRel } from './bescheid.linkrel'; describe('BescheidService', () => { let service: BescheidService; @@ -34,21 +40,25 @@ describe('BescheidService', () => { let vorgangService: Mock<VorgangService>; let resourceRepository: Mock<ResourceRepository>; let commandService: Mock<CommandService>; + let vorgangCommandService: Mock<VorgangCommandService>; - const vorgangWithEingangStateResource$: Observable<StateResource<VorgangWithEingangResource>> = - of(createStateResource(createVorgangWithEingangResource())); + const vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource> = + createStateResource(createVorgangWithEingangResource()); beforeEach(() => { facade = mock(BescheidFacade); - vorgangService = mock(VorgangService); resourceRepository = mock(ResourceRepository); commandService = mock(CommandService); - vorgangService.getVorgangWithEingang.mockReturnValue(vorgangWithEingangStateResource$); + vorgangCommandService = mock(VorgangCommandService); + + vorgangService = mock(VorgangService); + vorgangService.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); service = new BescheidService( useFromMock(facade), useFromMock(vorgangService), useFromMock(commandService), + useFromMock(vorgangCommandService), useFromMock(resourceRepository), ); }); @@ -104,141 +114,196 @@ describe('BescheidService', () => { }); describe('createBescheid', () => { - let vorgangWithEingang: VorgangWithEingangResource; - - beforeEach(() => { - vorgangWithEingang = createVorgangWithEingangResource(); - }); + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); it('should call facade', () => { service.createBescheid(vorgangWithEingang); - expect(facade.createBescheid).toHaveBeenCalledWith( - vorgangWithEingang, - buildCreateBescheidCommand(), - ); + expect(facade.createBescheid).toHaveBeenCalledWith(vorgangWithEingang, { + order: CommandOrder.CREATE_BESCHEID, + }); + }); + }); + + describe('bescheidErstellungUeberspringen', () => { + describe('Bescheid Draft exists', () => { + const vorgangWithEingangResource: VorgangWithEingangResource = + createVorgangWithEingangResource([VorgangWithEingangLinkRel.BESCHEID_DRAFT]); + + const bescheidResource: BescheidResource = createBescheidResource(); + const bescheidStateResource: StateResource<BescheidResource> = + createStateResource(bescheidResource); + + const commandStateResource: StateResource<CommandResource> = createCommandStateResource(); + + beforeEach(() => { + service.getBescheidDraft = jest.fn().mockReturnValue(of(bescheidStateResource)); + service.bescheidLoeschenUndErstellungUeberspringen = jest + .fn() + .mockReturnValue(of(commandStateResource)); + }); + + it('should get bescheid draft', (done) => { + const command$: Observable<StateResource<CommandResource>> = + service.bescheidErstellungUeberspringen(vorgangWithEingangResource); + + command$.subscribe(() => { + expect(service.getBescheidDraft).toHaveBeenCalled(); + done(); + }); + }); + + it('should Bescheid löschen und Erstellung überspringen', (done) => { + const command$: Observable<StateResource<CommandResource>> = + service.bescheidErstellungUeberspringen(vorgangWithEingangResource); + + command$.subscribe(() => { + expect(service.bescheidLoeschenUndErstellungUeberspringen).toHaveBeenCalledWith( + vorgangWithEingangResource, + bescheidResource, + ); + done(); + }); + }); + + it('should return command', () => { + const command$: Observable<StateResource<CommandResource>> = + service.bescheidErstellungUeberspringen(vorgangWithEingangResource); + + expect(command$).toBeObservable(cold('(a|)', { a: commandStateResource })); + }); + }); + + describe('Bescheid Draft not exists', () => { + const vorgangWithEingangResource: VorgangWithEingangResource = + createVorgangWithEingangResource(); + const commandStateResource: StateResource<CommandResource> = createCommandStateResource(); + + beforeEach(() => { + service.vorgangAbschliesen = jest.fn().mockReturnValue(of(commandStateResource)); + }); + + it('should call vorgang abschliessen', (done) => { + const command$: Observable<StateResource<CommandResource>> = + service.bescheidErstellungUeberspringen(vorgangWithEingangResource); + + command$.subscribe(() => { + expect(service.vorgangAbschliesen).toHaveBeenCalledWith(vorgangWithEingangResource); + done(); + }); + }); + + it('should return command', () => { + const command$: Observable<StateResource<CommandResource>> = + service.bescheidErstellungUeberspringen(vorgangWithEingangResource); + + expect(command$).toBeObservable(cold('(a|)', { a: commandStateResource })); + }); }); }); describe('bescheidLoeschenUndErstellungUeberspringen', () => { - let vorgangWithEingangResource: VorgangWithEingangResource; - let bescheidResource: BescheidResource; - let bescheidErstellungUeberspringen: jest.Mock; - let deleteBescheid: jest.Mock; + const vorgangWithEingangResource: VorgangWithEingangResource = + createVorgangWithEingangResource(); + const bescheidResource: BescheidResource = createBescheidResource(); + const commandStateResource: StateResource<CommandResource> = createCommandStateResource(); beforeEach(() => { - vorgangWithEingangResource = createVorgangWithEingangResource(); - bescheidResource = createBescheidResource(); - bescheidErstellungUeberspringen = service.bescheidErstellungUeberspringen = jest.fn(); - deleteBescheid = service.deleteBescheid = jest.fn(); - bescheidErstellungUeberspringen.mockReturnValue(of(createCommandStateResource())); - deleteBescheid.mockReturnValue(of(createCommandStateResource())); + service.vorgangAbschliesen = jest.fn().mockReturnValue(of(createCommandStateResource())); + service.deleteBescheid = jest.fn().mockReturnValue(of(commandStateResource)); }); it('should Bescheiderstellung überspringen', (done) => { - const command$ = service.bescheidLoeschenUndErstellungUeberspringen( - vorgangWithEingangResource, - bescheidResource, - ); + const command$: Observable<StateResource<CommandResource>> = + service.bescheidLoeschenUndErstellungUeberspringen( + vorgangWithEingangResource, + bescheidResource, + ); command$.subscribe(() => { - expect(bescheidErstellungUeberspringen).toHaveBeenCalledWith(vorgangWithEingangResource); + expect(service.vorgangAbschliesen).toHaveBeenCalledWith(vorgangWithEingangResource); done(); }); }); it('should Bescheid löschen', (done) => { - const command$ = service.bescheidLoeschenUndErstellungUeberspringen( - vorgangWithEingangResource, - bescheidResource, - ); - - command$.subscribe(() => { - expect(deleteBescheid).toHaveBeenCalledWith( - bescheidResource.id, + const command$: Observable<StateResource<CommandResource>> = + service.bescheidLoeschenUndErstellungUeberspringen( vorgangWithEingangResource, + bescheidResource, ); + + command$.subscribe(() => { + expect(service.deleteBescheid).toHaveBeenCalledWith(bescheidResource); done(); }); }); it('should emit delete bescheid command', () => { - const deleteBescheidCommand = createCommandStateResource(); - deleteBescheid.mockReturnValue(of(deleteBescheidCommand)); - - const command$ = service.bescheidLoeschenUndErstellungUeberspringen( - vorgangWithEingangResource, - bescheidResource, - ); + const command$: Observable<StateResource<CommandResource>> = + service.bescheidLoeschenUndErstellungUeberspringen( + vorgangWithEingangResource, + bescheidResource, + ); - expect(command$).toBeObservable(cold('(a|)', { a: deleteBescheidCommand })); + expect(command$).toBeObservable(cold('(a|)', { a: commandStateResource })); }); }); - describe('bescheidErstellungUeberspringen', () => { - let vorgangWithEingangResource: VorgangWithEingangResource; + describe('vorgang abschliessen', () => { + const vorgangWithEingangResource: VorgangWithEingangResource = + createVorgangWithEingangResource(); + const commandStateResource: StateResource<CommandResource> = createCommandStateResource(); beforeEach(() => { - vorgangWithEingangResource = createVorgangWithEingangResource(); - commandService.createCommand.mockReturnValue(of(createCommandStateResource())); + vorgangCommandService.abschliessen.mockReturnValue(of(commandStateResource)); }); - it('should create command', (done) => { - const command$ = service.bescheidErstellungUeberspringen(vorgangWithEingangResource); + it('should call vorgang command service', (done) => { + const command$: Observable<StateResource<CommandResource>> = service.vorgangAbschliesen( + vorgangWithEingangResource, + ); command$.subscribe(() => { - expect(commandService.createCommand).toHaveBeenCalledWith( - vorgangWithEingangResource, - VorgangWithEingangLinkRel.UEBERSPRINGEN_UND_ABSCHLIESSEN, - { - order: CommandOrder.VORGANG_ABSCHLIESSEN, - body: null, - } as CreateCommand, - ); + expect(vorgangCommandService.abschliessen).toHaveBeenCalledWith(vorgangWithEingangResource); done(); }); }); it('should return command', () => { - const command = createCommandStateResource(); - commandService.createCommand.mockReturnValue(of(command)); + const command$: Observable<StateResource<CommandResource>> = + service.bescheidErstellungUeberspringen(vorgangWithEingangResource); - const command$ = service.bescheidErstellungUeberspringen(vorgangWithEingangResource); - - expect(command$).toBeObservable(cold('(a|)', { a: command })); + expect(command$).toBeObservable(cold('(a|)', { a: commandStateResource })); }); }); describe('deleteBescheid', () => { - let bescheidId: string; - let vorgang: VorgangWithEingangResource; - - beforeEach(() => { - bescheidId = faker.datatype.uuid(); - vorgang = createVorgangWithEingangResource(); - }); + const bescheidResource: BescheidResource = createBescheidResource(); it('should create command', () => { - service.deleteBescheid(bescheidId, vorgang); + service.deleteBescheid(bescheidResource); - expect(commandService.createCommand).toHaveBeenCalledWith( - vorgang, - VorgangWithEingangLinkRel.UEBERSPRINGEN_UND_ABSCHLIESSEN, - { + const expectedProps: CreateCommandProps = { + resource: bescheidResource, + linkRel: BescheidLinkRel.DELETE, + command: { order: CommandOrder.DELETE_BESCHEID, body: null, - relationId: bescheidId, - } as CreateCommand, - ); + }, + snackBarMessage: EMPTY_STRING, + }; + expect(commandService.createCommandByProps).toHaveBeenCalledWith(expectedProps); }); it('should return command', () => { - const command = createEmptyStateResource(); - commandService.createCommand.mockReturnValue(command); + const commandStateResource: StateResource<CommandResource> = createEmptyStateResource(); + commandService.createCommandByProps.mockReturnValue(commandStateResource); - const createdCommand = service.deleteBescheid(bescheidId, vorgang); + const createdCommand: Observable<StateResource<CommandResource>> = + service.deleteBescheid(bescheidResource); - expect(createdCommand).toEqual(command); + expect(createdCommand).toEqual(commandStateResource); }); }); }); diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts index e82eaef444b5f2ca4044b9d7da247d47a58d044f..73338e50f814496947c94341c78c13a149e78ff1 100644 --- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts +++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts @@ -4,20 +4,22 @@ import { CommandService, onCommandSuccessfullyDone, } from '@alfa-client/command-shared'; -import { StateResource } from '@alfa-client/tech-shared'; +import { EMPTY_STRING, isLoaded, notHasLink, StateResource } from '@alfa-client/tech-shared'; import { + VorgangCommandService, VorgangService, VorgangWithEingangLinkRel, VorgangWithEingangResource, } from '@alfa-client/vorgang-shared'; import { Injectable } from '@angular/core'; -import { Observable, switchMap } from 'rxjs'; +import { filter, first, Observable, switchMap } from 'rxjs'; import { ResourceServiceConfig } from '../../../tech-shared/src/lib/resource/resource.model'; import { ResourceRepository } from '../../../tech-shared/src/lib/resource/resource.repository'; import { ResourceService } from '../../../tech-shared/src/lib/resource/resource.service'; import { BescheidFacade } from './+state/bescheid.facade'; import { Bescheid, BescheidResource } from './bescheid.model'; import { buildCreateBescheidCommand } from './bescheid.util'; +import { BescheidLinkRel } from './bescheid.linkrel'; @Injectable({ providedIn: 'root' }) export class BescheidService { @@ -27,6 +29,7 @@ export class BescheidService { private readonly facade: BescheidFacade, private readonly vorgangService: VorgangService, private readonly commandService: CommandService, + private readonly vorgangCommandService: VorgangCommandService, repository: ResourceRepository, ) { this.resourceService = new ResourceService(this.buildConfig(), repository); @@ -55,40 +58,45 @@ export class BescheidService { this.facade.createBescheid(vorgangWithEingang, buildCreateBescheidCommand(bescheid)); } - public bescheidLoeschenUndErstellungUeberspringen( + public bescheidErstellungUeberspringen( vorgangWithEingangResource: VorgangWithEingangResource, - bescheidResource: BescheidResource, ): Observable<StateResource<CommandResource>> { - return this.bescheidErstellungUeberspringen(vorgangWithEingangResource).pipe( - switchMap(() => this.deleteBescheid(bescheidResource.id, vorgangWithEingangResource)), + if (notHasLink(vorgangWithEingangResource, VorgangWithEingangLinkRel.BESCHEID_DRAFT)) { + return this.vorgangAbschliesen(vorgangWithEingangResource); + } + return this.getBescheidDraft().pipe( + filter((stateResource) => isLoaded(stateResource)), + first(), + switchMap((bescheidStateResource: StateResource<BescheidResource>) => + this.bescheidLoeschenUndErstellungUeberspringen( + vorgangWithEingangResource, + bescheidStateResource.resource, + ), + ), ); } - public bescheidErstellungUeberspringen( + bescheidLoeschenUndErstellungUeberspringen( vorgangWithEingangResource: VorgangWithEingangResource, + bescheidResource: BescheidResource, ): Observable<StateResource<CommandResource>> { - return this.commandService.createCommand( - vorgangWithEingangResource, - VorgangWithEingangLinkRel.UEBERSPRINGEN_UND_ABSCHLIESSEN, - { - order: CommandOrder.VORGANG_ABSCHLIESSEN, - body: null, - }, + return this.vorgangAbschliesen(vorgangWithEingangResource).pipe( + switchMap(() => this.deleteBescheid(bescheidResource)), ); } - public deleteBescheid( - bescheidId: string, + vorgangAbschliesen( vorgangWithEingangResource: VorgangWithEingangResource, ): Observable<StateResource<CommandResource>> { - return this.commandService.createCommand( - vorgangWithEingangResource, - VorgangWithEingangLinkRel.UEBERSPRINGEN_UND_ABSCHLIESSEN, - { - order: CommandOrder.DELETE_BESCHEID, - relationId: bescheidId, - body: null, - }, - ); + return this.vorgangCommandService.abschliessen(vorgangWithEingangResource); + } + + deleteBescheid(bescheid: BescheidResource): Observable<StateResource<CommandResource>> { + return this.commandService.createCommandByProps({ + resource: bescheid, + linkRel: BescheidLinkRel.DELETE, + command: { order: CommandOrder.DELETE_BESCHEID, body: null }, + snackBarMessage: EMPTY_STRING, + }); } } diff --git a/alfa-client/libs/bescheid-shared/src/test/bescheid.ts b/alfa-client/libs/bescheid-shared/src/test/bescheid.ts index aa3156fbb7f957d8ee0ccb9d22154a04bddc611c..7e9a103fa847ca26673184a0ff99f787f43767ef 100644 --- a/alfa-client/libs/bescheid-shared/src/test/bescheid.ts +++ b/alfa-client/libs/bescheid-shared/src/test/bescheid.ts @@ -1,11 +1,9 @@ import { Bescheid, BescheidResource } from '../lib/bescheid.model'; import { toResource } from 'libs/tech-shared/test/resource'; -import faker from '@faker-js/faker'; import { createStateResource, StateResource } from '@alfa-client/tech-shared'; export function createBescheid(): Bescheid { return { - id: faker.datatype.uuid(), beschiedenAm: '2024-01-01', bewilligt: true, }; diff --git a/alfa-client/libs/command-shared/src/lib/command.model.ts b/alfa-client/libs/command-shared/src/lib/command.model.ts index 7f93bf9c85ba48e4a20a17d6028fbe12ccf9b2e4..feca739803eb92ff5a3056cee412464173af58ae 100644 --- a/alfa-client/libs/command-shared/src/lib/command.model.ts +++ b/alfa-client/libs/command-shared/src/lib/command.model.ts @@ -127,5 +127,6 @@ export interface CreateCommandProps { resource: Resource; linkRel: string; command: CreateCommand; + //set to EMPTY_STRING/'' if no snackbar should be display snackBarMessage?: string; } diff --git a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.facade.ts b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.facade.ts index 56950c2a7e0a3ea85cee1f71151156a13f72d3de..28b3ee2c08cb7816f79f19b4e0c01c7e983988a1 100644 --- a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.facade.ts +++ b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.facade.ts @@ -43,7 +43,7 @@ import * as BinaryFileActions from '@alfa-client/binary-file-shared'; import * as PostfachActions from './postfach.actions'; import * as PostfachSelectors from './postfach.selectors'; -@Injectable() +@Injectable({ providedIn: 'root' }) export class PostfachFacade { constructor(private readonly store: Store) {} diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach-shared.module.ts b/alfa-client/libs/postfach-shared/src/lib/postfach-shared.module.ts index d8f2355dde1b6ab424dbb3c22b412578acb0916d..c2bb6613dec3353c55066137491d7e0e879b78bb 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach-shared.module.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach-shared.module.ts @@ -27,9 +27,7 @@ import { NgModule } from '@angular/core'; import { EffectsModule } from '@ngrx/effects'; import { StoreModule } from '@ngrx/store'; import { PostfachEffects } from './+state/postfach.effects'; -import { PostfachFacade } from './+state/postfach.facade'; import * as fromPostfach from './+state/postfach.reducer'; -import { PostfachService } from './postfach.service'; @NgModule({ imports: [ @@ -38,6 +36,5 @@ import { PostfachService } from './postfach.service'; StoreModule.forFeature(fromPostfach.POSTFACH_FEATURE_KEY, fromPostfach.postfachReducer), EffectsModule.forFeature([PostfachEffects]), ], - providers: [PostfachFacade, PostfachService], }) export class PostfachSharedModule {} diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach.service.ts b/alfa-client/libs/postfach-shared/src/lib/postfach.service.ts index 2ac92221cab36de52d7ea812a75a5a965f9346a1..dec067e551da7b7af88fdfdaf84bae1997f9b400 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach.service.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach.service.ts @@ -66,7 +66,7 @@ import { import { PostfachRepository } from './postfach.repository'; import { createResendPostfachMailCommand, createSendPostfachMailCommand } from './postfach.util'; -@Injectable() +@Injectable({ providedIn: 'root' }) export class PostfachService { private readonly isPollSendPostachMail: BehaviorSubject<boolean> = new BehaviorSubject<boolean>( false, diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.ts index 8082307ffa9c731904c0c93e6f137b87ec3ff5d3..6335536d0fd0d2f8e03c413cad7f304c9e06cfae 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.ts @@ -21,12 +21,12 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { Component, Inject, OnInit } from '@angular/core'; -import { MAT_DIALOG_DATA } from '@angular/material/dialog'; import { CommandResource } from '@alfa-client/command-shared'; +import { PostfachMailFormDialogData } from '@alfa-client/postfach-shared'; import { StateResource, createEmptyStateResource, isNotNil } from '@alfa-client/tech-shared'; import { DialogService } from '@alfa-client/ui'; -import { PostfachMailFormDialogData } from 'libs/postfach-shared/src/lib/postfach.model'; +import { Component, Inject, OnInit } from '@angular/core'; +import { MAT_DIALOG_DATA } from '@angular/material/dialog'; import { Observable, of, tap } from 'rxjs'; import { PostfachMailFormservice } from './postfach-mail.formservice'; diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.ts index eec257adbcb1e50627936c64d8fe2da8f7c320f4..7d1aad74943eb34874ef94577135ba5a7dd8a13c 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.ts @@ -1,9 +1,9 @@ -import { Component, Input } from '@angular/core'; import { PostfachMailFormDialogData, PostfachMailResource } from '@alfa-client/postfach-shared'; import { EMPTY_STRING, StateResource, isNotNil } from '@alfa-client/tech-shared'; import { DialogService } from '@alfa-client/ui'; import { Antragsteller, VorgangWithEingang } from '@alfa-client/vorgang-shared'; -import { PostfachMailFormComponent } from 'libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component'; +import { Component, Input } from '@angular/core'; +import { PostfachMailFormComponent } from '../../../../../postfach-mail-form/postfach-mail-form.component'; @Component({ selector: 'alfa-postfach-nachricht-edit-button-container', diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-steps-content.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-steps-content.component.html index f339099acd49dbfb607aaa102882c70a7335fcc3..8e3f5a5e4cf12c7ab8618957d3a2ba4dbec86083 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-steps-content.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-steps-content.component.html @@ -2,7 +2,7 @@ title="Antrag bescheiden" [step]="1" [nextStep]="2" - [activeStep]="activeStep" + [activeStep]="activeStep$ | async" > <alfa-vorgang-detail-antrag-bescheiden-step></alfa-vorgang-detail-antrag-bescheiden-step> <alfa-vorgang-detail-bescheiden-weiter-button @@ -14,7 +14,7 @@ title="Dokumente hinzufügen" [step]="2" [nextStep]="3" - [activeStep]="activeStep" + [activeStep]="activeStep$ | async" > <alfa-vorgang-detail-bescheiden-weiter-button (submitSuccess)="changeActiveStep(3)" @@ -25,10 +25,10 @@ title="Bescheid versenden" [step]="3" [nextStep]="3" - [activeStep]="activeStep" + [activeStep]="activeStep$ | async" > </alfa-vorgang-detail-bescheiden-step-content> <alfa-vorgang-detail-bescheiden-ueberspringen-button - *ngIf="showBescheiderstellungUeberspringen" + *ngIf="showBescheidErstellungUeberspringen$ | async" ></alfa-vorgang-detail-bescheiden-ueberspringen-button> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-steps-content.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-steps-content.component.spec.ts index a70bede3ef5a468d28140815cb18106d89f3fa75..1e7904653f18e8488ed7a7998c3c2d5f8240031e 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-steps-content.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-steps-content.component.spec.ts @@ -8,21 +8,21 @@ import { VorgangDetailBescheidenStepContentComponent } from './vorgang-detail-be import { VorgangDetailBescheidenStepsContentComponent } from './vorgang-detail-bescheiden-steps-content.component'; import { VorgangDetailAntragBescheidenStepComponent } from './vorgang-detail-bescheiden-antrag-bescheiden-step/vorgang-detail-antrag-bescheiden-step.component'; import { VorgangDetailBescheidenUeberspringenButtonComponent } from './vorgang-detail-bescheiden-ueberspringen-button/vorgang-detail-bescheiden-ueberspringen-button.component'; -import { BescheidenFormService } from '../../bescheiden.formservice'; import { createVorgangWithEingangResource } from '../../../../../../../vorgang-shared/test/vorgang'; -import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { VorgangService, VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared'; +import { singleCold } from '../../../../../../../tech-shared/src/lib/resource/marbles'; +import { EMPTY, of } from 'rxjs'; +import { createStateResource } from '@alfa-client/tech-shared'; describe('VorgangDetailBescheidenStepsContentComponent', () => { let component: VorgangDetailBescheidenStepsContentComponent; let fixture: ComponentFixture<VorgangDetailBescheidenStepsContentComponent>; - let formService: Mock<BescheidenFormService>; - let vorgangWithEingangResource: VorgangWithEingangResource; + let vorgangService: Mock<VorgangService>; beforeEach(async () => { - formService = mock(BescheidenFormService); - vorgangWithEingangResource = createVorgangWithEingangResource(); - formService.getVorgangWithEingangResource.mockReturnValue(vorgangWithEingangResource); + vorgangService = mock(VorgangService); + vorgangService.getVorgangWithEingang.mockReturnValue(EMPTY); await TestBed.configureTestingModule({ declarations: [ @@ -35,8 +35,8 @@ describe('VorgangDetailBescheidenStepsContentComponent', () => { ], providers: [ { - provide: BescheidenFormService, - useValue: formService, + provide: VorgangService, + useValue: vorgangService, }, ], }).compileComponents(); @@ -65,37 +65,43 @@ describe('VorgangDetailBescheidenStepsContentComponent', () => { describe('ngOnInit', () => { it('should render überspringen und abschliessen button', () => { component.activeStep = 1; - formService.getVorgangWithEingangResource.mockReturnValue( - createVorgangWithEingangResource([ - VorgangWithEingangLinkRel.UEBERSPRINGEN_UND_ABSCHLIESSEN, - ]), + vorgangService.getVorgangWithEingang.mockReturnValue( + of( + createStateResource( + createVorgangWithEingangResource([VorgangWithEingangLinkRel.ABSCHLIESSEN]), + ), + ), ); component.ngOnInit(); - expect(component.showBescheiderstellungUeberspringen).toBeTruthy(); + expect(component.showBescheidErstellungUeberspringen$).toBeObservable(singleCold(true)); }); - it('should not render überspringen und abschliessen button for active step 1', () => { + it('should not render überspringen und abschliessen button for active step 2', () => { component.activeStep = 2; - formService.getVorgangWithEingangResource.mockReturnValue( - createVorgangWithEingangResource([ - VorgangWithEingangLinkRel.UEBERSPRINGEN_UND_ABSCHLIESSEN, - ]), + vorgangService.getVorgangWithEingang.mockReturnValue( + of( + createStateResource( + createVorgangWithEingangResource([VorgangWithEingangLinkRel.ABSCHLIESSEN]), + ), + ), ); component.ngOnInit(); - expect(component.showBescheiderstellungUeberspringen).toBeFalsy(); + expect(component.showBescheidErstellungUeberspringen$).toBeObservable(singleCold(false)); }); it('should not render überspringen und abschliessen button if link missing', () => { component.activeStep = 1; - formService.getVorgangWithEingangResource.mockReturnValue(createVorgangWithEingangResource()); + vorgangService.getVorgangWithEingang.mockReturnValue( + of(createStateResource(createVorgangWithEingangResource())), + ); component.ngOnInit(); - expect(component.showBescheiderstellungUeberspringen).toBeFalsy(); + expect(component.showBescheidErstellungUeberspringen$).toBeObservable(singleCold(false)); }); }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-steps-content.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-steps-content.component.ts index 6558d2cc365be0179fe676a036bf64a5c70e46c6..c71f656d1faade479f6f020b3ceb70c84da5e6ca 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-steps-content.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-steps-content.component.ts @@ -1,7 +1,12 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { BescheidenFormService } from '../../bescheiden.formservice'; -import { VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared'; +import { + VorgangService, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { hasLink } from '@ngxp/rest'; +import { BehaviorSubject, combineLatest, filter, map, Observable } from 'rxjs'; +import { isLoaded, StateResource } from '@alfa-client/tech-shared'; @Component({ selector: 'alfa-vorgang-detail-bescheiden-steps-content', @@ -9,21 +14,27 @@ import { hasLink } from '@ngxp/rest'; styles: [':host {@apply flex flex-col}'], }) export class VorgangDetailBescheidenStepsContentComponent implements OnInit { - @Input() activeStep: number = 1; + readonly activeStep$ = new BehaviorSubject(1); + @Input() set activeStep(step: number) { + this.activeStep$.next(step); + } @Output() activeStepChange = new EventEmitter<number>(); - showBescheiderstellungUeberspringen = false; + showBescheidErstellungUeberspringen$: Observable<boolean>; - constructor(private readonly formService: BescheidenFormService) {} + constructor(private readonly vorgangService: VorgangService) {} ngOnInit(): void { - const vorgangWithEingangResource = this.formService.getVorgangWithEingangResource(); - this.showBescheiderstellungUeberspringen = - hasLink( - vorgangWithEingangResource, - VorgangWithEingangLinkRel.UEBERSPRINGEN_UND_ABSCHLIESSEN, - ) && this.activeStep === 1; + this.showBescheidErstellungUeberspringen$ = combineLatest([ + this.vorgangService.getVorgangWithEingang().pipe( + filter((stateResource) => isLoaded(stateResource)), + map((stateResource: StateResource<VorgangWithEingangResource>) => + hasLink(stateResource.resource, VorgangWithEingangLinkRel.ABSCHLIESSEN), + ), + ), + this.activeStep$.pipe(map((step) => step === 1)), + ]).pipe(map(([hasAbschliessenLink, isFirstStep]) => hasAbschliessenLink && isFirstStep)); } public changeActiveStep(step: number): void { diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component.spec.ts index 71f794d276fff9cf640189625308419fcdd81f6e..3519995184aa0e2cdc205aa5121a80eadc943021 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component.spec.ts @@ -1,21 +1,24 @@ import { Mock, mock } from '@alfa-client/test-utils'; import { DIALOG_DATA, DialogRef } from '@angular/cdk/dialog'; -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing'; import { VorgangDetailBescheidenUeberspringenDialogComponent } from './vorgang-detail-bescheiden-ueberspringen-dialog.component'; import { MockComponent } from 'ng-mocks'; import { OzgcloudDialogService, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; import { MatIcon } from '@angular/material/icon'; -import { BescheidResource, BescheidService } from '@alfa-client/bescheid-shared'; +import { BescheidService } from '@alfa-client/bescheid-shared'; import { createVorgangWithEingangResource } from '../../../../../../../../vorgang-shared/test/vorgang'; -import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; -import { BescheiderstellungUeberspringenDialogData } from '@alfa-client/vorgang-detail'; -import { createCommandStateResource } from '../../../../../../../../command-shared/test/command'; +import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { createCommandResource } from '../../../../../../../../command-shared/test/command'; import { of } from 'rxjs'; import { cold } from 'jest-marbles'; -import { createStateResource, StateResource } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createStateResource, + StateResource, +} from '@alfa-client/tech-shared'; import { CommandLinkRel } from '../../../../../../../../command-shared/src/lib/command.linkrel'; -import { createBescheidResource } from '../../../../../../../../bescheid-shared/src/test/bescheid'; import { CommandResource } from '@alfa-client/command-shared'; +import { BescheiderstellungUeberspringenDialogData } from '../../../bescheiden.model'; describe('VorgangDetailBescheidenUeberspringenButtonComponent', () => { let component: VorgangDetailBescheidenUeberspringenDialogComponent; @@ -79,25 +82,23 @@ describe('VorgangDetailBescheidenUeberspringenButtonComponent', () => { }); describe('onConfirm', () => { - let bescheidErstellungUeberspringen: jest.Mock; - let bescheidErstellungUeberspringenCommand: StateResource<CommandResource>; + const successfullyDoneCommandStateResource: StateResource<CommandResource> = + createStateResource(createCommandResource([CommandLinkRel.EFFECTED_RESOURCE])); beforeEach(() => { - bescheidErstellungUeberspringen = component.bescheidErstellungUeberspringen = jest.fn(); - bescheidErstellungUeberspringenCommand = createCommandStateResource([ - CommandLinkRel.EFFECTED_RESOURCE, - ]); - bescheidErstellungUeberspringen.mockReturnValue(of(bescheidErstellungUeberspringenCommand)); + bescheidService.bescheidErstellungUeberspringen.mockReturnValue( + of(successfullyDoneCommandStateResource), + ); }); - it('should call bescheidErstellungUeberspringen', (done) => { + it('should call bescheid service erstellung ueberspringen', fakeAsync(() => { component.onConfirm(); + tick(); - component.bescheiderstellungUeberspringen$.subscribe(() => { - expect(bescheidErstellungUeberspringen).toHaveBeenCalled(); - done(); - }); - }); + expect(bescheidService.bescheidErstellungUeberspringen).toHaveBeenCalledWith( + vorgangWithEingangResource, + ); + })); it('should close all dialogs on success', (done) => { component.onConfirm(); @@ -108,8 +109,10 @@ describe('VorgangDetailBescheidenUeberspringenButtonComponent', () => { }); }); - it('should not close all dialogs on failre', (done) => { - bescheidErstellungUeberspringen.mockReturnValue(of(createCommandStateResource())); + it('should not close all dialogs on command not done successfully', (done) => { + bescheidService.bescheidErstellungUeberspringen.mockReturnValue( + of(createEmptyStateResource()), + ); component.onConfirm(); @@ -123,93 +126,11 @@ describe('VorgangDetailBescheidenUeberspringenButtonComponent', () => { component.onConfirm(); expect(component.bescheiderstellungUeberspringen$).toBeObservable( - cold('(a|)', { a: bescheidErstellungUeberspringenCommand }), + cold('(a|)', { a: successfullyDoneCommandStateResource }), ); }); }); - describe('bescheidErstellungUeberspringen', () => { - describe('Bescheid Draft exists', () => { - let vorgangWithEingangResource: VorgangWithEingangResource; - let bescheidResource: BescheidResource; - - beforeEach(() => { - vorgangWithEingangResource = createVorgangWithEingangResource([ - VorgangWithEingangLinkRel.BESCHEID_DRAFT, - ]); - dialogData.vorgangWithEingangResource = vorgangWithEingangResource; - bescheidResource = createBescheidResource(); - bescheidService.getBescheidDraft.mockReturnValue(of(createStateResource(bescheidResource))); - bescheidService.bescheidLoeschenUndErstellungUeberspringen.mockReturnValue( - of(createCommandStateResource()), - ); - }); - - it('should get bescheid draft', (done) => { - const command$ = component.bescheidErstellungUeberspringen(); - - command$.subscribe(() => { - expect(bescheidService.getBescheidDraft).toHaveBeenCalled(); - done(); - }); - }); - - it('should Bescheid löschen und Erstellung überspringen', (done) => { - const command$ = component.bescheidErstellungUeberspringen(); - - command$.subscribe(() => { - expect(bescheidService.bescheidLoeschenUndErstellungUeberspringen).toHaveBeenCalledWith( - vorgangWithEingangResource, - bescheidResource, - ); - done(); - }); - }); - - it('should return command', () => { - const command = createCommandStateResource(); - bescheidService.bescheidLoeschenUndErstellungUeberspringen.mockReturnValue(of(command)); - - const command$ = component.bescheidErstellungUeberspringen(); - - expect(command$).toBeObservable(cold('(a|)', { a: command })); - }); - }); - - describe('Bescheid Draft not exists', () => { - let vorgangWithEingangResource: VorgangWithEingangResource; - - beforeEach(() => { - vorgangWithEingangResource = createVorgangWithEingangResource(); - dialogData.vorgangWithEingangResource = vorgangWithEingangResource; - }); - - it('should Bescheiderstellung überspringen', (done) => { - bescheidService.bescheidErstellungUeberspringen.mockReturnValue( - of(createCommandStateResource()), - ); - - const command$ = component.bescheidErstellungUeberspringen(); - - command$.subscribe(() => { - expect(bescheidService.bescheidErstellungUeberspringen).toHaveBeenCalledWith( - vorgangWithEingangResource, - ); - done(); - }); - }); - - it('should return command', () => { - const command = createCommandStateResource(); - bescheidService.bescheidErstellungUeberspringen.mockReturnValue(of(command)); - - const command$ = component.bescheidErstellungUeberspringen(); - - expect(command$).toBeObservable(cold('(a|)', { a: command })); - }); - }); - }); - describe('onClose', () => { it('should close dialog', () => { component.onClose(); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component.ts index c33af98fa79df291216ad75505be960d5353e702..9344ce4fdbaa22268d9f5815f5846a61bcbd4b34 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component.ts @@ -2,11 +2,10 @@ import { Component, Inject } from '@angular/core'; import { DIALOG_DATA, DialogRef } from '@angular/cdk/dialog'; import { OzgcloudDialogService } from '@alfa-client/ui'; import { BescheidService } from '@alfa-client/bescheid-shared'; -import { Observable, switchMap, tap } from 'rxjs'; -import { CommandResource, isSuccessfulDone } from '@alfa-client/command-shared'; -import { notHasLink, StateResource } from '@alfa-client/tech-shared'; -import { BescheiderstellungUeberspringenDialogData } from '@alfa-client/vorgang-detail'; -import { VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared'; +import { Observable } from 'rxjs'; +import { CommandResource, onCommandSuccessfullyDone } from '@alfa-client/command-shared'; +import { StateResource } from '@alfa-client/tech-shared'; +import { BescheiderstellungUeberspringenDialogData } from '../../../bescheiden.model'; @Component({ selector: 'alfa-vorgang-detail-bescheiden-ueberspringen-dialog', @@ -22,40 +21,17 @@ export class VorgangDetailBescheidenUeberspringenDialogComponent { @Inject(DIALOG_DATA) private readonly dialogData: BescheiderstellungUeberspringenDialogData, ) {} - onCancel(): void { + public onClose(): void { this.dialogRef.close(); } - onConfirm(): void { - this.bescheiderstellungUeberspringen$ = this.bescheidErstellungUeberspringen().pipe( - tap((command) => { - if (isSuccessfulDone(command.resource)) { - this.ozgcloudDialogService.closeAll(); - } - }), - ); + public onConfirm(): void { + this.bescheiderstellungUeberspringen$ = this.bescheidService + .bescheidErstellungUeberspringen(this.dialogData.vorgangWithEingangResource) + .pipe(onCommandSuccessfullyDone(() => this.ozgcloudDialogService.closeAll())); } - bescheidErstellungUeberspringen(): Observable<StateResource<CommandResource>> { - const vorgangWithEingangResource = this.dialogData.vorgangWithEingangResource; - - if (notHasLink(vorgangWithEingangResource, VorgangWithEingangLinkRel.BESCHEID_DRAFT)) { - return this.bescheidService.bescheidErstellungUeberspringen(vorgangWithEingangResource); - } else { - return this.bescheidService - .getBescheidDraft() - .pipe( - switchMap((bescheidStateResource) => - this.bescheidService.bescheidLoeschenUndErstellungUeberspringen( - vorgangWithEingangResource, - bescheidStateResource.resource, - ), - ), - ); - } - } - - onClose(): void { + public onCancel(): void { this.dialogRef.close(); } } diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang-command.service.spec.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang-command.service.spec.ts index f6ba035446518ba10b12353177a3f766c8a0f1e4..2f25a6ec1e4d178d2c401ac3de20d93e81d7a653 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang-command.service.spec.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang-command.service.spec.ts @@ -21,13 +21,16 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { CommandOrder } from '@alfa-client/command-shared'; +import { CommandOrder, CommandResource } from '@alfa-client/command-shared'; import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; -import { createCreateCommand } from 'libs/command-shared/test/command'; +import { createCommandResource, createCreateCommand } from 'libs/command-shared/test/command'; import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; import { VorgangFacade } from './+state/vorgang.facade'; import { VorgangCommandService } from './vorgang-command.service'; import { VorgangWithEingangResource } from './vorgang.model'; +import { StateResource, createStateResource } from '@alfa-client/tech-shared'; +import { of } from 'rxjs'; +import { cold } from 'jest-marbles'; describe('VorgangCommandService', () => { let service: VorgangCommandService; @@ -191,6 +194,26 @@ describe('VorgangCommandService', () => { createCreateCommand(CommandOrder.VORGANG_ABSCHLIESSEN), ); }); + + it('should call service get abschliessen command', () => { + service.getAbschliessenCommand = jest.fn(); + + service.abschliessen(vorgangWithEingang); + + expect(service.getAbschliessenCommand).toHaveBeenCalled(); + }); + + it('should return value', () => { + const abschliessenCommandStateResource: StateResource<CommandResource> = + createStateResource(createCommandResource()); + service.getAbschliessenCommand = jest + .fn() + .mockReturnValue(of(abschliessenCommandStateResource)); + + const abschliessen$ = service.abschliessen(vorgangWithEingang); + + expect(abschliessen$).toBeObservable(cold('(a|)', { a: abschliessenCommandStateResource })); + }); }); describe('getRevokeCommand', () => { diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang-command.service.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang-command.service.ts index 96059578bb8016fbac9f6b1780e53e86eac22296..f4c673801d98ef42a7bb0a13c9ac023dc54463f4 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang-command.service.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang-command.service.ts @@ -24,7 +24,7 @@ import { Injectable } from '@angular/core'; import { CommandOrder, CommandResource } from '@alfa-client/command-shared'; import { StateResource } from '@alfa-client/tech-shared'; -import { Observable } from 'rxjs'; +import { Observable, of } from 'rxjs'; import { VorgangFacade } from './+state/vorgang.facade'; import { VorgangWithEingangResource } from './vorgang.model'; import { @@ -98,12 +98,15 @@ export class VorgangCommandService { this.facade.zurueckstellen(vorgang, createZurueckstellenCommand()); } - public getAbschliessenCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getStatusCommand(CommandOrder.VORGANG_ABSCHLIESSEN); + public abschliessen( + vorgang: VorgangWithEingangResource, + ): Observable<StateResource<CommandResource>> { + this.facade.abschliessen(vorgang, createAbschliessenCommand()); + return this.getAbschliessenCommand(); } - public abschliessen(vorgang: VorgangWithEingangResource): void { - this.facade.abschliessen(vorgang, createAbschliessenCommand()); + public getAbschliessenCommand(): Observable<StateResource<CommandResource>> { + return this.facade.getStatusCommand(CommandOrder.VORGANG_ABSCHLIESSEN); } public getRevokeCommand(): Observable<StateResource<CommandResource>> { diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/Bescheid.java b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/Bescheid.java index 0c45b6add7b914103ff595267b96e84cc38ad4a6..4c18385b40365bf1d5bfc9ced257e3ed2d809d27 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/Bescheid.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/Bescheid.java @@ -1,11 +1,10 @@ package de.ozgcloud.alfa.bescheid; -import jakarta.validation.constraints.NotNull; - import com.fasterxml.jackson.annotation.JsonIgnore; import de.ozgcloud.alfa.common.ValidationMessageCodes; import de.ozgcloud.alfa.common.command.CommandBody; +import jakarta.validation.constraints.NotNull; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; @@ -20,6 +19,10 @@ import lombok.ToString; @ToString public class Bescheid implements CommandBody { + @JsonIgnore + private String id; + @JsonIgnore + private long version; @JsonIgnore private String vorgangId; diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidMapper.java b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidMapper.java index a9e38edadc4b28eae35780380d3650222d58690d..d554be64f8df82bafc8731e8247b651aa832b640 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidMapper.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidMapper.java @@ -6,7 +6,7 @@ import org.mapstruct.ReportingPolicy; import de.ozgcloud.bescheid.GrpcBescheid; -@Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) +@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) interface BescheidMapper { Bescheid fromGrpc(GrpcBescheid grpcBescheid, String vorgangId); diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidModelAssembler.java b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidModelAssembler.java index f74b96ddc4ffa2791646e375d90f0f0de464e8f4..25e66337a44635ed88121c0eff5514db1d7c45fb 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidModelAssembler.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidModelAssembler.java @@ -7,17 +7,23 @@ import org.springframework.hateoas.server.RepresentationModelAssembler; import org.springframework.stereotype.Component; import de.ozgcloud.alfa.common.ModelBuilder; +import de.ozgcloud.alfa.common.command.CommandController.CommandByRelationController; import lombok.RequiredArgsConstructor; @Component @RequiredArgsConstructor public class BescheidModelAssembler implements RepresentationModelAssembler<Bescheid, EntityModel<Bescheid>> { + static final String REL_DELETE = "delete"; + @Override public EntityModel<Bescheid> toModel(Bescheid bescheid) { + var selfLink = linkTo(methodOn(BescheidController.class).getDraft(bescheid.getVorgangId(), BescheidController.REQUEST_PARAM_STATUS_DRAFT)); + var deleteLink = linkTo(methodOn(CommandByRelationController.class).createCommand(bescheid.getVorgangId(), bescheid.getId(), bescheid.getVersion(), null)); + return ModelBuilder.fromEntity(bescheid) - .addLink(linkTo(methodOn(BescheidController.class).getDraft(bescheid.getVorgangId(), - BescheidController.REQUEST_PARAM_STATUS_DRAFT)).withSelfRel()) + .addLink(selfLink.withSelfRel()) + .addLink(deleteLink.withRel(REL_DELETE)) .buildModel(); } } diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidVorgangProcessor.java b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidVorgangProcessor.java index fa60bb0b188ac33e509a84ba4cf3e6e90051cef2..9cd10c20e7d696386c8064428b4aa3f10b98b562 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidVorgangProcessor.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidVorgangProcessor.java @@ -23,7 +23,6 @@ class BescheidVorgangProcessor implements RepresentationModelProcessor<EntityMod static final LinkRelation REL_DRAFT = LinkRelation.of("bescheidDraft"); static final LinkRelation REL_CREATE_BESCHEID_DRAFT = LinkRelation.of("createBescheidDraft"); - static final LinkRelation REL_UEBERSPRINGEN_UND_ABSCHLIESSEN = LinkRelation.of("ueberspringen_und_abschliessen"); private final FeatureToggleProperties featureToggleProperties; private final BescheidService bescheidService; @@ -43,9 +42,6 @@ class BescheidVorgangProcessor implements RepresentationModelProcessor<EntityMod .ifMatch(isCreatingDraftAllowed(vorgang)) .addLink(linkTo(methodOn(CommandByRelationController.class).createCommand(vorgang.getId(), vorgang.getId(), vorgang.getVersion(), null)).withRel(REL_CREATE_BESCHEID_DRAFT)) - .ifMatch(isCreatingDraftAllowed(vorgang)) - .addLink(linkTo(methodOn(CommandByRelationController.class).createCommand(vorgang.getId(), - vorgang.getId(), vorgang.getVersion(), null)).withRel(REL_UEBERSPRINGEN_UND_ABSCHLIESSEN)) .buildModel(); } 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 2474a7366f3866272e0bf19fd5ce1273f00cad62..4168fcf828056858862d0e1a0dae1c92e499aefa 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 @@ -46,7 +46,7 @@ public interface Vorgang { NEU.allowedFollowStatusByRole.put(UserRole.VERWALTUNG_USER, Set.of(ANGENOMMEN, VERWORFEN)); VERWORFEN.allowedFollowStatusByRole.put(UserRole.VERWALTUNG_USER, Set.of(NEU)); ANGENOMMEN.allowedFollowStatusByRole.put(UserRole.VERWALTUNG_USER, Set.of(IN_BEARBEITUNG)); - IN_BEARBEITUNG.allowedFollowStatusByRole.put(UserRole.VERWALTUNG_USER, Set.of(BESCHIEDEN, ANGENOMMEN)); + IN_BEARBEITUNG.allowedFollowStatusByRole.put(UserRole.VERWALTUNG_USER, Set.of(BESCHIEDEN, ANGENOMMEN, ABGESCHLOSSEN)); BESCHIEDEN.allowedFollowStatusByRole.put(UserRole.VERWALTUNG_USER, Set.of(ABGESCHLOSSEN, IN_BEARBEITUNG)); ABGESCHLOSSEN.allowedFollowStatusByRole.put(UserRole.VERWALTUNG_USER, Set.of(IN_BEARBEITUNG)); } diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidModelAssemblerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidModelAssemblerTest.java index 955c75f6753a884f64b737b84e0308189e963fef..dc5043a2a9f2d97bb6fec0e122adc209658d5cd3 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidModelAssemblerTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidModelAssemblerTest.java @@ -5,9 +5,12 @@ import static org.assertj.core.api.Assertions.*; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mockito.Spy; +import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.Link; +import org.springframework.web.util.UriTemplate; +import de.ozgcloud.alfa.common.command.CommandController; import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory; class BescheidModelAssemblerTest { @@ -22,18 +25,31 @@ class BescheidModelAssemblerTest { @Test void shouldHaveSelfLink() { - var model = assembler.toModel(bescheid); + var model = callToModel(); assertThat(model.getLink(IanaLinkRelations.SELF)).isPresent().get().extracting(Link::getHref) .isEqualTo(BescheidController.PATH + "?vorgangId=" + VorgangHeaderTestFactory.ID + "&status=" + BescheidController.REQUEST_PARAM_STATUS_DRAFT); } + @Test + void shouldHaveDeleteLink() { + var model = callToModel(); + + assertThat(model.getLink(BescheidModelAssembler.REL_DELETE)).isPresent().get().extracting(Link::getHref) + .isEqualTo(new UriTemplate(CommandController.CommandByRelationController.COMMAND_BY_RELATION_PATH) + .expand(VorgangHeaderTestFactory.ID, BescheidTestFactory.ID, BescheidTestFactory.VERSION).toString()); + } + @Test void shouldHaveBody() { - var model = assembler.toModel(bescheid); + var model = callToModel(); assertThat(model.getContent()).isEqualTo(bescheid); } + + private EntityModel<Bescheid> callToModel() { + return assembler.toModel(bescheid); + } } } diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidTestFactory.java index a14aee0bcd8a5c1c5dd2f1030985e089d4a0b72d..e49f3392e50cb50cdcdb6c91b386b65f087fed26 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidTestFactory.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidTestFactory.java @@ -1,15 +1,21 @@ package de.ozgcloud.alfa.bescheid; +import java.util.UUID; + import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory; public class BescheidTestFactory { + public static final String ID = UUID.randomUUID().toString(); + public static final long VERSION = 42; public static final String VORGANG_ID = VorgangHeaderTestFactory.ID; public static final String BESCHIEDEN_AM = "01.04.2024"; public static final boolean BEWILLIGT = true; public static Bescheid.BescheidBuilder createBuilder() { return Bescheid.builder() + .id(ID) + .version(VERSION) .vorgangId(VORGANG_ID) .beschiedenAm(BESCHIEDEN_AM) .bewilligt(BEWILLIGT); diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidVorgangProcessorTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidVorgangProcessorTest.java index 69f2e7690b0a0a4911875a7ad402b4219d22752a..3a9ff91ba68f357c061279f6ed7976e14c3a497e 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidVorgangProcessorTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidVorgangProcessorTest.java @@ -17,11 +17,9 @@ import org.mockito.Mock; import org.mockito.Spy; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; -import org.springframework.web.util.UriTemplate; import de.ozgcloud.alfa.common.FeatureToggleProperties; import de.ozgcloud.alfa.common.UserProfileUrlProvider; -import de.ozgcloud.alfa.common.command.CommandController.CommandByRelationController; import de.ozgcloud.alfa.vorgang.Vorgang; import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory; import de.ozgcloud.alfa.vorgang.VorgangWithEingang; @@ -101,26 +99,6 @@ class BescheidVorgangProcessorTest { assertThat(model.getLink(BescheidVorgangProcessor.REL_CREATE_BESCHEID_DRAFT)).isEmpty(); } - @Test - void shouldNotHaveLinkToBescheidUeberspringenUndVorgangAbschliessen() { - givenCreatingDraftIsAllowed(false); - - var model = callProcess(); - - assertThat(model.getLink(BescheidVorgangProcessor.REL_UEBERSPRINGEN_UND_ABSCHLIESSEN)).isEmpty(); - } - - @Test - void shouldHaveLinkToBescheidUeberspringenUndVorgangAbschliessen() { - givenCreatingDraftIsAllowed(true); - - var model = callProcess(); - - assertThat(model.getLink(BescheidVorgangProcessor.REL_UEBERSPRINGEN_UND_ABSCHLIESSEN)).isPresent().map(Link::getHref) - .hasValue(new UriTemplate(CommandByRelationController.COMMAND_BY_RELATION_PATH).expand(VorgangHeaderTestFactory.ID, - VorgangHeaderTestFactory.ID, VorgangHeaderTestFactory.VERSION).toString()); - } - private void givenRetrievingDraftIsAllowed(boolean shouldBeAdded) { doReturn((BooleanSupplier) () -> shouldBeAdded).when(processor).isRetrievingDraftAllowed(vorgang); } diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/command/VorgangCommandProcessorTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/command/VorgangCommandProcessorTest.java index e219bf93b84e1208f3c0d79f2ccb303e645d0cf7..1634c996844cf484572f9e23e5c7398c499f4cf3 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/command/VorgangCommandProcessorTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/command/VorgangCommandProcessorTest.java @@ -242,9 +242,10 @@ class VorgangCommandProcessorTest { doReturn(UserRole.VERWALTUNG_USER).when(processor).getUserRole(); } - @Test - void shouldBePresent() { - var processed = processor.process(buildVorgangInStatus(VorgangStatus.BESCHIEDEN)); + @ParameterizedTest + @EnumSource(mode = Mode.INCLUDE, names = { "IN_BEARBEITUNG", "BESCHIEDEN" }) + void shouldBePresent(VorgangStatus status) { + var processed = processor.process(buildVorgangInStatus(status)); assertThat(processed.getLink(linkRel)).isPresent().get() .extracting(Link::getHref) @@ -252,7 +253,7 @@ class VorgangCommandProcessorTest { } @ParameterizedTest - @EnumSource(mode = Mode.EXCLUDE, names = { "BESCHIEDEN" }) + @EnumSource(mode = Mode.EXCLUDE, names = { "IN_BEARBEITUNG", "BESCHIEDEN" }) void shouldNOTbePresentbyStatus(VorgangStatus status) { var processed = processor.process(buildVorgangInStatus(status)); diff --git a/pom.xml b/pom.xml index dfddfa5256d2280e00dba0f4534565269fb3e37f..3c6690ecdc086c929bf7c031829dedd2801d9f98 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,7 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> - <vorgang-manager.version>2.4.0</vorgang-manager.version> + <vorgang-manager.version>2.5.0-SNAPSHOT</vorgang-manager.version> <ozgcloud-common-pdf.version>3.0.1</ozgcloud-common-pdf.version> <user-manager.version>2.2.0</user-manager.version>