Implemented caching on all get endpoints and service layer #19

Merged
khwezi merged 1 commits from endpoints into main 2026-09-05 08:30:16 +02:00
61 changed files with 1185 additions and 255 deletions
@@ -23,14 +23,15 @@ public sealed class GetIndicatorEndpoint : IEndpoint
var r when r.HasError<NotFoundError>() => Results.NotFound(),
var r => Results.InternalServerError(r.Errors.ToProblems())
})
.WithDescription("Get a specific indicator.")
.WithName(typeof(GetIndicatorEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces<Indicator>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Evidence);
.WithDescription("Get a specific indicator.")
.WithName(typeof(GetIndicatorEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces<Indicator>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Evidence)
.CacheOutput();
}
}
@@ -27,6 +27,7 @@ public class GetIndicatorsEndpoint : IEndpoint
.Produces<Indicator[]>(StatusCodes.Status200OK)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Evidence);
.WithTags(EndpointTags.Evidence)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Execution;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
@@ -14,7 +14,7 @@ public class ApproveDisbursementEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPost("api/execution/disbursements/{disbursementId}/approve", async (string disbursementId,
ExecutionService service, HttpContext context, CancellationToken cancellationToken = default) =>
IExecutionService service, HttpContext context, CancellationToken cancellationToken = default) =>
await service.ApproveDisbursementAsync(disbursementId, context.GetUserId(), cancellationToken) switch
{
{ IsSuccess: true } => Results.Ok(),
@@ -1,3 +1,4 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Execution;
using PostFundManagement.Domain.Abstractions;
@@ -14,7 +15,7 @@ public class CreateDisbursementEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPost("api/execution/disbursements", async (CreateDisbursementRequest request,
ExecutionService service, HttpContext context, CancellationToken cancellationToken = default) =>
IExecutionService service, HttpContext context, CancellationToken cancellationToken = default) =>
await service.CreateDisbursementAsync(request, context.GetUserId(), cancellationToken) switch
{
{ IsSuccess: true } => Results.Ok(),
@@ -1,3 +1,4 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Execution;
using PostFundManagement.Domain.Abstractions;
@@ -13,7 +14,7 @@ public class CreateRiskEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPost("api/execution/risks", async (CreateRiskRequest request, ExecutionService service,
builder.MapPost("api/execution/risks", async (CreateRiskRequest request, IExecutionService service,
HttpContext context, CancellationToken cancellationToken = default) =>
await service.CreateRiskAsync(request, context.GetUserId(), cancellationToken) switch
{
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Execution;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
@@ -14,7 +14,7 @@ public sealed class GetDisbursementEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/execution/disbursements/{disbursementId}", async (string disbursementId, ExecutionService service,
builder.MapGet("api/execution/disbursements/{disbursementId}", async (string disbursementId, IExecutionService service,
CancellationToken cancellationToken = default) =>
await service.GetDisbursementAsync(disbursementIdHash: disbursementId, cancellationToken) switch
{
@@ -31,6 +31,7 @@ public sealed class GetDisbursementEndpoint : IEndpoint
.Produces(StatusCodes.Status401Unauthorized)
.Produces<Problems>(StatusCodes.Status400BadRequest)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Execution);
.WithTags(EndpointTags.Execution)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Execution;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Extensions;
@@ -14,7 +14,7 @@ public class GetDisbursementsEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/execution/disbursements", async (ExecutionService service,
builder.MapGet("api/execution/disbursements", async (IExecutionService service,
int page = 1, int pageSize = 10, CancellationToken cancellationToken = default) =>
await service.GetDisbursementsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
{
@@ -28,6 +28,7 @@ public class GetDisbursementsEndpoint : IEndpoint
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status404NotFound)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Execution);
.WithTags(EndpointTags.Execution)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Execution;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
@@ -14,7 +14,7 @@ public sealed class GetRiskEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/execution/risks/{riskId}", async (string riskId, ExecutionService service,
builder.MapGet("api/execution/risks/{riskId}", async (string riskId, IExecutionService service,
CancellationToken cancellationToken = default) =>
await service.GetRiskAsync(riskIdHash: riskId, cancellationToken) switch
{
@@ -30,6 +30,7 @@ public sealed class GetRiskEndpoint : IEndpoint
.Produces(StatusCodes.Status404NotFound)
.Produces(StatusCodes.Status401Unauthorized)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Execution);
.WithTags(EndpointTags.Execution)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Execution;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Extensions;
@@ -13,7 +13,7 @@ public class GetRisksEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/execution/risks", async (ExecutionService service,
builder.MapGet("api/execution/risks", async (IExecutionService service,
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
await service.GetRisksAsync(Pagination.Create(page, pageSize), cancellationToken) switch
{
@@ -26,6 +26,7 @@ public class GetRisksEndpoint : IEndpoint
.Produces(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Execution);
.WithTags(EndpointTags.Execution)
.CacheOutput();
}
}
@@ -1,4 +1,5 @@
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Execution;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
@@ -14,7 +15,7 @@ public sealed class UpdateDisbursementEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPut("api/execution/disbursements", async (UpdateDisbursementRequest request, HttpContext context,
ExecutionService service, CancellationToken cancellationToken = default) =>
IExecutionService service, CancellationToken cancellationToken = default) =>
await service.UpdateDisbursementAsync(request, userId: context.GetUserId(), cancellationToken) switch
{
{ IsSuccess: true } => Results.Ok(),
@@ -1,4 +1,5 @@
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Execution;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
@@ -14,7 +15,7 @@ public sealed class UpdateRiskEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPut("api/execution/risks", async (UpdateRiskRequest request,
ExecutionService service, CancellationToken cancellationToken = default) =>
IExecutionService service, CancellationToken cancellationToken = default) =>
await service.UpdateRiskAsync(request, cancellationToken) switch
{
{ IsSuccess: true } => Results.Ok(),
@@ -1,3 +1,4 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Governance;
using PostFundManagement.Domain.Abstractions;
@@ -14,7 +15,7 @@ public sealed class CreateOrganisationEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPost("api/governance/organisations", async (CreateOrganisationRequest request, HttpContext context,
GovernanceService service, CancellationToken cancellationToken = default) =>
IGovernanceService service, CancellationToken cancellationToken = default) =>
await service.CreateOrganisationAsync(request, context.GetUserId(), cancellationToken) switch
{
{ IsSuccess: true } => Results.Ok(),
@@ -1,3 +1,4 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Governance;
using PostFundManagement.Domain.Abstractions;
@@ -12,7 +13,7 @@ public class DashboardEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/governance/dashboard", async (GovernanceService service,
builder.MapGet("api/governance/dashboard", async (IGovernanceService service,
CancellationToken cancellationToken = default) =>
await service.GetDashboardAsync(cancellationToken) switch
{
@@ -25,6 +26,7 @@ public class DashboardEndpoint : IEndpoint
.Produces<Dashboard>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Governance);
.WithTags(EndpointTags.Governance)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Governance;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Extensions;
using PostFundManagement.Domain.Models;
@@ -13,7 +13,7 @@ public class GetInstrumentsEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/governance/instruments", async (GovernanceService service,
builder.MapGet("api/governance/instruments", async (IGovernanceService service,
CancellationToken cancellationToken = default) =>
await service.GetInstrumentsAsync(cancellationToken) switch
{
@@ -26,6 +26,7 @@ public class GetInstrumentsEndpoint : IEndpoint
.Produces<Instrument[]>(StatusCodes.Status200OK)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Governance);
.WithTags(EndpointTags.Governance)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Governance;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
@@ -15,7 +15,7 @@ public class GetOrganisationEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/governance/organisations/{organisationId}", async (string organisationId,
GovernanceService service, CancellationToken cancellationToken = default) =>
IGovernanceService service, CancellationToken cancellationToken = default) =>
await service.GetOrganisationAsync(organisationId, cancellationToken) switch
{
{ IsSuccess: true, Value: var organisation } => Results.Ok(organisationId),
@@ -31,6 +31,7 @@ public class GetOrganisationEndpoint : IEndpoint
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Governance);
.WithTags(EndpointTags.Governance)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Governance;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Extensions;
@@ -14,7 +14,7 @@ public class GetOrganisationsEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/governance/organisations", async (GovernanceService service,
builder.MapGet("api/governance/organisations", async (IGovernanceService service,
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
await service.GetOrganisationsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
{
@@ -27,6 +27,7 @@ public class GetOrganisationsEndpoint : IEndpoint
.Produces<Organisation[]>(StatusCodes.Status200OK)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Governance);
.WithTags(EndpointTags.Governance)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Governance;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Extensions;
using PostFundManagement.Domain.Models;
@@ -13,7 +13,7 @@ public class GetPortfoliosEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/governance/portfolios", async (GovernanceService service,
builder.MapGet("api/governance/portfolios", async (IGovernanceService service,
CancellationToken cancellationToken = default) =>
await service.GetPorfoliosAsync(cancellationToken) switch
{
@@ -26,6 +26,7 @@ public class GetPortfoliosEndpoint : IEndpoint
.Produces<Portfolio[]>(StatusCodes.Status200OK)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Governance);
.WithTags(EndpointTags.Governance)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Governance;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Extensions;
using PostFundManagement.Domain.Models;
@@ -13,7 +13,7 @@ public class GetProgrammesEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/governance/programmes", async (GovernanceService service,
builder.MapGet("api/governance/programmes", async (IGovernanceService service,
CancellationToken cancellationToken = default) =>
await service.GetProgrammesAsync(cancellationToken) switch
{
@@ -26,6 +26,7 @@ public class GetProgrammesEndpoint : IEndpoint
.Produces<Programme[]>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Governance);
.WithTags(EndpointTags.Governance)
.CacheOutput();
}
}
@@ -1,4 +1,5 @@
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Governance;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
@@ -14,7 +15,7 @@ public sealed class UpdateOrganisationEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPut("api/governance/organisations", async (UpdateOrganisationRequest request,
GovernanceService service, CancellationToken cancellationToken = default) =>
IGovernanceService service, CancellationToken cancellationToken = default) =>
await service.UpdateOrganisationAsync(request, cancellationToken) switch
{
{ IsSuccess: true } => Results.Ok(),
@@ -1,3 +1,4 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Grants;
using PostFundManagement.Domain.Abstractions;
@@ -14,7 +15,7 @@ public class CreateAwardEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPost("api/grants/awards", async (CreateAwardRequest request, HttpContext context,
GrantsService service, CancellationToken cancellationToken = default) =>
IGrantsService service, CancellationToken cancellationToken = default) =>
await service.CreateAwardAsync(request, context.GetUserId(), cancellationToken) switch
{
{ IsSuccess: true } => Results.Ok(),
@@ -1,3 +1,4 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Grants;
using PostFundManagement.Domain.Abstractions;
@@ -14,7 +15,7 @@ public class CreateBudgetEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPost("api/grants/budgets", async (CreateBudgetRequest request, HttpContext context,
GrantsService service, CancellationToken cancellationToken = default) =>
IGrantsService service, CancellationToken cancellationToken = default) =>
await service.CreateBudgetAsync(request, context.GetUserId(), cancellationToken) switch
{
{ IsSuccess: true } => Results.Ok(),
@@ -23,15 +24,15 @@ public class CreateBudgetEndpoint : IEndpoint
var r when r.HasError<CreateError>() => Results.BadRequest(),
var r => Results.InternalServerError(r.Errors.ToProblems())
})
.WithDescription("Create a new budget line (M05)")
.WithName(typeof(CreateBudgetEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound)
.Produces(StatusCodes.Status400BadRequest)
.Produces<Problems>(StatusCodes.Status400BadRequest)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Grants);
.WithDescription("Create a new budget line (M05)")
.WithName(typeof(CreateBudgetEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound)
.Produces(StatusCodes.Status400BadRequest)
.Produces<Problems>(StatusCodes.Status400BadRequest)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Grants);
}
}
@@ -1,3 +1,4 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Grants;
using PostFundManagement.Domain.Abstractions;
@@ -14,7 +15,7 @@ public class CreateContractEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPost("api/grants/contracts", async (CreateContractRequest request, HttpContext context,
GrantsService service, CancellationToken cancellationToken = default) =>
IGrantsService service, CancellationToken cancellationToken = default) =>
await service.CreateContractAsync(request, context.GetUserId(), cancellationToken) switch
{
{ IsSuccess: true } => Results.Ok(),
@@ -1,3 +1,4 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Grants;
using PostFundManagement.Domain.Abstractions;
@@ -14,7 +15,7 @@ public class ExecuteContractEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPost("api/grants/contracts/execute", async (ExecuteContractRequest request, HttpContext context,
GrantsService service, CancellationToken cancellationToken = default) =>
IGrantsService service, CancellationToken cancellationToken = default) =>
await service.ExecuteContractAsync(request, context.GetUserId(), cancellationToken) switch
{
{ IsSuccess: true } => Results.Ok(),
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Grants;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
@@ -14,7 +14,7 @@ public class GetAwardEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/grants/awards/{awardId}", async (string awardId, GrantsService service,
builder.MapGet("api/grants/awards/{awardId}", async (string awardId, IGrantsService service,
CancellationToken cancellationToken = default) =>
await service.GetAwardAsync(awardId, cancellationToken) switch
{
@@ -23,14 +23,15 @@ public class GetAwardEndpoint : IEndpoint
var r when r.HasError<NotFoundError>() => Results.NotFound(),
var r => Results.InternalServerError(r.Errors.ToProblems())
})
.WithDescription("Get award by ID")
.WithName(typeof(GetAwardEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces<Award>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status404NotFound)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Grants);
.WithDescription("Get award by ID")
.WithName(typeof(GetAwardEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces<Award>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status404NotFound)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Grants)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Grants;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Extensions;
@@ -14,19 +14,20 @@ public class GetAwardsEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/grants/awards", async (GrantsService service,
builder.MapGet("api/grants/awards", async (IGrantsService service,
int page = 1, int pageSize = 10, CancellationToken cancellationToken = default) =>
await service.GetAwardsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
{
{ IsSuccess: true, Value: var awards } => Results.Ok(awards),
var r => Results.InternalServerError(r.Errors.ToProblems())
})
.WithDescription("Get a list of awards")
.WithName(typeof(GetAwardsEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces<Award[]>(StatusCodes.Status200OK)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Grants);
.WithDescription("Get a list of awards")
.WithName(typeof(GetAwardsEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces<Award[]>(StatusCodes.Status200OK)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Grants)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Grants;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
@@ -14,7 +14,7 @@ public class GetBudgetEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/grants/budgets/{budgetId}", async (string budgetId, GrantsService service,
builder.MapGet("api/grants/budgets/{budgetId}", async (string budgetId, IGrantsService service,
CancellationToken cancellationToken = default) =>
await service.GetBudgetAsync(budgetId, cancellationToken) switch
{
@@ -23,14 +23,15 @@ public class GetBudgetEndpoint : IEndpoint
var r when r.HasError<NotFoundError>() => Results.NotFound(),
var r => Results.InternalServerError(r.Errors.ToProblems())
})
.WithDescription("Get budget by ID")
.WithName(typeof(GetBudgetEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces<Budget>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status401Unauthorized)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Grants);
.WithDescription("Get budget by ID")
.WithName(typeof(GetBudgetEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces<Budget>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status401Unauthorized)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Grants)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Grants;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Extensions;
@@ -14,19 +14,20 @@ public class GetBudgetsEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/grants/budgets", async (GrantsService service,
builder.MapGet("api/grants/budgets", async (IGrantsService service,
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
await service.GetBudgetsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
{
{ IsSuccess: true, Value: var budgets } => Results.Ok(budgets),
var r => Results.InternalServerError(r.Errors.ToProblems())
})
.WithDescription("Get all budgets")
.WithName(typeof(GetBudgetsEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces<Budget[]>(StatusCodes.Status200OK)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Grants);
.WithDescription("Get all budgets")
.WithName(typeof(GetBudgetsEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces<Budget[]>(StatusCodes.Status200OK)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Grants)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Grants;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
@@ -14,7 +14,7 @@ public class GetContractEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/grants/contracts/{contractId}", async (string contractId, GrantsService service,
builder.MapGet("api/grants/contracts/{contractId}", async (string contractId, IGrantsService service,
CancellationToken cancellationToken = default) =>
await service.GetContractAsync(contractId, cancellationToken) switch
{
@@ -23,14 +23,15 @@ public class GetContractEndpoint : IEndpoint
var r when r.HasError<NotFoundError>() => Results.NotFound(),
var r => Results.InternalServerError(r.Errors.ToProblems())
})
.WithDescription("Get contract by ID")
.WithName(typeof(GetContractEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces<Contract>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status401Unauthorized)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Grants);
.WithDescription("Get contract by ID")
.WithName(typeof(GetContractEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces<Contract>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status401Unauthorized)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Grants)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Grants;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Extensions;
@@ -14,7 +14,7 @@ public class GetContractsEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/grants/contracts", async (GrantsService service,
builder.MapGet("api/grants/contracts", async (IGrantsService service,
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
await service.GetContractsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
{
@@ -27,6 +27,7 @@ public class GetContractsEndpoint : IEndpoint
.Produces<Contract[]>(StatusCodes.Status200OK)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Grants);
.WithTags(EndpointTags.Grants)
.CacheOutput();
}
}
@@ -1,3 +1,4 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Projects;
using PostFundManagement.Domain.Abstractions;
@@ -14,7 +15,7 @@ public class CreateActivityEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPost("api/projects/activities", async (CreateActivityRequest request,
HttpContext context, ProjectService service, CancellationToken cancellationToken = default) =>
HttpContext context, IProjectService service, CancellationToken cancellationToken = default) =>
await service.CreateActivityAsync(request, context.GetUserId(), cancellationToken) switch
{
{ IsSuccess: true } result => Results.Ok(),
@@ -1,3 +1,4 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Projects;
using PostFundManagement.Domain.Abstractions;
@@ -14,7 +15,7 @@ public class CreateProjectEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPost("api/projects", async (CreateProjectRequest request, HttpContext context,
ProjectService service, CancellationToken cancellationToken = default) =>
IProjectService service, CancellationToken cancellationToken = default) =>
await service.CreateProjectAsync(request, context.GetUserId(), cancellationToken) switch
{
{ IsSuccess: true } result => Results.Ok(),
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Projects;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
@@ -14,7 +14,7 @@ public class GetActivitiesEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/projects/{projectId}/activities", async (string projectId,
ProjectService service, CancellationToken cancellationToken = default) =>
IProjectService service, CancellationToken cancellationToken = default) =>
await service.GetActivitiesAsync(projectId, cancellationToken) switch
{
{ IsSuccess: true, Value: var activities } => Results.Ok(activities),
@@ -28,6 +28,7 @@ public class GetActivitiesEndpoint : IEndpoint
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status401Unauthorized)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Projects);
.WithTags(EndpointTags.Projects)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Projects;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
@@ -14,7 +14,7 @@ public class GetActivityEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/projects/activities/{activityId}", async (string activityId,
ProjectService service, CancellationToken cancellationToken = default) =>
IProjectService service, CancellationToken cancellationToken = default) =>
await service.GetActivityAsync(activityId, cancellationToken) switch
{
{ IsSuccess: true, Value: var activity } => Results.Ok(activity),
@@ -30,6 +30,7 @@ public class GetActivityEndpoint : IEndpoint
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status401Unauthorized)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Projects);
.WithTags(EndpointTags.Projects)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Projects;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
@@ -14,7 +14,7 @@ public class GetMilestoneEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/projects/milestones/{milestoneId}", async (string milestoneId, ProjectService service,
builder.MapGet("api/projects/milestones/{milestoneId}", async (string milestoneId, IProjectService service,
CancellationToken cancellationToken = default) =>
await service.GetMilestoneAsync(milestoneId, cancellationToken) switch
{
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Projects;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Extensions;
@@ -14,7 +14,7 @@ public class GetMilestonesEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/projects/milestones/{page:int}/{pageSize:int}", async (ProjectService service,
builder.MapGet("api/projects/milestones/{page:int}/{pageSize:int}", async (IProjectService service,
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
await service.GetMilestonesAsync(Pagination.Create(page, pageSize), cancellationToken) switch
{
@@ -28,6 +28,7 @@ public class GetMilestonesEndpoint : IEndpoint
.Produces<Milestone[]>(StatusCodes.Status200OK)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Projects);
.WithTags(EndpointTags.Projects)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Projects;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
@@ -14,7 +14,7 @@ public class GetProjectEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/projects/{projectId}", async (string projectId, ProjectService service,
builder.MapGet("api/projects/{projectId}", async (string projectId, IProjectService service,
CancellationToken cancellationToken = default) =>
await service.GetProjectAsync(projectId, cancellationToken) switch
{
@@ -31,6 +31,7 @@ public class GetProjectEndpoint : IEndpoint
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status401Unauthorized)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Projects);
.WithTags(EndpointTags.Projects)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Projects;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
@@ -14,7 +14,7 @@ public class GetProjectIndicatorsEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/projects/indicators/project/{projectId}", async (string projectId, ProjectService service,
builder.MapGet("api/projects/indicators/project/{projectId}", async (string projectId, IProjectService service,
CancellationToken cancellationToken = default) =>
await service.GetProjectIndicatorsAsync(projectIdHash: projectId, cancellationToken) switch
{
@@ -30,6 +30,7 @@ public class GetProjectIndicatorsEndpoint : IEndpoint
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status401Unauthorized)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Projects);
.WithTags(EndpointTags.Projects)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Projects;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
@@ -15,7 +15,7 @@ public class GetProjectMilestonesEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/projects/{projectId}/milestones", async (string projectId,
ProjectService service, CancellationToken cancellationToken = default) =>
IProjectService service, CancellationToken cancellationToken = default) =>
await service.GetProjectMilestonesAsync(projectId, cancellationToken) switch
{
{ IsSuccess: true, Value: var milestones } => Results.Ok(milestones),
@@ -30,6 +30,7 @@ public class GetProjectMilestonesEndpoint : IEndpoint
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status401Unauthorized)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Projects);
.WithTags(EndpointTags.Projects)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Projects;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
@@ -15,7 +15,7 @@ public class GetProjectRisksEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/projects/{projectId}/risks", async (string projectId,
ProjectService service, CancellationToken cancellationToken = default) =>
IProjectService service, CancellationToken cancellationToken = default) =>
await service.GetProjectRisksAsync(projectId, cancellationToken) switch
{
{ IsSuccess: true, Value: var risks } => Results.Ok(risks),
@@ -30,6 +30,7 @@ public class GetProjectRisksEndpoint : IEndpoint
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status401Unauthorized)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.WithTags(EndpointTags.Projects);
.WithTags(EndpointTags.Projects)
.CacheOutput();
}
}
@@ -1,5 +1,5 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Projects;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Extensions;
@@ -14,7 +14,7 @@ public class GetProjectsEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapGet("api/projects", async (ProjectService service,
builder.MapGet("api/projects", async (IProjectService service,
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
await service.GetProjectsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
{
@@ -27,6 +27,7 @@ public class GetProjectsEndpoint : IEndpoint
.Produces<Project[]>(StatusCodes.Status200OK)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Projects);
.WithTags(EndpointTags.Projects)
.CacheOutput();
}
}
@@ -1,4 +1,5 @@
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Projects;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Extensions;
@@ -12,7 +13,7 @@ public sealed class UpdateMilestoneEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPut("api/projects/milestone", async (UpdateMilestoneRequest request, ProjectService service,
builder.MapPut("api/projects/milestone", async (UpdateMilestoneRequest request, IProjectService service,
HttpContext context, CancellationToken cancellationToken = default) =>
await service.UpdateMilestoneAsync(request, context.GetUserId(), cancellationToken) switch
{
@@ -1,4 +1,5 @@
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Projects;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
@@ -14,20 +15,20 @@ public sealed class UpdateProjectEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPut("api/projects", async (UpdateProjectRequest request,
ProjectService service, HttpContext context, CancellationToken cancellationToken = default) =>
IProjectService service, HttpContext context, CancellationToken cancellationToken = default) =>
await service.UpdateProjectAsync(request, userId: context.GetUserId(), cancellationToken) switch
{
{ IsSuccess: true } => Results.Ok(),
var r when r.HasError<UpdateError>() => Results.BadRequest(r.Errors.ToProblems()),
var r => Results.InternalServerError(r.Errors.ToProblems())
})
.WithDescription("Update project details")
.WithName(typeof(UpdateProjectEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK)
.Produces<Problems>(StatusCodes.Status400BadRequest)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Projects);
.WithDescription("Update project details")
.WithName(typeof(UpdateProjectEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces(StatusCodes.Status200OK)
.Produces<Problems>(StatusCodes.Status400BadRequest)
.Produces<Problems>(StatusCodes.Status500InternalServerError)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Projects);
}
}
@@ -1,3 +1,4 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Projects;
using PostFundManagement.Domain.Abstractions;
@@ -14,7 +15,7 @@ public class UpdateProjectStatusEndpoint : IEndpoint
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPut("api/projects/status", async (UpdateProjectStatusRequest request, HttpContext context,
ProjectService service, CancellationToken cancellationToken = default) =>
IProjectService service, CancellationToken cancellationToken = default) =>
await service.UpdateProjectStatusAsync(request, context.GetUserId(), cancellationToken) switch
{
{ IsSuccess: true } => Results.Ok(),
@@ -10,6 +10,14 @@
<PackageLicenseFile>..\LICENSE</PackageLicenseFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<NoWarn>1701;1702;AV0029;AV0030;</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<NoWarn>1701;1702;AV0029;AV0030;</NoWarn>
</PropertyGroup>
<!-- Security (IODC)-->
<ItemGroup>
<PackageReference Include="IdentityModel.AspNetCore" Version="4.3.0" />
@@ -0,0 +1,26 @@
using PostFundManagement.Application.Services.Execution;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Models;
namespace PostFundManagement.Application.Abstractions.Services;
public interface IExecutionService
{
ValueTask<Result<Risk[]>> GetRisksAsync(Pagination pagination, CancellationToken cancellationToken = default);
ValueTask<Result<Disbursement[]>> GetDisbursementsAsync(Pagination pagination, CancellationToken cancellationToken = default);
ValueTask<Result> CreateRiskAsync(CreateRiskRequest request, Guid userId, CancellationToken cancellationToken = default);
ValueTask<Result> CreateDisbursementAsync(CreateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default);
ValueTask<Result> ApproveDisbursementAsync(string disbursementIdHash, Guid userId, CancellationToken cancellationToken = default);
ValueTask<Result<Disbursement>> GetDisbursementAsync(string disbursementIdHash, CancellationToken cancellationToken = default);
ValueTask<Result<Risk>> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken = default);
ValueTask<Result> UpdateRiskAsync(UpdateRiskRequest request, CancellationToken cancellationToken = default);
ValueTask<Result> UpdateDisbursementAsync(UpdateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default);
}
@@ -0,0 +1,24 @@
using PostFundManagement.Application.Services.Governance;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Models;
namespace PostFundManagement.Application.Abstractions.Services;
public interface IGovernanceService
{
ValueTask<Result<Programme[]>> GetProgrammesAsync(CancellationToken cancellationToken = default);
ValueTask<Result<Portfolio[]>> GetPorfoliosAsync(CancellationToken cancellationToken = default);
ValueTask<Result<Organisation[]>> GetOrganisationsAsync(Pagination pagination, CancellationToken cancellationToken = default);
ValueTask<Result<Organisation>> GetOrganisationAsync(string organisationIdHash, CancellationToken cancellationToken = default);
ValueTask<Result<Instrument[]>> GetInstrumentsAsync(CancellationToken cancellationToken = default);
ValueTask<Result<Dashboard>> GetDashboardAsync(CancellationToken cancellationToken = default);
ValueTask<Result> CreateOrganisationAsync(CreateOrganisationRequest request, Guid userId, CancellationToken cancellationToken = default);
ValueTask<Result<Organisation>> UpdateOrganisationAsync(UpdateOrganisationRequest request, CancellationToken cancellationToken = default);
}
@@ -0,0 +1,28 @@
using PostFundManagement.Application.Services.Grants;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Models;
namespace PostFundManagement.Application.Abstractions.Services;
public interface IGrantsService
{
ValueTask<Result<Contract[]>> GetContractsAsync(Pagination pagination, CancellationToken cancellationToken = default);
ValueTask<Result<Contract>> GetContractAsync(string contractIdHash, CancellationToken cancellationToken = default);
ValueTask<Result<Budget[]>> GetBudgetsAsync(Pagination pagination, CancellationToken cancellationToken = default);
ValueTask<Result<Budget>> GetBudgetAsync(string budgetIdHash, CancellationToken cancellationToken = default);
ValueTask<Result<Award[]>> GetAwardsAsync(Pagination pagination, CancellationToken cancellationToken = default);
ValueTask<Result<Award>> GetAwardAsync(string awardIdHash, CancellationToken cancellationToken = default);
ValueTask<Result> ExecuteContractAsync(ExecuteContractRequest request, Guid userId, CancellationToken cancellationToken = default);
ValueTask<Result> CreateContractAsync(CreateContractRequest request, Guid userId, CancellationToken cancellationToken = default);
ValueTask<Result> CreateBudgetAsync(CreateBudgetRequest request, Guid userId, CancellationToken cancellationToken = default);
ValueTask<Result> CreateAwardAsync(CreateAwardRequest request, Guid userId, CancellationToken cancellationToken = default);
}
@@ -0,0 +1,36 @@
using PostFundManagement.Application.Services.Projects;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Models;
namespace PostFundManagement.Application.Abstractions.Services;
public interface IProjectService
{
ValueTask<Result> UpdateProjectStatusAsync(UpdateProjectStatusRequest request, Guid userId, CancellationToken cancellationToken = default);
ValueTask<Result<Project[]>> GetProjectsAsync(Pagination pagination, CancellationToken cancellationToken = default);
ValueTask<Result<Project>> GetProjectAsync(string projectIdHash, CancellationToken cancellationToken = default);
ValueTask<Result<Domain.Models.Activity[]>> GetActivitiesAsync(string projectIdHash, CancellationToken cancellationToken = default);
ValueTask<Result> CreateProjectAsync(CreateProjectRequest request, Guid userId, CancellationToken cancellationToken = default);
ValueTask<Result> CreateActivityAsync(CreateActivityRequest request, Guid userId, CancellationToken cancellationToken = default);
ValueTask<Result<Milestone[]>> GetProjectMilestonesAsync(string projectIdHash, CancellationToken cancellationToken = default);
ValueTask<Result<Indicator[]>> GetProjectIndicatorsAsync(string projectIdHash, CancellationToken cancellationToken = default);
ValueTask<Result<Milestone>> GetMilestoneAsync(string milestoneIdHash, CancellationToken cancellationToken = default);
ValueTask<Result<Milestone[]>> GetMilestonesAsync(Pagination pagination, CancellationToken cancellationToken = default);
ValueTask<Result> UpdateMilestoneAsync(UpdateMilestoneRequest request, Guid userId, CancellationToken cancellationToken = default);
ValueTask<Result> UpdateProjectAsync(UpdateProjectRequest request, Guid userId, CancellationToken cancellationToken = default);
ValueTask<Result<Domain.Models.Activity>> GetActivityAsync(string activityIdHash, CancellationToken cancellationToken = default);
ValueTask<Result<Risk[]>> GetProjectRisksAsync(string projectIdHash, CancellationToken cancellationToken = default);
}
@@ -1,55 +1,10 @@
using PostFundManagement.Application.Abstractions;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Services.Communications;
using PostFundManagement.Application.Services.Evidence;
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Application.Services.Users;
using PostFundManagement.Domain.Abstractions;
namespace PostFundManagement.Application.Extensions;
namespace PostFundManagement.Application.Extensions;
public static class General
{
public static IServiceCollection AddRegisterServicesWithCaching(this IServiceCollection services, IConfiguration configuration)
{
services.AddScoped<ICommunicationsService, CommunicationsService>();
services.Decorate<ICommunicationsService, CommunicationsCacheService>();
public static string ToJson<TValue>(this TValue obj) where TValue : class => JsonSerializer.Serialize(obj);
services.AddScoped<IEvidenceService, EvidenceService>();
services.Decorate<IEvidenceService, EvidenceCacheService>();
services.AddScoped<IUserService, UserService>();
services.Decorate<IUserService, UserCacheService>();
services.AddScoped<IIdentityService, IdentityService>();
services.Decorate<IIdentityService, IdentityCacheService>();
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = configuration.GetConnectionString("Redis");
options.InstanceName = "PFM-API_";
});
services.AddHybridCache(options => options.DefaultEntryOptions = new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromMinutes(2),
LocalCacheExpiration = TimeSpan.FromMinutes(30)
});
return services;
}
public static IServiceCollection AddSharedServices(this IServiceCollection services)
{
var serviceType = typeof(IService);
var sharedImplementations = typeof(IApplication).Assembly.GetTypes()
.Where(t => serviceType.IsAssignableFrom(t) && t.IsClass && !t.IsAbstract);
foreach (var sharedImplementation in sharedImplementations) services.AddScoped(sharedImplementation);
return services;
}
public static TValue FromJson<TValue>(this string json) where TValue : class => JsonSerializer.Deserialize<TValue>(json)!;
public static Guid GetUserId(this HttpContext context) => (Guid)context.Items[Domain.Extensions.Constants.UserIdItemKey]!;
@@ -0,0 +1,69 @@
using PostFundManagement.Application.Abstractions;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Services.Communications;
using PostFundManagement.Application.Services.Evidence;
using PostFundManagement.Application.Services.Execution;
using PostFundManagement.Application.Services.Governance;
using PostFundManagement.Application.Services.Grants;
using PostFundManagement.Application.Services.Projects;
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Application.Services.Users;
using PostFundManagement.Domain.Abstractions;
namespace PostFundManagement.Application.Extensions;
public static class Services
{
public static IServiceCollection AddRegisterServicesWithCaching(this IServiceCollection services, IConfiguration configuration)
{
services.AddScoped<ICommunicationsService, CommunicationsService>();
services.Decorate<ICommunicationsService, CommunicationsCacheService>();
services.AddScoped<IEvidenceService, EvidenceService>();
services.Decorate<IEvidenceService, EvidenceCacheService>();
services.AddScoped<IUserService, UserService>();
services.Decorate<IUserService, UserCacheService>();
services.AddScoped<IIdentityService, IdentityService>();
services.Decorate<IIdentityService, IdentityCacheService>();
services.AddScoped<IExecutionService, ExecutionService>();
services.Decorate<IExecutionService, ExecutionCacheService>();
services.AddScoped<IGovernanceService, GovernanceService>();
services.Decorate<IGovernanceService, GovernanceCacheService>();
services.AddScoped<IGrantsService, GrantsService>();
services.Decorate<IGrantsService, GrantsCacheService>();
services.AddScoped<IProjectService, ProjectService>();
services.Decorate<IProjectService, ProjectCacheService>();
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = configuration.GetConnectionString("Redis");
options.InstanceName = "PFM-API_";
});
services.AddHybridCache(options => options.DefaultEntryOptions = new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromMinutes(2),
LocalCacheExpiration = TimeSpan.FromMinutes(30)
});
return services;
}
public static IServiceCollection AddSharedServices(this IServiceCollection services)
{
var serviceType = typeof(IService);
var sharedImplementations = typeof(IApplication).Assembly.GetTypes()
.Where(t => serviceType.IsAssignableFrom(t) && t.IsClass && !t.IsAbstract);
foreach (var sharedImplementation in sharedImplementations) services.AddScoped(sharedImplementation);
return services;
}
}
@@ -1,22 +1,53 @@
using PostFundManagement.Application.Abstractions;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Models;
namespace PostFundManagement.Application.Services.Communications;
public sealed class CommunicationsCacheService(CommunicationsService service, HybridCache cache) : ServiceCacheBase, ICommunicationsService
public sealed class CommunicationsCacheService(CommunicationsService service, IDistributedCache cache) : ServiceCacheBase, ICommunicationsService
{
public async ValueTask<Result<Invite>> GetApplicantInviteAsync(Guid userId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Invite>>>)(async () =>
await cache.GetOrCreateAsync(HashService.ToMd5Hash($"getapplicantinvite-{userId}").Value,
async cancel => await service.GetApplicantInviteAsync(userId, cancellationToken))));
{
var cacheKey = HashService.ToMd5Hash($"getapplicantinvite-{userId}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetApplicantInviteAsync(userId, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
}
return Result.Ok(cached!.FromJson<Invite>());
}));
public async ValueTask<Result<Invite[]>> GetInvitesAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Invite[]>>>)(async () =>
await cache.GetOrCreateAsync(HashService.ToMd5Hash($"getinvites-{pagination.Page}-{pagination.PageSize}").Value,
async cancel => await service.GetInvitesAsync(pagination, cancellationToken))));
{
var cacheKey = HashService.ToMd5Hash($"getinvites-{pagination.Page}-{pagination.PageSize}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetInvitesAsync(pagination, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return Result.Ok(result.Value);
}
return Result.Ok(cached.FromJson<Invite[]>());
}));
public async ValueTask<Result<Invite>> SendInviteAsync(InviteRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await service.SendInviteAsync(request, userId, cancellationToken);
@@ -1,12 +1,13 @@
using PostFundManagement.Application.Abstractions;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Models;
namespace PostFundManagement.Application.Services.Evidence;
public sealed class EvidenceCacheService(EvidenceService service, HybridCache cache) : ServiceCacheBase, IEvidenceService
public sealed class EvidenceCacheService(EvidenceService service, IDistributedCache cache) : ServiceCacheBase, IEvidenceService
{
public async ValueTask<Result> CreateEvidenceAsync(Guid userId, IFormCollection form, IFormFile file, CancellationToken cancellationToken = default) =>
await service.CreateEvidenceAsync(userId, form, file, cancellationToken);
@@ -19,33 +20,129 @@ public sealed class EvidenceCacheService(EvidenceService service, HybridCache ca
public async ValueTask<Result<Domain.Models.Evidence>> GetEvidenceAsync(string evidenceId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Domain.Models.Evidence>>>)(async () =>
await cache.GetOrCreateAsync(HashService.ToMd5Hash($"getevidence-{evidenceId}").Value,
async cancel => await service.GetEvidenceAsync(evidenceId, cancellationToken))));
{
var cacheKey = HashService.ToMd5Hash($"getevidence-{evidenceId}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetEvidenceAsync(evidenceId, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Domain.Models.Evidence>());
}));
public async ValueTask<Result<Domain.Models.Evidence[]>> GetEvidenceFilesAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Domain.Models.Evidence[]>>>)(async () =>
await cache.GetOrCreateAsync(HashService.ToMd5Hash($"getevidencefiles-{pagination.Page}-{pagination.PageSize}").Value,
async cancel => await service.GetEvidenceFilesAsync(pagination, cancellationToken))));
{
var cacheKey = HashService.ToMd5Hash($"getevidencefiles-{pagination.Page}-{pagination.PageSize}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetEvidenceFilesAsync(pagination, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Domain.Models.Evidence[]>());
}));
public async ValueTask<Result<Indicator>> GetIndicatorAsync(string indicatorId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Indicator>>>)(async () =>
await cache.GetOrCreateAsync(HashService.ToMd5Hash($"getindicator-{indicatorId}").Value,
async cancel => await service.GetIndicatorAsync(indicatorId, cancellationToken))));
{
var cacheKey = HashService.ToMd5Hash($"getindicator-{indicatorId}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetIndicatorAsync(indicatorId, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Indicator>());
}));
public async ValueTask<Result<Indicator[]>> GetIndicatorsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Indicator[]>>>)(async () =>
await cache.GetOrCreateAsync(HashService.ToMd5Hash($"getindicators-{pagination.Page}-{pagination.PageSize}").Value,
async cancel => await service.GetIndicatorsAsync(pagination, cancellationToken))));
{
var cacheKey = HashService.ToMd5Hash($"getindicators-{pagination.Page}-{pagination.PageSize}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetIndicatorsAsync(pagination, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Indicator[]>());
}));
public async ValueTask<Result<Domain.Models.Evidence[]>> GetMilestoneEvidencesAsync(string milestoneIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Domain.Models.Evidence[]>>>)(async () =>
await cache.GetOrCreateAsync(HashService.ToMd5Hash($"getmilestoneevidences-{milestoneIdHash}").Value,
async cancel => await service.GetMilestoneEvidencesAsync(milestoneIdHash, cancellationToken))));
{
var cacheKey = HashService.ToMd5Hash($"getmilestoneevidences-{milestoneIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if(string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetMilestoneEvidencesAsync(milestoneIdHash, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Domain.Models.Evidence[]>());
}));
public async ValueTask<Result<Domain.Models.Evidence[]>> GetProjectEvidencesAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Domain.Models.Evidence[]>>>)(async () =>
await cache.GetOrCreateAsync(HashService.ToMd5Hash($"getprojectevidences-{projectIdHash}").Value,
async cancel => await service.GetProjectEvidencesAsync(projectIdHash, cancellationToken))));
{
var cacheKey = HashService.ToMd5Hash($"getprojectevidences-{projectIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if(string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetProjectEvidencesAsync(projectIdHash, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Domain.Models.Evidence[]>());
}));
public async ValueTask<Result> RecordIndicatorActualAmountAsync(string indicatorIdHash, decimal amount, Guid userId, CancellationToken cancellationToken = default) =>
await service.RecordIndicatorActualAmountAsync(indicatorIdHash, amount, userId, cancellationToken);
@@ -0,0 +1,110 @@
using PostFundManagement.Application.Abstractions;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Models;
namespace PostFundManagement.Application.Services.Execution;
public sealed class ExecutionCacheService(ExecutionService service, IDistributedCache cache) : ServiceCacheBase, IExecutionService
{
public async ValueTask<Result> ApproveDisbursementAsync(string disbursementIdHash, Guid userId, CancellationToken cancellationToken = default) =>
await service.ApproveDisbursementAsync(disbursementIdHash, userId, cancellationToken);
public async ValueTask<Result> CreateDisbursementAsync(CreateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await service.CreateDisbursementAsync(request, userId, cancellationToken);
public async ValueTask<Result> CreateRiskAsync(CreateRiskRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await service.CreateRiskAsync(request, userId, cancellationToken);
public async ValueTask<Result<Disbursement>> GetDisbursementAsync(string disbursementIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Disbursement>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getdisbursement-{disbursementIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetDisbursementAsync(disbursementIdHash, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Disbursement>());
}));
public async ValueTask<Result<Disbursement[]>> GetDisbursementsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Disbursement[]>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getdisbursements-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetDisbursementsAsync(pagination, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Disbursement[]>());
}));
public async ValueTask<Result<Risk>> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Risk>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getrisk-{riskIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetRiskAsync(riskIdHash, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Risk>());
}));
public async ValueTask<Result<Risk[]>> GetRisksAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Risk[]>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getrisks-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetRisksAsync(pagination, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Risk[]>());
}));
public async ValueTask<Result> UpdateDisbursementAsync(UpdateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await service.UpdateDisbursementAsync(request, userId, cancellationToken);
public async ValueTask<Result> UpdateRiskAsync(UpdateRiskRequest request, CancellationToken cancellationToken = default) =>
await service.UpdateRiskAsync(request, cancellationToken);
}
@@ -1,6 +1,6 @@
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
using PostFundManagement.Domain.Models;
@@ -8,7 +8,7 @@ using PostFundManagement.Infrastructure.Database;
namespace PostFundManagement.Application.Services.Execution;
public sealed class ExecutionService(IDbContextFactory<ApplicationDbContext> contextFactory, HashService hashService) : IService
public sealed class ExecutionService(IDbContextFactory<ApplicationDbContext> contextFactory, HashService hashService) : IExecutionService
{
public async ValueTask<Result<Risk[]>> GetRisksAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Risk[]>>>)(async () =>
@@ -120,7 +120,7 @@ public sealed class ExecutionService(IDbContextFactory<ApplicationDbContext> con
: Result.Fail<Disbursement>(NotFoundError.New);
}));
public async ValueTask<Result<Risk>> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken) =>
public async ValueTask<Result<Risk>> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Risk>>>)(async () =>
{
var decodeResult = hashService.DecodeLongIdHash(riskIdHash);
@@ -139,7 +139,7 @@ public sealed class ExecutionService(IDbContextFactory<ApplicationDbContext> con
: Result.Fail<Risk>(NotFoundError.New);
}));
public async ValueTask<Result> UpdateRiskAsync(UpdateRiskRequest request, CancellationToken cancellationToken) =>
public async ValueTask<Result> UpdateRiskAsync(UpdateRiskRequest request, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result>>)(async () =>
{
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
@@ -155,7 +155,7 @@ public sealed class ExecutionService(IDbContextFactory<ApplicationDbContext> con
return Result.FailIf(changedTotal <= 0, UpdateError.New);
}));
public async ValueTask<Result> UpdateDisbursementAsync(UpdateDisbursementRequest request, Guid userId, CancellationToken cancellationToken) =>
public async ValueTask<Result> UpdateDisbursementAsync(UpdateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result>>)(async () =>
{
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
@@ -0,0 +1,143 @@
using PostFundManagement.Application.Abstractions;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Models;
namespace PostFundManagement.Application.Services.Governance;
public sealed class GovernanceCacheService(GovernanceService service, IDistributedCache cache) : ServiceCacheBase, IGovernanceService
{
public async ValueTask<Result> CreateOrganisationAsync(CreateOrganisationRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await service.CreateOrganisationAsync(request, userId, cancellationToken);
public async ValueTask<Result<Dashboard>> GetDashboardAsync(CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Dashboard>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getdashboard").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if(string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetDashboardAsync(cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Dashboard>());
}));
public async ValueTask<Result<Instrument[]>> GetInstrumentsAsync(CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Instrument[]>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getinstruments").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if(string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetInstrumentsAsync(cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Instrument[]>());
}));
public async ValueTask<Result<Organisation>> GetOrganisationAsync(string organisationIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Organisation>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getorganisation-{organisationIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetOrganisationAsync(organisationIdHash, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Organisation>());
}));
public async ValueTask<Result<Organisation[]>> GetOrganisationsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Organisation[]>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getorganisations-{pagination.Page}-{pagination.PageSize}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetOrganisationsAsync(pagination, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Organisation[]>());
}));
public async ValueTask<Result<Portfolio[]>> GetPorfoliosAsync(CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Portfolio[]>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getportfolios").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetPorfoliosAsync(cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Portfolio[]>());
}));
public async ValueTask<Result<Programme[]>> GetProgrammesAsync(CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Programme[]>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getprogrammes").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetProgrammesAsync(cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Programme[]>());
}));
public async ValueTask<Result<Organisation>> UpdateOrganisationAsync(UpdateOrganisationRequest request, CancellationToken cancellationToken = default) =>
await service.UpdateOrganisationAsync(request, cancellationToken);
}
@@ -1,6 +1,6 @@
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
using PostFundManagement.Domain.Models;
@@ -8,7 +8,7 @@ using PostFundManagement.Infrastructure.Database;
namespace PostFundManagement.Application.Services.Governance;
public sealed class GovernanceService(IDbContextFactory<ApplicationDbContext> contextFactory, HashService hashService) : IService
public sealed class GovernanceService(IDbContextFactory<ApplicationDbContext> contextFactory, HashService hashService) : IGovernanceService
{
public async ValueTask<Result<Programme[]>> GetProgrammesAsync(CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Programme[]>>>)(async () =>
@@ -0,0 +1,149 @@
using PostFundManagement.Application.Abstractions;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Models;
namespace PostFundManagement.Application.Services.Grants;
public sealed class GrantsCacheService(GrantsService service, IDistributedCache cache) : ServiceCacheBase, IGrantsService
{
public async ValueTask<Result> CreateAwardAsync(CreateAwardRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await service.CreateAwardAsync(request, userId, cancellationToken);
public async ValueTask<Result> CreateBudgetAsync(CreateBudgetRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await service.CreateBudgetAsync(request, userId, cancellationToken);
public async ValueTask<Result> CreateContractAsync(CreateContractRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await service.CreateContractAsync(request, userId, cancellationToken);
public async ValueTask<Result> ExecuteContractAsync(ExecuteContractRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await service.ExecuteContractAsync(request, userId, cancellationToken);
public async ValueTask<Result<Award>> GetAwardAsync(string awardIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Award>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getaward-{awardIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetAwardAsync(awardIdHash, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Award>());
}));
public async ValueTask<Result<Award[]>> GetAwardsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Award[]>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getawards-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetAwardsAsync(pagination, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Award[]>());
}));
public async ValueTask<Result<Budget>> GetBudgetAsync(string budgetIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Budget>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getbudget-{budgetIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetBudgetAsync(budgetIdHash, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Budget>());
}));
public async ValueTask<Result<Budget[]>> GetBudgetsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Budget[]>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getbudgets-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetBudgetsAsync(pagination, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Budget[]>());
}));
public async ValueTask<Result<Contract>> GetContractAsync(string contractIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Contract>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getctract-{contractIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetContractAsync(contractIdHash, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Contract>());
}));
public async ValueTask<Result<Contract[]>> GetContractsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Contract[]>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getcontracts-{pagination.Index}-{pagination.PageSize}-{pagination.Page}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetContractsAsync(pagination, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Contract[]>());
}));
}
@@ -1,6 +1,6 @@
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
using PostFundManagement.Domain.Models;
@@ -8,7 +8,7 @@ using PostFundManagement.Infrastructure.Database;
namespace PostFundManagement.Application.Services.Grants;
public sealed class GrantsService(IDbContextFactory<ApplicationDbContext> contextFactory, HashService hashService) : IService
public sealed class GrantsService(IDbContextFactory<ApplicationDbContext> contextFactory, HashService hashService) : IGrantsService
{
public async ValueTask<Result<Contract[]>> GetContractsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Contract[]>>>)(async () =>
@@ -0,0 +1,215 @@
using PostFundManagement.Application.Abstractions;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Models;
namespace PostFundManagement.Application.Services.Projects;
public sealed class ProjectCacheService(ProjectService service, IDistributedCache cache) : ServiceCacheBase, IProjectService
{
public async ValueTask<Result> CreateActivityAsync(CreateActivityRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await service.CreateActivityAsync(request, userId, cancellationToken);
public async ValueTask<Result> CreateProjectAsync(CreateProjectRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await service.CreateProjectAsync(request, userId, cancellationToken);
public async ValueTask<Result<Domain.Models.Activity[]>> GetActivitiesAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Domain.Models.Activity[]>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getactivities-{projectIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetActivitiesAsync(projectIdHash, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Domain.Models.Activity[]>());
}));
public async ValueTask<Result<Domain.Models.Activity>> GetActivityAsync(string activityIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Domain.Models.Activity>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getactivity-{activityIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if(string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetActivityAsync(activityIdHash, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Domain.Models.Activity>());
}));
public async ValueTask<Result<Milestone>> GetMilestoneAsync(string milestoneIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Milestone>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getmilestone-{milestoneIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetMilestoneAsync(milestoneIdHash, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Milestone>());
}));
public async ValueTask<Result<Milestone[]>> GetMilestonesAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Milestone[]>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getmilestones-{pagination.Index}-{pagination.PageSize}-{pagination.Page}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetMilestonesAsync(pagination, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Milestone[]>());
}));
public async ValueTask<Result<Project>> GetProjectAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Project>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getproject-{projectIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetProjectAsync(projectIdHash, cancellationToken);
if (result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Project>());
}));
public async ValueTask<Result<Indicator[]>> GetProjectIndicatorsAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Indicator[]>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getprojectindicators-{projectIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetProjectIndicatorsAsync(projectIdHash, cancellationToken);
if(result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Indicator[]>());
}));
public async ValueTask<Result<Milestone[]>> GetProjectMilestonesAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Milestone[]>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getprojectmilestones-{projectIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if(string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetProjectMilestonesAsync(projectIdHash, cancellationToken);
if(result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Milestone[]>());
}));
public async ValueTask<Result<Risk[]>> GetProjectRisksAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Risk[]>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getprojectrisks-{projectIdHash}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetProjectRisksAsync(projectIdHash, cancellationToken);
if(result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Risk[]>());
}));
public async ValueTask<Result<Project[]>> GetProjectsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Project[]>>>)(async () =>
{
var cacheKey = HashService.ToMd5Hash($"getprojects-{pagination.Index}-{pagination.Page}-{pagination.PageSize}").Value;
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
if (string.IsNullOrWhiteSpace(cached))
{
var result = await service.GetProjectsAsync(pagination, cancellationToken);
if(result.IsFailed) return result;
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
return result.Value;
}
return Result.Ok(cached.FromJson<Project[]>());
}));
public async ValueTask<Result> UpdateMilestoneAsync(UpdateMilestoneRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await service.UpdateMilestoneAsync(request, userId, cancellationToken);
public async ValueTask<Result> UpdateProjectAsync(UpdateProjectRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await service.UpdateProjectAsync(request, userId, cancellationToken);
public async ValueTask<Result> UpdateProjectStatusAsync(UpdateProjectStatusRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await service.UpdateProjectStatusAsync(request, userId, cancellationToken);
}
@@ -1,6 +1,6 @@
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Errors;
using PostFundManagement.Domain.Extensions;
using PostFundManagement.Domain.Models;
@@ -8,7 +8,7 @@ using PostFundManagement.Infrastructure.Database;
namespace PostFundManagement.Application.Services.Projects;
public sealed class ProjectService(IDbContextFactory<ApplicationDbContext> contextFactory, HashService hashService) : IService
public sealed class ProjectService(IDbContextFactory<ApplicationDbContext> contextFactory, HashService hashService) : IProjectService
{
public async ValueTask<Result> UpdateProjectStatusAsync(UpdateProjectStatusRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result>>)(async () =>
@@ -179,7 +179,7 @@ public sealed class ProjectService(IDbContextFactory<ApplicationDbContext> conte
return Result.Ok(evidences.Select(e => e.Map()).ToArray());
}));
public async ValueTask<Result<Milestone>> GetMilestoneAsync(string milestoneIdHash, CancellationToken cancellationToken) =>
public async ValueTask<Result<Milestone>> GetMilestoneAsync(string milestoneIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Milestone>>>)(async () =>
{
var decodeResult = hashService.DecodeLongIdHash(milestoneIdHash);
@@ -211,7 +211,7 @@ public sealed class ProjectService(IDbContextFactory<ApplicationDbContext> conte
return Result.Ok(milestones.Select(i => i.Map()).ToArray());
}));
public async ValueTask<Result> UpdateMilestoneAsync(UpdateMilestoneRequest request, Guid userId, CancellationToken cancellationToken) =>
public async ValueTask<Result> UpdateMilestoneAsync(UpdateMilestoneRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result>>)(async () =>
{
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
@@ -228,7 +228,7 @@ public sealed class ProjectService(IDbContextFactory<ApplicationDbContext> conte
return Result.FailIf(changedTotal <= 0, UpdateError.New);
}));
public async ValueTask<Result> UpdateProjectAsync(UpdateProjectRequest request, Guid userId, CancellationToken cancellationToken) =>
public async ValueTask<Result> UpdateProjectAsync(UpdateProjectRequest request, Guid userId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result>>)(async () =>
{
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
@@ -247,7 +247,7 @@ public sealed class ProjectService(IDbContextFactory<ApplicationDbContext> conte
return Result.FailIf(changedTotal <= 0, UpdateError.New);
}));
public async ValueTask<Result<Domain.Models.Activity>> GetActivityAsync(string activityIdHash, CancellationToken cancellationToken) =>
public async ValueTask<Result<Domain.Models.Activity>> GetActivityAsync(string activityIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<ValueTask<Result<Domain.Models.Activity>>>)(async () =>
{
var decodeResult = hashService.DecodeLongIdHash(activityIdHash);
@@ -1,5 +1,6 @@
using PostFundManagement.Application.Abstractions;
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Extensions;
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Models;
@@ -21,14 +22,12 @@ public sealed class UserCacheService(UserService service, IDistributedCache cach
if (userResult.IsFailed) return userResult;
await cache.SetStringAsync(cacheKey, JsonSerializer.Serialize(userResult.Value), cacheOptions, cancellationToken);
await cache.SetStringAsync(cacheKey, userResult.Value.ToJson(), cacheOptions, cancellationToken);
return userResult;
}
var restored = JsonSerializer.Deserialize<User>(cached)!;
return Result.Ok(restored);
return Result.Ok(cached.FromJson<User>());
}));
public async ValueTask<Result<User[]>> GetUsersAsync(Pagination pagination, UserFilterRequest request, CancellationToken cancellationToken = default) =>
@@ -45,15 +44,13 @@ public sealed class UserCacheService(UserService service, IDistributedCache cach
if (usersResult.IsFailed) return usersResult;
await cache.SetStringAsync(cacheKey, JsonSerializer.Serialize(usersResult.Value),
await cache.SetStringAsync(cacheKey, usersResult.Value.ToJson(),
cacheOptions, cancellationToken);
return usersResult;
}
var restored = JsonSerializer.Deserialize<User[]>(cached)!;
return Result.Ok(restored);
return Result.Ok(cached.FromJson<User[]>());
}));
public async ValueTask<Result> SyncUserAsync(Guid userId, string email, CancellationToken cancellationToken = default) =>