отказ от mediatr

This commit is contained in:
gorbenko.pavel
2026-07-23 16:45:18 +05:00
parent 0ddb9f0ba6
commit 7cce18e67b
16 changed files with 336 additions and 494 deletions
@@ -1,41 +0,0 @@
using FluentResults;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Tnsu.ApprovalRoute.Application.Common.Errors;
using Tnsu.ApprovalRoute.Infrastructure.Persistence;
namespace Tnsu.ApprovalRoute.Application.TemplateRouteSteps;
public sealed record GetTemplateRouteStepQuery(Guid RouteId, Guid Id) : IRequest<Result<TemplateRouteStepDto>>;
public sealed record ListTemplateRouteStepsQuery(Guid RouteId) : IRequest<Result<IReadOnlyList<TemplateRouteStepDto>>>;
public sealed class GetTemplateRouteStepHandler(ApprovalRouteDbContext db)
: IRequestHandler<GetTemplateRouteStepQuery, Result<TemplateRouteStepDto>>
{
public async Task<Result<TemplateRouteStepDto>> Handle(GetTemplateRouteStepQuery request, CancellationToken cancellationToken)
{
var entity = await db.TemplateRouteSteps.AsNoTracking()
.FirstOrDefaultAsync(x => x.Id == request.Id && x.RouteId == request.RouteId, cancellationToken);
return entity is null
? Result.Fail<TemplateRouteStepDto>(new NotFoundError("Шаг маршрута", request.Id))
: Result.Ok(TemplateRouteStepMapper.ToDto(entity));
}
}
public sealed class ListTemplateRouteStepsHandler(ApprovalRouteDbContext db)
: IRequestHandler<ListTemplateRouteStepsQuery, Result<IReadOnlyList<TemplateRouteStepDto>>>
{
public async Task<Result<IReadOnlyList<TemplateRouteStepDto>>> Handle(ListTemplateRouteStepsQuery request, CancellationToken cancellationToken)
{
var items = await db.TemplateRouteSteps.AsNoTracking()
.Where(x => x.RouteId == request.RouteId)
.OrderBy(x => x.OrderNo)
.Select(x => new TemplateRouteStepDto(
x.Id, x.OrderNo, x.ExecutorEmail, x.Position, x.ProjectRole, x.HeadType, x.Status, x.RouteId, x.AllowReassignToOtherApprovers))
.ToListAsync(cancellationToken);
return Result.Ok<IReadOnlyList<TemplateRouteStepDto>>(items);
}
}
@@ -1,5 +1,4 @@
using FluentResults;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Tnsu.ApprovalRoute.Application.Common.Errors;
using Tnsu.ApprovalRoute.Domain.Entities;
@@ -8,25 +7,37 @@ using Tnsu.ApprovalRoute.Infrastructure.Persistence;
namespace Tnsu.ApprovalRoute.Application.TemplateRouteSteps;
public sealed record CreateTemplateRouteStepCommand(Guid RouteId, CreateTemplateRouteStepRequest Request)
: IRequest<Result<TemplateRouteStepDto>>;
public sealed record UpdateTemplateRouteStepCommand(Guid RouteId, Guid Id, UpdateTemplateRouteStepRequest Request)
: IRequest<Result<TemplateRouteStepDto>>;
public sealed record DeleteTemplateRouteStepCommand(Guid RouteId, Guid Id) : IRequest<Result>;
public sealed class CreateTemplateRouteStepHandler(ApprovalRouteDbContext db)
: IRequestHandler<CreateTemplateRouteStepCommand, Result<TemplateRouteStepDto>>
public sealed class TemplateRouteStepService(ApprovalRouteDbContext db)
{
public async Task<Result<TemplateRouteStepDto>> Handle(CreateTemplateRouteStepCommand command, CancellationToken cancellationToken)
public async Task<Result<IReadOnlyList<TemplateRouteStepDto>>> ListAsync(Guid routeId, CancellationToken cancellationToken)
{
var route = await db.TemplateRoutes.FirstOrDefaultAsync(x => x.Id == command.RouteId, cancellationToken);
if (route is null)
return Result.Fail<TemplateRouteStepDto>(new NotFoundError("Маршрут", command.RouteId));
var items = await db.TemplateRouteSteps.AsNoTracking()
.Where(x => x.RouteId == routeId)
.OrderBy(x => x.OrderNo)
.Select(x => new TemplateRouteStepDto(
x.Id, x.OrderNo, x.ExecutorEmail, x.Position, x.ProjectRole, x.HeadType, x.Status, x.RouteId, x.AllowReassignToOtherApprovers))
.ToListAsync(cancellationToken);
var r = command.Request;
var fieldsError = TemplateRouteStepValidation.ValidateFields(r.ExecutorEmail, r.Position, r.ProjectRole, route.ByProject);
return Result.Ok<IReadOnlyList<TemplateRouteStepDto>>(items);
}
public async Task<Result<TemplateRouteStepDto>> GetAsync(Guid routeId, Guid id, CancellationToken cancellationToken)
{
var entity = await db.TemplateRouteSteps.AsNoTracking()
.FirstOrDefaultAsync(x => x.Id == id && x.RouteId == routeId, cancellationToken);
return entity is null
? Result.Fail<TemplateRouteStepDto>(new NotFoundError("Шаг маршрута", id))
: Result.Ok(ToDto(entity));
}
public async Task<Result<TemplateRouteStepDto>> CreateAsync(Guid routeId, CreateTemplateRouteStepRequest r, CancellationToken cancellationToken)
{
var route = await db.TemplateRoutes.FirstOrDefaultAsync(x => x.Id == routeId, cancellationToken);
if (route is null)
return Result.Fail<TemplateRouteStepDto>(new NotFoundError("Маршрут", routeId));
var fieldsError = ValidateFields(r.ExecutorEmail, r.Position, r.ProjectRole, route.ByProject);
if (fieldsError is not null)
return Result.Fail<TemplateRouteStepDto>(fieldsError);
@@ -44,27 +55,22 @@ public sealed class CreateTemplateRouteStepHandler(ApprovalRouteDbContext db)
db.TemplateRouteSteps.Add(entity);
await db.SaveChangesAsync(cancellationToken);
var result = Result.Ok(TemplateRouteStepMapper.ToDto(entity));
return await TemplateRouteStepValidation.AppendMissingProjectRoleWarningAsync(db, route, result, cancellationToken);
var result = Result.Ok(ToDto(entity));
return await AppendMissingProjectRoleWarningAsync(route, result, cancellationToken);
}
}
public sealed class UpdateTemplateRouteStepHandler(ApprovalRouteDbContext db)
: IRequestHandler<UpdateTemplateRouteStepCommand, Result<TemplateRouteStepDto>>
{
public async Task<Result<TemplateRouteStepDto>> Handle(UpdateTemplateRouteStepCommand command, CancellationToken cancellationToken)
public async Task<Result<TemplateRouteStepDto>> UpdateAsync(
Guid routeId, Guid id, UpdateTemplateRouteStepRequest r, CancellationToken cancellationToken)
{
var route = await db.TemplateRoutes.FirstOrDefaultAsync(x => x.Id == command.RouteId, cancellationToken);
var route = await db.TemplateRoutes.FirstOrDefaultAsync(x => x.Id == routeId, cancellationToken);
if (route is null)
return Result.Fail<TemplateRouteStepDto>(new NotFoundError("Маршрут", command.RouteId));
return Result.Fail<TemplateRouteStepDto>(new NotFoundError("Маршрут", routeId));
var entity = await db.TemplateRouteSteps
.FirstOrDefaultAsync(x => x.Id == command.Id && x.RouteId == command.RouteId, cancellationToken);
var entity = await db.TemplateRouteSteps.FirstOrDefaultAsync(x => x.Id == id && x.RouteId == routeId, cancellationToken);
if (entity is null)
return Result.Fail<TemplateRouteStepDto>(new NotFoundError("Шаг маршрута", command.Id));
return Result.Fail<TemplateRouteStepDto>(new NotFoundError("Шаг маршрута", id));
var r = command.Request;
var fieldsError = TemplateRouteStepValidation.ValidateFields(r.ExecutorEmail, r.Position, r.ProjectRole, route.ByProject);
var fieldsError = ValidateFields(r.ExecutorEmail, r.Position, r.ProjectRole, route.ByProject);
if (fieldsError is not null)
return Result.Fail<TemplateRouteStepDto>(fieldsError);
@@ -77,31 +83,23 @@ public sealed class UpdateTemplateRouteStepHandler(ApprovalRouteDbContext db)
entity.AllowReassignToOtherApprovers = r.AllowReassignToOtherApprovers;
await db.SaveChangesAsync(cancellationToken);
var result = Result.Ok(TemplateRouteStepMapper.ToDto(entity));
return await TemplateRouteStepValidation.AppendMissingProjectRoleWarningAsync(db, route, result, cancellationToken);
var result = Result.Ok(ToDto(entity));
return await AppendMissingProjectRoleWarningAsync(route, result, cancellationToken);
}
}
public sealed class DeleteTemplateRouteStepHandler(ApprovalRouteDbContext db)
: IRequestHandler<DeleteTemplateRouteStepCommand, Result>
{
public async Task<Result> Handle(DeleteTemplateRouteStepCommand request, CancellationToken cancellationToken)
public async Task<Result> DeleteAsync(Guid routeId, Guid id, CancellationToken cancellationToken)
{
var entity = await db.TemplateRouteSteps
.FirstOrDefaultAsync(x => x.Id == request.Id && x.RouteId == request.RouteId, cancellationToken);
var entity = await db.TemplateRouteSteps.FirstOrDefaultAsync(x => x.Id == id && x.RouteId == routeId, cancellationToken);
if (entity is null)
return Result.Fail(new NotFoundError("Шаг маршрута", request.Id));
return Result.Fail(new NotFoundError("Шаг маршрута", id));
db.TemplateRouteSteps.Remove(entity);
await db.SaveChangesAsync(cancellationToken);
return Result.Ok();
}
}
internal static class TemplateRouteStepValidation
{
public static IError? ValidateFields(string executorEmail, string position, ProjectRole projectRole, bool routeByProject)
private static IError? ValidateFields(string executorEmail, string position, ProjectRole projectRole, bool routeByProject)
{
if (string.IsNullOrWhiteSpace(executorEmail) && string.IsNullOrWhiteSpace(position) && projectRole == ProjectRole.None)
return new ValidationError("Исполнитель, должность и роль в проекте не могут быть пустыми одновременно.");
@@ -112,8 +110,8 @@ internal static class TemplateRouteStepValidation
return null;
}
public static async Task<Result<TemplateRouteStepDto>> AppendMissingProjectRoleWarningAsync(
ApprovalRouteDbContext db, TemplateRoute route, Result<TemplateRouteStepDto> result, CancellationToken cancellationToken)
private async Task<Result<TemplateRouteStepDto>> AppendMissingProjectRoleWarningAsync(
TemplateRoute route, Result<TemplateRouteStepDto> result, CancellationToken cancellationToken)
{
if (!route.ByProject)
return result;
@@ -125,10 +123,7 @@ internal static class TemplateRouteStepValidation
? result
: result.WithReason(new Warning("Должен быть хотя бы один шаг с ролью в проекте."));
}
}
internal static class TemplateRouteStepMapper
{
public static TemplateRouteStepDto ToDto(TemplateRouteStep e) => new(
private static TemplateRouteStepDto ToDto(TemplateRouteStep e) => new(
e.Id, e.OrderNo, e.ExecutorEmail, e.Position, e.ProjectRole, e.HeadType, e.Status, e.RouteId, e.AllowReassignToOtherApprovers);
}