bd3e5c8216
feat(tradein): аккаунт praktika + лимит 15 оценок/мес, чистка PRINZIP в UI ( #635 )
Deploy / changes (push) Successful in 5s
Deploy Trade-In / changes (push) Successful in 7s
Deploy / build-backend (push) Successful in 29s
Deploy / build-frontend (push) Successful in 28s
Deploy / build-worker (push) Successful in 29s
Deploy Trade-In / build-backend (push) Successful in 46s
Deploy / deploy (push) Successful in 58s
Deploy Trade-In / build-frontend (push) Successful in 1m40s
Deploy Trade-In / deploy (push) Successful in 39s
2026-05-28 22:04:58 +00:00
492dd0aba6
feat(tradein): бейдж точности адреса (qc_geo) на карточке оценки (accuracy #1 )
...
Честность к пользователю: показываем насколько точно определён адрес —
«до дома» / «до улицы» / «приблизительно» — рядом с confidence.
- schemas/trade_in.py: address_precision: Literal["house","street","approximate"]|None
- estimator.py: _qc_geo_to_precision (qc_geo 0→house, 1→street, ≥2→approximate,
None→None), set в основном return + _empty_estimate
- api/v1/trade_in.py: get_estimate + estimate_pdf теперь rehydrate'ят DaData-поля
(canonical_address, house_cadnum, house_fias_id, address_precision, metro_nearest)
из row — раньше на ?id= reopen / в PDF вся Q1-обогащёнка пропадала (поймал
code-reviewer). Колонки уже persisted, фикс read-path.
- frontend: AddressPrecision type + precision-badge в HeroSummary (.card-meta),
токены --success/--accent-2/--bg-card-alt, без новых токенов.
Канон: tech-analyst (план) → backend-engineer + frontend-engineer → code-reviewer
(✅ APPROVE, поймал reopen-path gap) → fold-in fix. Tests: 7 passed, tsc clean, ruff clean.
match_house_readonly wiring отложен (fast-follow).
2026-05-28 15:37:33 +05:00
b0c03942be
feat(tradein): tier badge на DealsCard rows ( #603 )
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m38s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / deploy (push) Successful in 38s
2026-05-27 13:15:49 +00:00
63756c3c29
feat(tradein): StreetDealsCard с paired listings (PR L, #564 Phase 2) ( #599 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Successful in 1m38s
Deploy Trade-In / deploy (push) Successful in 35s
Deploy Trade-In / build-backend (push) Has been skipped
2026-05-27 12:29:06 +00:00
42ab74e2e8
feat(tradein): MapPicker snap marker — Phase 5 of #582 ( #594 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Successful in 48s
Deploy Trade-In / build-frontend (push) Successful in 1m44s
Deploy Trade-In / deploy (push) Successful in 39s
2026-05-27 09:30:17 +00:00
56a7a36c9a
feat(auth): UserMenu — личный кабинет top-right (PR D) ( #590 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy / changes (push) Successful in 4s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m45s
Deploy Trade-In / deploy (push) Successful in 38s
Deploy / build-frontend (push) Successful in 3m0s
Deploy / deploy (push) Successful in 58s
2026-05-26 10:48:57 +00:00
7a2b055b35
feat(rbac): frontend route-guard + nav filter ( #586 )
...
Deploy / changes (push) Successful in 5s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m42s
Deploy Trade-In / deploy (push) Successful in 39s
Deploy / build-frontend (push) Successful in 2m55s
Deploy / deploy (push) Successful in 1m1s
PR B (frontend) to backend RBAC #585 . RouteGuard wraps app, NoAccessScreen on 403 from /me, TopNav filtered by role.
2026-05-26 06:51:45 +00:00
dcf5e32aa1
fix(tradein): убрать «PRINZIP» wordmark из шапки
...
Оставляем TI-логотип и «Trade-In» рядом. PRINZIP-брендинг скрыт — для
текущего демо/пилота он не нужен. Когда понадобится white-label под
конкретного заказчика, вернём через `brand-name` slot.
Найдено пользователем в шапке gendsgn.ru/trade-in.
2026-05-25 13:28:48 +05:00
33c4c84467
feat(tradein): этаж/этажность optional + best test presets по deal count ( #558 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Successful in 44s
Deploy Trade-In / build-frontend (push) Successful in 1m53s
Deploy Trade-In / deploy (push) Successful in 44s
2026-05-24 21:44:44 +00:00
4d1c409e18
feat(tradein): «По вашей улице» — StreetDealsCard на real ДКП-сделки Росреестра ( #556 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m35s
Deploy Trade-In / deploy (push) Successful in 40s
2026-05-24 20:37:29 +00:00
lekss361
0ac54d1de0
feat(tradein): sell-time sensitivity block (4 цены × медиана срока продажи)
...
Backend: GET /api/v1/trade-in/estimate/{id}/sell-time-sensitivity
- 4 фиксированных бакета по premium к медиане года: −5% / медиана (±3%) / +5% / +10%
- Median exposure_days + p25/p75 per bucket
- Filter outliers: last_price > start_price * 0.7 (отбрасываем подозрительно дешёвые)
- Benchmark: median ₽/м² за последние 2 года
Frontend: новый SellTimeSensitivity component (4-card grid)
- color-coded buckets (green→blue→yellow→red)
- median highlighted синей рамкой
- показывает "~31 дн" + "обычно 31-61 дн" + count лотов
- встроен в HouseAnalyticsSection между KpiRow и PriceHistoryChart
Использует существующий house_placement_history (15k+ rows).
2026-05-24 22:43:32 +03:00
5bfacd51b0
feat(tradein): «Росреестр» button — copy address + open EGRN request form ( #550 )
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 6s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Has been cancelled
2026-05-24 19:42:09 +00:00
967e7185ca
feat(tradein): cian price-change badges + split chart Avito/Yandex ( #547 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Successful in 42s
Deploy Trade-In / build-frontend (push) Successful in 1m36s
Deploy Trade-In / deploy (push) Successful in 45s
2026-05-24 18:24:00 +00:00
80850a591e
feat(tradein): house analytics section (chart + KPI + sold list) ( #546 )
Deploy Trade-In / build-backend (push) Successful in 43s
Deploy Trade-In / changes (push) Successful in 6s
Deploy Trade-In / build-frontend (push) Successful in 2m34s
Deploy Trade-In / deploy (push) Successful in 39s
2026-05-24 18:09:45 +00:00
08cf615ad7
feat(tradein/cian): surface valuation chart + rent + change-pct on /trade-in ( #530 )
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Successful in 48s
Deploy Trade-In / build-frontend (push) Has been cancelled
2026-05-24 14:32:54 +00:00
f2f9e5b79b
feat(tradein-ui): placement history card ( #529 )
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / build-frontend (push) Has been cancelled
Deploy Trade-In / changes (push) Successful in 6s
Deploy Trade-In / build-backend (push) Has been skipped
2026-05-24 14:22:16 +00:00
591039493c
feat(tradein/cian): admin endpoints + UI for detail+newbuilding history scrape ( #525 )
Deploy Trade-In / build-backend (push) Successful in 58s
Deploy Trade-In / build-frontend (push) Successful in 1m37s
Deploy Trade-In / deploy (push) Successful in 1m45s
Deploy Trade-In / changes (push) Successful in 6s
2026-05-24 14:05:55 +00:00
92d00ec874
feat(tradein-ui): mock-disclaimer + progressive enrichment + UX polish ( #517 )
Deploy Trade-In / build-frontend (push) Successful in 1m42s
Deploy Trade-In / deploy (push) Successful in 35s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Has been skipped
2026-05-24 12:58:39 +00:00
3190bbec54
fix(tradein-frontend): MapPicker focus trap + Leaflet SRI, PhotoUpload size check ( #514 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m26s
Deploy Trade-In / deploy (push) Successful in 32s
2026-05-24 12:01:17 +00:00
3665a61e48
fix(tradein-frontend): safeUrl validator, apiFetch dedup, ListingsCard a11y, error boundary ( #512 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m24s
Deploy Trade-In / deploy (push) Successful in 32s
2026-05-24 11:47:38 +00:00
726e774a7f
feat(tradein-ui): Yandex admin scraper page — mirror Avito + global delay control ( #488 )
...
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Has been cancelled
Replaces 5-line stub at /scrapers/yandex with full admin page mirroring Avito. 5 sections: global delay (umbrella yandex key), search around, detail snapshot, JK newbuilding, valuation. TanStack Query hooks + apiFetch, TS strict, reuses trade-in.css.
Fixup: useScraperSettings unwraps {settings:[...]} response wrapper; PUT body includes required source field (matches backend Pydantic ScraperSettingPayload). useEffect race guarded with initializedRef so 30s refetch doesn't clobber user input mid-edit.
Verdict: APPROVE — deep-code-reviewer (response shape unwrap + source field both applied).
2026-05-23 20:07:48 +00:00
ffb0c67c84
fix(tradein-ui): double /trade-in/ prefix in Cian page Link (PR #486 follow-up) ( #489 )
Deploy Trade-In / build-frontend (push) Successful in 1m23s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / deploy (push) Successful in 23s
2026-05-23 15:56:01 +00:00
ebfd29a0a6
feat(tradein-ui): Cian scraper admin page + global request delay control ( #486 )
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m21s
Deploy Trade-In / deploy (push) Successful in 24s
2026-05-23 15:36:07 +00:00
65029cd1a7
feat(tradein-ui): Cian cookies upload admin page ( #481 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m22s
Deploy Trade-In / deploy (push) Successful in 23s
2026-05-23 15:19:42 +00:00
fd3cb4e6ed
feat(tradein): /scrapers/avito — 6-я секция Расписание (in-app scheduler UI) ( #483 )
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / build-frontend (push) Successful in 1m22s
Deploy Trade-In / deploy (push) Successful in 23s
Deploy Trade-In / build-backend (push) Has been skipped
2026-05-23 14:55:31 +00:00
dd24bd8136
feat(tradein): /scrapers/avito — 5-я секция City sweep (auto + cancel + runs list) ( #478 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m22s
Deploy Trade-In / deploy (push) Successful in 23s
2026-05-23 14:40:11 +00:00
649034479f
feat(tradein): Stage 4c — scrapers admin pages (Avito real + Cian/Yandex stubs) ( #472 )
Deploy Trade-In / build-frontend (push) Successful in 1m23s
Deploy Trade-In / deploy (push) Successful in 22s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Has been skipped
2026-05-23 14:05:56 +00:00
72d2b97ee0
feat(tradein): Stage 4b — IMV benchmark badge + house info card on estimate result ( #461 )
Deploy Trade-In / deploy (push) Successful in 21s
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m21s
2026-05-23 13:28:23 +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
6041ac8464
fix(tradein): фото аналога в Сводке больше не скрыто плейсхолдером
...
В .hero-photo псевдоэлементы ::before/::after рисуют декоративный
скелет-плейсхолдер «фасада дома». Они position:absolute, а <img> с
фото аналога — position:static, поэтому абсолютные псевдоэлементы
рисовались ПОВЕРХ картинки: реальное фото загружалось (naturalWidth
есть), но визуально всегда был серый плейсхолдер.
Фото (z-index 1) и подпись .photo-meta (z-index 2) теперь над
скелетом. Скелет остаётся виден, когда фото нет или оно не
загрузилось (onError → display:none).
2026-05-22 15:35:01 +05:00
14c81dd5ac
fix(tradein): N1.ru — честный статус источника вместо хардкод-timeout
...
SourcesProgress хардкодил N1.ru как error («timeout — нет ответа»)
при готовой оценке — строка никогда не сверялась с sources_used.
Но N1 — реальный рабочий источник (224 объявления на проде), и при
вкладе в оценку он показывался красным крестом-ошибкой.
Теперь строка N1 ведёт себя как cian/avito/yandex: done + счётчик
лотов, если источник в sources_used, иначе loading/idle.
2026-05-22 14:16:30 +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
1941c3d7df
fix(tradein): фото аналога в Сводке + честный статус источников
...
UI-баги, замеченные при обзоре результата оценки:
- HeroSummary: блок hero-photo был пустым серым плейсхолдером (в
макете там фото, в коде слот не подключён). Теперь показывает фото
первого аналога с картинкой; onError → fallback на плейсхолдер.
- SourcesProgress: источники без данных после завершения оценки
оставались в статусе idle с подписью «ожидает запрос» — выглядело
как зависший запрос. Теперь после готовности → «нет данных»
(терминальный статус).
2026-05-22 12:02:56 +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
48ccbdafc8
feat(tradein): CRM-поля в форме оценки ( #395 )
...
Доп. поля для трейд-ин менеджера: тип собственности, ипотека/
обременение, имя и телефон клиента. На расчёт оценки не влияют —
сохраняются в trade_in_estimates вместе с записью.
- data/sql/008_crm_fields.sql — 4 колонки в trade_in_estimates.
- TradeInEstimateInput + estimator INSERT — приём и сохранение.
- EstimateForm — секция «CRM — для менеджера» (4 поля).
Closes #395
2026-05-22 11:15:15 +05:00
TradeIn Deploy
0a1df4d13a
feat(tradein): фронтенд загрузки фото квартиры ( #394 )
...
Компонент PhotoUpload на result-view: выбор image/* (multiple),
загрузка в POST /estimate/{id}/photos, превью загруженных фото.
Multipart напрямую через fetch — apiFetch форсит JSON content-type.
Closes #394
2026-05-22 11:10:50 +05:00
lekss361
aeb895a9dc
fix(tradein): PDF-ссылка через API_BASE_URL (basePath)
...
href Скачать PDF был /api/v1/... без префикса /trade-in → попадал в
main gendesign backend (404). Та же причина что #373 для apiFetch.
2026-05-21 10:15:44 +03:00
lekss361
a17a73af71
fix(tradein): префиксить API_BASE_URL через basePath
...
Без префикса /trade-in клиентский fetch шёл на gendsgn.ru/api/v1/...
который Caddy маршрутизировал в main gendesign backend (не tradein).
Теперь NEXT_PUBLIC_API_BASE_URL fallback на NEXT_PUBLIC_BASE_PATH —
build с BASE_PATH=/trade-in корректно префиксит запросы.
2026-05-21 01:13:46 +03:00
lekss361
5082f50d53
fix(tradein): убрать basePath redirect-loop
...
Под basePath=/trade-in next.config redirects() + app/page.tsx с
redirect(/trade-in) делали /trade-in/ → /trade-in/trade-in (двойной
префикс basePath) → пустая страница / 404.
- Перенёс контент app/trade-in/page.tsx → app/page.tsx (теперь корень
Next = /trade-in/ snaружи)
- Удалил app/trade-in/ как избыточный
- Удалил redirects() блок из next.config.ts
- router.replace("/?id=...") вместо "/trade-in?id=..." — basePath
префиксит автоматически
2026-05-21 01:05:49 +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