# Чек-лист миграции 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}» / «Ошибка при загрузке отчёта» 🐞 Лишний запрос к «Доступы» без фильтра по пользователю. --- ## 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`. Проверить на сайте.