59 lines
2.4 KiB
TypeScript
59 lines
2.4 KiB
TypeScript
import { ApiError, apiFetch, apiFetchBlob } from '../../api/client';
|
||
import type { FileOut, Page, UploadResult } from '../../types/api';
|
||
|
||
export function isUploadResult(body: unknown): body is UploadResult {
|
||
return (
|
||
typeof body === 'object' &&
|
||
body !== null &&
|
||
Array.isArray((body as UploadResult).accepted) &&
|
||
Array.isArray((body as UploadResult).rejected)
|
||
);
|
||
}
|
||
|
||
/** Маршрут файлов ЮЛ: с консолидацией — файлы в контексте консолидации, без неё — файлы ЮЛ (design D-2). */
|
||
export function filesPath(legalEntityId: string, consolidationId: string | null): string {
|
||
return consolidationId
|
||
? `/consolidations/${encodeURIComponent(consolidationId)}/legal-entities/${legalEntityId}/files`
|
||
: `/legal-entities/${legalEntityId}/files`;
|
||
}
|
||
|
||
/** Загрузка файлов ЮЛ одним запросом (в консолидацию или без контекста); 422 «ни один не принят» возвращается как результат, прочие ошибки — throw. */
|
||
export async function uploadFiles(legalEntityId: string, files: File[], consolidationId: string | null): Promise<UploadResult> {
|
||
const form = new FormData();
|
||
for (const file of files) {
|
||
form.append('files', file);
|
||
}
|
||
try {
|
||
return await apiFetch<UploadResult>(filesPath(legalEntityId, consolidationId), { method: 'POST', body: form });
|
||
} catch (e: unknown) {
|
||
if (e instanceof ApiError && e.status === 422 && isUploadResult(e.body)) {
|
||
return e.body;
|
||
}
|
||
throw e;
|
||
}
|
||
}
|
||
|
||
export function summarizeUpload(result: UploadResult): { accepted: string[]; rejected: { name: string; reason: string }[] } {
|
||
return {
|
||
accepted: result.accepted.map((a) => a.name),
|
||
rejected: result.rejected.map((r) => ({ name: r.name, reason: r.message })),
|
||
};
|
||
}
|
||
|
||
export async function listLegalEntityFiles(legalEntityId: string, consolidationId: string | null): Promise<FileOut[]> {
|
||
const page = await apiFetch<Page<FileOut>>(`${filesPath(legalEntityId, consolidationId)}?limit=100`);
|
||
return page.items;
|
||
}
|
||
|
||
export function hasPendingFiles(files: FileOut[]): boolean {
|
||
return files.some((f) => f.status === 'UPLOADED' || f.status === 'PROCESSING');
|
||
}
|
||
|
||
export function fetchFileContent(fileId: string): Promise<{ blob: Blob; filename: string | null }> {
|
||
return apiFetchBlob(`/files/${fileId}/content?disposition=inline`);
|
||
}
|
||
|
||
export function getFile(id: string): Promise<FileOut> {
|
||
return apiFetch<FileOut>(`/files/${id}`);
|
||
}
|