Несколько условий шага, объединяемых через И/ИЛИ #16
@@ -13,6 +13,13 @@ namespace Tnsu.ApprovalRoute.Application.TemplateRoutes;
|
|||||||
/// <param name="AskOverdueReason">
|
/// <param name="AskOverdueReason">
|
||||||
/// Спрашивать ли причину просрочки — так же с уже применённым наследованием.
|
/// Спрашивать ли причину просрочки — так же с уже применённым наследованием.
|
||||||
/// </param>
|
/// </param>
|
||||||
|
/// <param name="PositionCode">
|
||||||
|
/// HeadType шага (Chief/DirectionHead/DirectorTansu/ManagingDirectorTansu/DepartmentHead),
|
||||||
|
/// если исполнитель задан типом руководителя, иначе null. В отличие от <see cref="Position"/>
|
||||||
|
/// (реальная должность резолвнутого сотрудника из справочника api.tnsu.kz — свободный
|
||||||
|
/// текст), это код роли из самого шага маршрута — чтобы вызывающая сторона могла отличить,
|
||||||
|
/// например, «директора Tansu» от «руководителя направления», не разбирая Position текстом.
|
||||||
|
/// </param>
|
||||||
public sealed record ResolvedRouteStepDto(
|
public sealed record ResolvedRouteStepDto(
|
||||||
int Id,
|
int Id,
|
||||||
int OrderNo,
|
int OrderNo,
|
||||||
@@ -21,7 +28,8 @@ public sealed record ResolvedRouteStepDto(
|
|||||||
bool AllowReassignToOtherApprovers,
|
bool AllowReassignToOtherApprovers,
|
||||||
string? Warning = null,
|
string? Warning = null,
|
||||||
int? SlaHours = null,
|
int? SlaHours = null,
|
||||||
bool? AskOverdueReason = null);
|
bool? AskOverdueReason = null,
|
||||||
|
HeadType? PositionCode = null);
|
||||||
|
|
||||||
public sealed record ResolveTemplateRouteResultDto(
|
public sealed record ResolveTemplateRouteResultDto(
|
||||||
int RouteId,
|
int RouteId,
|
||||||
|
|||||||
@@ -340,7 +340,8 @@ public sealed class TemplateRouteService(
|
|||||||
step.AllowReassignToOtherApprovers,
|
step.AllowReassignToOtherApprovers,
|
||||||
combinedWarning.Length == 0 ? null : combinedWarning,
|
combinedWarning.Length == 0 ? null : combinedWarning,
|
||||||
step.SlaHours ?? requestType.SlaHours,
|
step.SlaHours ?? requestType.SlaHours,
|
||||||
step.AskOverdueReason ?? requestType.AskOverdueReason);
|
step.AskOverdueReason ?? requestType.AskOverdueReason,
|
||||||
|
step.HeadType is null or HeadType.None ? null : step.HeadType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
+3
@@ -182,6 +182,8 @@ public sealed class TemplateRouteServiceTests : IClassFixture<PostgresDatabaseFi
|
|||||||
resolved.Value.RouteId.ShouldBe(route.Value.Id);
|
resolved.Value.RouteId.ShouldBe(route.Value.Id);
|
||||||
resolved.Value.Steps.ShouldHaveSingleItem();
|
resolved.Value.Steps.ShouldHaveSingleItem();
|
||||||
resolved.Value.Steps[0].ExecutorEmail.ShouldBe("approver@tnsu.kz");
|
resolved.Value.Steps[0].ExecutorEmail.ShouldBe("approver@tnsu.kz");
|
||||||
|
// Исполнитель задан email'ом, а не типом руководителя — PositionCode пуст.
|
||||||
|
resolved.Value.Steps[0].PositionCode.ShouldBeNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
// SLA приезжает в резолв уже с применённым наследованием — это осознанное
|
// SLA приезжает в резолв уже с применённым наследованием — это осознанное
|
||||||
@@ -704,6 +706,7 @@ public sealed class TemplateRouteServiceTests : IClassFixture<PostgresDatabaseFi
|
|||||||
resolved.IsSuccess.ShouldBeTrue();
|
resolved.IsSuccess.ShouldBeTrue();
|
||||||
resolved.Value.Steps.ShouldHaveSingleItem();
|
resolved.Value.Steps.ShouldHaveSingleItem();
|
||||||
resolved.Value.Steps[0].ExecutorEmail.ShouldBe("chief@tnsu.kz");
|
resolved.Value.Steps[0].ExecutorEmail.ShouldBe("chief@tnsu.kz");
|
||||||
|
resolved.Value.Steps[0].PositionCode.ShouldBe(HeadType.Chief);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(DisplayName = "Резолв шага с типом руководителя DirectorTansu подставляет захардкоженный email из настроек")]
|
[Fact(DisplayName = "Резолв шага с типом руководителя DirectorTansu подставляет захардкоженный email из настроек")]
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// (Application/TemplateRoutes/ResolveTemplateRouteDto.cs).
|
// (Application/TemplateRoutes/ResolveTemplateRouteDto.cs).
|
||||||
/* eslint-disable @rushstack/no-new-null -- поля 1:1 зеркалят nullable JSON-контракт бэкенда */
|
/* eslint-disable @rushstack/no-new-null -- поля 1:1 зеркалят nullable JSON-контракт бэкенда */
|
||||||
|
|
||||||
import { RouteStepStatus } from './enums';
|
import { HeadType, RouteStepStatus } from './enums';
|
||||||
|
|
||||||
/** Значение поля списка SharePoint (field_name шага) для проверки условий шагов. */
|
/** Значение поля списка SharePoint (field_name шага) для проверки условий шагов. */
|
||||||
export interface ResolveFieldValue {
|
export interface ResolveFieldValue {
|
||||||
@@ -28,6 +28,12 @@ export interface ResolvedRouteStep {
|
|||||||
allowReassignToOtherApprovers: boolean;
|
allowReassignToOtherApprovers: boolean;
|
||||||
/** Причина, по которой исполнитель шага не определился (текст с бэкенда). */
|
/** Причина, по которой исполнитель шага не определился (текст с бэкенда). */
|
||||||
warning: string | null;
|
warning: string | null;
|
||||||
|
/**
|
||||||
|
* HeadType шага (Chief/DirectionHead/...), если исполнитель задан типом
|
||||||
|
* руководителя, иначе null. В отличие от position (реальная должность
|
||||||
|
* резолвнутого сотрудника из справочника) — это код роли из самого шага.
|
||||||
|
*/
|
||||||
|
positionCode: HeadType | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ResolveTemplateRouteResult {
|
export interface ResolveTemplateRouteResult {
|
||||||
|
|||||||
Reference in New Issue
Block a user