Implemented basic endpoints

This commit is contained in:
2026-08-25 17:52:44 +02:00
parent be5fbdbb5f
commit 5a4c621950
43 changed files with 1870 additions and 6 deletions
@@ -0,0 +1,41 @@
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Api;
using PostFundManagement.Domain.Extensions;
using PostFundManagement.Infrastructure.Database;
namespace PostFundManagement.Api.Endpoints.Communications;
[ApiVersionTarget(1)]
public class GetInvitesEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/communications/invites", async (IDbContextFactory<ApplicationDbContext> contextFactory,
int page = 1, int pageSize = 10, CancellationToken cancellationToken = default) =>
{
if (page < 1) page = 1;
if (pageSize < 1) pageSize = 10;
if (pageSize > 100) pageSize = 100;
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
var query = context.Invites.AsNoTracking();
var totalCount = await query.CountAsync(cancellationToken);
var items = await query.OrderByDescending(i => i.CreatedAt)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToListAsync(cancellationToken);
return Results.Ok(new { Items = items, TotalCount = totalCount, Page = page, PageSize = pageSize });
})
.RequireAuthorization()
.WithDescription("Get a list of sent invitations")
.WithName(typeof(GetInvitesEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Communications);
}
}
@@ -1,23 +1,61 @@
using PostFundManagement.Domain;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Api;
using PostFundManagement.Domain.Extensions;
using PostFundManagement.Infrastructure.Database;
namespace PostFundManagement.Api.Endpoints.Communications;
[ApiVersionTarget(1)]
public class SendInviteEndpoint : IEndpoint
{
public record InviteRequest(long OrganisationId, long InvitedOrganisationId, long AwardId, long ContractId, Guid Recipient, string Message, NotificationPlatform Platform);
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPost("api/communications/invite", () =>
builder.MapPost("api/communications/invite", async (InviteRequest request, ClaimsPrincipal principal,
IDbContextFactory<ApplicationDbContext> contextFactory, CancellationToken cancellationToken = default) =>
{
throw new NotImplementedException();
var sidClaim = principal.FindFirst("sid")?.Value ?? principal.FindFirst(ClaimTypes.Sid)?.Value;
if (!Guid.TryParse(sidClaim, out var currentUserId))
return Results.BadRequest("Missing or invalid 'sid' claim.");
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
var invite = new Domain.Entities.Invite
{
OrganisationId = request.OrganisationId,
InvitedOrganisationId = request.InvitedOrganisationId,
AwardId = request.AwardId,
ContractId = request.ContractId,
Recipient = request.Recipient,
CreatedBy = currentUserId,
CreatedAt = DateTime.UtcNow
};
context.Invites.Add(invite);
context.Notifications.Add(new Domain.Entities.Notification
{
OrganisationId = request.OrganisationId,
Recipient = request.Recipient,
Platform = request.Platform,
Status = NotificationStatus.Pending,
Subject = "Invitation to Onboard",
Message = request.Message,
CreatedAt = DateTime.UtcNow
});
return await context.SaveChangesAsync(cancellationToken) > 0
? Results.Ok(invite)
: Results.BadRequest("Failed to create invite");
})
.RequireAuthorization()
.WithDescription("Trigger an invite to an organization or candidate (specifying NotificationPlatform)")
.WithName(typeof(SendInviteEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK)
.Produces<Domain.Entities.Invite>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Communications);
@@ -0,0 +1,44 @@
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Api;
using PostFundManagement.Domain.Extensions;
namespace PostFundManagement.Api.Endpoints.Communications;
public class SyncEvent : EventBase, IEvent
{
public string Name { get; set; } = nameof(SyncEvent);
}
public class SyncEventHandler : INotificationHandler<SyncEvent>
{
public ValueTask Handle(SyncEvent notification, CancellationToken cancellationToken)
{
Trace.WriteLine($"Integration Sync executed. Correlation ID: {notification.CorrelationId}");
return ValueTask.CompletedTask;
}
}
[ApiVersionTarget(1)]
public class SyncEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPost("api/integration/sync", async (IJobOrchestrator jobOrchestrator,
CancellationToken cancellationToken = default) =>
{
var syncEvent = new SyncEvent();
await jobOrchestrator.SendAsync(syncEvent, cancellationToken);
return Results.Ok(new { Queued = true, syncEvent.CorrelationId });
})
.RequireAuthorization()
.WithDescription("Trigger integration and data synchronization in the background")
.WithName(typeof(SyncEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Communications);
}
}