Commit graph

13 commits

Author SHA1 Message Date
2dd76ea5e8 feat(tradein): cian_session cookies management + admin endpoints (Wave 4 Worker A) (#457)
Some checks failed
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 39s
Deploy Trade-In / deploy (push) Has been cancelled
2026-05-23 13:22:00 +00:00
9b2a54788b fix(tradein): восстановленная оценка показывает этаж/площадь, не 0/0
AggregatedEstimate не нёс параметры целевой квартиры (площадь, этаж,
комнаты, год, тип дома). HeroSummary брал их из формы-инпута — у
свежей оценки работало, но при открытии оценки по ссылке (?id=, из
Истории) формы нет → «Сводка» показывала «ЭТАЖ 0/0, Площадь 0 м²».

Параметры теперь проходят сквозь весь стек:
- AggregatedEstimate + TS-тип получили area_m2/rooms/floor/
  total_floors/year_built/house_type/repair_state/has_balcony;
- estimate_quality заполняет их из payload, get_estimate — из строки
  trade_in_estimates (колонки там уже есть);
- HeroSummary читает из estimate с откатом на input.

Заодно в TS-тип добавлен пропущенный est_days_on_market.
2026-05-22 15:50:19 +05:00
0b14538f7d fix(tradein): бюджет по времени в geocode-missing — cron не таймаутит
cron geocode-missing-шаг дёргает эндпоинт через `curl -m 320`, а
геокодинг 100 адресов упирается в Nominatim (1 req/sec + typo-тиры на
провалах) и выходит за 320с. При таймауте curl cron-loop обрывался —
объявления Cian/N1 оставались без координат и были невидимы для оценки
(ST_DWithin по geom). Сейчас ~200 таких объявлений в БД.

geocode_missing теперь выходит из цикла по бюджету 240с (заведомо
меньше cron-таймаута) и возвращает remaining > 0 — cron штатно
продолжает следующим чанком. Заодно убран мёртвый import asyncio.
2026-05-22 14:37:15 +05:00
TradeIn Deploy
18c2e64182 fix(tradein): GET /estimate/{id} возвращает полный набор полей
При открытии оценки по ссылке (?id=) или перезагрузке страницы
get_estimate отдавал огрызок: без sources_used, confidence_explanation,
target_address, координат, data_freshness_minutes. Из-за этого карточка
«Сбор данных по квартире» пустела до «0 / 7 источников · ожидает
запрос» — хотя данные в БД есть.

Теперь SELECT и ответ включают полный набор полей AggregatedEstimate.
period_months 24 → 12 (совпадает с estimator / DEALS_PERIOD_MONTHS).
2026-05-22 13:20:53 +05:00
TradeIn Deploy
d456e4fecb feat(tradein): выбор адреса на карте ЕКБ (#415)
Кнопка справа от поля адреса → модалка с картой Екатеринбурга.
Клик по дому → reverse-геокодинг → адрес подставляется в форму.

- geocoder.reverse_geocode + GET /api/v1/geocode/reverse — Nominatim
  /reverse (координаты → адрес).
- MapPicker.tsx — модалка с Leaflet + OSM-тайлами (Leaflet с CDN,
  без npm-зависимости), circleMarker по клику.
- EstimateForm — кнопка-карта справа от AddressInput.

Карта на OSM (без API-ключа). При появлении ключа Yandex (#402)
можно перейти на Я.Карты.

Closes #415
2026-05-22 12:09:35 +05:00
TradeIn Deploy
abafb60120 feat(tradein): рабочие страницы История и Кэш (#399)
Заглушки навбара (href=#) → рабочие страницы.

- GET /api/v1/trade-in/history — последние оценки из trade_in_estimates.
- GET /api/v1/trade-in/cache-stats — счётчики данных/кэшей.
- app/history/page.tsx — таблица прошлых оценок, ссылки на отчёты.
- app/cache/page.tsx — состояние данных (объявления, сделки, кадастр,
  кэш геокодера, последний парсинг).
- navbar — ссылки История / Кэш ведут на страницы.

Closes #399
2026-05-22 11:28:27 +05:00
TradeIn Deploy
5413cce953 feat(tradein): backend загрузки фото квартиры (#394)
Фото квартиры прикрепляются к оценке, хранятся в Postgres (bytea) —
без отдельного файлового тома, уезжают вместе с бэкапом БД.

- data/sql/007_estimate_photos.sql — таблица estimate_photos
  (FK на trade_in_estimates, ON DELETE CASCADE).
- POST /estimate/{id}/photos — multipart-загрузка (image/*, ≤10 МБ,
  ≤12 фото на оценку).
- GET  /estimate/{id}/photos — список метаданных.
- GET  /estimate/{id}/photos/{photo_id} — отдать содержимое.
- python-multipart добавлен в зависимости (FastAPI UploadFile).

Фронтенд (file-drop в форме) — отдельным PR.
2026-05-22 11:05:35 +05:00
TradeIn Deploy
4ea35d5740 feat(tradein): geocode-missing для deals (#4 завершение)
geocode-missing получил target=listings|deals. deals.geocode_tried_at
добавлен в миграцию 005. cron геокодит и сделки Росреестра по улицам.
2026-05-21 20:04:19 +03:00
TradeIn Deploy
7adb7cff66 feat(tradein): auth на admin-эндпоинтах (#2)
/api/v1/admin/scrape и geocode-missing закрыты X-Admin-Token.
settings.admin_token (env ADMIN_TOKEN). Пусто = открыто (dev),
задано = требуем заголовок. cron шлёт токен из .env.runtime.
2026-05-21 19:47:01 +03:00
TradeIn Deploy
609744df91 fix(tradein): чанковый геокодинг — cron больше не таймаутится (#1)
geocode_tried_at: после каждой попытки NOW(), повтор только через 7 дней.
Эндпоинт чанкуется (limit=100), отдаёт remaining. cron вызывает в цикле.
2026-05-21 19:43:12 +03:00
TradeIn Deploy
d2a740779d fix(tradein): реальные координаты Cian/N1 через геокодинг (был баг 0 аналогов)
Cian/N1 ставили anchor+jitter координаты — фейковые, вокруг центрального
якоря. Для адресов вдали от центра ST_DWithin не находил аналоги → 0.

Теперь Cian/N1 оставляют lat/lon=None, geocode-missing проставляет реальные
координаты по адресу (geom пересчитывается триггером). cron вызывает
geocode-missing после скрейпа. Адрес чистится от суффикса · р-н.
2026-05-21 13:14:33 +03:00
TradeIn Deploy
42a0c31f27 feat(tradein): N1.ru scraper + cron для 4 источников
Добавлен 4-й источник N1.ru (ekaterinburg.n1.ru) — региональный портал,
хорошо представлен на Урале. DOM-парсинг карточек data-test=offers-list-item
через curl_cffi. Multi-room сегментация 1/2/3/4к.

cron-scrape.sh переписан под прод: запрос к backend через docker exec
(без публичного admin/scrape), все 4 источника (avito/cian/yandex/n1).
2026-05-21 11:44:32 +03:00
lekss361
02267d0306 feat: add tradein-mvp subproject (Trade-In Estimator под /trade-in)
- FastAPI backend: PostGIS estimator + 3 scrapers (Avito/Cian/Yandex)
- Next.js 15 frontend: tradein.html mockup design, basePath=/trade-in
- WeasyPrint PDF (Брусника-style 4-page report)
- Address autocomplete с typo-tolerance + 6 EKB presets
- Изолированный docker stack gendesign-tradein (отдельная postgres БД)
- Caddy inline routes: gendsgn.ru/trade-in/* и /trade-in/api/v1/*
- Forgejo Actions: .forgejo/workflows/deploy-tradein.yml (shell-based GHCR login)
- Триггер только по paths: tradein-mvp/** (не пересекается с deploy.yml)
- Образы: ghcr.io/lekss361/gendesign-tradein-{backend,frontend}:latest

Первый запуск на сервере (вручную, один раз):
  - создать /opt/gendesign/tradein-mvp/.env.runtime (postgres pwd, contact email)
  - docker network create gendesign_shared (если нет)
  - docker compose -p gendesign-tradein up -d
  - docker compose -p gendesign exec caddy caddy reload
2026-05-21 00:25:39 +03:00