---
name: tbr-map-reports-pivot
description: "ТБР развернулся: карта всех лотов + отчёты по объекту вместо броней; ловушки torgi API"
metadata: 
  node_type: memory
  type: project
  originSessionId: d0c6c5aa-4d05-42e2-a1f9-034482b88603
  modified: 2026-07-27T09:41:01.870Z
---

**[TR-MAP-2026 / TR-REPORT-2026]** «Торги без риска» перестроен 2026-07-25: обезличенная лента + бронь 2990₽ → **карта всех лотов** (публично) + **AI-отчёт по объекту 599₽** (`TBR_REPORT_PRICE`, одна ручка на сайт+бот+Robokassa) (2 бесплатных при регистрации). КН/адрес/ссылка/бенчмарк — только вошедшим и только в ответе API. Переходы на торги логируются (`lot_link_clicks`, без IP/UA).

**Ловушки torgi.gov.ru (стоили времени, не наступать снова):**
- фильтры дат (`biddEndTimeFrom`, `createDateFrom`, +6 вариантов) **молча игнорируются**;
- `size` ≤ 10, `totalPages` ≤ 1000 → потолок 10 000 записей; по стране это ~4,7 мес;
- **`dynSubjRF` — внутренний порядковый индекс субъекта, НЕ код региона** (33→Архангельская 29). Карта из 83 индексов зашита в `tbr/closed_poller.py` + guard на чужой регион;
- состоявшиеся сделки лежат в статусе **FAILED** (единственный участник забирает по стартовой цене).

**Главная ловушка данных:** `detail.point` есть почти у всех лотов, НО организаторы ставят **одну точку на партию** — 2094 из 3004 на общих координатах, до 109 км от кадастрового центроида. Отсюда `Lot.geo_precision` = parcel/point/approx; approx помечается на карте и уточняется через НСПД (pynspd-сайдкар, ~0.12 с/лот).

**Ключевые файлы:** `tbr/closed_poller.py`, `tbr/benchmark.py`, `tbr/web/reports_service.py`, `tbr/web/api.py` (`/api/lots/map`, `/detail`, `/visit`, `/api/lots/{id}/report`), фронт `components/LotsMap.tsx` + `LotDetailPanel.tsx`. Robokassa отчётов — `WEB_REPORT_OFFSET=4_000_000` (брони были 3_000_000).

**Карточка бота (2026-07-26):** показывает КН, адрес и кнопку «🔗 Открыть лот на торгах»; кнопка отчёта подписана «бесплатно (N осталось)» либо ценой. Повторный заказ того же лота говорит «уже заказан, ничего не списываем» — раньше писал «заказан» и создавал ощущение, что отчёты в боте бесплатные.

**Карта в боте (2026-07-26):** вход в 4 местах — кнопка «Меню» у поля ввода (`setChatMenuButton`), инлайн-кнопка в `/start`, команда `/map` (+`setMyCommands`), reply-кнопка с текстовым фолбэком. Раньше жила ТОЛЬКО в reply-клавиатуре, которую держат свёрнутой → карты фактически не было. **Гоча:** `sendMessage` НЕ возвращает ReplyKeyboardMarkup в ответе (только инлайн) — «reply_markup: НЕТ» ничего не доказывает.

**Оценка рынка в панели карты (2026-07-26):** API отдавал `recommended_price`/`discount_pct`/`confidence`, а `LotDetailPanel` их не рендерил — на карте не было главного сигнала выгоды. Добавлен блок `MarketEstimate` (та же честная логика, что в `LotCard`: `region` → «Ориентир по региону», «≈», оговорка про медиану региона; `high` → «просят продавцы, а не цена сделки») + строка «📉 старт ниже оценки на N%» в попапе маркера.

**Поиск места на карте:** `GET /api/geocode` — прокси к геокодеру «Земли» (127.0.0.1:20140, 11.9 млн адресов OSM). **Гоча:** он рубит запросы без `User-Agent` («Invalid HTTP request received»). Плюс `near_lat/near_lon/radius_km` в `/api/lots/map`, компонент `MapSearch.tsx` (подсказки + «рядом со мной» + радиусы 5/10/25/50/100 км), круг области на карте и подгон масштаба под радиус, а не под разброс точек.

