Files
state-corp-backend/docs/source-record-export-matrix-ru.md
Aleksandr Meshchriakov 2b9ecc2681
All checks were successful
CI/CD Pipeline / Code Quality Checks (push) Successful in 3m16s
CI/CD Pipeline / Run Tests (push) Successful in 4m58s
CI/CD Pipeline / Build and Push Dev Images (push) Successful in 32s
CI/CD Pipeline / Deploy Dev via Compose (push) Successful in 33s
feat: limit source exports to current year
2026-08-04 23:25:36 +02:00

7.4 KiB
Raw Permalink Blame History

Матрица файловых выгрузок внешних данных State Corp

Пользовательский контракт

Администраторский frontend отправляет POST /api/v2/organization-source-records/export-ticket/ с массивом sources и форматом. Backend проверяет последнее полностью опубликованное поколение и возвращает короткоживущий одноразовый ticket. Затем frontend передаёт ticket в теле обычной HTML-формы на POST /api/v2/organization-source-records/export-download/.

Имя скачиваемого архива формируется по выбранным источникам и времени создания запроса: <source-stem>_YYYYMMDD_HHMMSS.zip, а для нескольких источников их имена соединяются через __. Значение file_name из ticket и итоговый Content-Disposition совпадают.

Браузер получает потоковый ZIP напрямую, без многогигабайтного Blob в JavaScript. Ticket не попадает в URL и после первого запроса становится недействительным. Совместимый администраторский endpoint POST /api/v2/organization-source-records/export/ сразу возвращает тот же ZIP для API-клиентов.

Во время скачивания таблицы external_data не читаются: endpoint упаковывает готовые файлы последнего ночного поколения. При отсутствии поколения API возвращает 503 с кодом source_export_not_ready.

Каждое поколение содержит только текущий календарный год в timezone сервиса. Для моделей с предметной датой год определяется по ней, для моделей без такой даты — по created_at, для финансовых отчётов — по году строк отчёта. Строки других лет из финансового отчёта не выгружаются. После смены года старое поколение не раздаётся: до успешной сборки нового года API отвечает 503 source_export_not_ready.

Матрица

Группа API Таблицы State Corp Файл CSV XLSX JSON
financial_indicators FinancialReport, FinancialReportLine financial-indicators да
government_procurements PublicProcurement public-procurements да да да
industrial_production IndustrialProduct, IndustrialCertificate, ManufacturerRegistryEntry manufacturers-and-products да да да
planned_inspections ProsecutorCheck planned-inspections да да да
bankruptcy BankruptcyProcedure bankruptcy-procedures да да да
defense_suppliers DefenseUnreliableSupplier defense-unreliable-suppliers да да да
arbitration ArbitrationCase arbitration-cases да да да
security_registries InformationSecurityRegistryEntry information-security-registries да да да
vacancies LaborVacancy labor-vacancies да да да

Итого формируется 25 логических артефактов. Финансовые показатели всегда выгружаются в JSON с вложенным массивом financial_lines. Промышленная группа объединяет три таблицы, а поле record_type различает тип строки. Все строки используют тот же контракт, что и Mostovik: реквизиты организации, включая ОКПО, общие поля записи источника и специфичные поля в payload.*.

Все записи текущего года включаются в публичные файлы, а техническое наименование внешнего поставщика нейтрализуется. Исходные значения в БД сохраняются для работы интеграции и дедупликации.

Физических XLSX-файлов может быть больше: по умолчанию один файл содержит не более 100 000 строк данных и получает суффикс -part-001, -part-002 и далее.

Ночная генерация

Celery Beat запускает apps.external_data.tasks.refresh_source_record_export_artifacts ежедневно в 05:30 Europe/Moscow.

Генератор:

  1. читает каждую нормализованную таблицу один раз без model-level сортировки; предметные даты и fallback по created_at индексированы;
  2. создаёт компактный JSON-массив и переиспользует его как готовый JSON;
  3. потоково формирует CSV и write-only XLSX;
  4. записывает календарный export_year в manifest;
  5. атомарно публикует current.json только после готовности всей матрицы;
  6. при ошибке удаляет staging и продолжает отдавать предыдущее поколение того же года;
  7. сохраняет текущее и предыдущее поколения по умолчанию.

Web и Celery worker должны использовать общий read-write volume /app/media.

Первый запуск и настройки

Первое поколение можно сформировать вручную:

PYTHONPATH=src uv run python src/manage.py build_source_record_exports
Настройка Значение по умолчанию Назначение
SOURCE_RECORD_EXPORT_DIRECTORY media/source-record-exports Общий каталог поколений
SOURCE_RECORD_EXPORT_GENERATIONS_TO_KEEP 2 Число успешных поколений
SOURCE_RECORD_EXPORT_LOCK_TTL_SECONDS 21600 TTL распределённой блокировки
SOURCE_RECORD_EXPORT_XLSX_ROWS_PER_FILE 100000 Строк данных в одной XLSX-части
SOURCE_RECORD_EXPORT_DOWNLOAD_TICKET_TTL_SECONDS 300 Срок действия download-ticket

Для атомарной генерации требуется свободное место не меньше (GENERATIONS_TO_KEEP + 1) * размер поколения плюс запас файловой системы.

На локальном снимке от 2026-08-04 поколение за 2026 год содержит 1 962 записи и занимает 4 738 872 байта (4,52 MiB) для всей матрицы. Архив со всеми источниками оценивается в 2,49 MiB для JSON, 1,59 MiB для CSV и 0,44 MiB для XLSX; к сумме добавляется небольшой служебный overhead ZIP.