50 lines
2.8 KiB
TypeScript
50 lines
2.8 KiB
TypeScript
import { ComparisonOperator, Employee, HeadType, ProjectRole, StepExecutorKind, TemplateRouteStep } from '../models';
|
|
import { comparisonOperatorSymbols, 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.fieldName || !step.operation || step.operation === ComparisonOperator.None || !step.value) return undefined;
|
|
return `${step.fieldName} ${comparisonOperatorSymbols[step.operation]} ${step.value}`;
|
|
}
|