diff --git a/src/AssociationRegistry.Acm.Api/Projections/VerenigingenPerInszProjection.cs b/src/AssociationRegistry.Acm.Api/Projections/VerenigingenPerInszProjection.cs index ee9a24e4d..39c838445 100644 --- a/src/AssociationRegistry.Acm.Api/Projections/VerenigingenPerInszProjection.cs +++ b/src/AssociationRegistry.Acm.Api/Projections/VerenigingenPerInszProjection.cs @@ -72,6 +72,16 @@ public async Task Project(IEvent verenigingWerdGestopt, I ops.StoreObjects(docs); } + public async Task Project(IEvent verenigingWerdVerwijderd, IDocumentOperations ops) + { + var docs = new List(); + + docs.Add(await VerenigingDocumentProjector.Apply(verenigingWerdVerwijderd, ops)); + docs.AddRange(await VerenigingenPerInszProjector.Apply(verenigingWerdVerwijderd, ops)); + + ops.StoreObjects(docs); + } + private static class VerenigingenPerInszProjector { public static async Task> Apply( @@ -183,6 +193,26 @@ public static async Task> Apply( return docs; } + + public static async Task> Apply( + IEvent verenigingWerdVerwijderd, + IDocumentOperations ops) + { + var docs = new List(); + var documents = await ops.GetVerenigingenPerInszDocuments(verenigingWerdVerwijderd.StreamKey!); + + foreach (var verenigingenPerInszDocument in documents) + { + verenigingenPerInszDocument.Verenigingen = verenigingenPerInszDocument.Verenigingen + .Where(v => v.VCode != + verenigingWerdVerwijderd.StreamKey) + .ToList(); + + docs.Add(verenigingenPerInszDocument); + } + + return docs; + } } private static class VerenigingDocumentProjector @@ -220,5 +250,14 @@ public static async Task Apply(IEvent return verenigingDocument; } + + public static async Task Apply( + IEvent verenigingWerdVerwijderd, + IDocumentOperations ops) + { + ops.Delete(verenigingWerdVerwijderd.StreamKey!); + + return await ops.GetVerenigingDocument(verenigingWerdVerwijderd.StreamKey!); + } } } diff --git a/src/AssociationRegistry.Acm.Schema/VerenigingenPerInsz/VerenigingDocument.cs b/src/AssociationRegistry.Acm.Schema/VerenigingenPerInsz/VerenigingDocument.cs index a2eeedf1e..f8d93f01a 100644 --- a/src/AssociationRegistry.Acm.Schema/VerenigingenPerInsz/VerenigingDocument.cs +++ b/src/AssociationRegistry.Acm.Schema/VerenigingenPerInsz/VerenigingDocument.cs @@ -1,8 +1,9 @@ namespace AssociationRegistry.Acm.Schema.VerenigingenPerInsz; +using Marten.Metadata; using Marten.Schema; -public class VerenigingDocument +public class VerenigingDocument: ISoftDeleted { [Identity] public string VCode { get; set; } = null!; @@ -10,4 +11,6 @@ public class VerenigingDocument public string Naam { get; set; } = null!; public string Status { get; set; } = null!; public string KboNummer { get; set; } = null!; + public bool Deleted { get; set; } + public DateTimeOffset? DeletedAt { get; set; } } diff --git a/src/AssociationRegistry.Admin.Api/DuplicateDetection/SearchDuplicateVerenigingDetectionService.cs b/src/AssociationRegistry.Admin.Api/DuplicateDetection/SearchDuplicateVerenigingDetectionService.cs index 3b38a42dc..f8bfc97db 100644 --- a/src/AssociationRegistry.Admin.Api/DuplicateDetection/SearchDuplicateVerenigingDetectionService.cs +++ b/src/AssociationRegistry.Admin.Api/DuplicateDetection/SearchDuplicateVerenigingDetectionService.cs @@ -36,7 +36,8 @@ await _client q => q.Bool( b => b.Must( MatchOpNaam(naam), - IsNietGestopt + IsNietGestopt, + IsNietVerwijderd ) .Filter(MatchOpPostcodeOfGemeente(gemeentes, postcodes) ) @@ -70,6 +71,12 @@ private static QueryContainer IsNietGestopt(QueryContainerDescriptor descriptor) + { + return descriptor.Term(queryDescriptor => queryDescriptor.Field(document => document.IsVerwijderd) + .Value(false)); + } + private static Func, QueryContainer> MatchOpPostcode(string[] postcodes) { return postalCodesQuery => postalCodesQuery diff --git a/src/AssociationRegistry.Admin.Api/Infrastructure/ProjectionHostController.cs b/src/AssociationRegistry.Admin.Api/ProjectieBeheer/ProjectionHostController.cs similarity index 96% rename from src/AssociationRegistry.Admin.Api/Infrastructure/ProjectionHostController.cs rename to src/AssociationRegistry.Admin.Api/ProjectieBeheer/ProjectionHostController.cs index fbb2f9ab1..b26c8d608 100644 --- a/src/AssociationRegistry.Admin.Api/Infrastructure/ProjectionHostController.cs +++ b/src/AssociationRegistry.Admin.Api/ProjectieBeheer/ProjectionHostController.cs @@ -1,7 +1,8 @@ -namespace AssociationRegistry.Admin.Api.Infrastructure; +namespace AssociationRegistry.Admin.Api.ProjectieBeheer; +using AssociationRegistry.Admin.Api.Infrastructure; +using AssociationRegistry.Admin.Api.Infrastructure.HttpClients; using Be.Vlaanderen.Basisregisters.Api; -using HttpClients; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.Net.Http; diff --git a/src/AssociationRegistry.Admin.Api/Verenigingen/Search/SearchVerenigingenController.cs b/src/AssociationRegistry.Admin.Api/Verenigingen/Search/SearchVerenigingenController.cs index 0f08a1f63..ac6a1609d 100644 --- a/src/AssociationRegistry.Admin.Api/Verenigingen/Search/SearchVerenigingenController.cs +++ b/src/AssociationRegistry.Admin.Api/Verenigingen/Search/SearchVerenigingenController.cs @@ -103,7 +103,8 @@ private static async Task> Search( boolQueryDescriptor => boolQueryDescriptor.Must( queryContainerDescriptor => queryContainerDescriptor.QueryString( queryStringQueryDescriptor => queryStringQueryDescriptor.Query(q) - ) + ), + descriptor => descriptor.Term(document => document.IsVerwijderd, false) ) ) ) diff --git a/src/AssociationRegistry.Admin.Api/Verenigingen/Verwijder/RequestModels/VerwijderVerenigingRequest.cs b/src/AssociationRegistry.Admin.Api/Verenigingen/Verwijder/RequestModels/VerwijderVerenigingRequest.cs new file mode 100644 index 000000000..10338fe84 --- /dev/null +++ b/src/AssociationRegistry.Admin.Api/Verenigingen/Verwijder/RequestModels/VerwijderVerenigingRequest.cs @@ -0,0 +1,15 @@ +namespace AssociationRegistry.Admin.Api.Verenigingen.Verwijderen.RequestModels; + +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; + +[DataContract] +public class VerwijderVerenigingRequest +{ + /// + /// De reden waarom de vereniging verwijderd werd. + /// + [DataMember] + [Required] + public string Reden { get; set; } +} diff --git a/src/AssociationRegistry.Admin.Api/Verenigingen/Verwijder/VerwijderVerenigingController.cs b/src/AssociationRegistry.Admin.Api/Verenigingen/Verwijder/VerwijderVerenigingController.cs new file mode 100644 index 000000000..383f03f0d --- /dev/null +++ b/src/AssociationRegistry.Admin.Api/Verenigingen/Verwijder/VerwijderVerenigingController.cs @@ -0,0 +1,56 @@ +namespace AssociationRegistry.Admin.Api.Verenigingen.Verwijder; + +using Acties.VerwijderVereniging; +using Infrastructure.ConfigurationBindings; +using Infrastructure.Extensions; +using Infrastructure.Middleware; +using Framework; +using Vereniging; +using Be.Vlaanderen.Basisregisters.Api; +using FluentValidation; +using Infrastructure.Swagger.Annotations; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using Verwijderen.RequestModels; +using Wolverine; + +[ApiVersion("1.0")] +[AdvertiseApiVersions("1.0")] +[ApiRoute("verenigingen")] +[ApiExplorerSettings(IgnoreApi = true)] +[Authorize(Policy = Program.SuperAdminPolicyName)] +public class VerwijderVerenigingController : ApiController +{ + private readonly IMessageBus _bus; + private readonly AppSettings _appsettings; + private readonly IValidator _validator; + + public VerwijderVerenigingController(IMessageBus bus, AppSettings appsettings, IValidator validator) + { + _bus = bus; + _appsettings = appsettings; + _validator = validator; + } + + [HttpDelete("{vCode}")] + [ConsumesJson] + [ProducesJson] + public async Task Delete( + [FromBody] VerwijderVerenigingRequest? request, + [FromRoute] string vCode, + [FromServices] ICommandMetadataProvider metadataProvider) + { + await _validator.NullValidateAndThrowAsync(request); + + var command = new VerwijderVerenigingCommand(VCode.Create(vCode), request.Reden); + + var metaData = metadataProvider.GetMetadata(); + var envelope = new CommandEnvelope(command, metaData); + var stopResult = await _bus.InvokeAsync(envelope); + + if (!stopResult.HasChanges()) return Ok(); + + return this.AcceptedCommand(_appsettings, stopResult); + } +} diff --git a/src/AssociationRegistry.Admin.Api/Verenigingen/Verwijder/VerwijderVerenigingRequestValidator.cs b/src/AssociationRegistry.Admin.Api/Verenigingen/Verwijder/VerwijderVerenigingRequestValidator.cs new file mode 100644 index 000000000..d86e88754 --- /dev/null +++ b/src/AssociationRegistry.Admin.Api/Verenigingen/Verwijder/VerwijderVerenigingRequestValidator.cs @@ -0,0 +1,15 @@ +namespace AssociationRegistry.Admin.Api.Verenigingen.Verwijderen; + +using FluentValidation; +using Infrastructure.Validation; +using RequestModels; + +public class VerwijderVerenigingRequestValidator : AbstractValidator +{ + public VerwijderVerenigingRequestValidator() + { + this.RequireNotNullOrEmpty(request => request.Reden); + + RuleFor(request => request.Reden).MustNotContainHtml(); + } +} diff --git a/src/AssociationRegistry.Admin.ProjectionHost/Projections/Detail/BeheerVerenigingDetailProjection.cs b/src/AssociationRegistry.Admin.ProjectionHost/Projections/Detail/BeheerVerenigingDetailProjection.cs index 707837303..bcf3e283b 100644 --- a/src/AssociationRegistry.Admin.ProjectionHost/Projections/Detail/BeheerVerenigingDetailProjection.cs +++ b/src/AssociationRegistry.Admin.ProjectionHost/Projections/Detail/BeheerVerenigingDetailProjection.cs @@ -4,6 +4,7 @@ using Marten; using Marten.Events; using Marten.Events.Projections; +using Marten.Schema; using Schema.Detail; public class BeheerVerenigingDetailProjection : EventProjection @@ -133,6 +134,14 @@ public async Task Project(IEvent @event, public async Task Project(IEvent @event, IDocumentOperations ops) => await Update(@event, ops, BeheerVerenigingDetailProjector.Apply); + public async Task Project(IEvent @event, IDocumentOperations ops) + => await SoftDelete(@event.StreamKey, ops); + + private async Task SoftDelete(string? streamKey, IDocumentOperations ops) + { + ops.Delete(streamKey); + } + private static async Task Update( IEvent @event, IDocumentOperations ops, diff --git a/src/AssociationRegistry.Admin.ProjectionHost/Projections/Historiek/BeheerVerenigingHistoriekProjection.cs b/src/AssociationRegistry.Admin.ProjectionHost/Projections/Historiek/BeheerVerenigingHistoriekProjection.cs index 5421e9ec6..1f8e07b8a 100644 --- a/src/AssociationRegistry.Admin.ProjectionHost/Projections/Historiek/BeheerVerenigingHistoriekProjection.cs +++ b/src/AssociationRegistry.Admin.ProjectionHost/Projections/Historiek/BeheerVerenigingHistoriekProjection.cs @@ -122,6 +122,9 @@ public async Task Project(IEvent @event, IDocumentOperati public async Task Project(IEvent @event, IDocumentOperations ops) => await Update(@event, ops, BeheerVerenigingHistoriekProjector.Apply); + public async Task Project(IEvent @event, IDocumentOperations ops) + => await Update(@event, ops, BeheerVerenigingHistoriekProjector.Apply); + public async Task Project( IEvent vertegenwoordigerWerdOvergenomenUitKbo, IDocumentOperations ops) @@ -139,6 +142,7 @@ private static async Task Update( Action, BeheerVerenigingHistoriekDocument> action) where T : notnull => await Update(@event.StreamKey!, @event, ops, action); + private static async Task Update( string vCode, IEvent @event, diff --git a/src/AssociationRegistry.Admin.ProjectionHost/Projections/Historiek/BeheerVerenigingHistoriekProjector.cs b/src/AssociationRegistry.Admin.ProjectionHost/Projections/Historiek/BeheerVerenigingHistoriekProjector.cs index 1fbf29e95..82758e2f6 100644 --- a/src/AssociationRegistry.Admin.ProjectionHost/Projections/Historiek/BeheerVerenigingHistoriekProjector.cs +++ b/src/AssociationRegistry.Admin.ProjectionHost/Projections/Historiek/BeheerVerenigingHistoriekProjector.cs @@ -15,12 +15,7 @@ public class BeheerVerenigingHistoriekProjector public static BeheerVerenigingHistoriekDocument Create( IEvent feitelijkeVerenigingWerdGeregistreerd) { - var beheerVerenigingHistoriekDocument = new BeheerVerenigingHistoriekDocument - { - VCode = feitelijkeVerenigingWerdGeregistreerd.Data.VCode, - Gebeurtenissen = new List(), - Metadata = new Metadata(Sequence: 0, Version: 0), - }; + var beheerVerenigingHistoriekDocument = CreateNewDocument(feitelijkeVerenigingWerdGeregistreerd.Data.VCode); AddHistoriekEntry( feitelijkeVerenigingWerdGeregistreerd, @@ -34,12 +29,7 @@ public static BeheerVerenigingHistoriekDocument Create( public static BeheerVerenigingHistoriekDocument Create( IEvent verenigingMetRechtspersoonlijkheidWerdGeregistreerd) { - var beheerVerenigingHistoriekDocument = new BeheerVerenigingHistoriekDocument - { - VCode = verenigingMetRechtspersoonlijkheidWerdGeregistreerd.Data.VCode, - Gebeurtenissen = new List(), - Metadata = new Metadata(Sequence: 0, Version: 0), - }; + var beheerVerenigingHistoriekDocument = CreateNewDocument(verenigingMetRechtspersoonlijkheidWerdGeregistreerd.Data.VCode); AddHistoriekEntry( verenigingMetRechtspersoonlijkheidWerdGeregistreerd, @@ -388,4 +378,23 @@ public static void UpdateMetadata(IEvent @event, BeheerVerenigingHistoriekDocume { document.Metadata = new Metadata(@event.Sequence, @event.Version); } + + public static void Apply(IEvent verenigingWerdVerwijderd, BeheerVerenigingHistoriekDocument document) + { + document.Gebeurtenissen = new List(); + + AddHistoriekEntry( + verenigingWerdVerwijderd, + document, + "Deze vereniging werd verwijderd." + ); + } + + private static BeheerVerenigingHistoriekDocument CreateNewDocument(string vCode) + => new() + { + VCode = vCode, + Gebeurtenissen = new List(), + Metadata = new Metadata(Sequence: 0, Version: 0), + }; } diff --git a/src/AssociationRegistry.Admin.ProjectionHost/Projections/Search/DuplicateDetection/DuplicateDetectionProjectionHandler.cs b/src/AssociationRegistry.Admin.ProjectionHost/Projections/Search/DuplicateDetection/DuplicateDetectionProjectionHandler.cs index 18c0b15e3..b3f9a4434 100644 --- a/src/AssociationRegistry.Admin.ProjectionHost/Projections/Search/DuplicateDetection/DuplicateDetectionProjectionHandler.cs +++ b/src/AssociationRegistry.Admin.ProjectionHost/Projections/Search/DuplicateDetection/DuplicateDetectionProjectionHandler.cs @@ -25,6 +25,7 @@ public async Task Handle(EventEnvelope me Locaties = message.Data.Locaties.Select(Map).ToArray(), HoofdactiviteitVerenigingsloket = MapHoofdactiviteitVerenigingsloket(message.Data.HoofdactiviteitenVerenigingsloket), IsGestopt = false, + IsVerwijderd = false, } ); @@ -39,6 +40,7 @@ public async Task Handle(EventEnvelope(), HoofdactiviteitVerenigingsloket = Array.Empty(), IsGestopt = false, + IsVerwijderd = false, } ); @@ -87,6 +89,15 @@ public async Task Handle(EventEnvelope message) } ); + public async Task Handle(EventEnvelope message) + => await _elasticRepository.UpdateAsync( + message.VCode, + new DuplicateDetectionDocument + { + IsVerwijderd = true, + } + ); + public async Task Handle(EventEnvelope message) => await _elasticRepository.AppendLocatie(message.VCode, Map(message.Data.Locatie)); diff --git a/src/AssociationRegistry.Admin.ProjectionHost/Projections/Search/Zoeken/BeheerZoekProjection.cs b/src/AssociationRegistry.Admin.ProjectionHost/Projections/Search/Zoeken/BeheerZoekProjection.cs index 7163c697c..ca9e42485 100644 --- a/src/AssociationRegistry.Admin.ProjectionHost/Projections/Search/Zoeken/BeheerZoekProjection.cs +++ b/src/AssociationRegistry.Admin.ProjectionHost/Projections/Search/Zoeken/BeheerZoekProjection.cs @@ -223,4 +223,14 @@ await _elasticRepository.UpdateAsync( Status = VerenigingStatus.Gestopt, }); } + + public async Task Handle(EventEnvelope message) + { + await _elasticRepository.UpdateAsync( + message.VCode, + new VerenigingZoekDocument + { + IsVerwijderd = true, + }); + } } diff --git a/src/AssociationRegistry.Admin.Schema/Detail/BeheerVerenigingDetailDocument.cs b/src/AssociationRegistry.Admin.Schema/Detail/BeheerVerenigingDetailDocument.cs index 67be840ca..55b0a1c8a 100644 --- a/src/AssociationRegistry.Admin.Schema/Detail/BeheerVerenigingDetailDocument.cs +++ b/src/AssociationRegistry.Admin.Schema/Detail/BeheerVerenigingDetailDocument.cs @@ -1,5 +1,6 @@ namespace AssociationRegistry.Admin.Schema.Detail; +using Marten.Metadata; using Marten.Schema; public record Doelgroep @@ -8,7 +9,7 @@ public record Doelgroep public int Maximumleeftijd { get; init; } } -public record BeheerVerenigingDetailDocument : IVCode, IMetadata +public record BeheerVerenigingDetailDocument : IVCode, ISoftDeleted, IMetadata { public string Naam { get; set; } = null!; public VerenigingsType Verenigingstype { get; init; } = null!; @@ -107,6 +108,9 @@ public record GerelateerdeVereniging public string Naam { get; init; } = null!; } } + + public bool Deleted { get; set; } + public DateTimeOffset? DeletedAt { get; set; } } public class AdresId diff --git a/src/AssociationRegistry.Admin.Schema/Search/DuplicateDetectionDocument.cs b/src/AssociationRegistry.Admin.Schema/Search/DuplicateDetectionDocument.cs index 096a8604a..225c3d0ad 100644 --- a/src/AssociationRegistry.Admin.Schema/Search/DuplicateDetectionDocument.cs +++ b/src/AssociationRegistry.Admin.Schema/Search/DuplicateDetectionDocument.cs @@ -9,6 +9,7 @@ public record DuplicateDetectionDocument public string KorteNaam { get; set; } = null!; public string[] HoofdactiviteitVerenigingsloket { get; set; } = Array.Empty(); public bool IsGestopt { get; set; } + public bool IsVerwijderd { get; set; } public record Locatie : ILocatie { diff --git a/src/AssociationRegistry.Admin.Schema/Search/DuplicateDetectionDocumentMapping.cs b/src/AssociationRegistry.Admin.Schema/Search/DuplicateDetectionDocumentMapping.cs index 8004bb227..1b46ec23a 100644 --- a/src/AssociationRegistry.Admin.Schema/Search/DuplicateDetectionDocumentMapping.cs +++ b/src/AssociationRegistry.Admin.Schema/Search/DuplicateDetectionDocumentMapping.cs @@ -28,6 +28,9 @@ public static TypeMappingDescriptor Get(TypeMappingD .Boolean( propertyDescriptor => propertyDescriptor .Name(document => document.IsGestopt)) + .Boolean( + propertyDescriptor => propertyDescriptor + .Name(document => document.IsVerwijderd)) .Nested( propertyDescriptor => propertyDescriptor .Name(document => document.Locaties) diff --git a/src/AssociationRegistry.Admin.Schema/Search/VerenigingZoekDocument.cs b/src/AssociationRegistry.Admin.Schema/Search/VerenigingZoekDocument.cs index 5dcac2131..6be00b7d8 100644 --- a/src/AssociationRegistry.Admin.Schema/Search/VerenigingZoekDocument.cs +++ b/src/AssociationRegistry.Admin.Schema/Search/VerenigingZoekDocument.cs @@ -13,6 +13,7 @@ public class VerenigingZoekDocument public HoofdactiviteitVerenigingsloket[] HoofdactiviteitenVerenigingsloket { get; set; } = null!; public Sleutel[] Sleutels { get; set; } = null!; public bool IsUitgeschrevenUitPubliekeDatastroom { get; set; } + public bool IsVerwijderd { get; set; } public class Locatie : ILocatie { diff --git a/src/AssociationRegistry.Admin.Schema/Search/VerenigingZoekDocumentMapping.cs b/src/AssociationRegistry.Admin.Schema/Search/VerenigingZoekDocumentMapping.cs index 28a5d7129..d128c8ebe 100644 --- a/src/AssociationRegistry.Admin.Schema/Search/VerenigingZoekDocumentMapping.cs +++ b/src/AssociationRegistry.Admin.Schema/Search/VerenigingZoekDocumentMapping.cs @@ -25,6 +25,9 @@ public static TypeMappingDescriptor Get(TypeMappingDescr .Boolean( propertyDescriptor => propertyDescriptor .Name(document => document.IsUitgeschrevenUitPubliekeDatastroom)) + .Boolean( + propertyDescriptor => propertyDescriptor + .Name(document => document.IsVerwijderd)) .Nested( propertyDescriptor => propertyDescriptor .Name(document => document.Doelgroep) diff --git a/src/AssociationRegistry.Public.Api/Verenigingen/Search/SearchVerenigingenController.cs b/src/AssociationRegistry.Public.Api/Verenigingen/Search/SearchVerenigingenController.cs index a1968f0be..277606478 100755 --- a/src/AssociationRegistry.Public.Api/Verenigingen/Search/SearchVerenigingenController.cs +++ b/src/AssociationRegistry.Public.Api/Verenigingen/Search/SearchVerenigingenController.cs @@ -186,7 +186,9 @@ private static async Task> Search( $"{q}{BuildHoofdActiviteiten(hoofdactiviteiten)}"), BeActief ) - .MustNot(BeUitgeschrevenUitPubliekeDatastroom) + .MustNot( + BeUitgeschrevenUitPubliekeDatastroom, + BeRemoved) ) ) .Aggregations( @@ -221,20 +223,26 @@ private static AggregationContainerDescriptor QueryFilterAggregation( AggregationContainerDescriptor aggregationContainerDescriptor, string query, Func, IAggregationContainer> aggregations) - where T : class, ICanBeUitgeschrevenUitPubliekeDatastroom, IHasStatus + where T : class, ICanBeUitgeschrevenUitPubliekeDatastroom, IHasStatus, IDeletable { return aggregationContainerDescriptor.Filter( WellknownFacets.FilterAggregateName, - selector: aggregationDescriptor => aggregationDescriptor.Filter( - containerDescriptor => containerDescriptor.Bool( - queryDescriptor => queryDescriptor.Must( - m => - MatchQueryString(m, query), - BeActief - ).MustNot(BeUitgeschrevenUitPubliekeDatastroom) - ) - ) - .Aggregations(aggregations) + selector: aggregationDescriptor => + aggregationDescriptor + .Filter(containerDescriptor => + containerDescriptor + .Bool(queryDescriptor => + queryDescriptor + .Must(m => + MatchQueryString(m, query), + BeActief + ) + .MustNot( + BeUitgeschrevenUitPubliekeDatastroom, + BeRemoved) + ) + ) + .Aggregations(aggregations) ); } @@ -282,12 +290,18 @@ private static string BuildHoofdActiviteiten(IReadOnlyCollection hoofdac private static QueryContainer BeUitgeschrevenUitPubliekeDatastroom(QueryContainerDescriptor q) where T : class, ICanBeUitgeschrevenUitPubliekeDatastroom { - return q.Terms(t => t.Field(arg => arg.IsUitgeschrevenUitPubliekeDatastroom).Terms(true)); + return q.Term(arg => arg.IsUitgeschrevenUitPubliekeDatastroom, true); } private static QueryContainer BeActief(QueryContainerDescriptor q) where T : class, IHasStatus { - return q.Terms(t => t.Field(arg => arg.Status).Terms(VerenigingStatus.Actief)); + return q.Term(arg => arg.Status, VerenigingStatus.Actief); + } + + private static QueryContainer BeRemoved(QueryContainerDescriptor q) + where T : class, IDeletable + { + return q.Term(arg => arg.IsVerwijderd, true); } } diff --git a/src/AssociationRegistry.Public.ProjectionHost/Projections/Detail/PubliekVerenigingDetailProjection.cs b/src/AssociationRegistry.Public.ProjectionHost/Projections/Detail/PubliekVerenigingDetailProjection.cs index 2756d4ade..b2e549324 100644 --- a/src/AssociationRegistry.Public.ProjectionHost/Projections/Detail/PubliekVerenigingDetailProjection.cs +++ b/src/AssociationRegistry.Public.ProjectionHost/Projections/Detail/PubliekVerenigingDetailProjection.cs @@ -128,6 +128,9 @@ public async Task Project(IEvent @event, IDoc public async Task Project(IEvent @event, IDocumentOperations ops) => await Update(@event, ops, PubliekVerenigingDetailProjector.Apply); + public void Project(IEvent @event, IDocumentOperations ops) + => ops.Delete(@event.StreamKey); + private static async Task Update( IEvent @event, IDocumentOperations ops, diff --git a/src/AssociationRegistry.Public.ProjectionHost/Projections/Search/ElasticEventProjection.cs b/src/AssociationRegistry.Public.ProjectionHost/Projections/Search/ElasticEventProjection.cs index 8de8a5caf..b00ffcd09 100644 --- a/src/AssociationRegistry.Public.ProjectionHost/Projections/Search/ElasticEventProjection.cs +++ b/src/AssociationRegistry.Public.ProjectionHost/Projections/Search/ElasticEventProjection.cs @@ -223,4 +223,10 @@ public async Task Handle(EventEnvelope message) await _elasticRepository.UpdateAsync(message.VCode, new VerenigingZoekDocument { Status = VerenigingStatus.Gestopt }); } + + public async Task Handle(EventEnvelope message) + { + await _elasticRepository.UpdateAsync(message.VCode, new VerenigingZoekDocument + { IsVerwijderd = true }); + } } diff --git a/src/AssociationRegistry.Public.Schema/Detail/VerenigingDetailDocument.cs b/src/AssociationRegistry.Public.Schema/Detail/VerenigingDetailDocument.cs index 6636dcb10..8d2771ef5 100644 --- a/src/AssociationRegistry.Public.Schema/Detail/VerenigingDetailDocument.cs +++ b/src/AssociationRegistry.Public.Schema/Detail/VerenigingDetailDocument.cs @@ -1,6 +1,6 @@ namespace AssociationRegistry.Public.Schema.Detail; -using Marten.Schema; +using Marten.Metadata;using Marten.Schema; public record Doelgroep { @@ -8,7 +8,7 @@ public record Doelgroep public int Maximumleeftijd { get; set; } } -public class PubliekVerenigingDetailDocument : IVCode, ICanBeUitgeschrevenUitPubliekeDatastroom +public class PubliekVerenigingDetailDocument : IVCode,ISoftDeleted, ICanBeUitgeschrevenUitPubliekeDatastroom { public VerenigingsType Verenigingstype { get; set; } = null!; public string Naam { get; set; } = null!; @@ -97,4 +97,7 @@ public class Adres public string Gemeente { get; init; } = null!; public string Land { get; init; } = null!; } + + public bool Deleted { get; set; } + public DateTimeOffset? DeletedAt { get; set; } } diff --git a/src/AssociationRegistry.Public.Schema/IDeletable.cs b/src/AssociationRegistry.Public.Schema/IDeletable.cs new file mode 100644 index 000000000..be8100fba --- /dev/null +++ b/src/AssociationRegistry.Public.Schema/IDeletable.cs @@ -0,0 +1,6 @@ +namespace AssociationRegistry.Public.Schema; + +public interface IDeletable +{ + public bool IsVerwijderd { get; } +} diff --git a/src/AssociationRegistry.Public.Schema/Search/VerenigingZoekDocument.cs b/src/AssociationRegistry.Public.Schema/Search/VerenigingZoekDocument.cs index 6ee0a431e..584490769 100644 --- a/src/AssociationRegistry.Public.Schema/Search/VerenigingZoekDocument.cs +++ b/src/AssociationRegistry.Public.Schema/Search/VerenigingZoekDocument.cs @@ -1,6 +1,6 @@ namespace AssociationRegistry.Public.Schema.Search; -public class VerenigingZoekDocument : ICanBeUitgeschrevenUitPubliekeDatastroom, IHasStatus +public class VerenigingZoekDocument : ICanBeUitgeschrevenUitPubliekeDatastroom, IHasStatus, IDeletable { public string VCode { get; set; } = null!; public VerenigingsType Verenigingstype { get; set; } = null!; @@ -14,6 +14,8 @@ public class VerenigingZoekDocument : ICanBeUitgeschrevenUitPubliekeDatastroom, public Relatie[] Relaties { get; set; } = null!; public bool IsUitgeschrevenUitPubliekeDatastroom { get; set; } public string Status { get; set; } = null!; + public bool IsVerwijderd { get; set; } + public class Locatie { diff --git a/src/AssociationRegistry.Public.Schema/Search/VerenigingZoekDocumentMapping.cs b/src/AssociationRegistry.Public.Schema/Search/VerenigingZoekDocumentMapping.cs index aae1e177f..b3a44df63 100644 --- a/src/AssociationRegistry.Public.Schema/Search/VerenigingZoekDocumentMapping.cs +++ b/src/AssociationRegistry.Public.Schema/Search/VerenigingZoekDocumentMapping.cs @@ -28,6 +28,9 @@ public static TypeMappingDescriptor Get(TypeMappingDescr .Boolean( propertyDescriptor => propertyDescriptor .Name(document => document.IsUitgeschrevenUitPubliekeDatastroom)) + .Boolean( + propertyDescriptor => propertyDescriptor + .Name(document => document.IsVerwijderd)) .Nested( propertyDescriptor => propertyDescriptor .Name(document => document.Verenigingstype) diff --git a/src/AssociationRegistry/Acties/VerwijderVereniging/VerwijderVerenigingCommand.cs b/src/AssociationRegistry/Acties/VerwijderVereniging/VerwijderVerenigingCommand.cs new file mode 100644 index 000000000..6b05d484f --- /dev/null +++ b/src/AssociationRegistry/Acties/VerwijderVereniging/VerwijderVerenigingCommand.cs @@ -0,0 +1,5 @@ +namespace AssociationRegistry.Acties.VerwijderVereniging; + +using Vereniging; + +public record VerwijderVerenigingCommand(VCode VCode, string Reden); diff --git a/src/AssociationRegistry/Acties/VerwijderVereniging/VerwijderVerenigingCommandHandler.cs b/src/AssociationRegistry/Acties/VerwijderVereniging/VerwijderVerenigingCommandHandler.cs new file mode 100644 index 000000000..9567677e3 --- /dev/null +++ b/src/AssociationRegistry/Acties/VerwijderVereniging/VerwijderVerenigingCommandHandler.cs @@ -0,0 +1,30 @@ +namespace AssociationRegistry.Acties.VerwijderVereniging; + +using Framework; +using Vereniging; +using Vereniging.Exceptions; + +public class VerwijderVerenigingCommandHandler +{ + private readonly IVerenigingsRepository _repository; + + public VerwijderVerenigingCommandHandler(IVerenigingsRepository repository) + { + _repository = repository; + } + + public async Task Handle( + CommandEnvelope message, + CancellationToken cancellationToken = default) + { + var vereniging = await _repository.Load(message.Command.VCode, message.Metadata.ExpectedVersion) + .OrWhenUnsupportedOperationForType() + .Throw(); + + vereniging.Verwijder(message.Command.Reden); + + var result = await _repository.Save(vereniging, message.Metadata, cancellationToken); + + return CommandResult.Create(VCode.Create(message.Command.VCode), result); + } +} diff --git a/src/AssociationRegistry/EventStore/VerenigingsRepository.cs b/src/AssociationRegistry/EventStore/VerenigingsRepository.cs index d3aa6d0ca..4afd3f25a 100644 --- a/src/AssociationRegistry/EventStore/VerenigingsRepository.cs +++ b/src/AssociationRegistry/EventStore/VerenigingsRepository.cs @@ -2,6 +2,7 @@ using Framework; using Vereniging; +using Vereniging.Exceptions; public class VerenigingsRepository : IVerenigingsRepository { @@ -29,6 +30,7 @@ public async Task Load(VCode vCode, long? expectedVers where TVereniging : IHydrate, new() { var verenigingState = await _eventStore.Load(vCode); + ThrowIfVerwijderd(verenigingState); var vereniging = new TVereniging(); vereniging.Hydrate(verenigingState); @@ -56,4 +58,10 @@ public static VCodeAndNaam Fallback(KboNummer kboNummer) VCode: null, VerenigingsNaam.Create($"Moeder {kboNummer}")); } + + private void ThrowIfVerwijderd(VerenigingState verenigingState) + { + if (verenigingState.IsVerwijderd) + throw new VerenigingWerdVerwijderd(verenigingState.VCode); + } } diff --git a/src/AssociationRegistry/Events/VerenigingWerdVerwijderd.cs b/src/AssociationRegistry/Events/VerenigingWerdVerwijderd.cs new file mode 100644 index 000000000..62d81fc54 --- /dev/null +++ b/src/AssociationRegistry/Events/VerenigingWerdVerwijderd.cs @@ -0,0 +1,9 @@ +namespace AssociationRegistry.Events; + +using Framework; + +public record VerenigingWerdVerwijderd(string Reden) : IEvent +{ + public static VerenigingWerdVerwijderd With(string reden) + => new(reden); +} diff --git a/src/AssociationRegistry/Resources/ExceptionMessages.Designer.cs b/src/AssociationRegistry/Resources/ExceptionMessages.Designer.cs index c8393678e..f774eab14 100644 --- a/src/AssociationRegistry/Resources/ExceptionMessages.Designer.cs +++ b/src/AssociationRegistry/Resources/ExceptionMessages.Designer.cs @@ -11,32 +11,46 @@ namespace AssociationRegistry { using System; - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class ExceptionMessages { - private static System.Resources.ResourceManager resourceMan; + private static global::System.Resources.ResourceManager resourceMan; - private static System.Globalization.CultureInfo resourceCulture; + private static global::System.Globalization.CultureInfo resourceCulture; - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal ExceptionMessages() { } - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] - public static System.Resources.ResourceManager ResourceManager { + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { get { - if (object.Equals(null, resourceMan)) { - System.Resources.ResourceManager temp = new System.Resources.ResourceManager("AssociationRegistry.Resources.ExceptionMessages", typeof(ExceptionMessages).Assembly); + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AssociationRegistry.Resources.ExceptionMessages", typeof(ExceptionMessages).Assembly); resourceMan = temp; } return resourceMan; } } - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] - public static System.Globalization.CultureInfo Culture { + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } @@ -45,351 +59,545 @@ public static System.Globalization.CultureInfo Culture { } } - public static string WebsiteMissingPeriod { + /// + /// Looks up a localized string similar to Achternaam mag geen nummers bevatten.. + /// + public static string AchternaamBevatNummers { get { - return ResourceManager.GetString("WebsiteMissingPeriod", resourceCulture); + return ResourceManager.GetString("AchternaamBevatNummers", resourceCulture); } } - public static string InvalidWebsiteStart { + /// + /// Looks up a localized string similar to Achternaam moet een letter bevatten.. + /// + public static string AchternaamZonderLetters { get { - return ResourceManager.GetString("InvalidWebsiteStart", resourceCulture); + return ResourceManager.GetString("AchternaamZonderLetters", resourceCulture); } } - public static string InvalidTelefoonNummerCharacter { + /// + /// Looks up a localized string similar to Contactgegevens die uit KBO werden overgenomen, kunnen niet verwijderd worden.. + /// + public static string ContactgegevenFromKboCannotBeRemoved { get { - return ResourceManager.GetString("InvalidTelefoonNummerCharacter", resourceCulture); + return ResourceManager.GetString("ContactgegevenFromKboCannotBeRemoved", resourceCulture); } } - public static string NoNumbersInTelefoonNummer { + /// + /// Looks up a localized string similar to Contactgegevens die uit KBO werden overgenomen, kunnen niet aangepast worden.. + /// + public static string ContactgegevenFromKboCannotBeUpdated { get { - return ResourceManager.GetString("NoNumbersInTelefoonNummer", resourceCulture); + return ResourceManager.GetString("ContactgegevenFromKboCannotBeUpdated", resourceCulture); } } - public static string InvalidSocialMediaStart { + /// + /// Looks up a localized string similar to Request kon niet correct behandeld worden. Controleer het formaat en probeer het opnieuw.. + /// + public static string CouldNotParseRequestException { get { - return ResourceManager.GetString("InvalidSocialMediaStart", resourceCulture); + return ResourceManager.GetString("CouldNotParseRequestException", resourceCulture); } } - public static string SocialMediaMissingPeriod { + /// + /// Looks up a localized string similar to Minimum en maximum leeftijd moeten tussen 0 en 150 inclusief liggen.. + /// + public static string DoelgroepOutOfRange { get { - return ResourceManager.GetString("SocialMediaMissingPeriod", resourceCulture); + return ResourceManager.GetString("DoelgroepOutOfRange", resourceCulture); } } - public static string InvalidContactType { + /// + /// Looks up a localized string similar to Een waarde in de hoofdactiviteitenLijst mag slechts 1 maal voorkomen.. + /// + public static string DuplicateHoofdactiviteit { get { - return ResourceManager.GetString("InvalidContactType", resourceCulture); + return ResourceManager.GetString("DuplicateHoofdactiviteit", resourceCulture); } } - public static string DoelgroepOutOfRange { + /// + /// Looks up a localized string similar to INSZ moet uniek zijn binnen de vereniging.. + /// + public static string DuplicateInszProvided { get { - return ResourceManager.GetString("DoelgroepOutOfRange", resourceCulture); + return ResourceManager.GetString("DuplicateInszProvided", resourceCulture); } } - public static string InvalidDoelgroepRange { + /// + /// Looks up a localized string similar to Locaties moeten uniek zijn binnen de vereniging.. + /// + public static string DuplicateLocatie { get { - return ResourceManager.GetString("InvalidDoelgroepRange", resourceCulture); + return ResourceManager.GetString("DuplicateLocatie", resourceCulture); } } + /// + /// Looks up a localized string similar to Einddatum moet na startdatum liggen.. + /// + public static string EinddatumIsBeforeStartdatum { + get { + return ResourceManager.GetString("EinddatumIsBeforeStartdatum", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Einddatum mag niet in de toekomst liggen.. + /// + public static string EinddatumIsInFuture { + get { + return ResourceManager.GetString("EinddatumIsInFuture", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to De naam van de vereniging is verplicht.. + /// + public static string EmptyVerenigingsNaam { + get { + return ResourceManager.GetString("EmptyVerenigingsNaam", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Er werd voor dit KBO-nummer geen geldige vereniging gevonden.. + /// public static string GeenGeldigeVerenigingInKbo { get { return ResourceManager.GetString("GeenGeldigeVerenigingInKbo", resourceCulture); } } - public static string UnsupportedOperationForVerenigingstype { + /// + /// Looks up a localized string similar to Een adres moet bestaan uit straatnaam, huisnummer, postcode, gemeente en land.. + /// + public static string IncompleteAdres { get { - return ResourceManager.GetString("UnsupportedOperationForVerenigingstype", resourceCulture); + return ResourceManager.GetString("IncompleteAdres", resourceCulture); } } - public static string DuplicateHoofdactiviteit { + /// + /// Looks up a localized string similar to Een adresId moet een adresbron en waarde bevatten.. + /// + public static string IncompleteAdresId { get { - return ResourceManager.GetString("DuplicateHoofdactiviteit", resourceCulture); + return ResourceManager.GetString("IncompleteAdresId", resourceCulture); } } - public static string InvalidInszChars { + /// + /// Looks up a localized string similar to Het bevestigingstoken is niet geldig voor deze request.. + /// + public static string InvalidBevestigingstokenProvided { get { - return ResourceManager.GetString("InvalidInszChars", resourceCulture); + return ResourceManager.GetString("InvalidBevestigingstokenProvided", resourceCulture); } } - public static string InvalidInszLength { + /// + /// Looks up a localized string similar to De broncode voor dit adres is niet gekend.. + /// + public static string InvalidBroncode { get { - return ResourceManager.GetString("InvalidInszLength", resourceCulture); + return ResourceManager.GetString("InvalidBroncode", resourceCulture); } } - public static string InvalidInszMod97 { + /// + /// Looks up a localized string similar to De bronwaarde voor een adres uit het addressenregister moet een Data Vlaanderen PURI zijn.. + /// + public static string InvalidBronwaardeForAR { get { - return ResourceManager.GetString("InvalidInszMod97", resourceCulture); + return ResourceManager.GetString("InvalidBronwaardeForAR", resourceCulture); } } - public static string InvalidKboNummerChars { + /// + /// Looks up a localized string similar to Het opgegeven contacttype werd niet herkend. ('email', 'website', 'socialmedia', 'telefoon'). + /// + public static string InvalidContactType { get { - return ResourceManager.GetString("InvalidKboNummerChars", resourceCulture); + return ResourceManager.GetString("InvalidContactType", resourceCulture); } } - public static string InvalidKboNummerLength { + /// + /// Looks up a localized string similar to Datum moet van het formaat 'yyyy-MM-dd' zijn.. + /// + public static string InvalidDateFormat { get { - return ResourceManager.GetString("InvalidKboNummerLength", resourceCulture); + return ResourceManager.GetString("InvalidDateFormat", resourceCulture); } } - public static string InvalidKboNummerMod97 { + /// + /// Looks up a localized string similar to Minimum leeftijd moet kleiner of gelijk zijn aan maximum leeftijd.. + /// + public static string InvalidDoelgroepRange { get { - return ResourceManager.GetString("InvalidKboNummerMod97", resourceCulture); + return ResourceManager.GetString("InvalidDoelgroepRange", resourceCulture); } } - public static string DuplicateLocatie { + /// + /// Looks up a localized string similar to E-mail voldoet niet aan het verwachte formaat (naam@domein.vlaanderen). In naam worden de volgende tekens + /// toegestaan '!#$%&'*+/=?^_`{|}~-', in domein enkel '.' en '-'. + /// . + /// + public static string InvalidEmailFormat { get { - return ResourceManager.GetString("DuplicateLocatie", resourceCulture); + return ResourceManager.GetString("InvalidEmailFormat", resourceCulture); } } - public static string IncompleteAdres { + /// + /// Looks up a localized string similar to Foutieve tekens in INSZ.. + /// + public static string InvalidInszChars { get { - return ResourceManager.GetString("IncompleteAdres", resourceCulture); + return ResourceManager.GetString("InvalidInszChars", resourceCulture); } } - public static string IncompleteAdresId { + /// + /// Looks up a localized string similar to INSZ moet 11 cijfers bevatten.. + /// + public static string InvalidInszLength { get { - return ResourceManager.GetString("IncompleteAdresId", resourceCulture); + return ResourceManager.GetString("InvalidInszLength", resourceCulture); } } - public static string InvalidBroncode { + /// + /// Looks up a localized string similar to Incorrect INSZ: foutieve checksum.. + /// + public static string InvalidInszMod97 { get { - return ResourceManager.GetString("InvalidBroncode", resourceCulture); + return ResourceManager.GetString("InvalidInszMod97", resourceCulture); } } - public static string InvalidBronwaardeForAR { + /// + /// Looks up a localized string similar to Foutieve tekens in Kbo nummer.. + /// + public static string InvalidKboNummerChars { get { - return ResourceManager.GetString("InvalidBronwaardeForAR", resourceCulture); + return ResourceManager.GetString("InvalidKboNummerChars", resourceCulture); } } - public static string MissingAdres { + /// + /// Looks up a localized string similar to Kbo nummer moet 10 cijfers bevatten.. + /// + public static string InvalidKboNummerLength { get { - return ResourceManager.GetString("MissingAdres", resourceCulture); + return ResourceManager.GetString("InvalidKboNummerLength", resourceCulture); } } - public static string MultipleCorrespondentieLocaties { + /// + /// Looks up a localized string similar to Incorrect Kbo nummer: foutieve checksum.. + /// + public static string InvalidKboNummerMod97 { get { - return ResourceManager.GetString("MultipleCorrespondentieLocaties", resourceCulture); + return ResourceManager.GetString("InvalidKboNummerMod97", resourceCulture); } } - public static string MultiplePrimaireLocaties { + /// + /// Looks up a localized string similar to Social media url moet beginnen met 'http://' of 'https://'. + /// + public static string InvalidSocialMediaStart { get { - return ResourceManager.GetString("MultiplePrimaireLocaties", resourceCulture); + return ResourceManager.GetString("InvalidSocialMediaStart", resourceCulture); } } - public static string StartdatumIsInFuture { + /// + /// Looks up a localized string similar to TelefoonNummer moet bestaan uit cijfers, whitespace en ". / ( ) - + ". + /// + public static string InvalidTelefoonNummerCharacter { get { - return ResourceManager.GetString("StartdatumIsInFuture", resourceCulture); + return ResourceManager.GetString("InvalidTelefoonNummerCharacter", resourceCulture); } } + /// + /// Looks up a localized string similar to Formaat van de VCode moet 'V0000000' zijn. + /// public static string InvalidVCodeFormat { get { return ResourceManager.GetString("InvalidVCodeFormat", resourceCulture); } } - public static string OutOfRangeVCode { + /// + /// Looks up a localized string similar to Website url moet beginnen met 'http://' of 'https://'. + /// + public static string InvalidWebsiteStart { get { - return ResourceManager.GetString("OutOfRangeVCode", resourceCulture); + return ResourceManager.GetString("InvalidWebsiteStart", resourceCulture); } } - public static string EmptyVerenigingsNaam { + /// + /// Looks up a localized string similar to De maatschappelijke zetel volgens KBO kan niet verwijderd worden.. + /// + public static string MaatschappelijkeZetelCanNotBeRemoved { get { - return ResourceManager.GetString("EmptyVerenigingsNaam", resourceCulture); + return ResourceManager.GetString("MaatschappelijkeZetelCanNotBeRemoved", resourceCulture); } } - public static string AchternaamBevatNummers { + /// + /// Looks up a localized string similar to De maatschappelijke zetel volgens KBO kan niet gewijzigd worden.. + /// + public static string MaatschappelijkeZetelCanNotBeUpdated { get { - return ResourceManager.GetString("AchternaamBevatNummers", resourceCulture); + return ResourceManager.GetString("MaatschappelijkeZetelCanNotBeUpdated", resourceCulture); } } - public static string AchternaamZonderLetters { + /// + /// Looks up a localized string similar to Het locatietype 'Maatschappelijke zetel volgens KBO' kan niet toegekend worden.. + /// + public static string MaatschappelijkeZetelIsNotAllowed { get { - return ResourceManager.GetString("AchternaamZonderLetters", resourceCulture); + return ResourceManager.GetString("MaatschappelijkeZetelIsNotAllowed", resourceCulture); } } - public static string DuplicateInszProvided { + /// + /// Looks up a localized string similar to Een locatie moet minstens een adresId of een adres bevatten.. + /// + public static string MissingAdres { get { - return ResourceManager.GetString("DuplicateInszProvided", resourceCulture); + return ResourceManager.GetString("MissingAdres", resourceCulture); } } - public static string MultiplePrimaireVertegenwoordigers { + /// + /// Looks up a localized string similar to Er kan maar één correspondentie locatie zijn binnen de vereniging.. + /// + public static string MultipleCorrespondentieLocaties { get { - return ResourceManager.GetString("MultiplePrimaireVertegenwoordigers", resourceCulture); + return ResourceManager.GetString("MultipleCorrespondentieLocaties", resourceCulture); } } - public static string UnknownInsz { + /// + /// Looks up a localized string similar to Er kan maar één primaire locatie zijn binnen de vereniging.. + /// + public static string MultiplePrimaireLocaties { get { - return ResourceManager.GetString("UnknownInsz", resourceCulture); + return ResourceManager.GetString("MultiplePrimaireLocaties", resourceCulture); } } - public static string VoornaamBevatNummers { + /// + /// Looks up a localized string similar to Er mag maar één vertegenwoordiger aangeduid zijn als primair contactpersoon.. + /// + public static string MultiplePrimaireVertegenwoordigers { get { - return ResourceManager.GetString("VoornaamBevatNummers", resourceCulture); + return ResourceManager.GetString("MultiplePrimaireVertegenwoordigers", resourceCulture); } } - public static string VoornaamZonderLetters { + /// + /// Looks up a localized string similar to TelefoonNummer moet minstens één cijfer bevatten. + /// + public static string NoNumbersInTelefoonNummer { get { - return ResourceManager.GetString("VoornaamZonderLetters", resourceCulture); + return ResourceManager.GetString("NoNumbersInTelefoonNummer", resourceCulture); } } - public static string InvalidEmailFormat { + /// + /// Looks up a localized string similar to VCode moet groter zijn dan 1000. + /// + public static string OutOfRangeVCode { get { - return ResourceManager.GetString("InvalidEmailFormat", resourceCulture); + return ResourceManager.GetString("OutOfRangeVCode", resourceCulture); } } - public static string InvalidDateFormat { + /// + /// Looks up a localized string similar to Social media url moet minsens één punt bevatten. + /// + public static string SocialMediaMissingPeriod { get { - return ResourceManager.GetString("InvalidDateFormat", resourceCulture); + return ResourceManager.GetString("SocialMediaMissingPeriod", resourceCulture); } } - public static string CouldNotParseRequestException { + /// + /// Looks up a localized string similar to Startdatum moet voor einddatum liggen.. + /// + public static string StartdatumIsAfterEinddatum { get { - return ResourceManager.GetString("CouldNotParseRequestException", resourceCulture); + return ResourceManager.GetString("StartdatumIsAfterEinddatum", resourceCulture); } } - public static string InvalidBevestigingstokenProvided { + /// + /// Looks up a localized string similar to Startdatum mag niet in de toekomst liggen.. + /// + public static string StartdatumIsInFuture { get { - return ResourceManager.GetString("InvalidBevestigingstokenProvided", resourceCulture); + return ResourceManager.GetString("StartdatumIsInFuture", resourceCulture); } } - public static string MaatschappelijkeZetelIsNotAllowed { + /// + /// Looks up a localized string similar to De gevraagde vereniging heeft niet de verwachte sequentiewaarde.. + /// + public static string UnexpectedAggregateVersion { get { - return ResourceManager.GetString("MaatschappelijkeZetelIsNotAllowed", resourceCulture); + return ResourceManager.GetString("UnexpectedAggregateVersion", resourceCulture); } } - public static string MaatschappelijkeZetelCanNotBeUpdated { + /// + /// Looks up a localized string similar to INSZ is niet gekend. + /// + public static string UnknownInsz { get { - return ResourceManager.GetString("MaatschappelijkeZetelCanNotBeUpdated", resourceCulture); + return ResourceManager.GetString("UnknownInsz", resourceCulture); } } - public static string MaatschappelijkeZetelCanNotBeRemoved { + /// + /// Looks up a localized string similar to Deze waarde bevat niet toegestane tekens.. + /// + public static string UnsupportedContent { get { - return ResourceManager.GetString("MaatschappelijkeZetelCanNotBeRemoved", resourceCulture); + return ResourceManager.GetString("UnsupportedContent", resourceCulture); } } - public static string ContactgegevenFromKboCannotBeUpdated { + /// + /// Looks up a localized string similar to Deze actie kan niet uitgevoerd worden op dit contactgegeven.. + /// + public static string UnsupportedOperationForContactgegevenBron { get { - return ResourceManager.GetString("ContactgegevenFromKboCannotBeUpdated", resourceCulture); + return ResourceManager.GetString("UnsupportedOperationForContactgegevenBron", resourceCulture); } } - public static string ContactgegevenFromKboCannotBeRemoved { + /// + /// Looks up a localized string similar to Deze actie kan niet uitgevoerd worden op deze locatie.. + /// + public static string UnsupportedOperationForLocatietype { get { - return ResourceManager.GetString("ContactgegevenFromKboCannotBeRemoved", resourceCulture); + return ResourceManager.GetString("UnsupportedOperationForLocatietype", resourceCulture); } } - public static string EinddatumIsInFuture { + /// + /// Looks up a localized string similar to Deze actie kan niet uitgevoerd worden op dit type vereniging.. + /// + public static string UnsupportedOperationForVerenigingstype { get { - return ResourceManager.GetString("EinddatumIsInFuture", resourceCulture); + return ResourceManager.GetString("UnsupportedOperationForVerenigingstype", resourceCulture); } } - public static string EinddatumIsBeforeStartdatum { + /// + /// Looks up a localized string similar to Deze vereniging kan niet verwijderd worden.. + /// + public static string VerenigingKanNietVerwijderdWorden { get { - return ResourceManager.GetString("EinddatumIsBeforeStartdatum", resourceCulture); + return ResourceManager.GetString("VerenigingKanNietVerwijderdWorden", resourceCulture); } } - public static string StartdatumIsAfterEinddatum { + /// + /// Looks up a localized string similar to Aan een KBO vereniging kunnen geen vertegenwoordigers toegevoegd worden.. + /// + public static string VerenigingMetRechtspersoonlijkheidCannotAddVertegenwoordigers { get { - return ResourceManager.GetString("StartdatumIsAfterEinddatum", resourceCulture); + return ResourceManager.GetString("VerenigingMetRechtspersoonlijkheidCannotAddVertegenwoordigers", resourceCulture); } } - public static string VerenigingMetRechtspersoonlijkheidKanNietGestoptWorden { + /// + /// Looks up a localized string similar to Een vertegenwoordiger van een KBO vereniging kan niet verwijderd worden.. + /// + public static string VerenigingMetRechtspersoonlijkheidCannotRemoveVertegenwoordigers { get { - return ResourceManager.GetString("VerenigingMetRechtspersoonlijkheidKanNietGestoptWorden", resourceCulture); + return ResourceManager.GetString("VerenigingMetRechtspersoonlijkheidCannotRemoveVertegenwoordigers", resourceCulture); } } - public static string UnsupportedOperationForLocatietype { + /// + /// Looks up a localized string similar to Een KBO-vereniging kan niet gestopt worden.. + /// + public static string VerenigingMetRechtspersoonlijkheidKanNietGestoptWorden { get { - return ResourceManager.GetString("UnsupportedOperationForLocatietype", resourceCulture); + return ResourceManager.GetString("VerenigingMetRechtspersoonlijkheidKanNietGestoptWorden", resourceCulture); } } - public static string UnsupportedOperationForContactgegevenBron { + /// + /// Looks up a localized string similar to Deze vereniging werd verwijderd.. + /// + public static string VerenigingWerdVerwijderd { get { - return ResourceManager.GetString("UnsupportedOperationForContactgegevenBron", resourceCulture); + return ResourceManager.GetString("VerenigingWerdVerwijderd", resourceCulture); } } - public static string VerenigingMetRechtspersoonlijkheidCannotAddVertegenwoordigers { + /// + /// Looks up a localized string similar to Voornaam mag geen nummers bevatten.. + /// + public static string VoornaamBevatNummers { get { - return ResourceManager.GetString("VerenigingMetRechtspersoonlijkheidCannotAddVertegenwoordigers", resourceCulture); + return ResourceManager.GetString("VoornaamBevatNummers", resourceCulture); } } - public static string VerenigingMetRechtspersoonlijkheidCannotRemoveVertegenwoordigers { + /// + /// Looks up a localized string similar to Voornaam moet een letter bevatten.. + /// + public static string VoornaamZonderLetters { get { - return ResourceManager.GetString("VerenigingMetRechtspersoonlijkheidCannotRemoveVertegenwoordigers", resourceCulture); + return ResourceManager.GetString("VoornaamZonderLetters", resourceCulture); } } - public static string ZoekOpdrachtWasIncorrect { + /// + /// Looks up a localized string similar to Website url moet minsens één punt bevatten. + /// + public static string WebsiteMissingPeriod { get { - return ResourceManager.GetString("ZoekOpdrachtWasIncorrect", resourceCulture); + return ResourceManager.GetString("WebsiteMissingPeriod", resourceCulture); } } + /// + /// Looks up a localized string similar to Deze zoekopdracht bevat onbekende sorteervelden en kon niet uitgevoerd worden. Onbekende velden: {0}. + /// public static string ZoekOpdrachtBevatOnbekendeSorteerVelden { get { return ResourceManager.GetString("ZoekOpdrachtBevatOnbekendeSorteerVelden", resourceCulture); } } - public static string UnexpectedAggregateVersion { - get { - return ResourceManager.GetString("UnexpectedAggregateVersion", resourceCulture); - } - } - - public static string UnsupportedContent { + /// + /// Looks up a localized string similar to Deze zoekopdracht kon niet uitgevoerd worden. Controleer alle parameters en probeer opnieuw.. + /// + public static string ZoekOpdrachtWasIncorrect { get { - return ResourceManager.GetString("UnsupportedContent", resourceCulture); + return ResourceManager.GetString("ZoekOpdrachtWasIncorrect", resourceCulture); } } } diff --git a/src/AssociationRegistry/Resources/ExceptionMessages.resx b/src/AssociationRegistry/Resources/ExceptionMessages.resx index f6647bbf3..e1f16c0de 100644 --- a/src/AssociationRegistry/Resources/ExceptionMessages.resx +++ b/src/AssociationRegistry/Resources/ExceptionMessages.resx @@ -175,6 +175,12 @@ Een KBO-vereniging kan niet gestopt worden. + + Deze vereniging kan niet verwijderd worden. + + + Deze vereniging werd verwijderd. + Deze actie kan niet uitgevoerd worden op deze locatie. diff --git a/src/AssociationRegistry/Vereniging/Exceptions/VerenigingKanNietVerwijderdWorden.cs b/src/AssociationRegistry/Vereniging/Exceptions/VerenigingKanNietVerwijderdWorden.cs new file mode 100644 index 000000000..15477146a --- /dev/null +++ b/src/AssociationRegistry/Vereniging/Exceptions/VerenigingKanNietVerwijderdWorden.cs @@ -0,0 +1,16 @@ +namespace AssociationRegistry.Vereniging.Exceptions; + +using Be.Vlaanderen.Basisregisters.AggregateSource; +using System.Runtime.Serialization; + +[Serializable] +public class VerenigingKanNietVerwijderdWorden : DomainException +{ + public VerenigingKanNietVerwijderdWorden() : base(ExceptionMessages.VerenigingKanNietVerwijderdWorden) + { + } + + protected VerenigingKanNietVerwijderdWorden(SerializationInfo info, StreamingContext context) : base(info, context) + { + } +} diff --git a/src/AssociationRegistry/Vereniging/Exceptions/VerenigingWerdVerwijderd.cs b/src/AssociationRegistry/Vereniging/Exceptions/VerenigingWerdVerwijderd.cs new file mode 100644 index 000000000..22122fbdd --- /dev/null +++ b/src/AssociationRegistry/Vereniging/Exceptions/VerenigingWerdVerwijderd.cs @@ -0,0 +1,19 @@ +namespace AssociationRegistry.Vereniging.Exceptions; + +using Be.Vlaanderen.Basisregisters.AggregateSource; +using System.Runtime.Serialization; + +[Serializable] +public class VerenigingWerdVerwijderd : DomainException +{ + public VCode Vcode { get; } + + public VerenigingWerdVerwijderd(VCode vcode) : base(ExceptionMessages.VerenigingWerdVerwijderd) + { + Vcode = vcode; + } + + protected VerenigingWerdVerwijderd(SerializationInfo info, StreamingContext context) : base(info, context) + { + } +} diff --git a/src/AssociationRegistry/Vereniging/Vereniging.cs b/src/AssociationRegistry/Vereniging/Vereniging.cs index 312dbf568..76c379ab9 100644 --- a/src/AssociationRegistry/Vereniging/Vereniging.cs +++ b/src/AssociationRegistry/Vereniging/Vereniging.cs @@ -52,7 +52,8 @@ public static Vereniging RegistreerFeitelijkeVereniging( private static Registratiedata.Contactgegeven[] ToEventContactgegevens(Contactgegeven[] contactgegevens) => contactgegevens.Select(Registratiedata.Contactgegeven.With).ToArray(); - private static Registratiedata.HoofdactiviteitVerenigingsloket[] ToHoofdactiviteitenLijst(HoofdactiviteitVerenigingsloket[] hoofdactiviteitenVerenigingsloketLijst) + private static Registratiedata.HoofdactiviteitVerenigingsloket[] ToHoofdactiviteitenLijst( + HoofdactiviteitVerenigingsloket[] hoofdactiviteitenVerenigingsloketLijst) => hoofdactiviteitenVerenigingsloketLijst.Select(Registratiedata.HoofdactiviteitVerenigingsloket.With).ToArray(); private static Registratiedata.Vertegenwoordiger[] ToVertegenwoordigersLijst(Vertegenwoordiger[] vertegenwoordigersLijst) @@ -109,6 +110,12 @@ public void Stop(Datum einddatum, IClock clock) AddEvent(VerenigingWerdGestopt.With(einddatum)); } + public void Verwijder(string reden) + { + Throw.If(State.IsVerwijderd); + AddEvent(Events.VerenigingWerdVerwijderd.With(reden)); + } + public void WijzigDoelgroep(Doelgroep doelgroep) { if (Doelgroep.Equals(State.Doelgroep, doelgroep)) return; @@ -132,9 +139,18 @@ public void VoegVertegenwoordigerToe(Vertegenwoordiger vertegenwoordiger) AddEvent(VertegenwoordigerWerdToegevoegd.With(toegevoegdeVertegenwoordiger)); } - public void WijzigVertegenwoordiger(int vertegenwoordigerId, string? rol, string? roepnaam, Email? email, TelefoonNummer? telefoonNummer, TelefoonNummer? mobiel, SocialMedia? socialMedia, bool? isPrimair) + public void WijzigVertegenwoordiger( + int vertegenwoordigerId, + string? rol, + string? roepnaam, + Email? email, + TelefoonNummer? telefoonNummer, + TelefoonNummer? mobiel, + SocialMedia? socialMedia, + bool? isPrimair) { - var gewijzigdeVertegenwoordiger = State.Vertegenwoordigers.Wijzig(vertegenwoordigerId, rol, roepnaam, email, telefoonNummer, mobiel, socialMedia, isPrimair); + var gewijzigdeVertegenwoordiger = + State.Vertegenwoordigers.Wijzig(vertegenwoordigerId, rol, roepnaam, email, telefoonNummer, mobiel, socialMedia, isPrimair); if (gewijzigdeVertegenwoordiger is null) return; diff --git a/src/AssociationRegistry/Vereniging/VerenigingState.cs b/src/AssociationRegistry/Vereniging/VerenigingState.cs index c301654d1..7b426ee42 100644 --- a/src/AssociationRegistry/Vereniging/VerenigingState.cs +++ b/src/AssociationRegistry/Vereniging/VerenigingState.cs @@ -35,6 +35,7 @@ public string Identity HoofdactiviteitenVerenigingsloket.Empty; public bool IsGestopt => Einddatum is not null; + public bool IsVerwijderd { get; set; } public long Version { get; set; } public VerenigingState Apply(FeitelijkeVerenigingWerdGeregistreerd @event) @@ -129,6 +130,9 @@ public VerenigingState Apply(StartdatumWerdGewijzigd @event) public VerenigingState Apply(VerenigingWerdGestopt @event) => this with { Einddatum = Datum.Hydrate(@event.Einddatum) }; + public VerenigingState Apply(VerenigingWerdVerwijderd @event) + => this with { IsVerwijderd = true }; + public VerenigingState Apply(EinddatumWerdGewijzigd @event) => this with { Einddatum = Datum.Hydrate(@event.Einddatum) }; diff --git a/test/AssociationRegistry.Test.Acm.Api/Fixtures/EventsInDbScenariosFixture.cs b/test/AssociationRegistry.Test.Acm.Api/Fixtures/EventsInDbScenariosFixture.cs index 973c6f274..18a7567b5 100644 --- a/test/AssociationRegistry.Test.Acm.Api/Fixtures/EventsInDbScenariosFixture.cs +++ b/test/AssociationRegistry.Test.Acm.Api/Fixtures/EventsInDbScenariosFixture.cs @@ -21,6 +21,9 @@ public readonly VerenigingMetRechtspersoonlijkheidWerdGeregistreerd_EventsInDbSc public readonly FeitelijkeVerenigingWerdGestopt_EventsInDbScenario FeitelijkeVerenigingWerdGestoptEventsInDbScenario = new(); + public readonly FeitelijkeVerenigingWerdVerwijderd_EventsInDbScenario + FeitelijkeVerenigingWerdVerwijderdEventsInDbScenario = new(); + protected override async Task Given() { var scenarios = new IEventsInDbScenario[] @@ -32,6 +35,7 @@ protected override async Task Given() VertegenwoordigerWerdVerwijderdEventsInDbScenario, VerenigingMetRechtspersoonlijkheidWerdGeregistreerdEventsInDbScenario, FeitelijkeVerenigingWerdGestoptEventsInDbScenario, + FeitelijkeVerenigingWerdVerwijderdEventsInDbScenario, }; foreach (var scenario in scenarios) diff --git a/test/AssociationRegistry.Test.Acm.Api/Fixtures/Scenarios/EventsInDbScenarios.cs b/test/AssociationRegistry.Test.Acm.Api/Fixtures/Scenarios/EventsInDbScenarios.cs index bf0c096f3..b5f665a6f 100644 --- a/test/AssociationRegistry.Test.Acm.Api/Fixtures/Scenarios/EventsInDbScenarios.cs +++ b/test/AssociationRegistry.Test.Acm.Api/Fixtures/Scenarios/EventsInDbScenarios.cs @@ -252,3 +252,33 @@ public IEvent[] GetEvents() public CommandMetadata GetCommandMetadata() => Metadata; } + +public class FeitelijkeVerenigingWerdVerwijderd_EventsInDbScenario : IEventsInDbScenario +{ + public readonly FeitelijkeVerenigingWerdGeregistreerd FeitelijkeVerenigingWerdGeregistreerd; + public readonly VerenigingWerdVerwijderd VerenigingWerdVerwijderd; + public readonly CommandMetadata Metadata; + + public FeitelijkeVerenigingWerdVerwijderd_EventsInDbScenario() + { + var fixture = new Fixture().CustomizeAcmApi(); + VCode = "V0003009"; + FeitelijkeVerenigingWerdGeregistreerd = fixture.Create() with { VCode = VCode }; + VerenigingWerdVerwijderd = fixture.Create(); + Metadata = fixture.Create() with { ExpectedVersion = null }; + } + + public string VCode { get; set; } + public StreamActionResult Result { get; set; } = null!; + + public string Insz + => FeitelijkeVerenigingWerdGeregistreerd.Vertegenwoordigers[0].Insz; + + public IEvent[] GetEvents() + => new IEvent[] + { FeitelijkeVerenigingWerdGeregistreerd, + VerenigingWerdVerwijderd}; + + public CommandMetadata GetCommandMetadata() + => Metadata; +} diff --git a/test/AssociationRegistry.Test.Acm.Api/Given_VerengingWerdVerwijderd/When_retrieving_Vereniging_for_Insz.cs b/test/AssociationRegistry.Test.Acm.Api/Given_VerengingWerdVerwijderd/When_retrieving_Vereniging_for_Insz.cs new file mode 100644 index 000000000..2952cb1e0 --- /dev/null +++ b/test/AssociationRegistry.Test.Acm.Api/Given_VerengingWerdVerwijderd/When_retrieving_Vereniging_for_Insz.cs @@ -0,0 +1,42 @@ +namespace AssociationRegistry.Test.Acm.Api.Given_VerengingWerdVerwijderd; + +using AssociationRegistry.Acm.Schema.Constants; +using AssociationRegistry.Test.Acm.Api.Fixtures; +using AssociationRegistry.Test.Acm.Api.Fixtures.Scenarios; +using AssociationRegistry.Test.Acm.Api.templates; +using AssociationRegistry.Test.Framework; +using FluentAssertions; +using System.Net; +using Xunit; +using Xunit.Categories; + +[Collection(nameof(AcmApiCollection))] +[Category("AcmApi")] +[IntegrationTest] +public class When_retrieving_Vereniging_for_Insz +{ + private readonly HttpResponseMessage _response; + private readonly FeitelijkeVerenigingWerdVerwijderd_EventsInDbScenario _scenario; + + public When_retrieving_Vereniging_for_Insz(EventsInDbScenariosFixture fixture) + { + _scenario = fixture.FeitelijkeVerenigingWerdVerwijderdEventsInDbScenario; + _response = fixture.DefaultClient.GetVerenigingenForInsz(_scenario.Insz).GetAwaiter().GetResult(); + } + + [Fact] + public void Then_we_get_a_200() + => _response.StatusCode.Should().Be(HttpStatusCode.OK); + + [Fact] + public async Task Then_we_get_a_response_with_one_vereniging() + { + var content = await _response.Content.ReadAsStringAsync(); + + var expected = + new VerenigingenPerInszResponseTemplate() + .WithInsz(_scenario.Insz); + + content.Should().BeEquivalentJson(expected); + } +} diff --git a/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/CommandHandling/With_A_Reden.cs b/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/CommandHandling/With_A_Reden.cs new file mode 100644 index 000000000..5a8d12f7b --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/CommandHandling/With_A_Reden.cs @@ -0,0 +1,50 @@ +namespace AssociationRegistry.Test.Admin.Api.FeitelijkeVereniging.When_Removing_A_Vereniging.CommandHandling; + +using Acties.VerwijderVereniging; +using AssociationRegistry.Framework; +using AutoFixture; +using Events; +using Fakes; +using Fixtures.Scenarios.CommandHandling; +using Framework; +using Vereniging; +using Xunit; + +public class With_A_Reden +{ + private readonly FeitelijkeVerenigingWerdGeregistreerdScenario _scenario; + private readonly VerenigingRepositoryMock _verenigingRepositoryMock; + private readonly VerwijderVerenigingCommand _command; + + public With_A_Reden() + { + _scenario = new FeitelijkeVerenigingWerdGeregistreerdScenario(); + _verenigingRepositoryMock = new VerenigingRepositoryMock(_scenario.GetVerenigingState()); + + var fixture = new Fixture().CustomizeAdminApi(); + + _command = new VerwijderVerenigingCommand(_scenario.VCode, Reden: "Omdat weg moet"); + + var commandMetadata = fixture.Create(); + + var commandHandler = new VerwijderVerenigingCommandHandler(_verenigingRepositoryMock); + + commandHandler.Handle( + new CommandEnvelope(_command, commandMetadata), + CancellationToken.None).GetAwaiter().GetResult(); + } + + [Fact] + public void Then_The_Correct_Vereniging_Is_Loaded_Once() + { + _verenigingRepositoryMock.ShouldHaveLoaded(_scenario.VCode); + } + + [Fact] + public void Then_A_VerenigingWerdVerwijderd_Event_Is_Saved() + { + _verenigingRepositoryMock.ShouldHaveSaved( + new VerenigingWerdVerwijderd("Omdat weg moet") + ); + } +} diff --git a/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/Given_A_Removed_Vereniging.cs b/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/Given_A_Removed_Vereniging.cs new file mode 100644 index 000000000..c5d0c6893 --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/Given_A_Removed_Vereniging.cs @@ -0,0 +1,76 @@ +namespace AssociationRegistry.Test.Admin.Api.FeitelijkeVereniging.When_Removing_A_Vereniging; + +using Events; +using Fixtures; +using Fixtures.Scenarios.EventsInDb; +using FluentAssertions; +using Marten; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System.Net; +using Xunit; +using Xunit.Categories; + +public class Remove_A_Removed_Vereniging : IAsyncLifetime +{ + private readonly EventsInDbScenariosFixture _fixture; + public V059_FeitelijkeVerenigingWerdGeregistreerd_AndRemoved Scenario { get; } + public IDocumentStore DocumentStore { get; } + public HttpResponseMessage Response { get; private set; } = null!; + + public Remove_A_Removed_Vereniging(EventsInDbScenariosFixture fixture) + { + _fixture = fixture; + + Scenario = fixture.V059FeitelijkeVerenigingWerdGeregistreerdAndRemoved; + DocumentStore = _fixture.DocumentStore; + } + + public async Task InitializeAsync() + { + Response = await _fixture.SuperAdminApiClient.DeleteVereniging(Scenario.VCode, "Omdat"); + } + + public Task DisposeAsync() + => Task.CompletedTask; +} + +[IntegrationTest] +[Collection(nameof(AdminApiCollection))] +[Category("AdminApi")] +public class Given_A_Removed_Vereniging : IClassFixture +{ + private readonly Remove_A_Removed_Vereniging _classFixture; + + public Given_A_Removed_Vereniging(Remove_A_Removed_Vereniging classFixture) + { + _classFixture = classFixture; + } + + [Fact] + public async Task Then_it_saves_no_events() + { + await using var session = _classFixture.DocumentStore.LightweightSession(); + + var verenigingWerdVerwijderd = (await session.Events + .FetchStreamAsync(_classFixture.Scenario.VCode)) + .Where(e => e.Data.GetType() == typeof(VerenigingWerdVerwijderd)); + + verenigingWerdVerwijderd.Should().HaveCount(1); + } + + [Fact] + public void Then_it_returns_a_bad_request_response() + { + _classFixture.Response.StatusCode.Should().Be(HttpStatusCode.BadRequest); + } + + [Fact] + public async Task Then_it_returns_a_correct_message() + { + var responseBody = await _classFixture.Response.Content.ReadAsStringAsync(); + var problemDetails = JsonConvert.DeserializeObject(responseBody); + + problemDetails["detail"].Value().Should().Be(ExceptionMessages.VerenigingKanNietVerwijderdWorden); + } +} diff --git a/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/Given_An_Client_With_Insufficient_Rights.cs b/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/Given_An_Client_With_Insufficient_Rights.cs new file mode 100644 index 000000000..26acbd74e --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/Given_An_Client_With_Insufficient_Rights.cs @@ -0,0 +1,65 @@ +namespace AssociationRegistry.Test.Admin.Api.FeitelijkeVereniging.When_Removing_A_Vereniging; + +using AssociationRegistry.Events; +using AssociationRegistry.Test.Admin.Api.Fixtures; +using AssociationRegistry.Test.Admin.Api.Fixtures.Scenarios.EventsInDb; +using FluentAssertions; +using Marten; +using System.Net; +using Xunit; +using Xunit.Categories; + +public class Remove_An_Existing_Vereniging_With_Insufficient_Rights : IAsyncLifetime +{ + private readonly EventsInDbScenariosFixture _fixture; + public V001_FeitelijkeVerenigingWerdGeregistreerd_WithAllFields Scenario { get; } + public IDocumentStore DocumentStore { get; } + public HttpResponseMessage Response { get; private set; } = null!; + + public Remove_An_Existing_Vereniging_With_Insufficient_Rights(EventsInDbScenariosFixture fixture) + { + _fixture = fixture; + + Scenario = fixture.V001FeitelijkeVerenigingWerdGeregistreerdWithAllFields; + DocumentStore = _fixture.DocumentStore; + } + + public async Task InitializeAsync() + { + Response = await _fixture.AdminApiClient.DeleteVereniging(Scenario.VCode, "Omdat"); + } + + public Task DisposeAsync() + => Task.CompletedTask; +} + +[IntegrationTest] +[Collection(nameof(AdminApiCollection))] +[Category("AdminApi")] +public class Given_An_Client_With_Insufficient_Rights : IClassFixture +{ + private readonly Remove_An_Existing_Vereniging_With_Insufficient_Rights _classFixture; + + public Given_An_Client_With_Insufficient_Rights(Remove_An_Existing_Vereniging_With_Insufficient_Rights classFixture) + { + _classFixture = classFixture; + } + + [Fact] + public async Task Then_it_saves_no_events() + { + await using var session = _classFixture.DocumentStore.LightweightSession(); + + var verenigingWerdVerwijderd = (await session.Events + .FetchStreamAsync(_classFixture.Scenario.VCode)) + .SingleOrDefault(e => e.Data.GetType() == typeof(VerenigingWerdVerwijderd)); + + verenigingWerdVerwijderd.Should().BeNull(); + } + + [Fact] + public void Then_it_returns_an_forbidden_response() + { + _classFixture.Response.StatusCode.Should().Be(HttpStatusCode.Forbidden); + } +} diff --git a/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/Given_An_Existing_Vereniging.cs b/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/Given_An_Existing_Vereniging.cs new file mode 100644 index 000000000..6abad9b71 --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/Given_An_Existing_Vereniging.cs @@ -0,0 +1,66 @@ +namespace AssociationRegistry.Test.Admin.Api.FeitelijkeVereniging.When_Removing_A_Vereniging; + +using AssociationRegistry.Events; +using AssociationRegistry.Test.Admin.Api.Fixtures; +using AssociationRegistry.Test.Admin.Api.Fixtures.Scenarios.EventsInDb; +using FluentAssertions; +using Marten; +using System.Net; +using Xunit; +using Xunit.Categories; + +public class Remove_An_Existing_Vereniging : IAsyncLifetime +{ + private readonly EventsInDbScenariosFixture _fixture; + public V058_FeitelijkeVerenigingWerdGeregistreerd_ForRemoval Scenario { get; } + public IDocumentStore DocumentStore { get; } + public HttpResponseMessage Response { get; private set; } = null!; + + public Remove_An_Existing_Vereniging(EventsInDbScenariosFixture fixture) + { + _fixture = fixture; + + Scenario = fixture.V058FeitelijkeVerenigingWerdGeregistreerdForRemoval; + DocumentStore = _fixture.DocumentStore; + } + + public async Task InitializeAsync() + { + Response = await _fixture.SuperAdminApiClient.DeleteVereniging(Scenario.VCode, "Omdat"); + } + + public Task DisposeAsync() + => Task.CompletedTask; +} + +[IntegrationTest] +[Collection(nameof(AdminApiCollection))] +[Category("AdminApi")] +public class Given_An_Existing_Vereniging : IClassFixture +{ + private readonly Remove_An_Existing_Vereniging _classFixture; + + public Given_An_Existing_Vereniging(Remove_An_Existing_Vereniging classFixture) + { + _classFixture = classFixture; + } + + [Fact] + public async Task Then_it_saves_the_events() + { + await using var session = _classFixture.DocumentStore.LightweightSession(); + + var verenigingWerdVerwijderd = (await session.Events + .FetchStreamAsync(_classFixture.Scenario.VCode)) + .Single(e => e.Data.GetType() == typeof(VerenigingWerdVerwijderd)); + + verenigingWerdVerwijderd.Data.Should() + .BeEquivalentTo(new VerenigingWerdVerwijderd("Omdat")); + } + + [Fact] + public void Then_it_returns_an_accepted_response() + { + _classFixture.Response.StatusCode.Should().Be(HttpStatusCode.Accepted); + } +} diff --git a/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/RequestValidating/Is_Null.cs b/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/RequestValidating/Is_Null.cs new file mode 100644 index 000000000..e197c80ca --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/RequestValidating/Is_Null.cs @@ -0,0 +1,24 @@ +namespace AssociationRegistry.Test.Admin.Api.FeitelijkeVereniging.When_Removing_A_Vereniging.RequestValidating; + +using AssociationRegistry.Admin.Api.Verenigingen.Stop; +using AssociationRegistry.Admin.Api.Verenigingen.Stop.RequestModels; +using AssociationRegistry.Admin.Api.Verenigingen.Verwijderen; +using AssociationRegistry.Admin.Api.Verenigingen.Verwijderen.RequestModels; +using AssociationRegistry.Test.Admin.Api.Framework; +using FluentValidation.TestHelper; +using Xunit; +using Xunit.Categories; + +[UnitTest] +public class Reden_Is_Null : ValidatorTest +{ + [Fact] + public void Has_validation_error_for_reden() + { + var validator = new VerwijderVerenigingRequestValidator(); + var result = validator.TestValidate(new VerwijderVerenigingRequest { Reden = null }); + + result.ShouldHaveValidationErrorFor(nameof(VerwijderVerenigingRequest.Reden)) + .WithErrorMessage("'Reden' is verplicht."); + } +} diff --git a/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/RequestValidating/Is_Valid.cs b/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/RequestValidating/Is_Valid.cs new file mode 100644 index 000000000..bff900464 --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/RequestValidating/Is_Valid.cs @@ -0,0 +1,24 @@ +namespace AssociationRegistry.Test.Admin.Api.FeitelijkeVereniging.When_Removing_A_Vereniging.RequestValidating; + +using AssociationRegistry.Admin.Api.Verenigingen.Stop; +using AssociationRegistry.Admin.Api.Verenigingen.Stop.RequestModels; +using AssociationRegistry.Admin.Api.Verenigingen.Verwijderen; +using AssociationRegistry.Admin.Api.Verenigingen.Verwijderen.RequestModels; +using AssociationRegistry.Test.Admin.Api.Framework; +using AssociationRegistry.Vereniging; +using FluentValidation.TestHelper; +using Xunit; +using Xunit.Categories; + +[UnitTest] +public class Reden_Is_Valid : ValidatorTest +{ + [Fact] + public void Has_no_validation_error_for_reden() + { + var validator = new VerwijderVerenigingRequestValidator(); + var result = validator.TestValidate(new VerwijderVerenigingRequest { Reden = "Eender welke reden is goed!" }); + + result.ShouldNotHaveValidationErrorFor(nameof(VerwijderVerenigingRequest.Reden)); + } +} diff --git a/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/RequestValidating/Reden_Is_Empty.cs b/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/RequestValidating/Reden_Is_Empty.cs new file mode 100644 index 000000000..fe5008a2d --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/RequestValidating/Reden_Is_Empty.cs @@ -0,0 +1,22 @@ +namespace AssociationRegistry.Test.Admin.Api.FeitelijkeVereniging.When_Removing_A_Vereniging.RequestValidating; + +using AssociationRegistry.Admin.Api.Verenigingen.Verwijderen; +using AssociationRegistry.Admin.Api.Verenigingen.Verwijderen.RequestModels; +using FluentValidation.TestHelper; +using Framework; +using Xunit; +using Xunit.Categories; + +[UnitTest] +public class Reden_Is_Empty : ValidatorTest +{ + [Fact] + public void Has_validation_error_for_reden() + { + var validator = new VerwijderVerenigingRequestValidator(); + var result = validator.TestValidate(new VerwijderVerenigingRequest { Reden = string.Empty }); + + result.ShouldHaveValidationErrorFor(nameof(VerwijderVerenigingRequest.Reden)) + .WithErrorMessage("'Reden' mag niet leeg zijn."); + } +} diff --git a/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/RequestValidating/Reden_Is_Html.cs b/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/RequestValidating/Reden_Is_Html.cs new file mode 100644 index 000000000..f6a01064c --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/FeitelijkeVereniging/When_Removing_A_Vereniging/RequestValidating/Reden_Is_Html.cs @@ -0,0 +1,22 @@ +namespace AssociationRegistry.Test.Admin.Api.FeitelijkeVereniging.When_Removing_A_Vereniging.RequestValidating; + +using AssociationRegistry.Admin.Api.Verenigingen.Verwijderen; +using AssociationRegistry.Admin.Api.Verenigingen.Verwijderen.RequestModels; +using FluentValidation.TestHelper; +using Framework; +using Xunit; +using Xunit.Categories; + +[UnitTest] +public class Reden_Is_Html : ValidatorTest +{ + [Fact] + public void Has_validation_error_for_reden() + { + var validator = new VerwijderVerenigingRequestValidator(); + var result = validator.TestValidate(new VerwijderVerenigingRequest { Reden = "

Injecteer html

" }); + + result.ShouldHaveValidationErrorFor(nameof(VerwijderVerenigingRequest.Reden)) + .WithErrorMessage(ExceptionMessages.UnsupportedContent); + } +} diff --git a/test/AssociationRegistry.Test.Admin.Api/Fixtures/AdminApiClient.cs b/test/AssociationRegistry.Test.Admin.Api/Fixtures/AdminApiClient.cs index cefe00ef0..514a158ca 100644 --- a/test/AssociationRegistry.Test.Admin.Api/Fixtures/AdminApiClient.cs +++ b/test/AssociationRegistry.Test.Admin.Api/Fixtures/AdminApiClient.cs @@ -3,6 +3,7 @@ namespace AssociationRegistry.Test.Admin.Api.Fixtures; using Framework.Helpers; using global::AssociationRegistry.Admin.Api.Infrastructure; using Microsoft.Net.Http.Headers; +using Newtonsoft.Json; public class AdminApiClient : IDisposable { @@ -174,6 +175,7 @@ public async Task DeleteVertegenwoordiger( { Method = HttpMethod.Delete, RequestUri = new Uri($"/v1/verenigingen/{vCode}/vertegenwoordigers/{vertegenwoordigerId}", UriKind.Relative), + Content = jsonBody.AsJsonContent(), }; return await HttpClient.SendAsync(request); @@ -279,6 +281,25 @@ public async Task RebuildPubliekDetailProjection(Cancellati public async Task RebuildPubliekZoekenProjection(CancellationToken cancellationToken) => await HttpClient.PostAsync(requestUri: "/v1/projections/public/search/rebuild", content: null, cancellationToken); + public async Task DeleteVereniging( + string vCode, + string reason, + long? version = null, + string initiator = "V0001001") + { + WithHeaders(version, initiator); + + var request = new HttpRequestMessage + { + Method = HttpMethod.Delete, + RequestUri = new Uri($"/v1/verenigingen/{vCode}", UriKind.Relative), + Content = JsonConvert.SerializeObject(new { Reden = reason }).AsJsonContent(), + }; + + return await HttpClient.SendAsync(request); + } + + public async Task GetJsonLdContext(string contextName) => await HttpClient.GetAsync($"/v1/contexten/beheer/{contextName}"); } diff --git a/test/AssociationRegistry.Test.Admin.Api/Fixtures/AdminApiFixture.cs b/test/AssociationRegistry.Test.Admin.Api/Fixtures/AdminApiFixture.cs index 125ed4583..ba40715f1 100644 --- a/test/AssociationRegistry.Test.Admin.Api/Fixtures/AdminApiFixture.cs +++ b/test/AssociationRegistry.Test.Admin.Api/Fixtures/AdminApiFixture.cs @@ -44,6 +44,9 @@ public IDocumentStore DocumentStore public AdminApiClient AdminApiClient => new(Clients.GetAuthenticatedHttpClient()); + public AdminApiClient SuperAdminApiClient + => Clients.SuperAdmin; + private string VerenigingenIndexName => GetConfiguration()["ElasticClientOptions:Indices:Verenigingen"]; diff --git a/test/AssociationRegistry.Test.Admin.Api/Fixtures/EventsInDbScenariosFixture.cs b/test/AssociationRegistry.Test.Admin.Api/Fixtures/EventsInDbScenariosFixture.cs index f80aa787c..2d5f37893 100644 --- a/test/AssociationRegistry.Test.Admin.Api/Fixtures/EventsInDbScenariosFixture.cs +++ b/test/AssociationRegistry.Test.Admin.Api/Fixtures/EventsInDbScenariosFixture.cs @@ -127,6 +127,18 @@ public readonly V056_VerenigingWerdGeregistreerd_And_Gestopt_For_DuplicateDetect public readonly V057_VerenigingWerdGeregistreerd_With_KboLocatie_For_DuplicateDetection V057VerenigingWerdGeregistreerdWithKboLocatieForDuplicateDetection = new(); + public readonly V058_FeitelijkeVerenigingWerdGeregistreerd_ForRemoval + V058FeitelijkeVerenigingWerdGeregistreerdForRemoval = new(); + + public readonly V059_FeitelijkeVerenigingWerdGeregistreerd_AndRemoved + V059FeitelijkeVerenigingWerdGeregistreerdAndRemoved = new(); + + public readonly V060_VerenigingWerdGeregistreerd_And_Verwijderd_For_DuplicateDetection + V060VerenigingWerdGeregistreerdAndVerwijderdForDuplicateDetection = new(); + + public readonly V061_VerenigingWerdGeregistreerd_And_Verwijderd_And_FollowedByUpdates + V061VerenigingWerdGeregistreerdAndVerwijderdAndFollowedByUpdates = new(); + protected override async Task Given() { var scenarios = new IEventsInDbScenario[] @@ -174,6 +186,10 @@ protected override async Task Given() V046FeitelijkeVerenigingWerdGeregistreerdForWijzigStartdatum, V056VerenigingWerdGeregistreerdAndGestoptForDuplicateDetection, V057VerenigingWerdGeregistreerdWithKboLocatieForDuplicateDetection, + V058FeitelijkeVerenigingWerdGeregistreerdForRemoval, + V059FeitelijkeVerenigingWerdGeregistreerdAndRemoved, + V060VerenigingWerdGeregistreerdAndVerwijderdForDuplicateDetection, + V061VerenigingWerdGeregistreerdAndVerwijderdAndFollowedByUpdates, }; foreach (var scenario in scenarios) diff --git a/test/AssociationRegistry.Test.Admin.Api/Fixtures/Scenarios/EventsInDb/V058_FeitelijkeVerenigingWerdGeregistreerd_ForRemoval.cs b/test/AssociationRegistry.Test.Admin.Api/Fixtures/Scenarios/EventsInDb/V058_FeitelijkeVerenigingWerdGeregistreerd_ForRemoval.cs new file mode 100644 index 000000000..624b30241 --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/Fixtures/Scenarios/EventsInDb/V058_FeitelijkeVerenigingWerdGeregistreerd_ForRemoval.cs @@ -0,0 +1,43 @@ +namespace AssociationRegistry.Test.Admin.Api.Fixtures.Scenarios.EventsInDb; + +using AssociationRegistry.Framework; +using AutoFixture; +using Events; +using EventStore; +using Framework; + +public class V058_FeitelijkeVerenigingWerdGeregistreerd_ForRemoval : IEventsInDbScenario +{ + public readonly FeitelijkeVerenigingWerdGeregistreerd FeitelijkeVerenigingWerdGeregistreerd; + public readonly CommandMetadata Metadata; + + public V058_FeitelijkeVerenigingWerdGeregistreerd_ForRemoval() + { + var fixture = new Fixture().CustomizeAdminApi(); + VCode = VCode; + + FeitelijkeVerenigingWerdGeregistreerd = fixture.Create() with + { + VCode = VCode, + Locaties = Array.Empty(), + KorteNaam = string.Empty, + Startdatum = null, + KorteBeschrijving = string.Empty, + Contactgegevens = Array.Empty(), + Vertegenwoordigers = Array.Empty(), + HoofdactiviteitenVerenigingsloket = Array.Empty(), + }; + + Metadata = fixture.Create() with { ExpectedVersion = null }; + } + + public string VCode { get; set; } = "V9999058"; + public StreamActionResult Result { get; set; } = null!; + + public IEvent[] GetEvents() + => new IEvent[] + { FeitelijkeVerenigingWerdGeregistreerd }; + + public CommandMetadata GetCommandMetadata() + => Metadata; +} diff --git a/test/AssociationRegistry.Test.Admin.Api/Fixtures/Scenarios/EventsInDb/V059_FeitelijkeVerenigingWerdGeregistreerd_AndRemoved.cs b/test/AssociationRegistry.Test.Admin.Api/Fixtures/Scenarios/EventsInDb/V059_FeitelijkeVerenigingWerdGeregistreerd_AndRemoved.cs new file mode 100644 index 000000000..2bd9ff110 --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/Fixtures/Scenarios/EventsInDb/V059_FeitelijkeVerenigingWerdGeregistreerd_AndRemoved.cs @@ -0,0 +1,45 @@ +namespace AssociationRegistry.Test.Admin.Api.Fixtures.Scenarios.EventsInDb; + +using AssociationRegistry.Framework; +using AutoFixture; +using Events; +using EventStore; +using Framework; + +public class V059_FeitelijkeVerenigingWerdGeregistreerd_AndRemoved : IEventsInDbScenario +{ + public readonly FeitelijkeVerenigingWerdGeregistreerd FeitelijkeVerenigingWerdGeregistreerd; + public readonly VerenigingWerdVerwijderd VerenigingWerdVerwijderd; + public readonly CommandMetadata Metadata; + + public V059_FeitelijkeVerenigingWerdGeregistreerd_AndRemoved() + { + var fixture = new Fixture().CustomizeAdminApi(); + VCode = VCode; + + FeitelijkeVerenigingWerdGeregistreerd = fixture.Create() with + { + VCode = VCode, + Locaties = Array.Empty(), + KorteNaam = string.Empty, + Startdatum = null, + KorteBeschrijving = string.Empty, + Contactgegevens = Array.Empty(), + Vertegenwoordigers = Array.Empty(), + HoofdactiviteitenVerenigingsloket = Array.Empty(), + }; + + VerenigingWerdVerwijderd = fixture.Create(); + Metadata = fixture.Create() with { ExpectedVersion = null }; + } + + public string VCode { get; set; } = "V9999059"; + public StreamActionResult Result { get; set; } = null!; + + public IEvent[] GetEvents() + => new IEvent[] + { FeitelijkeVerenigingWerdGeregistreerd, VerenigingWerdVerwijderd }; + + public CommandMetadata GetCommandMetadata() + => Metadata; +} diff --git a/test/AssociationRegistry.Test.Admin.Api/Fixtures/Scenarios/EventsInDb/V060_VerenigingWerdGeregistreerd_And_Verwijderd_For_DuplicateDetection.cs b/test/AssociationRegistry.Test.Admin.Api/Fixtures/Scenarios/EventsInDb/V060_VerenigingWerdGeregistreerd_And_Verwijderd_For_DuplicateDetection.cs new file mode 100644 index 000000000..9f5e540df --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/Fixtures/Scenarios/EventsInDb/V060_VerenigingWerdGeregistreerd_And_Verwijderd_For_DuplicateDetection.cs @@ -0,0 +1,44 @@ +namespace AssociationRegistry.Test.Admin.Api.Fixtures.Scenarios.EventsInDb; + +using AssociationRegistry.Framework; +using AutoFixture; +using Events; +using EventStore; +using Framework; + +public class V060_VerenigingWerdGeregistreerd_And_Verwijderd_For_DuplicateDetection : IEventsInDbScenario +{ + public readonly CommandMetadata Metadata; + public readonly FeitelijkeVerenigingWerdGeregistreerd FeitelijkeVerenigingWerdGeregistreerd; + public readonly VerenigingWerdVerwijderd VerenigingWerdVerwijderd; + + public V060_VerenigingWerdGeregistreerd_And_Verwijderd_For_DuplicateDetection() + { + var fixture = new Fixture().CustomizeAdminApi(); + + FeitelijkeVerenigingWerdGeregistreerd = fixture.Create() with + { + VCode = VCode, + Locaties = new[] + { + fixture.Create() with + { + Adres = fixture.Create(), + }, + }, + }; + + VerenigingWerdVerwijderd = fixture.Create(); + Metadata = fixture.Create() with { ExpectedVersion = null }; + } + + public string VCode { get; set; } = "V9999060"; + public StreamActionResult Result { get; set; } = null!; + + public IEvent[] GetEvents() + => new IEvent[] + { FeitelijkeVerenigingWerdGeregistreerd, VerenigingWerdVerwijderd }; + + public CommandMetadata GetCommandMetadata() + => Metadata; +} diff --git a/test/AssociationRegistry.Test.Admin.Api/Fixtures/Scenarios/EventsInDb/V061_VerenigingWerdGeregistreerd_And_Verwijderd_And_FollowedByUpdates.cs b/test/AssociationRegistry.Test.Admin.Api/Fixtures/Scenarios/EventsInDb/V061_VerenigingWerdGeregistreerd_And_Verwijderd_And_FollowedByUpdates.cs new file mode 100644 index 000000000..ddd81227a --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/Fixtures/Scenarios/EventsInDb/V061_VerenigingWerdGeregistreerd_And_Verwijderd_And_FollowedByUpdates.cs @@ -0,0 +1,52 @@ +namespace AssociationRegistry.Test.Admin.Api.Fixtures.Scenarios.EventsInDb; + +using AssociationRegistry.Framework; +using AutoFixture; +using Events; +using EventStore; +using Framework; + +public class V061_VerenigingWerdGeregistreerd_And_Verwijderd_And_FollowedByUpdates : IEventsInDbScenario +{ + public readonly CommandMetadata Metadata; + public readonly FeitelijkeVerenigingWerdGeregistreerd FeitelijkeVerenigingWerdGeregistreerd; + public readonly VerenigingWerdVerwijderd VerenigingWerdVerwijderd; + + public V061_VerenigingWerdGeregistreerd_And_Verwijderd_And_FollowedByUpdates() + { + var fixture = new Fixture().CustomizeAdminApi(); + + FeitelijkeVerenigingWerdGeregistreerd = fixture.Create() with + { + VCode = VCode, + Locaties = new[] + { + fixture.Create() with + { + Adres = fixture.Create(), + }, + }, + Vertegenwoordigers = new[] + { + fixture.Create() with + { + VertegenwoordigerId = VertegenwoordigerId, + }, + }, + }; + + VerenigingWerdVerwijderd = fixture.Create(); + Metadata = fixture.Create() with { ExpectedVersion = null }; + } + + public string VCode { get; set; } = "V9999061"; + public int VertegenwoordigerId = 12345; + public StreamActionResult Result { get; set; } = null!; + + public IEvent[] GetEvents() + => new IEvent[] + { FeitelijkeVerenigingWerdGeregistreerd, VerenigingWerdVerwijderd }; + + public CommandMetadata GetCommandMetadata() + => Metadata; +} diff --git a/test/AssociationRegistry.Test.Admin.Api/WhenDetectingDuplicates/Given_A_Gestopte_Vereniging.cs b/test/AssociationRegistry.Test.Admin.Api/WhenDetectingDuplicates/Given_A_Gestopte_Vereniging.cs new file mode 100644 index 000000000..e185495b1 --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/WhenDetectingDuplicates/Given_A_Gestopte_Vereniging.cs @@ -0,0 +1,73 @@ +namespace AssociationRegistry.Test.Admin.Api.WhenDetectingDuplicates; + +using AssociationRegistry.Admin.Api.Verenigingen.Common; +using AssociationRegistry.Admin.Api.Verenigingen.Registreer.FeitelijkeVereniging.RequetsModels; +using AutoFixture; +using Fixtures; +using Fixtures.Scenarios.EventsInDb; +using FluentAssertions; +using Framework; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System.Net; +using Vereniging; +using Xunit; +using Xunit.Categories; +using Adres = AssociationRegistry.Admin.Api.Verenigingen.Common.Adres; + +[Collection(nameof(AdminApiCollection))] +[Category("AdminApi")] +[IntegrationTest] +public class Given_A_Gestopte_Vereniging +{ + private readonly AdminApiClient _adminApiClient; + private readonly Fixture _fixture; + private readonly V056_VerenigingWerdGeregistreerd_And_Gestopt_For_DuplicateDetection _scenario; + + public Given_A_Gestopte_Vereniging(EventsInDbScenariosFixture fixture) + { + _fixture = new Fixture().CustomizeAdminApi(); + _adminApiClient = fixture.AdminApiClient; + _scenario = fixture.V056VerenigingWerdGeregistreerdAndGestoptForDuplicateDetection; + } + + [Fact] + public async Task? Then_no_duplicate_is_returned() + { + var request = CreateRegistreerFeitelijkeVerenigingRequest(_scenario.FeitelijkeVerenigingWerdGeregistreerd.Naam, + _scenario.FeitelijkeVerenigingWerdGeregistreerd.Locaties.First().Adres + .Gemeente, + _scenario.FeitelijkeVerenigingWerdGeregistreerd.Locaties.First().Adres + .Postcode); + + var response = await _adminApiClient.RegistreerFeitelijkeVereniging(JsonConvert.SerializeObject(request)); + response.StatusCode.Should().Be(HttpStatusCode.Accepted); + + } + + private RegistreerFeitelijkeVerenigingRequest CreateRegistreerFeitelijkeVerenigingRequest(string naam, string gemeente, string postcode) + { + return new RegistreerFeitelijkeVerenigingRequest + { + Naam = naam, + Startdatum = null, + KorteNaam = "", + KorteBeschrijving = "", + Locaties = new[] + { + new ToeTeVoegenLocatie + { + Locatietype = Locatietype.Correspondentie, + Adres = new Adres + { + Straatnaam = _fixture.Create(), + Huisnummer = _fixture.Create(), + Postcode = postcode, + Gemeente = gemeente, + Land = _fixture.Create(), + }, + }, + }, + }; + } +} diff --git a/test/AssociationRegistry.Test.Admin.Api/WhenDetectingDuplicates/Given_A_Verwijderde_Vereniging.cs b/test/AssociationRegistry.Test.Admin.Api/WhenDetectingDuplicates/Given_A_Verwijderde_Vereniging.cs index 208133592..6d68b4995 100644 --- a/test/AssociationRegistry.Test.Admin.Api/WhenDetectingDuplicates/Given_A_Verwijderde_Vereniging.cs +++ b/test/AssociationRegistry.Test.Admin.Api/WhenDetectingDuplicates/Given_A_Verwijderde_Vereniging.cs @@ -8,7 +8,6 @@ using FluentAssertions; using Framework; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using System.Net; using Vereniging; using Xunit; @@ -22,13 +21,13 @@ public class Given_A_Verwijderde_Vereniging { private readonly AdminApiClient _adminApiClient; private readonly Fixture _fixture; - private readonly V056_VerenigingWerdGeregistreerd_And_Gestopt_For_DuplicateDetection _scenario; + private readonly V060_VerenigingWerdGeregistreerd_And_Verwijderd_For_DuplicateDetection _scenario; public Given_A_Verwijderde_Vereniging(EventsInDbScenariosFixture fixture) { _fixture = new Fixture().CustomizeAdminApi(); _adminApiClient = fixture.AdminApiClient; - _scenario = fixture.V056VerenigingWerdGeregistreerdAndGestoptForDuplicateDetection; + _scenario = fixture.V060VerenigingWerdGeregistreerdAndVerwijderdForDuplicateDetection; } [Fact] @@ -42,7 +41,6 @@ public Given_A_Verwijderde_Vereniging(EventsInDbScenariosFixture fixture) var response = await _adminApiClient.RegistreerFeitelijkeVereniging(JsonConvert.SerializeObject(request)); response.StatusCode.Should().Be(HttpStatusCode.Accepted); - } private RegistreerFeitelijkeVerenigingRequest CreateRegistreerFeitelijkeVerenigingRequest(string naam, string gemeente, string postcode) diff --git a/test/AssociationRegistry.Test.Admin.Api/When_Retrieving_Detail/Given_A_Vereniging_Has_Been_Removed.cs b/test/AssociationRegistry.Test.Admin.Api/When_Retrieving_Detail/Given_A_Vereniging_Has_Been_Removed.cs new file mode 100644 index 000000000..25fe73c55 --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/When_Retrieving_Detail/Given_A_Vereniging_Has_Been_Removed.cs @@ -0,0 +1,42 @@ +namespace AssociationRegistry.Test.Admin.Api.When_Retrieving_Detail; + +using AssociationRegistry.Admin.Api; +using Be.Vlaanderen.Basisregisters.BasicApiProblem; +using Fixtures; +using Fixtures.Scenarios.EventsInDb; +using FluentAssertions; +using Newtonsoft.Json; +using System.Net; +using Xunit; +using Xunit.Categories; + +[Collection(nameof(AdminApiCollection))] +[Category("AdminApi")] +[IntegrationTest] +public class Given_A_Vereniging_Has_Been_Removed +{ + private readonly AdminApiClient _adminApiClient; + private readonly V059_FeitelijkeVerenigingWerdGeregistreerd_AndRemoved _scenario; + private readonly HttpResponseMessage _response; + + public Given_A_Vereniging_Has_Been_Removed(EventsInDbScenariosFixture fixture) + { + _adminApiClient = fixture.SuperAdminApiClient; + _scenario = fixture.V059FeitelijkeVerenigingWerdGeregistreerdAndRemoved; + _response = _adminApiClient.GetDetail(_scenario.VCode).GetAwaiter().GetResult(); + } + + [Fact] + public void Then_we_get_a_404() + => _response.StatusCode.Should().Be(HttpStatusCode.NotFound); + + [Fact] + public async Task Then_we_get_a_detail() + { + var content = await _response.Content.ReadAsStringAsync(); + var problemDetails = JsonConvert.DeserializeObject(content); + + problemDetails.Detail.Should().NotBeEmpty(); + problemDetails.Detail.Should().Be(ValidationMessages.Status404Detail); + } +} diff --git a/test/AssociationRegistry.Test.Admin.Api/When_Retrieving_Historiek/Given_VerenigingWerdVerwijderd.cs b/test/AssociationRegistry.Test.Admin.Api/When_Retrieving_Historiek/Given_VerenigingWerdVerwijderd.cs new file mode 100644 index 000000000..5a866d476 --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/When_Retrieving_Historiek/Given_VerenigingWerdVerwijderd.cs @@ -0,0 +1,77 @@ +namespace AssociationRegistry.Test.Admin.Api.When_Retrieving_Historiek; + +using AssociationRegistry.Admin.ProjectionHost.Infrastructure.Extensions; +using AssociationRegistry.Framework; +using Fixtures; +using Fixtures.Scenarios.EventsInDb; +using EventStore; +using FluentAssertions; +using Framework; +using System.Net; +using System.Text.RegularExpressions; +using Xunit; +using Xunit.Categories; + +[Collection(nameof(AdminApiCollection))] +[Category("AdminApi")] +[IntegrationTest] +public class Given_VerenigingWerdVerwijderd +{ + private readonly AdminApiClient _adminApiClient; + private readonly StreamActionResult _result; + private readonly HttpResponseMessage _response; + private readonly CommandMetadata _metadata; + private readonly V059_FeitelijkeVerenigingWerdGeregistreerd_AndRemoved _scenario; + + public Given_VerenigingWerdVerwijderd(EventsInDbScenariosFixture fixture) + { + _adminApiClient = fixture.SuperAdminApiClient; + _scenario = fixture.V059FeitelijkeVerenigingWerdGeregistreerdAndRemoved; + _metadata = _scenario.Metadata; + _result = _scenario.Result; + _response = _adminApiClient.GetHistoriek(_scenario.VCode).GetAwaiter().GetResult(); + } + + [Fact] + public async Task Then_we_get_a_successful_response_if_sequence_is_equal_or_greater_than_expected_sequence() + => (await _adminApiClient.GetHistoriek(_scenario.VCode, _result.Sequence)) + .Should().BeSuccessful(); + + [Fact] + public async Task Then_we_get_a_successful_response_if_no_sequence_provided() + => (await _adminApiClient.GetHistoriek(_scenario.VCode)) + .Should().BeSuccessful(); + + [Fact] + public async Task Then_we_get_a_precondition_failed_response_if_sequence_is_less_than_expected_sequence() + => (await _adminApiClient.GetHistoriek(_scenario.VCode, long.MaxValue)) + .StatusCode + .Should().Be(HttpStatusCode.PreconditionFailed); + + [Fact] + public async Task Then_we_get_registratie_gebeurtenissen() + { + var content = await _response.Content.ReadAsStringAsync(); + content = Regex.Replace(content, "\"datumLaatsteAanpassing\":\".+\"", "\"datumLaatsteAanpassing\":\"\""); + + var expected = $@" + {{ + ""@context"": ""{"http://127.0.0.1:11003/v1/contexten/beheer/historiek-vereniging-context.json"}"", + ""vCode"": ""{_scenario.VCode}"", + ""gebeurtenissen"": [ + {{ + ""beschrijving"": ""Deze vereniging werd verwijderd."", + ""gebeurtenis"": ""VerenigingWerdVerwijderd"", + ""data"": {{ + ""reden"": ""{_scenario.VerenigingWerdVerwijderd.Reden}"" + }}, + ""initiator"":""{_metadata.Initiator}"", + ""tijdstip"":""{_metadata.Tijdstip.ToZuluTime()}"" + }} + ] + }} + "; + + content.Should().BeEquivalentJson(expected); + } +} diff --git a/test/AssociationRegistry.Test.Admin.Api/When_Retrieving_Historiek/Projecting/Given_VerenigingWerdVerwijderd.cs b/test/AssociationRegistry.Test.Admin.Api/When_Retrieving_Historiek/Projecting/Given_VerenigingWerdVerwijderd.cs new file mode 100644 index 000000000..3b9c285a7 --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/When_Retrieving_Historiek/Projecting/Given_VerenigingWerdVerwijderd.cs @@ -0,0 +1,36 @@ +namespace AssociationRegistry.Test.Admin.Api.When_Retrieving_Historiek.Projecting; + +using AssociationRegistry.Admin.ProjectionHost.Infrastructure.Extensions; +using AssociationRegistry.Admin.ProjectionHost.Projections.Historiek; +using AssociationRegistry.Admin.Schema.Historiek; +using AutoFixture; +using Events; +using FluentAssertions; +using Framework; +using Xunit; +using Xunit.Categories; + +[UnitTest] +public class Given_VerenigingWerdVerwijderd +{ + [Fact] + public void Then_it_adds_the_verwijderd_gebeurtenis() + { + var fixture = new Fixture().CustomizeAdminApi(); + var verenigingWerdVerwijderd = fixture.Create>(); + + var doc = fixture.Create(); + + BeheerVerenigingHistoriekProjector.Apply(verenigingWerdVerwijderd, doc); + + doc.Gebeurtenissen.Should().HaveCount(1); + + doc.Gebeurtenissen.Should().ContainEquivalentOf( + new BeheerVerenigingHistoriekGebeurtenis( + "Deze vereniging werd verwijderd.", + nameof(VerenigingWerdVerwijderd), + verenigingWerdVerwijderd.Data, + verenigingWerdVerwijderd.Initiator, + verenigingWerdVerwijderd.Tijdstip.ToZuluTime())); + } +} diff --git a/test/AssociationRegistry.Test.Admin.Api/When_Searching/Given_A_Vereniging_Has_Been_Removed.cs b/test/AssociationRegistry.Test.Admin.Api/When_Searching/Given_A_Vereniging_Has_Been_Removed.cs new file mode 100644 index 000000000..fc5f4bd76 --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/When_Searching/Given_A_Vereniging_Has_Been_Removed.cs @@ -0,0 +1,41 @@ +namespace AssociationRegistry.Test.Admin.Api.When_Searching; + +using Fixtures; +using Fixtures.Scenarios.EventsInDb; +using FluentAssertions; +using templates; +using Test.Framework; +using Xunit; +using Xunit.Categories; + +[Collection(nameof(AdminApiCollection))] +[Category("AdminApi")] +[IntegrationTest] +public class Given_A_Vereniging_Has_Been_Removed +{ + private readonly AdminApiClient _adminApiClient; + private readonly V059_FeitelijkeVerenigingWerdGeregistreerd_AndRemoved _scenario; + + public Given_A_Vereniging_Has_Been_Removed(EventsInDbScenariosFixture fixture) + { + _adminApiClient = fixture.SuperAdminApiClient; + _scenario = fixture.V059FeitelijkeVerenigingWerdGeregistreerdAndRemoved; + } + + [Fact] + public async Task Then_we_get_a_successful_response() + => (await _adminApiClient.Search(_scenario.VCode)).Should().BeSuccessful(); + + [Fact] + public async Task? Then_we_retrieve_no_vereniging_matching_the_VCode_searched() + { + var query = $"vCode:{_scenario.FeitelijkeVerenigingWerdGeregistreerd.VCode}"; + var response = await _adminApiClient.Search(query); + var content = await response.Content.ReadAsStringAsync(); + + var goldenMaster = new ZoekVerenigingenResponseTemplate() + .FromQuery(query); + + content.Should().BeEquivalentJson(goldenMaster); + } +} diff --git a/test/AssociationRegistry.Test.Admin.Api/When_Wijzig_Anything_In_A_Vereniging/Given_A_Vereniging_Has_Been_Deleted.cs b/test/AssociationRegistry.Test.Admin.Api/When_Wijzig_Anything_In_A_Vereniging/Given_A_Vereniging_Has_Been_Deleted.cs new file mode 100644 index 000000000..4f8995d75 --- /dev/null +++ b/test/AssociationRegistry.Test.Admin.Api/When_Wijzig_Anything_In_A_Vereniging/Given_A_Vereniging_Has_Been_Deleted.cs @@ -0,0 +1,106 @@ +namespace AssociationRegistry.Test.Admin.Api.When_Wijzig_Anything_In_A_Vereniging; + +using AssociationRegistry.Admin.Api.Verenigingen.Common; +using AssociationRegistry.Admin.Api.Verenigingen.Contactgegevens.FeitelijkeVereniging.VoegContactGegevenToe.RequestsModels; +using AssociationRegistry.Admin.Api.Verenigingen.Locaties.FeitelijkeVereniging.VoegLocatieToe.RequestModels; +using AssociationRegistry.Admin.Api.Verenigingen.Verwijderen.RequestModels; +using AssociationRegistry.Admin.Api.Verenigingen.WijzigBasisgegevens.FeitelijkeVereniging.RequestModels; +using AutoFixture; +using EventStore; +using Fixtures; +using Fixtures.Scenarios.EventsInDb; +using FluentAssertions; +using Framework; +using Newtonsoft.Json; +using System.Net; +using Vereniging; +using Xunit; +using Xunit.Categories; + +[Collection(nameof(AdminApiCollection))] +[Category("AdminApi")] +[IntegrationTest] +public class Given_A_Vereniging_Has_Been_Deleted +{ + private const string TEST_INITIATOR = EventStore.DigitaalVlaanderenOvoNumber; + private readonly Clients _clients; + private readonly Fixture _fixture; + private readonly V061_VerenigingWerdGeregistreerd_And_Verwijderd_And_FollowedByUpdates _scenario; + + public Given_A_Vereniging_Has_Been_Deleted(EventsInDbScenariosFixture fixture) + { + _fixture = new Fixture().CustomizeAdminApi(); + _clients = fixture.Clients; + _scenario = fixture.V061VerenigingWerdGeregistreerdAndVerwijderdAndFollowedByUpdates; + } + + [Fact] + // Naam wijzigen van vereniging + public async Task It_Should_Return_NotFound_Or_BadRequest_OnPatch_When_WijzigVereniging() + { + var response = await _clients.Authenticated.PatchVereniging( + VCode.Create(_scenario.VCode), + JsonConvert.SerializeObject(new WijzigBasisgegevensRequest + { + Naam = "Nieuwe naam voor vereniging", + }), + initiator: TEST_INITIATOR); + + response.StatusCode.Should().BeOneOf(HttpStatusCode.NotFound, HttpStatusCode.BadRequest); + } + + [Fact] + // Nieuw contactgegeven toevoegen + public async Task It_Should_Return_NotFound_Or_BadRequest_OnPost_When_Adding_Contactgegeven() + { + var response = await _clients.Authenticated.PostContactgegevens( + VCode.Create(_scenario.VCode), + JsonConvert.SerializeObject(new VoegContactgegevenToeRequest + { + Contactgegeven = _fixture.Create(), + }), + initiator: TEST_INITIATOR); + + response.StatusCode.Should().BeOneOf(HttpStatusCode.NotFound, HttpStatusCode.BadRequest); + } + + [Fact] + // Vertegenwoordiger verwijderen + public async Task It_Should_Return_NotFound_Or_BadRequest_OnDelete_When_Removing_Vertegenwoordiger() + { + var response = await _clients.Authenticated.DeleteVertegenwoordiger( + VCode.Create(_scenario.VCode), + _scenario.VertegenwoordigerId, + jsonBody: "", + initiator: TEST_INITIATOR); + + response.StatusCode.Should().BeOneOf(HttpStatusCode.NotFound, HttpStatusCode.BadRequest); + } + + [Fact] + // Nieuwe locatie toevoegen + public async Task It_Should_Return_NotFound_Or_BadRequest_OnPost_When_Adding_Locatie() + { + var response = await _clients.Authenticated.PostLocatie( + VCode.Create(_scenario.VCode), + JsonConvert.SerializeObject(new VoegLocatieToeRequest + { + Locatie = _fixture.Create(), + }), + initiator: TEST_INITIATOR); + + response.StatusCode.Should().BeOneOf(HttpStatusCode.NotFound, HttpStatusCode.BadRequest); + } + + [Fact] + // Nieuwe locatie toevoegen + public async Task It_Should_Return_NotFound_Or_BadRequest_OnDelete() + { + var response = await _clients.SuperAdmin.DeleteVereniging( + VCode.Create(_scenario.VCode), + JsonConvert.SerializeObject(_fixture.Create()), + initiator: TEST_INITIATOR); + + response.StatusCode.Should().BeOneOf(HttpStatusCode.NotFound, HttpStatusCode.BadRequest); + } +} diff --git a/test/AssociationRegistry.Test.Public.Api/Fixtures/GivenEvents/GivenEventsFixture.cs b/test/AssociationRegistry.Test.Public.Api/Fixtures/GivenEvents/GivenEventsFixture.cs index 60ab0114a..725bfc47b 100644 --- a/test/AssociationRegistry.Test.Public.Api/Fixtures/GivenEvents/GivenEventsFixture.cs +++ b/test/AssociationRegistry.Test.Public.Api/Fixtures/GivenEvents/GivenEventsFixture.cs @@ -5,19 +5,39 @@ namespace AssociationRegistry.Test.Public.Api.Fixtures.GivenEvents; public class GivenEventsFixture : PublicApiFixture { public readonly V001_FeitelijkeVerenigingWerdGeregistreerdScenario V001FeitelijkeVerenigingWerdGeregistreerdScenario = new(); - public readonly V002_FeitelijkeVerenigingWerdGeregistreerdWithMinimalFieldsScenario V002FeitelijkeVerenigingWerdGeregistreerdWithMinimalFieldsScenario = new(); + + public readonly V002_FeitelijkeVerenigingWerdGeregistreerdWithMinimalFieldsScenario + V002FeitelijkeVerenigingWerdGeregistreerdWithMinimalFieldsScenario = new(); + public readonly V003_BasisgegevensWerdenGewijzigdScenario V003BasisgegevensWerdenGewijzigdScenario = new(); - public readonly V004_UnHandledEventAndFeitelijkeVerenigingWerdGeregistreerdScenario V004UnHandledEventAndFeitelijkeVerenigingWerdGeregistreerdScenario = new(); + + public readonly V004_UnHandledEventAndFeitelijkeVerenigingWerdGeregistreerdScenario + V004UnHandledEventAndFeitelijkeVerenigingWerdGeregistreerdScenario = new(); + public readonly V005_ContactgegevenWerdToegevoegdScenario V005ContactgegevenWerdToegevoegdScenario = new(); - public readonly V006_VerenigingMetRechtspersoonlijkheidWerdGeregistreerdScenario V006VerenigingMetRechtspersoonlijkheidWerdGeregistreerdScenario = new(); - public readonly V010_FeitelijkeVerenigingWerdGeregistreerdAndUitgeschrevenUitPubliekeDatastroomScenario V010FeitelijkeVerenigingWerdGeregistreerdAndUitgeschrevenUitPubliekeDatastroomScenario = new(); + + public readonly V006_VerenigingMetRechtspersoonlijkheidWerdGeregistreerdScenario + V006VerenigingMetRechtspersoonlijkheidWerdGeregistreerdScenario = new(); + + public readonly V010_FeitelijkeVerenigingWerdGeregistreerdAndUitgeschrevenUitPubliekeDatastroomScenario + V010FeitelijkeVerenigingWerdGeregistreerdAndUitgeschrevenUitPubliekeDatastroomScenario = new(); + public readonly V011_LocatieWerdToegevoegdScenario V011LocatieWerdToegevoegdScenario = new(); public readonly V012_LocatieWerdVerwijderdScenario V012LocatieWerdVerwijderdScenario = new(); public readonly V013_LocatieWerdGewijzigdScenario V013LocatieWerdGewijzigdScenario = new(); - public readonly V014_VerenigingMetRechtspersoonlijkheidWerdGeregistreerd_With_All_Data_Scenario V014VerenigingMetRechtspersoonlijkheidWerdGeregistreerdWithAllDataScenario = new(); - public readonly V015_VerenigingMetRechtspersoonlijkheidWerdGeregistreerd_With_WijzigBasisgegevens V015VerenigingMetRechtspersoonlijkheidWerdGeregistreerdWithWijzigBasisgegevens = new(); + + public readonly V014_VerenigingMetRechtspersoonlijkheidWerdGeregistreerd_With_All_Data_Scenario + V014VerenigingMetRechtspersoonlijkheidWerdGeregistreerdWithAllDataScenario = new(); + + public readonly V015_VerenigingMetRechtspersoonlijkheidWerdGeregistreerd_With_WijzigBasisgegevens + V015VerenigingMetRechtspersoonlijkheidWerdGeregistreerdWithWijzigBasisgegevens = new(); + public readonly V016_VerenigingWerdGestopt V016VerenigingWerdGestopt = new(); - public readonly V017_VerenigingMetRechtspersoonlijkheidWerdGeregistreerd_With_WijzigMaatschappelijkeZetel_Scenario V017VerenigingMetRechtspersoonlijkheidWerdGeregistreerdWithWijzigMaatschappelijkeZetelScenario = new(); + + public readonly V017_VerenigingMetRechtspersoonlijkheidWerdGeregistreerd_With_WijzigMaatschappelijkeZetel_Scenario + V017VerenigingMetRechtspersoonlijkheidWerdGeregistreerdWithWijzigMaatschappelijkeZetelScenario = new(); + + public readonly V018_FeitelijkeVerenigingWerdVerwijderdScenario V018_FeitelijkeVerenigingWerdVerwijderdScenario = new(); private IEnumerable Scenarios => new IScenario[] @@ -36,9 +56,9 @@ private IEnumerable Scenarios V015VerenigingMetRechtspersoonlijkheidWerdGeregistreerdWithWijzigBasisgegevens, V016VerenigingWerdGestopt, V017VerenigingMetRechtspersoonlijkheidWerdGeregistreerdWithWijzigMaatschappelijkeZetelScenario, + V018_FeitelijkeVerenigingWerdVerwijderdScenario, }; - public override async Task InitializeAsync() { foreach (var scenario in Scenarios) diff --git a/test/AssociationRegistry.Test.Public.Api/Fixtures/GivenEvents/Scenarios/V018_FeitelijkeVerenigingWerdVerwijderdScenario.cs b/test/AssociationRegistry.Test.Public.Api/Fixtures/GivenEvents/Scenarios/V018_FeitelijkeVerenigingWerdVerwijderdScenario.cs new file mode 100644 index 000000000..445556caf --- /dev/null +++ b/test/AssociationRegistry.Test.Public.Api/Fixtures/GivenEvents/Scenarios/V018_FeitelijkeVerenigingWerdVerwijderdScenario.cs @@ -0,0 +1,101 @@ +namespace AssociationRegistry.Test.Public.Api.Fixtures.GivenEvents.Scenarios; + +using AssociationRegistry.Framework; +using Events; +using NodaTime; +using Vereniging; + +public class V018_FeitelijkeVerenigingWerdVerwijderdScenario : IScenario +{ + public readonly FeitelijkeVerenigingWerdGeregistreerd FeitelijkeVerenigingWerdGeregistreerd = new( + VCode: "V0001018", + Naam: "Feestcommittee Oudenaarde", + KorteNaam: "FOud", + KorteBeschrijving: "Het feestcommittee van Oudenaarde", + DateOnly.FromDateTime(new DateTime(year: 2022, month: 11, day: 9)), + new Registratiedata.Doelgroep(Minimumleeftijd: 20, Maximumleeftijd: 71), + IsUitgeschrevenUitPubliekeDatastroom: false, + new[] + { + new Registratiedata.Contactgegeven( + ContactgegevenId: 1, + Contactgegeventype.Email, + Waarde: "info@FOud.be", + Beschrijving: "Algemeen", + IsPrimair: true), + }, + new[] + { + new( + LocatieId: 1, + Locatietype: "Correspondentie", + IsPrimair: true, + Naam: "Correspondentie", + new Registratiedata.Adres( + Straatnaam: "Stationsstraat", + Huisnummer: "1", + Busnummer: "B", + Postcode: "1790", + Gemeente: "Affligem", + Land: "België"), + new Registratiedata.AdresId( + Adresbron.AR, + Bronwaarde: "https://data.vlaanderen.be/id/adres/0")), + new( + LocatieId: 2, + Locatietype: "Activiteiten", + IsPrimair: false, + Naam: "Activiteiten", + Adres: null, + new Registratiedata.AdresId( + Adresbron.AR, + Bronwaarde: "https://data.vlaanderen.be/id/adres/0")), + new Registratiedata.Locatie( + LocatieId: 3, + Locatietype: "Activiteiten", + IsPrimair: false, + Naam: "Activiteiten", + new Registratiedata.Adres( + Straatnaam: "Dorpstraat", + Huisnummer: "1", + Busnummer: "B", + Postcode: "1790", + Gemeente: "Affligem", + Land: "België"), + AdresId: null), + }, + new[] + { + new Registratiedata.Vertegenwoordiger( + VertegenwoordigerId: 1, + Insz: "01234567890", + IsPrimair: true, + Roepnaam: "father", + Rol: "Leader", + Voornaam: "Odin", + Achternaam: "Allfather", + Email: "asgard@world.tree", + Telefoon: "", + Mobiel: "", + SocialMedia: ""), + }, + new Registratiedata.HoofdactiviteitVerenigingsloket[] + { + new(Code: "BLA", Naam: "Buitengewoon Leuke Afkortingen"), + }); + + public VCode VCode + => VCode.Create(FeitelijkeVerenigingWerdGeregistreerd.VCode); + + public IEvent[] GetEvents() + { + return new IEvent[] + { + FeitelijkeVerenigingWerdGeregistreerd, + new VerenigingWerdVerwijderd("Zomaar"), + }; + } + + public CommandMetadata GetCommandMetadata() + => new(Initiator: "OVO000001", new Instant(), Guid.NewGuid()); +} diff --git a/test/AssociationRegistry.Test.Public.Api/When_Retrieving_Detail/Given_FeitelijkeVerenigingWerdVerwijderd.cs b/test/AssociationRegistry.Test.Public.Api/When_Retrieving_Detail/Given_FeitelijkeVerenigingWerdVerwijderd.cs new file mode 100644 index 000000000..b6c0b4c8b --- /dev/null +++ b/test/AssociationRegistry.Test.Public.Api/When_Retrieving_Detail/Given_FeitelijkeVerenigingWerdVerwijderd.cs @@ -0,0 +1,34 @@ +namespace AssociationRegistry.Test.Public.Api.When_Retrieving_Detail; + +using AssociationRegistry.Public.Api.Constants; +using Fixtures; +using Fixtures.GivenEvents; +using Fixtures.GivenEvents.Scenarios; +using Framework; +using FluentAssertions; +using System.Net; +using templates; +using Xunit; +using Xunit.Categories; + +[Collection(nameof(PublicApiCollection))] +[Category("PublicApi")] +[IntegrationTest] +public class Given_FeitelijkeVerenigingWerdVerwijderd +{ + private readonly PublicApiClient _publicApiClient; + private V018_FeitelijkeVerenigingWerdVerwijderdScenario _scenario; + + public Given_FeitelijkeVerenigingWerdVerwijderd(GivenEventsFixture fixture) + { + _publicApiClient = fixture.PublicApiClient; + _scenario = fixture.V018_FeitelijkeVerenigingWerdVerwijderdScenario; + } + + [Fact] + public async Task Then_we_get_a_notfound_response() + { + var response = await _publicApiClient.GetDetail(_scenario.VCode); + response.StatusCode.Should().Be(HttpStatusCode.NotFound); + } +} diff --git a/test/AssociationRegistry.Test.Public.Api/When_Searching/Given_VerenigingWerdVerwijderd.cs b/test/AssociationRegistry.Test.Public.Api/When_Searching/Given_VerenigingWerdVerwijderd.cs new file mode 100644 index 000000000..43e83bf7a --- /dev/null +++ b/test/AssociationRegistry.Test.Public.Api/When_Searching/Given_VerenigingWerdVerwijderd.cs @@ -0,0 +1,38 @@ +namespace AssociationRegistry.Test.Public.Api.When_Searching; + +using Fixtures; +using Fixtures.GivenEvents; +using Fixtures.GivenEvents.Scenarios; +using FluentAssertions; +using Framework; +using templates; +using Xunit; +using Xunit.Categories; + +[Collection(nameof(PublicApiCollection))] +[Category("PublicApi")] +[IntegrationTest] +public class Given_VerenigingWerdVerwijderd +{ + private readonly V018_FeitelijkeVerenigingWerdVerwijderdScenario _scenario; + private readonly PublicApiClient _publicApiClient; + + public Given_VerenigingWerdVerwijderd(GivenEventsFixture fixture) + { + _scenario = fixture.V018_FeitelijkeVerenigingWerdVerwijderdScenario; + _publicApiClient = fixture.PublicApiClient; + } + + [Fact] + public async Task Then_we_get_a_successful_response() + => (await _publicApiClient.Search(_scenario.VCode)).Should().BeSuccessful(); + + [Fact] + public async Task Then_we_retrieve_no_vereniging_matching_the_vCode_searched() + { + var response = await _publicApiClient.Search(_scenario.VCode); + var content = await response.Content.ReadAsStringAsync(); + var goldenMaster = new ZoekVerenigingenResponseTemplate(); + content.Should().BeEquivalentJson(goldenMaster); + } +}