import { ConditionsLogic, Employee, HeadType, ProjectRole, StepExecutorKind, TemplateRouteStep } from '../models'; import { comparisonOperatorSymbols, conditionsLogicJoiners, headTypeLabels, projectRoleLabels, texts } from '../texts'; import { findEmployeeByEmail } from './employee'; /** Каким из четырёх взаимоисключающих способов у шага задан исполнитель. */ /* eslint-disable @rushstack/no-new-null -- форма зеркалит TemplateRouteStep (nullable JSON-контракт бэкенда) */ export function detectExecutorKind(step: { executorEmail?: string | null; position?: string | null; projectRole?: ProjectRole | null; headType?: HeadType | null; }): StepExecutorKind { /* eslint-enable @rushstack/no-new-null */ if (step.executorEmail) return 'email'; if (step.position) return 'position'; if (step.projectRole && step.projectRole !== ProjectRole.None) return 'projectRole'; return 'headType'; } export interface StepExecutorDisplay { primary: string; /** Должность и email под ФИО — когда исполнитель задан конкретным сотрудником и тот найден в справочнике. */ secondary?: string; } /** Колонка «Исполнитель» в таблице шагов шаблона маршрута. */ export function describeStepExecutor(step: TemplateRouteStep, employees: Employee[]): StepExecutorDisplay { if (step.executorEmail) { const employee = findEmployeeByEmail(employees, step.executorEmail ?? undefined); if (!employee) return { primary: step.executorEmail }; // Должность рядом с email: по одному ФИО не видно, тот ли это человек, что // задумывался при настройке маршрута (в справочнике есть однофамильцы). return { primary: employee.fio, secondary: [employee.position, employee.email].filter(Boolean).join(' · ') }; } if (step.position) return { primary: step.position }; if (step.projectRole && step.projectRole !== ProjectRole.None) { return { primary: texts.routeSteps.executorRole(projectRoleLabels[step.projectRole]) }; } if (step.headType && step.headType !== HeadType.None) { return { primary: texts.routeSteps.executorHead(headTypeLabels[step.headType]) }; } return { primary: texts.common.empty }; } /** Колонка «Условие» в таблице шагов — undefined, если у шага условий нет. */ export function describeStepCondition(step: TemplateRouteStep): string | undefined { if (step.conditions.length === 0) return undefined; const joiner = conditionsLogicJoiners[step.conditionsLogic ?? ConditionsLogic.And]; return step.conditions .map(c => `${c.fieldName} ${comparisonOperatorSymbols[c.operation]} ${c.value}`) .join(joiner); }