fix: «Обучение» подведено под общий заголовок «Суммы к списанию»

TrainingAmount («Обучение: сумма», правит только КДП, не блокируется после
ввода) физически перенесено рядом с 5 суммами списания (правит любой активный
согласующий, блокируются навсегда) — под один заголовок-подпись «СУММЫ К
СПИСАНИЮ». Права и поведение остались разными (readOnly у TrainingAmount
по-прежнему считается отдельно, hrRecordsEditable, а не writeOffEditableKeys),
изменилось только визуальное соседство: раньше поле стояло сразу после «Дата
расторжения договора», далеко от одноимённой группы, из которой недавно убрали
дублирующее «Обучение».

Заголовок группы рисуется независимо от TrainingAmount (только когда
writeOffEditableKeys задан, т.е. в режиме просмотра) — само поле показывается
и на форме подачи, без заголовка, как и раньше.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
gorbenko.pavel
2026-08-26 14:22:47 +05:00
parent 89fceaab1d
commit 27e156abf8
2 changed files with 59 additions and 51 deletions
@@ -55,13 +55,21 @@ RequestTypeId» в `docs/forms.md`). Тип уже зарегистрирова
заведённых руками, ссылки нет и поле не рендерится.
## Суммы к списанию (согласование)
5 НЕЗАВИСИМЫХ сумм, компактной сеткой под подписью «СУММЫ К СПИСАНИЮ» (короткие
подписи, обычная 2-колоночная сетка секции), колонки
`WriteOff{Assets,Ppe,Accountable,Nma,Tmc}Amount` (см. `model.ts
WRITE_OFF_CATEGORIES`): «ОС», «СИЗ», «Подотчётная сумма», «НМА», «ТМЦ».
Обучение сюда НЕ входит — у него уже есть `TrainingAmount` (см. выше) с ДРУГИМ
поведением (правит только КДП); заводить второе одноимённое поле с иным
поведением рядом только путало.
Общий заголовок-подпись «СУММЫ К СПИСАНИЮ» (`RequestSection.module.scss`,
`.writeOffLabel`) объединяет визуально ДВЕ РАЗНЫЕ по правам вещи, идущие сразу
за подписью:
1. **`TrainingAmount`** («Обучение: сумма») — уже существовавшее поле, правит
только КДП (`hrRecordsEditable`, `approverRights.ts`), сумма НЕ блокируется
после ввода. Заголовок рисуется независимо от него (`writeOffEditableKeys &&
<div>…</div>`, а само поле — БЕЗ этого условия), поэтому на форме подачи
(`ClearanceForm`, `writeOffEditableKeys` не передан) поле видно и без заголовка.
2. **5 НЕЗАВИСИМЫХ сумм**, компактной сеткой (короткие подписи, обычная
2-колоночная сетка секции), колонки `WriteOff{Assets,Ppe,Accountable,Nma,
Tmc}Amount` (см. `model.ts WRITE_OFF_CATEGORIES`): «ОС», «СИЗ», «Подотчётная
сумма», «НМА», «ТМЦ» — правит любой активный согласующий, см. ниже. Раньше
среди них было ещё и «Обучение» — убрали как дубль `TrainingAmount` с ДРУГИМ
поведением под тем же названием; общий заголовок группы остался.
- **Не привязаны к должности**, в отличие от отметок выше: заполнить может ЛЮБОЙ
согласующий, у которого сейчас активный шаг (`ClearanceView.canEditWriteOffs`,
@@ -89,9 +97,9 @@ WRITE_OFF_CATEGORIES`): «ОС», «СИЗ», «Подотчётная сумм
поведение существующего поля.
## Секции формы
RequestSection (сотрудник · должность · подразделение · дата расторжения · сумма
обучения · парковочная карта · карта СКУД · суммы к списанию (компактно) ·
ссылка на заявление)
RequestSection (сотрудник · должность · подразделение · дата расторжения ·
парковочная карта · карта СКУД · «Суммы к списанию»: обучение + 5 сумм списания
компактно под общим заголовком · ссылка на заявление)
## Точки входа
- rptype: `clearance-form`
@@ -74,16 +74,6 @@ export const RequestSection: React.FC<IRequestSectionProps> = ({
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}
@@ -100,23 +90,35 @@ export const RequestSection: React.FC<IRequestSectionProps> = ({
readOnly={hrRecordsEditable ? false : undefined}
/>
</FormField>
{/* Суммы к списанию — 6 независимых сумм, компактной сеткой (обычная
2-колоночная сетка секции, короткие подписи — без full). Заголовок
группы ОБЯЗАТЕЛЕН: без него «Обучение» здесь читается продолжением
«Обучение: сумма» чуть выше (разные поля — то принадлежит КДП, это
любому согласующему, см. README «Отдельный механизм от TrainingAmount»).
Каждую сумму может заполнить ЛЮБОЙ активный согласующий (не только
профильный, в отличие от отметок выше) — но как только сумма указана,
блокируется навсегда для всех, поэтому у незаблокированных
(writeOffEditableKeys.has(cat.key)) есть readOnly={false}, у остальных
— обычное поведение FormMode (просмотр — заблокировано и так). «За что
конкретно» — своего поля здесь нет: заполнил хоть одну сумму —
обязательным становится СТАНДАРТНЫЙ комментарий решения в DecisionPanel
(«Ваше решение»), см. ClearanceView (commentRequired/commentPlaceholder). */}
{writeOffEditableKeys && (
<>
<div className={styles.writeOffLabel}>Суммы к списанию</div>
{WRITE_OFF_CATEGORIES.map((cat) => {
{/* Суммы к списанию — TrainingAmount («Обучение: сумма», правит только
КДП) ПОДВЕДЕНА под тот же заголовок, что и 5 сумм ниже (правит любой
активный согласующий, см. WRITE_OFF_CATEGORIES) — визуально одна
группа «Суммы к списанию», хотя права на них разные. Без заголовка
«Обучение» из WRITE_OFF_CATEGORIES читалось бы дублем «Обучение:
сумма» — их когда-то было два похожих поля, оставили одно (TrainingAmount,
см. README «Отдельный механизм от TrainingAmount»), но заголовок группы
пригодился и без второго «Обучение».
Явный readOnly={false} у TrainingAmount перебивает read-only контекст
просмотра (профильный согласующий правит своё поле); undefined —
обычное поведение из FormMode. У сумм из WRITE_OFF_CATEGORIES —
заполнить может ЛЮБОЙ активный согласующий (не только профильный), но
как только сумма указана, блокируется навсегда для всех, поэтому у
незаблокированных (writeOffEditableKeys.has(cat.key)) readOnly={false},
у остальных — обычное поведение FormMode. «За что конкретно» — своего
поля здесь нет: заполнил хоть одну сумму — обязательным становится
СТАНДАРТНЫЙ комментарий решения в DecisionPanel («Ваше решение»), см.
ClearanceView (commentRequired/commentPlaceholder). */}
{writeOffEditableKeys && <div className={styles.writeOffLabel}>Суммы к списанию</div>}
<FormField label="Обучение: сумма" htmlFor="TrainingAmount">
<MoneyInput
id="TrainingAmount"
value={data.TrainingAmount}
onChange={(v) => set('TrainingAmount', v)}
readOnly={hrRecordsEditable ? false : undefined}
/>
</FormField>
{writeOffEditableKeys &&
WRITE_OFF_CATEGORIES.map((cat) => {
const editable = writeOffEditableKeys.has(cat.key);
return (
<FormField key={cat.key} label={cat.label} htmlFor={cat.amountField}>
@@ -129,8 +131,6 @@ export const RequestSection: React.FC<IRequestSectionProps> = ({
</FormField>
);
})}
</>
)}
{/* Есть только у листов, созданных автоматически по согласованному заявлению
на увольнение (см. forms/Dismissal/createClearance.ts). */}
<LinkField