All checks were successful
Deploy Trade-In / changes (push) Successful in 12s
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 45s
Deploy Trade-In / build-backend (push) Successful in 1m1s
Deploy Trade-In / deploy (push) Successful in 2m46s
124 lines
5.3 KiB
Python
124 lines
5.3 KiB
Python
"""CLI: ДОМ.РФ капремонт open data → houses.year_built/material_walls (issue #2013).
|
||
|
||
Тянет КР1.1 (house registry) + КР1.2 (constructive elements) с открытых данных
|
||
ДОМ.РФ (region 66), UPSERT'ит в staging `domrf_kapremont` (мигр. 176), затем:
|
||
1. backfill_houses_from_domrf — COALESCE(houses.year_built, domrf.commission_year,
|
||
houses.zhkh_year) + material_walls + total_floors (fold-in уже загруженного
|
||
ГИС-ЖКХ года — houses без domrf-матча тоже выигрывают).
|
||
2. propagate_listings_year_from_houses — UPDATE listings.year_built = houses.year_built
|
||
там, где listing ещё NULL. Именно это открывает estimator'у (year_built BETWEEN
|
||
когорта-фильтр) реальные годы на источниках вроде avito (0% year_built, 52.5%
|
||
linked к houses).
|
||
|
||
Запуск из контейнера tradein-backend (у прода есть интернет к домрф.рф):
|
||
|
||
python -m app.tasks.domrf_kapremont_load # полный прогон
|
||
python -m app.tasks.domrf_kapremont_load --dry-run # без записи, только подсчёт
|
||
python -m app.tasks.domrf_kapremont_load --load-only # только staging, без backfill
|
||
python -m app.tasks.domrf_kapremont_load --backfill-only # staging уже загружена — только
|
||
# backfill+propagate
|
||
python -m app.tasks.domrf_kapremont_load \\
|
||
--kr11-path /tmp/kr11.csv --kr12-path /tmp/kr12.csv # локальные CSV, без скачивания
|
||
|
||
В режиме --dry-run скачивание/парс (если применимо) происходят, но НИ ОДНОЙ записи
|
||
в БД не делается.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import argparse
|
||
import logging
|
||
|
||
from app.core.db import SessionLocal
|
||
from app.services.domrf_kapremont_loader import (
|
||
backfill_houses_from_domrf,
|
||
load_domrf_kapremont,
|
||
propagate_listings_year_from_houses,
|
||
)
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
def build_parser() -> argparse.ArgumentParser:
|
||
"""Парсер CLI (вынесен для тестируемости флагов без запуска main)."""
|
||
parser = argparse.ArgumentParser(
|
||
description=(
|
||
"ДОМ.РФ капремонт loader: КР1.1+КР1.2 → domrf_kapremont staging → "
|
||
"houses.year_built/material_walls/total_floors → listings.year_built"
|
||
)
|
||
)
|
||
parser.add_argument(
|
||
"--kr11-path", default=None, help="локальный CSV КР1.1 (пропустить скачивание)"
|
||
)
|
||
parser.add_argument(
|
||
"--kr12-path", default=None, help="локальный CSV КР1.2 (пропустить скачивание)"
|
||
)
|
||
parser.add_argument(
|
||
"--work-dir",
|
||
default=None,
|
||
help="каталог для скачанных/распакованных CSV (по умолчанию — временный, удаляется после)",
|
||
)
|
||
parser.add_argument(
|
||
"--dry-run", action="store_true", help="без записи в БД — только скачивание/парс/подсчёт"
|
||
)
|
||
parser.add_argument(
|
||
"--load-only",
|
||
action="store_true",
|
||
help="только скачать+распарсить+UPSERT staging, без backfill houses/propagate listings",
|
||
)
|
||
parser.add_argument(
|
||
"--backfill-only",
|
||
action="store_true",
|
||
help="пропустить скачивание/load staging (считаем что уже загружена этим же "
|
||
"или предыдущим прогоном) — только backfill houses + propagate listings",
|
||
)
|
||
return parser
|
||
|
||
|
||
def main() -> None:
|
||
logging.basicConfig(
|
||
level=logging.INFO,
|
||
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
||
)
|
||
parser = build_parser()
|
||
args = parser.parse_args()
|
||
|
||
if args.load_only and args.backfill_only:
|
||
parser.error("--load-only и --backfill-only взаимоисключающи")
|
||
|
||
db = SessionLocal()
|
||
try:
|
||
load_counts: dict[str, int] = {}
|
||
if not args.backfill_only:
|
||
load_counts = load_domrf_kapremont(
|
||
db,
|
||
kr11_path=args.kr11_path,
|
||
kr12_path=args.kr12_path,
|
||
work_dir=args.work_dir,
|
||
dry_run=args.dry_run,
|
||
)
|
||
if not args.dry_run:
|
||
db.commit()
|
||
logger.info("domrf_kapremont_load: load stage done: %s", load_counts)
|
||
|
||
houses_counts: dict[str, int] = {}
|
||
listings_counts: dict[str, int] = {}
|
||
if not args.load_only:
|
||
houses_counts = backfill_houses_from_domrf(db, dry_run=args.dry_run)
|
||
listings_counts = propagate_listings_year_from_houses(db, dry_run=args.dry_run)
|
||
if not args.dry_run:
|
||
db.commit()
|
||
|
||
logger.info(
|
||
"domrf_kapremont_load DONE: dry_run=%s load=%s houses=%s listings=%s",
|
||
args.dry_run,
|
||
load_counts,
|
||
houses_counts,
|
||
listings_counts,
|
||
)
|
||
finally:
|
||
db.close()
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|