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)} га. +

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