From fa551caf5e59f6e6a0a5d04eec6c1ff9bb2abaa5 Mon Sep 17 00:00:00 2001 From: "gorbenko.pavel" Date: Fri, 14 Aug 2026 12:09:28 +0500 Subject: [PATCH] =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D0=B0=D1=8F=20=D1=84=D0=BE?= =?UTF-8?q?=D1=80=D0=BC=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../forms/Clearance/ClearanceForm.tsx | 14 +++++++------ .../Clearance/sections/RequestSection.tsx | 21 +++++++++++++++++-- .../shared/approval/approvalList.service.ts | 14 ++++++++++--- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/src/webparts/requestPortal/forms/Clearance/ClearanceForm.tsx b/src/webparts/requestPortal/forms/Clearance/ClearanceForm.tsx index f21246c..13f5a13 100644 --- a/src/webparts/requestPortal/forms/Clearance/ClearanceForm.tsx +++ b/src/webparts/requestPortal/forms/Clearance/ClearanceForm.tsx @@ -70,17 +70,19 @@ const ClearanceForm: React.FC = ({ requestType, context, onCa // eslint-disable-next-line react-hooks/exhaustive-deps }, [editId]); - // Выбор увольняемого сотрудника подтягивает его текущую должность — это только - // отправная точка для поля «Должность» (её можно поправить вручную, например - // если человек занимал руководящую должность до перевода), а не жёсткая связь. + // Должность/подразделение больше не вводятся вручную — подтягиваются из + // SharePoint User Profile (SPS-JobTitle/SPS-Department) при выборе сотрудника. + // Если профиль не синхронизирован и поле там пусто — пока просто остаётся + // пустым (TODO: фолбэк на справочник api.tnsu.kz, если это окажется частой + // проблемой на практике). const handleEmployeeChange = (login: string): void => { - setData((prev) => ({ ...prev, Employee: login })); + setData((prev) => ({ ...prev, Employee: login, Position: '', Department: '' })); if (!login) { return; } approval - .getJobTitle(login) - .then((title) => setData((prev) => ({ ...prev, Position: title || prev.Position }))) + .getProfileFields(login) + .then((profile) => setData((prev) => ({ ...prev, Position: profile.jobTitle, Department: profile.department }))) .catch(() => undefined); }; diff --git a/src/webparts/requestPortal/forms/Clearance/sections/RequestSection.tsx b/src/webparts/requestPortal/forms/Clearance/sections/RequestSection.tsx index 3ce6e36..9e84cfe 100644 --- a/src/webparts/requestPortal/forms/Clearance/sections/RequestSection.tsx +++ b/src/webparts/requestPortal/forms/Clearance/sections/RequestSection.tsx @@ -2,6 +2,11 @@ import * as React from 'react'; import { CollapseSection, FormField, TextInput, MoneyInput, Toggle, PeopleField } from '../../../shared/ui'; import { ISectionProps, EMPLOYEE_PLACEHOLDER } from '../model'; +// Должность/подразделение подтягиваются автоматически при выборе сотрудника +// (см. ClearanceForm.handleEmployeeChange — SharePoint User Profile) — +// свободный ввод здесь намеренно убран, чтобы не расходиться с профилем. +const NOOP = (): void => undefined; + /** Единственная секция формы «Обходной лист»: увольняемый, должность, подразделение, даты, карты, обучение. */ export const RequestSection: React.FC = ({ data, set, context, onEmployeeChange }) => ( @@ -14,10 +19,22 @@ export const RequestSection: React.FC = ({ data, set, context, on /> - set('Position', v)} /> + - set('Department', v)} /> + { - if (!loginName) return ''; + return (await this.getProfileFields(loginName)).jobTitle; + } + + // Должность + подразделение из профиля SharePoint (SPS-JobTitle/SPS-Department) + // ОДНИМ запросом — используется там, где нужны оба поля (напр. предзаполнение + // «Обходного листа»), чтобы не дёргать getPropertiesFor дважды подряд. + // '' по каждому полю, если недоступно/профиль не синхронизирован. + public async getProfileFields(loginName: string): Promise<{ jobTitle: string; department: string }> { + if (!loginName) return { jobTitle: '', department: '' }; const account = loginName.indexOf('|') >= 0 ? loginName : `i:0#.f|membership|${loginName}`; try { const props = (await getSP().profiles.getPropertiesFor(account)) as { @@ -313,9 +321,9 @@ export class ApprovalListService { : ((raw as { results?: Array<{ Key: string; Value: string }> })?.results ?? []); const map: Record = {}; for (const p of list) map[p.Key] = p.Value; - return map['SPS-JobTitle'] || map.Title || ''; + return { jobTitle: map['SPS-JobTitle'] || map.Title || '', department: map['SPS-Department'] || '' }; } catch { - return ''; + return { jobTitle: '', department: '' }; } }