Skip to content

Commit

Permalink
feat: or-2350 add admin endpoint to analyze duplicates
Browse files Browse the repository at this point in the history
  • Loading branch information
koenmetsu committed Jan 16, 2025
1 parent aaffa1d commit be381d3
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
namespace AssociationRegistry.Admin.Api.Adapters.DuplicateVerenigingDetectionService;

using AssociationRegistry.Admin.Schema.Search;
using AssociationRegistry.DuplicateVerenigingDetection;
using AssociationRegistry.Vereniging;
using Schema.Search;
using DuplicateVerenigingDetection;
using Vereniging;
using Nest;
using System.Collections.Immutable;

Expand All @@ -15,8 +15,11 @@ public SearchDuplicateVerenigingDetectionService(IElasticClient client)
_client = client;
}

public async Task<IReadOnlyCollection<DuplicaatVereniging>> GetDuplicates(VerenigingsNaam naam, Locatie[] locaties)
public async Task<IReadOnlyCollection<DuplicaatVereniging>> GetDuplicates(VerenigingsNaam naam, Locatie[] locaties,
bool includeScore = false, MinimumScore? minimumScoreOverride = null)
{
minimumScoreOverride ??= MinimumScore.Default;

var locatiesMetAdres = locaties.Where(l => l.Adres is not null).ToArray();

if (locatiesMetAdres.Length == 0) return Array.Empty<DuplicaatVereniging>();
Expand All @@ -28,6 +31,9 @@ public async Task<IReadOnlyCollection<DuplicaatVereniging>> GetDuplicates(Vereni
await _client
.SearchAsync<DuplicateDetectionDocument>(
s => s
.Explain(includeScore)
.TrackScores(includeScore)
//.MinScore(minimumScoreOverride.Value)
.Query(
q => q.Bool(
b => b.Must(
Expand All @@ -41,7 +47,8 @@ await _client
)
));

return searchResponse.Documents.Select(ToDuplicateVereniging)
return searchResponse.Hits
.Select(ToDuplicateVereniging)
.ToArray();
}

Expand Down Expand Up @@ -140,17 +147,24 @@ private static Func<QueryContainerDescriptor<DuplicateDetectionDocument>, QueryC
);
}

private static DuplicaatVereniging ToDuplicateVereniging(DuplicateDetectionDocument document)
private static DuplicaatVereniging ToDuplicateVereniging(IHit<DuplicateDetectionDocument> document)
=> new(
document.VCode,
new DuplicaatVereniging.VerenigingsType(document.VerenigingsTypeCode,
Verenigingstype.Parse(document.VerenigingsTypeCode).Naam),
document.Naam,
document.KorteNaam,
document.HoofdactiviteitVerenigingsloket?
document.Source.VCode,
new DuplicaatVereniging.VerenigingsType(document.Source.VerenigingsTypeCode,
Verenigingstype.Parse(document.Source.VerenigingsTypeCode).Naam),
document.Source.Naam,
document.Source.KorteNaam,
document.Source.HoofdactiviteitVerenigingsloket?
.Select(h => new DuplicaatVereniging.HoofdactiviteitVerenigingsloket(
h, HoofdactiviteitVerenigingsloket.Create(h).Naam)).ToImmutableArray() ?? [],
document.Locaties.Select(ToLocatie).ToImmutableArray());
document.Source.Locaties.Select(ToLocatie).ToImmutableArray(),
IncludesScore(document)
? new DuplicaatVereniging.ScoringInfo(document.Explanation.Description, document.Score)
: DuplicaatVereniging.ScoringInfo.NotApplicable
);

private static bool IncludesScore(IHit<DuplicateDetectionDocument> document)
=> document.Explanation is not null && document.Score is not null;

