arm-web/src/widgets/FilesDrawer/documentRows.ts

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),
};
});
});
}