Обходной лист #7
@@ -70,17 +70,19 @@ const ClearanceForm: React.FC<IRequestFormProps> = ({ 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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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<ISectionProps> = ({ data, set, context, onEmployeeChange }) => (
|
||||
<CollapseSection title="Обходной лист" icon="people">
|
||||
@@ -14,10 +19,22 @@ export const RequestSection: React.FC<ISectionProps> = ({ data, set, context, on
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label="Должность" htmlFor="Position" required>
|
||||
<TextInput id="Position" value={data.Position} onChange={(v) => set('Position', v)} />
|
||||
<TextInput
|
||||
id="Position"
|
||||
value={data.Position}
|
||||
onChange={NOOP}
|
||||
readOnly
|
||||
placeholder="Подставится автоматически по выбранному сотруднику"
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label="Подразделение" htmlFor="Department">
|
||||
<TextInput id="Department" value={data.Department} onChange={(v) => set('Department', v)} />
|
||||
<TextInput
|
||||
id="Department"
|
||||
value={data.Department}
|
||||
onChange={NOOP}
|
||||
readOnly
|
||||
placeholder="Подставится автоматически по выбранному сотруднику"
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label="Дата расторжения договора" htmlFor="TerminationDate" required>
|
||||
<TextInput
|
||||
|
||||
@@ -301,7 +301,15 @@ export class ApprovalListService {
|
||||
// сотрудника отдаёт именно e-mail (см. pickedLogin), а getPropertiesFor ждёт
|
||||
// account name — приводим e-mail к клеймовому виду так же, как ensure().
|
||||
public async getJobTitle(loginName: string): Promise<string> {
|
||||
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<string, string> = {};
|
||||
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: '' };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user