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) <noreply@anthropic.com>
This commit is contained in:
Тимур Городецкий
2026-10-19 10:07:07 +05:00
parent 3128190b5c
commit 7ca71c6b6c
3 changed files with 19 additions and 1 deletions
@@ -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() : '';
@@ -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);
@@ -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() !== '';
}