private static DuplicaatVereniging.Locatie ToLocatie(DuplicateDetectionDocument.Locatie loc)
=> new(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
namespace AssociationRegistry.Admin.Api.Administratie.DubbelControle;

using Asp.Versioning;
using Be.Vlaanderen.Basisregisters.Api;
using DecentraalBeheer.Verenigingen.Registreer.FeitelijkeVereniging.RequetsModels;
using DuplicateVerenigingDetection;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

[ApiVersion("1.0")]
[AdvertiseApiVersions("1.0")]
[ApiRoute("projections")]
[ApiExplorerSettings(IgnoreApi = true)]
[Authorize(Policy = Program.SuperAdminPolicyName)]
public class DubbelControleController : ApiController
{
[HttpPost("admin/dubbelcontrole")]
public async Task<IActionResult> ControleerOpDubbels(
[FromBody] RegistreerFeitelijkeVerenigingRequest? request,
[FromQuery] double? minimumScoreOverride,
[FromServices] IDuplicateVerenigingDetectionService duplicateVerenigingDetectionService
)
{
var command = request.ToCommand();

var result = await duplicateVerenigingDetectionService.GetDuplicates(
command.Naam, command.Locaties,
true,
minimumScoreOverride.HasValue
? new MinimumScore(minimumScoreOverride.Value)
: MinimumScore.Default);

return Ok(result);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,5 @@
</EmbeddedResource>
</ItemGroup>

<ItemGroup>
<Folder Include="Administratie\" />
</ItemGroup>

<Import Project="..\..\.paket\Paket.Restore.targets" />
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ public PotentialDuplicatesResponse GetExamples()
Verenigingstype.FeitelijkeVereniging.Naam),
Naam: "Naam",
KorteNaam: "Korte naam",
ImmutableArray.Create(
[
new DuplicaatVereniging.HoofdactiviteitVerenigingsloket(Code: "CODE", Naam: "Beschrijving")
),
ImmutableArray.Create(
],
[
new DuplicaatVereniging.Locatie(Locatietype: "Locatietype", IsPrimair: true, Adres: "Adresvoorstelling",
Naam: "Naam", Postcode: "Postcode", Gemeente: "Gemeente")
)),
]),
}),
_appSettings);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ public record DuplicaatVereniging(
string Naam,
string KorteNaam,
ImmutableArray<DuplicaatVereniging.HoofdactiviteitVerenigingsloket> HoofdactiviteitenVerenigingsloket,
ImmutableArray<DuplicaatVereniging.Locatie> Locaties)
ImmutableArray<DuplicaatVereniging.Locatie> Locaties,
DuplicaatVereniging.ScoringInfo? Scoring = null
)
{
public record Locatie(
string Locatietype,
Expand All @@ -21,4 +23,9 @@ public record Locatie(
public record VerenigingsType(string Code, string Naam);
public record Activiteit(int Id, string Categorie);
public record HoofdactiviteitVerenigingsloket(string Code, string Naam);

public record ScoringInfo(string Explanation, double? Score)
{
public static ScoringInfo NotApplicable => new("N/A", null);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@

public interface IDuplicateVerenigingDetectionService
{
Task<IReadOnlyCollection<DuplicaatVereniging>> GetDuplicates(VerenigingsNaam naam, Locatie[] locaties);
Task<IReadOnlyCollection<DuplicaatVereniging>> GetDuplicates(
VerenigingsNaam naam,
Locatie[] locaties,
bool includeScore = false,
MinimumScore? minimumScoreOverride = null);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace AssociationRegistry.DuplicateVerenigingDetection;

public record MinimumScore(double Value)
{
public static MinimumScore Default = new(1);
};
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ public With_A_PotentialDuplicate()
d =>
d.GetDuplicates(
command.Naam,
command.Locaties))
command.Locaties,
false, null))
.ReturnsAsync(_potentialDuplicates);

var commandMetadata = fixture.Create<CommandMetadata>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ public With_A_PotentialDuplicate_And_Force()
d =>
d.GetDuplicates(
_command.Naam,
_command.Locaties))
_command.Locaties,
false,
MinimumScore.Default))
.ReturnsAsync(potentialDuplicates);

var commandMetadata = fixture.Create<CommandMetadata>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@

public class NoDuplicateVerenigingDetectionService : IDuplicateVerenigingDetectionService
{
public Task<IReadOnlyCollection<DuplicaatVereniging>> GetDuplicates(VerenigingsNaam naam, Locatie[] locaties)
public Task<IReadOnlyCollection<DuplicaatVereniging>> GetDuplicates(VerenigingsNaam naam, Locatie[] locaties, bool includeScore = false, MinimumScore? minimumScoreOverride = null)
=> Task.FromResult<IReadOnlyCollection<DuplicaatVereniging>>(new List<DuplicaatVereniging>());
}

0 comments on commit be381d3

Please sign in to comment.