Commit graph

363 commits

Author SHA1 Message Date
6612c1cd2b feat(22begh): schema extension — flats+6 / objects+30 / developers+4 / metro_top3 (#306)
All checks were successful
Deploy / build-backend (push) Successful in 1m32s
Deploy / build-frontend (push) Has been skipped
Deploy / changes (push) Successful in 5s
Deploy / build-worker (push) Successful in 3m32s
Deploy / deploy (push) Successful in 56s
2026-05-17 15:26:59 +00:00
171a029997 feat(22i): domrf_kn_documents new table + parser (#305)
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Successful in 1m34s
Deploy / build-frontend (push) Has been skipped
Deploy / build-worker (push) Successful in 2m42s
Deploy / deploy (push) Successful in 59s
2026-05-17 15:21:31 +00:00
3183abe41b fix(22j): DEDUP domrf_kn_infrastructure + ON CONFLICT (issue #297) (#304)
All checks were successful
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Successful in 1m34s
Deploy / build-frontend (push) Has been skipped
Deploy / build-worker (push) Successful in 2m45s
Deploy / deploy (push) Successful in 1m4s
2026-05-17 15:15:03 +00:00
16e3d5c86d feat(22f): domrf_obj_checks table — 6 "Проверено на наш.дом.рф" checks (#303)
All checks were successful
Deploy / changes (push) Successful in 5s
Deploy / deploy (push) Successful in 46s
Deploy / build-backend (push) Successful in 32s
Deploy / build-frontend (push) Has been skipped
Deploy / build-worker (push) Successful in 30s
2026-05-17 15:07:24 +00:00
0b12a55eb6 fix(bug-22a): map missing kn-API fields (flat_number/living_area/wall_type/energy_eff) + backfill (#302)
All checks were successful
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Successful in 1m46s
Deploy / build-frontend (push) Has been skipped
Deploy / deploy (push) Successful in 58s
Deploy / build-worker (push) Successful in 2m50s
2026-05-17 14:59:02 +00:00
bfe16ae71b fix(sf-16): derive price_per_m2 from price_rub in _norm_flat + backfill SQL (#298)
All checks were successful
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Successful in 1m34s
Deploy / build-frontend (push) Has been skipped
Deploy / build-worker (push) Successful in 2m33s
Deploy / deploy (push) Successful in 58s
2026-05-17 14:32:23 +00:00
e054395464 Merge pull request 'fix(sf-15): extract obj_class from aiDescription (DOM.РФ list API never returns objClass)' (#293) from fix/sf-15-obj-class-scraping into main
All checks were successful
Deploy / build-frontend (push) Has been skipped
Deploy / changes (push) Successful in 9s
Deploy / build-backend (push) Successful in 1m29s
Deploy / build-worker (push) Successful in 2m24s
Deploy / deploy (push) Successful in 1m1s
2026-05-17 14:18:49 +00:00
a86cce79af refactor(sf-19): BestLayouts inline hex → Tailwind tokens (#296)
Some checks failed
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Has been cancelled
2026-05-17 14:17:05 +00:00
4b967343f8 fix(sf-13): MarketTab above-the-fold headline + 3 KPI cards (#294)
All checks were successful
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 2m53s
Deploy / deploy (push) Successful in 49s
2026-05-17 14:10:06 +00:00
33f44b59cb feat(sf-18): is_sales_started flag для domrf_kn_objects (#292)
Some checks failed
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Successful in 32s
Deploy / build-frontend (push) Has been skipped
Deploy / build-worker (push) Successful in 30s
Deploy / deploy (push) Has been cancelled
2026-05-17 14:09:21 +00:00
lekss361
440bba99cc fix(sf-15): rename migration 105 → 106 (collision with PR #292 sf-18) 2026-05-17 17:03:16 +03:00
9f5f887393 Merge pull request 'fix(sf-21): mv_layout_velocity weighted AVG (P0 data corruption)' (#290) from fix/sf-21-mv-weighted-avg into main
All checks were successful
Deploy / build-backend (push) Successful in 1m38s
Deploy / build-worker (push) Successful in 2m44s
Deploy / changes (push) Successful in 4s
Deploy / build-frontend (push) Has been skipped
Deploy / deploy (push) Successful in 1m3s
2026-05-17 14:02:46 +00:00
9f7224de33 Merge pull request 'fix(sf-21b): _INLINE_VELOCITY_SQL weighted AVG (P0 follow-up)' (#291) from fix/sf-21b-inline-velocity-weighted into main
Some checks failed
Deploy / build-backend (push) Blocked by required conditions
Deploy / build-worker (push) Blocked by required conditions
Deploy / build-frontend (push) Blocked by required conditions
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Has been cancelled
2026-05-17 14:02:43 +00:00
lekss361
3daf2a1fb1 fix(sf-15): extract obj_class from aiDescription (DOM.RF list API never returns objClass field)
Add _extract_obj_class_from_ai() with regex patterns for Комфорт/Бизнес/Премиум/Элит/Стандарт.
_norm_object() uses it as fallback; objClass from API still takes priority if ever returned.
Add backfill SQL 105 to retroactively populate existing rows from raw JSON payloads.
Coverage: ~1806/4548 rows will be filled; remainder NULL is expected (Нежилое/no AI desc).
2026-05-17 17:02:07 +03:00
lekss361
2104ed879b fix(sf-21b): weighted AVG in _INLINE_VELOCITY_SQL (best_layouts.py)
Replace unweighted AVG(deals_total_avg_area_m2) and AVG(deals_total_avg_price_thousand_rub_per_m2)
with SUM(x * count) / NULLIF(SUM(count), 0) pattern in _INLINE_VELOCITY_SQL.
Months with zero deals no longer dilute the weighted mean 2-4x.
P0 follow-up to PR #290 (mv fix, issue #21).
2026-05-17 16:56:22 +03:00
f0589bcdff Merge pull request 'fix(sf-17): rosreestr velocity fallback via cad_quarter (~100% EKB coverage)' (#289) from fix/sf-17-rosreestr-velocity-fallback into main
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Successful in 1m37s
Deploy / build-frontend (push) Successful in 3m8s
Deploy / deploy (push) Successful in 1m4s
Deploy / build-worker (push) Successful in 2m46s
2026-05-17 13:55:20 +00:00
lekss361
913cdcfcef fix(sf-21): mv_layout_velocity weighted AVG — P0 data corruption
AVG(deals_total_avg_area_m2) averaged pre-aggregated monthly values
including months with 0 deals (area=0, price=0), pulling results down
2-14x. Replace with SUM(x * count) / NULLIF(SUM(count), 0).

Verified on prod: obj 65307 room 4+ area 7.4->105.8 m2, price 7.9->112 k/m2.
Migration 100_ includes REFRESH — no manual step needed post-deploy.
2026-05-17 16:53:36 +03:00
lekss361
e1a8ad9395 fix(sf-17): rosreestr velocity fallback via cad_quarter (~100% EKB coverage)
When Objective mapping coverage falls below 50% of competitors in the radius,
fall back to rosreestr_deals JOIN on the parcel's cadastral quarter. Audit shows
237/237 EKB quarters (100%) have rosreestr data for the last 12 months, compared
to <20% Objective coverage before bulk mapping.

- velocity.py: add _compute_rosreestr_fallback(), _OBJECTIVE_COVERAGE_MIN_RATIO
  constant, velocity_source field on VelocityResult (objective/rosreestr_fallback/none)
- parcels.py: extract cad_quarter from cad_num, pass to compute_velocity
- site-finder.ts: add velocity_source field to Velocity interface
- VelocityBlock.tsx: badge "Источник: квартальные сделки" when rosreestr_fallback

Epic #271 item #17
2026-05-17 16:50:19 +03:00
9eed55cd30 Merge pull request 'fix(sf-20): adaptive district threshold 30→15 with data_confidence flag' (#288) from fix/sf-20-district-threshold-adaptive into main
All checks were successful
Deploy / changes (push) Successful in 4s
Deploy / build-backend (push) Successful in 1m49s
Deploy / deploy (push) Successful in 1m0s
Deploy / build-worker (push) Successful in 2m41s
Deploy / build-frontend (push) Successful in 3m9s
2026-05-17 13:39:52 +00:00
fcfc492ab5 Merge pull request 'feat: fuzzy matcher v2 — Objective mapping coverage 8.5%→20%' (#286) from feat/fuzzy-matcher-v2-coverage into main
Some checks failed
Deploy / build-frontend (push) Blocked by required conditions
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Successful in 5s
Deploy / build-worker (push) Has been cancelled
Deploy / build-backend (push) Has been cancelled
2026-05-17 13:39:28 +00:00
edb0a3e728 Merge pull request 'fix(sf-12): MarketTrend — adaptive n&lt;30/n&lt;100 confidence warnings' (#287) from fix/sf-12-trend-confidence-warning into main
Some checks failed
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Has been cancelled
2026-05-17 13:39:03 +00:00
lekss361
989d4e5b7d fix(sf-20): adaptive district threshold 30→15 with data_confidence flag
- v_bucket_success_score HAVING >= 30 → >= 15 so sparse districts
  (Кировский etc.) are no longer silently excluded from the block
- Backend: SUCCESS_REC_MIN_DEALS=15, SUCCESS_REC_STRONG_DEALS=30;
  data_confidence='weak' (15-29 deals) or 'strong' (≥30) in response
- TS type ParcelSuccessRecommendation: add data_confidence literal
- SuccessRecommendationBlock: amber badge for weak, all hex → CSS tokens,
  emoji star removed (ui-ux.md), empty-state text min 30→15
2026-05-17 16:34:52 +03:00
lekss361
1e1737e829 fix(sf-12): MarketTrend — adaptive n<30/n<100 confidence warnings
n<30: hide trend block, show 'insufficient data — expand radius'.
30≤n<100: show trend + amber banner 'weak data (n=X) — expand radius'.
n≥100: unchanged, no banner.
2026-05-17 16:33:22 +03:00
lekss361
2694e3180b feat(etl): fuzzy matcher v2 — pruned threshold 0.85→0.80 for objective mapping coverage
- Add AUTO_ACCEPT_THRESHOLD_V2 = 0.80 constant to objective_backfill.py
- Add min_threshold param to find_match_candidates() (default REVIEW_THRESHOLD=0.6)
- Add match_method param to auto_apply_matches() (default 'fuzzy_trgm')
- Add ?v2=true query param to POST /api/v1/admin/etl/objective-backfill
  - v2 mode: threshold=0.80, method='fuzzy_v2', search from 0.80 (not 0.60)
- Return type widened to dict[str,object] to include threshold_used + match_method_used

DB audit: 1068 unmapped EKB objs; v1 adds ~133 rows, v2 adds ~47 more.
Expected coverage: 8.5% → ~20% after sequential v1+v2 runs on prod.
Run: POST /objective-backfill (v1) then POST /objective-backfill?v2=true (v2).
Part of task #44 Part A, epic #271.
2026-05-17 16:28:20 +03:00
eb865a08bc Merge pull request 'fix(sf-11): Top layouts — sales period column + drill-in expand' (#285) from fix/sf-11-sales-period-drill-in into main
All checks were successful
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 4m20s
Deploy / deploy (push) Successful in 49s
2026-05-17 13:19:24 +00:00
lekss361
1959283a41 fix(sf-11): review-pass — DOM.РФ latin URL + Fragment key + a11y keyboard
Per review #285 (HIGH BLOCK):
- DOM.РФ URL: кириллический slug → latin path
  (/services/catalog-newbuildings/object/{id}) для stable behavior
- Replace <> Fragment без key → <Fragment key={signature}>
  (убирает React warning при .map). Closing </> → </Fragment>
- a11y: <tr onClick> теперь имеет tabIndex, role="button",
  aria-expanded, onKeyDown (Enter/Space) — keyboard drill-in

Inline hex tokens (medium) — отложено в follow-up (epic #271 #19).
2026-05-17 16:16:24 +03:00
lekss361
d3a51c3657 fix(sf-11): Top layouts — sales period column + drill-in expand
Add «Срок продажи (мес)» column (supply / velocity, colored by urgency)
and click-to-expand drill-in row showing competitor_obj_ids as DOM.РФ
linked badges. Both fields were already present in TopLayoutRow type.

Closes #271 item 11
2026-05-17 16:07:30 +03:00
e1300b1955 Merge pull request 'fix(sf-10): velocity LEFT JOIN + velocity_data_available flag' (#284) from fix/sf-10-velocity-left-join-v2 into main
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Successful in 1m37s
Deploy / build-worker (push) Successful in 2m46s
Deploy / build-frontend (push) Successful in 3m1s
Deploy / deploy (push) Successful in 59s
2026-05-17 13:00:19 +00:00
lekss361
b7ce4a589c fix(sf-10): velocity LEFT JOIN + velocity_data_available flag
Replace INNER JOIN on objective_complex_mapping with LEFT JOIN approach:
competitors without mapping now return velocity=0 with
velocity_data_available=False instead of being silently dropped.

UI: VelocityBlock shows 'нет данных velocity' badge when flag is False
and hides the gauge (meaningless zero). TS type updated (additive optional
field, backward compat).

Audit (EKB, region_cd=66): mapped=129, unmapped=1387, total=1516.

Closes #271 item #10
2026-05-17 15:51:43 +03:00
5ffee75c9f Merge pull request 'chore: refresh preview pages + add tradein landing' (#283) from chore/preview-pages-refresh into main
All checks were successful
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 2m50s
Deploy / deploy (push) Successful in 46s
Reviewed-on: #283
2026-05-17 12:38:16 +00:00
lekss361
6d9eddc8e9 chore: refresh preview pages + add tradein landing
Заменяем устаревшие preview-странички (старая landing.html из PR #279) на
новый набор из аудита gendsgn.ru:

- public/analytics.html (44KB)
- public/developers.html (37KB)
- public/index.html (30KB)
- public/landing.html (41KB, replaces PR #279 version)
- public/site-finder.html (31KB)
- public/site-finder-analysis.html (86KB)
- public/tradein.html (85KB) — новая страничка trade-in

Все 7 файлов self-contained HTML (inline assets) → доступны после deploy
по URL https://gendsgn.ru/<filename>.html. Не пересекаются с Next.js
routes (расширение .html — public/ wins).
2026-05-17 15:37:28 +03:00
3d4511ef00 Merge pull request 'fix(sf-09): MAX_BUCKET_SHARE 35% cap + frontend warning banner' (#282) from fix/sf-09-max-bucket-share into main
Some checks failed
Deploy / build-backend (push) Successful in 1m34s
Deploy / build-worker (push) Successful in 2m36s
Deploy / changes (push) Successful in 5s
Deploy / build-frontend (push) Successful in 2m59s
Deploy / deploy (push) Has been cancelled
2026-05-17 12:33:13 +00:00
lekss361
689327909c fix(sf-09): capacity-aware redistribute (round 2) — bounded + correct invariant
Round 1 (commit bcd7dc8) был broken: на 2-bucket входах surplus уходил в free
полностью без учёта capacity → free превышал cap → следующая итерация
clamp'ировала его и наоборот. Infinite oscillation в FastAPI handler.

Round 2 fix per review BLOCK (#282 comment):
- Surplus распределяется пропорционально available capacity (cap - v),
  не текущему v. Free никогда не вылетит выше cap.
- free = строго < cap (не <=) — иначе деление на 0 capacity.
- Hard guard `for _ in range(N+1)` — гарантированно завершается.
- Pathological (surplus > total_capacity): возвращаем оригинальный pct_map
  + cap_skipped=True (sum=100 invariant сохранён).
- Hamilton round вынесен в _hamilton_round() helper.

Tests:
- 2-bucket cases (90/10, 70/30, 99/1) expected cap_skipped=True
- test_cap_iteration_count_bounded — все pathological завершаются < 100ms
- All 13 cases verified standalone (3 fast-path + 7 reproduced + 3 pathological)
2026-05-17 15:30:50 +03:00
lekss361
bcd7dc8f75 fix(sf-09): iterative cap algorithm + cap_skipped flag + unit tests
Review verdict MINOR (PR #282) — single-pass cap_and_redistribute
не гарантировал invariant max ≤ MAX_BUCKET_SHARE_PCT. Surplus от clamped
поднимал free выше cap (например {1k:75, studio:15, 2k:10} → studio=39).

- backend/app/services/site_finder/best_layouts.py
  - _cap_and_redistribute → iterative while-loop до сходимости
  - Returns (result_map, cap_skipped) — флаг для pathological all-clamped
  - Float work map, Hamilton финальный pass для invariant sum=100
- backend/app/schemas/parcel.py
  - LayoutTzRecommendation.cap_skipped: bool = False
- backend/tests/services/site_finder/test_best_layouts.py
  - 6 parametrized tests: invariants, 7 failing cases from review,
    no-dominant unchanged, empty, cap_skipped propagation, normal-case
- frontend/src/types/best-layouts.ts — cap_skipped: boolean
- frontend/src/components/site-finder/BestLayoutsBlock.tsx
  - banner условие сменилось с maxPct > 60 на rec.cap_skipped (honest signal)
2026-05-17 15:21:51 +03:00
lekss361
0d11f426b2 fix(sf-09): MAX_BUCKET_SHARE 35% cap + frontend warning banner
_build_recommendation зеркалило рынок через чистый Hamilton apportionment.
Добавлен _cap_and_redistribute: bucket >35% clamp к 35%, surplus
пропорционально перераспределяется в остальные bucket'ы (Hamilton финальный
pass гарантирует sum=100). Pathological case (все bucket'ы >35%) — warning
в лог, cap пропускается. Frontend: warning banner при maxPct>60 в
RecommendationCard (Tailwind amber utilities, без inline hex).
2026-05-17 14:49:56 +03:00
d6a9824473 Merge pull request 'fix(sf-08): room_bucket euro-1/euro-2 classification' (#281) from fix/sf-08-room-bucket-euro into main
All checks were successful
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Successful in 1m35s
Deploy / build-frontend (push) Has been skipped
Deploy / build-worker (push) Successful in 2m35s
Deploy / deploy (push) Successful in 57s
2026-05-17 11:42:42 +00:00
lekss361
b9259cd8ed fix(sf-08): add euro-1/euro-2 room_bucket for small-format rooms=2 flats
DOM.РФ API classifies euro-format flats (26-50м²) as rooms=2.
_SUPPLY_BATCH_SQL now maps:
  rooms=2 + area<35 → 'euro-1'
  rooms=2 + area<50 → 'euro-2'
before the generic rooms IN (1,2,3) branch.

Audit: 4 140 units rooms=2 + area<35 in domrf_kn_flats were inflating
the supply count for genuine 2-room apartments (median 57м²).
euro buckets have no velocity counterpart in objective_corpus_room_month
so they are filtered out of top_layouts by min_velocity.

Also extends RoomBucket Literal and room_bucket_from_flat() in
layout_signature.py with the new euro-1/euro-2 values.

Closes #271 item 8
2026-05-17 14:38:48 +03:00
df2b47d27c Merge pull request 'fix(sf-07): median_12m alias + UI 12mo hint' (#280) from fix/sf-07-median-12m-alias into main
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Successful in 1m44s
Deploy / build-worker (push) Successful in 2m59s
Deploy / build-frontend (push) Successful in 2m57s
Deploy / deploy (push) Successful in 56s
2026-05-17 11:31:18 +00:00
lekss361
4d39ae5b5d fix(sf-07): use median_12m from mv_quarter_price_per_m2 for district price
ekb_districts.median_price_per_m2 was populated from a 24-month window.
LEFT JOIN mv_quarter_price_per_m2 on the cad quarter and COALESCE(median_12m,
fallback) so the API returns the 12-month median where available.
Frontend OverviewTab adds a "(12 мес)" hint next to the value.

Closes #271 item 7
2026-05-17 14:28:32 +03:00
28ca7bf6a8 Merge pull request 'chore: add landing.html static page' (#279) from chore/landing-html into main
All checks were successful
Deploy / build-frontend (push) Successful in 2m56s
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / deploy (push) Successful in 47s
2026-05-17 11:03:16 +00:00
lekss361
a3066733c2 chore: add landing.html static page
Marketing landing «gendsgn — аналитика спроса для девелоперов».
Self-contained HTML (50KB, inline assets) — будет доступен через
Next.js public/ serving по URL https://gendsgn.ru/landing.html
2026-05-17 13:59:23 +03:00
102ef88d56 Merge pull request 'fix(sf-03): CompetitorTable Status column + filter tabs' (#278) from fix/sf-03-competitor-table-status into main
All checks were successful
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 2m58s
Deploy / deploy (push) Successful in 48s
2026-05-17 10:50:27 +00:00
8d95bf0c5a Merge pull request 'fix(sf-04b): bulk seed mappings для всех ЖК (audit extension PR #273)' (#277) from fix/sf-04b-bulk-mapping-audit into main
All checks were successful
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Successful in 33s
Deploy / build-frontend (push) Has been skipped
Deploy / build-worker (push) Successful in 27s
Deploy / deploy (push) Successful in 46s
2026-05-17 10:43:09 +00:00
lekss361
98323027aa fix(sf-03): CompetitorTable Status column + filter tabs
Some checks failed
CI / backend (pull_request) Failing after 49s
CI / frontend (pull_request) Successful in 1m55s
После backend PR #276 (site_status в /analyze) — frontend показывает
статус строящиеся/сданные с цветным badge и фильтр-tabs наверху таблицы.

TS type extended manually (backward compat) — codegen подхватит после
backend deploy.

Closes (epic part) #271 item 3
2026-05-17 13:41:15 +03:00
lekss361
da1c619a9c fix(sf-04b): bulk seed mappings для всех ЖК с активностью в Objective
Audit 2026-05-17 (extension PR #273): 13 high-confidence (sim > 0.85)
auto-inserted, 25 medium-confidence (0.6-0.85) commented for manual review.
118 unmapped projects scanned via pg_trgm vs domrf_kn_objects EKB.

Closes (epic part) #271 item 4 extension
2026-05-17 13:36:34 +03:00
7a27cb857f Merge pull request 'fix(sf-02): добавить site_status/ready_dt в /analyze competitors + sort строящиеся first' (#276) from fix/sf-02-competitors-status-analyze into main
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Successful in 1m36s
Deploy / build-frontend (push) Has been skipped
Deploy / build-worker (push) Successful in 2m38s
Deploy / deploy (push) Successful in 53s
2026-05-17 10:35:46 +00:00
lekss361
1799e1fb30 fix(sf-02): добавить site_status/ready_dt в /analyze competitors + sort строящиеся first
SQL в /analyze не выбирал site_status, ready_dt из domrf_kn_objects;
ORDER BY flat_count DESC ставил сданные ЖК в топ.

Closes (epic part) #271 item 2
2026-05-17 13:29:59 +03:00
15e75c20dc Merge pull request 'fix(sf-01): time_window honest velocity — inline SQL с реальным фильтром report_month' (#275) from fix/sf-01-velocity-time-window into main
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Successful in 1m33s
Deploy / build-frontend (push) Has been skipped
Deploy / build-worker (push) Successful in 2m38s
Deploy / deploy (push) Successful in 55s
2026-05-17 09:24:57 +00:00
lekss361
c701636515 Merge forgejo/main into fix/sf-01-velocity-time-window
Resolve conflict in best_layouts.py: keep SF-01 inline velocity
(deals_window numerator) + add SF-05 sold_pct clamp at 100% and
is_oversold flag from main.
2026-05-17 12:15:40 +03:00
lekss361
5a4408e0ab fix(sf-01): time_window honest velocity — inline SQL с реальным фильтром report_month
Раньше _VELOCITY_DIVISORS делил агрегаты mv_layout_velocity (24 мес)
на 4/12 для quarter/year, не меняя реальное окно данных. Теперь
inline SQL из objective_corpus_room_month с CAST(:window_interval AS interval).

velocity_per_month = deals_window / months_in_window (1.0/3.0/12.0).
Разные time_window → разные строки из БД → разный mix/velocity/jk_count.

Closes (epic part) #271 item 1
2026-05-17 12:12:19 +03:00