Files
request-portal/src/webparts/requestPortal/shared/dictionary/employeeLookup.service.ts
T
2026-08-26 07:07:03 +00:00

100 lines
4.9 KiB
TypeScript

import { AadHttpClient, HttpClientResponse } from '@microsoft/sp-http';
import { WebPartContext } from '@microsoft/sp-webpart-base';
import { APPROVAL_API_CLIENT_ID, DICTIONARY_API_BASE_URL } from '../config';
/**
* Название должности директора по компании — ЗЕРКАЛО того же справочника, что
* использует approval-route на бэкенде для маршрута HeadType.CompanyDirectors
* (см. tnsu-approval-route TemplateRouteService.DirectorPositionByCompany).
* Держим копию здесь, а не тянем с бэкенда: нужен только на фронте, чтобы найти
* СТРОКУ МАТРИЦЫ, соответствующую конкретной компании (см.
* forms/Dismissal/sections/OrganizationsTable.tsx) — сама матрица уже пришла
* готовой от approval-route, эта функция лишь опознаёт в ней директора нужной
* компании тем же способом, каким его туда положил бэкенд.
*
* Если бэкендный справочник изменится — эту копию нужно поправить вручную,
* отдельного источника правды на два репозитория нет.
*/
const DIRECTOR_POSITION_BY_COMPANY: Record<string, string> = {
'ТОО KazPromService': 'Главный механик',
'ТОО СТ Global': 'Генеральный директор'
};
const DEFAULT_DIRECTOR_POSITION = 'Директор';
function normalizeCompany(company: string): string {
return company.trim().toLowerCase();
}
const DIRECTOR_POSITION_BY_COMPANY_NORMALIZED: Record<string, string> = Object.keys(
DIRECTOR_POSITION_BY_COMPANY
).reduce<Record<string, string>>((acc, key) => {
acc[normalizeCompany(key)] = DIRECTOR_POSITION_BY_COMPANY[key];
return acc;
}, {});
/** Название должности директора для компании (регистронезависимо). */
export function directorPositionFor(company: string): string {
return DIRECTOR_POSITION_BY_COMPANY_NORMALIZED[normalizeCompany(company)] || DEFAULT_DIRECTOR_POSITION;
}
async function getClient(context: WebPartContext): Promise<AadHttpClient> {
return context.aadHttpClientFactory.getClient(APPROVAL_API_CLIENT_ID);
}
/**
* GET /Employee/ByPosition — сотрудник на должности в компании (напр. директор).
* 404/«не найден» — не ошибка формы, просто вернуть '' (см. вызывающий код:
* отсутствие директора не должно ронять форму, только не даст найти строку матрицы).
*/
export async function getEmployeeEmailByPosition(
context: WebPartContext,
position: string,
company: string
): Promise<string> {
const client = await getClient(context);
const response: HttpClientResponse = await client.get(
`${DICTIONARY_API_BASE_URL}/Employee/ByPosition?position=${encodeURIComponent(
position
)}&company=${encodeURIComponent(company)}`,
AadHttpClient.configurations.v1
);
if (response.status === 404) return '';
if (!response.ok) {
throw new Error(`Employee/ByPosition: ${response.status} ${response.statusText}`);
}
const body = (await response.json()) as { Email?: string; error?: string };
return body.Email || '';
}
/** Директор (или должностной эквивалент, см. directorPositionFor) компании. */
export function getCompanyDirectorEmail(context: WebPartContext, company: string): Promise<string> {
return getEmployeeEmailByPosition(context, directorPositionFor(company), company);
}
/**
* GET /Employee/Manager — руководитель сотрудника по типу связи. 'chief' —
* непосредственный руководитель (тот же managerType, что использует
* approval-route для HeadType.Chief — см. TemplateRouteService.ResolveStepAsync).
* Не найден/сотрудник без руководителя — '' (не ошибка).
*/
export async function getManagerEmail(
context: WebPartContext,
email: string,
managerType: 'chief' | 'directionHead' = 'chief'
): Promise<string> {
if (!email) return '';
const client = await getClient(context);
const response: HttpClientResponse = await client.get(
`${DICTIONARY_API_BASE_URL}/Employee/Manager?email=${encodeURIComponent(email)}&managerType=${encodeURIComponent(
managerType
)}`,
AadHttpClient.configurations.v1
);
if (response.status === 404) return '';
if (!response.ok) {
throw new Error(`Employee/Manager: ${response.status} ${response.statusText}`);
}
const body = (await response.json()) as { managerEmail?: string };
return body.managerEmail || '';
}