From f448b550b545640c0a25dfb8522ebf991ae734a6 Mon Sep 17 00:00:00 2001 From: bot-backend Date: Mon, 29 Jun 2026 12:24:21 +0000 Subject: [PATCH] =?UTF-8?q?feat(site-finder):=20=C2=A77=20=C2=AB=D0=9A?= =?UTF-8?q?=D0=BE=D0=BD=D1=86=D0=B5=D0=BF=D1=86=D0=B8=D1=8F=C2=BB=20?= =?UTF-8?q?=E2=80=94=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=B8=D0=BA=D0=B8=20?= =?UTF-8?q?+=20=D1=81=D0=B8=D0=BD=D1=85=D1=80=D0=BE=D0=BD=D0=B8=D0=B7?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D1=8F=20=D0=BF=D0=BE=D0=B4=D0=BF=D0=B8=D1=81?= =?UTF-8?q?=D0=B5=D0=B9=20(#1953,=20batch=20D)=20(#2098)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../site-finder/analysis/MassingEconomics.tsx | 60 +++++++++++++++++- .../site-finder/analysis/Section7Concept.tsx | 63 +++++++++++++------ 2 files changed, 102 insertions(+), 21 deletions(-) diff --git a/frontend/src/components/site-finder/analysis/MassingEconomics.tsx b/frontend/src/components/site-finder/analysis/MassingEconomics.tsx index 59fb7687..272c6239 100644 --- a/frontend/src/components/site-finder/analysis/MassingEconomics.tsx +++ b/frontend/src/components/site-finder/analysis/MassingEconomics.tsx @@ -114,16 +114,19 @@ function KpiGrid({ label="Общая площадь (GFA)" value={formatInt(teap.total_floor_area_sqm)} unit="м²" + hint="Поэтажная площадь всех корпусов = пятно застройки × этажность." /> @@ -149,10 +153,12 @@ function KpiGrid({ @@ -253,9 +266,20 @@ interface Props { farTarget: number; /** True when факт-КСИТ exceeds the cap (model.over, computed scene-side). */ ksitOver: boolean; + /** + * True when the parcel is regulatorily constrained for МКД (gate-blocked / + * non-residential / ЗОУИТ-СЗЗ) — drives the honest «условный расчёт» caveat + * below the strip alongside the negative-economics case. + */ + gateConstrained?: boolean; } -export function MassingEconomics({ program, farTarget, ksitOver }: Props) { +export function MassingEconomics({ + program, + farTarget, + ksitOver, + gateConstrained = false, +}: Props) { const recompute = useRecomputeMassing(); // Last successful result kept locally so a failed/stale recompute never blanks @@ -316,6 +340,13 @@ export function MassingEconomics({ program, farTarget, ksitOver }: Props) { // A fresher request is in flight over the last-good values. const stale = recompute.isPending; + // Honest «условный расчёт» caveat: when the economics turn negative OR the + // parcel is regulatorily constrained (gate-blocked / ЗОУИТ-СЗЗ / нежилое), + // we say so plainly rather than presenting the figures as a viable project. + const economicsNegative = + result.financial.net_profit_rub < 0 || result.financial.npv_rub < 0; + const showConditionalNote = economicsNegative || gateConstrained; + return (
+ {showConditionalNote ? ( +

+

+ ) : null} + {errored ? (

{/* Collapsed by default (above-the-fold rule) — form + button inside; @@ -358,7 +369,7 @@ export function Section7Concept({ analysis }: Props) { >

@@ -397,9 +409,20 @@ export function Section7Concept({ analysis }: Props) { color: "var(--fg-primary)", }} > - Кадастровый номер {analysis.cad_num} · площадь ≈{" "} - {ha(parcelAreaSqm)} га. + Кадастровый номер {analysis.cad_num} · площадь пятна по + геометрии ≈ {ha(parcelAreaSqm)} га. +

+ Массинг и КСИТ считаются от площади застраиваемого пятна по + геометрии участка (контур НСПД), поэтому она может + отличаться от площади по ЕГРН в карточке участка. +