feat: bulk-дампы открытых данных ФНС по юрлицам + lookup по ИНН #3429

Merged
lekss361 merged 2 commits from feat/fns-legal-entities into main 2026-09-08 22:29:11 +00:00

2 commits

Author SHA1 Message Date
bot-backend
60c355b9a5 merge main в feat/fns-legal-entities
All checks were successful
CI Trade-In / changes (pull_request) Successful in 7s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 5m9s
# Conflicts:
#	tradein-mvp/backend/app/services/product_handlers.py
2026-09-09 01:20:12 +03:00
bot-backend
1b1859b7d3 feat: bulk-дампы открытых данных ФНС по юрлицам + lookup по ИНН
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 5m19s
Легальный обход блокера ЕГРН: сведений о правообладателях-физлицах в открытом
доступе не существует (218-ФЗ ст. 62), а по ЮЛ данные открыты и типовые условия
ФНС разрешают переработку и перераспространение со ссылкой на источник.

Наборы 7707329152-{revexp,sshr2019,debtam,snr}. URL дампа НЕ хардкодится —
дата в имени файла меняется при каждой публикации, ссылка резолвится со
страницы каталога; загруженная версия трекается в fns_dataset_versions, чтобы
не перекачивать одно и то же. Обход XML внутри ZIP потоковый (lxml iterparse
с очисткой), архив не распаковывается ни в память, ни на диск.

ДВА ДЕФЕКТА, найденные прогоном на реальном дампе (revexp, data-20260825,
104 МБ, 2118 XML) — до этого парсер извлекал НОЛЬ записей при 17 зелёных
тестах, потому что фикстуры были написаны по выдуманной форме:

1. ИНН и показатели лежат на РАЗНЫХ соседних элементах внутри <Документ>:
   ИНН на <СведНП ИННЮЛ="...">, суммы на <СведДохРасх СумДоход="...">.
   Харвестер требовал их на одном элементе — совпадений не было ни одного.
   Теперь носители ИНН ищутся по поддереву, а значения без собственного ИНН
   привязываются к организации только когда носитель в документе один.
2. Безусловный elem.clear() на каждом элементе вычищал детей ДО закрытия
   <Документ> (end-события детей приходят раньше родительского). Чистка
   теперь только на границе записи.

Отчётный период берётся из ДатаСост документа, а не из подставленного
значения. Служебные атрибуты (ИдДок, ДатаДок, ВерсФорм, КолДок) фактами
не считаются.

Проверено: 40 002 факта на первых 20 001 организаций, серии СумДоход/СумРасход,
период 31.12.2025, нечисловых ИНН — ноль.

СКОУП: только загрузка и lookup по ИНН. Потребителя нет и он не изобретается —
estimator.py не тронут, ручек API не добавлено. Подключение к скорингу
застройщика/УК — отдельная задача.

Миграции 296 (таблицы) и 297 (сид расписания, enabled=false, interval_days 30).
2026-09-09 00:39:56 +03:00