84 lines
2.8 KiB
TypeScript
84 lines
2.8 KiB
TypeScript
import type { CheckResult, DocumentStatus, FileOut, FileType } from '../../types/api';
|
|
import { formatMoscowDate } from '../../utils/dates';
|
|
import { documentStatusLabel, documentTypeLabel, periodLabel } from '../../utils/labels';
|
|
|
|
export type RowStatus = 'success' | 'warning' | 'processing' | 'error';
|
|
|
|
export interface DocumentRow {
|
|
key: string;
|
|
/** id документа; null — строка файла без документов */
|
|
documentId: string | null;
|
|
name: string;
|
|
fileType: FileType;
|
|
subtitle: string;
|
|
period: string;
|
|
periodCheck?: CheckResult | null;
|
|
counterpartyCheck?: CheckResult | null;
|
|
status: RowStatus;
|
|
statusLabel: string;
|
|
errorReason: string | null;
|
|
linkable: boolean;
|
|
}
|
|
|
|
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);
|
|
if (f.documents.length === 0) {
|
|
const failed = f.status === 'ERROR';
|
|
return [
|
|
{
|
|
key: f.id,
|
|
documentId: null,
|
|
name,
|
|
fileType: f.file_type,
|
|
subtitle: join([f.file_type, date, extra]),
|
|
period: '—',
|
|
status: failed ? 'error' : 'processing',
|
|
statusLabel: failed ? 'Ошибка' : 'Обработка',
|
|
errorReason: errorReason(f),
|
|
linkable: false,
|
|
},
|
|
];
|
|
}
|
|
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,
|
|
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),
|
|
};
|
|
});
|
|
});
|
|
}
|