# Провижионинг списков ct-forms-portal Списки форм **CT / OID / KPS** воспроизводятся на боевом сайте портала **`/sites/sed`** из манифестов `provisioning.json`. Манифесты **снимаются 1:1 с живых списков** (Export-ListSchema.ps1), затем воспроизводятся на цели (Provision-Lists.ps1). Так схема всегда «под рукой» и одинаково создаётся на тесте и в бою (по аналогии с `request-portal/provisioning`). ## Почему так, а не копия request-portal - Здесь **литеральные имена** списков (`Сравнительная таблица`, `Позиции СТ ОИД`…), а не конвенция «Форма N — данные/согласование». Скрипт request-portal на таких именах падал бы. - Поддержаны **библиотеки документов** (`Коммерческие предложения*`), а не только списки. - Одна форма (KPS) = **много списков** → манифест мультисписковый. ## Коллизия имён KPS ↔ CT (важно!) CT уже живёт на `/sites/sed` и владеет `Сравнительная таблица`, `Позиции СТ`, `Оценка поставщиков`, `Критерии`, `Согласование СТ`, библиотекой `Коммерческие предложения`. KPS раньше жил один на `/sites/kps` с **теми же именами**. При переезде на `/sites/sed` data-списки KPS получают суффикс **` КПС`** (зеркально суффиксу ` ОИД` у OID): | Роль | Было (на /sites/kps) | Стало (на /sites/sed) | | --- | --- | --- | | шапка | Сравнительная таблица | **Сравнительная таблица КПС** | | позиции | Позиции СТ | **Позиции СТ КПС** | | офферы | Оценка поставщиков | **Оценка поставщиков КПС** | | критерии | Критерии | **Критерии КПС** | | согласование | Согласование СТ | **Согласование СТ КПС** | | библиотека КП | Коммерческие предложения | **Коммерческие предложения КПС** | | без КП | Не получены КП КПС | Не получены КП КПС (уже уникально) | | матрица | Матрица согласования КПС | Матрица согласования КПС (уже уникально) | | справочник | Поставщики | **Поставщики** (ОБЩИЙ с CT) | | справочник | Курс Валют | **Курс Валют** (ОБЩИЙ с CT) | Суффикс применяет Export автоматически (`renameSuffix`/`renameExclude` в `sources.json`), включая цели Lookup-колонок. Код уже приведён к новым именам: - `forms/kps/services/KpsCtFormService.ts` — карта `LISTS`; - `components/config/kpsDocumentConfig.ts` — `siteUrl` → `/sites/sed`, имена списков. > Общие справочники `Поставщики`, `Курс Валют` и `Матрица согласования СТ` создаёт > манифест **CT**. OID тоже опирается на них (своей матрицы у OID нет). Поэтому > провижионь **вместе с CT** (или все формы разом) — иначе Lookup'ы KPS/OID не найдут цель. ## Что провижионинг НЕ делает (перенести отдельно!) - **Данные справочников** — содержимое `Поставщики`, `Курс Валют`, `Матрица согласования *`. Создаются только пустые списки с колонками. - **Настройка Syntex** на библиотеках `Коммерческие предложения*` (колонка `file_content` создаётся, но модель распознавания настраивается вручную). - **URL потоков Power Automate** (в коде сервисов) — указывают на прежнее окружение. - **`Единицы измерения`** (OID) живёт на `/sites/stroy` — внешний справочник, не трогаем. ## Разовая подготовка (app-only, Sites.Selected) Как в request-portal. Приложению нужен доступ **и к `/sites/sed`, и к `/sites/kps`** (последнее — только для экспорта схемы KPS с текущего сайта): ```powershell # один раз (если приложения ещё нет) Register-PnPEntraIDApp -ApplicationName "PnP-Provisioning-Scoped" -Tenant "tnsukz.onmicrosoft.com" -SharePointApplicationPermissions "Sites.Selected" -Store CurrentUser # админ выдаёт доступ к обоим сайтам Grant-PnPAzureADAppSitePermission -AppId "" -DisplayName "PnP-Provisioning-Scoped" -Permissions FullControl -Site "https://tnsukz.sharepoint.com/sites/sed" Grant-PnPAzureADAppSitePermission -AppId "" -DisplayName "PnP-Provisioning-Scoped" -Permissions Read -Site "https://tnsukz.sharepoint.com/sites/kps" ``` Отпечаток сертификата: ```powershell Get-ChildItem Cert:\CurrentUser\My | Where-Object { $_.Subject -like "*PnP-Provisioning-Scoped*" } | Select-Object Subject, Thumbprint ``` ## Шаг 1. Снять схему с живых списков → манифесты ```powershell cd provisioning ./Export-ListSchema.ps1 ` -ClientId "" ` -Tenant "tnsukz.onmicrosoft.com" ` -Thumbprint "<отпечаток>" ``` Создаст `manifests/kps.provisioning.json`, `manifests/ct.provisioning.json`, `manifests/oid.provisioning.json`. Только одна форма — флаг `-Only kps`. **Проверь манифесты глазами** и закоммить в репозиторий — это и есть источник правды по схеме. ## Шаг 2. Воспроизвести списки на `/sites/sed` Сначала на **тестовом** сайте, потом на бою. ```powershell ./Provision-Lists.ps1 ` -SiteUrl "https://tnsukz.sharepoint.com/sites/sed" ` -ClientId "" ` -Tenant "tnsukz.onmicrosoft.com" ` -Thumbprint "<отпечаток>" ``` Идёт в два прохода: сначала все списки/библиотеки (чтобы Lookup нашли цель), потом колонки. Идемпотентно — повторный запуск ничего не ломает. `-Only kps` провижионит только KPS (но общие `Поставщики`/`Курс Валют` должны уже существовать). Лог: `[+]` создано, `[=]` уже было, `[~]` обновлено, `[!]` предупреждение. ## Сверка манифестов с живыми списками Манифест отстаёт, когда колонки добавляют руками или кодом. Перед провижинингом на рабочем сайте и после ручных правок списков — сверка (только чтение): ```powershell ./Compare-Manifests.ps1 ` -SiteUrl "https://tnsukz.sharepoint.com/sites/sed" ` -ClientId "" ` -Tenant "tnsukz.onmicrosoft.com" ` -CertificatePath "<путь к .pfx>" -CertificatePassword "<пароль>" ``` `-` есть в манифесте, нет в живом (создаст Provision-Lists.ps1), `+` есть в живом, нет в манифесте (при пересоздании пропадёт — дописать в манифест), `~` отличаются тип, варианты или лукап. ## Добавить новый список на рабочий сайт Полный прогон Provision-Lists.ps1 синхронизирует варианты Choice у ВСЕХ живых списков с манифестами. Новый список добавляй точечно — `-Lists "Название"`: остальные списки не трогаются. ## Формат манифеста ```jsonc { "form": "kps", "targetSite": "https://tnsukz.sharepoint.com/sites/sed", "lists": [ { "title": "Сравнительная таблица КПС", "template": "GenericList", // или "DocumentLibrary" "shared": false, "columns": [ { "internalName": "number", "title": "Номер СТ", "type": "Number" }, { "internalName": "status", "title": "Статус", "type": "Choice", "choices": ["Черновик", "..."] }, { "internalName": "winSupplier", "title": "Победитель", "type": "Lookup", "lookupList": "Поставщики", "lookupShowField": "Title" } ] } ] } ``` Типы колонок: `Text`, `Note`, `Number` (+`decimals`), `Choice` (+`choices`, +`multiChoice`), `DateTime` (+`dateOnly`), `Boolean`, `User` (+`userSelectionMode`, +`allowMultiple`), `Lookup` (+`lookupList`, +`lookupShowField`, +`allowMultiple`). ## Порядок миграции KPS (cutover) 1. Экспорт (Шаг 1) → манифесты в репозитории. 2. Провижн на `/sites/sed` (Шаг 2) → пустые списки `… КПС` + общие справочники. 3. Перенести данные (справочники, а при необходимости — рабочие СТ) на новые списки. 4. Задеплоить обновлённый `ct-forms-portal` (код уже смотрит на `… КПС` / `/sites/sed`). До шага 4 старый `kps-ct-form` на `/sites/kps` продолжает работать — он не тронут.