Единая нормализация ББ/ОФР: экран формы и карточка файла по API v5.19 (#43, arm-ka-docs#116) #44

Merged
aep merged 22 commits from feat/43-statements-v2 into test 2026-10-18 19:09:18 +03:00
5 changed files with 16 additions and 7 deletions
Showing only changes of commit 12fcea7560 - Show all commits

View File

@ -22,7 +22,7 @@ const failureList = (list: FailedCheckOut[], onShow?: (key: string) => void) =>
{list.map((f) => (
<div key={`${f.column_index}-${f.relation}`}>
{failureText(f)}
{onShow && f.line_ids.length > 0 && (
{onShow && (f.line_ids ?? []).length > 0 && (
<Button type='link' size='small' onClick={() => onShow(f.line_ids[0])}>
Показать
</Button>

View File

@ -119,7 +119,7 @@ export function OsvDocument({ document, onChanged }: { document: DocumentOut; on
const labelSpan = 2 + (table.hasDepartments ? 1 : 0) + (table.hasCounterparties ? 1 : 0);
// предупреждения документа (P6-19): все записи issues, без привязки к строкам
const issueItems = useMemo(
() => document.issues.map((i) => ({ id: i.id, severity: i.severity, message: i.message, place: '', targetKey: null })),
() => (document.issues ?? []).map((i) => ({ id: i.id, severity: i.severity, message: i.message, place: '', targetKey: null })),
[document.issues],
);
const canConfirm = document.status === 'RECOGNIZED' || document.status === 'NEEDS_CHECK';

View File

@ -40,19 +40,20 @@ export function issuePlaces(
for (const r of rows) if (r.lineId !== null) rowByLineId.set(r.lineId, r);
const columnIds = new Set(columns.map((c) => c.id));
for (const issue of issues) {
const lineIds = issue.line_ids ?? [];
if (issue.field !== null) {
if (fields.includes(issue.field)) push(places.byField, issue.field, issue);
else places.document.push(issue);
continue;
}
const known = issue.line_ids.map((id) => rowByLineId.get(id)).filter((r): r is GridRow => r !== undefined);
const known = lineIds.map((id) => rowByLineId.get(id)).filter((r): r is GridRow => r !== undefined);
const columnId = issue.column_id !== null && columnIds.has(issue.column_id) ? issue.column_id : null;
if (issue.line_ids.length > 0 && known.length > 0) {
if (lineIds.length > 0 && known.length > 0) {
for (const r of known) {
if (columnId !== null) push(places.byCell, cellKey(r.key, columnId), issue);
else push(places.byRow, r.key, issue);
}
} else if (issue.line_ids.length === 0 && columnId !== null) {
} else if (lineIds.length === 0 && columnId !== null) {
push(places.byColumn, columnId, issue);
} else {
places.document.push(issue);
@ -92,7 +93,7 @@ export function issueListItems(issues: IssueOut[], places: IssuePlaces, rows: Gr
const items = issues
.filter((issue) => issue.kind === 'warning')
.map((issue): IssueListItem => {
const first = issue.line_ids.map((id) => rowByLineId.get(id)).find((r) => r !== undefined);
const first = (issue.line_ids ?? []).map((id) => rowByLineId.get(id)).find((r) => r !== undefined);
const column = issue.column_id !== null ? columnById.get(issue.column_id) : undefined;
let place: string;
let targetKey: string | null = null;

View File

@ -151,6 +151,13 @@ describe('buildDocumentRows: предупреждения', () => {
expect(legacy[0].fileWarnings[0]).toMatchObject({ code: 'LEGACY_WARNING', message: 'старое' });
});
it('ядро без issue_counts (до v5.19) — нули, не падает', () => {
const old = doc() as Partial<DocumentBrief>;
old.issue_counts = undefined;
const rows = buildDocumentRows([file({ documents: [old as DocumentBrief] })]);
expect(rows[0].issueCounts).toEqual({ error: 0, info: 0 });
});
it('issue_counts документа переносятся в issueCounts', () => {
const rows = buildDocumentRows([file({ documents: [doc({ issue_counts: { error: 1, info: 3 } })] })]);
expect(rows[0].issueCounts).toEqual({ error: 1, info: 3 });

View File

@ -99,7 +99,8 @@ export function buildDocumentRows(files: FileOut[], labelFor?: (f: FileOut) => s
linkable: LINKABLE.has(d.document_type),
fileWarnings,
mappingWarnings,
issueCounts: d.issue_counts,
// ядро без v5.19 не присылает issue_counts — считаем, что замечаний нет
issueCounts: d.issue_counts ?? { error: 0, info: 0 },
};
});
});