Files
request-portal/src/webparts/requestPortal/shared/dictionary/employeeOrganizations.service.ts
T
gorbenko.pavel 637e51d7f9
Tests / frontend-test (push) Successful in 1m24s
Feature/vacation edo signing (#23)
Co-authored-by: gorbenko.pavel <gorbenko.pavel@tansu.kz>
Reviewed-on: http://git.tnsu.kz/timur.gorodetskiy/request-portal/pulls/23
2026-10-05 08:53:18 +00:00

71 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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';
import { IEmployeeOrganization } from './models/IEmployeeOrganization';
import { ICompany } from './models/ICompany';
// GET /Employee/ByEmail?Email=... — организации сотрудника (см. IEmployeeOrganization:
// один email может вернуть несколько записей). 404 (email не найден в системе
// кадров) — не ошибка формы, просто пусто: не у каждого приглашённого/внешнего
// пользователя портала есть карточка сотрудника.
async function fetchEmployeeOrganizations(context: WebPartContext, email: string): Promise<IEmployeeOrganization[]> {
const client = await context.aadHttpClientFactory.getClient(APPROVAL_API_CLIENT_ID);
const response: HttpClientResponse = await client.get(
`${DICTIONARY_API_BASE_URL}/Employee/ByEmail?Email=${encodeURIComponent(email)}`,
AadHttpClient.configurations.v1
);
if (response.status === 404) return [];
if (!response.ok) {
throw new Error(`Employee/ByEmail: ${response.status} ${response.statusText}`);
}
const body = (await response.json()) as Array<Record<string, unknown>>;
return body.map((r) => ({
id: (r.Id as string) || '',
fio: (r.Fio as string) || '',
email: (r.Email as string) || '',
iin: (r.Iin as string) || '',
company: (r.Company as string) || '',
companyId: (r.CompanyId as string) || '',
section: (r.Section as string) || '',
departmentId: (r.DepartmentId as string) || '',
position: (r.Position as string) || '',
mobile: (r.Mobile as string) || ''
}));
}
// Кеш по e-mail (не один общий промис, как у companies/departments — там список
// один на всех, здесь результат зависит от аргумента). Ошибку не кешируем — см.
// companies.service.ts, тот же принцип.
const cache = new Map<string, Promise<IEmployeeOrganization[]>>();
/** Организации сотрудника по e-mail. Пустой email → [] без обращения к API. */
export function getEmployeeOrganizations(context: WebPartContext, email: string): Promise<IEmployeeOrganization[]> {
if (!email) return Promise.resolve([]);
const cached = cache.get(email);
if (cached) return cached;
const promise = fetchEmployeeOrganizations(context, email).catch((e) => {
cache.delete(email);
throw e;
});
cache.set(email, promise);
return promise;
}
/**
* «Компания — должность» по каждой записи, по одной на строку (`\n`) — общий
* формат и для отображения (построчно), и для хранения в списке SharePoint
* (колонка Organization, Note — поддерживает переносы строк).
*/
export function formatEmployeeOrganizations(records: IEmployeeOrganization[]): string {
return records.map((r) => (r.position ? `${r.company} — ${r.position}` : r.company)).join('\n');
}
/**
* Организации сотрудника → значение для CompanyPickerMulti. companyId из
* Employee/ByEmail совпадает с Id в Dictionary/Companies (тот же источник),
* поэтому доп. запрос в справочник не нужен. Записи без компании пропускаем.
*/
export function employeeCompanies(records: IEmployeeOrganization[]): ICompany[] {
return records.filter((r) => r.companyId && r.company).map((r) => ({ Id: r.companyId, Name: r.company }));
}