diff --git a/src/StreetNameRegistry.Api.BackOffice.Abstractions/Validation/RenameStreetName.cs b/src/StreetNameRegistry.Api.BackOffice.Abstractions/Validation/RenameStreetName.cs index a93172c2f..2916452e9 100644 --- a/src/StreetNameRegistry.Api.BackOffice.Abstractions/Validation/RenameStreetName.cs +++ b/src/StreetNameRegistry.Api.BackOffice.Abstractions/Validation/RenameStreetName.cs @@ -29,6 +29,14 @@ public static class SourceAndDestinationStreetNameAreNotInSameMunicipality public static TicketError ToTicketError() => new TicketError(Message, Code); } + + public static class SourceAndDestinationStreetNameAreTheSame + { + public const string Code = "BronStraatnaamIdHetzelfdeAlsDoelStraatnaam"; + public static string Message(string straatNaamId) => $"Het doelStraatnaamId is hetzelfde als de bron straatnaam: {straatNaamId}."; + + public static TicketError ToTicketError(string straatNaamId) => new TicketError(Message(straatNaamId), Code); + } } } } diff --git a/src/StreetNameRegistry.Api.BackOffice/Validators/RenameStreetNameRequestValidator.cs b/src/StreetNameRegistry.Api.BackOffice/Validators/RenameStreetNameRequestValidator.cs index 86a0936d8..e9bc206f1 100644 --- a/src/StreetNameRegistry.Api.BackOffice/Validators/RenameStreetNameRequestValidator.cs +++ b/src/StreetNameRegistry.Api.BackOffice/Validators/RenameStreetNameRequestValidator.cs @@ -3,7 +3,9 @@ namespace StreetNameRegistry.Api.BackOffice.Validators using Abstractions; using Abstractions.Requests; using Abstractions.Validation; + using Azure.Core; using Be.Vlaanderen.Basisregisters.GrAr.Edit.Validators; + using Be.Vlaanderen.Basisregisters.GrAr.Legacy; using Be.Vlaanderen.Basisregisters.GrAr.Legacy.Straatnaam; using FluentValidation; @@ -15,6 +17,18 @@ public RenameStreetNameRequestValidator(BackOfficeContext backOfficeContext) .Must(straatNaamId => OsloPuriValidator.TryParseIdentifier(straatNaamId, out var persistentLocalId) && int.TryParse(persistentLocalId, out _)) .DependentRules(() => + { + RuleFor(x => x.DoelStraatnaamId) + .MustAsync(async (request, straatNaamId, ct) => + { + OsloPuriValidator.TryParseIdentifier(straatNaamId, out var persistentLocalIdAsString); + + var persistentLocalId = int.Parse(persistentLocalIdAsString); + return persistentLocalId != request.StreetNamePersistentLocalId; + }) + .WithMessage((_, straatNaamId) => ValidationErrors.RenameStreetName.SourceAndDestinationStreetNameAreTheSame.Message(straatNaamId)) + .WithErrorCode(ValidationErrors.RenameStreetName.SourceAndDestinationStreetNameAreTheSame.Code); + RuleFor(x => x.DoelStraatnaamId) .MustAsync(async (straatNaamId, ct) => { @@ -49,13 +63,15 @@ public RenameStreetNameRequestValidator(BackOfficeContext backOfficeContext) return municipalityIdBySourcePersistentLocalId is null || municipalityIdByDestinationPersistentLocalId is null - || municipalityIdByDestinationPersistentLocalId.MunicipalityId == municipalityIdBySourcePersistentLocalId.MunicipalityId; + || municipalityIdByDestinationPersistentLocalId.MunicipalityId == + municipalityIdBySourcePersistentLocalId.MunicipalityId; }) .WithMessage(ValidationErrors.RenameStreetName.SourceAndDestinationStreetNameAreNotInSameMunicipality.Message) .WithErrorCode(ValidationErrors.RenameStreetName.SourceAndDestinationStreetNameAreNotInSameMunicipality.Code) ) .WithMessage((_, straatNaamId) => ValidationErrors.Common.StreetNameInvalid.Message(straatNaamId)) - .WithErrorCode(ValidationErrors.Common.StreetNameInvalid.Code)) + .WithErrorCode(ValidationErrors.Common.StreetNameInvalid.Code); + }) .WithMessage(ValidationErrors.Common.StreetNameNotFound.Message) .WithErrorCode(ValidationErrors.Common.StreetNameNotFound.Code); } diff --git a/src/StreetNameRegistry/Municipality/Exceptions/SourceAndDestinationStreetNameAreTheSameException.cs b/src/StreetNameRegistry/Municipality/Exceptions/SourceAndDestinationStreetNameAreTheSameException.cs new file mode 100644 index 000000000..0e4c1212d --- /dev/null +++ b/src/StreetNameRegistry/Municipality/Exceptions/SourceAndDestinationStreetNameAreTheSameException.cs @@ -0,0 +1,30 @@ +namespace StreetNameRegistry.Municipality.Exceptions +{ + using System; + using System.Runtime.Serialization; + + [Serializable] + public sealed class SourceAndDestinationStreetNameAreTheSameException : StreetNameRegistryException + { + /// + /// The streetname id which already exists + /// + public string StreetNameId { get; } + + public SourceAndDestinationStreetNameAreTheSameException() + { + StreetNameId = string.Empty; + } + + public SourceAndDestinationStreetNameAreTheSameException(string streetNameId) + { + StreetNameId = streetNameId; + } + + private SourceAndDestinationStreetNameAreTheSameException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + StreetNameId = string.Empty; + } + } +} diff --git a/src/StreetNameRegistry/Municipality/Municipality_StreetName.cs b/src/StreetNameRegistry/Municipality/Municipality_StreetName.cs index 7086a1ea6..ad2090dd9 100644 --- a/src/StreetNameRegistry/Municipality/Municipality_StreetName.cs +++ b/src/StreetNameRegistry/Municipality/Municipality_StreetName.cs @@ -219,6 +219,9 @@ public void RemoveStreetName(PersistentLocalId persistentLocalId) public void RenameStreetName(PersistentLocalId sourcePersistentLocalId, PersistentLocalId destinationPersistentLocalId) { + if(sourcePersistentLocalId == destinationPersistentLocalId) + throw new SourceAndDestinationStreetNameAreTheSameException(sourcePersistentLocalId); + var streetName = StreetNames.GetNotRemovedByPersistentLocalId(sourcePersistentLocalId); var destinationStreetName = StreetNames.GetNotRemovedByPersistentLocalId(destinationPersistentLocalId); diff --git a/test/StreetNameRegistry.Tests/AggregateTests/WhenRenamingStreetName/GivenMunicipality.cs b/test/StreetNameRegistry.Tests/AggregateTests/WhenRenamingStreetName/GivenMunicipality.cs index 8faeca20e..7c97997b3 100644 --- a/test/StreetNameRegistry.Tests/AggregateTests/WhenRenamingStreetName/GivenMunicipality.cs +++ b/test/StreetNameRegistry.Tests/AggregateTests/WhenRenamingStreetName/GivenMunicipality.cs @@ -5,6 +5,7 @@ namespace StreetNameRegistry.Tests.AggregateTests.WhenRenamingStreetName using Be.Vlaanderen.Basisregisters.AggregateSource; using Be.Vlaanderen.Basisregisters.AggregateSource.Snapshotting; using Be.Vlaanderen.Basisregisters.AggregateSource.Testing; + using Be.Vlaanderen.Basisregisters.GrAr.Provenance; using Builders; using FluentAssertions; using global::AutoFixture; @@ -61,6 +62,34 @@ public void ThenSourceStreetNameWasRenamedAndDestinationStreetNameWasApproved() new Fact(_streamId, new StreetNameWasRenamed(_municipalityId, command.PersistentLocalId, command.DestinationPersistentLocalId)))); } + [Fact] + public void WithDestinationSameAsSource_ThenThrowsSourceAndDestinationStreetNameAreTheSameException() + { + var command = new RenameStreetName( + Fixture.Create(), + new PersistentLocalId(1), + new PersistentLocalId(1), + Fixture.Create()); + + var sourceStreetNameWasProposed = new StreetNameWasProposedV2Builder(Fixture) + .WithPersistentLocalId(command.PersistentLocalId) + .Build(); + + var sourceStreetNameWasApproved = new StreetNameWasApprovedBuilder(Fixture) + .WithPersistentLocalId(sourceStreetNameWasProposed.PersistentLocalId) + .Build(); + + // Act, assert + Assert(new Scenario() + .Given(_streamId, + Fixture.Create(), + Fixture.Create(), + sourceStreetNameWasProposed, + sourceStreetNameWasApproved) + .When(command) + .Throws(new SourceAndDestinationStreetNameAreTheSameException(command.PersistentLocalId))); + } + [Fact] public void WithApprovedDestinationStreetName_ThenSourceStreetNameWasRenamed() { diff --git a/test/StreetNameRegistry.Tests/BackOffice/Validators/RenameStreetNameRequestValidatorTests.cs b/test/StreetNameRegistry.Tests/BackOffice/Validators/RenameStreetNameRequestValidatorTests.cs index 749097037..6ad40e9eb 100644 --- a/test/StreetNameRegistry.Tests/BackOffice/Validators/RenameStreetNameRequestValidatorTests.cs +++ b/test/StreetNameRegistry.Tests/BackOffice/Validators/RenameStreetNameRequestValidatorTests.cs @@ -101,5 +101,28 @@ public async Task GivenStreetNamesInDifferentMunicipalities_ReturnsExpectedError .WithErrorMessage("De meegegeven straatnamen liggen in verschillende gemeenten.") .WithErrorCode("StraatnamenAndereGemeenten"); } + + [Fact] + public async Task GivenSourceAndDestinationStreetNameAreTheSame_ReturnsExpectedError() + { + var municipalityId = Guid.NewGuid(); + var persistentLocalId = 10000; + _backOfficeContext.MunicipalityIdByPersistentLocalId.Add(new MunicipalityIdByPersistentLocalId( + persistentLocalId, + municipalityId, + "NISCODE")); + await _backOfficeContext.SaveChangesAsync(); + + var doelStraatnaamId = $"https://data.vlaanderen.be/id/straatnaam/{persistentLocalId}"; + var result = await _validator.TestValidateAsync(new RenameStreetNameRequest + { + DoelStraatnaamId = doelStraatnaamId, + StreetNamePersistentLocalId = persistentLocalId + }); + + result.ShouldHaveValidationErrorFor(nameof(RenameStreetNameRequest.DoelStraatnaamId)) + .WithErrorMessage($"Het doelStraatnaamId is hetzelfde als de bron straatnaam: {doelStraatnaamId}.") + .WithErrorCode("BronStraatnaamIdHetzelfdeAlsDoelStraatnaam"); + } } }