bed230f045
Project picker, section cards and the period Excel export now live on the app's home page. The selected project is shared app state, so the sidebar hides sections with the same rules main used to disable its cards (archived, finished, no edit0 right). Queries are 1:1 with stroy-bot-main and covered by tests against a fake HTTP client. Behaviour differences are listed in the migration checklist. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
221 lines
21 KiB
Markdown
221 lines
21 KiB
Markdown
# Чек-лист миграции StroyBot → монорепо
|
||
|
||
Каждый раздел считается перенесённым только когда все пункты проверены в workbench.
|
||
Пишущие операции (создание / правка / удаление / импорт) проверяем **только на тестовом проекте «ТЕСТ StroyBot»**.
|
||
|
||
Правила переноса:
|
||
- Запросы, поля, фильтры, права и тексты переносятся **1:1** из исходного репозитория.
|
||
- Известные баги переносятся как есть (помечены 🐞) — исправляем позже отдельными коммитами.
|
||
- Старые страницы и web parts не трогаем, поддержка старых URL не нужна.
|
||
|
||
Легенда: `[ ]` — не проверено, `[x]` — проверено в workbench.
|
||
|
||
---
|
||
|
||
## 0. Общее (оболочка)
|
||
|
||
- [ ] Одна web part, разделы переключаются через `?page=…`, проект — через `?projectId=…`
|
||
- [ ] Кнопки «назад/вперёд» браузера переключают разделы
|
||
- [ ] Ссылку на любой раздел можно скопировать и открыть в новой вкладке
|
||
- [ ] Выбранный проект сохраняется между перезагрузками (`sessionStorage`, ключ `stroybot_selected_project`)
|
||
- [ ] Шрифты Inter и Lora подгружаются (раньше грузили report-list и assigner)
|
||
- [ ] `webApiPermissionRequests` в одном пакете: `api.tnsu.kz` (`9232d9e2-…`, `Reports.Read` и `user_impersonation`) + Dataverse `https://tansu.crm5.dynamics.com` (`user_impersonation`)
|
||
|
||
**Сознательные изменения (не функционал, а настройка):**
|
||
- Настройки property pane из 8 web parts сведены в одну группу «Подключение». Имена списков больше не настраиваются в property pane — они в константах.
|
||
- `worksPageUrl` (objects → works) больше не нужен: переход внутри приложения.
|
||
|
||
---
|
||
|
||
## 1. Главная (stroy-bot-main)
|
||
|
||
### Выбор проекта
|
||
- [ ] Поле «Проект:», плейсхолдер «Выберите проект», иконка поиска
|
||
- [ ] Список грузится при первом фокусе, «Загрузка проектов…»
|
||
- [ ] При фокусе текст выделяется
|
||
- [ ] Фильтр по Title (без учёта регистра, подстрока), максимум **7** результатов
|
||
- [ ] У каждого — бейдж статуса, «Без статуса» если пусто
|
||
- [ ] Сообщения: «Нет доступных проектов», «Проекты не найдены», «Ошибка загрузки. Попробуйте ещё раз.»
|
||
- [ ] Клик вне / Esc — закрыть и вернуть выбранное название (или очистить)
|
||
- [ ] Бейдж статуса рядом с полем: текущий — зелёный, завершен/завершён — серый, архивный — золотой, иначе — нейтральный
|
||
- [ ] Сортировка по алфавиту, затем до 7 недавно активных (из Dataverse `cree9_reports`) — наверх
|
||
- [ ] Права из «Доступы»: `read | edit0 | aproove`, `canEdit` = OR по `edit0`
|
||
- [ ] Подсказка «Выберите проект, чтобы активировать ссылки ниже»
|
||
|
||
### Разделы проекта
|
||
- [ ] Объекты / «Объекты по проекту»
|
||
- [ ] Отчёты по проекту / «Просмотр отчётности»
|
||
- [ ] Отправить отчёт / «Отправка отчёта по проекту»
|
||
- [ ] Загрузить работы из сметы / «Импорт работ в систему»
|
||
- [ ] Архив проекта / «Библиотека документов» → `{SITE}/Shared Documents/Архив/{Title}` (внешняя ссылка, новая вкладка)
|
||
- [ ] Ресурсы проекта / «Профессии и компании»
|
||
- [ ] Без выбранного проекта карточки неактивны
|
||
- [ ] Статус «архивный» — неактивно всё, кроме Архива; экспорт тоже неактивен
|
||
- [ ] Статус «завершен/завершён» — неактивно «Отправить отчёт»
|
||
- [ ] `canEdit = false` — неактивно «Отправить отчёт»
|
||
|
||
### Экспорт данных «Выгрузить за период»
|
||
- [ ] Кнопка «?» — поповер с 3 строками (день / Пн–Вс / произвольный), закрытие по клику мимо
|
||
- [ ] Поля «Начало» и «Конец» видны только при выбранном проекте
|
||
- [ ] «Укажите период для активации ссылки», пока даты не заданы
|
||
- [ ] Ошибка «Дата начала не может быть позже даты конца», кнопка неактивна
|
||
- [ ] Бейдж: «Ежедневный отчёт» (`daily`) / «Еженедельный отчёт» (Пн–Вс, `weekly`) / «Отчёт за период» (`period`)
|
||
- [ ] «Выгрузить» → спиннер «Формируется…» → файл `{prefix}_{from}_{to}.xlsx`
|
||
- [ ] Запрос `GET https://api.tnsu.kz/Report/StroyBot?start=…&end=…&projectId=…` (unix UTC 00:00:00 / 23:59:59)
|
||
- [ ] Ошибки: «Ошибка API: {status} {statusText}» / «Ошибка при загрузке отчёта»
|
||
|
||
**Сознательные отличия от main:**
|
||
- Лишний запрос к «Доступы» без фильтра по пользователю (его результат не использовался) — убран, на поведение не влияет.
|
||
- Список проектов грузится сразу при открытии, а не при первом фокусе: от статуса и прав проекта теперь зависит и меню слева.
|
||
- Карточки разделов открывают раздел в этой же вкладке; новая вкладка — Ctrl+клик или средняя кнопка (раньше всегда `_blank`). Архив — по-прежнему в новой вкладке.
|
||
- Ошибки выгрузки показываются под кнопкой, а не через `alert()`. Тексты те же.
|
||
- Поповер «?» всегда открывается вниз (раньше переворачивался вверх у края экрана).
|
||
- Адрес выгрузки берётся из настройки «Базовый URL API» (по умолчанию тот же `https://api.tnsu.kz`).
|
||
- Меню слева скрывает разделы по правилам карточек: архивный — только «Проект»; завершён или нет `edit0` — без «Отправить отчёт»; «Привязка к справочнику» — только с `edit0`.
|
||
|
||
---
|
||
|
||
## 2. Объекты (stroy-bot-objects) — `?page=objects&projectId=`
|
||
|
||
- [ ] Шапка «Объекты проекта» + название проекта («Загрузка...» / «Ошибка»)
|
||
- [ ] «Добавить объект» (только `canEdit`), «Экспорт» → «Экспортируется...» → `objects-{projectId}.xlsx` (`GET https://api.tnsu.kz/Report/ProjectObjects?projectId=`)
|
||
- [ ] Без projectId — «Вы не выбрали проект»; «Проект с ID={id} не найден»; «Ошибка: …»
|
||
- [ ] Пусто — «Объекты не найдены» + «+ Добавить объект» (если `canEdit`)
|
||
- [ ] Тулбар «{N} объектов» (рекурсивно), «Развернуть», «Свернуть»
|
||
- [ ] Дерево: отступ, иконка папки/файла, счётчик детей, шеврон, клик по строке — выделить + раскрыть
|
||
- [ ] Раскрытые узлы сохраняются между перезагрузками в рамках сессии
|
||
- [ ] Уровни: 0 — Объект-пятно, 1 — Раздел, 2 — Вид работ (не глубже 3 уровней)
|
||
- [ ] Контекстное меню (⋮ и правый клик, только `canEdit`): Добавить объект (не на уровне 2), Редактировать, Работы, Удалить
|
||
- [ ] Модалка: «Название *» (обязательно, Enter — сохранить), «Родительский объект» (select только при правке Раздела: узлы уровня 0, сортировка ru, без себя и потомков), «Проект» (read-only)
|
||
- [ ] Заголовки модалки: «Добавить Объект-пятно / Раздел / Вид работ», «Редактировать …», «— (корневой)»
|
||
- [ ] Удаление: подтверждение с числом дочерних, «Это действие нельзя отменить.»
|
||
- [ ] Drag & drop (только `canEdit`): до / внутрь / после, запрет на себя и потомков, ошибка «Не удалось переместить: …»
|
||
- [ ] «Работы» → раздел Работы с `objectId`
|
||
- [ ] После любой операции дерево перезагружается
|
||
- [ ] Список «Объекты»: `Title`, `project` (текст = название проекта), `parent` (self-lookup)
|
||
- [ ] Права: «Доступы» `projectId`/`userId` → `edit0`
|
||
|
||
🐞 Перетаскивание меняет только родителя, порядок не сохраняется. 🐞 Удаление узла не удаляет детей.
|
||
|
||
---
|
||
|
||
## 3. Работы (stroy-bot-works) — `?page=works&projectId=&objectId=`
|
||
|
||
- [ ] Шапка с названием проекта
|
||
- [ ] «Добавить работу» (только `canEdit`)
|
||
- [ ] Таблица-дерево: #, Наименование, Ед. изм., Проектный объём (ru-RU, 3 знака), Дата (`dd.mm.yy`, «start – finish» / одна / «—»)
|
||
- [ ] Родители свёрнуты по умолчанию, шеврон «Свернуть/Развернуть», нумерация по видимым строкам
|
||
- [ ] «Загрузка данных...», «Работы не найдены» (+ кнопка), ошибки Dataverse
|
||
- [ ] Меню строки ⋮ (`canEdit`): Добавить дочернюю, Редактировать, Удалить
|
||
- [ ] Модалка: НАИМЕНОВАНИЕ *, ЕД. ИЗМ. (список «Единицы измерения», с пагинацией; текущее значение не из списка — добавить наверх), ПРОЕКТНЫЙ ОБЪЁМ (шаг 0.001), РОДИТЕЛЬСКАЯ РАБОТА (без себя и потомков), ОБЪЕКТ (read-only), ДАТА НАЧАЛА / ОКОНЧАНИЯ
|
||
- [ ] «Сохранить и добавить еще» (в режиме добавления: модалка остаётся, родитель сохраняется)
|
||
- [ ] Подтверждение удаления «Подтвердите удаление»
|
||
- [ ] Dataverse `cree9_tables`, фильтр `cree9_objectid eq '{objectId}'`; без objectId — все работы
|
||
- [ ] Навигационное свойство родителя определяется через `EntityDefinitions` (fallback `cree9_parentid`)
|
||
- [ ] Проект находится подъёмом по родителям объекта до непустого `project`
|
||
|
||
🐞 Путь объекта (`#headerTitle`) не выводится. 🐞 Нет проверки «начало ≤ окончание».
|
||
|
||
---
|
||
|
||
## 4. Отчёты по проекту (stroy-bot-report-list) — `?page=reports&projectId=`
|
||
|
||
- [ ] Заголовок — название проекта
|
||
- [ ] Нет доступа — «Нет доступа» / «У вас нет прав на просмотр отчётов данного проекта.»
|
||
- [ ] Период по умолчанию — текущая неделя Пн–Вс; «С:», «По:», «Применить»
|
||
- [ ] Поиск «Поиск по любому полю...» (дата, номер, автор, компания, путь объекта, комментарий)
|
||
- [ ] Карточка «Отправить отчёт» (если `edit0 || aproove`)
|
||
- [ ] Карточки: `#номер`, дата, «✓ Утверждено», Пользователь, Компания (или «ID: n»), Объект (путь), Комментарий
|
||
- [ ] Копировать (`edit0 || aproove`) → форма отчёта с `copyFromId`
|
||
- [ ] Удалить (`aproove`, или `edit0` и не утверждён) → «Удалить отчёт?» → мягкое удаление `cree9_deleted = true`
|
||
- [ ] Клик / Enter / Space по карточке → форма отчёта с `reportId`
|
||
- [ ] Сортировка: дата desc, номер desc
|
||
- [ ] Пусто — «Отчёты не найдены за выбранный период.»
|
||
- [ ] Права: «Доступы» `user/Id` + `project/Id` (lookup)
|
||
|
||
🐞 Нет пагинации Dataverse (`@odata.nextLink` не читается). 🐞 Неделя по умолчанию считается в UTC.
|
||
|
||
---
|
||
|
||
## 5. Форма отчёта (stroy-bot-report) — `?page=report&projectId=[&reportId=|©FromId=]`
|
||
|
||
### Режимы
|
||
- [ ] Нет projectId — «Не указан projectId в URL»
|
||
- [ ] `reportId`: NoAccess / Approve (`aproove && !approved`) / Edit (`edit0 && !approved && дней < editDays`, по умолчанию 5) / ReadOnly
|
||
- [ ] `copyFromId`: Create, предзаполнены объект, компания, смена, комментарий, работы (с персоналом/техникой), персонал, техника; дата — сегодня, номер — 0, фото — пусто
|
||
- [ ] Без параметров — Create, смена — первая из «Смены», дата — сегодня
|
||
|
||
### Поля
|
||
- [ ] «← Вернуться назад»
|
||
- [ ] Заголовок «Отчет №N» / «Новый отчет», «Проект: …», бейдж «Утверждён» / «На утверждении»
|
||
- [ ] Дата отчета*, Смена*, Объект* (пикер с путями; смена объекта очищает работы), Компания* (с фильтром по «Компании по проекту», fallback — все)
|
||
- [ ] Работы: «+ Выбрать работу» («Сначала выберите объект»), Значение, План-факт (П / Ф / +/-, цвет), Комментарий
|
||
- [ ] Вложенные «Персонал на работе» / «Техника на работе»: Кол-во, Часы, «+ Добавить профессию / технику»
|
||
- [ ] Персонал: Кол-во, Часы, Тип часов (работы / простоя), Комментарий (обязателен для простоя)
|
||
- [ ] Техника: то же + «Часы ремонта» (комментарий обязателен для простоя и ремонта)
|
||
- [ ] Общий комментарий (contentEditable), Enter не отправляет форму SharePoint
|
||
- [ ] Фото: «Открыть папку с фото», «Добавить фото» (multiple), превью с удалением
|
||
|
||
### Пикер
|
||
- [ ] Поиск, группы для техники («Фильтры», чипы, «Все»), drill-down для работ (крошки «Все работы › …», «Выбрать «X»», «Нет работ на этом уровне»)
|
||
- [ ] Создание новой техники и новой работы (Ед. изм., План, Родительская работа)
|
||
|
||
### Сохранение
|
||
- [ ] Валидация (все сообщения из исходника)
|
||
- [ ] Номер = количество неудалённых отчётов проекта + 1
|
||
- [ ] При правке — удалить все старые строки (сначала дочерние), создать заново
|
||
- [ ] Фото → `DocLib/{projectId}_{number}`
|
||
- [ ] «Отчет успешно сохранен!», кнопка меняется на «← Вернуться назад»
|
||
- [ ] Утверждение: подтверждение → `cree9_aprooved = true` → «Отчет утвержден!»
|
||
- [ ] Права: «Доступы» `projectId` + `userId*` (несколько вариантов имени поля)
|
||
|
||
🐞 Create без проверки NoAccess. 🐞 Номер может совпасть после мягкого удаления. 🐞 Дата «сегодня» — UTC.
|
||
|
||
---
|
||
|
||
## 6. Импорт работ (stroy-bot-import-works) — `?page=import&projectId=`
|
||
|
||
- [ ] «ИМПОРТ РАБОТ» + название проекта
|
||
- [ ] Нет projectId — «Не указан projectId в URL»; нет `UniqueId0` — «Проект не привязан к справочнику проектов. Обратитесь к администратору.»
|
||
- [ ] Загрузка работ из API постранично по 200 с прогрессом «Загрузка работ... X из Y»
|
||
- [ ] Выбор объекта (модалка с поиском, сброс ×)
|
||
- [ ] Таблица: чекбокс, #, Наименование (+ бейдж объекта, «✓ импортировано», подзаголовок), Код СНБ, Ед. изм., Объём
|
||
- [ ] Поиск с debounce 250 мс по всем полям; пагинация по 100
|
||
- [ ] «Выделить всё на странице» / «Снять все на странице» (фактически — все отфильтрованные)
|
||
- [ ] Уже импортированные — неактивны, «Уже импортировано»
|
||
- [ ] «Импортировать» (нужен объект, иначе тост) и «Импорт с созданием объекта» (поиск/создание объекта и раздела по названиям из сметы)
|
||
- [ ] Подсказка «Объекты из сметы:» (3 строки + «ещё N»)
|
||
- [ ] Тосты «✓ Успешно импортировано: N» / «Импортировано: N, ошибок: M»
|
||
- [ ] Защита от дублей по `cree9_comment` = id работы из сметы
|
||
|
||
🐞 Пагинация в модалке объектов не выводится (видны только первые 100).
|
||
|
||
---
|
||
|
||
## 7. Ресурсы проекта (stroy-bot-project-assigner) — `?page=resources&projectId=`
|
||
|
||
- [ ] Нет projectId — «Проект не найден. Откройте страницу через список проектов.»
|
||
- [ ] Вкладки «Профессии (N)» и «Компании (N)»
|
||
- [ ] Слева «Доступные»: поиск, очистка ✕, «уже добавлено», «+», «Ничего не найдено» / «Нет элементов»
|
||
- [ ] Справа «Привязаны к проекту»: «−», «Ничего не добавлено»
|
||
- [ ] Оптимистичное добавление / удаление с откатом и ошибкой
|
||
- [ ] На узких экранах колонки друг под другом
|
||
|
||
---
|
||
|
||
## 8. Привязка к справочнику (stroy-bot-projects-binder) — `?page=binder&projectId=`
|
||
|
||
- [ ] Карточка проекта: название, Описание, Адрес, Статус (цвет), Начало, Окончание, Координаты
|
||
- [ ] Бейдж «Привязан» / «Не привязан», `UniqueName · UniqueId0`, «Отвязать»
|
||
- [ ] Поиск по справочнику (debounce 400 мс, пустой — все), пагинация ← / →, «{page} / {total} · всего: N»
|
||
- [ ] Карточки результатов: name, Код, Описание, Адрес, Координаты; выбор / снятие выбора; «Связать»
|
||
- [ ] Сообщения успеха и ошибок
|
||
- [ ] Запись `UniqueId0` и `UniqueName` в «Проекты»
|
||
|
||
---
|
||
|
||
## Открытые вопросы
|
||
|
||
- Схема списка **«Доступы»**: в репозиториях встречаются и поля `projectId`/`userId`, и lookup `user`/`project`. Проверить на сайте.
|
||
- Схема списка **«Объекты»**: родитель читается то как `parentId`, то как `parent/Id`. Проверить на сайте.
|