gendesign/tradein-mvp/backend/app/services
Light1YT b8f9213cd9 feat(tradein): persistent infra для backfill scripts
3 проблемы фиксятся:
1. tradein-mvp/backend/Dockerfile копировал только COPY app — scripts/
   слетал при каждом deploy, требовал manual docker cp.
2. docker-compose.prod.yml без env_file — .env.runtime не читался
   контейнером, переменные приходили только через host env.
3. Env-var name mismatch: compose YANDEX_GEOCODER_KEY vs script
   YANDEX_GEOCODER_API_KEY — script всегда видел None.

Изменения:
- backend/Dockerfile: COPY scripts ./scripts в builder + runner stage
- docker-compose.prod.yml:
  * env_file: ./backend/.env.runtime (required: false) — pattern из
    main backend (PR #585)
  * убран дубль `YANDEX_GEOCODER_API_KEY: ${...}` из environment:
    block — он бы overrideal env_file пустым значением. Reviewer nit
    applied inline.
- pydantic Settings (app/core/config.py): rename yandex_geocoder_key
  → yandex_geocoder_api_key. Case-insensitive env binding автоматически
  подхватывает `YANDEX_GEOCODER_API_KEY` (no Field alias нужен).
- All 5 call sites в app/services/geocoder.py обновлены.
- app/tasks/geocode_missing.py docstring + test mock обновлены.
- backend/scripts/README.md: canonical `docker exec` commands без
  manual `docker cp` workflow.
- DEPLOY.md + .env.example обновлены с новым именем переменной.

Verified:
- pytest tests/test_backfill_house_coords.py + test_audit_address_mismatch.py
  + test_cadastral_reverse.py → 56 pass
- docker compose -f docker-compose.prod.yml config → valid syntax
- pydantic binding: YANDEX_GEOCODER_API_KEY=foo → settings.yandex_geocoder_api_key=='foo'
- code-reviewer LGTM (nit applied inline)

После merge — на VPS уже создан /opt/gendesign/tradein-mvp/backend/.env.runtime
с YANDEX_GEOCODER_API_KEY (см. PR #591 deploy). deploy.yml triggers
force-recreate из-за нового image hash → env_file pick up автоматически.
2026-05-27 11:59:14 +05:00
..
exporters feat(tradein): этаж/этажность optional + best test presets по deal count (#558) 2026-05-24 21:44:44 +00:00
matching fix(tradein-matching): pg_advisory_xact_lock to prevent duplicate house INSERTs (#501) 2026-05-24 10:52:10 +00:00
scrapers fix(yandex-valuation): off-by-one cell index in _parse_row_cells (#552) 2026-05-24 19:57:17 +00:00
__init__.py feat: add tradein-mvp subproject (Trade-In Estimator под /trade-in) 2026-05-21 00:25:39 +03:00
brand.py feat: add tradein-mvp subproject (Trade-In Estimator под /trade-in) 2026-05-21 00:25:39 +03:00
cache.py feat(tradein): Phase 3.2 — /api/v1/search endpoint + Redis cache (#479) 2026-05-23 14:44:22 +00:00
cian_session.py fix(tradein): CIAN_REQUIRED_COOKIES — add real auth cookies (DMIR_AUTH + Cian session) (#480) 2026-05-23 14:52:24 +00:00
estimator.py feat(tradein): этаж/этажность optional + best test presets по deal count (#558) 2026-05-24 21:44:44 +00:00
geocoder.py feat(tradein): persistent infra для backfill scripts 2026-05-27 11:59:14 +05:00
house_metadata.py feat(tradein): postgres_fdw live read of gendesign.cad_buildings (replaces snapshot) (#493) 2026-05-24 08:57:30 +00:00
image_sanitizer.py fix(tradein-photos): sanitize uploaded images via Pillow re-encode (#511) 2026-05-24 11:32:04 +00:00
scheduler.py feat(tradein): in-app scheduler — UI-managed schedule (replaces SSH crontab) (#482) 2026-05-23 14:54:25 +00:00
scrape_pipeline.py fix(tradein/avito): anti-bot hardening — sleep + abort + shared session (#487) 2026-05-23 20:08:40 +00:00
scrape_runs.py fix(tradein/avito): anti-bot hardening — sleep + abort + shared session (#487) 2026-05-23 20:08:40 +00:00
scraper_settings.py feat(tradein): global scraper delay setting (applies across all scrapers) (#485) 2026-05-23 15:43:28 +00:00
search_query.py feat(tradein): Phase 3.2 — /api/v1/search endpoint + Redis cache (#479) 2026-05-23 14:44:22 +00:00