# Портал заявок — план работ Живая карта проекта: где мы, что осталось, как делать. Отмечай сделанное галочками. --- ## 1. Что это за проект (в одну строку) SPFx web part: **категории → плитки заявок → форма**. Форма пишет данные в списки SharePoint; у части заявок есть **согласование** (маршрут утверждающих). --- ## 2. Что уже готово ✅ **Каркас и общее** - [x] UI-поток: категории → плитки → форма (центрированная колонка 1080px, full-width канвы) - [x] Переиспользуемые примитивы формы (`shared/ui`): Button, FormCard, FormField, FormGrid, TextInput, TextArea, Select, Toggle, CollapseSection, FormActions, Alert, Icon, PeopleField / PeopleFieldMulti - [x] Ленивая загрузка форм (реестр `forms/registry.ts`, каждая форма — отдельный чанк) - [x] PnPjs подключён (`shared/pnp/pnpjs.ts`), клиент нацелен на сайт данных `DATA_SITE_URL` **Провижининг (создание списков)** - [x] Инструмент `provisioning/` — из `provisioning.json` создаёт списки/колонки идемпотентно - [x] Поддержка типов: Text, Note, Number(точность), DateTime(только дата), Boolean, Choice, Lookup, User (одиночный/мульти, «только люди») - [x] Доступ: приложение `Sites.Selected`, заперто на сайт `/sites/requests` - [x] Правило именования: `<Название заявки> — данные` / `<Название заявки> — согласование` **Формы** - [x] **Заявка на подбор** (`recruiting-selection`) — 42 поля, пишет в SP. Без согласования. - [x] **Заявка на прием** (`recruiting-hire`) — с согласованием (сторона автора). **Согласование (`shared/approval`)** - [x] Внешний API маршрутов (`approvalRoute.service.ts`, AadHttpClient/SSO) - [x] Матрица согласующих на форме (`ApprovalMatrix`, `useMatrixEditor`) - [x] Запись строк согласования в SP-список (`approvalList.service`, `approvalSubmission.service`) - [x] Сторона автора: «Сохранить черновик» / «Отправить на согласование» --- ## 3. Что НЕ готово ⏳ (главные пробелы) - [ ] **Экран согласующего** — логика есть (`approverDecision.service.ts`: согласовать/вернуть/ отклонить, делегирование, пересчёт статуса), но НЕТ UI и маршрутизации «мои согласования → открыть заявку → решение». - [ ] **8 форм** ещё не сделаны (см. таблицу ниже). - [ ] **Деплой**: web part пока только в workbench; не упакован в каталог приложений. - [ ] **Конфиг**: `DATA_SITE_URL` и id API захардкожены (потом — в property pane). --- ## 4. План по фазам (предлагаемый порядок) ### Фаза A — Закрыть согласование целиком Довести до конца одну сквозную вертикаль, чтобы механизм был полным. Согласующий приходит **по ссылке из потока Power Automate** (не ищет заявку сам). Контракт ссылки (портал — одностраничник, поэтому нужен и тип формы): `…/СтраницаПортала.aspx?rpmode=approve&rptype=<форма>&rpid=` (префикс `rp`: имена `id/mode/type` зарезервированы SharePoint и ломают страницу) - [x] `readOnly` у примитивов формы - [x] Скелет маршрутизации: `shared/routing.ts` (parseRoute) + ветка в оболочке → `features/approve/ApproveFeature` (пока заглушка, читает type/id) - [ ] Загрузка заявки по `id` из списка данных → форма в режиме чтения (уточнить: `RowID` = id элемента списка ДАННЫХ?) - [ ] Панель решения: Согласовать / Вернуть / Отклонить + комментарий (логика — `approverDecision.service`) - [ ] (опц.) Делегирование - [ ] Проверка статусов end-to-end на «Заявке на прием» ### Фаза B — Согласование для «Заявки на подбор» - [ ] Список «Заявка на подбор — согласование» (манифест + провижининг) - [ ] Подключить матрицу и submit-поток к форме подбора (id типа = 4) ### Фаза C — Остальные формы (конвейер) Для каждой формы по «рецепту одной формы» (раздел 6). Порядок — по важности для бизнеса. - [ ] IT: Организация рабочего места - [ ] Бухгалтерия: Аванс - [ ] Отдел кадров: Трудовой отпуск - [ ] Отдел кадров: Отгул - [ ] Отдел кадров: Увольнение - [ ] Отдел кадров: Обходной лист - [ ] Отдел кадров: БС - [ ] Отдел кадров: Командировка ### Фаза D — Развёртывание и настройки - [ ] Вынести `DATA_SITE_URL` и id API в property pane - [ ] Одобрить web API permission для approval API (SharePoint admin → API access) - [ ] Упаковать (`heft package-solution`) и выкатить в каталог приложений - [ ] Разместить web part на странице портала --- ## 5. Справочники ### Формы и их статус | Категория | Заявка | id (реестр) | id API | Форма | Согласование | | --- | --- | --- | --- | --- | --- | | Рекрутинг | Заявка на подбор | recruiting-selection | 4 | ✅ | ⏳ (Фаза B) | | Рекрутинг | Заявка на прием | recruiting-hire | 5 | ✅ | ✅ автор / ⏳ согласующий | | IT | Организация раб. места | it-workplace-setup | — | ⏳ | ? | | Бухгалтерия | Аванс | accounting-advance | — | ⏳ | ? | | Отдел кадров | Трудовой отпуск | hr-labor-leave | — | ⏳ | ? | | Отдел кадров | Отгул | hr-day-off | — | ⏳ | ? | | Отдел кадров | Увольнение | hr-dismissal | — | ⏳ | ? | | Отдел кадров | Обходной лист | hr-clearance-sheet | — | ⏳ | ? | | Отдел кадров | БС | hr-bs | — | ⏳ | ? | | Отдел кадров | Командировка | hr-business-trip | — | ⏳ | ? | > «?» в согласовании — решить по каждой заявке: нужно ли ей согласование вообще. ### Списки в SharePoint (`/sites/requests`) - `Заявка на подбор — данные` ✅ - `Прием на работу — данные` ✅ - `Прием на работу — согласование` ✅ --- ## 6. Рецепт одной формы (чеклист) Как добавить новую заявку — всегда одни и те же шаги: 1. **Данные (список):** создать `forms/<Форма>/provisioning.json` (колонки) → прогнать `provisioning/Provision-Lists.ps1` → появится список `<Название> — данные`. 2. **Согласование (если нужно):** `forms/<Форма>/approval/provisioning.json` → список `<Название> — согласование`. 3. **Форма (UI):** - `forms/<Форма>/model.ts` — `IFormData` (ключи = internalName колонок), `EMPTY_DATA` - `forms/<Форма>/sections/*.tsx` — секции из примитивов `shared/ui` - `forms/<Форма>/<Форма>Form.tsx` — сборка секций + валидация + кнопки - `forms/<Форма>/submit.ts` — запись в SP (маппинг типов, люди через ensureUser) 4. **Реестр:** строка в `forms/registry.ts` (`'': React.lazy(...)`). 5. **Плитка:** уже есть в `data/requests.ts` (id совпадает с реестром). 6. **Проверка:** `heft build` → тест на hosted workbench сайта `/sites/requests`. ### Обязательные примитивы под тип поля (единообразие во ВСЕХ формах) - **Телефон** → `PhoneInput` (маска `+7 (XXX) XXX-XX-XX`). Не `TextInput`. - **Сумма/деньги/оклад/ставка** → `MoneyInput` (разделитель тысяч, в модели — чистые цифры). Не `TextInput type=number`. - Пользователь(и) → `PeopleField` / `PeopleFieldMulti`; дата → `TextInput type=date`; да/нет → `Toggle`; выбор → `Select`. - **Вложения** (если у формы есть файлы): секция с `FileDropzone` (состояние `File[]`); при сабмите — `uploadAttachments(листДанных, id, files)` ПОСЛЕ создания элемента; в режиме согласующего — `AttachmentList` из `getAttachments(...)`. Хранятся как вложения элемента списка (`AttachmentFiles`), без отдельной библиотеки. --- ## 7. Открытые вопросы (решить по ходу) - Каким заявкам нужно согласование, а каким нет? - Порядок Фазы C (какие формы делаем первыми)? - Нужен ли реестр/дашборд поданных заявок (просмотр своих заявок и их статусов)?