refactor(application): centralize API envelope creation and command mapping
This commit is contained in:
@@ -0,0 +1,49 @@
|
|||||||
|
using DigitalData.TaskFlow.Domain.Common;
|
||||||
|
using DigitalData.TaskFlow.Domain.Enums;
|
||||||
|
|
||||||
|
namespace DigitalData.TaskFlow.Application.Common.Factories;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates standard API envelope instances with centralized meta code/message handling.
|
||||||
|
/// </summary>
|
||||||
|
public static class ApiEnvelopeFactory
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a successful or business-result response envelope.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Payload type.</typeparam>
|
||||||
|
/// <param name="data">Payload data.</param>
|
||||||
|
/// <param name="code">Business result code.</param>
|
||||||
|
/// <param name="message">Optional custom message. If not supplied, a default message is resolved from <paramref name="code"/>.</param>
|
||||||
|
/// <returns>Response envelope containing meta and payload.</returns>
|
||||||
|
public static ApiEnvelope<T> Create<T>(T data, MetaCode code = MetaCode.Ok, string? message = null)
|
||||||
|
{
|
||||||
|
return new ApiEnvelope<T>
|
||||||
|
{
|
||||||
|
Meta =
|
||||||
|
[
|
||||||
|
new MetaEntry
|
||||||
|
{
|
||||||
|
Code = (int)code,
|
||||||
|
Message = message ?? ResolveDefaultMessage(code)
|
||||||
|
}
|
||||||
|
],
|
||||||
|
Data = data
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ResolveDefaultMessage(MetaCode code)
|
||||||
|
{
|
||||||
|
return code switch
|
||||||
|
{
|
||||||
|
MetaCode.Ok => "OK",
|
||||||
|
MetaCode.NoOpenWorkflows => "Keine offenen Workflows",
|
||||||
|
MetaCode.NoAccess => "Kein Zugriff",
|
||||||
|
MetaCode.InvalidRequest => "Ungultiger Request",
|
||||||
|
MetaCode.InternalError => "Interner Fehler",
|
||||||
|
MetaCode.NotFound => "Vorgang nicht gefunden",
|
||||||
|
MetaCode.AlreadyClosed => "Vorgang bereits abgeschlossen",
|
||||||
|
_ => "Interner Fehler"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
|
using DigitalData.TaskFlow.Application.Features.Workflows.Commands.CloseWorkflow;
|
||||||
|
using DigitalData.TaskFlow.Domain.Closing;
|
||||||
|
|
||||||
namespace DigitalData.TaskFlow.Application.Common.Mappings;
|
namespace DigitalData.TaskFlow.Application.Common.Mappings;
|
||||||
|
|
||||||
@@ -12,5 +14,6 @@ public sealed class ApplicationMappingProfile : Profile
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ApplicationMappingProfile()
|
public ApplicationMappingProfile()
|
||||||
{
|
{
|
||||||
|
CreateMap<CloseWorkflowCommand, CloseWorkflowDecision>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
using DigitalData.TaskFlow.Application.Common.Factories;
|
||||||
using DigitalData.TaskFlow.Application.Common.Interfaces;
|
using DigitalData.TaskFlow.Application.Common.Interfaces;
|
||||||
using DigitalData.TaskFlow.Domain.Common;
|
using DigitalData.TaskFlow.Domain.Common;
|
||||||
using DigitalData.TaskFlow.Domain.Documents;
|
using DigitalData.TaskFlow.Domain.Documents;
|
||||||
using DigitalData.TaskFlow.Domain.Enums;
|
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
|
|
||||||
@@ -44,17 +44,6 @@ public sealed class GetDocumentQueryHandler(IDocumentRepository documentReposito
|
|||||||
{
|
{
|
||||||
var document = await documentRepository.GetAsync(request.Id, cancellationToken);
|
var document = await documentRepository.GetAsync(request.Id, cancellationToken);
|
||||||
|
|
||||||
return new ApiEnvelope<DocumentBinaryResult>
|
return ApiEnvelopeFactory.Create(document);
|
||||||
{
|
|
||||||
Meta =
|
|
||||||
[
|
|
||||||
new MetaEntry
|
|
||||||
{
|
|
||||||
Code = (int)MetaCode.Ok,
|
|
||||||
Message = "OK"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
Data = document
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
using DigitalData.TaskFlow.Application.Common.Interfaces;
|
using DigitalData.TaskFlow.Application.Common.Interfaces;
|
||||||
|
using DigitalData.TaskFlow.Application.Common.Factories;
|
||||||
|
using AutoMapper;
|
||||||
using DigitalData.TaskFlow.Domain.Closing;
|
using DigitalData.TaskFlow.Domain.Closing;
|
||||||
using DigitalData.TaskFlow.Domain.Common;
|
using DigitalData.TaskFlow.Domain.Common;
|
||||||
using DigitalData.TaskFlow.Domain.Enums;
|
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
|
|
||||||
@@ -56,7 +57,7 @@ public sealed class CloseWorkflowCommandValidator : AbstractValidator<CloseWorkf
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles <see cref="CloseWorkflowCommand"/> requests.
|
/// Handles <see cref="CloseWorkflowCommand"/> requests.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class CloseWorkflowCommandHandler(IWorkflowRepository workflowRepository)
|
public sealed class CloseWorkflowCommandHandler(IWorkflowRepository workflowRepository, IMapper mapper)
|
||||||
: IRequestHandler<CloseWorkflowCommand, ApiEnvelope<CloseWorkflowResult>>
|
: IRequestHandler<CloseWorkflowCommand, ApiEnvelope<CloseWorkflowResult>>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -67,12 +68,7 @@ public sealed class CloseWorkflowCommandHandler(IWorkflowRepository workflowRepo
|
|||||||
/// <returns>Closing result envelope.</returns>
|
/// <returns>Closing result envelope.</returns>
|
||||||
public async Task<ApiEnvelope<CloseWorkflowResult>> Handle(CloseWorkflowCommand request, CancellationToken cancellationToken)
|
public async Task<ApiEnvelope<CloseWorkflowResult>> Handle(CloseWorkflowCommand request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var decision = new CloseWorkflowDecision
|
var decision = mapper.Map<CloseWorkflowDecision>(request);
|
||||||
{
|
|
||||||
ClosingMethodId = request.ClosingMethodId,
|
|
||||||
Comment = request.Comment,
|
|
||||||
RejectionReasonId = request.RejectionReasonId
|
|
||||||
};
|
|
||||||
|
|
||||||
var result = await workflowRepository.CloseAsync(
|
var result = await workflowRepository.CloseAsync(
|
||||||
request.WisagId,
|
request.WisagId,
|
||||||
@@ -81,17 +77,6 @@ public sealed class CloseWorkflowCommandHandler(IWorkflowRepository workflowRepo
|
|||||||
decision,
|
decision,
|
||||||
cancellationToken);
|
cancellationToken);
|
||||||
|
|
||||||
return new ApiEnvelope<CloseWorkflowResult>
|
return ApiEnvelopeFactory.Create(result);
|
||||||
{
|
|
||||||
Meta =
|
|
||||||
[
|
|
||||||
new MetaEntry
|
|
||||||
{
|
|
||||||
Code = (int)MetaCode.Ok,
|
|
||||||
Message = "OK"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
Data = result
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
using DigitalData.TaskFlow.Application.Common.Factories;
|
||||||
using DigitalData.TaskFlow.Application.Common.Interfaces;
|
using DigitalData.TaskFlow.Application.Common.Interfaces;
|
||||||
using DigitalData.TaskFlow.Domain.Common;
|
using DigitalData.TaskFlow.Domain.Common;
|
||||||
using DigitalData.TaskFlow.Domain.Enums;
|
|
||||||
using DigitalData.TaskFlow.Domain.Workflows;
|
using DigitalData.TaskFlow.Domain.Workflows;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
@@ -44,17 +44,6 @@ public sealed class GetWorkflowsQueryHandler(IWorkflowRepository workflowReposit
|
|||||||
{
|
{
|
||||||
var data = await workflowRepository.GetAsync(request.WisagId, cancellationToken);
|
var data = await workflowRepository.GetAsync(request.WisagId, cancellationToken);
|
||||||
|
|
||||||
return new ApiEnvelope<WorkflowSourcesResponse>
|
return ApiEnvelopeFactory.Create(data);
|
||||||
{
|
|
||||||
Meta =
|
|
||||||
[
|
|
||||||
new MetaEntry
|
|
||||||
{
|
|
||||||
Code = (int)MetaCode.Ok,
|
|
||||||
Message = "OK"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
Data = data
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user