feat: feat: брендированная печать, поле «Подразделение» и подача ТМЦ за другого

- Печать доступна только после согласования (Отдел рекрутинга); выбор
  организации и логотип-шапка для форм с несколькими юрлицами
- «СЗ на перемещение ТМЦ»: заявителя можно выбрать (подача за другого),
  маршрут резолвится на выбранного
- «Реферальная рекомендация»: организация вакансии (мультивыбор) и
  подразделение/проект вакансии
- Поле «Подразделение» (справочник) — Vacation, UnpaidLeave, Clearance,
  WorkplaceSetup, RecruitingHire, RecruitingSelection, TmcTransfer
- Поле «Проект» — Vacation, UnpaidLeave, Clearance
This commit is contained in:
Тимур Городецкий
2026-08-26 15:49:25 +05:00
parent f751f03060
commit a4bc54def2
71 changed files with 749 additions and 103 deletions
@@ -11,7 +11,8 @@ import {
useMatrixEditor,
notifyActiveStep,
useRequestTypeId,
APPROVAL_PHASE
APPROVAL_PHASE,
isApprovedStatus
} from '../../shared/approval';
import { navigate } from '../../shared/routing';
import { getAttachments, IAttachmentInfo } from '../../shared/attachments/attachments.service';
@@ -169,7 +170,7 @@ const RecruitingHireView: React.FC<IRecruitingHireViewProps> = ({ context, itemI
<Icon name="copy" size="sm" />
Организация рабочего места на основе этой
</Button>
<PrintButton />
{isApprovedStatus(status) && <PrintButton />}
</div>
<div className="rp-print-root">
@@ -18,7 +18,7 @@ function parseJsonArray<T>(raw: unknown): T[] {
const SCALAR_FIELDS: (keyof IFormData)[] = [
'Phone', 'HireType', 'ReplacedEmployee', 'Project', 'ProjectId', 'ProjectCode',
'CandidateName', 'HireDate', 'Position', 'WorkKind',
'SiteName', 'SiteLocation', 'PpeHeight', 'PpeClothingSize', 'PpeShoeSize', 'ProbationPeriod',
'Department', 'DepartmentId', 'SiteLocation', 'PpeHeight', 'PpeClothingSize', 'PpeShoeSize', 'ProbationPeriod',
'SalaryProbation', 'SalaryAfterProbation', 'WorkSchedule', 'WorkScheduleOther',
'AgencyName', 'AgencyTerms',
'SelectionRequestId', 'SelectionRequestListId', 'SelectionRequestCode'
@@ -34,7 +34,16 @@ export interface IFormData {
HireDate: string;
Position: string;
WorkKind: string;
SiteName: string;
/**
* Подразделение по справочнику (Dictionary/Departments, см.
* shared/dictionary/DepartmentPicker) — как в WorkplaceSetup/RecruitingSelection:
* ручной выбор, чисто информационное, на маршрут согласования НЕ влияет.
* Заменило прежнее свободнотекстовое поле «Отдел / участок» (колонка SiteName
* в SP осталась в схеме нетронутой — просто больше не используется формой).
*/
Department: string;
/** Id отдела из справочника; '' — если введён вручную без выбора из списка. */
DepartmentId: string;
SiteLocation: string;
// СИЗ
PpeHeight: string;
@@ -77,7 +86,8 @@ export const EMPTY_DATA: IFormData = {
HireDate: '',
Position: '',
WorkKind: '',
SiteName: '',
Department: '',
DepartmentId: '',
SiteLocation: '',
PpeHeight: '',
PpeClothingSize: '',
@@ -22,7 +22,9 @@
{ "internalName": "HireDate", "title": "Дата приёма", "type": "DateTime", "dateOnly": true },
{ "internalName": "Position", "title": "Должность", "type": "Text", "required": true },
{ "internalName": "WorkKind", "title": "Вид работ", "type": "Text" },
{ "internalName": "SiteName", "title": "Отдел / участок", "type": "Text" },
{ "internalName": "SiteName", "title": "Отдел / участок (устарело)", "type": "Text" },
{ "internalName": "Department", "title": "Подразделение (справочник)", "type": "Text" },
{ "internalName": "DepartmentId", "title": "Id подразделения (справочник)", "type": "Text" },
{ "internalName": "SiteLocation", "title": "Местоположение", "type": "Text" },
{ "internalName": "PpeHeight", "title": "СИЗ: рост", "type": "Number" },
@@ -1,8 +1,9 @@
import * as React from 'react';
import { CollapseSection, FormField, TextInput } from '../../../shared/ui';
import { DepartmentPicker } from '../../../shared/dictionary';
import { ISectionProps } from '../model';
export const CandidateSection: React.FC<ISectionProps> = ({ data, set }) => (
export const CandidateSection: React.FC<ISectionProps> = ({ data, set, context }) => (
<CollapseSection title="Кандидат" icon="people">
<FormField label="Ф.И.О. кандидата" htmlFor="CandidateName" required full>
<TextInput id="CandidateName" value={data.CandidateName} onChange={(v) => set('CandidateName', v)} />
@@ -16,8 +17,16 @@ export const CandidateSection: React.FC<ISectionProps> = ({ data, set }) => (
<FormField label="Вид работ" htmlFor="WorkKind">
<TextInput id="WorkKind" value={data.WorkKind} onChange={(v) => set('WorkKind', v)} />
</FormField>
<FormField label="Отдел / участок" htmlFor="SiteName">
<TextInput id="SiteName" value={data.SiteName} onChange={(v) => set('SiteName', v)} />
<FormField label="Подразделение" htmlFor="Department">
<DepartmentPicker
id="Department"
context={context}
value={data.Department}
onChange={(name, id) => {
set('Department', name);
set('DepartmentId', id);
}}
/>
</FormField>
<FormField label="Местоположение" htmlFor="SiteLocation">
<TextInput id="SiteLocation" value={data.SiteLocation} onChange={(v) => set('SiteLocation', v)} />