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 { 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>; 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>(); /** Организации сотрудника по e-mail. Пустой email → [] без обращения к API. */ export function getEmployeeOrganizations(context: WebPartContext, email: string): Promise { 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 })); }