diff --git a/openspec/changes/corrections-table-ui/design.md b/openspec/changes/corrections-table-ui/design.md index eeba600..0088baf 100644 --- a/openspec/changes/corrections-table-ui/design.md +++ b/openspec/changes/corrections-table-ui/design.md @@ -213,3 +213,4 @@ | 29.10.2026 | R-32: меню строки в раскрытии агрегата («Перенести в правило…», «Убрать из правила», «Вернуть к автоматике») оставлено | п. 4 разрешает убирать строки из агрегата «при корректировках»; меню таблицы делает то же, что «×» в окне, и перенос, о котором Лысенко не писал | если перенос из таблицы не нужен — убрать меню строки, оставить «×» в окне | | 29.10.2026 | R-33: у нераспределённой строки — `line_code` (строка баланса владельца) в контракте и на экране; фильтр «Строка баланса» теперь действует и на нераспределённые по `line_code` (без строки — скрыта), их коды есть в выборе | Лысенко 29.10, п. 11: «можно оставить у нераспределённых эту строку»; раньше фильтр прятал нераспределённые, потому что строки у них не было | при `line_code = null` строка пропадает из фильтра по коду | | 29.10.2026 | R-34: граница 5 % на фронте — как в контракте (≥ 5 % — на проверку: фейк и красная разница в окне); в API 1540 ровно 5 % — в допуске | DOC-272613 «от 5 % включительно»; Лысенко на это не отвечал, вопрос не задан | при ровно 5,00 % окно покажет красным, а сервер — в допуске; таблица берёт `exceeds_threshold` из ответа и расходиться не будет | +| 02.11.2026 | R-35 (Task 8): граница 5 % в живом контроле окна (`editorModel.diffOf`) и подпись фильтра «Отклонение, %» приведены к фактическому поведению API 1540 (`domain/corrections.py`, `exceeds = percent > 5`, строго больше) — `>`, не `≥`; R-34 снимается как источник расхождения | API 1540 уже в main, фронт без Task 8 не существовал в проде — совпадение с реальным сервером важнее совпадения с неоднозначным текстом контракта («от 5 % включительно», на который Лысенко не ответил); сама таблица и так брала `exceeds_threshold` из ответа и не расходилась | ровно 5,00 % теперь не красное и в окне, и в фильтре, как у сервера; если Лысенко подтвердит «включительно» — одна правка оператора в `editorModel.ts`/`CorrectionTable.tsx`, вопрос не снят, просто фронт временно синхронен с текущим сервером | diff --git a/web/src/widgets/CorrectionTable/CorrectionTable.tsx b/web/src/widgets/CorrectionTable/CorrectionTable.tsx index 485bbb6..d9eb9c9 100644 --- a/web/src/widgets/CorrectionTable/CorrectionTable.tsx +++ b/web/src/widgets/CorrectionTable/CorrectionTable.tsx @@ -45,8 +45,8 @@ type Props = { const DEVIATION_OPTIONS: { value: DeviationFilter; label: string }[] = [ { value: 'all', label: 'Все' }, - { value: 'over', label: '≥ 5 %' }, - { value: 'under', label: '< 5 %' }, + { value: 'over', label: '> 5 %' }, + { value: 'under', label: '≤ 5 %' }, ]; const COLOR_OVER = '#d92d20'; diff --git a/web/src/widgets/CorrectionTable/editorModel.test.ts b/web/src/widgets/CorrectionTable/editorModel.test.ts index 54d830f..5168280 100644 --- a/web/src/widgets/CorrectionTable/editorModel.test.ts +++ b/web/src/widgets/CorrectionTable/editorModel.test.ts @@ -127,7 +127,7 @@ describe('liveControl', () => { describe('граница порога и пустые стороны', () => { const base = { debit: [], credit: [], comment: '' }; - it('отклонение ровно 5.00 % — красный', () => { + it('отклонение ровно 5.00 % — не красный (R-35: сервер — строго больше 5 %)', () => { const a = findBy(table(), 'ЭПТ'); // 100.00 к 105.00 — 5.00 % к меньшей const c = liveControl(a, { @@ -136,6 +136,16 @@ describe('граница порога и пустые стороны', () => { credit: [{ line_code: '1520', amount: '105.00' }], }); expect(c.allocationDiff.percent).toBe('5.00'); + expect(c.allocationDiff.red).toBe(false); + }); + it('отклонение 5.01 % — красный', () => { + const a = findBy(table(), 'ЭПТ'); + const c = liveControl(a, { + ...base, + debit: [{ line_code: '1230', amount: '100.00' }], + credit: [{ line_code: '1520', amount: '105.01' }], + }); + expect(c.allocationDiff.percent).toBe('5.01'); expect(c.allocationDiff.red).toBe(true); }); it('отклонение 4.99 % — не красный', () => { diff --git a/web/src/widgets/CorrectionTable/editorModel.ts b/web/src/widgets/CorrectionTable/editorModel.ts index e568053..9e16e0c 100644 --- a/web/src/widgets/CorrectionTable/editorModel.ts +++ b/web/src/widgets/CorrectionTable/editorModel.ts @@ -110,7 +110,8 @@ function sideSum(lines: EditLine[]): string | null { ); } -/** Разница двух сумм и процент к меньшей (для распределения статей); красный — процент ≥ 5 или одна сторона 0 при ненулевой другой. */ +/** Разница двух сумм и процент к меньшей (для распределения статей); красный — процент > 5 (R-35: как считает сервер, + * `domain/corrections.py` строго больше) или одна сторона 0 при ненулевой другой. */ function diffOf(left: string | null, right: string | null): Diff { const l = left ?? '0.00'; const r = right ?? '0.00'; @@ -119,7 +120,7 @@ function diffOf(left: string | null, right: string | null): Diff { const difference = fromCents(lc > rc ? lc - rc : rc - lc); const percent: Percent = percentOfSmaller(l, r); const oneZero = (lc === 0n) !== (rc === 0n); - const red = (percent !== null && toCents(percent) >= THRESHOLD_PERCENT_HUNDREDTHS) || oneZero; + const red = (percent !== null && toCents(percent) > THRESHOLD_PERCENT_HUNDREDTHS) || oneZero; return { left, right, difference, percent, red }; }