From 7ca71c6b6cf2996658bcedb36f30952464e9313b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A2=D0=B8=D0=BC=D1=83=D1=80=20=D0=93=D0=BE=D1=80=D0=BE?= =?UTF-8?q?=D0=B4=D0=B5=D1=86=D0=BA=D0=B8=D0=B9?= Date: Mon, 19 Oct 2026 10:07:07 +0500 Subject: [PATCH] fix: reject work finish date earlier than start date The legacy works form saved any dates. The finish date picker now has the start date as minimum and saving shows an error. Found in T-WRK. Co-Authored-By: Claude Opus 5.5 (1M context) --- src/webparts/stroyBot/pages/works/useWorkEditor.ts | 7 ++++++- src/webparts/stroyBot/pages/works/worksRules.test.ts | 8 ++++++++ src/webparts/stroyBot/pages/works/worksRules.ts | 5 +++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/webparts/stroyBot/pages/works/useWorkEditor.ts b/src/webparts/stroyBot/pages/works/useWorkEditor.ts index 86abfcc..73b7f3c 100644 --- a/src/webparts/stroyBot/pages/works/useWorkEditor.ts +++ b/src/webparts/stroyBot/pages/works/useWorkEditor.ts @@ -1,6 +1,6 @@ import * as React from 'react'; import { buildWorkBody, IWorksRepository } from './worksRepository'; -import { isTitleValid, needsClearParent, resetFormKeepParent, workToForm } from './worksRules'; +import { isDateRangeValid, isTitleValid, needsClearParent, resetFormKeepParent, workToForm } from './worksRules'; import { EMPTY_WORK_FORM, IWork, IWorkForm, WorkModalMode } from './worksTypes'; import { WORKS_TEXTS } from './texts'; @@ -63,6 +63,11 @@ export function useWorkEditor({ repository, objectId, reloadWorks }: IEditorDeps titleInputRef.current?.focus(); return; } + // В старом stroy-bot-works проверки не было — исправлено при ручной проверке (T-WRK). + if (!isDateRangeValid(form)) { + setState((prev) => ({ ...prev, isTitleInvalid: false, saveError: WORKS_TEXTS.modal.dateRangeError })); + return; + } setState((prev) => ({ ...prev, isTitleInvalid: false, isSaving: true, saveError: undefined })); try { const parentNavProperty = form.parentId.trim() ? await repository.getParentNavProperty() : ''; diff --git a/src/webparts/stroyBot/pages/works/worksRules.test.ts b/src/webparts/stroyBot/pages/works/worksRules.test.ts index 2c04c98..e5df3b4 100644 --- a/src/webparts/stroyBot/pages/works/worksRules.test.ts +++ b/src/webparts/stroyBot/pages/works/worksRules.test.ts @@ -2,6 +2,7 @@ import { buildWorkTree, formatDateRange, formatVolume, + isDateRangeValid, isTitleValid, needsClearParent, parentOptions, @@ -80,6 +81,13 @@ describe('форма', () => { }); }); + it('окончание не раньше начала; пустые даты не проверяются (баг старого кода исправлен)', () => { + expect(isDateRangeValid({ ...EMPTY_WORK_FORM, start: '2026-10-19', finish: '2026-10-16' })).toBe(false); + expect(isDateRangeValid({ ...EMPTY_WORK_FORM, start: '2026-10-19', finish: '2026-10-19' })).toBe(true); + expect(isDateRangeValid({ ...EMPTY_WORK_FORM, start: '2026-10-19', finish: '' })).toBe(true); + expect(isDateRangeValid({ ...EMPTY_WORK_FORM, start: '', finish: '2026-10-16' })).toBe(true); + }); + it('наименование обязательно (пробелы не считаются)', () => { expect(isTitleValid({ ...EMPTY_WORK_FORM, title: ' ' })).toBe(false); expect(isTitleValid({ ...EMPTY_WORK_FORM, title: 'Бетон' })).toBe(true); diff --git a/src/webparts/stroyBot/pages/works/worksRules.ts b/src/webparts/stroyBot/pages/works/worksRules.ts index 1ec03a5..52dc0df 100644 --- a/src/webparts/stroyBot/pages/works/worksRules.ts +++ b/src/webparts/stroyBot/pages/works/worksRules.ts @@ -84,6 +84,11 @@ export function resetFormKeepParent(form: IWorkForm): IWorkForm { return { title: '', unit: '', volume: '', parentId: form.parentId, start: '', finish: '' }; } +/** Окончание не раньше начала (даты YYYY-MM-DD сравниваются строками). Пустые даты не проверяются. */ +export function isDateRangeValid(form: IWorkForm): boolean { + return !form.start || !form.finish || form.start <= form.finish; +} + export function isTitleValid(form: IWorkForm): boolean { return form.title.trim() !== ''; }