Added missing instrument endpoints #96
@@ -0,0 +1,36 @@
|
|||||||
|
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 CreateInstrumentEndpoint : IEndpoint
|
||||||
|
{
|
||||||
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
|
{
|
||||||
|
builder.MapPost("api/governance/instruments", async (CreateInstrumentRequest request, HttpContext context,
|
||||||
|
IGovernanceService service, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.CreateInstrumentAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
|
{
|
||||||
|
{ IsSuccess: true} => Results.Ok(),
|
||||||
|
var r when r.HasError<CreateError>() => Results.BadRequest(r.Errors.ToProblems()),
|
||||||
|
var r => Results.InternalServerError(r.Errors.ToProblems())
|
||||||
|
})
|
||||||
|
.WithDescription("Creates a new programme funding instrument")
|
||||||
|
.RequireAuthorization(Constants.MainScope)
|
||||||
|
.WithName(typeof(CreateInstrumentEndpoint).ToEndpointName())
|
||||||
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
|
.Produces(StatusCodes.Status200OK)
|
||||||
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
|
.Produces<Problems>(StatusCodes.Status400BadRequest)
|
||||||
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
|
.WithTags(EndpointTags.Governance)
|
||||||
|
.CacheOutput();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
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 UpdateInstrumentEndpoint : IEndpoint
|
||||||
|
{
|
||||||
|
public void Map(IEndpointRouteBuilder builder)
|
||||||
|
{
|
||||||
|
builder.MapPut("api/governance/instruments", async (UpdateInstrumentRequest request, HttpContext context,
|
||||||
|
IGovernanceService service, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.UpdateInstrumentAsync(request, context.GetUserId(), cancellationToken) switch
|
||||||
|
{
|
||||||
|
{ IsSuccess: true } => Results.Ok(),
|
||||||
|
var r when r.HasError<UpdateError>() => Results.BadRequest(r.Errors.ToProblems()),
|
||||||
|
var r => Results.InternalServerError(r.Errors.ToProblems()),
|
||||||
|
})
|
||||||
|
.WithDescription("Updates a programme funding instrument")
|
||||||
|
.RequireAuthorization(Constants.MainScope)
|
||||||
|
.WithName(typeof(UpdateInstrumentEndpoint).ToEndpointName())
|
||||||
|
.MapToApiVersion(new ApiVersion(1))
|
||||||
|
.Produces(StatusCodes.Status200OK)
|
||||||
|
.Produces(StatusCodes.Status401Unauthorized)
|
||||||
|
.Produces<Problems>(StatusCodes.Status400BadRequest)
|
||||||
|
.Produces<Problems>(StatusCodes.Status500InternalServerError)
|
||||||
|
.WithTags(EndpointTags.Governance)
|
||||||
|
.CacheOutput();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,14 @@ namespace PostFundManagement.Application.Abstractions.Services;
|
|||||||
|
|
||||||
public interface IGovernanceService
|
public interface IGovernanceService
|
||||||
{
|
{
|
||||||
|
[Log]
|
||||||
|
[Audit]
|
||||||
|
Task<Result> UpdateInstrumentAsync(UpdateInstrumentRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
[Log]
|
||||||
|
[Audit]
|
||||||
|
Task<Result> CreateInstrumentAsync(CreateInstrumentRequest request, Guid userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
[Log]
|
[Log]
|
||||||
Task<Result<Programme[]>> GetProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default);
|
Task<Result<Programme[]>> GetProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ namespace PostFundManagement.Application.Services.Governance;
|
|||||||
public sealed class GovernanceCacheService(GovernanceService service, IDistributedCache cache,
|
public sealed class GovernanceCacheService(GovernanceService service, IDistributedCache cache,
|
||||||
IFeatureManager featureManager) : ServiceCacheBase, IGovernanceService
|
IFeatureManager featureManager) : ServiceCacheBase, IGovernanceService
|
||||||
{
|
{
|
||||||
|
public async Task<Result> CreateInstrumentAsync(CreateInstrumentRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.CreateInstrumentAsync(request, userId, cancellationToken);
|
||||||
|
|
||||||
public async Task<Result> CreateOrganisationAsync(CreateOrganisationRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
public async Task<Result> CreateOrganisationAsync(CreateOrganisationRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
await service.CreateOrganisationAsync(request, userId, cancellationToken);
|
await service.CreateOrganisationAsync(request, userId, cancellationToken);
|
||||||
|
|
||||||
@@ -311,6 +314,9 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
|
|||||||
return Result.Ok(cached.FromJson<Tenant[]>());
|
return Result.Ok(cached.FromJson<Tenant[]>());
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
public async Task<Result> UpdateInstrumentAsync(UpdateInstrumentRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await service.UpdateInstrumentAsync(request, userId, cancellationToken);
|
||||||
|
|
||||||
public async Task<Result<Organisation>> UpdateOrganisationAsync(UpdateOrganisationRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
public async Task<Result<Organisation>> UpdateOrganisationAsync(UpdateOrganisationRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
await service.UpdateOrganisationAsync(request, userId, cancellationToken);
|
await service.UpdateOrganisationAsync(request, userId, cancellationToken);
|
||||||
|
|
||||||
|
|||||||
@@ -435,4 +435,40 @@ public sealed class GovernanceService(IDbContextFactory<ApplicationDbContext> co
|
|||||||
return Result.FailIf(tenantOrganisation is null, NotFoundError.Create("Failed to find tenant organisation map"))
|
return Result.FailIf(tenantOrganisation is null, NotFoundError.Create("Failed to find tenant organisation map"))
|
||||||
.ToResult(tenantOrganisation!.Map());
|
.ToResult(tenantOrganisation!.Map());
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
public async Task<Result> UpdateInstrumentAsync(UpdateInstrumentRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<Task<Result>>)(async () =>
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var changedTotal = await context.Instruments
|
||||||
|
.Where(i => i.Id == request.InstructionId)
|
||||||
|
.ExecuteUpdateAsync(f => f
|
||||||
|
.SetProperty(u => u.Name, request.Name.Humanize(LetterCasing.Title).Trim())
|
||||||
|
.SetProperty(u => u.Code, request.Code)
|
||||||
|
.SetProperty(u => u.Description, request.Description)
|
||||||
|
.SetProperty(u => u.Status, request.Status), cancellationToken);
|
||||||
|
|
||||||
|
return Result.OkIf(changedTotal > 0, UpdateError.Create("Failed to update instrument"));
|
||||||
|
}));
|
||||||
|
|
||||||
|
public async Task<Result> CreateInstrumentAsync(CreateInstrumentRequest request, Guid userId, CancellationToken cancellationToken = default) =>
|
||||||
|
await Result.Try((Func<Task<Result>>)(async () =>
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
context.Instruments.Add(new Domain.Entities.Instrument
|
||||||
|
{
|
||||||
|
Code = request.Code,
|
||||||
|
CreatedAt = DateTime.UtcNow,
|
||||||
|
CreatedBy = userId,
|
||||||
|
Description = request.Description,
|
||||||
|
Name = request.Name.Humanize(LetterCasing.Title).Trim(),
|
||||||
|
Status = ActivityStatus.Active,
|
||||||
|
ProgrammeId = request.ProgrammeId,
|
||||||
|
TenantId = tenantContext.TenantId
|
||||||
|
});
|
||||||
|
|
||||||
|
return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.Create("Failed to create instrument"));
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,17 @@ using static PostFundManagement.Domain.Extensions.Constants;
|
|||||||
|
|
||||||
namespace PostFundManagement.Application.Services.Governance;
|
namespace PostFundManagement.Application.Services.Governance;
|
||||||
|
|
||||||
|
public sealed record UpdateInstrumentRequest([Required] long InstructionId,
|
||||||
|
[Required][MaxLength(LabelLength)] string Name,
|
||||||
|
[Required][MaxLength(LabelLength)] string Code,
|
||||||
|
[Required][MaxLength(TextLength)] string Description,
|
||||||
|
[Required] ActivityStatus Status);
|
||||||
|
|
||||||
|
public sealed record CreateInstrumentRequest([Required] long ProgrammeId,
|
||||||
|
[Required][MaxLength(LabelLength)] string Name,
|
||||||
|
[Required][MaxLength(LabelLength)] string Code,
|
||||||
|
[Required][MaxLength(TextLength)] string Description);
|
||||||
|
|
||||||
public sealed record CreateTenantRequest([Required][MaxLength(LabelLength)] string Name);
|
public sealed record CreateTenantRequest([Required][MaxLength(LabelLength)] string Name);
|
||||||
|
|
||||||
public sealed record UpdateTenantUserRequest([Required] Guid UserId, [Required] ActivityStatus Status);
|
public sealed record UpdateTenantUserRequest([Required] Guid UserId, [Required] ActivityStatus Status);
|
||||||
|
|||||||
Reference in New Issue
Block a user