Skip to content

Commit 81714eb

Browse files
authored
Add new endpoints (#958)
* add observingV2 * add statistics:my
1 parent a57938f commit 81714eb

File tree

23 files changed

+441
-15
lines changed

23 files changed

+441
-15
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,3 +272,4 @@ log*.txt
272272

273273
OfflineCapabilities
274274
/api/src/Vote.Monitor.Api/Uploads
275+
**/**/dist

api/Vote.Monitor.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Feature.Citizen.Notificatio
165165
EndProject
166166
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Feature.Coalitions", "src\Feature.Coalitions\Feature.Coalitions.csproj", "{5F573792-C095-44F5-8DDD-05257CA41C9E}"
167167
EndProject
168+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Feature.DataCleanup", "src\Feature.DataCleanup\Feature.DataCleanup.csproj", "{8FA245E6-7A81-4332-80AE-4D345B618AA7}"
169+
EndProject
168170
Global
169171
GlobalSection(SolutionConfigurationPlatforms) = preSolution
170172
Debug|Any CPU = Debug|Any CPU
@@ -471,6 +473,10 @@ Global
471473
{5F573792-C095-44F5-8DDD-05257CA41C9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
472474
{5F573792-C095-44F5-8DDD-05257CA41C9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
473475
{5F573792-C095-44F5-8DDD-05257CA41C9E}.Release|Any CPU.Build.0 = Release|Any CPU
476+
{8FA245E6-7A81-4332-80AE-4D345B618AA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
477+
{8FA245E6-7A81-4332-80AE-4D345B618AA7}.Debug|Any CPU.Build.0 = Debug|Any CPU
478+
{8FA245E6-7A81-4332-80AE-4D345B618AA7}.Release|Any CPU.ActiveCfg = Release|Any CPU
479+
{8FA245E6-7A81-4332-80AE-4D345B618AA7}.Release|Any CPU.Build.0 = Release|Any CPU
474480
EndGlobalSection
475481
GlobalSection(SolutionProperties) = preSolution
476482
HideSolutionNode = FALSE
@@ -551,6 +557,7 @@ Global
551557
{DF354318-6856-4925-96A0-0C458E530091} = {3441EE1D-E3C6-45BE-A020-553816015081}
552558
{A43F29F9-5765-4143-AB9A-C3ECFCDD402F} = {17945B3C-5A4C-4279-8022-65ABC606A510}
553559
{5F573792-C095-44F5-8DDD-05257CA41C9E} = {17945B3C-5A4C-4279-8022-65ABC606A510}
560+
{8FA245E6-7A81-4332-80AE-4D345B618AA7} = {17945B3C-5A4C-4279-8022-65ABC606A510}
554561
EndGlobalSection
555562
GlobalSection(ExtensibilityGlobals) = postSolution
556563
SolutionGuid = {50C20C9F-F2AF-45D8-994A-06661772B31C}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
3+
namespace Feature.DataCleanup;
4+
5+
public static class DataCleanupFeatureInstaller
6+
{
7+
public static IServiceCollection AddDataCleanupFeature(this IServiceCollection services)
8+
{
9+
return services;
10+
}
11+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using Authorization.Policies;
2+
using Microsoft.EntityFrameworkCore;
3+
using Vote.Monitor.Domain;
4+
using Vote.Monitor.Domain.Entities.FormAnswerBase.Answers;
5+
6+
namespace Feature.DataCleanup.DeleteNgoData;
7+
8+
public class Endpoint(VoteMonitorContext context) : Endpoint<Request>
9+
{
10+
public override void Configure()
11+
{
12+
Get("/api/election-rounds/{electionRoundId}/ngo/{ngoId}/data:cleanup");
13+
DontAutoTag();
14+
Options(x => x.WithTags("data-cleanup"));
15+
Policies(PolicyNames.PlatformAdminsOnly);
16+
}
17+
18+
public override async Task HandleAsync(Request req, CancellationToken ct)
19+
{
20+
await context
21+
.Notes
22+
.Where(n =>
23+
n.ElectionRoundId == req.ElectionRoundId
24+
&& n.MonitoringObserver.MonitoringNgo.NgoId == req.NgoId
25+
&& n.MonitoringObserver.MonitoringNgo.ElectionRoundId == req.ElectionRoundId)
26+
.ExecuteDeleteAsync(cancellationToken: ct);
27+
28+
await context
29+
.Attachments
30+
.Where(a =>
31+
a.ElectionRoundId == req.ElectionRoundId
32+
&& a.MonitoringObserver.MonitoringNgo.NgoId == req.NgoId
33+
&& a.MonitoringObserver.MonitoringNgo.ElectionRoundId == req.ElectionRoundId)
34+
.ExecuteUpdateAsync(fs => fs.SetProperty(p => p.IsDeleted, true), cancellationToken: ct);
35+
36+
await context
37+
.QuickReportAttachments
38+
.Where(qra =>
39+
qra.ElectionRoundId == req.ElectionRoundId
40+
&& qra.MonitoringObserver.MonitoringNgo.NgoId == req.NgoId
41+
&& qra.MonitoringObserver.MonitoringNgo.ElectionRoundId == req.ElectionRoundId)
42+
.ExecuteUpdateAsync(fs => fs.SetProperty(p => p.IsDeleted, true), cancellationToken: ct);
43+
44+
await context.Database
45+
.ExecuteSqlInterpolatedAsync($"""
46+
UPDATE "FormSubmissions" AS fs
47+
SET "NumberOfQuestionsAnswered" = 0,
48+
"NumberOfFlaggedAnswers" = 0,
49+
"Answers" = '[]'
50+
FROM "MonitoringObservers" AS m
51+
INNER JOIN "MonitoringNgos" AS m0 ON m."MonitoringNgoId" = m0."Id"
52+
WHERE fs."MonitoringObserverId" = m."Id"
53+
AND fs."ElectionRoundId" = {req.ElectionRoundId}
54+
AND m0."NgoId" = {req.NgoId}
55+
AND m0."ElectionRoundId" = {req.ElectionRoundId}
56+
""", ct);
57+
58+
await context.Database
59+
.ExecuteSqlInterpolatedAsync($"""
60+
UPDATE "PollingStationInformation" AS psi
61+
SET "NumberOfQuestionsAnswered" = 0,
62+
"NumberOfFlaggedAnswers" = 0,
63+
"Answers" = '[]'
64+
FROM "MonitoringObservers" AS m
65+
INNER JOIN "MonitoringNgos" AS m0 ON m."MonitoringNgoId" = m0."Id"
66+
WHERE psi."MonitoringObserverId" = m."Id"
67+
AND psi."ElectionRoundId" = {req.ElectionRoundId}
68+
AND m0."NgoId" = {req.NgoId}
69+
AND m0."ElectionRoundId" = {req.ElectionRoundId}
70+
""", ct);
71+
72+
await context
73+
.QuickReports
74+
.Where(qr =>
75+
qr.ElectionRoundId == req.ElectionRoundId
76+
&& qr.MonitoringObserver.MonitoringNgo.NgoId == req.NgoId
77+
&& qr.MonitoringObserver.MonitoringNgo.ElectionRoundId == req.ElectionRoundId)
78+
.ExecuteDeleteAsync(cancellationToken: ct);
79+
}
80+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Feature.DataCleanup.DeleteNgoData;
2+
3+
public class Request
4+
{
5+
public Guid ElectionRoundId { get; set; }
6+
public Guid NgoId { get; set; }
7+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
using System.Runtime.CompilerServices;
2+
3+
[assembly: InternalsVisibleTo("Feature.DataCleanup.UnitTests")]
4+
[assembly: InternalsVisibleTo("Feature.DataCleanup.IntegrationTests")]
5+
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Ardalis.SmartEnum.SystemTextJson" />
11+
<PackageReference Include="FastEndpoints" />
12+
<PackageReference Include="FastEndpoints.Security" />
13+
<PackageReference Include="Microsoft.AspNetCore.Authorization" />
14+
</ItemGroup>
15+
16+
<ItemGroup>
17+
<ProjectReference Include="..\Authorization.Policies\Authorization.Policies.csproj" />
18+
<ProjectReference Include="..\Vote.Monitor.Domain\Vote.Monitor.Domain.csproj" />
19+
</ItemGroup>
20+
21+
</Project>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Global using directives
2+
3+
global using FastEndpoints;
4+
global using FluentValidation;
5+
global using Microsoft.AspNetCore.Http;
6+
global using Microsoft.AspNetCore.Http.HttpResults;
7+
global using Vote.Monitor.Domain.Constants;

api/src/Feature.ElectionRounds/Observing/Endpoint.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public override void Configure()
1515
Summary(s =>
1616
{
1717
s.Summary = "Lists election rounds which are observed by current observer";
18-
s.Description = "Election rounds with status NotStarted and Started are listed";
18+
s.Description = "Only election rounds with status Started are listed";
1919
});
2020
Policies(PolicyNames.ObserversOnly);
2121
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
namespace Feature.ElectionRounds.ObservingV2;
2+
3+
public class Endpoint(IReadRepository<ElectionRoundAggregate> repository)
4+
: Endpoint<Request, Results<Ok<Result>, ProblemDetails>>
5+
{
6+
public override void Configure()
7+
{
8+
Get("/api/election-rounds:myV2");
9+
DontAutoTag();
10+
Options(x => x.WithTags("election-rounds", "mobile"));
11+
Summary(s =>
12+
{
13+
s.Summary = "Lists election rounds which are observed by current observer";
14+
s.Description = "Election rounds with status Archived and Started are listed";
15+
});
16+
Policies(PolicyNames.ObserversOnly);
17+
}
18+
19+
public override async Task<Results<Ok<Result>, ProblemDetails>> ExecuteAsync(Request request, CancellationToken ct)
20+
{
21+
List<ElectionRoundModel> electionRounds =
22+
await repository.ListAsync(new GetObserverElectionV2Specification(request.UserId), ct);
23+
24+
return TypedResults.Ok(new Result { ElectionRounds = electionRounds });
25+
}
26+
}

0 commit comments

Comments
 (0)