добавлен новый тип менеджера и условие новое
Tests / frontend-test (pull_request) Successful in 43s
Tests / backend-test (pull_request) Successful in 4m0s

This commit is contained in:
gorbenko.pavel
2026-08-13 12:16:22 +05:00
parent d076f4e98d
commit f4542c7b39
7 changed files with 74 additions and 13 deletions
@@ -163,6 +163,11 @@ public sealed class TemplateRouteService(
.GroupBy(f => f.FieldName, StringComparer.OrdinalIgnoreCase)
.ToDictionary(g => g.Key, g => g.First().Value, StringComparer.OrdinalIgnoreCase);
// Синтетическое поле условия (не пришедшее из request.FieldValues, а вычисленное
// здесь): должность в справочнике — свободный текст, поэтому «руководитель или
// нет» определяем по ключевым словам в её названии, а не по отдельному флагу.
fieldValues["IsManager"] = IsManagerPosition(employee.Position) ? "true" : "false";
var matchingSteps = route.Steps
.Where(s => s.Status == request.Status)
.Where(s => MatchesCondition(s, fieldValues))
@@ -264,6 +269,7 @@ public sealed class TemplateRouteService(
HeadType.Chief => await portalClient.GetManagerAsync(initiatorEmail, "chief", cancellationToken),
HeadType.DirectionHead => await portalClient.GetManagerAsync(initiatorEmail, "directionHead", cancellationToken),
HeadType.DirectorTansu => portalOptions.Value.DirectorTansuEmail,
HeadType.ManagingDirectorTansu => portalOptions.Value.ManagingDirectorTansuEmail,
_ => null
};
if (string.IsNullOrWhiteSpace(resolvedEmail))
@@ -328,6 +334,21 @@ public sealed class TemplateRouteService(
private static bool TryParseNumber(string? value, out double number) =>
double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out number);
/// <summary>
/// Должность в справочнике api.tnsu.kz — свободный текст без структуры (нет
/// отдельного флага «это руководитель»), поэтому определяем это по ключевым
/// словам в названии должности. Список подобран по фактическим должностям
/// в справочнике — Начальник/Руководитель/Директор/Заместитель/Главный/
/// Заведующий складом. «Ведущий», «Старший» и «Менеджер» намеренно не входят:
/// это старший специалист, а не должность с подчинёнными.
/// </summary>
private static readonly string[] ManagerPositionKeywords =
["начальник", "руководитель", "директор", "заместитель", "главный", "заведующий склад"];
private static bool IsManagerPosition(string? position) =>
!string.IsNullOrWhiteSpace(position) &&
ManagerPositionKeywords.Any(keyword => position.Contains(keyword, StringComparison.OrdinalIgnoreCase));
private static IReadOnlyList<ResolvedRouteStepDto> CollapseByExecutorEmail(IReadOnlyList<ResolvedRouteStepDto> steps)
{
var seenEmails = new HashSet<string>(StringComparer.OrdinalIgnoreCase);