diff --git a/src/webparts/requestPortal/forms/Clearance/README.md b/src/webparts/requestPortal/forms/Clearance/README.md index 048fa68..646084b 100644 --- a/src/webparts/requestPortal/forms/Clearance/README.md +++ b/src/webparts/requestPortal/forms/Clearance/README.md @@ -36,7 +36,7 @@ RequestTypeId» в `docs/forms.md`). Тип уже зарегистрирова - **Сумма обучения** — `MoneyInput` (разделитель тысяч в UI, в списке — «сырое» число), колонка `TrainingAmount` (Number, 2 знака), поле необязательное. - **Дата расторжения договора** — обычный `input type=date`, без вычислений - (в отличие от `EndDate` в «Заявке на отпуск», которая считается). + (в отличие от даты окончания отпуска, которой нет совсем). - **Заголовок элемента** (`Title`): `Обходной лист — {ФИО} — дд.мм.гггг`. ## Связь с заявлением на увольнение diff --git a/src/webparts/requestPortal/forms/UnpaidLeave/README.md b/src/webparts/requestPortal/forms/UnpaidLeave/README.md index 277c2cb..f3ad67f 100644 --- a/src/webparts/requestPortal/forms/UnpaidLeave/README.md +++ b/src/webparts/requestPortal/forms/UnpaidLeave/README.md @@ -25,11 +25,11 @@ - **Заголовок элемента** (`Title`): `Отпуск без содержания — {ФИО} — дд.мм.гггг`. ## Отличия от «Заявка на отпуск» (hr-vacation) -- Даты с/по вместо «дата начала + количество дней». +- Те же «дата начала + количество дней»: даты окончания нет, праздники и выходные не считаются. - Добавлены поля «В связи с» (`Reason`) и «Лицо замещающее» (`Substitute`). ## Секции формы -RequestSection (сотрудник · должность · дата начала · дата окончания · основание · замещающий) +RequestSection (сотрудник · должность · дата начала · количество дней · основание · замещающий) ## Точки входа - rptype: `hr-unpaid-leave` diff --git a/src/webparts/requestPortal/forms/UnpaidLeave/UnpaidLeaveForm.tsx b/src/webparts/requestPortal/forms/UnpaidLeave/UnpaidLeaveForm.tsx index c737fab..ca38166 100644 --- a/src/webparts/requestPortal/forms/UnpaidLeave/UnpaidLeaveForm.tsx +++ b/src/webparts/requestPortal/forms/UnpaidLeave/UnpaidLeaveForm.tsx @@ -183,8 +183,9 @@ const UnpaidLeaveForm: React.FC = ({ editId }); - // Даты корректны, если конец не раньше начала (обе обязательны). - const datesValid = !!(data.StartDate && data.EndDate && data.EndDate >= data.StartDate); + // Продолжительность: целое положительное число календарных дней. + const daysNum = Number(data.DaysCount); + const daysValid = Number.isFinite(daysNum) && daysNum > 0; // Заявку нужно подавать не позднее чем за MIN_NOTICE_DAYS дней до даты начала // отпуска — календарь (min у input type=date, см. RequestSection) не даёт // выбрать более раннюю дату, но проверяем и здесь на случай обхода UI. @@ -193,7 +194,8 @@ const UnpaidLeaveForm: React.FC = ({ const isValid = !!( data.Employee && data.Position.trim() && - datesValid && + data.StartDate && + daysValid && isStartDateValid && data.Reason.trim() ); @@ -201,10 +203,10 @@ const UnpaidLeaveForm: React.FC = ({ if (data.StartDate && !isStartDateValid) { return `Заявку на отпуск нужно подать не позднее чем за ${MIN_NOTICE_DAYS} дней до даты начала — минимально доступная дата: ${formatIsoDate(minStartDate)}.`; } - if (!data.Employee || !data.Position.trim() || !data.StartDate || !data.EndDate || !data.Reason.trim()) { - return 'Заполните обязательные поля: сотрудник, должность, дата начала, дата окончания, основание.'; + if (!data.Employee || !data.Position.trim() || !data.StartDate || !data.Reason.trim()) { + return 'Заполните обязательные поля: сотрудник, должность, дата начала, основание.'; } - if (!datesValid) return 'Дата окончания не может быть раньше даты начала.'; + if (!daysValid) return 'Количество дней должно быть больше нуля.'; if (requestTypeIdState.error) return `Не удалось определить тип заявки: ${requestTypeIdState.error}`; if (!requestTypeId) return 'Тип заявки ещё определяется — подождите немного и повторите.'; return undefined; diff --git a/src/webparts/requestPortal/forms/UnpaidLeave/load.ts b/src/webparts/requestPortal/forms/UnpaidLeave/load.ts index 25ace41..22f33dc 100644 --- a/src/webparts/requestPortal/forms/UnpaidLeave/load.ts +++ b/src/webparts/requestPortal/forms/UnpaidLeave/load.ts @@ -27,7 +27,7 @@ export async function loadUnpaidLeaveRequest(itemId: number, listId?: string): P 'Id', 'Position', 'StartDate', - 'EndDate', + 'DaysCount', 'Reason', 'Organization', 'Department', @@ -45,14 +45,14 @@ export async function loadUnpaidLeaveRequest(itemId: number, listId?: string): P const employee = item.Employee as { Title?: string; EMail?: string } | undefined; const substitute = item.Substitute as { EMail?: string } | undefined; const start = (item.StartDate as string) || ''; - const end = (item.EndDate as string) || ''; + const days = item.DaysCount; const data: IFormData = { ...EMPTY_DATA, Employee: employee?.EMail || '', Position: (item.Position as string) || '', StartDate: start.slice(0, 10), // ISO → YYYY-MM-DD для input type=date - EndDate: end.slice(0, 10), + DaysCount: days === null || days === undefined ? '' : String(days), Reason: (item.Reason as string) || '', Substitute: substitute?.EMail || '', Organization: (item.Organization as string) || '', diff --git a/src/webparts/requestPortal/forms/UnpaidLeave/model.ts b/src/webparts/requestPortal/forms/UnpaidLeave/model.ts index 4259f10..b70bd49 100644 --- a/src/webparts/requestPortal/forms/UnpaidLeave/model.ts +++ b/src/webparts/requestPortal/forms/UnpaidLeave/model.ts @@ -12,8 +12,8 @@ export const FORM_ID: RequestTypeId = 'hr-unpaid-leave'; * по возможности = internalName колонок списка данных (см. shared/listTitles.ts). * Employee/Substitute хранят e-mail выбранного сотрудника (то, что отдаёт * PeopleField); по Employee резолвится маршрут согласования, поэтому заявку можно - * подать и за другого сотрудника. В отличие от «Заявки на отпуск» здесь обе даты - * (с/по) вводятся явно, а DaysCount считается при сохранении. + * подать и за другого сотрудника. Как и в «Заявке на отпуск», даты окончания нет: + * отпуск задаётся началом и количеством дней, чтобы не считать праздники и выходные. */ export interface IFormData { /** E-mail сотрудника, за которого заявка (People). Пусто = не выбран. */ @@ -21,8 +21,8 @@ export interface IFormData { Position: string; /** ISO YYYY-MM-DD (input type=date). */ StartDate: string; - /** ISO YYYY-MM-DD (input type=date). */ - EndDate: string; + /** Количество календарных дней (строка из input type=number). */ + DaysCount: string; /** Основание «В связи с …». */ Reason: string; /** E-mail замещающего на время отсутствия (People). Пусто = не выбран. */ @@ -68,7 +68,7 @@ export const EMPTY_DATA: IFormData = { Employee: '', Position: '', StartDate: '', - EndDate: '', + DaysCount: '', Reason: '', Substitute: '', Organization: '', diff --git a/src/webparts/requestPortal/forms/UnpaidLeave/provisioning.json b/src/webparts/requestPortal/forms/UnpaidLeave/provisioning.json index 8c994ba..c53f544 100644 --- a/src/webparts/requestPortal/forms/UnpaidLeave/provisioning.json +++ b/src/webparts/requestPortal/forms/UnpaidLeave/provisioning.json @@ -7,7 +7,6 @@ { "internalName": "Employee", "title": "Сотрудник", "type": "User", "userSelectionMode": "PeopleOnly", "required": true }, { "internalName": "Position", "title": "Должность", "type": "Text" }, { "internalName": "StartDate", "title": "Дата начала", "type": "DateTime", "dateOnly": true }, - { "internalName": "EndDate", "title": "Дата окончания", "type": "DateTime", "dateOnly": true }, { "internalName": "DaysCount", "title": "Количество дней", "type": "Number" }, { "internalName": "Reason", "title": "Основание (в связи с)", "type": "Note" }, { "internalName": "Substitute", "title": "Лицо, замещающее на время отсутствия", "type": "User", "userSelectionMode": "PeopleOnly" }, diff --git a/src/webparts/requestPortal/forms/UnpaidLeave/sections/RequestSection.tsx b/src/webparts/requestPortal/forms/UnpaidLeave/sections/RequestSection.tsx index bf35601..ece13c1 100644 --- a/src/webparts/requestPortal/forms/UnpaidLeave/sections/RequestSection.tsx +++ b/src/webparts/requestPortal/forms/UnpaidLeave/sections/RequestSection.tsx @@ -51,8 +51,8 @@ export const RequestSection: React.FC = ({ data, set, context, on min={isoDatePlusDays(MIN_NOTICE_DAYS)} /> - - set('EndDate', v)} /> + + set('DaysCount', v)} />