using PostFundManagement.Domain; using PostFundManagement.Domain.Abstractions; using PostFundManagement.Domain.Api; using PostFundManagement.Domain.Extensions; using PostFundManagement.Infrastructure.Database; namespace PostFundManagement.Api.Endpoints.Governance; [ApiVersionTarget(1)] public class DashboardEndpoint : IEndpoint { public void Map(IEndpointRouteBuilder builder) { builder.MapGet("api/governance/dashboard", async (IDbContextFactory contextFactory, CancellationToken cancellationToken = default) => { using var context = await contextFactory.CreateDbContextAsync(cancellationToken); var totalPortfolioValue = await context.Awards.SumAsync(a => a.Amount, cancellationToken); var activeAwardsCount = await context.Awards.CountAsync(a => a.Status == ApprovalStatus.Approved, cancellationToken); var disbursedAmount = await context.Disbursements.Where(d => d.Status == ApprovalStatus.Approved) .SumAsync(d => d.Amount, cancellationToken); var totalProjects = await context.Projects.CountAsync(cancellationToken); var onTrackProjects = await context.Projects.CountAsync(p => p.Status == ApprovalStatus.Approved, cancellationToken); var onTrackPercentage = totalProjects > 0 ? Math.Round((double)onTrackProjects / totalProjects * 100, 1) : 100.0; var atRiskCount = await context.Risks.CountAsync(r => r.Impact == RiskImpact.Critical || r.Impact == RiskImpact.Major, cancellationToken); var beneficiariesReached = await context.Beneficiaries.SumAsync(b => b.ReachedCount, cancellationToken); return Results.Ok(new { PortfolioValue = totalPortfolioValue, ActiveAwards = activeAwardsCount, Disbursed = disbursedAmount, OnTrackPercentage = onTrackPercentage, AtRiskCount = atRiskCount, BeneficiariesReached = beneficiariesReached }); }) .RequireAuthorization() .WithDescription("Get executive portfolio dashboard metrics and KPIs") .WithName(typeof(DashboardEndpoint).ToEndpointName()) .MapToApiVersion(new ApiVersion(1)) .Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status401Unauthorized) .WithTags(EndpointTags.Governance); } }