feat(tradein): extend base.py save_listings to persist Cian-specific columns (PR #450 follow-up) #455
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#455
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/tradein-base-save-listings-cian-cols"
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?
Summary
Stage 3.5 of CianScraper v1 — addresses PR #450 deep-code-reviewer MEDIUM follow-up. Without this fix, all Stage-2 model fields populated by
_offer_to_lotare silently dropped at INSERT → Stage 8 cross-source matching cannot usedescription_minhash/cadastral_number/building_cadastral_numbersignals.Must merge before Wave 4 (Stages 5/6) — иначе detail/newbuilding scrapers тоже будут терять данные.
Diff
base.py: +38 lines (extend INSERT + ON CONFLICT UPDATE SET)tests/test_base_save_listings.py: NEW 260 lines, 6 testsFields persisted (13)
All confirmed present в
ScrapedLottop-level (PR #447, base.py:97-109):living_area_m2living_area_m2bedrooms_countbedrooms_countbalconies_countbalconies_countloggias_countloggias_countdescription_minhashdescription_minhashcadastral_numbercadastral_numberbuilding_cadastral_numberbuilding_cadastral_numberphonesphonesis_homeowneris_homeowneris_pro_selleris_pro_sellerbargain_allowedbargain_allowedsale_typesale_typemetro_stationsmetro_stationsON CONFLICT
DO UPDATE SETextended — re-scrape refreshes all 13 new cols (not just inserts on first scrape).Backward compat
test_save_listings_avito_compat_cian_cols_are_nullverifies — Avito lot без Cian fields → все 13 params =None→ SQLNULL. No regression in existing Avito/DomRF/other scrapers.Fields NOT yet in ScrapedLot (deferred to Stage 5)
windows_view_type,separate_wcs_count,combined_wcs_count,ceiling_height,repair_type— это detail-page fields. Currently stored inraw_payloadonly. Stage 5 (cian_detail.py) или follow-up PR может promote to top-level + extend INSERT.Tests (6)
Full suite: 77/77 pass.
psycopg v3 compliance
json.dumps(value) if value else None:x::typecasts (CAST(:x AS type) where needed)import psycopg2Refs
decisions/Schema_Cian_SERP_Inventory.mdsec 11 (field mapping)decisions/CianScraper_v1_Implementation_Plan.mdStages 2/8Test plan
Merged via deep-code-reviewer — verdict APPROVE.
Verification summary:
CAST(:phones AS jsonb)+CAST(:metro_stations AS jsonb)correct, no:x::typecastsNone(or[]for phones/metro_stations) → INSERT writes NULL → no regressionif lot.phones else Nonehelper; aligned with_to_json([])="[]"avoidedMinor observations (non-blocking, для будущих PR):
metro_stations DEFAULT '[]'::jsonb; this PR writes explicitNULLwhen list empty. Existing Avito rows have'[]', new Avito rows haveNULL— cosmetic inconsistency, Stage 8 matching shouldCOALESCE(metro_stations, '[]')defensively.phones/metro_stationscollapse "scraper didn't fetch" (None) и "scraper got 0 results" ([]) в SQL NULL — acceptable trade-off per PR body, no caller currently distinguishes.save_listingsв same PR.Wave 4 (Stages 5/6 cian_detail/cian_newbuilding) unblocked.