refactor: причины открытия вакансии перенесены под количество вакансий (п. 2.3)
Tests / frontend-test (push) Successful in 1m16s
Tests / frontend-test (push) Successful in 1m16s
This commit is contained in:
@@ -121,7 +121,7 @@ const RecruitingSelectionForm: React.FC<IRequestFormProps> = ({
|
|||||||
}, [editId, editListId, notifyCode, setSubmitError]);
|
}, [editId, editListId, notifyCode, setSubmitError]);
|
||||||
|
|
||||||
// Компании ответственного (Employee/ByEmail.company/companyId) → предзаполнение
|
// Компании ответственного (Employee/ByEmail.company/companyId) → предзаполнение
|
||||||
// «1.6 Организация» (Companies/CompanyPickerMulti). companyId из Employee/ByEmail
|
// «1.5 Организация» (Companies/CompanyPickerMulti). companyId из Employee/ByEmail
|
||||||
// совпадает с Id из Dictionary/Companies (тот же источник) — доп. запрос не нужен.
|
// совпадает с Id из Dictionary/Companies (тот же источник) — доп. запрос не нужен.
|
||||||
// Поле остаётся редактируемым: значения только ПРЕДЛАГАЮТСЯ, как и DepartmentName.
|
// Поле остаётся редактируемым: значения только ПРЕДЛАГАЮТСЯ, как и DepartmentName.
|
||||||
const toCompanies = (records: IEmployeeOrganization[]): ICompany[] =>
|
const toCompanies = (records: IEmployeeOrganization[]): ICompany[] =>
|
||||||
@@ -450,7 +450,7 @@ const RecruitingSelectionForm: React.FC<IRequestFormProps> = ({
|
|||||||
editor={matrix}
|
editor={matrix}
|
||||||
search={(q) => approval.searchUsers(q)}
|
search={(q) => approval.searchUsers(q)}
|
||||||
waiting={!matrixReady}
|
waiting={!matrixReady}
|
||||||
waitingText="Выберите «Объект/Проект» (п. 1.7), чтобы построить маршрут согласования."
|
waitingText="Выберите «Объект/Проект» (п. 1.6), чтобы построить маршрут согласования."
|
||||||
canRemoveRow={canRemoveApprover ? () => true : undefined}
|
canRemoveRow={canRemoveApprover ? () => true : undefined}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export interface IFormData {
|
|||||||
SubmitDate: string;
|
SubmitDate: string;
|
||||||
ClosingDeadline: string;
|
ClosingDeadline: string;
|
||||||
/**
|
/**
|
||||||
* 1.5 Причины открытия вакансии. Одна причина — при одной вакансии; при 2.2 > 1
|
* 2.3 Причины открытия вакансии. Одна причина — при одной вакансии; при 2.2 > 1
|
||||||
* можно несколько, и у причин с ФИО — несколько сотрудников. Хранится JSON в
|
* можно несколько, и у причин с ФИО — несколько сотрудников. Хранится JSON в
|
||||||
* колонке VacancyReasonsJson; старые колонки VacancyOpenReason (первая
|
* колонке VacancyReasonsJson; старые колонки VacancyOpenReason (первая
|
||||||
* причина) и VacancyOpenReasonDetails (сводка текстом) заполняются для
|
* причина) и VacancyOpenReasonDetails (сводка текстом) заполняются для
|
||||||
@@ -83,7 +83,7 @@ export interface IFormData {
|
|||||||
HiringDecisionMaker: string[];
|
HiringDecisionMaker: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Одна причина открытия вакансии (п. 1.5). */
|
/** Одна причина открытия вакансии (п. 2.3). */
|
||||||
export interface IVacancyReason {
|
export interface IVacancyReason {
|
||||||
/** Значение из OPEN_REASON_OPTIONS. */
|
/** Значение из OPEN_REASON_OPTIONS. */
|
||||||
reason: string;
|
reason: string;
|
||||||
|
|||||||
+2
-18
@@ -2,12 +2,8 @@ import * as React from 'react';
|
|||||||
import { CollapseSection, FormField, TextInput, PeopleField } from '../../../shared/ui';
|
import { CollapseSection, FormField, TextInput, PeopleField } from '../../../shared/ui';
|
||||||
import { CompanyPickerMulti, ProjectPicker } from '../../../shared/dictionary';
|
import { CompanyPickerMulti, ProjectPicker } from '../../../shared/dictionary';
|
||||||
import { ISectionProps, PERSON_PLACEHOLDER } from '../model';
|
import { ISectionProps, PERSON_PLACEHOLDER } from '../model';
|
||||||
import { parseVacanciesCount } from '../vacancyReasons';
|
|
||||||
import { VacancyReasonsField } from './VacancyReasonsField';
|
|
||||||
|
|
||||||
export const ApplicationSection: React.FC<ISectionProps> = ({ data, set, context, onResponsibleChange }) => {
|
export const ApplicationSection: React.FC<ISectionProps> = ({ data, set, context, onResponsibleChange }) => {
|
||||||
const vacanciesCount = parseVacanciesCount(data.OpenVacanciesCount);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CollapseSection title="1. Заявка" icon="clipboard">
|
<CollapseSection title="1. Заявка" icon="clipboard">
|
||||||
<FormField label="1.1 Ответственный за подачу заявки" fieldKey="Responsible" required full>
|
<FormField label="1.1 Ответственный за подачу заявки" fieldKey="Responsible" required full>
|
||||||
@@ -38,19 +34,7 @@ export const ApplicationSection: React.FC<ISectionProps> = ({ data, set, context
|
|||||||
min={data.SubmitDate || undefined}
|
min={data.SubmitDate || undefined}
|
||||||
/>
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
<FormField
|
<FormField label="1.5 Организация" htmlFor="Companies" required full>
|
||||||
label={vacanciesCount > 1 ? '1.5 Причины открытия вакансий' : '1.5 Причина открытия вакансии'}
|
|
||||||
fieldKey="VacancyReasons"
|
|
||||||
required
|
|
||||||
full
|
|
||||||
>
|
|
||||||
<VacancyReasonsField
|
|
||||||
value={data.VacancyReasons}
|
|
||||||
onChange={(v) => set('VacancyReasons', v)}
|
|
||||||
vacanciesCount={vacanciesCount}
|
|
||||||
/>
|
|
||||||
</FormField>
|
|
||||||
<FormField label="1.6 Организация" htmlFor="Companies" required full>
|
|
||||||
<CompanyPickerMulti
|
<CompanyPickerMulti
|
||||||
context={context}
|
context={context}
|
||||||
id="Companies"
|
id="Companies"
|
||||||
@@ -59,7 +43,7 @@ export const ApplicationSection: React.FC<ISectionProps> = ({ data, set, context
|
|||||||
placeholder="Начните вводить название организации…"
|
placeholder="Начните вводить название организации…"
|
||||||
/>
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
<FormField label="1.7 Объект/Проект" htmlFor="ObjectProject" required full>
|
<FormField label="1.6 Объект/Проект" htmlFor="ObjectProject" required full>
|
||||||
<ProjectPicker
|
<ProjectPicker
|
||||||
context={context}
|
context={context}
|
||||||
id="ObjectProject"
|
id="ObjectProject"
|
||||||
|
|||||||
+20
-1
@@ -2,8 +2,13 @@ import * as React from 'react';
|
|||||||
import { CollapseSection, FormField, TextInput } from '../../../shared/ui';
|
import { CollapseSection, FormField, TextInput } from '../../../shared/ui';
|
||||||
import { DepartmentPicker } from '../../../shared/dictionary';
|
import { DepartmentPicker } from '../../../shared/dictionary';
|
||||||
import { ISectionProps } from '../model';
|
import { ISectionProps } from '../model';
|
||||||
|
import { parseVacanciesCount } from '../vacancyReasons';
|
||||||
|
import { VacancyReasonsField } from './VacancyReasonsField';
|
||||||
|
|
||||||
export const DepartmentSection: React.FC<ISectionProps> = ({ data, set, context }) => (
|
export const DepartmentSection: React.FC<ISectionProps> = ({ data, set, context }) => {
|
||||||
|
const vacanciesCount = parseVacanciesCount(data.OpenVacanciesCount);
|
||||||
|
|
||||||
|
return (
|
||||||
<CollapseSection title="2. Отдел / Подразделение" icon="building">
|
<CollapseSection title="2. Отдел / Подразделение" icon="building">
|
||||||
<FormField label="2.1 Подразделение" htmlFor="Department" required full>
|
<FormField label="2.1 Подразделение" htmlFor="Department" required full>
|
||||||
<DepartmentPicker
|
<DepartmentPicker
|
||||||
@@ -24,5 +29,19 @@ export const DepartmentSection: React.FC<ISectionProps> = ({ data, set, context
|
|||||||
onChange={(v) => set('OpenVacanciesCount', v !== '' && Number(v) < 0 ? '0' : v)}
|
onChange={(v) => set('OpenVacanciesCount', v !== '' && Number(v) < 0 ? '0' : v)}
|
||||||
/>
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
{/* Сразу под количеством: от него зависит, одна причина или несколько. */}
|
||||||
|
<FormField
|
||||||
|
label={vacanciesCount > 1 ? '2.3 Причины открытия вакансий' : '2.3 Причина открытия вакансии'}
|
||||||
|
fieldKey="VacancyReasons"
|
||||||
|
required
|
||||||
|
full
|
||||||
|
>
|
||||||
|
<VacancyReasonsField
|
||||||
|
value={data.VacancyReasons}
|
||||||
|
onChange={(v) => set('VacancyReasons', v)}
|
||||||
|
vacanciesCount={vacanciesCount}
|
||||||
|
/>
|
||||||
|
</FormField>
|
||||||
</CollapseSection>
|
</CollapseSection>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ interface IVacancyReasonsFieldProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 1.5 Причины открытия вакансии.
|
* 2.3 Причины открытия вакансии.
|
||||||
*
|
*
|
||||||
* Одна вакансия — выпадающий список, одна причина, один сотрудник. Больше одной
|
* Одна вакансия — выпадающий список, одна причина, один сотрудник. Больше одной
|
||||||
* — флажки: несколько причин, у причин с ФИО — несколько сотрудников. Если
|
* — флажки: несколько причин, у причин с ФИО — несколько сотрудников. Если
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
} from './model';
|
} from './model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Причины открытия вакансии (п. 1.5): несколько причин при 2.2 > 1 и несколько
|
* Причины открытия вакансии (п. 2.3): несколько причин при 2.2 > 1 и несколько
|
||||||
* сотрудников на причину. Логика без UI — разбор/сводка/проверки.
|
* сотрудников на причину. Логика без UI — разбор/сводка/проверки.
|
||||||
*
|
*
|
||||||
* Хранение: полная структура — JSON в VacancyReasonsJson (из неё читает
|
* Хранение: полная структура — JSON в VacancyReasonsJson (из неё читает
|
||||||
@@ -113,7 +113,7 @@ export function allowsMultipleReasons(vacanciesCount: number): boolean {
|
|||||||
/** Блокирующая проблема для отправки: несколько причин при одной вакансии. */
|
/** Блокирующая проблема для отправки: несколько причин при одной вакансии. */
|
||||||
export function vacancyReasonsError(reasons: IVacancyReason[], vacanciesCount: number): string | undefined {
|
export function vacancyReasonsError(reasons: IVacancyReason[], vacanciesCount: number): string | undefined {
|
||||||
if (!allowsMultipleReasons(vacanciesCount) && reasons.length > 1) {
|
if (!allowsMultipleReasons(vacanciesCount) && reasons.length > 1) {
|
||||||
return 'При одной вакансии оставьте одну причину открытия (п. 1.5) или увеличьте количество вакансий (п. 2.2).';
|
return 'При одной вакансии оставьте одну причину открытия (п. 2.3) или увеличьте количество вакансий (п. 2.2).';
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@@ -122,7 +122,7 @@ export function vacancyReasonsError(reasons: IVacancyReason[], vacanciesCount: n
|
|||||||
export function vacancyReasonsWarning(reasons: IVacancyReason[], vacanciesCount: number): string | undefined {
|
export function vacancyReasonsWarning(reasons: IVacancyReason[], vacanciesCount: number): string | undefined {
|
||||||
const employees = cleanVacancyReasons(reasons).reduce((sum, r) => sum + r.employees.length, 0);
|
const employees = cleanVacancyReasons(reasons).reduce((sum, r) => sum + r.employees.length, 0);
|
||||||
if (vacanciesCount > 0 && employees > vacanciesCount) {
|
if (vacanciesCount > 0 && employees > vacanciesCount) {
|
||||||
return `Указано сотрудников: ${employees}, а вакансий: ${vacanciesCount}. Проверьте п. 1.5 и 2.2.`;
|
return `Указано сотрудников: ${employees}, а вакансий: ${vacanciesCount}. Проверьте п. 2.2 и 2.3.`;
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ import { parseVacanciesCount, vacancyReasonsError } from './vacancyReasons';
|
|||||||
const REQUIRED_FIELDS: ReadonlyArray<{ label: string; ok: (d: IFormData) => boolean }> = [
|
const REQUIRED_FIELDS: ReadonlyArray<{ label: string; ok: (d: IFormData) => boolean }> = [
|
||||||
{ label: '1.3 дата подачи заявки', ok: (d) => !!d.SubmitDate },
|
{ label: '1.3 дата подачи заявки', ok: (d) => !!d.SubmitDate },
|
||||||
{ label: '1.4 крайний срок закрытия', ok: (d) => !!d.ClosingDeadline },
|
{ label: '1.4 крайний срок закрытия', ok: (d) => !!d.ClosingDeadline },
|
||||||
{ label: '1.5 причина открытия вакансии', ok: (d) => d.VacancyReasons.length > 0 },
|
{ label: '1.5 организация', ok: (d) => d.Companies.length > 0 },
|
||||||
{ label: '1.6 организация', ok: (d) => d.Companies.length > 0 },
|
|
||||||
{ label: '2.1 подразделение', ok: (d) => !!d.Department.trim() },
|
{ label: '2.1 подразделение', ok: (d) => !!d.Department.trim() },
|
||||||
{ label: '2.2 количество открытых вакансий', ok: (d) => !!d.OpenVacanciesCount.trim() },
|
{ label: '2.2 количество открытых вакансий', ok: (d) => !!d.OpenVacanciesCount.trim() },
|
||||||
|
{ label: '2.3 причина открытия вакансии', ok: (d) => d.VacancyReasons.length > 0 },
|
||||||
{ label: '3.2 характер занятости', ok: (d) => !!d.EmploymentType },
|
{ label: '3.2 характер занятости', ok: (d) => !!d.EmploymentType },
|
||||||
{ label: '3.3 функционал', ok: (d) => !!d.JobFunction.trim() },
|
{ label: '3.3 функционал', ok: (d) => !!d.JobFunction.trim() },
|
||||||
{ label: '3.4 компетенции', ok: (d) => !!d.Competencies.trim() },
|
{ label: '3.4 компетенции', ok: (d) => !!d.Competencies.trim() },
|
||||||
|
|||||||
Reference in New Issue
Block a user