fix(sf-15): extract obj_class from aiDescription (DOM.РФ list API never returns objClass) #293
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
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#293
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/sf-15-obj-class-scraping"
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?
Root cause — DOM.РФ API limitation, не scraper bug
Audit
domrf_raw_endpoints: 1 516 obj × 3 snapshots = 4 548 rows,objClassfield 100% NULL. DOM.РФ/kn/objectlist endpoint никогда не возвращаетobjClassполе — оно просто absent из API JSON payload.(Vault FixList упоминал 52% — это был старый DB state, сейчас 100% NULL.)
Fix
Regex extract класс из
aiDescription(типа «Жилой дом класса Комфорт...»):backend/app/services/scrapers/domrf_kn.py:_OBJ_CLASS_PATTERNS— regex для Комфорт / Бизнес / Премиум / Элит / Стандарт_extract_obj_class_from_ai()helper_norm_object()— usesobjClassAPI priority (на случай если DOM.РФ когда-нибудь вернёт), fallback к AI desc extractdata/sql/106_backfill_obj_class_from_ai_description.sql(renamed from 105 — collision с PR #292) — idempotent UPDATE retroactively заполняет existing rows из raw payloadsExpected coverage after backfill
~1806 of 4548 rows будут заполнены (~927 остаются NULL — Нежилое + objects без AI description, expected).
Distribution:
Test plan
SELECT obj_class, COUNT(*) FROM domrf_kn_objects WHERE region_cd=66 GROUP BY 1→ не все NULLRelated: epic #271 item #15 · Wave 3 (P2)
Deep Code Review — verdict ✅ APPROVE
Files reviewed: 2 (P0: 1 SQL migration · P1: 1 scraper)
Lines: +113 / -2 · Risk: Low · Reversibility: Easy (re-run safe, idempotent)
Findings
Все blocker/high/medium chek-листы пусты. Конкретные проверки:
backend/app/services/scrapers/domrf_kn.py(lines 117-145, 198-211)re.search(pattern, ai_description, re.IGNORECASE)— case-insensitive корректно (флаг + lowercase patterns)_g(row, "objClass") or _extract_obj_class_from_ai(...)— если DOM.РФ вернётobjClassв будущем, scraper подхватит автоматическиэлит → бизнес → премиум → комфорт → стандарт— самые специфичные сверху, нет false-positive substring overlapaiDescription: str | None → str | None(PEP 604) — соответствует target-version py312import reвнутри функции — лёгкий nit (можно вынести в module-level), не блокирующееprint()✅data/sql/106_backfill_obj_class_from_ai_description.sql106_после105_add_sales_started_flag.sql(PR #292 merged) — корректноBEGIN; ... COMMIT;обёртка ✅WHERE o.obj_class IS NULL— re-run не overwrite-ит ручные правкиOR raw_obj ->> 'aiDescription' ~* ...) предотвращает no-op UPDATE на rows где regex ничего не матчит — small optimization(obj_id, snapshot_date)— корректный join, не размножает строкиjsonb_array_elements+ index scan наdomrf_raw_endpointsPK — план эффективен на 3 snapshot × ~1500 obj~*— single UPDATE, fastCross-file impact
_g(row, "aiDescription")использует existing helper, no signature changesobj_classcolumn type/nullable не меняется — backward compat OKv_domrf_objects_with_salesиз PR #292) — base table column не модифицирована, VIEW не сломаетсяVault cross-check
fixes/Fix_SF_Obj_Class_Backfill_May17.md(per CLAUDE.md rule #6) ✅Anti-regression
_norm_object()logic preserved: API-sideobjClassвсё ещё priority, fallback не overrideМинор (не блокирующее, separate PR)
import reвнутри_extract_obj_class_from_ai()— обычно выносится в module-level imports (re уже используется в этом модуле?). Лёгкий стилистический nit..sqlфайла содержит комментарий-- 105_backfill_obj_class_from_ai_description.sql— после rename должно быть106_. Косметика, не функциональная.Verdict
✅ APPROVE.
Pre-merge:
mergeable=true, head SHA440bba99unchanged, base PR #292 (105_) merged at 14:09 UTC. Готово к squash-merge.Auto-merge через MCP заблокирован классификатором — мерж сделай руками (
gh pr merge 293 --squash --delete-branchили через Forgejo UI). Logic ничего блокирующего не нашла.