fix(report): авторетрай §7 с densify — «не вместила ни одной секции» больше не 422 при загрузке (#2242)
All checks were successful
Deploy / build-frontend (push) Successful in 3m26s
Deploy / deploy (push) Successful in 1m29s
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped

This commit is contained in:
bot-backend 2026-07-03 00:31:25 +00:00
parent 1bba3db7eb
commit 4b6d1cbc06

View file

@ -212,6 +212,14 @@ export function Section7Concept({ analysis }: Props) {
// <details> 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<HTMLDetailsElement>) => {
if (e.currentTarget.open) setExpanded(true);