From 15db2b07c6906bf3f8cdd9bcad5a865dac267bae Mon Sep 17 00:00:00 2001 From: bot-backend Date: Fri, 3 Jul 2026 05:28:32 +0500 Subject: [PATCH] =?UTF-8?q?fix(report):=20=D0=B0=D0=B2=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D0=B5=D1=82=D1=80=D0=B0=D0=B9=20=C2=A77=20=D1=81=20densify=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=20=C2=AB=D0=BD=D0=B5=20=D0=B2=D0=BC=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=B8=D0=BB=D0=B0=20=D0=BD=D0=B8=20=D0=BE=D0=B4?= =?UTF-8?q?=D0=BD=D0=BE=D0=B9=20=D1=81=D0=B5=D0=BA=D1=86=D0=B8=D0=B8=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Автозапуск концепции (#2179) на узких/мелких участках отдавал 422 при загрузке отчёта: дефолтная программа (3 корпуса comfort 21×18) честно не влезает в геометрию (прод-кейс 66:41:0702033:20, найден browser-capture'ом реального payload — фронт шлёт валидный Polygon, extractPolygon ни при чём). Одноразовый авторетрай с densify=true (greedy max-FAR — движок сам вмещает, что физически влезает); ручные запуски не ретраятся, ошибка честно показывается если не влезло и так. --- .../site-finder/analysis/Section7Concept.tsx | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/frontend/src/components/site-finder/analysis/Section7Concept.tsx b/frontend/src/components/site-finder/analysis/Section7Concept.tsx index b80c5228..883cb004 100644 --- a/frontend/src/components/site-finder/analysis/Section7Concept.tsx +++ b/frontend/src/components/site-finder/analysis/Section7Concept.tsx @@ -212,6 +212,14 @@ export function Section7Concept({ analysis }: Props) { //
via the summary; onToggle keeps `expanded` in sync when reopened. const [expanded, setExpanded] = useState(true); + // Одноразовый авторетрай (fix 2026-07-03): на узких/мелких участках дефолтная + // программа (3 корпуса comfort 21×18) честно не влезает — движок отвечает 422 + // «программа застройки не вместила ни одной секции». Показывать это ошибкой + // при ЗАГРУЗКЕ отчёта нельзя (прод-кейс 66:41:0702033:20) — пробуем один раз + // densify=true: greedy-раскладка сама вмещает, что физически влезает. + // Не влезло и так → честная ошибка остаётся. Ручные запуски не ретраятся. + const autoRetriedRef = useRef(false); + useEffect(() => { if (autoRanRef.current || !expanded) return; if (!polygon || catalog.length === 0) return; @@ -233,6 +241,27 @@ export function Section7Concept({ analysis }: Props) { }); }, [expanded, polygon, catalog, concept, seeded, handleGenerate]); + useEffect(() => { + if (!autoRanRef.current || autoRetriedRef.current) return; + if (!concept.isError || !polygon || catalog.length === 0) return; + if (!/не вместила/i.test(concept.error.message)) return; + const def = pickDefaultType(catalog); + if (!def) return; + autoRetriedRef.current = true; + handleGenerate({ + corpuses: CORPUSES_DEFAULT, + floors: def.default_floors > 0 ? def.default_floors : FLOORS_FALLBACK, + floor_height_m: 3.0, + section_type: def.section_type, + footprint_w_m: def.footprint_w_m, + footprint_d_m: def.footprint_d_m, + housing_class: seeded.housing_class, + development_type: seeded.development_type, + land_cost_rub: seeded.land_cost_rub, + densify: true, // greedy max-FAR: вместить, что физически влезает + }); + }, [concept, polygon, catalog, seeded, handleGenerate]); + const handleToggle = useCallback( (e: React.SyntheticEvent) => { if (e.currentTarget.open) setExpanded(true); -- 2.45.3