Merge remote-tracking branch 'origin/main' into trynode22
This commit is contained in:
@@ -7,5 +7,7 @@ public sealed class CurrentUserAccessor(IHttpContextAccessor httpContextAccessor
|
||||
{
|
||||
public string? Email =>
|
||||
httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.Email)
|
||||
?? httpContextAccessor.HttpContext?.User.FindFirstValue("preferred_username");
|
||||
?? httpContextAccessor.HttpContext?.User.FindFirstValue("preferred_username")
|
||||
?? httpContextAccessor.HttpContext?.User.FindFirstValue("upn")
|
||||
?? httpContextAccessor.HttpContext?.User.FindFirstValue("unique_name");
|
||||
}
|
||||
|
||||
+3
@@ -114,6 +114,9 @@ public sealed class TemplateRouteStepService(ApprovalRouteDbContext db)
|
||||
var headType = r.HeadType ?? entity.HeadType;
|
||||
var status = r.Status ?? entity.Status;
|
||||
|
||||
if (status == RouteStepStatus.None)
|
||||
return Result.Fail<TemplateRouteStepDto>(new ValidationError("Статус обязателен: Approval или Execution."));
|
||||
|
||||
if (!route.ByProject && projectRole is not (null or ProjectRole.None))
|
||||
return Result.Fail<TemplateRouteStepDto>(new ValidationError(
|
||||
"Роль в проекте недопустима для шага маршрута, который не учитывает проект (by_project = false)."));
|
||||
|
||||
+2
@@ -7,6 +7,7 @@ public sealed class CreateTemplateRouteStepRequestValidator : AbstractValidator<
|
||||
{
|
||||
public CreateTemplateRouteStepRequestValidator()
|
||||
{
|
||||
RuleFor(x => x.Status).NotEqual(RouteStepStatus.None).WithMessage("Статус обязателен: Approval или Execution.");
|
||||
RuleFor(x => x)
|
||||
.Must(x => TemplateRouteStepFields.CountFilled(x.ExecutorEmail, x.Position, x.ProjectRole, x.HeadType) == 1)
|
||||
.WithMessage("Должно быть заполнено ровно одно из полей: исполнитель, должность, роль в проекте или тип руководителя.");
|
||||
@@ -17,6 +18,7 @@ public sealed class UpdateTemplateRouteStepRequestValidator : AbstractValidator<
|
||||
{
|
||||
public UpdateTemplateRouteStepRequestValidator()
|
||||
{
|
||||
RuleFor(x => x.Status).NotEqual(RouteStepStatus.None).WithMessage("Статус обязателен: Approval или Execution.");
|
||||
RuleFor(x => x)
|
||||
.Must(x => TemplateRouteStepFields.CountFilled(x.ExecutorEmail, x.Position, x.ProjectRole, x.HeadType) == 1)
|
||||
.WithMessage("Должно быть заполнено ровно одно из полей: исполнитель, должность, роль в проекте или тип руководителя.");
|
||||
|
||||
+2
-1
@@ -7,7 +7,8 @@ public sealed record ResolvedRouteStepDto(
|
||||
int OrderNo,
|
||||
string? ExecutorEmail,
|
||||
string? Position,
|
||||
bool AllowReassignToOtherApprovers);
|
||||
bool AllowReassignToOtherApprovers,
|
||||
string? Warning = null);
|
||||
|
||||
public sealed record ResolveTemplateRouteResultDto(
|
||||
int RouteId,
|
||||
|
||||
@@ -197,14 +197,26 @@ public sealed class TemplateRouteService(
|
||||
IReadOnlyList<ProjectExecutorInfo> projectExecutors, CancellationToken cancellationToken)
|
||||
{
|
||||
string? resolvedEmail;
|
||||
string? warning = null;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(step.ExecutorEmail))
|
||||
{
|
||||
resolvedEmail = step.ExecutorEmail;
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(step.Position))
|
||||
{
|
||||
resolvedEmail = await portalClient.GetEmployeeByPositionAsync(step.Position, initiatorCompany, cancellationToken);
|
||||
if (string.IsNullOrWhiteSpace(resolvedEmail))
|
||||
warning = $"Не найден сотрудник на должности «{step.Position}» в компании «{initiatorCompany}».";
|
||||
}
|
||||
else if (step.ProjectRole is not (null or ProjectRole.None))
|
||||
{
|
||||
resolvedEmail = projectExecutors.FirstOrDefault(e => e.ProjectRole == step.ProjectRole)?.Email;
|
||||
if (string.IsNullOrWhiteSpace(resolvedEmail))
|
||||
warning = $"Не найден исполнитель с ролью в проекте «{step.ProjectRole}».";
|
||||
}
|
||||
else if (step.HeadType is not (null or HeadType.None))
|
||||
{
|
||||
resolvedEmail = step.HeadType switch
|
||||
{
|
||||
HeadType.Chief => await portalClient.GetManagerAsync(initiatorEmail, "chief", cancellationToken),
|
||||
@@ -212,8 +224,14 @@ public sealed class TemplateRouteService(
|
||||
HeadType.DirectorTansu => portalOptions.Value.DirectorTansuEmail,
|
||||
_ => null
|
||||
};
|
||||
if (string.IsNullOrWhiteSpace(resolvedEmail))
|
||||
warning = $"Не найден руководитель типа «{step.HeadType}».";
|
||||
}
|
||||
else
|
||||
{
|
||||
resolvedEmail = null;
|
||||
warning = "Не удалось определить исполнителя шага: не заполнено ни одно из полей.";
|
||||
}
|
||||
|
||||
string? resolvedPosition = null;
|
||||
if (!string.IsNullOrWhiteSpace(resolvedEmail))
|
||||
@@ -222,7 +240,7 @@ public sealed class TemplateRouteService(
|
||||
resolvedPosition = resolvedEmployee?.Position;
|
||||
}
|
||||
|
||||
return new ResolvedRouteStepDto(step.Id, step.OrderNo, resolvedEmail, resolvedPosition, step.AllowReassignToOtherApprovers);
|
||||
return new ResolvedRouteStepDto(step.Id, step.OrderNo, resolvedEmail, resolvedPosition, step.AllowReassignToOtherApprovers, warning);
|
||||
}
|
||||
|
||||
private static IReadOnlyList<ResolvedRouteStepDto> CollapseByExecutorEmail(IReadOnlyList<ResolvedRouteStepDto> steps)
|
||||
|
||||
Reference in New Issue
Block a user