fix(web): окно корректировки — база черновика, подпись выбора (#206)
T6.11: при пересборке окна из нового агрегата (правок не было) база черновика обновляется до текущей редакции корректировки, иначе при следующем открытии показывалась ложная плашка об изменении. T6.12: подпись кнопки «Выбрать» называет контрагента; ошибки полей статьи объявляются role=alert. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
c1d402f0e3
commit
84c4f25a9b
@ -1,7 +1,7 @@
|
|||||||
// Выбор нераспределённой строки для «Добавить строку ОСВ»: клик по строке отправляет ASSIGN (в окне, через onPick).
|
// Выбор нераспределённой строки для «Добавить строку ОСВ»: клик по строке отправляет ASSIGN (в окне, через onPick).
|
||||||
import { Button, Modal, Table } from 'antd';
|
import { Button, Modal, Table } from 'antd';
|
||||||
import type { UnallocatedEntryOut } from '../../types/corrections';
|
import type { UnallocatedEntryOut } from '../../types/corrections';
|
||||||
import { formatRub } from './editorView';
|
import { formatRub, pickLabel } from './editorView';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@ -48,7 +48,7 @@ export function AllocationPicker({ open, sideLabel, article, candidates, busy, o
|
|||||||
<Button
|
<Button
|
||||||
size='small'
|
size='small'
|
||||||
disabled={busy}
|
disabled={busy}
|
||||||
aria-label={`Выбрать: ${u.account_code}, ${formatRub(u.amount)}`}
|
aria-label={pickLabel(u.counterparty.name, u.account_code, u.amount)}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onPick(u);
|
onPick(u);
|
||||||
|
|||||||
@ -96,7 +96,11 @@ export function CorrectionEditorModal({ versionId, table, aggregateKey, editable
|
|||||||
if (prevInitial.current === initial) return;
|
if (prevInitial.current === initial) return;
|
||||||
const next = rebaseState(prevInitial.current, initial, plain(stateRef.current));
|
const next = rebaseState(prevInitial.current, initial, plain(stateRef.current));
|
||||||
prevInitial.current = initial;
|
prevInitial.current = initial;
|
||||||
if (next) setState(withIds(next));
|
if (next) {
|
||||||
|
setState(withIds(next));
|
||||||
|
// правок не было — окно целиком на новой редакции, база черновика тоже; иначе при следующем открытии плашка «изменили после ваших правок» ложная
|
||||||
|
setBase(aggregate?.correction?.version_no ?? null);
|
||||||
|
}
|
||||||
}, [initial]);
|
}, [initial]);
|
||||||
|
|
||||||
// без агрегата окно только на просмотр: правок и «несохранённого» нет
|
// без агрегата окно только на просмотр: правок и «несохранённого» нет
|
||||||
|
|||||||
@ -153,7 +153,7 @@ function LineRow({ line, index, sideName, err, articleCodes, editable, onRemoveL
|
|||||||
<Input maxLength={4} status={err.line_code ? 'error' : undefined} aria-label={`Строка баланса, ${where}`} aria-describedby={err.line_code ? codeErrId : undefined} />
|
<Input maxLength={4} status={err.line_code ? 'error' : undefined} aria-label={`Строка баланса, ${where}`} aria-describedby={err.line_code ? codeErrId : undefined} />
|
||||||
</AutoComplete>
|
</AutoComplete>
|
||||||
{err.line_code && (
|
{err.line_code && (
|
||||||
<div id={codeErrId} style={{ color: '#d92d20', fontSize: 12 }}>
|
<div id={codeErrId} role='alert' style={{ color: '#d92d20', fontSize: 12 }}>
|
||||||
{err.line_code}
|
{err.line_code}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -170,7 +170,7 @@ function LineRow({ line, index, sideName, err, articleCodes, editable, onRemoveL
|
|||||||
onChange={(e) => onChangeLine(line.id, { amount: e.target.value })}
|
onChange={(e) => onChangeLine(line.id, { amount: e.target.value })}
|
||||||
/>
|
/>
|
||||||
{err.amount && (
|
{err.amount && (
|
||||||
<div id={amountErrId} style={{ color: '#d92d20', fontSize: 12 }}>
|
<div id={amountErrId} role='alert' style={{ color: '#d92d20', fontSize: 12 }}>
|
||||||
{err.amount}
|
{err.amount}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
import { ApiError } from '../../api/client';
|
import { ApiError } from '../../api/client';
|
||||||
import type { CorrectionAggregateOut } from '../../types/corrections';
|
import type { CorrectionAggregateOut } from '../../types/corrections';
|
||||||
import { CONFLICT_MESSAGE, controlText, draftNotice, formatRub, saveErrorOutcome, timeHHMM } from './editorView';
|
import { CONFLICT_MESSAGE, controlText, draftNotice, formatRub, pickLabel, saveErrorOutcome, timeHHMM } from './editorView';
|
||||||
|
|
||||||
const err = (status: number, code: string, detail: Record<string, unknown> = {}) =>
|
const err = (status: number, code: string, detail: Record<string, unknown> = {}) =>
|
||||||
new ApiError(status, code, `msg ${code}`, { detail: { code, message: `msg ${code}`, ...detail } });
|
new ApiError(status, code, `msg ${code}`, { detail: { code, message: `msg ${code}`, ...detail } });
|
||||||
@ -69,3 +69,9 @@ describe('formatRub', () => {
|
|||||||
expect(formatRub(null)).toBe('—');
|
expect(formatRub(null)).toBe('—');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('pickLabel', () => {
|
||||||
|
it('содержит контрагента, счёт и сумму', () => {
|
||||||
|
expect(pickLabel('ООО Ромашка', '6001', '1234.5')).toBe('Выбрать: ООО Ромашка, 6001, 1 234,50');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@ -13,6 +13,9 @@ export const DISCARD_QUESTION = 'Есть несохранённые измен
|
|||||||
/** Сумма в рублях с двумя знаками («1 000 000,00»); окно показывает рубли независимо от единиц панели таблицы. */
|
/** Сумма в рублях с двумя знаками («1 000 000,00»); окно показывает рубли независимо от единиц панели таблицы. */
|
||||||
export const formatRub = (value: string | null): string => formatScaledAmount(value, { scale: 0, precision: 2 });
|
export const formatRub = (value: string | null): string => formatScaledAmount(value, { scale: 0, precision: 2 });
|
||||||
|
|
||||||
|
/** Подпись кнопки «Выбрать» в списке нераспределённых: читалка экрана называет контрагента, счёт и сумму. */
|
||||||
|
export const pickLabel = (counterparty: string, account: string, amount: string): string => `Выбрать: ${counterparty}, ${account}, ${formatRub(amount)}`;
|
||||||
|
|
||||||
/** «394.27» → «394,27%»; строка в число не переводится. */
|
/** «394.27» → «394,27%»; строка в число не переводится. */
|
||||||
export const percentText = (p: string): string => `${p.replace('.', ',')}%`;
|
export const percentText = (p: string): string => `${p.replace('.', ',')}%`;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user