From 1d406a91847432da20d6bb4813c50f971fa6efeb Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Sun, 30 Aug 2026 15:57:50 +0200 Subject: [PATCH 1/2] Implemented GetApplicantInviteEndpoint --- .../GetApplicantInviteEndpoint.cs | 33 +++++++++++++++++++ .../Communications/CommunicationsService.cs | 18 ++++++++++ 2 files changed, 51 insertions(+) create mode 100644 PostFundManagement.Api/Endpoints/Communications/GetApplicantInviteEndpoint.cs diff --git a/PostFundManagement.Api/Endpoints/Communications/GetApplicantInviteEndpoint.cs b/PostFundManagement.Api/Endpoints/Communications/GetApplicantInviteEndpoint.cs new file mode 100644 index 0000000..132709e --- /dev/null +++ b/PostFundManagement.Api/Endpoints/Communications/GetApplicantInviteEndpoint.cs @@ -0,0 +1,33 @@ +using PostFundManagement.Application.Extensions; +using PostFundManagement.Application.Services.Communications; +using PostFundManagement.Domain.Abstractions; +using PostFundManagement.Domain.Extensions; +using PostFundManagement.Domain.Models; +using PostFundManagement.Domain.Security; + +namespace PostFundManagement.Api.Endpoints.Communications; + +[ApiVersionTarget(1)] +public sealed class GetApplicantInviteEndpoint : IEndpoint +{ + public void Map(IEndpointRouteBuilder builder) + { + builder.MapGet("api/communications/invites/applicant/{userId:Guid}", async (Guid userId, CommunicationsService service, + HttpContext context, CancellationToken cancellationToken = default) => + { + var result = await service.GetApplicantInviteAsync(userId, cancellationToken); + + return result.IsSuccess + ? Results.Ok(result.Value) + : Results.NotFound(); + }) + .WithDescription("Gets an applicant's invite") + .WithName(typeof(GetApplicantInviteEndpoint).ToEndpointName()) + .MapToApiVersion(new ApiVersion(1)) + .Produces(StatusCodes.Status200OK) + .Produces(StatusCodes.Status404NotFound) + .Produces(StatusCodes.Status401Unauthorized) + .WithTags(EndpointTags.Communications) + .CacheOutput(); + } +} diff --git a/PostFundManagement.Application/Services/Communications/CommunicationsService.cs b/PostFundManagement.Application/Services/Communications/CommunicationsService.cs index 960292b..1ab6761 100644 --- a/PostFundManagement.Application/Services/Communications/CommunicationsService.cs +++ b/PostFundManagement.Application/Services/Communications/CommunicationsService.cs @@ -67,4 +67,22 @@ public sealed class CommunicationsService(IDbContextFactory> GetApplicantInviteAsync(Guid userId, CancellationToken cancellationToken) + { + try + { + using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + + var invite = await context.Invites.AsNoTracking().FirstOrDefaultAsync(i => i.Recipient == userId, cancellationToken); + + return invite is not null + ? Result.Ok(invite.Map()) + : Result.Fail("Failed to find specific invite."); + } + catch (Exception ex) + { + return Result.Fail(new Error(ex.Message).CausedBy(ex)); + } + } } From db8d336c18fd08f455961fdffa17bcd788594643 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Sun, 30 Aug 2026 16:08:22 +0200 Subject: [PATCH 2/2] Implemented GetIndicatorByIdEndpoint --- .../Evidence/GetIndicatorByIdEndpoint.cs | 32 +++++++++++++++++++ .../Services/Evidence/EvidenceService.cs | 23 +++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 PostFundManagement.Api/Endpoints/Evidence/GetIndicatorByIdEndpoint.cs diff --git a/PostFundManagement.Api/Endpoints/Evidence/GetIndicatorByIdEndpoint.cs b/PostFundManagement.Api/Endpoints/Evidence/GetIndicatorByIdEndpoint.cs new file mode 100644 index 0000000..2e34ac3 --- /dev/null +++ b/PostFundManagement.Api/Endpoints/Evidence/GetIndicatorByIdEndpoint.cs @@ -0,0 +1,32 @@ +using PostFundManagement.Application.Extensions; +using PostFundManagement.Application.Services.Evidence; +using PostFundManagement.Domain.Abstractions; +using PostFundManagement.Domain.Extensions; +using PostFundManagement.Domain.Models; +using PostFundManagement.Domain.Security; + +namespace PostFundManagement.Api.Endpoints.Evidence; + +[ApiVersionTarget(1)] +public sealed class GetIndicatorByIdEndpoint : IEndpoint +{ + public void Map(IEndpointRouteBuilder builder) + { + builder.MapGet("api/evidence/indicators/{indicatorId}", async (string indicatorId, EvidenceService service, + CancellationToken cancellationToken = default) => + { + var result = await service.GetIndicatorAsync(indicatorId, cancellationToken); + + return result.IsSuccess + ? Results.Ok(result.Value) + : Results.NotFound(); + }) + .WithDescription("Get a specific indicator.") + .WithName(typeof(GetIndicatorByIdEndpoint).ToEndpointName()) + .MapToApiVersion(new ApiVersion(1)) + .Produces(StatusCodes.Status200OK) + .Produces(StatusCodes.Status404NotFound) + .Produces(StatusCodes.Status401Unauthorized) + .WithTags(EndpointTags.Evidence); + } +} diff --git a/PostFundManagement.Application/Services/Evidence/EvidenceService.cs b/PostFundManagement.Application/Services/Evidence/EvidenceService.cs index f764a6c..fffe880 100644 --- a/PostFundManagement.Application/Services/Evidence/EvidenceService.cs +++ b/PostFundManagement.Application/Services/Evidence/EvidenceService.cs @@ -230,4 +230,27 @@ public sealed class EvidenceService(IDbContextFactory cont return Result.Fail(new Error(ex.Message).CausedBy(ex)); } } + + public async Task> GetIndicatorAsync(string indicatorId, CancellationToken cancellationToken) + { + try + { + var decodeResult = hashService.DecodeLongIdHash(indicatorId); + + if (decodeResult.IsFailed) + return Result.Fail(decodeResult.Errors); + + using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + + var indicator = await context.Indicators.AsNoTracking().FirstOrDefaultAsync(i => i.Id == decodeResult.Value, cancellationToken); + + return indicator is not null + ? Result.Ok(indicator.Map()) + : Result.Fail("Failed to find specific indicator."); + } + catch (Exception ex) + { + return Result.Fail(new Error(ex.Message).CausedBy(ex)); + } + } }