40839cc8d8
Манифесты отстают от живых списков, когда колонки добавляют руками или кодом, и пересоздание по ним ломает функции. Скрипт только читает и показывает, чего нет в манифесте, чего нет на сайте и где отличаются тип, варианты или лукап. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
160 lines
10 KiB
Markdown
160 lines
10 KiB
Markdown
# Провижионинг списков 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 "<client-id>" -DisplayName "PnP-Provisioning-Scoped" -Permissions FullControl -Site "https://tnsukz.sharepoint.com/sites/sed"
|
||
Grant-PnPAzureADAppSitePermission -AppId "<client-id>" -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 "<client-id>" `
|
||
-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 "<client-id>" `
|
||
-Tenant "tnsukz.onmicrosoft.com" `
|
||
-Thumbprint "<отпечаток>"
|
||
```
|
||
|
||
Идёт в два прохода: сначала все списки/библиотеки (чтобы Lookup нашли цель), потом
|
||
колонки. Идемпотентно — повторный запуск ничего не ломает. `-Only kps` провижионит
|
||
только KPS (но общие `Поставщики`/`Курс Валют` должны уже существовать).
|
||
|
||
Лог: `[+]` создано, `[=]` уже было, `[~]` обновлено, `[!]` предупреждение.
|
||
|
||
## Сверка манифестов с живыми списками
|
||
|
||
Манифест отстаёт, когда колонки добавляют руками или кодом. Перед провижинингом на рабочем
|
||
сайте и после ручных правок списков — сверка (только чтение):
|
||
|
||
```powershell
|
||
./Compare-Manifests.ps1 `
|
||
-SiteUrl "https://tnsukz.sharepoint.com/sites/sed" `
|
||
-ClientId "<client-id>" `
|
||
-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` продолжает работать — он не тронут.
|