7.4 KiB
Матрица файловых выгрузок внешних данных 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.
Генератор:
- читает каждую нормализованную таблицу один раз без model-level сортировки;
предметные даты и fallback по
created_atиндексированы; - создаёт компактный JSON-массив и переиспользует его как готовый JSON;
- потоково формирует CSV и write-only XLSX;
- записывает календарный
export_yearв manifest; - атомарно публикует
current.jsonтолько после готовности всей матрицы; - при ошибке удаляет staging и продолжает отдавать предыдущее поколение того же года;
- сохраняет текущее и предыдущее поколения по умолчанию.
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.