feat: убрано «Самостоятельное подразделение», суммы к списанию компактно с общим комментарием

Заявление на увольнение: убрано поле «Самостоятельное подразделение»
(StandaloneUnit) — из модели, формы и манифеста провижинера. Колонка на
тенанте остаётся (провижинер их не удаляет), но код её больше не пишет и не
читает.

Обходной лист: убраны 6 отдельных textarea-комментариев под каждой суммой —
сетка сумм теперь компактная (короткие подписи, обычная 2-колоночная сетка
секции, без full). Вместо пары «сумма+комментарий» на категорию — ОДИН общий
комментарий, который появляется и становится обязательным, как только хоть
одна редактируемая сумма заполнена (при сохранении бросает ДО записи, если
сумма есть, а комментарий пуст). Плейсхолдер называет категории, для которых
он сейчас пишется («Введите, за что сумма: ОС, ТМЦ»).

При записи общий текст дублируется в Comment-колонку КАЖДОЙ заполняемой сейчас
категории (SP-схема из 6 пар Amount/Comment не менялась) — так по каждой
категории в списке остаётся свой комментарий, а форма не заставляет писать
одно и то же несколько раз подряд.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
gorbenko.pavel
2026-08-26 12:37:04 +05:00
parent 04f1d0d547
commit cd1fd76c76
11 changed files with 178 additions and 155 deletions
+1 -1
View File
@@ -45,7 +45,7 @@
| [`recruiting-referral`](../src/webparts/requestPortal/forms/Referral/README.md) | Реферальная рекомендация | Рекрутинг | да | да | да | кандидат — внешний (текстовые поля, не People); маршрут по рекомендателю; исполнитель переназначает на реального; условное уточнение «откуда знаете» | ✅ |
| [`it-workplace-setup`](../src/webparts/requestPortal/forms/WorkplaceSetup/README.md) | Организация рабочего места | IT | да | да | да | префилл из «прием», поля ПО/доступы правит руководитель | ✅ |
| [`it-1c-ticket`](../src/webparts/requestPortal/forms/Ticket1C/README.md) | Заявка в отдел 1С | IT | да | нет | да | контакты предзаполняются из Graph (/me); вместо фазы исполнения — карточка в Microsoft Planner (согласовано/сразу без согласования — рабочий бакет, отклонено — отдельный бакет) | ✅ |
| [`clearance-form`](../src/webparts/requestPortal/forms/Clearance/README.md) | Обходной лист | Отдел кадров | да | нет | да | подаётся HR за увольняемого (People-picker) либо создаётся сам по согласованному «Заявлению на увольнение»; условие «IsManager» резолвится по должности из самой заявки; да/нет-поля (парковка, СКУД); 6 независимых пар «сумма к списанию + комментарий» (ОС, СИЗ, подотчётная сумма, обучение, НМА, ТМЦ) — вводит любой активный согласующий, блокируется навсегда после первого ввода | ✅ |
| [`clearance-form`](../src/webparts/requestPortal/forms/Clearance/README.md) | Обходной лист | Отдел кадров | да | нет | да | подаётся HR за увольняемого (People-picker) либо создаётся сам по согласованному «Заявлению на увольнение»; условие «IsManager» резолвится по должности из самой заявки; да/нет-поля (парковка, СКУД); 6 независимых сумм к списанию компактной сеткой (ОС, СИЗ, подотчётная сумма, обучение, НМА, ТМЦ) — вводит любой активный согласующий, блокируется навсегда после первого ввода; заполнил хоть одну — общий комментарий «за что» становится обязательным | ✅ |
| [`hr-dismissal`](../src/webparts/requestPortal/forms/Dismissal/README.md) | Заявление на увольнение | Отдел кадров | да | нет | да | совместители — таблица компаний с удалением строки (снимает и согласующего из матрицы); должность/организация из справочника; **после согласования сам создаёт обходной лист**; печать заблокирована до согласования обходного листа; «Лицо, принимающее ОС/НМА» — заполняет только непосредственный руководитель | ✅ |
| `hr-transfer` | Перемещение сотрудников | Отдел кадров | — | — | — | — | ⏳ заглушка (плитка есть, форма не сделана) |
@@ -170,10 +170,13 @@ const ClearanceView: React.FC<IClearanceViewProps> = ({ context, itemId, formKey
);
// Пишем ТОЛЬКО те отметки, на которые у согласующего есть права: иначе он
// затёр бы чужие поля значениями, которые видел у себя на экране. Пары сумм к
// списанию — только НЕПУСТЫЕ и только среди editableWriteOffKeys; частично
// заполненная пара (сумма без комментария или наоборот) бросает ДО записи
// чего бы то ни было — половинчатая запись хуже отказа сохранить.
// затёр бы чужие поля значениями, которые видел у себя на экране. Суммы к
// списанию — только НЕПУСТЫЕ и только среди editableWriteOffKeys; комментарий
// ОДИН на все суммы, заполняемые СЕЙЧАС (не пара на каждую, см. IFormData.
// WriteOffComment) — если хоть одна из них не пуста, комментарий обязателен
// (бросает ДО записи чего бы то ни было) и при записи дублируется в
// Comment-колонку КАЖДОЙ такой категории — так каждая остаётся
// прокомментированной в самом списке.
const saveApproverFields = useCallback(async (): Promise<void> => {
const fields: Partial<IApproverEditableFields> = {};
if (hrRecordsEditable) {
@@ -184,19 +187,19 @@ const ClearanceView: React.FC<IClearanceViewProps> = ({ context, itemId, formKey
fields.ParkingCard = data.ParkingCard;
}
const touched = WRITE_OFF_CATEGORIES.filter(
(cat) => editableWriteOffKeys.has(cat.key) && data[cat.amountField].trim() !== ''
);
const writeOffFields: Partial<IWriteOffFields> = {};
for (const cat of WRITE_OFF_CATEGORIES) {
if (!editableWriteOffKeys.has(cat.key)) continue;
const amount = data[cat.amountField].trim();
const comment = data[cat.commentField].trim();
if (!amount && !comment) continue; // не трогали — не пишем
if (!amount || !comment) {
throw new Error(
`«${cat.label}»: заполните и сумму, и комментарий (за что конкретно) — или оставьте пару пустой.`
);
if (touched.length > 0) {
const comment = data.WriteOffComment.trim();
if (!comment) {
throw new Error('Укажите комментарий — за что списываются суммы.');
}
for (const cat of touched) {
writeOffFields[cat.amountField] = data[cat.amountField];
writeOffFields[cat.commentField] = comment;
}
writeOffFields[cat.amountField] = data[cat.amountField];
writeOffFields[cat.commentField] = data[cat.commentField];
}
await updateApproverFields(itemId, fields, listId);
@@ -55,21 +55,28 @@ RequestTypeId» в `docs/forms.md`). Тип уже зарегистрирова
заведённых руками, ссылки нет и поле не рендерится.
## Суммы к списанию (согласование)
6 НЕЗАВИСИМЫХ пар «сумма + обязательный комментарий (за что конкретно)», колонки
`WriteOff{Assets,Ppe,Accountable,Training,Nma,Tmc}{Amount,Comment}` (см. `model.ts
WRITE_OFF_CATEGORIES`): «ОС», «СИЗ», «Подотчётная сумма», «Обучение», «НМА», «ТМЦ».
6 НЕЗАВИСИМЫХ сумм, компактной сеткой (короткие подписи, без комментария под
каждой — см. ниже), колонки `WriteOff{Assets,Ppe,Accountable,Training,Nma,Tmc}
{Amount,Comment}` (см. `model.ts WRITE_OFF_CATEGORIES`): «ОС», «СИЗ», «Подотчётная
сумма», «Обучение», «НМА», «ТМЦ».
- **Не привязаны к должности**, в отличие от отметок выше: заполнить может ЛЮБОЙ
согласующий, у которого сейчас активный шаг (`ClearanceView.canEditWriteOffs`,
фаза «Согласование» — исполнителям недоступно, как и остальным отметкам).
- **Каждая пара блокируется НАВСЕГДА после первого ввода** — как только сумма
- **Каждая сумма блокируется НАВСЕГДА после первого ввода** — как только она
непустая, поле становится read-only для всех, включая того, кто её ввёл.
Признак блокировки — сама непустая сумма на МОМЕНТ ЗАГРУЗКИ страницы
(`ClearanceView.lockedWriteOffs`, снимок при загрузке, а не реактивно от
текущего `data` — иначе поле блокировалось бы прямо во время набора цифр).
- **Комментарий обязателен вместе с суммой**: заполнить можно либо обе половины
пары, либо ни одной — `saveApproverFields` бросает ДО записи чего бы то ни
было, если половина пары осталась пустой.
- **Комментарий — ОДИН на все суммы, заполняемые в ЭТОМ сохранении** (не пара на
каждую категорию, как раньше): появляется под сеткой, только когда хоть одна
редактируемая сумма не пуста (`writeOffTouchedCategories` в `RequestSection`),
и обязателен в этот момент — `saveApproverFields` бросает ДО записи чего бы то
ни было, если сумма есть, а комментарий пуст. Плейсхолдер называет категории,
для которых он сейчас пишется («Введите, за что сумма: ОС, ТМЦ»). При записи
этот ОДИН текст дублируется в Comment-колонку КАЖДОЙ заполняемой сейчас
категории — так индивидуальный комментарий по категории в списке остаётся, а
форма не заставляет писать одно и то же под каждой суммой отдельно.
- Сохраняются той же кнопкой «Сохранить» (`reviewBar`), что и остальные отметки,
и тем же `onBeforeDecide` — при решении несохранённые суммы уйдут вместе с ним.
- Это ОТДЕЛЬНЫЙ механизм от `TrainingAmount` («Обучение: сумма» выше, привязана к
@@ -78,7 +85,8 @@ WRITE_OFF_CATEGORIES`): «ОС», «СИЗ», «Подотчётная сумм
## Секции формы
RequestSection (сотрудник · должность · подразделение · дата расторжения · сумма
обучения · парковочная карта · карта СКУД · суммы к списанию · ссылка на заявление)
обучения · парковочная карта · карта СКУД · суммы к списанию (компактно) + общий
комментарий · ссылка на заявление)
## Точки входа
- rptype: `clearance-form`
@@ -39,13 +39,20 @@ export interface IFormData {
DismissalUrl: string;
/**
* Суммы к списанию по обходному листу — 6 независимых пар (сумма +
* обязательный комментарий, «за что конкретно»), см. WRITE_OFF_CATEGORIES.
* «Сырые» цифры без пробелов, как TrainingAmount (см. MoneyInput). Пусто =
* не заполнено. КАЖДАЯ пара — независимая: заполнить может любой активный
* согласующий (см. ClearanceView.canEditWriteOffs), но как только сумма
* непустая — пара блокируется НАВСЕГДА, для всех (включая того, кто её ввёл).
* Признак блокировки — сама непустая сумма, отдельного флага в списке нет.
* Суммы к списанию по обходному листу — 6 независимых сумм (компактная сетка
* полей, см. WRITE_OFF_CATEGORIES). «Сырые» цифры без пробелов, как
* TrainingAmount (см. MoneyInput). Пусто = не заполнено. КАЖДАЯ —
* независимая: заполнить может любой активный согласующий (см.
* ClearanceView.canEditWriteOffs), но как только сумма непустая — блокируется
* НАВСЕГДА, для всех (включая того, кто её ввёл). Признак блокировки — сама
* непустая сумма, отдельного флага в списке нет.
*
* Комментарий («за что конкретно») — ОБЩИЙ на все суммы, вводимые ОДНИМ
* сохранением (WriteOffComment, ниже), не отдельная пара на каждую категорию:
* при записи он дублируется в Comment-колонку КАЖДОЙ категории, чью сумму
* заполнили именно сейчас (см. ClearanceView.saveApproverFields) — так каждая
* категория остаётся комментированной в самом списке, а форма не заставляет
* писать одно и то же по кругу под каждой суммой.
*/
WriteOffAssetsAmount: string;
WriteOffAssetsComment: string;
@@ -59,6 +66,12 @@ export interface IFormData {
WriteOffNmaComment: string;
WriteOffTmcAmount: string;
WriteOffTmcComment: string;
/**
* Комментарий к сумме(ам), заполняемым ПРЯМО СЕЙЧАС (не из списка — вводится
* заново при каждом сохранении, см. комментарий выше). Обязателен, если хоть
* одна из редактируемых сумм не пуста (см. RequestSection).
*/
WriteOffComment: string;
}
/** Имена всех 12 строковых полей сумм/комментариев к списанию — см. IFormData.WriteOff*. */
@@ -145,7 +158,8 @@ export const EMPTY_DATA: IFormData = {
WriteOffNmaAmount: '',
WriteOffNmaComment: '',
WriteOffTmcAmount: '',
WriteOffTmcComment: ''
WriteOffTmcComment: '',
WriteOffComment: ''
};
/** Плейсхолдер для поля выбора сотрудника. */
@@ -31,114 +31,125 @@ export const RequestSection: React.FC<IRequestSectionProps> = ({
hrRecordsEditable,
parkingEditable,
writeOffEditableKeys
}) => (
<CollapseSection title="Обходной лист" icon="people">
<FormField label="Сотрудник" htmlFor="Employee" required full>
<PeopleField
context={context}
value={data.Employee}
onChange={onEmployeeChange ?? ((v) => set('Employee', v))}
placeholder={EMPLOYEE_PLACEHOLDER}
/>
</FormField>
{/* Подтягивается из профиля при выборе сотрудника, но поле остаётся
редактируемым: если профиль не синхронизирован (SPS-JobTitle пуст),
HR должен суметь ввести должность вручную — иначе маршрут
согласования (условие «IsManager» резолвится именно по ней) не
соберётся, и список исполнителей ниже останется пустым. */}
<FormField label="Должность" htmlFor="Position" required>
<TextInput
id="Position"
value={data.Position}
onChange={(v) => set('Position', v)}
placeholder="Подставится автоматически по выбранному сотруднику"
/>
</FormField>
<FormField label="Подразделение" htmlFor="Department">
<TextInput
id="Department"
value={data.Department}
onChange={NOOP}
readOnly
placeholder="Подставится автоматически по выбранному сотруднику"
/>
</FormField>
<OrganizationField value={data.Organization} />
<FormField label="Дата расторжения договора" htmlFor="TerminationDate" required>
<TextInput
id="TerminationDate"
type="date"
value={data.TerminationDate}
onChange={(v) => set('TerminationDate', v)}
/>
</FormField>
{/* Явный readOnly={false} перебивает read-only контекст просмотра (профильный
согласующий правит своё поле); undefined — обычное поведение из FormMode. */}
<FormField label="Обучение: сумма" htmlFor="TrainingAmount">
<MoneyInput
id="TrainingAmount"
value={data.TrainingAmount}
onChange={(v) => set('TrainingAmount', v)}
readOnly={hrRecordsEditable ? false : undefined}
/>
</FormField>
<FormField label="Парковочная карта">
<Toggle
checked={data.ParkingCard}
onChange={(v) => set('ParkingCard', v)}
onLabel="Да"
readOnly={parkingEditable ? false : undefined}
/>
</FormField>
<FormField label="Карта СКУД">
<Toggle
checked={data.AccessCard}
onChange={(v) => set('AccessCard', v)}
onLabel="Да"
readOnly={hrRecordsEditable ? false : undefined}
/>
</FormField>
{/* Суммы к списанию — 6 независимых пар (сумма + обязательный комментарий,
за что конкретно). Каждую может заполнить ЛЮБОЙ активный согласующий
(не только профильный, в отличие от отметок выше) — но как только сумма
указана, пара блокируется навсегда для всех, поэтому у незаблокированных
(writeOffEditableKeys.has(cat.key)) есть readOnly={false}, у остальных —
обычное поведение FormMode (просмотр — заблокировано и так). */}
{writeOffEditableKeys &&
WRITE_OFF_CATEGORIES.map((cat) => {
const editable = writeOffEditableKeys.has(cat.key);
return (
<React.Fragment key={cat.key}>
<FormField label={`${cat.label}: сумма`} htmlFor={cat.amountField}>
<MoneyInput
id={cat.amountField}
value={data[cat.amountField]}
onChange={(v) => set(cat.amountField, v)}
readOnly={editable ? false : undefined}
/>
</FormField>
<FormField
label={`${cat.label}: за что конкретно`}
htmlFor={cat.commentField}
required={editable}
full
>
}) => {
// Категории, чью сумму заполняют ПРЯМО СЕЙЧАС (редактируема и не пуста) —
// от них зависит, показывать ли общий комментарий и что подставить в его
// плейсхолдер (см. IFormData.WriteOffComment в model.ts).
const writeOffTouchedCategories = writeOffEditableKeys
? WRITE_OFF_CATEGORIES.filter((cat) => writeOffEditableKeys.has(cat.key) && data[cat.amountField].trim() !== '')
: [];
return (
<CollapseSection title="Обходной лист" icon="people">
<FormField label="Сотрудник" htmlFor="Employee" required full>
<PeopleField
context={context}
value={data.Employee}
onChange={onEmployeeChange ?? ((v) => set('Employee', v))}
placeholder={EMPLOYEE_PLACEHOLDER}
/>
</FormField>
{/* Подтягивается из профиля при выборе сотрудника, но поле остаётся
редактируемым: если профиль не синхронизирован (SPS-JobTitle пуст),
HR должен суметь ввести должность вручную — иначе маршрут
согласования (условие «IsManager» резолвится именно по ней) не
соберётся, и список исполнителей ниже останется пустым. */}
<FormField label="Должность" htmlFor="Position" required>
<TextInput
id="Position"
value={data.Position}
onChange={(v) => set('Position', v)}
placeholder="Подставится автоматически по выбранному сотруднику"
/>
</FormField>
<FormField label="Подразделение" htmlFor="Department">
<TextInput
id="Department"
value={data.Department}
onChange={NOOP}
readOnly
placeholder="Подставится автоматически по выбранному сотруднику"
/>
</FormField>
<OrganizationField value={data.Organization} />
<FormField label="Дата расторжения договора" htmlFor="TerminationDate" required>
<TextInput
id="TerminationDate"
type="date"
value={data.TerminationDate}
onChange={(v) => set('TerminationDate', v)}
/>
</FormField>
{/* Явный readOnly={false} перебивает read-only контекст просмотра (профильный
согласующий правит своё поле); undefined — обычное поведение из FormMode. */}
<FormField label="Обучение: сумма" htmlFor="TrainingAmount">
<MoneyInput
id="TrainingAmount"
value={data.TrainingAmount}
onChange={(v) => set('TrainingAmount', v)}
readOnly={hrRecordsEditable ? false : undefined}
/>
</FormField>
<FormField label="Парковочная карта">
<Toggle
checked={data.ParkingCard}
onChange={(v) => set('ParkingCard', v)}
onLabel="Да"
readOnly={parkingEditable ? false : undefined}
/>
</FormField>
<FormField label="Карта СКУД">
<Toggle
checked={data.AccessCard}
onChange={(v) => set('AccessCard', v)}
onLabel="Да"
readOnly={hrRecordsEditable ? false : undefined}
/>
</FormField>
{/* Суммы к списанию — 6 независимых сумм, компактной сеткой (обычная
2-колоночная сетка секции, короткие подписи — без full). Каждую может
заполнить ЛЮБОЙ активный согласующий (не только профильный, в отличие
от отметок выше) — но как только сумма указана, блокируется навсегда
для всех, поэтому у незаблокированных (writeOffEditableKeys.has(cat.key))
есть readOnly={false}, у остальных — обычное поведение FormMode
(просмотр — заблокировано и так). Комментарий — ОДИН на все суммы,
вводимые сейчас (см. WRITE_OFF_CATEGORIES/WriteOffComment в model.ts). */}
{writeOffEditableKeys && (
<>
{WRITE_OFF_CATEGORIES.map((cat) => {
const editable = writeOffEditableKeys.has(cat.key);
return (
<FormField key={cat.key} label={cat.label} htmlFor={cat.amountField}>
<MoneyInput
id={cat.amountField}
value={data[cat.amountField]}
onChange={(v) => set(cat.amountField, v)}
readOnly={editable ? false : undefined}
/>
</FormField>
);
})}
{writeOffTouchedCategories.length > 0 && (
<FormField label="Комментарий: за что списание" htmlFor="WriteOffComment" required full>
<TextArea
id={cat.commentField}
value={data[cat.commentField]}
onChange={(v) => set(cat.commentField, v)}
readOnly={editable ? false : undefined}
id="WriteOffComment"
value={data.WriteOffComment}
onChange={(v) => set('WriteOffComment', v)}
placeholder={`Введите, за что сумма${
writeOffTouchedCategories.length > 1 ? 'ы' : ''
}: ${writeOffTouchedCategories.map((c) => c.label).join(', ')}`}
/>
</FormField>
</React.Fragment>
);
})}
{/* Есть только у листов, созданных автоматически по согласованному заявлению
на увольнение (см. forms/Dismissal/createClearance.ts). */}
<LinkField
label="Заявление на увольнение"
url={data.DismissalUrl}
text="Открыть заявление, по которому создан этот лист"
/>
</CollapseSection>
);
)}
</>
)}
{/* Есть только у листов, созданных автоматически по согласованному заявлению
на увольнение (см. forms/Dismissal/createClearance.ts). */}
<LinkField
label="Заявление на увольнение"
url={data.DismissalUrl}
text="Открыть заявление, по которому создан этот лист"
/>
</CollapseSection>
);
};
@@ -52,8 +52,6 @@ RequestTypeId» в `docs/forms.md`). Тип заведён в админке app
/ `organizationColumn` в `model.ts`/`submit.ts`; не-JSON значение (заявка,
сохранённая до перехода на этот формат) не роняет чтение — трактуется как одна
компания (см. `parseOrganizationColumn`).
- **Самостоятельное подразделение** (`StandaloneUnit`) — в справочнике его нет,
свободный ввод, единственное текстовое поле, оставшееся отдельно от таблицы.
- **Последний рабочий день** (`LastWorkingDay`) — обязателен, не раньше чем через
`MIN_NOTICE_MONTHS` (1) календарный месяц от сегодня (`isoDatePlusMonths`,
`min` у `input type=date` + проверка в `validate` на случай обхода UI) — срок
@@ -173,9 +171,8 @@ approval-route (`getPlannedMatrix` для фаз «Согласование» и
## Секции формы
RequestSection (сотрудник · организация/департамент/должность (таблица —
редактируемая на форме подачи, read-only в просмотре) · самостоятельное
подразделение · последний рабочий день · телефон · комментарий · ссылка на
обходной лист · лицо, принимающее ОС/НМА)
редактируемая на форме подачи, read-only в просмотре) · последний рабочий день ·
телефон · комментарий · ссылка на обходной лист · лицо, принимающее ОС/НМА)
## Точки входа
- rptype: `hr-dismissal`
@@ -27,7 +27,6 @@ export async function loadDismissalRequest(itemId: number, listId?: string): Pro
'Id',
'Position',
'Department',
'StandaloneUnit',
'LastWorkingDay',
'Phone',
'Comment',
@@ -48,7 +47,6 @@ export async function loadDismissalRequest(itemId: number, listId?: string): Pro
const data: IFormData = {
...EMPTY_DATA,
Employee: employee?.EMail || '',
StandaloneUnit: (item.StandaloneUnit as string) || '',
LastWorkingDay: lastDay.slice(0, 10), // ISO → YYYY-MM-DD для input type=date
Phone: (item.Phone as string) || '',
Comment: (item.Comment as string) || '',
@@ -86,8 +86,6 @@ export function zipOrganization(
export interface IFormData {
/** E-mail сотрудника, за которого заявка (People). Пусто = не выбран. */
Employee: string;
/** Самостоятельное подразделение — в справочнике его нет, вводится вручную. */
StandaloneUnit: string;
/** Последний рабочий день, ISO YYYY-MM-DD (input type=date). */
LastWorkingDay: string;
/** Контактный телефон (маска, см. PhoneInput). */
@@ -139,7 +137,6 @@ export interface ISectionProps {
export const EMPTY_DATA: IFormData = {
Employee: '',
StandaloneUnit: '',
LastWorkingDay: '',
Phone: '',
Comment: '',
@@ -7,7 +7,6 @@
{ "internalName": "Employee", "title": "Сотрудник", "type": "User", "userSelectionMode": "PeopleOnly", "required": true },
{ "internalName": "Position", "title": "Должность", "type": "Text" },
{ "internalName": "Department", "title": "Департамент", "type": "Text" },
{ "internalName": "StandaloneUnit", "title": "Самостоятельное подразделение", "type": "Text" },
{ "internalName": "LastWorkingDay", "title": "Последний рабочий день", "type": "DateTime", "dateOnly": true },
{ "internalName": "Phone", "title": "Контактный телефон", "type": "Text" },
{ "internalName": "Comment", "title": "Комментарий", "type": "Note" },
@@ -55,9 +55,6 @@ export const RequestSection: React.FC<IRequestSectionProps> = ({
}
onRemove={onRemoveOrganization}
/>
<FormField label="Самостоятельное подразделение" htmlFor="StandaloneUnit">
<TextInput id="StandaloneUnit" value={data.StandaloneUnit} onChange={(v) => set('StandaloneUnit', v)} />
</FormField>
{/* Заявление подаётся заранее — датой увольнения нельзя назначить ближе,
чем через MIN_NOTICE_MONTHS месяц от сегодня (min). */}
<FormField label="Последний рабочий день" htmlFor="LastWorkingDay" required>
@@ -85,7 +85,6 @@ function buildItem(
Position: organizationColumn(data.Organization, (r) => r.position, 'Должность', TEXT_COLUMN_LIMIT),
Department: organizationColumn(data.Organization, (r) => r.department, 'Департамент', TEXT_COLUMN_LIMIT),
Organization: organizationColumn(data.Organization, (r) => r.company, 'Организация'),
StandaloneUnit: data.StandaloneUnit || null,
LastWorkingDay: data.LastWorkingDay || null,
Phone: data.Phone || null,
Comment: data.Comment || null