fix(site-finder): §4.1 «Применить» действительно применяет веса POI (#2790) #2810
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#2810
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/2790-weights-apply"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
П.1 (видимая поломка). Постановка верна.
weightsв §4.1 был write-only: жил вSection31Settingsи читался только обратно в ту же панель. Прод-доказательство (Playwright, участок 66:41:0702017:131): двигаю Парки 1.8→3.0 и Трамвайные −0.5→−2.0, жму «Применить», жду 120 с — скор 18.91 до и 18.91 после, за всё время один POST /analyze и тот без тела.Веса подняты на страницу и уходят в запрос через
AnalyzeWeightsContext, а не пропом:useParcelAnalyzeQueryзовут шесть мест (§1, §2, §4, §5, страница, /ptica) на общем ключе кэша["parcel-analyze", cad, horizon]. Проп, забытый в одной секции, развёл бы ключи — половина страницы считала бы по одним весам, половина по другим, и дорогой (10-30 c) analyze ушёл бы дважды. Контекст держит всех потребителей одного ключа на одном значении по построению.Веса шлём inline, а не через
profile_id: тело запроса равно ползункам, ответ рапортуетsource="inline"— расхождению между показанным и посчитанным взяться неоткуда.После правки (тот же сценарий на собранном фронте против прод-бэкенда): 18.91 → 17.95, второй POST несёт
{"weights":{…,"park":3,…,"tram_stop":-2}}. Живой прод-запрос с теми же весами даёт ровно 17.95.П.2 (системные пресеты). Постановка верна, но требование «сначала бэкенд» снимается: пресет не обязательно адресовать через
profile_id. Теперьinclude_system=trueв списке, а «Применить» на пресете отдаётprofileId = null→ уходят inline-веса пресета. Тихому откату неоткуда взяться, бэкенд не тронут.Прод-проверка: дропдаун стал
По умолчанию · admin ★ · Эконом · пресет · Комфорт · пресет · Бизнес · пресет; выбор «Бизнес» → телоmetro_stop 2.5 / shop_mall 2.0 / park 2.0(совпадает с сидом100_user_weight_profiles_default_seed.sql) → скор 13.13,source="inline",profile_id=null.П.3.
useUpdateProfile/useDeleteProfileудалены. За три месяца в проде 1 профиль на всю базу (admin, создан 15.05.2026,updated_at = created_at) + 3 системных пресета: ни одного обновления, ни одной попытки удаления. Достраивать UI под нулевой спрос дороже, чем убрать мёртвый код; PUT/DELETE на бэкенде живы и покрыты тестами.Test plan
AnalysisPageContent.weights.test.tsx— рендерит настоящую страницу с настоящей §4.1 и настоящимuseParcelAnalyzeQuery, двигает ползунки, жмёт «Применить», проверяет тело второго POST /analyze. На коде до фикса красный:expected 2, received 1— второго запроса нет вовсе.npx vitest run— 271/271 (вuseParcelAnalyzeQuery.test.tsхук теперь зовётся черезrenderHook: он читает контекст, вне рендера у React нет dispatcher'а).npx tsc --noEmit, eslint, prettier — чисто.npm run build— проходит (контекст вsite-finder-api.tsне утекает в серверный граф).source="inline"; пресет «Бизнес» → 13.13.Refs #2790
weights_profile.source = "profile"ставится по факту параметра, а не по факту найденного профиля #2811weights_profile.source = "profile"ставится по факту параметра, а не по факту найденного профиля #2811