Refactor workflow closure logic and enhance API
Updated `CloseWorkflowCommand` to use nullable `Code` and `Message` properties for better result representation. Refactored `CloseWorkflowCommandHandler` to use a capitalized `Repo` and improved exception handling with `InvalidWorkflowPayloadException`. Enhanced `WorkflowsController` by implementing the `CloseAsync` method, which now processes `CloseWorkflowReqBody` and returns appropriate HTTP status codes. Updated XML documentation for clarity.
This commit is contained in:
@@ -11,5 +11,5 @@ public sealed record CloseWorkflowCommand(
|
||||
byte? RejectionReasonId) : IRequest<CloseWorkflowResult>;
|
||||
|
||||
public sealed record CloseWorkflowResult(
|
||||
int ResultCode,
|
||||
string ResultMessage);
|
||||
int? Code,
|
||||
string Message);
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
using DigitalData.TaskFlow.Application.Common.Exceptions;
|
||||
using DigitalData.TaskFlow.Application.Common.Interfaces;
|
||||
using MediatR;
|
||||
|
||||
namespace DigitalData.TaskFlow.Application.Features.Workflows.Commands;
|
||||
|
||||
public sealed class CloseWorkflowCommandHandler(IWorkflowRepository repo)
|
||||
: IRequestHandler<CloseWorkflowCommand, CloseWorkflowResult>
|
||||
public sealed class CloseWorkflowCommandHandler(IWorkflowRepository Repo) : IRequestHandler<CloseWorkflowCommand, CloseWorkflowResult>
|
||||
{
|
||||
public async Task<CloseWorkflowResult> Handle(
|
||||
CloseWorkflowCommand request,
|
||||
CancellationToken cancellationToken)
|
||||
public async Task<CloseWorkflowResult> Handle(CloseWorkflowCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var procedureResult = await repo.CloseAsync(
|
||||
var procedureResult = await Repo.CloseAsync(
|
||||
userId: request.WisagId,
|
||||
source: request.Source,
|
||||
processId: request.ProcessId,
|
||||
@@ -19,14 +17,10 @@ public sealed class CloseWorkflowCommandHandler(IWorkflowRepository repo)
|
||||
rejectionReasonId: request.RejectionReasonId,
|
||||
cancellationToken: cancellationToken);
|
||||
|
||||
if (procedureResult?.Code is null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Stored procedure returned an invalid close result.");
|
||||
}
|
||||
|
||||
return new CloseWorkflowResult(
|
||||
ResultCode: procedureResult.Code.Value,
|
||||
ResultMessage: procedureResult.Result ?? string.Empty);
|
||||
return procedureResult is null
|
||||
? throw new InvalidWorkflowPayloadException("Close workflow closing procedure returned no result.")
|
||||
: new CloseWorkflowResult(
|
||||
Code: procedureResult.Code,
|
||||
Message: procedureResult.Result ?? string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
using DigitalData.TaskFlow.API.Models;
|
||||
using DigitalData.TaskFlow.Application.Common.Exceptions;
|
||||
using DigitalData.TaskFlow.Application.Features.Workflows.Commands;
|
||||
using DigitalData.TaskFlow.Application.Features.Workflows.Queries;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@@ -29,18 +32,45 @@ public sealed class WorkflowsController(ISender sender) : ControllerBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// Closes a workflow for a WISAG user identifier, source, and process identifier.
|
||||
/// </summary>
|
||||
/// <param name="wisagId"></param>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="processId"></param>
|
||||
/// <param name="body"></param>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
[HttpPost("{wisagId:int}/{source}/{processId:long}/closing")]
|
||||
[ProducesResponseType(StatusCodes.Status501NotImplemented)]
|
||||
public Task<ActionResult<JsonElement>> CloseAsync([FromRoute] int wisagId, [FromRoute] string source, [FromRoute] long processId, CancellationToken cancellationToken)
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesResponseType(StatusCodes.Status409Conflict)]
|
||||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
public async Task<IActionResult> CloseAsync(
|
||||
[FromRoute] int wisagId,
|
||||
[FromRoute] long processId,
|
||||
[FromBody] CloseWorkflowReqBody body,
|
||||
[FromRoute] string source = "Ferdinand",
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var result = await sender.Send(
|
||||
new CloseWorkflowCommand(
|
||||
WisagId: wisagId,
|
||||
Source: source,
|
||||
ProcessId: processId,
|
||||
ClosingMethodId: body.ClosingMethodId,
|
||||
Comment: body.Comment,
|
||||
RejectionReasonId: body.RejectionReasonId),
|
||||
cancellationToken);
|
||||
|
||||
var metaResult = new CloseWorkflowReqResponse() { Meta = [result] };
|
||||
return result.Code switch
|
||||
{
|
||||
0 => Ok(metaResult),
|
||||
4 => BadRequest(metaResult),
|
||||
6 => NotFound(metaResult),
|
||||
7 => Conflict(metaResult),
|
||||
_ => StatusCode(StatusCodes.Status500InternalServerError, metaResult)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user