fix(ptica): act_date — дата акта об изъятии, а не первой попавшейся ссылки (#2464) #2981
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#2981
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/2464-act-date-citation"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Как нашлось
Не по чтению кода. Смотрел
land_reservationи увидел, что 11 строк из 27 делят одну дату 2004-07-06, причём это два разных документа — развязка на Сибирском тракте и улица Энергостроителей, проекты 2020-х. Совпадение даты у несвязанных актов и было признаком, что дата не своя.Доказано, а не предположено
Все пять исходных PDF загружены с екатеринбург.рф и распознаны тем же трактом, что использует загрузчик (
ocr_pdf_textв прод-контейнере). Вот откуда бралась дата:_extract_act_dateбрал первое «от DD.MM.YYYY» во всём тексте. У «Сообщений о планируемом изъятии» первой строкой оснований почти всегда стоит Генплан-2004.Три документа были верны случайно — у них первой датой и оказалось нужное постановление.
Правка
Дата принимается, только если в 120 символах перед ней стоит слово «постановлени». Ссылки-помехи (
Решение … Думы,Приказ Министерства) его не содержат.Окно шире самой фразы (~50 символов), потому что OCR перемешивает колонки таблицы:
…Администрации города документами) Екатеринбурга от 19.04.2019….Нет подходящей даты →
None. Дата чужого документа хуже пустоты: по ней нельзя ни отфильтровать актуальные изъятия, ни сверить срок, и она неотличима от настоящей.Калибровка — на всех пяти сразу, не на одном
постановленипостановлени+администрациУзкий вариант давал те же 5/5, но ломал законный случай
Постановление № 509-ПП— областной акт без слова «администрация», уже закреплённый тестомtest_act_date_extracted_from_text. Это и решило выбор: на живых данных широкое условие не хуже, а лишнего не отсекает. Правило, откалиброванное на одном образце, работает только на нём — потому и брал все пять.Сквозная проверка
Патченный код прогнан по всем пяти распознанным текстам целиком:
27 — ровно столько же строк, сколько в
land_reservationна проде. 11 меняют дату, 16 не двигаются.Как проверено
origin/mainтри теста красные с реальным неверным значением (assert '2004-07-06' == '2020-02-12'), ни одного TypeError: тесты идут черезextract_izyatie_records, чья сигнатура одинакова на обеих сторонах, а не через приватный хелпер с новым параметром.None, а не чужая дата; заголовок разбирается по-прежнему.pytest backend/tests/services/scrapers/— 312 passed, 6 skipped.Остаётся открытым
act_numberпуст у всех 27 строк:_RE_ACT_NUMBERтребует суффиксПП|ПА|РП|ПГ|ГП|МО, а реальные номера —1413,259,1504,2687,863. Не чиню здесь:act_numberвходит в уникальный ключ(cad_num, act_number)(миграция 189), поэтому его заполнение меняет дедупликацию и требует отдельного разбора.Часть эпика #2464.
`_extract_act_date` брал ПЕРВОЕ «от DD.MM.YYYY» во всём OCR-тексте. «Сообщение о планируемом изъятии» открывается списком оснований, и первой строкой там стоит «Решение Екатеринбургской городской Думы от 06.07.2004 № 60/1 «Об утверждении Генерального плана города»» — Генплан, а не акт об изъятии. На проде это дало 11 строк из 27 с датой 2004-07-06 при проектах 2020 и 2022 годов, причём одну и ту же дату получили ДВА разных документа (развязка на Сибирском тракте и улица Энергостроителей). Совпадение даты у несвязанных актов и было первым признаком, что дата не своя. Дата принимается, только если в 120 символах перед ней стоит слово «постановлени». Ссылки-помехи в этих документах — «Решение … Думы» и «Приказ Министерства» — его не содержат. Окно шире самой фразы, потому что OCR перемешивает колонки таблицы и вклинивает в неё чужой текст («…Администрации города документами) Екатеринбурга от 19.04.2019…»). Если подходящей даты нет — None. Дата чужого документа хуже пустоты: по ней нельзя ни отфильтровать актуальные изъятия, ни сверить срок, и она неотличима от настоящей. Калибровка не на одном образце: все пять исходных PDF загружены и распознаны тем же трактом, что использует загрузчик (ocr_pdf_text в прод-контейнере). Окна 80/120/160 дают одинаковые 5 из 5. Более узкое правило (плюс «администраци») давало те же 5 из 5, но ломало законный случай «Постановление № 509-ПП» — областной акт без слова «администрация», уже закреплённый тестом test_act_date_extracted_from_text; взято широкое. Сквозная проверка: патченный код прогнан по всем пяти распознанным текстам целиком — 27 записей, ровно столько же, сколько строк в land_reservation; 11 меняют 2004-07-06 на настоящую дату, 16 не двигаются. Двусторонне: против origin/main три теста красные с реальным неверным значением ('2004-07-06'), ни одного TypeError — тесты идут через extract_izyatie_records, чья сигнатура одинакова на обеих сторонах. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>Важное уточнение: правка действует только вперёд
Проверил, что будет со старыми строками, и ответ — ничего. UPSERT загрузчика заканчивается
ON CONFLICT (cad_num, act_number) DO NOTHING, а неDO UPDATE. Пятничный прогон (0 7 * * fri) наткнётся на конфликт и 11 строк с датой Генплана-2004 перезаписаны не будут.То есть один этот PR оставил бы прод в прежнем состоянии, а выглядел бы как починка. Разовое исправление вынесено отдельно: #2984 (миграция 191, 9 строк → 2022-05-27, 2 строки → 2020-02-12, с сужением по doc_url и контролем-двойником).