arm-core/web/src/widgets/FilesDrawer/documentRows.ts
2026-10-27 00:22:28 +04:00

116 lines
4.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { CheckResult, DocumentStatus, FileOut, FileType, FileWarningOut, IssueCountsOut, Severity } from '../../types/api';
import { formatMoscowDate } from '../../utils/dates';
import { documentStatusLabel, documentTypeLabel, periodLabel } from '../../utils/labels';
import { toFileWarnings, warningsLevel } from './fileWarnings';
export type RowStatus = 'success' | 'warning' | 'processing' | 'error';
export interface DocumentRow {
key: string;
/** id документа; null — строка файла без документов */
documentId: string | null;
/** id файла: удаление и замена — файлом целиком */
fileId: string;
name: string;
fileType: FileType;
subtitle: string;
period: string;
periodCheck?: CheckResult | null;
counterpartyCheck?: CheckResult | null;
status: RowStatus;
statusLabel: string;
errorReason: string | null;
linkable: boolean;
/** предупреждения разбора файла (общие для всех документов файла) */
fileWarnings: FileWarningOut[];
mappingWarnings: string[];
/** счётчики issues документа; у строки файла без документов — нули */
issueCounts: IssueCountsOut;
/** число комментариев документа; у строки файла без документов — 0 */
commentsCount: number;
}
/** Значок у статуса (P6-12): число предупреждений и цвет уровня; ничего нет — null. */
export function rowBadge(row: DocumentRow): { count: number; level: Severity } | null {
const count = row.fileWarnings.length + row.issueCounts.error + row.issueCounts.info;
if (count === 0) return null;
const level = warningsLevel(row.fileWarnings) === 'error' || row.issueCounts.error > 0 ? 'error' : 'info';
return { count, level };
}
const LINKABLE = new Set(['OSV', 'BALANCE', 'INCOME']);
const join = (parts: (string | null)[]) => parts.filter(Boolean).join(' · ');
function errorReason(f: FileOut): string | null {
if (f.status !== 'ERROR' || !f.job) return null;
return f.job.mapping_error ?? f.job.error_message ?? f.job.error_code ?? null;
}
function documentRowStatus(status: DocumentStatus): RowStatus {
if (status === 'CONFIRMED') return 'success';
if (status === 'ERROR') return 'error';
return 'warning';
}
/** Файлы → строки таблицы: одна строка на документ, файл без документов — одна строка на файл. */
export function buildDocumentRows(files: FileOut[], labelFor?: (f: FileOut) => string | null): DocumentRow[] {
return files.flatMap((f): DocumentRow[] => {
const extra = labelFor?.(f) ?? null;
const name = f.original_name ?? 'без имени';
const date = formatMoscowDate(f.uploaded_at);
const fileWarnings = toFileWarnings(f.job?.warnings);
const mappingWarnings = f.job?.mapping_warnings ?? [];
if (f.documents.length === 0) {
const failed = f.status === 'ERROR';
return [
{
key: f.id,
documentId: null,
fileId: f.id,
name,
fileType: f.file_type,
subtitle: join([f.file_type, date, extra]),
period: '—',
status: failed ? 'error' : 'processing',
statusLabel: failed ? 'Ошибка' : 'Обработка',
errorReason: errorReason(f),
linkable: false,
fileWarnings,
mappingWarnings,
issueCounts: { error: 0, info: 0 },
commentsCount: 0,
},
];
}
return f.documents.map((d) => {
const typeText =
d.document_type === 'DISCLOSURE' || d.document_type === 'OTHER'
? 'Прочий документ'
: documentTypeLabel(d.document_type, d.osv_account_code);
const status = documentRowStatus(d.status);
return {
key: d.id,
documentId: d.id,
fileId: f.id,
name,
fileType: f.file_type,
subtitle: join([typeText, f.file_type, date, extra]),
period: periodLabel(d.period_year, d.period_quarter, d.is_cumulative),
periodCheck: d.period_check,
counterpartyCheck: d.counterparty_check,
status,
statusLabel: documentStatusLabel(d.status),
errorReason: null,
linkable: LINKABLE.has(d.document_type),
fileWarnings,
mappingWarnings,
// ядро без v5.19 не присылает issue_counts — считаем, что замечаний нет
issueCounts: d.issue_counts ?? { error: 0, info: 0 },
commentsCount: d.comments_count ?? 0,
};
});
});
}