From 0a1378fe25d15368c29ef2b0edcc2f573a93b865 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Sat, 5 Sep 2026 08:26:15 +0200 Subject: [PATCH] Implemented caching on all get endpoints and service layer --- .../Evidence/GetIndicatorEndpoint.cs | 19 +- .../Evidence/GetIndicatorsEndpoint.cs | 3 +- .../Execution/ApproveDisbursementEndpoint.cs | 4 +- .../Execution/CreateDisbursementEndpoint.cs | 3 +- .../Endpoints/Execution/CreateRiskEndpoint.cs | 3 +- .../Execution/GetDisbursementEndpoint.cs | 9 +- .../Execution/GetDisbursementsEndpoint.cs | 7 +- .../Endpoints/Execution/GetRiskEndpoint.cs | 9 +- .../Endpoints/Execution/GetRisksEndpoint.cs | 7 +- .../Execution/UpdateDisbursementEndpoint.cs | 5 +- .../Endpoints/Execution/UpdateRiskEndpoint.cs | 5 +- .../Governance/CreateOrganisationEndpoint.cs | 3 +- .../Endpoints/Governance/DashboardEndpoint.cs | 6 +- .../Governance/GetInstrumentsEndpoint.cs | 7 +- .../Governance/GetOrganisationEndpoint.cs | 7 +- .../Governance/GetOrganisationsEndpoint.cs | 7 +- .../Governance/GetPortfoliosEndpoint.cs | 7 +- .../Governance/GetProgrammesEndpoint.cs | 7 +- .../Governance/UpdateOrganisationEndpoint.cs | 5 +- .../Endpoints/Grants/CreateAwardEndpoint.cs | 3 +- .../Endpoints/Grants/CreateBudgetEndpoint.cs | 23 +- .../Grants/CreateContractEndpoint.cs | 3 +- .../Grants/ExecuteContractEndpoint.cs | 3 +- .../Endpoints/Grants/GetAwardEndpoint.cs | 23 +- .../Endpoints/Grants/GetAwardsEndpoint.cs | 19 +- .../Endpoints/Grants/GetBudgetEndpoint.cs | 23 +- .../Endpoints/Grants/GetBudgetsEndpoint.cs | 19 +- .../Endpoints/Grants/GetContractEndpoint.cs | 23 +- .../Endpoints/Grants/GetContractsEndpoint.cs | 7 +- .../Projects/CreateActivityEndpoint.cs | 3 +- .../Projects/CreateProjectEndpoint.cs | 3 +- .../Projects/GetActivitiesEndpoint.cs | 7 +- .../Endpoints/Projects/GetActivityEndpoint.cs | 7 +- .../Projects/GetMilestoneEndpoint.cs | 6 +- .../Projects/GetMilestonesEndpoint.cs | 7 +- .../Endpoints/Projects/GetProjectEndpoint.cs | 7 +- .../Projects/GetProjectIndicatorsEndpoint.cs | 7 +- .../Projects/GetProjectMilestonesEndpoint.cs | 7 +- .../Projects/GetProjectRisksEndpoint.cs | 7 +- .../Endpoints/Projects/GetProjectsEndpoint.cs | 7 +- .../Projects/UpdateMilestoneEndpoint.cs | 5 +- .../Projects/UpdateProjectEndpoint.cs | 21 +- .../Projects/UpdateProjectStatusEndpoint.cs | 3 +- .../PostFundManagement.Api.csproj | 8 + .../Services/IExecutionService.cs | 26 +++ .../Services/IGovernanceService.cs | 24 ++ .../Abstractions/Services/IGrantsService.cs | 28 +++ .../Abstractions/Services/IProjectService.cs | 36 +++ .../Extensions/General.cs | 51 +---- .../Extensions/Services.cs | 69 ++++++ .../CommunicationsCacheService.cs | 41 +++- .../Services/Evidence/EvidenceCacheService.cs | 123 ++++++++-- .../Execution/ExecutionCacheService.cs | 110 +++++++++ .../Services/Execution/ExecutionService.cs | 12 +- .../Governance/GovernanceCacheService.cs | 143 ++++++++++++ .../Services/Governance/GovernanceService.cs | 6 +- .../Services/Grants/GrantsCacheService.cs | 149 ++++++++++++ .../Services/Grants/GrantsService.cs | 6 +- .../Services/Projects/ProjectCacheService.cs | 215 ++++++++++++++++++ .../Services/Projects/ProjectService.cs | 14 +- .../Services/Users/UserCacheService.cs | 13 +- 61 files changed, 1185 insertions(+), 255 deletions(-) create mode 100644 PostFundManagement.Application/Abstractions/Services/IExecutionService.cs create mode 100644 PostFundManagement.Application/Abstractions/Services/IGovernanceService.cs create mode 100644 PostFundManagement.Application/Abstractions/Services/IGrantsService.cs create mode 100644 PostFundManagement.Application/Abstractions/Services/IProjectService.cs create mode 100644 PostFundManagement.Application/Extensions/Services.cs create mode 100644 PostFundManagement.Application/Services/Execution/ExecutionCacheService.cs create mode 100644 PostFundManagement.Application/Services/Governance/GovernanceCacheService.cs create mode 100644 PostFundManagement.Application/Services/Grants/GrantsCacheService.cs create mode 100644 PostFundManagement.Application/Services/Projects/ProjectCacheService.cs diff --git a/PostFundManagement.Api/Endpoints/Evidence/GetIndicatorEndpoint.cs b/PostFundManagement.Api/Endpoints/Evidence/GetIndicatorEndpoint.cs index ff62c3a..d495c8f 100644 --- a/PostFundManagement.Api/Endpoints/Evidence/GetIndicatorEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Evidence/GetIndicatorEndpoint.cs @@ -23,14 +23,15 @@ public sealed class GetIndicatorEndpoint : IEndpoint var r when r.HasError() => Results.NotFound(), var r => Results.InternalServerError(r.Errors.ToProblems()) }) - .WithDescription("Get a specific indicator.") - .WithName(typeof(GetIndicatorEndpoint).ToEndpointName()) - .MapToApiVersion(new ApiVersion(1)) - .Produces(StatusCodes.Status200OK) - .Produces(StatusCodes.Status404NotFound) - .Produces(StatusCodes.Status401Unauthorized) - .Produces(StatusCodes.Status403Forbidden) - .Produces(StatusCodes.Status500InternalServerError) - .WithTags(EndpointTags.Evidence); + .WithDescription("Get a specific indicator.") + .WithName(typeof(GetIndicatorEndpoint).ToEndpointName()) + .MapToApiVersion(new ApiVersion(1)) + .Produces(StatusCodes.Status200OK) + .Produces(StatusCodes.Status404NotFound) + .Produces(StatusCodes.Status401Unauthorized) + .Produces(StatusCodes.Status403Forbidden) + .Produces(StatusCodes.Status500InternalServerError) + .WithTags(EndpointTags.Evidence) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Evidence/GetIndicatorsEndpoint.cs b/PostFundManagement.Api/Endpoints/Evidence/GetIndicatorsEndpoint.cs index ab0640c..e0a9bf4 100644 --- a/PostFundManagement.Api/Endpoints/Evidence/GetIndicatorsEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Evidence/GetIndicatorsEndpoint.cs @@ -27,6 +27,7 @@ public class GetIndicatorsEndpoint : IEndpoint .Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status500InternalServerError) .Produces(StatusCodes.Status401Unauthorized) - .WithTags(EndpointTags.Evidence); + .WithTags(EndpointTags.Evidence) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Execution/ApproveDisbursementEndpoint.cs b/PostFundManagement.Api/Endpoints/Execution/ApproveDisbursementEndpoint.cs index f8611dd..e0bcbc3 100644 --- a/PostFundManagement.Api/Endpoints/Execution/ApproveDisbursementEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Execution/ApproveDisbursementEndpoint.cs @@ -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(), diff --git a/PostFundManagement.Api/Endpoints/Execution/CreateDisbursementEndpoint.cs b/PostFundManagement.Api/Endpoints/Execution/CreateDisbursementEndpoint.cs index 31536e0..8b1aeaa 100644 --- a/PostFundManagement.Api/Endpoints/Execution/CreateDisbursementEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Execution/CreateDisbursementEndpoint.cs @@ -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(), diff --git a/PostFundManagement.Api/Endpoints/Execution/CreateRiskEndpoint.cs b/PostFundManagement.Api/Endpoints/Execution/CreateRiskEndpoint.cs index 14d5eba..3b83375 100644 --- a/PostFundManagement.Api/Endpoints/Execution/CreateRiskEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Execution/CreateRiskEndpoint.cs @@ -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 { diff --git a/PostFundManagement.Api/Endpoints/Execution/GetDisbursementEndpoint.cs b/PostFundManagement.Api/Endpoints/Execution/GetDisbursementEndpoint.cs index f8d3acb..5d07ac8 100644 --- a/PostFundManagement.Api/Endpoints/Execution/GetDisbursementEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Execution/GetDisbursementEndpoint.cs @@ -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(StatusCodes.Status400BadRequest) .Produces(StatusCodes.Status500InternalServerError) - .WithTags(EndpointTags.Execution); + .WithTags(EndpointTags.Execution) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Execution/GetDisbursementsEndpoint.cs b/PostFundManagement.Api/Endpoints/Execution/GetDisbursementsEndpoint.cs index 3b55a5c..fc1f804 100644 --- a/PostFundManagement.Api/Endpoints/Execution/GetDisbursementsEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Execution/GetDisbursementsEndpoint.cs @@ -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(StatusCodes.Status500InternalServerError) - .WithTags(EndpointTags.Execution); + .WithTags(EndpointTags.Execution) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Execution/GetRiskEndpoint.cs b/PostFundManagement.Api/Endpoints/Execution/GetRiskEndpoint.cs index 65d12ce..941b33e 100644 --- a/PostFundManagement.Api/Endpoints/Execution/GetRiskEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Execution/GetRiskEndpoint.cs @@ -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(StatusCodes.Status500InternalServerError) - .WithTags(EndpointTags.Execution); + .WithTags(EndpointTags.Execution) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Execution/GetRisksEndpoint.cs b/PostFundManagement.Api/Endpoints/Execution/GetRisksEndpoint.cs index a1814c9..e919d7f 100644 --- a/PostFundManagement.Api/Endpoints/Execution/GetRisksEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Execution/GetRisksEndpoint.cs @@ -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(StatusCodes.Status500InternalServerError) - .WithTags(EndpointTags.Execution); + .WithTags(EndpointTags.Execution) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Execution/UpdateDisbursementEndpoint.cs b/PostFundManagement.Api/Endpoints/Execution/UpdateDisbursementEndpoint.cs index d188977..1fd1247 100644 --- a/PostFundManagement.Api/Endpoints/Execution/UpdateDisbursementEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Execution/UpdateDisbursementEndpoint.cs @@ -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(), diff --git a/PostFundManagement.Api/Endpoints/Execution/UpdateRiskEndpoint.cs b/PostFundManagement.Api/Endpoints/Execution/UpdateRiskEndpoint.cs index de72b1c..4bb7c37 100644 --- a/PostFundManagement.Api/Endpoints/Execution/UpdateRiskEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Execution/UpdateRiskEndpoint.cs @@ -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(), diff --git a/PostFundManagement.Api/Endpoints/Governance/CreateOrganisationEndpoint.cs b/PostFundManagement.Api/Endpoints/Governance/CreateOrganisationEndpoint.cs index 16c27f0..5eb565b 100644 --- a/PostFundManagement.Api/Endpoints/Governance/CreateOrganisationEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Governance/CreateOrganisationEndpoint.cs @@ -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(), diff --git a/PostFundManagement.Api/Endpoints/Governance/DashboardEndpoint.cs b/PostFundManagement.Api/Endpoints/Governance/DashboardEndpoint.cs index 76397a4..ba40669 100644 --- a/PostFundManagement.Api/Endpoints/Governance/DashboardEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Governance/DashboardEndpoint.cs @@ -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(StatusCodes.Status200OK) .Produces(StatusCodes.Status401Unauthorized) .Produces(StatusCodes.Status500InternalServerError) - .WithTags(EndpointTags.Governance); + .WithTags(EndpointTags.Governance) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Governance/GetInstrumentsEndpoint.cs b/PostFundManagement.Api/Endpoints/Governance/GetInstrumentsEndpoint.cs index 2a75b08..8912e95 100644 --- a/PostFundManagement.Api/Endpoints/Governance/GetInstrumentsEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Governance/GetInstrumentsEndpoint.cs @@ -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(StatusCodes.Status200OK) .Produces(StatusCodes.Status500InternalServerError) .Produces(StatusCodes.Status401Unauthorized) - .WithTags(EndpointTags.Governance); + .WithTags(EndpointTags.Governance) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Governance/GetOrganisationEndpoint.cs b/PostFundManagement.Api/Endpoints/Governance/GetOrganisationEndpoint.cs index b8c475a..6937726 100644 --- a/PostFundManagement.Api/Endpoints/Governance/GetOrganisationEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Governance/GetOrganisationEndpoint.cs @@ -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(StatusCodes.Status500InternalServerError) - .WithTags(EndpointTags.Governance); + .WithTags(EndpointTags.Governance) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Governance/GetOrganisationsEndpoint.cs b/PostFundManagement.Api/Endpoints/Governance/GetOrganisationsEndpoint.cs index 6042f3d..0ede350 100644 --- a/PostFundManagement.Api/Endpoints/Governance/GetOrganisationsEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Governance/GetOrganisationsEndpoint.cs @@ -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(StatusCodes.Status200OK) .Produces(StatusCodes.Status500InternalServerError) .Produces(StatusCodes.Status401Unauthorized) - .WithTags(EndpointTags.Governance); + .WithTags(EndpointTags.Governance) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Governance/GetPortfoliosEndpoint.cs b/PostFundManagement.Api/Endpoints/Governance/GetPortfoliosEndpoint.cs index a9fe24c..2876198 100644 --- a/PostFundManagement.Api/Endpoints/Governance/GetPortfoliosEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Governance/GetPortfoliosEndpoint.cs @@ -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(StatusCodes.Status200OK) .Produces(StatusCodes.Status500InternalServerError) .Produces(StatusCodes.Status401Unauthorized) - .WithTags(EndpointTags.Governance); + .WithTags(EndpointTags.Governance) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Governance/GetProgrammesEndpoint.cs b/PostFundManagement.Api/Endpoints/Governance/GetProgrammesEndpoint.cs index 82c8cb5..b373117 100644 --- a/PostFundManagement.Api/Endpoints/Governance/GetProgrammesEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Governance/GetProgrammesEndpoint.cs @@ -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(StatusCodes.Status200OK) .Produces(StatusCodes.Status401Unauthorized) .Produces(StatusCodes.Status500InternalServerError) - .WithTags(EndpointTags.Governance); + .WithTags(EndpointTags.Governance) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Governance/UpdateOrganisationEndpoint.cs b/PostFundManagement.Api/Endpoints/Governance/UpdateOrganisationEndpoint.cs index ab60568..891ff07 100644 --- a/PostFundManagement.Api/Endpoints/Governance/UpdateOrganisationEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Governance/UpdateOrganisationEndpoint.cs @@ -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(), diff --git a/PostFundManagement.Api/Endpoints/Grants/CreateAwardEndpoint.cs b/PostFundManagement.Api/Endpoints/Grants/CreateAwardEndpoint.cs index 0cbd807..6c2d4ab 100644 --- a/PostFundManagement.Api/Endpoints/Grants/CreateAwardEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Grants/CreateAwardEndpoint.cs @@ -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(), diff --git a/PostFundManagement.Api/Endpoints/Grants/CreateBudgetEndpoint.cs b/PostFundManagement.Api/Endpoints/Grants/CreateBudgetEndpoint.cs index 0a9c8f2..b81a6e3 100644 --- a/PostFundManagement.Api/Endpoints/Grants/CreateBudgetEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Grants/CreateBudgetEndpoint.cs @@ -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() => 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(StatusCodes.Status400BadRequest) - .Produces(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(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status500InternalServerError) + .Produces(StatusCodes.Status401Unauthorized) + .WithTags(EndpointTags.Grants); } } diff --git a/PostFundManagement.Api/Endpoints/Grants/CreateContractEndpoint.cs b/PostFundManagement.Api/Endpoints/Grants/CreateContractEndpoint.cs index 4438757..8b54d64 100644 --- a/PostFundManagement.Api/Endpoints/Grants/CreateContractEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Grants/CreateContractEndpoint.cs @@ -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(), diff --git a/PostFundManagement.Api/Endpoints/Grants/ExecuteContractEndpoint.cs b/PostFundManagement.Api/Endpoints/Grants/ExecuteContractEndpoint.cs index 1d95635..de8deaf 100644 --- a/PostFundManagement.Api/Endpoints/Grants/ExecuteContractEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Grants/ExecuteContractEndpoint.cs @@ -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(), diff --git a/PostFundManagement.Api/Endpoints/Grants/GetAwardEndpoint.cs b/PostFundManagement.Api/Endpoints/Grants/GetAwardEndpoint.cs index ff79c77..c7507a4 100644 --- a/PostFundManagement.Api/Endpoints/Grants/GetAwardEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Grants/GetAwardEndpoint.cs @@ -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() => Results.NotFound(), var r => Results.InternalServerError(r.Errors.ToProblems()) }) - .WithDescription("Get award by ID") - .WithName(typeof(GetAwardEndpoint).ToEndpointName()) - .MapToApiVersion(new ApiVersion(1)) - .Produces(StatusCodes.Status200OK) - .Produces(StatusCodes.Status403Forbidden) - .Produces(StatusCodes.Status401Unauthorized) - .Produces(StatusCodes.Status404NotFound) - .Produces(StatusCodes.Status500InternalServerError) - .WithTags(EndpointTags.Grants); + .WithDescription("Get award by ID") + .WithName(typeof(GetAwardEndpoint).ToEndpointName()) + .MapToApiVersion(new ApiVersion(1)) + .Produces(StatusCodes.Status200OK) + .Produces(StatusCodes.Status403Forbidden) + .Produces(StatusCodes.Status401Unauthorized) + .Produces(StatusCodes.Status404NotFound) + .Produces(StatusCodes.Status500InternalServerError) + .WithTags(EndpointTags.Grants) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Grants/GetAwardsEndpoint.cs b/PostFundManagement.Api/Endpoints/Grants/GetAwardsEndpoint.cs index 960d828..9b73556 100644 --- a/PostFundManagement.Api/Endpoints/Grants/GetAwardsEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Grants/GetAwardsEndpoint.cs @@ -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(StatusCodes.Status200OK) - .Produces(StatusCodes.Status500InternalServerError) - .Produces(StatusCodes.Status401Unauthorized) - .WithTags(EndpointTags.Grants); + .WithDescription("Get a list of awards") + .WithName(typeof(GetAwardsEndpoint).ToEndpointName()) + .MapToApiVersion(new ApiVersion(1)) + .Produces(StatusCodes.Status200OK) + .Produces(StatusCodes.Status500InternalServerError) + .Produces(StatusCodes.Status401Unauthorized) + .WithTags(EndpointTags.Grants) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Grants/GetBudgetEndpoint.cs b/PostFundManagement.Api/Endpoints/Grants/GetBudgetEndpoint.cs index 501cfea..7a0ccc9 100644 --- a/PostFundManagement.Api/Endpoints/Grants/GetBudgetEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Grants/GetBudgetEndpoint.cs @@ -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() => Results.NotFound(), var r => Results.InternalServerError(r.Errors.ToProblems()) }) - .WithDescription("Get budget by ID") - .WithName(typeof(GetBudgetEndpoint).ToEndpointName()) - .MapToApiVersion(new ApiVersion(1)) - .Produces(StatusCodes.Status200OK) - .Produces(StatusCodes.Status404NotFound) - .Produces(StatusCodes.Status403Forbidden) - .Produces(StatusCodes.Status401Unauthorized) - .Produces(StatusCodes.Status500InternalServerError) - .WithTags(EndpointTags.Grants); + .WithDescription("Get budget by ID") + .WithName(typeof(GetBudgetEndpoint).ToEndpointName()) + .MapToApiVersion(new ApiVersion(1)) + .Produces(StatusCodes.Status200OK) + .Produces(StatusCodes.Status404NotFound) + .Produces(StatusCodes.Status403Forbidden) + .Produces(StatusCodes.Status401Unauthorized) + .Produces(StatusCodes.Status500InternalServerError) + .WithTags(EndpointTags.Grants) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Grants/GetBudgetsEndpoint.cs b/PostFundManagement.Api/Endpoints/Grants/GetBudgetsEndpoint.cs index 4118bb5..f883860 100644 --- a/PostFundManagement.Api/Endpoints/Grants/GetBudgetsEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Grants/GetBudgetsEndpoint.cs @@ -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(StatusCodes.Status200OK) - .Produces(StatusCodes.Status500InternalServerError) - .Produces(StatusCodes.Status401Unauthorized) - .WithTags(EndpointTags.Grants); + .WithDescription("Get all budgets") + .WithName(typeof(GetBudgetsEndpoint).ToEndpointName()) + .MapToApiVersion(new ApiVersion(1)) + .Produces(StatusCodes.Status200OK) + .Produces(StatusCodes.Status500InternalServerError) + .Produces(StatusCodes.Status401Unauthorized) + .WithTags(EndpointTags.Grants) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Grants/GetContractEndpoint.cs b/PostFundManagement.Api/Endpoints/Grants/GetContractEndpoint.cs index 51c0d8f..82f28a2 100644 --- a/PostFundManagement.Api/Endpoints/Grants/GetContractEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Grants/GetContractEndpoint.cs @@ -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() => Results.NotFound(), var r => Results.InternalServerError(r.Errors.ToProblems()) }) - .WithDescription("Get contract by ID") - .WithName(typeof(GetContractEndpoint).ToEndpointName()) - .MapToApiVersion(new ApiVersion(1)) - .Produces(StatusCodes.Status200OK) - .Produces(StatusCodes.Status404NotFound) - .Produces(StatusCodes.Status403Forbidden) - .Produces(StatusCodes.Status401Unauthorized) - .Produces(StatusCodes.Status500InternalServerError) - .WithTags(EndpointTags.Grants); + .WithDescription("Get contract by ID") + .WithName(typeof(GetContractEndpoint).ToEndpointName()) + .MapToApiVersion(new ApiVersion(1)) + .Produces(StatusCodes.Status200OK) + .Produces(StatusCodes.Status404NotFound) + .Produces(StatusCodes.Status403Forbidden) + .Produces(StatusCodes.Status401Unauthorized) + .Produces(StatusCodes.Status500InternalServerError) + .WithTags(EndpointTags.Grants) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Grants/GetContractsEndpoint.cs b/PostFundManagement.Api/Endpoints/Grants/GetContractsEndpoint.cs index 35b980d..fdc65dc 100644 --- a/PostFundManagement.Api/Endpoints/Grants/GetContractsEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Grants/GetContractsEndpoint.cs @@ -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(StatusCodes.Status200OK) .Produces(StatusCodes.Status500InternalServerError) .Produces(StatusCodes.Status401Unauthorized) - .WithTags(EndpointTags.Grants); + .WithTags(EndpointTags.Grants) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Projects/CreateActivityEndpoint.cs b/PostFundManagement.Api/Endpoints/Projects/CreateActivityEndpoint.cs index e9bcac1..0bca4db 100644 --- a/PostFundManagement.Api/Endpoints/Projects/CreateActivityEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Projects/CreateActivityEndpoint.cs @@ -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(), diff --git a/PostFundManagement.Api/Endpoints/Projects/CreateProjectEndpoint.cs b/PostFundManagement.Api/Endpoints/Projects/CreateProjectEndpoint.cs index 6636b2a..01a7016 100644 --- a/PostFundManagement.Api/Endpoints/Projects/CreateProjectEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Projects/CreateProjectEndpoint.cs @@ -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(), diff --git a/PostFundManagement.Api/Endpoints/Projects/GetActivitiesEndpoint.cs b/PostFundManagement.Api/Endpoints/Projects/GetActivitiesEndpoint.cs index 571b7a8..326f708 100644 --- a/PostFundManagement.Api/Endpoints/Projects/GetActivitiesEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Projects/GetActivitiesEndpoint.cs @@ -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(StatusCodes.Status500InternalServerError) - .WithTags(EndpointTags.Projects); + .WithTags(EndpointTags.Projects) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Projects/GetActivityEndpoint.cs b/PostFundManagement.Api/Endpoints/Projects/GetActivityEndpoint.cs index bf1299c..8fad21c 100644 --- a/PostFundManagement.Api/Endpoints/Projects/GetActivityEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Projects/GetActivityEndpoint.cs @@ -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(StatusCodes.Status500InternalServerError) - .WithTags(EndpointTags.Projects); + .WithTags(EndpointTags.Projects) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Projects/GetMilestoneEndpoint.cs b/PostFundManagement.Api/Endpoints/Projects/GetMilestoneEndpoint.cs index 317c5db..030b52a 100644 --- a/PostFundManagement.Api/Endpoints/Projects/GetMilestoneEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Projects/GetMilestoneEndpoint.cs @@ -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 { diff --git a/PostFundManagement.Api/Endpoints/Projects/GetMilestonesEndpoint.cs b/PostFundManagement.Api/Endpoints/Projects/GetMilestonesEndpoint.cs index 70bc4aa..77feb4c 100644 --- a/PostFundManagement.Api/Endpoints/Projects/GetMilestonesEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Projects/GetMilestonesEndpoint.cs @@ -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(StatusCodes.Status200OK) .Produces(StatusCodes.Status500InternalServerError) .Produces(StatusCodes.Status401Unauthorized) - .WithTags(EndpointTags.Projects); + .WithTags(EndpointTags.Projects) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Projects/GetProjectEndpoint.cs b/PostFundManagement.Api/Endpoints/Projects/GetProjectEndpoint.cs index f8e0e56..7feac9d 100644 --- a/PostFundManagement.Api/Endpoints/Projects/GetProjectEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Projects/GetProjectEndpoint.cs @@ -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(StatusCodes.Status500InternalServerError) - .WithTags(EndpointTags.Projects); + .WithTags(EndpointTags.Projects) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Projects/GetProjectIndicatorsEndpoint.cs b/PostFundManagement.Api/Endpoints/Projects/GetProjectIndicatorsEndpoint.cs index 4c3605f..23536dd 100644 --- a/PostFundManagement.Api/Endpoints/Projects/GetProjectIndicatorsEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Projects/GetProjectIndicatorsEndpoint.cs @@ -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(StatusCodes.Status500InternalServerError) - .WithTags(EndpointTags.Projects); + .WithTags(EndpointTags.Projects) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Projects/GetProjectMilestonesEndpoint.cs b/PostFundManagement.Api/Endpoints/Projects/GetProjectMilestonesEndpoint.cs index 3efcdac..d9067a9 100644 --- a/PostFundManagement.Api/Endpoints/Projects/GetProjectMilestonesEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Projects/GetProjectMilestonesEndpoint.cs @@ -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(StatusCodes.Status500InternalServerError) - .WithTags(EndpointTags.Projects); + .WithTags(EndpointTags.Projects) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Projects/GetProjectRisksEndpoint.cs b/PostFundManagement.Api/Endpoints/Projects/GetProjectRisksEndpoint.cs index 8b1a8b0..ee0dac4 100644 --- a/PostFundManagement.Api/Endpoints/Projects/GetProjectRisksEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Projects/GetProjectRisksEndpoint.cs @@ -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(StatusCodes.Status500InternalServerError) - .WithTags(EndpointTags.Projects); + .WithTags(EndpointTags.Projects) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Projects/GetProjectsEndpoint.cs b/PostFundManagement.Api/Endpoints/Projects/GetProjectsEndpoint.cs index f421d4b..27aa19c 100644 --- a/PostFundManagement.Api/Endpoints/Projects/GetProjectsEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Projects/GetProjectsEndpoint.cs @@ -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(StatusCodes.Status200OK) .Produces(StatusCodes.Status500InternalServerError) .Produces(StatusCodes.Status401Unauthorized) - .WithTags(EndpointTags.Projects); + .WithTags(EndpointTags.Projects) + .CacheOutput(); } } diff --git a/PostFundManagement.Api/Endpoints/Projects/UpdateMilestoneEndpoint.cs b/PostFundManagement.Api/Endpoints/Projects/UpdateMilestoneEndpoint.cs index 584e4f2..9d83e93 100644 --- a/PostFundManagement.Api/Endpoints/Projects/UpdateMilestoneEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Projects/UpdateMilestoneEndpoint.cs @@ -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 { diff --git a/PostFundManagement.Api/Endpoints/Projects/UpdateProjectEndpoint.cs b/PostFundManagement.Api/Endpoints/Projects/UpdateProjectEndpoint.cs index 4b3e640..49d5f29 100644 --- a/PostFundManagement.Api/Endpoints/Projects/UpdateProjectEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Projects/UpdateProjectEndpoint.cs @@ -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() => 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(StatusCodes.Status400BadRequest) - .Produces(StatusCodes.Status500InternalServerError) - .Produces(StatusCodes.Status401Unauthorized) - .WithTags(EndpointTags.Projects); + .WithDescription("Update project details") + .WithName(typeof(UpdateProjectEndpoint).ToEndpointName()) + .MapToApiVersion(new ApiVersion(1)) + .Produces(StatusCodes.Status200OK) + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status500InternalServerError) + .Produces(StatusCodes.Status401Unauthorized) + .WithTags(EndpointTags.Projects); } } diff --git a/PostFundManagement.Api/Endpoints/Projects/UpdateProjectStatusEndpoint.cs b/PostFundManagement.Api/Endpoints/Projects/UpdateProjectStatusEndpoint.cs index 1a15510..a731e62 100644 --- a/PostFundManagement.Api/Endpoints/Projects/UpdateProjectStatusEndpoint.cs +++ b/PostFundManagement.Api/Endpoints/Projects/UpdateProjectStatusEndpoint.cs @@ -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(), diff --git a/PostFundManagement.Api/PostFundManagement.Api.csproj b/PostFundManagement.Api/PostFundManagement.Api.csproj index 10f785b..df1910a 100644 --- a/PostFundManagement.Api/PostFundManagement.Api.csproj +++ b/PostFundManagement.Api/PostFundManagement.Api.csproj @@ -10,6 +10,14 @@ ..\LICENSE + + 1701;1702;AV0029;AV0030; + + + + 1701;1702;AV0029;AV0030; + + diff --git a/PostFundManagement.Application/Abstractions/Services/IExecutionService.cs b/PostFundManagement.Application/Abstractions/Services/IExecutionService.cs new file mode 100644 index 0000000..df89145 --- /dev/null +++ b/PostFundManagement.Application/Abstractions/Services/IExecutionService.cs @@ -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> GetRisksAsync(Pagination pagination, CancellationToken cancellationToken = default); + + ValueTask> GetDisbursementsAsync(Pagination pagination, CancellationToken cancellationToken = default); + + ValueTask CreateRiskAsync(CreateRiskRequest request, Guid userId, CancellationToken cancellationToken = default); + + ValueTask CreateDisbursementAsync(CreateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default); + + ValueTask ApproveDisbursementAsync(string disbursementIdHash, Guid userId, CancellationToken cancellationToken = default); + + ValueTask> GetDisbursementAsync(string disbursementIdHash, CancellationToken cancellationToken = default); + + ValueTask> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken = default); + + ValueTask UpdateRiskAsync(UpdateRiskRequest request, CancellationToken cancellationToken = default); + + ValueTask UpdateDisbursementAsync(UpdateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default); +} diff --git a/PostFundManagement.Application/Abstractions/Services/IGovernanceService.cs b/PostFundManagement.Application/Abstractions/Services/IGovernanceService.cs new file mode 100644 index 0000000..2a5a123 --- /dev/null +++ b/PostFundManagement.Application/Abstractions/Services/IGovernanceService.cs @@ -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> GetProgrammesAsync(CancellationToken cancellationToken = default); + + ValueTask> GetPorfoliosAsync(CancellationToken cancellationToken = default); + + ValueTask> GetOrganisationsAsync(Pagination pagination, CancellationToken cancellationToken = default); + + ValueTask> GetOrganisationAsync(string organisationIdHash, CancellationToken cancellationToken = default); + + ValueTask> GetInstrumentsAsync(CancellationToken cancellationToken = default); + + ValueTask> GetDashboardAsync(CancellationToken cancellationToken = default); + + ValueTask CreateOrganisationAsync(CreateOrganisationRequest request, Guid userId, CancellationToken cancellationToken = default); + + ValueTask> UpdateOrganisationAsync(UpdateOrganisationRequest request, CancellationToken cancellationToken = default); +} diff --git a/PostFundManagement.Application/Abstractions/Services/IGrantsService.cs b/PostFundManagement.Application/Abstractions/Services/IGrantsService.cs new file mode 100644 index 0000000..dda3e2d --- /dev/null +++ b/PostFundManagement.Application/Abstractions/Services/IGrantsService.cs @@ -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> GetContractsAsync(Pagination pagination, CancellationToken cancellationToken = default); + + ValueTask> GetContractAsync(string contractIdHash, CancellationToken cancellationToken = default); + + ValueTask> GetBudgetsAsync(Pagination pagination, CancellationToken cancellationToken = default); + + ValueTask> GetBudgetAsync(string budgetIdHash, CancellationToken cancellationToken = default); + + ValueTask> GetAwardsAsync(Pagination pagination, CancellationToken cancellationToken = default); + + ValueTask> GetAwardAsync(string awardIdHash, CancellationToken cancellationToken = default); + + ValueTask ExecuteContractAsync(ExecuteContractRequest request, Guid userId, CancellationToken cancellationToken = default); + + ValueTask CreateContractAsync(CreateContractRequest request, Guid userId, CancellationToken cancellationToken = default); + + ValueTask CreateBudgetAsync(CreateBudgetRequest request, Guid userId, CancellationToken cancellationToken = default); + + ValueTask CreateAwardAsync(CreateAwardRequest request, Guid userId, CancellationToken cancellationToken = default); +} diff --git a/PostFundManagement.Application/Abstractions/Services/IProjectService.cs b/PostFundManagement.Application/Abstractions/Services/IProjectService.cs new file mode 100644 index 0000000..e833517 --- /dev/null +++ b/PostFundManagement.Application/Abstractions/Services/IProjectService.cs @@ -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 UpdateProjectStatusAsync(UpdateProjectStatusRequest request, Guid userId, CancellationToken cancellationToken = default); + + ValueTask> GetProjectsAsync(Pagination pagination, CancellationToken cancellationToken = default); + + ValueTask> GetProjectAsync(string projectIdHash, CancellationToken cancellationToken = default); + + ValueTask> GetActivitiesAsync(string projectIdHash, CancellationToken cancellationToken = default); + + ValueTask CreateProjectAsync(CreateProjectRequest request, Guid userId, CancellationToken cancellationToken = default); + + ValueTask CreateActivityAsync(CreateActivityRequest request, Guid userId, CancellationToken cancellationToken = default); + + ValueTask> GetProjectMilestonesAsync(string projectIdHash, CancellationToken cancellationToken = default); + + ValueTask> GetProjectIndicatorsAsync(string projectIdHash, CancellationToken cancellationToken = default); + + ValueTask> GetMilestoneAsync(string milestoneIdHash, CancellationToken cancellationToken = default); + + ValueTask> GetMilestonesAsync(Pagination pagination, CancellationToken cancellationToken = default); + + ValueTask UpdateMilestoneAsync(UpdateMilestoneRequest request, Guid userId, CancellationToken cancellationToken = default); + + ValueTask UpdateProjectAsync(UpdateProjectRequest request, Guid userId, CancellationToken cancellationToken = default); + + ValueTask> GetActivityAsync(string activityIdHash, CancellationToken cancellationToken = default); + + ValueTask> GetProjectRisksAsync(string projectIdHash, CancellationToken cancellationToken = default); +} diff --git a/PostFundManagement.Application/Extensions/General.cs b/PostFundManagement.Application/Extensions/General.cs index fb50e28..282a08e 100644 --- a/PostFundManagement.Application/Extensions/General.cs +++ b/PostFundManagement.Application/Extensions/General.cs @@ -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(); - services.Decorate(); + public static string ToJson(this TValue obj) where TValue : class => JsonSerializer.Serialize(obj); - services.AddScoped(); - services.Decorate(); - - services.AddScoped(); - services.Decorate(); - - services.AddScoped(); - services.Decorate(); - - 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(this string json) where TValue : class => JsonSerializer.Deserialize(json)!; public static Guid GetUserId(this HttpContext context) => (Guid)context.Items[Domain.Extensions.Constants.UserIdItemKey]!; diff --git a/PostFundManagement.Application/Extensions/Services.cs b/PostFundManagement.Application/Extensions/Services.cs new file mode 100644 index 0000000..d93fd2e --- /dev/null +++ b/PostFundManagement.Application/Extensions/Services.cs @@ -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(); + services.Decorate(); + + services.AddScoped(); + services.Decorate(); + + services.AddScoped(); + services.Decorate(); + + services.AddScoped(); + services.Decorate(); + + services.AddScoped(); + services.Decorate(); + + services.AddScoped(); + services.Decorate(); + + services.AddScoped(); + services.Decorate(); + + services.AddScoped(); + services.Decorate(); + + 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; + } +} diff --git a/PostFundManagement.Application/Services/Communications/CommunicationsCacheService.cs b/PostFundManagement.Application/Services/Communications/CommunicationsCacheService.cs index 66920ee..a87e48b 100644 --- a/PostFundManagement.Application/Services/Communications/CommunicationsCacheService.cs +++ b/PostFundManagement.Application/Services/Communications/CommunicationsCacheService.cs @@ -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> GetApplicantInviteAsync(Guid userId, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(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()); + })); public async ValueTask> GetInvitesAsync(Pagination pagination, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(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()); + })); public async ValueTask> SendInviteAsync(InviteRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.SendInviteAsync(request, userId, cancellationToken); diff --git a/PostFundManagement.Application/Services/Evidence/EvidenceCacheService.cs b/PostFundManagement.Application/Services/Evidence/EvidenceCacheService.cs index a9db1fa..126b601 100644 --- a/PostFundManagement.Application/Services/Evidence/EvidenceCacheService.cs +++ b/PostFundManagement.Application/Services/Evidence/EvidenceCacheService.cs @@ -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 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> GetEvidenceAsync(string evidenceId, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(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()); + })); public async ValueTask> GetEvidenceFilesAsync(Pagination pagination, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(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()); + })); public async ValueTask> GetIndicatorAsync(string indicatorId, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(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()); + })); public async ValueTask> GetIndicatorsAsync(Pagination pagination, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(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()); + })); public async ValueTask> GetMilestoneEvidencesAsync(string milestoneIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(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()); + })); public async ValueTask> GetProjectEvidencesAsync(string projectIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(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()); + })); public async ValueTask RecordIndicatorActualAmountAsync(string indicatorIdHash, decimal amount, Guid userId, CancellationToken cancellationToken = default) => await service.RecordIndicatorActualAmountAsync(indicatorIdHash, amount, userId, cancellationToken); diff --git a/PostFundManagement.Application/Services/Execution/ExecutionCacheService.cs b/PostFundManagement.Application/Services/Execution/ExecutionCacheService.cs new file mode 100644 index 0000000..5dbbacd --- /dev/null +++ b/PostFundManagement.Application/Services/Execution/ExecutionCacheService.cs @@ -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 ApproveDisbursementAsync(string disbursementIdHash, Guid userId, CancellationToken cancellationToken = default) => + await service.ApproveDisbursementAsync(disbursementIdHash, userId, cancellationToken); + + public async ValueTask CreateDisbursementAsync(CreateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default) => + await service.CreateDisbursementAsync(request, userId, cancellationToken); + + public async ValueTask CreateRiskAsync(CreateRiskRequest request, Guid userId, CancellationToken cancellationToken = default) => + await service.CreateRiskAsync(request, userId, cancellationToken); + + public async ValueTask> GetDisbursementAsync(string disbursementIdHash, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetDisbursementsAsync(Pagination pagination, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetRisksAsync(Pagination pagination, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask UpdateDisbursementAsync(UpdateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default) => + await service.UpdateDisbursementAsync(request, userId, cancellationToken); + + public async ValueTask UpdateRiskAsync(UpdateRiskRequest request, CancellationToken cancellationToken = default) => + await service.UpdateRiskAsync(request, cancellationToken); +} diff --git a/PostFundManagement.Application/Services/Execution/ExecutionService.cs b/PostFundManagement.Application/Services/Execution/ExecutionService.cs index db5b0b1..8d122fd 100644 --- a/PostFundManagement.Application/Services/Execution/ExecutionService.cs +++ b/PostFundManagement.Application/Services/Execution/ExecutionService.cs @@ -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 contextFactory, HashService hashService) : IService +public sealed class ExecutionService(IDbContextFactory contextFactory, HashService hashService) : IExecutionService { public async ValueTask> GetRisksAsync(Pagination pagination, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => @@ -120,7 +120,7 @@ public sealed class ExecutionService(IDbContextFactory con : Result.Fail(NotFoundError.New); })); - public async ValueTask> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken) => + public async ValueTask> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { var decodeResult = hashService.DecodeLongIdHash(riskIdHash); @@ -139,7 +139,7 @@ public sealed class ExecutionService(IDbContextFactory con : Result.Fail(NotFoundError.New); })); - public async ValueTask UpdateRiskAsync(UpdateRiskRequest request, CancellationToken cancellationToken) => + public async ValueTask UpdateRiskAsync(UpdateRiskRequest request, CancellationToken cancellationToken = default) => await Result.Try((Func>)(async () => { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); @@ -155,7 +155,7 @@ public sealed class ExecutionService(IDbContextFactory con return Result.FailIf(changedTotal <= 0, UpdateError.New); })); - public async ValueTask UpdateDisbursementAsync(UpdateDisbursementRequest request, Guid userId, CancellationToken cancellationToken) => + public async ValueTask UpdateDisbursementAsync(UpdateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default) => await Result.Try((Func>)(async () => { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); diff --git a/PostFundManagement.Application/Services/Governance/GovernanceCacheService.cs b/PostFundManagement.Application/Services/Governance/GovernanceCacheService.cs new file mode 100644 index 0000000..6914c79 --- /dev/null +++ b/PostFundManagement.Application/Services/Governance/GovernanceCacheService.cs @@ -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 CreateOrganisationAsync(CreateOrganisationRequest request, Guid userId, CancellationToken cancellationToken = default) => + await service.CreateOrganisationAsync(request, userId, cancellationToken); + + public async ValueTask> GetDashboardAsync(CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetInstrumentsAsync(CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetOrganisationAsync(string organisationIdHash, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetOrganisationsAsync(Pagination pagination, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetPorfoliosAsync(CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetProgrammesAsync(CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> UpdateOrganisationAsync(UpdateOrganisationRequest request, CancellationToken cancellationToken = default) => + await service.UpdateOrganisationAsync(request, cancellationToken); +} diff --git a/PostFundManagement.Application/Services/Governance/GovernanceService.cs b/PostFundManagement.Application/Services/Governance/GovernanceService.cs index f1e03fe..db0b4c8 100644 --- a/PostFundManagement.Application/Services/Governance/GovernanceService.cs +++ b/PostFundManagement.Application/Services/Governance/GovernanceService.cs @@ -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 contextFactory, HashService hashService) : IService +public sealed class GovernanceService(IDbContextFactory contextFactory, HashService hashService) : IGovernanceService { public async ValueTask> GetProgrammesAsync(CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => diff --git a/PostFundManagement.Application/Services/Grants/GrantsCacheService.cs b/PostFundManagement.Application/Services/Grants/GrantsCacheService.cs new file mode 100644 index 0000000..979c1e0 --- /dev/null +++ b/PostFundManagement.Application/Services/Grants/GrantsCacheService.cs @@ -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 CreateAwardAsync(CreateAwardRequest request, Guid userId, CancellationToken cancellationToken = default) => + await service.CreateAwardAsync(request, userId, cancellationToken); + + public async ValueTask CreateBudgetAsync(CreateBudgetRequest request, Guid userId, CancellationToken cancellationToken = default) => + await service.CreateBudgetAsync(request, userId, cancellationToken); + + public async ValueTask CreateContractAsync(CreateContractRequest request, Guid userId, CancellationToken cancellationToken = default) => + await service.CreateContractAsync(request, userId, cancellationToken); + + public async ValueTask ExecuteContractAsync(ExecuteContractRequest request, Guid userId, CancellationToken cancellationToken = default) => + await service.ExecuteContractAsync(request, userId, cancellationToken); + + public async ValueTask> GetAwardAsync(string awardIdHash, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetAwardsAsync(Pagination pagination, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetBudgetAsync(string budgetIdHash, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetBudgetsAsync(Pagination pagination, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetContractAsync(string contractIdHash, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetContractsAsync(Pagination pagination, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); +} diff --git a/PostFundManagement.Application/Services/Grants/GrantsService.cs b/PostFundManagement.Application/Services/Grants/GrantsService.cs index c191589..9c4061f 100644 --- a/PostFundManagement.Application/Services/Grants/GrantsService.cs +++ b/PostFundManagement.Application/Services/Grants/GrantsService.cs @@ -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 contextFactory, HashService hashService) : IService +public sealed class GrantsService(IDbContextFactory contextFactory, HashService hashService) : IGrantsService { public async ValueTask> GetContractsAsync(Pagination pagination, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => diff --git a/PostFundManagement.Application/Services/Projects/ProjectCacheService.cs b/PostFundManagement.Application/Services/Projects/ProjectCacheService.cs new file mode 100644 index 0000000..3a57158 --- /dev/null +++ b/PostFundManagement.Application/Services/Projects/ProjectCacheService.cs @@ -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 CreateActivityAsync(CreateActivityRequest request, Guid userId, CancellationToken cancellationToken = default) => + await service.CreateActivityAsync(request, userId, cancellationToken); + + public async ValueTask CreateProjectAsync(CreateProjectRequest request, Guid userId, CancellationToken cancellationToken = default) => + await service.CreateProjectAsync(request, userId, cancellationToken); + + public async ValueTask> GetActivitiesAsync(string projectIdHash, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetActivityAsync(string activityIdHash, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetMilestoneAsync(string milestoneIdHash, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetMilestonesAsync(Pagination pagination, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetProjectAsync(string projectIdHash, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetProjectIndicatorsAsync(string projectIdHash, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetProjectMilestonesAsync(string projectIdHash, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetProjectRisksAsync(string projectIdHash, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask> GetProjectsAsync(Pagination pagination, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(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()); + })); + + public async ValueTask UpdateMilestoneAsync(UpdateMilestoneRequest request, Guid userId, CancellationToken cancellationToken = default) => + await service.UpdateMilestoneAsync(request, userId, cancellationToken); + + public async ValueTask UpdateProjectAsync(UpdateProjectRequest request, Guid userId, CancellationToken cancellationToken = default) => + await service.UpdateProjectAsync(request, userId, cancellationToken); + + public async ValueTask UpdateProjectStatusAsync(UpdateProjectStatusRequest request, Guid userId, CancellationToken cancellationToken = default) => + await service.UpdateProjectStatusAsync(request, userId, cancellationToken); +} diff --git a/PostFundManagement.Application/Services/Projects/ProjectService.cs b/PostFundManagement.Application/Services/Projects/ProjectService.cs index be0e319..22be636 100644 --- a/PostFundManagement.Application/Services/Projects/ProjectService.cs +++ b/PostFundManagement.Application/Services/Projects/ProjectService.cs @@ -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 contextFactory, HashService hashService) : IService +public sealed class ProjectService(IDbContextFactory contextFactory, HashService hashService) : IProjectService { public async ValueTask UpdateProjectStatusAsync(UpdateProjectStatusRequest request, Guid userId, CancellationToken cancellationToken = default) => await Result.Try((Func>)(async () => @@ -179,7 +179,7 @@ public sealed class ProjectService(IDbContextFactory conte return Result.Ok(evidences.Select(e => e.Map()).ToArray()); })); - public async ValueTask> GetMilestoneAsync(string milestoneIdHash, CancellationToken cancellationToken) => + public async ValueTask> GetMilestoneAsync(string milestoneIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { var decodeResult = hashService.DecodeLongIdHash(milestoneIdHash); @@ -211,7 +211,7 @@ public sealed class ProjectService(IDbContextFactory conte return Result.Ok(milestones.Select(i => i.Map()).ToArray()); })); - public async ValueTask UpdateMilestoneAsync(UpdateMilestoneRequest request, Guid userId, CancellationToken cancellationToken) => + public async ValueTask UpdateMilestoneAsync(UpdateMilestoneRequest request, Guid userId, CancellationToken cancellationToken = default) => await Result.Try((Func>)(async () => { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); @@ -228,7 +228,7 @@ public sealed class ProjectService(IDbContextFactory conte return Result.FailIf(changedTotal <= 0, UpdateError.New); })); - public async ValueTask UpdateProjectAsync(UpdateProjectRequest request, Guid userId, CancellationToken cancellationToken) => + public async ValueTask UpdateProjectAsync(UpdateProjectRequest request, Guid userId, CancellationToken cancellationToken = default) => await Result.Try((Func>)(async () => { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); @@ -247,7 +247,7 @@ public sealed class ProjectService(IDbContextFactory conte return Result.FailIf(changedTotal <= 0, UpdateError.New); })); - public async ValueTask> GetActivityAsync(string activityIdHash, CancellationToken cancellationToken) => + public async ValueTask> GetActivityAsync(string activityIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { var decodeResult = hashService.DecodeLongIdHash(activityIdHash); diff --git a/PostFundManagement.Application/Services/Users/UserCacheService.cs b/PostFundManagement.Application/Services/Users/UserCacheService.cs index 41c533b..0f83137 100644 --- a/PostFundManagement.Application/Services/Users/UserCacheService.cs +++ b/PostFundManagement.Application/Services/Users/UserCacheService.cs @@ -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(cached)!; - - return Result.Ok(restored); + return Result.Ok(cached.FromJson()); })); public async ValueTask> 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(cached)!; - - return Result.Ok(restored); + return Result.Ok(cached.FromJson()); })); public async ValueTask SyncUserAsync(Guid userId, string email, CancellationToken cancellationToken = default) =>