From 040ab475b523ce5c9ac25a93de45f19f1451fd5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A2=D0=B8=D0=BC=D1=83=D1=80=20=D0=93=D0=BE=D1=80=D0=BE?= =?UTF-8?q?=D0=B4=D0=B5=D1=86=D0=BA=D0=B8=D0=B9?= Date: Thu, 29 Oct 2026 15:11:34 +0500 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=B8=D0=BD=D0=B8=D1=86=D0=B8=D0=B0?= =?UTF-8?q?=D1=82=D0=BE=D1=80=20(=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BD?= =?UTF-8?q?=D0=B8=D0=BA=20/=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BE=D0=B4?= =?UTF-8?q?=D0=B0=D1=82=D0=B5=D0=BB=D1=8C)=20=D0=B2=20=D0=B8=D0=B7=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B8=20=D1=83=D1=81=D0=BB=D0=BE?= =?UTF-8?q?=D0=B2=D0=B8=D0=B9=20=D0=A2=D0=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit По ТЗ у видов, которые может начать и сам работник (3, 4, 5, 7), шаблон разный: у работника — только текст заявления, у работодателя — причины из списка и обоснование. Разделяем строго по ТЗ полем «Инициатор»: по умолчанию «на себя — работник, за другого — работодатель» (с подсказкой под полем), следует за сменой сотрудника, пока его не выбрали руками. Причина у работника при сохранении очищается. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../ContractChange/ContractChangeForm.tsx | 18 +++---- .../forms/ContractChange/README.md | 16 +++++- .../DepartmentTransferSection.tsx | 33 ++++++------ .../byType/InitiatorReasonFields.tsx | 41 +++++++++++++++ .../PositionTransferSection.tsx | 33 ++++++------ .../WorkplaceChangeSection.tsx | 31 ++++++----- .../ContractChange/byType/submitChecks.ts | 10 +++- .../forms/ContractChange/changeTypes.ts | 33 ++++++++++++ .../forms/ContractChange/load.ts | 4 +- .../forms/ContractChange/model.ts | 30 ++++++++++- .../forms/ContractChange/provisioning.json | 1 + .../sections/RequestSection.tsx | 51 ++++++++++++++++-- .../forms/ContractChange/submit.ts | 19 +++++-- .../ContractChange/useInitiatorAutofill.ts | 52 +++++++++++++++++++ 14 files changed, 298 insertions(+), 74 deletions(-) create mode 100644 src/webparts/requestPortal/forms/ContractChange/byType/InitiatorReasonFields.tsx create mode 100644 src/webparts/requestPortal/forms/ContractChange/useInitiatorAutofill.ts diff --git a/src/webparts/requestPortal/forms/ContractChange/ContractChangeForm.tsx b/src/webparts/requestPortal/forms/ContractChange/ContractChangeForm.tsx index 553438d..4785acd 100644 --- a/src/webparts/requestPortal/forms/ContractChange/ContractChangeForm.tsx +++ b/src/webparts/requestPortal/forms/ContractChange/ContractChangeForm.tsx @@ -36,17 +36,11 @@ import { dataListTitle, dataListTitleForListId } from '../../shared/listTitles'; -import { - FORM_ID, - IFormData, - EMPTY_DATA, - SetField, - REQUIRED_FIELDS_MESSAGE, - routeEmail -} from './model'; +import { FORM_ID, IFormData, EMPTY_DATA, SetField, REQUIRED_FIELDS_MESSAGE, routeEmail } from './model'; import { saveContractChangeRequest, contractChangeApprovalService } from './submit'; import { loadContractChangeRequest } from './load'; import { useContractEmployee } from './useContractEmployee'; +import { useInitiatorAutofill } from './useInitiatorAutofill'; import { RequestSection } from './sections/RequestSection'; import { ChangeTypeSections } from './byType/ChangeTypeSections'; import { prepareFilesFor } from './byType/attachmentSlots'; @@ -116,10 +110,11 @@ const ContractChangeForm: React.FC = ({ const employeeControl = useContractEmployee(context, applicantEmail, !editId, data.Employee, (record) => set('Employee', record) ); + // Пропсы шапки: сотрудник + инициатор, который следует за сотрудником, пока его не выбрали руками. + const headerProps = useInitiatorAutofill(!!editId, data, set, applicantEmail, employeeControl); // Маршрут — по сотруднику, без учётной записи — по заявителю (см. routeEmail); при // переводе в другое подразделение принимающий руководитель — первым шагом. - const isDepartmentTransfer = data.ChangeTypes.includes('department-transfer'); const { matrix, executors } = useContractRoute({ context, approval, @@ -128,7 +123,8 @@ const ContractChangeForm: React.FC = ({ editId, requestStatus, readOnly, - receivingHeadEmail: !readOnly && isDepartmentTransfer ? data.DepartmentTransferReceivingHead : '' + receivingHeadEmail: + !readOnly && data.ChangeTypes.includes('department-transfer') ? data.DepartmentTransferReceivingHead : '' }); const isValid = !!data.Employee && data.ChangeTypes.length > 0; @@ -257,7 +253,7 @@ const ContractChangeForm: React.FC = ({ {submit.error && {submit.error}} - + diff --git a/src/webparts/requestPortal/forms/ContractChange/README.md b/src/webparts/requestPortal/forms/ContractChange/README.md index 631ac92..4ffb7b6 100644 --- a/src/webparts/requestPortal/forms/ContractChange/README.md +++ b/src/webparts/requestPortal/forms/ContractChange/README.md @@ -64,8 +64,20 @@ RequestTypeId» в `docs/forms.md`). Тип и маршрут в админке | Изменение места работы (другая местность) | `WorkplaceChange` | место работы «было → стало» парой **организация + проект**: текущая организация — из «Организации» сотрудника (только чтение, отдельно не хранится — это `EmployeeCompany`), текущий проект (`ProjectPicker`); новая организация (`Dictionary/Companies`, **обязательна при отправке**, не подставляется) и новый проект; адрес нового места, дата, причина (новый объект / переезд подразделения или работодателя / иное), условия переезда и компенсации; переключатель **«Вахта»** → «График работы» (тот же набор, что в подборе и приёме, «Другое» → ручной ввод; без вахты график очищается); обоснование | | Остальные 5 | — | ещё не разобраны с кадрами | -Обязательное по виду при отправке (документы, принимающий руководитель, новая -организация) — одна функция `byType/submitChecks.ts`; черновик сохраняется без них. +Обязательное по виду при отправке (инициатор, документы, принимающий руководитель, +новая организация) — одна функция `byType/submitChecks.ts`; черновик сохраняется без них. + +**Инициатор (работник / работодатель)** — решение 2026-10-29: разделяем строго по +ТЗ, чтобы у кадров не было вопросов. Поле `ChangeInitiator` в шапке — только у +видов, которые по ТЗ может начать и работник (3, 4, 5, 7; `hasInitiatorChoice`). +По умолчанию при выборе вида: подаёт на себя — «Работник», за другого — +«Работодатель» (`defaultInitiatorRole`), под полем подсказка об этом; можно +поменять. Пока инициатора не выбирали руками, он следует за сотрудником: сменили +сотрудника — пересчитался (`useInitiatorAutofill`); после ручного выбора и у +открытого черновика — не трогается. От роли (`byType/InitiatorReasonFields`): работник — только «Текст +заявления» (по ТЗ «От работника: заявление (текст)»), работодатель — причина из +списка + «Обоснование». Текст пишется в ту же колонку `*Justification`; причина у +работника при сохранении очищается. Остальные поля вида — у обеих ролей. **Принимающий руководитель — временное решение (2026-10-29).** По ТЗ (лист «Маршрут»: А шаг 2, Б шаг 3 параллельно с непосредственным руководителем) его diff --git a/src/webparts/requestPortal/forms/ContractChange/byType/DepartmentTransfer/DepartmentTransferSection.tsx b/src/webparts/requestPortal/forms/ContractChange/byType/DepartmentTransfer/DepartmentTransferSection.tsx index 01f624e..504880d 100644 --- a/src/webparts/requestPortal/forms/ContractChange/byType/DepartmentTransfer/DepartmentTransferSection.tsx +++ b/src/webparts/requestPortal/forms/ContractChange/byType/DepartmentTransfer/DepartmentTransferSection.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; -import { CollapseSection, FormField, TextInput, TextArea, Select, PeopleField } from '../../../../shared/ui'; +import { CollapseSection, FormField, TextInput, PeopleField } from '../../../../shared/ui'; +import { InitiatorReasonFields } from '../InitiatorReasonFields'; import { DepartmentPicker } from '../../../../shared/dictionary'; import { CHANGE_TYPE_LABELS } from '../../changeTypes'; import { ISectionProps } from '../../model'; @@ -44,21 +45,19 @@ export const DepartmentTransferSection: React.FC = ({ data, set, placeholder="Начните вводить Ф.И.О. руководителя, который принимает работника…" /> - -