refactor: преобразование организаций сотрудника в компании вынесено в shared/dictionary

employeeCompanies() нужен теперь не только подбору, но и заявке на рабочее
место — одна реализация вместо копий в каждой форме.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Тимур Городецкий
2026-09-25 17:38:50 +05:00
parent 05b1163484
commit 0989168476
3 changed files with 20 additions and 11 deletions
@@ -42,7 +42,7 @@ import {
IAttachmentInfo IAttachmentInfo
} from '../../shared/attachments/attachments.service'; } from '../../shared/attachments/attachments.service';
import { effectiveUserEmail } from '../../shared/impersonation'; import { effectiveUserEmail } from '../../shared/impersonation';
import { getEmployeeOrganizations, ICompany, IEmployeeOrganization } from '../../shared/dictionary'; import { getEmployeeOrganizations, employeeCompanies } from '../../shared/dictionary';
import { friendlyErrorMessage } from '../../shared/diagnostics'; import { friendlyErrorMessage } from '../../shared/diagnostics';
import { IRequestFormProps } from '../../models/types'; import { IRequestFormProps } from '../../models/types';
import { import {
@@ -120,16 +120,11 @@ const RecruitingSelectionForm: React.FC<IRequestFormProps> = ({
}; };
}, [editId, editListId, notifyCode, setSubmitError]); }, [editId, editListId, notifyCode, setSubmitError]);
// Компании ответственного (Employee/ByEmail.company/companyId) → предзаполнение
// «1.5 Организация» (Companies/CompanyPickerMulti). companyId из Employee/ByEmail
// совпадает с Id из Dictionary/Companies (тот же источник) — доп. запрос не нужен.
// Поле остаётся редактируемым: значения только ПРЕДЛАГАЮТСЯ, как и DepartmentName.
const toCompanies = (records: IEmployeeOrganization[]): ICompany[] =>
records.filter((r) => r.companyId && r.company).map((r) => ({ Id: r.companyId, Name: r.company }));
// Новая заявка — по умолчанию ответственный: сам подающий, подразделение и // Новая заявка — по умолчанию ответственный: сам подающий, подразделение и
// организация — из Employee/ByEmail (Section/company), как в остальных формах // организация — из Employee/ByEmail (Section/company), как в остальных формах
// с авто-«Организацией» (см. shared/dictionary/employeeOrganizations.service.ts). // с авто-«Организацией» (см. shared/dictionary/employeeOrganizations.service.ts).
// «1.5 Организация» остаётся редактируемой: значения только ПРЕДЛАГАЮТСЯ,
// как и DepartmentName.
useEffect(() => { useEffect(() => {
if (editId) { if (editId) {
return; return;
@@ -143,7 +138,7 @@ const RecruitingSelectionForm: React.FC<IRequestFormProps> = ({
setData((prev) => ({ setData((prev) => ({
...prev, ...prev,
DepartmentName: prev.DepartmentName || records[0]?.section || prev.DepartmentName, DepartmentName: prev.DepartmentName || records[0]?.section || prev.DepartmentName,
Companies: prev.Companies.length > 0 ? prev.Companies : toCompanies(records) Companies: prev.Companies.length > 0 ? prev.Companies : employeeCompanies(records)
})); }));
} }
}) })
@@ -166,7 +161,7 @@ const RecruitingSelectionForm: React.FC<IRequestFormProps> = ({
setData((prev) => ({ setData((prev) => ({
...prev, ...prev,
DepartmentName: records[0]?.section || prev.DepartmentName, DepartmentName: records[0]?.section || prev.DepartmentName,
Companies: toCompanies(records) Companies: employeeCompanies(records)
})) }))
) )
.catch(() => undefined); .catch(() => undefined);
@@ -2,6 +2,7 @@ import { AadHttpClient, HttpClientResponse } from '@microsoft/sp-http';
import { WebPartContext } from '@microsoft/sp-webpart-base'; import { WebPartContext } from '@microsoft/sp-webpart-base';
import { APPROVAL_API_CLIENT_ID, DICTIONARY_API_BASE_URL } from '../config'; import { APPROVAL_API_CLIENT_ID, DICTIONARY_API_BASE_URL } from '../config';
import { IEmployeeOrganization } from './models/IEmployeeOrganization'; import { IEmployeeOrganization } from './models/IEmployeeOrganization';
import { ICompany } from './models/ICompany';
// GET /Employee/ByEmail?Email=... — организации сотрудника (см. IEmployeeOrganization: // GET /Employee/ByEmail?Email=... — организации сотрудника (см. IEmployeeOrganization:
// один email может вернуть несколько записей). 404 (email не найден в системе // один email может вернуть несколько записей). 404 (email не найден в системе
@@ -57,3 +58,12 @@ export function getEmployeeOrganizations(context: WebPartContext, email: string)
export function formatEmployeeOrganizations(records: IEmployeeOrganization[]): string { export function formatEmployeeOrganizations(records: IEmployeeOrganization[]): string {
return records.map((r) => (r.position ? `${r.company} — ${r.position}` : r.company)).join('\n'); 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 }));
}
@@ -10,7 +10,11 @@ export { getCompanies } from './companies.service';
export type { ICompany } from './models/ICompany'; export type { ICompany } from './models/ICompany';
export { CompanyPickerMulti } from './ui/CompanyPickerMulti'; export { CompanyPickerMulti } from './ui/CompanyPickerMulti';
export type { ICompanyPickerMultiProps } from './ui/CompanyPickerMulti'; export type { ICompanyPickerMultiProps } from './ui/CompanyPickerMulti';
export { getEmployeeOrganizations, formatEmployeeOrganizations } from './employeeOrganizations.service'; export {
getEmployeeOrganizations,
formatEmployeeOrganizations,
employeeCompanies
} from './employeeOrganizations.service';
export type { IEmployeeOrganization } from './models/IEmployeeOrganization'; export type { IEmployeeOrganization } from './models/IEmployeeOrganization';
export { getNomenclature } from './nomenclature.service'; export { getNomenclature } from './nomenclature.service';
export type { INomenclatureRow } from './models/INomenclatureRow'; export type { INomenclatureRow } from './models/INomenclatureRow';