-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
886ae40
commit 3c958be
Showing
16 changed files
with
429 additions
and
149 deletions.
There are no files selected for viewing
87 changes: 87 additions & 0 deletions
87
src/MunicipalityRegistry.Api.Import/Merger/MergerController-Merge.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
namespace MunicipalityRegistry.Api.Import.Merger | ||
{ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Autofac; | ||
using Be.Vlaanderen.Basisregisters.CommandHandling.Idempotency; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.EntityFrameworkCore; | ||
using Municipality.Commands; | ||
|
||
public partial class MergerController | ||
{ | ||
[HttpPost("{fusieJaar}")] | ||
public async Task<IActionResult> Merge( | ||
[FromRoute(Name = "fusieJaar")] int mergerYear, | ||
CancellationToken cancellationToken = default) | ||
{ | ||
var municipalityMergers = await _importContext.MunicipalityMergers | ||
.Where(x => x.Year == mergerYear) | ||
.ToListAsync(cancellationToken: cancellationToken); | ||
|
||
if (!municipalityMergers.Any()) | ||
{ | ||
return BadRequest($"No municipality mergers found for year {mergerYear}"); | ||
} | ||
|
||
var municipalityIdToNisCodeMapping = await _legacyContext.MunicipalityDetail | ||
.ToDictionaryAsync(x => x.MunicipalityId!.Value, x => new NisCode(x.NisCode!), cancellationToken: cancellationToken); | ||
|
||
foreach (var mergersPerNewMunicipality in municipalityMergers.GroupBy(x => x.NewMunicipalityId)) | ||
{ | ||
var newMunicipalityId = new MunicipalityId(mergersPerNewMunicipality.Key); | ||
var newNisCode = municipalityIdToNisCodeMapping[newMunicipalityId]; | ||
|
||
{ | ||
var activateMunicipalityCommand = new ActivateMunicipality(newMunicipalityId, CreateProvenance($"Fusie {mergerYear}")); | ||
|
||
try | ||
{ | ||
await using var scopedContainer = _container.BeginLifetimeScope(); | ||
var idempotentCommandHandler = scopedContainer.Resolve<IIdempotentCommandHandler>(); | ||
await idempotentCommandHandler.Dispatch( | ||
activateMunicipalityCommand.CreateCommandId(), | ||
activateMunicipalityCommand, | ||
new Dictionary<string, object>(), | ||
cancellationToken); | ||
} | ||
catch (IdempotencyException) | ||
{ | ||
// Do nothing | ||
} | ||
} | ||
|
||
foreach (var mergeMunicipality in mergersPerNewMunicipality) | ||
{ | ||
var mergeMunicipalityCommand = new MergeMunicipality( | ||
new MunicipalityId(mergeMunicipality.MunicipalityId), | ||
mergeMunicipality.MunicipalityIdsToMergeWith.Select(x => new MunicipalityId(x)).ToList(), | ||
mergeMunicipality.MunicipalityIdsToMergeWith.Select(x => municipalityIdToNisCodeMapping[x]).ToList(), | ||
newMunicipalityId, | ||
newNisCode, | ||
CreateProvenance($"Fusie {mergerYear}") | ||
); | ||
|
||
try | ||
{ | ||
await using var scopedContainer = _container.BeginLifetimeScope(); | ||
var idempotentCommandHandler = scopedContainer.Resolve<IIdempotentCommandHandler>(); | ||
await idempotentCommandHandler.Dispatch( | ||
mergeMunicipalityCommand.CreateCommandId(), | ||
mergeMunicipalityCommand, | ||
new Dictionary<string, object>(), | ||
cancellationToken); | ||
} | ||
catch (IdempotencyException) | ||
{ | ||
// Do nothing | ||
} | ||
} | ||
} | ||
|
||
return Ok(); | ||
} | ||
} | ||
} |
130 changes: 130 additions & 0 deletions
130
src/MunicipalityRegistry.Api.Import/Merger/MergerController-Propose.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
namespace MunicipalityRegistry.Api.Import.Merger | ||
{ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Autofac; | ||
using Be.Vlaanderen.Basisregisters.CommandHandling.Idempotency; | ||
using Be.Vlaanderen.Basisregisters.GrAr.Legacy; | ||
using Be.Vlaanderen.Basisregisters.GrAr.Provenance; | ||
using Exceptions; | ||
using FluentValidation; | ||
using Infrastructure.Vrbg; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Municipality.Commands; | ||
using NetTopologySuite.Geometries; | ||
using NodaTime; | ||
using Propose; | ||
|
||
public partial class MergerController | ||
{ | ||
[HttpPost("propose")] | ||
public async Task<IActionResult> Propose( | ||
[FromBody] ProposeMergersRequest request, | ||
[FromServices] IValidator<ProposeMergersRequest> validator, | ||
[FromServices] IMunicipalityGeometryReader municipalityGeometryReader, | ||
CancellationToken cancellationToken = default) | ||
{ | ||
await validator.ValidateAndThrowAsync(request, cancellationToken: cancellationToken); | ||
|
||
foreach (var municipality in request.Municipalities) | ||
{ | ||
var futureMunicipalityId = await EnsureMunicipalityExistsAndReturnMunicipalityId( | ||
request.MergerYear, | ||
municipality, | ||
municipalityGeometryReader, | ||
cancellationToken); | ||
|
||
var municipalitiesToMerge = municipality.MergerOf | ||
.Select(niscode => _legacyContext.MunicipalityDetail.Single(x => x.NisCode == niscode)) | ||
.ToList(); | ||
|
||
foreach (var municipalityToMerge in municipalitiesToMerge) | ||
{ | ||
await _importContext.MunicipalityMergers.AddAsync(new MunicipalityMerger( | ||
request.MergerYear, | ||
municipalityToMerge.MunicipalityId!.Value, | ||
municipalitiesToMerge.Where(x => x.NisCode != municipalityToMerge.NisCode).Select(x => x.MunicipalityId!.Value), | ||
futureMunicipalityId | ||
), cancellationToken); | ||
} | ||
|
||
await _importContext.SaveChangesAsync(cancellationToken); | ||
} | ||
|
||
return Ok(); | ||
} | ||
|
||
private async Task<Guid> EnsureMunicipalityExistsAndReturnMunicipalityId( | ||
int mergerYear, | ||
ProposeMergerRequest municipality, | ||
IMunicipalityGeometryReader municipalityGeometryReader, | ||
CancellationToken cancellationToken) | ||
{ | ||
var existingMunicipality = _legacyContext.MunicipalityDetail.SingleOrDefault(x => x.NisCode == municipality.NisCode); | ||
if (existingMunicipality is not null) | ||
{ | ||
return existingMunicipality.MunicipalityId!.Value; | ||
} | ||
|
||
var newMunicipalityGeometry = await BuildMunicipalityGeometry(municipality, municipalityGeometryReader); | ||
|
||
var registerMunicipalityCommand = new RegisterMunicipality( | ||
new MunicipalityId(Guid.NewGuid()), | ||
new NisCode(municipality.NisCode), | ||
municipality.ProposeMunicipality!.OfficialLanguages.Select(ToLanguage).ToList(), | ||
municipality.ProposeMunicipality.FacilitiesLanguages.Select(ToLanguage).ToList(), | ||
municipality.ProposeMunicipality.Names.Select(n => new MunicipalityName(n.Value, ToLanguage(n.Key))).ToList(), | ||
ExtendedWkbGeometry.CreateEWkb(newMunicipalityGeometry.ToBinary())!, | ||
CreateProvenance($"Fusie {mergerYear}") | ||
); | ||
|
||
await using var scopedContainer = _container.BeginLifetimeScope(); | ||
var idempotentCommandHandler = scopedContainer.Resolve<IIdempotentCommandHandler>(); | ||
await idempotentCommandHandler.Dispatch( | ||
registerMunicipalityCommand.CreateCommandId(), | ||
registerMunicipalityCommand, | ||
new Dictionary<string, object>(), | ||
cancellationToken); | ||
|
||
return registerMunicipalityCommand.MunicipalityId; | ||
} | ||
|
||
private static async Task<MultiPolygon> BuildMunicipalityGeometry(ProposeMergerRequest municipality, IMunicipalityGeometryReader municipalityGeometryReader) | ||
{ | ||
var geometryFactory = GeometryConfiguration.CreateGeometryFactory(); | ||
|
||
var municipalityGeometriesToMerge = await Task.WhenAll(municipality.MergerOf.Select(municipalityGeometryReader.GetGeometry)); | ||
var newMunicipalityGeometry = new MultiPolygon( | ||
municipalityGeometriesToMerge.SelectMany(geometry => | ||
{ | ||
return geometry switch | ||
{ | ||
MultiPolygon multiPolygon => multiPolygon.Geometries.Cast<Polygon>(), | ||
Polygon polygon => new[] { polygon }, | ||
_ => throw new InvalidPolygonException() | ||
}; | ||
}) | ||
.ToArray(), | ||
geometryFactory) | ||
{ | ||
SRID = geometryFactory.SRID | ||
}; | ||
return newMunicipalityGeometry; | ||
} | ||
|
||
private static Language ToLanguage(Taal taal) | ||
{ | ||
return taal switch | ||
{ | ||
Taal.NL => Language.Dutch, | ||
Taal.FR => Language.French, | ||
Taal.DE => Language.German, | ||
Taal.EN => Language.English, | ||
_ => throw new ArgumentOutOfRangeException(nameof(taal), taal, $"Non existing language '{taal}'.") | ||
}; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...erger/ProposeMergerMunicipalityRequest.cs → ...opose/ProposeMergerMunicipalityRequest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...Api.Import/Merger/ProposeMergerRequest.cs → ...rt/Merger/Propose/ProposeMergerRequest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.