1. Группы НПА (фазы B–D)
— Admin backend: модель NpaGroup, NpaGroupController с CRUD, NpaGroupRepository, NpaGroupSeeder (7 узлов), фильтрация документов по groupId с recursive, защита от удаления непустых групп и циклов parentId=self
— Admin frontend: UI групп НПА (фаза C, v2.3.42)
— User backend: группы НПА в user-app (фаза D, v2.3.53)
— User frontend: дерево групп НПА в модале документов (v2.3.53)
— Файлы: NpaGroup.java, NpaGroupController.java, NpaController.java, NpaGroupSeeder.java
— Метрики: +261/-11 только по admin backend (NPA-часть)
2. Импортёр сборников ГЭСН с fgiscs.minstroyrf.ru (фаза E)
— Python-скрипт scripts/fgiscs_import_gesn.py (240 строк) на stdlib (без requests), multipart собран вручную
— Идемпотентность через сравнение по name, флаги —dry-run и —only-category
— Прогнан на TEST: 2 файла загружены, повтор показал 0 загружено / 2 пропущено
— Метрики: +240 строк одним коммитом
3. Phase 27 — методики сборников ФСНБ для агента
— Admin backend: модель методик, brief-эндпоинт через agent-сервис, AgentBriefClient под фактический контракт agent (v2.3.26–2.3.28)
— User backend: выдача методик сборников агенту (v2.3.54)
— Admin frontend: UI методик для агента (v2.3.43)
— 4 коммита, 3 проекта
4. Phase 28 — fsnb_mapping и трассировка ВОР↔ФСНБ
— Backend: JSONB-колонка vor_rabota.fsnb_mapping, endpoint состава работ ФСНБ по коду (phase28.2)
— Frontend: VorMappingCell, popover «Состав работ» через Teleport с position:fixed и авто-флипом, edIzm всегда, удалена legacy textarea fsnbKody
— Phase 26 (стартовое для трассировки): колонка vor_rabota.fsnb_kody, фронт-колонка «Учтено в смете (ФСНБ)»
— Файлы: VorMappingCell.vue, popover-компоненты, миграции БД
5. Phase 30 — переключение LLM провайдера и модели
— Admin backend: прокси /api/admin/llm-providers с валидацией model (v2.3.29)
— Admin frontend: UI переключения провайдера/модели (v2.3.44)
— 2 коммита, оба проекта
6. Phase 35 — VOR grid с дочерними строками ФСНБ + popup карточки
— Новый компонент VorRabotaWithMappings.vue (151 строка) с 3-колоночным child row для дочерних расценок
— VorFsnbCard.vue в стиле WorkPicker (143 строки), popup карточки расценок
— Переписан VorView.vue (+115/-65)
— Бэкенд не менялся — переиспользованы GET /api/catalog/rabota/{id} и /api/catalog/search
— Метрики: +346/-65 в одном коммите
7. Phase 36–37 — фильтры агента и точечное обновление ВОР
— Backend: фильтры sbornikTip и razdelKod в /api/agent/fsnb/search, endpoints дерева ФСНБ для алгоритма агента (phase34), единый формат razdel.kod, GET /api/vor/rabota/{id}
— Frontend: точечное обновление ВОР по entity_updated через SSE, видимый блок SSE-ошибок и Retry в чате (phase31)
8. UI-доводка VOR и MaterialPicker
— MaterialPicker с input количества + warning по ed_izm (v2.3.70)
— ID ВОР в шапке (моноспейс + клик-копировать)
— Заголовки разделов ВОР с акцентным градиентом, работа ВОР с бежевым фоном-карточкой, ФСНБ-строки светло-серый фон + перенос длинных названий, клик по коду ФСНБ открывает карточку (убрана иконка ⓘ)
— ~7 коммитов стилевых правок
9. Мелкие фиксы инфраструктуры
— ON DELETE CASCADE для smeta_vm_selection (phase33)
— Spring перестаёт писать в agent_usage (phase29)
— Токен берётся из localStorage smeta_user_token вместо smeta_token
— Автоподбор ВМ предпочитает ресурс с совпадающей ed_izm
— VmSelectRequest.userQuantity опциональный + апдейт user_quantity в selectVmResurs
Сводная статистика по коду:
Проект | Добавлено строк | Удалено строк | Коммитов
smeta_admin_backend | 1278 | 59 | 6
smeta_admin_frontend | 567 | 83 | 3
smeta-user-backend | 826 | 122 | 13
smeta_user_frontend | 1341 | 367 | 18
Итого | 4012 | 631 | 40
Оценка трудозатрат:
Задача | ~Часы
Группы НПА (фазы B–D, 4 проекта) | 6
Импортёр ГЭСН fgiscs.minstroyrf.ru | 4
Phase 27 методики сборников ФСНБ для агента | 6
Phase 28 fsnb_mapping + VorMappingCell + popover | 6
Phase 30 переключение LLM провайдера/модели | 3
Phase 35 VOR grid с дочерними строками + popup карточки | 5
Phase 36–37 фильтры агента + точечное обновление ВОР | 3
UI-доводка VOR + MaterialPicker | 5
Мелкие фиксы (CASCADE, agent_usage, token, ed_izm) | 2
Итого | ~40 час