**Mini App в TG (2026-07-27):** маршрут `/tma` в tbr-frontend — карта на весь экран + карточка лота шторкой (`TmaLotSheet`), без шапки/футера сайта. Вход автоматом: `POST /api/auth/telegram-webapp` валидирует `initData` и выдаёт обычную сессионную cookie; юзер ищется по `telegram_id` тем же `upsert_telegram_user`, что и бот → баланс и отчёты общие. **Гоча №1:** у Mini Apps подпись НЕ как у Login Widget — `secret = HMAC("WebAppData", bot_token)` vs `sha256(bot_token)`. **Гоча №2:** SDK Telegram надо грузить самим (`telegram-web-app.js`) и ждать — иначе `window.Telegram` не появится. **Гоча №3 (тест):** web.telegram.org показывает окно «LAUNCH/CANCEL», без клика iframe не создаётся; и кнопку брать только из последнего пузыря, иначе откроется старая ссылка. Тесты: `tests/e2e/test_initdata.py` (10, подпись) + `tests/e2e/e2e_tma.py` (13, реальный TG).

**Точный адрес (2026-07-26):** `tbr/address.py` — `clean_address()` вырезает адрес из текста лота ЕФРСБ (там поля адреса НЕТ, только `tradeObject` целиком), схлопывает дубли региона/района от torgi, раскрывает `м.р-н`/`с.п.`/`з/у`. Авторитетный источник — **официальный адрес Росреестра из НСПД по КН** (`geocode._nspd_for` теперь возвращает и адрес), провенанс в `Lot.address_source` (nspd/torgi/efrsb) + `address_precise` в `/detail`. «Пробить»: панель даёт копию, Яндекс.Карты **по координатам** (не по строке) и НСПД по КН; в боте — кнопка «🗺 Участок на публичной карте». **Гоча:** `\b` после точки не срабатывает — «обл.», «с.п.» не матчатся, нужен явный lookahead `(?=[\s,;]|$)`.

**Хвосты брони, найденные глазами (2026-07-26):** `/api/auth/me` отдавал баланс из мёртвой `free_bookings` вместо `free_reports`; на главной начальная цена отчёта была 2990, фолбэк 1200; подпись «Бесплатные брони». Всё исправлено — но урок: legacy-колонка, которую никто не списывает, тихо жила в ответе API.

**E2E-наборы теперь в репо** `~/Services/tbr/tests/e2e/` (`e2e_site.py` 38, `e2e_bot.py` 24, `e2e_bot_repeat.py` 10, `e2e_bot_map.py` 5) — раньше лежали в `/tmp` на mini и их снесла системная чистка. Запуск: `TBR_DB_PATH=.../data/db/tbr.db PYTHONPATH=.../tests/e2e` + интерпретатор `~/Services/zemlya-bot/venv/bin/python3` (своего venv у tbr нет).

**Старое расположение (устарело):** `/tmp/e2e_site.py` (31), `/tmp/e2e_bot.py` (20, реальный TG), `/tmp/e2e_rep.py` (10, Dispatcher.feed_update), `/tmp/e2e_map.py` (5, карта в боте), `/tmp/vbm.py` (5, меню-кнопка+команды). web.telegram.org НЕ доставляет второй клик по той же inline-кнопке — ветку повторов проверять только детерминированно.

**Бронь снята полностью:** удалены `/api/book` (→404), 7 бот-колбэков (`book/bookok/bookcancel/pay/paycheck/payfree/cancel`), `cards.payment_card`, `BOOKING_FEE`. Таблица `bookings` и 28 оплат ОСТАВЛЕНЫ намеренно — финансовая история. Админ-бонусы переведены с legacy `free_bookings` на `free_reports` (иначе выданные вручную бонусы не работали бы).

Родств.: [[tbr_overview]], [[tbr_multisource_efrsb]], [[zemlya_web_overview]].
