import { DownloadOutlined, FilterOutlined } from '@ant-design/icons'; import { Alert, Button, Select, message } from 'antd'; import { useEffect, useState } from 'react'; import { useParams } from 'react-router-dom'; import { ApiError } from '../../api/client'; import { exportOsv } from '../../services/api/osv'; import type { ConsolidatedRowOut } from '../../types/api'; import type { VersionCard } from '../../types/consolidations/version_members'; import { exportFilename, saveBlob } from '../../utils/download'; import { CounterpartyMapModal } from '../ConsolidatedOsv/CounterpartyMapModal'; import { OsvGaps } from '../ConsolidatedOsv/OsvGaps'; import { OsvTable } from '../ConsolidatedOsv/OsvTable'; import { mapEntryId } from '../ConsolidatedOsv/counterpartyMapping'; import { OSV_PAGE_SIZE, useConsolidatedOsv } from '../ConsolidatedOsv/useConsolidatedOsv'; import { PRECISIONS, UNITS, useNumberDisplay } from '../ConsolidatedOsv/useNumberDisplay'; type Props = { card: VersionCard | null; /** Сообщает странице отчёта `unmapped_total` сводки — для модалки [31-00] при уходе с вкладки «ОСВ». */ onUnmappedChange?: (total: number) => void; }; export function OsvContent({ card, onUnmappedChange }: Props) { const [exporting, setExporting] = useState(false); const { version_id } = useParams<{ version_id: string }>(); // строка, для которой открыт выбор организации («Указать» или ИНН сопоставленного ЮЛ) const [mapping, setMapping] = useState(null); const osv = useConsolidatedOsv(version_id ?? ''); const { unit, setUnit, precision, setPrecision, format } = useNumberDisplay(); const download = async () => { if (!version_id) { return; } setExporting(true); try { const { blob, filename } = await exportOsv(version_id, osv.filters); saveBlob(blob, filename ?? exportFilename(card?.company_group.name ?? 'ГК', card?.year ?? 0, card?.quarter ?? '')); } catch (e: unknown) { message.error(e instanceof ApiError ? e.message : 'Не удалось выгрузить свод'); } finally { setExporting(false); } }; const s = osv.summary; const unmapped = s?.unmapped_total ?? 0; const onlyUnmapped = osv.filters.unmapped === true; useEffect(() => { onUnmappedChange?.(unmapped); }, [unmapped, onUnmappedChange]); // вне вкладки «ОСВ» предупреждать не о чем useEffect(() => () => onUnmappedChange?.(0), [onUnmappedChange]); return ( <>
Единицы
({ label: i, value: i }))} value={precision} onChange={(v) => setPrecision(v ?? 2)} style={{ width: 90 }} />
{osv.error && } {unmapped > 0 && ( // `osv-mapping-alert` макета [30] / [32-osv-no-inn]
Требуется указать соответствия Для перехода к следующему шагу сопоставьте все внешние организации без ИНН. Осталось: {unmapped}. {/* макет оставляет кнопку как есть, снимать фильтр — воронкой ИНН или «Сбросить фильтры» (панель — позже) */}
)} ({ id: m.id, name: m.name }))} onPage={osv.setPage} numFormat={format} onFilter={osv.patchFilters} onMap={setMapping} />
{mapping && version_id && ( setMapping(null)} onMapped={osv.refresh} /> )} ); }