diff --git a/src/modules/person/api/created-personenkontext-organisation.dto.ts b/src/modules/person/api/created-personenkontext-organisation.dto.ts deleted file mode 100644 index 8ed72435d..000000000 --- a/src/modules/person/api/created-personenkontext-organisation.dto.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class CreatedPersonenkontextOrganisationDto { - public readonly id!: string; -} diff --git a/src/modules/person/api/person-api.mapper.profile.spec.ts b/src/modules/person/api/person-api.mapper.profile.spec.ts index db2390385..f05ea9457 100644 --- a/src/modules/person/api/person-api.mapper.profile.spec.ts +++ b/src/modules/person/api/person-api.mapper.profile.spec.ts @@ -11,7 +11,7 @@ import { CreatePersonBodyParams } from './create-person.body.params.js'; import { CreatePersonDto } from './create-person.dto.js'; import { CreatePersonenkontextBodyParams } from './create-personenkontext.body.params.js'; import { CreatePersonenkontextDto } from './create-personenkontext.dto.js'; -import { CreatedPersonenkontextDto } from './created-personenkontext.dto.js'; +import { SavedPersonenkontextDto } from './saved-personenkontext.dto.js'; import { FindPersonenkontextByIdDto } from './find-personenkontext-by-id.dto.js'; import { FindPersonenkontextByIdParams } from './find-personenkontext-by-id.params.js'; import { FindPersonenkontextDto } from './find-personenkontext.dto.js'; @@ -30,6 +30,8 @@ import { PersonenkontextQueryParams } from './personenkontext-query.params.js'; import { PersonenkontextDto } from './personenkontext.dto.js'; import { PersonenkontextResponse } from './personenkontext.response.js'; import { PersonenkontextdatensatzResponse } from './personenkontextdatensatz.response.js'; +import { UpdatePersonenkontextDto } from './update-personenkontext.dto.js'; +import { UpdatePersonenkontextBodyParams } from './update-personenkontext.body.params.js'; describe('PersonApiMapperProfile', () => { let module: TestingModule; @@ -105,7 +107,7 @@ describe('PersonApiMapperProfile', () => { it('should map PersonenkontextDo to CreatedPersonenkontextDto', () => { const personenkontextDo: PersonenkontextDo = DoFactory.createPersonenkontext(true); - expect(() => sut.map(personenkontextDo, PersonenkontextDo, CreatedPersonenkontextDto)).not.toThrowError( + expect(() => sut.map(personenkontextDo, PersonenkontextDo, SavedPersonenkontextDto)).not.toThrowError( MappingError, ); }); @@ -114,14 +116,14 @@ describe('PersonApiMapperProfile', () => { const personenkontextDo: PersonenkontextDo = DoFactory.createPersonenkontext(true); personenkontextDo.loeschungZeitpunkt = undefined; - expect(() => sut.map(personenkontextDo, PersonenkontextDo, CreatedPersonenkontextDto)).not.toThrowError( + expect(() => sut.map(personenkontextDo, PersonenkontextDo, SavedPersonenkontextDto)).not.toThrowError( MappingError, ); }); it('should map CreatedPersonenkontextDto to PersonenkontextResponse', () => { expect(() => - sut.map({} as CreatedPersonenkontextDto, CreatedPersonenkontextDto, PersonenkontextResponse), + sut.map({} as SavedPersonenkontextDto, SavedPersonenkontextDto, PersonenkontextResponse), ).not.toThrowError(MappingError); }); @@ -199,5 +201,21 @@ describe('PersonApiMapperProfile', () => { sut.map({} as PersonenkontextDto, PersonenkontextDto, PersonenkontextdatensatzResponse), ).not.toThrowError(MappingError); }); + + it('should map UpdatePersonenkontextBodyParams to UpdatePersonenkontextDto', () => { + expect(() => + sut.map( + {} as UpdatePersonenkontextBodyParams, + UpdatePersonenkontextBodyParams, + UpdatePersonenkontextDto, + ), + ).not.toThrowError(MappingError); + }); + + it('should map UpdatePersonenkontextDto to PersonenkontextDo', () => { + expect(() => + sut.map({} as UpdatePersonenkontextDto, UpdatePersonenkontextDto, PersonenkontextDo), + ).not.toThrowError(MappingError); + }); }); }); diff --git a/src/modules/person/api/person-api.mapper.profile.ts b/src/modules/person/api/person-api.mapper.profile.ts index dd3b32164..e36078e1a 100644 --- a/src/modules/person/api/person-api.mapper.profile.ts +++ b/src/modules/person/api/person-api.mapper.profile.ts @@ -9,8 +9,8 @@ import { CreatePersonBodyParams } from './create-person.body.params.js'; import { CreatePersonDto } from './create-person.dto.js'; import { CreatePersonenkontextBodyParams } from './create-personenkontext.body.params.js'; import { CreatePersonenkontextDto } from './create-personenkontext.dto.js'; -import { CreatedPersonenkontextOrganisationDto } from './created-personenkontext-organisation.dto.js'; -import { CreatedPersonenkontextDto } from './created-personenkontext.dto.js'; +import { SavedPersonenkontextOrganisationDto } from './saved-personenkontext-organisation.dto.js'; +import { SavedPersonenkontextDto } from './saved-personenkontext.dto.js'; import { FindPersonendatensatzDto } from './find-personendatensatz.dto.js'; import { FindPersonenkontextByIdDto } from './find-personenkontext-by-id.dto.js'; import { FindPersonenkontextByIdParams } from './find-personenkontext-by-id.params.js'; @@ -31,6 +31,8 @@ import { PersonenkontextQueryParams } from './personenkontext-query.params.js'; import { PersonenkontextDto } from './personenkontext.dto.js'; import { PersonenkontextResponse } from './personenkontext.response.js'; import { PersonenkontextdatensatzResponse } from './personenkontextdatensatz.response.js'; +import { UpdatePersonenkontextBodyParams } from './update-personenkontext.body.params.js'; +import { UpdatePersonenkontextDto } from './update-personenkontext.dto.js'; @Injectable() export class PersonApiMapperProfile extends AutomapperProfile { @@ -228,18 +230,18 @@ export class PersonApiMapperProfile extends AutomapperProfile { createMap( mapper, PersonenkontextDo, - CreatedPersonenkontextDto, + SavedPersonenkontextDto, forMember( - (dest: CreatedPersonenkontextDto) => dest.loeschung, + (dest: SavedPersonenkontextDto) => dest.loeschung, mapFrom((src: PersonenkontextDo) => src.loeschungZeitpunkt ? new LoeschungDto({ zeitpunkt: src.loeschungZeitpunkt }) : undefined, ), ), ); - createMap(mapper, OrganisationDo, CreatedPersonenkontextOrganisationDto); + createMap(mapper, OrganisationDo, SavedPersonenkontextOrganisationDto); - createMap(mapper, CreatedPersonenkontextDto, PersonenkontextResponse); + createMap(mapper, SavedPersonenkontextDto, PersonenkontextResponse); createMap( mapper, @@ -352,6 +354,27 @@ export class PersonApiMapperProfile extends AutomapperProfile { ]), ), ); + + createMap( + mapper, + UpdatePersonenkontextBodyParams, + UpdatePersonenkontextDto, + forMember((dest: UpdatePersonenkontextDto) => dest.id, ignore()), + ); + + createMap( + mapper, + UpdatePersonenkontextDto, + PersonenkontextDo, + forMember((dest: PersonenkontextDo) => dest.createdAt, ignore()), + forMember((dest: PersonenkontextDo) => dest.updatedAt, ignore()), + forMember((dest: PersonenkontextDo) => dest.personId, ignore()), + forMember((dest: PersonenkontextDo) => dest.mandant, ignore()), + forMember((dest: PersonenkontextDo) => dest.organisation, ignore()), + forMember((dest: PersonenkontextDo) => dest.rolle, ignore()), + forMember((dest: PersonenkontextDo) => dest.loeschungZeitpunkt, ignore()), + forMember((dest: PersonenkontextDo) => dest.sichtfreigabe, ignore()), + ); }; } } diff --git a/src/modules/person/api/person.controller.spec.ts b/src/modules/person/api/person.controller.spec.ts index 65c32a7d0..1b5584b93 100644 --- a/src/modules/person/api/person.controller.spec.ts +++ b/src/modules/person/api/person.controller.spec.ts @@ -8,7 +8,7 @@ import { Geschlecht, Vertrauensstufe } from '../domain/person.enums.js'; import { Jahrgangsstufe, Personenstatus, Rolle, SichtfreigabeType } from '../domain/personenkontext.enums.js'; import { CreatePersonBodyParams } from './create-person.body.params.js'; import { CreatePersonenkontextBodyParams } from './create-personenkontext.body.params.js'; -import { CreatedPersonenkontextDto } from './created-personenkontext.dto.js'; +import { SavedPersonenkontextDto } from './saved-personenkontext.dto.js'; import { PersonApiMapperProfile } from './person-api.mapper.profile.js'; import { PersonBirthParams } from './person-birth.params.js'; import { PersonByIdParams } from './person-by-id.param.js'; @@ -191,7 +191,7 @@ describe('PersonController', () => { personenstatus: Personenstatus.AKTIV, referrer: 'referrer', }; - const ucResult: CreatedPersonenkontextDto = { + const ucResult: SavedPersonenkontextDto = { id: faker.string.uuid(), mandant: faker.string.uuid(), organisation: { diff --git a/src/modules/person/api/person.controller.ts b/src/modules/person/api/person.controller.ts index 8d0e7c752..9bc78a1cd 100644 --- a/src/modules/person/api/person.controller.ts +++ b/src/modules/person/api/person.controller.ts @@ -33,7 +33,7 @@ import { CreatePersonBodyParams } from './create-person.body.params.js'; import { CreatePersonDto } from './create-person.dto.js'; import { CreatePersonenkontextBodyParams } from './create-personenkontext.body.params.js'; import { CreatePersonenkontextDto } from './create-personenkontext.dto.js'; -import { CreatedPersonenkontextDto } from './created-personenkontext.dto.js'; +import { SavedPersonenkontextDto } from './saved-personenkontext.dto.js'; import { FindPersonendatensatzDto } from './find-personendatensatz.dto.js'; import { FindPersonenkontextDto } from './find-personenkontext.dto.js'; import { PersonByIdParams } from './person-by-id.param.js'; @@ -105,9 +105,9 @@ export class PersonController { ); personenkontextDto.personId = pathParams.personId; - const createdPersonenkontext: CreatedPersonenkontextDto = + const createdPersonenkontext: SavedPersonenkontextDto = await this.personenkontextUc.createPersonenkontext(personenkontextDto); - return this.mapper.map(createdPersonenkontext, CreatedPersonenkontextDto, PersonenkontextResponse); + return this.mapper.map(createdPersonenkontext, SavedPersonenkontextDto, PersonenkontextResponse); } @Get(':personId/personenkontexte') diff --git a/src/modules/person/api/personenkontext.controller.ts b/src/modules/person/api/personenkontext.controller.ts index a8661d2e8..9d2f08cf3 100644 --- a/src/modules/person/api/personenkontext.controller.ts +++ b/src/modules/person/api/personenkontext.controller.ts @@ -1,6 +1,6 @@ import { Mapper } from '@automapper/core'; import { getMapperToken } from '@automapper/nestjs'; -import { Controller, Get, HttpException, HttpStatus, Inject, Param, Query } from '@nestjs/common'; +import { Body, Controller, Get, HttpException, HttpStatus, Inject, Param, Put, Query } from '@nestjs/common'; import { ApiBadRequestResponse, ApiForbiddenResponse, @@ -14,6 +14,7 @@ import { Public } from 'nest-keycloak-connect'; import { EntityNotFoundError } from '../../../shared/error/entity-not-found.error.js'; import { Paged } from '../../../shared/paging/paged.js'; import { PagedResponse } from '../../../shared/paging/paged.response.js'; +import { PagingHeadersObject } from '../../../shared/paging/paging.enums.js'; import { FindPersonenkontextByIdDto } from './find-personenkontext-by-id.dto.js'; import { FindPersonenkontextByIdParams } from './find-personenkontext-by-id.params.js'; import { FindPersonenkontextDto } from './find-personenkontext.dto.js'; @@ -21,9 +22,12 @@ import { PersonendatensatzDto } from './personendatensatz.dto.js'; import { PersonendatensatzResponse } from './personendatensatz.response.js'; import { PersonenkontextQueryParams } from './personenkontext-query.params.js'; import { PersonenkontextDto } from './personenkontext.dto.js'; +import { PersonenkontextResponse } from './personenkontext.response.js'; import { PersonenkontextUc } from './personenkontext.uc.js'; import { PersonenkontextdatensatzResponse } from './personenkontextdatensatz.response.js'; -import { PagingHeadersObject } from '../../../shared/paging/paging.enums.js'; +import { UpdatePersonenkontextBodyParams } from './update-personenkontext.body.params.js'; +import { UpdatePersonenkontextDto } from './update-personenkontext.dto.js'; +import { SavedPersonenkontextDto } from './saved-personenkontext.dto.js'; @Public() @ApiTags('personenkontexte') @@ -104,4 +108,30 @@ export class PersonenkontextController { return response; } + + @Put(':personenkontextId') + @ApiOkResponse({ + description: 'The personenkontext was successfully updated.', + type: PersonenkontextResponse, + }) + @ApiBadRequestResponse({ description: 'Request has wrong format.' }) + @ApiUnauthorizedResponse({ description: 'Request is not authorized.' }) + @ApiNotFoundResponse({ description: 'The personenkontext was not found.' }) + @ApiForbiddenResponse({ description: 'Insufficient permissions to perform operation.' }) + @ApiInternalServerErrorResponse({ description: 'An internal server error occurred.' }) + public async updatePersonenkontextWithId( + @Param() params: FindPersonenkontextByIdParams, + @Body() body: UpdatePersonenkontextBodyParams, + ): Promise { + const dto: UpdatePersonenkontextDto = this.mapper.map( + body, + UpdatePersonenkontextBodyParams, + UpdatePersonenkontextDto, + ); + dto.id = params.personenkontextId; + + const response: SavedPersonenkontextDto = await this.personenkontextUc.updatePersonenkontext(dto); + + return this.mapper.map(response, SavedPersonenkontextDto, PersonenkontextResponse); + } } diff --git a/src/modules/person/api/personenkontext.dto.ts b/src/modules/person/api/personenkontext.dto.ts index 6aa703656..2c9307c89 100644 --- a/src/modules/person/api/personenkontext.dto.ts +++ b/src/modules/person/api/personenkontext.dto.ts @@ -1,6 +1,6 @@ import { AutoMap } from '@automapper/classes'; import { Jahrgangsstufe, Personenstatus, Rolle, SichtfreigabeType } from '../domain/personenkontext.enums.js'; -import { CreatedPersonenkontextOrganisationDto } from './created-personenkontext-organisation.dto.js'; +import { SavedPersonenkontextOrganisationDto } from './saved-personenkontext-organisation.dto.js'; import { LoeschungDto } from './loeschung.dto.js'; export class PersonenkontextDto { @@ -16,8 +16,8 @@ export class PersonenkontextDto { @AutoMap() public readonly mandant!: string; - @AutoMap(() => CreatedPersonenkontextOrganisationDto) - public readonly organisation!: CreatedPersonenkontextOrganisationDto; + @AutoMap(() => SavedPersonenkontextOrganisationDto) + public readonly organisation!: SavedPersonenkontextOrganisationDto; @AutoMap(() => String) public readonly rolle!: Rolle; diff --git a/src/modules/person/api/personenkontext.response.ts b/src/modules/person/api/personenkontext.response.ts index c3bc49538..92b9b6c37 100644 --- a/src/modules/person/api/personenkontext.response.ts +++ b/src/modules/person/api/personenkontext.response.ts @@ -1,7 +1,7 @@ import { AutoMap } from '@automapper/classes'; import { ApiProperty } from '@nestjs/swagger'; import { Jahrgangsstufe, Personenstatus, Rolle, SichtfreigabeType } from '../domain/personenkontext.enums.js'; -import { CreatedPersonenkontextOrganisationDto } from './created-personenkontext-organisation.dto.js'; +import { SavedPersonenkontextOrganisationDto } from './saved-personenkontext-organisation.dto.js'; import { LoeschungResponse } from './loeschung.response.js'; export class PersonenkontextResponse { @@ -17,9 +17,9 @@ export class PersonenkontextResponse { @ApiProperty() public readonly mandant!: string; - @AutoMap(() => CreatedPersonenkontextOrganisationDto) + @AutoMap(() => SavedPersonenkontextOrganisationDto) @ApiProperty() - public readonly organisation!: CreatedPersonenkontextOrganisationDto; + public readonly organisation!: SavedPersonenkontextOrganisationDto; @AutoMap(() => String) @ApiProperty() diff --git a/src/modules/person/api/personenkontext.uc.spec.ts b/src/modules/person/api/personenkontext.uc.spec.ts index 3fc8995a7..ccb7917bf 100644 --- a/src/modules/person/api/personenkontext.uc.spec.ts +++ b/src/modules/person/api/personenkontext.uc.spec.ts @@ -11,7 +11,7 @@ import { PersonenkontextDo } from '../domain/personenkontext.do.js'; import { Personenstatus, Rolle, SichtfreigabeType } from '../domain/personenkontext.enums.js'; import { PersonenkontextService } from '../domain/personenkontext.service.js'; import { CreatePersonenkontextDto } from './create-personenkontext.dto.js'; -import { CreatedPersonenkontextDto } from './created-personenkontext.dto.js'; +import { SavedPersonenkontextDto } from './saved-personenkontext.dto.js'; import { FindPersonenkontextByIdDto } from './find-personenkontext-by-id.dto.js'; import { FindPersonenkontextDto } from './find-personenkontext.dto.js'; import { PersonApiMapperProfile } from './person-api.mapper.profile.js'; @@ -66,7 +66,7 @@ describe('PersonenkontextUc', () => { value: personenkontextDo, }); - const createPersonPromise: Promise = sut.createPersonenkontext( + const createPersonPromise: Promise = sut.createPersonenkontext( {} as CreatePersonenkontextDto, ); @@ -82,7 +82,7 @@ describe('PersonenkontextUc', () => { error: error, }); - const createPersonPromise: Promise = sut.createPersonenkontext( + const createPersonPromise: Promise = sut.createPersonenkontext( {} as CreatePersonenkontextDto, ); diff --git a/src/modules/person/api/personenkontext.uc.ts b/src/modules/person/api/personenkontext.uc.ts index f20078de3..a8e579d05 100644 --- a/src/modules/person/api/personenkontext.uc.ts +++ b/src/modules/person/api/personenkontext.uc.ts @@ -7,12 +7,14 @@ import { PersonService } from '../domain/person.service.js'; import { PersonenkontextDo } from '../domain/personenkontext.do.js'; import { PersonenkontextService } from '../domain/personenkontext.service.js'; import { CreatePersonenkontextDto } from './create-personenkontext.dto.js'; -import { CreatedPersonenkontextDto } from './created-personenkontext.dto.js'; +import { SavedPersonenkontextDto } from './saved-personenkontext.dto.js'; import { FindPersonenkontextByIdDto } from './find-personenkontext-by-id.dto.js'; import { FindPersonenkontextDto } from './find-personenkontext.dto.js'; import { PersonDto } from './person.dto.js'; import { PersonendatensatzDto } from './personendatensatz.dto.js'; import { PersonenkontextDto } from './personenkontext.dto.js'; +import { UpdatePersonenkontextDto } from './update-personenkontext.dto.js'; +import { DomainError } from '../../../shared/error/domain.error.js'; @Injectable() export class PersonenkontextUc { @@ -24,7 +26,7 @@ export class PersonenkontextUc { public async createPersonenkontext( personenkontextDto: CreatePersonenkontextDto, - ): Promise { + ): Promise { const personenkontextDo: PersonenkontextDo = this.mapper.map( personenkontextDto, CreatePersonenkontextDto, @@ -33,7 +35,7 @@ export class PersonenkontextUc { const result: Result> = await this.personenkontextService.createPersonenkontext(personenkontextDo); if (result.ok) { - return this.mapper.map(result.value, PersonenkontextDo, CreatedPersonenkontextDto); + return this.mapper.map(result.value, PersonenkontextDo, SavedPersonenkontextDto); } throw result.error; } @@ -86,4 +88,28 @@ export class PersonenkontextUc { personenkontexte: [this.mapper.map(personenkontextResult.value, PersonenkontextDo, PersonenkontextDto)], }); } + + public async updatePersonenkontext(updateDto: UpdatePersonenkontextDto): Promise { + const personenkontextDo: PersonenkontextDo = this.mapper.map( + updateDto, + UpdatePersonenkontextDto, + PersonenkontextDo, + ); + const result: Result< + PersonenkontextDo, + DomainError + > = await this.personenkontextService.updatePersonenkontext(personenkontextDo); + + if (!result.ok) { + throw result.error; + } + + const updated: SavedPersonenkontextDto = this.mapper.map( + result.value, + PersonenkontextDo, + SavedPersonenkontextDto, + ); + + return updated; + } } diff --git a/src/modules/person/api/saved-personenkontext-organisation.dto.ts b/src/modules/person/api/saved-personenkontext-organisation.dto.ts new file mode 100644 index 000000000..ede9d7410 --- /dev/null +++ b/src/modules/person/api/saved-personenkontext-organisation.dto.ts @@ -0,0 +1,3 @@ +export class SavedPersonenkontextOrganisationDto { + public readonly id!: string; +} diff --git a/src/modules/person/api/created-personenkontext.dto.ts b/src/modules/person/api/saved-personenkontext.dto.ts similarity index 78% rename from src/modules/person/api/created-personenkontext.dto.ts rename to src/modules/person/api/saved-personenkontext.dto.ts index 7d135cac6..df4b687f0 100644 --- a/src/modules/person/api/created-personenkontext.dto.ts +++ b/src/modules/person/api/saved-personenkontext.dto.ts @@ -1,9 +1,9 @@ import { AutoMap } from '@automapper/classes'; import { Jahrgangsstufe, Personenstatus, Rolle, SichtfreigabeType } from '../domain/personenkontext.enums.js'; -import { CreatedPersonenkontextOrganisationDto } from './created-personenkontext-organisation.dto.js'; +import { SavedPersonenkontextOrganisationDto } from './saved-personenkontext-organisation.dto.js'; import { LoeschungDto } from './loeschung.dto.js'; -export class CreatedPersonenkontextDto { +export class SavedPersonenkontextDto { @AutoMap() public readonly id!: string; @@ -14,7 +14,7 @@ export class CreatedPersonenkontextDto { public readonly mandant!: string; @AutoMap() - public readonly organisation!: CreatedPersonenkontextOrganisationDto; + public readonly organisation!: SavedPersonenkontextOrganisationDto; @AutoMap() public readonly rolle!: Rolle; diff --git a/src/modules/person/api/update-personenkontext.body.params.ts b/src/modules/person/api/update-personenkontext.body.params.ts new file mode 100644 index 000000000..aa8129cec --- /dev/null +++ b/src/modules/person/api/update-personenkontext.body.params.ts @@ -0,0 +1,37 @@ +import { AutoMap } from '@automapper/classes'; +import { ApiProperty } from '@nestjs/swagger'; +import { IsEnum, IsOptional, IsString } from 'class-validator'; +import { Jahrgangsstufe, Personenstatus } from '../domain/personenkontext.enums.js'; + +export class UpdatePersonenkontextBodyParams { + @AutoMap() + @IsString() + @IsOptional() + @ApiProperty({ required: false, description: 'The new referrer of the personenkontext.' }) + public readonly referrer?: string; + + @AutoMap(() => String) + @IsEnum(Personenstatus) + @IsOptional() + @ApiProperty({ + enum: Personenstatus, + required: false, + description: 'The new personenstatus of the personenkontext.', + }) + public readonly personenstatus?: Personenstatus; + + @AutoMap(() => String) + @IsEnum(Jahrgangsstufe) + @IsOptional() + @ApiProperty({ + enum: Jahrgangsstufe, + required: false, + description: 'The new jahrgangsstufe of the personenkontext.', + }) + public readonly jahrgangsstufe?: Jahrgangsstufe; + + @AutoMap() + @IsString() + @ApiProperty({ required: true, description: 'The revision of the personenkontext.' }) + public readonly revision!: string; +} diff --git a/src/modules/person/api/update-personenkontext.dto.ts b/src/modules/person/api/update-personenkontext.dto.ts new file mode 100644 index 000000000..293a18887 --- /dev/null +++ b/src/modules/person/api/update-personenkontext.dto.ts @@ -0,0 +1,19 @@ +import { AutoMap } from '@automapper/classes'; +import { Jahrgangsstufe, Personenstatus } from '../domain/personenkontext.enums.js'; + +export class UpdatePersonenkontextDto { + @AutoMap() + public id!: string; + + @AutoMap() + public readonly referrer?: string; + + @AutoMap(() => String) + public readonly personenstatus?: Personenstatus; + + @AutoMap(() => String) + public readonly jahrgangsstufe?: Jahrgangsstufe; + + @AutoMap() + public readonly revision!: string; +} diff --git a/src/modules/person/domain/personenkontext.service.ts b/src/modules/person/domain/personenkontext.service.ts index bd7e47e83..748775753 100644 --- a/src/modules/person/domain/personenkontext.service.ts +++ b/src/modules/person/domain/personenkontext.service.ts @@ -8,6 +8,8 @@ import { PersonenkontextRepo } from '../persistence/personenkontext.repo.js'; import { PersonenkontextScope } from '../persistence/personenkontext.scope.js'; import { PersonDo } from './person.do.js'; import { PersonenkontextDo } from './personenkontext.do.js'; +import { MismatchedRevisionError } from '../../../shared/error/mismatched-revision-error.error.js'; +import { EntityCouldNotBeUpdated } from '../../../shared/error/entity-could-not-be-updated.error.js'; @Injectable() export class PersonenkontextService { @@ -66,4 +68,45 @@ export class PersonenkontextService { return result; } + + public async updatePersonenkontext( + personenkontextDo: PersonenkontextDo, + ): Promise, DomainError>> { + const storedPersonenkontext: Option> = await this.personenkontextRepo.findById( + personenkontextDo.id, + ); + if (!storedPersonenkontext) { + return { ok: false, error: new EntityNotFoundError('Personenkontext', personenkontextDo.id) }; + } + + if (personenkontextDo.revision !== storedPersonenkontext.revision) { + return { + ok: false, + error: new MismatchedRevisionError( + `Revision ${personenkontextDo.revision} does not match revision ${storedPersonenkontext.revision} of stored personenkontext.`, + ), + }; + } + + const newRevision: string = (parseInt(storedPersonenkontext.revision) + 1).toString(); + const newData: { + referrer?: string; + personenstatus?: string; + jahrgangsstufe?: string; + revision: string; + } = { + referrer: personenkontextDo.referrer, + personenstatus: personenkontextDo.personenstatus, + jahrgangsstufe: personenkontextDo.jahrgangsstufe, + revision: newRevision, + }; + Object.assign(storedPersonenkontext, newData); + + const saved: Option> = await this.personenkontextRepo.save(storedPersonenkontext); + if (!saved) { + return { ok: false, error: new EntityCouldNotBeUpdated('Personenkontext', storedPersonenkontext.id) }; + } + + return { ok: true, value: saved }; + } } diff --git a/src/shared/error/entity-could-not-be-updated.error.ts b/src/shared/error/entity-could-not-be-updated.error.ts new file mode 100644 index 000000000..327d9af7b --- /dev/null +++ b/src/shared/error/entity-could-not-be-updated.error.ts @@ -0,0 +1,7 @@ +import { DomainError } from './domain.error.js'; + +export class EntityCouldNotBeUpdated extends DomainError { + public constructor(entityName: string, entityId: string, details?: unknown[] | Record) { + super(`${entityName} with ID ${entityId} could not be updated`, 'ENTITY_COULD_NOT_BE_UPDATED', details); + } +} diff --git a/src/shared/error/index.ts b/src/shared/error/index.ts index 9d0526111..146f4199d 100644 --- a/src/shared/error/index.ts +++ b/src/shared/error/index.ts @@ -1,6 +1,7 @@ export * from './domain.error.js'; +export * from './entity-could-not-be-updated.error.js'; export * from './entity-not-found.error.js'; export * from './keycloak-client.error.js'; export * from './mapping.error.js'; +export * from './mismatched-revision-error.error.js'; export * from './person-already-exists.error.js'; -export * from './entity-not-found.error.js'; diff --git a/src/shared/error/mismatched-revision-error.error.ts b/src/shared/error/mismatched-revision-error.error.ts new file mode 100644 index 000000000..1846dedfa --- /dev/null +++ b/src/shared/error/mismatched-revision-error.error.ts @@ -0,0 +1,7 @@ +import { DomainError } from './domain.error.js'; + +export class MismatchedRevisionError extends DomainError { + public constructor(message: string, details?: unknown[] | Record) { + super(message, 'MISMATCHED_REVISION_ERROR', details); + } +}