fix(tradein/pdf): scale offer-page rent by room count (LOW audit R2 #5) (#2506)
Some checks failed
Deploy Trade-In / test (push) Blocked by required conditions
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / build-frontend (push) Blocked by required conditions
Deploy Trade-In / build-browser (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Has been cancelled
Some checks failed
Deploy Trade-In / test (push) Blocked by required conditions
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / build-frontend (push) Blocked by required conditions
Deploy Trade-In / build-browser (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Has been cancelled
This commit is contained in:
parent
7fa52bb3ad
commit
92371e7d9e
2 changed files with 63 additions and 5 deletions
|
|
@ -1600,7 +1600,7 @@ def _build_deals_page(estimate: AggregatedEstimate, input_snapshot: dict, brand)
|
|||
# ── Page 4: Offer (Trade-In vs Самопродажа) ──────────────────────────────────
|
||||
|
||||
|
||||
def _build_offer_page(estimate: AggregatedEstimate, brand) -> str: # type: ignore[no-untyped-def]
|
||||
def _build_offer_page(estimate: AggregatedEstimate, input_snapshot: dict, brand) -> str: # type: ignore[no-untyped-def,type-arg]
|
||||
median = estimate.median_price_rub
|
||||
|
||||
# Расчёт расходов: часть — на основе медианы (торг «от цены в объявлении»),
|
||||
|
|
@ -1627,8 +1627,24 @@ def _build_offer_page(estimate: AggregatedEstimate, brand) -> str: # type: igno
|
|||
rieltor_low = int(sold_price * rieltor_pct_low / 100)
|
||||
rieltor_high = int(sold_price * rieltor_pct_high / 100)
|
||||
|
||||
# 3 месяца аренды 1-комнатной квартиры, ЕКБ 2026: ~28-45 тыс. руб./мес.
|
||||
rent_low, rent_high = 84_000, 135_000
|
||||
# 3 месяца аренды квартиры, ЕКБ 2026 (базовая ставка — студия/1-комн., ~28-45
|
||||
# тыс. руб./мес.), масштабируется по числу комнат объекта (#pdf-honesty: раньше
|
||||
# был плоский 1-комнатный тариф для ЛЮБОГО объекта, включая 3-4-комнатные).
|
||||
# Ориентировочные месячные ставки аренды по комнатности, ЕКБ 2026:
|
||||
# студия/1к ~28-45k, 2к ~40-60k, 3к ~55-80k, 4к+ ~75-110k.
|
||||
# Множители — грубое отношение верхних границ этих диапазонов к базовой (1к).
|
||||
rooms = int(input_snapshot.get("rooms", 0) or 0)
|
||||
if rooms <= 1:
|
||||
rent_multiplier = 1.0
|
||||
elif rooms == 2:
|
||||
rent_multiplier = 1.35
|
||||
elif rooms == 3:
|
||||
rent_multiplier = 1.8
|
||||
else:
|
||||
rent_multiplier = 2.4
|
||||
rent_base_low, rent_base_high = 84_000, 135_000
|
||||
rent_low = round(rent_base_low * rent_multiplier / 1000) * 1000
|
||||
rent_high = round(rent_base_high * rent_multiplier / 1000) * 1000
|
||||
# Юридическое сопровождение сделки — диапазон (не фикс), варьируется по объёму работ.
|
||||
juridical_low, juridical_high = 15_000, 50_000
|
||||
# Реклама/продвижение за 3 месяца — низкая уверенность в оценке (нет единого
|
||||
|
|
@ -1709,7 +1725,8 @@ def _build_offer_page(estimate: AggregatedEstimate, brand) -> str: # type: igno
|
|||
<tr style="border-bottom:1px solid {_BORDER};">
|
||||
<td style="padding:6pt 4pt;">
|
||||
<div class="bold">Аренда после сделки</div>
|
||||
<div style="font-size:{_FS_XS};color:{_MUTED};">однокомнатной квартиры на 3 месяца</div>
|
||||
<div style="font-size:{_FS_XS};color:{_MUTED};">
|
||||
{f"{rooms}-комн. квартиры на 3 месяца" if rooms > 0 else "квартиры на 3 месяца"}</div>
|
||||
</td>
|
||||
<td style="padding:6pt 4pt;text-align:right;color:{_SUCCESS};font-weight:700;">
|
||||
бесплатно</td>
|
||||
|
|
@ -2190,7 +2207,7 @@ def generate_trade_in_pdf(
|
|||
_build_cover(estimate, input_snapshot, brand)
|
||||
+ _build_listings_page(estimate, input_snapshot, brand)
|
||||
+ _build_deals_page(estimate, input_snapshot, brand)
|
||||
+ _build_offer_page(estimate, brand)
|
||||
+ _build_offer_page(estimate, input_snapshot, brand)
|
||||
)
|
||||
|
||||
html_str = (
|
||||
|
|
|
|||
|
|
@ -349,3 +349,44 @@ def test_deals_banner_neutral_when_no_discount() -> None:
|
|||
_assert_well_formed(html)
|
||||
assert "10–18%" not in html
|
||||
assert "продаются дешевле, чем заявлено" in html
|
||||
|
||||
|
||||
# ── _build_offer_page — rent scales with room count, not a flat 1-room figure ──
|
||||
# (#pdf-honesty LOW audit R2 #5: «Общие финансовые потери» hardcoded a 1-room
|
||||
# 3-month rent for EVERY object, including 3-4-room ones.)
|
||||
|
||||
|
||||
def test_offer_page_rent_scales_up_for_larger_objects() -> None:
|
||||
est = _estimate()
|
||||
snapshot_1room = {**_SNAPSHOT, "rooms": 1}
|
||||
snapshot_3room = {**_SNAPSHOT, "rooms": 3}
|
||||
|
||||
html_1room = mod._build_offer_page(est, snapshot_1room, _BRAND)
|
||||
html_3room = mod._build_offer_page(est, snapshot_3room, _BRAND)
|
||||
_assert_well_formed(html_1room)
|
||||
_assert_well_formed(html_3room)
|
||||
|
||||
# Base (1-room) rent range unchanged: 84 000 – 135 000.
|
||||
assert mod._fmt_rub(84_000) in html_1room
|
||||
assert mod._fmt_rub(135_000) in html_1room
|
||||
# 3-room rent scaled up (×1.8 heuristic): 151 000 – 243 000.
|
||||
assert mod._fmt_rub(151_000) in html_3room
|
||||
assert mod._fmt_rub(243_000) in html_3room
|
||||
# The flat 1-room figure must NOT leak into the 3-room object's report.
|
||||
assert mod._fmt_rub(135_000) not in html_3room
|
||||
|
||||
|
||||
def test_offer_page_rent_subtitle_reflects_room_count() -> None:
|
||||
est = _estimate()
|
||||
|
||||
html_1room = mod._build_offer_page(est, {**_SNAPSHOT, "rooms": 1}, _BRAND)
|
||||
assert "1-комн. квартиры на 3 месяца" in html_1room
|
||||
assert "однокомнатной квартиры на 3 месяца" not in html_1room
|
||||
|
||||
html_3room = mod._build_offer_page(est, {**_SNAPSHOT, "rooms": 3}, _BRAND)
|
||||
assert "3-комн. квартиры на 3 месяца" in html_3room
|
||||
|
||||
# Unknown room count (0/missing) → neutral subtitle, no fabricated room number.
|
||||
html_unknown = mod._build_offer_page(est, {**_SNAPSHOT, "rooms": 0}, _BRAND)
|
||||
assert "квартиры на 3 месяца" in html_unknown
|
||||
assert "-комн. квартиры на 3 месяца" not in html_unknown
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue