From 7e824ce6e4355b8a985a653c244f7625849bbd8c Mon Sep 17 00:00:00 2001 From: Light1YT Date: Sun, 28 Jun 2026 00:38:28 +0500 Subject: [PATCH] chore(frontend): regenerate api-types.ts for /concepts/recompute (#1965 Stage 2a) The new POST /api/v1/concepts/recompute endpoint + MassingProgram / MassingRecomputeOutput schemas changed the backend OpenAPI; the generated frontend/src/lib/api-types.ts was out of sync, failing the CI openapi-codegen-check gate. Regenerated via the exact CI sequence (openapi-typescript + prettier 3.9.0). Byte-stable on 2nd regen; tsc --noEmit clean. --- frontend/src/lib/api-types.ts | 147 ++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/frontend/src/lib/api-types.ts b/frontend/src/lib/api-types.ts index 8e505843..93bf0a79 100644 --- a/frontend/src/lib/api-types.ts +++ b/frontend/src/lib/api-types.ts @@ -34,6 +34,44 @@ export interface paths { patch?: never; trace?: never; }; + "/api/v1/concepts/recompute": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Recompute Massing + * @description Stage 2a (#1965, эпик #1953) — LIVE-пересчёт экономики из 3D-массинга. + * + * Hot, debounced-эндпоинт для интерактивных слайдеров Stage 2b: фронтовый + * ``computeModel`` отдаёт агрегированную программу (суммарное пятно × этажность), + * мы синтезируем :class:`TEAP` (``synthesize_teap_from_program`` — те же нормативные + * константы, что и обычная генерация) и прогоняем готовый чистый ``compute_financial`` + * → пересчитанный ТЭП + финмодель. + * + * Цена продажи жилья: + * * ``market_price_per_sqm`` в теле → используется как есть (FAST path, БЕЗ БД) — + * фронт резолвит цену один раз и шлёт её в каждом keystroke-запросе. Источник + * берём из ``payload.price_source`` (ПОДЛИННЫЙ source, который фронт получил из + * financial_estimate — objective_geo_radius / objective_district_median / + * district_reference / class_norm); если фронт его не прислал — дефолтный лейбл. + * НЕ хардкодим source — иначе honest-флаг в UI/PDF врёт о происхождении цены. + * * иначе, если передан ``parcel_centroid_wkt`` → ``_lookup_market_price`` по центроиду + * через ``run_in_threadpool`` (тот же приём, что и в ``create_concept``; sync SQLAlchemy + * не должен блокировать event loop). Падение lookup'а → норматив класса, не 500. + * * иначе (нет ни цены, ни центроида) → норматив класса (``price_source="class_norm"``). + */ + post: operations["recompute_massing_api_v1_concepts_recompute_post"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/api/v1/chat/ask": { parameters: { query?: never; @@ -4065,6 +4103,82 @@ export interface components { */ updated_at: string; }; + /** + * MassingProgram + * @description Stage 2a (#1965) — агрегированная массинг-программа для LIVE-пересчёта экономики. + * + * Контракт POST ``/api/v1/concepts/recompute``: вход — уже СВЁРНУТАЯ программа из + * фронтового ``computeModel`` интерактивного 3D-массинга (суммарное пятно × этажность), + * без покомпонентной геометрии секций. Эндпоинт синтезирует из неё :class:`TEAP` и + * прогоняет готовый ``compute_financial`` → пересчитанная экономика для дебаунс-слайдеров + * Stage 2b. + * + * Класс жилья / тип застройки — те же Literal-множества, что у :class:`ConceptInput` + * и ``compute_financial`` (single source of truth по допустимым значениям). + */ + MassingProgram: { + /** + * Total Footprint Sqm + * @description Суммарное пятно застройки всех секций, кв.м (скаляр) + */ + total_footprint_sqm: number; + /** + * Floors + * @description Этажность программы + */ + floors: number; + /** + * Sections + * @description Число секций (метаданные программы) + * @default 1 + */ + sections: number; + /** + * Site Area Sqm + * @description Площадь участка для плотности (FAR) + */ + site_area_sqm: number; + /** + * Housing Class + * @default comfort + * @enum {string} + */ + housing_class: "econom" | "comfort" | "business"; + /** + * Development Type + * @default mid_rise + * @enum {string} + */ + development_type: "spot" | "mid_rise" | "high_rise"; + /** + * Land Cost Rub + * @description Стоимость участка для финмодели (опционально) + */ + land_cost_rub?: number | null; + /** + * Market Price Per Sqm + * @description Предрезолвленная рыночная цена жилья, руб/кв.м (skip DB lookup) + */ + market_price_per_sqm?: number | null; + /** + * Price Source + * @description Подлинный источник предрезолвленной цены (forward из financial_estimate) + */ + price_source?: string | null; + /** + * Parcel Centroid Wkt + * @description WKT-точка центроида участка (WGS84) для DB-резолва цены при fallback + */ + parcel_centroid_wkt?: string | null; + }; + /** + * MassingRecomputeOutput + * @description Stage 2a (#1965) — результат LIVE-пересчёта: синтезированный ТЭП + финмодель. + */ + MassingRecomputeOutput: { + teap: components["schemas"]["TEAP"]; + financial: components["schemas"]["FinancialModel"]; + }; /** * ObjectiveConfigUpdateRequest * @description PATCH-style — обновляет только переданные поля. @@ -4911,6 +5025,39 @@ export interface operations { }; }; }; + recompute_massing_api_v1_concepts_recompute_post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["MassingProgram"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["MassingRecomputeOutput"]; + }; + }; + /** @description Validation Error */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; ask_api_v1_chat_ask_post: { parameters: { query?: never;