feat(mera/b2c): раздел статей и хаб документов (макет 29.08) + числа статьи заменены на замер #3223

Merged
bot-backend merged 1 commit from feat/b2c-articles-docs into main 2026-08-29 12:56:44 +00:00
Collaborator

Последняя часть макета Макса «B2C модуль для МЕРА». После лэндинга (#3215) и экрана отчёта (#3221) закрываются оставшиеся два холста: «МЕРА статьи» / «МЕРА статья» и «МЕРА документы».

Что появилось

адрес что это
/articles список разборов: одна живая статья + две карточки «СКОРО» (рубрики и подводки — из макета)
/articles/kak-ocenit-kvartiru статья целиком: оглавление, фильтр аналогов, таблица поправок, плитки, CTA, пять ошибок
/docs хаб: юридические документы, тарифы, контакты и реквизиты

Проводка доведена до конца: «Статьи» в шапке и подвале и «Проверьте себя» (#game) перестали быть неактивными заглушками — цели теперь существуют. EstimateHeader переименован в InnerHeader: он стоит уже на трёх страницах, а не только на проверке.

Главное: числа статьи — не из макета, а из замера

Макет писал в голосе продукта: «По нашим данным, средний разрыв между первой ценой в объявлении и ценой сделки — 4,1%, а у квартир, провисевших больше трёх месяцев, он доходит до 9%». Прогнал это через прод (poincare, 29.08.2026, только SELECT) — величины такого рода у нас нет в принципе:

  • связки «объявление → его же сделка» в данных не существует: cadastral_number пуст у всех 108 623 сделок и всех 111 693 объявлений;
  • ближайший суррогат asking_to_sold_ratios — это отношение медиан двух разных популяций (сделки Росреестра за 12 мес. против активных объявлений за 14 дней), а не парная величина. Разброс по кольцам от центра 0.73 → 1.34, то есть «коэффициент» — функция того, где сидят обе выборки, а не характеристика торга. Назвать 1 − ratio разрывом «объявление ↔ сделка» нельзя.

Поэтому §1 и §4 переписаны на то, что измеряется парно: цена публикации → цена на дату среза внутри одного объявления.

Замер: 6202 объявления квартир Домклик в Екатеринбурге, срез 18.07.2026 (offer_price_history, единственный источник с настоящими таймстемпами площадки; avito/yandex непригодны — триггер не пишет стартовую цену, а yandex_price_history сеет синтетическую пару now − 1 день).

экспозиция n снижали цену медиана снижения
до 30 дн 734 6,7% −2,55%
30–90 дн 2955 38,5% −3,03%
дольше 90 дн 2513 62,3% −4,92%
всего 6202 44,4% −3,97%

Шесть скептиков в отдельных контекстах воспроизвели SQL и попытались опровергнуть. Числа устояли бит-в-бит; формулировку опровергли — и она исправлена: в выборке нет ни одного объявления моложе 21 дня (прогон обогащения 18.07 их не захватил), а это ровно та когорта, которая цену почти не режет. Поэтому в тексте прямо сказано: (1) это движение цены в объявлении, а не скидка на сделке; (2) самых свежих объявлений в замере нет, и по всему живому рынку доля ниже. Цифра по долгостою от этой дыры не зависит.

Остальные утверждения макета

макет что сделано
«расхождение с кадастровой доходит до 40%» снято: кадастровой стоимости ПОМЕЩЕНИЙ нет ни в одной базе. Есть только стоимость ЗДАНИЯ в базе ПТИЦЫ (cad_buildings.cost_value); замер по ней даёт −67%, но это другой объект — почти плоские 40 355 ₽/м² по всем домам выдают массовую формулу от площади. Проверить нечем — значит, числа нет
«РАССТОЯНИЕ: до 1 км, в пределах того же района» район из подбора убран — оценщик его не использует; добавлен реальный каскад послаблений (год → 2 км → площадь ±25% и комнатность ±1 → 3 и 5 км)
«ПЛОЩАДЬ: ±10%» ±15%AREA_TOLERANCE в estimator.py:92. По факту показанных аналогов в ±10% укладывается только две трети
поправки §3 (−5…−8% за этаж и т.п.) оставлены, но сноска честная: «ОРИЕНТИРЫ РЫНОЧНОЙ ПРАКТИКИ, А НЕ ЗАМЕР МЕРЫ»
плитки −4,3% / ×2,4 / 83% заменены на измеренные 7% / 38% / 62%. Плейсхолдеров marketing-v3 в статье не осталось (для справки: честные прокси к макетным плиткам — −1,1%/мес, ×1,04 и коридор шириной 47% от цены)
«91% аналогов ближе 1 км» не опубликовано: это свойство показанной десятки (display_pool[:10], отсортированной по близости), а не поиска. Тавтология
новая редакция оферты, ИНН 66700XXXXX, mera.example не публикуются — макет сам помечал их как «замените на согласованный с юристом документ». Хаб только ведёт на существующие /oferta, /privacy, /refund от 13.08. Реквизиты в блоке «Контакты» — настоящие, из LEGAL_ENTITY
«Отвечаем по будням с 9:00 до 19:00» снято: регламента ответа никто не устанавливал, а на странице документов срок читается как обязательство
фильтр рубрик, «новые статьи — каждую неделю» не рендерятся: фильтровать нечего, расписания публикаций нет

Периметр и гейты

Три списка сходятся: @meraPages / @meraShortSlash / @meraLongPages в apps.caddyPUBLIC_ROUTESPUBLIC_SHORT_PATHS в гварде. Полный прогон тестов сразу поймал забытый гвард — RouteGuard.publicPaths покраснел на /articles до того, как я успел это заметить сам.

Два гейта, оба фальсифицированы, а не просто «зелёные»:

  • новый@meraShortSlash до сих пор не проверялся ничем, хотя это третье место того же класса дефекта (адрес со слэшем мимо матчера уходит в 404). Проверка добавлена; снятие /docs из альтернации красит её.
  • #2904articles/articles-content.ts внесён в V3_SOURCES. Проверено с ОДНИМ этим файлом в списке: снятие noindex красит гейт, то есть строка не декоративная.

Проверено

tsc · eslint · vitest 69/69 · check:mera-public-isolation · скриншоты трёх страниц на 1180 / 375 / 320 px, горизонтального переполнения нет.

Что осталось за решениями владельца

  1. Тексты двух оставшихся статей — карточки стоят с рубриками и подводками из макета, помечены «СКОРО».
  2. Платёжный контур (#2896). Тарифная таблица описывает порядок оплаты из оферты, но приёма платежей нет (PUBLIC_ESTIMATE_ENABLED = false, payments и payment_entitlements на проде пусты). Записано в докстринге docs/page.tsx: открывать страницу наружу можно только вместе с контуром либо сняв таблицу.
  3. «Продажа под ключ» — строка тарифа «по договору» есть, пункт меню неактивен. Формы заявки нет, канал один — поддержка.
  4. Мелкий долг, не в этом PR: #9fb0b4 / #2c3a3f на тёмных плашках — сырой hex, но так написан весь файл (17+ мест), выносить в токены надо отдельным проходом.
Последняя часть макета Макса «B2C модуль для МЕРА». После лэндинга (#3215) и экрана отчёта (#3221) закрываются оставшиеся два холста: **«МЕРА статьи» / «МЕРА статья»** и **«МЕРА документы»**. ## Что появилось | адрес | что это | |---|---| | `/articles` | список разборов: одна живая статья + две карточки «СКОРО» (рубрики и подводки — из макета) | | `/articles/kak-ocenit-kvartiru` | статья целиком: оглавление, фильтр аналогов, таблица поправок, плитки, CTA, пять ошибок | | `/docs` | хаб: юридические документы, тарифы, контакты и реквизиты | Проводка доведена до конца: «Статьи» в шапке и подвале и «Проверьте себя» (`#game`) перестали быть неактивными заглушками — цели теперь существуют. `EstimateHeader` переименован в `InnerHeader`: он стоит уже на трёх страницах, а не только на проверке. ## Главное: числа статьи — не из макета, а из замера Макет писал в голосе продукта: **«По нашим данным, средний разрыв между первой ценой в объявлении и ценой сделки — 4,1%, а у квартир, провисевших больше трёх месяцев, он доходит до 9%»**. Прогнал это через прод (poincare, 29.08.2026, только SELECT) — величины такого рода у нас нет в принципе: * связки «объявление → его же сделка» в данных не существует: `cadastral_number` пуст у **всех** 108 623 сделок и **всех** 111 693 объявлений; * ближайший суррогат `asking_to_sold_ratios` — это отношение **медиан двух разных популяций** (сделки Росреестра за 12 мес. против активных объявлений за 14 дней), а не парная величина. Разброс по кольцам от центра 0.73 → 1.34, то есть «коэффициент» — функция того, где сидят обе выборки, а не характеристика торга. Назвать `1 − ratio` разрывом «объявление ↔ сделка» нельзя. Поэтому §1 и §4 переписаны на то, что **измеряется парно**: цена публикации → цена на дату среза внутри одного объявления. **Замер:** 6202 объявления квартир Домклик в Екатеринбурге, срез 18.07.2026 (`offer_price_history`, единственный источник с настоящими таймстемпами площадки; avito/yandex непригодны — триггер не пишет стартовую цену, а `yandex_price_history` сеет синтетическую пару `now − 1 день`). | экспозиция | n | снижали цену | медиана снижения | |---|---|---|---| | до 30 дн | 734 | **6,7%** | −2,55% | | 30–90 дн | 2955 | **38,5%** | −3,03% | | дольше 90 дн | 2513 | **62,3%** | −4,92% | | всего | 6202 | **44,4%** | −3,97% | Шесть скептиков в отдельных контекстах воспроизвели SQL и попытались опровергнуть. Числа устояли бит-в-бит; **формулировку опровергли** — и она исправлена: в выборке **нет ни одного объявления моложе 21 дня** (прогон обогащения 18.07 их не захватил), а это ровно та когорта, которая цену почти не режет. Поэтому в тексте прямо сказано: (1) это движение цены **в объявлении**, а не скидка на сделке; (2) самых свежих объявлений в замере нет, и по всему живому рынку доля ниже. Цифра по долгостою от этой дыры не зависит. ## Остальные утверждения макета | макет | что сделано | |---|---| | «расхождение с кадастровой доходит до 40%» | **снято**: кадастровой стоимости ПОМЕЩЕНИЙ нет ни в одной базе. Есть только стоимость ЗДАНИЯ в базе ПТИЦЫ (`cad_buildings.cost_value`); замер по ней даёт −67%, но это другой объект — почти плоские 40 355 ₽/м² по всем домам выдают массовую формулу от площади. Проверить нечем — значит, числа нет | | «РАССТОЯНИЕ: до 1 км, в пределах того же района» | район из подбора убран — оценщик его не использует; добавлен реальный каскад послаблений (год → 2 км → площадь ±25% и комнатность ±1 → 3 и 5 км) | | «ПЛОЩАДЬ: ±10%» | **±15%** — `AREA_TOLERANCE` в `estimator.py:92`. По факту показанных аналогов в ±10% укладывается только две трети | | поправки §3 (−5…−8% за этаж и т.п.) | оставлены, но сноска честная: «ОРИЕНТИРЫ РЫНОЧНОЙ ПРАКТИКИ, А НЕ ЗАМЕР МЕРЫ» | | плитки −4,3% / ×2,4 / 83% | **заменены** на измеренные 7% / 38% / 62%. Плейсхолдеров marketing-v3 в статье не осталось (для справки: честные прокси к макетным плиткам — −1,1%/мес, ×1,04 и коридор шириной 47% от цены) | | «91% аналогов ближе 1 км» | **не опубликовано**: это свойство показанной десятки (`display_pool[:10]`, отсортированной по близости), а не поиска. Тавтология | | новая редакция оферты, ИНН 66700XXXXX, `mera.example` | не публикуются — макет сам помечал их как «замените на согласованный с юристом документ». Хаб только ведёт на существующие /oferta, /privacy, /refund от 13.08. Реквизиты в блоке «Контакты» — настоящие, из `LEGAL_ENTITY` | | «Отвечаем по будням с 9:00 до 19:00» | снято: регламента ответа никто не устанавливал, а на странице документов срок читается как обязательство | | фильтр рубрик, «новые статьи — каждую неделю» | не рендерятся: фильтровать нечего, расписания публикаций нет | ## Периметр и гейты Три списка сходятся: `@meraPages` / `@meraShortSlash` / `@meraLongPages` в `apps.caddy` ↔ `PUBLIC_ROUTES` ↔ `PUBLIC_SHORT_PATHS` в гварде. Полный прогон тестов сразу поймал забытый гвард — `RouteGuard.publicPaths` покраснел на `/articles` до того, как я успел это заметить сам. Два гейта, оба **фальсифицированы**, а не просто «зелёные»: * **новый** — `@meraShortSlash` до сих пор не проверялся ничем, хотя это третье место того же класса дефекта (адрес со слэшем мимо матчера уходит в 404). Проверка добавлена; снятие `/docs` из альтернации красит её. * **#2904** — `articles/articles-content.ts` внесён в `V3_SOURCES`. Проверено с ОДНИМ этим файлом в списке: снятие `noindex` красит гейт, то есть строка не декоративная. ## Проверено `tsc` · `eslint` · `vitest 69/69` · `check:mera-public-isolation` · скриншоты трёх страниц на 1180 / 375 / 320 px, горизонтального переполнения нет. ## Что осталось за решениями владельца 1. **Тексты двух оставшихся статей** — карточки стоят с рубриками и подводками из макета, помечены «СКОРО». 2. **Платёжный контур (#2896).** Тарифная таблица описывает порядок оплаты из оферты, но приёма платежей нет (`PUBLIC_ESTIMATE_ENABLED = false`, `payments` и `payment_entitlements` на проде пусты). Записано в докстринге `docs/page.tsx`: открывать страницу наружу можно только вместе с контуром либо сняв таблицу. 3. **«Продажа под ключ»** — строка тарифа «по договору» есть, пункт меню неактивен. Формы заявки нет, канал один — поддержка. 4. Мелкий долг, не в этом PR: `#9fb0b4` / `#2c3a3f` на тёмных плашках — сырой hex, но так написан весь файл (17+ мест), выносить в токены надо отдельным проходом.
bot-backend added 1 commit 2026-08-29 12:55:03 +00:00
feat(mera/b2c): раздел статей и хаб документов (макет 29.08) + числа статьи заменены на замер
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 10s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Successful in 58s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
2d8edd2c4f
Последняя часть макета Макса «B2C модуль для МЕРА»: /articles, /articles/kak-ocenit-kvartiru,
/docs. Проводка ссылок доведена до конца — «Статьи» и «Проверьте себя» в шапке и подвале
перестали быть заглушками, EstimateHeader переименован в InnerHeader (он теперь стоит на
трёх страницах, а не только на проверке).

ЧИСЛА СТАТЬИ — НЕ ИЗ МАКЕТА. Макет утверждал «по нашим данным, средний разрыв между
первой ценой в объявлении и ценой сделки — 4,1%, а у провисевших дольше трёх месяцев
доходит до 9%». Прод-замер (poincare, 29.08) показал, что величины такого рода у нас нет
вовсе: связки листинга со сделкой в данных не существует (cadastral_number пуст у всех
108 623 сделок и 111 693 объявлений). Заменено на то, что измеряется парно и честно:
по 6202 объявлениям Домклик в ЕКБ (срез 18.07.2026) цену снижали 44%, а среди провисевших
дольше трёх месяцев — 62% в медиане на 4,9%. Границы замера названы в самом тексте:
это движение цены В ОБЪЯВЛЕНИИ, а не скидка на сделке, и объявлений моложе трёх недель
в выборке нет (прогон обогащения их не захватил), поэтому по всему живому рынку доля ниже.

Заодно сняты остальные непроверяемые утверждения: «расхождение с кадастровой до 40%»
(кадастровой стоимости ПОМЕЩЕНИЙ нет ни в одной базе — проверить нечем), поправки §3
помечены как рыночная практика, а не наш замер, пороги фильтра §2 приведены к тем, что
реально стоят в оценщике (радиус 1 км, площадь ±15%, минимум 5 аналогов + каскад
послаблений). Плейсхолдеров marketing-v3 в статье не осталось.

Периметр закрыт во всех трёх местах: @meraPages / @meraShortSlash / @meraLongPages в
apps.caddy, PUBLIC_ROUTES и PUBLIC_SHORT_PATHS в гварде. @meraShortSlash до сих пор не
проверялся ничем — добавлен гейт в public-perimeter.test.ts (фальсифицирован: снятие
/docs из альтернации красит тест).

Гейт #2904 теперь видит и статью (articles-content.ts в V3_SOURCES) — фальсифицировано
отдельно: с одним этим файлом в списке снятие noindex красит гейт.

Честные отличия от макета — в докстрингах страниц: масок реквизитов и макетной редакции
оферты нет (источник правды — /oferta, /privacy, /refund от 13.08), регламент ответа
поддержки «9:00-19:00» снят (никто его не устанавливал), фильтр рубрик и обещание
«новые статьи каждую неделю» не рендерятся.

Проверено: tsc, eslint, vitest 69/69, изоляция mera-public, скриншоты трёх страниц
на 1180/375/320px без горизонтального переполнения.
bot-backend merged commit deddef80ad into main 2026-08-29 12:56:44 +00:00
bot-backend deleted branch feat/b2c-articles-docs 2026-08-29 12:56:44 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#3223
No description provided.