Compare commits
26
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea0e4eb018 | ||
|
|
9ebbafb840 | ||
|
|
f3863c785d | ||
|
|
9874eac65d | ||
|
|
2b8edd05e3 | ||
|
|
edbae6defb | ||
|
|
b3e884336d | ||
|
|
1b0ceb8ea9 | ||
|
|
d779e4152e | ||
|
|
9e611cb79c | ||
|
|
b99ebf657c | ||
|
|
99ab5b2ce6 | ||
|
|
a15b25248d | ||
|
|
66f720a20b | ||
|
|
81c111c3c3 | ||
|
|
415aa30cf7 | ||
|
|
72ea20a2de | ||
|
|
15661ce8cb | ||
|
|
e274c33592 | ||
|
|
a218b19875 | ||
|
|
0a1378fe25 | ||
|
|
6719699689 | ||
|
|
8ea014e4fb | ||
|
|
9728459223 | ||
|
|
a73f53a0d9 | ||
|
|
9f76b203e3 |
@@ -1,5 +1,5 @@
|
|||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Services.Communications;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,9 +14,9 @@ public sealed class GetApplicantInviteEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/communications/invites/applicant/{userId:Guid}", async (Guid userId, CommunicationsService service,
|
builder.MapGet("api/communications/invites/applicant/{applicantUserId:Guid}", async (Guid applicantUserId, ICommunicationsService service,
|
||||||
HttpContext context, CancellationToken cancellationToken = default) =>
|
HttpContext context, CancellationToken cancellationToken = default) =>
|
||||||
await service.GetApplicantInviteAsync(userId, cancellationToken) switch
|
await service.GetApplicantInviteAsync(applicantUserId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true, Value: var invite } => Results.Ok(invite),
|
{ IsSuccess: true, Value: var invite } => Results.Ok(invite),
|
||||||
var r when r.HasError<NotFoundError>() => Results.NotFound(),
|
var r when r.HasError<NotFoundError>() => Results.NotFound(),
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Extensions;
|
||||||
|
using PostFundManagement.Domain.Abstractions;
|
||||||
|
using PostFundManagement.Domain.Errors;
|
||||||
|
using PostFundManagement.Domain.Extensions;
|
||||||
|
using PostFundManagement.Domain.Models;
|
||||||
|
using PostFundManagement.Domain.Security;
|
||||||
|
using Problems = Microsoft.AspNetCore.Mvc.ProblemDetails;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Api.Endpoints.Communications;
|
||||||
|
|
||||||
|
[ApiVersionTarget(1)]
|
||||||
|
public sealed class GetApplicantInvitesEndpoint : IEndpoint
|
||||||
|
{
|
||||||
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
|
{
|
||||||
|
builder.MapGet("api/communications/invites/{applicantUserId:Guid}", async (Guid applicantUserId, ICommunicationsService service,
|
||||||
|
HttpContext context, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.GetApplicantInvitesAsync(applicantUserId, cancellationToken) switch
|
||||||
|
{
|
||||||
|
{ IsSuccess: true, Value: var invite } => Results.Ok(invite),
|
||||||
|
var r when r.HasError<NotFoundError>() => Results.NotFound(),
|
||||||
|
var r => Results.InternalServerError(r.Errors.ToProblems()),
|
||||||
|
})
|
||||||
|
.WithDescription("Gets an applicant's invite list")
|
||||||
|
.WithName(typeof(GetApplicantInvitesEndpoint).ToEndpointName())
|
||||||
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
|
.Produces<Invite[]>(StatusCodes.Status200OK)
|
||||||
|
.Produces(StatusCodes.Status404NotFound)
|
||||||
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
|
.WithTags(EndpointTags.Communications)
|
||||||
|
.CacheOutput();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Communications;
|
|
||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -15,7 +15,7 @@ public sealed class GetInvitesEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/communications/invites/{page:int}/{pageSize:int}", async (CommunicationsService service,
|
builder.MapGet("api/communications/invites/{page:int}/{pageSize:int}", async (ICommunicationsService service,
|
||||||
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
|
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
|
||||||
await service.GetInvitesAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
await service.GetInvitesAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Communications;
|
using PostFundManagement.Application.Services.Communications;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
@@ -15,7 +16,7 @@ public sealed class SendInviteEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPost("api/communications/invite", async (InviteRequest request,
|
builder.MapPost("api/communications/invite", async (InviteRequest request,
|
||||||
HttpContext context, CommunicationsService service, CancellationToken cancellationToken = default) =>
|
HttpContext context, ICommunicationsService service, CancellationToken cancellationToken = default) =>
|
||||||
await service.SendInviteAsync(request, context.GetUserId(), cancellationToken) switch
|
await service.SendInviteAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true, Value: var invite } => Results.Ok(invite),
|
{ IsSuccess: true, Value: var invite } => Results.Ok(invite),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Evidence;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -13,7 +13,7 @@ public class CreateEvidenceEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPut("api/evidence/file", async (HttpRequest request, EvidenceService service,
|
builder.MapPut("api/evidence/file", async (HttpRequest request, IEvidenceService service,
|
||||||
CancellationToken cancellationToken = default) =>
|
CancellationToken cancellationToken = default) =>
|
||||||
{
|
{
|
||||||
var userId = request.HttpContext.GetUserId();
|
var userId = request.HttpContext.GetUserId();
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Evidence;
|
using PostFundManagement.Application.Services.Evidence;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
@@ -14,7 +15,7 @@ public class CreateIndicatorEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPost("api/evidence/indicators", async (CreateIndicatorRequest request, HttpContext context,
|
builder.MapPost("api/evidence/indicators", async (CreateIndicatorRequest request, HttpContext context,
|
||||||
EvidenceService service, CancellationToken cancellationToken = default) =>
|
IEvidenceService service, CancellationToken cancellationToken = default) =>
|
||||||
await service.CreateIndicatorAsync(request, context.GetUserId(), cancellationToken) switch
|
await service.CreateIndicatorAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } => Results.Ok(),
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Evidence;
|
using PostFundManagement.Application.Services.Evidence;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
@@ -14,7 +15,7 @@ public class CreateMilestoneEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPost("api/evidence/milestones", async (CreateMilestoneRequest request, HttpContext context,
|
builder.MapPost("api/evidence/milestones", async (CreateMilestoneRequest request, HttpContext context,
|
||||||
EvidenceService service, CancellationToken cancellationToken = default) =>
|
IEvidenceService service, CancellationToken cancellationToken = default) =>
|
||||||
await service.CreateMilestoneAsync(request, context.GetUserId(), cancellationToken) switch
|
await service.CreateMilestoneAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } => Results.Ok(),
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Services.Evidence;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -13,7 +13,7 @@ public sealed class GetEvidenceEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/evidence/{evidenceId}", async (string evidenceId, EvidenceService service,
|
builder.MapGet("api/evidence/{evidenceId}", async (string evidenceId, IEvidenceService service,
|
||||||
CancellationToken cancellationToken = default) =>
|
CancellationToken cancellationToken = default) =>
|
||||||
await service.GetEvidenceAsync(evidenceId, cancellationToken) switch
|
await service.GetEvidenceAsync(evidenceId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Evidence;
|
|
||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -13,7 +13,7 @@ public class GetEvidenceFilesEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/evidence/files/{page:int}/{pageSize:int}", async (EvidenceService service,
|
builder.MapGet("api/evidence/files/{page:int}/{pageSize:int}", async (IEvidenceService service,
|
||||||
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
|
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
|
||||||
await service.GetEvidenceFilesAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
await service.GetEvidenceFilesAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Services.Evidence;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public sealed class GetIndicatorEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/evidence/indicators/{indicatorId}", async (string indicatorId, EvidenceService service,
|
builder.MapGet("api/evidence/indicators/{indicatorId}", async (string indicatorId, IEvidenceService service,
|
||||||
CancellationToken cancellationToken = default) =>
|
CancellationToken cancellationToken = default) =>
|
||||||
await service.GetIndicatorAsync(indicatorId, cancellationToken) switch
|
await service.GetIndicatorAsync(indicatorId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
@@ -31,6 +31,7 @@ public sealed class GetIndicatorEndpoint : IEndpoint
|
|||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.Produces(StatusCodes.Status403Forbidden)
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.WithTags(EndpointTags.Evidence);
|
.WithTags(EndpointTags.Evidence)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Evidence;
|
|
||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public class GetIndicatorsEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/evidence/indicators/{page:int}/{pageSize:int}", async (EvidenceService service,
|
builder.MapGet("api/evidence/indicators/{page:int}/{pageSize:int}", async (IEvidenceService service,
|
||||||
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
|
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
|
||||||
await service.GetIndicatorsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
await service.GetIndicatorsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
||||||
{
|
{
|
||||||
@@ -27,6 +27,7 @@ public class GetIndicatorsEndpoint : IEndpoint
|
|||||||
.Produces<Indicator[]>(StatusCodes.Status200OK)
|
.Produces<Indicator[]>(StatusCodes.Status200OK)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.WithTags(EndpointTags.Evidence);
|
.WithTags(EndpointTags.Evidence)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Evidence;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -13,7 +13,7 @@ public class GetMilestoneEvidenceEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/evidence/milestone/{milestoneId}", async (string milestoneId, EvidenceService service,
|
builder.MapGet("api/evidence/milestone/{milestoneId}", async (string milestoneId, IEvidenceService service,
|
||||||
CancellationToken cancellationToken = default) =>
|
CancellationToken cancellationToken = default) =>
|
||||||
await service.GetMilestoneEvidencesAsync(milestoneId, cancellationToken) switch
|
await service.GetMilestoneEvidencesAsync(milestoneId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Evidence;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -13,7 +13,7 @@ public class GetProjectEvidenceEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/evidence/milestone/{projectId}", async (string projectId, EvidenceService service,
|
builder.MapGet("api/evidence/{projectId}", async (string projectId, IEvidenceService service,
|
||||||
CancellationToken cancellationToken = default) =>
|
CancellationToken cancellationToken = default) =>
|
||||||
await service.GetProjectEvidencesAsync(projectId, cancellationToken) switch
|
await service.GetProjectEvidencesAsync(projectId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Evidence;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public class RecordIndicatorAmountEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPost("api/evidence/indicators/{indicatorId}/actuals/{actualAmount:decimal}", async (string indicatorId, decimal actualAmount,
|
builder.MapPost("api/evidence/indicators/{indicatorId}/actuals/{actualAmount:decimal}", async (string indicatorId, decimal actualAmount,
|
||||||
HttpContext context, EvidenceService service, CancellationToken cancellationToken = default) =>
|
HttpContext context, IEvidenceService service, CancellationToken cancellationToken = default) =>
|
||||||
await service.RecordIndicatorActualAmountAsync(indicatorId, actualAmount, context.GetUserId(), cancellationToken) switch
|
await service.RecordIndicatorActualAmountAsync(indicatorId, actualAmount, context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } => Results.Ok(),
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Evidence;
|
using PostFundManagement.Application.Services.Evidence;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
@@ -13,19 +14,19 @@ public sealed class UpdateEvidenceEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPut("api/evidence", async (UpdateEvidenceRequest request, HttpContext context, EvidenceService service,
|
builder.MapPut("api/evidence", async (UpdateEvidenceRequest request, HttpContext context, IEvidenceService service,
|
||||||
CancellationToken cancellationToken = default) =>
|
CancellationToken cancellationToken = default) =>
|
||||||
await service.UpdateEvidenceAsync(request, context.GetUserId(), cancellationToken) switch
|
await service.UpdateEvidenceAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } => Results.Ok(),
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
var r when r.HasError<IdDecodeError>() => Results.Forbid(),
|
var r when r.HasError<NotFoundError>() => Results.NotFound(),
|
||||||
var r when r.HasError<UpdateError>() => Results.BadRequest(r.Errors.ToProblems()),
|
var r when r.HasError<UpdateError>() => Results.BadRequest(r.Errors.ToProblems()),
|
||||||
var r => Results.InternalServerError(r.Errors.ToProblems())
|
var r => Results.InternalServerError(r.Errors.ToProblems())
|
||||||
})
|
})
|
||||||
.WithDescription("Updates a specific evidence record metadata")
|
.WithDescription("Updates a specific evidence record metadata")
|
||||||
.WithName(typeof(UpdateEvidenceEndpoint).ToEndpointName())
|
.WithName(typeof(UpdateEvidenceEndpoint).ToEndpointName())
|
||||||
.MapToApiVersion(new ApiVersion(1))
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
.Produces<Domain.Models.Evidence>(StatusCodes.Status200OK)
|
.Produces(StatusCodes.Status200OK)
|
||||||
.Produces(StatusCodes.Status404NotFound)
|
.Produces(StatusCodes.Status404NotFound)
|
||||||
.Produces(StatusCodes.Status403Forbidden)
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Execution;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public class ApproveDisbursementEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPost("api/execution/disbursements/{disbursementId}/approve", async (string disbursementId,
|
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
|
await service.ApproveDisbursementAsync(disbursementId, context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } => Results.Ok(),
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Execution;
|
using PostFundManagement.Application.Services.Execution;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
@@ -14,7 +15,7 @@ public class CreateDisbursementEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPost("api/execution/disbursements", async (CreateDisbursementRequest request,
|
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
|
await service.CreateDisbursementAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } => Results.Ok(),
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Execution;
|
using PostFundManagement.Application.Services.Execution;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
@@ -13,7 +14,7 @@ public class CreateRiskEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
HttpContext context, CancellationToken cancellationToken = default) =>
|
||||||
await service.CreateRiskAsync(request, context.GetUserId(), cancellationToken) switch
|
await service.CreateRiskAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Services.Execution;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public sealed class GetDisbursementEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
CancellationToken cancellationToken = default) =>
|
||||||
await service.GetDisbursementAsync(disbursementIdHash: disbursementId, cancellationToken) switch
|
await service.GetDisbursementAsync(disbursementIdHash: disbursementId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
@@ -31,6 +31,7 @@ public sealed class GetDisbursementEndpoint : IEndpoint
|
|||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.Produces<Problems>(StatusCodes.Status400BadRequest)
|
.Produces<Problems>(StatusCodes.Status400BadRequest)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.WithTags(EndpointTags.Execution);
|
.WithTags(EndpointTags.Execution)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Execution;
|
|
||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public class GetDisbursementsEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
int page = 1, int pageSize = 10, CancellationToken cancellationToken = default) =>
|
||||||
await service.GetDisbursementsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
await service.GetDisbursementsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
||||||
{
|
{
|
||||||
@@ -28,6 +28,7 @@ public class GetDisbursementsEndpoint : IEndpoint
|
|||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.Produces(StatusCodes.Status404NotFound)
|
.Produces(StatusCodes.Status404NotFound)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.WithTags(EndpointTags.Execution);
|
.WithTags(EndpointTags.Execution)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Services.Execution;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public sealed class GetRiskEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
CancellationToken cancellationToken = default) =>
|
||||||
await service.GetRiskAsync(riskIdHash: riskId, cancellationToken) switch
|
await service.GetRiskAsync(riskIdHash: riskId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
@@ -30,6 +30,7 @@ public sealed class GetRiskEndpoint : IEndpoint
|
|||||||
.Produces(StatusCodes.Status404NotFound)
|
.Produces(StatusCodes.Status404NotFound)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.WithTags(EndpointTags.Execution);
|
.WithTags(EndpointTags.Execution)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Execution;
|
|
||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -13,7 +13,7 @@ public class GetRisksEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
|
||||||
await service.GetRisksAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
await service.GetRisksAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
||||||
{
|
{
|
||||||
@@ -26,6 +26,7 @@ public class GetRisksEndpoint : IEndpoint
|
|||||||
.Produces(StatusCodes.Status200OK)
|
.Produces(StatusCodes.Status200OK)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.WithTags(EndpointTags.Execution);
|
.WithTags(EndpointTags.Execution)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Execution;
|
using PostFundManagement.Application.Services.Execution;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
@@ -14,7 +15,7 @@ public sealed class UpdateDisbursementEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPut("api/execution/disbursements", async (UpdateDisbursementRequest request, HttpContext context,
|
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
|
await service.UpdateDisbursementAsync(request, userId: context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } => Results.Ok(),
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Execution;
|
using PostFundManagement.Application.Services.Execution;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
@@ -14,7 +15,7 @@ public sealed class UpdateRiskEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPut("api/execution/risks", async (UpdateRiskRequest request,
|
builder.MapPut("api/execution/risks", async (UpdateRiskRequest request,
|
||||||
ExecutionService service, CancellationToken cancellationToken = default) =>
|
IExecutionService service, CancellationToken cancellationToken = default) =>
|
||||||
await service.UpdateRiskAsync(request, cancellationToken) switch
|
await service.UpdateRiskAsync(request, cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } => Results.Ok(),
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Governance;
|
using PostFundManagement.Application.Services.Governance;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
@@ -14,7 +15,7 @@ public sealed class CreateOrganisationEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPost("api/governance/organisations", async (CreateOrganisationRequest request, HttpContext context,
|
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
|
await service.CreateOrganisationAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } => Results.Ok(),
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
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;
|
||||||
|
using PostFundManagement.Domain.Security;
|
||||||
|
using Problems = Microsoft.AspNetCore.Mvc.ProblemDetails;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Api.Endpoints.Governance;
|
||||||
|
|
||||||
|
[ApiVersionTarget(1)]
|
||||||
|
public sealed class CreatePortfolioEndpoint : IEndpoint
|
||||||
|
{
|
||||||
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
|
{
|
||||||
|
builder.MapPost("api/governance/organisations/portfolio", async (CreatePortfolioRequest request, HttpContext context,
|
||||||
|
IGovernanceService service, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.CreatePortfolioAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
|
{
|
||||||
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
var r when r.HasError<CreateError>() => Results.BadRequest(r.Errors.ToProblems()),
|
||||||
|
var r when r.HasError<NotFoundError>() => Results.NotFound(r.Errors.ToProblems()),
|
||||||
|
var r when r.HasError<ValidationError>() => Results.BadRequest(r.Errors.ToProblems()),
|
||||||
|
var r => Results.InternalServerError(r.Errors.ToProblems())
|
||||||
|
})
|
||||||
|
.WithDescription("Create a new organization portfolio")
|
||||||
|
.WithName(typeof(CreatePortfolioEndpoint).ToEndpointName())
|
||||||
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
|
.Produces(StatusCodes.Status200OK)
|
||||||
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
|
.Produces<Problems>(StatusCodes.Status404NotFound)
|
||||||
|
.Produces<Problems>(StatusCodes.Status400BadRequest)
|
||||||
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
|
.WithTags(EndpointTags.Governance);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Governance;
|
using PostFundManagement.Application.Services.Governance;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
@@ -12,7 +13,7 @@ public class DashboardEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/governance/dashboard", async (GovernanceService service,
|
builder.MapGet("api/governance/dashboard", async (IGovernanceService service,
|
||||||
CancellationToken cancellationToken = default) =>
|
CancellationToken cancellationToken = default) =>
|
||||||
await service.GetDashboardAsync(cancellationToken) switch
|
await service.GetDashboardAsync(cancellationToken) switch
|
||||||
{
|
{
|
||||||
@@ -25,6 +26,7 @@ public class DashboardEndpoint : IEndpoint
|
|||||||
.Produces<Dashboard>(StatusCodes.Status200OK)
|
.Produces<Dashboard>(StatusCodes.Status200OK)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.WithTags(EndpointTags.Governance);
|
.WithTags(EndpointTags.Governance)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Governance;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
using PostFundManagement.Domain.Models;
|
using PostFundManagement.Domain.Models;
|
||||||
using PostFundManagement.Domain.Security;
|
using PostFundManagement.Domain.Security;
|
||||||
@@ -13,19 +14,22 @@ public class GetInstrumentsEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/governance/instruments", async (GovernanceService service,
|
builder.MapGet("api/governance/instruments/{programmeId}", async (string programmeId, IGovernanceService service,
|
||||||
CancellationToken cancellationToken = default) =>
|
CancellationToken cancellationToken = default) =>
|
||||||
await service.GetInstrumentsAsync(cancellationToken) switch
|
await service.GetInstrumentsAsync(programmeId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true, Value: var instrumenrs } => Results.Ok(instrumenrs),
|
{ IsSuccess: true, Value: var instrumenrs } => Results.Ok(instrumenrs),
|
||||||
|
var r when r.HasError<IdDecodeError>() => Results.Forbid(),
|
||||||
var r => Results.InternalServerError(r.Errors.ToProblems()),
|
var r => Results.InternalServerError(r.Errors.ToProblems()),
|
||||||
})
|
})
|
||||||
.WithDescription("Get all funding instruments")
|
.WithDescription("Get all funding instruments")
|
||||||
.WithName(typeof(GetInstrumentsEndpoint).ToEndpointName())
|
.WithName(typeof(GetInstrumentsEndpoint).ToEndpointName())
|
||||||
.MapToApiVersion(new ApiVersion(1))
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
.Produces<Instrument[]>(StatusCodes.Status200OK)
|
.Produces<Instrument[]>(StatusCodes.Status200OK)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.WithTags(EndpointTags.Governance);
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
|
.WithTags(EndpointTags.Governance)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Governance;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -15,10 +15,10 @@ public class GetOrganisationEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/governance/organisations/{organisationId}", async (string organisationId,
|
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
|
await service.GetOrganisationAsync(organisationId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true, Value: var organisation } => Results.Ok(organisationId),
|
{ IsSuccess: true, Value: var organisation } => Results.Ok(organisation),
|
||||||
var r when r.HasError<IdDecodeError>() => Results.Forbid(),
|
var r when r.HasError<IdDecodeError>() => Results.Forbid(),
|
||||||
var r when r.HasError<NotFoundError>() => Results.NotFound(),
|
var r when r.HasError<NotFoundError>() => Results.NotFound(),
|
||||||
var r => Results.InternalServerError(r.Errors.ToProblems())
|
var r => Results.InternalServerError(r.Errors.ToProblems())
|
||||||
@@ -31,6 +31,7 @@ public class GetOrganisationEndpoint : IEndpoint
|
|||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.Produces(StatusCodes.Status403Forbidden)
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.WithTags(EndpointTags.Governance);
|
.WithTags(EndpointTags.Governance)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Governance;
|
|
||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public class GetOrganisationsEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
|
||||||
await service.GetOrganisationsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
await service.GetOrganisationsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
||||||
{
|
{
|
||||||
@@ -27,6 +27,7 @@ public class GetOrganisationsEndpoint : IEndpoint
|
|||||||
.Produces<Organisation[]>(StatusCodes.Status200OK)
|
.Produces<Organisation[]>(StatusCodes.Status200OK)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.WithTags(EndpointTags.Governance);
|
.WithTags(EndpointTags.Governance)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Extensions;
|
||||||
|
using PostFundManagement.Domain.Abstractions;
|
||||||
|
using PostFundManagement.Domain.Errors;
|
||||||
|
using PostFundManagement.Domain.Extensions;
|
||||||
|
using PostFundManagement.Domain.Models;
|
||||||
|
using PostFundManagement.Domain.Security;
|
||||||
|
using Problems = Microsoft.AspNetCore.Mvc.ProblemDetails;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Api.Endpoints.Governance;
|
||||||
|
|
||||||
|
[ApiVersionTarget(1)]
|
||||||
|
public sealed class GetPortfolioEndpoint : IEndpoint
|
||||||
|
{
|
||||||
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
|
{
|
||||||
|
builder.MapGet("api/governance/portfolios/{portfolioId}", async (string portfolioId, IGovernanceService service,
|
||||||
|
CancellationToken cancellationToken = default) =>
|
||||||
|
await service.GetPortfolioAsync(portfolioIdHash: portfolioId, cancellationToken) switch
|
||||||
|
{
|
||||||
|
{ IsSuccess: true, Value: var portfolio } => Results.Ok(portfolio),
|
||||||
|
var r when r.HasError<NotFoundError>() => Results.NotFound(),
|
||||||
|
var r => Results.InternalServerError(r.Errors.ToProblems())
|
||||||
|
})
|
||||||
|
.WithDescription("Get a specific portfolios")
|
||||||
|
.WithName(typeof(GetPortfolioEndpoint).ToEndpointName())
|
||||||
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
|
.Produces<Portfolio[]>(StatusCodes.Status200OK)
|
||||||
|
.Produces<Portfolio[]>(StatusCodes.Status404NotFound)
|
||||||
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
|
.WithTags(EndpointTags.Governance)
|
||||||
|
.CacheOutput();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Extensions;
|
||||||
|
using PostFundManagement.Domain.Abstractions;
|
||||||
|
using PostFundManagement.Domain.Errors;
|
||||||
|
using PostFundManagement.Domain.Extensions;
|
||||||
|
using PostFundManagement.Domain.Models;
|
||||||
|
using PostFundManagement.Domain.Security;
|
||||||
|
using Problems = Microsoft.AspNetCore.Mvc.ProblemDetails;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Api.Endpoints.Governance;
|
||||||
|
|
||||||
|
[ApiVersionTarget(1)]
|
||||||
|
public sealed class GetPortfolioProgrammesEndpoint : IEndpoint
|
||||||
|
{
|
||||||
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
|
{
|
||||||
|
builder.MapGet("api/governance/portfolios/{portfolioId}/programmes", async (string portfolioId, IGovernanceService service,
|
||||||
|
CancellationToken cancellationToken = default) =>
|
||||||
|
await service.GetPortfolioProgrammesAsync(portfolioId, cancellationToken) switch
|
||||||
|
{
|
||||||
|
{ IsSuccess: true, Value: var portfolios } => Results.Ok(portfolios),
|
||||||
|
var r when r.HasError<NotFoundError>() => Results.NotFound(),
|
||||||
|
var r when r.HasError<IdDecodeError>() => Results.Forbid(),
|
||||||
|
var r => Results.InternalServerError(r.Errors.ToProblems())
|
||||||
|
})
|
||||||
|
.WithDescription("Get a programme's portfolios")
|
||||||
|
.WithName(typeof(GetPortfolioProgrammesEndpoint).ToEndpointName())
|
||||||
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
|
.Produces<Programme[]>(StatusCodes.Status200OK)
|
||||||
|
.Produces(StatusCodes.Status404NotFound)
|
||||||
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
|
.WithTags(EndpointTags.Governance)
|
||||||
|
.CacheOutput();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Governance;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
using PostFundManagement.Domain.Models;
|
using PostFundManagement.Domain.Models;
|
||||||
using PostFundManagement.Domain.Security;
|
using PostFundManagement.Domain.Security;
|
||||||
@@ -13,19 +14,22 @@ public class GetPortfoliosEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/governance/portfolios", async (GovernanceService service,
|
builder.MapGet("api/governance/organisations/{organisationId}/portfolio", async (string organisationId,
|
||||||
CancellationToken cancellationToken = default) =>
|
IGovernanceService service, CancellationToken cancellationToken = default) =>
|
||||||
await service.GetPorfoliosAsync(cancellationToken) switch
|
await service.GetPorfoliosAsync(organisationId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true, Value: var portfolios } => Results.Ok(portfolios),
|
{ IsSuccess: true, Value: var portfolios } => Results.Ok(portfolios),
|
||||||
|
var r when r.HasError<IdDecodeError>() => Results.Forbid(),
|
||||||
var r => Results.InternalServerError(r.Errors.ToProblems())
|
var r => Results.InternalServerError(r.Errors.ToProblems())
|
||||||
})
|
})
|
||||||
.WithDescription("Get all portfolios")
|
.WithDescription("Get all portfolios")
|
||||||
.WithName(typeof(GetPortfoliosEndpoint).ToEndpointName())
|
.WithName(typeof(GetPortfoliosEndpoint).ToEndpointName())
|
||||||
.MapToApiVersion(new ApiVersion(1))
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
.Produces<Portfolio[]>(StatusCodes.Status200OK)
|
.Produces<Portfolio[]>(StatusCodes.Status200OK)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.WithTags(EndpointTags.Governance);
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
|
.WithTags(EndpointTags.Governance)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Governance;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
using PostFundManagement.Domain.Models;
|
using PostFundManagement.Domain.Models;
|
||||||
using PostFundManagement.Domain.Security;
|
using PostFundManagement.Domain.Security;
|
||||||
@@ -13,19 +14,22 @@ public class GetProgrammesEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/governance/programmes", async (GovernanceService service,
|
builder.MapGet("api/governance/programmes/{portfolioId}", async (string portfolioId, IGovernanceService service,
|
||||||
CancellationToken cancellationToken = default) =>
|
CancellationToken cancellationToken = default) =>
|
||||||
await service.GetProgrammesAsync(cancellationToken) switch
|
await service.GetProgrammesAsync(portfolioId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true, Value: var programmes } => Results.Ok(programmes),
|
{ IsSuccess: true, Value: var programmes } => Results.Ok(programmes),
|
||||||
|
var r when r.HasError<IdDecodeError>() => Results.Forbid(),
|
||||||
var r => Results.InternalServerError(r.Errors.ToProblems())
|
var r => Results.InternalServerError(r.Errors.ToProblems())
|
||||||
})
|
})
|
||||||
.WithDescription("Get all programmes")
|
.WithDescription("Get all programmes")
|
||||||
.WithName(typeof(GetProgrammesEndpoint).ToEndpointName())
|
.WithName(typeof(GetProgrammesEndpoint).ToEndpointName())
|
||||||
.MapToApiVersion(new ApiVersion(1))
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
.Produces<Programme[]>(StatusCodes.Status200OK)
|
.Produces<Programme[]>(StatusCodes.Status200OK)
|
||||||
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.WithTags(EndpointTags.Governance);
|
.WithTags(EndpointTags.Governance)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Governance;
|
using PostFundManagement.Application.Services.Governance;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
@@ -14,7 +15,7 @@ public sealed class UpdateOrganisationEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPut("api/governance/organisations", async (UpdateOrganisationRequest request,
|
builder.MapPut("api/governance/organisations", async (UpdateOrganisationRequest request,
|
||||||
GovernanceService service, CancellationToken cancellationToken = default) =>
|
IGovernanceService service, CancellationToken cancellationToken = default) =>
|
||||||
await service.UpdateOrganisationAsync(request, cancellationToken) switch
|
await service.UpdateOrganisationAsync(request, cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } => Results.Ok(),
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
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;
|
||||||
|
using PostFundManagement.Domain.Security;
|
||||||
|
using Problems = Microsoft.AspNetCore.Mvc.ProblemDetails;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Api.Endpoints.Governance;
|
||||||
|
|
||||||
|
[ApiVersionTarget(1)]
|
||||||
|
public sealed class UpdatePortfolioEndpoint : IEndpoint
|
||||||
|
{
|
||||||
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
|
{
|
||||||
|
builder.MapPut("api/governance/organisations/portfolio", async (UpdatePortfolioRequest request, HttpContext context,
|
||||||
|
IGovernanceService service, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.UpdatePortfolioAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
|
{
|
||||||
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
var r when r.HasError<NotFoundError>() => Results.NotFound(),
|
||||||
|
var r when r.HasError<IdDecodeError>() => Results.Forbid(),
|
||||||
|
var r when r.HasError<UpdateError>() => Results.BadRequest(r.Errors.ToProblems()),
|
||||||
|
var r => Results.InternalServerError(r.Errors.ToProblems())
|
||||||
|
})
|
||||||
|
.WithDescription("Update an existing organization portfolio")
|
||||||
|
.WithName(typeof(UpdatePortfolioEndpoint).ToEndpointName())
|
||||||
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
|
.Produces(StatusCodes.Status200OK)
|
||||||
|
.Produces(StatusCodes.Status404NotFound)
|
||||||
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
|
.Produces<Problems>(StatusCodes.Status400BadRequest)
|
||||||
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
|
.WithTags(EndpointTags.Governance);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Grants;
|
using PostFundManagement.Application.Services.Grants;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
@@ -14,7 +15,7 @@ public class CreateAwardEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPost("api/grants/awards", async (CreateAwardRequest request, HttpContext context,
|
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
|
await service.CreateAwardAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } => Results.Ok(),
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Grants;
|
using PostFundManagement.Application.Services.Grants;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
@@ -14,7 +15,7 @@ public class CreateBudgetEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPost("api/grants/budgets", async (CreateBudgetRequest request, HttpContext context,
|
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
|
await service.CreateBudgetAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } => Results.Ok(),
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Grants;
|
using PostFundManagement.Application.Services.Grants;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
@@ -14,7 +15,7 @@ public class CreateContractEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPost("api/grants/contracts", async (CreateContractRequest request, HttpContext context,
|
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
|
await service.CreateContractAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } => Results.Ok(),
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Grants;
|
using PostFundManagement.Application.Services.Grants;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
@@ -14,7 +15,7 @@ public class ExecuteContractEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPost("api/grants/contracts/execute", async (ExecuteContractRequest request, HttpContext context,
|
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
|
await service.ExecuteContractAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } => Results.Ok(),
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Grants;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public class GetAwardEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
CancellationToken cancellationToken = default) =>
|
||||||
await service.GetAwardAsync(awardId, cancellationToken) switch
|
await service.GetAwardAsync(awardId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
@@ -31,6 +31,7 @@ public class GetAwardEndpoint : IEndpoint
|
|||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.Produces(StatusCodes.Status404NotFound)
|
.Produces(StatusCodes.Status404NotFound)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.WithTags(EndpointTags.Grants);
|
.WithTags(EndpointTags.Grants)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Grants;
|
|
||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public class GetAwardsEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
int page = 1, int pageSize = 10, CancellationToken cancellationToken = default) =>
|
||||||
await service.GetAwardsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
await service.GetAwardsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
||||||
{
|
{
|
||||||
@@ -27,6 +27,7 @@ public class GetAwardsEndpoint : IEndpoint
|
|||||||
.Produces<Award[]>(StatusCodes.Status200OK)
|
.Produces<Award[]>(StatusCodes.Status200OK)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.WithTags(EndpointTags.Grants);
|
.WithTags(EndpointTags.Grants)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Grants;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public class GetBudgetEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
CancellationToken cancellationToken = default) =>
|
||||||
await service.GetBudgetAsync(budgetId, cancellationToken) switch
|
await service.GetBudgetAsync(budgetId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
@@ -31,6 +31,7 @@ public class GetBudgetEndpoint : IEndpoint
|
|||||||
.Produces(StatusCodes.Status403Forbidden)
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.WithTags(EndpointTags.Grants);
|
.WithTags(EndpointTags.Grants)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Grants;
|
|
||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public class GetBudgetsEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
|
||||||
await service.GetBudgetsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
await service.GetBudgetsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
||||||
{
|
{
|
||||||
@@ -27,6 +27,7 @@ public class GetBudgetsEndpoint : IEndpoint
|
|||||||
.Produces<Budget[]>(StatusCodes.Status200OK)
|
.Produces<Budget[]>(StatusCodes.Status200OK)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.WithTags(EndpointTags.Grants);
|
.WithTags(EndpointTags.Grants)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Grants;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public class GetContractEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
CancellationToken cancellationToken = default) =>
|
||||||
await service.GetContractAsync(contractId, cancellationToken) switch
|
await service.GetContractAsync(contractId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
@@ -31,6 +31,7 @@ public class GetContractEndpoint : IEndpoint
|
|||||||
.Produces(StatusCodes.Status403Forbidden)
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.WithTags(EndpointTags.Grants);
|
.WithTags(EndpointTags.Grants)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Grants;
|
|
||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public class GetContractsEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
|
||||||
await service.GetContractsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
await service.GetContractsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
||||||
{
|
{
|
||||||
@@ -27,6 +27,7 @@ public class GetContractsEndpoint : IEndpoint
|
|||||||
.Produces<Contract[]>(StatusCodes.Status200OK)
|
.Produces<Contract[]>(StatusCodes.Status200OK)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.WithTags(EndpointTags.Grants);
|
.WithTags(EndpointTags.Grants)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Projects;
|
using PostFundManagement.Application.Services.Projects;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
@@ -14,7 +15,7 @@ public class CreateActivityEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPost("api/projects/activities", async (CreateActivityRequest request,
|
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
|
await service.CreateActivityAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } result => Results.Ok(),
|
{ IsSuccess: true } result => Results.Ok(),
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
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;
|
||||||
|
using PostFundManagement.Domain.Security;
|
||||||
|
using Problems = Microsoft.AspNetCore.Mvc.ProblemDetails;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Api.Endpoints.Projects;
|
||||||
|
|
||||||
|
[ApiVersionTarget(1)]
|
||||||
|
public sealed class CreateProgrammeEndpoint : IEndpoint
|
||||||
|
{
|
||||||
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
|
{
|
||||||
|
builder.MapPost("api/projects/programme", async (CreateProgrammeRequest request, HttpContext context,
|
||||||
|
IProjectService service, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.CreateProgrammeAsync(request, userId: context.GetUserId(), cancellationToken) switch
|
||||||
|
{
|
||||||
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
var r when r.HasError<NotFoundError>() => Results.NotFound(),
|
||||||
|
var r when r.HasError<ValidationError>() => Results.BadRequest(r.Errors.ToProblems()),
|
||||||
|
var r when r.HasError<CreateError>() => Results.BadRequest(),
|
||||||
|
var r => Results.InternalServerError(r.Errors.ToProblems())
|
||||||
|
})
|
||||||
|
.WithDescription("Create programme")
|
||||||
|
.WithName(typeof(CreateProgrammeEndpoint).ToEndpointName())
|
||||||
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
|
.Produces(StatusCodes.Status200OK)
|
||||||
|
.Produces(StatusCodes.Status404NotFound)
|
||||||
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
|
.WithTags(EndpointTags.Projects);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Projects;
|
using PostFundManagement.Application.Services.Projects;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
@@ -14,7 +15,7 @@ public class CreateProjectEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPost("api/projects", async (CreateProjectRequest request, HttpContext context,
|
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
|
await service.CreateProjectAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } result => Results.Ok(),
|
{ IsSuccess: true } result => Results.Ok(),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Projects;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public class GetActivitiesEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/projects/{projectId}/activities", async (string projectId,
|
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
|
await service.GetActivitiesAsync(projectId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true, Value: var activities } => Results.Ok(activities),
|
{ IsSuccess: true, Value: var activities } => Results.Ok(activities),
|
||||||
@@ -28,6 +28,7 @@ public class GetActivitiesEndpoint : IEndpoint
|
|||||||
.Produces(StatusCodes.Status403Forbidden)
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.WithTags(EndpointTags.Projects);
|
.WithTags(EndpointTags.Projects)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Projects;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public class GetActivityEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/projects/activities/{activityId}", async (string activityId,
|
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
|
await service.GetActivityAsync(activityId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true, Value: var activity } => Results.Ok(activity),
|
{ IsSuccess: true, Value: var activity } => Results.Ok(activity),
|
||||||
@@ -30,6 +30,7 @@ public class GetActivityEndpoint : IEndpoint
|
|||||||
.Produces(StatusCodes.Status403Forbidden)
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.WithTags(EndpointTags.Projects);
|
.WithTags(EndpointTags.Projects)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Services.Projects;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public class GetMilestoneEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
CancellationToken cancellationToken = default) =>
|
||||||
await service.GetMilestoneAsync(milestoneId, cancellationToken) switch
|
await service.GetMilestoneAsync(milestoneId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Projects;
|
|
||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,20 +14,20 @@ public class GetMilestonesEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
|
||||||
await service.GetMilestonesAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
await service.GetMilestonesAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true, Value: var milestones } => Results.Ok(milestones),
|
{ IsSuccess: true, Value: var milestones } => Results.Ok(milestones),
|
||||||
var r => Results.InternalServerError(r.Errors.ToProblems())
|
var r => Results.InternalServerError(r.Errors.ToProblems())
|
||||||
})
|
})
|
||||||
.RequireAuthorization()
|
|
||||||
.WithDescription("Get a list of all milestones")
|
.WithDescription("Get a list of all milestones")
|
||||||
.WithName(typeof(GetMilestonesEndpoint).ToEndpointName())
|
.WithName(typeof(GetMilestonesEndpoint).ToEndpointName())
|
||||||
.MapToApiVersion(new ApiVersion(1))
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
.Produces<Milestone[]>(StatusCodes.Status200OK)
|
.Produces<Milestone[]>(StatusCodes.Status200OK)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.WithTags(EndpointTags.Projects);
|
.WithTags(EndpointTags.Projects)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Extensions;
|
||||||
|
using PostFundManagement.Domain.Abstractions;
|
||||||
|
using PostFundManagement.Domain.Errors;
|
||||||
|
using PostFundManagement.Domain.Extensions;
|
||||||
|
using PostFundManagement.Domain.Models;
|
||||||
|
using PostFundManagement.Domain.Security;
|
||||||
|
using Problems = Microsoft.AspNetCore.Mvc.ProblemDetails;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Api.Endpoints.Projects;
|
||||||
|
|
||||||
|
[ApiVersionTarget(1)]
|
||||||
|
public sealed class GetProgrammeEndpoint : IEndpoint
|
||||||
|
{
|
||||||
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
|
{
|
||||||
|
builder.MapGet("api/projects/programme/{programmeId}", async (string programmeId, IProjectService service,
|
||||||
|
CancellationToken cancellationToken = default) =>
|
||||||
|
await service.GetProgrammeAsync(programmeId, cancellationToken) switch
|
||||||
|
{
|
||||||
|
{ IsSuccess: true, Value: var programme } => Results.Ok(programme),
|
||||||
|
var r when r.HasError<NotFoundError>() => Results.NotFound(),
|
||||||
|
var r when r.HasError<IdDecodeError>() => Results.Forbid(),
|
||||||
|
var r => Results.InternalServerError(r.Errors.ToProblems())
|
||||||
|
})
|
||||||
|
.WithDescription("Get specific programme")
|
||||||
|
.WithName(typeof(GetProgrammeEndpoint).ToEndpointName())
|
||||||
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
|
.Produces<Programme>(StatusCodes.Status200OK)
|
||||||
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
|
.WithTags(EndpointTags.Projects)
|
||||||
|
.CacheOutput();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Extensions;
|
||||||
|
using PostFundManagement.Domain.Abstractions;
|
||||||
|
using PostFundManagement.Domain.Errors;
|
||||||
|
using PostFundManagement.Domain.Extensions;
|
||||||
|
using PostFundManagement.Domain.Models;
|
||||||
|
using PostFundManagement.Domain.Security;
|
||||||
|
using Problems = Microsoft.AspNetCore.Mvc.ProblemDetails;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Api.Endpoints.Projects;
|
||||||
|
|
||||||
|
[ApiVersionTarget(1)]
|
||||||
|
public sealed class GetProgrammeProjectsEndpoint : IEndpoint
|
||||||
|
{
|
||||||
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
|
{
|
||||||
|
builder.MapGet("api/projects/{programmeId}/programme", async (string programmeId,
|
||||||
|
IProjectService service, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.GetProgrammeProjectsAsync(programmeId, cancellationToken) switch
|
||||||
|
{
|
||||||
|
{ IsSuccess: true, Value: var projects } => Results.Ok(projects),
|
||||||
|
var r when r.HasError<NotFoundError>() => Results.NotFound(),
|
||||||
|
var r when r.HasError<IdDecodeError>() => Results.Forbid(),
|
||||||
|
var r => Results.InternalServerError(r.Errors.ToProblems()),
|
||||||
|
})
|
||||||
|
.WithDescription("Get a list of all projects under a programme")
|
||||||
|
.WithName(typeof(GetProgrammeProjectsEndpoint).ToEndpointName())
|
||||||
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
|
.Produces<Project[]>(StatusCodes.Status200OK)
|
||||||
|
.Produces(StatusCodes.Status404NotFound)
|
||||||
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
|
.WithTags(EndpointTags.Projects)
|
||||||
|
.CacheOutput();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Extensions;
|
||||||
|
using PostFundManagement.Domain;
|
||||||
|
using PostFundManagement.Domain.Abstractions;
|
||||||
|
using PostFundManagement.Domain.Extensions;
|
||||||
|
using PostFundManagement.Domain.Models;
|
||||||
|
using PostFundManagement.Domain.Security;
|
||||||
|
using Problems = Microsoft.AspNetCore.Mvc.ProblemDetails;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Api.Endpoints.Projects;
|
||||||
|
|
||||||
|
[ApiVersionTarget(1)]
|
||||||
|
public sealed class GetProgrammesEndpoint : IEndpoint
|
||||||
|
{
|
||||||
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
|
{
|
||||||
|
builder.MapGet("api/projects/programme/{page:int}/{pageSize:int}", async (IProjectService service,
|
||||||
|
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.GetProgrammesAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
||||||
|
{
|
||||||
|
{ IsSuccess: true, Value: var programmes } => Results.Ok(programmes),
|
||||||
|
var r => Results.InternalServerError(r.Errors.ToProblems())
|
||||||
|
})
|
||||||
|
.WithDescription("Get a list of all programmes")
|
||||||
|
.WithName(typeof(GetProgrammesEndpoint).ToEndpointName("Projects"))
|
||||||
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
|
.Produces<Programme[]>(StatusCodes.Status200OK)
|
||||||
|
.Produces(StatusCodes.Status404NotFound)
|
||||||
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
|
.WithTags(EndpointTags.Projects)
|
||||||
|
.CacheOutput();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Projects;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public class GetProjectEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
CancellationToken cancellationToken = default) =>
|
||||||
await service.GetProjectAsync(projectId, cancellationToken) switch
|
await service.GetProjectAsync(projectId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
@@ -31,6 +31,7 @@ public class GetProjectEndpoint : IEndpoint
|
|||||||
.Produces(StatusCodes.Status403Forbidden)
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.WithTags(EndpointTags.Projects);
|
.WithTags(EndpointTags.Projects)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Projects;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public class GetProjectIndicatorsEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
CancellationToken cancellationToken = default) =>
|
||||||
await service.GetProjectIndicatorsAsync(projectIdHash: projectId, cancellationToken) switch
|
await service.GetProjectIndicatorsAsync(projectIdHash: projectId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
@@ -30,6 +30,7 @@ public class GetProjectIndicatorsEndpoint : IEndpoint
|
|||||||
.Produces(StatusCodes.Status403Forbidden)
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.WithTags(EndpointTags.Projects);
|
.WithTags(EndpointTags.Projects)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Projects;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -15,7 +15,7 @@ public class GetProjectMilestonesEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/projects/{projectId}/milestones", async (string projectId,
|
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
|
await service.GetProjectMilestonesAsync(projectId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true, Value: var milestones } => Results.Ok(milestones),
|
{ IsSuccess: true, Value: var milestones } => Results.Ok(milestones),
|
||||||
@@ -30,6 +30,7 @@ public class GetProjectMilestonesEndpoint : IEndpoint
|
|||||||
.Produces(StatusCodes.Status403Forbidden)
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.WithTags(EndpointTags.Projects);
|
.WithTags(EndpointTags.Projects)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Projects;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -15,7 +15,7 @@ public class GetProjectRisksEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/projects/{projectId}/risks", async (string projectId,
|
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
|
await service.GetProjectRisksAsync(projectId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true, Value: var risks } => Results.Ok(risks),
|
{ IsSuccess: true, Value: var risks } => Results.Ok(risks),
|
||||||
@@ -30,6 +30,7 @@ public class GetProjectRisksEndpoint : IEndpoint
|
|||||||
.Produces(StatusCodes.Status403Forbidden)
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.WithTags(EndpointTags.Projects);
|
.WithTags(EndpointTags.Projects)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Projects;
|
|
||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public class GetProjectsEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
|
||||||
await service.GetProjectsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
await service.GetProjectsAsync(Pagination.Create(page, pageSize), cancellationToken) switch
|
||||||
{
|
{
|
||||||
@@ -27,6 +27,7 @@ public class GetProjectsEndpoint : IEndpoint
|
|||||||
.Produces<Project[]>(StatusCodes.Status200OK)
|
.Produces<Project[]>(StatusCodes.Status200OK)
|
||||||
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
.Produces(StatusCodes.Status401Unauthorized)
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
.WithTags(EndpointTags.Projects);
|
.WithTags(EndpointTags.Projects)
|
||||||
|
.CacheOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Projects;
|
using PostFundManagement.Application.Services.Projects;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -12,7 +13,7 @@ public sealed class UpdateMilestoneEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
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) =>
|
HttpContext context, CancellationToken cancellationToken = default) =>
|
||||||
await service.UpdateMilestoneAsync(request, context.GetUserId(), cancellationToken) switch
|
await service.UpdateMilestoneAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
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;
|
||||||
|
using PostFundManagement.Domain.Security;
|
||||||
|
using Problems = Microsoft.AspNetCore.Mvc.ProblemDetails;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Api.Endpoints.Projects;
|
||||||
|
|
||||||
|
[ApiVersionTarget(1)]
|
||||||
|
public sealed class UpdateProgrammeEndpoint : IEndpoint
|
||||||
|
{
|
||||||
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
|
{
|
||||||
|
builder.MapPut("api/projects/programme", async (UpdateProgrammeRequest request, HttpContext context,
|
||||||
|
IProjectService service, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.UpdateProgrammeAsync(request, userId: context.GetUserId(), cancellationToken) switch
|
||||||
|
{
|
||||||
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
var r when r.HasError<NotFoundError>() => Results.NotFound(),
|
||||||
|
var r when r.HasError<UpdateError>() => Results.BadRequest(r.Errors.ToProblems()),
|
||||||
|
var r => Results.InternalServerError(r.Errors.ToProblems())
|
||||||
|
})
|
||||||
|
.WithDescription("Update existing programme")
|
||||||
|
.WithName(typeof(UpdateProgrammeEndpoint).ToEndpointName())
|
||||||
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
|
.Produces(StatusCodes.Status200OK)
|
||||||
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
|
.Produces<Problems>(StatusCodes.Status400BadRequest)
|
||||||
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
|
.WithTags(EndpointTags.Projects);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Projects;
|
using PostFundManagement.Application.Services.Projects;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
@@ -14,7 +15,7 @@ public sealed class UpdateProjectEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPut("api/projects", async (UpdateProjectRequest request,
|
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
|
await service.UpdateProjectAsync(request, userId: context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } => Results.Ok(),
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Projects;
|
using PostFundManagement.Application.Services.Projects;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
@@ -14,7 +15,7 @@ public class UpdateProjectStatusEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPut("api/projects/status", async (UpdateProjectStatusRequest request, HttpContext context,
|
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
|
await service.UpdateProjectStatusAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } => Results.Ok(),
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Extensions;
|
||||||
|
using PostFundManagement.Domain.Abstractions;
|
||||||
|
using PostFundManagement.Domain.Errors;
|
||||||
|
using PostFundManagement.Domain.Extensions;
|
||||||
|
using PostFundManagement.Domain.Security;
|
||||||
|
using Problems = Microsoft.AspNetCore.Mvc.ProblemDetails;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Api.Endpoints.Tools;
|
||||||
|
|
||||||
|
[ApiVersionTarget(1)]
|
||||||
|
public sealed class EncodeIdEndpoint : IEndpoint
|
||||||
|
{
|
||||||
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
|
{
|
||||||
|
builder.MapGet("api/tools/hashid/{id64:long}", async (long id64, IToolService service,
|
||||||
|
CancellationToken cancellationToken) =>
|
||||||
|
await service.EncodeLong(id64, cancellationToken) switch
|
||||||
|
{
|
||||||
|
{ IsSuccess: true, Value: var hash } => Results.Ok(hash),
|
||||||
|
var r when r.HasError<ValidationError>() => Results.BadRequest(r.Errors.ToProblems()),
|
||||||
|
var r => Results.InternalServerError(r.Errors.ToProblems())
|
||||||
|
})
|
||||||
|
.WithDescription("Hashes an int64 identifier")
|
||||||
|
.WithName(typeof(EncodeIdEndpoint).ToEndpointName())
|
||||||
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
|
.Produces<string>(StatusCodes.Status200OK)
|
||||||
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
|
.Produces(StatusCodes.Status403Forbidden)
|
||||||
|
.Produces<Problems>(StatusCodes.Status400BadRequest)
|
||||||
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
|
.WithTags(EndpointTags.Tools)
|
||||||
|
.CacheOutput();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Services.Users;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -14,7 +14,7 @@ public sealed class GetUserEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/users/{userId:Guid}", async (Guid userId, UserService service,
|
builder.MapGet("api/users/{userId:Guid}", async (Guid userId, IUserService service,
|
||||||
HttpContext context, CancellationToken cancellationToken = default) =>
|
HttpContext context, CancellationToken cancellationToken = default) =>
|
||||||
await service.GetUserAsync(userId, cancellationToken) switch
|
await service.GetUserAsync(userId, cancellationToken) switch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Users;
|
using PostFundManagement.Application.Services.Users;
|
||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
@@ -14,7 +15,7 @@ public class GetUsersEndpoint : IEndpoint
|
|||||||
{
|
{
|
||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPost("api/users/{page:int}/{pageSize:int}", async (UserFilterRequest request, UserService service,
|
builder.MapPost("api/users/{page:int}/{pageSize:int}", async (UserFilterRequest request, IUserService service,
|
||||||
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
|
int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) =>
|
||||||
await service.GetUsersAsync(Pagination.Create(page, pageSize), request, cancellationToken) switch
|
await service.GetUsersAsync(Pagination.Create(page, pageSize), request, cancellationToken) switch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Services.Communications.Events;
|
using PostFundManagement.Application.Services.Communications.Events;
|
||||||
using PostFundManagement.Application.Services.Users;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
@@ -15,7 +15,7 @@ public class SyncUserEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapPost("api/integration/sync", async (IJobOrchestrator jobOrchestrator,
|
builder.MapPost("api/integration/sync", async (IJobOrchestrator jobOrchestrator,
|
||||||
HttpContext context, UserService service, CancellationToken cancellationToken = default) =>
|
HttpContext context, IUserService service, CancellationToken cancellationToken = default) =>
|
||||||
{
|
{
|
||||||
var result = await service.SyncUserAsync(context.GetUserId(), context.GetUserEmail(), cancellationToken);
|
var result = await service.SyncUserAsync(context.GetUserId(), context.GetUserEmail(), cancellationToken);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using PostFundManagement.Application.Extensions;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Application.Services.Users;
|
using PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
@@ -15,7 +15,7 @@ public sealed class UpdateUserStatusEndpoint : IEndpoint
|
|||||||
public void Map(IEndpointRouteBuilder builder)
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
{
|
{
|
||||||
builder.MapGet("api/users/{userId:Guid}/status/{status:int}", async (Guid userId, ActivityStatus status,
|
builder.MapGet("api/users/{userId:Guid}/status/{status:int}", async (Guid userId, ActivityStatus status,
|
||||||
UserService service, CancellationToken cancellationToken = default) =>
|
IUserService service, CancellationToken cancellationToken = default) =>
|
||||||
await service.UpdateUserStatusAsync(userId, status, cancellationToken) switch
|
await service.UpdateUserStatusAsync(userId, status, cancellationToken) switch
|
||||||
{
|
{
|
||||||
{ IsSuccess: true } => Results.Ok(),
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
|||||||
@@ -10,6 +10,14 @@
|
|||||||
<PackageLicenseFile>..\LICENSE</PackageLicenseFile>
|
<PackageLicenseFile>..\LICENSE</PackageLicenseFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<NoWarn>1701;1702;AV0029;AV0030;</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
|
<NoWarn>1701;1702;AV0029;AV0030;</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- Security (IODC)-->
|
<!-- Security (IODC)-->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="IdentityModel.AspNetCore" Version="4.3.0" />
|
<PackageReference Include="IdentityModel.AspNetCore" Version="4.3.0" />
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ builder.Services.AddScoped<ActiveUserFilter>();
|
|||||||
|
|
||||||
builder.Services.AddEndpoints(Assembly.GetExecutingAssembly());
|
builder.Services.AddEndpoints(Assembly.GetExecutingAssembly());
|
||||||
builder.Services.AddApiServices(builder.Configuration);
|
builder.Services.AddApiServices(builder.Configuration);
|
||||||
builder.Services.AddRegisterServices(builder.Configuration);
|
builder.Services.AddSharedServices();
|
||||||
|
builder.Services.AddRegisterServicesWithCaching(builder.Configuration);
|
||||||
builder.Services.AddEndpointAndServiceCaching(builder.Configuration);
|
builder.Services.AddEndpointAndServiceCaching(builder.Configuration);
|
||||||
|
|
||||||
builder.Services.AddMediator();
|
builder.Services.AddMediator();
|
||||||
@@ -41,6 +42,9 @@ builder.Services.AddHealthChecks()
|
|||||||
|
|
||||||
IEnumerable<string> identityScopes = ["openid", "profile", "roles", "email", "address"];
|
IEnumerable<string> identityScopes = ["openid", "profile", "roles", "email", "address"];
|
||||||
|
|
||||||
|
builder.Services.AddValidation()
|
||||||
|
.AddEndpointValidation();
|
||||||
|
|
||||||
builder.Services.AddOpenApi(options =>
|
builder.Services.AddOpenApi(options =>
|
||||||
{
|
{
|
||||||
options.AddDocumentTransformer((document, context, cancellationToken) =>
|
options.AddDocumentTransformer((document, context, cancellationToken) =>
|
||||||
@@ -87,6 +91,12 @@ builder.Services.AddOpenApi(options =>
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
builder.Services.AddCors(options => options.AddPolicy("AllowFrontend", policy =>
|
||||||
|
policy.WithOrigins("https://localhost:3000", "https://localhost:8076", "https://console.ifri.khongisa.co.za")
|
||||||
|
.AllowAnyHeader()
|
||||||
|
.AllowAnyMethod()
|
||||||
|
.AllowCredentials()));
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
var schedulerFactory = app.Services.GetRequiredService<ISchedulerFactory>();
|
var schedulerFactory = app.Services.GetRequiredService<ISchedulerFactory>();
|
||||||
@@ -99,6 +109,7 @@ app.UseHsts();
|
|||||||
app.UseHttpsRedirection();
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
app.UseCors("AllowFrontend");
|
||||||
app.UseOutputCache();
|
app.UseOutputCache();
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace PostFundManagement.Application.Abstractions;
|
||||||
|
|
||||||
|
public abstract class ServiceCacheBase
|
||||||
|
{
|
||||||
|
protected readonly DistributedCacheEntryOptions cacheOptions = new()
|
||||||
|
{
|
||||||
|
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(2)
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using PostFundManagement.Application.Services.Communications;
|
||||||
|
using PostFundManagement.Domain;
|
||||||
|
using PostFundManagement.Domain.Models;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Application.Abstractions.Services;
|
||||||
|
|
||||||
|
public interface ICommunicationsService
|
||||||
|
{
|
||||||
|
ValueTask<Result<Invite>> SendInviteAsync(InviteRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Invite[]>> GetInvitesAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Invite>> GetApplicantInviteAsync(Guid applicantUserId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Invite[]>> GetApplicantInvitesAsync(Guid applicantUserId, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using PostFundManagement.Application.Services.Evidence;
|
||||||
|
using PostFundManagement.Domain;
|
||||||
|
using PostFundManagement.Domain.Models;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Application.Abstractions.Services;
|
||||||
|
|
||||||
|
public interface IEvidenceService
|
||||||
|
{
|
||||||
|
ValueTask<Result> CreateEvidenceAsync(Guid userId, IFormCollection form, IFormFile file, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> RecordIndicatorActualAmountAsync(string indicatorIdHash, decimal amount, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Indicator[]>> GetIndicatorsAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Evidence[]>> GetEvidenceFilesAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> CreateMilestoneAsync(CreateMilestoneRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> CreateIndicatorAsync(CreateIndicatorRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Indicator>> GetIndicatorAsync(string indicatorId, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
ValueTask<Result<Evidence>> GetEvidenceAsync(string evidenceId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Evidence[]>> GetMilestoneEvidencesAsync(string milestoneIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Evidence[]>> GetProjectEvidencesAsync(string projectIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> UpdateEvidenceAsync(UpdateEvidenceRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using PostFundManagement.Application.Services.Execution;
|
||||||
|
using PostFundManagement.Domain;
|
||||||
|
using PostFundManagement.Domain.Models;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Application.Abstractions.Services;
|
||||||
|
|
||||||
|
public interface IExecutionService
|
||||||
|
{
|
||||||
|
ValueTask<Result<Risk[]>> GetRisksAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Disbursement[]>> GetDisbursementsAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> CreateRiskAsync(CreateRiskRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> CreateDisbursementAsync(CreateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> ApproveDisbursementAsync(string disbursementIdHash, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Disbursement>> GetDisbursementAsync(string disbursementIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Risk>> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> UpdateRiskAsync(UpdateRiskRequest request, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> UpdateDisbursementAsync(UpdateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using PostFundManagement.Application.Services.Governance;
|
||||||
|
using PostFundManagement.Domain;
|
||||||
|
using PostFundManagement.Domain.Models;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Application.Abstractions.Services;
|
||||||
|
|
||||||
|
public interface IGovernanceService
|
||||||
|
{
|
||||||
|
ValueTask<Result<Programme[]>> GetProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Portfolio[]>> GetPorfoliosAsync(string organisationIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Organisation[]>> GetOrganisationsAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Organisation>> GetOrganisationAsync(string organisationIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Instrument[]>> GetInstrumentsAsync(string programmeIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Dashboard>> GetDashboardAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> CreateOrganisationAsync(CreateOrganisationRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Organisation>> UpdateOrganisationAsync(UpdateOrganisationRequest request, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> CreatePortfolioAsync(CreatePortfolioRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> UpdatePortfolioAsync(UpdatePortfolioRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Programme[]>> GetPortfolioProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Portfolio>> GetPortfolioAsync(string portfolioIdHash, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using PostFundManagement.Application.Services.Grants;
|
||||||
|
using PostFundManagement.Domain;
|
||||||
|
using PostFundManagement.Domain.Models;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Application.Abstractions.Services;
|
||||||
|
|
||||||
|
public interface IGrantsService
|
||||||
|
{
|
||||||
|
ValueTask<Result<Contract[]>> GetContractsAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Contract>> GetContractAsync(string contractIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Budget[]>> GetBudgetsAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Budget>> GetBudgetAsync(string budgetIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Award[]>> GetAwardsAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Award>> GetAwardAsync(string awardIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> ExecuteContractAsync(ExecuteContractRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> CreateContractAsync(CreateContractRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> CreateBudgetAsync(CreateBudgetRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> CreateAwardAsync(CreateAwardRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace PostFundManagement.Application.Abstractions.Services;
|
||||||
|
|
||||||
|
public interface IIdentityService
|
||||||
|
{
|
||||||
|
ValueTask<Result> UserIsAuthorisedAsync(Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using PostFundManagement.Application.Services.Projects;
|
||||||
|
using PostFundManagement.Domain;
|
||||||
|
using PostFundManagement.Domain.Models;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Application.Abstractions.Services;
|
||||||
|
|
||||||
|
public interface IProjectService
|
||||||
|
{
|
||||||
|
ValueTask<Result> UpdateProjectStatusAsync(UpdateProjectStatusRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Project[]>> GetProjectsAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Project>> GetProjectAsync(string projectIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Domain.Models.Activity[]>> GetActivitiesAsync(string projectIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> CreateProjectAsync(CreateProjectRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> CreateActivityAsync(CreateActivityRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Milestone[]>> GetProjectMilestonesAsync(string projectIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Indicator[]>> GetProjectIndicatorsAsync(string projectIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Milestone>> GetMilestoneAsync(string milestoneIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Milestone[]>> GetMilestonesAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> UpdateMilestoneAsync(UpdateMilestoneRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> UpdateProjectAsync(UpdateProjectRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Domain.Models.Activity>> GetActivityAsync(string activityIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Risk[]>> GetProjectRisksAsync(string projectIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> CreateProgrammeAsync(CreateProgrammeRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> UpdateProgrammeAsync(UpdateProgrammeRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Programme>> GetProgrammeAsync(string programmeIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Programme[]>> GetProgrammesAsync(Pagination pagination, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<Project[]>> GetProgrammeProjectsAsync(string programmeIdHash, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace PostFundManagement.Application.Abstractions.Services;
|
||||||
|
|
||||||
|
public interface IToolService
|
||||||
|
{
|
||||||
|
ValueTask<Result<string>> EncodeLong(long id, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using PostFundManagement.Application.Services.Users;
|
||||||
|
using PostFundManagement.Domain;
|
||||||
|
using PostFundManagement.Domain.Models;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Application.Abstractions.Services;
|
||||||
|
|
||||||
|
public interface IUserService
|
||||||
|
{
|
||||||
|
ValueTask<Result> SyncUserAsync(Guid userId, string email, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<User[]>> GetUsersAsync(Pagination pagination, UserFilterRequest request, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result> UpdateUserStatusAsync(Guid userId, ActivityStatus status, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
ValueTask<Result<User>> GetUserAsync(Guid userId, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
@@ -6,6 +6,8 @@ namespace PostFundManagement.Application.Extensions;
|
|||||||
|
|
||||||
public static class Api
|
public static class Api
|
||||||
{
|
{
|
||||||
|
public static IServiceCollection AddEndpointValidation(this IServiceCollection services) => services.AddValidation();
|
||||||
|
|
||||||
public static IServiceCollection AddEndpointAndServiceCaching(this IServiceCollection services, IConfiguration configuration)
|
public static IServiceCollection AddEndpointAndServiceCaching(this IServiceCollection services, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
services.AddStackExchangeRedisOutputCache(options =>
|
services.AddStackExchangeRedisOutputCache(options =>
|
||||||
|
|||||||
@@ -1,31 +1,12 @@
|
|||||||
using Microsoft.Extensions.Caching.Hybrid;
|
namespace PostFundManagement.Application.Extensions;
|
||||||
using PostFundManagement.Application.Abstractions;
|
|
||||||
using PostFundManagement.Domain.Abstractions;
|
|
||||||
|
|
||||||
namespace PostFundManagement.Application.Extensions;
|
|
||||||
|
|
||||||
public static class General
|
public static class General
|
||||||
{
|
{
|
||||||
public static IServiceCollection AddRegisterServices(this IServiceCollection services, IConfiguration configuration)
|
public static string Clean(this string input) => Patterns.SpaceRegex().Replace(input, string.Empty);
|
||||||
{
|
|
||||||
var serviceType = typeof(IService);
|
|
||||||
|
|
||||||
var sharedImplementations = typeof(IApplication).Assembly.GetTypes()
|
public static string ToJson<TValue>(this TValue obj) where TValue : class => JsonSerializer.Serialize(obj);
|
||||||
.Where(t => serviceType.IsAssignableFrom(t) && t.IsClass && !t.IsAbstract);
|
|
||||||
|
|
||||||
foreach (var sharedImplementation in sharedImplementations) services.AddScoped(sharedImplementation);
|
public static TValue FromJson<TValue>(this string json) where TValue : class => JsonSerializer.Deserialize<TValue>(json)!;
|
||||||
|
|
||||||
services.AddStackExchangeRedisCache(options =>
|
|
||||||
options.Configuration = configuration.GetConnectionString("Redis"));
|
|
||||||
|
|
||||||
services.AddHybridCache(options => options.DefaultEntryOptions = new HybridCacheEntryOptions
|
|
||||||
{
|
|
||||||
Expiration = TimeSpan.FromMinutes(2),
|
|
||||||
LocalCacheExpiration = TimeSpan.FromMinutes(1)
|
|
||||||
});
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Guid GetUserId(this HttpContext context) => (Guid)context.Items[Domain.Extensions.Constants.UserIdItemKey]!;
|
public static Guid GetUserId(this HttpContext context) => (Guid)context.Items[Domain.Extensions.Constants.UserIdItemKey]!;
|
||||||
|
|
||||||
@@ -53,6 +34,6 @@ public static class General
|
|||||||
{
|
{
|
||||||
Detail = string.Join(',', errors.Select(e => e.Message)),
|
Detail = string.Join(',', errors.Select(e => e.Message)),
|
||||||
Status = StatusCodes.Status400BadRequest,
|
Status = StatusCodes.Status400BadRequest,
|
||||||
Title = errors[0]?.Message,
|
Title = "Error",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
namespace PostFundManagement.Application.Extensions;
|
||||||
|
|
||||||
|
public partial class Patterns
|
||||||
|
{
|
||||||
|
[GeneratedRegex(@"\s+")]
|
||||||
|
public static partial Regex SpaceRegex();
|
||||||
|
|
||||||
|
[GeneratedRegex(@"\A\b[0-9a-fA-F]+\b\Z", RegexOptions.None, matchTimeoutMilliseconds: 100)]
|
||||||
|
public static partial Regex HexHashRegex { get; }
|
||||||
|
|
||||||
|
[GeneratedRegex(@"\A[0-9a-fA-F]{32}\Z", RegexOptions.None, matchTimeoutMilliseconds: 100)]
|
||||||
|
public static partial Regex Md5Regex { get; }
|
||||||
|
|
||||||
|
[GeneratedRegex(@"\A[0-9a-fA-F]{64}\Z", RegexOptions.None, matchTimeoutMilliseconds: 100)]
|
||||||
|
public static partial Regex Sha256Regex { get; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
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.Tools;
|
||||||
|
using PostFundManagement.Application.Services.Users;
|
||||||
|
using PostFundManagement.Domain.Abstractions;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Application.Extensions;
|
||||||
|
|
||||||
|
public static class Services
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddRegisterServicesWithCaching(this IServiceCollection services, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
services.AddScoped<ICommunicationsService, CommunicationsService>();
|
||||||
|
services.Decorate<ICommunicationsService, CommunicationsCacheService>();
|
||||||
|
|
||||||
|
services.AddScoped<IEvidenceService, EvidenceService>();
|
||||||
|
services.Decorate<IEvidenceService, EvidenceCacheService>();
|
||||||
|
|
||||||
|
services.AddScoped<IUserService, UserService>();
|
||||||
|
services.Decorate<IUserService, UserCacheService>();
|
||||||
|
|
||||||
|
services.AddScoped<IIdentityService, IdentityService>();
|
||||||
|
services.Decorate<IIdentityService, IdentityCacheService>();
|
||||||
|
|
||||||
|
services.AddScoped<IExecutionService, ExecutionService>();
|
||||||
|
services.Decorate<IExecutionService, ExecutionCacheService>();
|
||||||
|
|
||||||
|
services.AddScoped<IGovernanceService, GovernanceService>();
|
||||||
|
services.Decorate<IGovernanceService, GovernanceCacheService>();
|
||||||
|
|
||||||
|
services.AddScoped<IGrantsService, GrantsService>();
|
||||||
|
services.Decorate<IGrantsService, GrantsCacheService>();
|
||||||
|
|
||||||
|
services.AddScoped<IProjectService, ProjectService>();
|
||||||
|
services.Decorate<IProjectService, ProjectCacheService>();
|
||||||
|
|
||||||
|
services.AddScoped<IToolService, ToolService>();
|
||||||
|
services.Decorate<IToolService, ToolCacheService>();
|
||||||
|
|
||||||
|
services.AddStackExchangeRedisCache(options =>
|
||||||
|
{
|
||||||
|
options.Configuration = configuration.GetConnectionString("Redis");
|
||||||
|
options.InstanceName = "PFM-API_";
|
||||||
|
});
|
||||||
|
|
||||||
|
services.AddHybridCache(options => options.DefaultEntryOptions = new HybridCacheEntryOptions
|
||||||
|
{
|
||||||
|
Expiration = TimeSpan.FromMinutes(2),
|
||||||
|
LocalCacheExpiration = TimeSpan.FromMinutes(30)
|
||||||
|
});
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IServiceCollection AddSharedServices(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
var serviceType = typeof(IService);
|
||||||
|
|
||||||
|
var sharedImplementations = typeof(IApplication).Assembly.GetTypes()
|
||||||
|
.Where(t => serviceType.IsAssignableFrom(t) && t.IsClass && !t.IsAbstract);
|
||||||
|
|
||||||
|
foreach (var sharedImplementation in sharedImplementations) services.AddScoped(sharedImplementation);
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
using PostFundManagement.Application.Services.Shared;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using static PostFundManagement.Application.Extensions.General;
|
using static PostFundManagement.Application.Extensions.General;
|
||||||
using static PostFundManagement.Domain.Extensions.Constants;
|
using static PostFundManagement.Domain.Extensions.Constants;
|
||||||
|
|
||||||
namespace PostFundManagement.Application.Filters;
|
namespace PostFundManagement.Application.Filters;
|
||||||
|
|
||||||
public sealed class ActiveUserFilter(IdentityService identityService) : IEndpointFilter
|
public sealed class ActiveUserFilter(IIdentityService identityService) : IEndpointFilter
|
||||||
{
|
{
|
||||||
public async ValueTask<object?> InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next)
|
public async ValueTask<object?> InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,6 +9,14 @@
|
|||||||
<PackageLicenseFile>..\LICENSE</PackageLicenseFile>
|
<PackageLicenseFile>..\LICENSE</PackageLicenseFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<NoWarn>1701;1702;AV0029;AV0030;</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
|
<NoWarn>1701;1702;AV0029;AV0030;</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\PostFundManagement.Domain\PostFundManagement.Domain.csproj" />
|
<ProjectReference Include="..\PostFundManagement.Domain\PostFundManagement.Domain.csproj" />
|
||||||
<ProjectReference Include="..\PostFundManagement.Infrastructure\PostFundManagement.Infrastructure.csproj" />
|
<ProjectReference Include="..\PostFundManagement.Infrastructure\PostFundManagement.Infrastructure.csproj" />
|
||||||
@@ -17,6 +25,7 @@
|
|||||||
<!-- API Documentation -->
|
<!-- API Documentation -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.11" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.11" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Validation" Version="10.0.11" />
|
||||||
<PackageReference Include="Scalar.AspNetCore" Version="2.17.2" />
|
<PackageReference Include="Scalar.AspNetCore" Version="2.17.2" />
|
||||||
|
|
||||||
<Using Include="Scalar.AspNetCore" />
|
<Using Include="Scalar.AspNetCore" />
|
||||||
@@ -26,6 +35,10 @@
|
|||||||
|
|
||||||
<!-- Shared Usings -->
|
<!-- Shared Usings -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Using Include="Humanizer" />
|
||||||
|
<Using Include="System.ComponentModel.DataAnnotations" />
|
||||||
|
<Using Include="Microsoft.Extensions.Caching.Distributed" />
|
||||||
|
<Using Include="Microsoft.Extensions.Caching.Hybrid" />
|
||||||
<Using Include="System.IdentityModel.Tokens.Jwt" />
|
<Using Include="System.IdentityModel.Tokens.Jwt" />
|
||||||
<Using Include="Asp.Versioning" />
|
<Using Include="Asp.Versioning" />
|
||||||
<Using Include="System.Security.Claims" />
|
<Using Include="System.Security.Claims" />
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
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, IDistributedCache cache) : ServiceCacheBase, ICommunicationsService
|
||||||
|
{
|
||||||
|
public async ValueTask<Result<Invite>> GetApplicantInviteAsync(Guid applicantUserId, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Invite>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getapplicantinvite-{applicantUserId}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetApplicantInviteAsync(applicantUserId, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached!.FromJson<Invite>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Invite[]>> GetApplicantInvitesAsync(Guid applicantUserId, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Invite[]>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getapplicantinvites-{applicantUserId}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if(string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetApplicantInvitesAsync(applicantUserId, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Invite[]>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Invite[]>> GetInvitesAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Invite[]>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getinvites-{pagination.Page}-{pagination.PageSize}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetInvitesAsync(pagination, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return Result.Ok(result.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Invite[]>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Invite>> SendInviteAsync(InviteRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.SendInviteAsync(request, userId, cancellationToken);
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
using PostFundManagement.Domain.Models;
|
using PostFundManagement.Domain.Models;
|
||||||
@@ -7,7 +7,7 @@ using PostFundManagement.Infrastructure.Database;
|
|||||||
|
|
||||||
namespace PostFundManagement.Application.Services.Communications;
|
namespace PostFundManagement.Application.Services.Communications;
|
||||||
|
|
||||||
public sealed class CommunicationsService(IDbContextFactory<ApplicationDbContext> contextFactory) : IService
|
public sealed class CommunicationsService(IDbContextFactory<ApplicationDbContext> contextFactory) : ICommunicationsService
|
||||||
{
|
{
|
||||||
public async ValueTask<Result<Invite>> SendInviteAsync(InviteRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
public async ValueTask<Result<Invite>> SendInviteAsync(InviteRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
await Result.Try((Func<ValueTask<Result<Invite>>>)(async () =>
|
await Result.Try((Func<ValueTask<Result<Invite>>>)(async () =>
|
||||||
@@ -38,9 +38,8 @@ public sealed class CommunicationsService(IDbContextFactory<ApplicationDbContext
|
|||||||
CreatedAt = DateTime.UtcNow
|
CreatedAt = DateTime.UtcNow
|
||||||
});
|
});
|
||||||
|
|
||||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New)
|
||||||
? Result.Ok(invite.Map())
|
.ToResult(invite.Map());
|
||||||
: Result.Fail<Invite>(CreateError.New);
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async ValueTask<Result<Invite[]>> GetInvitesAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
|
public async ValueTask<Result<Invite[]>> GetInvitesAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
|
||||||
@@ -57,15 +56,27 @@ public sealed class CommunicationsService(IDbContextFactory<ApplicationDbContext
|
|||||||
return Result.Ok(invites.Select(i => i.Map()).ToArray());
|
return Result.Ok(invites.Select(i => i.Map()).ToArray());
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async ValueTask<Result<Invite>> GetApplicantInviteAsync(Guid userId, CancellationToken cancellationToken) =>
|
public async ValueTask<Result<Invite>> GetApplicantInviteAsync(Guid applicantUserId, CancellationToken cancellationToken) =>
|
||||||
await Result.Try((Func<ValueTask<Result<Invite>>>)(async () =>
|
await Result.Try((Func<ValueTask<Result<Invite>>>)(async () =>
|
||||||
{
|
{
|
||||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
var invite = await context.Invites.AsNoTracking().FirstOrDefaultAsync(i => i.Recipient == userId, cancellationToken);
|
var invite = await context.Invites.AsNoTracking().FirstOrDefaultAsync(i => i.Recipient == applicantUserId, cancellationToken);
|
||||||
|
|
||||||
return invite is not null
|
return Result.FailIf(invite is null, NotFoundError.New)
|
||||||
? Result.Ok(invite.Map())
|
.ToResult(invite!.Map());
|
||||||
: Result.Fail<Invite>(NotFoundError.New);
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Invite[]>> GetApplicantInvitesAsync(Guid applicantUserId, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Invite[]>>>)(async () =>
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var invites = await context.Invites.AsNoTracking()
|
||||||
|
.Where(i => i.Recipient == applicantUserId)
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
return Result.Ok(invites.Select(i => i.Map()).ToArray());
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
|
using static PostFundManagement.Domain.Extensions.Constants;
|
||||||
|
|
||||||
namespace PostFundManagement.Application.Services.Communications;
|
namespace PostFundManagement.Application.Services.Communications;
|
||||||
|
|
||||||
public record InviteRequest(long OrganisationId, long InvitedOrganisationId, long AwardId, long ContractId, Guid Recipient, string Message, NotificationPlatform Platform);
|
public record InviteRequest([Required] long OrganisationId,
|
||||||
|
[Required] long InvitedOrganisationId,
|
||||||
|
[Required] long AwardId,
|
||||||
|
[Required] long ContractId,
|
||||||
|
[Required] Guid Recipient,
|
||||||
|
[Required][MaxLength(LabelLength)] string Message,
|
||||||
|
[Required] NotificationPlatform Platform);
|
||||||
|
|||||||
@@ -0,0 +1,152 @@
|
|||||||
|
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, IDistributedCache cache) : ServiceCacheBase, IEvidenceService
|
||||||
|
{
|
||||||
|
public async ValueTask<Result> CreateEvidenceAsync(Guid userId, IFormCollection form, IFormFile file, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.CreateEvidenceAsync(userId, form, file, cancellationToken);
|
||||||
|
|
||||||
|
public async ValueTask<Result> CreateIndicatorAsync(CreateIndicatorRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.CreateIndicatorAsync(request, userId, cancellationToken);
|
||||||
|
|
||||||
|
public async ValueTask<Result> CreateMilestoneAsync(CreateMilestoneRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.CreateMilestoneAsync(request, userId, cancellationToken);
|
||||||
|
|
||||||
|
public async ValueTask<Result<Domain.Models.Evidence>> GetEvidenceAsync(string evidenceId, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Domain.Models.Evidence>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getevidence-{evidenceId}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetEvidenceAsync(evidenceId, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Domain.Models.Evidence>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Domain.Models.Evidence[]>> GetEvidenceFilesAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Domain.Models.Evidence[]>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getevidencefiles-{pagination.Page}-{pagination.PageSize}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetEvidenceFilesAsync(pagination, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Domain.Models.Evidence[]>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Indicator>> GetIndicatorAsync(string indicatorId, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Indicator>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getindicator-{indicatorId}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetIndicatorAsync(indicatorId, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Indicator>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Indicator[]>> GetIndicatorsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Indicator[]>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getindicators-{pagination.Page}-{pagination.PageSize}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetIndicatorsAsync(pagination, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Indicator[]>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Domain.Models.Evidence[]>> GetMilestoneEvidencesAsync(string milestoneIdHash, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Domain.Models.Evidence[]>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getmilestoneevidences-{milestoneIdHash}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if(string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetMilestoneEvidencesAsync(milestoneIdHash, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Domain.Models.Evidence[]>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Domain.Models.Evidence[]>> GetProjectEvidencesAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Domain.Models.Evidence[]>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getprojectevidences-{projectIdHash}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if(string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetProjectEvidencesAsync(projectIdHash, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Domain.Models.Evidence[]>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result> RecordIndicatorActualAmountAsync(string indicatorIdHash, decimal amount, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.RecordIndicatorActualAmountAsync(indicatorIdHash, amount, userId, cancellationToken);
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdateEvidenceAsync(UpdateEvidenceRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.UpdateEvidenceAsync(request, userId, cancellationToken);
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using PostFundManagement.Application.Services.Shared;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Services.Shared;
|
||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
using PostFundManagement.Domain.Abstractions;
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
@@ -9,7 +10,7 @@ using PostFundManagement.Infrastructure.Database;
|
|||||||
namespace PostFundManagement.Application.Services.Evidence;
|
namespace PostFundManagement.Application.Services.Evidence;
|
||||||
|
|
||||||
public sealed class EvidenceService(IDbContextFactory<ApplicationDbContext> contextFactory, HashService hashService,
|
public sealed class EvidenceService(IDbContextFactory<ApplicationDbContext> contextFactory, HashService hashService,
|
||||||
[FromKeyedServices(Constants.EvidenceBucketName)] IS3Service s3Service) : IService
|
[FromKeyedServices(Constants.EvidenceBucketName)] IS3Service s3Service) : IEvidenceService
|
||||||
{
|
{
|
||||||
public async ValueTask<Result> CreateEvidenceAsync(Guid userId, IFormCollection form, IFormFile file, CancellationToken cancellationToken = default) =>
|
public async ValueTask<Result> CreateEvidenceAsync(Guid userId, IFormCollection form, IFormFile file, CancellationToken cancellationToken = default) =>
|
||||||
await Result.Try((Func<ValueTask<Result>>)(async () =>
|
await Result.Try((Func<ValueTask<Result>>)(async () =>
|
||||||
@@ -46,7 +47,7 @@ public sealed class EvidenceService(IDbContextFactory<ApplicationDbContext> cont
|
|||||||
|
|
||||||
context.Evidences.Add(evidence);
|
context.Evidences.Add(evidence);
|
||||||
|
|
||||||
return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New);
|
return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async ValueTask<Result> RecordIndicatorActualAmountAsync(string indicatorIdHash, decimal amount, Guid userId, CancellationToken cancellationToken = default) =>
|
public async ValueTask<Result> RecordIndicatorActualAmountAsync(string indicatorIdHash, decimal amount, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
@@ -65,7 +66,7 @@ public sealed class EvidenceService(IDbContextFactory<ApplicationDbContext> cont
|
|||||||
.SetProperty(f => f.ActualAmount, amount)
|
.SetProperty(f => f.ActualAmount, amount)
|
||||||
.SetProperty(f => f.CreatedBy, userId), cancellationToken);
|
.SetProperty(f => f.CreatedBy, userId), cancellationToken);
|
||||||
|
|
||||||
return Result.FailIf(changedTotal <= 0, UpdateError.New);
|
return Result.OkIf(changedTotal > 0, UpdateError.New);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async ValueTask<Result<Indicator[]>> GetIndicatorsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
|
public async ValueTask<Result<Indicator[]>> GetIndicatorsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
|
||||||
@@ -101,6 +102,9 @@ public sealed class EvidenceService(IDbContextFactory<ApplicationDbContext> cont
|
|||||||
{
|
{
|
||||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Users.AnyAsync(u => u.Id == userId, cancellationToken))
|
||||||
|
return Result.Fail(NotFoundError.New);
|
||||||
|
|
||||||
if (!await context.Projects.AnyAsync(p => p.Id == request.ProjectId, cancellationToken))
|
if (!await context.Projects.AnyAsync(p => p.Id == request.ProjectId, cancellationToken))
|
||||||
return Result.Fail(NotFoundError.New);
|
return Result.Fail(NotFoundError.New);
|
||||||
|
|
||||||
@@ -115,7 +119,8 @@ public sealed class EvidenceService(IDbContextFactory<ApplicationDbContext> cont
|
|||||||
CreatedAt = DateTime.UtcNow
|
CreatedAt = DateTime.UtcNow
|
||||||
});
|
});
|
||||||
|
|
||||||
return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New);
|
return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0,
|
||||||
|
CreateError.Create("No record could be created."));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async ValueTask<Result> CreateIndicatorAsync(CreateIndicatorRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
public async ValueTask<Result> CreateIndicatorAsync(CreateIndicatorRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
@@ -138,7 +143,7 @@ public sealed class EvidenceService(IDbContextFactory<ApplicationDbContext> cont
|
|||||||
CreatedAt = DateTime.UtcNow
|
CreatedAt = DateTime.UtcNow
|
||||||
});
|
});
|
||||||
|
|
||||||
return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New);
|
return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async ValueTask<Result<Indicator>> GetIndicatorAsync(string indicatorId, CancellationToken cancellationToken) =>
|
public async ValueTask<Result<Indicator>> GetIndicatorAsync(string indicatorId, CancellationToken cancellationToken) =>
|
||||||
@@ -154,9 +159,8 @@ public sealed class EvidenceService(IDbContextFactory<ApplicationDbContext> cont
|
|||||||
|
|
||||||
var indicator = await context.Indicators.AsNoTracking().FirstOrDefaultAsync(i => i.Id == decodeResult.Value, cancellationToken);
|
var indicator = await context.Indicators.AsNoTracking().FirstOrDefaultAsync(i => i.Id == decodeResult.Value, cancellationToken);
|
||||||
|
|
||||||
return indicator is not null
|
return Result.FailIf(indicator is null, NotFoundError.New)
|
||||||
? Result.Ok(indicator.Map())
|
.ToResult(indicator!.Map());
|
||||||
: Result.Fail(NotFoundError.New);
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async ValueTask<Result<Domain.Models.Evidence>> GetEvidenceAsync(string evidenceId, CancellationToken cancellationToken = default) =>
|
public async ValueTask<Result<Domain.Models.Evidence>> GetEvidenceAsync(string evidenceId, CancellationToken cancellationToken = default) =>
|
||||||
@@ -172,9 +176,8 @@ public sealed class EvidenceService(IDbContextFactory<ApplicationDbContext> cont
|
|||||||
|
|
||||||
var evidence = await context.Evidences.AsNoTracking().FirstOrDefaultAsync(e => e.Id == decodeResult.Value, cancellationToken);
|
var evidence = await context.Evidences.AsNoTracking().FirstOrDefaultAsync(e => e.Id == decodeResult.Value, cancellationToken);
|
||||||
|
|
||||||
return evidence is not null
|
return Result.FailIf(evidence is null, NotFoundError.New)
|
||||||
? Result.Ok(evidence.Map())
|
.ToResult(evidence!.Map());
|
||||||
: Result.Fail<Domain.Models.Evidence>(NotFoundError.New);
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async ValueTask<Result<Domain.Models.Evidence[]>> GetMilestoneEvidencesAsync(string milestoneIdHash, CancellationToken cancellationToken = default) =>
|
public async ValueTask<Result<Domain.Models.Evidence[]>> GetMilestoneEvidencesAsync(string milestoneIdHash, CancellationToken cancellationToken = default) =>
|
||||||
@@ -217,8 +220,22 @@ public sealed class EvidenceService(IDbContextFactory<ApplicationDbContext> cont
|
|||||||
return Result.Ok(evidences.Select(e => e.Map()).ToArray());
|
return Result.Ok(evidences.Select(e => e.Map()).ToArray());
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async Task<Result> UpdateEvidenceAsync(UpdateEvidenceRequest request, Guid userId, CancellationToken cancellationToken)
|
public async ValueTask<Result> UpdateEvidenceAsync(UpdateEvidenceRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result>>)(async () =>
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
}
|
|
||||||
|
if (!await context.Evidences.AnyAsync(e => e.Id == request.EvidenceId, cancellationToken))
|
||||||
|
return Result.Fail(NotFoundError.New);
|
||||||
|
|
||||||
|
var changedTotal = await context.Evidences.Where(e => e.Id == request.EvidenceId)
|
||||||
|
.ExecuteUpdateAsync(f => f
|
||||||
|
.SetProperty(f => f.Version, request.Version)
|
||||||
|
.SetProperty(f => f.Type, request.EvidenceType)
|
||||||
|
.SetProperty(f => f.Status, request.Status)
|
||||||
|
.SetProperty(f => f.UpdatedBy, userId)
|
||||||
|
.SetProperty(f => f.UpdatedAt, DateTime.UtcNow), cancellationToken);
|
||||||
|
|
||||||
|
return Result.OkIf(changedTotal > 0, UpdateError.New);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,22 @@
|
|||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
|
using static PostFundManagement.Domain.Extensions.Constants;
|
||||||
|
|
||||||
namespace PostFundManagement.Application.Services.Evidence;
|
namespace PostFundManagement.Application.Services.Evidence;
|
||||||
|
|
||||||
public record UpdateEvidenceRequest(long EvidenceId, int Version, EvidenceType EvidenceType, ApprovalStatus Status);
|
public record UpdateEvidenceRequest([Required] long EvidenceId,
|
||||||
|
[Required] int Version,
|
||||||
|
[Required] EvidenceType EvidenceType,
|
||||||
|
[Required] ApprovalStatus Status);
|
||||||
|
|
||||||
public record RecordActualRequest(decimal ActualAmount);
|
public record RecordActualRequest([Required] decimal ActualAmount);
|
||||||
|
|
||||||
public record CreateMilestoneRequest(long ProjectId, DateTime DueAt, string Name, Priority Priority);
|
public record CreateMilestoneRequest([Required] long ProjectId,
|
||||||
|
[Required] DateTime DueAt,
|
||||||
|
[Required][MaxLength(LabelLength)] string Name,
|
||||||
|
[Required] Priority Priority);
|
||||||
|
|
||||||
public record CreateIndicatorRequest(long ProjectId, string Name, UnitOfMeasure UnitOfMeasure, decimal BaselineAmount, decimal TargetAmount);
|
public record CreateIndicatorRequest([Required] long ProjectId,
|
||||||
|
[Required][MaxLength(LabelLength)] string Name,
|
||||||
|
[Required] UnitOfMeasure UnitOfMeasure,
|
||||||
|
[Required] decimal BaselineAmount,
|
||||||
|
[Required] decimal TargetAmount);
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions;
|
||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Extensions;
|
||||||
|
using PostFundManagement.Application.Services.Shared;
|
||||||
|
using PostFundManagement.Domain;
|
||||||
|
using PostFundManagement.Domain.Models;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Application.Services.Execution;
|
||||||
|
|
||||||
|
public sealed class ExecutionCacheService(ExecutionService service, IDistributedCache cache) : ServiceCacheBase, IExecutionService
|
||||||
|
{
|
||||||
|
public async ValueTask<Result> ApproveDisbursementAsync(string disbursementIdHash, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.ApproveDisbursementAsync(disbursementIdHash, userId, cancellationToken);
|
||||||
|
|
||||||
|
public async ValueTask<Result> CreateDisbursementAsync(CreateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.CreateDisbursementAsync(request, userId, cancellationToken);
|
||||||
|
|
||||||
|
public async ValueTask<Result> CreateRiskAsync(CreateRiskRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.CreateRiskAsync(request, userId, cancellationToken);
|
||||||
|
|
||||||
|
public async ValueTask<Result<Disbursement>> GetDisbursementAsync(string disbursementIdHash, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Disbursement>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getdisbursement-{disbursementIdHash}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetDisbursementAsync(disbursementIdHash, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Disbursement>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Disbursement[]>> GetDisbursementsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Disbursement[]>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getdisbursements-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetDisbursementsAsync(pagination, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Disbursement[]>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Risk>> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Risk>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getrisk-{riskIdHash}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetRiskAsync(riskIdHash, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Risk>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Risk[]>> GetRisksAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Risk[]>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getrisks-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetRisksAsync(pagination, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Risk[]>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdateDisbursementAsync(UpdateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.UpdateDisbursementAsync(request, userId, cancellationToken);
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdateRiskAsync(UpdateRiskRequest request, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.UpdateRiskAsync(request, cancellationToken);
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using PostFundManagement.Application.Services.Shared;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Services.Shared;
|
||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
using PostFundManagement.Domain.Models;
|
using PostFundManagement.Domain.Models;
|
||||||
@@ -8,7 +8,7 @@ using PostFundManagement.Infrastructure.Database;
|
|||||||
|
|
||||||
namespace PostFundManagement.Application.Services.Execution;
|
namespace PostFundManagement.Application.Services.Execution;
|
||||||
|
|
||||||
public sealed class ExecutionService(IDbContextFactory<ApplicationDbContext> contextFactory, HashService hashService) : IService
|
public sealed class ExecutionService(IDbContextFactory<ApplicationDbContext> contextFactory, HashService hashService) : IExecutionService
|
||||||
{
|
{
|
||||||
public async ValueTask<Result<Risk[]>> GetRisksAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
|
public async ValueTask<Result<Risk[]>> GetRisksAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
|
||||||
await Result.Try((Func<ValueTask<Result<Risk[]>>>)(async () =>
|
await Result.Try((Func<ValueTask<Result<Risk[]>>>)(async () =>
|
||||||
@@ -57,7 +57,7 @@ public sealed class ExecutionService(IDbContextFactory<ApplicationDbContext> con
|
|||||||
CreatedAt = DateTime.UtcNow
|
CreatedAt = DateTime.UtcNow
|
||||||
});
|
});
|
||||||
|
|
||||||
return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New);
|
return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async ValueTask<Result> CreateDisbursementAsync(CreateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
public async ValueTask<Result> CreateDisbursementAsync(CreateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
@@ -78,7 +78,7 @@ public sealed class ExecutionService(IDbContextFactory<ApplicationDbContext> con
|
|||||||
CreatedAt = DateTime.UtcNow
|
CreatedAt = DateTime.UtcNow
|
||||||
});
|
});
|
||||||
|
|
||||||
return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New);
|
return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async ValueTask<Result> ApproveDisbursementAsync(string disbursementIdHash, Guid userId, CancellationToken cancellationToken = default) =>
|
public async ValueTask<Result> ApproveDisbursementAsync(string disbursementIdHash, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
@@ -98,7 +98,7 @@ public sealed class ExecutionService(IDbContextFactory<ApplicationDbContext> con
|
|||||||
.SetProperty(f => f.UpdatedBy, userId)
|
.SetProperty(f => f.UpdatedBy, userId)
|
||||||
.SetProperty(f => f.UpdatedAt, DateTime.UtcNow), cancellationToken);
|
.SetProperty(f => f.UpdatedAt, DateTime.UtcNow), cancellationToken);
|
||||||
|
|
||||||
return Result.FailIf(changedTotal <= 0, UpdateError.New);
|
return Result.OkIf(changedTotal > 0, UpdateError.New);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async ValueTask<Result<Disbursement>> GetDisbursementAsync(string disbursementIdHash, CancellationToken cancellationToken) =>
|
public async ValueTask<Result<Disbursement>> GetDisbursementAsync(string disbursementIdHash, CancellationToken cancellationToken) =>
|
||||||
@@ -115,12 +115,11 @@ public sealed class ExecutionService(IDbContextFactory<ApplicationDbContext> con
|
|||||||
var disbursement = await context.Disbursements.AsNoTracking()
|
var disbursement = await context.Disbursements.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(d => d.Id == decodeResult.Value, cancellationToken);
|
.FirstOrDefaultAsync(d => d.Id == decodeResult.Value, cancellationToken);
|
||||||
|
|
||||||
return disbursement is not null
|
return Result.FailIf(disbursement is null, NotFoundError.New)
|
||||||
? Result.Ok(disbursement.Map())
|
.ToResult(disbursement!.Map());
|
||||||
: Result.Fail<Disbursement>(NotFoundError.New);
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async ValueTask<Result<Risk>> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken) =>
|
public async ValueTask<Result<Risk>> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken = default) =>
|
||||||
await Result.Try((Func<ValueTask<Result<Risk>>>)(async () =>
|
await Result.Try((Func<ValueTask<Result<Risk>>>)(async () =>
|
||||||
{
|
{
|
||||||
var decodeResult = hashService.DecodeLongIdHash(riskIdHash);
|
var decodeResult = hashService.DecodeLongIdHash(riskIdHash);
|
||||||
@@ -134,12 +133,11 @@ public sealed class ExecutionService(IDbContextFactory<ApplicationDbContext> con
|
|||||||
var risk = await context.Risks.AsNoTracking()
|
var risk = await context.Risks.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(r => r.Id == decodeResult.Value, cancellationToken);
|
.FirstOrDefaultAsync(r => r.Id == decodeResult.Value, cancellationToken);
|
||||||
|
|
||||||
return risk is not null
|
return Result.FailIf(risk is null, NotFoundError.New)
|
||||||
? Result.Ok(risk.Map())
|
.ToResult(risk!.Map());
|
||||||
: Result.Fail<Risk>(NotFoundError.New);
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async ValueTask<Result> UpdateRiskAsync(UpdateRiskRequest request, CancellationToken cancellationToken) =>
|
public async ValueTask<Result> UpdateRiskAsync(UpdateRiskRequest request, CancellationToken cancellationToken = default) =>
|
||||||
await Result.Try((Func<ValueTask<Result>>)(async () =>
|
await Result.Try((Func<ValueTask<Result>>)(async () =>
|
||||||
{
|
{
|
||||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
@@ -152,10 +150,10 @@ public sealed class ExecutionService(IDbContextFactory<ApplicationDbContext> con
|
|||||||
.SetProperty(u => u.Likelihood, request.Likelihood)
|
.SetProperty(u => u.Likelihood, request.Likelihood)
|
||||||
.SetProperty(u => u.Impact, request.Impact), cancellationToken);
|
.SetProperty(u => u.Impact, request.Impact), cancellationToken);
|
||||||
|
|
||||||
return Result.FailIf(changedTotal <= 0, UpdateError.New);
|
return Result.OkIf(changedTotal > 0, UpdateError.New);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async ValueTask<Result> UpdateDisbursementAsync(UpdateDisbursementRequest request, Guid userId, CancellationToken cancellationToken) =>
|
public async ValueTask<Result> UpdateDisbursementAsync(UpdateDisbursementRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
await Result.Try((Func<ValueTask<Result>>)(async () =>
|
await Result.Try((Func<ValueTask<Result>>)(async () =>
|
||||||
{
|
{
|
||||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
@@ -168,6 +166,6 @@ public sealed class ExecutionService(IDbContextFactory<ApplicationDbContext> con
|
|||||||
.SetProperty(d => d.UpdatedAt, DateTime.UtcNow)
|
.SetProperty(d => d.UpdatedAt, DateTime.UtcNow)
|
||||||
.SetProperty(d => d.UpdatedBy, userId), cancellationToken);
|
.SetProperty(d => d.UpdatedBy, userId), cancellationToken);
|
||||||
|
|
||||||
return Result.FailIf(changedTotal <= 0, UpdateError.New);
|
return Result.OkIf(changedTotal > 0, UpdateError.New);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,20 @@
|
|||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
|
using static PostFundManagement.Domain.Extensions.Constants;
|
||||||
|
|
||||||
namespace PostFundManagement.Application.Services.Execution;
|
namespace PostFundManagement.Application.Services.Execution;
|
||||||
|
|
||||||
public record UpdateDisbursementRequest(long DisbursementId, long? MilestoneId, decimal Amount);
|
public record UpdateDisbursementRequest([Required] long DisbursementId, long? MilestoneId, [Required] decimal Amount);
|
||||||
|
|
||||||
public record UpdateRiskRequest(long RiskId, RiskLikelihood Likelihood, RiskImpact Impact, string Name, string Description);
|
public record UpdateRiskRequest([Required] long RiskId,
|
||||||
|
[Required] RiskLikelihood Likelihood,
|
||||||
|
[Required] RiskImpact Impact,
|
||||||
|
[Required][MaxLength(LabelLength)] string Name,
|
||||||
|
[Required][MaxLength(TextLength)] string Description);
|
||||||
|
|
||||||
public record CreateDisbursementRequest(long ProjectId, long? MilestoneId, decimal Amount);
|
public record CreateDisbursementRequest([Required] long ProjectId, long? MilestoneId, [Required] decimal Amount);
|
||||||
|
|
||||||
public record CreateRiskRequest(long ProjectId, RiskLikelihood Likelihood, RiskImpact Impact, string Name, string Description);
|
public record CreateRiskRequest([Required] long ProjectId,
|
||||||
|
[Required] RiskLikelihood Likelihood,
|
||||||
|
[Required] RiskImpact Impact,
|
||||||
|
[Required][MaxLength(LabelLength)] string Name,
|
||||||
|
[Required][MaxLength(TextLength)] string Description);
|
||||||
|
|||||||
@@ -0,0 +1,191 @@
|
|||||||
|
using PostFundManagement.Application.Abstractions;
|
||||||
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Extensions;
|
||||||
|
using PostFundManagement.Application.Services.Shared;
|
||||||
|
using PostFundManagement.Domain;
|
||||||
|
using PostFundManagement.Domain.Models;
|
||||||
|
|
||||||
|
namespace PostFundManagement.Application.Services.Governance;
|
||||||
|
|
||||||
|
public sealed class GovernanceCacheService(GovernanceService service, IDistributedCache cache) : ServiceCacheBase, IGovernanceService
|
||||||
|
{
|
||||||
|
public async ValueTask<Result> CreateOrganisationAsync(CreateOrganisationRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.CreateOrganisationAsync(request, userId, cancellationToken);
|
||||||
|
|
||||||
|
public async ValueTask<Result> CreatePortfolioAsync(CreatePortfolioRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.CreatePortfolioAsync(request, userId, cancellationToken);
|
||||||
|
|
||||||
|
public async ValueTask<Result<Dashboard>> GetDashboardAsync(CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Dashboard>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getdashboard").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetDashboardAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Dashboard>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Instrument[]>> GetInstrumentsAsync(string programmeIdHash, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Instrument[]>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getinstruments").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetInstrumentsAsync(programmeIdHash, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Instrument[]>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Organisation>> GetOrganisationAsync(string organisationIdHash, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Organisation>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getorganisation-{organisationIdHash}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetOrganisationAsync(organisationIdHash, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Organisation>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Organisation[]>> GetOrganisationsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Organisation[]>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getorganisations-{pagination.Page}-{pagination.PageSize}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetOrganisationsAsync(pagination, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Organisation[]>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Portfolio[]>> GetPorfoliosAsync(string organisationIdHash, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Portfolio[]>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getportfolios-{organisationIdHash}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetPorfoliosAsync(organisationIdHash, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Portfolio[]>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Portfolio>> GetPortfolioAsync(string portfolioIdHash, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Portfolio>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getportfolio-{portfolioIdHash}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if(string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetPortfolioAsync(portfolioIdHash, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Portfolio>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Programme[]>> GetPortfolioProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Programme[]>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getportfolioprogrammes-{portfolioIdHash}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if(string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetPortfolioProgrammesAsync(portfolioIdHash, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Programme[]>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Programme[]>> GetProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Programme[]>>>)(async () =>
|
||||||
|
{
|
||||||
|
var cacheKey = HashService.ToMd5Hash($"getprogrammes-{portfolioIdHash}").Value;
|
||||||
|
|
||||||
|
var cached = await cache.GetStringAsync(cacheKey, cancellationToken);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(cached))
|
||||||
|
{
|
||||||
|
var result = await service.GetProgrammesAsync(portfolioIdHash, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed) return result;
|
||||||
|
|
||||||
|
await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken);
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(cached.FromJson<Programme[]>());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Organisation>> UpdateOrganisationAsync(UpdateOrganisationRequest request, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.UpdateOrganisationAsync(request, cancellationToken);
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdatePortfolioAsync(UpdatePortfolioRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.UpdatePortfolioAsync(request, userId, cancellationToken);
|
||||||
|
}
|
||||||
@@ -1,31 +1,50 @@
|
|||||||
using PostFundManagement.Application.Services.Shared;
|
using PostFundManagement.Application.Abstractions.Services;
|
||||||
|
using PostFundManagement.Application.Services.Shared;
|
||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
using PostFundManagement.Domain.Abstractions;
|
|
||||||
using PostFundManagement.Domain.Errors;
|
using PostFundManagement.Domain.Errors;
|
||||||
using PostFundManagement.Domain.Extensions;
|
using PostFundManagement.Domain.Extensions;
|
||||||
using PostFundManagement.Domain.Models;
|
using PostFundManagement.Domain.Models;
|
||||||
using PostFundManagement.Infrastructure.Database;
|
using PostFundManagement.Infrastructure.Database;
|
||||||
|
using PostFundManagement.Application.Extensions;
|
||||||
|
|
||||||
namespace PostFundManagement.Application.Services.Governance;
|
namespace PostFundManagement.Application.Services.Governance;
|
||||||
|
|
||||||
public sealed class GovernanceService(IDbContextFactory<ApplicationDbContext> contextFactory, HashService hashService) : IService
|
public sealed class GovernanceService(IDbContextFactory<ApplicationDbContext> contextFactory, HashService hashService) : IGovernanceService
|
||||||
{
|
{
|
||||||
public async ValueTask<Result<Programme[]>> GetProgrammesAsync(CancellationToken cancellationToken = default) =>
|
public async ValueTask<Result<Programme[]>> GetProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default) =>
|
||||||
await Result.Try((Func<ValueTask<Result<Programme[]>>>)(async () =>
|
await Result.Try((Func<ValueTask<Result<Programme[]>>>)(async () =>
|
||||||
{
|
{
|
||||||
|
var decodeResult = hashService.DecodeLongIdHash(portfolioIdHash);
|
||||||
|
|
||||||
|
if (decodeResult.IsFailed)
|
||||||
|
return Result.Fail(IdDecodeError.Create()
|
||||||
|
.CausedBy(decodeResult.Errors));
|
||||||
|
|
||||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
var programmes = await context.Programmes.AsNoTracking().ToListAsync(cancellationToken);
|
var programmes = await context.Programmes.AsNoTracking()
|
||||||
|
.Where(p => p.PortfolioId == decodeResult.Value)
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
return Result.Ok(programmes.Select(p => p.Map()).ToArray());
|
return Result.Ok(programmes.Select(p => p.Map()).ToArray());
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async ValueTask<Result<Portfolio[]>> GetPorfoliosAsync(CancellationToken cancellationToken = default) =>
|
public async ValueTask<Result<Portfolio[]>> GetPorfoliosAsync(string organisationIdHash, CancellationToken cancellationToken = default) =>
|
||||||
await Result.Try((Func<ValueTask<Result<Portfolio[]>>>)(async () =>
|
await Result.Try((Func<ValueTask<Result<Portfolio[]>>>)(async () =>
|
||||||
{
|
{
|
||||||
|
var decodeResult = hashService.DecodeLongIdHash(organisationIdHash);
|
||||||
|
|
||||||
|
if (decodeResult.IsFailed)
|
||||||
|
return Result.Fail(IdDecodeError.Create()
|
||||||
|
.CausedBy(decodeResult.Errors));
|
||||||
|
|
||||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
var portfolios = await context.Portfolios.AsNoTracking().ToListAsync(cancellationToken);
|
var portfolios = await context.Portfolios.AsNoTracking()
|
||||||
|
.Where(f => f.Id == decodeResult.Value)
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
return Result.Ok(portfolios.Select(p => p.Map()).ToArray());
|
return Result.Ok(portfolios.Select(p => p.Map()).ToArray());
|
||||||
}));
|
}));
|
||||||
@@ -58,17 +77,25 @@ public sealed class GovernanceService(IDbContextFactory<ApplicationDbContext> co
|
|||||||
var organisation = await context.Organisations.AsNoTracking()
|
var organisation = await context.Organisations.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(o => o.Id == decodeResult.Value, cancellationToken);
|
.FirstOrDefaultAsync(o => o.Id == decodeResult.Value, cancellationToken);
|
||||||
|
|
||||||
return organisation is not null
|
return Result.FailIf(organisation is null, NotFoundError.New)
|
||||||
? Result.Ok(organisation.Map())
|
.ToResult(organisation!.Map());
|
||||||
: Result.Fail(NotFoundError.New);
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async ValueTask<Result<Instrument[]>> GetInstrumentsAsync(CancellationToken cancellationToken = default) =>
|
public async ValueTask<Result<Instrument[]>> GetInstrumentsAsync(string programmeIdHash, CancellationToken cancellationToken = default) =>
|
||||||
await Result.Try((Func<ValueTask<Result<Instrument[]>>>)(async () =>
|
await Result.Try((Func<ValueTask<Result<Instrument[]>>>)(async () =>
|
||||||
{
|
{
|
||||||
|
var decodeResult = hashService.DecodeLongIdHash(programmeIdHash);
|
||||||
|
|
||||||
|
if (decodeResult.IsFailed)
|
||||||
|
return Result.Fail(IdDecodeError.Create()
|
||||||
|
.CausedBy(decodeResult.Errors));
|
||||||
|
|
||||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
var instruments = await context.Instruments.AsNoTracking().ToListAsync(cancellationToken);
|
var instruments = await context.Instruments.AsNoTracking()
|
||||||
|
.Where(i => i.ProgrammeId == decodeResult.Value)
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
return Result.Ok(instruments.Select(i => i.Map()).ToArray());
|
return Result.Ok(instruments.Select(i => i.Map()).ToArray());
|
||||||
}));
|
}));
|
||||||
@@ -104,21 +131,23 @@ public sealed class GovernanceService(IDbContextFactory<ApplicationDbContext> co
|
|||||||
{
|
{
|
||||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
if (await context.Organisations.AnyAsync(o => o.RegistrationNo == request.RegistrationNo, cancellationToken))
|
var registrationNo = request.RegistrationNo.Clean();
|
||||||
|
|
||||||
|
if (await context.Organisations.AnyAsync(o => o.RegistrationNo == registrationNo, cancellationToken))
|
||||||
return Result.Fail(CreateError.Create("Organisation with the same registration number already exists"));
|
return Result.Fail(CreateError.Create("Organisation with the same registration number already exists"));
|
||||||
|
|
||||||
context.Organisations.Add(new Domain.Entities.Organisation
|
context.Organisations.Add(new Domain.Entities.Organisation
|
||||||
{
|
{
|
||||||
Name = request.Name,
|
Name = request.Name.Humanize(LetterCasing.Title).Trim(),
|
||||||
RegistrationNo = request.RegistrationNo,
|
RegistrationNo = registrationNo,
|
||||||
Email = request.Email,
|
Email = request.Email.ToLower(CultureInfo.InvariantCulture).Clean(),
|
||||||
Type = request.Type,
|
Type = request.Type,
|
||||||
Status = ActivityStatus.Active,
|
Status = ActivityStatus.Active,
|
||||||
CreatedBy = userId,
|
CreatedBy = userId,
|
||||||
CreatedAt = DateTime.UtcNow
|
CreatedAt = DateTime.UtcNow
|
||||||
});
|
});
|
||||||
|
|
||||||
return Result.FailIf(await context.SaveChangesAsync(cancellationToken) <= 0, CreateError.New);
|
return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
public async ValueTask<Result<Organisation>> UpdateOrganisationAsync(UpdateOrganisationRequest request, CancellationToken cancellationToken = default) =>
|
public async ValueTask<Result<Organisation>> UpdateOrganisationAsync(UpdateOrganisationRequest request, CancellationToken cancellationToken = default) =>
|
||||||
@@ -129,11 +158,95 @@ public sealed class GovernanceService(IDbContextFactory<ApplicationDbContext> co
|
|||||||
var changedTotal = await context.Organisations
|
var changedTotal = await context.Organisations
|
||||||
.Where(f => f.Id == request.OrganisationId)
|
.Where(f => f.Id == request.OrganisationId)
|
||||||
.ExecuteUpdateAsync(f => f
|
.ExecuteUpdateAsync(f => f
|
||||||
.SetProperty(u => u.Name, request.Name)
|
.SetProperty(u => u.Name, request.Name.Humanize(LetterCasing.Title).Trim())
|
||||||
.SetProperty(u => u.RegistrationNo, request.RegistrationNo)
|
.SetProperty(u => u.RegistrationNo, request.RegistrationNo.Clean())
|
||||||
.SetProperty(u => u.Email, request.Email)
|
.SetProperty(u => u.Email, request.Email.ToLower(CultureInfo.InvariantCulture).Clean())
|
||||||
.SetProperty(u => u.Type, request.Type), cancellationToken);
|
.SetProperty(u => u.Type, request.Type), cancellationToken);
|
||||||
|
|
||||||
return Result.FailIf(changedTotal <= 0, UpdateError.New);
|
return Result.OkIf(changedTotal > 0, UpdateError.New);
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result> CreatePortfolioAsync(CreatePortfolioRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result>>)(async () =>
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Users.AnyAsync(u => u.Id == request.OwnerId, cancellationToken))
|
||||||
|
return Result.Fail(NotFoundError.Create("Owner user not found"));
|
||||||
|
|
||||||
|
if (!await context.Organisations.AnyAsync(u => u.Id == request.OrganisationId, cancellationToken))
|
||||||
|
return Result.Fail(NotFoundError.Create("Organisation not found"));
|
||||||
|
|
||||||
|
var name = request.Name.Humanize(LetterCasing.Title).Trim();
|
||||||
|
|
||||||
|
if (await context.Portfolios.AnyAsync(p => p.Name == name && p.OrganisationId == request.OrganisationId, cancellationToken))
|
||||||
|
return Result.Fail(ValidationError.Create("A portfolio with the same name exists in this organisation"));
|
||||||
|
|
||||||
|
context.Portfolios.Add(new Domain.Entities.Portfolio
|
||||||
|
{
|
||||||
|
CreatedAt = DateTime.UtcNow,
|
||||||
|
CreatedBy = userId,
|
||||||
|
OrganisationId = request.OrganisationId,
|
||||||
|
OwnedBy = request.OwnerId,
|
||||||
|
Name = name,
|
||||||
|
Description = request.Description.Humanize(LetterCasing.Sentence).Trim()
|
||||||
|
});
|
||||||
|
|
||||||
|
return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New);
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdatePortfolioAsync(UpdatePortfolioRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result>>)(async () =>
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Users.AnyAsync(u => u.Id == request.OwnerId, cancellationToken))
|
||||||
|
return Result.Fail(NotFoundError.Create("Owner user not found"));
|
||||||
|
|
||||||
|
var changedTotal = await context.Portfolios
|
||||||
|
.Where(p => p.Id == request.PortfolioId)
|
||||||
|
.ExecuteUpdateAsync(f => f
|
||||||
|
.SetProperty(u => u.Name, request.Name.Humanize(LetterCasing.Title).Trim())
|
||||||
|
.SetProperty(u => u.OwnedBy, request.OwnerId)
|
||||||
|
.SetProperty(u => u.Description, request.Description.Humanize(LetterCasing.Sentence).Trim()), cancellationToken);
|
||||||
|
|
||||||
|
return Result.OkIf(changedTotal > 0, UpdateError.Create("Nothing was saved, no change detected."));
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Programme[]>> GetPortfolioProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Programme[]>>>)(async () =>
|
||||||
|
{
|
||||||
|
var decodeResult = hashService.DecodeLongIdHash(portfolioIdHash);
|
||||||
|
|
||||||
|
if (decodeResult.IsFailed)
|
||||||
|
return Result.Fail(IdDecodeError.Create()
|
||||||
|
.CausedBy(decodeResult.Errors));
|
||||||
|
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var programmes = await context.Programmes.AsNoTracking()
|
||||||
|
.Where(f => f.PortfolioId == decodeResult.Value)
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
return Result.Ok(programmes.Select(p => p.Map()).ToArray());
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async ValueTask<Result<Portfolio>> GetPortfolioAsync(string portfolioIdHash, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<ValueTask<Result<Portfolio>>>)(async () =>
|
||||||
|
{
|
||||||
|
var decodeResult = hashService.DecodeLongIdHash(portfolioIdHash);
|
||||||
|
|
||||||
|
if (decodeResult.IsFailed)
|
||||||
|
return Result.Fail(IdDecodeError.Create()
|
||||||
|
.CausedBy(decodeResult.Errors));
|
||||||
|
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var portfolio = await context.Portfolios.AsNoTracking()
|
||||||
|
.FirstOrDefaultAsync(p => p.Id == decodeResult.Value, cancellationToken);
|
||||||
|
|
||||||
|
return Result.FailIf(portfolio is null, NotFoundError.New)
|
||||||
|
.ToResult(portfolio!.Map());
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,32 @@
|
|||||||
using PostFundManagement.Domain;
|
using PostFundManagement.Domain;
|
||||||
|
using static PostFundManagement.Domain.Extensions.Constants;
|
||||||
|
|
||||||
namespace PostFundManagement.Application.Services.Governance;
|
namespace PostFundManagement.Application.Services.Governance;
|
||||||
|
|
||||||
public record UpdateOrganisationRequest(long OrganisationId, string Name, string RegistrationNo, string Email, OrganisationType Type);
|
public record UpdatePortfolioRequest([Required] long PortfolioId,
|
||||||
|
[Required][MaxLength(LabelLength)] string Name,
|
||||||
|
[Required][MaxLength(TextLength)] string Description,
|
||||||
|
[Required] Guid OwnerId);
|
||||||
|
|
||||||
public record CreateOrganisationRequest(string Name, string RegistrationNo, string Email, OrganisationType Type);
|
public record CreatePortfolioRequest([Required][MaxLength(LabelLength)] string Name,
|
||||||
|
[Required][MaxLength(TextLength)] string Description,
|
||||||
|
[Required] long OrganisationId,
|
||||||
|
[Required] Guid OwnerId);
|
||||||
|
|
||||||
public record Dashboard(decimal PortfolioValue, int ActiveAwards, decimal Disbursed, double OnTrackPercentage, int AtRiskCount, int BeneficiariesReached);
|
public record UpdateOrganisationRequest([Required] long OrganisationId,
|
||||||
|
[Required][MaxLength(LabelLength)] string Name,
|
||||||
|
[Required][MaxLength(LabelLength)] string RegistrationNo,
|
||||||
|
[Required][EmailAddress][MaxLength(LabelLength)] string Email,
|
||||||
|
[Required] OrganisationType Type);
|
||||||
|
|
||||||
|
public record CreateOrganisationRequest([Required][MaxLength(LabelLength)] string Name,
|
||||||
|
[Required][MaxLength(LabelLength)] string RegistrationNo,
|
||||||
|
[Required][EmailAddress][MaxLength(LabelLength)] string Email,
|
||||||
|
[Required] OrganisationType Type = OrganisationType.PrivateLimitedCompany);
|
||||||
|
|
||||||
|
public record Dashboard([Required] decimal PortfolioValue,
|
||||||
|
[Required] int ActiveAwards,
|
||||||
|
[Required] decimal Disbursed,
|
||||||
|
[Required] double OnTrackPercentage,
|
||||||
|
[Required] int AtRiskCount,
|
||||||
|
[Required] int BeneficiariesReached);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user