mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-14 06:45:17 +03:00
chore(repo): нормализация EOL к LF + .gitattributes
Приводим авторский контент (.ps1/.psm1/.py/.mjs/.md/.json, пин .bsl) к единому LF и закрепляем политикой в .gitattributes. Инструмент правки всегда пишет LF, поэтому единый LF убирает EOL-шум в диффах, ложные срабатывания blame и налог на ручную синхронизацию CRLF-файлов. BOM на .ps1 сохранён (git с eol=lf меняет только CR<->LF, BOM не трогает). Данные 1С (*.xml) и бинарники под нормализацию не берём. Гейт: PS-порт 459/459, Python-порт 459/459, web-test E2E 22/22 (с пересборкой стенда). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,60 +1,60 @@
|
|||||||
---
|
---
|
||||||
name: cf-edit
|
name: cf-edit
|
||||||
description: Точечное редактирование конфигурации 1С. Используй когда нужно изменить свойства конфигурации, добавить или удалить объект из состава, настроить роли по умолчанию, поменять раскладку панелей, настроить начальную страницу
|
description: Точечное редактирование конфигурации 1С. Используй когда нужно изменить свойства конфигурации, добавить или удалить объект из состава, настроить роли по умолчанию, поменять раскладку панелей, настроить начальную страницу
|
||||||
argument-hint: -ConfigPath <path> -Operation <op> -Value <value>
|
argument-hint: -ConfigPath <path> -Operation <op> -Value <value>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Write
|
- Write
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /cf-edit — редактирование конфигурации 1С
|
# /cf-edit — редактирование конфигурации 1С
|
||||||
|
|
||||||
Точечное редактирование Configuration.xml: свойства, состав ChildObjects, роли по умолчанию.
|
Точечное редактирование Configuration.xml: свойства, состав ChildObjects, роли по умолчанию.
|
||||||
|
|
||||||
## Параметры и команда
|
## Параметры и команда
|
||||||
|
|
||||||
| Параметр | Описание |
|
| Параметр | Описание |
|
||||||
|----------|----------|
|
|----------|----------|
|
||||||
| `ConfigPath` | Путь к Configuration.xml или каталогу выгрузки |
|
| `ConfigPath` | Путь к Configuration.xml или каталогу выгрузки |
|
||||||
| `Operation` | Операция (см. таблицу) |
|
| `Operation` | Операция (см. таблицу) |
|
||||||
| `Value` | Значение для операции (batch через `;;`) |
|
| `Value` | Значение для операции (batch через `;;`) |
|
||||||
| `DefinitionFile` | JSON-файл с массивом операций |
|
| `DefinitionFile` | JSON-файл с массивом операций |
|
||||||
| `NoValidate` | Пропустить авто-валидацию |
|
| `NoValidate` | Пропустить авто-валидацию |
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-edit.ps1" -ConfigPath '<path>' -Operation modify-property -Value 'Version=1.0.0.1'
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-edit.ps1" -ConfigPath '<path>' -Operation modify-property -Value 'Version=1.0.0.1'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Операции
|
## Операции
|
||||||
|
|
||||||
| Операция | Формат Value | Описание |
|
| Операция | Формат Value | Описание |
|
||||||
|----------|-------------|----------|
|
|----------|-------------|----------|
|
||||||
| `modify-property` | `Ключ=Значение` (batch `;;`) | Изменить свойство |
|
| `modify-property` | `Ключ=Значение` (batch `;;`) | Изменить свойство |
|
||||||
| `add-childObject` | `Type.Name` (batch `;;`) | Зарегистрировать уже существующий файл объекта в ChildObjects. Для создания нового объекта используй `/meta-compile`, `/role-compile`, `/subsystem-compile` — они регистрируют автоматически |
|
| `add-childObject` | `Type.Name` (batch `;;`) | Зарегистрировать уже существующий файл объекта в ChildObjects. Для создания нового объекта используй `/meta-compile`, `/role-compile`, `/subsystem-compile` — они регистрируют автоматически |
|
||||||
| `remove-childObject` | `Type.Name` (batch `;;`) | Удалить объект из ChildObjects |
|
| `remove-childObject` | `Type.Name` (batch `;;`) | Удалить объект из ChildObjects |
|
||||||
| `add-defaultRole` | `Role.Name` или `Name` | Добавить роль по умолчанию |
|
| `add-defaultRole` | `Role.Name` или `Name` | Добавить роль по умолчанию |
|
||||||
| `remove-defaultRole` | `Role.Name` или `Name` | Удалить роль по умолчанию |
|
| `remove-defaultRole` | `Role.Name` или `Name` | Удалить роль по умолчанию |
|
||||||
| `set-defaultRoles` | Имена через `;;` | Заменить список ролей по умолчанию |
|
| `set-defaultRoles` | Имена через `;;` | Заменить список ролей по умолчанию |
|
||||||
| `set-panels` | JSON-объект (см. [reference.md](reference.md)) | Перезаписать `Ext/ClientApplicationInterface.xml` (раскладка панелей) |
|
| `set-panels` | JSON-объект (см. [reference.md](reference.md)) | Перезаписать `Ext/ClientApplicationInterface.xml` (раскладка панелей) |
|
||||||
| `set-home-page` | JSON-объект (см. [reference.md](reference.md)) | Перезаписать `Ext/HomePageWorkArea.xml` (начальная страница) |
|
| `set-home-page` | JSON-объект (см. [reference.md](reference.md)) | Перезаписать `Ext/HomePageWorkArea.xml` (начальная страница) |
|
||||||
|
|
||||||
Допустимые значения свойств, формат DefinitionFile (JSON), каноничный порядок: [reference.md](reference.md)
|
Допустимые значения свойств, формат DefinitionFile (JSON), каноничный порядок: [reference.md](reference.md)
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Изменить версию и поставщика
|
# Изменить версию и поставщика
|
||||||
... -ConfigPath src -Operation modify-property -Value "Version=1.0.0.1 ;; Vendor=Фирма 1С"
|
... -ConfigPath src -Operation modify-property -Value "Version=1.0.0.1 ;; Vendor=Фирма 1С"
|
||||||
|
|
||||||
# Добавить объекты
|
# Добавить объекты
|
||||||
... -ConfigPath src -Operation add-childObject -Value "Catalog.Товары ;; Document.Заказ"
|
... -ConfigPath src -Operation add-childObject -Value "Catalog.Товары ;; Document.Заказ"
|
||||||
|
|
||||||
# Удалить объект
|
# Удалить объект
|
||||||
... -ConfigPath src -Operation remove-childObject -Value "Catalog.Устаревший"
|
... -ConfigPath src -Operation remove-childObject -Value "Catalog.Устаревший"
|
||||||
|
|
||||||
# Роли по умолчанию
|
# Роли по умолчанию
|
||||||
... -ConfigPath src -Operation add-defaultRole -Value "ПолныеПрава"
|
... -ConfigPath src -Operation add-defaultRole -Value "ПолныеПрава"
|
||||||
... -ConfigPath src -Operation set-defaultRoles -Value "ПолныеПрава ;; Администратор"
|
... -ConfigPath src -Operation set-defaultRoles -Value "ПолныеПрава ;; Администратор"
|
||||||
```
|
```
|
||||||
|
|||||||
+150
-150
@@ -1,150 +1,150 @@
|
|||||||
# cf-edit — справочник операций
|
# cf-edit — справочник операций
|
||||||
|
|
||||||
## modify-property
|
## modify-property
|
||||||
|
|
||||||
Свойства для редактирования:
|
Свойства для редактирования:
|
||||||
|
|
||||||
### Скалярные
|
### Скалярные
|
||||||
`Name`, `Version`, `Vendor`, `Comment`, `NamePrefix`, `UpdateCatalogAddress`
|
`Name`, `Version`, `Vendor`, `Comment`, `NamePrefix`, `UpdateCatalogAddress`
|
||||||
|
|
||||||
### LocalString (многоязычные)
|
### LocalString (многоязычные)
|
||||||
`Synonym`, `BriefInformation`, `DetailedInformation`, `Copyright`, `VendorInformationAddress`, `ConfigurationInformationAddress`
|
`Synonym`, `BriefInformation`, `DetailedInformation`, `Copyright`, `VendorInformationAddress`, `ConfigurationInformationAddress`
|
||||||
|
|
||||||
### Enum
|
### Enum
|
||||||
| Свойство | Допустимые значения |
|
| Свойство | Допустимые значения |
|
||||||
|----------|---------------------|
|
|----------|---------------------|
|
||||||
| `CompatibilityMode` | `Version8_3_20` ... `Version8_3_28`, `Version8_5_1`, `DontUse` |
|
| `CompatibilityMode` | `Version8_3_20` ... `Version8_3_28`, `Version8_5_1`, `DontUse` |
|
||||||
| `ConfigurationExtensionCompatibilityMode` | то же |
|
| `ConfigurationExtensionCompatibilityMode` | то же |
|
||||||
| `DefaultRunMode` | `ManagedApplication`, `OrdinaryApplication`, `Auto` |
|
| `DefaultRunMode` | `ManagedApplication`, `OrdinaryApplication`, `Auto` |
|
||||||
| `ScriptVariant` | `Russian`, `English` |
|
| `ScriptVariant` | `Russian`, `English` |
|
||||||
| `DataLockControlMode` | `Managed`, `Automatic`, `AutomaticAndManaged` |
|
| `DataLockControlMode` | `Managed`, `Automatic`, `AutomaticAndManaged` |
|
||||||
| `ObjectAutonumerationMode` | `NotAutoFree`, `AutoFree` |
|
| `ObjectAutonumerationMode` | `NotAutoFree`, `AutoFree` |
|
||||||
| `ModalityUseMode` | `DontUse`, `Use`, `UseWithWarnings` |
|
| `ModalityUseMode` | `DontUse`, `Use`, `UseWithWarnings` |
|
||||||
| `SynchronousPlatformExtensionAndAddInCallUseMode` | `DontUse`, `Use`, `UseWithWarnings` |
|
| `SynchronousPlatformExtensionAndAddInCallUseMode` | `DontUse`, `Use`, `UseWithWarnings` |
|
||||||
| `InterfaceCompatibilityMode` | `Version8_2`, `Version8_2EnableTaxi`, `Taxi`, `TaxiEnableVersion8_2`, `TaxiEnableVersion8_5`, `Version8_5EnableTaxi`, `Version8_5` |
|
| `InterfaceCompatibilityMode` | `Version8_2`, `Version8_2EnableTaxi`, `Taxi`, `TaxiEnableVersion8_2`, `TaxiEnableVersion8_5`, `Version8_5EnableTaxi`, `Version8_5` |
|
||||||
| `DatabaseTablespacesUseMode` | `DontUse`, `Use` |
|
| `DatabaseTablespacesUseMode` | `DontUse`, `Use` |
|
||||||
| `MainClientApplicationWindowMode` | `Normal`, `Fullscreen`, `Kiosk` |
|
| `MainClientApplicationWindowMode` | `Normal`, `Fullscreen`, `Kiosk` |
|
||||||
|
|
||||||
### Ref
|
### Ref
|
||||||
`DefaultLanguage` — значение вида `Language.Русский`
|
`DefaultLanguage` — значение вида `Language.Русский`
|
||||||
|
|
||||||
### Формат batch
|
### Формат batch
|
||||||
`"Version=1.0.0.1 ;; Vendor=Фирма 1С ;; Synonym=Тестовая конфигурация"`
|
`"Version=1.0.0.1 ;; Vendor=Фирма 1С ;; Synonym=Тестовая конфигурация"`
|
||||||
|
|
||||||
## add-childObject / remove-childObject
|
## add-childObject / remove-childObject
|
||||||
|
|
||||||
Формат: `Type.Name` — XML-тип и имя объекта через точку.
|
Формат: `Type.Name` — XML-тип и имя объекта через точку.
|
||||||
|
|
||||||
**Важно про `add-childObject`**: регистрирует в `<ChildObjects>` объект, **файл которого уже существует на диске**. Если файла нет — exit 1. Для создания нового объекта используй профильный навык — `/meta-compile` (Catalog, Document, Enum, Report, регистры и т.д.), `/role-compile` (Role), `/subsystem-compile` (Subsystem). Они создают файл И регистрируют его за один вызов.
|
**Важно про `add-childObject`**: регистрирует в `<ChildObjects>` объект, **файл которого уже существует на диске**. Если файла нет — exit 1. Для создания нового объекта используй профильный навык — `/meta-compile` (Catalog, Document, Enum, Report, регистры и т.д.), `/role-compile` (Role), `/subsystem-compile` (Subsystem). Они создают файл И регистрируют его за один вызов.
|
||||||
|
|
||||||
Batch: `"Catalog.Товары ;; Document.Заказ ;; Enum.ВидыОплат"`
|
Batch: `"Catalog.Товары ;; Document.Заказ ;; Enum.ВидыОплат"`
|
||||||
|
|
||||||
## add-defaultRole / remove-defaultRole / set-defaultRoles
|
## add-defaultRole / remove-defaultRole / set-defaultRoles
|
||||||
|
|
||||||
Имя роли: `ПолныеПрава` или `Role.ПолныеПрава` (префикс `Role.` добавляется автоматически).
|
Имя роли: `ПолныеПрава` или `Role.ПолныеПрава` (префикс `Role.` добавляется автоматически).
|
||||||
|
|
||||||
`set-defaultRoles` полностью заменяет список ролей.
|
`set-defaultRoles` полностью заменяет список ролей.
|
||||||
|
|
||||||
## set-panels
|
## set-panels
|
||||||
|
|
||||||
Перезаписывает `Ext/ClientApplicationInterface.xml` — раскладку панелей рабочего пространства Taxi. Файл создаётся с нуля; то, что не упомянуто в `value`, отсутствует на экране.
|
Перезаписывает `Ext/ClientApplicationInterface.xml` — раскладку панелей рабочего пространства Taxi. Файл создаётся с нуля; то, что не упомянуто в `value`, отсутствует на экране.
|
||||||
|
|
||||||
`value` — объект с ключами `top`, `left`, `right`, `bottom`. Каждый ключ — массив записей. Ключ можно опустить (= пустая сторона).
|
`value` — объект с ключами `top`, `left`, `right`, `bottom`. Каждый ключ — массив записей. Ключ можно опустить (= пустая сторона).
|
||||||
|
|
||||||
**Запись** — одна из:
|
**Запись** — одна из:
|
||||||
- Строка-алиас (одна панель в этом слоте)
|
- Строка-алиас (одна панель в этом слоте)
|
||||||
- Объект `{"group": [...]}` (стек: панели/подгруппы внутри располагаются друг под другом)
|
- Объект `{"group": [...]}` (стек: панели/подгруппы внутри располагаются друг под другом)
|
||||||
|
|
||||||
**Алиасы панелей:**
|
**Алиасы панелей:**
|
||||||
|
|
||||||
| Алиас | Панель |
|
| Алиас | Панель |
|
||||||
|-------|--------|
|
|-------|--------|
|
||||||
| `sections` | Панель разделов |
|
| `sections` | Панель разделов |
|
||||||
| `open` | Панель открытых |
|
| `open` | Панель открытых |
|
||||||
| `favorites` | Панель избранного |
|
| `favorites` | Панель избранного |
|
||||||
| `history` | Панель истории |
|
| `history` | Панель истории |
|
||||||
| `functions` | Панель функций текущего раздела |
|
| `functions` | Панель функций текущего раздела |
|
||||||
|
|
||||||
**Семантика:**
|
**Семантика:**
|
||||||
- Несколько записей в одной стороне → отдельные слоты «рядом» (несколько тегов `<top>`/...)
|
- Несколько записей в одной стороне → отдельные слоты «рядом» (несколько тегов `<top>`/...)
|
||||||
- `{"group":[...]}` → один тег с `<group>`-обёрткой, элементы внутри идут стеком
|
- `{"group":[...]}` → один тег с `<group>`-обёрткой, элементы внутри идут стеком
|
||||||
|
|
||||||
**Пример** (DefinitionFile):
|
**Пример** (DefinitionFile):
|
||||||
```json
|
```json
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"operation": "set-panels",
|
"operation": "set-panels",
|
||||||
"value": {
|
"value": {
|
||||||
"top": ["open"],
|
"top": ["open"],
|
||||||
"left": ["sections"],
|
"left": ["sections"],
|
||||||
"right": [{ "group": ["favorites", "history"] }],
|
"right": [{ "group": ["favorites", "history"] }],
|
||||||
"bottom": ["functions"]
|
"bottom": ["functions"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Через `-Value` (CLI): передай объект как JSON-строку — `... -Operation set-panels -Value '{"top":["open"]}'`.
|
Через `-Value` (CLI): передай объект как JSON-строку — `... -Operation set-panels -Value '{"top":["open"]}'`.
|
||||||
|
|
||||||
## set-home-page
|
## set-home-page
|
||||||
|
|
||||||
Перезаписывает `Ext/HomePageWorkArea.xml` — раскладка форм на начальной странице (рабочая область). Файл создаётся с нуля; то, что не упомянуто в `value`, отсутствует.
|
Перезаписывает `Ext/HomePageWorkArea.xml` — раскладка форм на начальной странице (рабочая область). Файл создаётся с нуля; то, что не упомянуто в `value`, отсутствует.
|
||||||
|
|
||||||
`value` — объект:
|
`value` — объект:
|
||||||
|
|
||||||
| Ключ | Канонич. (XML) | Описание |
|
| Ключ | Канонич. (XML) | Описание |
|
||||||
|------|----------------|----------|
|
|------|----------------|----------|
|
||||||
| `template` | `WorkingAreaTemplate` | `OneColumn` / `TwoColumnsEqualWidth` (дефолт) / `TwoColumnsVariableWidth` |
|
| `template` | `WorkingAreaTemplate` | `OneColumn` / `TwoColumnsEqualWidth` (дефолт) / `TwoColumnsVariableWidth` |
|
||||||
| `left` | `LeftColumn` | массив записей форм |
|
| `left` | `LeftColumn` | массив записей форм |
|
||||||
| `right` | `RightColumn` | массив записей форм (запрещён при `OneColumn`) |
|
| `right` | `RightColumn` | массив записей форм (запрещён при `OneColumn`) |
|
||||||
|
|
||||||
Принимаются и короткие и канонич. ключи (XML-имена) — оба работают.
|
Принимаются и короткие и канонич. ключи (XML-имена) — оба работают.
|
||||||
|
|
||||||
**Запись формы** — одна из:
|
**Запись формы** — одна из:
|
||||||
- Строка `"<form>"` — только имя формы, дефолты `height=10`, `visibility=true`
|
- Строка `"<form>"` — только имя формы, дефолты `height=10`, `visibility=true`
|
||||||
- Объект `{form, height?, visibility?, roles?}`
|
- Объект `{form, height?, visibility?, roles?}`
|
||||||
|
|
||||||
| Поле | Канонич. | Дефолт | Описание |
|
| Поле | Канонич. | Дефолт | Описание |
|
||||||
|------|----------|--------|----------|
|
|------|----------|--------|----------|
|
||||||
| `form` | `Form` | — | `CommonForm.X` или `Type.Object.Form.Name` (или UUID) |
|
| `form` | `Form` | — | `CommonForm.X` или `Type.Object.Form.Name` (или UUID) |
|
||||||
| `height` | `Height` | `10` | Высота |
|
| `height` | `Height` | `10` | Высота |
|
||||||
| `visibility` | `Visibility` | `true` | Общая видимость (`<xr:Common>`) |
|
| `visibility` | `Visibility` | `true` | Общая видимость (`<xr:Common>`) |
|
||||||
| `roles` | — | — | `{"Role.Имя": true|false, ...}` — переопределения по ролям |
|
| `roles` | — | — | `{"Role.Имя": true|false, ...}` — переопределения по ролям |
|
||||||
|
|
||||||
**Семантика visibility:** `visibility` = общее правило, `roles` — точечные исключения. Скрыть для всех кроме одной роли: `{"visibility": false, "roles": {"Role.Опер": true}}`.
|
**Семантика visibility:** `visibility` = общее правило, `roles` — точечные исключения. Скрыть для всех кроме одной роли: `{"visibility": false, "roles": {"Role.Опер": true}}`.
|
||||||
|
|
||||||
**Пример:**
|
**Пример:**
|
||||||
```json
|
```json
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"operation": "set-home-page",
|
"operation": "set-home-page",
|
||||||
"value": {
|
"value": {
|
||||||
"template": "TwoColumnsVariableWidth",
|
"template": "TwoColumnsVariableWidth",
|
||||||
"left": [
|
"left": [
|
||||||
"CommonForm.НачалоРаботы",
|
"CommonForm.НачалоРаботы",
|
||||||
{ "form": "CommonForm.СписокЗадач", "height": 100, "visibility": false },
|
{ "form": "CommonForm.СписокЗадач", "height": 100, "visibility": false },
|
||||||
{ "form": "Catalog.Контрагенты.Form.ФормаСписка", "height": 50 },
|
{ "form": "Catalog.Контрагенты.Form.ФормаСписка", "height": 50 },
|
||||||
{
|
{
|
||||||
"form": "CommonForm.РабочийСтолОператора",
|
"form": "CommonForm.РабочийСтолОператора",
|
||||||
"visibility": false,
|
"visibility": false,
|
||||||
"roles": { "Role.Оператор": true, "Role.ПолныеПрава": false }
|
"roles": { "Role.Оператор": true, "Role.ПолныеПрава": false }
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"right": [
|
"right": [
|
||||||
{ "form": "DataProcessor.Поиск.Form.ФормаПоиска", "height": 30 }
|
{ "form": "DataProcessor.Поиск.Form.ФормаПоиска", "height": 30 }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
## DefinitionFile (JSON)
|
## DefinitionFile (JSON)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
[
|
[
|
||||||
{ "operation": "modify-property", "value": "Version=2.0.0.1 ;; Vendor=Test" },
|
{ "operation": "modify-property", "value": "Version=2.0.0.1 ;; Vendor=Test" },
|
||||||
{ "operation": "add-childObject", "value": "Catalog.Товары ;; Document.Заказ" },
|
{ "operation": "add-childObject", "value": "Catalog.Товары ;; Document.Заказ" },
|
||||||
{ "operation": "add-defaultRole", "value": "ПолныеПрава" }
|
{ "operation": "add-defaultRole", "value": "ПолныеПрава" }
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,54 +1,54 @@
|
|||||||
---
|
---
|
||||||
name: cf-info
|
name: cf-info
|
||||||
description: Анализ структуры конфигурации 1С — свойства, состав, счётчики объектов. Используй для обзора конфигурации — какие объекты есть, сколько их, какие настройки
|
description: Анализ структуры конфигурации 1С — свойства, состав, счётчики объектов. Используй для обзора конфигурации — какие объекты есть, сколько их, какие настройки
|
||||||
argument-hint: <ConfigPath> [-Mode overview|brief|full] [-Section home-page]
|
argument-hint: <ConfigPath> [-Mode overview|brief|full] [-Section home-page]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /cf-info — Структура конфигурации 1С
|
# /cf-info — Структура конфигурации 1С
|
||||||
|
|
||||||
Читает Configuration.xml из выгрузки конфигурации и выводит компактное описание структуры.
|
Читает Configuration.xml из выгрузки конфигурации и выводит компактное описание структуры.
|
||||||
|
|
||||||
## Параметры и команда
|
## Параметры и команда
|
||||||
|
|
||||||
| Параметр | Описание |
|
| Параметр | Описание |
|
||||||
|----------|----------|
|
|----------|----------|
|
||||||
| `ConfigPath` | Путь к Configuration.xml или каталогу выгрузки |
|
| `ConfigPath` | Путь к Configuration.xml или каталогу выгрузки |
|
||||||
| `Mode` | Режим: `overview` (default), `brief`, `full` |
|
| `Mode` | Режим: `overview` (default), `brief`, `full` |
|
||||||
| `Section` | Drill-down по разделу (alias: `Name`). Сейчас: `home-page` |
|
| `Section` | Drill-down по разделу (alias: `Name`). Сейчас: `home-page` |
|
||||||
| `Limit` / `Offset` | Пагинация (по умолчанию 150 строк) |
|
| `Limit` / `Offset` | Пагинация (по умолчанию 150 строк) |
|
||||||
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
|
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-info.ps1" -ConfigPath "<путь>"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-info.ps1" -ConfigPath "<путь>"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Три режима
|
## Три режима
|
||||||
|
|
||||||
| Режим | Что показывает |
|
| Режим | Что показывает |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `overview` *(default)* | Заголовок + ключевые свойства + таблица счётчиков объектов по типам |
|
| `overview` *(default)* | Заголовок + ключевые свойства + таблица счётчиков объектов по типам |
|
||||||
| `brief` | Одна строка: Имя — "Синоним" vВерсия \| N объектов \| совместимость |
|
| `brief` | Одна строка: Имя — "Синоним" vВерсия \| N объектов \| совместимость |
|
||||||
| `full` | Все свойства по категориям + полный список ChildObjects + DefaultRoles + мобильные функциональности |
|
| `full` | Все свойства по категориям + полный список ChildObjects + DefaultRoles + мобильные функциональности |
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Обзор пустой конфигурации
|
# Обзор пустой конфигурации
|
||||||
... -ConfigPath src
|
... -ConfigPath src
|
||||||
|
|
||||||
# Краткая сводка реальной конфигурации
|
# Краткая сводка реальной конфигурации
|
||||||
... -ConfigPath src -Mode brief
|
... -ConfigPath src -Mode brief
|
||||||
|
|
||||||
# Полная информация
|
# Полная информация
|
||||||
... -ConfigPath src -Mode full
|
... -ConfigPath src -Mode full
|
||||||
|
|
||||||
# С пагинацией
|
# С пагинацией
|
||||||
... -ConfigPath src -Mode full -Limit 50 -Offset 100
|
... -ConfigPath src -Mode full -Limit 50 -Offset 100
|
||||||
|
|
||||||
# Drill-down: только начальная страница (раскладка форм с ролями)
|
# Drill-down: только начальная страница (раскладка форм с ролями)
|
||||||
... -ConfigPath src -Section home-page
|
... -ConfigPath src -Section home-page
|
||||||
```
|
```
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,49 +1,49 @@
|
|||||||
---
|
---
|
||||||
name: cf-init
|
name: cf-init
|
||||||
description: Создать пустую конфигурацию 1С (scaffold XML-исходников). Используй когда нужно начать новую конфигурацию с нуля
|
description: Создать пустую конфигурацию 1С (scaffold XML-исходников). Используй когда нужно начать новую конфигурацию с нуля
|
||||||
argument-hint: <Name> [-Synonym <name>] [-OutputDir src]
|
argument-hint: <Name> [-Synonym <name>] [-OutputDir src]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /cf-init — Создание пустой конфигурации 1С
|
# /cf-init — Создание пустой конфигурации 1С
|
||||||
|
|
||||||
Создаёт scaffold исходников пустой конфигурации 1С: `Configuration.xml`, `Languages/Русский.xml`.
|
Создаёт scaffold исходников пустой конфигурации 1С: `Configuration.xml`, `Languages/Русский.xml`.
|
||||||
|
|
||||||
## Параметры и команда
|
## Параметры и команда
|
||||||
|
|
||||||
| Параметр | Описание |
|
| Параметр | Описание |
|
||||||
|----------|----------|
|
|----------|----------|
|
||||||
| `Name` | Имя конфигурации (обязат.) |
|
| `Name` | Имя конфигурации (обязат.) |
|
||||||
| `Synonym` | Синоним (= Name если не указан) |
|
| `Synonym` | Синоним (= Name если не указан) |
|
||||||
| `OutputDir` | Каталог для создания (default: `src`) |
|
| `OutputDir` | Каталог для создания (default: `src`) |
|
||||||
| `Version` | Версия конфигурации |
|
| `Version` | Версия конфигурации |
|
||||||
| `Vendor` | Поставщик |
|
| `Vendor` | Поставщик |
|
||||||
| `CompatibilityMode` | Режим совместимости (default: `Version8_3_24`) |
|
| `CompatibilityMode` | Режим совместимости (default: `Version8_3_24`) |
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-init.ps1" -Name "МояКонфигурация"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-init.ps1" -Name "МояКонфигурация"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Базовая конфигурация
|
# Базовая конфигурация
|
||||||
... -Name МояКонфигурация -Synonym "Моя конфигурация" -OutputDir test-tmp/cf
|
... -Name МояКонфигурация -Synonym "Моя конфигурация" -OutputDir test-tmp/cf
|
||||||
|
|
||||||
# С версией и поставщиком
|
# С версией и поставщиком
|
||||||
... -Name TestCfg -Synonym "Тестовая" -Version "1.0.0.1" -Vendor "Фирма 1С" -OutputDir test-tmp/cf2
|
... -Name TestCfg -Synonym "Тестовая" -Version "1.0.0.1" -Vendor "Фирма 1С" -OutputDir test-tmp/cf2
|
||||||
|
|
||||||
# Другой режим совместимости
|
# Другой режим совместимости
|
||||||
... -Name TestCfg -CompatibilityMode Version8_3_27 -OutputDir test-tmp/cf3
|
... -Name TestCfg -CompatibilityMode Version8_3_27 -OutputDir test-tmp/cf3
|
||||||
```
|
```
|
||||||
|
|
||||||
## Верификация
|
## Верификация
|
||||||
|
|
||||||
```
|
```
|
||||||
/cf-init TestConfig -OutputDir test-tmp/cf
|
/cf-init TestConfig -OutputDir test-tmp/cf
|
||||||
/cf-info test-tmp/cf — проверить созданное
|
/cf-info test-tmp/cf — проверить созданное
|
||||||
/cf-validate test-tmp/cf — валидировать
|
/cf-validate test-tmp/cf — валидировать
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,249 +1,249 @@
|
|||||||
# cf-init v1.2 — Create empty 1C configuration scaffold
|
# cf-init v1.2 — Create empty 1C configuration scaffold
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$Name,
|
[string]$Name,
|
||||||
[string]$Synonym = $Name,
|
[string]$Synonym = $Name,
|
||||||
[string]$OutputDir = "src",
|
[string]$OutputDir = "src",
|
||||||
[string]$Version,
|
[string]$Version,
|
||||||
[string]$Vendor,
|
[string]$Vendor,
|
||||||
[string]$CompatibilityMode = "Version8_3_24"
|
[string]$CompatibilityMode = "Version8_3_24"
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Resolve output dir ---
|
# --- Resolve output dir ---
|
||||||
if (-not [System.IO.Path]::IsPathRooted($OutputDir)) {
|
if (-not [System.IO.Path]::IsPathRooted($OutputDir)) {
|
||||||
$OutputDir = Join-Path (Get-Location).Path $OutputDir
|
$OutputDir = Join-Path (Get-Location).Path $OutputDir
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Check existing ---
|
# --- Check existing ---
|
||||||
$cfgFile = Join-Path $OutputDir "Configuration.xml"
|
$cfgFile = Join-Path $OutputDir "Configuration.xml"
|
||||||
if (Test-Path $cfgFile) {
|
if (Test-Path $cfgFile) {
|
||||||
Write-Error "Configuration.xml already exists: $cfgFile"
|
Write-Error "Configuration.xml already exists: $cfgFile"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Generate UUIDs ---
|
# --- Generate UUIDs ---
|
||||||
$uuidCfg = [guid]::NewGuid().ToString()
|
$uuidCfg = [guid]::NewGuid().ToString()
|
||||||
$uuidLang = [guid]::NewGuid().ToString()
|
$uuidLang = [guid]::NewGuid().ToString()
|
||||||
# 7 ContainedObject ObjectIds
|
# 7 ContainedObject ObjectIds
|
||||||
$co1 = [guid]::NewGuid().ToString()
|
$co1 = [guid]::NewGuid().ToString()
|
||||||
$co2 = [guid]::NewGuid().ToString()
|
$co2 = [guid]::NewGuid().ToString()
|
||||||
$co3 = [guid]::NewGuid().ToString()
|
$co3 = [guid]::NewGuid().ToString()
|
||||||
$co4 = [guid]::NewGuid().ToString()
|
$co4 = [guid]::NewGuid().ToString()
|
||||||
$co5 = [guid]::NewGuid().ToString()
|
$co5 = [guid]::NewGuid().ToString()
|
||||||
$co6 = [guid]::NewGuid().ToString()
|
$co6 = [guid]::NewGuid().ToString()
|
||||||
$co7 = [guid]::NewGuid().ToString()
|
$co7 = [guid]::NewGuid().ToString()
|
||||||
|
|
||||||
# --- Mobile functionalities ---
|
# --- Mobile functionalities ---
|
||||||
$mobileFuncs = @(
|
$mobileFuncs = @(
|
||||||
@("Biometrics","true"), @("Location","false"), @("BackgroundLocation","false"),
|
@("Biometrics","true"), @("Location","false"), @("BackgroundLocation","false"),
|
||||||
@("BluetoothPrinters","false"), @("WiFiPrinters","false"), @("Contacts","false"),
|
@("BluetoothPrinters","false"), @("WiFiPrinters","false"), @("Contacts","false"),
|
||||||
@("Calendars","false"), @("PushNotifications","false"), @("LocalNotifications","false"),
|
@("Calendars","false"), @("PushNotifications","false"), @("LocalNotifications","false"),
|
||||||
@("InAppPurchases","false"), @("PersonalComputerFileExchange","false"), @("Ads","false"),
|
@("InAppPurchases","false"), @("PersonalComputerFileExchange","false"), @("Ads","false"),
|
||||||
@("NumberDialing","false"), @("CallProcessing","false"), @("CallLog","false"),
|
@("NumberDialing","false"), @("CallProcessing","false"), @("CallLog","false"),
|
||||||
@("AutoSendSMS","false"), @("ReceiveSMS","false"), @("SMSLog","false"),
|
@("AutoSendSMS","false"), @("ReceiveSMS","false"), @("SMSLog","false"),
|
||||||
@("Camera","false"), @("Microphone","false"), @("MusicLibrary","false"),
|
@("Camera","false"), @("Microphone","false"), @("MusicLibrary","false"),
|
||||||
@("PictureAndVideoLibraries","false"), @("AudioPlaybackAndVibration","false"),
|
@("PictureAndVideoLibraries","false"), @("AudioPlaybackAndVibration","false"),
|
||||||
@("BackgroundAudioPlaybackAndVibration","false"), @("InstallPackages","false"),
|
@("BackgroundAudioPlaybackAndVibration","false"), @("InstallPackages","false"),
|
||||||
@("OSBackup","true"), @("ApplicationUsageStatistics","false"),
|
@("OSBackup","true"), @("ApplicationUsageStatistics","false"),
|
||||||
@("BarcodeScanning","false"), @("BackgroundAudioRecording","false"),
|
@("BarcodeScanning","false"), @("BackgroundAudioRecording","false"),
|
||||||
@("AllFilesAccess","false"), @("Videoconferences","false"), @("NFC","false"),
|
@("AllFilesAccess","false"), @("Videoconferences","false"), @("NFC","false"),
|
||||||
@("DocumentScanning","false"), @("SpeechToText","false"), @("Geofences","false"),
|
@("DocumentScanning","false"), @("SpeechToText","false"), @("Geofences","false"),
|
||||||
@("IncomingShareRequests","false"), @("AllIncomingShareRequestsTypesProcessing","false")
|
@("IncomingShareRequests","false"), @("AllIncomingShareRequestsTypesProcessing","false")
|
||||||
)
|
)
|
||||||
|
|
||||||
$mobileXml = ""
|
$mobileXml = ""
|
||||||
foreach ($mf in $mobileFuncs) {
|
foreach ($mf in $mobileFuncs) {
|
||||||
$mobileXml += "`r`n`t`t`t`t<app:functionality>`r`n`t`t`t`t`t<app:functionality>$($mf[0])</app:functionality>`r`n`t`t`t`t`t<app:use>$($mf[1])</app:use>`r`n`t`t`t`t</app:functionality>"
|
$mobileXml += "`r`n`t`t`t`t<app:functionality>`r`n`t`t`t`t`t<app:functionality>$($mf[0])</app:functionality>`r`n`t`t`t`t`t<app:use>$($mf[1])</app:use>`r`n`t`t`t`t</app:functionality>"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Synonym XML ---
|
# --- Synonym XML ---
|
||||||
$synonymXml = ""
|
$synonymXml = ""
|
||||||
if ($Synonym) {
|
if ($Synonym) {
|
||||||
$synonymXml = "`r`n`t`t`t`t<v8:item>`r`n`t`t`t`t`t<v8:lang>ru</v8:lang>`r`n`t`t`t`t`t<v8:content>$([System.Security.SecurityElement]::Escape($Synonym))</v8:content>`r`n`t`t`t`t</v8:item>`r`n`t`t`t"
|
$synonymXml = "`r`n`t`t`t`t<v8:item>`r`n`t`t`t`t`t<v8:lang>ru</v8:lang>`r`n`t`t`t`t`t<v8:content>$([System.Security.SecurityElement]::Escape($Synonym))</v8:content>`r`n`t`t`t`t</v8:item>`r`n`t`t`t"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Optional properties ---
|
# --- Optional properties ---
|
||||||
$vendorXml = if ($Vendor) { [System.Security.SecurityElement]::Escape($Vendor) } else { "" }
|
$vendorXml = if ($Vendor) { [System.Security.SecurityElement]::Escape($Vendor) } else { "" }
|
||||||
$versionXml = if ($Version) { [System.Security.SecurityElement]::Escape($Version) } else { "" }
|
$versionXml = if ($Version) { [System.Security.SecurityElement]::Escape($Version) } else { "" }
|
||||||
|
|
||||||
# --- Configuration.xml ---
|
# --- Configuration.xml ---
|
||||||
$cfgXml = @"
|
$cfgXml = @"
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
||||||
<Configuration uuid="$uuidCfg">
|
<Configuration uuid="$uuidCfg">
|
||||||
<InternalInfo>
|
<InternalInfo>
|
||||||
<xr:ContainedObject>
|
<xr:ContainedObject>
|
||||||
<xr:ClassId>9cd510cd-abfc-11d4-9434-004095e12fc7</xr:ClassId>
|
<xr:ClassId>9cd510cd-abfc-11d4-9434-004095e12fc7</xr:ClassId>
|
||||||
<xr:ObjectId>$co1</xr:ObjectId>
|
<xr:ObjectId>$co1</xr:ObjectId>
|
||||||
</xr:ContainedObject>
|
</xr:ContainedObject>
|
||||||
<xr:ContainedObject>
|
<xr:ContainedObject>
|
||||||
<xr:ClassId>9fcd25a0-4822-11d4-9414-008048da11f9</xr:ClassId>
|
<xr:ClassId>9fcd25a0-4822-11d4-9414-008048da11f9</xr:ClassId>
|
||||||
<xr:ObjectId>$co2</xr:ObjectId>
|
<xr:ObjectId>$co2</xr:ObjectId>
|
||||||
</xr:ContainedObject>
|
</xr:ContainedObject>
|
||||||
<xr:ContainedObject>
|
<xr:ContainedObject>
|
||||||
<xr:ClassId>e3687481-0a87-462c-a166-9f34594f9bba</xr:ClassId>
|
<xr:ClassId>e3687481-0a87-462c-a166-9f34594f9bba</xr:ClassId>
|
||||||
<xr:ObjectId>$co3</xr:ObjectId>
|
<xr:ObjectId>$co3</xr:ObjectId>
|
||||||
</xr:ContainedObject>
|
</xr:ContainedObject>
|
||||||
<xr:ContainedObject>
|
<xr:ContainedObject>
|
||||||
<xr:ClassId>9de14907-ec23-4a07-96f0-85521cb6b53b</xr:ClassId>
|
<xr:ClassId>9de14907-ec23-4a07-96f0-85521cb6b53b</xr:ClassId>
|
||||||
<xr:ObjectId>$co4</xr:ObjectId>
|
<xr:ObjectId>$co4</xr:ObjectId>
|
||||||
</xr:ContainedObject>
|
</xr:ContainedObject>
|
||||||
<xr:ContainedObject>
|
<xr:ContainedObject>
|
||||||
<xr:ClassId>51f2d5d8-ea4d-4064-8892-82951750031e</xr:ClassId>
|
<xr:ClassId>51f2d5d8-ea4d-4064-8892-82951750031e</xr:ClassId>
|
||||||
<xr:ObjectId>$co5</xr:ObjectId>
|
<xr:ObjectId>$co5</xr:ObjectId>
|
||||||
</xr:ContainedObject>
|
</xr:ContainedObject>
|
||||||
<xr:ContainedObject>
|
<xr:ContainedObject>
|
||||||
<xr:ClassId>e68182ea-4237-4383-967f-90c1e3370bc7</xr:ClassId>
|
<xr:ClassId>e68182ea-4237-4383-967f-90c1e3370bc7</xr:ClassId>
|
||||||
<xr:ObjectId>$co6</xr:ObjectId>
|
<xr:ObjectId>$co6</xr:ObjectId>
|
||||||
</xr:ContainedObject>
|
</xr:ContainedObject>
|
||||||
<xr:ContainedObject>
|
<xr:ContainedObject>
|
||||||
<xr:ClassId>fb282519-d103-4dd3-bc12-cb271d631dfc</xr:ClassId>
|
<xr:ClassId>fb282519-d103-4dd3-bc12-cb271d631dfc</xr:ClassId>
|
||||||
<xr:ObjectId>$co7</xr:ObjectId>
|
<xr:ObjectId>$co7</xr:ObjectId>
|
||||||
</xr:ContainedObject>
|
</xr:ContainedObject>
|
||||||
</InternalInfo>
|
</InternalInfo>
|
||||||
<Properties>
|
<Properties>
|
||||||
<Name>$([System.Security.SecurityElement]::Escape($Name))</Name>
|
<Name>$([System.Security.SecurityElement]::Escape($Name))</Name>
|
||||||
<Synonym>$synonymXml</Synonym>
|
<Synonym>$synonymXml</Synonym>
|
||||||
<Comment/>
|
<Comment/>
|
||||||
<NamePrefix/>
|
<NamePrefix/>
|
||||||
<ConfigurationExtensionCompatibilityMode>$CompatibilityMode</ConfigurationExtensionCompatibilityMode>
|
<ConfigurationExtensionCompatibilityMode>$CompatibilityMode</ConfigurationExtensionCompatibilityMode>
|
||||||
<DefaultRunMode>ManagedApplication</DefaultRunMode>
|
<DefaultRunMode>ManagedApplication</DefaultRunMode>
|
||||||
<UsePurposes>
|
<UsePurposes>
|
||||||
<v8:Value xsi:type="app:ApplicationUsePurpose">PlatformApplication</v8:Value>
|
<v8:Value xsi:type="app:ApplicationUsePurpose">PlatformApplication</v8:Value>
|
||||||
</UsePurposes>
|
</UsePurposes>
|
||||||
<ScriptVariant>Russian</ScriptVariant>
|
<ScriptVariant>Russian</ScriptVariant>
|
||||||
<DefaultRoles/>
|
<DefaultRoles/>
|
||||||
<Vendor>$vendorXml</Vendor>
|
<Vendor>$vendorXml</Vendor>
|
||||||
<Version>$versionXml</Version>
|
<Version>$versionXml</Version>
|
||||||
<UpdateCatalogAddress/>
|
<UpdateCatalogAddress/>
|
||||||
<IncludeHelpInContents>false</IncludeHelpInContents>
|
<IncludeHelpInContents>false</IncludeHelpInContents>
|
||||||
<UseManagedFormInOrdinaryApplication>false</UseManagedFormInOrdinaryApplication>
|
<UseManagedFormInOrdinaryApplication>false</UseManagedFormInOrdinaryApplication>
|
||||||
<UseOrdinaryFormInManagedApplication>false</UseOrdinaryFormInManagedApplication>
|
<UseOrdinaryFormInManagedApplication>false</UseOrdinaryFormInManagedApplication>
|
||||||
<AdditionalFullTextSearchDictionaries/>
|
<AdditionalFullTextSearchDictionaries/>
|
||||||
<CommonSettingsStorage/>
|
<CommonSettingsStorage/>
|
||||||
<ReportsUserSettingsStorage/>
|
<ReportsUserSettingsStorage/>
|
||||||
<ReportsVariantsStorage/>
|
<ReportsVariantsStorage/>
|
||||||
<FormDataSettingsStorage/>
|
<FormDataSettingsStorage/>
|
||||||
<DynamicListsUserSettingsStorage/>
|
<DynamicListsUserSettingsStorage/>
|
||||||
<URLExternalDataStorage/>
|
<URLExternalDataStorage/>
|
||||||
<Content/>
|
<Content/>
|
||||||
<DefaultReportForm/>
|
<DefaultReportForm/>
|
||||||
<DefaultReportVariantForm/>
|
<DefaultReportVariantForm/>
|
||||||
<DefaultReportSettingsForm/>
|
<DefaultReportSettingsForm/>
|
||||||
<DefaultReportAppearanceTemplate/>
|
<DefaultReportAppearanceTemplate/>
|
||||||
<DefaultDynamicListSettingsForm/>
|
<DefaultDynamicListSettingsForm/>
|
||||||
<DefaultSearchForm/>
|
<DefaultSearchForm/>
|
||||||
<DefaultDataHistoryChangeHistoryForm/>
|
<DefaultDataHistoryChangeHistoryForm/>
|
||||||
<DefaultDataHistoryVersionDataForm/>
|
<DefaultDataHistoryVersionDataForm/>
|
||||||
<DefaultDataHistoryVersionDifferencesForm/>
|
<DefaultDataHistoryVersionDifferencesForm/>
|
||||||
<DefaultCollaborationSystemUsersChoiceForm/>
|
<DefaultCollaborationSystemUsersChoiceForm/>
|
||||||
<RequiredMobileApplicationPermissions/>
|
<RequiredMobileApplicationPermissions/>
|
||||||
<UsedMobileApplicationFunctionalities>$mobileXml
|
<UsedMobileApplicationFunctionalities>$mobileXml
|
||||||
</UsedMobileApplicationFunctionalities>
|
</UsedMobileApplicationFunctionalities>
|
||||||
<StandaloneConfigurationRestrictionRoles/>
|
<StandaloneConfigurationRestrictionRoles/>
|
||||||
<MobileApplicationURLs/>
|
<MobileApplicationURLs/>
|
||||||
<AllowedIncomingShareRequestTypes/>
|
<AllowedIncomingShareRequestTypes/>
|
||||||
<MainClientApplicationWindowMode>Normal</MainClientApplicationWindowMode>
|
<MainClientApplicationWindowMode>Normal</MainClientApplicationWindowMode>
|
||||||
<DefaultInterface/>
|
<DefaultInterface/>
|
||||||
<DefaultStyle/>
|
<DefaultStyle/>
|
||||||
<DefaultLanguage>Language.Русский</DefaultLanguage>
|
<DefaultLanguage>Language.Русский</DefaultLanguage>
|
||||||
<BriefInformation/>
|
<BriefInformation/>
|
||||||
<DetailedInformation/>
|
<DetailedInformation/>
|
||||||
<Copyright/>
|
<Copyright/>
|
||||||
<VendorInformationAddress/>
|
<VendorInformationAddress/>
|
||||||
<ConfigurationInformationAddress/>
|
<ConfigurationInformationAddress/>
|
||||||
<DataLockControlMode>Managed</DataLockControlMode>
|
<DataLockControlMode>Managed</DataLockControlMode>
|
||||||
<ObjectAutonumerationMode>NotAutoFree</ObjectAutonumerationMode>
|
<ObjectAutonumerationMode>NotAutoFree</ObjectAutonumerationMode>
|
||||||
<ModalityUseMode>DontUse</ModalityUseMode>
|
<ModalityUseMode>DontUse</ModalityUseMode>
|
||||||
<SynchronousPlatformExtensionAndAddInCallUseMode>DontUse</SynchronousPlatformExtensionAndAddInCallUseMode>
|
<SynchronousPlatformExtensionAndAddInCallUseMode>DontUse</SynchronousPlatformExtensionAndAddInCallUseMode>
|
||||||
<InterfaceCompatibilityMode>TaxiEnableVersion8_2</InterfaceCompatibilityMode>
|
<InterfaceCompatibilityMode>TaxiEnableVersion8_2</InterfaceCompatibilityMode>
|
||||||
<DatabaseTablespacesUseMode>DontUse</DatabaseTablespacesUseMode>
|
<DatabaseTablespacesUseMode>DontUse</DatabaseTablespacesUseMode>
|
||||||
<CompatibilityMode>$CompatibilityMode</CompatibilityMode>
|
<CompatibilityMode>$CompatibilityMode</CompatibilityMode>
|
||||||
<DefaultConstantsForm/>
|
<DefaultConstantsForm/>
|
||||||
</Properties>
|
</Properties>
|
||||||
<ChildObjects>
|
<ChildObjects>
|
||||||
<Language>Русский</Language>
|
<Language>Русский</Language>
|
||||||
</ChildObjects>
|
</ChildObjects>
|
||||||
</Configuration>
|
</Configuration>
|
||||||
</MetaDataObject>
|
</MetaDataObject>
|
||||||
"@
|
"@
|
||||||
|
|
||||||
# --- Languages/Русский.xml ---
|
# --- Languages/Русский.xml ---
|
||||||
$langXml = @"
|
$langXml = @"
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
||||||
<Language uuid="$uuidLang">
|
<Language uuid="$uuidLang">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Name>Русский</Name>
|
<Name>Русский</Name>
|
||||||
<Synonym>
|
<Synonym>
|
||||||
<v8:item>
|
<v8:item>
|
||||||
<v8:lang>ru</v8:lang>
|
<v8:lang>ru</v8:lang>
|
||||||
<v8:content>Русский</v8:content>
|
<v8:content>Русский</v8:content>
|
||||||
</v8:item>
|
</v8:item>
|
||||||
</Synonym>
|
</Synonym>
|
||||||
<Comment/>
|
<Comment/>
|
||||||
<LanguageCode>ru</LanguageCode>
|
<LanguageCode>ru</LanguageCode>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Language>
|
</Language>
|
||||||
</MetaDataObject>
|
</MetaDataObject>
|
||||||
"@
|
"@
|
||||||
|
|
||||||
# --- Ext/ClientApplicationInterface.xml (default ERP-style panel layout) ---
|
# --- Ext/ClientApplicationInterface.xml (default ERP-style panel layout) ---
|
||||||
# Open panel on top, Sections panel on left; Functions/Favorites/History declared
|
# Open panel on top, Sections panel on left; Functions/Favorites/History declared
|
||||||
# via panelDef but not placed by default. Without this file the web client renders
|
# via panelDef but not placed by default. Without this file the web client renders
|
||||||
# section icons without labels (icon-only mode).
|
# section icons without labels (icon-only mode).
|
||||||
$openPanelInst = [guid]::NewGuid().ToString()
|
$openPanelInst = [guid]::NewGuid().ToString()
|
||||||
$sectionsPanelInst = [guid]::NewGuid().ToString()
|
$sectionsPanelInst = [guid]::NewGuid().ToString()
|
||||||
$caiXml = @"
|
$caiXml = @"
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ClientApplicationInterface xmlns="http://v8.1c.ru/8.2/managed-application/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="InterfaceLayouter">
|
<ClientApplicationInterface xmlns="http://v8.1c.ru/8.2/managed-application/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="InterfaceLayouter">
|
||||||
<top>
|
<top>
|
||||||
<panel id="$openPanelInst">
|
<panel id="$openPanelInst">
|
||||||
<uuid>cbab57f2-a0f3-4f0a-89ea-4cb19570ab75</uuid>
|
<uuid>cbab57f2-a0f3-4f0a-89ea-4cb19570ab75</uuid>
|
||||||
</panel>
|
</panel>
|
||||||
</top>
|
</top>
|
||||||
<left>
|
<left>
|
||||||
<panel id="$sectionsPanelInst">
|
<panel id="$sectionsPanelInst">
|
||||||
<uuid>b553047f-c9aa-4157-978d-448ecad24248</uuid>
|
<uuid>b553047f-c9aa-4157-978d-448ecad24248</uuid>
|
||||||
</panel>
|
</panel>
|
||||||
</left>
|
</left>
|
||||||
<panelDef id="b553047f-c9aa-4157-978d-448ecad24248"/>
|
<panelDef id="b553047f-c9aa-4157-978d-448ecad24248"/>
|
||||||
<panelDef id="13322b22-3960-4d68-93a6-fe2dd7f28ca3"/>
|
<panelDef id="13322b22-3960-4d68-93a6-fe2dd7f28ca3"/>
|
||||||
<panelDef id="c933ac92-92cd-459d-81cc-e0c8a83ced99"/>
|
<panelDef id="c933ac92-92cd-459d-81cc-e0c8a83ced99"/>
|
||||||
<panelDef id="cbab57f2-a0f3-4f0a-89ea-4cb19570ab75"/>
|
<panelDef id="cbab57f2-a0f3-4f0a-89ea-4cb19570ab75"/>
|
||||||
<panelDef id="b2735bd3-d822-4430-ba59-c9e869693b24"/>
|
<panelDef id="b2735bd3-d822-4430-ba59-c9e869693b24"/>
|
||||||
</ClientApplicationInterface>
|
</ClientApplicationInterface>
|
||||||
"@
|
"@
|
||||||
|
|
||||||
# --- Create directories ---
|
# --- Create directories ---
|
||||||
if (-not (Test-Path $OutputDir)) {
|
if (-not (Test-Path $OutputDir)) {
|
||||||
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
|
||||||
}
|
}
|
||||||
$langDir = Join-Path $OutputDir "Languages"
|
$langDir = Join-Path $OutputDir "Languages"
|
||||||
if (-not (Test-Path $langDir)) {
|
if (-not (Test-Path $langDir)) {
|
||||||
New-Item -ItemType Directory -Path $langDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $langDir -Force | Out-Null
|
||||||
}
|
}
|
||||||
$extDir = Join-Path $OutputDir "Ext"
|
$extDir = Join-Path $OutputDir "Ext"
|
||||||
if (-not (Test-Path $extDir)) {
|
if (-not (Test-Path $extDir)) {
|
||||||
New-Item -ItemType Directory -Path $extDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $extDir -Force | Out-Null
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Write files with UTF-8 BOM ---
|
# --- Write files with UTF-8 BOM ---
|
||||||
$enc = New-Object System.Text.UTF8Encoding($true)
|
$enc = New-Object System.Text.UTF8Encoding($true)
|
||||||
|
|
||||||
[System.IO.File]::WriteAllText($cfgFile, $cfgXml, $enc)
|
[System.IO.File]::WriteAllText($cfgFile, $cfgXml, $enc)
|
||||||
$langFile = Join-Path $langDir "Русский.xml"
|
$langFile = Join-Path $langDir "Русский.xml"
|
||||||
[System.IO.File]::WriteAllText($langFile, $langXml, $enc)
|
[System.IO.File]::WriteAllText($langFile, $langXml, $enc)
|
||||||
$caiFile = Join-Path $extDir "ClientApplicationInterface.xml"
|
$caiFile = Join-Path $extDir "ClientApplicationInterface.xml"
|
||||||
[System.IO.File]::WriteAllText($caiFile, $caiXml, $enc)
|
[System.IO.File]::WriteAllText($caiFile, $caiXml, $enc)
|
||||||
|
|
||||||
# --- Output ---
|
# --- Output ---
|
||||||
Write-Host "[OK] Создана конфигурация: $Name"
|
Write-Host "[OK] Создана конфигурация: $Name"
|
||||||
Write-Host " Каталог: $OutputDir"
|
Write-Host " Каталог: $OutputDir"
|
||||||
Write-Host " Configuration.xml: $cfgFile"
|
Write-Host " Configuration.xml: $cfgFile"
|
||||||
Write-Host " Languages: $langFile"
|
Write-Host " Languages: $langFile"
|
||||||
Write-Host " Ext/CAI: $caiFile"
|
Write-Host " Ext/CAI: $caiFile"
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
---
|
---
|
||||||
name: cf-validate
|
name: cf-validate
|
||||||
description: Валидация конфигурации 1С. Используй после создания или модификации конфигурации для проверки корректности
|
description: Валидация конфигурации 1С. Используй после создания или модификации конфигурации для проверки корректности
|
||||||
argument-hint: <ConfigPath> [-Detailed] [-MaxErrors 30]
|
argument-hint: <ConfigPath> [-Detailed] [-MaxErrors 30]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /cf-validate — валидация конфигурации 1С
|
# /cf-validate — валидация конфигурации 1С
|
||||||
|
|
||||||
Проверяет Configuration.xml на структурные ошибки: XML well-formedness, InternalInfo, свойства, enum-значения, ChildObjects, DefaultLanguage, файлы языков, каталоги объектов.
|
Проверяет Configuration.xml на структурные ошибки: XML well-formedness, InternalInfo, свойства, enum-значения, ChildObjects, DefaultLanguage, файлы языков, каталоги объектов.
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Обяз. | Умолч. | Описание |
|
| Параметр | Обяз. | Умолч. | Описание |
|
||||||
|------------|:-----:|---------|-------------------------------------------------|
|
|------------|:-----:|---------|-------------------------------------------------|
|
||||||
| ConfigPath | да | — | Путь к Configuration.xml или каталогу выгрузки |
|
| ConfigPath | да | — | Путь к Configuration.xml или каталогу выгрузки |
|
||||||
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
||||||
| MaxErrors | нет | 30 | Остановиться после N ошибок |
|
| MaxErrors | нет | 30 | Остановиться после N ошибок |
|
||||||
| OutFile | нет | — | Записать результат в файл (UTF-8 BOM) |
|
| OutFile | нет | — | Записать результат в файл (UTF-8 BOM) |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-validate.ps1" -ConfigPath "upload/cfempty"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-validate.ps1" -ConfigPath "upload/cfempty"
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-validate.ps1" -ConfigPath "upload/cfempty/Configuration.xml"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-validate.ps1" -ConfigPath "upload/cfempty/Configuration.xml"
|
||||||
```
|
```
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+101
-101
@@ -1,101 +1,101 @@
|
|||||||
---
|
---
|
||||||
name: cfe-borrow
|
name: cfe-borrow
|
||||||
description: Заимствование объектов из конфигурации 1С в расширение (CFE). Используй когда нужно перехватить метод, изменить форму или добавить реквизит к существующему объекту конфигурации
|
description: Заимствование объектов из конфигурации 1С в расширение (CFE). Используй когда нужно перехватить метод, изменить форму или добавить реквизит к существующему объекту конфигурации
|
||||||
argument-hint: -ExtensionPath <path> -ConfigPath <path> -Object "Catalog.Контрагенты.Form.ФормаЭлемента" -BorrowMainAttribute
|
argument-hint: -ExtensionPath <path> -ConfigPath <path> -Object "Catalog.Контрагенты.Form.ФормаЭлемента" -BorrowMainAttribute
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /cfe-borrow — Заимствование объектов из конфигурации
|
# /cfe-borrow — Заимствование объектов из конфигурации
|
||||||
|
|
||||||
Заимствует объекты из основной конфигурации в расширение. Создаёт XML-файлы с `ObjectBelonging=Adopted` и `ExtendedConfigurationObject`, добавляет запись в ChildObjects расширения.
|
Заимствует объекты из основной конфигурации в расширение. Создаёт XML-файлы с `ObjectBelonging=Adopted` и `ExtendedConfigurationObject`, добавляет запись в ChildObjects расширения.
|
||||||
|
|
||||||
## Предусловие
|
## Предусловие
|
||||||
|
|
||||||
Расширение должно быть создано (`/cfe-init`) и содержать валидный `Configuration.xml`.
|
Расширение должно быть создано (`/cfe-init`) и содержать валидный `Configuration.xml`.
|
||||||
|
|
||||||
### Авто-определение ConfigPath
|
### Авто-определение ConfigPath
|
||||||
|
|
||||||
Если пользователь не указал `-ConfigPath` — попробуй определить автоматически:
|
Если пользователь не указал `-ConfigPath` — попробуй определить автоматически:
|
||||||
1. Прочитай `.v8-project.json` из корня проекта
|
1. Прочитай `.v8-project.json` из корня проекта
|
||||||
2. Разреши целевую базу (по имени, ветке или `default` — алгоритм из `/db-list`)
|
2. Разреши целевую базу (по имени, ветке или `default` — алгоритм из `/db-list`)
|
||||||
3. Если у базы есть поле `configSrc` — используй как `-ConfigPath`
|
3. Если у базы есть поле `configSrc` — используй как `-ConfigPath`
|
||||||
4. Если `configSrc` нет — спроси у пользователя
|
4. Если `configSrc` нет — спроси у пользователя
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Описание |
|
| Параметр | Описание |
|
||||||
|----------|----------|
|
|----------|----------|
|
||||||
| `ExtensionPath` | Путь к каталогу расширения (обязат.) |
|
| `ExtensionPath` | Путь к каталогу расширения (обязат.) |
|
||||||
| `ConfigPath` | Путь к конфигурации-источнику (обязат.) |
|
| `ConfigPath` | Путь к конфигурации-источнику (обязат.) |
|
||||||
| `Object` | Что заимствовать (обязат.), batch через `;;` |
|
| `Object` | Что заимствовать (обязат.), batch через `;;` |
|
||||||
| `BorrowMainAttribute` | Заимствовать основной реквизит формы. Без параметра — не заимствует. `Form` — реквизиты, используемые на форме. `All` — все реквизиты объекта. Требует форму в -Object |
|
| `BorrowMainAttribute` | Заимствовать основной реквизит формы. Без параметра — не заимствует. `Form` — реквизиты, используемые на форме. `All` — все реквизиты объекта. Требует форму в -Object |
|
||||||
|
|
||||||
## Формат -Object
|
## Формат -Object
|
||||||
|
|
||||||
- `Catalog.Контрагенты` — справочник
|
- `Catalog.Контрагенты` — справочник
|
||||||
- `CommonModule.РаботаСФайлами` — общий модуль
|
- `CommonModule.РаботаСФайлами` — общий модуль
|
||||||
- `Document.РеализацияТоваров` — документ
|
- `Document.РеализацияТоваров` — документ
|
||||||
- `Enum.ВидыОплат` — перечисление
|
- `Enum.ВидыОплат` — перечисление
|
||||||
- `Catalog.Контрагенты.Form.ФормаЭлемента` — форма объекта (заимствование формы)
|
- `Catalog.Контрагенты.Form.ФормаЭлемента` — форма объекта (заимствование формы)
|
||||||
- `Catalog.X ;; CommonModule.Y ;; Enum.Z` — несколько объектов
|
- `Catalog.X ;; CommonModule.Y ;; Enum.Z` — несколько объектов
|
||||||
Поддерживаются все 44 типа объектов конфигурации.
|
Поддерживаются все 44 типа объектов конфигурации.
|
||||||
|
|
||||||
### Заимствование форм
|
### Заимствование форм
|
||||||
|
|
||||||
Формат `Тип.Имя.Form.ИмяФормы` заимствует форму конкретного объекта. Если родительский объект ещё не заимствован — он будет заимствован автоматически.
|
Формат `Тип.Имя.Form.ИмяФормы` заимствует форму конкретного объекта. Если родительский объект ещё не заимствован — он будет заимствован автоматически.
|
||||||
|
|
||||||
Создаётся:
|
Создаётся:
|
||||||
1. **Метаданные формы** — `Forms/ИмяФормы.xml` с `ObjectBelonging=Adopted`, `FormType=Managed`
|
1. **Метаданные формы** — `Forms/ИмяФормы.xml` с `ObjectBelonging=Adopted`, `FormType=Managed`
|
||||||
2. **Form.xml** — `Forms/ИмяФормы/Ext/Form.xml` с копией исходной формы + `<BaseForm>` (начальное состояние)
|
2. **Form.xml** — `Forms/ИмяФормы/Ext/Form.xml` с копией исходной формы + `<BaseForm>` (начальное состояние)
|
||||||
3. **Module.bsl** — пустой файл `Forms/ИмяФормы/Ext/Form/Module.bsl`
|
3. **Module.bsl** — пустой файл `Forms/ИмяФормы/Ext/Form/Module.bsl`
|
||||||
4. **Регистрация** — `<Form>` в ChildObjects родительского объекта
|
4. **Регистрация** — `<Form>` в ChildObjects родительского объекта
|
||||||
|
|
||||||
### Заимствование основного реквизита формы (-BorrowMainAttribute)
|
### Заимствование основного реквизита формы (-BorrowMainAttribute)
|
||||||
|
|
||||||
**Когда нужно**: пользователь хочет добавить новый реквизит в существующий объект конфигурации и вывести его на заимствованную форму. Без `-BorrowMainAttribute` форма заимствуется "пустой" — только визуальные элементы, без привязки к данным объекта. С `-BorrowMainAttribute` форма сохраняет привязки к реквизитам объекта (DataPath), что позволяет затем добавить на неё новые элементы через `/form-edit`.
|
**Когда нужно**: пользователь хочет добавить новый реквизит в существующий объект конфигурации и вывести его на заимствованную форму. Без `-BorrowMainAttribute` форма заимствуется "пустой" — только визуальные элементы, без привязки к данным объекта. С `-BorrowMainAttribute` форма сохраняет привязки к реквизитам объекта (DataPath), что позволяет затем добавить на неё новые элементы через `/form-edit`.
|
||||||
|
|
||||||
**Два режима**:
|
**Два режима**:
|
||||||
- `Form` (по умолчанию) — заимствует только те реквизиты объекта, которые уже выведены на форму. Оптимальный выбор для большинства случаев
|
- `Form` (по умолчанию) — заимствует только те реквизиты объекта, которые уже выведены на форму. Оптимальный выбор для большинства случаев
|
||||||
- `All` — заимствует все реквизиты и табличные части объекта. Используй если планируешь выводить на форму реквизиты, которых на ней ещё нет
|
- `All` — заимствует все реквизиты и табличные части объекта. Используй если планируешь выводить на форму реквизиты, которых на ней ещё нет
|
||||||
|
|
||||||
**Типовой сценарий** (добавление реквизита + вывод на форму):
|
**Типовой сценарий** (добавление реквизита + вывод на форму):
|
||||||
1. `/cfe-borrow` с `-BorrowMainAttribute` — заимствовать форму с реквизитами
|
1. `/cfe-borrow` с `-BorrowMainAttribute` — заимствовать форму с реквизитами
|
||||||
2. `/meta-edit` — добавить новый реквизит в объект расширения
|
2. `/meta-edit` — добавить новый реквизит в объект расширения
|
||||||
3. `/form-edit` — вывести реквизит на заимствованную форму
|
3. `/form-edit` — вывести реквизит на заимствованную форму
|
||||||
|
|
||||||
**Защита существующих данных**: если зависимый объект уже заимствован с содержимым (реквизитами, формами) — скрипт не перезаписывает его, а добавляет только недостающее.
|
**Защита существующих данных**: если зависимый объект уже заимствован с содержимым (реквизитами, формами) — скрипт не перезаписывает его, а добавляет только недостающее.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-borrow.ps1" -ExtensionPath src -ConfigPath C:\cfsrc\erp -Object "Catalog.Контрагенты"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-borrow.ps1" -ExtensionPath src -ConfigPath C:\cfsrc\erp -Object "Catalog.Контрагенты"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Заимствовать один объект
|
# Заимствовать один объект
|
||||||
... -ExtensionPath src -ConfigPath C:\cfsrc\erp -Object "Catalog.Контрагенты"
|
... -ExtensionPath src -ConfigPath C:\cfsrc\erp -Object "Catalog.Контрагенты"
|
||||||
|
|
||||||
# Заимствовать форму (автоматически заимствует родительский объект)
|
# Заимствовать форму (автоматически заимствует родительский объект)
|
||||||
... -ExtensionPath src -ConfigPath C:\cfsrc\erp -Object "Catalog.Контрагенты.Form.ФормаЭлемента"
|
... -ExtensionPath src -ConfigPath C:\cfsrc\erp -Object "Catalog.Контрагенты.Form.ФормаЭлемента"
|
||||||
|
|
||||||
# Несколько объектов за раз
|
# Несколько объектов за раз
|
||||||
... -ExtensionPath src -ConfigPath C:\cfsrc\erp -Object "Catalog.Контрагенты ;; CommonModule.ОбщийМодуль ;; Enum.ВидыОплат"
|
... -ExtensionPath src -ConfigPath C:\cfsrc\erp -Object "Catalog.Контрагенты ;; CommonModule.ОбщийМодуль ;; Enum.ВидыОплат"
|
||||||
|
|
||||||
# Заимствовать форму с основным реквизитом (реквизиты по DataPath формы)
|
# Заимствовать форму с основным реквизитом (реквизиты по DataPath формы)
|
||||||
... -ExtensionPath src -ConfigPath C:\cfsrc\erp -Object "Catalog.Номенклатура.Form.ФормаЭлемента" -BorrowMainAttribute
|
... -ExtensionPath src -ConfigPath C:\cfsrc\erp -Object "Catalog.Номенклатура.Form.ФормаЭлемента" -BorrowMainAttribute
|
||||||
|
|
||||||
# Заимствовать форму с ВСЕМИ реквизитами объекта
|
# Заимствовать форму с ВСЕМИ реквизитами объекта
|
||||||
... -ExtensionPath src -ConfigPath C:\cfsrc\erp -Object "Catalog.Номенклатура.Form.ФормаЭлемента" -BorrowMainAttribute All
|
... -ExtensionPath src -ConfigPath C:\cfsrc\erp -Object "Catalog.Номенклатура.Form.ФормаЭлемента" -BorrowMainAttribute All
|
||||||
```
|
```
|
||||||
|
|
||||||
## Верификация
|
## Верификация
|
||||||
|
|
||||||
```
|
```
|
||||||
/cfe-validate <ExtensionPath>
|
/cfe-validate <ExtensionPath>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,57 +1,57 @@
|
|||||||
---
|
---
|
||||||
name: cfe-diff
|
name: cfe-diff
|
||||||
description: Анализ расширения конфигурации 1С (CFE) — состав, заимствованные объекты, перехватчики, проверка переноса. Используй когда нужно понять что содержит расширение или проверить перенесены ли вставки в конфигурацию
|
description: Анализ расширения конфигурации 1С (CFE) — состав, заимствованные объекты, перехватчики, проверка переноса. Используй когда нужно понять что содержит расширение или проверить перенесены ли вставки в конфигурацию
|
||||||
argument-hint: -ExtensionPath <path> -ConfigPath <path> [-Mode A|B]
|
argument-hint: -ExtensionPath <path> -ConfigPath <path> [-Mode A|B]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /cfe-diff — Анализ расширения конфигурации
|
# /cfe-diff — Анализ расширения конфигурации
|
||||||
|
|
||||||
Анализирует расширение в двух режимах: обзор изменений (Mode A) или проверка переноса (Mode B).
|
Анализирует расширение в двух режимах: обзор изменений (Mode A) или проверка переноса (Mode B).
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Описание | По умолчанию |
|
| Параметр | Описание | По умолчанию |
|
||||||
|----------|----------|--------------|
|
|----------|----------|--------------|
|
||||||
| `ExtensionPath` | Путь к расширению (обязат.) | — |
|
| `ExtensionPath` | Путь к расширению (обязат.) | — |
|
||||||
| `ConfigPath` | Путь к конфигурации (обязат.) | — |
|
| `ConfigPath` | Путь к конфигурации (обязат.) | — |
|
||||||
| `Mode` | `A` (обзор) / `B` (проверка переноса) | `A` |
|
| `Mode` | `A` (обзор) / `B` (проверка переноса) | `A` |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-diff.ps1" -ExtensionPath src -ConfigPath C:\cfsrc\erp -Mode A
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-diff.ps1" -ExtensionPath src -ConfigPath C:\cfsrc\erp -Mode A
|
||||||
```
|
```
|
||||||
|
|
||||||
## Mode A — обзор расширения
|
## Mode A — обзор расширения
|
||||||
|
|
||||||
Для каждого объекта показывает:
|
Для каждого объекта показывает:
|
||||||
- `[BORROWED]` — заимствованный: перехватчики (`&Перед`, `&После`, `&ИзменениеИКонтроль`, `&Вместо`), собственные реквизиты/ТЧ/формы
|
- `[BORROWED]` — заимствованный: перехватчики (`&Перед`, `&После`, `&ИзменениеИКонтроль`, `&Вместо`), собственные реквизиты/ТЧ/формы
|
||||||
- `[OWN]` — собственный: количество реквизитов, ТЧ, форм
|
- `[OWN]` — собственный: количество реквизитов, ТЧ, форм
|
||||||
|
|
||||||
Для каждой формы заимствованного объекта показывается:
|
Для каждой формы заимствованного объекта показывается:
|
||||||
- `(borrowed)` / `(own)` — заимствованная или собственная форма
|
- `(borrowed)` / `(own)` — заимствованная или собственная форма
|
||||||
- callType-события формы и элементов
|
- callType-события формы и элементов
|
||||||
- callType на командах
|
- callType на командах
|
||||||
|
|
||||||
## Mode B — проверка переноса
|
## Mode B — проверка переноса
|
||||||
|
|
||||||
Для каждого `&ИзменениеИКонтроль` извлекает блоки `#Вставка`/`#КонецВставки` из расширения и ищет их в соответствующем модуле конфигурации.
|
Для каждого `&ИзменениеИКонтроль` извлекает блоки `#Вставка`/`#КонецВставки` из расширения и ищет их в соответствующем модуле конфигурации.
|
||||||
|
|
||||||
Статусы:
|
Статусы:
|
||||||
- `[TRANSFERRED]` — код найден в конфигурации
|
- `[TRANSFERRED]` — код найден в конфигурации
|
||||||
- `[NOT_TRANSFERRED]` — код не найден
|
- `[NOT_TRANSFERRED]` — код не найден
|
||||||
- `[NEEDS_REVIEW]` — нет блоков `#Вставка` или модуль конфигурации не найден
|
- `[NEEDS_REVIEW]` — нет блоков `#Вставка` или модуль конфигурации не найден
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Обзор — что изменено в расширении
|
# Обзор — что изменено в расширении
|
||||||
... -ExtensionPath src -ConfigPath C:\cfsrc\erp -Mode A
|
... -ExtensionPath src -ConfigPath C:\cfsrc\erp -Mode A
|
||||||
|
|
||||||
# Проверка переноса — все ли #Вставка перенесены
|
# Проверка переноса — все ли #Вставка перенесены
|
||||||
... -ExtensionPath src -ConfigPath C:\cfsrc\erp -Mode B
|
... -ExtensionPath src -ConfigPath C:\cfsrc\erp -Mode B
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,471 +1,471 @@
|
|||||||
# cfe-diff v1.0 — Analyze and compare 1C configuration extension (CFE)
|
# cfe-diff v1.0 — Analyze and compare 1C configuration extension (CFE)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$ExtensionPath,
|
[string]$ExtensionPath,
|
||||||
|
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$ConfigPath,
|
[string]$ConfigPath,
|
||||||
|
|
||||||
[ValidateSet("A","B")]
|
[ValidateSet("A","B")]
|
||||||
[string]$Mode = "A"
|
[string]$Mode = "A"
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Resolve paths ---
|
# --- Resolve paths ---
|
||||||
if (-not [System.IO.Path]::IsPathRooted($ExtensionPath)) {
|
if (-not [System.IO.Path]::IsPathRooted($ExtensionPath)) {
|
||||||
$ExtensionPath = Join-Path (Get-Location).Path $ExtensionPath
|
$ExtensionPath = Join-Path (Get-Location).Path $ExtensionPath
|
||||||
}
|
}
|
||||||
if (-not [System.IO.Path]::IsPathRooted($ConfigPath)) {
|
if (-not [System.IO.Path]::IsPathRooted($ConfigPath)) {
|
||||||
$ConfigPath = Join-Path (Get-Location).Path $ConfigPath
|
$ConfigPath = Join-Path (Get-Location).Path $ConfigPath
|
||||||
}
|
}
|
||||||
if (Test-Path $ExtensionPath -PathType Leaf) { $ExtensionPath = Split-Path $ExtensionPath -Parent }
|
if (Test-Path $ExtensionPath -PathType Leaf) { $ExtensionPath = Split-Path $ExtensionPath -Parent }
|
||||||
if (Test-Path $ConfigPath -PathType Leaf) { $ConfigPath = Split-Path $ConfigPath -Parent }
|
if (Test-Path $ConfigPath -PathType Leaf) { $ConfigPath = Split-Path $ConfigPath -Parent }
|
||||||
|
|
||||||
$extCfg = Join-Path $ExtensionPath "Configuration.xml"
|
$extCfg = Join-Path $ExtensionPath "Configuration.xml"
|
||||||
$srcCfg = Join-Path $ConfigPath "Configuration.xml"
|
$srcCfg = Join-Path $ConfigPath "Configuration.xml"
|
||||||
if (-not (Test-Path $extCfg)) { Write-Error "Extension Configuration.xml not found: $extCfg"; exit 1 }
|
if (-not (Test-Path $extCfg)) { Write-Error "Extension Configuration.xml not found: $extCfg"; exit 1 }
|
||||||
if (-not (Test-Path $srcCfg)) { Write-Error "Config Configuration.xml not found: $srcCfg"; exit 1 }
|
if (-not (Test-Path $srcCfg)) { Write-Error "Config Configuration.xml not found: $srcCfg"; exit 1 }
|
||||||
|
|
||||||
# --- Type -> directory mapping ---
|
# --- Type -> directory mapping ---
|
||||||
$childTypeDirMap = @{
|
$childTypeDirMap = @{
|
||||||
"Catalog"="Catalogs"; "Document"="Documents"; "Enum"="Enums"
|
"Catalog"="Catalogs"; "Document"="Documents"; "Enum"="Enums"
|
||||||
"CommonModule"="CommonModules"; "CommonPicture"="CommonPictures"
|
"CommonModule"="CommonModules"; "CommonPicture"="CommonPictures"
|
||||||
"CommonCommand"="CommonCommands"; "CommonTemplate"="CommonTemplates"
|
"CommonCommand"="CommonCommands"; "CommonTemplate"="CommonTemplates"
|
||||||
"ExchangePlan"="ExchangePlans"; "Report"="Reports"; "DataProcessor"="DataProcessors"
|
"ExchangePlan"="ExchangePlans"; "Report"="Reports"; "DataProcessor"="DataProcessors"
|
||||||
"InformationRegister"="InformationRegisters"; "AccumulationRegister"="AccumulationRegisters"
|
"InformationRegister"="InformationRegisters"; "AccumulationRegister"="AccumulationRegisters"
|
||||||
"ChartOfCharacteristicTypes"="ChartsOfCharacteristicTypes"
|
"ChartOfCharacteristicTypes"="ChartsOfCharacteristicTypes"
|
||||||
"ChartOfAccounts"="ChartsOfAccounts"; "AccountingRegister"="AccountingRegisters"
|
"ChartOfAccounts"="ChartsOfAccounts"; "AccountingRegister"="AccountingRegisters"
|
||||||
"ChartOfCalculationTypes"="ChartsOfCalculationTypes"; "CalculationRegister"="CalculationRegisters"
|
"ChartOfCalculationTypes"="ChartsOfCalculationTypes"; "CalculationRegister"="CalculationRegisters"
|
||||||
"BusinessProcess"="BusinessProcesses"; "Task"="Tasks"
|
"BusinessProcess"="BusinessProcesses"; "Task"="Tasks"
|
||||||
"Subsystem"="Subsystems"; "Role"="Roles"; "Constant"="Constants"
|
"Subsystem"="Subsystems"; "Role"="Roles"; "Constant"="Constants"
|
||||||
"FunctionalOption"="FunctionalOptions"; "DefinedType"="DefinedTypes"
|
"FunctionalOption"="FunctionalOptions"; "DefinedType"="DefinedTypes"
|
||||||
"FunctionalOptionsParameter"="FunctionalOptionsParameters"
|
"FunctionalOptionsParameter"="FunctionalOptionsParameters"
|
||||||
"CommonForm"="CommonForms"; "DocumentJournal"="DocumentJournals"
|
"CommonForm"="CommonForms"; "DocumentJournal"="DocumentJournals"
|
||||||
"SessionParameter"="SessionParameters"; "StyleItem"="StyleItems"
|
"SessionParameter"="SessionParameters"; "StyleItem"="StyleItems"
|
||||||
"EventSubscription"="EventSubscriptions"; "ScheduledJob"="ScheduledJobs"
|
"EventSubscription"="EventSubscriptions"; "ScheduledJob"="ScheduledJobs"
|
||||||
"SettingsStorage"="SettingsStorages"; "FilterCriterion"="FilterCriteria"
|
"SettingsStorage"="SettingsStorages"; "FilterCriterion"="FilterCriteria"
|
||||||
"CommandGroup"="CommandGroups"; "DocumentNumerator"="DocumentNumerators"
|
"CommandGroup"="CommandGroups"; "DocumentNumerator"="DocumentNumerators"
|
||||||
"Sequence"="Sequences"; "IntegrationService"="IntegrationServices"
|
"Sequence"="Sequences"; "IntegrationService"="IntegrationServices"
|
||||||
"CommonAttribute"="CommonAttributes"
|
"CommonAttribute"="CommonAttributes"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Parse extension Configuration.xml ---
|
# --- Parse extension Configuration.xml ---
|
||||||
$extDoc = New-Object System.Xml.XmlDocument
|
$extDoc = New-Object System.Xml.XmlDocument
|
||||||
$extDoc.PreserveWhitespace = $false
|
$extDoc.PreserveWhitespace = $false
|
||||||
$extDoc.Load($extCfg)
|
$extDoc.Load($extCfg)
|
||||||
|
|
||||||
$ns = New-Object System.Xml.XmlNamespaceManager($extDoc.NameTable)
|
$ns = New-Object System.Xml.XmlNamespaceManager($extDoc.NameTable)
|
||||||
$ns.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
|
$ns.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
|
||||||
$ns.AddNamespace("xr", "http://v8.1c.ru/8.3/xcf/readable")
|
$ns.AddNamespace("xr", "http://v8.1c.ru/8.3/xcf/readable")
|
||||||
|
|
||||||
$extProps = $extDoc.SelectSingleNode("//md:Configuration/md:Properties", $ns)
|
$extProps = $extDoc.SelectSingleNode("//md:Configuration/md:Properties", $ns)
|
||||||
$extNameNode = $extProps.SelectSingleNode("md:Name", $ns)
|
$extNameNode = $extProps.SelectSingleNode("md:Name", $ns)
|
||||||
$extName = if ($extNameNode) { $extNameNode.InnerText } else { "?" }
|
$extName = if ($extNameNode) { $extNameNode.InnerText } else { "?" }
|
||||||
$prefixNode = $extProps.SelectSingleNode("md:NamePrefix", $ns)
|
$prefixNode = $extProps.SelectSingleNode("md:NamePrefix", $ns)
|
||||||
$namePrefix = if ($prefixNode -and $prefixNode.InnerText) { $prefixNode.InnerText } else { "" }
|
$namePrefix = if ($prefixNode -and $prefixNode.InnerText) { $prefixNode.InnerText } else { "" }
|
||||||
$purposeNode = $extProps.SelectSingleNode("md:ConfigurationExtensionPurpose", $ns)
|
$purposeNode = $extProps.SelectSingleNode("md:ConfigurationExtensionPurpose", $ns)
|
||||||
$purpose = if ($purposeNode) { $purposeNode.InnerText } else { "?" }
|
$purpose = if ($purposeNode) { $purposeNode.InnerText } else { "?" }
|
||||||
|
|
||||||
Write-Host "=== cfe-diff Mode ${Mode}: $extName (${purpose}) ==="
|
Write-Host "=== cfe-diff Mode ${Mode}: $extName (${purpose}) ==="
|
||||||
Write-Host " NamePrefix: $namePrefix"
|
Write-Host " NamePrefix: $namePrefix"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
|
|
||||||
# --- Collect ChildObjects ---
|
# --- Collect ChildObjects ---
|
||||||
$childObjNode = $extDoc.SelectSingleNode("//md:Configuration/md:ChildObjects", $ns)
|
$childObjNode = $extDoc.SelectSingleNode("//md:Configuration/md:ChildObjects", $ns)
|
||||||
if (-not $childObjNode) {
|
if (-not $childObjNode) {
|
||||||
Write-Host "[WARN] No ChildObjects in extension"
|
Write-Host "[WARN] No ChildObjects in extension"
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
$objects = @()
|
$objects = @()
|
||||||
foreach ($child in $childObjNode.ChildNodes) {
|
foreach ($child in $childObjNode.ChildNodes) {
|
||||||
if ($child.NodeType -ne 'Element') { continue }
|
if ($child.NodeType -ne 'Element') { continue }
|
||||||
if ($child.LocalName -eq "Language") { continue }
|
if ($child.LocalName -eq "Language") { continue }
|
||||||
$objects += @{ Type = $child.LocalName; Name = $child.InnerText }
|
$objects += @{ Type = $child.LocalName; Name = $child.InnerText }
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($objects.Count -eq 0) {
|
if ($objects.Count -eq 0) {
|
||||||
Write-Host "No objects (besides Language) in extension."
|
Write-Host "No objects (besides Language) in extension."
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Helper: check if object is borrowed ---
|
# --- Helper: check if object is borrowed ---
|
||||||
function Get-ObjectInfo {
|
function Get-ObjectInfo {
|
||||||
param([string]$objType, [string]$objName)
|
param([string]$objType, [string]$objName)
|
||||||
|
|
||||||
if (-not $childTypeDirMap.ContainsKey($objType)) { return $null }
|
if (-not $childTypeDirMap.ContainsKey($objType)) { return $null }
|
||||||
$dirName = $childTypeDirMap[$objType]
|
$dirName = $childTypeDirMap[$objType]
|
||||||
$objFile = Join-Path (Join-Path $ExtensionPath $dirName) "${objName}.xml"
|
$objFile = Join-Path (Join-Path $ExtensionPath $dirName) "${objName}.xml"
|
||||||
|
|
||||||
if (-not (Test-Path $objFile)) { return @{ Borrowed = $false; File = $objFile; Exists = $false } }
|
if (-not (Test-Path $objFile)) { return @{ Borrowed = $false; File = $objFile; Exists = $false } }
|
||||||
|
|
||||||
$doc = New-Object System.Xml.XmlDocument
|
$doc = New-Object System.Xml.XmlDocument
|
||||||
$doc.PreserveWhitespace = $false
|
$doc.PreserveWhitespace = $false
|
||||||
$doc.Load($objFile)
|
$doc.Load($objFile)
|
||||||
|
|
||||||
$objNs = New-Object System.Xml.XmlNamespaceManager($doc.NameTable)
|
$objNs = New-Object System.Xml.XmlNamespaceManager($doc.NameTable)
|
||||||
$objNs.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
|
$objNs.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
|
||||||
|
|
||||||
$objEl = $null
|
$objEl = $null
|
||||||
foreach ($c in $doc.DocumentElement.ChildNodes) {
|
foreach ($c in $doc.DocumentElement.ChildNodes) {
|
||||||
if ($c.NodeType -eq 'Element') { $objEl = $c; break }
|
if ($c.NodeType -eq 'Element') { $objEl = $c; break }
|
||||||
}
|
}
|
||||||
if (-not $objEl) { return @{ Borrowed = $false; File = $objFile; Exists = $true } }
|
if (-not $objEl) { return @{ Borrowed = $false; File = $objFile; Exists = $true } }
|
||||||
|
|
||||||
$propsEl = $objEl.SelectSingleNode("md:Properties", $objNs)
|
$propsEl = $objEl.SelectSingleNode("md:Properties", $objNs)
|
||||||
$obNode = if ($propsEl) { $propsEl.SelectSingleNode("md:ObjectBelonging", $objNs) } else { $null }
|
$obNode = if ($propsEl) { $propsEl.SelectSingleNode("md:ObjectBelonging", $objNs) } else { $null }
|
||||||
|
|
||||||
$info = @{
|
$info = @{
|
||||||
Borrowed = ($obNode -and $obNode.InnerText -eq "Adopted")
|
Borrowed = ($obNode -and $obNode.InnerText -eq "Adopted")
|
||||||
File = $objFile
|
File = $objFile
|
||||||
Exists = $true
|
Exists = $true
|
||||||
Type = $objType
|
Type = $objType
|
||||||
Name = $objName
|
Name = $objName
|
||||||
DirName = $dirName
|
DirName = $dirName
|
||||||
ObjElement = $objEl
|
ObjElement = $objEl
|
||||||
ObjNs = $objNs
|
ObjNs = $objNs
|
||||||
}
|
}
|
||||||
return $info
|
return $info
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Helper: find .bsl files for object ---
|
# --- Helper: find .bsl files for object ---
|
||||||
function Get-BslFiles {
|
function Get-BslFiles {
|
||||||
param([string]$objType, [string]$objName)
|
param([string]$objType, [string]$objName)
|
||||||
|
|
||||||
if (-not $childTypeDirMap.ContainsKey($objType)) { return @() }
|
if (-not $childTypeDirMap.ContainsKey($objType)) { return @() }
|
||||||
$dirName = $childTypeDirMap[$objType]
|
$dirName = $childTypeDirMap[$objType]
|
||||||
$objDir = Join-Path (Join-Path $ExtensionPath $dirName) $objName
|
$objDir = Join-Path (Join-Path $ExtensionPath $dirName) $objName
|
||||||
|
|
||||||
if (-not (Test-Path $objDir -PathType Container)) { return @() }
|
if (-not (Test-Path $objDir -PathType Container)) { return @() }
|
||||||
|
|
||||||
$bslFiles = @()
|
$bslFiles = @()
|
||||||
$extDir = Join-Path $objDir "Ext"
|
$extDir = Join-Path $objDir "Ext"
|
||||||
if (Test-Path $extDir) {
|
if (Test-Path $extDir) {
|
||||||
$items = Get-ChildItem -Path $extDir -Filter "*.bsl" -ErrorAction SilentlyContinue
|
$items = Get-ChildItem -Path $extDir -Filter "*.bsl" -ErrorAction SilentlyContinue
|
||||||
foreach ($item in $items) { $bslFiles += $item.FullName }
|
foreach ($item in $items) { $bslFiles += $item.FullName }
|
||||||
}
|
}
|
||||||
|
|
||||||
# Forms
|
# Forms
|
||||||
$formsDir = Join-Path $objDir "Forms"
|
$formsDir = Join-Path $objDir "Forms"
|
||||||
if (Test-Path $formsDir) {
|
if (Test-Path $formsDir) {
|
||||||
$formModules = Get-ChildItem -Path $formsDir -Recurse -Filter "Module.bsl" -ErrorAction SilentlyContinue
|
$formModules = Get-ChildItem -Path $formsDir -Recurse -Filter "Module.bsl" -ErrorAction SilentlyContinue
|
||||||
foreach ($fm in $formModules) { $bslFiles += $fm.FullName }
|
foreach ($fm in $formModules) { $bslFiles += $fm.FullName }
|
||||||
}
|
}
|
||||||
|
|
||||||
return $bslFiles
|
return $bslFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Helper: parse interceptors from .bsl ---
|
# --- Helper: parse interceptors from .bsl ---
|
||||||
function Get-Interceptors {
|
function Get-Interceptors {
|
||||||
param([string]$bslPath)
|
param([string]$bslPath)
|
||||||
|
|
||||||
if (-not (Test-Path $bslPath)) { return @() }
|
if (-not (Test-Path $bslPath)) { return @() }
|
||||||
$lines = [System.IO.File]::ReadAllLines($bslPath, [System.Text.Encoding]::UTF8)
|
$lines = [System.IO.File]::ReadAllLines($bslPath, [System.Text.Encoding]::UTF8)
|
||||||
$interceptors = @()
|
$interceptors = @()
|
||||||
$i = 0
|
$i = 0
|
||||||
while ($i -lt $lines.Count) {
|
while ($i -lt $lines.Count) {
|
||||||
$line = $lines[$i].Trim()
|
$line = $lines[$i].Trim()
|
||||||
if ($line -match '^&(Перед|После|ИзменениеИКонтроль|Вместо)\("([^"]+)"\)') {
|
if ($line -match '^&(Перед|После|ИзменениеИКонтроль|Вместо)\("([^"]+)"\)') {
|
||||||
$type = $Matches[1]
|
$type = $Matches[1]
|
||||||
$method = $Matches[2]
|
$method = $Matches[2]
|
||||||
$interceptors += @{ Type = $type; Method = $method; Line = $i + 1; File = $bslPath }
|
$interceptors += @{ Type = $type; Method = $method; Line = $i + 1; File = $bslPath }
|
||||||
}
|
}
|
||||||
$i++
|
$i++
|
||||||
}
|
}
|
||||||
return $interceptors
|
return $interceptors
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Helper: extract #Вставка blocks from .bsl ---
|
# --- Helper: extract #Вставка blocks from .bsl ---
|
||||||
function Get-InsertionBlocks {
|
function Get-InsertionBlocks {
|
||||||
param([string]$bslPath)
|
param([string]$bslPath)
|
||||||
|
|
||||||
if (-not (Test-Path $bslPath)) { return @() }
|
if (-not (Test-Path $bslPath)) { return @() }
|
||||||
$lines = [System.IO.File]::ReadAllLines($bslPath, [System.Text.Encoding]::UTF8)
|
$lines = [System.IO.File]::ReadAllLines($bslPath, [System.Text.Encoding]::UTF8)
|
||||||
$blocks = @()
|
$blocks = @()
|
||||||
$inBlock = $false
|
$inBlock = $false
|
||||||
$blockLines = @()
|
$blockLines = @()
|
||||||
$startLine = 0
|
$startLine = 0
|
||||||
|
|
||||||
for ($i = 0; $i -lt $lines.Count; $i++) {
|
for ($i = 0; $i -lt $lines.Count; $i++) {
|
||||||
$line = $lines[$i].Trim()
|
$line = $lines[$i].Trim()
|
||||||
if ($line -eq "#Вставка") {
|
if ($line -eq "#Вставка") {
|
||||||
$inBlock = $true
|
$inBlock = $true
|
||||||
$blockLines = @()
|
$blockLines = @()
|
||||||
$startLine = $i + 1
|
$startLine = $i + 1
|
||||||
} elseif ($line -eq "#КонецВставки" -and $inBlock) {
|
} elseif ($line -eq "#КонецВставки" -and $inBlock) {
|
||||||
$inBlock = $false
|
$inBlock = $false
|
||||||
$blocks += @{
|
$blocks += @{
|
||||||
StartLine = $startLine
|
StartLine = $startLine
|
||||||
EndLine = $i + 1
|
EndLine = $i + 1
|
||||||
Code = ($blockLines -join "`n").Trim()
|
Code = ($blockLines -join "`n").Trim()
|
||||||
File = $bslPath
|
File = $bslPath
|
||||||
}
|
}
|
||||||
} elseif ($inBlock) {
|
} elseif ($inBlock) {
|
||||||
$blockLines += $lines[$i]
|
$blockLines += $lines[$i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $blocks
|
return $blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Helper: analyze form for callType events and commands ---
|
# --- Helper: analyze form for callType events and commands ---
|
||||||
function Get-FormInterceptors {
|
function Get-FormInterceptors {
|
||||||
param([string]$formXmlPath)
|
param([string]$formXmlPath)
|
||||||
|
|
||||||
if (-not (Test-Path $formXmlPath)) { return $null }
|
if (-not (Test-Path $formXmlPath)) { return $null }
|
||||||
|
|
||||||
$formDoc = New-Object System.Xml.XmlDocument
|
$formDoc = New-Object System.Xml.XmlDocument
|
||||||
$formDoc.PreserveWhitespace = $false
|
$formDoc.PreserveWhitespace = $false
|
||||||
try { $formDoc.Load($formXmlPath) } catch { return $null }
|
try { $formDoc.Load($formXmlPath) } catch { return $null }
|
||||||
|
|
||||||
$fNs = New-Object System.Xml.XmlNamespaceManager($formDoc.NameTable)
|
$fNs = New-Object System.Xml.XmlNamespaceManager($formDoc.NameTable)
|
||||||
$fNs.AddNamespace("f", "http://v8.1c.ru/8.3/xcf/logform")
|
$fNs.AddNamespace("f", "http://v8.1c.ru/8.3/xcf/logform")
|
||||||
|
|
||||||
$fRoot = $formDoc.DocumentElement
|
$fRoot = $formDoc.DocumentElement
|
||||||
$baseForm = $fRoot.SelectSingleNode("f:BaseForm", $fNs)
|
$baseForm = $fRoot.SelectSingleNode("f:BaseForm", $fNs)
|
||||||
$isBorrowed = ($baseForm -ne $null)
|
$isBorrowed = ($baseForm -ne $null)
|
||||||
|
|
||||||
$interceptors = @()
|
$interceptors = @()
|
||||||
|
|
||||||
# Form-level events with callType
|
# Form-level events with callType
|
||||||
$eventsNode = $fRoot.SelectSingleNode("f:Events", $fNs)
|
$eventsNode = $fRoot.SelectSingleNode("f:Events", $fNs)
|
||||||
if ($eventsNode) {
|
if ($eventsNode) {
|
||||||
foreach ($evt in $eventsNode.SelectNodes("f:Event", $fNs)) {
|
foreach ($evt in $eventsNode.SelectNodes("f:Event", $fNs)) {
|
||||||
$ct = $evt.GetAttribute("callType")
|
$ct = $evt.GetAttribute("callType")
|
||||||
if ($ct) {
|
if ($ct) {
|
||||||
$interceptors += "Event:$($evt.GetAttribute('name')) [$ct] -> $($evt.InnerText)"
|
$interceptors += "Event:$($evt.GetAttribute('name')) [$ct] -> $($evt.InnerText)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Element-level events with callType (scan all elements recursively)
|
# Element-level events with callType (scan all elements recursively)
|
||||||
$childItems = $fRoot.SelectSingleNode("f:ChildItems", $fNs)
|
$childItems = $fRoot.SelectSingleNode("f:ChildItems", $fNs)
|
||||||
if ($childItems) {
|
if ($childItems) {
|
||||||
foreach ($evtNode in $childItems.SelectNodes(".//*[f:Events/f:Event[@callType]]", $fNs)) {
|
foreach ($evtNode in $childItems.SelectNodes(".//*[f:Events/f:Event[@callType]]", $fNs)) {
|
||||||
$elName = $evtNode.GetAttribute("name")
|
$elName = $evtNode.GetAttribute("name")
|
||||||
foreach ($evt in $evtNode.SelectNodes("f:Events/f:Event[@callType]", $fNs)) {
|
foreach ($evt in $evtNode.SelectNodes("f:Events/f:Event[@callType]", $fNs)) {
|
||||||
$ct = $evt.GetAttribute("callType")
|
$ct = $evt.GetAttribute("callType")
|
||||||
$interceptors += "Element:${elName}.$($evt.GetAttribute('name')) [$ct] -> $($evt.InnerText)"
|
$interceptors += "Element:${elName}.$($evt.GetAttribute('name')) [$ct] -> $($evt.InnerText)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Commands with callType on Action
|
# Commands with callType on Action
|
||||||
foreach ($cmd in $fRoot.SelectNodes("f:Commands/f:Command", $fNs)) {
|
foreach ($cmd in $fRoot.SelectNodes("f:Commands/f:Command", $fNs)) {
|
||||||
$cmdName = $cmd.GetAttribute("name")
|
$cmdName = $cmd.GetAttribute("name")
|
||||||
foreach ($action in $cmd.SelectNodes("f:Action[@callType]", $fNs)) {
|
foreach ($action in $cmd.SelectNodes("f:Action[@callType]", $fNs)) {
|
||||||
$ct = $action.GetAttribute("callType")
|
$ct = $action.GetAttribute("callType")
|
||||||
$interceptors += "Command:$cmdName [$ct] -> $($action.InnerText)"
|
$interceptors += "Command:$cmdName [$ct] -> $($action.InnerText)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return @{
|
return @{
|
||||||
IsBorrowed = $isBorrowed
|
IsBorrowed = $isBorrowed
|
||||||
Interceptors = $interceptors
|
Interceptors = $interceptors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# MODE A: Extension overview
|
# MODE A: Extension overview
|
||||||
# ============================================================
|
# ============================================================
|
||||||
if ($Mode -eq "A") {
|
if ($Mode -eq "A") {
|
||||||
$borrowedList = @()
|
$borrowedList = @()
|
||||||
$ownList = @()
|
$ownList = @()
|
||||||
|
|
||||||
foreach ($obj in $objects) {
|
foreach ($obj in $objects) {
|
||||||
$info = Get-ObjectInfo $obj.Type $obj.Name
|
$info = Get-ObjectInfo $obj.Type $obj.Name
|
||||||
if (-not $info) {
|
if (-not $info) {
|
||||||
Write-Host " [?] $($obj.Type).$($obj.Name) — unknown type"
|
Write-Host " [?] $($obj.Type).$($obj.Name) — unknown type"
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (-not $info.Exists) {
|
if (-not $info.Exists) {
|
||||||
Write-Host " [?] $($obj.Type).$($obj.Name) — file not found"
|
Write-Host " [?] $($obj.Type).$($obj.Name) — file not found"
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($info.Borrowed) {
|
if ($info.Borrowed) {
|
||||||
$borrowedList += $obj
|
$borrowedList += $obj
|
||||||
|
|
||||||
Write-Host " [BORROWED] $($obj.Type).$($obj.Name)"
|
Write-Host " [BORROWED] $($obj.Type).$($obj.Name)"
|
||||||
|
|
||||||
# Find .bsl files and interceptors
|
# Find .bsl files and interceptors
|
||||||
$bslFiles = Get-BslFiles $obj.Type $obj.Name
|
$bslFiles = Get-BslFiles $obj.Type $obj.Name
|
||||||
foreach ($bsl in $bslFiles) {
|
foreach ($bsl in $bslFiles) {
|
||||||
$relPath = $bsl.Replace($ExtensionPath, "").TrimStart("\", "/")
|
$relPath = $bsl.Replace($ExtensionPath, "").TrimStart("\", "/")
|
||||||
$interceptors = Get-Interceptors $bsl
|
$interceptors = Get-Interceptors $bsl
|
||||||
if ($interceptors.Count -gt 0) {
|
if ($interceptors.Count -gt 0) {
|
||||||
foreach ($ic in $interceptors) {
|
foreach ($ic in $interceptors) {
|
||||||
Write-Host " &$($ic.Type)(`"$($ic.Method)`") — line $($ic.Line) in $relPath"
|
Write-Host " &$($ic.Type)(`"$($ic.Method)`") — line $($ic.Line) in $relPath"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Write-Host " $relPath (no interceptors)"
|
Write-Host " $relPath (no interceptors)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check for own attributes/forms in ChildObjects
|
# Check for own attributes/forms in ChildObjects
|
||||||
if ($info.ObjElement) {
|
if ($info.ObjElement) {
|
||||||
$childObj = $info.ObjElement.SelectSingleNode("md:ChildObjects", $info.ObjNs)
|
$childObj = $info.ObjElement.SelectSingleNode("md:ChildObjects", $info.ObjNs)
|
||||||
if ($childObj) {
|
if ($childObj) {
|
||||||
$ownAttrs = 0
|
$ownAttrs = 0
|
||||||
$ownForms = 0
|
$ownForms = 0
|
||||||
$ownTS = 0
|
$ownTS = 0
|
||||||
$borrowedItems = 0
|
$borrowedItems = 0
|
||||||
$formNames = @()
|
$formNames = @()
|
||||||
foreach ($c in $childObj.ChildNodes) {
|
foreach ($c in $childObj.ChildNodes) {
|
||||||
if ($c.NodeType -ne 'Element') { continue }
|
if ($c.NodeType -ne 'Element') { continue }
|
||||||
$cProps = $c.SelectSingleNode("md:Properties", $info.ObjNs)
|
$cProps = $c.SelectSingleNode("md:Properties", $info.ObjNs)
|
||||||
if ($cProps) {
|
if ($cProps) {
|
||||||
$cOb = $cProps.SelectSingleNode("md:ObjectBelonging", $info.ObjNs)
|
$cOb = $cProps.SelectSingleNode("md:ObjectBelonging", $info.ObjNs)
|
||||||
if ($cOb -and $cOb.InnerText -eq "Adopted") {
|
if ($cOb -and $cOb.InnerText -eq "Adopted") {
|
||||||
$borrowedItems++
|
$borrowedItems++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch ($c.LocalName) {
|
switch ($c.LocalName) {
|
||||||
"Attribute" { $ownAttrs++ }
|
"Attribute" { $ownAttrs++ }
|
||||||
"TabularSection" { $ownTS++ }
|
"TabularSection" { $ownTS++ }
|
||||||
"Form" { $formNames += $c.InnerText; $ownForms++ }
|
"Form" { $formNames += $c.InnerText; $ownForms++ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$parts = @()
|
$parts = @()
|
||||||
if ($ownAttrs -gt 0) { $parts += "$ownAttrs own attrs" }
|
if ($ownAttrs -gt 0) { $parts += "$ownAttrs own attrs" }
|
||||||
if ($ownTS -gt 0) { $parts += "$ownTS own TS" }
|
if ($ownTS -gt 0) { $parts += "$ownTS own TS" }
|
||||||
if ($ownForms -gt 0) { $parts += "$ownForms own forms" }
|
if ($ownForms -gt 0) { $parts += "$ownForms own forms" }
|
||||||
if ($borrowedItems -gt 0) { $parts += "$borrowedItems borrowed items" }
|
if ($borrowedItems -gt 0) { $parts += "$borrowedItems borrowed items" }
|
||||||
if ($parts.Count -gt 0) {
|
if ($parts.Count -gt 0) {
|
||||||
Write-Host " ChildObjects: $($parts -join ', ')"
|
Write-Host " ChildObjects: $($parts -join ', ')"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Analyze forms
|
# Analyze forms
|
||||||
$borrowedFormCount = 0
|
$borrowedFormCount = 0
|
||||||
$ownFormCount = 0
|
$ownFormCount = 0
|
||||||
foreach ($fn in $formNames) {
|
foreach ($fn in $formNames) {
|
||||||
$formXmlPath = Join-Path (Join-Path (Join-Path (Join-Path (Join-Path $ExtensionPath $info.DirName) $info.Name) "Forms") $fn) "Ext/Form.xml"
|
$formXmlPath = Join-Path (Join-Path (Join-Path (Join-Path (Join-Path $ExtensionPath $info.DirName) $info.Name) "Forms") $fn) "Ext/Form.xml"
|
||||||
$fi = Get-FormInterceptors $formXmlPath
|
$fi = Get-FormInterceptors $formXmlPath
|
||||||
if (-not $fi) {
|
if (-not $fi) {
|
||||||
Write-Host " Form.$fn (?)"
|
Write-Host " Form.$fn (?)"
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
$formTag = if ($fi.IsBorrowed) { "borrowed"; $borrowedFormCount++ } else { "own"; $ownFormCount++ }
|
$formTag = if ($fi.IsBorrowed) { "borrowed"; $borrowedFormCount++ } else { "own"; $ownFormCount++ }
|
||||||
if ($fi.Interceptors.Count -gt 0) {
|
if ($fi.Interceptors.Count -gt 0) {
|
||||||
Write-Host " Form.$fn ($formTag):"
|
Write-Host " Form.$fn ($formTag):"
|
||||||
foreach ($ic in $fi.Interceptors) {
|
foreach ($ic in $fi.Interceptors) {
|
||||||
Write-Host " $ic"
|
Write-Host " $ic"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Write-Host " Form.$fn ($formTag)"
|
Write-Host " Form.$fn ($formTag)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$ownList += $obj
|
$ownList += $obj
|
||||||
Write-Host " [OWN] $($obj.Type).$($obj.Name)"
|
Write-Host " [OWN] $($obj.Type).$($obj.Name)"
|
||||||
|
|
||||||
# Brief info for own objects
|
# Brief info for own objects
|
||||||
if ($info.ObjElement) {
|
if ($info.ObjElement) {
|
||||||
$childObj = $info.ObjElement.SelectSingleNode("md:ChildObjects", $info.ObjNs)
|
$childObj = $info.ObjElement.SelectSingleNode("md:ChildObjects", $info.ObjNs)
|
||||||
if ($childObj) {
|
if ($childObj) {
|
||||||
$attrs = 0; $forms = 0; $ts = 0
|
$attrs = 0; $forms = 0; $ts = 0
|
||||||
foreach ($c in $childObj.ChildNodes) {
|
foreach ($c in $childObj.ChildNodes) {
|
||||||
if ($c.NodeType -ne 'Element') { continue }
|
if ($c.NodeType -ne 'Element') { continue }
|
||||||
switch ($c.LocalName) {
|
switch ($c.LocalName) {
|
||||||
"Attribute" { $attrs++ }
|
"Attribute" { $attrs++ }
|
||||||
"TabularSection" { $ts++ }
|
"TabularSection" { $ts++ }
|
||||||
"Form" { $forms++ }
|
"Form" { $forms++ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$parts = @()
|
$parts = @()
|
||||||
if ($attrs -gt 0) { $parts += "$attrs attrs" }
|
if ($attrs -gt 0) { $parts += "$attrs attrs" }
|
||||||
if ($ts -gt 0) { $parts += "$ts TS" }
|
if ($ts -gt 0) { $parts += "$ts TS" }
|
||||||
if ($forms -gt 0) { $parts += "$forms forms" }
|
if ($forms -gt 0) { $parts += "$forms forms" }
|
||||||
if ($parts.Count -gt 0) {
|
if ($parts.Count -gt 0) {
|
||||||
Write-Host " $($parts -join ', ')"
|
Write-Host " $($parts -join ', ')"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "=== Summary: $($borrowedList.Count) borrowed, $($ownList.Count) own objects ==="
|
Write-Host "=== Summary: $($borrowedList.Count) borrowed, $($ownList.Count) own objects ==="
|
||||||
}
|
}
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# MODE B: Transfer check
|
# MODE B: Transfer check
|
||||||
# ============================================================
|
# ============================================================
|
||||||
if ($Mode -eq "B") {
|
if ($Mode -eq "B") {
|
||||||
$transferred = 0
|
$transferred = 0
|
||||||
$notTransferred = 0
|
$notTransferred = 0
|
||||||
$needsReview = 0
|
$needsReview = 0
|
||||||
|
|
||||||
foreach ($obj in $objects) {
|
foreach ($obj in $objects) {
|
||||||
$info = Get-ObjectInfo $obj.Type $obj.Name
|
$info = Get-ObjectInfo $obj.Type $obj.Name
|
||||||
if (-not $info -or -not $info.Exists -or -not $info.Borrowed) { continue }
|
if (-not $info -or -not $info.Exists -or -not $info.Borrowed) { continue }
|
||||||
|
|
||||||
# Find .bsl files with &ИзменениеИКонтроль
|
# Find .bsl files with &ИзменениеИКонтроль
|
||||||
$bslFiles = Get-BslFiles $obj.Type $obj.Name
|
$bslFiles = Get-BslFiles $obj.Type $obj.Name
|
||||||
foreach ($bsl in $bslFiles) {
|
foreach ($bsl in $bslFiles) {
|
||||||
$interceptors = Get-Interceptors $bsl
|
$interceptors = Get-Interceptors $bsl
|
||||||
$macInterceptors = @($interceptors | Where-Object { $_.Type -eq "ИзменениеИКонтроль" })
|
$macInterceptors = @($interceptors | Where-Object { $_.Type -eq "ИзменениеИКонтроль" })
|
||||||
|
|
||||||
if ($macInterceptors.Count -eq 0) { continue }
|
if ($macInterceptors.Count -eq 0) { continue }
|
||||||
|
|
||||||
foreach ($ic in $macInterceptors) {
|
foreach ($ic in $macInterceptors) {
|
||||||
$methodName = $ic.Method
|
$methodName = $ic.Method
|
||||||
$relBsl = $bsl.Replace($ExtensionPath, "").TrimStart("\", "/")
|
$relBsl = $bsl.Replace($ExtensionPath, "").TrimStart("\", "/")
|
||||||
|
|
||||||
# Find #Вставка blocks in this file
|
# Find #Вставка blocks in this file
|
||||||
$insertBlocks = Get-InsertionBlocks $bsl
|
$insertBlocks = Get-InsertionBlocks $bsl
|
||||||
|
|
||||||
if ($insertBlocks.Count -eq 0) {
|
if ($insertBlocks.Count -eq 0) {
|
||||||
Write-Host " [NEEDS_REVIEW] $($obj.Type).$($obj.Name) — &ИзменениеИКонтроль(`"$methodName`") — no #Вставка blocks"
|
Write-Host " [NEEDS_REVIEW] $($obj.Type).$($obj.Name) — &ИзменениеИКонтроль(`"$methodName`") — no #Вставка blocks"
|
||||||
$needsReview++
|
$needsReview++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
# Find corresponding module in config
|
# Find corresponding module in config
|
||||||
if (-not $childTypeDirMap.ContainsKey($obj.Type)) { continue }
|
if (-not $childTypeDirMap.ContainsKey($obj.Type)) { continue }
|
||||||
$dirName = $childTypeDirMap[$obj.Type]
|
$dirName = $childTypeDirMap[$obj.Type]
|
||||||
$configBsl = $bsl.Replace($ExtensionPath, $ConfigPath)
|
$configBsl = $bsl.Replace($ExtensionPath, $ConfigPath)
|
||||||
|
|
||||||
if (-not (Test-Path $configBsl)) {
|
if (-not (Test-Path $configBsl)) {
|
||||||
Write-Host " [NEEDS_REVIEW] $($obj.Type).$($obj.Name) — &ИзменениеИКонтроль(`"$methodName`") — config module not found"
|
Write-Host " [NEEDS_REVIEW] $($obj.Type).$($obj.Name) — &ИзменениеИКонтроль(`"$methodName`") — config module not found"
|
||||||
$needsReview++
|
$needsReview++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
$configContent = [System.IO.File]::ReadAllText($configBsl, [System.Text.Encoding]::UTF8)
|
$configContent = [System.IO.File]::ReadAllText($configBsl, [System.Text.Encoding]::UTF8)
|
||||||
|
|
||||||
$allTransferred = $true
|
$allTransferred = $true
|
||||||
foreach ($block in $insertBlocks) {
|
foreach ($block in $insertBlocks) {
|
||||||
$code = $block.Code
|
$code = $block.Code
|
||||||
if (-not $code) { continue }
|
if (-not $code) { continue }
|
||||||
|
|
||||||
# Normalize whitespace for comparison
|
# Normalize whitespace for comparison
|
||||||
$codeNorm = $code -replace '\s+', ' '
|
$codeNorm = $code -replace '\s+', ' '
|
||||||
$configNorm = $configContent -replace '\s+', ' '
|
$configNorm = $configContent -replace '\s+', ' '
|
||||||
|
|
||||||
if ($configNorm.Contains($codeNorm)) {
|
if ($configNorm.Contains($codeNorm)) {
|
||||||
# Found in config
|
# Found in config
|
||||||
} else {
|
} else {
|
||||||
$allTransferred = $false
|
$allTransferred = $false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($allTransferred) {
|
if ($allTransferred) {
|
||||||
Write-Host " [TRANSFERRED] $($obj.Type).$($obj.Name) — &ИзменениеИКонтроль(`"$methodName`") — $($insertBlocks.Count) block(s)"
|
Write-Host " [TRANSFERRED] $($obj.Type).$($obj.Name) — &ИзменениеИКонтроль(`"$methodName`") — $($insertBlocks.Count) block(s)"
|
||||||
$transferred++
|
$transferred++
|
||||||
} else {
|
} else {
|
||||||
Write-Host " [NOT_TRANSFERRED] $($obj.Type).$($obj.Name) — &ИзменениеИКонтроль(`"$methodName`") — some blocks not found in config"
|
Write-Host " [NOT_TRANSFERRED] $($obj.Type).$($obj.Name) — &ИзменениеИКонтроль(`"$methodName`") — some blocks not found in config"
|
||||||
$notTransferred++
|
$notTransferred++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "=== Transfer check: $transferred transferred, $notTransferred not transferred, $needsReview needs review ==="
|
Write-Host "=== Transfer check: $transferred transferred, $notTransferred not transferred, $needsReview needs review ==="
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,71 +1,71 @@
|
|||||||
---
|
---
|
||||||
name: cfe-init
|
name: cfe-init
|
||||||
description: Создать расширение конфигурации 1С (CFE) — scaffold XML-исходников. Используй когда нужно создать новое расширение для исправления, доработки или дополнения конфигурации
|
description: Создать расширение конфигурации 1С (CFE) — scaffold XML-исходников. Используй когда нужно создать новое расширение для исправления, доработки или дополнения конфигурации
|
||||||
argument-hint: <Name> [-ConfigPath <path>] [-Purpose Patch|Customization|AddOn] [-CompatibilityMode Version8_3_24]
|
argument-hint: <Name> [-ConfigPath <path>] [-Purpose Patch|Customization|AddOn] [-CompatibilityMode Version8_3_24]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /cfe-init — Создание расширения конфигурации 1С
|
# /cfe-init — Создание расширения конфигурации 1С
|
||||||
|
|
||||||
Создаёт scaffold расширения: `Configuration.xml`, `Languages/Русский.xml`, опционально `Roles/`.
|
Создаёт scaffold расширения: `Configuration.xml`, `Languages/Русский.xml`, опционально `Roles/`.
|
||||||
|
|
||||||
## Подготовка
|
## Подготовка
|
||||||
|
|
||||||
Если есть выгрузка базовой конфигурации, передай `-ConfigPath` — скрипт автоматически определит `CompatibilityMode` и UUID языка из базовой конфигурации.
|
Если есть выгрузка базовой конфигурации, передай `-ConfigPath` — скрипт автоматически определит `CompatibilityMode` и UUID языка из базовой конфигурации.
|
||||||
|
|
||||||
### Авто-определение ConfigPath
|
### Авто-определение ConfigPath
|
||||||
|
|
||||||
Если пользователь не указал `-ConfigPath` — попробуй определить автоматически:
|
Если пользователь не указал `-ConfigPath` — попробуй определить автоматически:
|
||||||
1. Прочитай `.v8-project.json` из корня проекта
|
1. Прочитай `.v8-project.json` из корня проекта
|
||||||
2. Разреши целевую базу (по имени, ветке или `default` — алгоритм из `/db-list`)
|
2. Разреши целевую базу (по имени, ветке или `default` — алгоритм из `/db-list`)
|
||||||
3. Если у базы есть поле `configSrc` — используй как `-ConfigPath`
|
3. Если у базы есть поле `configSrc` — используй как `-ConfigPath`
|
||||||
4. Если `configSrc` нет — спроси у пользователя
|
4. Если `configSrc` нет — спроси у пользователя
|
||||||
|
|
||||||
Если `.v8-project.json` не найден и `-ConfigPath` не задан — расширение создастся с предупреждением (UUID языка = нули, CompatibilityMode по умолчанию).
|
Если `.v8-project.json` не найден и `-ConfigPath` не задан — расширение создастся с предупреждением (UUID языка = нули, CompatibilityMode по умолчанию).
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Описание | По умолчанию |
|
| Параметр | Описание | По умолчанию |
|
||||||
|----------|----------|--------------|
|
|----------|----------|--------------|
|
||||||
| `Name` | Имя расширения (обязат.) | — |
|
| `Name` | Имя расширения (обязат.) | — |
|
||||||
| `Synonym` | Синоним | = Name |
|
| `Synonym` | Синоним | = Name |
|
||||||
| `NamePrefix` | Префикс собственных объектов | = Name + "_" |
|
| `NamePrefix` | Префикс собственных объектов | = Name + "_" |
|
||||||
| `OutputDir` | Каталог для создания | `src` |
|
| `OutputDir` | Каталог для создания | `src` |
|
||||||
| `Purpose` | `Patch` (исправление) / `Customization` (доработка) / `AddOn` (дополнение) | `Customization` |
|
| `Purpose` | `Patch` (исправление) / `Customization` (доработка) / `AddOn` (дополнение) | `Customization` |
|
||||||
| `Version` | Версия расширения | — |
|
| `Version` | Версия расширения | — |
|
||||||
| `Vendor` | Поставщик | — |
|
| `Vendor` | Поставщик | — |
|
||||||
| `CompatibilityMode` | Режим совместимости | `Version8_3_24` |
|
| `CompatibilityMode` | Режим совместимости | `Version8_3_24` |
|
||||||
| `ConfigPath` | Путь к выгрузке базовой конфигурации (авто-определяет CompatibilityMode и Language UUID) | — |
|
| `ConfigPath` | Путь к выгрузке базовой конфигурации (авто-определяет CompatibilityMode и Language UUID) | — |
|
||||||
| `NoRole` | Без основной роли | false |
|
| `NoRole` | Без основной роли | false |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-init.ps1" -Name "МоёРасширение"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-init.ps1" -Name "МоёРасширение"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Расширение для ERP с авто-определением совместимости из базовой конфигурации
|
# Расширение для ERP с авто-определением совместимости из базовой конфигурации
|
||||||
... -Name Расш1 -ConfigPath C:\WS\tasks\cfsrc\erp_8.3.24 -OutputDir src
|
... -Name Расш1 -ConfigPath C:\WS\tasks\cfsrc\erp_8.3.24 -OutputDir src
|
||||||
|
|
||||||
# Расширение-исправление с явным режимом совместимости
|
# Расширение-исправление с явным режимом совместимости
|
||||||
... -Name Расш1 -Purpose Patch -CompatibilityMode Version8_3_17 -OutputDir src
|
... -Name Расш1 -Purpose Patch -CompatibilityMode Version8_3_17 -OutputDir src
|
||||||
|
|
||||||
# Расширение-доработка с версией
|
# Расширение-доработка с версией
|
||||||
... -Name МоёРасширение -Version "1.0.0.1" -Vendor "Компания" -OutputDir src
|
... -Name МоёРасширение -Version "1.0.0.1" -Vendor "Компания" -OutputDir src
|
||||||
|
|
||||||
# Без роли, с явным префиксом
|
# Без роли, с явным префиксом
|
||||||
... -Name ИсправлениеБага -NamePrefix "ИБ_" -Purpose Patch -NoRole -OutputDir src
|
... -Name ИсправлениеБага -NamePrefix "ИБ_" -Purpose Patch -NoRole -OutputDir src
|
||||||
```
|
```
|
||||||
|
|
||||||
## Верификация
|
## Верификация
|
||||||
|
|
||||||
```
|
```
|
||||||
/cfe-validate <OutputDir>
|
/cfe-validate <OutputDir>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,279 +1,279 @@
|
|||||||
# cfe-init v1.2 — Create 1C configuration extension scaffold (CFE)
|
# cfe-init v1.2 — Create 1C configuration extension scaffold (CFE)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$Name,
|
[string]$Name,
|
||||||
[string]$Synonym = $Name,
|
[string]$Synonym = $Name,
|
||||||
[string]$NamePrefix,
|
[string]$NamePrefix,
|
||||||
[string]$OutputDir = "src",
|
[string]$OutputDir = "src",
|
||||||
[ValidateSet("Patch","Customization","AddOn")]
|
[ValidateSet("Patch","Customization","AddOn")]
|
||||||
[string]$Purpose = "Customization",
|
[string]$Purpose = "Customization",
|
||||||
[string]$Version,
|
[string]$Version,
|
||||||
[string]$Vendor,
|
[string]$Vendor,
|
||||||
[string]$CompatibilityMode = "Version8_3_24",
|
[string]$CompatibilityMode = "Version8_3_24",
|
||||||
[string]$ConfigPath,
|
[string]$ConfigPath,
|
||||||
[switch]$NoRole
|
[switch]$NoRole
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Default NamePrefix ---
|
# --- Default NamePrefix ---
|
||||||
if (-not $NamePrefix) {
|
if (-not $NamePrefix) {
|
||||||
$NamePrefix = "${Name}_"
|
$NamePrefix = "${Name}_"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Resolve output dir ---
|
# --- Resolve output dir ---
|
||||||
if (-not [System.IO.Path]::IsPathRooted($OutputDir)) {
|
if (-not [System.IO.Path]::IsPathRooted($OutputDir)) {
|
||||||
$OutputDir = Join-Path (Get-Location).Path $OutputDir
|
$OutputDir = Join-Path (Get-Location).Path $OutputDir
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Check existing ---
|
# --- Check existing ---
|
||||||
$cfgFile = Join-Path $OutputDir "Configuration.xml"
|
$cfgFile = Join-Path $OutputDir "Configuration.xml"
|
||||||
if (Test-Path $cfgFile) {
|
if (Test-Path $cfgFile) {
|
||||||
Write-Error "Configuration.xml already exists: $cfgFile"
|
Write-Error "Configuration.xml already exists: $cfgFile"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# MDClasses format version — inherited from the base config so the extension stays uniform
|
# MDClasses format version — inherited from the base config so the extension stays uniform
|
||||||
# with it (a 2.13 base must yield a 2.13 extension, else platform import rejects the mismatch).
|
# with it (a 2.13 base must yield a 2.13 extension, else platform import rejects the mismatch).
|
||||||
$formatVersion = "2.17"
|
$formatVersion = "2.17"
|
||||||
|
|
||||||
# --- Resolve ConfigPath ---
|
# --- Resolve ConfigPath ---
|
||||||
$baseLangUuid = "00000000-0000-0000-0000-000000000000"
|
$baseLangUuid = "00000000-0000-0000-0000-000000000000"
|
||||||
if ($ConfigPath) {
|
if ($ConfigPath) {
|
||||||
if (-not [System.IO.Path]::IsPathRooted($ConfigPath)) {
|
if (-not [System.IO.Path]::IsPathRooted($ConfigPath)) {
|
||||||
$ConfigPath = Join-Path (Get-Location).Path $ConfigPath
|
$ConfigPath = Join-Path (Get-Location).Path $ConfigPath
|
||||||
}
|
}
|
||||||
if (Test-Path $ConfigPath -PathType Container) {
|
if (Test-Path $ConfigPath -PathType Container) {
|
||||||
$candidate = Join-Path $ConfigPath "Configuration.xml"
|
$candidate = Join-Path $ConfigPath "Configuration.xml"
|
||||||
if (Test-Path $candidate) { $ConfigPath = $candidate }
|
if (Test-Path $candidate) { $ConfigPath = $candidate }
|
||||||
else { Write-Error "No Configuration.xml in config directory: $ConfigPath"; exit 1 }
|
else { Write-Error "No Configuration.xml in config directory: $ConfigPath"; exit 1 }
|
||||||
}
|
}
|
||||||
if (-not (Test-Path $ConfigPath)) { Write-Error "Config file not found: $ConfigPath"; exit 1 }
|
if (-not (Test-Path $ConfigPath)) { Write-Error "Config file not found: $ConfigPath"; exit 1 }
|
||||||
$cfgDir = Split-Path (Resolve-Path $ConfigPath).Path -Parent
|
$cfgDir = Split-Path (Resolve-Path $ConfigPath).Path -Parent
|
||||||
|
|
||||||
# 3a. Read Language UUID from base config
|
# 3a. Read Language UUID from base config
|
||||||
$baseLangFile = Join-Path (Join-Path $cfgDir "Languages") "Русский.xml"
|
$baseLangFile = Join-Path (Join-Path $cfgDir "Languages") "Русский.xml"
|
||||||
if (Test-Path $baseLangFile) {
|
if (Test-Path $baseLangFile) {
|
||||||
$baseLangDoc = New-Object System.Xml.XmlDocument
|
$baseLangDoc = New-Object System.Xml.XmlDocument
|
||||||
$baseLangDoc.PreserveWhitespace = $false
|
$baseLangDoc.PreserveWhitespace = $false
|
||||||
$baseLangDoc.Load($baseLangFile)
|
$baseLangDoc.Load($baseLangFile)
|
||||||
$langEl = $null
|
$langEl = $null
|
||||||
foreach ($c in $baseLangDoc.DocumentElement.ChildNodes) {
|
foreach ($c in $baseLangDoc.DocumentElement.ChildNodes) {
|
||||||
if ($c.NodeType -eq 'Element' -and $c.LocalName -eq 'Language') { $langEl = $c; break }
|
if ($c.NodeType -eq 'Element' -and $c.LocalName -eq 'Language') { $langEl = $c; break }
|
||||||
}
|
}
|
||||||
if ($langEl) {
|
if ($langEl) {
|
||||||
$baseLangUuid = $langEl.GetAttribute("uuid")
|
$baseLangUuid = $langEl.GetAttribute("uuid")
|
||||||
Write-Host "[INFO] Base config Language UUID: $baseLangUuid"
|
Write-Host "[INFO] Base config Language UUID: $baseLangUuid"
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[WARN] No <Language> element in $baseLangFile"
|
Write-Host "[WARN] No <Language> element in $baseLangFile"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[WARN] Base config language not found: $baseLangFile"
|
Write-Host "[WARN] Base config language not found: $baseLangFile"
|
||||||
}
|
}
|
||||||
|
|
||||||
# 3b. Read CompatibilityMode and InterfaceCompatibilityMode from base config
|
# 3b. Read CompatibilityMode and InterfaceCompatibilityMode from base config
|
||||||
$baseCfgDoc = New-Object System.Xml.XmlDocument
|
$baseCfgDoc = New-Object System.Xml.XmlDocument
|
||||||
$baseCfgDoc.PreserveWhitespace = $false
|
$baseCfgDoc.PreserveWhitespace = $false
|
||||||
$baseCfgDoc.Load((Resolve-Path $ConfigPath).Path)
|
$baseCfgDoc.Load((Resolve-Path $ConfigPath).Path)
|
||||||
$baseCfgNs = New-Object System.Xml.XmlNamespaceManager($baseCfgDoc.NameTable)
|
$baseCfgNs = New-Object System.Xml.XmlNamespaceManager($baseCfgDoc.NameTable)
|
||||||
$baseCfgNs.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
|
$baseCfgNs.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
|
||||||
$fmtVer = $baseCfgDoc.DocumentElement.GetAttribute("version")
|
$fmtVer = $baseCfgDoc.DocumentElement.GetAttribute("version")
|
||||||
if ($fmtVer) {
|
if ($fmtVer) {
|
||||||
$formatVersion = $fmtVer
|
$formatVersion = $fmtVer
|
||||||
Write-Host "[INFO] Base config format version: $formatVersion"
|
Write-Host "[INFO] Base config format version: $formatVersion"
|
||||||
}
|
}
|
||||||
$compatNode = $baseCfgDoc.SelectSingleNode("//md:Configuration/md:Properties/md:CompatibilityMode", $baseCfgNs)
|
$compatNode = $baseCfgDoc.SelectSingleNode("//md:Configuration/md:Properties/md:CompatibilityMode", $baseCfgNs)
|
||||||
if ($compatNode -and $compatNode.InnerText) {
|
if ($compatNode -and $compatNode.InnerText) {
|
||||||
$CompatibilityMode = $compatNode.InnerText.Trim()
|
$CompatibilityMode = $compatNode.InnerText.Trim()
|
||||||
Write-Host "[INFO] Base config CompatibilityMode: $CompatibilityMode"
|
Write-Host "[INFO] Base config CompatibilityMode: $CompatibilityMode"
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[WARN] CompatibilityMode not found in base config, using default: $CompatibilityMode"
|
Write-Host "[WARN] CompatibilityMode not found in base config, using default: $CompatibilityMode"
|
||||||
}
|
}
|
||||||
$ifcNode = $baseCfgDoc.SelectSingleNode("//md:Configuration/md:Properties/md:InterfaceCompatibilityMode", $baseCfgNs)
|
$ifcNode = $baseCfgDoc.SelectSingleNode("//md:Configuration/md:Properties/md:InterfaceCompatibilityMode", $baseCfgNs)
|
||||||
if ($ifcNode -and $ifcNode.InnerText) {
|
if ($ifcNode -and $ifcNode.InnerText) {
|
||||||
$InterfaceCompatibilityMode = $ifcNode.InnerText.Trim()
|
$InterfaceCompatibilityMode = $ifcNode.InnerText.Trim()
|
||||||
Write-Host "[INFO] Base config InterfaceCompatibilityMode: $InterfaceCompatibilityMode"
|
Write-Host "[INFO] Base config InterfaceCompatibilityMode: $InterfaceCompatibilityMode"
|
||||||
} else {
|
} else {
|
||||||
$InterfaceCompatibilityMode = "TaxiEnableVersion8_2"
|
$InterfaceCompatibilityMode = "TaxiEnableVersion8_2"
|
||||||
Write-Host "[WARN] InterfaceCompatibilityMode not found in base config, using default: $InterfaceCompatibilityMode"
|
Write-Host "[WARN] InterfaceCompatibilityMode not found in base config, using default: $InterfaceCompatibilityMode"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$InterfaceCompatibilityMode = "TaxiEnableVersion8_2"
|
$InterfaceCompatibilityMode = "TaxiEnableVersion8_2"
|
||||||
Write-Host "[WARN] Language ExtendedConfigurationObject set to zeros. Use -ConfigPath to auto-resolve from base config, or fix manually before loading."
|
Write-Host "[WARN] Language ExtendedConfigurationObject set to zeros. Use -ConfigPath to auto-resolve from base config, or fix manually before loading."
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Generate UUIDs ---
|
# --- Generate UUIDs ---
|
||||||
$uuidCfg = [guid]::NewGuid().ToString()
|
$uuidCfg = [guid]::NewGuid().ToString()
|
||||||
$uuidLang = [guid]::NewGuid().ToString()
|
$uuidLang = [guid]::NewGuid().ToString()
|
||||||
$uuidRole = [guid]::NewGuid().ToString()
|
$uuidRole = [guid]::NewGuid().ToString()
|
||||||
|
|
||||||
# 7 ContainedObject ObjectIds
|
# 7 ContainedObject ObjectIds
|
||||||
$co1 = [guid]::NewGuid().ToString()
|
$co1 = [guid]::NewGuid().ToString()
|
||||||
$co2 = [guid]::NewGuid().ToString()
|
$co2 = [guid]::NewGuid().ToString()
|
||||||
$co3 = [guid]::NewGuid().ToString()
|
$co3 = [guid]::NewGuid().ToString()
|
||||||
$co4 = [guid]::NewGuid().ToString()
|
$co4 = [guid]::NewGuid().ToString()
|
||||||
$co5 = [guid]::NewGuid().ToString()
|
$co5 = [guid]::NewGuid().ToString()
|
||||||
$co6 = [guid]::NewGuid().ToString()
|
$co6 = [guid]::NewGuid().ToString()
|
||||||
$co7 = [guid]::NewGuid().ToString()
|
$co7 = [guid]::NewGuid().ToString()
|
||||||
|
|
||||||
# --- Synonym XML ---
|
# --- Synonym XML ---
|
||||||
$synonymXml = ""
|
$synonymXml = ""
|
||||||
if ($Synonym) {
|
if ($Synonym) {
|
||||||
$synonymXml = "`r`n`t`t`t`t<v8:item>`r`n`t`t`t`t`t<v8:lang>ru</v8:lang>`r`n`t`t`t`t`t<v8:content>$([System.Security.SecurityElement]::Escape($Synonym))</v8:content>`r`n`t`t`t`t</v8:item>`r`n`t`t`t"
|
$synonymXml = "`r`n`t`t`t`t<v8:item>`r`n`t`t`t`t`t<v8:lang>ru</v8:lang>`r`n`t`t`t`t`t<v8:content>$([System.Security.SecurityElement]::Escape($Synonym))</v8:content>`r`n`t`t`t`t</v8:item>`r`n`t`t`t"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Optional properties ---
|
# --- Optional properties ---
|
||||||
$vendorXml = if ($Vendor) { [System.Security.SecurityElement]::Escape($Vendor) } else { "" }
|
$vendorXml = if ($Vendor) { [System.Security.SecurityElement]::Escape($Vendor) } else { "" }
|
||||||
$versionXml = if ($Version) { [System.Security.SecurityElement]::Escape($Version) } else { "" }
|
$versionXml = if ($Version) { [System.Security.SecurityElement]::Escape($Version) } else { "" }
|
||||||
|
|
||||||
# --- Role name ---
|
# --- Role name ---
|
||||||
$roleName = "${NamePrefix}ОсновнаяРоль"
|
$roleName = "${NamePrefix}ОсновнаяРоль"
|
||||||
|
|
||||||
# --- DefaultRoles XML ---
|
# --- DefaultRoles XML ---
|
||||||
$defaultRolesXml = ""
|
$defaultRolesXml = ""
|
||||||
if (-not $NoRole) {
|
if (-not $NoRole) {
|
||||||
$defaultRolesXml = "`r`n`t`t`t`t<xr:Item xsi:type=`"xr:MDObjectRef`">Role.$roleName</xr:Item>`r`n`t`t`t"
|
$defaultRolesXml = "`r`n`t`t`t`t<xr:Item xsi:type=`"xr:MDObjectRef`">Role.$roleName</xr:Item>`r`n`t`t`t"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- ChildObjects ---
|
# --- ChildObjects ---
|
||||||
$childObjectsXml = "`r`n`t`t`t<Language>Русский</Language>"
|
$childObjectsXml = "`r`n`t`t`t<Language>Русский</Language>"
|
||||||
if (-not $NoRole) {
|
if (-not $NoRole) {
|
||||||
$childObjectsXml += "`r`n`t`t`t<Role>$roleName</Role>"
|
$childObjectsXml += "`r`n`t`t`t<Role>$roleName</Role>"
|
||||||
}
|
}
|
||||||
$childObjectsXml += "`r`n`t`t"
|
$childObjectsXml += "`r`n`t`t"
|
||||||
|
|
||||||
# --- Configuration.xml ---
|
# --- Configuration.xml ---
|
||||||
$cfgXml = @"
|
$cfgXml = @"
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="$formatVersion">
|
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="$formatVersion">
|
||||||
<Configuration uuid="$uuidCfg">
|
<Configuration uuid="$uuidCfg">
|
||||||
<InternalInfo>
|
<InternalInfo>
|
||||||
<xr:ContainedObject>
|
<xr:ContainedObject>
|
||||||
<xr:ClassId>9cd510cd-abfc-11d4-9434-004095e12fc7</xr:ClassId>
|
<xr:ClassId>9cd510cd-abfc-11d4-9434-004095e12fc7</xr:ClassId>
|
||||||
<xr:ObjectId>$co1</xr:ObjectId>
|
<xr:ObjectId>$co1</xr:ObjectId>
|
||||||
</xr:ContainedObject>
|
</xr:ContainedObject>
|
||||||
<xr:ContainedObject>
|
<xr:ContainedObject>
|
||||||
<xr:ClassId>9fcd25a0-4822-11d4-9414-008048da11f9</xr:ClassId>
|
<xr:ClassId>9fcd25a0-4822-11d4-9414-008048da11f9</xr:ClassId>
|
||||||
<xr:ObjectId>$co2</xr:ObjectId>
|
<xr:ObjectId>$co2</xr:ObjectId>
|
||||||
</xr:ContainedObject>
|
</xr:ContainedObject>
|
||||||
<xr:ContainedObject>
|
<xr:ContainedObject>
|
||||||
<xr:ClassId>e3687481-0a87-462c-a166-9f34594f9bba</xr:ClassId>
|
<xr:ClassId>e3687481-0a87-462c-a166-9f34594f9bba</xr:ClassId>
|
||||||
<xr:ObjectId>$co3</xr:ObjectId>
|
<xr:ObjectId>$co3</xr:ObjectId>
|
||||||
</xr:ContainedObject>
|
</xr:ContainedObject>
|
||||||
<xr:ContainedObject>
|
<xr:ContainedObject>
|
||||||
<xr:ClassId>9de14907-ec23-4a07-96f0-85521cb6b53b</xr:ClassId>
|
<xr:ClassId>9de14907-ec23-4a07-96f0-85521cb6b53b</xr:ClassId>
|
||||||
<xr:ObjectId>$co4</xr:ObjectId>
|
<xr:ObjectId>$co4</xr:ObjectId>
|
||||||
</xr:ContainedObject>
|
</xr:ContainedObject>
|
||||||
<xr:ContainedObject>
|
<xr:ContainedObject>
|
||||||
<xr:ClassId>51f2d5d8-ea4d-4064-8892-82951750031e</xr:ClassId>
|
<xr:ClassId>51f2d5d8-ea4d-4064-8892-82951750031e</xr:ClassId>
|
||||||
<xr:ObjectId>$co5</xr:ObjectId>
|
<xr:ObjectId>$co5</xr:ObjectId>
|
||||||
</xr:ContainedObject>
|
</xr:ContainedObject>
|
||||||
<xr:ContainedObject>
|
<xr:ContainedObject>
|
||||||
<xr:ClassId>e68182ea-4237-4383-967f-90c1e3370bc7</xr:ClassId>
|
<xr:ClassId>e68182ea-4237-4383-967f-90c1e3370bc7</xr:ClassId>
|
||||||
<xr:ObjectId>$co6</xr:ObjectId>
|
<xr:ObjectId>$co6</xr:ObjectId>
|
||||||
</xr:ContainedObject>
|
</xr:ContainedObject>
|
||||||
<xr:ContainedObject>
|
<xr:ContainedObject>
|
||||||
<xr:ClassId>fb282519-d103-4dd3-bc12-cb271d631dfc</xr:ClassId>
|
<xr:ClassId>fb282519-d103-4dd3-bc12-cb271d631dfc</xr:ClassId>
|
||||||
<xr:ObjectId>$co7</xr:ObjectId>
|
<xr:ObjectId>$co7</xr:ObjectId>
|
||||||
</xr:ContainedObject>
|
</xr:ContainedObject>
|
||||||
</InternalInfo>
|
</InternalInfo>
|
||||||
<Properties>
|
<Properties>
|
||||||
<ObjectBelonging>Adopted</ObjectBelonging>
|
<ObjectBelonging>Adopted</ObjectBelonging>
|
||||||
<Name>$([System.Security.SecurityElement]::Escape($Name))</Name>
|
<Name>$([System.Security.SecurityElement]::Escape($Name))</Name>
|
||||||
<Synonym>$synonymXml</Synonym>
|
<Synonym>$synonymXml</Synonym>
|
||||||
<Comment/>
|
<Comment/>
|
||||||
<ConfigurationExtensionPurpose>$Purpose</ConfigurationExtensionPurpose>
|
<ConfigurationExtensionPurpose>$Purpose</ConfigurationExtensionPurpose>
|
||||||
<KeepMappingToExtendedConfigurationObjectsByIDs>true</KeepMappingToExtendedConfigurationObjectsByIDs>
|
<KeepMappingToExtendedConfigurationObjectsByIDs>true</KeepMappingToExtendedConfigurationObjectsByIDs>
|
||||||
<NamePrefix>$([System.Security.SecurityElement]::Escape($NamePrefix))</NamePrefix>
|
<NamePrefix>$([System.Security.SecurityElement]::Escape($NamePrefix))</NamePrefix>
|
||||||
<ConfigurationExtensionCompatibilityMode>$CompatibilityMode</ConfigurationExtensionCompatibilityMode>
|
<ConfigurationExtensionCompatibilityMode>$CompatibilityMode</ConfigurationExtensionCompatibilityMode>
|
||||||
<DefaultRunMode>ManagedApplication</DefaultRunMode>
|
<DefaultRunMode>ManagedApplication</DefaultRunMode>
|
||||||
<UsePurposes>
|
<UsePurposes>
|
||||||
<v8:Value xsi:type="app:ApplicationUsePurpose">PlatformApplication</v8:Value>
|
<v8:Value xsi:type="app:ApplicationUsePurpose">PlatformApplication</v8:Value>
|
||||||
</UsePurposes>
|
</UsePurposes>
|
||||||
<ScriptVariant>Russian</ScriptVariant>
|
<ScriptVariant>Russian</ScriptVariant>
|
||||||
<DefaultRoles>$defaultRolesXml</DefaultRoles>
|
<DefaultRoles>$defaultRolesXml</DefaultRoles>
|
||||||
<Vendor>$vendorXml</Vendor>
|
<Vendor>$vendorXml</Vendor>
|
||||||
<Version>$versionXml</Version>
|
<Version>$versionXml</Version>
|
||||||
<DefaultLanguage>Language.Русский</DefaultLanguage>
|
<DefaultLanguage>Language.Русский</DefaultLanguage>
|
||||||
<BriefInformation/>
|
<BriefInformation/>
|
||||||
<DetailedInformation/>
|
<DetailedInformation/>
|
||||||
<Copyright/>
|
<Copyright/>
|
||||||
<VendorInformationAddress/>
|
<VendorInformationAddress/>
|
||||||
<ConfigurationInformationAddress/>
|
<ConfigurationInformationAddress/>
|
||||||
<InterfaceCompatibilityMode>$InterfaceCompatibilityMode</InterfaceCompatibilityMode>
|
<InterfaceCompatibilityMode>$InterfaceCompatibilityMode</InterfaceCompatibilityMode>
|
||||||
</Properties>
|
</Properties>
|
||||||
<ChildObjects>$childObjectsXml</ChildObjects>
|
<ChildObjects>$childObjectsXml</ChildObjects>
|
||||||
</Configuration>
|
</Configuration>
|
||||||
</MetaDataObject>
|
</MetaDataObject>
|
||||||
"@
|
"@
|
||||||
|
|
||||||
# --- Languages/Русский.xml (adopted format) ---
|
# --- Languages/Русский.xml (adopted format) ---
|
||||||
$langXml = @"
|
$langXml = @"
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="$formatVersion">
|
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="$formatVersion">
|
||||||
<Language uuid="$uuidLang">
|
<Language uuid="$uuidLang">
|
||||||
<InternalInfo/>
|
<InternalInfo/>
|
||||||
<Properties>
|
<Properties>
|
||||||
<ObjectBelonging>Adopted</ObjectBelonging>
|
<ObjectBelonging>Adopted</ObjectBelonging>
|
||||||
<Name>Русский</Name>
|
<Name>Русский</Name>
|
||||||
<Comment/>
|
<Comment/>
|
||||||
<ExtendedConfigurationObject>$baseLangUuid</ExtendedConfigurationObject>
|
<ExtendedConfigurationObject>$baseLangUuid</ExtendedConfigurationObject>
|
||||||
<LanguageCode>ru</LanguageCode>
|
<LanguageCode>ru</LanguageCode>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Language>
|
</Language>
|
||||||
</MetaDataObject>
|
</MetaDataObject>
|
||||||
"@
|
"@
|
||||||
|
|
||||||
# --- Role XML ---
|
# --- Role XML ---
|
||||||
$roleXml = @"
|
$roleXml = @"
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="$formatVersion">
|
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="$formatVersion">
|
||||||
<Role uuid="$uuidRole">
|
<Role uuid="$uuidRole">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Name>$([System.Security.SecurityElement]::Escape($roleName))</Name>
|
<Name>$([System.Security.SecurityElement]::Escape($roleName))</Name>
|
||||||
<Synonym/>
|
<Synonym/>
|
||||||
<Comment/>
|
<Comment/>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Role>
|
</Role>
|
||||||
</MetaDataObject>
|
</MetaDataObject>
|
||||||
"@
|
"@
|
||||||
|
|
||||||
# --- Create directories ---
|
# --- Create directories ---
|
||||||
if (-not (Test-Path $OutputDir)) {
|
if (-not (Test-Path $OutputDir)) {
|
||||||
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
|
||||||
}
|
}
|
||||||
$langDir = Join-Path $OutputDir "Languages"
|
$langDir = Join-Path $OutputDir "Languages"
|
||||||
if (-not (Test-Path $langDir)) {
|
if (-not (Test-Path $langDir)) {
|
||||||
New-Item -ItemType Directory -Path $langDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $langDir -Force | Out-Null
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Write files with UTF-8 BOM ---
|
# --- Write files with UTF-8 BOM ---
|
||||||
$enc = New-Object System.Text.UTF8Encoding($true)
|
$enc = New-Object System.Text.UTF8Encoding($true)
|
||||||
|
|
||||||
[System.IO.File]::WriteAllText($cfgFile, $cfgXml, $enc)
|
[System.IO.File]::WriteAllText($cfgFile, $cfgXml, $enc)
|
||||||
$langFile = Join-Path $langDir "Русский.xml"
|
$langFile = Join-Path $langDir "Русский.xml"
|
||||||
[System.IO.File]::WriteAllText($langFile, $langXml, $enc)
|
[System.IO.File]::WriteAllText($langFile, $langXml, $enc)
|
||||||
|
|
||||||
# --- Role ---
|
# --- Role ---
|
||||||
if (-not $NoRole) {
|
if (-not $NoRole) {
|
||||||
$roleDir = Join-Path $OutputDir "Roles"
|
$roleDir = Join-Path $OutputDir "Roles"
|
||||||
if (-not (Test-Path $roleDir)) {
|
if (-not (Test-Path $roleDir)) {
|
||||||
New-Item -ItemType Directory -Path $roleDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $roleDir -Force | Out-Null
|
||||||
}
|
}
|
||||||
$roleFile = Join-Path $roleDir "$roleName.xml"
|
$roleFile = Join-Path $roleDir "$roleName.xml"
|
||||||
[System.IO.File]::WriteAllText($roleFile, $roleXml, $enc)
|
[System.IO.File]::WriteAllText($roleFile, $roleXml, $enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Output ---
|
# --- Output ---
|
||||||
Write-Host "[OK] Создано расширение: $Name"
|
Write-Host "[OK] Создано расширение: $Name"
|
||||||
Write-Host " Каталог: $OutputDir"
|
Write-Host " Каталог: $OutputDir"
|
||||||
Write-Host " Назначение: $Purpose"
|
Write-Host " Назначение: $Purpose"
|
||||||
Write-Host " Префикс: $NamePrefix"
|
Write-Host " Префикс: $NamePrefix"
|
||||||
Write-Host " Совместимость: $CompatibilityMode"
|
Write-Host " Совместимость: $CompatibilityMode"
|
||||||
Write-Host " Configuration.xml: $cfgFile"
|
Write-Host " Configuration.xml: $cfgFile"
|
||||||
Write-Host " Languages: $langFile"
|
Write-Host " Languages: $langFile"
|
||||||
if (-not $NoRole) {
|
if (-not $NoRole) {
|
||||||
Write-Host " Role: $roleFile"
|
Write-Host " Role: $roleFile"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,78 +1,78 @@
|
|||||||
---
|
---
|
||||||
name: cfe-patch-method
|
name: cfe-patch-method
|
||||||
description: Генерация перехватчика метода в расширении 1С (CFE). Используй когда нужно перехватить метод заимствованного объекта — вставить код до, после или вместо оригинального
|
description: Генерация перехватчика метода в расширении 1С (CFE). Используй когда нужно перехватить метод заимствованного объекта — вставить код до, после или вместо оригинального
|
||||||
argument-hint: -ExtensionPath <path> -ModulePath "Catalog.X.ObjectModule" -MethodName "ПриЗаписи" -InterceptorType Before
|
argument-hint: -ExtensionPath <path> -ModulePath "Catalog.X.ObjectModule" -MethodName "ПриЗаписи" -InterceptorType Before
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /cfe-patch-method — Генерация перехватчика метода
|
# /cfe-patch-method — Генерация перехватчика метода
|
||||||
|
|
||||||
Генерирует `.bsl` файл с декоратором перехвата для заимствованного объекта расширения. Создаёт файл или дописывает в существующий.
|
Генерирует `.bsl` файл с декоратором перехвата для заимствованного объекта расширения. Создаёт файл или дописывает в существующий.
|
||||||
|
|
||||||
## Предусловие
|
## Предусловие
|
||||||
|
|
||||||
Объект должен быть заимствован в расширение (`/cfe-borrow`). Скрипт читает `NamePrefix` из `Configuration.xml` расширения для формирования имени процедуры.
|
Объект должен быть заимствован в расширение (`/cfe-borrow`). Скрипт читает `NamePrefix` из `Configuration.xml` расширения для формирования имени процедуры.
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Описание | По умолчанию |
|
| Параметр | Описание | По умолчанию |
|
||||||
|----------|----------|--------------|
|
|----------|----------|--------------|
|
||||||
| `ExtensionPath` | Путь к расширению (обязат.) | — |
|
| `ExtensionPath` | Путь к расширению (обязат.) | — |
|
||||||
| `ModulePath` | Путь к модулю (обязат.) | — |
|
| `ModulePath` | Путь к модулю (обязат.) | — |
|
||||||
| `MethodName` | Имя перехватываемого метода (обязат.) | — |
|
| `MethodName` | Имя перехватываемого метода (обязат.) | — |
|
||||||
| `InterceptorType` | `Before` / `After` / `ModificationAndControl` (обязат.) | — |
|
| `InterceptorType` | `Before` / `After` / `ModificationAndControl` (обязат.) | — |
|
||||||
| `Context` | Директива контекста | `НаСервере` |
|
| `Context` | Директива контекста | `НаСервере` |
|
||||||
| `IsFunction` | Метод — функция (добавит `Возврат`) | false |
|
| `IsFunction` | Метод — функция (добавит `Возврат`) | false |
|
||||||
|
|
||||||
## Формат ModulePath
|
## Формат ModulePath
|
||||||
|
|
||||||
| ModulePath | Файл |
|
| ModulePath | Файл |
|
||||||
|------------|------|
|
|------------|------|
|
||||||
| `Catalog.X.ObjectModule` | `Catalogs/X/Ext/ObjectModule.bsl` |
|
| `Catalog.X.ObjectModule` | `Catalogs/X/Ext/ObjectModule.bsl` |
|
||||||
| `Catalog.X.ManagerModule` | `Catalogs/X/Ext/ManagerModule.bsl` |
|
| `Catalog.X.ManagerModule` | `Catalogs/X/Ext/ManagerModule.bsl` |
|
||||||
| `Catalog.X.Form.Y` | `Catalogs/X/Forms/Y/Ext/Form/Module.bsl` |
|
| `Catalog.X.Form.Y` | `Catalogs/X/Forms/Y/Ext/Form/Module.bsl` |
|
||||||
| `CommonModule.X` | `CommonModules/X/Ext/Module.bsl` |
|
| `CommonModule.X` | `CommonModules/X/Ext/Module.bsl` |
|
||||||
| `Document.X.ObjectModule` | `Documents/X/Ext/ObjectModule.bsl` |
|
| `Document.X.ObjectModule` | `Documents/X/Ext/ObjectModule.bsl` |
|
||||||
| `Document.X.Form.Y` | `Documents/X/Forms/Y/Ext/Form/Module.bsl` |
|
| `Document.X.Form.Y` | `Documents/X/Forms/Y/Ext/Form/Module.bsl` |
|
||||||
|
|
||||||
Аналогично для Report, DataProcessor, InformationRegister и других типов.
|
Аналогично для Report, DataProcessor, InformationRegister и других типов.
|
||||||
|
|
||||||
## Типы перехвата
|
## Типы перехвата
|
||||||
|
|
||||||
| InterceptorType | Декоратор | Назначение |
|
| InterceptorType | Декоратор | Назначение |
|
||||||
|-----------------|-----------|------------|
|
|-----------------|-----------|------------|
|
||||||
| `Before` | `&Перед` | Код до вызова оригинального метода |
|
| `Before` | `&Перед` | Код до вызова оригинального метода |
|
||||||
| `After` | `&После` | Код после вызова оригинального метода |
|
| `After` | `&После` | Код после вызова оригинального метода |
|
||||||
| `ModificationAndControl` | `&ИзменениеИКонтроль` | Копия тела метода с маркерами `#Вставка`/`#Удаление` |
|
| `ModificationAndControl` | `&ИзменениеИКонтроль` | Копия тела метода с маркерами `#Вставка`/`#Удаление` |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-patch-method.ps1" -ExtensionPath src -ModulePath "Catalog.Контрагенты.ObjectModule" -MethodName "ПриЗаписи" -InterceptorType Before
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-patch-method.ps1" -ExtensionPath src -ModulePath "Catalog.Контрагенты.ObjectModule" -MethodName "ПриЗаписи" -InterceptorType Before
|
||||||
```
|
```
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Перехват &Перед на сервере
|
# Перехват &Перед на сервере
|
||||||
... -ExtensionPath src -ModulePath "Catalog.Контрагенты.ObjectModule" -MethodName "ПриЗаписи" -InterceptorType Before
|
... -ExtensionPath src -ModulePath "Catalog.Контрагенты.ObjectModule" -MethodName "ПриЗаписи" -InterceptorType Before
|
||||||
|
|
||||||
# Перехват &После на клиенте
|
# Перехват &После на клиенте
|
||||||
... -ExtensionPath src -ModulePath "Document.Заказ.Form.ФормаДокумента" -MethodName "ПослеЗаписиНаСервере" -InterceptorType After -Context "НаКлиенте"
|
... -ExtensionPath src -ModulePath "Document.Заказ.Form.ФормаДокумента" -MethodName "ПослеЗаписиНаСервере" -InterceptorType After -Context "НаКлиенте"
|
||||||
|
|
||||||
# ИзменениеИКонтроль для функции
|
# ИзменениеИКонтроль для функции
|
||||||
... -ExtensionPath src -ModulePath "CommonModule.ОбщийМодуль" -MethodName "ПолучитьДанные" -InterceptorType ModificationAndControl -IsFunction
|
... -ExtensionPath src -ModulePath "CommonModule.ОбщийМодуль" -MethodName "ПолучитьДанные" -InterceptorType ModificationAndControl -IsFunction
|
||||||
```
|
```
|
||||||
|
|
||||||
## Генерируемый код (Before)
|
## Генерируемый код (Before)
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
&НаСервере
|
&НаСервере
|
||||||
&Перед("ПриЗаписи")
|
&Перед("ПриЗаписи")
|
||||||
Процедура Расш1_ПриЗаписи()
|
Процедура Расш1_ПриЗаписи()
|
||||||
// TODO: код перед вызовом оригинального метода
|
// TODO: код перед вызовом оригинального метода
|
||||||
КонецПроцедуры
|
КонецПроцедуры
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
---
|
---
|
||||||
name: cfe-validate
|
name: cfe-validate
|
||||||
description: Валидация расширения конфигурации 1С (CFE). Используй после создания или модификации расширения для проверки корректности
|
description: Валидация расширения конфигурации 1С (CFE). Используй после создания или модификации расширения для проверки корректности
|
||||||
argument-hint: <ExtensionPath> [-Detailed] [-MaxErrors 30]
|
argument-hint: <ExtensionPath> [-Detailed] [-MaxErrors 30]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /cfe-validate — валидация расширения конфигурации (CFE)
|
# /cfe-validate — валидация расширения конфигурации (CFE)
|
||||||
|
|
||||||
Проверяет структурную корректность расширения: XML-формат, свойства, состав, заимствованные объекты. Аналог `/cf-validate`, но для расширений.
|
Проверяет структурную корректность расширения: XML-формат, свойства, состав, заимствованные объекты. Аналог `/cf-validate`, но для расширений.
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Обяз. | Умолч. | Описание |
|
| Параметр | Обяз. | Умолч. | Описание |
|
||||||
|---------------|:-----:|---------|-------------------------------------------------|
|
|---------------|:-----:|---------|-------------------------------------------------|
|
||||||
| ExtensionPath | да | — | Путь к каталогу или Configuration.xml расширения |
|
| ExtensionPath | да | — | Путь к каталогу или Configuration.xml расширения |
|
||||||
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
||||||
| MaxErrors | нет | 30 | Остановиться после N ошибок |
|
| MaxErrors | нет | 30 | Остановиться после N ошибок |
|
||||||
| OutFile | нет | — | Записать результат в файл |
|
| OutFile | нет | — | Записать результат в файл |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-validate.ps1" -ExtensionPath "src"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-validate.ps1" -ExtensionPath "src"
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-validate.ps1" -ExtensionPath "src/Configuration.xml"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-validate.ps1" -ExtensionPath "src/Configuration.xml"
|
||||||
```
|
```
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,70 +1,70 @@
|
|||||||
---
|
---
|
||||||
name: db-create
|
name: db-create
|
||||||
description: Создание информационной базы 1С. Используй когда нужно создать базу, новую ИБ, пустую базу
|
description: Создание информационной базы 1С. Используй когда нужно создать базу, новую ИБ, пустую базу
|
||||||
argument-hint: <path|name>
|
argument-hint: <path|name>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Write
|
- Write
|
||||||
- Glob
|
- Glob
|
||||||
- AskUserQuestion
|
- AskUserQuestion
|
||||||
---
|
---
|
||||||
|
|
||||||
# /db-create — Создание информационной базы
|
# /db-create — Создание информационной базы
|
||||||
|
|
||||||
Создаёт новую информационную базу 1С (файловую или серверную) и предлагает зарегистрировать в `.v8-project.json`.
|
Создаёт новую информационную базу 1С (файловую или серверную) и предлагает зарегистрировать в `.v8-project.json`.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/db-create <path> — файловая база по указанному пути
|
/db-create <path> — файловая база по указанному пути
|
||||||
/db-create <server>/<name> — серверная база
|
/db-create <server>/<name> — серверная база
|
||||||
/db-create — интерактивно
|
/db-create — интерактивно
|
||||||
```
|
```
|
||||||
|
|
||||||
## Параметры подключения
|
## Параметры подключения
|
||||||
|
|
||||||
Прочитай `.v8-project.json` из корня проекта для `v8path` (путь к платформе).
|
Прочитай `.v8-project.json` из корня проекта для `v8path` (путь к платформе).
|
||||||
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
||||||
После создания базы предложи зарегистрировать через `/db-list add`.
|
После создания базы предложи зарегистрировать через `/db-list add`.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" <параметры>
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|----------|:------------:|----------|
|
|----------|:------------:|----------|
|
||||||
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
||||||
| `-InfoBasePath <путь>` | * | Путь к файловой базе |
|
| `-InfoBasePath <путь>` | * | Путь к файловой базе |
|
||||||
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
||||||
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
||||||
| `-UseTemplate <файл>` | нет | Создать из шаблона (.cf или .dt) |
|
| `-UseTemplate <файл>` | нет | Создать из шаблона (.cf или .dt) |
|
||||||
| `-AddToList` | нет | Добавить в список баз 1С |
|
| `-AddToList` | нет | Добавить в список баз 1С |
|
||||||
| `-ListName <имя>` | нет | Имя базы в списке |
|
| `-ListName <имя>` | нет | Имя базы в списке |
|
||||||
|
|
||||||
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
||||||
|
|
||||||
## После создания
|
## После создания
|
||||||
|
|
||||||
Предложи зарегистрировать базу в `.v8-project.json` (через `/db-list add`)
|
Предложи зарегистрировать базу в `.v8-project.json` (через `/db-list add`)
|
||||||
3. Если указан шаблон `/UseTemplate` — предупреди что конфигурация будет загружена из шаблона
|
3. Если указан шаблон `/UseTemplate` — предупреди что конфигурация будет загружена из шаблона
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Создать файловую базу
|
# Создать файловую базу
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB"
|
||||||
|
|
||||||
# Создать серверную базу
|
# Создать серверную базу
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test"
|
||||||
|
|
||||||
# Создать из шаблона CF
|
# Создать из шаблона CF
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB" -UseTemplate "C:\Templates\config.cf"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB" -UseTemplate "C:\Templates\config.cf"
|
||||||
|
|
||||||
# Создать и добавить в список баз
|
# Создать и добавить в список баз
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB" -AddToList -ListName "Новая база"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB" -AddToList -ListName "Новая база"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,220 +1,220 @@
|
|||||||
# db-create v1.4 — Create 1C information base
|
# db-create v1.4 — Create 1C information base
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Создание информационной базы 1С
|
Создание информационной базы 1С
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Создаёт новую информационную базу 1С (файловую или серверную).
|
Создаёт новую информационную базу 1С (файловую или серверную).
|
||||||
Поддерживает создание из шаблона и добавление в список баз.
|
Поддерживает создание из шаблона и добавление в список баз.
|
||||||
|
|
||||||
.PARAMETER V8Path
|
.PARAMETER V8Path
|
||||||
Путь к каталогу bin платформы или к 1cv8.exe
|
Путь к каталогу bin платформы или к 1cv8.exe
|
||||||
|
|
||||||
.PARAMETER InfoBasePath
|
.PARAMETER InfoBasePath
|
||||||
Путь к файловой информационной базе
|
Путь к файловой информационной базе
|
||||||
|
|
||||||
.PARAMETER InfoBaseServer
|
.PARAMETER InfoBaseServer
|
||||||
Сервер 1С (для серверной базы)
|
Сервер 1С (для серверной базы)
|
||||||
|
|
||||||
.PARAMETER InfoBaseRef
|
.PARAMETER InfoBaseRef
|
||||||
Имя базы на сервере
|
Имя базы на сервере
|
||||||
|
|
||||||
.PARAMETER UseTemplate
|
.PARAMETER UseTemplate
|
||||||
Путь к файлу шаблона (.cf или .dt)
|
Путь к файлу шаблона (.cf или .dt)
|
||||||
|
|
||||||
.PARAMETER AddToList
|
.PARAMETER AddToList
|
||||||
Добавить в список баз 1С
|
Добавить в список баз 1С
|
||||||
|
|
||||||
.PARAMETER ListName
|
.PARAMETER ListName
|
||||||
Имя базы в списке
|
Имя базы в списке
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-create.ps1 -InfoBasePath "C:\Bases\NewDB"
|
.\db-create.ps1 -InfoBasePath "C:\Bases\NewDB"
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-create.ps1 -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test"
|
.\db-create.ps1 -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test"
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-create.ps1 -InfoBasePath "C:\Bases\NewDB" -UseTemplate "C:\Templates\config.cf" -AddToList -ListName "Новая база"
|
.\db-create.ps1 -InfoBasePath "C:\Bases\NewDB" -UseTemplate "C:\Templates\config.cf" -AddToList -ListName "Новая база"
|
||||||
#>
|
#>
|
||||||
|
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$V8Path,
|
[string]$V8Path,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBasePath,
|
[string]$InfoBasePath,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseServer,
|
[string]$InfoBaseServer,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseRef,
|
[string]$InfoBaseRef,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$UseTemplate,
|
[string]$UseTemplate,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[switch]$AddToList,
|
[switch]$AddToList,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$ListName
|
[string]$ListName
|
||||||
)
|
)
|
||||||
|
|
||||||
$OutputEncoding = [System.Text.Encoding]::UTF8
|
$OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Resolve V8Path ---
|
# --- Resolve V8Path ---
|
||||||
function Find-ProjectV8Path {
|
function Find-ProjectV8Path {
|
||||||
$dir = (Get-Location).Path
|
$dir = (Get-Location).Path
|
||||||
while ($dir) {
|
while ($dir) {
|
||||||
$pf = Join-Path $dir ".v8-project.json"
|
$pf = Join-Path $dir ".v8-project.json"
|
||||||
if (Test-Path $pf) {
|
if (Test-Path $pf) {
|
||||||
try {
|
try {
|
||||||
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||||
if ($j.v8path) { return [string]$j.v8path }
|
if ($j.v8path) { return [string]$j.v8path }
|
||||||
} catch {}
|
} catch {}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
$parent = Split-Path $dir -Parent
|
$parent = Split-Path $dir -Parent
|
||||||
if (-not $parent -or $parent -eq $dir) { break }
|
if (-not $parent -or $parent -eq $dir) { break }
|
||||||
$dir = $parent
|
$dir = $parent
|
||||||
}
|
}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$V8Path = Find-ProjectV8Path
|
$V8Path = Find-ProjectV8Path
|
||||||
}
|
}
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
||||||
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
||||||
Select-Object -First 1
|
Select-Object -First 1
|
||||||
if ($found) {
|
if ($found) {
|
||||||
$V8Path = $found.FullName
|
$V8Path = $found.FullName
|
||||||
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Test-Path $V8Path -PathType Container) {
|
if (Test-Path $V8Path -PathType Container) {
|
||||||
$V8Path = Join-Path $V8Path "1cv8.exe"
|
$V8Path = Join-Path $V8Path "1cv8.exe"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $V8Path)) {
|
if (-not (Test-Path $V8Path)) {
|
||||||
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Detect engine (ibcmd vs 1cv8) by exe name ---
|
# --- Detect engine (ibcmd vs 1cv8) by exe name ---
|
||||||
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
||||||
|
|
||||||
# --- Validate connection ---
|
# --- Validate connection ---
|
||||||
if ($engine -eq "ibcmd") {
|
if ($engine -eq "ibcmd") {
|
||||||
if (-not $InfoBasePath) {
|
if (-not $InfoBasePath) {
|
||||||
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath)" -ForegroundColor Red
|
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath)" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
} elseif (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
} elseif (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
||||||
Write-Host "Error: specify -InfoBasePath or -InfoBaseServer + -InfoBaseRef" -ForegroundColor Red
|
Write-Host "Error: specify -InfoBasePath or -InfoBaseServer + -InfoBaseRef" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Validate template ---
|
# --- Validate template ---
|
||||||
if ($UseTemplate -and -not (Test-Path $UseTemplate)) {
|
if ($UseTemplate -and -not (Test-Path $UseTemplate)) {
|
||||||
Write-Host "Error: template file not found: $UseTemplate" -ForegroundColor Red
|
Write-Host "Error: template file not found: $UseTemplate" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Temp dir ---
|
# --- Temp dir ---
|
||||||
$tempDir = Join-Path $env:TEMP "db_create_$(Get-Random)"
|
$tempDir = Join-Path $env:TEMP "db_create_$(Get-Random)"
|
||||||
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($engine -eq "ibcmd") {
|
if ($engine -eq "ibcmd") {
|
||||||
# --- ibcmd branch (file infobase only) ---
|
# --- ibcmd branch (file infobase only) ---
|
||||||
$arguments = @("infobase", "create", "--db-path=$InfoBasePath", "--create-database")
|
$arguments = @("infobase", "create", "--db-path=$InfoBasePath", "--create-database")
|
||||||
if ($UseTemplate) {
|
if ($UseTemplate) {
|
||||||
if ([System.IO.Path]::GetExtension($UseTemplate) -ieq ".dt") {
|
if ([System.IO.Path]::GetExtension($UseTemplate) -ieq ".dt") {
|
||||||
$arguments += "--restore=$UseTemplate"
|
$arguments += "--restore=$UseTemplate"
|
||||||
} else {
|
} else {
|
||||||
$arguments += "--load=$UseTemplate", "--apply"
|
$arguments += "--load=$UseTemplate", "--apply"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$arguments += "--data=$tempDir"
|
$arguments += "--data=$tempDir"
|
||||||
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
||||||
$output = & $V8Path @arguments 2>&1
|
$output = & $V8Path @arguments 2>&1
|
||||||
$exitCode = $LASTEXITCODE
|
$exitCode = $LASTEXITCODE
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
Write-Host "Information base created successfully: $InfoBasePath" -ForegroundColor Green
|
Write-Host "Information base created successfully: $InfoBasePath" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error creating information base (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error creating information base (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
if ($output) { Write-Host ($output | Out-String) }
|
if ($output) { Write-Host ($output | Out-String) }
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 1cv8 branch ---
|
# --- 1cv8 branch ---
|
||||||
# --- Build arguments ---
|
# --- Build arguments ---
|
||||||
$arguments = @("CREATEINFOBASE")
|
$arguments = @("CREATEINFOBASE")
|
||||||
|
|
||||||
if ($InfoBaseServer -and $InfoBaseRef) {
|
if ($InfoBaseServer -and $InfoBaseRef) {
|
||||||
$arguments += "Srvr=`"$InfoBaseServer`";Ref=`"$InfoBaseRef`""
|
$arguments += "Srvr=`"$InfoBaseServer`";Ref=`"$InfoBaseRef`""
|
||||||
} else {
|
} else {
|
||||||
$arguments += "File=`"$InfoBasePath`""
|
$arguments += "File=`"$InfoBasePath`""
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Template ---
|
# --- Template ---
|
||||||
if ($UseTemplate) {
|
if ($UseTemplate) {
|
||||||
$arguments += "/UseTemplate", "`"$UseTemplate`""
|
$arguments += "/UseTemplate", "`"$UseTemplate`""
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Add to list ---
|
# --- Add to list ---
|
||||||
if ($AddToList) {
|
if ($AddToList) {
|
||||||
if ($ListName) {
|
if ($ListName) {
|
||||||
$arguments += "/AddToList", "`"$ListName`""
|
$arguments += "/AddToList", "`"$ListName`""
|
||||||
} else {
|
} else {
|
||||||
$arguments += "/AddToList"
|
$arguments += "/AddToList"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Output ---
|
# --- Output ---
|
||||||
$outFile = Join-Path $tempDir "create_log.txt"
|
$outFile = Join-Path $tempDir "create_log.txt"
|
||||||
$arguments += "/Out", "`"$outFile`""
|
$arguments += "/Out", "`"$outFile`""
|
||||||
$arguments += "/DisableStartupDialogs"
|
$arguments += "/DisableStartupDialogs"
|
||||||
|
|
||||||
# --- Execute ---
|
# --- Execute ---
|
||||||
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
||||||
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
||||||
$exitCode = $process.ExitCode
|
$exitCode = $process.ExitCode
|
||||||
|
|
||||||
# --- Result ---
|
# --- Result ---
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
if ($InfoBaseServer -and $InfoBaseRef) {
|
if ($InfoBaseServer -and $InfoBaseRef) {
|
||||||
Write-Host "Information base created successfully: $InfoBaseServer/$InfoBaseRef" -ForegroundColor Green
|
Write-Host "Information base created successfully: $InfoBaseServer/$InfoBaseRef" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Information base created successfully: $InfoBasePath" -ForegroundColor Green
|
Write-Host "Information base created successfully: $InfoBasePath" -ForegroundColor Green
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error creating information base (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error creating information base (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Test-Path $outFile) {
|
if (Test-Path $outFile) {
|
||||||
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
||||||
if ($logContent) {
|
if ($logContent) {
|
||||||
Write-Host "--- Log ---"
|
Write-Host "--- Log ---"
|
||||||
Write-Host $logContent
|
Write-Host $logContent
|
||||||
Write-Host "--- End ---"
|
Write-Host "--- End ---"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (Test-Path $tempDir) {
|
if (Test-Path $tempDir) {
|
||||||
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,68 +1,68 @@
|
|||||||
---
|
---
|
||||||
name: db-dump-cf
|
name: db-dump-cf
|
||||||
description: Выгрузка конфигурации 1С в CF-файл. Используй когда нужно выгрузить конфигурацию в CF, сохранить конфигурацию, сделать бэкап CF
|
description: Выгрузка конфигурации 1С в CF-файл. Используй когда нужно выгрузить конфигурацию в CF, сохранить конфигурацию, сделать бэкап CF
|
||||||
argument-hint: "[database] [output.cf]"
|
argument-hint: "[database] [output.cf]"
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
- AskUserQuestion
|
- AskUserQuestion
|
||||||
---
|
---
|
||||||
|
|
||||||
# /db-dump-cf — Выгрузка конфигурации в CF-файл
|
# /db-dump-cf — Выгрузка конфигурации в CF-файл
|
||||||
|
|
||||||
Выгружает конфигурацию информационной базы в бинарный CF-файл.
|
Выгружает конфигурацию информационной базы в бинарный CF-файл.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/db-dump-cf [database] [output.cf]
|
/db-dump-cf [database] [output.cf]
|
||||||
/db-dump-cf dev config.cf
|
/db-dump-cf dev config.cf
|
||||||
/db-dump-cf — база по умолчанию, файл config.cf
|
/db-dump-cf — база по умолчанию, файл config.cf
|
||||||
```
|
```
|
||||||
|
|
||||||
## Параметры подключения
|
## Параметры подключения
|
||||||
|
|
||||||
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
||||||
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
||||||
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
||||||
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
||||||
4. Если ветка не совпала — используй `default`
|
4. Если ветка не совпала — используй `default`
|
||||||
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
||||||
Если файла нет — предложи `/db-list add`.
|
Если файла нет — предложи `/db-list add`.
|
||||||
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" <параметры>
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|----------|:------------:|----------|
|
|----------|:------------:|----------|
|
||||||
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
||||||
| `-InfoBasePath <путь>` | * | Файловая база |
|
| `-InfoBasePath <путь>` | * | Файловая база |
|
||||||
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
||||||
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
||||||
| `-UserName <имя>` | нет | Имя пользователя |
|
| `-UserName <имя>` | нет | Имя пользователя |
|
||||||
| `-Password <пароль>` | нет | Пароль |
|
| `-Password <пароль>` | нет | Пароль |
|
||||||
| `-OutputFile <путь>` | да | Путь к выходному CF-файлу |
|
| `-OutputFile <путь>` | да | Путь к выходному CF-файлу |
|
||||||
| `-Extension <имя>` | нет | Выгрузить расширение |
|
| `-Extension <имя>` | нет | Выгрузить расширение |
|
||||||
| `-AllExtensions` | нет | Выгрузить все расширения |
|
| `-AllExtensions` | нет | Выгрузить все расширения |
|
||||||
|
|
||||||
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Выгрузка конфигурации (файловая база)
|
# Выгрузка конфигурации (файловая база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "C:\backup\config.cf"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "C:\backup\config.cf"
|
||||||
|
|
||||||
# Серверная база
|
# Серверная база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -OutputFile "config.cf"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -OutputFile "config.cf"
|
||||||
|
|
||||||
# Выгрузка расширения
|
# Выгрузка расширения
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "ext.cfe" -Extension "МоёРасширение"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "ext.cfe" -Extension "МоёРасширение"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,224 +1,224 @@
|
|||||||
# db-dump-cf v1.4 — Dump 1C configuration to CF file
|
# db-dump-cf v1.4 — Dump 1C configuration to CF file
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Выгрузка конфигурации 1С в CF-файл
|
Выгрузка конфигурации 1С в CF-файл
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Выгружает конфигурацию информационной базы в бинарный CF-файл.
|
Выгружает конфигурацию информационной базы в бинарный CF-файл.
|
||||||
Поддерживает выгрузку расширений.
|
Поддерживает выгрузку расширений.
|
||||||
|
|
||||||
.PARAMETER V8Path
|
.PARAMETER V8Path
|
||||||
Путь к каталогу bin платформы или к 1cv8.exe
|
Путь к каталогу bin платформы или к 1cv8.exe
|
||||||
|
|
||||||
.PARAMETER InfoBasePath
|
.PARAMETER InfoBasePath
|
||||||
Путь к файловой информационной базе
|
Путь к файловой информационной базе
|
||||||
|
|
||||||
.PARAMETER InfoBaseServer
|
.PARAMETER InfoBaseServer
|
||||||
Сервер 1С (для серверной базы)
|
Сервер 1С (для серверной базы)
|
||||||
|
|
||||||
.PARAMETER InfoBaseRef
|
.PARAMETER InfoBaseRef
|
||||||
Имя базы на сервере
|
Имя базы на сервере
|
||||||
|
|
||||||
.PARAMETER UserName
|
.PARAMETER UserName
|
||||||
Имя пользователя 1С
|
Имя пользователя 1С
|
||||||
|
|
||||||
.PARAMETER Password
|
.PARAMETER Password
|
||||||
Пароль пользователя
|
Пароль пользователя
|
||||||
|
|
||||||
.PARAMETER OutputFile
|
.PARAMETER OutputFile
|
||||||
Путь к выходному CF-файлу
|
Путь к выходному CF-файлу
|
||||||
|
|
||||||
.PARAMETER Extension
|
.PARAMETER Extension
|
||||||
Имя расширения для выгрузки
|
Имя расширения для выгрузки
|
||||||
|
|
||||||
.PARAMETER AllExtensions
|
.PARAMETER AllExtensions
|
||||||
Выгрузить все расширения
|
Выгрузить все расширения
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-dump-cf.ps1 -InfoBasePath "C:\Bases\MyDB" -OutputFile "config.cf"
|
.\db-dump-cf.ps1 -InfoBasePath "C:\Bases\MyDB" -OutputFile "config.cf"
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-dump-cf.ps1 -InfoBasePath "C:\Bases\MyDB" -OutputFile "ext.cfe" -Extension "МоёРасширение"
|
.\db-dump-cf.ps1 -InfoBasePath "C:\Bases\MyDB" -OutputFile "ext.cfe" -Extension "МоёРасширение"
|
||||||
#>
|
#>
|
||||||
|
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$V8Path,
|
[string]$V8Path,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBasePath,
|
[string]$InfoBasePath,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseServer,
|
[string]$InfoBaseServer,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseRef,
|
[string]$InfoBaseRef,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$UserName,
|
[string]$UserName,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Password,
|
[string]$Password,
|
||||||
|
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
[string]$OutputFile,
|
[string]$OutputFile,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Extension,
|
[string]$Extension,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[switch]$AllExtensions
|
[switch]$AllExtensions
|
||||||
)
|
)
|
||||||
|
|
||||||
$OutputEncoding = [System.Text.Encoding]::UTF8
|
$OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Resolve V8Path ---
|
# --- Resolve V8Path ---
|
||||||
function Find-ProjectV8Path {
|
function Find-ProjectV8Path {
|
||||||
$dir = (Get-Location).Path
|
$dir = (Get-Location).Path
|
||||||
while ($dir) {
|
while ($dir) {
|
||||||
$pf = Join-Path $dir ".v8-project.json"
|
$pf = Join-Path $dir ".v8-project.json"
|
||||||
if (Test-Path $pf) {
|
if (Test-Path $pf) {
|
||||||
try {
|
try {
|
||||||
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||||
if ($j.v8path) { return [string]$j.v8path }
|
if ($j.v8path) { return [string]$j.v8path }
|
||||||
} catch {}
|
} catch {}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
$parent = Split-Path $dir -Parent
|
$parent = Split-Path $dir -Parent
|
||||||
if (-not $parent -or $parent -eq $dir) { break }
|
if (-not $parent -or $parent -eq $dir) { break }
|
||||||
$dir = $parent
|
$dir = $parent
|
||||||
}
|
}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$V8Path = Find-ProjectV8Path
|
$V8Path = Find-ProjectV8Path
|
||||||
}
|
}
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
||||||
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
||||||
Select-Object -First 1
|
Select-Object -First 1
|
||||||
if ($found) {
|
if ($found) {
|
||||||
$V8Path = $found.FullName
|
$V8Path = $found.FullName
|
||||||
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Test-Path $V8Path -PathType Container) {
|
if (Test-Path $V8Path -PathType Container) {
|
||||||
$V8Path = Join-Path $V8Path "1cv8.exe"
|
$V8Path = Join-Path $V8Path "1cv8.exe"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $V8Path)) {
|
if (-not (Test-Path $V8Path)) {
|
||||||
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Detect engine (ibcmd vs 1cv8) by exe name ---
|
# --- Detect engine (ibcmd vs 1cv8) by exe name ---
|
||||||
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
||||||
|
|
||||||
# --- Validate connection ---
|
# --- Validate connection ---
|
||||||
if ($engine -eq "ibcmd") {
|
if ($engine -eq "ibcmd") {
|
||||||
if (-not $InfoBasePath) {
|
if (-not $InfoBasePath) {
|
||||||
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath)" -ForegroundColor Red
|
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath)" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
} elseif (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
} elseif (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
||||||
Write-Host "Error: specify -InfoBasePath or -InfoBaseServer + -InfoBaseRef" -ForegroundColor Red
|
Write-Host "Error: specify -InfoBasePath or -InfoBaseServer + -InfoBaseRef" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Ensure output directory exists ---
|
# --- Ensure output directory exists ---
|
||||||
$outDir = Split-Path $OutputFile -Parent
|
$outDir = Split-Path $OutputFile -Parent
|
||||||
if ($outDir -and -not (Test-Path $outDir)) {
|
if ($outDir -and -not (Test-Path $outDir)) {
|
||||||
New-Item -ItemType Directory -Path $outDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $outDir -Force | Out-Null
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Temp dir ---
|
# --- Temp dir ---
|
||||||
$tempDir = Join-Path $env:TEMP "db_dump_cf_$(Get-Random)"
|
$tempDir = Join-Path $env:TEMP "db_dump_cf_$(Get-Random)"
|
||||||
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($engine -eq "ibcmd") {
|
if ($engine -eq "ibcmd") {
|
||||||
# --- ibcmd branch (file infobase only) ---
|
# --- ibcmd branch (file infobase only) ---
|
||||||
if ($AllExtensions) {
|
if ($AllExtensions) {
|
||||||
Write-Host "Error: ibcmd config save does not support -AllExtensions (use -Extension)" -ForegroundColor Red
|
Write-Host "Error: ibcmd config save does not support -AllExtensions (use -Extension)" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
$arguments = @("infobase", "config", "save", "--db-path=$InfoBasePath")
|
$arguments = @("infobase", "config", "save", "--db-path=$InfoBasePath")
|
||||||
if ($Extension) { $arguments += "--extension=$Extension" }
|
if ($Extension) { $arguments += "--extension=$Extension" }
|
||||||
$arguments += "$OutputFile"
|
$arguments += "$OutputFile"
|
||||||
if ($UserName) { $arguments += "--user=$UserName" }
|
if ($UserName) { $arguments += "--user=$UserName" }
|
||||||
if ($Password) { $arguments += "--password=$Password" }
|
if ($Password) { $arguments += "--password=$Password" }
|
||||||
$arguments += "--data=$tempDir"
|
$arguments += "--data=$tempDir"
|
||||||
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
||||||
$output = & $V8Path @arguments 2>&1
|
$output = & $V8Path @arguments 2>&1
|
||||||
$exitCode = $LASTEXITCODE
|
$exitCode = $LASTEXITCODE
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
Write-Host "Configuration dumped successfully to: $OutputFile" -ForegroundColor Green
|
Write-Host "Configuration dumped successfully to: $OutputFile" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error dumping configuration (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error dumping configuration (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
if ($output) { Write-Host ($output | Out-String) }
|
if ($output) { Write-Host ($output | Out-String) }
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 1cv8 branch ---
|
# --- 1cv8 branch ---
|
||||||
# --- Build arguments ---
|
# --- Build arguments ---
|
||||||
$arguments = @("DESIGNER")
|
$arguments = @("DESIGNER")
|
||||||
|
|
||||||
if ($InfoBaseServer -and $InfoBaseRef) {
|
if ($InfoBaseServer -and $InfoBaseRef) {
|
||||||
$arguments += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
|
$arguments += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
|
||||||
} else {
|
} else {
|
||||||
$arguments += "/F", "`"$InfoBasePath`""
|
$arguments += "/F", "`"$InfoBasePath`""
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($UserName) { $arguments += "/N`"$UserName`"" }
|
if ($UserName) { $arguments += "/N`"$UserName`"" }
|
||||||
if ($Password) { $arguments += "/P`"$Password`"" }
|
if ($Password) { $arguments += "/P`"$Password`"" }
|
||||||
|
|
||||||
$arguments += "/DumpCfg", "`"$OutputFile`""
|
$arguments += "/DumpCfg", "`"$OutputFile`""
|
||||||
|
|
||||||
# --- Extensions ---
|
# --- Extensions ---
|
||||||
if ($Extension) {
|
if ($Extension) {
|
||||||
$arguments += "-Extension", "`"$Extension`""
|
$arguments += "-Extension", "`"$Extension`""
|
||||||
} elseif ($AllExtensions) {
|
} elseif ($AllExtensions) {
|
||||||
$arguments += "-AllExtensions"
|
$arguments += "-AllExtensions"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Output ---
|
# --- Output ---
|
||||||
$outFile = Join-Path $tempDir "dump_cf_log.txt"
|
$outFile = Join-Path $tempDir "dump_cf_log.txt"
|
||||||
$arguments += "/Out", "`"$outFile`""
|
$arguments += "/Out", "`"$outFile`""
|
||||||
$arguments += "/DisableStartupDialogs"
|
$arguments += "/DisableStartupDialogs"
|
||||||
|
|
||||||
# --- Execute ---
|
# --- Execute ---
|
||||||
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
||||||
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
||||||
$exitCode = $process.ExitCode
|
$exitCode = $process.ExitCode
|
||||||
|
|
||||||
# --- Result ---
|
# --- Result ---
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
Write-Host "Configuration dumped successfully to: $OutputFile" -ForegroundColor Green
|
Write-Host "Configuration dumped successfully to: $OutputFile" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error dumping configuration (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error dumping configuration (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Test-Path $outFile) {
|
if (Test-Path $outFile) {
|
||||||
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
||||||
if ($logContent) {
|
if ($logContent) {
|
||||||
Write-Host "--- Log ---"
|
Write-Host "--- Log ---"
|
||||||
Write-Host $logContent
|
Write-Host $logContent
|
||||||
Write-Host "--- End ---"
|
Write-Host "--- End ---"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (Test-Path $tempDir) {
|
if (Test-Path $tempDir) {
|
||||||
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,72 +1,72 @@
|
|||||||
---
|
---
|
||||||
name: db-dump-dt
|
name: db-dump-dt
|
||||||
description: Выгрузка информационной базы 1С в DT-файл (вся база — конфигурация + данные). Используй когда нужно выгрузить информационную базу, выгрузить архив базы, сделать бэкап, выгрузить dt
|
description: Выгрузка информационной базы 1С в DT-файл (вся база — конфигурация + данные). Используй когда нужно выгрузить информационную базу, выгрузить архив базы, сделать бэкап, выгрузить dt
|
||||||
argument-hint: "[database] [output.dt]"
|
argument-hint: "[database] [output.dt]"
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
- AskUserQuestion
|
- AskUserQuestion
|
||||||
---
|
---
|
||||||
|
|
||||||
# /db-dump-dt — Выгрузка информационной базы в DT-файл
|
# /db-dump-dt — Выгрузка информационной базы в DT-файл
|
||||||
|
|
||||||
Выгружает информационную базу целиком (конфигурация **+ данные**) в DT-файл — полный снимок ИБ.
|
Выгружает информационную базу целиком (конфигурация **+ данные**) в DT-файл — полный снимок ИБ.
|
||||||
|
|
||||||
> В отличие от `/db-dump-cf` (только конфигурация), `.dt` содержит **всю базу**: данные,
|
> В отличие от `/db-dump-cf` (только конфигурация), `.dt` содержит **всю базу**: данные,
|
||||||
> настройки, пользователей. Это бэкап/точка отката, а не выгрузка метаданных.
|
> настройки, пользователей. Это бэкап/точка отката, а не выгрузка метаданных.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/db-dump-dt [database] [output.dt]
|
/db-dump-dt [database] [output.dt]
|
||||||
/db-dump-dt dev backup.dt
|
/db-dump-dt dev backup.dt
|
||||||
/db-dump-dt — база по умолчанию, имя файла по базе и дате
|
/db-dump-dt — база по умолчанию, имя файла по базе и дате
|
||||||
```
|
```
|
||||||
|
|
||||||
## Параметры подключения
|
## Параметры подключения
|
||||||
|
|
||||||
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
||||||
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
||||||
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
||||||
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
||||||
4. Если ветка не совпала — используй `default`
|
4. Если ветка не совпала — используй `default`
|
||||||
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
||||||
Если файла нет — предложи `/db-list add`.
|
Если файла нет — предложи `/db-list add`.
|
||||||
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.ps1" <параметры>
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|----------|:------------:|----------|
|
|----------|:------------:|----------|
|
||||||
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
||||||
| `-InfoBasePath <путь>` | * | Файловая база |
|
| `-InfoBasePath <путь>` | * | Файловая база |
|
||||||
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
||||||
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
||||||
| `-UserName <имя>` | нет | Имя пользователя |
|
| `-UserName <имя>` | нет | Имя пользователя |
|
||||||
| `-Password <пароль>` | нет | Пароль |
|
| `-Password <пароль>` | нет | Пароль |
|
||||||
| `-OutputFile <путь>` | да | Путь к выходному DT-файлу |
|
| `-OutputFile <путь>` | да | Путь к выходному DT-файлу |
|
||||||
|
|
||||||
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Выгрузка ИБ (файловая база)
|
# Выгрузка ИБ (файловая база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "C:\backup\base.dt"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "C:\backup\base.dt"
|
||||||
|
|
||||||
# Серверная база
|
# Серверная база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -OutputFile "base.dt"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -OutputFile "base.dt"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Связанные навыки
|
## Связанные навыки
|
||||||
|
|
||||||
- `/db-load-dt` — загрузка ИБ из DT (обратная операция)
|
- `/db-load-dt` — загрузка ИБ из DT (обратная операция)
|
||||||
- `/db-dump-cf` — выгрузка только конфигурации (без данных)
|
- `/db-dump-cf` — выгрузка только конфигурации (без данных)
|
||||||
- `/db-create` — создать новую базу (в т.ч. из DT-шаблона)
|
- `/db-create` — создать новую базу (в т.ч. из DT-шаблона)
|
||||||
|
|||||||
@@ -1,90 +1,90 @@
|
|||||||
---
|
---
|
||||||
name: db-dump-xml
|
name: db-dump-xml
|
||||||
description: Выгрузка конфигурации 1С в XML-файлы. Используй когда нужно выгрузить конфигурацию в файлы, XML, исходники, DumpConfigToFiles
|
description: Выгрузка конфигурации 1С в XML-файлы. Используй когда нужно выгрузить конфигурацию в файлы, XML, исходники, DumpConfigToFiles
|
||||||
argument-hint: "[database] [outputDir]"
|
argument-hint: "[database] [outputDir]"
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
- AskUserQuestion
|
- AskUserQuestion
|
||||||
---
|
---
|
||||||
|
|
||||||
# /db-dump-xml — Выгрузка конфигурации в XML
|
# /db-dump-xml — Выгрузка конфигурации в XML
|
||||||
|
|
||||||
Выгружает конфигурацию информационной базы в XML-файлы (исходники). Поддерживает полную, инкрементальную, частичную выгрузку и обновление ConfigDumpInfo.
|
Выгружает конфигурацию информационной базы в XML-файлы (исходники). Поддерживает полную, инкрементальную, частичную выгрузку и обновление ConfigDumpInfo.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/db-dump-xml [database] [outputDir]
|
/db-dump-xml [database] [outputDir]
|
||||||
/db-dump-xml dev src/config
|
/db-dump-xml dev src/config
|
||||||
/db-dump-xml dev src/config -Mode Full
|
/db-dump-xml dev src/config -Mode Full
|
||||||
/db-dump-xml dev src/config -Mode Partial -Objects "Справочник.Номенклатура,Документ.Заказ"
|
/db-dump-xml dev src/config -Mode Partial -Objects "Справочник.Номенклатура,Документ.Заказ"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Параметры подключения
|
## Параметры подключения
|
||||||
|
|
||||||
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
||||||
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
||||||
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
||||||
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
||||||
4. Если ветка не совпала — используй `default`
|
4. Если ветка не совпала — используй `default`
|
||||||
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
||||||
Если файла нет — предложи `/db-list add`.
|
Если файла нет — предложи `/db-list add`.
|
||||||
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
||||||
Если в записи базы указан `configSrc` — используй как каталог выгрузки по умолчанию.
|
Если в записи базы указан `configSrc` — используй как каталог выгрузки по умолчанию.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" <параметры>
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|----------|:------------:|----------|
|
|----------|:------------:|----------|
|
||||||
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
||||||
| `-InfoBasePath <путь>` | * | Файловая база |
|
| `-InfoBasePath <путь>` | * | Файловая база |
|
||||||
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
||||||
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
||||||
| `-UserName <имя>` | нет | Имя пользователя |
|
| `-UserName <имя>` | нет | Имя пользователя |
|
||||||
| `-Password <пароль>` | нет | Пароль |
|
| `-Password <пароль>` | нет | Пароль |
|
||||||
| `-ConfigDir <путь>` | да | Каталог для выгрузки |
|
| `-ConfigDir <путь>` | да | Каталог для выгрузки |
|
||||||
| `-Mode <режим>` | нет | `Full` / `Changes` (по умолч.) / `Partial` / `UpdateInfo` |
|
| `-Mode <режим>` | нет | `Full` / `Changes` (по умолч.) / `Partial` / `UpdateInfo` |
|
||||||
| `-Objects <список>` | для Partial | Имена объектов через запятую |
|
| `-Objects <список>` | для Partial | Имена объектов через запятую |
|
||||||
| `-Extension <имя>` | нет | Выгрузить расширение |
|
| `-Extension <имя>` | нет | Выгрузить расширение |
|
||||||
| `-AllExtensions` | нет | Выгрузить все расширения |
|
| `-AllExtensions` | нет | Выгрузить все расширения |
|
||||||
| `-Format <формат>` | нет | `Hierarchical` (по умолч.) / `Plain` |
|
| `-Format <формат>` | нет | `Hierarchical` (по умолч.) / `Plain` |
|
||||||
|
|
||||||
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
||||||
|
|
||||||
### Режимы выгрузки
|
### Режимы выгрузки
|
||||||
|
|
||||||
| Режим | Описание |
|
| Режим | Описание |
|
||||||
|-------|----------|
|
|-------|----------|
|
||||||
| `Full` | Полная выгрузка — все объекты конфигурации |
|
| `Full` | Полная выгрузка — все объекты конфигурации |
|
||||||
| `Changes` | Инкрементальная — только изменённые с последней выгрузки (использует ConfigDumpInfo.xml) |
|
| `Changes` | Инкрементальная — только изменённые с последней выгрузки (использует ConfigDumpInfo.xml) |
|
||||||
| `Partial` | Частичная — выбранные объекты из параметра `-Objects` |
|
| `Partial` | Частичная — выбранные объекты из параметра `-Objects` |
|
||||||
| `UpdateInfo` | Обновить только ConfigDumpInfo.xml без выгрузки файлов |
|
| `UpdateInfo` | Обновить только ConfigDumpInfo.xml без выгрузки файлов |
|
||||||
|
|
||||||
> Если пользователь просит выгрузить конкретные объекты — используй `-Mode Partial` с `-Objects`.
|
> Если пользователь просит выгрузить конкретные объекты — используй `-Mode Partial` с `-Objects`.
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Полная выгрузка (файловая база)
|
# Полная выгрузка (файловая база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
||||||
|
|
||||||
# Инкрементальная выгрузка
|
# Инкрементальная выгрузка
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Changes
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Changes
|
||||||
|
|
||||||
# Частичная выгрузка
|
# Частичная выгрузка
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Partial -Objects "Справочник.Номенклатура,Документ.Заказ"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Partial -Objects "Справочник.Номенклатура,Документ.Заказ"
|
||||||
|
|
||||||
# Серверная база
|
# Серверная база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
||||||
|
|
||||||
# Выгрузка расширения
|
# Выгрузка расширения
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\ext_src" -Mode Full -Extension "МоёРасширение"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\ext_src" -Mode Full -Extension "МоёРасширение"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,294 +1,294 @@
|
|||||||
# db-dump-xml v1.6 — Dump 1C configuration to XML files
|
# db-dump-xml v1.6 — Dump 1C configuration to XML files
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Выгрузка конфигурации 1С в XML-файлы
|
Выгрузка конфигурации 1С в XML-файлы
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Выполняет выгрузку конфигурации 1С в файлы в четырёх режимах:
|
Выполняет выгрузку конфигурации 1С в файлы в четырёх режимах:
|
||||||
- Full: полная выгрузка всей конфигурации
|
- Full: полная выгрузка всей конфигурации
|
||||||
- Changes: инкрементальная выгрузка изменённых объектов
|
- Changes: инкрементальная выгрузка изменённых объектов
|
||||||
- Partial: выгрузка конкретных объектов из списка
|
- Partial: выгрузка конкретных объектов из списка
|
||||||
- UpdateInfo: обновление только ConfigDumpInfo.xml
|
- UpdateInfo: обновление только ConfigDumpInfo.xml
|
||||||
|
|
||||||
.PARAMETER V8Path
|
.PARAMETER V8Path
|
||||||
Путь к каталогу bin платформы или к 1cv8.exe
|
Путь к каталогу bin платформы или к 1cv8.exe
|
||||||
|
|
||||||
.PARAMETER InfoBasePath
|
.PARAMETER InfoBasePath
|
||||||
Путь к файловой информационной базе
|
Путь к файловой информационной базе
|
||||||
|
|
||||||
.PARAMETER InfoBaseServer
|
.PARAMETER InfoBaseServer
|
||||||
Сервер 1С (для серверной базы)
|
Сервер 1С (для серверной базы)
|
||||||
|
|
||||||
.PARAMETER InfoBaseRef
|
.PARAMETER InfoBaseRef
|
||||||
Имя базы на сервере
|
Имя базы на сервере
|
||||||
|
|
||||||
.PARAMETER UserName
|
.PARAMETER UserName
|
||||||
Имя пользователя 1С
|
Имя пользователя 1С
|
||||||
|
|
||||||
.PARAMETER Password
|
.PARAMETER Password
|
||||||
Пароль пользователя
|
Пароль пользователя
|
||||||
|
|
||||||
.PARAMETER ConfigDir
|
.PARAMETER ConfigDir
|
||||||
Каталог для выгрузки конфигурации
|
Каталог для выгрузки конфигурации
|
||||||
|
|
||||||
.PARAMETER Mode
|
.PARAMETER Mode
|
||||||
Режим выгрузки: Full, Changes, Partial, UpdateInfo (по умолчанию Changes)
|
Режим выгрузки: Full, Changes, Partial, UpdateInfo (по умолчанию Changes)
|
||||||
|
|
||||||
.PARAMETER Objects
|
.PARAMETER Objects
|
||||||
Имена объектов метаданных через запятую (для режима Partial)
|
Имена объектов метаданных через запятую (для режима Partial)
|
||||||
|
|
||||||
.PARAMETER Extension
|
.PARAMETER Extension
|
||||||
Имя расширения для выгрузки
|
Имя расширения для выгрузки
|
||||||
|
|
||||||
.PARAMETER AllExtensions
|
.PARAMETER AllExtensions
|
||||||
Выгрузить все расширения
|
Выгрузить все расширения
|
||||||
|
|
||||||
.PARAMETER Format
|
.PARAMETER Format
|
||||||
Формат выгрузки: Hierarchical или Plain (по умолчанию Hierarchical)
|
Формат выгрузки: Hierarchical или Plain (по умолчанию Hierarchical)
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-dump-xml.ps1 -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\src" -Mode Full
|
.\db-dump-xml.ps1 -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\src" -Mode Full
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-dump-xml.ps1 -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\src" -Mode Partial -Objects "Справочник.Номенклатура,Документ.Заказ"
|
.\db-dump-xml.ps1 -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\src" -Mode Partial -Objects "Справочник.Номенклатура,Документ.Заказ"
|
||||||
#>
|
#>
|
||||||
|
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$V8Path,
|
[string]$V8Path,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBasePath,
|
[string]$InfoBasePath,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseServer,
|
[string]$InfoBaseServer,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseRef,
|
[string]$InfoBaseRef,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$UserName,
|
[string]$UserName,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Password,
|
[string]$Password,
|
||||||
|
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
[string]$ConfigDir,
|
[string]$ConfigDir,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[ValidateSet("Full", "Changes", "Partial", "UpdateInfo")]
|
[ValidateSet("Full", "Changes", "Partial", "UpdateInfo")]
|
||||||
[string]$Mode = "Changes",
|
[string]$Mode = "Changes",
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Objects,
|
[string]$Objects,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Extension,
|
[string]$Extension,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[switch]$AllExtensions,
|
[switch]$AllExtensions,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[ValidateSet("Hierarchical", "Plain")]
|
[ValidateSet("Hierarchical", "Plain")]
|
||||||
[string]$Format = "Hierarchical"
|
[string]$Format = "Hierarchical"
|
||||||
)
|
)
|
||||||
|
|
||||||
$OutputEncoding = [System.Text.Encoding]::UTF8
|
$OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Resolve V8Path ---
|
# --- Resolve V8Path ---
|
||||||
function Find-ProjectV8Path {
|
function Find-ProjectV8Path {
|
||||||
$dir = (Get-Location).Path
|
$dir = (Get-Location).Path
|
||||||
while ($dir) {
|
while ($dir) {
|
||||||
$pf = Join-Path $dir ".v8-project.json"
|
$pf = Join-Path $dir ".v8-project.json"
|
||||||
if (Test-Path $pf) {
|
if (Test-Path $pf) {
|
||||||
try {
|
try {
|
||||||
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||||
if ($j.v8path) { return [string]$j.v8path }
|
if ($j.v8path) { return [string]$j.v8path }
|
||||||
} catch {}
|
} catch {}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
$parent = Split-Path $dir -Parent
|
$parent = Split-Path $dir -Parent
|
||||||
if (-not $parent -or $parent -eq $dir) { break }
|
if (-not $parent -or $parent -eq $dir) { break }
|
||||||
$dir = $parent
|
$dir = $parent
|
||||||
}
|
}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$V8Path = Find-ProjectV8Path
|
$V8Path = Find-ProjectV8Path
|
||||||
}
|
}
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
||||||
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
||||||
Select-Object -First 1
|
Select-Object -First 1
|
||||||
if ($found) {
|
if ($found) {
|
||||||
$V8Path = $found.FullName
|
$V8Path = $found.FullName
|
||||||
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Test-Path $V8Path -PathType Container) {
|
if (Test-Path $V8Path -PathType Container) {
|
||||||
$V8Path = Join-Path $V8Path "1cv8.exe"
|
$V8Path = Join-Path $V8Path "1cv8.exe"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $V8Path)) {
|
if (-not (Test-Path $V8Path)) {
|
||||||
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Detect engine (ibcmd vs 1cv8) by exe name ---
|
# --- Detect engine (ibcmd vs 1cv8) by exe name ---
|
||||||
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
||||||
|
|
||||||
# --- Validate connection ---
|
# --- Validate connection ---
|
||||||
if ($engine -eq "ibcmd") {
|
if ($engine -eq "ibcmd") {
|
||||||
if (-not $InfoBasePath) {
|
if (-not $InfoBasePath) {
|
||||||
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath)" -ForegroundColor Red
|
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath)" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
} elseif (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
} elseif (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
||||||
Write-Host "Error: specify -InfoBasePath or -InfoBaseServer + -InfoBaseRef" -ForegroundColor Red
|
Write-Host "Error: specify -InfoBasePath or -InfoBaseServer + -InfoBaseRef" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Validate Partial mode ---
|
# --- Validate Partial mode ---
|
||||||
if ($Mode -eq "Partial" -and -not $Objects) {
|
if ($Mode -eq "Partial" -and -not $Objects) {
|
||||||
Write-Host "Error: -Objects required for Partial mode" -ForegroundColor Red
|
Write-Host "Error: -Objects required for Partial mode" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Create output dir if needed ---
|
# --- Create output dir if needed ---
|
||||||
if (-not (Test-Path $ConfigDir)) {
|
if (-not (Test-Path $ConfigDir)) {
|
||||||
New-Item -ItemType Directory -Path $ConfigDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $ConfigDir -Force | Out-Null
|
||||||
Write-Host "Created output directory: $ConfigDir"
|
Write-Host "Created output directory: $ConfigDir"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Temp dir ---
|
# --- Temp dir ---
|
||||||
$tempDir = Join-Path $env:TEMP "db_dump_xml_$(Get-Random)"
|
$tempDir = Join-Path $env:TEMP "db_dump_xml_$(Get-Random)"
|
||||||
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($engine -eq "ibcmd") {
|
if ($engine -eq "ibcmd") {
|
||||||
# --- ibcmd branch (file infobase only; hierarchical Full/Changes) ---
|
# --- ibcmd branch (file infobase only; hierarchical Full/Changes) ---
|
||||||
if ($Format -eq "Plain") {
|
if ($Format -eq "Plain") {
|
||||||
Write-Host "Error: ibcmd config export supports hierarchical format only (use -Format Hierarchical or 1cv8)" -ForegroundColor Red
|
Write-Host "Error: ibcmd config export supports hierarchical format only (use -Format Hierarchical or 1cv8)" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
if ($AllExtensions) {
|
if ($AllExtensions) {
|
||||||
$arguments = @("infobase", "config", "export", "all-extensions", "$ConfigDir", "--db-path=$InfoBasePath")
|
$arguments = @("infobase", "config", "export", "all-extensions", "$ConfigDir", "--db-path=$InfoBasePath")
|
||||||
} elseif ($Mode -eq "UpdateInfo") {
|
} elseif ($Mode -eq "UpdateInfo") {
|
||||||
Write-Host "Error: ibcmd config export does not support Mode UpdateInfo; use 1cv8" -ForegroundColor Red
|
Write-Host "Error: ibcmd config export does not support Mode UpdateInfo; use 1cv8" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
} elseif ($Mode -eq "Partial") {
|
} elseif ($Mode -eq "Partial") {
|
||||||
$objList = @($Objects -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ })
|
$objList = @($Objects -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ })
|
||||||
$arguments = @("infobase", "config", "export", "objects") + $objList
|
$arguments = @("infobase", "config", "export", "objects") + $objList
|
||||||
$arguments += "--out=$ConfigDir", "--db-path=$InfoBasePath"
|
$arguments += "--out=$ConfigDir", "--db-path=$InfoBasePath"
|
||||||
if ($Extension) { $arguments += "--extension=$Extension" }
|
if ($Extension) { $arguments += "--extension=$Extension" }
|
||||||
} else {
|
} else {
|
||||||
$arguments = @("infobase", "config", "export", "--db-path=$InfoBasePath")
|
$arguments = @("infobase", "config", "export", "--db-path=$InfoBasePath")
|
||||||
if ($Extension) { $arguments += "--extension=$Extension" }
|
if ($Extension) { $arguments += "--extension=$Extension" }
|
||||||
$arguments += "$ConfigDir"
|
$arguments += "$ConfigDir"
|
||||||
}
|
}
|
||||||
if ($UserName) { $arguments += "--user=$UserName" }
|
if ($UserName) { $arguments += "--user=$UserName" }
|
||||||
if ($Password) { $arguments += "--password=$Password" }
|
if ($Password) { $arguments += "--password=$Password" }
|
||||||
$arguments += "--data=$tempDir"
|
$arguments += "--data=$tempDir"
|
||||||
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
||||||
$output = & $V8Path @arguments 2>&1
|
$output = & $V8Path @arguments 2>&1
|
||||||
$exitCode = $LASTEXITCODE
|
$exitCode = $LASTEXITCODE
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
Write-Host "Configuration exported successfully to: $ConfigDir" -ForegroundColor Green
|
Write-Host "Configuration exported successfully to: $ConfigDir" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error exporting configuration (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error exporting configuration (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
if ($output) { Write-Host ($output | Out-String) }
|
if ($output) { Write-Host ($output | Out-String) }
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 1cv8 branch ---
|
# --- 1cv8 branch ---
|
||||||
# --- Build arguments ---
|
# --- Build arguments ---
|
||||||
$arguments = @("DESIGNER")
|
$arguments = @("DESIGNER")
|
||||||
|
|
||||||
if ($InfoBaseServer -and $InfoBaseRef) {
|
if ($InfoBaseServer -and $InfoBaseRef) {
|
||||||
$arguments += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
|
$arguments += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
|
||||||
} else {
|
} else {
|
||||||
$arguments += "/F", "`"$InfoBasePath`""
|
$arguments += "/F", "`"$InfoBasePath`""
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($UserName) { $arguments += "/N`"$UserName`"" }
|
if ($UserName) { $arguments += "/N`"$UserName`"" }
|
||||||
if ($Password) { $arguments += "/P`"$Password`"" }
|
if ($Password) { $arguments += "/P`"$Password`"" }
|
||||||
|
|
||||||
$arguments += "/DumpConfigToFiles", "`"$ConfigDir`""
|
$arguments += "/DumpConfigToFiles", "`"$ConfigDir`""
|
||||||
$arguments += "-Format", $Format
|
$arguments += "-Format", $Format
|
||||||
|
|
||||||
switch ($Mode) {
|
switch ($Mode) {
|
||||||
"Full" {
|
"Full" {
|
||||||
Write-Host "Executing full configuration dump..."
|
Write-Host "Executing full configuration dump..."
|
||||||
}
|
}
|
||||||
"Changes" {
|
"Changes" {
|
||||||
Write-Host "Executing incremental configuration dump..."
|
Write-Host "Executing incremental configuration dump..."
|
||||||
$arguments += "-update"
|
$arguments += "-update"
|
||||||
$arguments += "-force"
|
$arguments += "-force"
|
||||||
}
|
}
|
||||||
"Partial" {
|
"Partial" {
|
||||||
Write-Host "Executing partial configuration dump..."
|
Write-Host "Executing partial configuration dump..."
|
||||||
$objectList = $Objects -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ }
|
$objectList = $Objects -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ }
|
||||||
|
|
||||||
$listFile = Join-Path $tempDir "dump_list.txt"
|
$listFile = Join-Path $tempDir "dump_list.txt"
|
||||||
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
||||||
[System.IO.File]::WriteAllLines($listFile, $objectList, $utf8Bom)
|
[System.IO.File]::WriteAllLines($listFile, $objectList, $utf8Bom)
|
||||||
|
|
||||||
$arguments += "-listFile", "`"$listFile`""
|
$arguments += "-listFile", "`"$listFile`""
|
||||||
Write-Host "Objects to dump: $($objectList.Count)"
|
Write-Host "Objects to dump: $($objectList.Count)"
|
||||||
foreach ($obj in $objectList) { Write-Host " $obj" }
|
foreach ($obj in $objectList) { Write-Host " $obj" }
|
||||||
}
|
}
|
||||||
"UpdateInfo" {
|
"UpdateInfo" {
|
||||||
Write-Host "Updating ConfigDumpInfo.xml..."
|
Write-Host "Updating ConfigDumpInfo.xml..."
|
||||||
$arguments += "-configDumpInfoOnly"
|
$arguments += "-configDumpInfoOnly"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Extensions ---
|
# --- Extensions ---
|
||||||
if ($Extension) {
|
if ($Extension) {
|
||||||
$arguments += "-Extension", "`"$Extension`""
|
$arguments += "-Extension", "`"$Extension`""
|
||||||
} elseif ($AllExtensions) {
|
} elseif ($AllExtensions) {
|
||||||
$arguments += "-AllExtensions"
|
$arguments += "-AllExtensions"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Output ---
|
# --- Output ---
|
||||||
$outFile = Join-Path $tempDir "dump_log.txt"
|
$outFile = Join-Path $tempDir "dump_log.txt"
|
||||||
$arguments += "/Out", "`"$outFile`""
|
$arguments += "/Out", "`"$outFile`""
|
||||||
$arguments += "/DisableStartupDialogs"
|
$arguments += "/DisableStartupDialogs"
|
||||||
|
|
||||||
# --- Execute ---
|
# --- Execute ---
|
||||||
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
||||||
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
||||||
$exitCode = $process.ExitCode
|
$exitCode = $process.ExitCode
|
||||||
|
|
||||||
# --- Result ---
|
# --- Result ---
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
Write-Host "Dump completed successfully" -ForegroundColor Green
|
Write-Host "Dump completed successfully" -ForegroundColor Green
|
||||||
Write-Host "Configuration dumped to: $ConfigDir"
|
Write-Host "Configuration dumped to: $ConfigDir"
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error dumping configuration (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error dumping configuration (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Test-Path $outFile) {
|
if (Test-Path $outFile) {
|
||||||
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
||||||
if ($logContent) {
|
if ($logContent) {
|
||||||
Write-Host "--- Log ---"
|
Write-Host "--- Log ---"
|
||||||
Write-Host $logContent
|
Write-Host $logContent
|
||||||
Write-Host "--- End ---"
|
Write-Host "--- End ---"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (Test-Path $tempDir) {
|
if (Test-Path $tempDir) {
|
||||||
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+158
-158
@@ -1,158 +1,158 @@
|
|||||||
---
|
---
|
||||||
name: db-list
|
name: db-list
|
||||||
description: Управление реестром баз данных 1С (.v8-project.json). Используй когда нужно работать с реестром баз — список баз, зарегистрировать базу в реестре, какие базы есть
|
description: Управление реестром баз данных 1С (.v8-project.json). Используй когда нужно работать с реестром баз — список баз, зарегистрировать базу в реестре, какие базы есть
|
||||||
argument-hint: "[add|remove|show]"
|
argument-hint: "[add|remove|show]"
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Read
|
- Read
|
||||||
- Write
|
- Write
|
||||||
- Glob
|
- Glob
|
||||||
- AskUserQuestion
|
- AskUserQuestion
|
||||||
---
|
---
|
||||||
|
|
||||||
# /db-list — Управление реестром баз данных
|
# /db-list — Управление реестром баз данных
|
||||||
|
|
||||||
Управляет файлом `.v8-project.json` — реестром информационных баз проекта. Файл хранит параметры подключения, алиасы, привязку к веткам Git.
|
Управляет файлом `.v8-project.json` — реестром информационных баз проекта. Файл хранит параметры подключения, алиасы, привязку к веткам Git.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/db-list — показать список баз
|
/db-list — показать список баз
|
||||||
/db-list add — добавить базу (интерактивно)
|
/db-list add — добавить базу (интерактивно)
|
||||||
/db-list remove <id> — удалить базу из реестра
|
/db-list remove <id> — удалить базу из реестра
|
||||||
/db-list show <id|alias> — подробности по базе
|
/db-list show <id|alias> — подробности по базе
|
||||||
```
|
```
|
||||||
|
|
||||||
## Формат `.v8-project.json`
|
## Формат `.v8-project.json`
|
||||||
|
|
||||||
Файл размещается в корне проекта (рядом с `.git/`).
|
Файл размещается в корне проекта (рядом с `.git/`).
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"v8path": "C:\\Program Files\\1cv8\\8.3.25.1257\\bin",
|
"v8path": "C:\\Program Files\\1cv8\\8.3.25.1257\\bin",
|
||||||
"databases": [
|
"databases": [
|
||||||
{
|
{
|
||||||
"id": "dev",
|
"id": "dev",
|
||||||
"name": "Разработка",
|
"name": "Разработка",
|
||||||
"type": "file",
|
"type": "file",
|
||||||
"path": "C:\\Bases\\MyApp_Dev",
|
"path": "C:\\Bases\\MyApp_Dev",
|
||||||
"user": "Admin",
|
"user": "Admin",
|
||||||
"password": "",
|
"password": "",
|
||||||
"aliases": ["dev", "разработка"],
|
"aliases": ["dev", "разработка"],
|
||||||
"branches": ["dev", "develop", "feature/*"],
|
"branches": ["dev", "develop", "feature/*"],
|
||||||
"configSrc": "C:\\WS\\myapp\\cfsrc"
|
"configSrc": "C:\\WS\\myapp\\cfsrc"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "test",
|
"id": "test",
|
||||||
"name": "Тестовая",
|
"name": "Тестовая",
|
||||||
"type": "server",
|
"type": "server",
|
||||||
"server": "srv01",
|
"server": "srv01",
|
||||||
"ref": "MyApp_Test",
|
"ref": "MyApp_Test",
|
||||||
"user": "Admin",
|
"user": "Admin",
|
||||||
"password": "123",
|
"password": "123",
|
||||||
"aliases": ["test", "тест"]
|
"aliases": ["test", "тест"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": "dev"
|
"default": "dev"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Поля корневого объекта
|
### Поля корневого объекта
|
||||||
|
|
||||||
| Поле | Тип | Описание |
|
| Поле | Тип | Описание |
|
||||||
|------|-----|----------|
|
|------|-----|----------|
|
||||||
| `v8path` | string | Каталог bin платформы 1С. Необязательный — если не задан, автоопределение |
|
| `v8path` | string | Каталог bin платформы 1С. Необязательный — если не задан, автоопределение |
|
||||||
| `databases` | array | Массив баз данных |
|
| `databases` | array | Массив баз данных |
|
||||||
| `default` | string | id базы по умолчанию |
|
| `default` | string | id базы по умолчанию |
|
||||||
|
|
||||||
### Поля объекта базы данных
|
### Поля объекта базы данных
|
||||||
|
|
||||||
| Поле | Тип | Обязательное | Описание |
|
| Поле | Тип | Обязательное | Описание |
|
||||||
|------|-----|:------------:|----------|
|
|------|-----|:------------:|----------|
|
||||||
| `id` | string | да | Уникальный идентификатор (латиница, без пробелов) |
|
| `id` | string | да | Уникальный идентификатор (латиница, без пробелов) |
|
||||||
| `name` | string | да | Человекочитаемое имя |
|
| `name` | string | да | Человекочитаемое имя |
|
||||||
| `type` | `"file"` / `"server"` | да | Тип подключения |
|
| `type` | `"file"` / `"server"` | да | Тип подключения |
|
||||||
| `path` | string | для file | Путь к каталогу файловой базы |
|
| `path` | string | для file | Путь к каталогу файловой базы |
|
||||||
| `server` | string | для server | Адрес сервера 1С |
|
| `server` | string | для server | Адрес сервера 1С |
|
||||||
| `ref` | string | для server | Имя базы на сервере |
|
| `ref` | string | для server | Имя базы на сервере |
|
||||||
| `user` | string | нет | Имя пользователя 1С |
|
| `user` | string | нет | Имя пользователя 1С |
|
||||||
| `password` | string | нет | Пароль |
|
| `password` | string | нет | Пароль |
|
||||||
| `aliases` | string[] | нет | Альтернативные имена для быстрого доступа |
|
| `aliases` | string[] | нет | Альтернативные имена для быстрого доступа |
|
||||||
| `branches` | string[] | нет | Git-ветки или glob-паттерны (`release/*`, `feature/*`), привязанные к этой базе |
|
| `branches` | string[] | нет | Git-ветки или glob-паттерны (`release/*`, `feature/*`), привязанные к этой базе |
|
||||||
| `configSrc` | string | нет | Каталог XML-выгрузки конфигурации |
|
| `configSrc` | string | нет | Каталог XML-выгрузки конфигурации |
|
||||||
|
|
||||||
## Алгоритм разрешения базы данных
|
## Алгоритм разрешения базы данных
|
||||||
|
|
||||||
Этот алгоритм используется ВСЕМИ навыками (`db-*`, `epf-build`, `epf-dump`, `erf-build`, `erf-dump`) для определения целевой базы.
|
Этот алгоритм используется ВСЕМИ навыками (`db-*`, `epf-build`, `epf-dump`, `erf-build`, `erf-dump`) для определения целевой базы.
|
||||||
|
|
||||||
1. Если пользователь указал **параметры подключения** (путь, сервер) — используй напрямую
|
1. Если пользователь указал **параметры подключения** (путь, сервер) — используй напрямую
|
||||||
2. Если пользователь указал **базу по имени** — ищи совпадение в таком порядке:
|
2. Если пользователь указал **базу по имени** — ищи совпадение в таком порядке:
|
||||||
1. По `id` (точное совпадение)
|
1. По `id` (точное совпадение)
|
||||||
2. По `aliases` (совпадение в массиве с учётом морфологии: «тестовую» = «тестовая» = «тестовой»)
|
2. По `aliases` (совпадение в массиве с учётом морфологии: «тестовую» = «тестовая» = «тестовой»)
|
||||||
3. По `name` (нечёткое совпадение с учётом морфологии и регистра)
|
3. По `name` (нечёткое совпадение с учётом морфологии и регистра)
|
||||||
3. Если пользователь **не указал** базу — сопоставь текущую ветку Git с `databases[].branches`:
|
3. Если пользователь **не указал** базу — сопоставь текущую ветку Git с `databases[].branches`:
|
||||||
- Точное совпадение: ветка `dev` → `"branches": ["dev"]`
|
- Точное совпадение: ветка `dev` → `"branches": ["dev"]`
|
||||||
- Glob-паттерн: ветка `release/2.1` → `"branches": ["release/*"]`
|
- Glob-паттерн: ветка `release/2.1` → `"branches": ["release/*"]`
|
||||||
4. Если ветка не совпала — используй `default`
|
4. Если ветка не совпала — используй `default`
|
||||||
5. Если не найдено или неоднозначно — спроси пользователя
|
5. Если не найдено или неоднозначно — спроси пользователя
|
||||||
6. Если файл `.v8-project.json` не найден — спроси параметры подключения и предложи создать файл
|
6. Если файл `.v8-project.json` не найден — спроси параметры подключения и предложи создать файл
|
||||||
|
|
||||||
После выполнения: если использованная база не зарегистрирована — предложи добавить через `/db-list add`.
|
После выполнения: если использованная база не зарегистрирована — предложи добавить через `/db-list add`.
|
||||||
|
|
||||||
### Автоопределение платформы
|
### Автоопределение платформы
|
||||||
|
|
||||||
Если `v8path` не задан в конфиге:
|
Если `v8path` не задан в конфиге:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
$v8 = Get-ChildItem "C:\Program Files\1cv8\*\bin\1cv8.exe" | Sort-Object -Descending | Select-Object -First 1
|
$v8 = Get-ChildItem "C:\Program Files\1cv8\*\bin\1cv8.exe" | Sort-Object -Descending | Select-Object -First 1
|
||||||
```
|
```
|
||||||
|
|
||||||
## Операции
|
## Операции
|
||||||
|
|
||||||
### Показать список баз
|
### Показать список баз
|
||||||
|
|
||||||
Прочитай `.v8-project.json`, выведи таблицу:
|
Прочитай `.v8-project.json`, выведи таблицу:
|
||||||
|
|
||||||
```
|
```
|
||||||
ID Имя Тип Путь/Сервер По умолч.
|
ID Имя Тип Путь/Сервер По умолч.
|
||||||
dev Разработка file C:\Bases\MyApp_Dev ✓
|
dev Разработка file C:\Bases\MyApp_Dev ✓
|
||||||
test Тестовая server srv01/MyApp_Test
|
test Тестовая server srv01/MyApp_Test
|
||||||
```
|
```
|
||||||
|
|
||||||
### Добавить базу
|
### Добавить базу
|
||||||
|
|
||||||
Спроси у пользователя через AskUserQuestion:
|
Спроси у пользователя через AskUserQuestion:
|
||||||
- id, name, type (file/server)
|
- id, name, type (file/server)
|
||||||
- path (для file) или server + ref (для server)
|
- path (для file) или server + ref (для server)
|
||||||
- user, password (необязательно)
|
- user, password (необязательно)
|
||||||
- aliases, branches (необязательно)
|
- aliases, branches (необязательно)
|
||||||
|
|
||||||
Добавь в массив `databases`. Если это первая база — установи как `default`.
|
Добавь в массив `databases`. Если это первая база — установи как `default`.
|
||||||
|
|
||||||
### Удалить базу
|
### Удалить базу
|
||||||
|
|
||||||
Удали из массива `databases` по id. Если удаляемая была `default` — спросить новый default.
|
Удали из массива `databases` по id. Если удаляемая была `default` — спросить новый default.
|
||||||
|
|
||||||
### Подробности по базе
|
### Подробности по базе
|
||||||
|
|
||||||
Выведи все поля конкретной базы.
|
Выведи все поля конкретной базы.
|
||||||
|
|
||||||
## Формирование строки подключения
|
## Формирование строки подключения
|
||||||
|
|
||||||
Для использования в шаблонах команд других навыков:
|
Для использования в шаблонах команд других навыков:
|
||||||
|
|
||||||
**Файловая база:**
|
**Файловая база:**
|
||||||
```
|
```
|
||||||
/F "<path>"
|
/F "<path>"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Серверная база:**
|
**Серверная база:**
|
||||||
```
|
```
|
||||||
/S "<server>/<ref>"
|
/S "<server>/<ref>"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Аутентификация** (добавляется если user задан):
|
**Аутентификация** (добавляется если user задан):
|
||||||
```
|
```
|
||||||
/N"<user>" /P"<password>"
|
/N"<user>" /P"<password>"
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Важно**: между `/N` и именем пробела нет. Между `/P` и паролем пробела нет. Если пароль пустой — опусти `/P` целиком.
|
> **Важно**: между `/N` и именем пробела нет. Между `/P` и паролем пробела нет. Если пароль пустой — опусти `/P` целиком.
|
||||||
|
|||||||
@@ -1,73 +1,73 @@
|
|||||||
---
|
---
|
||||||
name: db-load-cf
|
name: db-load-cf
|
||||||
description: Загрузка конфигурации 1С из CF-файла. Используй когда нужно загрузить конфигурацию из CF, восстановить из бэкапа CF
|
description: Загрузка конфигурации 1С из CF-файла. Используй когда нужно загрузить конфигурацию из CF, восстановить из бэкапа CF
|
||||||
argument-hint: <input.cf> [database]
|
argument-hint: <input.cf> [database]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
- AskUserQuestion
|
- AskUserQuestion
|
||||||
---
|
---
|
||||||
|
|
||||||
# /db-load-cf — Загрузка конфигурации из CF-файла
|
# /db-load-cf — Загрузка конфигурации из CF-файла
|
||||||
|
|
||||||
Загружает конфигурацию из бинарного CF-файла в информационную базу.
|
Загружает конфигурацию из бинарного CF-файла в информационную базу.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/db-load-cf <input.cf> [database]
|
/db-load-cf <input.cf> [database]
|
||||||
/db-load-cf config.cf dev
|
/db-load-cf config.cf dev
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Внимание**: загрузка CF **полностью заменяет** конфигурацию в базе. Перед выполнением запроси подтверждение у пользователя.
|
> **Внимание**: загрузка CF **полностью заменяет** конфигурацию в базе. Перед выполнением запроси подтверждение у пользователя.
|
||||||
|
|
||||||
## Параметры подключения
|
## Параметры подключения
|
||||||
|
|
||||||
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
||||||
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
||||||
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
||||||
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
||||||
4. Если ветка не совпала — используй `default`
|
4. Если ветка не совпала — используй `default`
|
||||||
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
||||||
Если файла нет — предложи `/db-list add`.
|
Если файла нет — предложи `/db-list add`.
|
||||||
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" <параметры>
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|----------|:------------:|----------|
|
|----------|:------------:|----------|
|
||||||
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
||||||
| `-InfoBasePath <путь>` | * | Файловая база |
|
| `-InfoBasePath <путь>` | * | Файловая база |
|
||||||
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
||||||
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
||||||
| `-UserName <имя>` | нет | Имя пользователя |
|
| `-UserName <имя>` | нет | Имя пользователя |
|
||||||
| `-Password <пароль>` | нет | Пароль |
|
| `-Password <пароль>` | нет | Пароль |
|
||||||
| `-InputFile <путь>` | да | Путь к CF-файлу |
|
| `-InputFile <путь>` | да | Путь к CF-файлу |
|
||||||
| `-Extension <имя>` | нет | Загрузить как расширение |
|
| `-Extension <имя>` | нет | Загрузить как расширение |
|
||||||
| `-AllExtensions` | нет | Загрузить все расширения из архива |
|
| `-AllExtensions` | нет | Загрузить все расширения из архива |
|
||||||
|
|
||||||
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
||||||
|
|
||||||
## После выполнения
|
## После выполнения
|
||||||
|
|
||||||
**Предложи выполнить `/db-update`** — загрузка CF обновляет только «основную» конфигурацию конфигуратора, для применения к БД нужен `/UpdateDBCfg`
|
**Предложи выполнить `/db-update`** — загрузка CF обновляет только «основную» конфигурацию конфигуратора, для применения к БД нужен `/UpdateDBCfg`
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Файловая база
|
# Файловая база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "C:\backup\config.cf"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "C:\backup\config.cf"
|
||||||
|
|
||||||
# Серверная база
|
# Серверная база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test" -UserName "Admin" -Password "secret" -InputFile "config.cf"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test" -UserName "Admin" -Password "secret" -InputFile "config.cf"
|
||||||
|
|
||||||
# Загрузка расширения
|
# Загрузка расширения
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "ext.cfe" -Extension "МоёРасширение"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "ext.cfe" -Extension "МоёРасширение"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,224 +1,224 @@
|
|||||||
# db-load-cf v1.4 — Load 1C configuration from CF file
|
# db-load-cf v1.4 — Load 1C configuration from CF file
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Загрузка конфигурации 1С из CF-файла
|
Загрузка конфигурации 1С из CF-файла
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Загружает конфигурацию из бинарного CF-файла в информационную базу.
|
Загружает конфигурацию из бинарного CF-файла в информационную базу.
|
||||||
Поддерживает загрузку расширений.
|
Поддерживает загрузку расширений.
|
||||||
|
|
||||||
.PARAMETER V8Path
|
.PARAMETER V8Path
|
||||||
Путь к каталогу bin платформы или к 1cv8.exe
|
Путь к каталогу bin платформы или к 1cv8.exe
|
||||||
|
|
||||||
.PARAMETER InfoBasePath
|
.PARAMETER InfoBasePath
|
||||||
Путь к файловой информационной базе
|
Путь к файловой информационной базе
|
||||||
|
|
||||||
.PARAMETER InfoBaseServer
|
.PARAMETER InfoBaseServer
|
||||||
Сервер 1С (для серверной базы)
|
Сервер 1С (для серверной базы)
|
||||||
|
|
||||||
.PARAMETER InfoBaseRef
|
.PARAMETER InfoBaseRef
|
||||||
Имя базы на сервере
|
Имя базы на сервере
|
||||||
|
|
||||||
.PARAMETER UserName
|
.PARAMETER UserName
|
||||||
Имя пользователя 1С
|
Имя пользователя 1С
|
||||||
|
|
||||||
.PARAMETER Password
|
.PARAMETER Password
|
||||||
Пароль пользователя
|
Пароль пользователя
|
||||||
|
|
||||||
.PARAMETER InputFile
|
.PARAMETER InputFile
|
||||||
Путь к CF-файлу для загрузки
|
Путь к CF-файлу для загрузки
|
||||||
|
|
||||||
.PARAMETER Extension
|
.PARAMETER Extension
|
||||||
Загрузить как расширение
|
Загрузить как расширение
|
||||||
|
|
||||||
.PARAMETER AllExtensions
|
.PARAMETER AllExtensions
|
||||||
Загрузить все расширения из архива
|
Загрузить все расширения из архива
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-load-cf.ps1 -InfoBasePath "C:\Bases\MyDB" -InputFile "config.cf"
|
.\db-load-cf.ps1 -InfoBasePath "C:\Bases\MyDB" -InputFile "config.cf"
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-load-cf.ps1 -InfoBasePath "C:\Bases\MyDB" -InputFile "ext.cfe" -Extension "МоёРасширение"
|
.\db-load-cf.ps1 -InfoBasePath "C:\Bases\MyDB" -InputFile "ext.cfe" -Extension "МоёРасширение"
|
||||||
#>
|
#>
|
||||||
|
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$V8Path,
|
[string]$V8Path,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBasePath,
|
[string]$InfoBasePath,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseServer,
|
[string]$InfoBaseServer,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseRef,
|
[string]$InfoBaseRef,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$UserName,
|
[string]$UserName,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Password,
|
[string]$Password,
|
||||||
|
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
[string]$InputFile,
|
[string]$InputFile,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Extension,
|
[string]$Extension,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[switch]$AllExtensions
|
[switch]$AllExtensions
|
||||||
)
|
)
|
||||||
|
|
||||||
$OutputEncoding = [System.Text.Encoding]::UTF8
|
$OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Resolve V8Path ---
|
# --- Resolve V8Path ---
|
||||||
function Find-ProjectV8Path {
|
function Find-ProjectV8Path {
|
||||||
$dir = (Get-Location).Path
|
$dir = (Get-Location).Path
|
||||||
while ($dir) {
|
while ($dir) {
|
||||||
$pf = Join-Path $dir ".v8-project.json"
|
$pf = Join-Path $dir ".v8-project.json"
|
||||||
if (Test-Path $pf) {
|
if (Test-Path $pf) {
|
||||||
try {
|
try {
|
||||||
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||||
if ($j.v8path) { return [string]$j.v8path }
|
if ($j.v8path) { return [string]$j.v8path }
|
||||||
} catch {}
|
} catch {}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
$parent = Split-Path $dir -Parent
|
$parent = Split-Path $dir -Parent
|
||||||
if (-not $parent -or $parent -eq $dir) { break }
|
if (-not $parent -or $parent -eq $dir) { break }
|
||||||
$dir = $parent
|
$dir = $parent
|
||||||
}
|
}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$V8Path = Find-ProjectV8Path
|
$V8Path = Find-ProjectV8Path
|
||||||
}
|
}
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
||||||
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
||||||
Select-Object -First 1
|
Select-Object -First 1
|
||||||
if ($found) {
|
if ($found) {
|
||||||
$V8Path = $found.FullName
|
$V8Path = $found.FullName
|
||||||
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Test-Path $V8Path -PathType Container) {
|
if (Test-Path $V8Path -PathType Container) {
|
||||||
$V8Path = Join-Path $V8Path "1cv8.exe"
|
$V8Path = Join-Path $V8Path "1cv8.exe"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $V8Path)) {
|
if (-not (Test-Path $V8Path)) {
|
||||||
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Detect engine (ibcmd vs 1cv8) by exe name ---
|
# --- Detect engine (ibcmd vs 1cv8) by exe name ---
|
||||||
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
||||||
|
|
||||||
# --- Validate connection ---
|
# --- Validate connection ---
|
||||||
if ($engine -eq "ibcmd") {
|
if ($engine -eq "ibcmd") {
|
||||||
if (-not $InfoBasePath) {
|
if (-not $InfoBasePath) {
|
||||||
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath)" -ForegroundColor Red
|
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath)" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
} elseif (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
} elseif (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
||||||
Write-Host "Error: specify -InfoBasePath or -InfoBaseServer + -InfoBaseRef" -ForegroundColor Red
|
Write-Host "Error: specify -InfoBasePath or -InfoBaseServer + -InfoBaseRef" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Validate input file ---
|
# --- Validate input file ---
|
||||||
if (-not (Test-Path $InputFile)) {
|
if (-not (Test-Path $InputFile)) {
|
||||||
Write-Host "Error: input file not found: $InputFile" -ForegroundColor Red
|
Write-Host "Error: input file not found: $InputFile" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Temp dir ---
|
# --- Temp dir ---
|
||||||
$tempDir = Join-Path $env:TEMP "db_load_cf_$(Get-Random)"
|
$tempDir = Join-Path $env:TEMP "db_load_cf_$(Get-Random)"
|
||||||
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($engine -eq "ibcmd") {
|
if ($engine -eq "ibcmd") {
|
||||||
# --- ibcmd branch (file infobase only) ---
|
# --- ibcmd branch (file infobase only) ---
|
||||||
if ($AllExtensions) {
|
if ($AllExtensions) {
|
||||||
Write-Host "Error: ibcmd config load does not support -AllExtensions (use -Extension)" -ForegroundColor Red
|
Write-Host "Error: ibcmd config load does not support -AllExtensions (use -Extension)" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
$arguments = @("infobase", "config", "load", "--db-path=$InfoBasePath")
|
$arguments = @("infobase", "config", "load", "--db-path=$InfoBasePath")
|
||||||
if ($Extension) { $arguments += "--extension=$Extension" }
|
if ($Extension) { $arguments += "--extension=$Extension" }
|
||||||
$arguments += "$InputFile"
|
$arguments += "$InputFile"
|
||||||
if ($UserName) { $arguments += "--user=$UserName" }
|
if ($UserName) { $arguments += "--user=$UserName" }
|
||||||
if ($Password) { $arguments += "--password=$Password" }
|
if ($Password) { $arguments += "--password=$Password" }
|
||||||
$arguments += "--data=$tempDir"
|
$arguments += "--data=$tempDir"
|
||||||
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
||||||
$output = & $V8Path @arguments 2>&1
|
$output = & $V8Path @arguments 2>&1
|
||||||
$exitCode = $LASTEXITCODE
|
$exitCode = $LASTEXITCODE
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
Write-Host "Configuration loaded successfully from: $InputFile" -ForegroundColor Green
|
Write-Host "Configuration loaded successfully from: $InputFile" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error loading configuration (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error loading configuration (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
if ($output) { Write-Host ($output | Out-String) }
|
if ($output) { Write-Host ($output | Out-String) }
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 1cv8 branch ---
|
# --- 1cv8 branch ---
|
||||||
# --- Build arguments ---
|
# --- Build arguments ---
|
||||||
$arguments = @("DESIGNER")
|
$arguments = @("DESIGNER")
|
||||||
|
|
||||||
if ($InfoBaseServer -and $InfoBaseRef) {
|
if ($InfoBaseServer -and $InfoBaseRef) {
|
||||||
$arguments += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
|
$arguments += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
|
||||||
} else {
|
} else {
|
||||||
$arguments += "/F", "`"$InfoBasePath`""
|
$arguments += "/F", "`"$InfoBasePath`""
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($UserName) { $arguments += "/N`"$UserName`"" }
|
if ($UserName) { $arguments += "/N`"$UserName`"" }
|
||||||
if ($Password) { $arguments += "/P`"$Password`"" }
|
if ($Password) { $arguments += "/P`"$Password`"" }
|
||||||
|
|
||||||
$arguments += "/LoadCfg", "`"$InputFile`""
|
$arguments += "/LoadCfg", "`"$InputFile`""
|
||||||
|
|
||||||
# --- Extensions ---
|
# --- Extensions ---
|
||||||
if ($Extension) {
|
if ($Extension) {
|
||||||
$arguments += "-Extension", "`"$Extension`""
|
$arguments += "-Extension", "`"$Extension`""
|
||||||
} elseif ($AllExtensions) {
|
} elseif ($AllExtensions) {
|
||||||
$arguments += "-AllExtensions"
|
$arguments += "-AllExtensions"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Output ---
|
# --- Output ---
|
||||||
$outFile = Join-Path $tempDir "load_cf_log.txt"
|
$outFile = Join-Path $tempDir "load_cf_log.txt"
|
||||||
$arguments += "/Out", "`"$outFile`""
|
$arguments += "/Out", "`"$outFile`""
|
||||||
$arguments += "/DisableStartupDialogs"
|
$arguments += "/DisableStartupDialogs"
|
||||||
|
|
||||||
# --- Execute ---
|
# --- Execute ---
|
||||||
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
||||||
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
||||||
$exitCode = $process.ExitCode
|
$exitCode = $process.ExitCode
|
||||||
|
|
||||||
# --- Result ---
|
# --- Result ---
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
Write-Host "Configuration loaded successfully from: $InputFile" -ForegroundColor Green
|
Write-Host "Configuration loaded successfully from: $InputFile" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error loading configuration (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error loading configuration (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Test-Path $outFile) {
|
if (Test-Path $outFile) {
|
||||||
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
||||||
if ($logContent) {
|
if ($logContent) {
|
||||||
Write-Host "--- Log ---"
|
Write-Host "--- Log ---"
|
||||||
Write-Host $logContent
|
Write-Host $logContent
|
||||||
Write-Host "--- End ---"
|
Write-Host "--- End ---"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (Test-Path $tempDir) {
|
if (Test-Path $tempDir) {
|
||||||
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,92 +1,92 @@
|
|||||||
---
|
---
|
||||||
name: db-load-dt
|
name: db-load-dt
|
||||||
description: Загрузка информационной базы 1С из DT-файла — полная перезапись базы (конфигурация + данные). Используй когда нужно загрузить архив информационной базы, восстановить базу, загрузить dt
|
description: Загрузка информационной базы 1С из DT-файла — полная перезапись базы (конфигурация + данные). Используй когда нужно загрузить архив информационной базы, восстановить базу, загрузить dt
|
||||||
disable-model-invocation: true
|
disable-model-invocation: true
|
||||||
argument-hint: <input.dt> [database]
|
argument-hint: <input.dt> [database]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
- AskUserQuestion
|
- AskUserQuestion
|
||||||
---
|
---
|
||||||
|
|
||||||
# /db-load-dt — Загрузка информационной базы из DT-файла
|
# /db-load-dt — Загрузка информационной базы из DT-файла
|
||||||
|
|
||||||
Восстанавливает информационную базу целиком (конфигурация **+ данные**) из DT-файла.
|
Восстанавливает информационную базу целиком (конфигурация **+ данные**) из DT-файла.
|
||||||
|
|
||||||
> ⚠️ **Необратимая операция.** Загрузка `.dt` **полностью перезаписывает базу** — и
|
> ⚠️ **Необратимая операция.** Загрузка `.dt` **полностью перезаписывает базу** — и
|
||||||
> конфигурацию, и все данные. Текущее содержимое базы будет потеряно. После загрузки
|
> конфигурацию, и все данные. Текущее содержимое базы будет потеряно. После загрузки
|
||||||
> `/db-update` **не нужен** — конфигурация БД уже синхронна внутри снимка.
|
> `/db-update` **не нужен** — конфигурация БД уже синхронна внутри снимка.
|
||||||
|
|
||||||
## Когда НЕ использовать
|
## Когда НЕ использовать
|
||||||
|
|
||||||
- Нужно создать **новую** базу из `.dt` → используй `/db-create` (из DT-шаблона), а не загрузку
|
- Нужно создать **новую** базу из `.dt` → используй `/db-create` (из DT-шаблона), а не загрузку
|
||||||
в существующую.
|
в существующую.
|
||||||
- Нужно обновить только конфигурацию (без данных) → `/db-load-cf` или `/db-load-xml`.
|
- Нужно обновить только конфигурацию (без данных) → `/db-load-cf` или `/db-load-xml`.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/db-load-dt <input.dt> [database]
|
/db-load-dt <input.dt> [database]
|
||||||
/db-load-dt backup.dt dev
|
/db-load-dt backup.dt dev
|
||||||
```
|
```
|
||||||
|
|
||||||
## Порядок действий перед загрузкой
|
## Порядок действий перед загрузкой
|
||||||
|
|
||||||
1. Предложи пользователю сначала сделать `/db-dump-dt` текущего состояния базы — это точка
|
1. Предложи пользователю сначала сделать `/db-dump-dt` текущего состояния базы — это точка
|
||||||
отката (восстановиться будет нечем, если не сохранить).
|
отката (восстановиться будет нечем, если не сохранить).
|
||||||
2. Запроси **явное подтверждение**: вся база (данные + конфигурация) будет перезаписана.
|
2. Запроси **явное подтверждение**: вся база (данные + конфигурация) будет перезаписана.
|
||||||
3. Только после подтверждения выполняй загрузку.
|
3. Только после подтверждения выполняй загрузку.
|
||||||
|
|
||||||
## Параметры подключения
|
## Параметры подключения
|
||||||
|
|
||||||
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
||||||
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
||||||
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
||||||
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
||||||
4. Если ветка не совпала — используй `default`
|
4. Если ветка не совпала — используй `default`
|
||||||
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
||||||
Если файла нет — предложи `/db-list add`.
|
Если файла нет — предложи `/db-list add`.
|
||||||
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.ps1" <параметры>
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|----------|:------------:|----------|
|
|----------|:------------:|----------|
|
||||||
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
||||||
| `-InfoBasePath <путь>` | * | Файловая база |
|
| `-InfoBasePath <путь>` | * | Файловая база |
|
||||||
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
||||||
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
||||||
| `-UserName <имя>` | нет | Имя пользователя |
|
| `-UserName <имя>` | нет | Имя пользователя |
|
||||||
| `-Password <пароль>` | нет | Пароль |
|
| `-Password <пароль>` | нет | Пароль |
|
||||||
| `-InputFile <путь>` | да | Путь к DT-файлу |
|
| `-InputFile <путь>` | да | Путь к DT-файлу |
|
||||||
| `-JobsCount <N>` | нет | Число фоновых заданий загрузки (0 = по числу процессоров) |
|
| `-JobsCount <N>` | нет | Число фоновых заданий загрузки (0 = по числу процессоров) |
|
||||||
| `-UnlockCode <код>` | нет | Код разблокировки (`/UC`), если заблокировано начало сеансов |
|
| `-UnlockCode <код>` | нет | Код разблокировки (`/UC`), если заблокировано начало сеансов |
|
||||||
|
|
||||||
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
||||||
|
|
||||||
## После выполнения
|
## После выполнения
|
||||||
|
|
||||||
Если база занята (активные сеансы), загрузка не выполнится — для серверной базы можно
|
Если база занята (активные сеансы), загрузка не выполнится — для серверной базы можно
|
||||||
передать `-UnlockCode`; иначе освободи базу и повтори.
|
передать `-UnlockCode`; иначе освободи базу и повтори.
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Файловая база
|
# Файловая база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "C:\backup\base.dt"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "C:\backup\base.dt"
|
||||||
|
|
||||||
# Серверная база с ускорением загрузки
|
# Серверная база с ускорением загрузки
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test" -UserName "Admin" -Password "secret" -InputFile "base.dt" -JobsCount 4
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test" -UserName "Admin" -Password "secret" -InputFile "base.dt" -JobsCount 4
|
||||||
```
|
```
|
||||||
|
|
||||||
## Связанные навыки
|
## Связанные навыки
|
||||||
|
|
||||||
- `/db-dump-dt` — выгрузка ИБ в DT (обратная операция, точка отката перед загрузкой)
|
- `/db-dump-dt` — выгрузка ИБ в DT (обратная операция, точка отката перед загрузкой)
|
||||||
- `/db-create` — создать новую базу (в т.ч. из DT-шаблона)
|
- `/db-create` — создать новую базу (в т.ч. из DT-шаблона)
|
||||||
|
|||||||
@@ -1,77 +1,77 @@
|
|||||||
---
|
---
|
||||||
name: db-load-git
|
name: db-load-git
|
||||||
description: Загрузка изменений из Git в базу 1С. Используй когда нужно загрузить изменения из гита, обновить базу из репозитория, partial load из коммита
|
description: Загрузка изменений из Git в базу 1С. Используй когда нужно загрузить изменения из гита, обновить базу из репозитория, partial load из коммита
|
||||||
argument-hint: "[database] [source]"
|
argument-hint: "[database] [source]"
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
- AskUserQuestion
|
- AskUserQuestion
|
||||||
---
|
---
|
||||||
|
|
||||||
# /db-load-git — Загрузка изменений из Git
|
# /db-load-git — Загрузка изменений из Git
|
||||||
|
|
||||||
Определяет изменённые файлы конфигурации по данным Git и выполняет частичную загрузку в информационную базу.
|
Определяет изменённые файлы конфигурации по данным Git и выполняет частичную загрузку в информационную базу.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/db-load-git [database]
|
/db-load-git [database]
|
||||||
/db-load-git dev — все незафиксированные изменения
|
/db-load-git dev — все незафиксированные изменения
|
||||||
/db-load-git dev -Source Staged — только staged
|
/db-load-git dev -Source Staged — только staged
|
||||||
/db-load-git dev -Source Commit -CommitRange "HEAD~3..HEAD"
|
/db-load-git dev -Source Commit -CommitRange "HEAD~3..HEAD"
|
||||||
/db-load-git dev -DryRun — только показать что будет загружено
|
/db-load-git dev -DryRun — только показать что будет загружено
|
||||||
```
|
```
|
||||||
|
|
||||||
## Параметры подключения
|
## Параметры подключения
|
||||||
|
|
||||||
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
||||||
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
||||||
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
||||||
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
||||||
4. Если ветка не совпала — используй `default`
|
4. Если ветка не совпала — используй `default`
|
||||||
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
||||||
Если файла нет — предложи `/db-list add`.
|
Если файла нет — предложи `/db-list add`.
|
||||||
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
||||||
Если в записи базы указан `configSrc` — используй как каталог конфигурации.
|
Если в записи базы указан `configSrc` — используй как каталог конфигурации.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" <параметры>
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|----------|:------------:|----------|
|
|----------|:------------:|----------|
|
||||||
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
||||||
| `-InfoBasePath <путь>` | * | Файловая база |
|
| `-InfoBasePath <путь>` | * | Файловая база |
|
||||||
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
||||||
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
||||||
| `-UserName <имя>` | нет | Имя пользователя |
|
| `-UserName <имя>` | нет | Имя пользователя |
|
||||||
| `-Password <пароль>` | нет | Пароль |
|
| `-Password <пароль>` | нет | Пароль |
|
||||||
| `-ConfigDir <путь>` | да | Каталог XML-выгрузки (git-репозиторий) |
|
| `-ConfigDir <путь>` | да | Каталог XML-выгрузки (git-репозиторий) |
|
||||||
| `-Source <источник>` | нет | `All` (по умолч.) / `Staged` / `Unstaged` / `Commit` |
|
| `-Source <источник>` | нет | `All` (по умолч.) / `Staged` / `Unstaged` / `Commit` |
|
||||||
| `-CommitRange <range>` | для Commit | Диапазон коммитов (напр. `HEAD~3..HEAD`) |
|
| `-CommitRange <range>` | для Commit | Диапазон коммитов (напр. `HEAD~3..HEAD`) |
|
||||||
| `-Extension <имя>` | нет | Загрузить в расширение |
|
| `-Extension <имя>` | нет | Загрузить в расширение |
|
||||||
| `-AllExtensions` | нет | Загрузить все расширения |
|
| `-AllExtensions` | нет | Загрузить все расширения |
|
||||||
| `-Format <формат>` | нет | `Hierarchical` (по умолч.) / `Plain` |
|
| `-Format <формат>` | нет | `Hierarchical` (по умолч.) / `Plain` |
|
||||||
| `-DryRun` | нет | Только показать что будет загружено (без загрузки) |
|
| `-DryRun` | нет | Только показать что будет загружено (без загрузки) |
|
||||||
| `-UpdateDB` | нет | После загрузки сразу обновить конфигурацию БД (`/UpdateDBCfg`) |
|
| `-UpdateDB` | нет | После загрузки сразу обновить конфигурацию БД (`/UpdateDBCfg`) |
|
||||||
|
|
||||||
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
||||||
|
|
||||||
## После выполнения
|
## После выполнения
|
||||||
|
|
||||||
Если `-UpdateDB` не был указан — **предложить `/db-update`** для применения изменений к БД
|
Если `-UpdateDB` не был указан — **предложить `/db-update`** для применения изменений к БД
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Все незафиксированные изменения
|
# Все незафиксированные изменения
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\WS\cfsrc" -Source All -UpdateDB
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\WS\cfsrc" -Source All -UpdateDB
|
||||||
|
|
||||||
# Из диапазона коммитов
|
# Из диапазона коммитов
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\WS\cfsrc" -Source Commit -CommitRange "HEAD~3..HEAD"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\WS\cfsrc" -Source Commit -CommitRange "HEAD~3..HEAD"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,445 +1,445 @@
|
|||||||
# db-load-git v1.8 — Load Git changes into 1C database
|
# db-load-git v1.8 — Load Git changes into 1C database
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Загрузка изменений из Git в базу 1С
|
Загрузка изменений из Git в базу 1С
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Определяет изменённые файлы конфигурации по данным Git и выполняет
|
Определяет изменённые файлы конфигурации по данным Git и выполняет
|
||||||
частичную загрузку в информационную базу.
|
частичную загрузку в информационную базу.
|
||||||
|
|
||||||
.PARAMETER V8Path
|
.PARAMETER V8Path
|
||||||
Путь к каталогу bin платформы или к 1cv8.exe
|
Путь к каталогу bin платформы или к 1cv8.exe
|
||||||
|
|
||||||
.PARAMETER InfoBasePath
|
.PARAMETER InfoBasePath
|
||||||
Путь к файловой информационной базе
|
Путь к файловой информационной базе
|
||||||
|
|
||||||
.PARAMETER InfoBaseServer
|
.PARAMETER InfoBaseServer
|
||||||
Сервер 1С (для серверной базы)
|
Сервер 1С (для серверной базы)
|
||||||
|
|
||||||
.PARAMETER InfoBaseRef
|
.PARAMETER InfoBaseRef
|
||||||
Имя базы на сервере
|
Имя базы на сервере
|
||||||
|
|
||||||
.PARAMETER UserName
|
.PARAMETER UserName
|
||||||
Имя пользователя 1С
|
Имя пользователя 1С
|
||||||
|
|
||||||
.PARAMETER Password
|
.PARAMETER Password
|
||||||
Пароль пользователя
|
Пароль пользователя
|
||||||
|
|
||||||
.PARAMETER ConfigDir
|
.PARAMETER ConfigDir
|
||||||
Каталог XML-выгрузки конфигурации (git-репозиторий)
|
Каталог XML-выгрузки конфигурации (git-репозиторий)
|
||||||
|
|
||||||
.PARAMETER Source
|
.PARAMETER Source
|
||||||
Источник изменений: All, Staged, Unstaged, Commit (по умолчанию All)
|
Источник изменений: All, Staged, Unstaged, Commit (по умолчанию All)
|
||||||
|
|
||||||
.PARAMETER CommitRange
|
.PARAMETER CommitRange
|
||||||
Диапазон коммитов (для Source=Commit), напр. HEAD~3..HEAD
|
Диапазон коммитов (для Source=Commit), напр. HEAD~3..HEAD
|
||||||
|
|
||||||
.PARAMETER Extension
|
.PARAMETER Extension
|
||||||
Имя расширения для загрузки
|
Имя расширения для загрузки
|
||||||
|
|
||||||
.PARAMETER AllExtensions
|
.PARAMETER AllExtensions
|
||||||
Загрузить все расширения
|
Загрузить все расширения
|
||||||
|
|
||||||
.PARAMETER Format
|
.PARAMETER Format
|
||||||
Формат файлов: Hierarchical или Plain (по умолчанию Hierarchical)
|
Формат файлов: Hierarchical или Plain (по умолчанию Hierarchical)
|
||||||
|
|
||||||
.PARAMETER DryRun
|
.PARAMETER DryRun
|
||||||
Только показать что будет загружено (без загрузки)
|
Только показать что будет загружено (без загрузки)
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-load-git.ps1 -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\src" -Source All
|
.\db-load-git.ps1 -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\src" -Source All
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-load-git.ps1 -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\src" -Source Commit -CommitRange "HEAD~3..HEAD"
|
.\db-load-git.ps1 -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\src" -Source Commit -CommitRange "HEAD~3..HEAD"
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-load-git.ps1 -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\src" -DryRun
|
.\db-load-git.ps1 -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\src" -DryRun
|
||||||
#>
|
#>
|
||||||
|
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$V8Path,
|
[string]$V8Path,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBasePath,
|
[string]$InfoBasePath,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseServer,
|
[string]$InfoBaseServer,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseRef,
|
[string]$InfoBaseRef,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$UserName,
|
[string]$UserName,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Password,
|
[string]$Password,
|
||||||
|
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
[string]$ConfigDir,
|
[string]$ConfigDir,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[ValidateSet("All", "Staged", "Unstaged", "Commit")]
|
[ValidateSet("All", "Staged", "Unstaged", "Commit")]
|
||||||
[string]$Source = "All",
|
[string]$Source = "All",
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$CommitRange,
|
[string]$CommitRange,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Extension,
|
[string]$Extension,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[switch]$AllExtensions,
|
[switch]$AllExtensions,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[ValidateSet("Hierarchical", "Plain")]
|
[ValidateSet("Hierarchical", "Plain")]
|
||||||
[string]$Format = "Hierarchical",
|
[string]$Format = "Hierarchical",
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[switch]$DryRun,
|
[switch]$DryRun,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[switch]$UpdateDB
|
[switch]$UpdateDB
|
||||||
)
|
)
|
||||||
|
|
||||||
$OutputEncoding = [System.Text.Encoding]::UTF8
|
$OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Helper: map sub-file path (BSL, HTML, etc.) to object XML ---
|
# --- Helper: map sub-file path (BSL, HTML, etc.) to object XML ---
|
||||||
function Get-ObjectXmlFromSubFile {
|
function Get-ObjectXmlFromSubFile {
|
||||||
param([string]$RelativePath)
|
param([string]$RelativePath)
|
||||||
|
|
||||||
$parts = $RelativePath -split '[\\/]'
|
$parts = $RelativePath -split '[\\/]'
|
||||||
if ($parts.Count -ge 2) {
|
if ($parts.Count -ge 2) {
|
||||||
return "$($parts[0])/$($parts[1]).xml"
|
return "$($parts[0])/$($parts[1]).xml"
|
||||||
}
|
}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Resolve V8Path (skip if DryRun) ---
|
# --- Resolve V8Path (skip if DryRun) ---
|
||||||
if (-not $DryRun) {
|
if (-not $DryRun) {
|
||||||
function Find-ProjectV8Path {
|
function Find-ProjectV8Path {
|
||||||
$dir = (Get-Location).Path
|
$dir = (Get-Location).Path
|
||||||
while ($dir) {
|
while ($dir) {
|
||||||
$pf = Join-Path $dir ".v8-project.json"
|
$pf = Join-Path $dir ".v8-project.json"
|
||||||
if (Test-Path $pf) {
|
if (Test-Path $pf) {
|
||||||
try {
|
try {
|
||||||
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||||
if ($j.v8path) { return [string]$j.v8path }
|
if ($j.v8path) { return [string]$j.v8path }
|
||||||
} catch {}
|
} catch {}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
$parent = Split-Path $dir -Parent
|
$parent = Split-Path $dir -Parent
|
||||||
if (-not $parent -or $parent -eq $dir) { break }
|
if (-not $parent -or $parent -eq $dir) { break }
|
||||||
$dir = $parent
|
$dir = $parent
|
||||||
}
|
}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$V8Path = Find-ProjectV8Path
|
$V8Path = Find-ProjectV8Path
|
||||||
}
|
}
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
||||||
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
||||||
Select-Object -First 1
|
Select-Object -First 1
|
||||||
if ($found) {
|
if ($found) {
|
||||||
$V8Path = $found.FullName
|
$V8Path = $found.FullName
|
||||||
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Test-Path $V8Path -PathType Container) {
|
if (Test-Path $V8Path -PathType Container) {
|
||||||
$V8Path = Join-Path $V8Path "1cv8.exe"
|
$V8Path = Join-Path $V8Path "1cv8.exe"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $V8Path)) {
|
if (-not (Test-Path $V8Path)) {
|
||||||
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Detect engine + validate connection (skip if DryRun) ---
|
# --- Detect engine + validate connection (skip if DryRun) ---
|
||||||
$engine = "1cv8"
|
$engine = "1cv8"
|
||||||
if (-not $DryRun) {
|
if (-not $DryRun) {
|
||||||
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
||||||
if ($engine -eq "ibcmd") {
|
if ($engine -eq "ibcmd") {
|
||||||
if (-not $InfoBasePath) {
|
if (-not $InfoBasePath) {
|
||||||
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath)" -ForegroundColor Red
|
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath)" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
} elseif (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
} elseif (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
||||||
Write-Host "Error: specify -InfoBasePath or -InfoBaseServer + -InfoBaseRef" -ForegroundColor Red
|
Write-Host "Error: specify -InfoBasePath or -InfoBaseServer + -InfoBaseRef" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Validate config dir ---
|
# --- Validate config dir ---
|
||||||
if (-not (Test-Path $ConfigDir)) {
|
if (-not (Test-Path $ConfigDir)) {
|
||||||
Write-Host "Error: config directory not found: $ConfigDir" -ForegroundColor Red
|
Write-Host "Error: config directory not found: $ConfigDir" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Validate Commit mode ---
|
# --- Validate Commit mode ---
|
||||||
if ($Source -eq "Commit" -and -not $CommitRange) {
|
if ($Source -eq "Commit" -and -not $CommitRange) {
|
||||||
Write-Host "Error: -CommitRange required for Source=Commit" -ForegroundColor Red
|
Write-Host "Error: -CommitRange required for Source=Commit" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Check git ---
|
# --- Check git ---
|
||||||
try {
|
try {
|
||||||
$null = git --version 2>&1
|
$null = git --version 2>&1
|
||||||
} catch {
|
} catch {
|
||||||
Write-Host "Error: git not found in PATH" -ForegroundColor Red
|
Write-Host "Error: git not found in PATH" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Get changed files from Git ---
|
# --- Get changed files from Git ---
|
||||||
$changedFiles = @()
|
$changedFiles = @()
|
||||||
$ConfigDir = (Resolve-Path $ConfigDir).Path.TrimEnd('\')
|
$ConfigDir = (Resolve-Path $ConfigDir).Path.TrimEnd('\')
|
||||||
$configDirNormalized = $ConfigDir.Replace('\', '/')
|
$configDirNormalized = $ConfigDir.Replace('\', '/')
|
||||||
|
|
||||||
Push-Location $ConfigDir
|
Push-Location $ConfigDir
|
||||||
try {
|
try {
|
||||||
switch ($Source) {
|
switch ($Source) {
|
||||||
"Staged" {
|
"Staged" {
|
||||||
Write-Host "Getting staged changes..."
|
Write-Host "Getting staged changes..."
|
||||||
$raw = git diff --cached --name-only --relative 2>&1
|
$raw = git diff --cached --name-only --relative 2>&1
|
||||||
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
|
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
|
||||||
}
|
}
|
||||||
"Unstaged" {
|
"Unstaged" {
|
||||||
Write-Host "Getting unstaged changes..."
|
Write-Host "Getting unstaged changes..."
|
||||||
$raw = git diff --name-only --relative 2>&1
|
$raw = git diff --name-only --relative 2>&1
|
||||||
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
|
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
|
||||||
$raw = git ls-files --others --exclude-standard 2>&1
|
$raw = git ls-files --others --exclude-standard 2>&1
|
||||||
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
|
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
|
||||||
}
|
}
|
||||||
"Commit" {
|
"Commit" {
|
||||||
Write-Host "Getting changes from $CommitRange..."
|
Write-Host "Getting changes from $CommitRange..."
|
||||||
$raw = git diff --name-only --relative $CommitRange 2>&1
|
$raw = git diff --name-only --relative $CommitRange 2>&1
|
||||||
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
|
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
|
||||||
}
|
}
|
||||||
"All" {
|
"All" {
|
||||||
Write-Host "Getting all uncommitted changes..."
|
Write-Host "Getting all uncommitted changes..."
|
||||||
$raw = git diff --cached --name-only --relative 2>&1
|
$raw = git diff --cached --name-only --relative 2>&1
|
||||||
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
|
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
|
||||||
$raw = git diff --name-only --relative 2>&1
|
$raw = git diff --name-only --relative 2>&1
|
||||||
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
|
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
|
||||||
$raw = git ls-files --others --exclude-standard 2>&1
|
$raw = git ls-files --others --exclude-standard 2>&1
|
||||||
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
|
if ($LASTEXITCODE -eq 0) { $changedFiles += $raw }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
Pop-Location
|
Pop-Location
|
||||||
}
|
}
|
||||||
|
|
||||||
$changedFiles = $changedFiles | Where-Object { $_ -is [string] -and -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -Unique
|
$changedFiles = $changedFiles | Where-Object { $_ -is [string] -and -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -Unique
|
||||||
|
|
||||||
if ($changedFiles.Count -eq 0) {
|
if ($changedFiles.Count -eq 0) {
|
||||||
Write-Host "No changes found"
|
Write-Host "No changes found"
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "Git changes detected: $($changedFiles.Count) files"
|
Write-Host "Git changes detected: $($changedFiles.Count) files"
|
||||||
|
|
||||||
# --- Filter and map to config files ---
|
# --- Filter and map to config files ---
|
||||||
$configFiles = @()
|
$configFiles = @()
|
||||||
$supportSkipped = @()
|
$supportSkipped = @()
|
||||||
|
|
||||||
foreach ($file in $changedFiles) {
|
foreach ($file in $changedFiles) {
|
||||||
$file = $file.Trim().Replace('\', '/')
|
$file = $file.Trim().Replace('\', '/')
|
||||||
if ([string]::IsNullOrWhiteSpace($file)) { continue }
|
if ([string]::IsNullOrWhiteSpace($file)) { continue }
|
||||||
|
|
||||||
# Skip service files (not partially loadable). Support-state files are tracked
|
# Skip service files (not partially loadable). Support-state files are tracked
|
||||||
# to warn the user: support changes apply only via a full load.
|
# to warn the user: support changes apply only via a full load.
|
||||||
if ($file -match 'ParentConfigurations\.bin$') { $supportSkipped += $file; continue }
|
if ($file -match 'ParentConfigurations\.bin$') { $supportSkipped += $file; continue }
|
||||||
if ($file -eq "ConfigDumpInfo.xml" -or $file -match '(^|/)ConfigDumpInfo\.xml$') { continue }
|
if ($file -eq "ConfigDumpInfo.xml" -or $file -match '(^|/)ConfigDumpInfo\.xml$') { continue }
|
||||||
|
|
||||||
$fullPath = Join-Path $ConfigDir $file
|
$fullPath = Join-Path $ConfigDir $file
|
||||||
|
|
||||||
if ($file -match '\.xml$') {
|
if ($file -match '\.xml$') {
|
||||||
# XML file — add directly if exists
|
# XML file — add directly if exists
|
||||||
if (Test-Path $fullPath) {
|
if (Test-Path $fullPath) {
|
||||||
if ($configFiles -notcontains $file) {
|
if ($configFiles -notcontains $file) {
|
||||||
$configFiles += $file
|
$configFiles += $file
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
# Non-XML (BSL, HTML, etc.) — map to parent object XML + include all Ext/ files
|
# Non-XML (BSL, HTML, etc.) — map to parent object XML + include all Ext/ files
|
||||||
$objectXml = Get-ObjectXmlFromSubFile -RelativePath $file
|
$objectXml = Get-ObjectXmlFromSubFile -RelativePath $file
|
||||||
if ($objectXml) {
|
if ($objectXml) {
|
||||||
$fullXmlPath = Join-Path $ConfigDir $objectXml
|
$fullXmlPath = Join-Path $ConfigDir $objectXml
|
||||||
if (Test-Path $fullXmlPath) {
|
if (Test-Path $fullXmlPath) {
|
||||||
if ($configFiles -notcontains $objectXml) {
|
if ($configFiles -notcontains $objectXml) {
|
||||||
$configFiles += $objectXml
|
$configFiles += $objectXml
|
||||||
}
|
}
|
||||||
if ((Test-Path $fullPath) -and $configFiles -notcontains $file) {
|
if ((Test-Path $fullPath) -and $configFiles -notcontains $file) {
|
||||||
$configFiles += $file
|
$configFiles += $file
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add all files from Ext/ directory of the object
|
# Add all files from Ext/ directory of the object
|
||||||
$parts = $file -split '[\\/]'
|
$parts = $file -split '[\\/]'
|
||||||
if ($parts.Count -ge 2) {
|
if ($parts.Count -ge 2) {
|
||||||
$extDir = Join-Path (Join-Path $ConfigDir $parts[0]) "$($parts[1])\Ext"
|
$extDir = Join-Path (Join-Path $ConfigDir $parts[0]) "$($parts[1])\Ext"
|
||||||
if (Test-Path $extDir) {
|
if (Test-Path $extDir) {
|
||||||
Get-ChildItem -Path $extDir -Recurse -File | ForEach-Object {
|
Get-ChildItem -Path $extDir -Recurse -File | ForEach-Object {
|
||||||
$extRelPath = $_.FullName.Replace("$ConfigDir\", '').Replace('\', '/')
|
$extRelPath = $_.FullName.Replace("$ConfigDir\", '').Replace('\', '/')
|
||||||
if ($configFiles -notcontains $extRelPath) {
|
if ($configFiles -notcontains $extRelPath) {
|
||||||
$configFiles += $extRelPath
|
$configFiles += $extRelPath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($supportSkipped.Count -gt 0) {
|
if ($supportSkipped.Count -gt 0) {
|
||||||
Write-Host "[ВНИМАНИЕ] Состояние поддержки изменено в коммите, но частично не загружается (исключено):" -ForegroundColor Yellow
|
Write-Host "[ВНИМАНИЕ] Состояние поддержки изменено в коммите, но частично не загружается (исключено):" -ForegroundColor Yellow
|
||||||
foreach ($sf in $supportSkipped) { Write-Host " - $sf" -ForegroundColor Yellow }
|
foreach ($sf in $supportSkipped) { Write-Host " - $sf" -ForegroundColor Yellow }
|
||||||
Write-Host " Смена состояния поддержки применяется только полной загрузкой (db-load-xml -Mode Full)." -ForegroundColor Yellow
|
Write-Host " Смена состояния поддержки применяется только полной загрузкой (db-load-xml -Mode Full)." -ForegroundColor Yellow
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($configFiles.Count -eq 0) {
|
if ($configFiles.Count -eq 0) {
|
||||||
Write-Host "No configuration files found in changes"
|
Write-Host "No configuration files found in changes"
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "Files for loading: $($configFiles.Count)"
|
Write-Host "Files for loading: $($configFiles.Count)"
|
||||||
foreach ($f in $configFiles) { Write-Host " $f" }
|
foreach ($f in $configFiles) { Write-Host " $f" }
|
||||||
|
|
||||||
# --- DryRun: stop here ---
|
# --- DryRun: stop here ---
|
||||||
if ($DryRun) {
|
if ($DryRun) {
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "DryRun mode - no changes applied"
|
Write-Host "DryRun mode - no changes applied"
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Temp dir ---
|
# --- Temp dir ---
|
||||||
$tempDir = Join-Path $env:TEMP "db_load_git_$(Get-Random)"
|
$tempDir = Join-Path $env:TEMP "db_load_git_$(Get-Random)"
|
||||||
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($engine -eq "ibcmd") {
|
if ($engine -eq "ibcmd") {
|
||||||
# --- ibcmd branch (file infobase only; import specific files) ---
|
# --- ibcmd branch (file infobase only; import specific files) ---
|
||||||
if ($Format -eq "Plain") {
|
if ($Format -eq "Plain") {
|
||||||
Write-Host "Error: ibcmd config import supports hierarchical format only (use -Format Hierarchical or 1cv8)" -ForegroundColor Red
|
Write-Host "Error: ibcmd config import supports hierarchical format only (use -Format Hierarchical or 1cv8)" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
if ($AllExtensions) {
|
if ($AllExtensions) {
|
||||||
Write-Host "Error: ibcmd config import does not support -AllExtensions (use -Extension or 1cv8)" -ForegroundColor Red
|
Write-Host "Error: ibcmd config import does not support -AllExtensions (use -Extension or 1cv8)" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
$arguments = @("infobase", "config", "import", "files") + $configFiles
|
$arguments = @("infobase", "config", "import", "files") + $configFiles
|
||||||
$arguments += "--base-dir=$ConfigDir", "--db-path=$InfoBasePath"
|
$arguments += "--base-dir=$ConfigDir", "--db-path=$InfoBasePath"
|
||||||
if ($Extension) { $arguments += "--extension=$Extension" }
|
if ($Extension) { $arguments += "--extension=$Extension" }
|
||||||
if ($UserName) { $arguments += "--user=$UserName" }
|
if ($UserName) { $arguments += "--user=$UserName" }
|
||||||
if ($Password) { $arguments += "--password=$Password" }
|
if ($Password) { $arguments += "--password=$Password" }
|
||||||
$arguments += "--data=$tempDir"
|
$arguments += "--data=$tempDir"
|
||||||
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
||||||
$output = & $V8Path @arguments 2>&1
|
$output = & $V8Path @arguments 2>&1
|
||||||
$exitCode = $LASTEXITCODE
|
$exitCode = $LASTEXITCODE
|
||||||
if ($exitCode -ne 0) {
|
if ($exitCode -ne 0) {
|
||||||
Write-Host "Error loading changes (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error loading changes (code: $exitCode)" -ForegroundColor Red
|
||||||
if ($output) { Write-Host ($output | Out-String) }
|
if ($output) { Write-Host ($output | Out-String) }
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
}
|
}
|
||||||
Write-Host "Changes loaded successfully ($($configFiles.Count) files)" -ForegroundColor Green
|
Write-Host "Changes loaded successfully ($($configFiles.Count) files)" -ForegroundColor Green
|
||||||
if ($output) { Write-Host ($output | Out-String) }
|
if ($output) { Write-Host ($output | Out-String) }
|
||||||
if ($UpdateDB) {
|
if ($UpdateDB) {
|
||||||
$applyArgs = @("infobase", "config", "apply", "--db-path=$InfoBasePath", "--force")
|
$applyArgs = @("infobase", "config", "apply", "--db-path=$InfoBasePath", "--force")
|
||||||
if ($UserName) { $applyArgs += "--user=$UserName" }
|
if ($UserName) { $applyArgs += "--user=$UserName" }
|
||||||
if ($Password) { $applyArgs += "--password=$Password" }
|
if ($Password) { $applyArgs += "--password=$Password" }
|
||||||
$applyArgs += "--data=$tempDir"
|
$applyArgs += "--data=$tempDir"
|
||||||
Write-Host "Running: ibcmd $($applyArgs -join ' ')"
|
Write-Host "Running: ibcmd $($applyArgs -join ' ')"
|
||||||
$applyOut = & $V8Path @applyArgs 2>&1
|
$applyOut = & $V8Path @applyArgs 2>&1
|
||||||
$exitCode = $LASTEXITCODE
|
$exitCode = $LASTEXITCODE
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
Write-Host "Database configuration updated successfully" -ForegroundColor Green
|
Write-Host "Database configuration updated successfully" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error updating database configuration (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error updating database configuration (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
if ($applyOut) { Write-Host ($applyOut | Out-String) }
|
if ($applyOut) { Write-Host ($applyOut | Out-String) }
|
||||||
}
|
}
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 1cv8 branch ---
|
# --- 1cv8 branch ---
|
||||||
# --- Write list file (UTF-8 with BOM) ---
|
# --- Write list file (UTF-8 with BOM) ---
|
||||||
$listFile = Join-Path $tempDir "load_list.txt"
|
$listFile = Join-Path $tempDir "load_list.txt"
|
||||||
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
||||||
[System.IO.File]::WriteAllLines($listFile, $configFiles, $utf8Bom)
|
[System.IO.File]::WriteAllLines($listFile, $configFiles, $utf8Bom)
|
||||||
|
|
||||||
# --- Build arguments ---
|
# --- Build arguments ---
|
||||||
$arguments = @("DESIGNER")
|
$arguments = @("DESIGNER")
|
||||||
|
|
||||||
if ($InfoBaseServer -and $InfoBaseRef) {
|
if ($InfoBaseServer -and $InfoBaseRef) {
|
||||||
$arguments += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
|
$arguments += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
|
||||||
} else {
|
} else {
|
||||||
$arguments += "/F", "`"$InfoBasePath`""
|
$arguments += "/F", "`"$InfoBasePath`""
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($UserName) { $arguments += "/N`"$UserName`"" }
|
if ($UserName) { $arguments += "/N`"$UserName`"" }
|
||||||
if ($Password) { $arguments += "/P`"$Password`"" }
|
if ($Password) { $arguments += "/P`"$Password`"" }
|
||||||
|
|
||||||
$arguments += "/LoadConfigFromFiles", "`"$ConfigDir`""
|
$arguments += "/LoadConfigFromFiles", "`"$ConfigDir`""
|
||||||
$arguments += "-listFile", "`"$listFile`""
|
$arguments += "-listFile", "`"$listFile`""
|
||||||
$arguments += "-Format", $Format
|
$arguments += "-Format", $Format
|
||||||
$arguments += "-partial"
|
$arguments += "-partial"
|
||||||
$arguments += "-updateConfigDumpInfo"
|
$arguments += "-updateConfigDumpInfo"
|
||||||
|
|
||||||
# --- Extensions ---
|
# --- Extensions ---
|
||||||
if ($Extension) {
|
if ($Extension) {
|
||||||
$arguments += "-Extension", "`"$Extension`""
|
$arguments += "-Extension", "`"$Extension`""
|
||||||
} elseif ($AllExtensions) {
|
} elseif ($AllExtensions) {
|
||||||
$arguments += "-AllExtensions"
|
$arguments += "-AllExtensions"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- UpdateDB ---
|
# --- UpdateDB ---
|
||||||
if ($UpdateDB) {
|
if ($UpdateDB) {
|
||||||
$arguments += "/UpdateDBCfg"
|
$arguments += "/UpdateDBCfg"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Output ---
|
# --- Output ---
|
||||||
$outFile = Join-Path $tempDir "load_log.txt"
|
$outFile = Join-Path $tempDir "load_log.txt"
|
||||||
$arguments += "/Out", "`"$outFile`""
|
$arguments += "/Out", "`"$outFile`""
|
||||||
$arguments += "/DisableStartupDialogs"
|
$arguments += "/DisableStartupDialogs"
|
||||||
|
|
||||||
# --- Execute ---
|
# --- Execute ---
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "Executing partial configuration load..."
|
Write-Host "Executing partial configuration load..."
|
||||||
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
||||||
|
|
||||||
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
||||||
$exitCode = $process.ExitCode
|
$exitCode = $process.ExitCode
|
||||||
|
|
||||||
# --- Result ---
|
# --- Result ---
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
Write-Host "Load completed successfully" -ForegroundColor Green
|
Write-Host "Load completed successfully" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error loading configuration (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error loading configuration (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Test-Path $outFile) {
|
if (Test-Path $outFile) {
|
||||||
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
||||||
if ($logContent) {
|
if ($logContent) {
|
||||||
Write-Host "--- Log ---"
|
Write-Host "--- Log ---"
|
||||||
Write-Host $logContent
|
Write-Host $logContent
|
||||||
Write-Host "--- End ---"
|
Write-Host "--- End ---"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (Test-Path $tempDir) {
|
if (Test-Path $tempDir) {
|
||||||
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+101
-101
@@ -1,101 +1,101 @@
|
|||||||
---
|
---
|
||||||
name: db-load-xml
|
name: db-load-xml
|
||||||
description: Загрузка конфигурации 1С из XML-файлов. Используй когда нужно загрузить конфигурацию из файлов, XML, исходников, LoadConfigFromFiles
|
description: Загрузка конфигурации 1С из XML-файлов. Используй когда нужно загрузить конфигурацию из файлов, XML, исходников, LoadConfigFromFiles
|
||||||
argument-hint: <configDir> [database]
|
argument-hint: <configDir> [database]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
- AskUserQuestion
|
- AskUserQuestion
|
||||||
---
|
---
|
||||||
|
|
||||||
# /db-load-xml — Загрузка конфигурации из XML
|
# /db-load-xml — Загрузка конфигурации из XML
|
||||||
|
|
||||||
Загружает конфигурацию в информационную базу из XML-файлов (исходников). Поддерживает полную и частичную загрузку.
|
Загружает конфигурацию в информационную базу из XML-файлов (исходников). Поддерживает полную и частичную загрузку.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/db-load-xml <configDir> [database]
|
/db-load-xml <configDir> [database]
|
||||||
/db-load-xml src/config dev
|
/db-load-xml src/config dev
|
||||||
/db-load-xml src/config dev -Mode Partial -Files "Catalogs/Номенклатура.xml,Catalogs/Номенклатура/Ext/ObjectModule.bsl"
|
/db-load-xml src/config dev -Mode Partial -Files "Catalogs/Номенклатура.xml,Catalogs/Номенклатура/Ext/ObjectModule.bsl"
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Внимание**: полная загрузка **заменяет всю конфигурацию** в базе. Перед выполнением запроси подтверждение у пользователя.
|
> **Внимание**: полная загрузка **заменяет всю конфигурацию** в базе. Перед выполнением запроси подтверждение у пользователя.
|
||||||
|
|
||||||
## Параметры подключения
|
## Параметры подключения
|
||||||
|
|
||||||
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
||||||
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
||||||
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
||||||
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
||||||
4. Если ветка не совпала — используй `default`
|
4. Если ветка не совпала — используй `default`
|
||||||
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
||||||
Если файла нет — предложи `/db-list add`.
|
Если файла нет — предложи `/db-list add`.
|
||||||
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
||||||
Если в записи базы указан `configSrc` — используй как каталог загрузки по умолчанию.
|
Если в записи базы указан `configSrc` — используй как каталог загрузки по умолчанию.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" <параметры>
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|----------|:------------:|----------|
|
|----------|:------------:|----------|
|
||||||
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
||||||
| `-InfoBasePath <путь>` | * | Файловая база |
|
| `-InfoBasePath <путь>` | * | Файловая база |
|
||||||
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
||||||
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
||||||
| `-UserName <имя>` | нет | Имя пользователя |
|
| `-UserName <имя>` | нет | Имя пользователя |
|
||||||
| `-Password <пароль>` | нет | Пароль |
|
| `-Password <пароль>` | нет | Пароль |
|
||||||
| `-ConfigDir <путь>` | да | Каталог XML-исходников |
|
| `-ConfigDir <путь>` | да | Каталог XML-исходников |
|
||||||
| `-Mode <режим>` | нет | `Full` (по умолч.) / `Partial` |
|
| `-Mode <режим>` | нет | `Full` (по умолч.) / `Partial` |
|
||||||
| `-Files <список>` | для Partial | Относительные пути файлов через запятую |
|
| `-Files <список>` | для Partial | Относительные пути файлов через запятую |
|
||||||
| `-ListFile <путь>` | для Partial | Путь к файлу со списком (альтернатива `-Files`) |
|
| `-ListFile <путь>` | для Partial | Путь к файлу со списком (альтернатива `-Files`) |
|
||||||
| `-Extension <имя>` | нет | Загрузить в расширение |
|
| `-Extension <имя>` | нет | Загрузить в расширение |
|
||||||
| `-AllExtensions` | нет | Загрузить все расширения |
|
| `-AllExtensions` | нет | Загрузить все расширения |
|
||||||
| `-Format <формат>` | нет | `Hierarchical` (по умолч.) / `Plain` |
|
| `-Format <формат>` | нет | `Hierarchical` (по умолч.) / `Plain` |
|
||||||
| `-UpdateDB` | нет | После загрузки сразу обновить конфигурацию БД (`/UpdateDBCfg`) |
|
| `-UpdateDB` | нет | После загрузки сразу обновить конфигурацию БД (`/UpdateDBCfg`) |
|
||||||
|
|
||||||
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
||||||
|
|
||||||
### Режимы загрузки
|
### Режимы загрузки
|
||||||
|
|
||||||
| Режим | Описание |
|
| Режим | Описание |
|
||||||
|-------|----------|
|
|-------|----------|
|
||||||
| `Full` | Полная загрузка — замена всей конфигурации из каталога XML |
|
| `Full` | Полная загрузка — замена всей конфигурации из каталога XML |
|
||||||
| `Partial` | Частичная — загрузка выбранных файлов (с `-partial -updateConfigDumpInfo`) |
|
| `Partial` | Частичная — загрузка выбранных файлов (с `-partial -updateConfigDumpInfo`) |
|
||||||
|
|
||||||
### Формат файла списка (listFile)
|
### Формат файла списка (listFile)
|
||||||
|
|
||||||
Файл содержит **относительные пути к файлам** в каталоге выгрузки (один на строку), кодировка **UTF-8 с BOM**:
|
Файл содержит **относительные пути к файлам** в каталоге выгрузки (один на строку), кодировка **UTF-8 с BOM**:
|
||||||
|
|
||||||
```
|
```
|
||||||
Catalogs/Номенклатура.xml
|
Catalogs/Номенклатура.xml
|
||||||
Catalogs/Номенклатура/Ext/ObjectModule.bsl
|
Catalogs/Номенклатура/Ext/ObjectModule.bsl
|
||||||
Documents/Заказ.xml
|
Documents/Заказ.xml
|
||||||
Documents/Заказ/Forms/ФормаДокумента.xml
|
Documents/Заказ/Forms/ФормаДокумента.xml
|
||||||
```
|
```
|
||||||
|
|
||||||
## После выполнения
|
## После выполнения
|
||||||
|
|
||||||
Если `-UpdateDB` не был указан — **предложи выполнить `/db-update`** для применения изменений к БД
|
Если `-UpdateDB` не был указан — **предложи выполнить `/db-update`** для применения изменений к БД
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Полная загрузка
|
# Полная загрузка
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
||||||
|
|
||||||
# Частичная загрузка конкретных файлов
|
# Частичная загрузка конкретных файлов
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Partial -Files "Catalogs/Номенклатура.xml,Catalogs/Номенклатура/Ext/ObjectModule.bsl"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Partial -Files "Catalogs/Номенклатура.xml,Catalogs/Номенклатура/Ext/ObjectModule.bsl"
|
||||||
|
|
||||||
# Загрузка расширения
|
# Загрузка расширения
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\ext_src" -Mode Full -Extension "МоёРасширение"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\ext_src" -Mode Full -Extension "МоёРасширение"
|
||||||
|
|
||||||
# Загрузка + обновление БД в одном запуске
|
# Загрузка + обновление БД в одном запуске
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full -UpdateDB
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full -UpdateDB
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,388 +1,388 @@
|
|||||||
# db-load-xml v1.10 — Load 1C configuration from XML files
|
# db-load-xml v1.10 — Load 1C configuration from XML files
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Загрузка конфигурации 1С из XML-файлов
|
Загрузка конфигурации 1С из XML-файлов
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Загружает конфигурацию в информационную базу из XML-файлов.
|
Загружает конфигурацию в информационную базу из XML-файлов.
|
||||||
Поддерживает полную и частичную загрузку.
|
Поддерживает полную и частичную загрузку.
|
||||||
|
|
||||||
.PARAMETER V8Path
|
.PARAMETER V8Path
|
||||||
Путь к каталогу bin платформы или к 1cv8.exe
|
Путь к каталогу bin платформы или к 1cv8.exe
|
||||||
|
|
||||||
.PARAMETER InfoBasePath
|
.PARAMETER InfoBasePath
|
||||||
Путь к файловой информационной базе
|
Путь к файловой информационной базе
|
||||||
|
|
||||||
.PARAMETER InfoBaseServer
|
.PARAMETER InfoBaseServer
|
||||||
Сервер 1С (для серверной базы)
|
Сервер 1С (для серверной базы)
|
||||||
|
|
||||||
.PARAMETER InfoBaseRef
|
.PARAMETER InfoBaseRef
|
||||||
Имя базы на сервере
|
Имя базы на сервере
|
||||||
|
|
||||||
.PARAMETER UserName
|
.PARAMETER UserName
|
||||||
Имя пользователя 1С
|
Имя пользователя 1С
|
||||||
|
|
||||||
.PARAMETER Password
|
.PARAMETER Password
|
||||||
Пароль пользователя
|
Пароль пользователя
|
||||||
|
|
||||||
.PARAMETER ConfigDir
|
.PARAMETER ConfigDir
|
||||||
Каталог XML-исходников конфигурации
|
Каталог XML-исходников конфигурации
|
||||||
|
|
||||||
.PARAMETER Mode
|
.PARAMETER Mode
|
||||||
Режим загрузки: Full или Partial (по умолчанию Full)
|
Режим загрузки: Full или Partial (по умолчанию Full)
|
||||||
|
|
||||||
.PARAMETER Files
|
.PARAMETER Files
|
||||||
Относительные пути файлов через запятую (для режима Partial)
|
Относительные пути файлов через запятую (для режима Partial)
|
||||||
|
|
||||||
.PARAMETER ListFile
|
.PARAMETER ListFile
|
||||||
Путь к файлу со списком файлов (альтернатива -Files, для режима Partial)
|
Путь к файлу со списком файлов (альтернатива -Files, для режима Partial)
|
||||||
|
|
||||||
.PARAMETER Extension
|
.PARAMETER Extension
|
||||||
Имя расширения для загрузки
|
Имя расширения для загрузки
|
||||||
|
|
||||||
.PARAMETER AllExtensions
|
.PARAMETER AllExtensions
|
||||||
Загрузить все расширения
|
Загрузить все расширения
|
||||||
|
|
||||||
.PARAMETER Format
|
.PARAMETER Format
|
||||||
Формат файлов: Hierarchical или Plain (по умолчанию Hierarchical)
|
Формат файлов: Hierarchical или Plain (по умолчанию Hierarchical)
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-load-xml.ps1 -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\src" -Mode Full
|
.\db-load-xml.ps1 -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\src" -Mode Full
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-load-xml.ps1 -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\src" -Mode Partial -Files "Catalogs/Номенклатура.xml,Catalogs/Номенклатура/Ext/ObjectModule.bsl"
|
.\db-load-xml.ps1 -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\src" -Mode Partial -Files "Catalogs/Номенклатура.xml,Catalogs/Номенклатура/Ext/ObjectModule.bsl"
|
||||||
#>
|
#>
|
||||||
|
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$V8Path,
|
[string]$V8Path,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBasePath,
|
[string]$InfoBasePath,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseServer,
|
[string]$InfoBaseServer,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseRef,
|
[string]$InfoBaseRef,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$UserName,
|
[string]$UserName,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Password,
|
[string]$Password,
|
||||||
|
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
[string]$ConfigDir,
|
[string]$ConfigDir,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[ValidateSet("Full", "Partial")]
|
[ValidateSet("Full", "Partial")]
|
||||||
[string]$Mode = "Full",
|
[string]$Mode = "Full",
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Files,
|
[string]$Files,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$ListFile,
|
[string]$ListFile,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Extension,
|
[string]$Extension,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[switch]$AllExtensions,
|
[switch]$AllExtensions,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[ValidateSet("Hierarchical", "Plain")]
|
[ValidateSet("Hierarchical", "Plain")]
|
||||||
[string]$Format = "Hierarchical",
|
[string]$Format = "Hierarchical",
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[switch]$UpdateDB,
|
[switch]$UpdateDB,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[switch]$StrictLog
|
[switch]$StrictLog
|
||||||
)
|
)
|
||||||
|
|
||||||
$OutputEncoding = [System.Text.Encoding]::UTF8
|
$OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Resolve V8Path ---
|
# --- Resolve V8Path ---
|
||||||
function Find-ProjectV8Path {
|
function Find-ProjectV8Path {
|
||||||
$dir = (Get-Location).Path
|
$dir = (Get-Location).Path
|
||||||
while ($dir) {
|
while ($dir) {
|
||||||
$pf = Join-Path $dir ".v8-project.json"
|
$pf = Join-Path $dir ".v8-project.json"
|
||||||
if (Test-Path $pf) {
|
if (Test-Path $pf) {
|
||||||
try {
|
try {
|
||||||
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||||
if ($j.v8path) { return [string]$j.v8path }
|
if ($j.v8path) { return [string]$j.v8path }
|
||||||
} catch {}
|
} catch {}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
$parent = Split-Path $dir -Parent
|
$parent = Split-Path $dir -Parent
|
||||||
if (-not $parent -or $parent -eq $dir) { break }
|
if (-not $parent -or $parent -eq $dir) { break }
|
||||||
$dir = $parent
|
$dir = $parent
|
||||||
}
|
}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$V8Path = Find-ProjectV8Path
|
$V8Path = Find-ProjectV8Path
|
||||||
}
|
}
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
||||||
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
||||||
Select-Object -First 1
|
Select-Object -First 1
|
||||||
if ($found) {
|
if ($found) {
|
||||||
$V8Path = $found.FullName
|
$V8Path = $found.FullName
|
||||||
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Test-Path $V8Path -PathType Container) {
|
if (Test-Path $V8Path -PathType Container) {
|
||||||
$V8Path = Join-Path $V8Path "1cv8.exe"
|
$V8Path = Join-Path $V8Path "1cv8.exe"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $V8Path)) {
|
if (-not (Test-Path $V8Path)) {
|
||||||
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Detect engine (ibcmd vs 1cv8) by exe name ---
|
# --- Detect engine (ibcmd vs 1cv8) by exe name ---
|
||||||
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
||||||
|
|
||||||
# --- Validate connection ---
|
# --- Validate connection ---
|
||||||
if ($engine -eq "ibcmd") {
|
if ($engine -eq "ibcmd") {
|
||||||
if (-not $InfoBasePath) {
|
if (-not $InfoBasePath) {
|
||||||
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath)" -ForegroundColor Red
|
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath)" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
} elseif (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
} elseif (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
||||||
Write-Host "Error: specify -InfoBasePath or -InfoBaseServer + -InfoBaseRef" -ForegroundColor Red
|
Write-Host "Error: specify -InfoBasePath or -InfoBaseServer + -InfoBaseRef" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Validate config dir ---
|
# --- Validate config dir ---
|
||||||
if (-not (Test-Path $ConfigDir)) {
|
if (-not (Test-Path $ConfigDir)) {
|
||||||
Write-Host "Error: config directory not found: $ConfigDir" -ForegroundColor Red
|
Write-Host "Error: config directory not found: $ConfigDir" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Validate Partial mode ---
|
# --- Validate Partial mode ---
|
||||||
if ($Mode -eq "Partial" -and -not $Files -and -not $ListFile) {
|
if ($Mode -eq "Partial" -and -not $Files -and -not $ListFile) {
|
||||||
Write-Host "Error: -Files or -ListFile required for Partial mode" -ForegroundColor Red
|
Write-Host "Error: -Files or -ListFile required for Partial mode" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Temp dir ---
|
# --- Temp dir ---
|
||||||
$tempDir = Join-Path $env:TEMP "db_load_xml_$(Get-Random)"
|
$tempDir = Join-Path $env:TEMP "db_load_xml_$(Get-Random)"
|
||||||
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($engine -eq "ibcmd") {
|
if ($engine -eq "ibcmd") {
|
||||||
# --- ibcmd branch (file infobase only; hierarchical full-directory import) ---
|
# --- ibcmd branch (file infobase only; hierarchical full-directory import) ---
|
||||||
if ($Format -eq "Plain") {
|
if ($Format -eq "Plain") {
|
||||||
Write-Host "Error: ibcmd config import supports hierarchical format only (use -Format Hierarchical or 1cv8)" -ForegroundColor Red
|
Write-Host "Error: ibcmd config import supports hierarchical format only (use -Format Hierarchical or 1cv8)" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
if ($AllExtensions) {
|
if ($AllExtensions) {
|
||||||
$arguments = @("infobase", "config", "import", "all-extensions", "$ConfigDir", "--db-path=$InfoBasePath")
|
$arguments = @("infobase", "config", "import", "all-extensions", "$ConfigDir", "--db-path=$InfoBasePath")
|
||||||
} elseif ($Mode -eq "Partial" -or $Files -or $ListFile) {
|
} elseif ($Mode -eq "Partial" -or $Files -or $ListFile) {
|
||||||
# partial: import specific files (relative to ConfigDir)
|
# partial: import specific files (relative to ConfigDir)
|
||||||
$fileList = @()
|
$fileList = @()
|
||||||
if ($ListFile) {
|
if ($ListFile) {
|
||||||
if (-not (Test-Path $ListFile)) {
|
if (-not (Test-Path $ListFile)) {
|
||||||
Write-Host "Error: list file not found: $ListFile" -ForegroundColor Red
|
Write-Host "Error: list file not found: $ListFile" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
$fileList = @(Get-Content -Path $ListFile -Encoding UTF8 | ForEach-Object { $_.Trim() } | Where-Object { $_ })
|
$fileList = @(Get-Content -Path $ListFile -Encoding UTF8 | ForEach-Object { $_.Trim() } | Where-Object { $_ })
|
||||||
} elseif ($Files) {
|
} elseif ($Files) {
|
||||||
$fileList = @($Files -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ })
|
$fileList = @($Files -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ })
|
||||||
}
|
}
|
||||||
if ($fileList.Count -eq 0) {
|
if ($fileList.Count -eq 0) {
|
||||||
Write-Host "Error: -Files or -ListFile required for partial import" -ForegroundColor Red
|
Write-Host "Error: -Files or -ListFile required for partial import" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
$arguments = @("infobase", "config", "import", "files") + $fileList
|
$arguments = @("infobase", "config", "import", "files") + $fileList
|
||||||
$arguments += "--base-dir=$ConfigDir", "--db-path=$InfoBasePath"
|
$arguments += "--base-dir=$ConfigDir", "--db-path=$InfoBasePath"
|
||||||
if ($Extension) { $arguments += "--extension=$Extension" }
|
if ($Extension) { $arguments += "--extension=$Extension" }
|
||||||
} else {
|
} else {
|
||||||
$arguments = @("infobase", "config", "import", "--db-path=$InfoBasePath")
|
$arguments = @("infobase", "config", "import", "--db-path=$InfoBasePath")
|
||||||
if ($Extension) { $arguments += "--extension=$Extension" }
|
if ($Extension) { $arguments += "--extension=$Extension" }
|
||||||
$arguments += "$ConfigDir"
|
$arguments += "$ConfigDir"
|
||||||
}
|
}
|
||||||
if ($UserName) { $arguments += "--user=$UserName" }
|
if ($UserName) { $arguments += "--user=$UserName" }
|
||||||
if ($Password) { $arguments += "--password=$Password" }
|
if ($Password) { $arguments += "--password=$Password" }
|
||||||
$arguments += "--data=$tempDir"
|
$arguments += "--data=$tempDir"
|
||||||
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
||||||
$output = & $V8Path @arguments 2>&1
|
$output = & $V8Path @arguments 2>&1
|
||||||
$exitCode = $LASTEXITCODE
|
$exitCode = $LASTEXITCODE
|
||||||
if ($exitCode -ne 0) {
|
if ($exitCode -ne 0) {
|
||||||
Write-Host "Error loading configuration from files (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error loading configuration from files (code: $exitCode)" -ForegroundColor Red
|
||||||
if ($output) { Write-Host ($output | Out-String) }
|
if ($output) { Write-Host ($output | Out-String) }
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
}
|
}
|
||||||
Write-Host "Configuration loaded successfully from: $ConfigDir" -ForegroundColor Green
|
Write-Host "Configuration loaded successfully from: $ConfigDir" -ForegroundColor Green
|
||||||
if ($output) { Write-Host ($output | Out-String) }
|
if ($output) { Write-Host ($output | Out-String) }
|
||||||
|
|
||||||
if ($UpdateDB) {
|
if ($UpdateDB) {
|
||||||
$applyArgs = @("infobase", "config", "apply", "--db-path=$InfoBasePath", "--force")
|
$applyArgs = @("infobase", "config", "apply", "--db-path=$InfoBasePath", "--force")
|
||||||
if ($UserName) { $applyArgs += "--user=$UserName" }
|
if ($UserName) { $applyArgs += "--user=$UserName" }
|
||||||
if ($Password) { $applyArgs += "--password=$Password" }
|
if ($Password) { $applyArgs += "--password=$Password" }
|
||||||
$applyArgs += "--data=$tempDir"
|
$applyArgs += "--data=$tempDir"
|
||||||
Write-Host "Running: ibcmd $($applyArgs -join ' ')"
|
Write-Host "Running: ibcmd $($applyArgs -join ' ')"
|
||||||
$applyOut = & $V8Path @applyArgs 2>&1
|
$applyOut = & $V8Path @applyArgs 2>&1
|
||||||
$exitCode = $LASTEXITCODE
|
$exitCode = $LASTEXITCODE
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
Write-Host "Database configuration updated successfully" -ForegroundColor Green
|
Write-Host "Database configuration updated successfully" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error updating database configuration (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error updating database configuration (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
if ($applyOut) { Write-Host ($applyOut | Out-String) }
|
if ($applyOut) { Write-Host ($applyOut | Out-String) }
|
||||||
}
|
}
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 1cv8 branch ---
|
# --- 1cv8 branch ---
|
||||||
# --- Build arguments ---
|
# --- Build arguments ---
|
||||||
$arguments = @("DESIGNER")
|
$arguments = @("DESIGNER")
|
||||||
|
|
||||||
if ($InfoBaseServer -and $InfoBaseRef) {
|
if ($InfoBaseServer -and $InfoBaseRef) {
|
||||||
$arguments += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
|
$arguments += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
|
||||||
} else {
|
} else {
|
||||||
$arguments += "/F", "`"$InfoBasePath`""
|
$arguments += "/F", "`"$InfoBasePath`""
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($UserName) { $arguments += "/N`"$UserName`"" }
|
if ($UserName) { $arguments += "/N`"$UserName`"" }
|
||||||
if ($Password) { $arguments += "/P`"$Password`"" }
|
if ($Password) { $arguments += "/P`"$Password`"" }
|
||||||
|
|
||||||
$arguments += "/LoadConfigFromFiles", "`"$ConfigDir`""
|
$arguments += "/LoadConfigFromFiles", "`"$ConfigDir`""
|
||||||
|
|
||||||
if ($Mode -eq "Full") {
|
if ($Mode -eq "Full") {
|
||||||
Write-Host "Executing full configuration load..."
|
Write-Host "Executing full configuration load..."
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Executing partial configuration load..."
|
Write-Host "Executing partial configuration load..."
|
||||||
|
|
||||||
# Build list file
|
# Build list file
|
||||||
$rawList = @()
|
$rawList = @()
|
||||||
if ($ListFile) {
|
if ($ListFile) {
|
||||||
if (-not (Test-Path $ListFile)) {
|
if (-not (Test-Path $ListFile)) {
|
||||||
Write-Host "Error: list file not found: $ListFile" -ForegroundColor Red
|
Write-Host "Error: list file not found: $ListFile" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
$rawList = @(Get-Content -Path $ListFile -Encoding UTF8 | ForEach-Object { $_.Trim() } | Where-Object { $_ })
|
$rawList = @(Get-Content -Path $ListFile -Encoding UTF8 | ForEach-Object { $_.Trim() } | Where-Object { $_ })
|
||||||
} else {
|
} else {
|
||||||
$rawList = @($Files -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ })
|
$rawList = @($Files -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ })
|
||||||
}
|
}
|
||||||
|
|
||||||
# Support-state service files are NOT partially loadable — exclude with a hint.
|
# Support-state service files are NOT partially loadable — exclude with a hint.
|
||||||
$supportRe = 'ParentConfigurations\.bin$|(^|[\\/])ConfigDumpInfo\.xml$'
|
$supportRe = 'ParentConfigurations\.bin$|(^|[\\/])ConfigDumpInfo\.xml$'
|
||||||
$supportFiles = @($rawList | Where-Object { $_ -match $supportRe })
|
$supportFiles = @($rawList | Where-Object { $_ -match $supportRe })
|
||||||
$fileList = @($rawList | Where-Object { $_ -notmatch $supportRe })
|
$fileList = @($rawList | Where-Object { $_ -notmatch $supportRe })
|
||||||
if ($supportFiles.Count -gt 0) {
|
if ($supportFiles.Count -gt 0) {
|
||||||
Write-Host "[ВНИМАНИЕ] Служебные файлы состояния поддержки исключены из частичной загрузки (частично не грузятся):" -ForegroundColor Yellow
|
Write-Host "[ВНИМАНИЕ] Служебные файлы состояния поддержки исключены из частичной загрузки (частично не грузятся):" -ForegroundColor Yellow
|
||||||
foreach ($sf in $supportFiles) { Write-Host " - $sf" -ForegroundColor Yellow }
|
foreach ($sf in $supportFiles) { Write-Host " - $sf" -ForegroundColor Yellow }
|
||||||
Write-Host " Смена состояния поддержки применяется только полной загрузкой: -Mode Full." -ForegroundColor Yellow
|
Write-Host " Смена состояния поддержки применяется только полной загрузкой: -Mode Full." -ForegroundColor Yellow
|
||||||
}
|
}
|
||||||
if ($fileList.Count -eq 0) {
|
if ($fileList.Count -eq 0) {
|
||||||
Write-Host "Error: после исключения служебных файлов поддержки загружать нечего. Для смены поддержки используйте -Mode Full." -ForegroundColor Red
|
Write-Host "Error: после исключения служебных файлов поддержки загружать нечего. Для смены поддержки используйте -Mode Full." -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
$generatedListFile = Join-Path $tempDir "load_list.txt"
|
$generatedListFile = Join-Path $tempDir "load_list.txt"
|
||||||
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
||||||
[System.IO.File]::WriteAllLines($generatedListFile, $fileList, $utf8Bom)
|
[System.IO.File]::WriteAllLines($generatedListFile, $fileList, $utf8Bom)
|
||||||
Write-Host "Files to load: $($fileList.Count)"
|
Write-Host "Files to load: $($fileList.Count)"
|
||||||
foreach ($f in $fileList) { Write-Host " $f" }
|
foreach ($f in $fileList) { Write-Host " $f" }
|
||||||
|
|
||||||
$arguments += "-listFile", "`"$generatedListFile`""
|
$arguments += "-listFile", "`"$generatedListFile`""
|
||||||
$arguments += "-partial"
|
$arguments += "-partial"
|
||||||
$arguments += "-updateConfigDumpInfo"
|
$arguments += "-updateConfigDumpInfo"
|
||||||
}
|
}
|
||||||
|
|
||||||
$arguments += "-Format", $Format
|
$arguments += "-Format", $Format
|
||||||
|
|
||||||
# --- Extensions ---
|
# --- Extensions ---
|
||||||
if ($Extension) {
|
if ($Extension) {
|
||||||
$arguments += "-Extension", "`"$Extension`""
|
$arguments += "-Extension", "`"$Extension`""
|
||||||
} elseif ($AllExtensions) {
|
} elseif ($AllExtensions) {
|
||||||
$arguments += "-AllExtensions"
|
$arguments += "-AllExtensions"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- UpdateDB ---
|
# --- UpdateDB ---
|
||||||
if ($UpdateDB) {
|
if ($UpdateDB) {
|
||||||
$arguments += "/UpdateDBCfg"
|
$arguments += "/UpdateDBCfg"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Output ---
|
# --- Output ---
|
||||||
$outFile = Join-Path $tempDir "load_log.txt"
|
$outFile = Join-Path $tempDir "load_log.txt"
|
||||||
$arguments += "/Out", "`"$outFile`""
|
$arguments += "/Out", "`"$outFile`""
|
||||||
$arguments += "/DisableStartupDialogs"
|
$arguments += "/DisableStartupDialogs"
|
||||||
|
|
||||||
# --- Execute ---
|
# --- Execute ---
|
||||||
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
||||||
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
||||||
$exitCode = $process.ExitCode
|
$exitCode = $process.ExitCode
|
||||||
|
|
||||||
# --- Read log ---
|
# --- Read log ---
|
||||||
$logContent = $null
|
$logContent = $null
|
||||||
if (Test-Path $outFile) {
|
if (Test-Path $outFile) {
|
||||||
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Scan log for silent rejections ---
|
# --- Scan log for silent rejections ---
|
||||||
# Platform often writes load-time rejections into /Out but exits with code 0.
|
# Platform often writes load-time rejections into /Out but exits with code 0.
|
||||||
# These patterns flag cases where metadata was dropped or rejected silently.
|
# These patterns flag cases where metadata was dropped or rejected silently.
|
||||||
$fatalLogPatterns = @(
|
$fatalLogPatterns = @(
|
||||||
'Неверное свойство объекта метаданных',
|
'Неверное свойство объекта метаданных',
|
||||||
'не входит в состав объекта метаданных',
|
'не входит в состав объекта метаданных',
|
||||||
'Неизвестное имя типа',
|
'Неизвестное имя типа',
|
||||||
'Неизвестный объект метаданных',
|
'Неизвестный объект метаданных',
|
||||||
'Ни один из документов не является регистратором для регистра',
|
'Ни один из документов не является регистратором для регистра',
|
||||||
'Неверное значение перечисления',
|
'Неверное значение перечисления',
|
||||||
'не может быть приведен к типу'
|
'не может быть приведен к типу'
|
||||||
)
|
)
|
||||||
$silentFailures = @()
|
$silentFailures = @()
|
||||||
if ($logContent) {
|
if ($logContent) {
|
||||||
foreach ($line in ($logContent -split "`r?`n")) {
|
foreach ($line in ($logContent -split "`r?`n")) {
|
||||||
foreach ($pat in $fatalLogPatterns) {
|
foreach ($pat in $fatalLogPatterns) {
|
||||||
if ($line -match [regex]::Escape($pat)) {
|
if ($line -match [regex]::Escape($pat)) {
|
||||||
$silentFailures += $line.Trim()
|
$silentFailures += $line.Trim()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Result ---
|
# --- Result ---
|
||||||
# Default: mirror platform's verdict via exit code. Log content (including any
|
# Default: mirror platform's verdict via exit code. Log content (including any
|
||||||
# rejection warnings) is always printed to stdout for visibility. With -StrictLog,
|
# rejection warnings) is always printed to stdout for visibility. With -StrictLog,
|
||||||
# elevate exit code to 1 when rejection patterns are found even if platform said 0.
|
# elevate exit code to 1 when rejection patterns are found even if platform said 0.
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
Write-Host "Load completed successfully" -ForegroundColor Green
|
Write-Host "Load completed successfully" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error loading configuration (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error loading configuration (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($logContent) {
|
if ($logContent) {
|
||||||
Write-Host "--- Log ---"
|
Write-Host "--- Log ---"
|
||||||
Write-Host $logContent
|
Write-Host $logContent
|
||||||
Write-Host "--- End ---"
|
Write-Host "--- End ---"
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($silentFailures.Count -gt 0) {
|
if ($silentFailures.Count -gt 0) {
|
||||||
$msg = "[warning] log contains $($silentFailures.Count) rejection(s) — platform loaded config but dropped properties/refs"
|
$msg = "[warning] log contains $($silentFailures.Count) rejection(s) — platform loaded config but dropped properties/refs"
|
||||||
if (-not $StrictLog) { $msg += " (pass -StrictLog to treat as error)" }
|
if (-not $StrictLog) { $msg += " (pass -StrictLog to treat as error)" }
|
||||||
Write-Host $msg -ForegroundColor Yellow
|
Write-Host $msg -ForegroundColor Yellow
|
||||||
foreach ($f in $silentFailures) { Write-Host " $f" -ForegroundColor Yellow }
|
foreach ($f in $silentFailures) { Write-Host " $f" -ForegroundColor Yellow }
|
||||||
if ($StrictLog -and $exitCode -eq 0) { $exitCode = 1 }
|
if ($StrictLog -and $exitCode -eq 0) { $exitCode = 1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (Test-Path $tempDir) {
|
if (Test-Path $tempDir) {
|
||||||
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,76 +1,76 @@
|
|||||||
---
|
---
|
||||||
name: db-run
|
name: db-run
|
||||||
description: Запуск 1С:Предприятие. Используй когда нужно запустить 1С, открыть базу, запустить предприятие
|
description: Запуск 1С:Предприятие. Используй когда нужно запустить 1С, открыть базу, запустить предприятие
|
||||||
argument-hint: "[database]"
|
argument-hint: "[database]"
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
- AskUserQuestion
|
- AskUserQuestion
|
||||||
---
|
---
|
||||||
|
|
||||||
# /db-run — Запуск 1С:Предприятие
|
# /db-run — Запуск 1С:Предприятие
|
||||||
|
|
||||||
Запускает информационную базу в режиме 1С:Предприятие (пользовательский режим).
|
Запускает информационную базу в режиме 1С:Предприятие (пользовательский режим).
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/db-run [database]
|
/db-run [database]
|
||||||
/db-run dev
|
/db-run dev
|
||||||
/db-run dev /Execute process.epf
|
/db-run dev /Execute process.epf
|
||||||
/db-run dev /C "параметр запуска"
|
/db-run dev /C "параметр запуска"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Параметры подключения
|
## Параметры подключения
|
||||||
|
|
||||||
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
||||||
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
||||||
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
||||||
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
||||||
4. Если ветка не совпала — используй `default`
|
4. Если ветка не совпала — используй `default`
|
||||||
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
||||||
Если файла нет — предложи `/db-list add`.
|
Если файла нет — предложи `/db-list add`.
|
||||||
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" <параметры>
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|----------|:------------:|----------|
|
|----------|:------------:|----------|
|
||||||
| `-V8Path <путь>` | нет | Каталог bin платформы (или полный путь к 1cv8.exe) |
|
| `-V8Path <путь>` | нет | Каталог bin платформы (или полный путь к 1cv8.exe) |
|
||||||
| `-InfoBasePath <путь>` | * | Файловая база |
|
| `-InfoBasePath <путь>` | * | Файловая база |
|
||||||
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
||||||
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
||||||
| `-UserName <имя>` | нет | Имя пользователя |
|
| `-UserName <имя>` | нет | Имя пользователя |
|
||||||
| `-Password <пароль>` | нет | Пароль |
|
| `-Password <пароль>` | нет | Пароль |
|
||||||
| `-Execute <файл.epf>` | нет | Запуск внешней обработки сразу после старта |
|
| `-Execute <файл.epf>` | нет | Запуск внешней обработки сразу после старта |
|
||||||
| `-CParam <строка>` | нет | Параметр запуска (/C) |
|
| `-CParam <строка>` | нет | Параметр запуска (/C) |
|
||||||
| `-URL <ссылка>` | нет | Навигационная ссылка (формат `e1cib/...`) |
|
| `-URL <ссылка>` | нет | Навигационная ссылка (формат `e1cib/...`) |
|
||||||
|
|
||||||
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
||||||
|
|
||||||
## Важно
|
## Важно
|
||||||
|
|
||||||
Скрипт запускает 1С в фоне (`Start-Process` без `-Wait`) — управление возвращается сразу.
|
Скрипт запускает 1С в фоне (`Start-Process` без `-Wait`) — управление возвращается сразу.
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Простой запуск
|
# Простой запуск
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
|
||||||
|
|
||||||
# Запуск с обработкой
|
# Запуск с обработкой
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -Execute "C:\epf\МояОбработка.epf"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -Execute "C:\epf\МояОбработка.epf"
|
||||||
|
|
||||||
# Открыть по навигационной ссылке
|
# Открыть по навигационной ссылке
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -URL "e1cib/data/Справочник.Номенклатура"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -URL "e1cib/data/Справочник.Номенклатура"
|
||||||
|
|
||||||
# Серверная база с параметром запуска
|
# Серверная база с параметром запуска
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -CParam "ЗапуститьОбновление"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -CParam "ЗапуститьОбновление"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,170 +1,170 @@
|
|||||||
# db-run v1.1 — Launch 1C:Enterprise
|
# db-run v1.1 — Launch 1C:Enterprise
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Запуск 1С:Предприятие
|
Запуск 1С:Предприятие
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Запускает информационную базу в режиме 1С:Предприятие (пользовательский режим).
|
Запускает информационную базу в режиме 1С:Предприятие (пользовательский режим).
|
||||||
Запуск в фоне — не ждёт завершения процесса.
|
Запуск в фоне — не ждёт завершения процесса.
|
||||||
|
|
||||||
.PARAMETER V8Path
|
.PARAMETER V8Path
|
||||||
Путь к каталогу bin платформы или к 1cv8.exe
|
Путь к каталогу bin платформы или к 1cv8.exe
|
||||||
|
|
||||||
.PARAMETER InfoBasePath
|
.PARAMETER InfoBasePath
|
||||||
Путь к файловой информационной базе
|
Путь к файловой информационной базе
|
||||||
|
|
||||||
.PARAMETER InfoBaseServer
|
.PARAMETER InfoBaseServer
|
||||||
Сервер 1С (для серверной базы)
|
Сервер 1С (для серверной базы)
|
||||||
|
|
||||||
.PARAMETER InfoBaseRef
|
.PARAMETER InfoBaseRef
|
||||||
Имя базы на сервере
|
Имя базы на сервере
|
||||||
|
|
||||||
.PARAMETER UserName
|
.PARAMETER UserName
|
||||||
Имя пользователя 1С
|
Имя пользователя 1С
|
||||||
|
|
||||||
.PARAMETER Password
|
.PARAMETER Password
|
||||||
Пароль пользователя
|
Пароль пользователя
|
||||||
|
|
||||||
.PARAMETER Execute
|
.PARAMETER Execute
|
||||||
Путь к внешней обработке для запуска
|
Путь к внешней обработке для запуска
|
||||||
|
|
||||||
.PARAMETER CParam
|
.PARAMETER CParam
|
||||||
Параметр запуска (/C)
|
Параметр запуска (/C)
|
||||||
|
|
||||||
.PARAMETER URL
|
.PARAMETER URL
|
||||||
Навигационная ссылка (e1cib/...)
|
Навигационная ссылка (e1cib/...)
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-run.ps1 -InfoBasePath "C:\Bases\MyDB"
|
.\db-run.ps1 -InfoBasePath "C:\Bases\MyDB"
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-run.ps1 -InfoBasePath "C:\Bases\MyDB" -Execute "C:\epf\МояОбработка.epf"
|
.\db-run.ps1 -InfoBasePath "C:\Bases\MyDB" -Execute "C:\epf\МояОбработка.epf"
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-run.ps1 -InfoBasePath "C:\Bases\MyDB" -CParam "ЗапуститьОбновление"
|
.\db-run.ps1 -InfoBasePath "C:\Bases\MyDB" -CParam "ЗапуститьОбновление"
|
||||||
#>
|
#>
|
||||||
|
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$V8Path,
|
[string]$V8Path,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBasePath,
|
[string]$InfoBasePath,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseServer,
|
[string]$InfoBaseServer,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseRef,
|
[string]$InfoBaseRef,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$UserName,
|
[string]$UserName,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Password,
|
[string]$Password,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Execute,
|
[string]$Execute,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$CParam,
|
[string]$CParam,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$URL
|
[string]$URL
|
||||||
)
|
)
|
||||||
|
|
||||||
$OutputEncoding = [System.Text.Encoding]::UTF8
|
$OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Resolve V8Path ---
|
# --- Resolve V8Path ---
|
||||||
function Find-ProjectV8Path {
|
function Find-ProjectV8Path {
|
||||||
$dir = (Get-Location).Path
|
$dir = (Get-Location).Path
|
||||||
while ($dir) {
|
while ($dir) {
|
||||||
$pf = Join-Path $dir ".v8-project.json"
|
$pf = Join-Path $dir ".v8-project.json"
|
||||||
if (Test-Path $pf) {
|
if (Test-Path $pf) {
|
||||||
try {
|
try {
|
||||||
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||||
if ($j.v8path) { return [string]$j.v8path }
|
if ($j.v8path) { return [string]$j.v8path }
|
||||||
} catch {}
|
} catch {}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
$parent = Split-Path $dir -Parent
|
$parent = Split-Path $dir -Parent
|
||||||
if (-not $parent -or $parent -eq $dir) { break }
|
if (-not $parent -or $parent -eq $dir) { break }
|
||||||
$dir = $parent
|
$dir = $parent
|
||||||
}
|
}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$V8Path = Find-ProjectV8Path
|
$V8Path = Find-ProjectV8Path
|
||||||
}
|
}
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
||||||
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
||||||
Select-Object -First 1
|
Select-Object -First 1
|
||||||
if ($found) {
|
if ($found) {
|
||||||
$V8Path = $found.FullName
|
$V8Path = $found.FullName
|
||||||
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Test-Path $V8Path -PathType Container) {
|
if (Test-Path $V8Path -PathType Container) {
|
||||||
$V8Path = Join-Path $V8Path "1cv8.exe"
|
$V8Path = Join-Path $V8Path "1cv8.exe"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $V8Path)) {
|
if (-not (Test-Path $V8Path)) {
|
||||||
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Validate connection ---
|
# --- Validate connection ---
|
||||||
if (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
if (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
||||||
Write-Host "Error: specify -InfoBasePath or -InfoBaseServer + -InfoBaseRef" -ForegroundColor Red
|
Write-Host "Error: specify -InfoBasePath or -InfoBaseServer + -InfoBaseRef" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Build arguments as single string ---
|
# --- Build arguments as single string ---
|
||||||
# Note: Start-Process without -NoNewWindow uses ShellExecute.
|
# Note: Start-Process without -NoNewWindow uses ShellExecute.
|
||||||
# Passing ArgumentList as array can corrupt Cyrillic when ShellExecute
|
# Passing ArgumentList as array can corrupt Cyrillic when ShellExecute
|
||||||
# re-joins elements. Single string avoids this.
|
# re-joins elements. Single string avoids this.
|
||||||
$argString = "ENTERPRISE"
|
$argString = "ENTERPRISE"
|
||||||
|
|
||||||
if ($InfoBaseServer -and $InfoBaseRef) {
|
if ($InfoBaseServer -and $InfoBaseRef) {
|
||||||
$argString += " /S `"$InfoBaseServer/$InfoBaseRef`""
|
$argString += " /S `"$InfoBaseServer/$InfoBaseRef`""
|
||||||
} else {
|
} else {
|
||||||
$argString += " /F `"$InfoBasePath`""
|
$argString += " /F `"$InfoBasePath`""
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($UserName) { $argString += " /N`"$UserName`"" }
|
if ($UserName) { $argString += " /N`"$UserName`"" }
|
||||||
if ($Password) { $argString += " /P`"$Password`"" }
|
if ($Password) { $argString += " /P`"$Password`"" }
|
||||||
|
|
||||||
# --- Optional params ---
|
# --- Optional params ---
|
||||||
if ($Execute) {
|
if ($Execute) {
|
||||||
$ext = [System.IO.Path]::GetExtension($Execute).ToLower()
|
$ext = [System.IO.Path]::GetExtension($Execute).ToLower()
|
||||||
if ($ext -eq ".erf") {
|
if ($ext -eq ".erf") {
|
||||||
Write-Host "[WARN] /Execute не поддерживает ERF-файлы (внешние отчёты)." -ForegroundColor Yellow
|
Write-Host "[WARN] /Execute не поддерживает ERF-файлы (внешние отчёты)." -ForegroundColor Yellow
|
||||||
Write-Host " Откройте отчёт через «Файл -> Открыть»: $Execute" -ForegroundColor Yellow
|
Write-Host " Откройте отчёт через «Файл -> Открыть»: $Execute" -ForegroundColor Yellow
|
||||||
Write-Host " Запускаю базу без /Execute." -ForegroundColor Yellow
|
Write-Host " Запускаю базу без /Execute." -ForegroundColor Yellow
|
||||||
$Execute = ""
|
$Execute = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($Execute) {
|
if ($Execute) {
|
||||||
$argString += " /Execute `"$Execute`""
|
$argString += " /Execute `"$Execute`""
|
||||||
}
|
}
|
||||||
if ($CParam) {
|
if ($CParam) {
|
||||||
$argString += " /C `"$CParam`""
|
$argString += " /C `"$CParam`""
|
||||||
}
|
}
|
||||||
if ($URL) {
|
if ($URL) {
|
||||||
$argString += " /URL `"$URL`""
|
$argString += " /URL `"$URL`""
|
||||||
}
|
}
|
||||||
|
|
||||||
$argString += " /DisableStartupDialogs"
|
$argString += " /DisableStartupDialogs"
|
||||||
|
|
||||||
# --- Execute (background, no wait) ---
|
# --- Execute (background, no wait) ---
|
||||||
Write-Host "Running: 1cv8.exe $argString"
|
Write-Host "Running: 1cv8.exe $argString"
|
||||||
Start-Process -FilePath $V8Path -ArgumentList $argString
|
Start-Process -FilePath $V8Path -ArgumentList $argString
|
||||||
Write-Host "1C:Enterprise launched" -ForegroundColor Green
|
Write-Host "1C:Enterprise launched" -ForegroundColor Green
|
||||||
|
|||||||
@@ -1,86 +1,86 @@
|
|||||||
---
|
---
|
||||||
name: db-update
|
name: db-update
|
||||||
description: Обновление конфигурации базы данных 1С. Используй когда нужно обновить БД, применить конфигурацию, UpdateDBCfg
|
description: Обновление конфигурации базы данных 1С. Используй когда нужно обновить БД, применить конфигурацию, UpdateDBCfg
|
||||||
argument-hint: "[database]"
|
argument-hint: "[database]"
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
- AskUserQuestion
|
- AskUserQuestion
|
||||||
---
|
---
|
||||||
|
|
||||||
# /db-update — Обновление конфигурации БД
|
# /db-update — Обновление конфигурации БД
|
||||||
|
|
||||||
Применяет изменения основной конфигурации к конфигурации базы данных (`/UpdateDBCfg`). Обязательный шаг после `/db-load-cf`, `/db-load-xml`, `/db-load-git`.
|
Применяет изменения основной конфигурации к конфигурации базы данных (`/UpdateDBCfg`). Обязательный шаг после `/db-load-cf`, `/db-load-xml`, `/db-load-git`.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/db-update [database]
|
/db-update [database]
|
||||||
/db-update dev
|
/db-update dev
|
||||||
/db-update dev -Dynamic+
|
/db-update dev -Dynamic+
|
||||||
```
|
```
|
||||||
|
|
||||||
## Параметры подключения
|
## Параметры подключения
|
||||||
|
|
||||||
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
||||||
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
||||||
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
||||||
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
||||||
4. Если ветка не совпала — используй `default`
|
4. Если ветка не совпала — используй `default`
|
||||||
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
||||||
Если файла нет — предложи `/db-list add`.
|
Если файла нет — предложи `/db-list add`.
|
||||||
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" <параметры>
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|----------|:------------:|----------|
|
|----------|:------------:|----------|
|
||||||
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
||||||
| `-InfoBasePath <путь>` | * | Файловая база |
|
| `-InfoBasePath <путь>` | * | Файловая база |
|
||||||
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
||||||
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
||||||
| `-UserName <имя>` | нет | Имя пользователя |
|
| `-UserName <имя>` | нет | Имя пользователя |
|
||||||
| `-Password <пароль>` | нет | Пароль |
|
| `-Password <пароль>` | нет | Пароль |
|
||||||
| `-Extension <имя>` | нет | Обновить расширение |
|
| `-Extension <имя>` | нет | Обновить расширение |
|
||||||
| `-AllExtensions` | нет | Обновить все расширения |
|
| `-AllExtensions` | нет | Обновить все расширения |
|
||||||
| `-Dynamic <+/->` | нет | `+` — динамическое обновление, `-` — отключить |
|
| `-Dynamic <+/->` | нет | `+` — динамическое обновление, `-` — отключить |
|
||||||
| `-Server` | нет | Обновление на стороне сервера |
|
| `-Server` | нет | Обновление на стороне сервера |
|
||||||
| `-WarningsAsErrors` | нет | Предупреждения считать ошибками |
|
| `-WarningsAsErrors` | нет | Предупреждения считать ошибками |
|
||||||
|
|
||||||
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
||||||
|
|
||||||
### Фоновое обновление (серверная база)
|
### Фоновое обновление (серверная база)
|
||||||
|
|
||||||
| Параметр | Описание |
|
| Параметр | Описание |
|
||||||
|----------|----------|
|
|----------|----------|
|
||||||
| `-BackgroundStart` | Начать фоновое обновление |
|
| `-BackgroundStart` | Начать фоновое обновление |
|
||||||
| `-BackgroundFinish` | Дождаться окончания |
|
| `-BackgroundFinish` | Дождаться окончания |
|
||||||
| `-BackgroundCancel` | Отменить |
|
| `-BackgroundCancel` | Отменить |
|
||||||
| `-BackgroundSuspend` | Приостановить |
|
| `-BackgroundSuspend` | Приостановить |
|
||||||
| `-BackgroundResume` | Возобновить |
|
| `-BackgroundResume` | Возобновить |
|
||||||
|
|
||||||
## Предупреждения
|
## Предупреждения
|
||||||
|
|
||||||
- Если обновление **не динамическое** — потребуется **монопольный доступ** к базе (все пользователи должны выйти)
|
- Если обновление **не динамическое** — потребуется **монопольный доступ** к базе (все пользователи должны выйти)
|
||||||
- Для серверных баз рекомендуется `-Dynamic+` для обновления без остановки
|
- Для серверных баз рекомендуется `-Dynamic+` для обновления без остановки
|
||||||
- Если структура данных существенно изменилась (удаление реквизитов, изменение типов) — динамическое обновление может быть невозможно
|
- Если структура данных существенно изменилась (удаление реквизитов, изменение типов) — динамическое обновление может быть невозможно
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Обычное обновление (файловая база)
|
# Обычное обновление (файловая база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
|
||||||
|
|
||||||
# Динамическое обновление (серверная база)
|
# Динамическое обновление (серверная база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -Dynamic "+"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -Dynamic "+"
|
||||||
|
|
||||||
# Обновление расширения
|
# Обновление расширения
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -Extension "МоёРасширение"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -Extension "МоёРасширение"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,243 +1,243 @@
|
|||||||
# db-update v1.4 — Update 1C database configuration
|
# db-update v1.4 — Update 1C database configuration
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Обновление конфигурации базы данных 1С
|
Обновление конфигурации базы данных 1С
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Применяет изменения основной конфигурации к конфигурации базы данных.
|
Применяет изменения основной конфигурации к конфигурации базы данных.
|
||||||
Поддерживает динамическое обновление, обновление расширений.
|
Поддерживает динамическое обновление, обновление расширений.
|
||||||
|
|
||||||
.PARAMETER V8Path
|
.PARAMETER V8Path
|
||||||
Путь к каталогу bin платформы или к 1cv8.exe
|
Путь к каталогу bin платформы или к 1cv8.exe
|
||||||
|
|
||||||
.PARAMETER InfoBasePath
|
.PARAMETER InfoBasePath
|
||||||
Путь к файловой информационной базе
|
Путь к файловой информационной базе
|
||||||
|
|
||||||
.PARAMETER InfoBaseServer
|
.PARAMETER InfoBaseServer
|
||||||
Сервер 1С (для серверной базы)
|
Сервер 1С (для серверной базы)
|
||||||
|
|
||||||
.PARAMETER InfoBaseRef
|
.PARAMETER InfoBaseRef
|
||||||
Имя базы на сервере
|
Имя базы на сервере
|
||||||
|
|
||||||
.PARAMETER UserName
|
.PARAMETER UserName
|
||||||
Имя пользователя 1С
|
Имя пользователя 1С
|
||||||
|
|
||||||
.PARAMETER Password
|
.PARAMETER Password
|
||||||
Пароль пользователя
|
Пароль пользователя
|
||||||
|
|
||||||
.PARAMETER Extension
|
.PARAMETER Extension
|
||||||
Имя расширения для обновления
|
Имя расширения для обновления
|
||||||
|
|
||||||
.PARAMETER AllExtensions
|
.PARAMETER AllExtensions
|
||||||
Обновить все расширения
|
Обновить все расширения
|
||||||
|
|
||||||
.PARAMETER Dynamic
|
.PARAMETER Dynamic
|
||||||
Динамическое обновление: "+" включить, "-" отключить
|
Динамическое обновление: "+" включить, "-" отключить
|
||||||
|
|
||||||
.PARAMETER Server
|
.PARAMETER Server
|
||||||
Обновление на стороне сервера
|
Обновление на стороне сервера
|
||||||
|
|
||||||
.PARAMETER WarningsAsErrors
|
.PARAMETER WarningsAsErrors
|
||||||
Предупреждения считать ошибками
|
Предупреждения считать ошибками
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-update.ps1 -InfoBasePath "C:\Bases\MyDB"
|
.\db-update.ps1 -InfoBasePath "C:\Bases\MyDB"
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\db-update.ps1 -InfoBasePath "C:\Bases\MyDB" -Dynamic "+" -Extension "МоёРасширение"
|
.\db-update.ps1 -InfoBasePath "C:\Bases\MyDB" -Dynamic "+" -Extension "МоёРасширение"
|
||||||
#>
|
#>
|
||||||
|
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$V8Path,
|
[string]$V8Path,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBasePath,
|
[string]$InfoBasePath,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseServer,
|
[string]$InfoBaseServer,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseRef,
|
[string]$InfoBaseRef,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$UserName,
|
[string]$UserName,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Password,
|
[string]$Password,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Extension,
|
[string]$Extension,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[switch]$AllExtensions,
|
[switch]$AllExtensions,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[ValidateSet("+", "-")]
|
[ValidateSet("+", "-")]
|
||||||
[string]$Dynamic,
|
[string]$Dynamic,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[switch]$Server,
|
[switch]$Server,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[switch]$WarningsAsErrors
|
[switch]$WarningsAsErrors
|
||||||
)
|
)
|
||||||
|
|
||||||
$OutputEncoding = [System.Text.Encoding]::UTF8
|
$OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Resolve V8Path ---
|
# --- Resolve V8Path ---
|
||||||
function Find-ProjectV8Path {
|
function Find-ProjectV8Path {
|
||||||
$dir = (Get-Location).Path
|
$dir = (Get-Location).Path
|
||||||
while ($dir) {
|
while ($dir) {
|
||||||
$pf = Join-Path $dir ".v8-project.json"
|
$pf = Join-Path $dir ".v8-project.json"
|
||||||
if (Test-Path $pf) {
|
if (Test-Path $pf) {
|
||||||
try {
|
try {
|
||||||
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||||
if ($j.v8path) { return [string]$j.v8path }
|
if ($j.v8path) { return [string]$j.v8path }
|
||||||
} catch {}
|
} catch {}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
$parent = Split-Path $dir -Parent
|
$parent = Split-Path $dir -Parent
|
||||||
if (-not $parent -or $parent -eq $dir) { break }
|
if (-not $parent -or $parent -eq $dir) { break }
|
||||||
$dir = $parent
|
$dir = $parent
|
||||||
}
|
}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$V8Path = Find-ProjectV8Path
|
$V8Path = Find-ProjectV8Path
|
||||||
}
|
}
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
||||||
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
||||||
Select-Object -First 1
|
Select-Object -First 1
|
||||||
if ($found) {
|
if ($found) {
|
||||||
$V8Path = $found.FullName
|
$V8Path = $found.FullName
|
||||||
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Test-Path $V8Path -PathType Container) {
|
if (Test-Path $V8Path -PathType Container) {
|
||||||
$V8Path = Join-Path $V8Path "1cv8.exe"
|
$V8Path = Join-Path $V8Path "1cv8.exe"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $V8Path)) {
|
if (-not (Test-Path $V8Path)) {
|
||||||
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Detect engine (ibcmd vs 1cv8) by exe name ---
|
# --- Detect engine (ibcmd vs 1cv8) by exe name ---
|
||||||
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
||||||
|
|
||||||
# --- Validate connection ---
|
# --- Validate connection ---
|
||||||
if ($engine -eq "ibcmd") {
|
if ($engine -eq "ibcmd") {
|
||||||
if (-not $InfoBasePath) {
|
if (-not $InfoBasePath) {
|
||||||
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath)" -ForegroundColor Red
|
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath)" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
} elseif (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
} elseif (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
||||||
Write-Host "Error: specify -InfoBasePath or -InfoBaseServer + -InfoBaseRef" -ForegroundColor Red
|
Write-Host "Error: specify -InfoBasePath or -InfoBaseServer + -InfoBaseRef" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Temp dir ---
|
# --- Temp dir ---
|
||||||
$tempDir = Join-Path $env:TEMP "db_update_$(Get-Random)"
|
$tempDir = Join-Path $env:TEMP "db_update_$(Get-Random)"
|
||||||
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($engine -eq "ibcmd") {
|
if ($engine -eq "ibcmd") {
|
||||||
# --- ibcmd branch (file infobase only) ---
|
# --- ibcmd branch (file infobase only) ---
|
||||||
if ($AllExtensions) {
|
if ($AllExtensions) {
|
||||||
Write-Host "Error: ibcmd config apply does not support -AllExtensions (use -Extension)" -ForegroundColor Red
|
Write-Host "Error: ibcmd config apply does not support -AllExtensions (use -Extension)" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
$arguments = @("infobase", "config", "apply", "--db-path=$InfoBasePath", "--force")
|
$arguments = @("infobase", "config", "apply", "--db-path=$InfoBasePath", "--force")
|
||||||
if ($Dynamic -eq "+") { $arguments += "--dynamic=auto" }
|
if ($Dynamic -eq "+") { $arguments += "--dynamic=auto" }
|
||||||
elseif ($Dynamic -eq "-") { $arguments += "--dynamic=disable" }
|
elseif ($Dynamic -eq "-") { $arguments += "--dynamic=disable" }
|
||||||
if ($Extension) { $arguments += "--extension=$Extension" }
|
if ($Extension) { $arguments += "--extension=$Extension" }
|
||||||
if ($UserName) { $arguments += "--user=$UserName" }
|
if ($UserName) { $arguments += "--user=$UserName" }
|
||||||
if ($Password) { $arguments += "--password=$Password" }
|
if ($Password) { $arguments += "--password=$Password" }
|
||||||
$arguments += "--data=$tempDir"
|
$arguments += "--data=$tempDir"
|
||||||
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
||||||
$output = & $V8Path @arguments 2>&1
|
$output = & $V8Path @arguments 2>&1
|
||||||
$exitCode = $LASTEXITCODE
|
$exitCode = $LASTEXITCODE
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
Write-Host "Database configuration updated successfully" -ForegroundColor Green
|
Write-Host "Database configuration updated successfully" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error updating database configuration (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error updating database configuration (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
if ($output) { Write-Host ($output | Out-String) }
|
if ($output) { Write-Host ($output | Out-String) }
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 1cv8 branch ---
|
# --- 1cv8 branch ---
|
||||||
# --- Build arguments ---
|
# --- Build arguments ---
|
||||||
$arguments = @("DESIGNER")
|
$arguments = @("DESIGNER")
|
||||||
|
|
||||||
if ($InfoBaseServer -and $InfoBaseRef) {
|
if ($InfoBaseServer -and $InfoBaseRef) {
|
||||||
$arguments += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
|
$arguments += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
|
||||||
} else {
|
} else {
|
||||||
$arguments += "/F", "`"$InfoBasePath`""
|
$arguments += "/F", "`"$InfoBasePath`""
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($UserName) { $arguments += "/N`"$UserName`"" }
|
if ($UserName) { $arguments += "/N`"$UserName`"" }
|
||||||
if ($Password) { $arguments += "/P`"$Password`"" }
|
if ($Password) { $arguments += "/P`"$Password`"" }
|
||||||
|
|
||||||
$arguments += "/UpdateDBCfg"
|
$arguments += "/UpdateDBCfg"
|
||||||
|
|
||||||
# --- Options ---
|
# --- Options ---
|
||||||
if ($Dynamic) {
|
if ($Dynamic) {
|
||||||
$arguments += "-Dynamic$Dynamic"
|
$arguments += "-Dynamic$Dynamic"
|
||||||
}
|
}
|
||||||
if ($Server) {
|
if ($Server) {
|
||||||
$arguments += "-Server"
|
$arguments += "-Server"
|
||||||
}
|
}
|
||||||
if ($WarningsAsErrors) {
|
if ($WarningsAsErrors) {
|
||||||
$arguments += "-WarningsAsErrors"
|
$arguments += "-WarningsAsErrors"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Extensions ---
|
# --- Extensions ---
|
||||||
if ($Extension) {
|
if ($Extension) {
|
||||||
$arguments += "-Extension", "`"$Extension`""
|
$arguments += "-Extension", "`"$Extension`""
|
||||||
} elseif ($AllExtensions) {
|
} elseif ($AllExtensions) {
|
||||||
$arguments += "-AllExtensions"
|
$arguments += "-AllExtensions"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Output ---
|
# --- Output ---
|
||||||
$outFile = Join-Path $tempDir "update_log.txt"
|
$outFile = Join-Path $tempDir "update_log.txt"
|
||||||
$arguments += "/Out", "`"$outFile`""
|
$arguments += "/Out", "`"$outFile`""
|
||||||
$arguments += "/DisableStartupDialogs"
|
$arguments += "/DisableStartupDialogs"
|
||||||
|
|
||||||
# --- Execute ---
|
# --- Execute ---
|
||||||
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
||||||
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
||||||
$exitCode = $process.ExitCode
|
$exitCode = $process.ExitCode
|
||||||
|
|
||||||
# --- Result ---
|
# --- Result ---
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
Write-Host "Database configuration updated successfully" -ForegroundColor Green
|
Write-Host "Database configuration updated successfully" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error updating database configuration (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error updating database configuration (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Test-Path $outFile) {
|
if (Test-Path $outFile) {
|
||||||
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
||||||
if ($logContent) {
|
if ($logContent) {
|
||||||
Write-Host "--- Log ---"
|
Write-Host "--- Log ---"
|
||||||
Write-Host $logContent
|
Write-Host $logContent
|
||||||
Write-Host "--- End ---"
|
Write-Host "--- End ---"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (Test-Path $tempDir) {
|
if (Test-Path $tempDir) {
|
||||||
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,196 +1,196 @@
|
|||||||
---
|
---
|
||||||
name: epf-bsp-add-command
|
name: epf-bsp-add-command
|
||||||
description: Определить команду в БСП‑описании обработки (`СведенияОВнешнейОбработке`) — открытие формы, вызов клиентского/серверного метода, заполнение объекта и т.п. Используй когда нужно зарегистрировать команду в дополнительной обработке БСП
|
description: Определить команду в БСП‑описании обработки (`СведенияОВнешнейОбработке`) — открытие формы, вызов клиентского/серверного метода, заполнение объекта и т.п. Используй когда нужно зарегистрировать команду в дополнительной обработке БСП
|
||||||
argument-hint: <ProcessorName> <Идентификатор> [ТипКоманды] [Представление]
|
argument-hint: <ProcessorName> <Идентификатор> [ТипКоманды] [Представление]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Read
|
- Read
|
||||||
- Edit
|
- Edit
|
||||||
- Glob
|
- Glob
|
||||||
- Grep
|
- Grep
|
||||||
---
|
---
|
||||||
|
|
||||||
# /epf-bsp-add-command — Добавление команды БСП
|
# /epf-bsp-add-command — Добавление команды БСП
|
||||||
|
|
||||||
Добавляет команду в существующую функцию `СведенияОВнешнейОбработке()` и генерирует соответствующий обработчик.
|
Добавляет команду в существующую функцию `СведенияОВнешнейОбработке()` и генерирует соответствующий обработчик.
|
||||||
|
|
||||||
Предварительно обработка должна быть инициализирована через `/epf-bsp-init`.
|
Предварительно обработка должна быть инициализирована через `/epf-bsp-init`.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/epf-bsp-add-command <ProcessorName> <Идентификатор> [ТипКоманды] [Представление]
|
/epf-bsp-add-command <ProcessorName> <Идентификатор> [ТипКоманды] [Представление]
|
||||||
```
|
```
|
||||||
|
|
||||||
| Параметр | Обязательный | По умолчанию | Описание |
|
| Параметр | Обязательный | По умолчанию | Описание |
|
||||||
|---------------|:------------:|-----------------------|--------------------------------------------|
|
|---------------|:------------:|-----------------------|--------------------------------------------|
|
||||||
| ProcessorName | да | — | Имя обработки |
|
| ProcessorName | да | — | Имя обработки |
|
||||||
| Идентификатор | да | — | Внутреннее имя команды (латиница) |
|
| Идентификатор | да | — | Внутреннее имя команды (латиница) |
|
||||||
| ТипКоманды | нет | из вида обработки | Тип запуска команды (см. маппинг ниже) |
|
| ТипКоманды | нет | из вида обработки | Тип запуска команды (см. маппинг ниже) |
|
||||||
| Представление | нет | = Идентификатор | Отображаемое имя команды для пользователя |
|
| Представление | нет | = Идентификатор | Отображаемое имя команды для пользователя |
|
||||||
| SrcDir | нет | `src` | Каталог исходников |
|
| SrcDir | нет | `src` | Каталог исходников |
|
||||||
|
|
||||||
## Маппинг типов команд
|
## Маппинг типов команд
|
||||||
|
|
||||||
Пользователь может указать тип в свободной форме:
|
Пользователь может указать тип в свободной форме:
|
||||||
|
|
||||||
| Пользователь пишет | ТипКоманды |
|
| Пользователь пишет | ТипКоманды |
|
||||||
|---------------------------------------|-----------------------------------------------------|
|
|---------------------------------------|-----------------------------------------------------|
|
||||||
| открыть форму, форма | `ТипКомандыОткрытиеФормы()` |
|
| открыть форму, форма | `ТипКомандыОткрытиеФормы()` |
|
||||||
| клиентский метод, на клиенте | `ТипКомандыВызовКлиентскогоМетода()` |
|
| клиентский метод, на клиенте | `ТипКомандыВызовКлиентскогоМетода()` |
|
||||||
| серверный метод, на сервере | `ТипКомандыВызовСерверногоМетода()` |
|
| серверный метод, на сервере | `ТипКомандыВызовСерверногоМетода()` |
|
||||||
| заполнение формы, заполнить форму | `ТипКомандыЗаполнениеФормы()` |
|
| заполнение формы, заполнить форму | `ТипКомандыЗаполнениеФормы()` |
|
||||||
| сценарий, безопасный режим | `ТипКомандыСценарийВБезопасномРежиме()` |
|
| сценарий, безопасный режим | `ТипКомандыСценарийВБезопасномРежиме()` |
|
||||||
|
|
||||||
Если пользователь не указал тип — определи по виду обработки из существующего кода `СведенияОВнешнейОбработке()`:
|
Если пользователь не указал тип — определи по виду обработки из существующего кода `СведенияОВнешнейОбработке()`:
|
||||||
|
|
||||||
| Вид обработки (из кода) | ТипКоманды по умолчанию |
|
| Вид обработки (из кода) | ТипКоманды по умолчанию |
|
||||||
|----------------------------|-------------------------------------------|
|
|----------------------------|-------------------------------------------|
|
||||||
| ДополнительнаяОбработка | `ТипКомандыОткрытиеФормы()` |
|
| ДополнительнаяОбработка | `ТипКомандыОткрытиеФормы()` |
|
||||||
| ДополнительныйОтчет | `ТипКомандыОткрытиеФормы()` |
|
| ДополнительныйОтчет | `ТипКомандыОткрытиеФормы()` |
|
||||||
| ЗаполнениеОбъекта | `ТипКомандыВызовСерверногоМетода()` |
|
| ЗаполнениеОбъекта | `ТипКомандыВызовСерверногоМетода()` |
|
||||||
| Отчет | `ТипКомандыОткрытиеФормы()` |
|
| Отчет | `ТипКомандыОткрытиеФормы()` |
|
||||||
| ПечатнаяФорма | `ТипКомандыВызовСерверногоМетода()` |
|
| ПечатнаяФорма | `ТипКомандыВызовСерверногоМетода()` |
|
||||||
| СозданиеСвязанныхОбъектов | `ТипКомандыВызовСерверногоМетода()` |
|
| СозданиеСвязанныхОбъектов | `ТипКомандыВызовСерверногоМетода()` |
|
||||||
|
|
||||||
## Шаблон добавления команды
|
## Шаблон добавления команды
|
||||||
|
|
||||||
Вставляется в `СведенияОВнешнейОбработке()` **перед** строкой `Возврат ПараметрыРегистрации`:
|
Вставляется в `СведенияОВнешнейОбработке()` **перед** строкой `Возврат ПараметрыРегистрации`:
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
|
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
|
||||||
НоваяКоманда.Представление = НСтр("ru = '{{Представление}}'");
|
НоваяКоманда.Представление = НСтр("ru = '{{Представление}}'");
|
||||||
НоваяКоманда.Идентификатор = "{{Идентификатор}}";
|
НоваяКоманда.Идентификатор = "{{Идентификатор}}";
|
||||||
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.{{ТипКоманды}};
|
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.{{ТипКоманды}};
|
||||||
НоваяКоманда.ПоказыватьОповещение = Ложь;
|
НоваяКоманда.ПоказыватьОповещение = Ложь;
|
||||||
```
|
```
|
||||||
|
|
||||||
Для печатных форм (ВидОбработкиПечатнаяФорма) добавь также:
|
Для печатных форм (ВидОбработкиПечатнаяФорма) добавь также:
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
НоваяКоманда.Модификатор = "ПечатьMXL";
|
НоваяКоманда.Модификатор = "ПечатьMXL";
|
||||||
```
|
```
|
||||||
|
|
||||||
Примечание: в отличие от первой команды (из `/epf-bsp-init`), дополнительные команды используют строковые литералы `НСтр("ru = '...'")` для представления и строку для идентификатора, а не `Метаданные()`.
|
Примечание: в отличие от первой команды (из `/epf-bsp-init`), дополнительные команды используют строковые литералы `НСтр("ru = '...'")` для представления и строку для идентификатора, а не `Метаданные()`.
|
||||||
|
|
||||||
## Шаблоны обработчиков
|
## Шаблоны обработчиков
|
||||||
|
|
||||||
### ВызовСерверногоМетода — если обработчик уже есть
|
### ВызовСерверногоМетода — если обработчик уже есть
|
||||||
|
|
||||||
Если процедура `ВыполнитьКоманду` уже существует в модуле объекта, добавь ветку перед `КонецЕсли`:
|
Если процедура `ВыполнитьКоманду` уже существует в модуле объекта, добавь ветку перед `КонецЕсли`:
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
ИначеЕсли ИдентификаторКоманды = "{{Идентификатор}}" Тогда
|
ИначеЕсли ИдентификаторКоманды = "{{Идентификатор}}" Тогда
|
||||||
// TODO: Реализация {{Идентификатор}}
|
// TODO: Реализация {{Идентификатор}}
|
||||||
```
|
```
|
||||||
|
|
||||||
### ВызовСерверногоМетода — если обработчика нет
|
### ВызовСерверногоМетода — если обработчика нет
|
||||||
|
|
||||||
Для глобальных обработок (без `ОбъектыНазначения`):
|
Для глобальных обработок (без `ОбъектыНазначения`):
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполненияКоманды) Экспорт
|
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполненияКоманды) Экспорт
|
||||||
|
|
||||||
Если ИдентификаторКоманды = "{{Идентификатор}}" Тогда
|
Если ИдентификаторКоманды = "{{Идентификатор}}" Тогда
|
||||||
// TODO: Реализация {{Идентификатор}}
|
// TODO: Реализация {{Идентификатор}}
|
||||||
КонецЕсли;
|
КонецЕсли;
|
||||||
|
|
||||||
КонецПроцедуры
|
КонецПроцедуры
|
||||||
```
|
```
|
||||||
|
|
||||||
Для назначаемых обработок (с `ОбъектыНазначения`):
|
Для назначаемых обработок (с `ОбъектыНазначения`):
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения, ПараметрыВыполненияКоманды) Экспорт
|
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения, ПараметрыВыполненияКоманды) Экспорт
|
||||||
|
|
||||||
Если ИдентификаторКоманды = "{{Идентификатор}}" Тогда
|
Если ИдентификаторКоманды = "{{Идентификатор}}" Тогда
|
||||||
// TODO: Реализация {{Идентификатор}}
|
// TODO: Реализация {{Идентификатор}}
|
||||||
КонецЕсли;
|
КонецЕсли;
|
||||||
|
|
||||||
КонецПроцедуры
|
КонецПроцедуры
|
||||||
```
|
```
|
||||||
|
|
||||||
### ПечатнаяФорма — если процедура Печать уже есть
|
### ПечатнаяФорма — если процедура Печать уже есть
|
||||||
|
|
||||||
Добавь блок перед `КонецПроцедуры`:
|
Добавь блок перед `КонецПроцедуры`:
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "{{Идентификатор}}");
|
ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "{{Идентификатор}}");
|
||||||
Если ПечатнаяФорма <> Неопределено Тогда
|
Если ПечатнаяФорма <> Неопределено Тогда
|
||||||
ПечатнаяФорма.ТабличныйДокумент = Сформировать{{Идентификатор}}(МассивОбъектов, ОбъектыПечати);
|
ПечатнаяФорма.ТабличныйДокумент = Сформировать{{Идентификатор}}(МассивОбъектов, ОбъектыПечати);
|
||||||
ПечатнаяФорма.СинонимМакета = НСтр("ru = '{{Представление}}'");
|
ПечатнаяФорма.СинонимМакета = НСтр("ru = '{{Представление}}'");
|
||||||
КонецЕсли;
|
КонецЕсли;
|
||||||
```
|
```
|
||||||
|
|
||||||
### ПечатнаяФорма — если процедуры Печать нет
|
### ПечатнаяФорма — если процедуры Печать нет
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
|
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
|
||||||
|
|
||||||
ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "{{Идентификатор}}");
|
ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "{{Идентификатор}}");
|
||||||
Если ПечатнаяФорма <> Неопределено Тогда
|
Если ПечатнаяФорма <> Неопределено Тогда
|
||||||
ПечатнаяФорма.ТабличныйДокумент = Сформировать{{Идентификатор}}(МассивОбъектов, ОбъектыПечати);
|
ПечатнаяФорма.ТабличныйДокумент = Сформировать{{Идентификатор}}(МассивОбъектов, ОбъектыПечати);
|
||||||
ПечатнаяФорма.СинонимМакета = НСтр("ru = '{{Представление}}'");
|
ПечатнаяФорма.СинонимМакета = НСтр("ru = '{{Представление}}'");
|
||||||
КонецЕсли;
|
КонецЕсли;
|
||||||
|
|
||||||
КонецПроцедуры
|
КонецПроцедуры
|
||||||
```
|
```
|
||||||
|
|
||||||
### ВызовКлиентскогоМетода
|
### ВызовКлиентскогоМетода
|
||||||
|
|
||||||
Добавляется в **модуль формы** (`Forms/<FormName>/Ext/Form/Module.bsl`):
|
Добавляется в **модуль формы** (`Forms/<FormName>/Ext/Form/Module.bsl`):
|
||||||
|
|
||||||
Для глобальных обработок:
|
Для глобальных обработок:
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
&НаКлиенте
|
&НаКлиенте
|
||||||
Процедура ВыполнитьКоманду(ИдентификаторКоманды) Экспорт
|
Процедура ВыполнитьКоманду(ИдентификаторКоманды) Экспорт
|
||||||
|
|
||||||
Если ИдентификаторКоманды = "{{Идентификатор}}" Тогда
|
Если ИдентификаторКоманды = "{{Идентификатор}}" Тогда
|
||||||
// TODO: Реализация {{Идентификатор}}
|
// TODO: Реализация {{Идентификатор}}
|
||||||
КонецЕсли;
|
КонецЕсли;
|
||||||
|
|
||||||
КонецПроцедуры
|
КонецПроцедуры
|
||||||
```
|
```
|
||||||
|
|
||||||
Для назначаемых обработок:
|
Для назначаемых обработок:
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
&НаКлиенте
|
&НаКлиенте
|
||||||
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт
|
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт
|
||||||
|
|
||||||
Если ИдентификаторКоманды = "{{Идентификатор}}" Тогда
|
Если ИдентификаторКоманды = "{{Идентификатор}}" Тогда
|
||||||
// TODO: Реализация {{Идентификатор}}
|
// TODO: Реализация {{Идентификатор}}
|
||||||
КонецЕсли;
|
КонецЕсли;
|
||||||
|
|
||||||
КонецПроцедуры
|
КонецПроцедуры
|
||||||
```
|
```
|
||||||
|
|
||||||
Если процедура уже есть — добавь ветку `ИначеЕсли`.
|
Если процедура уже есть — добавь ветку `ИначеЕсли`.
|
||||||
|
|
||||||
## Инструкции
|
## Инструкции
|
||||||
|
|
||||||
1. Найди и прочитай `ObjectModule.bsl` через Glob: `src/{{ProcessorName}}/Ext/ObjectModule.bsl`
|
1. Найди и прочитай `ObjectModule.bsl` через Glob: `src/{{ProcessorName}}/Ext/ObjectModule.bsl`
|
||||||
2. Убедись что `СведенияОВнешнейОбработке()` существует. Если нет — предложи вызвать `/epf-bsp-init`
|
2. Убедись что `СведенияОВнешнейОбработке()` существует. Если нет — предложи вызвать `/epf-bsp-init`
|
||||||
3. Определи вид обработки из существующего кода (найди строку с `ВидОбработки...()`)
|
3. Определи вид обработки из существующего кода (найди строку с `ВидОбработки...()`)
|
||||||
4. Вставь блок команды **перед** `Возврат ПараметрыРегистрации`
|
4. Вставь блок команды **перед** `Возврат ПараметрыРегистрации`
|
||||||
5. Добавь обработчик:
|
5. Добавь обработчик:
|
||||||
- Для серверных обработчиков — в `ObjectModule.bsl`, область `ПрограммныйИнтерфейс`
|
- Для серверных обработчиков — в `ObjectModule.bsl`, область `ПрограммныйИнтерфейс`
|
||||||
- Для клиентских обработчиков — в модуль формы (найти через Glob: `src/{{ProcessorName}}/Forms/*/Ext/Form/Module.bsl`)
|
- Для клиентских обработчиков — в модуль формы (найти через Glob: `src/{{ProcessorName}}/Forms/*/Ext/Form/Module.bsl`)
|
||||||
6. Если обработчик (`ВыполнитьКоманду` / `Печать`) уже есть — добавь ветку, не создавай дубль процедуры
|
6. Если обработчик (`ВыполнитьКоманду` / `Печать`) уже есть — добавь ветку, не создавай дубль процедуры
|
||||||
7. Используй табы для отступов
|
7. Используй табы для отступов
|
||||||
|
|
||||||
## Пример
|
## Пример
|
||||||
|
|
||||||
Пользователь: `/epf-bsp-add-command МояОбработка ЗаказПокупателя серверный "Заказ покупателя"`
|
Пользователь: `/epf-bsp-add-command МояОбработка ЗаказПокупателя серверный "Заказ покупателя"`
|
||||||
|
|
||||||
В `СведенияОВнешнейОбработке()` перед `Возврат` добавится:
|
В `СведенияОВнешнейОбработке()` перед `Возврат` добавится:
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
|
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
|
||||||
НоваяКоманда.Представление = НСтр("ru = 'Заказ покупателя'");
|
НоваяКоманда.Представление = НСтр("ru = 'Заказ покупателя'");
|
||||||
НоваяКоманда.Идентификатор = "ЗаказПокупателя";
|
НоваяКоманда.Идентификатор = "ЗаказПокупателя";
|
||||||
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода();
|
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода();
|
||||||
НоваяКоманда.ПоказыватьОповещение = Ложь;
|
НоваяКоманда.ПоказыватьОповещение = Ложь;
|
||||||
```
|
```
|
||||||
|
|
||||||
И в существующую процедуру `ВыполнитьКоманду` добавится блок обработки.
|
И в существующую процедуру `ВыполнитьКоманду` добавится блок обработки.
|
||||||
|
|||||||
@@ -1,208 +1,208 @@
|
|||||||
---
|
---
|
||||||
name: epf-bsp-init
|
name: epf-bsp-init
|
||||||
description: Сформировать функцию `СведенияОВнешнейОбработке` в модуле объекта обработки — описание для подключения через подсистему БСП «Дополнительные отчёты и обработки». Используй когда нужно сделать обработку совместимой с БСП, подключаемой через «Дополнительные отчёты и обработки»
|
description: Сформировать функцию `СведенияОВнешнейОбработке` в модуле объекта обработки — описание для подключения через подсистему БСП «Дополнительные отчёты и обработки». Используй когда нужно сделать обработку совместимой с БСП, подключаемой через «Дополнительные отчёты и обработки»
|
||||||
argument-hint: <ProcessorName> <Вид>
|
argument-hint: <ProcessorName> <Вид>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Read
|
- Read
|
||||||
- Edit
|
- Edit
|
||||||
- Glob
|
- Glob
|
||||||
- Grep
|
- Grep
|
||||||
---
|
---
|
||||||
|
|
||||||
# /epf-bsp-init — Регистрация обработки в БСП
|
# /epf-bsp-init — Регистрация обработки в БСП
|
||||||
|
|
||||||
Добавляет в модуль объекта обработки функцию `СведенияОВнешнейОбработке()`, необходимую для регистрации в подсистеме «Дополнительные отчёты и обработки» БСП.
|
Добавляет в модуль объекта обработки функцию `СведенияОВнешнейОбработке()`, необходимую для регистрации в подсистеме «Дополнительные отчёты и обработки» БСП.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/epf-bsp-init <ProcessorName> <Вид> [Назначение...]
|
/epf-bsp-init <ProcessorName> <Вид> [Назначение...]
|
||||||
```
|
```
|
||||||
|
|
||||||
| Параметр | Обязательный | По умолчанию | Описание |
|
| Параметр | Обязательный | По умолчанию | Описание |
|
||||||
|---------------|:------------:|--------------|---------------------------------------------------------|
|
|---------------|:------------:|--------------|---------------------------------------------------------|
|
||||||
| ProcessorName | да | — | Имя обработки (должна быть создана через `/epf-init`) |
|
| ProcessorName | да | — | Имя обработки (должна быть создана через `/epf-init`) |
|
||||||
| Вид | да | — | Вид обработки (см. маппинг ниже) |
|
| Вид | да | — | Вид обработки (см. маппинг ниже) |
|
||||||
| Назначение | * | — | Объекты метаданных для назначаемых видов |
|
| Назначение | * | — | Объекты метаданных для назначаемых видов |
|
||||||
| SrcDir | нет | `src` | Каталог исходников |
|
| SrcDir | нет | `src` | Каталог исходников |
|
||||||
|
|
||||||
\* Назначение обязательно для видов: ЗаполнениеОбъекта, Отчет, ПечатнаяФорма, СозданиеСвязанныхОбъектов.
|
\* Назначение обязательно для видов: ЗаполнениеОбъекта, Отчет, ПечатнаяФорма, СозданиеСвязанныхОбъектов.
|
||||||
|
|
||||||
## Маппинг вида обработки
|
## Маппинг вида обработки
|
||||||
|
|
||||||
Пользователь может указать вид в свободной форме. Определи нужный по контексту:
|
Пользователь может указать вид в свободной форме. Определи нужный по контексту:
|
||||||
|
|
||||||
| Пользователь пишет | Вид | API-метод |
|
| Пользователь пишет | Вид | API-метод |
|
||||||
|-------------------------------------------|----------------------------|----------------------------------------------|
|
|-------------------------------------------|----------------------------|----------------------------------------------|
|
||||||
| доп обработка, обработка, глобальная | ДополнительнаяОбработка | `ВидОбработкиДополнительнаяОбработка()` |
|
| доп обработка, обработка, глобальная | ДополнительнаяОбработка | `ВидОбработкиДополнительнаяОбработка()` |
|
||||||
| доп отчёт, глобальный отчёт | ДополнительныйОтчет | `ВидОбработкиДополнительныйОтчет()` |
|
| доп отчёт, глобальный отчёт | ДополнительныйОтчет | `ВидОбработкиДополнительныйОтчет()` |
|
||||||
| заполнение, заполнить | ЗаполнениеОбъекта | `ВидОбработкиЗаполнениеОбъекта()` |
|
| заполнение, заполнить | ЗаполнениеОбъекта | `ВидОбработкиЗаполнениеОбъекта()` |
|
||||||
| отчёт (назначаемый, для объекта) | Отчет | `ВидОбработкиОтчет()` |
|
| отчёт (назначаемый, для объекта) | Отчет | `ВидОбработкиОтчет()` |
|
||||||
| печатная форма, печать | ПечатнаяФорма | `ВидОбработкиПечатнаяФорма()` |
|
| печатная форма, печать | ПечатнаяФорма | `ВидОбработкиПечатнаяФорма()` |
|
||||||
| создание связанных объектов | СозданиеСвязанныхОбъектов | `ВидОбработкиСозданиеСвязанныхОбъектов()` |
|
| создание связанных объектов | СозданиеСвязанныхОбъектов | `ВидОбработкиСозданиеСвязанныхОбъектов()` |
|
||||||
|
|
||||||
## Тип команды по умолчанию
|
## Тип команды по умолчанию
|
||||||
|
|
||||||
| Вид | ТипКоманды по умолчанию |
|
| Вид | ТипКоманды по умолчанию |
|
||||||
|----------------------------|-------------------------------------------|
|
|----------------------------|-------------------------------------------|
|
||||||
| ДополнительнаяОбработка | `ТипКомандыОткрытиеФормы()` |
|
| ДополнительнаяОбработка | `ТипКомандыОткрытиеФормы()` |
|
||||||
| ДополнительныйОтчет | `ТипКомандыОткрытиеФормы()` |
|
| ДополнительныйОтчет | `ТипКомандыОткрытиеФормы()` |
|
||||||
| ЗаполнениеОбъекта | `ТипКомандыВызовСерверногоМетода()` |
|
| ЗаполнениеОбъекта | `ТипКомандыВызовСерверногоМетода()` |
|
||||||
| Отчет | `ТипКомандыОткрытиеФормы()` |
|
| Отчет | `ТипКомандыОткрытиеФормы()` |
|
||||||
| ПечатнаяФорма | `ТипКомандыВызовСерверногоМетода()` |
|
| ПечатнаяФорма | `ТипКомандыВызовСерверногоМетода()` |
|
||||||
| СозданиеСвязанныхОбъектов | `ТипКомандыВызовСерверногоМетода()` |
|
| СозданиеСвязанныхОбъектов | `ТипКомандыВызовСерверногоМетода()` |
|
||||||
|
|
||||||
## Шаблон: СведенияОВнешнейОбработке
|
## Шаблон: СведенияОВнешнейОбработке
|
||||||
|
|
||||||
Базовый шаблон — одинаковый для всех видов, отличаются только вызовы API-методов и условные секции.
|
Базовый шаблон — одинаковый для всех видов, отличаются только вызовы API-методов и условные секции.
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
Функция СведенияОВнешнейОбработке() Экспорт
|
Функция СведенияОВнешнейОбработке() Экспорт
|
||||||
|
|
||||||
МетаданныеОбработки = Метаданные();
|
МетаданныеОбработки = Метаданные();
|
||||||
|
|
||||||
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
|
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
|
||||||
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.{{ВидОбработки}};
|
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.{{ВидОбработки}};
|
||||||
ПараметрыРегистрации.Версия = "1.0";
|
ПараметрыРегистрации.Версия = "1.0";
|
||||||
|
|
||||||
{{СЕКЦИЯ_НАЗНАЧЕНИЕ}}
|
{{СЕКЦИЯ_НАЗНАЧЕНИЕ}}
|
||||||
|
|
||||||
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
|
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
|
||||||
НоваяКоманда.Представление = МетаданныеОбработки.Представление();
|
НоваяКоманда.Представление = МетаданныеОбработки.Представление();
|
||||||
НоваяКоманда.Идентификатор = МетаданныеОбработки.Имя;
|
НоваяКоманда.Идентификатор = МетаданныеОбработки.Имя;
|
||||||
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.{{ТипКоманды}};
|
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.{{ТипКоманды}};
|
||||||
НоваяКоманда.ПоказыватьОповещение = Ложь;
|
НоваяКоманда.ПоказыватьОповещение = Ложь;
|
||||||
{{СЕКЦИЯ_МОДИФИКАТОР}}
|
{{СЕКЦИЯ_МОДИФИКАТОР}}
|
||||||
|
|
||||||
Возврат ПараметрыРегистрации;
|
Возврат ПараметрыРегистрации;
|
||||||
|
|
||||||
КонецФункции
|
КонецФункции
|
||||||
```
|
```
|
||||||
|
|
||||||
### Подстановки
|
### Подстановки
|
||||||
|
|
||||||
- `{{ВидОбработки}}` — API-метод из таблицы маппинга вида
|
- `{{ВидОбработки}}` — API-метод из таблицы маппинга вида
|
||||||
- `{{ТипКоманды}}` — API-метод из таблицы типа команды по умолчанию
|
- `{{ТипКоманды}}` — API-метод из таблицы типа команды по умолчанию
|
||||||
|
|
||||||
### Условные секции
|
### Условные секции
|
||||||
|
|
||||||
**`{{СЕКЦИЯ_НАЗНАЧЕНИЕ}}`** — только для назначаемых видов (ЗаполнениеОбъекта, Отчет, ПечатнаяФорма, СозданиеСвязанныхОбъектов). Одна строка на каждый объект:
|
**`{{СЕКЦИЯ_НАЗНАЧЕНИЕ}}`** — только для назначаемых видов (ЗаполнениеОбъекта, Отчет, ПечатнаяФорма, СозданиеСвязанныхОбъектов). Одна строка на каждый объект:
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
ПараметрыРегистрации.Назначение.Добавить("Документ.СчетНаОплату");
|
ПараметрыРегистрации.Назначение.Добавить("Документ.СчетНаОплату");
|
||||||
```
|
```
|
||||||
|
|
||||||
Формат имени объекта: `ИмяКлассаОбъектаМетаданного.ИмяОбъекта` (например `Документ.СчетНаОплату`, `Справочник.Контрагенты`).
|
Формат имени объекта: `ИмяКлассаОбъектаМетаданного.ИмяОбъекта` (например `Документ.СчетНаОплату`, `Справочник.Контрагенты`).
|
||||||
|
|
||||||
Для глобальных видов (ДополнительнаяОбработка, ДополнительныйОтчет) — секция не нужна, удалить вместе с пустой строкой.
|
Для глобальных видов (ДополнительнаяОбработка, ДополнительныйОтчет) — секция не нужна, удалить вместе с пустой строкой.
|
||||||
|
|
||||||
**`{{СЕКЦИЯ_МОДИФИКАТОР}}`** — только для ПечатнаяФорма:
|
**`{{СЕКЦИЯ_МОДИФИКАТОР}}`** — только для ПечатнаяФорма:
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
НоваяКоманда.Модификатор = "ПечатьMXL";
|
НоваяКоманда.Модификатор = "ПечатьMXL";
|
||||||
```
|
```
|
||||||
|
|
||||||
Для остальных видов — удалить вместе с пустой строкой.
|
Для остальных видов — удалить вместе с пустой строкой.
|
||||||
|
|
||||||
## Шаблоны серверных обработчиков
|
## Шаблоны серверных обработчиков
|
||||||
|
|
||||||
Для видов с типом команды `ВызовСерверногоМетода` добавь соответствующую процедуру-обработчик в ту же область `ПрограммныйИнтерфейс`, после `СведенияОВнешнейОбработке`.
|
Для видов с типом команды `ВызовСерверногоМетода` добавь соответствующую процедуру-обработчик в ту же область `ПрограммныйИнтерфейс`, после `СведенияОВнешнейОбработке`.
|
||||||
|
|
||||||
### Для ЗаполнениеОбъекта / СозданиеСвязанныхОбъектов
|
### Для ЗаполнениеОбъекта / СозданиеСвязанныхОбъектов
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения, ПараметрыВыполненияКоманды) Экспорт
|
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения, ПараметрыВыполненияКоманды) Экспорт
|
||||||
|
|
||||||
// TODO: Реализация
|
// TODO: Реализация
|
||||||
|
|
||||||
КонецПроцедуры
|
КонецПроцедуры
|
||||||
```
|
```
|
||||||
|
|
||||||
### Для ПечатнаяФорма
|
### Для ПечатнаяФорма
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
|
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
|
||||||
|
|
||||||
// TODO: Реализация
|
// TODO: Реализация
|
||||||
|
|
||||||
КонецПроцедуры
|
КонецПроцедуры
|
||||||
```
|
```
|
||||||
|
|
||||||
### Для ДополнительнаяОбработка / ДополнительныйОтчет (с ВызовСерверногоМетода)
|
### Для ДополнительнаяОбработка / ДополнительныйОтчет (с ВызовСерверногоМетода)
|
||||||
|
|
||||||
Если пользователь явно выбрал серверный метод вместо открытия формы:
|
Если пользователь явно выбрал серверный метод вместо открытия формы:
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполненияКоманды) Экспорт
|
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполненияКоманды) Экспорт
|
||||||
|
|
||||||
// TODO: Реализация
|
// TODO: Реализация
|
||||||
|
|
||||||
КонецПроцедуры
|
КонецПроцедуры
|
||||||
```
|
```
|
||||||
|
|
||||||
Обрати внимание: у глобальных обработок нет параметра `ОбъектыНазначения`.
|
Обрати внимание: у глобальных обработок нет параметра `ОбъектыНазначения`.
|
||||||
|
|
||||||
## Инструкции
|
## Инструкции
|
||||||
|
|
||||||
1. Найди `ObjectModule.bsl` через Glob: `src/{{ProcessorName}}/Ext/ObjectModule.bsl`
|
1. Найди `ObjectModule.bsl` через Glob: `src/{{ProcessorName}}/Ext/ObjectModule.bsl`
|
||||||
2. Прочитай файл
|
2. Прочитай файл
|
||||||
3. Если `СведенияОВнешнейОбработке` уже есть — сообщи пользователю и не дублируй
|
3. Если `СведенияОВнешнейОбработке` уже есть — сообщи пользователю и не дублируй
|
||||||
4. Если файл не найден — предложи сначала вызвать `/epf-init`
|
4. Если файл не найден — предложи сначала вызвать `/epf-init`
|
||||||
5. Найди область `#Область ПрограммныйИнтерфейс` ... `#КонецОбласти`
|
5. Найди область `#Область ПрограммныйИнтерфейс` ... `#КонецОбласти`
|
||||||
6. Вставь функцию `СведенияОВнешнейОбработке()` внутрь этой области
|
6. Вставь функцию `СведенияОВнешнейОбработке()` внутрь этой области
|
||||||
7. Если вид требует серверный обработчик — вставь его тоже в эту область, после функции
|
7. Если вид требует серверный обработчик — вставь его тоже в эту область, после функции
|
||||||
8. Используй табы для отступов (как в исходном файле)
|
8. Используй табы для отступов (как в исходном файле)
|
||||||
|
|
||||||
## Пример
|
## Пример
|
||||||
|
|
||||||
Пользователь: `/epf-bsp-init МояОбработка печатная форма для Документ.СчетНаОплату`
|
Пользователь: `/epf-bsp-init МояОбработка печатная форма для Документ.СчетНаОплату`
|
||||||
|
|
||||||
Результат в `ObjectModule.bsl`:
|
Результат в `ObjectModule.bsl`:
|
||||||
|
|
||||||
```bsl
|
```bsl
|
||||||
#Область ОписаниеПеременных
|
#Область ОписаниеПеременных
|
||||||
|
|
||||||
#КонецОбласти
|
#КонецОбласти
|
||||||
|
|
||||||
#Область ПрограммныйИнтерфейс
|
#Область ПрограммныйИнтерфейс
|
||||||
|
|
||||||
Функция СведенияОВнешнейОбработке() Экспорт
|
Функция СведенияОВнешнейОбработке() Экспорт
|
||||||
|
|
||||||
МетаданныеОбработки = Метаданные();
|
МетаданныеОбработки = Метаданные();
|
||||||
|
|
||||||
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
|
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
|
||||||
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиПечатнаяФорма();
|
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиПечатнаяФорма();
|
||||||
ПараметрыРегистрации.Версия = "1.0";
|
ПараметрыРегистрации.Версия = "1.0";
|
||||||
|
|
||||||
ПараметрыРегистрации.Назначение.Добавить("Документ.СчетНаОплату");
|
ПараметрыРегистрации.Назначение.Добавить("Документ.СчетНаОплату");
|
||||||
|
|
||||||
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
|
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
|
||||||
НоваяКоманда.Представление = МетаданныеОбработки.Представление();
|
НоваяКоманда.Представление = МетаданныеОбработки.Представление();
|
||||||
НоваяКоманда.Идентификатор = МетаданныеОбработки.Имя;
|
НоваяКоманда.Идентификатор = МетаданныеОбработки.Имя;
|
||||||
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода();
|
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода();
|
||||||
НоваяКоманда.ПоказыватьОповещение = Ложь;
|
НоваяКоманда.ПоказыватьОповещение = Ложь;
|
||||||
НоваяКоманда.Модификатор = "ПечатьMXL";
|
НоваяКоманда.Модификатор = "ПечатьMXL";
|
||||||
|
|
||||||
Возврат ПараметрыРегистрации;
|
Возврат ПараметрыРегистрации;
|
||||||
|
|
||||||
КонецФункции
|
КонецФункции
|
||||||
|
|
||||||
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
|
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
|
||||||
|
|
||||||
// TODO: Реализация
|
// TODO: Реализация
|
||||||
|
|
||||||
КонецПроцедуры
|
КонецПроцедуры
|
||||||
|
|
||||||
#КонецОбласти
|
#КонецОбласти
|
||||||
|
|
||||||
#Область СлужебныеПроцедурыИФункции
|
#Область СлужебныеПроцедурыИФункции
|
||||||
|
|
||||||
#КонецОбласти
|
#КонецОбласти
|
||||||
```
|
```
|
||||||
|
|
||||||
## Дальнейшие шаги
|
## Дальнейшие шаги
|
||||||
|
|
||||||
- Добавить ещё команду: `/epf-bsp-add-command`
|
- Добавить ещё команду: `/epf-bsp-add-command`
|
||||||
- Добавить форму: `/form-add`
|
- Добавить форму: `/form-add`
|
||||||
- Добавить макет: `/template-add`
|
- Добавить макет: `/template-add`
|
||||||
- Собрать EPF: `/epf-build`
|
- Собрать EPF: `/epf-build`
|
||||||
|
|||||||
@@ -1,69 +1,69 @@
|
|||||||
---
|
---
|
||||||
name: epf-build
|
name: epf-build
|
||||||
description: Собрать внешнюю обработку 1С (EPF/ERF) из XML-исходников. Используй когда пользователь просит собрать, скомпилировать обработку или получить EPF/ERF файл из исходников
|
description: Собрать внешнюю обработку 1С (EPF/ERF) из XML-исходников. Используй когда пользователь просит собрать, скомпилировать обработку или получить EPF/ERF файл из исходников
|
||||||
argument-hint: <ProcessorName>
|
argument-hint: <ProcessorName>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
- Grep
|
- Grep
|
||||||
---
|
---
|
||||||
|
|
||||||
# /epf-build — Сборка обработки
|
# /epf-build — Сборка обработки
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/epf-build <ProcessorName> [SrcDir] [OutDir]
|
/epf-build <ProcessorName> [SrcDir] [OutDir]
|
||||||
```
|
```
|
||||||
|
|
||||||
| Параметр | Обязательный | По умолчанию | Описание |
|
| Параметр | Обязательный | По умолчанию | Описание |
|
||||||
|---------------|:------------:|--------------|--------------------------------------|
|
|---------------|:------------:|--------------|--------------------------------------|
|
||||||
| ProcessorName | да | — | Имя обработки (имя корневого XML) |
|
| ProcessorName | да | — | Имя обработки (имя корневого XML) |
|
||||||
| SrcDir | нет | `src` | Каталог исходников |
|
| SrcDir | нет | `src` | Каталог исходников |
|
||||||
| OutDir | нет | `build` | Каталог для результата |
|
| OutDir | нет | `build` | Каталог для результата |
|
||||||
|
|
||||||
## Параметры подключения (опционально)
|
## Параметры подключения (опционально)
|
||||||
|
|
||||||
Предпочтительно использовать конкретную базу — это надёжнее и не требует создания временной базы.
|
Предпочтительно использовать конкретную базу — это надёжнее и не требует создания временной базы.
|
||||||
|
|
||||||
1. Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` и разреши базу:
|
1. Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` и разреши базу:
|
||||||
2. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
2. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
||||||
3. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
3. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
||||||
4. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
4. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
||||||
5. Если ветка не совпала — используй `default`
|
5. Если ветка не совпала — используй `default`
|
||||||
6. Если `.v8-project.json` нет или база не найдена — не указывай параметры подключения: скрипт автоматически создаст временную базу. Для EPF со ссылочными типами (CatalogRef, DocumentRef и т.д.) генерируются заглушки метаданных. Временная база удаляется после сборки.
|
6. Если `.v8-project.json` нет или база не найдена — не указывай параметры подключения: скрипт автоматически создаст временную базу. Для EPF со ссылочными типами (CatalogRef, DocumentRef и т.д.) генерируются заглушки метаданных. Временная база удаляется после сборки.
|
||||||
|
|
||||||
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
||||||
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" <параметры>
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|----------|:------------:|----------|
|
|----------|:------------:|----------|
|
||||||
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
||||||
| `-InfoBasePath <путь>` | * | Файловая база |
|
| `-InfoBasePath <путь>` | * | Файловая база |
|
||||||
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
||||||
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
||||||
| `-UserName <имя>` | нет | Имя пользователя |
|
| `-UserName <имя>` | нет | Имя пользователя |
|
||||||
| `-Password <пароль>` | нет | Пароль |
|
| `-Password <пароль>` | нет | Пароль |
|
||||||
| `-SourceFile <путь>` | да | Путь к корневому XML-файлу исходников |
|
| `-SourceFile <путь>` | да | Путь к корневому XML-файлу исходников |
|
||||||
| `-OutputFile <путь>` | да | Путь к выходному EPF/ERF-файлу |
|
| `-OutputFile <путь>` | да | Путь к выходному EPF/ERF-файлу |
|
||||||
|
|
||||||
> `*` — опционально. Если не указано — автоматически создаётся временная база со заглушками метаданных
|
> `*` — опционально. Если не указано — автоматически создаётся временная база со заглушками метаданных
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Сборка обработки (файловая база)
|
# Сборка обработки (файловая база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" -InfoBasePath "C:\Bases\MyDB" -SourceFile "src/МояОбработка.xml" -OutputFile "build/МояОбработка.epf"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" -InfoBasePath "C:\Bases\MyDB" -SourceFile "src/МояОбработка.xml" -OutputFile "build/МояОбработка.epf"
|
||||||
|
|
||||||
# Серверная база
|
# Серверная база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -SourceFile "src/МояОбработка.xml" -OutputFile "build/МояОбработка.epf"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -SourceFile "src/МояОбработка.xml" -OutputFile "build/МояОбработка.epf"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,225 +1,225 @@
|
|||||||
# epf-build v1.4 — Build external data processor or report (EPF/ERF) from XML sources
|
# epf-build v1.4 — Build external data processor or report (EPF/ERF) from XML sources
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Сборка внешней обработки/отчёта 1С из XML-исходников
|
Сборка внешней обработки/отчёта 1С из XML-исходников
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Собирает EPF/ERF-файл из XML-исходников с помощью платформы 1С.
|
Собирает EPF/ERF-файл из XML-исходников с помощью платформы 1С.
|
||||||
Общий скрипт для epf-build и erf-build.
|
Общий скрипт для epf-build и erf-build.
|
||||||
|
|
||||||
.PARAMETER V8Path
|
.PARAMETER V8Path
|
||||||
Путь к каталогу bin платформы или к 1cv8.exe
|
Путь к каталогу bin платформы или к 1cv8.exe
|
||||||
|
|
||||||
.PARAMETER InfoBasePath
|
.PARAMETER InfoBasePath
|
||||||
Путь к файловой информационной базе
|
Путь к файловой информационной базе
|
||||||
|
|
||||||
.PARAMETER InfoBaseServer
|
.PARAMETER InfoBaseServer
|
||||||
Сервер 1С (для серверной базы)
|
Сервер 1С (для серверной базы)
|
||||||
|
|
||||||
.PARAMETER InfoBaseRef
|
.PARAMETER InfoBaseRef
|
||||||
Имя базы на сервере
|
Имя базы на сервере
|
||||||
|
|
||||||
.PARAMETER UserName
|
.PARAMETER UserName
|
||||||
Имя пользователя 1С
|
Имя пользователя 1С
|
||||||
|
|
||||||
.PARAMETER Password
|
.PARAMETER Password
|
||||||
Пароль пользователя
|
Пароль пользователя
|
||||||
|
|
||||||
.PARAMETER SourceFile
|
.PARAMETER SourceFile
|
||||||
Путь к корневому XML-файлу исходников
|
Путь к корневому XML-файлу исходников
|
||||||
|
|
||||||
.PARAMETER OutputFile
|
.PARAMETER OutputFile
|
||||||
Путь к выходному EPF/ERF-файлу
|
Путь к выходному EPF/ERF-файлу
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\epf-build.ps1 -InfoBasePath "C:\Bases\MyDB" -SourceFile "src\МояОбработка.xml" -OutputFile "build\МояОбработка.epf"
|
.\epf-build.ps1 -InfoBasePath "C:\Bases\MyDB" -SourceFile "src\МояОбработка.xml" -OutputFile "build\МояОбработка.epf"
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\epf-build.ps1 -InfoBasePath "C:\Bases\MyDB" -SourceFile "src\МойОтчёт.xml" -OutputFile "build\МойОтчёт.erf"
|
.\epf-build.ps1 -InfoBasePath "C:\Bases\MyDB" -SourceFile "src\МойОтчёт.xml" -OutputFile "build\МойОтчёт.erf"
|
||||||
#>
|
#>
|
||||||
|
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$V8Path,
|
[string]$V8Path,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBasePath,
|
[string]$InfoBasePath,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseServer,
|
[string]$InfoBaseServer,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseRef,
|
[string]$InfoBaseRef,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$UserName,
|
[string]$UserName,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Password,
|
[string]$Password,
|
||||||
|
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
[string]$SourceFile,
|
[string]$SourceFile,
|
||||||
|
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
[string]$OutputFile
|
[string]$OutputFile
|
||||||
)
|
)
|
||||||
|
|
||||||
$OutputEncoding = [System.Text.Encoding]::UTF8
|
$OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Resolve V8Path ---
|
# --- Resolve V8Path ---
|
||||||
function Find-ProjectV8Path {
|
function Find-ProjectV8Path {
|
||||||
$dir = (Get-Location).Path
|
$dir = (Get-Location).Path
|
||||||
while ($dir) {
|
while ($dir) {
|
||||||
$pf = Join-Path $dir ".v8-project.json"
|
$pf = Join-Path $dir ".v8-project.json"
|
||||||
if (Test-Path $pf) {
|
if (Test-Path $pf) {
|
||||||
try {
|
try {
|
||||||
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||||
if ($j.v8path) { return [string]$j.v8path }
|
if ($j.v8path) { return [string]$j.v8path }
|
||||||
} catch {}
|
} catch {}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
$parent = Split-Path $dir -Parent
|
$parent = Split-Path $dir -Parent
|
||||||
if (-not $parent -or $parent -eq $dir) { break }
|
if (-not $parent -or $parent -eq $dir) { break }
|
||||||
$dir = $parent
|
$dir = $parent
|
||||||
}
|
}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$V8Path = Find-ProjectV8Path
|
$V8Path = Find-ProjectV8Path
|
||||||
}
|
}
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
||||||
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
||||||
Select-Object -First 1
|
Select-Object -First 1
|
||||||
if ($found) {
|
if ($found) {
|
||||||
$V8Path = $found.FullName
|
$V8Path = $found.FullName
|
||||||
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Test-Path $V8Path -PathType Container) {
|
if (Test-Path $V8Path -PathType Container) {
|
||||||
$V8Path = Join-Path $V8Path "1cv8.exe"
|
$V8Path = Join-Path $V8Path "1cv8.exe"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $V8Path)) {
|
if (-not (Test-Path $V8Path)) {
|
||||||
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Detect engine (ibcmd vs 1cv8) by exe name ---
|
# --- Detect engine (ibcmd vs 1cv8) by exe name ---
|
||||||
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
||||||
if ($engine -eq "ibcmd" -and $InfoBaseServer -and $InfoBaseRef) {
|
if ($engine -eq "ibcmd" -and $InfoBaseServer -and $InfoBaseRef) {
|
||||||
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath or omit for stub)" -ForegroundColor Red
|
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath or omit for stub)" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Auto-create stub database if no connection specified ---
|
# --- Auto-create stub database if no connection specified ---
|
||||||
$autoCreatedBase = $null
|
$autoCreatedBase = $null
|
||||||
if (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
if (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
||||||
$sourceDir = Split-Path $SourceFile -Parent
|
$sourceDir = Split-Path $SourceFile -Parent
|
||||||
$autoBasePath = Join-Path $env:TEMP "epf_stub_db_$(Get-Random)"
|
$autoBasePath = Join-Path $env:TEMP "epf_stub_db_$(Get-Random)"
|
||||||
$stubScript = Join-Path $PSScriptRoot "stub-db-create.ps1"
|
$stubScript = Join-Path $PSScriptRoot "stub-db-create.ps1"
|
||||||
Write-Host "No database specified. Creating temporary stub database..."
|
Write-Host "No database specified. Creating temporary stub database..."
|
||||||
$stubArgs = "-SourceDir `"$sourceDir`" -V8Path `"$V8Path`" -TempBasePath `"$autoBasePath`""
|
$stubArgs = "-SourceDir `"$sourceDir`" -V8Path `"$V8Path`" -TempBasePath `"$autoBasePath`""
|
||||||
$stubProc = Start-Process -FilePath "powershell.exe" -ArgumentList "-NoProfile -File `"$stubScript`" $stubArgs" -NoNewWindow -Wait -PassThru
|
$stubProc = Start-Process -FilePath "powershell.exe" -ArgumentList "-NoProfile -File `"$stubScript`" $stubArgs" -NoNewWindow -Wait -PassThru
|
||||||
if ($stubProc.ExitCode -ne 0) {
|
if ($stubProc.ExitCode -ne 0) {
|
||||||
Write-Host "Error: failed to create stub database" -ForegroundColor Red
|
Write-Host "Error: failed to create stub database" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
$InfoBasePath = $autoBasePath
|
$InfoBasePath = $autoBasePath
|
||||||
$autoCreatedBase = $autoBasePath
|
$autoCreatedBase = $autoBasePath
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Validate source file ---
|
# --- Validate source file ---
|
||||||
if (-not (Test-Path $SourceFile)) {
|
if (-not (Test-Path $SourceFile)) {
|
||||||
Write-Host "Error: source file not found: $SourceFile" -ForegroundColor Red
|
Write-Host "Error: source file not found: $SourceFile" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Ensure output directory exists ---
|
# --- Ensure output directory exists ---
|
||||||
$outDir = Split-Path $OutputFile -Parent
|
$outDir = Split-Path $OutputFile -Parent
|
||||||
if ($outDir -and -not (Test-Path $outDir)) {
|
if ($outDir -and -not (Test-Path $outDir)) {
|
||||||
New-Item -ItemType Directory -Path $outDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $outDir -Force | Out-Null
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Temp dir ---
|
# --- Temp dir ---
|
||||||
$tempDir = Join-Path $env:TEMP "epf_build_$(Get-Random)"
|
$tempDir = Join-Path $env:TEMP "epf_build_$(Get-Random)"
|
||||||
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($engine -eq "ibcmd") {
|
if ($engine -eq "ibcmd") {
|
||||||
# --- ibcmd branch: build EPF/ERF via config import --out ---
|
# --- ibcmd branch: build EPF/ERF via config import --out ---
|
||||||
$srcDir = Split-Path $SourceFile -Parent
|
$srcDir = Split-Path $SourceFile -Parent
|
||||||
$arguments = @("infobase", "config", "import", "$srcDir", "--out=$OutputFile", "--db-path=$InfoBasePath")
|
$arguments = @("infobase", "config", "import", "$srcDir", "--out=$OutputFile", "--db-path=$InfoBasePath")
|
||||||
if ($UserName) { $arguments += "--user=$UserName" }
|
if ($UserName) { $arguments += "--user=$UserName" }
|
||||||
if ($Password) { $arguments += "--password=$Password" }
|
if ($Password) { $arguments += "--password=$Password" }
|
||||||
$arguments += "--data=$tempDir"
|
$arguments += "--data=$tempDir"
|
||||||
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
||||||
$output = & $V8Path @arguments 2>&1
|
$output = & $V8Path @arguments 2>&1
|
||||||
$exitCode = $LASTEXITCODE
|
$exitCode = $LASTEXITCODE
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
Write-Host "External data processor/report built successfully: $OutputFile" -ForegroundColor Green
|
Write-Host "External data processor/report built successfully: $OutputFile" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error building external data processor/report (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error building external data processor/report (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
if ($output) { Write-Host ($output | Out-String) }
|
if ($output) { Write-Host ($output | Out-String) }
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 1cv8 branch ---
|
# --- 1cv8 branch ---
|
||||||
# --- Build arguments ---
|
# --- Build arguments ---
|
||||||
$arguments = @("DESIGNER")
|
$arguments = @("DESIGNER")
|
||||||
|
|
||||||
if ($InfoBaseServer -and $InfoBaseRef) {
|
if ($InfoBaseServer -and $InfoBaseRef) {
|
||||||
$arguments += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
|
$arguments += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
|
||||||
} else {
|
} else {
|
||||||
$arguments += "/F", "`"$InfoBasePath`""
|
$arguments += "/F", "`"$InfoBasePath`""
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($UserName) { $arguments += "/N`"$UserName`"" }
|
if ($UserName) { $arguments += "/N`"$UserName`"" }
|
||||||
if ($Password) { $arguments += "/P`"$Password`"" }
|
if ($Password) { $arguments += "/P`"$Password`"" }
|
||||||
|
|
||||||
$arguments += "/LoadExternalDataProcessorOrReportFromFiles", "`"$SourceFile`"", "`"$OutputFile`""
|
$arguments += "/LoadExternalDataProcessorOrReportFromFiles", "`"$SourceFile`"", "`"$OutputFile`""
|
||||||
|
|
||||||
# --- Output ---
|
# --- Output ---
|
||||||
$outFile = Join-Path $tempDir "build_log.txt"
|
$outFile = Join-Path $tempDir "build_log.txt"
|
||||||
$arguments += "/Out", "`"$outFile`""
|
$arguments += "/Out", "`"$outFile`""
|
||||||
$arguments += "/DisableStartupDialogs"
|
$arguments += "/DisableStartupDialogs"
|
||||||
|
|
||||||
# --- Execute ---
|
# --- Execute ---
|
||||||
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
||||||
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
||||||
$exitCode = $process.ExitCode
|
$exitCode = $process.ExitCode
|
||||||
|
|
||||||
# --- Result ---
|
# --- Result ---
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
Write-Host "Build completed successfully: $OutputFile" -ForegroundColor Green
|
Write-Host "Build completed successfully: $OutputFile" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error building (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error building (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Test-Path $outFile) {
|
if (Test-Path $outFile) {
|
||||||
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
||||||
if ($logContent) {
|
if ($logContent) {
|
||||||
Write-Host "--- Log ---"
|
Write-Host "--- Log ---"
|
||||||
Write-Host $logContent
|
Write-Host $logContent
|
||||||
Write-Host "--- End ---"
|
Write-Host "--- End ---"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (Test-Path $tempDir) {
|
if (Test-Path $tempDir) {
|
||||||
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
if ($autoCreatedBase -and (Test-Path $autoCreatedBase)) {
|
if ($autoCreatedBase -and (Test-Path $autoCreatedBase)) {
|
||||||
Remove-Item -Path $autoCreatedBase -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $autoCreatedBase -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,69 +1,69 @@
|
|||||||
---
|
---
|
||||||
name: epf-dump
|
name: epf-dump
|
||||||
description: Разобрать EPF-файл обработки 1С (EPF/ERF) в XML-исходники. Используй когда пользователь просит разобрать, декомпилировать обработку, получить исходники из EPF/ERF файла
|
description: Разобрать EPF-файл обработки 1С (EPF/ERF) в XML-исходники. Используй когда пользователь просит разобрать, декомпилировать обработку, получить исходники из EPF/ERF файла
|
||||||
argument-hint: <EpfFile>
|
argument-hint: <EpfFile>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
- Grep
|
- Grep
|
||||||
---
|
---
|
||||||
|
|
||||||
# /epf-dump — Разборка обработки
|
# /epf-dump — Разборка обработки
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/epf-dump <EpfFile> [OutDir]
|
/epf-dump <EpfFile> [OutDir]
|
||||||
```
|
```
|
||||||
|
|
||||||
| Параметр | Обязательный | По умолчанию | Описание |
|
| Параметр | Обязательный | По умолчанию | Описание |
|
||||||
|----------|:------------:|--------------|-------------------------------------|
|
|----------|:------------:|--------------|-------------------------------------|
|
||||||
| EpfFile | да | — | Путь к EPF-файлу |
|
| EpfFile | да | — | Путь к EPF-файлу |
|
||||||
| OutDir | нет | `src` | Каталог для выгрузки исходников |
|
| OutDir | нет | `src` | Каталог для выгрузки исходников |
|
||||||
|
|
||||||
## Параметры подключения (обязательно)
|
## Параметры подключения (обязательно)
|
||||||
|
|
||||||
Для разборки EPF/ERF требуется информационная база с конфигурацией. Без базы ссылочные типы безвозвратно теряются.
|
Для разборки EPF/ERF требуется информационная база с конфигурацией. Без базы ссылочные типы безвозвратно теряются.
|
||||||
|
|
||||||
1. Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` и разреши базу:
|
1. Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` и разреши базу:
|
||||||
2. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
2. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
||||||
3. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
3. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
||||||
4. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
4. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
||||||
5. Если ветка не совпала — используй `default`
|
5. Если ветка не совпала — используй `default`
|
||||||
6. Если `.v8-project.json` нет или база не найдена — **сообщи пользователю об ошибке**. Для dump база обязательна: в пустой базе ссылочные типы (CatalogRef, DocumentRef и т.д.) безвозвратно сбрасываются в строки. Предложи указать базу или зарегистрировать через `/db-list add`.
|
6. Если `.v8-project.json` нет или база не найдена — **сообщи пользователю об ошибке**. Для dump база обязательна: в пустой базе ссылочные типы (CatalogRef, DocumentRef и т.д.) безвозвратно сбрасываются в строки. Предложи указать базу или зарегистрировать через `/db-list add`.
|
||||||
|
|
||||||
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
||||||
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" <параметры>
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|----------|:------------:|----------|
|
|----------|:------------:|----------|
|
||||||
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
| `-V8Path <путь>` | нет | Каталог bin платформы, или полный путь к `1cv8.exe` / `ibcmd.exe` |
|
||||||
| `-InfoBasePath <путь>` | * | Файловая база |
|
| `-InfoBasePath <путь>` | * | Файловая база |
|
||||||
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
||||||
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
||||||
| `-UserName <имя>` | нет | Имя пользователя |
|
| `-UserName <имя>` | нет | Имя пользователя |
|
||||||
| `-Password <пароль>` | нет | Пароль |
|
| `-Password <пароль>` | нет | Пароль |
|
||||||
| `-InputFile <путь>` | да | Путь к EPF/ERF-файлу |
|
| `-InputFile <путь>` | да | Путь к EPF/ERF-файлу |
|
||||||
| `-OutputDir <путь>` | да | Каталог для выгрузки исходников |
|
| `-OutputDir <путь>` | да | Каталог для выгрузки исходников |
|
||||||
| `-Format <формат>` | нет | `Hierarchical` (по умолч.) / `Plain` |
|
| `-Format <формат>` | нет | `Hierarchical` (по умолч.) / `Plain` |
|
||||||
|
|
||||||
> `*` — обязательно хотя бы одно подключение. Без базы скрипт завершится с ошибкой (dump в пустой базе безвозвратно теряет ссылочные типы)
|
> `*` — обязательно хотя бы одно подключение. Без базы скрипт завершится с ошибкой (dump в пустой базе безвозвратно теряет ссылочные типы)
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Разборка обработки (файловая база)
|
# Разборка обработки (файловая база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" -InfoBasePath "C:\Bases\MyDB" -InputFile "build/МояОбработка.epf" -OutputDir "src"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" -InfoBasePath "C:\Bases\MyDB" -InputFile "build/МояОбработка.epf" -OutputDir "src"
|
||||||
|
|
||||||
# Серверная база
|
# Серверная база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -InputFile "build/МояОбработка.epf" -OutputDir "src"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -InputFile "build/МояОбработка.epf" -OutputDir "src"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,224 +1,224 @@
|
|||||||
# epf-dump v1.4 — Dump external data processor or report (EPF/ERF) to XML sources
|
# epf-dump v1.4 — Dump external data processor or report (EPF/ERF) to XML sources
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Разборка внешней обработки/отчёта 1С в XML-исходники
|
Разборка внешней обработки/отчёта 1С в XML-исходники
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Разбирает EPF/ERF-файл во XML-исходники с помощью платформы 1С.
|
Разбирает EPF/ERF-файл во XML-исходники с помощью платформы 1С.
|
||||||
Общий скрипт для epf-dump и erf-dump.
|
Общий скрипт для epf-dump и erf-dump.
|
||||||
|
|
||||||
.PARAMETER V8Path
|
.PARAMETER V8Path
|
||||||
Путь к каталогу bin платформы или к 1cv8.exe
|
Путь к каталогу bin платформы или к 1cv8.exe
|
||||||
|
|
||||||
.PARAMETER InfoBasePath
|
.PARAMETER InfoBasePath
|
||||||
Путь к файловой информационной базе
|
Путь к файловой информационной базе
|
||||||
|
|
||||||
.PARAMETER InfoBaseServer
|
.PARAMETER InfoBaseServer
|
||||||
Сервер 1С (для серверной базы)
|
Сервер 1С (для серверной базы)
|
||||||
|
|
||||||
.PARAMETER InfoBaseRef
|
.PARAMETER InfoBaseRef
|
||||||
Имя базы на сервере
|
Имя базы на сервере
|
||||||
|
|
||||||
.PARAMETER UserName
|
.PARAMETER UserName
|
||||||
Имя пользователя 1С
|
Имя пользователя 1С
|
||||||
|
|
||||||
.PARAMETER Password
|
.PARAMETER Password
|
||||||
Пароль пользователя
|
Пароль пользователя
|
||||||
|
|
||||||
.PARAMETER InputFile
|
.PARAMETER InputFile
|
||||||
Путь к EPF/ERF-файлу
|
Путь к EPF/ERF-файлу
|
||||||
|
|
||||||
.PARAMETER OutputDir
|
.PARAMETER OutputDir
|
||||||
Каталог для выгрузки исходников
|
Каталог для выгрузки исходников
|
||||||
|
|
||||||
.PARAMETER Format
|
.PARAMETER Format
|
||||||
Формат выгрузки: Hierarchical или Plain (по умолчанию Hierarchical)
|
Формат выгрузки: Hierarchical или Plain (по умолчанию Hierarchical)
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\epf-dump.ps1 -InfoBasePath "C:\Bases\MyDB" -InputFile "build\МояОбработка.epf" -OutputDir "src"
|
.\epf-dump.ps1 -InfoBasePath "C:\Bases\MyDB" -InputFile "build\МояОбработка.epf" -OutputDir "src"
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
.\epf-dump.ps1 -InfoBasePath "C:\Bases\MyDB" -InputFile "build\МойОтчёт.erf" -OutputDir "src"
|
.\epf-dump.ps1 -InfoBasePath "C:\Bases\MyDB" -InputFile "build\МойОтчёт.erf" -OutputDir "src"
|
||||||
#>
|
#>
|
||||||
|
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$V8Path,
|
[string]$V8Path,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBasePath,
|
[string]$InfoBasePath,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseServer,
|
[string]$InfoBaseServer,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$InfoBaseRef,
|
[string]$InfoBaseRef,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$UserName,
|
[string]$UserName,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[string]$Password,
|
[string]$Password,
|
||||||
|
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
[string]$InputFile,
|
[string]$InputFile,
|
||||||
|
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
[string]$OutputDir,
|
[string]$OutputDir,
|
||||||
|
|
||||||
[Parameter(Mandatory=$false)]
|
[Parameter(Mandatory=$false)]
|
||||||
[ValidateSet("Hierarchical", "Plain")]
|
[ValidateSet("Hierarchical", "Plain")]
|
||||||
[string]$Format = "Hierarchical"
|
[string]$Format = "Hierarchical"
|
||||||
)
|
)
|
||||||
|
|
||||||
$OutputEncoding = [System.Text.Encoding]::UTF8
|
$OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Resolve V8Path ---
|
# --- Resolve V8Path ---
|
||||||
function Find-ProjectV8Path {
|
function Find-ProjectV8Path {
|
||||||
$dir = (Get-Location).Path
|
$dir = (Get-Location).Path
|
||||||
while ($dir) {
|
while ($dir) {
|
||||||
$pf = Join-Path $dir ".v8-project.json"
|
$pf = Join-Path $dir ".v8-project.json"
|
||||||
if (Test-Path $pf) {
|
if (Test-Path $pf) {
|
||||||
try {
|
try {
|
||||||
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
$j = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||||
if ($j.v8path) { return [string]$j.v8path }
|
if ($j.v8path) { return [string]$j.v8path }
|
||||||
} catch {}
|
} catch {}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
$parent = Split-Path $dir -Parent
|
$parent = Split-Path $dir -Parent
|
||||||
if (-not $parent -or $parent -eq $dir) { break }
|
if (-not $parent -or $parent -eq $dir) { break }
|
||||||
$dir = $parent
|
$dir = $parent
|
||||||
}
|
}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$V8Path = Find-ProjectV8Path
|
$V8Path = Find-ProjectV8Path
|
||||||
}
|
}
|
||||||
if (-not $V8Path) {
|
if (-not $V8Path) {
|
||||||
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
$found = Get-ChildItem @("C:\Program Files\1cv8\*\bin\1cv8.exe", "C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") -ErrorAction SilentlyContinue |
|
||||||
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
Sort-Object { try { [version]$_.Directory.Parent.Name } catch { [version]"0.0" } } -Descending |
|
||||||
Select-Object -First 1
|
Select-Object -First 1
|
||||||
if ($found) {
|
if ($found) {
|
||||||
$V8Path = $found.FullName
|
$V8Path = $found.FullName
|
||||||
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Test-Path $V8Path -PathType Container) {
|
if (Test-Path $V8Path -PathType Container) {
|
||||||
$V8Path = Join-Path $V8Path "1cv8.exe"
|
$V8Path = Join-Path $V8Path "1cv8.exe"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $V8Path)) {
|
if (-not (Test-Path $V8Path)) {
|
||||||
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Validate database connection ---
|
# --- Validate database connection ---
|
||||||
if (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
if (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) {
|
||||||
Write-Host "Error: database connection required. Specify -InfoBasePath or -InfoBaseServer/-InfoBaseRef" -ForegroundColor Red
|
Write-Host "Error: database connection required. Specify -InfoBasePath or -InfoBaseServer/-InfoBaseRef" -ForegroundColor Red
|
||||||
Write-Host "Dump in an empty database loses reference types (CatalogRef, DocumentRef, etc.) irreversibly." -ForegroundColor Yellow
|
Write-Host "Dump in an empty database loses reference types (CatalogRef, DocumentRef, etc.) irreversibly." -ForegroundColor Yellow
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Detect engine (ibcmd vs 1cv8) by exe name ---
|
# --- Detect engine (ibcmd vs 1cv8) by exe name ---
|
||||||
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
$engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" }
|
||||||
if ($engine -eq "ibcmd") {
|
if ($engine -eq "ibcmd") {
|
||||||
if (-not $InfoBasePath) {
|
if (-not $InfoBasePath) {
|
||||||
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath)" -ForegroundColor Red
|
Write-Host "Error: ibcmd supports file infobases only (use -InfoBasePath)" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
if ($Format -eq "Plain") {
|
if ($Format -eq "Plain") {
|
||||||
Write-Host "Error: ibcmd config export supports hierarchical format only (use -Format Hierarchical or 1cv8)" -ForegroundColor Red
|
Write-Host "Error: ibcmd config export supports hierarchical format only (use -Format Hierarchical or 1cv8)" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Validate input file ---
|
# --- Validate input file ---
|
||||||
if (-not (Test-Path $InputFile)) {
|
if (-not (Test-Path $InputFile)) {
|
||||||
Write-Host "Error: input file not found: $InputFile" -ForegroundColor Red
|
Write-Host "Error: input file not found: $InputFile" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Ensure output directory exists ---
|
# --- Ensure output directory exists ---
|
||||||
if (-not (Test-Path $OutputDir)) {
|
if (-not (Test-Path $OutputDir)) {
|
||||||
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Temp dir ---
|
# --- Temp dir ---
|
||||||
$tempDir = Join-Path $env:TEMP "epf_dump_$(Get-Random)"
|
$tempDir = Join-Path $env:TEMP "epf_dump_$(Get-Random)"
|
||||||
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($engine -eq "ibcmd") {
|
if ($engine -eq "ibcmd") {
|
||||||
# --- ibcmd branch: dump EPF/ERF via config export --file ---
|
# --- ibcmd branch: dump EPF/ERF via config export --file ---
|
||||||
$arguments = @("infobase", "config", "export", "--file=$InputFile", "$OutputDir", "--db-path=$InfoBasePath")
|
$arguments = @("infobase", "config", "export", "--file=$InputFile", "$OutputDir", "--db-path=$InfoBasePath")
|
||||||
if ($UserName) { $arguments += "--user=$UserName" }
|
if ($UserName) { $arguments += "--user=$UserName" }
|
||||||
if ($Password) { $arguments += "--password=$Password" }
|
if ($Password) { $arguments += "--password=$Password" }
|
||||||
$arguments += "--data=$tempDir"
|
$arguments += "--data=$tempDir"
|
||||||
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
Write-Host "Running: ibcmd $($arguments -join ' ')"
|
||||||
$output = & $V8Path @arguments 2>&1
|
$output = & $V8Path @arguments 2>&1
|
||||||
$exitCode = $LASTEXITCODE
|
$exitCode = $LASTEXITCODE
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
Write-Host "External data processor/report dumped successfully to: $OutputDir" -ForegroundColor Green
|
Write-Host "External data processor/report dumped successfully to: $OutputDir" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error dumping external data processor/report (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error dumping external data processor/report (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
if ($output) { Write-Host ($output | Out-String) }
|
if ($output) { Write-Host ($output | Out-String) }
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 1cv8 branch ---
|
# --- 1cv8 branch ---
|
||||||
# --- Build arguments ---
|
# --- Build arguments ---
|
||||||
$arguments = @("DESIGNER")
|
$arguments = @("DESIGNER")
|
||||||
|
|
||||||
if ($InfoBaseServer -and $InfoBaseRef) {
|
if ($InfoBaseServer -and $InfoBaseRef) {
|
||||||
$arguments += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
|
$arguments += "/S", "`"$InfoBaseServer/$InfoBaseRef`""
|
||||||
} else {
|
} else {
|
||||||
$arguments += "/F", "`"$InfoBasePath`""
|
$arguments += "/F", "`"$InfoBasePath`""
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($UserName) { $arguments += "/N`"$UserName`"" }
|
if ($UserName) { $arguments += "/N`"$UserName`"" }
|
||||||
if ($Password) { $arguments += "/P`"$Password`"" }
|
if ($Password) { $arguments += "/P`"$Password`"" }
|
||||||
|
|
||||||
$arguments += "/DumpExternalDataProcessorOrReportToFiles", "`"$OutputDir`"", "`"$InputFile`""
|
$arguments += "/DumpExternalDataProcessorOrReportToFiles", "`"$OutputDir`"", "`"$InputFile`""
|
||||||
$arguments += "-Format", $Format
|
$arguments += "-Format", $Format
|
||||||
|
|
||||||
# --- Output ---
|
# --- Output ---
|
||||||
$outFile = Join-Path $tempDir "dump_log.txt"
|
$outFile = Join-Path $tempDir "dump_log.txt"
|
||||||
$arguments += "/Out", "`"$outFile`""
|
$arguments += "/Out", "`"$outFile`""
|
||||||
$arguments += "/DisableStartupDialogs"
|
$arguments += "/DisableStartupDialogs"
|
||||||
|
|
||||||
# --- Execute ---
|
# --- Execute ---
|
||||||
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
Write-Host "Running: 1cv8.exe $($arguments -join ' ')"
|
||||||
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
$process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru
|
||||||
$exitCode = $process.ExitCode
|
$exitCode = $process.ExitCode
|
||||||
|
|
||||||
# --- Result ---
|
# --- Result ---
|
||||||
if ($exitCode -eq 0) {
|
if ($exitCode -eq 0) {
|
||||||
Write-Host "Dump completed successfully to: $OutputDir" -ForegroundColor Green
|
Write-Host "Dump completed successfully to: $OutputDir" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "Error dumping (code: $exitCode)" -ForegroundColor Red
|
Write-Host "Error dumping (code: $exitCode)" -ForegroundColor Red
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Test-Path $outFile) {
|
if (Test-Path $outFile) {
|
||||||
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
$logContent = Get-Content $outFile -Raw -ErrorAction SilentlyContinue
|
||||||
if ($logContent) {
|
if ($logContent) {
|
||||||
Write-Host "--- Log ---"
|
Write-Host "--- Log ---"
|
||||||
Write-Host $logContent
|
Write-Host $logContent
|
||||||
Write-Host "--- End ---"
|
Write-Host "--- End ---"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit $exitCode
|
exit $exitCode
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (Test-Path $tempDir) {
|
if (Test-Path $tempDir) {
|
||||||
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +1,41 @@
|
|||||||
---
|
---
|
||||||
name: epf-init
|
name: epf-init
|
||||||
description: Создать пустую внешнюю обработку 1С (scaffold XML-исходников). Используй когда нужно создать новую внешнюю обработку с нуля
|
description: Создать пустую внешнюю обработку 1С (scaffold XML-исходников). Используй когда нужно создать новую внешнюю обработку с нуля
|
||||||
argument-hint: <Name> [Synonym]
|
argument-hint: <Name> [Synonym]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Write
|
- Write
|
||||||
- Edit
|
- Edit
|
||||||
- Glob
|
- Glob
|
||||||
- Grep
|
- Grep
|
||||||
---
|
---
|
||||||
|
|
||||||
# /epf-init — Создание новой обработки
|
# /epf-init — Создание новой обработки
|
||||||
|
|
||||||
Генерирует минимальный набор XML-исходников для внешней обработки 1С: корневой файл метаданных и каталог обработки.
|
Генерирует минимальный набор XML-исходников для внешней обработки 1С: корневой файл метаданных и каталог обработки.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/epf-init <Name> [Synonym] [SrcDir]
|
/epf-init <Name> [Synonym] [SrcDir]
|
||||||
```
|
```
|
||||||
|
|
||||||
| Параметр | Обязательный | По умолчанию | Описание |
|
| Параметр | Обязательный | По умолчанию | Описание |
|
||||||
|-----------|:------------:|--------------|-------------------------------------|
|
|-----------|:------------:|--------------|-------------------------------------|
|
||||||
| Name | да | — | Имя обработки (латиница/кириллица) |
|
| Name | да | — | Имя обработки (латиница/кириллица) |
|
||||||
| Synonym | нет | = Name | Синоним (отображаемое имя) |
|
| Synonym | нет | = Name | Синоним (отображаемое имя) |
|
||||||
| SrcDir | нет | `src` | Каталог исходников относительно CWD |
|
| SrcDir | нет | `src` | Каталог исходников относительно CWD |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/init.ps1" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"]
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/init.ps1" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Дальнейшие шаги
|
## Дальнейшие шаги
|
||||||
|
|
||||||
- Добавить форму: `/form-add`
|
- Добавить форму: `/form-add`
|
||||||
- Добавить макет: `/template-add`
|
- Добавить макет: `/template-add`
|
||||||
- Добавить справку: `/help-add`
|
- Добавить справку: `/help-add`
|
||||||
- Собрать EPF: `/epf-build`
|
- Собрать EPF: `/epf-build`
|
||||||
|
|||||||
@@ -1,90 +1,90 @@
|
|||||||
# epf-init v1.1 — Init 1C external data processor scaffold
|
# epf-init v1.1 — Init 1C external data processor scaffold
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$Name,
|
[string]$Name,
|
||||||
|
|
||||||
[string]$Synonym = $Name,
|
[string]$Synonym = $Name,
|
||||||
|
|
||||||
[string]$SrcDir = "src"
|
[string]$SrcDir = "src"
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
$uuid1 = [guid]::NewGuid().ToString()
|
$uuid1 = [guid]::NewGuid().ToString()
|
||||||
$uuid2 = [guid]::NewGuid().ToString()
|
$uuid2 = [guid]::NewGuid().ToString()
|
||||||
$uuid3 = [guid]::NewGuid().ToString()
|
$uuid3 = [guid]::NewGuid().ToString()
|
||||||
$uuid4 = [guid]::NewGuid().ToString()
|
$uuid4 = [guid]::NewGuid().ToString()
|
||||||
|
|
||||||
$xml = @"
|
$xml = @"
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
||||||
<ExternalDataProcessor uuid="$uuid1">
|
<ExternalDataProcessor uuid="$uuid1">
|
||||||
<InternalInfo>
|
<InternalInfo>
|
||||||
<xr:ContainedObject>
|
<xr:ContainedObject>
|
||||||
<xr:ClassId>c3831ec8-d8d5-4f93-8a22-f9bfae07327f</xr:ClassId>
|
<xr:ClassId>c3831ec8-d8d5-4f93-8a22-f9bfae07327f</xr:ClassId>
|
||||||
<xr:ObjectId>$uuid2</xr:ObjectId>
|
<xr:ObjectId>$uuid2</xr:ObjectId>
|
||||||
</xr:ContainedObject>
|
</xr:ContainedObject>
|
||||||
<xr:GeneratedType name="ExternalDataProcessorObject.$Name" category="Object">
|
<xr:GeneratedType name="ExternalDataProcessorObject.$Name" category="Object">
|
||||||
<xr:TypeId>$uuid3</xr:TypeId>
|
<xr:TypeId>$uuid3</xr:TypeId>
|
||||||
<xr:ValueId>$uuid4</xr:ValueId>
|
<xr:ValueId>$uuid4</xr:ValueId>
|
||||||
</xr:GeneratedType>
|
</xr:GeneratedType>
|
||||||
</InternalInfo>
|
</InternalInfo>
|
||||||
<Properties>
|
<Properties>
|
||||||
<Name>$Name</Name>
|
<Name>$Name</Name>
|
||||||
<Synonym>
|
<Synonym>
|
||||||
<v8:item>
|
<v8:item>
|
||||||
<v8:lang>ru</v8:lang>
|
<v8:lang>ru</v8:lang>
|
||||||
<v8:content>$Synonym</v8:content>
|
<v8:content>$Synonym</v8:content>
|
||||||
</v8:item>
|
</v8:item>
|
||||||
</Synonym>
|
</Synonym>
|
||||||
<Comment/>
|
<Comment/>
|
||||||
<DefaultForm/>
|
<DefaultForm/>
|
||||||
<AuxiliaryForm/>
|
<AuxiliaryForm/>
|
||||||
</Properties>
|
</Properties>
|
||||||
<ChildObjects/>
|
<ChildObjects/>
|
||||||
</ExternalDataProcessor>
|
</ExternalDataProcessor>
|
||||||
</MetaDataObject>
|
</MetaDataObject>
|
||||||
"@
|
"@
|
||||||
|
|
||||||
$rootFile = Join-Path $SrcDir "$Name.xml"
|
$rootFile = Join-Path $SrcDir "$Name.xml"
|
||||||
$processorDir = Join-Path $SrcDir $Name
|
$processorDir = Join-Path $SrcDir $Name
|
||||||
|
|
||||||
if (Test-Path $rootFile) {
|
if (Test-Path $rootFile) {
|
||||||
Write-Error "Файл уже существует: $rootFile"
|
Write-Error "Файл уже существует: $rootFile"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $SrcDir)) {
|
if (-not (Test-Path $SrcDir)) {
|
||||||
New-Item -ItemType Directory -Path $SrcDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $SrcDir -Force | Out-Null
|
||||||
}
|
}
|
||||||
$extDir = Join-Path $processorDir "Ext"
|
$extDir = Join-Path $processorDir "Ext"
|
||||||
New-Item -ItemType Directory -Path $extDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $extDir -Force | Out-Null
|
||||||
|
|
||||||
$enc = New-Object System.Text.UTF8Encoding($true)
|
$enc = New-Object System.Text.UTF8Encoding($true)
|
||||||
[System.IO.File]::WriteAllText((Resolve-Path $SrcDir | Join-Path -ChildPath "$Name.xml"), $xml, $enc)
|
[System.IO.File]::WriteAllText((Resolve-Path $SrcDir | Join-Path -ChildPath "$Name.xml"), $xml, $enc)
|
||||||
|
|
||||||
# --- Модуль объекта ---
|
# --- Модуль объекта ---
|
||||||
|
|
||||||
$moduleBsl = @"
|
$moduleBsl = @"
|
||||||
#Область ОписаниеПеременных
|
#Область ОписаниеПеременных
|
||||||
|
|
||||||
#КонецОбласти
|
#КонецОбласти
|
||||||
|
|
||||||
#Область ПрограммныйИнтерфейс
|
#Область ПрограммныйИнтерфейс
|
||||||
|
|
||||||
#КонецОбласти
|
#КонецОбласти
|
||||||
|
|
||||||
#Область СлужебныеПроцедурыИФункции
|
#Область СлужебныеПроцедурыИФункции
|
||||||
|
|
||||||
#КонецОбласти
|
#КонецОбласти
|
||||||
"@
|
"@
|
||||||
|
|
||||||
$modulePath = Join-Path $extDir "ObjectModule.bsl"
|
$modulePath = Join-Path $extDir "ObjectModule.bsl"
|
||||||
[System.IO.File]::WriteAllText($modulePath, $moduleBsl, $enc)
|
[System.IO.File]::WriteAllText($modulePath, $moduleBsl, $enc)
|
||||||
|
|
||||||
Write-Host "[OK] Создана обработка: $rootFile"
|
Write-Host "[OK] Создана обработка: $rootFile"
|
||||||
Write-Host " Каталог: $processorDir"
|
Write-Host " Каталог: $processorDir"
|
||||||
Write-Host " Модуль: $modulePath"
|
Write-Host " Модуль: $modulePath"
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
---
|
---
|
||||||
name: epf-validate
|
name: epf-validate
|
||||||
description: Валидация внешней обработки 1С (EPF). Используй после создания или модификации обработки для проверки корректности
|
description: Валидация внешней обработки 1С (EPF). Используй после создания или модификации обработки для проверки корректности
|
||||||
argument-hint: <ObjectPath> [-Detailed] [-MaxErrors 30]
|
argument-hint: <ObjectPath> [-Detailed] [-MaxErrors 30]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /epf-validate — валидация внешней обработки (EPF)
|
# /epf-validate — валидация внешней обработки (EPF)
|
||||||
|
|
||||||
Проверяет структурную корректность XML-исходников внешней обработки: корневую структуру, InternalInfo, свойства, ChildObjects, реквизиты, табличные части, уникальность имён, наличие файлов форм и макетов. Также работает для внешних отчётов (ERF).
|
Проверяет структурную корректность XML-исходников внешней обработки: корневую структуру, InternalInfo, свойства, ChildObjects, реквизиты, табличные части, уникальность имён, наличие файлов форм и макетов. Также работает для внешних отчётов (ERF).
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Обяз. | Умолч. | Описание |
|
| Параметр | Обяз. | Умолч. | Описание |
|
||||||
|------------|:-----:|---------|-------------------------------------------------|
|
|------------|:-----:|---------|-------------------------------------------------|
|
||||||
| ObjectPath | да | — | Путь к корневому XML или каталогу обработки |
|
| ObjectPath | да | — | Путь к корневому XML или каталогу обработки |
|
||||||
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
||||||
| MaxErrors | нет | 30 | Остановиться после N ошибок |
|
| MaxErrors | нет | 30 | Остановиться после N ошибок |
|
||||||
| OutFile | нет | — | Записать результат в файл (UTF-8 BOM) |
|
| OutFile | нет | — | Записать результат в файл (UTF-8 BOM) |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-validate.ps1" -ObjectPath "src/МояОбработка"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-validate.ps1" -ObjectPath "src/МояОбработка"
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-validate.ps1" -ObjectPath "src/МояОбработка/МояОбработка.xml"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-validate.ps1" -ObjectPath "src/МояОбработка/МояОбработка.xml"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,71 +1,71 @@
|
|||||||
---
|
---
|
||||||
name: erf-build
|
name: erf-build
|
||||||
description: Собрать внешний отчёт 1С (ERF) из XML-исходников. Используй когда пользователь просит собрать, скомпилировать отчёт или получить ERF файл из исходников
|
description: Собрать внешний отчёт 1С (ERF) из XML-исходников. Используй когда пользователь просит собрать, скомпилировать отчёт или получить ERF файл из исходников
|
||||||
argument-hint: <ReportName>
|
argument-hint: <ReportName>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
- Grep
|
- Grep
|
||||||
---
|
---
|
||||||
|
|
||||||
# /erf-build — Сборка отчёта
|
# /erf-build — Сборка отчёта
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/erf-build <ReportName> [SrcDir] [OutDir]
|
/erf-build <ReportName> [SrcDir] [OutDir]
|
||||||
```
|
```
|
||||||
|
|
||||||
| Параметр | Обязательный | По умолчанию | Описание |
|
| Параметр | Обязательный | По умолчанию | Описание |
|
||||||
|------------|:------------:|--------------|--------------------------------------|
|
|------------|:------------:|--------------|--------------------------------------|
|
||||||
| ReportName | да | — | Имя отчёта (имя корневого XML) |
|
| ReportName | да | — | Имя отчёта (имя корневого XML) |
|
||||||
| SrcDir | нет | `src` | Каталог исходников |
|
| SrcDir | нет | `src` | Каталог исходников |
|
||||||
| OutDir | нет | `build` | Каталог для результата |
|
| OutDir | нет | `build` | Каталог для результата |
|
||||||
|
|
||||||
## Параметры подключения (опционально)
|
## Параметры подключения (опционально)
|
||||||
|
|
||||||
Предпочтительно использовать конкретную базу — это надёжнее и не требует создания временной базы.
|
Предпочтительно использовать конкретную базу — это надёжнее и не требует создания временной базы.
|
||||||
|
|
||||||
1. Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` и разреши базу:
|
1. Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` и разреши базу:
|
||||||
2. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
2. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
||||||
3. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
3. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
||||||
4. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
4. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
||||||
5. Если ветка не совпала — используй `default`
|
5. Если ветка не совпала — используй `default`
|
||||||
6. Если `.v8-project.json` нет или база не найдена — не указывай параметры подключения: скрипт автоматически создаст временную базу. Для ERF со ссылочными типами (CatalogRef, DocumentRef и т.д.) генерируются заглушки метаданных. Временная база удаляется после сборки.
|
6. Если `.v8-project.json` нет или база не найдена — не указывай параметры подключения: скрипт автоматически создаст временную базу. Для ERF со ссылочными типами (CatalogRef, DocumentRef и т.д.) генерируются заглушки метаданных. Временная база удаляется после сборки.
|
||||||
|
|
||||||
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
||||||
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
Используй общий скрипт из epf-build:
|
Используй общий скрипт из epf-build:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.ps1" <параметры>
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|----------|:------------:|----------|
|
|----------|:------------:|----------|
|
||||||
| `-V8Path <путь>` | нет | Каталог bin платформы (или полный путь к 1cv8.exe) |
|
| `-V8Path <путь>` | нет | Каталог bin платформы (или полный путь к 1cv8.exe) |
|
||||||
| `-InfoBasePath <путь>` | * | Файловая база |
|
| `-InfoBasePath <путь>` | * | Файловая база |
|
||||||
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
||||||
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
||||||
| `-UserName <имя>` | нет | Имя пользователя |
|
| `-UserName <имя>` | нет | Имя пользователя |
|
||||||
| `-Password <пароль>` | нет | Пароль |
|
| `-Password <пароль>` | нет | Пароль |
|
||||||
| `-SourceFile <путь>` | да | Путь к корневому XML-файлу исходников |
|
| `-SourceFile <путь>` | да | Путь к корневому XML-файлу исходников |
|
||||||
| `-OutputFile <путь>` | да | Путь к выходному ERF-файлу |
|
| `-OutputFile <путь>` | да | Путь к выходному ERF-файлу |
|
||||||
|
|
||||||
> `*` — опционально. Если не указано — автоматически создаётся временная база со заглушками метаданных
|
> `*` — опционально. Если не указано — автоматически создаётся временная база со заглушками метаданных
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Сборка отчёта (файловая база)
|
# Сборка отчёта (файловая база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.ps1" -InfoBasePath "C:\Bases\MyDB" -SourceFile "src/МойОтчёт.xml" -OutputFile "build/МойОтчёт.erf"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.ps1" -InfoBasePath "C:\Bases\MyDB" -SourceFile "src/МойОтчёт.xml" -OutputFile "build/МойОтчёт.erf"
|
||||||
|
|
||||||
# Серверная база
|
# Серверная база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -SourceFile "src/МойОтчёт.xml" -OutputFile "build/МойОтчёт.erf"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -SourceFile "src/МойОтчёт.xml" -OutputFile "build/МойОтчёт.erf"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,71 +1,71 @@
|
|||||||
---
|
---
|
||||||
name: erf-dump
|
name: erf-dump
|
||||||
description: Разобрать ERF-файл отчёта 1С в XML-исходники. Используй когда пользователь просит разобрать, декомпилировать отчёт, получить исходники из ERF файла
|
description: Разобрать ERF-файл отчёта 1С в XML-исходники. Используй когда пользователь просит разобрать, декомпилировать отчёт, получить исходники из ERF файла
|
||||||
argument-hint: <ErfFile>
|
argument-hint: <ErfFile>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
- Grep
|
- Grep
|
||||||
---
|
---
|
||||||
|
|
||||||
# /erf-dump — Разборка отчёта
|
# /erf-dump — Разборка отчёта
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/erf-dump <ErfFile> [OutDir]
|
/erf-dump <ErfFile> [OutDir]
|
||||||
```
|
```
|
||||||
|
|
||||||
| Параметр | Обязательный | По умолчанию | Описание |
|
| Параметр | Обязательный | По умолчанию | Описание |
|
||||||
|----------|:------------:|--------------|-------------------------------------|
|
|----------|:------------:|--------------|-------------------------------------|
|
||||||
| ErfFile | да | — | Путь к ERF-файлу |
|
| ErfFile | да | — | Путь к ERF-файлу |
|
||||||
| OutDir | нет | `src` | Каталог для выгрузки исходников |
|
| OutDir | нет | `src` | Каталог для выгрузки исходников |
|
||||||
|
|
||||||
## Параметры подключения (обязательно)
|
## Параметры подключения (обязательно)
|
||||||
|
|
||||||
Для разборки EPF/ERF требуется информационная база с конфигурацией. Без базы ссылочные типы безвозвратно теряются.
|
Для разборки EPF/ERF требуется информационная база с конфигурацией. Без базы ссылочные типы безвозвратно теряются.
|
||||||
|
|
||||||
1. Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` и разреши базу:
|
1. Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` и разреши базу:
|
||||||
2. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
2. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
||||||
3. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
3. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
||||||
4. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
4. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
||||||
5. Если ветка не совпала — используй `default`
|
5. Если ветка не совпала — используй `default`
|
||||||
6. Если `.v8-project.json` нет или база не найдена — **сообщи пользователю об ошибке**. Для dump база обязательна: в пустой базе ссылочные типы (CatalogRef, DocumentRef и т.д.) безвозвратно сбрасываются в строки. Предложи указать базу или зарегистрировать через `/db-list add`.
|
6. Если `.v8-project.json` нет или база не найдена — **сообщи пользователю об ошибке**. Для dump база обязательна: в пустой базе ссылочные типы (CatalogRef, DocumentRef и т.д.) безвозвратно сбрасываются в строки. Предложи указать базу или зарегистрировать через `/db-list add`.
|
||||||
|
|
||||||
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files).
|
||||||
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
Используй общий скрипт из epf-dump:
|
Используй общий скрипт из epf-dump:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.ps1" <параметры>
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|----------|:------------:|----------|
|
|----------|:------------:|----------|
|
||||||
| `-V8Path <путь>` | нет | Каталог bin платформы (или полный путь к 1cv8.exe) |
|
| `-V8Path <путь>` | нет | Каталог bin платформы (или полный путь к 1cv8.exe) |
|
||||||
| `-InfoBasePath <путь>` | * | Файловая база |
|
| `-InfoBasePath <путь>` | * | Файловая база |
|
||||||
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
||||||
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
||||||
| `-UserName <имя>` | нет | Имя пользователя |
|
| `-UserName <имя>` | нет | Имя пользователя |
|
||||||
| `-Password <пароль>` | нет | Пароль |
|
| `-Password <пароль>` | нет | Пароль |
|
||||||
| `-InputFile <путь>` | да | Путь к ERF-файлу |
|
| `-InputFile <путь>` | да | Путь к ERF-файлу |
|
||||||
| `-OutputDir <путь>` | да | Каталог для выгрузки исходников |
|
| `-OutputDir <путь>` | да | Каталог для выгрузки исходников |
|
||||||
| `-Format <формат>` | нет | `Hierarchical` (по умолч.) / `Plain` |
|
| `-Format <формат>` | нет | `Hierarchical` (по умолч.) / `Plain` |
|
||||||
|
|
||||||
> `*` — обязательно хотя бы одно подключение. Без базы скрипт завершится с ошибкой (dump в пустой базе безвозвратно теряет ссылочные типы)
|
> `*` — обязательно хотя бы одно подключение. Без базы скрипт завершится с ошибкой (dump в пустой базе безвозвратно теряет ссылочные типы)
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Разборка отчёта (файловая база)
|
# Разборка отчёта (файловая база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.ps1" -InfoBasePath "C:\Bases\MyDB" -InputFile "build/МойОтчёт.erf" -OutputDir "src"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.ps1" -InfoBasePath "C:\Bases\MyDB" -InputFile "build/МойОтчёт.erf" -OutputDir "src"
|
||||||
|
|
||||||
# Серверная база
|
# Серверная база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -InputFile "build/МойОтчёт.erf" -OutputDir "src"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -InputFile "build/МойОтчёт.erf" -OutputDir "src"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,42 +1,42 @@
|
|||||||
---
|
---
|
||||||
name: erf-init
|
name: erf-init
|
||||||
description: Создать пустой внешний отчёт 1С (scaffold XML-исходников). Используй когда нужно создать новый внешний отчёт с нуля
|
description: Создать пустой внешний отчёт 1С (scaffold XML-исходников). Используй когда нужно создать новый внешний отчёт с нуля
|
||||||
argument-hint: <Name> [Synonym] [--with-skd]
|
argument-hint: <Name> [Synonym] [--with-skd]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Write
|
- Write
|
||||||
- Edit
|
- Edit
|
||||||
- Glob
|
- Glob
|
||||||
- Grep
|
- Grep
|
||||||
---
|
---
|
||||||
|
|
||||||
# /erf-init — Создание нового отчёта
|
# /erf-init — Создание нового отчёта
|
||||||
|
|
||||||
Генерирует минимальный набор XML-исходников для внешнего отчёта 1С: корневой файл метаданных и каталог отчёта.
|
Генерирует минимальный набор XML-исходников для внешнего отчёта 1С: корневой файл метаданных и каталог отчёта.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/erf-init <Name> [Synonym] [SrcDir] [--with-skd]
|
/erf-init <Name> [Synonym] [SrcDir] [--with-skd]
|
||||||
```
|
```
|
||||||
|
|
||||||
| Параметр | Обязательный | По умолчанию | Описание |
|
| Параметр | Обязательный | По умолчанию | Описание |
|
||||||
|-----------|:------------:|--------------|---------------------------------------|
|
|-----------|:------------:|--------------|---------------------------------------|
|
||||||
| Name | да | — | Имя отчёта (латиница/кириллица) |
|
| Name | да | — | Имя отчёта (латиница/кириллица) |
|
||||||
| Synonym | нет | = Name | Синоним (отображаемое имя) |
|
| Synonym | нет | = Name | Синоним (отображаемое имя) |
|
||||||
| SrcDir | нет | `src` | Каталог исходников относительно CWD |
|
| SrcDir | нет | `src` | Каталог исходников относительно CWD |
|
||||||
| --WithSKD | нет | — | Создать пустую СКД и привязать к MainDataCompositionSchema |
|
| --WithSKD | нет | — | Создать пустую СКД и привязать к MainDataCompositionSchema |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/init.ps1" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-WithSKD]
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/init.ps1" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-WithSKD]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Дальнейшие шаги
|
## Дальнейшие шаги
|
||||||
|
|
||||||
- Добавить форму: `/form-add`
|
- Добавить форму: `/form-add`
|
||||||
- Добавить макет: `/template-add`
|
- Добавить макет: `/template-add`
|
||||||
- Добавить справку: `/help-add`
|
- Добавить справку: `/help-add`
|
||||||
- Собрать ERF: `/erf-build`
|
- Собрать ERF: `/erf-build`
|
||||||
|
|||||||
@@ -1,180 +1,180 @@
|
|||||||
# erf-init v1.1 — Init 1C external report scaffold
|
# erf-init v1.1 — Init 1C external report scaffold
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$Name,
|
[string]$Name,
|
||||||
|
|
||||||
[string]$Synonym = $Name,
|
[string]$Synonym = $Name,
|
||||||
|
|
||||||
[string]$SrcDir = "src",
|
[string]$SrcDir = "src",
|
||||||
|
|
||||||
[switch]$WithSKD
|
[switch]$WithSKD
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
$uuid1 = [guid]::NewGuid().ToString()
|
$uuid1 = [guid]::NewGuid().ToString()
|
||||||
$uuid2 = [guid]::NewGuid().ToString()
|
$uuid2 = [guid]::NewGuid().ToString()
|
||||||
$uuid3 = [guid]::NewGuid().ToString()
|
$uuid3 = [guid]::NewGuid().ToString()
|
||||||
$uuid4 = [guid]::NewGuid().ToString()
|
$uuid4 = [guid]::NewGuid().ToString()
|
||||||
|
|
||||||
# --- Формируем Properties ---
|
# --- Формируем Properties ---
|
||||||
|
|
||||||
$mainDCSValue = ""
|
$mainDCSValue = ""
|
||||||
$childObjectsContent = ""
|
$childObjectsContent = ""
|
||||||
|
|
||||||
if ($WithSKD) {
|
if ($WithSKD) {
|
||||||
$mainDCSValue = "ExternalReport.$Name.Template.ОсновнаяСхемаКомпоновкиДанных"
|
$mainDCSValue = "ExternalReport.$Name.Template.ОсновнаяСхемаКомпоновкиДанных"
|
||||||
$childObjectsContent = @"
|
$childObjectsContent = @"
|
||||||
|
|
||||||
<Template>ОсновнаяСхемаКомпоновкиДанных</Template>
|
<Template>ОсновнаяСхемаКомпоновкиДанных</Template>
|
||||||
|
|
||||||
"@
|
"@
|
||||||
}
|
}
|
||||||
|
|
||||||
$mainDCSElement = if ($mainDCSValue) {
|
$mainDCSElement = if ($mainDCSValue) {
|
||||||
"<MainDataCompositionSchema>$mainDCSValue</MainDataCompositionSchema>"
|
"<MainDataCompositionSchema>$mainDCSValue</MainDataCompositionSchema>"
|
||||||
} else {
|
} else {
|
||||||
"<MainDataCompositionSchema/>"
|
"<MainDataCompositionSchema/>"
|
||||||
}
|
}
|
||||||
|
|
||||||
$childObjectsXml = if ($childObjectsContent) {
|
$childObjectsXml = if ($childObjectsContent) {
|
||||||
"<ChildObjects>$childObjectsContent</ChildObjects>"
|
"<ChildObjects>$childObjectsContent</ChildObjects>"
|
||||||
} else {
|
} else {
|
||||||
"<ChildObjects/>"
|
"<ChildObjects/>"
|
||||||
}
|
}
|
||||||
|
|
||||||
$xml = @"
|
$xml = @"
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
||||||
<ExternalReport uuid="$uuid1">
|
<ExternalReport uuid="$uuid1">
|
||||||
<InternalInfo>
|
<InternalInfo>
|
||||||
<xr:ContainedObject>
|
<xr:ContainedObject>
|
||||||
<xr:ClassId>e41aff26-25cf-4bb6-b6c1-3f478a75f374</xr:ClassId>
|
<xr:ClassId>e41aff26-25cf-4bb6-b6c1-3f478a75f374</xr:ClassId>
|
||||||
<xr:ObjectId>$uuid2</xr:ObjectId>
|
<xr:ObjectId>$uuid2</xr:ObjectId>
|
||||||
</xr:ContainedObject>
|
</xr:ContainedObject>
|
||||||
<xr:GeneratedType name="ExternalReportObject.$Name" category="Object">
|
<xr:GeneratedType name="ExternalReportObject.$Name" category="Object">
|
||||||
<xr:TypeId>$uuid3</xr:TypeId>
|
<xr:TypeId>$uuid3</xr:TypeId>
|
||||||
<xr:ValueId>$uuid4</xr:ValueId>
|
<xr:ValueId>$uuid4</xr:ValueId>
|
||||||
</xr:GeneratedType>
|
</xr:GeneratedType>
|
||||||
</InternalInfo>
|
</InternalInfo>
|
||||||
<Properties>
|
<Properties>
|
||||||
<Name>$Name</Name>
|
<Name>$Name</Name>
|
||||||
<Synonym>
|
<Synonym>
|
||||||
<v8:item>
|
<v8:item>
|
||||||
<v8:lang>ru</v8:lang>
|
<v8:lang>ru</v8:lang>
|
||||||
<v8:content>$Synonym</v8:content>
|
<v8:content>$Synonym</v8:content>
|
||||||
</v8:item>
|
</v8:item>
|
||||||
</Synonym>
|
</Synonym>
|
||||||
<Comment/>
|
<Comment/>
|
||||||
<DefaultForm/>
|
<DefaultForm/>
|
||||||
<AuxiliaryForm/>
|
<AuxiliaryForm/>
|
||||||
$mainDCSElement
|
$mainDCSElement
|
||||||
<DefaultSettingsForm/>
|
<DefaultSettingsForm/>
|
||||||
<AuxiliarySettingsForm/>
|
<AuxiliarySettingsForm/>
|
||||||
<DefaultVariantForm/>
|
<DefaultVariantForm/>
|
||||||
<VariantsStorage/>
|
<VariantsStorage/>
|
||||||
<SettingsStorage/>
|
<SettingsStorage/>
|
||||||
</Properties>
|
</Properties>
|
||||||
$childObjectsXml
|
$childObjectsXml
|
||||||
</ExternalReport>
|
</ExternalReport>
|
||||||
</MetaDataObject>
|
</MetaDataObject>
|
||||||
"@
|
"@
|
||||||
|
|
||||||
$rootFile = Join-Path $SrcDir "$Name.xml"
|
$rootFile = Join-Path $SrcDir "$Name.xml"
|
||||||
$reportDir = Join-Path $SrcDir $Name
|
$reportDir = Join-Path $SrcDir $Name
|
||||||
|
|
||||||
if (Test-Path $rootFile) {
|
if (Test-Path $rootFile) {
|
||||||
Write-Error "Файл уже существует: $rootFile"
|
Write-Error "Файл уже существует: $rootFile"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $SrcDir)) {
|
if (-not (Test-Path $SrcDir)) {
|
||||||
New-Item -ItemType Directory -Path $SrcDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $SrcDir -Force | Out-Null
|
||||||
}
|
}
|
||||||
$extDir = Join-Path $reportDir "Ext"
|
$extDir = Join-Path $reportDir "Ext"
|
||||||
New-Item -ItemType Directory -Path $extDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $extDir -Force | Out-Null
|
||||||
|
|
||||||
$enc = New-Object System.Text.UTF8Encoding($true)
|
$enc = New-Object System.Text.UTF8Encoding($true)
|
||||||
[System.IO.File]::WriteAllText((Resolve-Path $SrcDir | Join-Path -ChildPath "$Name.xml"), $xml, $enc)
|
[System.IO.File]::WriteAllText((Resolve-Path $SrcDir | Join-Path -ChildPath "$Name.xml"), $xml, $enc)
|
||||||
|
|
||||||
# --- Модуль объекта ---
|
# --- Модуль объекта ---
|
||||||
|
|
||||||
$moduleBsl = @"
|
$moduleBsl = @"
|
||||||
#Область ОписаниеПеременных
|
#Область ОписаниеПеременных
|
||||||
|
|
||||||
#КонецОбласти
|
#КонецОбласти
|
||||||
|
|
||||||
#Область ПрограммныйИнтерфейс
|
#Область ПрограммныйИнтерфейс
|
||||||
|
|
||||||
#КонецОбласти
|
#КонецОбласти
|
||||||
|
|
||||||
#Область СлужебныеПроцедурыИФункции
|
#Область СлужебныеПроцедурыИФункции
|
||||||
|
|
||||||
#КонецОбласти
|
#КонецОбласти
|
||||||
"@
|
"@
|
||||||
|
|
||||||
$modulePath = Join-Path $extDir "ObjectModule.bsl"
|
$modulePath = Join-Path $extDir "ObjectModule.bsl"
|
||||||
[System.IO.File]::WriteAllText($modulePath, $moduleBsl, $enc)
|
[System.IO.File]::WriteAllText($modulePath, $moduleBsl, $enc)
|
||||||
|
|
||||||
Write-Host "[OK] Создан отчёт: $rootFile"
|
Write-Host "[OK] Создан отчёт: $rootFile"
|
||||||
Write-Host " Каталог: $reportDir"
|
Write-Host " Каталог: $reportDir"
|
||||||
Write-Host " Модуль: $modulePath"
|
Write-Host " Модуль: $modulePath"
|
||||||
|
|
||||||
# --- СКД-макет (если --WithSKD) ---
|
# --- СКД-макет (если --WithSKD) ---
|
||||||
|
|
||||||
if ($WithSKD) {
|
if ($WithSKD) {
|
||||||
$templatesDir = Join-Path $reportDir "Templates"
|
$templatesDir = Join-Path $reportDir "Templates"
|
||||||
$skdName = "ОсновнаяСхемаКомпоновкиДанных"
|
$skdName = "ОсновнаяСхемаКомпоновкиДанных"
|
||||||
$skdMetaPath = Join-Path $templatesDir "$skdName.xml"
|
$skdMetaPath = Join-Path $templatesDir "$skdName.xml"
|
||||||
$skdExtDir = Join-Path (Join-Path $templatesDir $skdName) "Ext"
|
$skdExtDir = Join-Path (Join-Path $templatesDir $skdName) "Ext"
|
||||||
New-Item -ItemType Directory -Path $skdExtDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $skdExtDir -Force | Out-Null
|
||||||
|
|
||||||
$skdUuid = [guid]::NewGuid().ToString()
|
$skdUuid = [guid]::NewGuid().ToString()
|
||||||
|
|
||||||
$skdMetaXml = @"
|
$skdMetaXml = @"
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
||||||
<Template uuid="$skdUuid">
|
<Template uuid="$skdUuid">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Name>$skdName</Name>
|
<Name>$skdName</Name>
|
||||||
<Synonym>
|
<Synonym>
|
||||||
<v8:item>
|
<v8:item>
|
||||||
<v8:lang>ru</v8:lang>
|
<v8:lang>ru</v8:lang>
|
||||||
<v8:content>Основная схема компоновки данных</v8:content>
|
<v8:content>Основная схема компоновки данных</v8:content>
|
||||||
</v8:item>
|
</v8:item>
|
||||||
</Synonym>
|
</Synonym>
|
||||||
<Comment/>
|
<Comment/>
|
||||||
<TemplateType>DataCompositionSchema</TemplateType>
|
<TemplateType>DataCompositionSchema</TemplateType>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Template>
|
</Template>
|
||||||
</MetaDataObject>
|
</MetaDataObject>
|
||||||
"@
|
"@
|
||||||
|
|
||||||
[System.IO.File]::WriteAllText($skdMetaPath, $skdMetaXml, $enc)
|
[System.IO.File]::WriteAllText($skdMetaPath, $skdMetaXml, $enc)
|
||||||
|
|
||||||
$skdContent = @"
|
$skdContent = @"
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<DataCompositionSchema xmlns="http://v8.1c.ru/8.1/data-composition-system/schema"
|
<DataCompositionSchema xmlns="http://v8.1c.ru/8.1/data-composition-system/schema"
|
||||||
xmlns:dcscom="http://v8.1c.ru/8.1/data-composition-system/common"
|
xmlns:dcscom="http://v8.1c.ru/8.1/data-composition-system/common"
|
||||||
xmlns:dcscor="http://v8.1c.ru/8.1/data-composition-system/core"
|
xmlns:dcscor="http://v8.1c.ru/8.1/data-composition-system/core"
|
||||||
xmlns:dcsset="http://v8.1c.ru/8.1/data-composition-system/settings"
|
xmlns:dcsset="http://v8.1c.ru/8.1/data-composition-system/settings"
|
||||||
xmlns:v8="http://v8.1c.ru/8.1/data/core"
|
xmlns:v8="http://v8.1c.ru/8.1/data/core"
|
||||||
xmlns:v8ui="http://v8.1c.ru/8.1/data/ui"
|
xmlns:v8ui="http://v8.1c.ru/8.1/data/ui"
|
||||||
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<dataSource>
|
<dataSource>
|
||||||
<name>ИсточникДанных1</name>
|
<name>ИсточникДанных1</name>
|
||||||
<dataSourceType>Local</dataSourceType>
|
<dataSourceType>Local</dataSourceType>
|
||||||
</dataSource>
|
</dataSource>
|
||||||
</DataCompositionSchema>
|
</DataCompositionSchema>
|
||||||
"@
|
"@
|
||||||
|
|
||||||
$skdFilePath = Join-Path $skdExtDir "Template.xml"
|
$skdFilePath = Join-Path $skdExtDir "Template.xml"
|
||||||
[System.IO.File]::WriteAllText($skdFilePath, $skdContent, $enc)
|
[System.IO.File]::WriteAllText($skdFilePath, $skdContent, $enc)
|
||||||
|
|
||||||
Write-Host " СКД: $skdMetaPath"
|
Write-Host " СКД: $skdMetaPath"
|
||||||
Write-Host " Тело: $skdFilePath"
|
Write-Host " Тело: $skdFilePath"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
---
|
---
|
||||||
name: erf-validate
|
name: erf-validate
|
||||||
description: Валидация внешнего отчёта 1С (ERF). Используй после создания или модификации отчёта для проверки корректности
|
description: Валидация внешнего отчёта 1С (ERF). Используй после создания или модификации отчёта для проверки корректности
|
||||||
argument-hint: <ObjectPath> [-Detailed] [-MaxErrors 30]
|
argument-hint: <ObjectPath> [-Detailed] [-MaxErrors 30]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /erf-validate — валидация внешнего отчёта (ERF)
|
# /erf-validate — валидация внешнего отчёта (ERF)
|
||||||
|
|
||||||
Проверяет структурную корректность XML-исходников внешнего отчёта: корневую структуру, InternalInfo, свойства (включая MainDataCompositionSchema), ChildObjects, реквизиты, табличные части, уникальность имён, наличие файлов форм и макетов.
|
Проверяет структурную корректность XML-исходников внешнего отчёта: корневую структуру, InternalInfo, свойства (включая MainDataCompositionSchema), ChildObjects, реквизиты, табличные части, уникальность имён, наличие файлов форм и макетов.
|
||||||
|
|
||||||
Использует тот же скрипт, что и `/epf-validate` — автоопределение по типу элемента (ExternalReport).
|
Использует тот же скрипт, что и `/epf-validate` — автоопределение по типу элемента (ExternalReport).
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Обяз. | Умолч. | Описание |
|
| Параметр | Обяз. | Умолч. | Описание |
|
||||||
|------------|:-----:|---------|-------------------------------------------------|
|
|------------|:-----:|---------|-------------------------------------------------|
|
||||||
| ObjectPath | да | — | Путь к корневому XML или каталогу отчёта |
|
| ObjectPath | да | — | Путь к корневому XML или каталогу отчёта |
|
||||||
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
||||||
| MaxErrors | нет | 30 | Остановиться после N ошибок |
|
| MaxErrors | нет | 30 | Остановиться после N ошибок |
|
||||||
| OutFile | нет | — | Записать результат в файл (UTF-8 BOM) |
|
| OutFile | нет | — | Записать результат в файл (UTF-8 BOM) |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МойОтчёт"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МойОтчёт"
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МойОтчёт/МойОтчёт.xml"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МойОтчёт/МойОтчёт.xml"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,71 +1,71 @@
|
|||||||
---
|
---
|
||||||
name: form-add
|
name: form-add
|
||||||
description: Добавить пустую управляемую форму к объекту 1С. Используй когда нужно создать у объекта новую форму
|
description: Добавить пустую управляемую форму к объекту 1С. Используй когда нужно создать у объекта новую форму
|
||||||
argument-hint: <ObjectPath> <FormName> [Purpose] [--set-default]
|
argument-hint: <ObjectPath> <FormName> [Purpose] [--set-default]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Write
|
- Write
|
||||||
- Edit
|
- Edit
|
||||||
- Glob
|
- Glob
|
||||||
- Grep
|
- Grep
|
||||||
---
|
---
|
||||||
|
|
||||||
# /form-add — Добавление формы к объекту конфигурации
|
# /form-add — Добавление формы к объекту конфигурации
|
||||||
|
|
||||||
Создаёт управляемую форму (metadata XML + Form.xml + Module.bsl) и регистрирует её в корневом XML объекта конфигурации (Document, Catalog, InformationRegister и др.).
|
Создаёт управляемую форму (metadata XML + Form.xml + Module.bsl) и регистрирует её в корневом XML объекта конфигурации (Document, Catalog, InformationRegister и др.).
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/form-add <ObjectPath> <FormName> [Purpose] [Synonym] [--set-default]
|
/form-add <ObjectPath> <FormName> [Purpose] [Synonym] [--set-default]
|
||||||
```
|
```
|
||||||
|
|
||||||
| Параметр | Обязательный | По умолчанию | Описание |
|
| Параметр | Обязательный | По умолчанию | Описание |
|
||||||
|-------------|:------------:|--------------|----------------------------------------------|
|
|-------------|:------------:|--------------|----------------------------------------------|
|
||||||
| ObjectPath | да | — | Путь к XML-файлу объекта (Documents/Док.xml) |
|
| ObjectPath | да | — | Путь к XML-файлу объекта (Documents/Док.xml) |
|
||||||
| FormName | да | — | Имя формы (ФормаДокумента) |
|
| FormName | да | — | Имя формы (ФормаДокумента) |
|
||||||
| Purpose | нет | Object | Назначение: Object, List, Choice, Record |
|
| Purpose | нет | Object | Назначение: Object, List, Choice, Record |
|
||||||
| Synonym | нет | = FormName | Синоним формы |
|
| Synonym | нет | = FormName | Синоним формы |
|
||||||
| --set-default | нет | авто | Установить как форму по умолчанию |
|
| --set-default | нет | авто | Установить как форму по умолчанию |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-add.ps1" -ObjectPath "<ObjectPath>" -FormName "<FormName>" [-Purpose "<Purpose>"] [-Synonym "<Synonym>"] [-SetDefault]
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-add.ps1" -ObjectPath "<ObjectPath>" -FormName "<FormName>" [-Purpose "<Purpose>"] [-Synonym "<Synonym>"] [-SetDefault]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Purpose — назначение формы
|
## Purpose — назначение формы
|
||||||
|
|
||||||
| Purpose | Допустимые типы объектов | Основной реквизит | DefaultForm-свойство |
|
| Purpose | Допустимые типы объектов | Основной реквизит | DefaultForm-свойство |
|
||||||
|---------|-------------------------|-------------------|---------------------|
|
|---------|-------------------------|-------------------|---------------------|
|
||||||
| Object | Document, Catalog, DataProcessor, Report, ExternalDataProcessor, ExternalReport, ChartOf*, ExchangePlan, BusinessProcess, Task | Объект (тип: *Object.Имя) | DefaultObjectForm (DefaultForm для DataProcessor/Report/ExternalDataProcessor/ExternalReport) |
|
| Object | Document, Catalog, DataProcessor, Report, ExternalDataProcessor, ExternalReport, ChartOf*, ExchangePlan, BusinessProcess, Task | Объект (тип: *Object.Имя) | DefaultObjectForm (DefaultForm для DataProcessor/Report/ExternalDataProcessor/ExternalReport) |
|
||||||
| List | Все кроме DataProcessor | Список (DynamicList) | DefaultListForm |
|
| List | Все кроме DataProcessor | Список (DynamicList) | DefaultListForm |
|
||||||
| Choice | Document, Catalog, ChartOf*, ExchangePlan, BusinessProcess, Task | Список (DynamicList) | DefaultChoiceForm |
|
| Choice | Document, Catalog, ChartOf*, ExchangePlan, BusinessProcess, Task | Список (DynamicList) | DefaultChoiceForm |
|
||||||
| Record | InformationRegister | Запись (InformationRegisterRecordManager) | DefaultRecordForm |
|
| Record | InformationRegister | Запись (InformationRegisterRecordManager) | DefaultRecordForm |
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```
|
```
|
||||||
# Форма документа
|
# Форма документа
|
||||||
/form-add Documents/АвансовыйОтчет.xml ФормаДокумента --purpose Object
|
/form-add Documents/АвансовыйОтчет.xml ФормаДокумента --purpose Object
|
||||||
|
|
||||||
# Форма списка каталога
|
# Форма списка каталога
|
||||||
/form-add Catalogs/Контрагенты.xml ФормаСписка --purpose List
|
/form-add Catalogs/Контрагенты.xml ФормаСписка --purpose List
|
||||||
|
|
||||||
# Форма записи регистра сведений
|
# Форма записи регистра сведений
|
||||||
/form-add InformationRegisters/КурсыВалют.xml ФормаЗаписи --purpose Record
|
/form-add InformationRegisters/КурсыВалют.xml ФормаЗаписи --purpose Record
|
||||||
|
|
||||||
# Форма выбора с синонимом
|
# Форма выбора с синонимом
|
||||||
/form-add Catalogs/Номенклатура.xml ФормаВыбора --purpose Choice --synonym "Выбор номенклатуры"
|
/form-add Catalogs/Номенклатура.xml ФормаВыбора --purpose Choice --synonym "Выбор номенклатуры"
|
||||||
|
|
||||||
# Установить как форму по умолчанию
|
# Установить как форму по умолчанию
|
||||||
/form-add Documents/Заказ.xml ФормаДокументаНовая --purpose Object --set-default
|
/form-add Documents/Заказ.xml ФормаДокументаНовая --purpose Object --set-default
|
||||||
```
|
```
|
||||||
|
|
||||||
## Workflow
|
## Workflow
|
||||||
|
|
||||||
1. `/form-add` — создать каркас формы
|
1. `/form-add` — создать каркас формы
|
||||||
2. `/form-compile` или `/form-edit` — наполнить Form.xml элементами
|
2. `/form-compile` или `/form-edit` — наполнить Form.xml элементами
|
||||||
3. `/form-validate` — проверить корректность
|
3. `/form-validate` — проверить корректность
|
||||||
4. `/form-info` — проанализировать результат
|
4. `/form-info` — проанализировать результат
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+142
-142
@@ -1,142 +1,142 @@
|
|||||||
---
|
---
|
||||||
name: form-edit
|
name: form-edit
|
||||||
description: Добавление элементов, реквизитов и команд в существующую управляемую форму 1С. Используй когда нужно точечно модифицировать готовую форму
|
description: Добавление элементов, реквизитов и команд в существующую управляемую форму 1С. Используй когда нужно точечно модифицировать готовую форму
|
||||||
argument-hint: <FormPath> <JsonPath>
|
argument-hint: <FormPath> <JsonPath>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Write
|
- Write
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /form-edit — Редактирование формы
|
# /form-edit — Редактирование формы
|
||||||
|
|
||||||
Добавляет элементы, реквизиты и/или команды в существующий Form.xml. Автоматически выделяет ID из правильного пула, генерирует companion-элементы (ContextMenu, ExtendedTooltip, и др.) и обработчики событий.
|
Добавляет элементы, реквизиты и/или команды в существующий Form.xml. Автоматически выделяет ID из правильного пула, генерирует companion-элементы (ContextMenu, ExtendedTooltip, и др.) и обработчики событий.
|
||||||
|
|
||||||
## Использование
|
## Использование
|
||||||
|
|
||||||
```
|
```
|
||||||
/form-edit <FormPath> <JsonPath>
|
/form-edit <FormPath> <JsonPath>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|-----------|:------------:|----------------------------------|
|
|-----------|:------------:|----------------------------------|
|
||||||
| FormPath | да | Путь к существующему Form.xml |
|
| FormPath | да | Путь к существующему Form.xml |
|
||||||
| JsonPath | да | Путь к JSON с описанием добавлений |
|
| JsonPath | да | Путь к JSON с описанием добавлений |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-edit.ps1" -FormPath "<путь>" -JsonPath "<путь>"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-edit.ps1" -FormPath "<путь>" -JsonPath "<путь>"
|
||||||
```
|
```
|
||||||
|
|
||||||
## JSON формат
|
## JSON формат
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"into": "ГруппаШапка",
|
"into": "ГруппаШапка",
|
||||||
"after": "Контрагент",
|
"after": "Контрагент",
|
||||||
"elements": [
|
"elements": [
|
||||||
{ "input": "Склад", "path": "Объект.Склад", "on": ["OnChange"] }
|
{ "input": "Склад", "path": "Объект.Склад", "on": ["OnChange"] }
|
||||||
],
|
],
|
||||||
"attributes": [
|
"attributes": [
|
||||||
{ "name": "СуммаИтого", "type": "decimal(15,2)" }
|
{ "name": "СуммаИтого", "type": "decimal(15,2)" }
|
||||||
],
|
],
|
||||||
"commands": [
|
"commands": [
|
||||||
{ "name": "Рассчитать", "action": "РассчитатьОбработка" }
|
{ "name": "Рассчитать", "action": "РассчитатьОбработка" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Расширения (extension-формы)
|
### Расширения (extension-формы)
|
||||||
|
|
||||||
Для заимствованных форм (с `<BaseForm>`) автоматически активируется extension-режим: ID начинаются с 1000000+. Доступны дополнительные секции:
|
Для заимствованных форм (с `<BaseForm>`) автоматически активируется extension-режим: ID начинаются с 1000000+. Доступны дополнительные секции:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"formEvents": [
|
"formEvents": [
|
||||||
{ "name": "OnCreateAtServer", "handler": "Расш1_ПриСозданииПосле", "callType": "After" },
|
{ "name": "OnCreateAtServer", "handler": "Расш1_ПриСозданииПосле", "callType": "After" },
|
||||||
{ "name": "OnOpen", "handler": "Расш1_ПриОткрытии", "callType": "Before" }
|
{ "name": "OnOpen", "handler": "Расш1_ПриОткрытии", "callType": "Before" }
|
||||||
],
|
],
|
||||||
"elementEvents": [
|
"elementEvents": [
|
||||||
{ "element": "Банк", "name": "OnChange", "handler": "Расш1_БанкПриИзменении", "callType": "Before" }
|
{ "element": "Банк", "name": "OnChange", "handler": "Расш1_БанкПриИзменении", "callType": "Before" }
|
||||||
],
|
],
|
||||||
"commands": [
|
"commands": [
|
||||||
{ "name": "Подбор", "action": "Расш1_ПодборПосле", "callType": "After" },
|
{ "name": "Подбор", "action": "Расш1_ПодборПосле", "callType": "After" },
|
||||||
{ "name": "Запрос", "actions": [
|
{ "name": "Запрос", "actions": [
|
||||||
{ "callType": "Before", "handler": "Расш1_ЗапросПеред" },
|
{ "callType": "Before", "handler": "Расш1_ЗапросПеред" },
|
||||||
{ "callType": "After", "handler": "Расш1_ЗапросПосле" }
|
{ "callType": "After", "handler": "Расш1_ЗапросПосле" }
|
||||||
]}
|
]}
|
||||||
],
|
],
|
||||||
"elements": [
|
"elements": [
|
||||||
{ "input": "Поле", "path": "Объект.Поле", "on": [{ "event": "OnChange", "callType": "After" }] }
|
{ "input": "Поле", "path": "Объект.Поле", "on": [{ "event": "OnChange", "callType": "After" }] }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Позиционирование элементов
|
### Позиционирование элементов
|
||||||
|
|
||||||
| Ключ | По умолчанию | Описание |
|
| Ключ | По умолчанию | Описание |
|
||||||
|------|-------------|----------|
|
|------|-------------|----------|
|
||||||
| `into` | корневой ChildItems | Имя группы/таблицы/страницы, куда вставлять |
|
| `into` | корневой ChildItems | Имя группы/таблицы/страницы, куда вставлять |
|
||||||
| `after` | в конец | Имя элемента, после которого вставлять |
|
| `after` | в конец | Имя элемента, после которого вставлять |
|
||||||
|
|
||||||
### Типы элементов
|
### Типы элементов
|
||||||
|
|
||||||
Те же DSL-ключи, что в `/form-compile`:
|
Те же DSL-ключи, что в `/form-compile`:
|
||||||
|
|
||||||
| Ключ | XML тег | Companions |
|
| Ключ | XML тег | Companions |
|
||||||
|------|---------|------------|
|
|------|---------|------------|
|
||||||
| `input` | InputField | ContextMenu, ExtendedTooltip |
|
| `input` | InputField | ContextMenu, ExtendedTooltip |
|
||||||
| `check` | CheckBoxField | ContextMenu, ExtendedTooltip |
|
| `check` | CheckBoxField | ContextMenu, ExtendedTooltip |
|
||||||
| `label` | LabelDecoration | ContextMenu, ExtendedTooltip |
|
| `label` | LabelDecoration | ContextMenu, ExtendedTooltip |
|
||||||
| `labelField` | LabelField | ContextMenu, ExtendedTooltip |
|
| `labelField` | LabelField | ContextMenu, ExtendedTooltip |
|
||||||
| `group` | UsualGroup | ExtendedTooltip |
|
| `group` | UsualGroup | ExtendedTooltip |
|
||||||
| `table` | Table | ContextMenu, AutoCommandBar, Search*, ViewStatus* |
|
| `table` | Table | ContextMenu, AutoCommandBar, Search*, ViewStatus* |
|
||||||
| `pages` | Pages | ExtendedTooltip |
|
| `pages` | Pages | ExtendedTooltip |
|
||||||
| `page` | Page | ExtendedTooltip |
|
| `page` | Page | ExtendedTooltip |
|
||||||
| `button` | Button | ExtendedTooltip |
|
| `button` | Button | ExtendedTooltip |
|
||||||
|
|
||||||
Группы и таблицы поддерживают `children`/`columns` для вложенных элементов.
|
Группы и таблицы поддерживают `children`/`columns` для вложенных элементов.
|
||||||
|
|
||||||
### Кнопки: command и stdCommand
|
### Кнопки: command и stdCommand
|
||||||
|
|
||||||
- `"command": "ИмяКоманды"` → `Form.Command.ИмяКоманды`
|
- `"command": "ИмяКоманды"` → `Form.Command.ИмяКоманды`
|
||||||
- `"stdCommand": "Close"` → `Form.StandardCommand.Close`
|
- `"stdCommand": "Close"` → `Form.StandardCommand.Close`
|
||||||
- `"stdCommand": "Товары.Add"` → `Form.Item.Товары.StandardCommand.Add` (стандартная команда элемента)
|
- `"stdCommand": "Товары.Add"` → `Form.Item.Товары.StandardCommand.Add` (стандартная команда элемента)
|
||||||
|
|
||||||
### Допустимые события (`on`)
|
### Допустимые события (`on`)
|
||||||
|
|
||||||
Компилятор предупреждает об ошибках в именах событий. Основные:
|
Компилятор предупреждает об ошибках в именах событий. Основные:
|
||||||
|
|
||||||
- **input**: `OnChange`, `StartChoice`, `ChoiceProcessing`, `Clearing`, `AutoComplete`, `TextEditEnd`
|
- **input**: `OnChange`, `StartChoice`, `ChoiceProcessing`, `Clearing`, `AutoComplete`, `TextEditEnd`
|
||||||
- **check**: `OnChange`
|
- **check**: `OnChange`
|
||||||
- **table**: `OnStartEdit`, `OnEditEnd`, `OnChange`, `Selection`, `BeforeAddRow`, `BeforeDeleteRow`, `OnActivateRow`
|
- **table**: `OnStartEdit`, `OnEditEnd`, `OnChange`, `Selection`, `BeforeAddRow`, `BeforeDeleteRow`, `OnActivateRow`
|
||||||
- **label/picture**: `Click`, `URLProcessing`
|
- **label/picture**: `Click`, `URLProcessing`
|
||||||
- **pages**: `OnCurrentPageChange`
|
- **pages**: `OnCurrentPageChange`
|
||||||
- **button**: `Click`
|
- **button**: `Click`
|
||||||
|
|
||||||
### Система типов (для attributes)
|
### Система типов (для attributes)
|
||||||
|
|
||||||
`string`, `string(100)`, `decimal(15,2)`, `boolean`, `date`, `dateTime`, `CatalogRef.XXX`, `DocumentObject.XXX`, `ValueTable`, `DynamicList`, `Type1 | Type2` (составной).
|
`string`, `string(100)`, `decimal(15,2)`, `boolean`, `date`, `dateTime`, `CatalogRef.XXX`, `DocumentObject.XXX`, `ValueTable`, `DynamicList`, `Type1 | Type2` (составной).
|
||||||
|
|
||||||
### Секции расширений
|
### Секции расширений
|
||||||
|
|
||||||
| Секция | Назначение |
|
| Секция | Назначение |
|
||||||
|--------|-----------|
|
|--------|-----------|
|
||||||
| `formEvents` | События уровня формы с `callType` (Before/After/Override) |
|
| `formEvents` | События уровня формы с `callType` (Before/After/Override) |
|
||||||
| `elementEvents` | События на существующих элементах заимствованной формы |
|
| `elementEvents` | События на существующих элементах заимствованной формы |
|
||||||
| `callType` на `commands` | callType на Action команды |
|
| `callType` на `commands` | callType на Action команды |
|
||||||
| `callType` на `on` | callType на событиях новых элементов (объектный формат) |
|
| `callType` на `on` | callType на событиях новых элементов (объектный формат) |
|
||||||
|
|
||||||
Все extension-секции опциональны — без них навык работает как с обычными формами.
|
Все extension-секции опциональны — без них навык работает как с обычными формами.
|
||||||
|
|
||||||
## Workflow
|
## Workflow
|
||||||
|
|
||||||
1. `/form-info` — посмотреть текущую структуру формы
|
1. `/form-info` — посмотреть текущую структуру формы
|
||||||
2. Создать JSON с описанием добавлений
|
2. Создать JSON с описанием добавлений
|
||||||
3. `/form-edit` — добавить в форму
|
3. `/form-edit` — добавить в форму
|
||||||
4. `/form-validate` — проверить корректность
|
4. `/form-validate` — проверить корректность
|
||||||
5. `/form-info` — убедиться что добавилось правильно
|
5. `/form-info` — убедиться что добавилось правильно
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,30 +1,30 @@
|
|||||||
---
|
---
|
||||||
name: form-info
|
name: form-info
|
||||||
description: Анализ структуры управляемой формы 1С (Form.xml) — элементы, реквизиты, команды, события. Используй для понимания формы — при написании модуля формы, анализе обработчиков и элементов
|
description: Анализ структуры управляемой формы 1С (Form.xml) — элементы, реквизиты, команды, события. Используй для понимания формы — при написании модуля формы, анализе обработчиков и элементов
|
||||||
argument-hint: <FormPath>
|
argument-hint: <FormPath>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /form-info — Компактная сводка формы
|
# /form-info — Компактная сводка формы
|
||||||
|
|
||||||
Читает Form.xml и выводит дерево элементов, реквизиты с типами, команды, события. Заменяет чтение тысяч строк XML.
|
Читает Form.xml и выводит дерево элементов, реквизиты с типами, команды, события. Заменяет чтение тысяч строк XML.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-info.ps1" -FormPath "<путь к Form.xml>"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-info.ps1" -FormPath "<путь к Form.xml>"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|----------|:------------:|----------|
|
|----------|:------------:|----------|
|
||||||
| FormPath | да | Путь к файлу Form.xml |
|
| FormPath | да | Путь к файлу Form.xml |
|
||||||
| Expand | нет | Раскрыть свёрнутую секцию по имени или title, `*` — все |
|
| Expand | нет | Раскрыть свёрнутую секцию по имени или title, `*` — все |
|
||||||
| Limit | нет | Макс. строк (по умолчанию 150) |
|
| Limit | нет | Макс. строк (по умолчанию 150) |
|
||||||
| Offset | нет | Пропустить N строк (пагинация) |
|
| Offset | нет | Пропустить N строк (пагинация) |
|
||||||
|
|
||||||
Вывод самодокументирован. `[Group:AH]`/`[Group:AV]` = AlwaysHorizontal/AlwaysVertical.
|
Вывод самодокументирован. `[Group:AH]`/`[Group:AV]` = AlwaysHorizontal/AlwaysVertical.
|
||||||
|
|||||||
@@ -1,253 +1,253 @@
|
|||||||
---
|
---
|
||||||
name: form-patterns
|
name: form-patterns
|
||||||
description: Справочник паттернов компоновки управляемых форм 1С. Используй как справочник при проектировании форм — архетипы, конвенции, продвинутые приёмы
|
description: Справочник паттернов компоновки управляемых форм 1С. Используй как справочник при проектировании форм — архетипы, конвенции, продвинутые приёмы
|
||||||
argument-hint: (no arguments)
|
argument-hint: (no arguments)
|
||||||
allowed-tools: []
|
allowed-tools: []
|
||||||
---
|
---
|
||||||
|
|
||||||
# /form-patterns — паттерны компоновки форм
|
# /form-patterns — паттерны компоновки форм
|
||||||
|
|
||||||
Справочник типовых паттернов дизайна управляемых форм 1С. Вызывай **перед** проектированием формы через `/form-compile`, когда требования пользователя не детализируют расположение элементов.
|
Справочник типовых паттернов дизайна управляемых форм 1С. Вызывай **перед** проектированием формы через `/form-compile`, когда требования пользователя не детализируют расположение элементов.
|
||||||
|
|
||||||
**Как использовать:** выбери подходящий архетип, применяй конвенции именования, при необходимости используй продвинутые паттерны.
|
**Как использовать:** выбери подходящий архетип, применяй конвенции именования, при необходимости используй продвинутые паттерны.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Архетипы форм
|
## Архетипы форм
|
||||||
|
|
||||||
### Форма документа
|
### Форма документа
|
||||||
|
|
||||||
```
|
```
|
||||||
Шапка (horizontal, 2 колонки)
|
Шапка (horizontal, 2 колонки)
|
||||||
├─ Левая (vertical): НомерДата (H: Номер + Дата "от"), Контрагент, Договор
|
├─ Левая (vertical): НомерДата (H: Номер + Дата "от"), Контрагент, Договор
|
||||||
├─ Правая (vertical): Организация, Подразделение, ЦеныИВалюта (надпись-ссылка)
|
├─ Правая (vertical): Организация, Подразделение, ЦеныИВалюта (надпись-ссылка)
|
||||||
Страницы (pages)
|
Страницы (pages)
|
||||||
├─ Товары: таблица Объект.Товары
|
├─ Товары: таблица Объект.Товары
|
||||||
├─ Услуги: таблица Объект.Услуги (опционально)
|
├─ Услуги: таблица Объект.Услуги (опционально)
|
||||||
└─ Дополнительно: прочие реквизиты
|
└─ Дополнительно: прочие реквизиты
|
||||||
Подвал (vertical)
|
Подвал (vertical)
|
||||||
├─ Итоги (horizontal): Всего, НДС, Скидка
|
├─ Итоги (horizontal): Всего, НДС, Скидка
|
||||||
└─ КомментарийОтветственный (horizontal): Комментарий + Ответственный
|
└─ КомментарийОтветственный (horizontal): Комментарий + Ответственный
|
||||||
```
|
```
|
||||||
|
|
||||||
**События:** OnCreateAtServer, OnReadAtServer, OnOpen, BeforeWriteAtServer, AfterWriteAtServer, AfterWrite, NotificationProcessing
|
**События:** OnCreateAtServer, OnReadAtServer, OnOpen, BeforeWriteAtServer, AfterWriteAtServer, AfterWrite, NotificationProcessing
|
||||||
**Свойства:** autoTitle=false
|
**Свойства:** autoTitle=false
|
||||||
|
|
||||||
### Форма обработки (DataProcessor)
|
### Форма обработки (DataProcessor)
|
||||||
|
|
||||||
```
|
```
|
||||||
Параметры (vertical)
|
Параметры (vertical)
|
||||||
├─ Группа полей ввода (Организация, Период, режимы работы)
|
├─ Группа полей ввода (Организация, Период, режимы работы)
|
||||||
├─ Информационные надписи (label, hyperlink)
|
├─ Информационные надписи (label, hyperlink)
|
||||||
Рабочая область
|
Рабочая область
|
||||||
├─ Таблица данных или Pages с вкладками
|
├─ Таблица данных или Pages с вкладками
|
||||||
Главная АКП формы (autoCmdBar)
|
Главная АКП формы (autoCmdBar)
|
||||||
├─ Выполнить / Применить (defaultButton: true)
|
├─ Выполнить / Применить (defaultButton: true)
|
||||||
└─ Закрыть (stdCommand: Close)
|
└─ Закрыть (stdCommand: Close)
|
||||||
```
|
```
|
||||||
|
|
||||||
**События:** OnCreateAtServer, OnOpen, NotificationProcessing
|
**События:** OnCreateAtServer, OnOpen, NotificationProcessing
|
||||||
**Свойства:** windowOpeningMode=LockOwnerWindow (если диалог), autoTitle=false
|
**Свойства:** windowOpeningMode=LockOwnerWindow (если диалог), autoTitle=false
|
||||||
|
|
||||||
### Форма списка
|
### Форма списка
|
||||||
|
|
||||||
```
|
```
|
||||||
Отборы (group: alwaysHorizontal)
|
Отборы (group: alwaysHorizontal)
|
||||||
├─ ГруппаОтбор[Поле] (H): Флажок + Поле ввода (для каждого фильтра)
|
├─ ГруппаОтбор[Поле] (H): Флажок + Поле ввода (для каждого фильтра)
|
||||||
Список (table, DynamicList)
|
Список (table, DynamicList)
|
||||||
├─ Колонки: labelField (не input — данные только для чтения)
|
├─ Колонки: labelField (не input — данные только для чтения)
|
||||||
```
|
```
|
||||||
|
|
||||||
**События:** OnCreateAtServer, OnOpen, NotificationProcessing, OnLoadDataFromSettingsAtServer
|
**События:** OnCreateAtServer, OnOpen, NotificationProcessing, OnLoadDataFromSettingsAtServer
|
||||||
**Свойства:** autoSaveDataInSettings=Use
|
**Свойства:** autoSaveDataInSettings=Use
|
||||||
**Фильтры:** пара реквизитов на каждый — `Отбор[Поле]` (значение) + `Отбор[Поле]Использование` (boolean)
|
**Фильтры:** пара реквизитов на каждый — `Отбор[Поле]` (значение) + `Отбор[Поле]Использование` (boolean)
|
||||||
|
|
||||||
### Форма элемента справочника
|
### Форма элемента справочника
|
||||||
|
|
||||||
**Простая:**
|
**Простая:**
|
||||||
```
|
```
|
||||||
ГруппаРеквизитов (horizontal)
|
ГруппаРеквизитов (horizontal)
|
||||||
├─ Наименование -> Объект.Description
|
├─ Наименование -> Объект.Description
|
||||||
└─ Код -> Объект.Code (если нужен)
|
└─ Код -> Объект.Code (если нужен)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Сложная:**
|
**Сложная:**
|
||||||
```
|
```
|
||||||
Главное (vertical)
|
Главное (vertical)
|
||||||
├─ Наименование -> Объект.Description
|
├─ Наименование -> Объект.Description
|
||||||
├─ Параметры (horizontal, 2 колонки)
|
├─ Параметры (horizontal, 2 колонки)
|
||||||
│ ├─ Левая: основные реквизиты
|
│ ├─ Левая: основные реквизиты
|
||||||
│ └─ Правая: дополнительные реквизиты
|
│ └─ Правая: дополнительные реквизиты
|
||||||
└─ КонтактныеДанные / Дополнительно (vertical)
|
└─ КонтактныеДанные / Дополнительно (vertical)
|
||||||
```
|
```
|
||||||
|
|
||||||
**События:** OnCreateAtServer, OnReadAtServer, BeforeWriteAtServer, NotificationProcessing
|
**События:** OnCreateAtServer, OnReadAtServer, BeforeWriteAtServer, NotificationProcessing
|
||||||
|
|
||||||
### Мастер (Wizard)
|
### Мастер (Wizard)
|
||||||
|
|
||||||
```
|
```
|
||||||
Страницы (pages, OnCurrentPageChange)
|
Страницы (pages, OnCurrentPageChange)
|
||||||
├─ Шаг1: описание + параметры
|
├─ Шаг1: описание + параметры
|
||||||
├─ Шаг2: основная работа
|
├─ Шаг2: основная работа
|
||||||
└─ Шаг3: результат
|
└─ Шаг3: результат
|
||||||
Главная АКП формы (autoCmdBar)
|
Главная АКП формы (autoCmdBar)
|
||||||
├─ Назад, Далее (defaultButton: true), Выполнить
|
├─ Назад, Далее (defaultButton: true), Выполнить
|
||||||
└─ Закрыть (stdCommand: Close)
|
└─ Закрыть (stdCommand: Close)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Свойства:** windowOpeningMode=LockOwnerWindow
|
**Свойства:** windowOpeningMode=LockOwnerWindow
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Конвенции именования
|
## Конвенции именования
|
||||||
|
|
||||||
### Группы
|
### Группы
|
||||||
|
|
||||||
| Назначение | Имя | Тип |
|
| Назначение | Имя | Тип |
|
||||||
|-----------|-----|-----|
|
|-----------|-----|-----|
|
||||||
| Шапка | `ГруппаШапка` | horizontal |
|
| Шапка | `ГруппаШапка` | horizontal |
|
||||||
| Левая колонка | `ГруппаШапкаЛевая` | vertical |
|
| Левая колонка | `ГруппаШапкаЛевая` | vertical |
|
||||||
| Правая колонка | `ГруппаШапкаПравая` | vertical |
|
| Правая колонка | `ГруппаШапкаПравая` | vertical |
|
||||||
| Номер+Дата | `ГруппаНомерДата` | horizontal |
|
| Номер+Дата | `ГруппаНомерДата` | horizontal |
|
||||||
| Подвал | `ГруппаПодвал` | vertical |
|
| Подвал | `ГруппаПодвал` | vertical |
|
||||||
| Итоги | `ГруппаИтоги` | horizontal |
|
| Итоги | `ГруппаИтоги` | horizontal |
|
||||||
| Главная АКП формы | `ФормаКоманднаяПанель` | autoCmdBar |
|
| Главная АКП формы | `ФормаКоманднаяПанель` | autoCmdBar |
|
||||||
| Страницы | `ГруппаСтраницы` / `Страницы` | pages |
|
| Страницы | `ГруппаСтраницы` / `Страницы` | pages |
|
||||||
| Предупреждение | `ГруппаПредупреждение` | horizontal, visible:false |
|
| Предупреждение | `ГруппаПредупреждение` | horizontal, visible:false |
|
||||||
| Доп. секция | `ГруппаДополнительно` / `ГруппаПрочее` | vertical, collapse |
|
| Доп. секция | `ГруппаДополнительно` / `ГруппаПрочее` | vertical, collapse |
|
||||||
|
|
||||||
### Элементы
|
### Элементы
|
||||||
|
|
||||||
| Назначение | Имя |
|
| Назначение | Имя |
|
||||||
|-----------|-----|
|
|-----------|-----|
|
||||||
| Поле в таблице | `[Таблица][Поле]` |
|
| Поле в таблице | `[Таблица][Поле]` |
|
||||||
| Итог | `Итоги[Поле]` |
|
| Итог | `Итоги[Поле]` |
|
||||||
| Надпись-ссылка | `[Поле]Надпись` |
|
| Надпись-ссылка | `[Поле]Надпись` |
|
||||||
| Фильтр | `Отбор[Поле]` |
|
| Фильтр | `Отбор[Поле]` |
|
||||||
| Флажок фильтра | `Отбор[Поле]Использование` |
|
| Флажок фильтра | `Отбор[Поле]Использование` |
|
||||||
| Кнопка команды | `[Команда]Кнопка` |
|
| Кнопка команды | `[Команда]Кнопка` |
|
||||||
| Баннер-картинка | `[Баннер]Картинка` |
|
| Баннер-картинка | `[Баннер]Картинка` |
|
||||||
| Баннер-надпись | `[Баннер]Надпись` |
|
| Баннер-надпись | `[Баннер]Надпись` |
|
||||||
| Подменю | `Подменю[Действие]` |
|
| Подменю | `Подменю[Действие]` |
|
||||||
|
|
||||||
### Обработчики событий
|
### Обработчики событий
|
||||||
|
|
||||||
Имя = имя элемента + суффикс на русском:
|
Имя = имя элемента + суффикс на русском:
|
||||||
|
|
||||||
| Событие | Суффикс | Пример |
|
| Событие | Суффикс | Пример |
|
||||||
|---------|---------|--------|
|
|---------|---------|--------|
|
||||||
| OnChange | ПриИзменении | `ОрганизацияПриИзменении` |
|
| OnChange | ПриИзменении | `ОрганизацияПриИзменении` |
|
||||||
| StartChoice | НачалоВыбора | `КонтрагентНачалоВыбора` |
|
| StartChoice | НачалоВыбора | `КонтрагентНачалоВыбора` |
|
||||||
| Click | Нажатие | `ЦеныИВалютаНажатие` |
|
| Click | Нажатие | `ЦеныИВалютаНажатие` |
|
||||||
| OnEditEnd | ПриОкончанииРедактирования | `ТоварыПриОкончанииРедактирования` |
|
| OnEditEnd | ПриОкончанииРедактирования | `ТоварыПриОкончанииРедактирования` |
|
||||||
| OnStartEdit | ПриНачалеРедактирования | `ТоварыПриНачалеРедактирования` |
|
| OnStartEdit | ПриНачалеРедактирования | `ТоварыПриНачалеРедактирования` |
|
||||||
|
|
||||||
Обработчики формы: `ПриСозданииНаСервере`, `ПриОткрытии`, `ПередЗакрытием`, `ОбработкаОповещения`.
|
Обработчики формы: `ПриСозданииНаСервере`, `ПриОткрытии`, `ПередЗакрытием`, `ОбработкаОповещения`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Принципы компоновки
|
## Принципы компоновки
|
||||||
|
|
||||||
1. **Порядок чтения.** Сверху вниз, слева направо. Самое важное — вверху.
|
1. **Порядок чтения.** Сверху вниз, слева направо. Самое важное — вверху.
|
||||||
2. **Двухколоночная шапка.** Основные реквизиты слева (контрагент, склад), организационные справа (организация, подразделение).
|
2. **Двухколоночная шапка.** Основные реквизиты слева (контрагент, склад), организационные справа (организация, подразделение).
|
||||||
3. **Кнопки действий — на главной АКП формы** (`autoCmdBar`), не в отдельной группе на форме. Главная кнопка — `defaultButton: true`. Закрыть — всегда последняя.
|
3. **Кнопки действий — на главной АКП формы** (`autoCmdBar`), не в отдельной группе на форме. Главная кнопка — `defaultButton: true`. Закрыть — всегда последняя.
|
||||||
4. **Таблицы — основная область.** Табличные части занимают большую часть формы, обычно на Pages.
|
4. **Таблицы — основная область.** Табличные части занимают большую часть формы, обычно на Pages.
|
||||||
5. **Итоги рядом с таблицей.** В подвале, горизонтальная группа, все поля readOnly.
|
5. **Итоги рядом с таблицей.** В подвале, горизонтальная группа, все поля readOnly.
|
||||||
6. **Фильтры — отдельная зона.** Над списком, alwaysHorizontal, пара «флажок + поле» на каждый фильтр.
|
6. **Фильтры — отдельная зона.** Над списком, alwaysHorizontal, пара «флажок + поле» на каждый фильтр.
|
||||||
7. **Скрытые элементы для состояний.** Баннеры, предупреждения — `visible: false`, показываются программно.
|
7. **Скрытые элементы для состояний.** Баннеры, предупреждения — `visible: false`, показываются программно.
|
||||||
8. **Надписи-ссылки для диалогов.** `labelField` с `hyperlink: true` и событием Click.
|
8. **Надписи-ссылки для диалогов.** `labelField` с `hyperlink: true` и событием Click.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Продвинутые паттерны (ERP)
|
## Продвинутые паттерны (ERP)
|
||||||
|
|
||||||
### Сворачиваемые группы
|
### Сворачиваемые группы
|
||||||
|
|
||||||
Для необязательных секций (подписи, дополнительно, прочее):
|
Для необязательных секций (подписи, дополнительно, прочее):
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "group": "collapsible", "name": "ГруппаПодписи", "title": "Подписи",
|
{ "group": "collapsible", "name": "ГруппаПодписи", "title": "Подписи",
|
||||||
"collapsed": true, "children": [...] }
|
"collapsed": true, "children": [...] }
|
||||||
```
|
```
|
||||||
|
|
||||||
### Баннер-предупреждение
|
### Баннер-предупреждение
|
||||||
|
|
||||||
Группа «картинка + надпись», скрыта по умолчанию, показывается программно:
|
Группа «картинка + надпись», скрыта по умолчанию, показывается программно:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "group": "horizontal", "name": "ГруппаПредупреждение", "showTitle": false,
|
{ "group": "horizontal", "name": "ГруппаПредупреждение", "showTitle": false,
|
||||||
"visible": false, "children": [
|
"visible": false, "children": [
|
||||||
{ "picture": "ПредупреждениеКартинка" },
|
{ "picture": "ПредупреждениеКартинка" },
|
||||||
{ "label": "ПредупреждениеНадпись", "title": "Текст", "maxWidth": 76, "autoMaxWidth": false }
|
{ "label": "ПредупреждениеНадпись", "title": "Текст", "maxWidth": 76, "autoMaxWidth": false }
|
||||||
]}
|
]}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Popup-меню в командной панели
|
### Popup-меню в командной панели
|
||||||
|
|
||||||
Группировка связанных команд (печать, отправка) в одну кнопку с иконкой:
|
Группировка связанных команд (печать, отправка) в одну кнопку с иконкой:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "cmdBar": "КоманднаяПанель", "children": [
|
{ "cmdBar": "КоманднаяПанель", "children": [
|
||||||
{ "popup": "ПодменюПечать", "title": "Печать",
|
{ "popup": "ПодменюПечать", "title": "Печать",
|
||||||
"picture": "StdPicture.Print", "representation": "Picture", "children": [
|
"picture": "StdPicture.Print", "representation": "Picture", "children": [
|
||||||
{ "button": "ПечатьНакладная", "command": "Печать" },
|
{ "button": "ПечатьНакладная", "command": "Печать" },
|
||||||
{ "button": "ПечатьСчёт", "command": "ПечатьСчёт" }
|
{ "button": "ПечатьСчёт", "command": "ПечатьСчёт" }
|
||||||
]}
|
]}
|
||||||
]}
|
]}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Форма без стандартной командной панели
|
### Форма без стандартной командной панели
|
||||||
|
|
||||||
Для модальных диалогов и мастеров:
|
Для модальных диалогов и мастеров:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "properties": { "commandBarLocation": "None", "windowOpeningMode": "LockWholeInterface" } }
|
{ "properties": { "commandBarLocation": "None", "windowOpeningMode": "LockWholeInterface" } }
|
||||||
```
|
```
|
||||||
|
|
||||||
### Надпись-гиперссылка
|
### Надпись-гиперссылка
|
||||||
|
|
||||||
Вместо кнопки для открытия подформ (ЦеныИВалюта, УчётнаяПолитика):
|
Вместо кнопки для открытия подформ (ЦеныИВалюта, УчётнаяПолитика):
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "labelField": "ЦеныИВалютаНадпись", "path": "ЦеныИВалюта", "hyperlink": true, "on": ["Click"] }
|
{ "labelField": "ЦеныИВалютаНадпись", "path": "ЦеныИВалюта", "hyperlink": true, "on": ["Click"] }
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Пример: форма обработки (полный DSL)
|
## Пример: форма обработки (полный DSL)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"title": "Загрузка данных из CSV",
|
"title": "Загрузка данных из CSV",
|
||||||
"properties": { "autoTitle": false, "windowOpeningMode": "LockOwnerWindow" },
|
"properties": { "autoTitle": false, "windowOpeningMode": "LockOwnerWindow" },
|
||||||
"events": { "OnCreateAtServer": "ПриСозданииНаСервере" },
|
"events": { "OnCreateAtServer": "ПриСозданииНаСервере" },
|
||||||
"elements": [
|
"elements": [
|
||||||
{ "group": "vertical", "name": "ГруппаПараметры", "children": [
|
{ "group": "vertical", "name": "ГруппаПараметры", "children": [
|
||||||
{ "input": "ФайлЗагрузки", "path": "ФайлЗагрузки", "title": "Файл", "clearButton": true, "horizontalStretch": true, "on": ["StartChoice"] },
|
{ "input": "ФайлЗагрузки", "path": "ФайлЗагрузки", "title": "Файл", "clearButton": true, "horizontalStretch": true, "on": ["StartChoice"] },
|
||||||
{ "input": "Кодировка", "path": "Кодировка" },
|
{ "input": "Кодировка", "path": "Кодировка" },
|
||||||
{ "input": "Разделитель", "path": "Разделитель", "title": "Разделитель колонок" }
|
{ "input": "Разделитель", "path": "Разделитель", "title": "Разделитель колонок" }
|
||||||
]},
|
]},
|
||||||
{ "table": "Данные", "path": "Объект.Данные", "on": ["OnStartEdit"], "columns": [
|
{ "table": "Данные", "path": "Объект.Данные", "on": ["OnStartEdit"], "columns": [
|
||||||
{ "input": "ДанныеНомерСтроки", "path": "Объект.Данные.LineNumber", "readOnly": true, "title": "№" },
|
{ "input": "ДанныеНомерСтроки", "path": "Объект.Данные.LineNumber", "readOnly": true, "title": "№" },
|
||||||
{ "input": "ДанныеНаименование", "path": "Объект.Данные.Наименование" },
|
{ "input": "ДанныеНаименование", "path": "Объект.Данные.Наименование" },
|
||||||
{ "input": "ДанныеКоличество", "path": "Объект.Данные.Количество", "on": ["OnChange"] },
|
{ "input": "ДанныеКоличество", "path": "Объект.Данные.Количество", "on": ["OnChange"] },
|
||||||
{ "input": "ДанныеСумма", "path": "Объект.Данные.Сумма", "readOnly": true }
|
{ "input": "ДанныеСумма", "path": "Объект.Данные.Сумма", "readOnly": true }
|
||||||
]},
|
]},
|
||||||
{ "autoCmdBar": "ФормаКоманднаяПанель", "children": [
|
{ "autoCmdBar": "ФормаКоманднаяПанель", "children": [
|
||||||
{ "button": "Загрузить", "command": "Загрузить", "title": "Загрузить из файла", "defaultButton": true },
|
{ "button": "Загрузить", "command": "Загрузить", "title": "Загрузить из файла", "defaultButton": true },
|
||||||
{ "button": "Очистить", "command": "Очистить", "title": "Очистить таблицу" },
|
{ "button": "Очистить", "command": "Очистить", "title": "Очистить таблицу" },
|
||||||
{ "button": "Закрыть", "stdCommand": "Close" }
|
{ "button": "Закрыть", "stdCommand": "Close" }
|
||||||
]}
|
]}
|
||||||
],
|
],
|
||||||
"attributes": [
|
"attributes": [
|
||||||
{ "name": "Объект", "type": "ExternalDataProcessorObject.ЗагрузкаИзCSV", "main": true },
|
{ "name": "Объект", "type": "ExternalDataProcessorObject.ЗагрузкаИзCSV", "main": true },
|
||||||
{ "name": "ФайлЗагрузки", "type": "string" },
|
{ "name": "ФайлЗагрузки", "type": "string" },
|
||||||
{ "name": "Кодировка", "type": "string(20)" },
|
{ "name": "Кодировка", "type": "string(20)" },
|
||||||
{ "name": "Разделитель", "type": "string(5)" }
|
{ "name": "Разделитель", "type": "string(5)" }
|
||||||
],
|
],
|
||||||
"commands": [
|
"commands": [
|
||||||
{ "name": "Загрузить", "action": "ЗагрузитьОбработка" },
|
{ "name": "Загрузить", "action": "ЗагрузитьОбработка" },
|
||||||
{ "name": "Очистить", "action": "ОчиститьОбработка" }
|
{ "name": "Очистить", "action": "ОчиститьОбработка" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,47 +1,47 @@
|
|||||||
---
|
---
|
||||||
name: form-remove
|
name: form-remove
|
||||||
description: Удалить форму из объекта 1С (обработка, отчёт, справочник, документ и др.)
|
description: Удалить форму из объекта 1С (обработка, отчёт, справочник, документ и др.)
|
||||||
argument-hint: <ObjectName> <FormName>
|
argument-hint: <ObjectName> <FormName>
|
||||||
disable-model-invocation: true
|
disable-model-invocation: true
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Write
|
- Write
|
||||||
- Edit
|
- Edit
|
||||||
- Glob
|
- Glob
|
||||||
- Grep
|
- Grep
|
||||||
---
|
---
|
||||||
|
|
||||||
# /form-remove — Удаление формы
|
# /form-remove — Удаление формы
|
||||||
|
|
||||||
Удаляет форму и убирает её регистрацию из корневого XML объекта.
|
Удаляет форму и убирает её регистрацию из корневого XML объекта.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/form-remove <ObjectName> <FormName>
|
/form-remove <ObjectName> <FormName>
|
||||||
```
|
```
|
||||||
|
|
||||||
| Параметр | Обязательный | По умолчанию | Описание |
|
| Параметр | Обязательный | По умолчанию | Описание |
|
||||||
|------------|:------------:|--------------|-------------------------------------|
|
|------------|:------------:|--------------|-------------------------------------|
|
||||||
| ObjectName | да | — | Имя объекта |
|
| ObjectName | да | — | Имя объекта |
|
||||||
| FormName | да | — | Имя формы для удаления |
|
| FormName | да | — | Имя формы для удаления |
|
||||||
| SrcDir | нет | `src` | Каталог исходников |
|
| SrcDir | нет | `src` | Каталог исходников |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/remove-form.ps1" -ObjectName "<ObjectName>" -FormName "<FormName>" [-SrcDir "<SrcDir>"]
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/remove-form.ps1" -ObjectName "<ObjectName>" -FormName "<FormName>" [-SrcDir "<SrcDir>"]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Что удаляется
|
## Что удаляется
|
||||||
|
|
||||||
```
|
```
|
||||||
<SrcDir>/<ObjectName>/Forms/<FormName>.xml # Метаданные формы
|
<SrcDir>/<ObjectName>/Forms/<FormName>.xml # Метаданные формы
|
||||||
<SrcDir>/<ObjectName>/Forms/<FormName>/ # Каталог формы (рекурсивно)
|
<SrcDir>/<ObjectName>/Forms/<FormName>/ # Каталог формы (рекурсивно)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Что модифицируется
|
## Что модифицируется
|
||||||
|
|
||||||
- `<SrcDir>/<ObjectName>.xml` — убирается `<Form>` из `ChildObjects`
|
- `<SrcDir>/<ObjectName>.xml` — убирается `<Form>` из `ChildObjects`
|
||||||
- Если удаляемая форма была DefaultForm — очищается значение DefaultForm
|
- Если удаляемая форма была DefaultForm — очищается значение DefaultForm
|
||||||
|
|||||||
@@ -1,89 +1,89 @@
|
|||||||
# form-remove v1.2 — Remove form from 1C object
|
# form-remove v1.2 — Remove form from 1C object
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[Alias("ProcessorName")]
|
[Alias("ProcessorName")]
|
||||||
[string]$ObjectName,
|
[string]$ObjectName,
|
||||||
|
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$FormName,
|
[string]$FormName,
|
||||||
|
|
||||||
[string]$SrcDir = "src"
|
[string]$SrcDir = "src"
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Проверки ---
|
# --- Проверки ---
|
||||||
|
|
||||||
$rootXmlPath = Join-Path $SrcDir "$ObjectName.xml"
|
$rootXmlPath = Join-Path $SrcDir "$ObjectName.xml"
|
||||||
if (-not (Test-Path $rootXmlPath)) {
|
if (-not (Test-Path $rootXmlPath)) {
|
||||||
Write-Error "Корневой файл обработки не найден: $rootXmlPath"
|
Write-Error "Корневой файл обработки не найден: $rootXmlPath"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
$processorDir = Join-Path $SrcDir $ObjectName
|
$processorDir = Join-Path $SrcDir $ObjectName
|
||||||
$formsDir = Join-Path $processorDir "Forms"
|
$formsDir = Join-Path $processorDir "Forms"
|
||||||
$formMetaPath = Join-Path $formsDir "$FormName.xml"
|
$formMetaPath = Join-Path $formsDir "$FormName.xml"
|
||||||
$formDir = Join-Path $formsDir $FormName
|
$formDir = Join-Path $formsDir $FormName
|
||||||
|
|
||||||
if (-not (Test-Path $formMetaPath)) {
|
if (-not (Test-Path $formMetaPath)) {
|
||||||
Write-Error "Метаданные формы не найдены: $formMetaPath"
|
Write-Error "Метаданные формы не найдены: $formMetaPath"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Удаление файлов ---
|
# --- Удаление файлов ---
|
||||||
|
|
||||||
if (Test-Path $formDir) {
|
if (Test-Path $formDir) {
|
||||||
Remove-Item -Path $formDir -Recurse -Force
|
Remove-Item -Path $formDir -Recurse -Force
|
||||||
Write-Host "[OK] Удалён каталог: $formDir"
|
Write-Host "[OK] Удалён каталог: $formDir"
|
||||||
}
|
}
|
||||||
|
|
||||||
Remove-Item -Path $formMetaPath -Force
|
Remove-Item -Path $formMetaPath -Force
|
||||||
Write-Host "[OK] Удалён файл: $formMetaPath"
|
Write-Host "[OK] Удалён файл: $formMetaPath"
|
||||||
|
|
||||||
# --- Модификация корневого XML ---
|
# --- Модификация корневого XML ---
|
||||||
|
|
||||||
$rootXmlFull = Resolve-Path $rootXmlPath
|
$rootXmlFull = Resolve-Path $rootXmlPath
|
||||||
$xmlDoc = New-Object System.Xml.XmlDocument
|
$xmlDoc = New-Object System.Xml.XmlDocument
|
||||||
$xmlDoc.PreserveWhitespace = $true
|
$xmlDoc.PreserveWhitespace = $true
|
||||||
$xmlDoc.Load($rootXmlFull.Path)
|
$xmlDoc.Load($rootXmlFull.Path)
|
||||||
|
|
||||||
$nsMgr = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
|
$nsMgr = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
|
||||||
$nsMgr.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
|
$nsMgr.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
|
||||||
|
|
||||||
# Удалить <Form>FormName</Form> из ChildObjects
|
# Удалить <Form>FormName</Form> из ChildObjects
|
||||||
$formNodes = $xmlDoc.SelectNodes("//md:ChildObjects/md:Form", $nsMgr)
|
$formNodes = $xmlDoc.SelectNodes("//md:ChildObjects/md:Form", $nsMgr)
|
||||||
foreach ($node in $formNodes) {
|
foreach ($node in $formNodes) {
|
||||||
if ($node.InnerText -eq $FormName) {
|
if ($node.InnerText -eq $FormName) {
|
||||||
$parent = $node.ParentNode
|
$parent = $node.ParentNode
|
||||||
# Удалить предшествующий whitespace
|
# Удалить предшествующий whitespace
|
||||||
$prev = $node.PreviousSibling
|
$prev = $node.PreviousSibling
|
||||||
if ($prev -and $prev.NodeType -eq [System.Xml.XmlNodeType]::Whitespace) {
|
if ($prev -and $prev.NodeType -eq [System.Xml.XmlNodeType]::Whitespace) {
|
||||||
$parent.RemoveChild($prev) | Out-Null
|
$parent.RemoveChild($prev) | Out-Null
|
||||||
}
|
}
|
||||||
$parent.RemoveChild($node) | Out-Null
|
$parent.RemoveChild($node) | Out-Null
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Очистить DefaultForm если указывала на эту форму
|
# Очистить DefaultForm если указывала на эту форму
|
||||||
$defaultForm = $xmlDoc.SelectSingleNode("//md:DefaultForm", $nsMgr)
|
$defaultForm = $xmlDoc.SelectSingleNode("//md:DefaultForm", $nsMgr)
|
||||||
if ($defaultForm -and $defaultForm.InnerText -match "Form\.$FormName$") {
|
if ($defaultForm -and $defaultForm.InnerText -match "Form\.$FormName$") {
|
||||||
$defaultForm.InnerText = ""
|
$defaultForm.InnerText = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
# Сохранить с BOM
|
# Сохранить с BOM
|
||||||
$encBom = New-Object System.Text.UTF8Encoding($true)
|
$encBom = New-Object System.Text.UTF8Encoding($true)
|
||||||
$settings = New-Object System.Xml.XmlWriterSettings
|
$settings = New-Object System.Xml.XmlWriterSettings
|
||||||
$settings.Encoding = $encBom
|
$settings.Encoding = $encBom
|
||||||
$settings.Indent = $false
|
$settings.Indent = $false
|
||||||
|
|
||||||
$stream = New-Object System.IO.FileStream($rootXmlFull.Path, [System.IO.FileMode]::Create)
|
$stream = New-Object System.IO.FileStream($rootXmlFull.Path, [System.IO.FileMode]::Create)
|
||||||
$writer = [System.Xml.XmlWriter]::Create($stream, $settings)
|
$writer = [System.Xml.XmlWriter]::Create($stream, $settings)
|
||||||
$xmlDoc.Save($writer)
|
$xmlDoc.Save($writer)
|
||||||
$writer.Close()
|
$writer.Close()
|
||||||
$stream.Close()
|
$stream.Close()
|
||||||
|
|
||||||
Write-Host "[OK] Форма $FormName удалена из $rootXmlPath"
|
Write-Host "[OK] Форма $FormName удалена из $rootXmlPath"
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
---
|
---
|
||||||
name: form-validate
|
name: form-validate
|
||||||
description: Валидация управляемой формы 1С. Используй после создания или модификации формы для проверки корректности. При наличии BaseForm автоматически проверяет callType и ID расширений
|
description: Валидация управляемой формы 1С. Используй после создания или модификации формы для проверки корректности. При наличии BaseForm автоматически проверяет callType и ID расширений
|
||||||
argument-hint: <FormPath> [-Detailed] [-MaxErrors 30]
|
argument-hint: <FormPath> [-Detailed] [-MaxErrors 30]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /form-validate — валидация управляемой формы 1С
|
# /form-validate — валидация управляемой формы 1С
|
||||||
|
|
||||||
Проверяет Form.xml на структурные ошибки: уникальность ID, наличие companion-элементов, корректность ссылок DataPath и команд.
|
Проверяет Form.xml на структурные ошибки: уникальность ID, наличие companion-элементов, корректность ссылок DataPath и команд.
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Обяз. | Умолч. | Описание |
|
| Параметр | Обяз. | Умолч. | Описание |
|
||||||
|-----------|:-----:|---------|-----------------------------------------|
|
|-----------|:-----:|---------|-----------------------------------------|
|
||||||
| FormPath | да | — | Путь к файлу Form.xml |
|
| FormPath | да | — | Путь к файлу Form.xml |
|
||||||
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
||||||
| MaxErrors | нет | 30 | Остановиться после N ошибок |
|
| MaxErrors | нет | 30 | Остановиться после N ошибок |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-validate.ps1" -FormPath "Catalogs/Номенклатура/Forms/ФормаЭлемента"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-validate.ps1" -FormPath "Catalogs/Номенклатура/Forms/ФормаЭлемента"
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-validate.ps1" -FormPath "src/МояОбработка/Forms/Форма/Ext/Form.xml"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-validate.ps1" -FormPath "src/МояОбработка/Forms/Форма/Ext/Form.xml"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,44 +1,44 @@
|
|||||||
---
|
---
|
||||||
name: help-add
|
name: help-add
|
||||||
description: Добавить встроенную справку к объекту 1С (обработка, отчёт, справочник, документ и др.). Используй когда пользователь просит добавить справку, help, встроенную помощь к объекту
|
description: Добавить встроенную справку к объекту 1С (обработка, отчёт, справочник, документ и др.). Используй когда пользователь просит добавить справку, help, встроенную помощь к объекту
|
||||||
argument-hint: <ObjectName>
|
argument-hint: <ObjectName>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Write
|
- Write
|
||||||
- Edit
|
- Edit
|
||||||
- Glob
|
- Glob
|
||||||
- Grep
|
- Grep
|
||||||
---
|
---
|
||||||
|
|
||||||
# /help-add — Добавление справки
|
# /help-add — Добавление справки
|
||||||
|
|
||||||
Добавляет встроенную справку к объекту: файл метаданных `Help.xml`, HTML-страницу и при необходимости обновляет метаданные форм.
|
Добавляет встроенную справку к объекту: файл метаданных `Help.xml`, HTML-страницу и при необходимости обновляет метаданные форм.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
/help-add <ObjectName> [Lang] [SrcDir]
|
/help-add <ObjectName> [Lang] [SrcDir]
|
||||||
```
|
```
|
||||||
|
|
||||||
| Параметр | Обязательный | По умолчанию | Описание |
|
| Параметр | Обязательный | По умолчанию | Описание |
|
||||||
|------------|:------------:|--------------|-------------------------------------|
|
|------------|:------------:|--------------|-------------------------------------|
|
||||||
| ObjectName | да | — | Путь объекта относительно SrcDir (например `Catalogs/МойСправочник`, `DataProcessors/МояОбработка`) |
|
| ObjectName | да | — | Путь объекта относительно SrcDir (например `Catalogs/МойСправочник`, `DataProcessors/МояОбработка`) |
|
||||||
| Lang | нет | `ru` | Код языка справки |
|
| Lang | нет | `ru` | Код языка справки |
|
||||||
| SrcDir | нет | `src` | Каталог исходников |
|
| SrcDir | нет | `src` | Каталог исходников |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/add-help.ps1" -ObjectName "<ObjectName>" [-Lang "<Lang>"] [-SrcDir "<SrcDir>"]
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/add-help.ps1" -ObjectName "<ObjectName>" [-Lang "<Lang>"] [-SrcDir "<SrcDir>"]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Что делает скрипт
|
## Что делает скрипт
|
||||||
|
|
||||||
- Создаёт `Ext/Help.xml` и `Ext/Help/ru.html` — шаблон справки
|
- Создаёт `Ext/Help.xml` и `Ext/Help/ru.html` — шаблон справки
|
||||||
- Если у объекта есть формы — добавляет `<IncludeHelpInContents>` в метаданные форм (если отсутствует)
|
- Если у объекта есть формы — добавляет `<IncludeHelpInContents>` в метаданные форм (если отсутствует)
|
||||||
- Справка **не регистрируется** в `ChildObjects` — достаточно наличия файлов
|
- Справка **не регистрируется** в `ChildObjects` — достаточно наличия файлов
|
||||||
|
|
||||||
## После запуска
|
## После запуска
|
||||||
|
|
||||||
Отредактируй `Ext/Help/ru.html` — наполни содержимым справки (стандартный HTML: `<h1>`..`<h4>`, `<p>`, `<ul>`, `<table>` и т.д.). Кнопка справки появится автоматически через `Autofill` в AutoCommandBar формы.
|
Отредактируй `Ext/Help/ru.html` — наполни содержимым справки (стандартный HTML: `<h1>`..`<h4>`, `<p>`, `<ul>`, `<table>` и т.д.). Кнопка справки появится автоматически через `Autofill` в AutoCommandBar формы.
|
||||||
|
|||||||
@@ -1,259 +1,259 @@
|
|||||||
# help-add v1.7 — Add built-in help to 1C object
|
# help-add v1.7 — Add built-in help to 1C object
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$ObjectName,
|
[string]$ObjectName,
|
||||||
|
|
||||||
[string]$Lang = "ru",
|
[string]$Lang = "ru",
|
||||||
|
|
||||||
[string]$SrcDir = "src"
|
[string]$SrcDir = "src"
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Support guard (Ext/ParentConfigurations.bin) ---
|
# --- Support guard (Ext/ParentConfigurations.bin) ---
|
||||||
# See docs/1c-support-state-spec.md. Blocks edits of vendor objects "на замке" /
|
# See docs/1c-support-state-spec.md. Blocks edits of vendor objects "на замке" /
|
||||||
# read-only configs unless allowed. Trigger = bin present; reaction from
|
# read-only configs unless allowed. Trigger = bin present; reaction from
|
||||||
# .v8-project.json editingAllowedCheck (deny|warn|off, default deny). Never
|
# .v8-project.json editingAllowedCheck (deny|warn|off, default deny). Never
|
||||||
# throws — guard errors degrade to allow.
|
# throws — guard errors degrade to allow.
|
||||||
function Get-RootUuid([string]$xmlPath) {
|
function Get-RootUuid([string]$xmlPath) {
|
||||||
if (-not (Test-Path $xmlPath)) { return $null }
|
if (-not (Test-Path $xmlPath)) { return $null }
|
||||||
try {
|
try {
|
||||||
[xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8
|
[xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8
|
||||||
$el = $mx.DocumentElement.FirstChild
|
$el = $mx.DocumentElement.FirstChild
|
||||||
while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling }
|
while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling }
|
||||||
if ($el) { $u = $el.GetAttribute("uuid"); if ($u) { return $u } }
|
if ($el) { $u = $el.GetAttribute("uuid"); if ($u) { return $u } }
|
||||||
} catch {}
|
} catch {}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
function Find-V8Project([string]$startDir) {
|
function Find-V8Project([string]$startDir) {
|
||||||
$d = $startDir
|
$d = $startDir
|
||||||
for ($i = 0; $i -lt 20 -and $d; $i++) {
|
for ($i = 0; $i -lt 20 -and $d; $i++) {
|
||||||
$pj = Join-Path $d ".v8-project.json"
|
$pj = Join-Path $d ".v8-project.json"
|
||||||
if (Test-Path $pj) { return $pj }
|
if (Test-Path $pj) { return $pj }
|
||||||
$parent = [System.IO.Path]::GetDirectoryName($d)
|
$parent = [System.IO.Path]::GetDirectoryName($d)
|
||||||
if ($parent -eq $d) { break }
|
if ($parent -eq $d) { break }
|
||||||
$d = $parent
|
$d = $parent
|
||||||
}
|
}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
function Get-EditMode([string]$cfgDir) {
|
function Get-EditMode([string]$cfgDir) {
|
||||||
try {
|
try {
|
||||||
$pj = Find-V8Project (Get-Location).Path
|
$pj = Find-V8Project (Get-Location).Path
|
||||||
if (-not $pj) { $pj = Find-V8Project $cfgDir }
|
if (-not $pj) { $pj = Find-V8Project $cfgDir }
|
||||||
if (-not $pj) { return 'deny' }
|
if (-not $pj) { return 'deny' }
|
||||||
$proj = Get-Content -Raw $pj | ConvertFrom-Json
|
$proj = Get-Content -Raw $pj | ConvertFrom-Json
|
||||||
$cfgFull = [System.IO.Path]::GetFullPath($cfgDir).TrimEnd('\', '/')
|
$cfgFull = [System.IO.Path]::GetFullPath($cfgDir).TrimEnd('\', '/')
|
||||||
if ($proj.databases) {
|
if ($proj.databases) {
|
||||||
foreach ($db in $proj.databases) {
|
foreach ($db in $proj.databases) {
|
||||||
if ($db.configSrc) {
|
if ($db.configSrc) {
|
||||||
$src = [System.IO.Path]::GetFullPath($db.configSrc).TrimEnd('\', '/')
|
$src = [System.IO.Path]::GetFullPath($db.configSrc).TrimEnd('\', '/')
|
||||||
if ($cfgFull -eq $src -or $cfgFull.StartsWith($src + [System.IO.Path]::DirectorySeparatorChar)) {
|
if ($cfgFull -eq $src -or $cfgFull.StartsWith($src + [System.IO.Path]::DirectorySeparatorChar)) {
|
||||||
if ($db.editingAllowedCheck) { return $db.editingAllowedCheck }
|
if ($db.editingAllowedCheck) { return $db.editingAllowedCheck }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($proj.editingAllowedCheck) { return $proj.editingAllowedCheck }
|
if ($proj.editingAllowedCheck) { return $proj.editingAllowedCheck }
|
||||||
return 'deny'
|
return 'deny'
|
||||||
} catch { return 'deny' }
|
} catch { return 'deny' }
|
||||||
}
|
}
|
||||||
function Assert-EditAllowed([string]$targetPath, [string]$require) {
|
function Assert-EditAllowed([string]$targetPath, [string]$require) {
|
||||||
try {
|
try {
|
||||||
$rp = $targetPath
|
$rp = $targetPath
|
||||||
try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {}
|
try { $rp = (Resolve-Path $targetPath -ErrorAction Stop).Path } catch {}
|
||||||
$elemUuid = Get-RootUuid $rp
|
$elemUuid = Get-RootUuid $rp
|
||||||
$cfgDir = $null; $binPath = $null
|
$cfgDir = $null; $binPath = $null
|
||||||
$d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) }
|
$d = if (Test-Path $rp -PathType Container) { $rp } else { [System.IO.Path]::GetDirectoryName($rp) }
|
||||||
for ($i = 0; $i -lt 12 -and $d; $i++) {
|
for ($i = 0; $i -lt 12 -and $d; $i++) {
|
||||||
if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" }
|
if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" }
|
||||||
if (-not $cfgDir) {
|
if (-not $cfgDir) {
|
||||||
$cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin"
|
$cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin"
|
||||||
if ((Test-Path $cand) -or (Test-Path (Join-Path $d "Configuration.xml"))) { $cfgDir = $d; $binPath = $cand }
|
if ((Test-Path $cand) -or (Test-Path (Join-Path $d "Configuration.xml"))) { $cfgDir = $d; $binPath = $cand }
|
||||||
}
|
}
|
||||||
if ($elemUuid -and $cfgDir) { break }
|
if ($elemUuid -and $cfgDir) { break }
|
||||||
$parent = [System.IO.Path]::GetDirectoryName($d)
|
$parent = [System.IO.Path]::GetDirectoryName($d)
|
||||||
if ($parent -eq $d) { break }
|
if ($parent -eq $d) { break }
|
||||||
$d = $parent
|
$d = $parent
|
||||||
}
|
}
|
||||||
# New object (no element file): fall back to config root uuid.
|
# New object (no element file): fall back to config root uuid.
|
||||||
if (-not $elemUuid -and $cfgDir) { $elemUuid = Get-RootUuid (Join-Path $cfgDir "Configuration.xml") }
|
if (-not $elemUuid -and $cfgDir) { $elemUuid = Get-RootUuid (Join-Path $cfgDir "Configuration.xml") }
|
||||||
if (-not $binPath -or -not (Test-Path $binPath)) { return }
|
if (-not $binPath -or -not (Test-Path $binPath)) { return }
|
||||||
$bytes = [System.IO.File]::ReadAllBytes($binPath)
|
$bytes = [System.IO.File]::ReadAllBytes($binPath)
|
||||||
if ($bytes.Length -le 32) { return }
|
if ($bytes.Length -le 32) { return }
|
||||||
$start = 0
|
$start = 0
|
||||||
if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { $start = 3 }
|
if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { $start = 3 }
|
||||||
$text = [System.Text.Encoding]::UTF8.GetString($bytes, $start, $bytes.Length - $start)
|
$text = [System.Text.Encoding]::UTF8.GetString($bytes, $start, $bytes.Length - $start)
|
||||||
$hm = [regex]::Match($text, '^\{6,(\d+),(\d+),')
|
$hm = [regex]::Match($text, '^\{6,(\d+),(\d+),')
|
||||||
if (-not $hm.Success) { return }
|
if (-not $hm.Success) { return }
|
||||||
$G = [int]$hm.Groups[1].Value
|
$G = [int]$hm.Groups[1].Value
|
||||||
$K = [int]$hm.Groups[2].Value
|
$K = [int]$hm.Groups[2].Value
|
||||||
if ($K -eq 0) { return }
|
if ($K -eq 0) { return }
|
||||||
$best = $null
|
$best = $null
|
||||||
if ($elemUuid) {
|
if ($elemUuid) {
|
||||||
$u = [regex]::Escape($elemUuid.ToLower())
|
$u = [regex]::Escape($elemUuid.ToLower())
|
||||||
foreach ($m in [regex]::Matches($text, "([0-2]),0,$u")) {
|
foreach ($m in [regex]::Matches($text, "([0-2]),0,$u")) {
|
||||||
$f1 = [int]$m.Groups[1].Value
|
$f1 = [int]$m.Groups[1].Value
|
||||||
if ($null -eq $best -or $f1 -lt $best) { $best = $f1 }
|
if ($null -eq $best -or $f1 -lt $best) { $best = $f1 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$blocked = $false; $code = ""; $reason = ""
|
$blocked = $false; $code = ""; $reason = ""
|
||||||
if ($G -eq 1) { $blocked = $true; $code = "capability-off"; $reason = "возможность изменения конфигурации выключена (вся конфигурация read-only)" }
|
if ($G -eq 1) { $blocked = $true; $code = "capability-off"; $reason = "возможность изменения конфигурации выключена (вся конфигурация read-only)" }
|
||||||
elseif ($require -eq 'removed') {
|
elseif ($require -eq 'removed') {
|
||||||
if ($null -ne $best -and $best -ne 2) { $blocked = $true; $code = "not-removed"; $reason = "объект не снят с поддержки — удаление сломает обновления" }
|
if ($null -ne $best -and $best -ne 2) { $blocked = $true; $code = "not-removed"; $reason = "объект не снят с поддержки — удаление сломает обновления" }
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ($null -ne $best -and $best -eq 0) { $blocked = $true; $code = "locked"; $reason = "объект на замке — редактирование сломает обновления" }
|
if ($null -ne $best -and $best -eq 0) { $blocked = $true; $code = "locked"; $reason = "объект на замке — редактирование сломает обновления" }
|
||||||
}
|
}
|
||||||
if (-not $blocked) { return }
|
if (-not $blocked) { return }
|
||||||
$mode = Get-EditMode $cfgDir
|
$mode = Get-EditMode $cfgDir
|
||||||
if ($mode -eq 'off') { return }
|
if ($mode -eq 'off') { return }
|
||||||
# Use Console.Error (not Write-Error) — under ErrorActionPreference=Stop the
|
# Use Console.Error (not Write-Error) — under ErrorActionPreference=Stop the
|
||||||
# latter throws and would be swallowed by this function's own catch.
|
# latter throws and would be swallowed by this function's own catch.
|
||||||
if ($mode -eq 'warn') { [Console]::Error.WriteLine("[support-guard] ПРЕДУПРЕЖДЕНИЕ: $reason. Цель: $rp"); return }
|
if ($mode -eq 'warn') { [Console]::Error.WriteLine("[support-guard] ПРЕДУПРЕЖДЕНИЕ: $reason. Цель: $rp"); return }
|
||||||
$head = "[support-guard] Редактирование отклонено: это объект типовой конфигурации на поддержке поставщика, прямое редактирование молча сломает будущие обновления."
|
$head = "[support-guard] Редактирование отклонено: это объект типовой конфигурации на поддержке поставщика, прямое редактирование молча сломает будущие обновления."
|
||||||
$cfe = "Рекомендуемый путь: внести доработку в расширение (навыки cfe-borrow / cfe-patch-method) — состояние поддержки менять не нужно, обновления вендора сохраняются."
|
$cfe = "Рекомендуемый путь: внести доработку в расширение (навыки cfe-borrow / cfe-patch-method) — состояние поддержки менять не нужно, обновления вендора сохраняются."
|
||||||
$offNote = "Снять проверку для этой базы: editingAllowedCheck = warn|off в .v8-project.json."
|
$offNote = "Снять проверку для этой базы: editingAllowedCheck = warn|off в .v8-project.json."
|
||||||
if ($code -eq "capability-off") {
|
if ($code -eq "capability-off") {
|
||||||
$state = "Состояние: у всей конфигурации выключена возможность изменения (режим read-only «из коробки») — поэтому объект «$rp» редактировать нельзя."
|
$state = "Состояние: у всей конфигурации выключена возможность изменения (режим read-only «из коробки») — поэтому объект «$rp» редактировать нельзя."
|
||||||
$fix = "Либо снять защиту явно (навык support-edit, два шага):`n 1. support-edit -Path ""$cfgDir"" -Capability on — включить возможность изменения (объекты пока остаются на замке);`n 2. support-edit -Path ""$rp"" -Set editable — открыть этот объект для редактирования.`n Изменение применяется в базу полной загрузкой выгрузки и обходит механизм обновлений вендора."
|
$fix = "Либо снять защиту явно (навык support-edit, два шага):`n 1. support-edit -Path ""$cfgDir"" -Capability on — включить возможность изменения (объекты пока остаются на замке);`n 2. support-edit -Path ""$rp"" -Set editable — открыть этот объект для редактирования.`n Изменение применяется в базу полной загрузкой выгрузки и обходит механизм обновлений вендора."
|
||||||
} elseif ($code -eq "not-removed") {
|
} elseif ($code -eq "not-removed") {
|
||||||
$state = "Состояние: объект «$rp» на поддержке (не снят с поддержки) — его удаление разорвёт обновления вендора."
|
$state = "Состояние: объект «$rp» на поддержке (не снят с поддержки) — его удаление разорвёт обновления вендора."
|
||||||
$fix = "Либо сначала снять объект с поддержки, затем удалять:`n support-edit -Path ""$rp"" -Set off-support — объект уходит из-под обновлений, после этого удаление безопасно."
|
$fix = "Либо сначала снять объект с поддержки, затем удалять:`n support-edit -Path ""$rp"" -Set off-support — объект уходит из-под обновлений, после этого удаление безопасно."
|
||||||
} else {
|
} else {
|
||||||
$state = "Состояние: объект «$rp» на замке (возможность изменения конфигурации включена, но сам объект не редактируется)."
|
$state = "Состояние: объект «$rp» на замке (возможность изменения конфигурации включена, но сам объект не редактируется)."
|
||||||
$fix = "Либо разрешить редактирование этого объекта (навык support-edit, выбрать одно):`n support-edit -Path ""$rp"" -Set editable — редактировать и дальше получать обновления вендора (возможны конфликты слияния);`n support-edit -Path ""$rp"" -Set off-support — снять с поддержки: обновления по объекту больше не приходят."
|
$fix = "Либо разрешить редактирование этого объекта (навык support-edit, выбрать одно):`n support-edit -Path ""$rp"" -Set editable — редактировать и дальше получать обновления вендора (возможны конфликты слияния);`n support-edit -Path ""$rp"" -Set off-support — снять с поддержки: обновления по объекту больше не приходят."
|
||||||
}
|
}
|
||||||
[Console]::Error.WriteLine("$head`n$state`n$cfe`n$fix`n$offNote")
|
[Console]::Error.WriteLine("$head`n$state`n$cfe`n$fix`n$offNote")
|
||||||
exit 1
|
exit 1
|
||||||
} catch { return }
|
} catch { return }
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Detect format version ---
|
# --- Detect format version ---
|
||||||
|
|
||||||
function Detect-FormatVersion([string]$dir) {
|
function Detect-FormatVersion([string]$dir) {
|
||||||
$d = $dir
|
$d = $dir
|
||||||
while ($d) {
|
while ($d) {
|
||||||
$cfgPath = Join-Path $d "Configuration.xml"
|
$cfgPath = Join-Path $d "Configuration.xml"
|
||||||
if (Test-Path $cfgPath) {
|
if (Test-Path $cfgPath) {
|
||||||
$content = [System.IO.File]::ReadAllText($cfgPath, [System.Text.Encoding]::UTF8)
|
$content = [System.IO.File]::ReadAllText($cfgPath, [System.Text.Encoding]::UTF8)
|
||||||
$head = $content.Substring(0, [Math]::Min(2000, $content.Length))
|
$head = $content.Substring(0, [Math]::Min(2000, $content.Length))
|
||||||
if ($head -match '<MetaDataObject[^>]+version="(\d+\.\d+)"') { return $Matches[1] }
|
if ($head -match '<MetaDataObject[^>]+version="(\d+\.\d+)"') { return $Matches[1] }
|
||||||
}
|
}
|
||||||
$parent = Split-Path $d -Parent
|
$parent = Split-Path $d -Parent
|
||||||
if ($parent -eq $d) { break }
|
if ($parent -eq $d) { break }
|
||||||
$d = $parent
|
$d = $parent
|
||||||
}
|
}
|
||||||
return "2.17"
|
return "2.17"
|
||||||
}
|
}
|
||||||
|
|
||||||
$formatVersion = Detect-FormatVersion (Resolve-Path $SrcDir).Path
|
$formatVersion = Detect-FormatVersion (Resolve-Path $SrcDir).Path
|
||||||
|
|
||||||
# --- Проверки ---
|
# --- Проверки ---
|
||||||
|
|
||||||
$objectDir = Join-Path $SrcDir $ObjectName
|
$objectDir = Join-Path $SrcDir $ObjectName
|
||||||
$extDir = Join-Path $objectDir "Ext"
|
$extDir = Join-Path $objectDir "Ext"
|
||||||
|
|
||||||
if (-not (Test-Path $extDir)) {
|
if (-not (Test-Path $extDir)) {
|
||||||
Write-Error "Каталог объекта не найден: $extDir. Проверьте путь ObjectName (например Catalogs/МойСправочник)."
|
Write-Error "Каталог объекта не найден: $extDir. Проверьте путь ObjectName (например Catalogs/МойСправочник)."
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
$helpXmlPath = Join-Path $extDir "Help.xml"
|
$helpXmlPath = Join-Path $extDir "Help.xml"
|
||||||
if (Test-Path $helpXmlPath) {
|
if (Test-Path $helpXmlPath) {
|
||||||
Write-Error "Справка уже существует: $helpXmlPath"
|
Write-Error "Справка уже существует: $helpXmlPath"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert-EditAllowed $objectDir 'editable'
|
Assert-EditAllowed $objectDir 'editable'
|
||||||
|
|
||||||
# --- Кодировка ---
|
# --- Кодировка ---
|
||||||
|
|
||||||
$encBom = New-Object System.Text.UTF8Encoding($true)
|
$encBom = New-Object System.Text.UTF8Encoding($true)
|
||||||
|
|
||||||
# --- 1. Help.xml ---
|
# --- 1. Help.xml ---
|
||||||
|
|
||||||
$helpXml = @"
|
$helpXml = @"
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Help xmlns="http://v8.1c.ru/8.3/xcf/extrnprops" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="$formatVersion">
|
<Help xmlns="http://v8.1c.ru/8.3/xcf/extrnprops" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="$formatVersion">
|
||||||
<Page>$Lang</Page>
|
<Page>$Lang</Page>
|
||||||
</Help>
|
</Help>
|
||||||
"@
|
"@
|
||||||
|
|
||||||
[System.IO.File]::WriteAllText($helpXmlPath, $helpXml, $encBom)
|
[System.IO.File]::WriteAllText($helpXmlPath, $helpXml, $encBom)
|
||||||
|
|
||||||
# --- 2. Help/<lang>.html ---
|
# --- 2. Help/<lang>.html ---
|
||||||
|
|
||||||
$helpDir = Join-Path $extDir "Help"
|
$helpDir = Join-Path $extDir "Help"
|
||||||
New-Item -ItemType Directory -Path $helpDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $helpDir -Force | Out-Null
|
||||||
|
|
||||||
$helpHtmlPath = Join-Path $helpDir "$Lang.html"
|
$helpHtmlPath = Join-Path $helpDir "$Lang.html"
|
||||||
|
|
||||||
$helpHtml = @"
|
$helpHtml = @"
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||||
<link rel="stylesheet" type="text/css" href="v8help://service_book/service_style"/>
|
<link rel="stylesheet" type="text/css" href="v8help://service_book/service_style"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>$ObjectName</h1>
|
<h1>$ObjectName</h1>
|
||||||
<p>Описание.</p>
|
<p>Описание.</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
"@
|
"@
|
||||||
|
|
||||||
[System.IO.File]::WriteAllText($helpHtmlPath, $helpHtml, $encBom)
|
[System.IO.File]::WriteAllText($helpHtmlPath, $helpHtml, $encBom)
|
||||||
|
|
||||||
# --- 3. Проверка IncludeHelpInContents в метаданных форм ---
|
# --- 3. Проверка IncludeHelpInContents в метаданных форм ---
|
||||||
|
|
||||||
$formsDir = Join-Path $objectDir "Forms"
|
$formsDir = Join-Path $objectDir "Forms"
|
||||||
if (Test-Path $formsDir) {
|
if (Test-Path $formsDir) {
|
||||||
$formMetaFiles = Get-ChildItem -Path $formsDir -Filter "*.xml" -File
|
$formMetaFiles = Get-ChildItem -Path $formsDir -Filter "*.xml" -File
|
||||||
foreach ($formMeta in $formMetaFiles) {
|
foreach ($formMeta in $formMetaFiles) {
|
||||||
$xmlDoc = New-Object System.Xml.XmlDocument
|
$xmlDoc = New-Object System.Xml.XmlDocument
|
||||||
$xmlDoc.PreserveWhitespace = $true
|
$xmlDoc.PreserveWhitespace = $true
|
||||||
$xmlDoc.Load($formMeta.FullName)
|
$xmlDoc.Load($formMeta.FullName)
|
||||||
|
|
||||||
$nsMgr = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
|
$nsMgr = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
|
||||||
$nsMgr.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
|
$nsMgr.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
|
||||||
|
|
||||||
$includeHelp = $xmlDoc.SelectSingleNode("//md:IncludeHelpInContents", $nsMgr)
|
$includeHelp = $xmlDoc.SelectSingleNode("//md:IncludeHelpInContents", $nsMgr)
|
||||||
if (-not $includeHelp) {
|
if (-not $includeHelp) {
|
||||||
# Добавить после <FormType>
|
# Добавить после <FormType>
|
||||||
$formType = $xmlDoc.SelectSingleNode("//md:FormType", $nsMgr)
|
$formType = $xmlDoc.SelectSingleNode("//md:FormType", $nsMgr)
|
||||||
if ($formType) {
|
if ($formType) {
|
||||||
$newElem = $xmlDoc.CreateElement("IncludeHelpInContents", "http://v8.1c.ru/8.3/MDClasses")
|
$newElem = $xmlDoc.CreateElement("IncludeHelpInContents", "http://v8.1c.ru/8.3/MDClasses")
|
||||||
$newElem.InnerText = "false"
|
$newElem.InnerText = "false"
|
||||||
$parent = $formType.ParentNode
|
$parent = $formType.ParentNode
|
||||||
$nextSibling = $formType.NextSibling
|
$nextSibling = $formType.NextSibling
|
||||||
# Вставить перенос + табуляцию + элемент
|
# Вставить перенос + табуляцию + элемент
|
||||||
$ws = $xmlDoc.CreateWhitespace("`n`t`t`t")
|
$ws = $xmlDoc.CreateWhitespace("`n`t`t`t")
|
||||||
if ($nextSibling) {
|
if ($nextSibling) {
|
||||||
$parent.InsertBefore($ws, $nextSibling) | Out-Null
|
$parent.InsertBefore($ws, $nextSibling) | Out-Null
|
||||||
$parent.InsertBefore($newElem, $ws) | Out-Null
|
$parent.InsertBefore($newElem, $ws) | Out-Null
|
||||||
} else {
|
} else {
|
||||||
$parent.AppendChild($ws) | Out-Null
|
$parent.AppendChild($ws) | Out-Null
|
||||||
$parent.AppendChild($newElem) | Out-Null
|
$parent.AppendChild($newElem) | Out-Null
|
||||||
}
|
}
|
||||||
|
|
||||||
$settings = New-Object System.Xml.XmlWriterSettings
|
$settings = New-Object System.Xml.XmlWriterSettings
|
||||||
$settings.Encoding = $encBom
|
$settings.Encoding = $encBom
|
||||||
$settings.Indent = $false
|
$settings.Indent = $false
|
||||||
$stream = New-Object System.IO.FileStream($formMeta.FullName, [System.IO.FileMode]::Create)
|
$stream = New-Object System.IO.FileStream($formMeta.FullName, [System.IO.FileMode]::Create)
|
||||||
$writer = [System.Xml.XmlWriter]::Create($stream, $settings)
|
$writer = [System.Xml.XmlWriter]::Create($stream, $settings)
|
||||||
$xmlDoc.Save($writer)
|
$xmlDoc.Save($writer)
|
||||||
$writer.Close()
|
$writer.Close()
|
||||||
$stream.Close()
|
$stream.Close()
|
||||||
|
|
||||||
Write-Host " IncludeHelpInContents добавлен: $($formMeta.Name)"
|
Write-Host " IncludeHelpInContents добавлен: $($formMeta.Name)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "[OK] Создана справка: $ObjectName"
|
Write-Host "[OK] Создана справка: $ObjectName"
|
||||||
Write-Host " Метаданные: $helpXmlPath"
|
Write-Host " Метаданные: $helpXmlPath"
|
||||||
Write-Host " Страница: $helpHtmlPath"
|
Write-Host " Страница: $helpHtmlPath"
|
||||||
|
|||||||
@@ -1,77 +1,77 @@
|
|||||||
---
|
---
|
||||||
name: img-grid
|
name: img-grid
|
||||||
description: Наложить пронумерованную сетку на изображение. Используй при анализе скриншота макета или печатной формы — измерить пропорции колонок перед генерацией табличного документа
|
description: Наложить пронумерованную сетку на изображение. Используй при анализе скриншота макета или печатной формы — измерить пропорции колонок перед генерацией табличного документа
|
||||||
argument-hint: <ImagePath> [-c COLS]
|
argument-hint: <ImagePath> [-c COLS]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
---
|
---
|
||||||
|
|
||||||
# /img-grid — Сетка для анализа макета
|
# /img-grid — Сетка для анализа макета
|
||||||
|
|
||||||
Накладывает пронумерованную сетку на изображение печатной формы. Позволяет точно определить границы колонок, их пропорции и span-ы для генерации макета табличного документа.
|
Накладывает пронумерованную сетку на изображение печатной формы. Позволяет точно определить границы колонок, их пропорции и span-ы для генерации макета табличного документа.
|
||||||
|
|
||||||
## Использование
|
## Использование
|
||||||
|
|
||||||
```
|
```
|
||||||
/img-grid <ImagePath> [-c COLS] [-o OUTPUT]
|
/img-grid <ImagePath> [-c COLS] [-o OUTPUT]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Обязательный | По умолчанию | Описание |
|
| Параметр | Обязательный | По умолчанию | Описание |
|
||||||
|-----------|:------------:|--------------|-----------------------------------------------|
|
|-----------|:------------:|--------------|-----------------------------------------------|
|
||||||
| ImagePath | да | — | Путь к изображению (PNG, JPG) |
|
| ImagePath | да | — | Путь к изображению (PNG, JPG) |
|
||||||
| -c COLS | нет | 50 | Количество вертикальных делений |
|
| -c COLS | нет | 50 | Количество вертикальных делений |
|
||||||
| -r ROWS | нет | авто | Количество горизонтальных делений (авто = квадратные ячейки) |
|
| -r ROWS | нет | авто | Количество горизонтальных делений (авто = квадратные ячейки) |
|
||||||
| -o OUTPUT | нет | `<name>-grid.<ext>` | Путь для результата |
|
| -o OUTPUT | нет | `<name>-grid.<ext>` | Путь для результата |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python "${CLAUDE_SKILL_DIR}/scripts/overlay-grid.py" "<ImagePath>" [-c 50] [-o "<OutputPath>"]
|
python "${CLAUDE_SKILL_DIR}/scripts/overlay-grid.py" "<ImagePath>" [-c 50] [-o "<OutputPath>"]
|
||||||
```
|
```
|
||||||
|
|
||||||
Требуется Python 3 с библиотекой Pillow (`pip install Pillow`).
|
Требуется Python 3 с библиотекой Pillow (`pip install Pillow`).
|
||||||
|
|
||||||
## Что делает
|
## Что делает
|
||||||
|
|
||||||
1. Рисует полупрозрачные вертикальные (красные) и горизонтальные (синие) линии
|
1. Рисует полупрозрачные вертикальные (красные) и горизонтальные (синие) линии
|
||||||
2. Нумерует линии в отдельных полях сверху и слева (не перекрывает содержимое)
|
2. Нумерует линии в отдельных полях сверху и слева (не перекрывает содержимое)
|
||||||
3. Каждая 5-я и 10-я линия выделены ярче для удобства счёта
|
3. Каждая 5-я и 10-я линия выделены ярче для удобства счёта
|
||||||
|
|
||||||
## Как использовать результат
|
## Как использовать результат
|
||||||
|
|
||||||
### 1. Определить границы колонок
|
### 1. Определить границы колонок
|
||||||
|
|
||||||
Посмотреть на изображение с сеткой и записать координаты вертикальных границ каждой колонки таблицы (в номерах grid-линий).
|
Посмотреть на изображение с сеткой и записать координаты вертикальных границ каждой колонки таблицы (в номерах grid-линий).
|
||||||
|
|
||||||
### 2. Найти базовую решётку
|
### 2. Найти базовую решётку
|
||||||
|
|
||||||
Если на форме несколько таблиц с разной раскладкой (например, шапка документа и основная таблица), объединить все граничные точки. Каждый сегмент между соседними границами — одна колонка MXL.
|
Если на форме несколько таблиц с разной раскладкой (например, шапка документа и основная таблица), объединить все граничные точки. Каждый сегмент между соседними границами — одна колонка MXL.
|
||||||
|
|
||||||
Пример для М-11:
|
Пример для М-11:
|
||||||
- Шапка: границы 0, 2, 4, 9, 14, 21, 28, 34, 40, 48
|
- Шапка: границы 0, 2, 4, 9, 14, 21, 28, 34, 40, 48
|
||||||
- Таблица: границы 0, 2, 4, 11, 16, 19, 23, 28, 32, 36, 42, 48
|
- Таблица: границы 0, 2, 4, 11, 16, 19, 23, 28, 32, 36, 42, 48
|
||||||
- Объединение: 0, 2, 4, 9, 11, 14, 16, 19, 21, 23, 28, 32, 34, 36, 40, 42, 48
|
- Объединение: 0, 2, 4, 9, 11, 14, 16, 19, 21, 23, 28, 32, 34, 36, 40, 42, 48
|
||||||
- Результат: **16 базовых колонок** с пропорциями 2, 2, 5, 2, 3, 2, 3, 2, 2, 5, 4, 2, 2, 4, 2, 6
|
- Результат: **16 базовых колонок** с пропорциями 2, 2, 5, 2, 3, 2, 3, 2, 2, 5, 4, 2, 2, 4, 2, 6
|
||||||
|
|
||||||
### 3. Записать в JSON DSL
|
### 3. Записать в JSON DSL
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"columns": 16,
|
"columns": 16,
|
||||||
"page": "A4-landscape",
|
"page": "A4-landscape",
|
||||||
"columnWidths": {
|
"columnWidths": {
|
||||||
"1": "2x", "2": "2x", "3": "5x", "4": "2x", "5": "3x",
|
"1": "2x", "2": "2x", "3": "5x", "4": "2x", "5": "3x",
|
||||||
"6": "2x", "7": "3x", "8": "2x", "9": "2x", "10": "5x",
|
"6": "2x", "7": "3x", "8": "2x", "9": "2x", "10": "5x",
|
||||||
"11": "4x", "12": "2x", "13": "2x", "14": "4x", "15": "2x", "16": "6x"
|
"11": "4x", "12": "2x", "13": "2x", "14": "4x", "15": "2x", "16": "6x"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Поле `"page"` позволяет компилятору автоматически вычислить абсолютные ширины из пропорций.
|
Поле `"page"` позволяет компилятору автоматически вычислить абсолютные ширины из пропорций.
|
||||||
|
|
||||||
### 4. Скомпилировать
|
### 4. Скомпилировать
|
||||||
|
|
||||||
`/mxl-compile` → `/mxl-validate` → `/mxl-info`
|
`/mxl-compile` → `/mxl-validate` → `/mxl-info`
|
||||||
|
|||||||
@@ -1,75 +1,75 @@
|
|||||||
---
|
---
|
||||||
name: interface-edit
|
name: interface-edit
|
||||||
description: Настройка командного интерфейса подсистемы 1С. Используй когда нужно скрыть или показать команды, разместить в группах, настроить порядок
|
description: Настройка командного интерфейса подсистемы 1С. Используй когда нужно скрыть или показать команды, разместить в группах, настроить порядок
|
||||||
argument-hint: <CIPath> <Operation> <Value>
|
argument-hint: <CIPath> <Operation> <Value>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Write
|
- Write
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /interface-edit — редактирование CommandInterface.xml
|
# /interface-edit — редактирование CommandInterface.xml
|
||||||
|
|
||||||
Точечное редактирование файла командного интерфейса подсистемы 1С.
|
Точечное редактирование файла командного интерфейса подсистемы 1С.
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Обяз. | Описание |
|
| Параметр | Обяз. | Описание |
|
||||||
|----------|:-----:|----------|
|
|----------|:-----:|----------|
|
||||||
| CIPath | да | Путь к CommandInterface.xml |
|
| CIPath | да | Путь к CommandInterface.xml |
|
||||||
| Operation | нет | Операция: hide, show, place, order, subsystem-order, group-order |
|
| Operation | нет | Операция: hide, show, place, order, subsystem-order, group-order |
|
||||||
| Value | нет | Значение для операции |
|
| Value | нет | Значение для операции |
|
||||||
| DefinitionFile | нет | JSON-файл с массивом операций (альтернатива Operation) |
|
| DefinitionFile | нет | JSON-файл с массивом операций (альтернатива Operation) |
|
||||||
| CreateIfMissing | нет | Создать файл если не существует |
|
| CreateIfMissing | нет | Создать файл если не существует |
|
||||||
| NoValidate | нет | Пропустить авто-валидацию |
|
| NoValidate | нет | Пропустить авто-валидацию |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
### Inline mode
|
### Inline mode
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/interface-edit.ps1" -CIPath '<path>' -Operation hide -Value '<cmd>'
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/interface-edit.ps1" -CIPath '<path>' -Operation hide -Value '<cmd>'
|
||||||
```
|
```
|
||||||
|
|
||||||
### JSON mode
|
### JSON mode
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/interface-edit.ps1" -CIPath '<path>' -DefinitionFile '<json>'
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/interface-edit.ps1" -CIPath '<path>' -DefinitionFile '<json>'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Операции
|
## Операции
|
||||||
|
|
||||||
| Операция | Значение | Описание |
|
| Операция | Значение | Описание |
|
||||||
|----------|----------|----------|
|
|----------|----------|----------|
|
||||||
| hide | Cmd.Name или массив | Скрыть команду (CommandsVisibility, false) |
|
| hide | Cmd.Name или массив | Скрыть команду (CommandsVisibility, false) |
|
||||||
| show | Cmd.Name или массив | Показать команду (visibility, true) |
|
| show | Cmd.Name или массив | Показать команду (visibility, true) |
|
||||||
| place | {"command":"...","group":"CommandGroup.X"} | Разместить команду в группе |
|
| place | {"command":"...","group":"CommandGroup.X"} | Разместить команду в группе |
|
||||||
| order | {"group":"...","commands":[...]} | Задать порядок команд в группе |
|
| order | {"group":"...","commands":[...]} | Задать порядок команд в группе |
|
||||||
| subsystem-order | ["Subsystem.X.Subsystem.A",...] | Порядок дочерних подсистем |
|
| subsystem-order | ["Subsystem.X.Subsystem.A",...] | Порядок дочерних подсистем |
|
||||||
| group-order | ["NavigationPanelOrdinary",...] | Порядок групп |
|
| group-order | ["NavigationPanelOrdinary",...] | Порядок групп |
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Скрыть команду
|
# Скрыть команду
|
||||||
... -CIPath Subsystems/Продажи/Ext/CommandInterface.xml -Operation hide -Value "Catalog.Товары.StandardCommand.OpenList"
|
... -CIPath Subsystems/Продажи/Ext/CommandInterface.xml -Operation hide -Value "Catalog.Товары.StandardCommand.OpenList"
|
||||||
|
|
||||||
# Показать команду
|
# Показать команду
|
||||||
... -Operation show -Value "Report.Продажи.Command.Отчёт"
|
... -Operation show -Value "Report.Продажи.Command.Отчёт"
|
||||||
|
|
||||||
# Разместить в группе
|
# Разместить в группе
|
||||||
... -Operation place -Value '{"command":"Report.X.Command.Y","group":"CommandGroup.Отчеты"}'
|
... -Operation place -Value '{"command":"Report.X.Command.Y","group":"CommandGroup.Отчеты"}'
|
||||||
|
|
||||||
# Задать порядок подсистем
|
# Задать порядок подсистем
|
||||||
... -Operation subsystem-order -Value '["Subsystem.X.Subsystem.A","Subsystem.X.Subsystem.B"]'
|
... -Operation subsystem-order -Value '["Subsystem.X.Subsystem.A","Subsystem.X.Subsystem.B"]'
|
||||||
|
|
||||||
# Создать новый CI
|
# Создать новый CI
|
||||||
... -CIPath <new-path> -Operation subsystem-order -Value '[...]' -CreateIfMissing
|
... -CIPath <new-path> -Operation subsystem-order -Value '[...]' -CreateIfMissing
|
||||||
```
|
```
|
||||||
|
|
||||||
## Верификация
|
## Верификация
|
||||||
|
|
||||||
```
|
```
|
||||||
/interface-validate <CIPath>
|
/interface-validate <CIPath>
|
||||||
```
|
```
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,29 +1,29 @@
|
|||||||
---
|
---
|
||||||
name: interface-validate
|
name: interface-validate
|
||||||
description: Валидация командного интерфейса 1С. Используй после настройки командного интерфейса подсистемы для проверки корректности
|
description: Валидация командного интерфейса 1С. Используй после настройки командного интерфейса подсистемы для проверки корректности
|
||||||
argument-hint: <CIPath> [-Detailed] [-MaxErrors 30]
|
argument-hint: <CIPath> [-Detailed] [-MaxErrors 30]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /interface-validate — валидация CommandInterface.xml
|
# /interface-validate — валидация CommandInterface.xml
|
||||||
|
|
||||||
Проверяет XML командного интерфейса на структурные ошибки: корневой элемент, допустимые секции, порядок, формат ссылок на команды, дубликаты.
|
Проверяет XML командного интерфейса на структурные ошибки: корневой элемент, допустимые секции, порядок, формат ссылок на команды, дубликаты.
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Обяз. | Умолч. | Описание |
|
| Параметр | Обяз. | Умолч. | Описание |
|
||||||
|-----------|:-----:|---------|-----------------------------------------|
|
|-----------|:-----:|---------|-----------------------------------------|
|
||||||
| CIPath | да | — | Путь к CommandInterface.xml |
|
| CIPath | да | — | Путь к CommandInterface.xml |
|
||||||
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
||||||
| MaxErrors | нет | 30 | Остановиться после N ошибок |
|
| MaxErrors | нет | 30 | Остановиться после N ошибок |
|
||||||
| OutFile | нет | — | Записать результат в файл (UTF-8 BOM) |
|
| OutFile | нет | — | Записать результат в файл (UTF-8 BOM) |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/interface-validate.ps1" -CIPath "Subsystems/Продажи"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/interface-validate.ps1" -CIPath "Subsystems/Продажи"
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/interface-validate.ps1" -CIPath "Subsystems/Продажи/Ext/CommandInterface.xml"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/interface-validate.ps1" -CIPath "Subsystems/Продажи/Ext/CommandInterface.xml"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,403 +1,403 @@
|
|||||||
# interface-validate v1.1 — Validate 1C CommandInterface.xml structure
|
# interface-validate v1.1 — Validate 1C CommandInterface.xml structure
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)][Alias('Path')][string]$CIPath,
|
[Parameter(Mandatory)][Alias('Path')][string]$CIPath,
|
||||||
[switch]$Detailed,
|
[switch]$Detailed,
|
||||||
[int]$MaxErrors = 30,
|
[int]$MaxErrors = 30,
|
||||||
[string]$OutFile
|
[string]$OutFile
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Resolve path ---
|
# --- Resolve path ---
|
||||||
if (-not [System.IO.Path]::IsPathRooted($CIPath)) {
|
if (-not [System.IO.Path]::IsPathRooted($CIPath)) {
|
||||||
$CIPath = Join-Path (Get-Location).Path $CIPath
|
$CIPath = Join-Path (Get-Location).Path $CIPath
|
||||||
}
|
}
|
||||||
# A: Directory → Ext/CommandInterface.xml
|
# A: Directory → Ext/CommandInterface.xml
|
||||||
if (Test-Path $CIPath -PathType Container) {
|
if (Test-Path $CIPath -PathType Container) {
|
||||||
$CIPath = Join-Path (Join-Path $CIPath "Ext") "CommandInterface.xml"
|
$CIPath = Join-Path (Join-Path $CIPath "Ext") "CommandInterface.xml"
|
||||||
}
|
}
|
||||||
# B1: Missing Ext/ (e.g. Subsystems/X/CommandInterface.xml → Subsystems/X/Ext/CommandInterface.xml)
|
# B1: Missing Ext/ (e.g. Subsystems/X/CommandInterface.xml → Subsystems/X/Ext/CommandInterface.xml)
|
||||||
if (-not (Test-Path $CIPath)) {
|
if (-not (Test-Path $CIPath)) {
|
||||||
$fn = [System.IO.Path]::GetFileName($CIPath)
|
$fn = [System.IO.Path]::GetFileName($CIPath)
|
||||||
if ($fn -eq "CommandInterface.xml") {
|
if ($fn -eq "CommandInterface.xml") {
|
||||||
$c = Join-Path (Join-Path (Split-Path $CIPath) "Ext") $fn
|
$c = Join-Path (Join-Path (Split-Path $CIPath) "Ext") $fn
|
||||||
if (Test-Path $c) { $CIPath = $c }
|
if (Test-Path $c) { $CIPath = $c }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (-not (Test-Path $CIPath)) {
|
if (-not (Test-Path $CIPath)) {
|
||||||
Write-Host "[ERROR] File not found: $CIPath"
|
Write-Host "[ERROR] File not found: $CIPath"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
$resolvedPath = (Resolve-Path $CIPath).Path
|
$resolvedPath = (Resolve-Path $CIPath).Path
|
||||||
|
|
||||||
# --- Derive context name from path ---
|
# --- Derive context name from path ---
|
||||||
$contextName = ""
|
$contextName = ""
|
||||||
$parentParts = $resolvedPath -split '[/\\]'
|
$parentParts = $resolvedPath -split '[/\\]'
|
||||||
for ($i = 0; $i -lt $parentParts.Count; $i++) {
|
for ($i = 0; $i -lt $parentParts.Count; $i++) {
|
||||||
if ($parentParts[$i] -eq "Subsystems" -and ($i + 1) -lt $parentParts.Count) {
|
if ($parentParts[$i] -eq "Subsystems" -and ($i + 1) -lt $parentParts.Count) {
|
||||||
$contextName = $parentParts[$i + 1]
|
$contextName = $parentParts[$i + 1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (-not $contextName) { $contextName = "Root" }
|
if (-not $contextName) { $contextName = "Root" }
|
||||||
|
|
||||||
# --- Output infrastructure ---
|
# --- Output infrastructure ---
|
||||||
$script:errors = 0
|
$script:errors = 0
|
||||||
$script:warnings = 0
|
$script:warnings = 0
|
||||||
$script:stopped = $false
|
$script:stopped = $false
|
||||||
$script:okCount = 0
|
$script:okCount = 0
|
||||||
$script:output = New-Object System.Text.StringBuilder 8192
|
$script:output = New-Object System.Text.StringBuilder 8192
|
||||||
$script:allCommandNames = @()
|
$script:allCommandNames = @()
|
||||||
|
|
||||||
function Out-Line([string]$msg) { $script:output.AppendLine($msg) | Out-Null }
|
function Out-Line([string]$msg) { $script:output.AppendLine($msg) | Out-Null }
|
||||||
function Report-OK([string]$msg) {
|
function Report-OK([string]$msg) {
|
||||||
$script:okCount++
|
$script:okCount++
|
||||||
if ($Detailed) { Out-Line "[OK] $msg" }
|
if ($Detailed) { Out-Line "[OK] $msg" }
|
||||||
}
|
}
|
||||||
function Report-Error([string]$msg) {
|
function Report-Error([string]$msg) {
|
||||||
$script:errors++
|
$script:errors++
|
||||||
Out-Line "[ERROR] $msg"
|
Out-Line "[ERROR] $msg"
|
||||||
if ($script:errors -ge $MaxErrors) { $script:stopped = $true }
|
if ($script:errors -ge $MaxErrors) { $script:stopped = $true }
|
||||||
}
|
}
|
||||||
function Report-Warn([string]$msg) {
|
function Report-Warn([string]$msg) {
|
||||||
$script:warnings++
|
$script:warnings++
|
||||||
Out-Line "[WARN] $msg"
|
Out-Line "[WARN] $msg"
|
||||||
}
|
}
|
||||||
|
|
||||||
Out-Line "=== Validation: CommandInterface ($contextName) ==="
|
Out-Line "=== Validation: CommandInterface ($contextName) ==="
|
||||||
Out-Line ""
|
Out-Line ""
|
||||||
|
|
||||||
# --- Valid section names and order ---
|
# --- Valid section names and order ---
|
||||||
$validSections = @("CommandsVisibility","CommandsPlacement","CommandsOrder","SubsystemsOrder","GroupsOrder")
|
$validSections = @("CommandsVisibility","CommandsPlacement","CommandsOrder","SubsystemsOrder","GroupsOrder")
|
||||||
|
|
||||||
# Command reference patterns
|
# Command reference patterns
|
||||||
$stdCmdPattern = '^[A-Za-z]+\.[^\s\.]+\.StandardCommand\.\w+$'
|
$stdCmdPattern = '^[A-Za-z]+\.[^\s\.]+\.StandardCommand\.\w+$'
|
||||||
$customCmdPattern = '^[A-Za-z]+\.[^\s\.]+\.Command\.\w+$'
|
$customCmdPattern = '^[A-Za-z]+\.[^\s\.]+\.Command\.\w+$'
|
||||||
$commonCmdPattern = '^CommonCommand\.\w+$'
|
$commonCmdPattern = '^CommonCommand\.\w+$'
|
||||||
$uuidCmdPattern = '^0:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'
|
$uuidCmdPattern = '^0:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'
|
||||||
|
|
||||||
# --- 1. XML well-formedness + root structure ---
|
# --- 1. XML well-formedness + root structure ---
|
||||||
$xmlDoc = $null
|
$xmlDoc = $null
|
||||||
try {
|
try {
|
||||||
[xml]$xmlDoc = Get-Content -Path $resolvedPath -Encoding UTF8
|
[xml]$xmlDoc = Get-Content -Path $resolvedPath -Encoding UTF8
|
||||||
} catch {
|
} catch {
|
||||||
Report-Error "1. XML parse error: $($_.Exception.Message)"
|
Report-Error "1. XML parse error: $($_.Exception.Message)"
|
||||||
$script:stopped = $true
|
$script:stopped = $true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not $script:stopped) {
|
if (-not $script:stopped) {
|
||||||
$root = $xmlDoc.DocumentElement
|
$root = $xmlDoc.DocumentElement
|
||||||
|
|
||||||
if ($root.LocalName -ne "CommandInterface") {
|
if ($root.LocalName -ne "CommandInterface") {
|
||||||
Report-Error "1. Root element: expected <CommandInterface>, got <$($root.LocalName)>"
|
Report-Error "1. Root element: expected <CommandInterface>, got <$($root.LocalName)>"
|
||||||
$script:stopped = $true
|
$script:stopped = $true
|
||||||
} else {
|
} else {
|
||||||
$nsUri = $root.NamespaceURI
|
$nsUri = $root.NamespaceURI
|
||||||
$version = $root.GetAttribute("version")
|
$version = $root.GetAttribute("version")
|
||||||
$expectedNs = "http://v8.1c.ru/8.3/xcf/extrnprops"
|
$expectedNs = "http://v8.1c.ru/8.3/xcf/extrnprops"
|
||||||
if ($nsUri -ne $expectedNs) {
|
if ($nsUri -ne $expectedNs) {
|
||||||
Report-Error "1. Root namespace: expected $expectedNs, got $nsUri"
|
Report-Error "1. Root namespace: expected $expectedNs, got $nsUri"
|
||||||
} elseif (-not $version) {
|
} elseif (-not $version) {
|
||||||
Report-Warn "1. Root structure: CommandInterface, namespace valid, but no version attribute"
|
Report-Warn "1. Root structure: CommandInterface, namespace valid, but no version attribute"
|
||||||
} else {
|
} else {
|
||||||
Report-OK "1. Root structure: CommandInterface, version $version, namespace valid"
|
Report-OK "1. Root structure: CommandInterface, version $version, namespace valid"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Setup namespace manager ---
|
# --- Setup namespace manager ---
|
||||||
$ns = $null
|
$ns = $null
|
||||||
if (-not $script:stopped) {
|
if (-not $script:stopped) {
|
||||||
$ns = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
|
$ns = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
|
||||||
$ns.AddNamespace("ci", "http://v8.1c.ru/8.3/xcf/extrnprops")
|
$ns.AddNamespace("ci", "http://v8.1c.ru/8.3/xcf/extrnprops")
|
||||||
$ns.AddNamespace("xr", "http://v8.1c.ru/8.3/xcf/readable")
|
$ns.AddNamespace("xr", "http://v8.1c.ru/8.3/xcf/readable")
|
||||||
$ns.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance")
|
$ns.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance")
|
||||||
$ns.AddNamespace("xs", "http://www.w3.org/2001/XMLSchema")
|
$ns.AddNamespace("xs", "http://www.w3.org/2001/XMLSchema")
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 2. Valid child elements ---
|
# --- 2. Valid child elements ---
|
||||||
if (-not $script:stopped) {
|
if (-not $script:stopped) {
|
||||||
$root = $xmlDoc.DocumentElement
|
$root = $xmlDoc.DocumentElement
|
||||||
$foundSections = @()
|
$foundSections = @()
|
||||||
$invalidElements = @()
|
$invalidElements = @()
|
||||||
foreach ($child in $root.ChildNodes) {
|
foreach ($child in $root.ChildNodes) {
|
||||||
if ($child.NodeType -ne 'Element') { continue }
|
if ($child.NodeType -ne 'Element') { continue }
|
||||||
if ($child.LocalName -in $validSections) {
|
if ($child.LocalName -in $validSections) {
|
||||||
$foundSections += $child.LocalName
|
$foundSections += $child.LocalName
|
||||||
} else {
|
} else {
|
||||||
$invalidElements += $child.LocalName
|
$invalidElements += $child.LocalName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($invalidElements.Count -gt 0) {
|
if ($invalidElements.Count -gt 0) {
|
||||||
Report-Error "2. Invalid child elements: $($invalidElements -join ', ')"
|
Report-Error "2. Invalid child elements: $($invalidElements -join ', ')"
|
||||||
} else {
|
} else {
|
||||||
Report-OK "2. Child elements: $($foundSections.Count) valid sections"
|
Report-OK "2. Child elements: $($foundSections.Count) valid sections"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 3. Section order ---
|
# --- 3. Section order ---
|
||||||
if (-not $script:stopped) {
|
if (-not $script:stopped) {
|
||||||
$orderOk = $true
|
$orderOk = $true
|
||||||
$lastIdx = -1
|
$lastIdx = -1
|
||||||
foreach ($sec in $foundSections) {
|
foreach ($sec in $foundSections) {
|
||||||
$idx = [array]::IndexOf($validSections, $sec)
|
$idx = [array]::IndexOf($validSections, $sec)
|
||||||
if ($idx -lt $lastIdx) {
|
if ($idx -lt $lastIdx) {
|
||||||
Report-Error "3. Section order: '$sec' appears after a later section (expected: CommandsVisibility -> CommandsPlacement -> CommandsOrder -> SubsystemsOrder -> GroupsOrder)"
|
Report-Error "3. Section order: '$sec' appears after a later section (expected: CommandsVisibility -> CommandsPlacement -> CommandsOrder -> SubsystemsOrder -> GroupsOrder)"
|
||||||
$orderOk = $false
|
$orderOk = $false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
$lastIdx = $idx
|
$lastIdx = $idx
|
||||||
}
|
}
|
||||||
if ($orderOk) { Report-OK "3. Section order: correct" }
|
if ($orderOk) { Report-OK "3. Section order: correct" }
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 4. No duplicate sections ---
|
# --- 4. No duplicate sections ---
|
||||||
if (-not $script:stopped) {
|
if (-not $script:stopped) {
|
||||||
$dupes = $foundSections | Group-Object | Where-Object { $_.Count -gt 1 }
|
$dupes = $foundSections | Group-Object | Where-Object { $_.Count -gt 1 }
|
||||||
if ($dupes) {
|
if ($dupes) {
|
||||||
$dupeNames = ($dupes | ForEach-Object { $_.Name }) -join ", "
|
$dupeNames = ($dupes | ForEach-Object { $_.Name }) -join ", "
|
||||||
Report-Error "4. Duplicate sections: $dupeNames"
|
Report-Error "4. Duplicate sections: $dupeNames"
|
||||||
} else {
|
} else {
|
||||||
Report-OK "4. No duplicate sections"
|
Report-OK "4. No duplicate sections"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 5. CommandsVisibility ---
|
# --- 5. CommandsVisibility ---
|
||||||
if (-not $script:stopped) {
|
if (-not $script:stopped) {
|
||||||
$visSection = $root.SelectSingleNode("ci:CommandsVisibility", $ns)
|
$visSection = $root.SelectSingleNode("ci:CommandsVisibility", $ns)
|
||||||
if ($visSection) {
|
if ($visSection) {
|
||||||
$visOk = $true
|
$visOk = $true
|
||||||
$visNames = @()
|
$visNames = @()
|
||||||
$visCount = 0
|
$visCount = 0
|
||||||
foreach ($cmd in $visSection.ChildNodes) {
|
foreach ($cmd in $visSection.ChildNodes) {
|
||||||
if ($cmd.NodeType -ne 'Element') { continue }
|
if ($cmd.NodeType -ne 'Element') { continue }
|
||||||
$visCount++
|
$visCount++
|
||||||
$cmdName = $cmd.GetAttribute("name")
|
$cmdName = $cmd.GetAttribute("name")
|
||||||
if (-not $cmdName) {
|
if (-not $cmdName) {
|
||||||
Report-Error "5. CommandsVisibility: Command element without 'name' attribute"
|
Report-Error "5. CommandsVisibility: Command element without 'name' attribute"
|
||||||
$visOk = $false; continue
|
$visOk = $false; continue
|
||||||
}
|
}
|
||||||
$visNames += $cmdName
|
$visNames += $cmdName
|
||||||
$script:allCommandNames += $cmdName
|
$script:allCommandNames += $cmdName
|
||||||
$visibility = $cmd.SelectSingleNode("ci:Visibility", $ns)
|
$visibility = $cmd.SelectSingleNode("ci:Visibility", $ns)
|
||||||
if (-not $visibility) {
|
if (-not $visibility) {
|
||||||
Report-Error "5. CommandsVisibility[$cmdName]: missing <Visibility>"
|
Report-Error "5. CommandsVisibility[$cmdName]: missing <Visibility>"
|
||||||
$visOk = $false; continue
|
$visOk = $false; continue
|
||||||
}
|
}
|
||||||
$common = $visibility.SelectSingleNode("xr:Common", $ns)
|
$common = $visibility.SelectSingleNode("xr:Common", $ns)
|
||||||
if (-not $common) {
|
if (-not $common) {
|
||||||
Report-Error "5. CommandsVisibility[$cmdName]: missing <xr:Common>"
|
Report-Error "5. CommandsVisibility[$cmdName]: missing <xr:Common>"
|
||||||
$visOk = $false; continue
|
$visOk = $false; continue
|
||||||
}
|
}
|
||||||
$val = $common.InnerText.Trim()
|
$val = $common.InnerText.Trim()
|
||||||
if ($val -ne "true" -and $val -ne "false") {
|
if ($val -ne "true" -and $val -ne "false") {
|
||||||
Report-Error "5. CommandsVisibility[$cmdName]: xr:Common='$val' (expected true/false)"
|
Report-Error "5. CommandsVisibility[$cmdName]: xr:Common='$val' (expected true/false)"
|
||||||
$visOk = $false
|
$visOk = $false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($visOk) { Report-OK "5. CommandsVisibility: $visCount entries, all valid" }
|
if ($visOk) { Report-OK "5. CommandsVisibility: $visCount entries, all valid" }
|
||||||
} else {
|
} else {
|
||||||
Report-OK "5. CommandsVisibility: not present"
|
Report-OK "5. CommandsVisibility: not present"
|
||||||
$visNames = @()
|
$visNames = @()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 6. CommandsVisibility duplicates ---
|
# --- 6. CommandsVisibility duplicates ---
|
||||||
if (-not $script:stopped) {
|
if (-not $script:stopped) {
|
||||||
if ($visNames.Count -gt 0) {
|
if ($visNames.Count -gt 0) {
|
||||||
$dupes = $visNames | Group-Object | Where-Object { $_.Count -gt 1 }
|
$dupes = $visNames | Group-Object | Where-Object { $_.Count -gt 1 }
|
||||||
if ($dupes) {
|
if ($dupes) {
|
||||||
$dupeNames = ($dupes | ForEach-Object { $_.Name }) -join ", "
|
$dupeNames = ($dupes | ForEach-Object { $_.Name }) -join ", "
|
||||||
Report-Warn "6. CommandsVisibility: duplicates: $dupeNames"
|
Report-Warn "6. CommandsVisibility: duplicates: $dupeNames"
|
||||||
} else {
|
} else {
|
||||||
Report-OK "6. CommandsVisibility: no duplicates"
|
Report-OK "6. CommandsVisibility: no duplicates"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Report-OK "6. CommandsVisibility: no duplicates (empty)"
|
Report-OK "6. CommandsVisibility: no duplicates (empty)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 7. CommandsPlacement ---
|
# --- 7. CommandsPlacement ---
|
||||||
if (-not $script:stopped) {
|
if (-not $script:stopped) {
|
||||||
$plcSection = $root.SelectSingleNode("ci:CommandsPlacement", $ns)
|
$plcSection = $root.SelectSingleNode("ci:CommandsPlacement", $ns)
|
||||||
if ($plcSection) {
|
if ($plcSection) {
|
||||||
$plcOk = $true
|
$plcOk = $true
|
||||||
$plcCount = 0
|
$plcCount = 0
|
||||||
foreach ($cmd in $plcSection.ChildNodes) {
|
foreach ($cmd in $plcSection.ChildNodes) {
|
||||||
if ($cmd.NodeType -ne 'Element') { continue }
|
if ($cmd.NodeType -ne 'Element') { continue }
|
||||||
$plcCount++
|
$plcCount++
|
||||||
$cmdName = $cmd.GetAttribute("name")
|
$cmdName = $cmd.GetAttribute("name")
|
||||||
if (-not $cmdName) {
|
if (-not $cmdName) {
|
||||||
Report-Error "7. CommandsPlacement: Command without 'name' attribute"
|
Report-Error "7. CommandsPlacement: Command without 'name' attribute"
|
||||||
$plcOk = $false; continue
|
$plcOk = $false; continue
|
||||||
}
|
}
|
||||||
$script:allCommandNames += $cmdName
|
$script:allCommandNames += $cmdName
|
||||||
$grpEl = $cmd.SelectSingleNode("ci:CommandGroup", $ns)
|
$grpEl = $cmd.SelectSingleNode("ci:CommandGroup", $ns)
|
||||||
if (-not $grpEl -or -not $grpEl.InnerText.Trim()) {
|
if (-not $grpEl -or -not $grpEl.InnerText.Trim()) {
|
||||||
Report-Error "7. CommandsPlacement[$cmdName]: missing or empty <CommandGroup>"
|
Report-Error "7. CommandsPlacement[$cmdName]: missing or empty <CommandGroup>"
|
||||||
$plcOk = $false; continue
|
$plcOk = $false; continue
|
||||||
}
|
}
|
||||||
$placementEl = $cmd.SelectSingleNode("ci:Placement", $ns)
|
$placementEl = $cmd.SelectSingleNode("ci:Placement", $ns)
|
||||||
if (-not $placementEl) {
|
if (-not $placementEl) {
|
||||||
Report-Error "7. CommandsPlacement[$cmdName]: missing <Placement>"
|
Report-Error "7. CommandsPlacement[$cmdName]: missing <Placement>"
|
||||||
$plcOk = $false
|
$plcOk = $false
|
||||||
} elseif ($placementEl.InnerText.Trim() -ne "Auto") {
|
} elseif ($placementEl.InnerText.Trim() -ne "Auto") {
|
||||||
Report-Warn "7. CommandsPlacement[$cmdName]: Placement='$($placementEl.InnerText.Trim())' (expected Auto)"
|
Report-Warn "7. CommandsPlacement[$cmdName]: Placement='$($placementEl.InnerText.Trim())' (expected Auto)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($plcOk) { Report-OK "7. CommandsPlacement: $plcCount entries, all valid" }
|
if ($plcOk) { Report-OK "7. CommandsPlacement: $plcCount entries, all valid" }
|
||||||
} else {
|
} else {
|
||||||
Report-OK "7. CommandsPlacement: not present"
|
Report-OK "7. CommandsPlacement: not present"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 8. CommandsOrder ---
|
# --- 8. CommandsOrder ---
|
||||||
if (-not $script:stopped) {
|
if (-not $script:stopped) {
|
||||||
$ordSection = $root.SelectSingleNode("ci:CommandsOrder", $ns)
|
$ordSection = $root.SelectSingleNode("ci:CommandsOrder", $ns)
|
||||||
if ($ordSection) {
|
if ($ordSection) {
|
||||||
$ordOk = $true
|
$ordOk = $true
|
||||||
$ordCount = 0
|
$ordCount = 0
|
||||||
foreach ($cmd in $ordSection.ChildNodes) {
|
foreach ($cmd in $ordSection.ChildNodes) {
|
||||||
if ($cmd.NodeType -ne 'Element') { continue }
|
if ($cmd.NodeType -ne 'Element') { continue }
|
||||||
$ordCount++
|
$ordCount++
|
||||||
$cmdName = $cmd.GetAttribute("name")
|
$cmdName = $cmd.GetAttribute("name")
|
||||||
if (-not $cmdName) {
|
if (-not $cmdName) {
|
||||||
Report-Error "8. CommandsOrder: Command without 'name' attribute"
|
Report-Error "8. CommandsOrder: Command without 'name' attribute"
|
||||||
$ordOk = $false; continue
|
$ordOk = $false; continue
|
||||||
}
|
}
|
||||||
$script:allCommandNames += $cmdName
|
$script:allCommandNames += $cmdName
|
||||||
$grpEl = $cmd.SelectSingleNode("ci:CommandGroup", $ns)
|
$grpEl = $cmd.SelectSingleNode("ci:CommandGroup", $ns)
|
||||||
if (-not $grpEl -or -not $grpEl.InnerText.Trim()) {
|
if (-not $grpEl -or -not $grpEl.InnerText.Trim()) {
|
||||||
Report-Error "8. CommandsOrder[$cmdName]: missing or empty <CommandGroup>"
|
Report-Error "8. CommandsOrder[$cmdName]: missing or empty <CommandGroup>"
|
||||||
$ordOk = $false
|
$ordOk = $false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($ordOk) { Report-OK "8. CommandsOrder: $ordCount entries, all valid" }
|
if ($ordOk) { Report-OK "8. CommandsOrder: $ordCount entries, all valid" }
|
||||||
} else {
|
} else {
|
||||||
Report-OK "8. CommandsOrder: not present"
|
Report-OK "8. CommandsOrder: not present"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 9. SubsystemsOrder format ---
|
# --- 9. SubsystemsOrder format ---
|
||||||
if (-not $script:stopped) {
|
if (-not $script:stopped) {
|
||||||
$subSection = $root.SelectSingleNode("ci:SubsystemsOrder", $ns)
|
$subSection = $root.SelectSingleNode("ci:SubsystemsOrder", $ns)
|
||||||
$subNames = @()
|
$subNames = @()
|
||||||
if ($subSection) {
|
if ($subSection) {
|
||||||
$subOk = $true
|
$subOk = $true
|
||||||
$subCount = 0
|
$subCount = 0
|
||||||
foreach ($sub in $subSection.ChildNodes) {
|
foreach ($sub in $subSection.ChildNodes) {
|
||||||
if ($sub.NodeType -ne 'Element') { continue }
|
if ($sub.NodeType -ne 'Element') { continue }
|
||||||
$subCount++
|
$subCount++
|
||||||
$text = $sub.InnerText.Trim()
|
$text = $sub.InnerText.Trim()
|
||||||
$subNames += $text
|
$subNames += $text
|
||||||
if (-not $text) {
|
if (-not $text) {
|
||||||
Report-Error "9. SubsystemsOrder: empty <Subsystem> element"
|
Report-Error "9. SubsystemsOrder: empty <Subsystem> element"
|
||||||
$subOk = $false
|
$subOk = $false
|
||||||
} elseif ($text -notmatch '^Subsystem\.') {
|
} elseif ($text -notmatch '^Subsystem\.') {
|
||||||
Report-Error "9. SubsystemsOrder: '$text' - expected format Subsystem.X..."
|
Report-Error "9. SubsystemsOrder: '$text' - expected format Subsystem.X..."
|
||||||
$subOk = $false
|
$subOk = $false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($subOk) { Report-OK "9. SubsystemsOrder: $subCount entries, all valid format" }
|
if ($subOk) { Report-OK "9. SubsystemsOrder: $subCount entries, all valid format" }
|
||||||
} else {
|
} else {
|
||||||
Report-OK "9. SubsystemsOrder: not present"
|
Report-OK "9. SubsystemsOrder: not present"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 10. SubsystemsOrder duplicates ---
|
# --- 10. SubsystemsOrder duplicates ---
|
||||||
if (-not $script:stopped) {
|
if (-not $script:stopped) {
|
||||||
if ($subNames.Count -gt 0) {
|
if ($subNames.Count -gt 0) {
|
||||||
$dupes = $subNames | Group-Object | Where-Object { $_.Count -gt 1 }
|
$dupes = $subNames | Group-Object | Where-Object { $_.Count -gt 1 }
|
||||||
if ($dupes) {
|
if ($dupes) {
|
||||||
$dupeNames = ($dupes | ForEach-Object { $_.Name }) -join ", "
|
$dupeNames = ($dupes | ForEach-Object { $_.Name }) -join ", "
|
||||||
Report-Warn "10. SubsystemsOrder: duplicates: $dupeNames"
|
Report-Warn "10. SubsystemsOrder: duplicates: $dupeNames"
|
||||||
} else {
|
} else {
|
||||||
Report-OK "10. SubsystemsOrder: no duplicates"
|
Report-OK "10. SubsystemsOrder: no duplicates"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Report-OK "10. SubsystemsOrder: no duplicates (empty)"
|
Report-OK "10. SubsystemsOrder: no duplicates (empty)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 11. GroupsOrder entries ---
|
# --- 11. GroupsOrder entries ---
|
||||||
if (-not $script:stopped) {
|
if (-not $script:stopped) {
|
||||||
$grpSection = $root.SelectSingleNode("ci:GroupsOrder", $ns)
|
$grpSection = $root.SelectSingleNode("ci:GroupsOrder", $ns)
|
||||||
$grpNames = @()
|
$grpNames = @()
|
||||||
if ($grpSection) {
|
if ($grpSection) {
|
||||||
$grpOk = $true
|
$grpOk = $true
|
||||||
$grpCount = 0
|
$grpCount = 0
|
||||||
foreach ($grp in $grpSection.ChildNodes) {
|
foreach ($grp in $grpSection.ChildNodes) {
|
||||||
if ($grp.NodeType -ne 'Element') { continue }
|
if ($grp.NodeType -ne 'Element') { continue }
|
||||||
$grpCount++
|
$grpCount++
|
||||||
$text = $grp.InnerText.Trim()
|
$text = $grp.InnerText.Trim()
|
||||||
$grpNames += $text
|
$grpNames += $text
|
||||||
if (-not $text) {
|
if (-not $text) {
|
||||||
Report-Error "11. GroupsOrder: empty <Group> element"
|
Report-Error "11. GroupsOrder: empty <Group> element"
|
||||||
$grpOk = $false
|
$grpOk = $false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($grpOk) { Report-OK "11. GroupsOrder: $grpCount entries, all valid" }
|
if ($grpOk) { Report-OK "11. GroupsOrder: $grpCount entries, all valid" }
|
||||||
} else {
|
} else {
|
||||||
Report-OK "11. GroupsOrder: not present"
|
Report-OK "11. GroupsOrder: not present"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 12. GroupsOrder duplicates ---
|
# --- 12. GroupsOrder duplicates ---
|
||||||
if (-not $script:stopped) {
|
if (-not $script:stopped) {
|
||||||
if ($grpNames.Count -gt 0) {
|
if ($grpNames.Count -gt 0) {
|
||||||
$dupes = $grpNames | Group-Object | Where-Object { $_.Count -gt 1 }
|
$dupes = $grpNames | Group-Object | Where-Object { $_.Count -gt 1 }
|
||||||
if ($dupes) {
|
if ($dupes) {
|
||||||
$dupeNames = ($dupes | ForEach-Object { $_.Name }) -join ", "
|
$dupeNames = ($dupes | ForEach-Object { $_.Name }) -join ", "
|
||||||
Report-Warn "12. GroupsOrder: duplicates: $dupeNames"
|
Report-Warn "12. GroupsOrder: duplicates: $dupeNames"
|
||||||
} else {
|
} else {
|
||||||
Report-OK "12. GroupsOrder: no duplicates"
|
Report-OK "12. GroupsOrder: no duplicates"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Report-OK "12. GroupsOrder: no duplicates (empty)"
|
Report-OK "12. GroupsOrder: no duplicates (empty)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 13. Command reference format ---
|
# --- 13. Command reference format ---
|
||||||
if (-not $script:stopped) {
|
if (-not $script:stopped) {
|
||||||
if ($script:allCommandNames.Count -gt 0) {
|
if ($script:allCommandNames.Count -gt 0) {
|
||||||
$badRefs = @()
|
$badRefs = @()
|
||||||
foreach ($ref in $script:allCommandNames) {
|
foreach ($ref in $script:allCommandNames) {
|
||||||
if ($ref -match $stdCmdPattern) { continue }
|
if ($ref -match $stdCmdPattern) { continue }
|
||||||
if ($ref -match $customCmdPattern) { continue }
|
if ($ref -match $customCmdPattern) { continue }
|
||||||
if ($ref -match $commonCmdPattern) { continue }
|
if ($ref -match $commonCmdPattern) { continue }
|
||||||
if ($ref -match $uuidCmdPattern) { continue }
|
if ($ref -match $uuidCmdPattern) { continue }
|
||||||
$badRefs += $ref
|
$badRefs += $ref
|
||||||
}
|
}
|
||||||
if ($badRefs.Count -eq 0) {
|
if ($badRefs.Count -eq 0) {
|
||||||
Report-OK "13. Command reference format: all $($script:allCommandNames.Count) valid"
|
Report-OK "13. Command reference format: all $($script:allCommandNames.Count) valid"
|
||||||
} else {
|
} else {
|
||||||
$shown = $badRefs[0..([Math]::Min(4, $badRefs.Count - 1))]
|
$shown = $badRefs[0..([Math]::Min(4, $badRefs.Count - 1))]
|
||||||
Report-Warn "13. Command reference format: $($badRefs.Count) unrecognized: $($shown -join ', ')$(if($badRefs.Count -gt 5){' ...'})"
|
Report-Warn "13. Command reference format: $($badRefs.Count) unrecognized: $($shown -join ', ')$(if($badRefs.Count -gt 5){' ...'})"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Finalize ---
|
# --- Finalize ---
|
||||||
$checks = $script:okCount + $script:errors + $script:warnings
|
$checks = $script:okCount + $script:errors + $script:warnings
|
||||||
|
|
||||||
if ($script:errors -eq 0 -and $script:warnings -eq 0 -and -not $Detailed) {
|
if ($script:errors -eq 0 -and $script:warnings -eq 0 -and -not $Detailed) {
|
||||||
$result = "=== Validation OK: CommandInterface ($contextName) ($checks checks) ==="
|
$result = "=== Validation OK: CommandInterface ($contextName) ($checks checks) ==="
|
||||||
} else {
|
} else {
|
||||||
Out-Line ""
|
Out-Line ""
|
||||||
Out-Line "=== Result: $($script:errors) errors, $($script:warnings) warnings ($checks checks) ==="
|
Out-Line "=== Result: $($script:errors) errors, $($script:warnings) warnings ($checks checks) ==="
|
||||||
$result = $script:output.ToString()
|
$result = $script:output.ToString()
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host $result
|
Write-Host $result
|
||||||
|
|
||||||
if ($OutFile) {
|
if ($OutFile) {
|
||||||
if (-not [System.IO.Path]::IsPathRooted($OutFile)) {
|
if (-not [System.IO.Path]::IsPathRooted($OutFile)) {
|
||||||
$OutFile = Join-Path (Get-Location).Path $OutFile
|
$OutFile = Join-Path (Get-Location).Path $OutFile
|
||||||
}
|
}
|
||||||
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
||||||
[System.IO.File]::WriteAllText($OutFile, $result, $utf8Bom)
|
[System.IO.File]::WriteAllText($OutFile, $result, $utf8Bom)
|
||||||
Write-Host "Written to: $OutFile"
|
Write-Host "Written to: $OutFile"
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($script:errors -gt 0) { exit 1 } else { exit 0 }
|
if ($script:errors -gt 0) { exit 1 } else { exit 0 }
|
||||||
|
|||||||
@@ -1,119 +1,119 @@
|
|||||||
---
|
---
|
||||||
name: meta-compile
|
name: meta-compile
|
||||||
description: Создать объект метаданных 1С. Используй когда нужно создать или добавить справочник, документ, регистр, перечисление, константу, общий модуль, обработку, отчёт и др.
|
description: Создать объект метаданных 1С. Используй когда нужно создать или добавить справочник, документ, регистр, перечисление, константу, общий модуль, обработку, отчёт и др.
|
||||||
argument-hint: <JsonPath> <OutputDir>
|
argument-hint: <JsonPath> <OutputDir>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Write
|
- Write
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /meta-compile — генерация объектов метаданных из JSON DSL
|
# /meta-compile — генерация объектов метаданных из JSON DSL
|
||||||
|
|
||||||
Принимает JSON-определение объекта метаданных → генерирует XML + модули в структуре выгрузки конфигурации + регистрирует в Configuration.xml.
|
Принимает JSON-определение объекта метаданных → генерирует XML + модули в структуре выгрузки конфигурации + регистрирует в Configuration.xml.
|
||||||
|
|
||||||
## Порядок работы
|
## Порядок работы
|
||||||
|
|
||||||
1. Составь JSON по синтаксису и примерам ниже → запиши во временный файл
|
1. Составь JSON по синтаксису и примерам ниже → запиши во временный файл
|
||||||
2. Запусти скрипт meta-compile
|
2. Запусти скрипт meta-compile
|
||||||
3. Если нужно изменить созданный объект — `/meta-edit`
|
3. Если нужно изменить созданный объект — `/meta-edit`
|
||||||
4. Если нужно проверить — `/meta-validate`
|
4. Если нужно проверить — `/meta-validate`
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-compile.ps1" -JsonPath "<json>" -OutputDir "<ConfigDir>"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-compile.ps1" -JsonPath "<json>" -OutputDir "<ConfigDir>"
|
||||||
```
|
```
|
||||||
|
|
||||||
| Параметр | Описание |
|
| Параметр | Описание |
|
||||||
|----------|----------|
|
|----------|----------|
|
||||||
| `JsonPath` | Путь к JSON-файлу (один объект `{...}` или массив `[{...}, ...]`) |
|
| `JsonPath` | Путь к JSON-файлу (один объект `{...}` или массив `[{...}, ...]`) |
|
||||||
| `OutputDir` | Корень выгрузки конфигурации (где `Configuration.xml`, `Catalogs/`, `Documents/` и т.д.) |
|
| `OutputDir` | Корень выгрузки конфигурации (где `Configuration.xml`, `Catalogs/`, `Documents/` и т.д.) |
|
||||||
|
|
||||||
## JSON DSL
|
## JSON DSL
|
||||||
|
|
||||||
### Общая структура
|
### Общая структура
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "type": "Catalog", "name": "Номенклатура", ...свойства типа... }
|
{ "type": "Catalog", "name": "Номенклатура", ...свойства типа... }
|
||||||
```
|
```
|
||||||
|
|
||||||
`type` и `name` — обязательные. `synonym` генерируется из `name` автоматически (CamelCase → слова через пробел). Можно задать явно: `"synonym": "Мой синоним"`.
|
`type` и `name` — обязательные. `synonym` генерируется из `name` автоматически (CamelCase → слова через пробел). Можно задать явно: `"synonym": "Мой синоним"`.
|
||||||
|
|
||||||
### Shorthand реквизитов
|
### Shorthand реквизитов
|
||||||
|
|
||||||
Используется в `attributes`, `dimensions`, `resources`, `tabularSections`:
|
Используется в `attributes`, `dimensions`, `resources`, `tabularSections`:
|
||||||
|
|
||||||
```
|
```
|
||||||
"ИмяРеквизита" → String(10) по умолчанию
|
"ИмяРеквизита" → String(10) по умолчанию
|
||||||
"ИмяРеквизита: Тип" → с типом
|
"ИмяРеквизита: Тип" → с типом
|
||||||
"ИмяРеквизита: Тип | req, index" → с флагами
|
"ИмяРеквизита: Тип | req, index" → с флагами
|
||||||
```
|
```
|
||||||
|
|
||||||
Типы: `String(100)`, `Number(15,2)`, `Boolean`, `Date`, `DateTime`, `CatalogRef.Xxx`, `DocumentRef.Xxx`, `EnumRef.Xxx`, `DefinedType.Xxx` и др. ссылочные.
|
Типы: `String(100)`, `Number(15,2)`, `Boolean`, `Date`, `DateTime`, `CatalogRef.Xxx`, `DocumentRef.Xxx`, `EnumRef.Xxx`, `DefinedType.Xxx` и др. ссылочные.
|
||||||
|
|
||||||
Составной тип: `"Значение: String + Number(15,2) + CatalogRef.Контрагенты"`.
|
Составной тип: `"Значение: String + Number(15,2) + CatalogRef.Контрагенты"`.
|
||||||
|
|
||||||
Флаги: `req`, `index`, `indexAdditional`, `nonneg`, `master`, `mainFilter`, `denyIncomplete`, `useInTotals`.
|
Флаги: `req`, `index`, `indexAdditional`, `nonneg`, `master`, `mainFilter`, `denyIncomplete`, `useInTotals`.
|
||||||
|
|
||||||
### Свойства по типам
|
### Свойства по типам
|
||||||
|
|
||||||
Примеров и shorthand-синтаксиса выше достаточно для типовых задач. Если нужны свойства типа, не показанные в примерах, и их допустимые значения — см. reference-файл:
|
Примеров и shorthand-синтаксиса выше достаточно для типовых задач. Если нужны свойства типа, не показанные в примерах, и их допустимые значения — см. reference-файл:
|
||||||
|
|
||||||
- `reference/types-basic.md` — Catalog, Document, Enum, Constant, DefinedType, Report, DataProcessor
|
- `reference/types-basic.md` — Catalog, Document, Enum, Constant, DefinedType, Report, DataProcessor
|
||||||
- `reference/types-registers.md` — InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister, ChartOfAccounts, ChartOfCharacteristicTypes, ChartOfCalculationTypes
|
- `reference/types-registers.md` — InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister, ChartOfAccounts, ChartOfCharacteristicTypes, ChartOfCalculationTypes
|
||||||
- `reference/types-process.md` — BusinessProcess, Task, ExchangePlan, CommonModule, ScheduledJob, EventSubscription, DocumentJournal
|
- `reference/types-process.md` — BusinessProcess, Task, ExchangePlan, CommonModule, ScheduledJob, EventSubscription, DocumentJournal
|
||||||
- `reference/types-web.md` — HTTPService, WebService
|
- `reference/types-web.md` — HTTPService, WebService
|
||||||
|
|
||||||
Эта инструкция и reference-файлы — полная документация для генерации. Не ищи примеры XML в выгрузках конфигураций.
|
Эта инструкция и reference-файлы — полная документация для генерации. Не ищи примеры XML в выгрузках конфигураций.
|
||||||
|
|
||||||
## Примеры паттернов DSL
|
## Примеры паттернов DSL
|
||||||
|
|
||||||
### Минимальный объект
|
### Минимальный объект
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "type": "Catalog", "name": "Валюты" }
|
{ "type": "Catalog", "name": "Валюты" }
|
||||||
```
|
```
|
||||||
|
|
||||||
### С реквизитами
|
### С реквизитами
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"type": "Catalog", "name": "Организации",
|
"type": "Catalog", "name": "Организации",
|
||||||
"descriptionLength": 100,
|
"descriptionLength": 100,
|
||||||
"attributes": ["ИНН: String(12)", "КПП: String(9)", "Директор: CatalogRef.ФизическиеЛица"]
|
"attributes": ["ИНН: String(12)", "КПП: String(9)", "Директор: CatalogRef.ФизическиеЛица"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### С табличной частью
|
### С табличной частью
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"type": "Document", "name": "ПриходнаяНакладная",
|
"type": "Document", "name": "ПриходнаяНакладная",
|
||||||
"registerRecords": ["AccumulationRegister.ОстаткиТоваров"],
|
"registerRecords": ["AccumulationRegister.ОстаткиТоваров"],
|
||||||
"attributes": ["Организация: CatalogRef.Организации", "Контрагент: CatalogRef.Контрагенты"],
|
"attributes": ["Организация: CatalogRef.Организации", "Контрагент: CatalogRef.Контрагенты"],
|
||||||
"tabularSections": { "Товары": ["Номенклатура: CatalogRef.Номенклатура", "Количество: Number(15,3)", "Цена: Number(15,2)"] }
|
"tabularSections": { "Товары": ["Номенклатура: CatalogRef.Номенклатура", "Количество: Number(15,3)", "Цена: Number(15,2)"] }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Регистровый паттерн (измерения + ресурсы)
|
### Регистровый паттерн (измерения + ресурсы)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"type": "InformationRegister", "name": "КурсыВалют", "periodicity": "Day",
|
"type": "InformationRegister", "name": "КурсыВалют", "periodicity": "Day",
|
||||||
"dimensions": ["Валюта: CatalogRef.Валюты | master, mainFilter, denyIncomplete"],
|
"dimensions": ["Валюта: CatalogRef.Валюты | master, mainFilter, denyIncomplete"],
|
||||||
"resources": ["Курс: Number(15,4)", "Кратность: Number(10,0)"]
|
"resources": ["Курс: Number(15,4)", "Кратность: Number(10,0)"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Batch — несколько объектов в одном файле
|
### Batch — несколько объектов в одном файле
|
||||||
|
|
||||||
```json
|
```json
|
||||||
[
|
[
|
||||||
{ "type": "Enum", "name": "Статусы", "values": ["Новый", "Закрыт"] },
|
{ "type": "Enum", "name": "Статусы", "values": ["Новый", "Закрыт"] },
|
||||||
{ "type": "Catalog", "name": "Валюты" },
|
{ "type": "Catalog", "name": "Валюты" },
|
||||||
{ "type": "Constant", "name": "ОсновнаяВалюта", "valueType": "CatalogRef.Валюты" }
|
{ "type": "Constant", "name": "ОсновнаяВалюта", "valueType": "CatalogRef.Валюты" }
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+108
-108
@@ -1,108 +1,108 @@
|
|||||||
---
|
---
|
||||||
name: meta-edit
|
name: meta-edit
|
||||||
description: Точечное редактирование объекта метаданных 1С. Используй когда нужно добавить, удалить или изменить реквизиты, табличные части, измерения, ресурсы или свойства существующего объекта конфигурации
|
description: Точечное редактирование объекта метаданных 1С. Используй когда нужно добавить, удалить или изменить реквизиты, табличные части, измерения, ресурсы или свойства существующего объекта конфигурации
|
||||||
argument-hint: <ObjectPath> -Operation <op> -Value "<val>" | -DefinitionFile <json> [-NoValidate]
|
argument-hint: <ObjectPath> -Operation <op> -Value "<val>" | -DefinitionFile <json> [-NoValidate]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Write
|
- Write
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /meta-edit — точечное редактирование метаданных 1С
|
# /meta-edit — точечное редактирование метаданных 1С
|
||||||
|
|
||||||
Атомарные операции модификации существующих XML объектов метаданных.
|
Атомарные операции модификации существующих XML объектов метаданных.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
### Inline mode (простые операции)
|
### Inline mode (простые операции)
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-edit.ps1" -ObjectPath "<path>" -Operation <op> -Value "<val>"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-edit.ps1" -ObjectPath "<path>" -Operation <op> -Value "<val>"
|
||||||
```
|
```
|
||||||
|
|
||||||
### JSON mode (сложные/комбинированные)
|
### JSON mode (сложные/комбинированные)
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-edit.ps1" -DefinitionFile "<json>" -ObjectPath "<path>"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-edit.ps1" -DefinitionFile "<json>" -ObjectPath "<path>"
|
||||||
```
|
```
|
||||||
|
|
||||||
| Параметр | Описание |
|
| Параметр | Описание |
|
||||||
|----------|----------|
|
|----------|----------|
|
||||||
| ObjectPath | XML-файл или директория объекта (обязательный, авторезолв `<dirName>.xml`) |
|
| ObjectPath | XML-файл или директория объекта (обязательный, авторезолв `<dirName>.xml`) |
|
||||||
| Operation | Inline-операция (альтернатива DefinitionFile) |
|
| Operation | Inline-операция (альтернатива DefinitionFile) |
|
||||||
| Value | Значение для inline-операции |
|
| Value | Значение для inline-операции |
|
||||||
| DefinitionFile | JSON-файл с операциями (альтернатива Operation) |
|
| DefinitionFile | JSON-файл с операциями (альтернатива Operation) |
|
||||||
| NoValidate | Не запускать meta-validate после правки |
|
| NoValidate | Не запускать meta-validate после правки |
|
||||||
|
|
||||||
## Операции — сводная таблица
|
## Операции — сводная таблица
|
||||||
|
|
||||||
Batch через `;;` во всех операциях. Подробный синтаксис — в файлах по ссылкам.
|
Batch через `;;` во всех операциях. Подробный синтаксис — в файлах по ссылкам.
|
||||||
|
|
||||||
### Дочерние элементы — [child-operations.md](child-operations.md)
|
### Дочерние элементы — [child-operations.md](child-operations.md)
|
||||||
|
|
||||||
| Операция | Формат Value | Пример |
|
| Операция | Формат Value | Пример |
|
||||||
|----------|-------------|--------|
|
|----------|-------------|--------|
|
||||||
| `add-attribute` | `Имя: Тип \| флаги` | `"Сумма: Число(15,2) \| req, index"` |
|
| `add-attribute` | `Имя: Тип \| флаги` | `"Сумма: Число(15,2) \| req, index"` |
|
||||||
| `add-ts` | `ТЧ: Рекв1: Тип1, Рекв2: Тип2` | `"Товары: Ном: CatalogRef.Ном, Кол: Число(15,3)"` |
|
| `add-ts` | `ТЧ: Рекв1: Тип1, Рекв2: Тип2` | `"Товары: Ном: CatalogRef.Ном, Кол: Число(15,3)"` |
|
||||||
| `add-dimension` | `Имя: Тип \| флаги` | `"Организация: CatalogRef.Организации \| master"` |
|
| `add-dimension` | `Имя: Тип \| флаги` | `"Организация: CatalogRef.Организации \| master"` |
|
||||||
| `add-resource` | `Имя: Тип` | `"Сумма: Число(15,2)"` |
|
| `add-resource` | `Имя: Тип` | `"Сумма: Число(15,2)"` |
|
||||||
| `add-enumValue` | `Имя` | `"Значение1 ;; Значение2"` |
|
| `add-enumValue` | `Имя` | `"Значение1 ;; Значение2"` |
|
||||||
| `add-column` | `Имя: Тип` | `"Тип: EnumRef.ТипыДокументов"` |
|
| `add-column` | `Имя: Тип` | `"Тип: EnumRef.ТипыДокументов"` |
|
||||||
| `add-form` / `add-template` / `add-command` | `Имя` | `"ФормаЭлемента"` |
|
| `add-form` / `add-template` / `add-command` | `Имя` | `"ФормаЭлемента"` |
|
||||||
| `add-ts-attribute` | `ТЧ.Имя: Тип` | `"Товары.Скидка: Число(15,2)"` |
|
| `add-ts-attribute` | `ТЧ.Имя: Тип` | `"Товары.Скидка: Число(15,2)"` |
|
||||||
| `remove-*` | `Имя` | `"СтарыйРеквизит ;; ЕщёОдин"` |
|
| `remove-*` | `Имя` | `"СтарыйРеквизит ;; ЕщёОдин"` |
|
||||||
| `remove-ts-attribute` | `ТЧ.Имя` | `"Товары.УстаревшийРекв"` |
|
| `remove-ts-attribute` | `ТЧ.Имя` | `"Товары.УстаревшийРекв"` |
|
||||||
| `modify-attribute` | `Имя: ключ=значение` | `"СтароеИмя: name=НовоеИмя, type=Строка(500)"` |
|
| `modify-attribute` | `Имя: ключ=значение` | `"СтароеИмя: name=НовоеИмя, type=Строка(500)"` |
|
||||||
| `modify-ts-attribute` | `ТЧ.Имя: ключ=значение` | `"Товары.Рекв: name=НовоеИмя"` |
|
| `modify-ts-attribute` | `ТЧ.Имя: ключ=значение` | `"Товары.Рекв: name=НовоеИмя"` |
|
||||||
| `modify-ts` | `ТЧ: ключ=значение` | `"Товары: synonym=Товарный состав"` |
|
| `modify-ts` | `ТЧ: ключ=значение` | `"Товары: synonym=Товарный состав"` |
|
||||||
|
|
||||||
Позиционная вставка: `"Склад: CatalogRef.Склады >> after Организация"`.
|
Позиционная вставка: `"Склад: CatalogRef.Склады >> after Организация"`.
|
||||||
|
|
||||||
### Свойства объекта — [properties-reference.md](properties-reference.md)
|
### Свойства объекта — [properties-reference.md](properties-reference.md)
|
||||||
|
|
||||||
| Операция | Формат Value | Пример |
|
| Операция | Формат Value | Пример |
|
||||||
|----------|-------------|--------|
|
|----------|-------------|--------|
|
||||||
| `modify-property` | `Ключ=Значение` | `"CodeLength=11 ;; DescriptionLength=150"` |
|
| `modify-property` | `Ключ=Значение` | `"CodeLength=11 ;; DescriptionLength=150"` |
|
||||||
| `add-owner` | `MetaType.Name` | `"Catalog.Контрагенты ;; Catalog.Организации"` |
|
| `add-owner` | `MetaType.Name` | `"Catalog.Контрагенты ;; Catalog.Организации"` |
|
||||||
| `add-registerRecord` | `MetaType.Name` | `"AccumulationRegister.ОстаткиТоваров"` |
|
| `add-registerRecord` | `MetaType.Name` | `"AccumulationRegister.ОстаткиТоваров"` |
|
||||||
| `add-basedOn` | `MetaType.Name` | `"Document.ЗаказКлиента"` |
|
| `add-basedOn` | `MetaType.Name` | `"Document.ЗаказКлиента"` |
|
||||||
| `add-inputByString` | `Путь поля` | `"StandardAttribute.Description"` |
|
| `add-inputByString` | `Путь поля` | `"StandardAttribute.Description"` |
|
||||||
| `set-owners` / `set-registerRecords` / `set-basedOn` / `set-inputByString` | Замена всего списка | `"Catalog.Орг ;; Catalog.Контр"` |
|
| `set-owners` / `set-registerRecords` / `set-basedOn` / `set-inputByString` | Замена всего списка | `"Catalog.Орг ;; Catalog.Контр"` |
|
||||||
| `remove-owner` / `remove-registerRecord` / ... | Удаление из списка | `"Catalog.Контрагенты"` |
|
| `remove-owner` / `remove-registerRecord` / ... | Удаление из списка | `"Catalog.Контрагенты"` |
|
||||||
|
|
||||||
### JSON DSL — [json-dsl.md](json-dsl.md)
|
### JSON DSL — [json-dsl.md](json-dsl.md)
|
||||||
|
|
||||||
Для комбинированных операций (add + remove + modify в одном файле), синонимы ключей/типов, таблица поддерживаемых объектов.
|
Для комбинированных операций (add + remove + modify в одном файле), синонимы ключей/типов, таблица поддерживаемых объектов.
|
||||||
|
|
||||||
## Быстрые примеры
|
## Быстрые примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Добавить реквизиты
|
# Добавить реквизиты
|
||||||
-Operation add-attribute -Value "Комментарий: Строка(200) ;; Сумма: Число(15,2) | index"
|
-Operation add-attribute -Value "Комментарий: Строка(200) ;; Сумма: Число(15,2) | index"
|
||||||
|
|
||||||
# Составной тип (несколько типов через +)
|
# Составной тип (несколько типов через +)
|
||||||
-Operation add-attribute -Value "Значение: Строка + Число(15,2) + Дата + CatalogRef.Контрагенты"
|
-Operation add-attribute -Value "Значение: Строка + Число(15,2) + Дата + CatalogRef.Контрагенты"
|
||||||
|
|
||||||
# Добавить ТЧ с реквизитами
|
# Добавить ТЧ с реквизитами
|
||||||
-Operation add-ts -Value "Товары: Ном: CatalogRef.Ном | req, Кол: Число(15,3), Цена: Число(15,2)"
|
-Operation add-ts -Value "Товары: Ном: CatalogRef.Ном | req, Кол: Число(15,3), Цена: Число(15,2)"
|
||||||
|
|
||||||
# Удалить реквизит
|
# Удалить реквизит
|
||||||
-Operation remove-attribute -Value "УстаревшийРеквизит"
|
-Operation remove-attribute -Value "УстаревшийРеквизит"
|
||||||
|
|
||||||
# Переименовать + сменить тип
|
# Переименовать + сменить тип
|
||||||
-Operation modify-attribute -Value "СтароеИмя: name=НовоеИмя, type=Строка(500)"
|
-Operation modify-attribute -Value "СтароеИмя: name=НовоеИмя, type=Строка(500)"
|
||||||
|
|
||||||
# Изменить свойства объекта
|
# Изменить свойства объекта
|
||||||
-Operation modify-property -Value "CodeLength=11 ;; DescriptionLength=150"
|
-Operation modify-property -Value "CodeLength=11 ;; DescriptionLength=150"
|
||||||
|
|
||||||
# Владельцы справочника
|
# Владельцы справочника
|
||||||
-Operation set-owners -Value "Catalog.Контрагенты ;; Catalog.Организации"
|
-Operation set-owners -Value "Catalog.Контрагенты ;; Catalog.Организации"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Верификация
|
## Верификация
|
||||||
|
|
||||||
```
|
```
|
||||||
/meta-validate <ObjectPath> — валидация после редактирования
|
/meta-validate <ObjectPath> — валидация после редактирования
|
||||||
/meta-info <ObjectPath> — визуальная сводка
|
/meta-info <ObjectPath> — визуальная сводка
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,116 +1,116 @@
|
|||||||
# Inline-операции над дочерними элементами
|
# Inline-операции над дочерними элементами
|
||||||
|
|
||||||
Подробный справочник операций `add-*` / `remove-*` / `modify-*` для дочерних элементов объекта метаданных.
|
Подробный справочник операций `add-*` / `remove-*` / `modify-*` для дочерних элементов объекта метаданных.
|
||||||
|
|
||||||
## Общие правила
|
## Общие правила
|
||||||
|
|
||||||
**Batch-режим** — несколько элементов через `;;`:
|
**Batch-режим** — несколько элементов через `;;`:
|
||||||
```
|
```
|
||||||
-Value "Комментарий: Строка(200) ;; Сумма: Число(15,2) | index"
|
-Value "Комментарий: Строка(200) ;; Сумма: Число(15,2) | index"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Shorthand-формат** реквизитов: `ИмяРеквизита: Тип | флаги`
|
**Shorthand-формат** реквизитов: `ИмяРеквизита: Тип | флаги`
|
||||||
|
|
||||||
Флаги: `req` (FillChecking=ShowError), `index` (Indexing=Index), `master` (Master=true, только dimensions), `mainFilter` (MainFilterOperand, только dimensions).
|
Флаги: `req` (FillChecking=ShowError), `index` (Indexing=Index), `master` (Master=true, только dimensions), `mainFilter` (MainFilterOperand, только dimensions).
|
||||||
|
|
||||||
**Позиционная вставка**: `>> after ИмяЭлемента` или `<< before ИмяЭлемента`:
|
**Позиционная вставка**: `>> after ИмяЭлемента` или `<< before ИмяЭлемента`:
|
||||||
```powershell
|
```powershell
|
||||||
-Operation add-attribute -Value "Склад: CatalogRef.Склады >> after Организация"
|
-Operation add-attribute -Value "Склад: CatalogRef.Склады >> after Организация"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Составные типы
|
## Составные типы
|
||||||
|
|
||||||
Для реквизитов с несколькими допустимыми типами — разделитель `+`:
|
Для реквизитов с несколькими допустимыми типами — разделитель `+`:
|
||||||
```powershell
|
```powershell
|
||||||
-Operation add-attribute -Value "Значение: Строка + Число(15,2) + Дата + CatalogRef.Контрагенты"
|
-Operation add-attribute -Value "Значение: Строка + Число(15,2) + Дата + CatalogRef.Контрагенты"
|
||||||
-Operation add-attribute -Value "Значение: Строка + Число(15,2) | req"
|
-Operation add-attribute -Value "Значение: Строка + Число(15,2) | req"
|
||||||
-Operation modify-ts-attribute -Value "Данные.Значение: type=Строка + Число(15,2) + Дата"
|
-Operation modify-ts-attribute -Value "Данные.Значение: type=Строка + Число(15,2) + Дата"
|
||||||
```
|
```
|
||||||
|
|
||||||
В JSON DSL — массив в `type`:
|
В JSON DSL — массив в `type`:
|
||||||
```json
|
```json
|
||||||
{ "name": "Значение", "type": ["Строка", "Число(15,2)", "Дата", "CatalogRef.Контрагенты"] }
|
{ "name": "Значение", "type": ["Строка", "Число(15,2)", "Дата", "CatalogRef.Контрагенты"] }
|
||||||
```
|
```
|
||||||
|
|
||||||
## add-attribute / add-dimension / add-resource / add-column
|
## add-attribute / add-dimension / add-resource / add-column
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
-Operation add-attribute -Value "Комментарий: Строка(200)"
|
-Operation add-attribute -Value "Комментарий: Строка(200)"
|
||||||
-Operation add-attribute -Value "Сумма: Число(15,2) | req, index"
|
-Operation add-attribute -Value "Сумма: Число(15,2) | req, index"
|
||||||
-Operation add-attribute -Value "Ном: CatalogRef.Номенклатура | req ;; Кол: Число(15,3)"
|
-Operation add-attribute -Value "Ном: CatalogRef.Номенклатура | req ;; Кол: Число(15,3)"
|
||||||
-Operation add-dimension -Value "Организация: CatalogRef.Организации | master, mainFilter"
|
-Operation add-dimension -Value "Организация: CatalogRef.Организации | master, mainFilter"
|
||||||
-Operation add-resource -Value "Сумма: Число(15,2)"
|
-Operation add-resource -Value "Сумма: Число(15,2)"
|
||||||
-Operation add-column -Value "Тип: EnumRef.ТипыДокументов"
|
-Operation add-column -Value "Тип: EnumRef.ТипыДокументов"
|
||||||
```
|
```
|
||||||
|
|
||||||
## add-ts
|
## add-ts
|
||||||
|
|
||||||
Формат: `ИмяТЧ: Реквизит1: Тип1, Реквизит2: Тип2, ...`
|
Формат: `ИмяТЧ: Реквизит1: Тип1, Реквизит2: Тип2, ...`
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
-Operation add-ts -Value "Товары: Ном: CatalogRef.Ном | req, Кол: Число(15,3), Цена: Число(15,2), Сумма: Число(15,2)"
|
-Operation add-ts -Value "Товары: Ном: CatalogRef.Ном | req, Кол: Число(15,3), Цена: Число(15,2), Сумма: Число(15,2)"
|
||||||
```
|
```
|
||||||
|
|
||||||
## add-ts-attribute / remove-ts-attribute / modify-ts-attribute
|
## add-ts-attribute / remove-ts-attribute / modify-ts-attribute
|
||||||
|
|
||||||
Операции над реквизитами **внутри существующей ТЧ**. Формат: `ИмяТЧ.ОпределениеРеквизита` (dot-нотация).
|
Операции над реквизитами **внутри существующей ТЧ**. Формат: `ИмяТЧ.ОпределениеРеквизита` (dot-нотация).
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Добавить реквизит в ТЧ
|
# Добавить реквизит в ТЧ
|
||||||
-Operation add-ts-attribute -Value "Товары.СтавкаНДС: EnumRef.СтавкиНДС"
|
-Operation add-ts-attribute -Value "Товары.СтавкаНДС: EnumRef.СтавкиНДС"
|
||||||
-Operation add-ts-attribute -Value "Товары.Скидка: Число(15,2) ;; Товары.Бонус: Число(15,2)"
|
-Operation add-ts-attribute -Value "Товары.Скидка: Число(15,2) ;; Товары.Бонус: Число(15,2)"
|
||||||
|
|
||||||
# Позиционная вставка в ТЧ
|
# Позиционная вставка в ТЧ
|
||||||
-Operation add-ts-attribute -Value "Товары.Скидка: Число(15,2) >> after Цена"
|
-Operation add-ts-attribute -Value "Товары.Скидка: Число(15,2) >> after Цена"
|
||||||
|
|
||||||
# Удалить реквизит из ТЧ
|
# Удалить реквизит из ТЧ
|
||||||
-Operation remove-ts-attribute -Value "Товары.УстаревшийРекв"
|
-Operation remove-ts-attribute -Value "Товары.УстаревшийРекв"
|
||||||
-Operation remove-ts-attribute -Value "Товары.Рекв1 ;; Товары.Рекв2"
|
-Operation remove-ts-attribute -Value "Товары.Рекв1 ;; Товары.Рекв2"
|
||||||
|
|
||||||
# Изменить реквизит в ТЧ (rename, type change и т.д.)
|
# Изменить реквизит в ТЧ (rename, type change и т.д.)
|
||||||
-Operation modify-ts-attribute -Value "Товары.СтароеИмя: name=НовоеИмя, type=Строка(500)"
|
-Operation modify-ts-attribute -Value "Товары.СтароеИмя: name=НовоеИмя, type=Строка(500)"
|
||||||
```
|
```
|
||||||
|
|
||||||
Batch через `;;` — можно указать разные ТЧ: `"Товары.А: Строка(50) ;; Услуги.Б: Число(10)"`.
|
Batch через `;;` — можно указать разные ТЧ: `"Товары.А: Строка(50) ;; Услуги.Б: Число(10)"`.
|
||||||
|
|
||||||
## modify-ts
|
## modify-ts
|
||||||
|
|
||||||
Изменение свойств **самой табличной части** (Synonym, FillChecking, Use и др.):
|
Изменение свойств **самой табличной части** (Synonym, FillChecking, Use и др.):
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
-Operation modify-ts -Value "Товары: synonym=Товарный состав"
|
-Operation modify-ts -Value "Товары: synonym=Товарный состав"
|
||||||
-Operation modify-ts -Value "Товары: fillChecking=ShowError"
|
-Operation modify-ts -Value "Товары: fillChecking=ShowError"
|
||||||
```
|
```
|
||||||
|
|
||||||
Формат аналогичен `modify-attribute`: `ИмяТЧ: ключ=значение, ключ=значение`.
|
Формат аналогичен `modify-attribute`: `ИмяТЧ: ключ=значение, ключ=значение`.
|
||||||
|
|
||||||
## add-enumValue / add-form / add-template / add-command
|
## add-enumValue / add-form / add-template / add-command
|
||||||
|
|
||||||
Просто имена (batch через `;;`):
|
Просто имена (batch через `;;`):
|
||||||
```powershell
|
```powershell
|
||||||
-Operation add-enumValue -Value "Значение1 ;; Значение2 ;; Значение3"
|
-Operation add-enumValue -Value "Значение1 ;; Значение2 ;; Значение3"
|
||||||
-Operation add-form -Value "ФормаЭлемента ;; ФормаСписка"
|
-Operation add-form -Value "ФормаЭлемента ;; ФормаСписка"
|
||||||
-Operation add-template -Value "ПечатнаяФорма"
|
-Operation add-template -Value "ПечатнаяФорма"
|
||||||
-Operation add-command -Value "Команда1"
|
-Operation add-command -Value "Команда1"
|
||||||
```
|
```
|
||||||
|
|
||||||
## remove-*
|
## remove-*
|
||||||
|
|
||||||
Имя элемента (или несколько через `;;`):
|
Имя элемента (или несколько через `;;`):
|
||||||
```powershell
|
```powershell
|
||||||
-Operation remove-attribute -Value "СтарыйРеквизит ;; ЕщёОдин"
|
-Operation remove-attribute -Value "СтарыйРеквизит ;; ЕщёОдин"
|
||||||
-Operation remove-ts -Value "УстаревшаяТЧ"
|
-Operation remove-ts -Value "УстаревшаяТЧ"
|
||||||
-Operation remove-enumValue -Value "НеиспользуемоеЗначение"
|
-Operation remove-enumValue -Value "НеиспользуемоеЗначение"
|
||||||
```
|
```
|
||||||
|
|
||||||
## modify-attribute / modify-dimension / modify-resource / modify-enumValue / modify-column
|
## modify-attribute / modify-dimension / modify-resource / modify-enumValue / modify-column
|
||||||
|
|
||||||
Формат: `ИмяЭлемента: ключ=значение, ключ=значение`
|
Формат: `ИмяЭлемента: ключ=значение, ключ=значение`
|
||||||
|
|
||||||
Ключи: `name` (rename), `type`, `synonym`, `indexing`, `fillChecking`, `use` и др.
|
Ключи: `name` (rename), `type`, `synonym`, `indexing`, `fillChecking`, `use` и др.
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
-Operation modify-attribute -Value "СтароеИмя: name=НовоеИмя, type=Строка(500)"
|
-Operation modify-attribute -Value "СтароеИмя: name=НовоеИмя, type=Строка(500)"
|
||||||
-Operation modify-attribute -Value "Комментарий: indexing=Index"
|
-Operation modify-attribute -Value "Комментарий: indexing=Index"
|
||||||
-Operation modify-enumValue -Value "СтароеЗначение: name=НовоеЗначение"
|
-Operation modify-enumValue -Value "СтароеЗначение: name=НовоеЗначение"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,148 +1,148 @@
|
|||||||
# JSON DSL — режим определений
|
# JSON DSL — режим определений
|
||||||
|
|
||||||
Для сложных и комбинированных операций используйте JSON-файл вместо inline-режима.
|
Для сложных и комбинированных операций используйте JSON-файл вместо inline-режима.
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File .claude/skills/meta-edit/scripts/meta-edit.ps1 -DefinitionFile "<json>" -ObjectPath "<path>"
|
powershell.exe -NoProfile -File .claude/skills/meta-edit/scripts/meta-edit.ps1 -DefinitionFile "<json>" -ObjectPath "<path>"
|
||||||
```
|
```
|
||||||
|
|
||||||
## add — добавить элементы
|
## add — добавить элементы
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"add": {
|
"add": {
|
||||||
"attributes": [
|
"attributes": [
|
||||||
{ "name": "Комментарий", "type": "Строка(200)" },
|
{ "name": "Комментарий", "type": "Строка(200)" },
|
||||||
{ "name": "Сумма", "type": "Число(15,2)", "indexing": "Index" }
|
{ "name": "Сумма", "type": "Число(15,2)", "indexing": "Index" }
|
||||||
],
|
],
|
||||||
"tabularSections": [{
|
"tabularSections": [{
|
||||||
"name": "Товары",
|
"name": "Товары",
|
||||||
"attrs": [
|
"attrs": [
|
||||||
{ "name": "Номенклатура", "type": "CatalogRef.Номенклатура" },
|
{ "name": "Номенклатура", "type": "CatalogRef.Номенклатура" },
|
||||||
{ "name": "Количество", "type": "Число(15,3)" }
|
{ "name": "Количество", "type": "Число(15,3)" }
|
||||||
]
|
]
|
||||||
}],
|
}],
|
||||||
"forms": ["ФормаЭлемента"],
|
"forms": ["ФормаЭлемента"],
|
||||||
"templates": ["ПечатнаяФорма"]
|
"templates": ["ПечатнаяФорма"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Реквизиты можно задавать shorthand-строками: `"Сумма: Число(15,2) | req, index"`.
|
Реквизиты можно задавать shorthand-строками: `"Сумма: Число(15,2) | req, index"`.
|
||||||
|
|
||||||
## remove — удалить элементы
|
## remove — удалить элементы
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"remove": {
|
"remove": {
|
||||||
"attributes": ["СтарыйРеквизит"],
|
"attributes": ["СтарыйРеквизит"],
|
||||||
"tabularSections": ["УстаревшаяТЧ"]
|
"tabularSections": ["УстаревшаяТЧ"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## modify — изменить существующие
|
## modify — изменить существующие
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"modify": {
|
"modify": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"CodeLength": 11,
|
"CodeLength": 11,
|
||||||
"Hierarchical": true,
|
"Hierarchical": true,
|
||||||
"Owners": ["Catalog.Контрагенты", "Catalog.Организации"],
|
"Owners": ["Catalog.Контрагенты", "Catalog.Организации"],
|
||||||
"RegisterRecords": ["AccumulationRegister.Продажи"],
|
"RegisterRecords": ["AccumulationRegister.Продажи"],
|
||||||
"InputByString": ["StandardAttribute.Description"]
|
"InputByString": ["StandardAttribute.Description"]
|
||||||
},
|
},
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"Комментарий": { "type": "Строка(500)" },
|
"Комментарий": { "type": "Строка(500)" },
|
||||||
"СтароеИмя": { "name": "НовоеИмя" }
|
"СтароеИмя": { "name": "НовоеИмя" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## modify — реквизиты внутри ТЧ
|
## modify — реквизиты внутри ТЧ
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"modify": {
|
"modify": {
|
||||||
"tabularSections": {
|
"tabularSections": {
|
||||||
"Товары": {
|
"Товары": {
|
||||||
"add": ["СтавкаНДС: EnumRef.СтавкиНДС", "Скидка: Число(15,2)"],
|
"add": ["СтавкаНДС: EnumRef.СтавкиНДС", "Скидка: Число(15,2)"],
|
||||||
"remove": ["УстаревшийРекв"],
|
"remove": ["УстаревшийРекв"],
|
||||||
"modify": {
|
"modify": {
|
||||||
"СтароеИмя": { "name": "НовоеИмя", "type": "Строка(500)" }
|
"СтароеИмя": { "name": "НовоеИмя", "type": "Строка(500)" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Комбинирование
|
## Комбинирование
|
||||||
|
|
||||||
Все три операции (`add`, `remove`, `modify`) можно указать в одном JSON-файле:
|
Все три операции (`add`, `remove`, `modify`) можно указать в одном JSON-файле:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"add": { "tabularSections": [{ "name": "НоваяТЧ", "attrs": ["Имя: Строка(100)"] }] },
|
"add": { "tabularSections": [{ "name": "НоваяТЧ", "attrs": ["Имя: Строка(100)"] }] },
|
||||||
"modify": {
|
"modify": {
|
||||||
"tabularSections": {
|
"tabularSections": {
|
||||||
"СуществующаяТЧ": {
|
"СуществующаяТЧ": {
|
||||||
"add": ["НовыйРекв: Число(15,2)"],
|
"add": ["НовыйРекв: Число(15,2)"],
|
||||||
"remove": ["СтарыйРекв"]
|
"remove": ["СтарыйРекв"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Позиционная вставка
|
## Позиционная вставка
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "name": "Склад", "type": "CatalogRef.Склады", "after": "Организация" }
|
{ "name": "Склад", "type": "CatalogRef.Склады", "after": "Организация" }
|
||||||
```
|
```
|
||||||
|
|
||||||
## Синонимы ключей (case-insensitive)
|
## Синонимы ключей (case-insensitive)
|
||||||
|
|
||||||
**Операции:** `add`/`добавить`, `remove`/`удалить`, `modify`/`изменить`
|
**Операции:** `add`/`добавить`, `remove`/`удалить`, `modify`/`изменить`
|
||||||
|
|
||||||
| Каноническое | Синонимы |
|
| Каноническое | Синонимы |
|
||||||
|-------------|----------|
|
|-------------|----------|
|
||||||
| attributes | реквизиты, attrs |
|
| attributes | реквизиты, attrs |
|
||||||
| tabularSections | табличныеЧасти, тч, ts |
|
| tabularSections | табличныеЧасти, тч, ts |
|
||||||
| dimensions | измерения, dims |
|
| dimensions | измерения, dims |
|
||||||
| resources | ресурсы, res |
|
| resources | ресурсы, res |
|
||||||
| enumValues | значения, values |
|
| enumValues | значения, values |
|
||||||
| columns | графы, колонки |
|
| columns | графы, колонки |
|
||||||
| forms | формы |
|
| forms | формы |
|
||||||
| templates | макеты |
|
| templates | макеты |
|
||||||
| commands | команды |
|
| commands | команды |
|
||||||
| properties | свойства |
|
| properties | свойства |
|
||||||
|
|
||||||
## Составные типы
|
## Составные типы
|
||||||
|
|
||||||
Для полей с несколькими допустимыми типами — массив в `type`:
|
Для полей с несколькими допустимыми типами — массив в `type`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "name": "Значение", "type": ["Строка", "Число(15,2)", "Дата", "CatalogRef.Контрагенты"] }
|
{ "name": "Значение", "type": ["Строка", "Число(15,2)", "Дата", "CatalogRef.Контрагенты"] }
|
||||||
```
|
```
|
||||||
|
|
||||||
В inline-формате — через `+`:
|
В inline-формате — через `+`:
|
||||||
```
|
```
|
||||||
"Значение: Строка + Число(15,2) + Дата + CatalogRef.Контрагенты"
|
"Значение: Строка + Число(15,2) + Дата + CatalogRef.Контрагенты"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Синонимы типов
|
## Синонимы типов
|
||||||
|
|
||||||
`Строка(200)`, `Число(15,2)`, `Булево`, `Дата`, `ДатаВремя`, `ХранилищеЗначения`, `СправочникСсылка.XXX`, `ДокументСсылка.XXX`, `ПеречислениеСсылка.XXX`, `ОпределяемыйТип.XXX`.
|
`Строка(200)`, `Число(15,2)`, `Булево`, `Дата`, `ДатаВремя`, `ХранилищеЗначения`, `СправочникСсылка.XXX`, `ДокументСсылка.XXX`, `ПеречислениеСсылка.XXX`, `ОпределяемыйТип.XXX`.
|
||||||
|
|
||||||
## Поддерживаемые типы объектов
|
## Поддерживаемые типы объектов
|
||||||
|
|
||||||
| Тип объекта | Допустимые add-типы |
|
| Тип объекта | Допустимые add-типы |
|
||||||
|-------------|-------------------|
|
|-------------|-------------------|
|
||||||
| Catalog, Document, ExchangePlan, ChartOf*, BP, Task, Report, DP | attributes, tabularSections, forms, templates, commands |
|
| Catalog, Document, ExchangePlan, ChartOf*, BP, Task, Report, DP | attributes, tabularSections, forms, templates, commands |
|
||||||
| Enum | enumValues, forms, templates, commands |
|
| Enum | enumValues, forms, templates, commands |
|
||||||
| *Register (4 типа) | dimensions, resources, attributes, forms, templates, commands |
|
| *Register (4 типа) | dimensions, resources, attributes, forms, templates, commands |
|
||||||
| DocumentJournal | columns, forms, templates, commands |
|
| DocumentJournal | columns, forms, templates, commands |
|
||||||
| Constant | forms |
|
| Constant | forms |
|
||||||
|
|||||||
@@ -1,54 +1,54 @@
|
|||||||
# Свойства объекта и complex properties
|
# Свойства объекта и complex properties
|
||||||
|
|
||||||
Справочник операций для скалярных свойств объекта и свойств со вложенной XML-структурой (Owners, RegisterRecords, BasedOn, InputByString).
|
Справочник операций для скалярных свойств объекта и свойств со вложенной XML-структурой (Owners, RegisterRecords, BasedOn, InputByString).
|
||||||
|
|
||||||
## modify-property
|
## modify-property
|
||||||
|
|
||||||
Изменение скалярных свойств объекта. Формат: `Ключ=Значение` (batch через `;;`):
|
Изменение скалярных свойств объекта. Формат: `Ключ=Значение` (batch через `;;`):
|
||||||
```powershell
|
```powershell
|
||||||
-Operation modify-property -Value "CodeLength=11 ;; DescriptionLength=150"
|
-Operation modify-property -Value "CodeLength=11 ;; DescriptionLength=150"
|
||||||
-Operation modify-property -Value "Hierarchical=true"
|
-Operation modify-property -Value "Hierarchical=true"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Complex properties
|
## Complex properties
|
||||||
|
|
||||||
Свойства со вложенной XML-структурой. Поддерживаются через inline `add-*` / `remove-*` / `set-*` и через JSON `modify.properties`.
|
Свойства со вложенной XML-структурой. Поддерживаются через inline `add-*` / `remove-*` / `set-*` и через JSON `modify.properties`.
|
||||||
|
|
||||||
| Свойство | Объекты | Inline-значение |
|
| Свойство | Объекты | Inline-значение |
|
||||||
|----------|---------|-----------------|
|
|----------|---------|-----------------|
|
||||||
| Owners | Catalog, ChartOfCharacteristicTypes | `Catalog.XXX` |
|
| Owners | Catalog, ChartOfCharacteristicTypes | `Catalog.XXX` |
|
||||||
| RegisterRecords | Document | `AccumulationRegister.XXX` |
|
| RegisterRecords | Document | `AccumulationRegister.XXX` |
|
||||||
| BasedOn | Document, Catalog, BP, Task | `Document.XXX` |
|
| BasedOn | Document, Catalog, BP, Task | `Document.XXX` |
|
||||||
| InputByString | Catalog, ChartOf*, Task | `StandardAttribute.Description` |
|
| InputByString | Catalog, ChartOf*, Task | `StandardAttribute.Description` |
|
||||||
|
|
||||||
### add-owner / add-registerRecord / add-basedOn
|
### add-owner / add-registerRecord / add-basedOn
|
||||||
|
|
||||||
Полное имя метаданных `MetaType.Name`:
|
Полное имя метаданных `MetaType.Name`:
|
||||||
```powershell
|
```powershell
|
||||||
-Operation add-owner -Value "Catalog.Контрагенты ;; Catalog.Организации"
|
-Operation add-owner -Value "Catalog.Контрагенты ;; Catalog.Организации"
|
||||||
-Operation add-registerRecord -Value "AccumulationRegister.ОстаткиТоваров"
|
-Operation add-registerRecord -Value "AccumulationRegister.ОстаткиТоваров"
|
||||||
-Operation add-basedOn -Value "Document.ЗаказКлиента"
|
-Operation add-basedOn -Value "Document.ЗаказКлиента"
|
||||||
```
|
```
|
||||||
|
|
||||||
### add-inputByString
|
### add-inputByString
|
||||||
|
|
||||||
Пути полей (префикс `MetaType.Name.` добавляется автоматически):
|
Пути полей (префикс `MetaType.Name.` добавляется автоматически):
|
||||||
```powershell
|
```powershell
|
||||||
-Operation add-inputByString -Value "StandardAttribute.Description ;; StandardAttribute.Code"
|
-Operation add-inputByString -Value "StandardAttribute.Description ;; StandardAttribute.Code"
|
||||||
```
|
```
|
||||||
|
|
||||||
### remove-owner / remove-registerRecord / remove-basedOn / remove-inputByString
|
### remove-owner / remove-registerRecord / remove-basedOn / remove-inputByString
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
-Operation remove-owner -Value "Catalog.Контрагенты"
|
-Operation remove-owner -Value "Catalog.Контрагенты"
|
||||||
-Operation remove-inputByString -Value "Catalog.МойСпр.StandardAttribute.Code"
|
-Operation remove-inputByString -Value "Catalog.МойСпр.StandardAttribute.Code"
|
||||||
```
|
```
|
||||||
|
|
||||||
### set-owners / set-registerRecords / set-basedOn / set-inputByString
|
### set-owners / set-registerRecords / set-basedOn / set-inputByString
|
||||||
|
|
||||||
Заменяют **весь список** (в отличие от add/remove):
|
Заменяют **весь список** (в отличие от add/remove):
|
||||||
```powershell
|
```powershell
|
||||||
-Operation set-owners -Value "Catalog.Организации ;; Catalog.Контрагенты"
|
-Operation set-owners -Value "Catalog.Организации ;; Catalog.Контрагенты"
|
||||||
-Operation set-registerRecords -Value "AccumulationRegister.Продажи ;; AccumulationRegister.ОстаткиТоваров"
|
-Operation set-registerRecords -Value "AccumulationRegister.Продажи ;; AccumulationRegister.ОстаткиТоваров"
|
||||||
-Operation set-inputByString -Value "StandardAttribute.Description ;; StandardAttribute.Code"
|
-Operation set-inputByString -Value "StandardAttribute.Description ;; StandardAttribute.Code"
|
||||||
```
|
```
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,87 +1,87 @@
|
|||||||
---
|
---
|
||||||
name: meta-info
|
name: meta-info
|
||||||
description: Анализ структуры объекта метаданных 1С из XML-выгрузки — реквизиты, табличные части, формы, движения, типы. Используй для изучения структуры объектов (вместо чтения XML-файлов напрямую) и как подготовительный шаг при написании запросов и кода, работающего с объектами
|
description: Анализ структуры объекта метаданных 1С из XML-выгрузки — реквизиты, табличные части, формы, движения, типы. Используй для изучения структуры объектов (вместо чтения XML-файлов напрямую) и как подготовительный шаг при написании запросов и кода, работающего с объектами
|
||||||
argument-hint: <ObjectPath> [-Mode overview|brief|full] [-Name <элемент>]
|
argument-hint: <ObjectPath> [-Mode overview|brief|full] [-Name <элемент>]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /meta-info — Структура объекта метаданных 1С
|
# /meta-info — Структура объекта метаданных 1С
|
||||||
|
|
||||||
Читает XML объекта метаданных из выгрузки конфигурации 1С и выводит компактное описание структуры.
|
Читает XML объекта метаданных из выгрузки конфигурации 1С и выводит компактное описание структуры.
|
||||||
|
|
||||||
## Параметры и команда
|
## Параметры и команда
|
||||||
|
|
||||||
| Параметр | Описание |
|
| Параметр | Описание |
|
||||||
|----------|----------|
|
|----------|----------|
|
||||||
| `ObjectPath` | Путь к XML-файлу объекта или каталогу (авто-резолв `<name>/<name>.xml`) |
|
| `ObjectPath` | Путь к XML-файлу объекта или каталогу (авто-резолв `<name>/<name>.xml`) |
|
||||||
| `Mode` | Режим: `overview` (default), `brief`, `full` |
|
| `Mode` | Режим: `overview` (default), `brief`, `full` |
|
||||||
| `Name` | Drill-down по имени элемента (реквизит, ТЧ, значение перечисления, шаблон URL, операция) |
|
| `Name` | Drill-down по имени элемента (реквизит, ТЧ, значение перечисления, шаблон URL, операция) |
|
||||||
| `Limit` / `Offset` | Пагинация (по умолчанию 150 строк) |
|
| `Limit` / `Offset` | Пагинация (по умолчанию 150 строк) |
|
||||||
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
|
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-info.ps1" -ObjectPath "<путь>"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-info.ps1" -ObjectPath "<путь>"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Три режима
|
## Три режима
|
||||||
|
|
||||||
| Режим | Что показывает |
|
| Режим | Что показывает |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `overview` *(default)* | Заголовок + ключевые свойства + структура без раскрытия деталей |
|
| `overview` *(default)* | Заголовок + ключевые свойства + структура без раскрытия деталей |
|
||||||
| `brief` | Всё одной-двумя строками: имена полей, счётчики |
|
| `brief` | Всё одной-двумя строками: имена полей, счётчики |
|
||||||
| `full` | Всё раскрыто: колонки ТЧ, список источников подписки, движения, формы |
|
| `full` | Всё раскрыто: колонки ТЧ, список источников подписки, движения, формы |
|
||||||
|
|
||||||
`-Name` — drill-down: раскрыть конкретный элемент объекта (ТЧ, реквизит, шаблон URL, операцию веб-сервиса).
|
`-Name` — drill-down: раскрыть конкретный элемент объекта (ТЧ, реквизит, шаблон URL, операцию веб-сервиса).
|
||||||
|
|
||||||
## Поддерживаемые типы (23)
|
## Поддерживаемые типы (23)
|
||||||
|
|
||||||
**Ссылочные:** Справочник, Документ, Перечисление, Бизнес-процесс, Задача, План обмена, План счетов, ПВХ, ПВР
|
**Ссылочные:** Справочник, Документ, Перечисление, Бизнес-процесс, Задача, План обмена, План счетов, ПВХ, ПВР
|
||||||
**Регистры:** Регистр сведений, Регистр накопления, Регистр бухгалтерии, Регистр расчёта
|
**Регистры:** Регистр сведений, Регистр накопления, Регистр бухгалтерии, Регистр расчёта
|
||||||
**Сервисные:** Отчёт, Обработка, HTTP-сервис, Веб-сервис, Общий модуль, Регламентное задание, Подписка на событие
|
**Сервисные:** Отчёт, Обработка, HTTP-сервис, Веб-сервис, Общий модуль, Регламентное задание, Подписка на событие
|
||||||
**Прочие:** Константа, Журнал документов, Определяемый тип
|
**Прочие:** Константа, Журнал документов, Определяемый тип
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Справочник — overview
|
# Справочник — overview
|
||||||
... -ObjectPath Catalogs/Валюты/Валюты.xml
|
... -ObjectPath Catalogs/Валюты/Валюты.xml
|
||||||
|
|
||||||
# Документ — полная сводка с колонками ТЧ, движениями, формами
|
# Документ — полная сводка с колонками ТЧ, движениями, формами
|
||||||
... -ObjectPath Documents/АвансовыйОтчет/АвансовыйОтчет.xml -Mode full
|
... -ObjectPath Documents/АвансовыйОтчет/АвансовыйОтчет.xml -Mode full
|
||||||
|
|
||||||
# Регистр сведений — краткая сводка
|
# Регистр сведений — краткая сводка
|
||||||
... -ObjectPath InformationRegisters/КурсыВалют/КурсыВалют.xml -Mode brief
|
... -ObjectPath InformationRegisters/КурсыВалют/КурсыВалют.xml -Mode brief
|
||||||
|
|
||||||
# Drill-down в ТЧ документа
|
# Drill-down в ТЧ документа
|
||||||
... -ObjectPath Documents/АвансовыйОтчет/АвансовыйОтчет.xml -Name Товары
|
... -ObjectPath Documents/АвансовыйОтчет/АвансовыйОтчет.xml -Name Товары
|
||||||
|
|
||||||
# Drill-down в реквизит
|
# Drill-down в реквизит
|
||||||
... -ObjectPath Catalogs/Валюты/Валюты.xml -Name ОсновнаяВалюта
|
... -ObjectPath Catalogs/Валюты/Валюты.xml -Name ОсновнаяВалюта
|
||||||
|
|
||||||
# Общий модуль — флаги контекста и повторное использование
|
# Общий модуль — флаги контекста и повторное использование
|
||||||
... -ObjectPath CommonModules/ОбщегоНазначения/ОбщегоНазначения.xml
|
... -ObjectPath CommonModules/ОбщегоНазначения/ОбщегоНазначения.xml
|
||||||
|
|
||||||
# HTTP-сервис — шаблоны URL и методы
|
# HTTP-сервис — шаблоны URL и методы
|
||||||
... -ObjectPath HTTPServices/ExternalAPI/ExternalAPI.xml
|
... -ObjectPath HTTPServices/ExternalAPI/ExternalAPI.xml
|
||||||
|
|
||||||
# HTTP-сервис — drill-down в шаблон URL
|
# HTTP-сервис — drill-down в шаблон URL
|
||||||
... -ObjectPath HTTPServices/ExternalAPI/ExternalAPI.xml -Name АктуальныеЗадачи
|
... -ObjectPath HTTPServices/ExternalAPI/ExternalAPI.xml -Name АктуальныеЗадачи
|
||||||
|
|
||||||
# Веб-сервис — операции с параметрами
|
# Веб-сервис — операции с параметрами
|
||||||
... -ObjectPath WebServices/EnterpriseDataUpload_1_0_1_1/EnterpriseDataUpload_1_0_1_1.xml
|
... -ObjectPath WebServices/EnterpriseDataUpload_1_0_1_1/EnterpriseDataUpload_1_0_1_1.xml
|
||||||
|
|
||||||
# Веб-сервис — drill-down в операцию
|
# Веб-сервис — drill-down в операцию
|
||||||
... -ObjectPath WebServices/EnterpriseDataUpload_1_0_1_1/EnterpriseDataUpload_1_0_1_1.xml -Name TestConnection
|
... -ObjectPath WebServices/EnterpriseDataUpload_1_0_1_1/EnterpriseDataUpload_1_0_1_1.xml -Name TestConnection
|
||||||
|
|
||||||
# Подписка на событие — full раскрывает список источников
|
# Подписка на событие — full раскрывает список источников
|
||||||
... -ObjectPath EventSubscriptions/ПолныйРегистрацияУдаления/ПолныйРегистрацияУдаления.xml -Mode full
|
... -ObjectPath EventSubscriptions/ПолныйРегистрацияУдаления/ПолныйРегистрацияУдаления.xml -Mode full
|
||||||
|
|
||||||
# Регламентное задание
|
# Регламентное задание
|
||||||
... -ObjectPath ScheduledJobs/АвтоматическоеЗакрытиеМесяца/АвтоматическоеЗакрытиеМесяца.xml
|
... -ObjectPath ScheduledJobs/АвтоматическоеЗакрытиеМесяца/АвтоматическоеЗакрытиеМесяца.xml
|
||||||
|
|
||||||
# Определяемый тип
|
# Определяемый тип
|
||||||
... -ObjectPath DefinedTypes/GLN/GLN.xml
|
... -ObjectPath DefinedTypes/GLN/GLN.xml
|
||||||
```
|
```
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,60 +1,60 @@
|
|||||||
---
|
---
|
||||||
name: meta-remove
|
name: meta-remove
|
||||||
description: Удалить объект метаданных из конфигурации 1С. Используй когда нужно удалить, убрать объект из конфигурации
|
description: Удалить объект метаданных из конфигурации 1С. Используй когда нужно удалить, убрать объект из конфигурации
|
||||||
argument-hint: <ConfigDir> -Object <Type.Name>
|
argument-hint: <ConfigDir> -Object <Type.Name>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
- AskUserQuestion
|
- AskUserQuestion
|
||||||
---
|
---
|
||||||
|
|
||||||
# /meta-remove — удаление объекта метаданных
|
# /meta-remove — удаление объекта метаданных
|
||||||
|
|
||||||
Безопасно удаляет объект из XML-выгрузки конфигурации. Перед удалением проверяет ссылки на объект в реквизитах, коде и других метаданных. Если ссылки найдены — удаление блокируется.
|
Безопасно удаляет объект из XML-выгрузки конфигурации. Перед удалением проверяет ссылки на объект в реквизитах, коде и других метаданных. Если ссылки найдены — удаление блокируется.
|
||||||
|
|
||||||
## Использование
|
## Использование
|
||||||
|
|
||||||
```
|
```
|
||||||
/meta-remove <ConfigDir> -Object <Type.Name>
|
/meta-remove <ConfigDir> -Object <Type.Name>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|------------|:------------:|-------------------------------------------------|
|
|------------|:------------:|-------------------------------------------------|
|
||||||
| ConfigDir | да | Корневая директория выгрузки (где Configuration.xml) |
|
| ConfigDir | да | Корневая директория выгрузки (где Configuration.xml) |
|
||||||
| Object | да | Тип и имя объекта: `Catalog.Товары`, `Document.Заказ` и т.д. |
|
| Object | да | Тип и имя объекта: `Catalog.Товары`, `Document.Заказ` и т.д. |
|
||||||
| DryRun | нет | Только показать что будет удалено, без изменений |
|
| DryRun | нет | Только показать что будет удалено, без изменений |
|
||||||
| KeepFiles | нет | Не удалять файлы, только дерегистрировать |
|
| KeepFiles | нет | Не удалять файлы, только дерегистрировать |
|
||||||
| Force | нет | Удалить несмотря на найденные ссылки |
|
| Force | нет | Удалить несмотря на найденные ссылки |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-remove.ps1" -ConfigDir "<путь>" -Object "Catalog.Товары"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-remove.ps1" -ConfigDir "<путь>" -Object "Catalog.Товары"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Поддерживаемые типы
|
## Поддерживаемые типы
|
||||||
|
|
||||||
Catalog, Document, Enum, Constant, InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister, ChartOfAccounts, ChartOfCharacteristicTypes, ChartOfCalculationTypes, BusinessProcess, Task, ExchangePlan, DocumentJournal, Report, DataProcessor, CommonModule, ScheduledJob, EventSubscription, HTTPService, WebService, DefinedType, Role, Subsystem, CommonForm, CommonTemplate, CommonPicture, CommonAttribute, SessionParameter, FunctionalOption, FunctionalOptionsParameter, Sequence, FilterCriterion, SettingsStorage, XDTOPackage, WSReference, StyleItem, Language
|
Catalog, Document, Enum, Constant, InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister, ChartOfAccounts, ChartOfCharacteristicTypes, ChartOfCalculationTypes, BusinessProcess, Task, ExchangePlan, DocumentJournal, Report, DataProcessor, CommonModule, ScheduledJob, EventSubscription, HTTPService, WebService, DefinedType, Role, Subsystem, CommonForm, CommonTemplate, CommonPicture, CommonAttribute, SessionParameter, FunctionalOption, FunctionalOptionsParameter, Sequence, FilterCriterion, SettingsStorage, XDTOPackage, WSReference, StyleItem, Language
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Проверка ссылок + dry run
|
# Проверка ссылок + dry run
|
||||||
... -ConfigDir C:\WS\tasks\cfsrc\acc_8.3.24 -Object "Catalog.Устаревший" -DryRun
|
... -ConfigDir C:\WS\tasks\cfsrc\acc_8.3.24 -Object "Catalog.Устаревший" -DryRun
|
||||||
|
|
||||||
# Удалить объект без ссылок
|
# Удалить объект без ссылок
|
||||||
... -ConfigDir C:\WS\tasks\cfsrc\acc_8.3.24 -Object "Catalog.Устаревший"
|
... -ConfigDir C:\WS\tasks\cfsrc\acc_8.3.24 -Object "Catalog.Устаревший"
|
||||||
|
|
||||||
# Принудительно удалить несмотря на ссылки
|
# Принудительно удалить несмотря на ссылки
|
||||||
... -ConfigDir C:\WS\tasks\cfsrc\acc_8.3.24 -Object "Catalog.Устаревший" -Force
|
... -ConfigDir C:\WS\tasks\cfsrc\acc_8.3.24 -Object "Catalog.Устаревший" -Force
|
||||||
|
|
||||||
# Только дерегистрировать (файлы оставить)
|
# Только дерегистрировать (файлы оставить)
|
||||||
... -ConfigDir C:\WS\tasks\cfsrc\acc_8.3.24 -Object "Report.Старый" -KeepFiles
|
... -ConfigDir C:\WS\tasks\cfsrc\acc_8.3.24 -Object "Report.Старый" -KeepFiles
|
||||||
|
|
||||||
# Удалить общий модуль
|
# Удалить общий модуль
|
||||||
... -ConfigDir src -Object "CommonModule.МойМодуль"
|
... -ConfigDir src -Object "CommonModule.МойМодуль"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
---
|
---
|
||||||
name: meta-validate
|
name: meta-validate
|
||||||
description: Валидация объекта метаданных 1С. Используй после создания или модификации объекта конфигурации для проверки корректности
|
description: Валидация объекта метаданных 1С. Используй после создания или модификации объекта конфигурации для проверки корректности
|
||||||
argument-hint: <ObjectPath> [-Detailed] [-MaxErrors 30] — pipe-separated paths for batch
|
argument-hint: <ObjectPath> [-Detailed] [-MaxErrors 30] — pipe-separated paths for batch
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /meta-validate — валидация объекта метаданных 1С
|
# /meta-validate — валидация объекта метаданных 1С
|
||||||
|
|
||||||
Проверяет XML объекта метаданных из выгрузки конфигурации на структурные ошибки.
|
Проверяет XML объекта метаданных из выгрузки конфигурации на структурные ошибки.
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Обяз. | Умолч. | Описание |
|
| Параметр | Обяз. | Умолч. | Описание |
|
||||||
|------------|:-----:|---------|-------------------------------------------------|
|
|------------|:-----:|---------|-------------------------------------------------|
|
||||||
| ObjectPath | да | — | Путь к XML-файлу или каталогу. Через `\|` для batch |
|
| ObjectPath | да | — | Путь к XML-файлу или каталогу. Через `\|` для batch |
|
||||||
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
||||||
| MaxErrors | нет | 30 | Остановиться после N ошибок (per object) |
|
| MaxErrors | нет | 30 | Остановиться после N ошибок (per object) |
|
||||||
| OutFile | нет | — | Записать результат в файл (UTF-8 BOM) |
|
| OutFile | нет | — | Записать результат в файл (UTF-8 BOM) |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-validate.ps1" -ObjectPath "Catalogs/Номенклатура/Номенклатура.xml"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-validate.ps1" -ObjectPath "Catalogs/Номенклатура/Номенклатура.xml"
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-validate.ps1" -ObjectPath "Catalogs/Банки|Documents/Заказ"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-validate.ps1" -ObjectPath "Catalogs/Банки|Documents/Заказ"
|
||||||
```
|
```
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,65 +1,65 @@
|
|||||||
---
|
---
|
||||||
name: mxl-compile
|
name: mxl-compile
|
||||||
description: Компиляция табличного документа (MXL) из JSON-определения. Используй когда нужно создать макет печатной формы
|
description: Компиляция табличного документа (MXL) из JSON-определения. Используй когда нужно создать макет печатной формы
|
||||||
argument-hint: <JsonPath> <OutputPath>
|
argument-hint: <JsonPath> <OutputPath>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Write
|
- Write
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /mxl-compile — Компилятор макета из DSL
|
# /mxl-compile — Компилятор макета из DSL
|
||||||
|
|
||||||
Принимает компактное JSON-определение макета и генерирует корректный Template.xml для табличного документа 1С. Claude описывает *что* нужно (области, параметры, стили), скрипт обеспечивает *корректность* XML (палитры, индексы, объединения, namespace).
|
Принимает компактное JSON-определение макета и генерирует корректный Template.xml для табличного документа 1С. Claude описывает *что* нужно (области, параметры, стили), скрипт обеспечивает *корректность* XML (палитры, индексы, объединения, namespace).
|
||||||
|
|
||||||
## Использование
|
## Использование
|
||||||
|
|
||||||
```
|
```
|
||||||
/mxl-compile <JsonPath> <OutputPath>
|
/mxl-compile <JsonPath> <OutputPath>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|------------|:------------:|------------------------------------|
|
|------------|:------------:|------------------------------------|
|
||||||
| JsonPath | да | Путь к JSON-определению макета |
|
| JsonPath | да | Путь к JSON-определению макета |
|
||||||
| OutputPath | да | Путь для генерации Template.xml |
|
| OutputPath | да | Путь для генерации Template.xml |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-compile.ps1" -JsonPath "<путь>.json" -OutputPath "<путь>/Template.xml"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-compile.ps1" -JsonPath "<путь>.json" -OutputPath "<путь>/Template.xml"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Рабочий процесс
|
## Рабочий процесс
|
||||||
|
|
||||||
1. Claude пишет JSON-определение (Write tool) → файл `.json`
|
1. Claude пишет JSON-определение (Write tool) → файл `.json`
|
||||||
2. Claude вызывает `/mxl-compile` для генерации Template.xml
|
2. Claude вызывает `/mxl-compile` для генерации Template.xml
|
||||||
3. Claude вызывает `/mxl-validate` для проверки корректности
|
3. Claude вызывает `/mxl-validate` для проверки корректности
|
||||||
4. Claude вызывает `/mxl-info` для верификации структуры
|
4. Claude вызывает `/mxl-info` для верификации структуры
|
||||||
|
|
||||||
**Если макет создаётся по изображению** (скриншот, скан печатной формы) — сначала вызвать `/img-grid` для наложения сетки, по ней определить границы колонок и пропорции, затем использовать `"Nx"` ширины + `"page"` для автоматического расчёта размеров.
|
**Если макет создаётся по изображению** (скриншот, скан печатной формы) — сначала вызвать `/img-grid` для наложения сетки, по ней определить границы колонок и пропорции, затем использовать `"Nx"` ширины + `"page"` для автоматического расчёта размеров.
|
||||||
|
|
||||||
## JSON-схема DSL
|
## JSON-схема DSL
|
||||||
|
|
||||||
Полная спецификация формата: **`docs/mxl-dsl-spec.md`** (прочитать через Read tool перед написанием JSON).
|
Полная спецификация формата: **`docs/mxl-dsl-spec.md`** (прочитать через Read tool перед написанием JSON).
|
||||||
|
|
||||||
Краткая структура:
|
Краткая структура:
|
||||||
|
|
||||||
```
|
```
|
||||||
{ columns, page, defaultWidth, columnWidths,
|
{ columns, page, defaultWidth, columnWidths,
|
||||||
fonts: { name: { face, size, bold, italic, underline, strikeout } },
|
fonts: { name: { face, size, bold, italic, underline, strikeout } },
|
||||||
styles: { name: { font, align, valign, border, borderWidth, wrap, format } },
|
styles: { name: { font, align, valign, border, borderWidth, wrap, format } },
|
||||||
areas: [{ name, rows: [{ height, rowStyle, cells: [
|
areas: [{ name, rows: [{ height, rowStyle, cells: [
|
||||||
{ col, span, rowspan, style, param, detail, text, template }
|
{ col, span, rowspan, style, param, detail, text, template }
|
||||||
]}]}]
|
]}]}]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Ключевые правила:
|
Ключевые правила:
|
||||||
- `page` — формат страницы (`"A4-landscape"`, `"A4-portrait"` или число). Автоматически вычисляет `defaultWidth` из суммы пропорций `"Nx"`
|
- `page` — формат страницы (`"A4-landscape"`, `"A4-portrait"` или число). Автоматически вычисляет `defaultWidth` из суммы пропорций `"Nx"`
|
||||||
- `col` — 1-based позиция колонки
|
- `col` — 1-based позиция колонки
|
||||||
- `rowStyle` — автозаполнение пустот стилем (рамки по всей ширине)
|
- `rowStyle` — автозаполнение пустот стилем (рамки по всей ширине)
|
||||||
- Тип заполнения определяется автоматически: `param` → Parameter, `text` → Text, `template` → Template
|
- Тип заполнения определяется автоматически: `param` → Parameter, `text` → Text, `template` → Template
|
||||||
- `rowspan` — объединение строк вниз (rowStyle учитывает занятые ячейки)
|
- `rowspan` — объединение строк вниз (rowStyle учитывает занятые ячейки)
|
||||||
|
|||||||
@@ -1,57 +1,57 @@
|
|||||||
---
|
---
|
||||||
name: mxl-decompile
|
name: mxl-decompile
|
||||||
description: Декомпиляция табличного документа (MXL) в JSON-определение. Используй когда нужно получить редактируемое описание существующего макета
|
description: Декомпиляция табличного документа (MXL) в JSON-определение. Используй когда нужно получить редактируемое описание существующего макета
|
||||||
argument-hint: <TemplatePath> [OutputPath]
|
argument-hint: <TemplatePath> [OutputPath]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Write
|
- Write
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /mxl-decompile — Декомпилятор макета в DSL
|
# /mxl-decompile — Декомпилятор макета в DSL
|
||||||
|
|
||||||
Принимает Template.xml табличного документа 1С и генерирует компактное JSON-определение (DSL). Обратная операция к `/mxl-compile`.
|
Принимает Template.xml табличного документа 1С и генерирует компактное JSON-определение (DSL). Обратная операция к `/mxl-compile`.
|
||||||
|
|
||||||
## Использование
|
## Использование
|
||||||
|
|
||||||
```
|
```
|
||||||
/mxl-decompile <TemplatePath> [OutputPath]
|
/mxl-decompile <TemplatePath> [OutputPath]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|--------------|:------------:|-----------------------------------------|
|
|--------------|:------------:|-----------------------------------------|
|
||||||
| TemplatePath | да | Путь к Template.xml |
|
| TemplatePath | да | Путь к Template.xml |
|
||||||
| OutputPath | нет | Путь для JSON (если не указан — stdout) |
|
| OutputPath | нет | Путь для JSON (если не указан — stdout) |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-decompile.ps1" -TemplatePath "<путь>/Template.xml" [-OutputPath "<путь>.json"]
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-decompile.ps1" -TemplatePath "<путь>/Template.xml" [-OutputPath "<путь>.json"]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Рабочий процесс
|
## Рабочий процесс
|
||||||
|
|
||||||
Декомпиляция существующего макета для анализа или доработки:
|
Декомпиляция существующего макета для анализа или доработки:
|
||||||
|
|
||||||
1. Claude вызывает `/mxl-decompile` для получения JSON из Template.xml
|
1. Claude вызывает `/mxl-decompile` для получения JSON из Template.xml
|
||||||
2. Claude анализирует или модифицирует JSON (добавляет области, меняет стили)
|
2. Claude анализирует или модифицирует JSON (добавляет области, меняет стили)
|
||||||
3. Claude вызывает `/mxl-compile` для генерации нового Template.xml
|
3. Claude вызывает `/mxl-compile` для генерации нового Template.xml
|
||||||
4. Claude вызывает `/mxl-validate` для проверки
|
4. Claude вызывает `/mxl-validate` для проверки
|
||||||
|
|
||||||
## JSON-схема DSL
|
## JSON-схема DSL
|
||||||
|
|
||||||
Полная спецификация формата: **`docs/mxl-dsl-spec.md`** (прочитать через Read tool).
|
Полная спецификация формата: **`docs/mxl-dsl-spec.md`** (прочитать через Read tool).
|
||||||
|
|
||||||
## Генерация имён
|
## Генерация имён
|
||||||
|
|
||||||
Скрипт автоматически генерирует осмысленные имена:
|
Скрипт автоматически генерирует осмысленные имена:
|
||||||
|
|
||||||
- **Шрифты**: `default`, `bold`, `header`, `small`, `italic` — или описательные имена по свойствам
|
- **Шрифты**: `default`, `bold`, `header`, `small`, `italic` — или описательные имена по свойствам
|
||||||
- **Стили**: `bordered`, `bordered-center`, `bold-right`, `border-top` и т.д. — по комбинации свойств
|
- **Стили**: `bordered`, `bordered-center`, `bold-right`, `border-top` и т.д. — по комбинации свойств
|
||||||
|
|
||||||
## Детектирование `rowStyle`
|
## Детектирование `rowStyle`
|
||||||
|
|
||||||
Если в строке есть пустые ячейки (без параметров/текста) и все они имеют одинаковый формат — этот формат распознаётся как `rowStyle`, а пустые ячейки исключаются из вывода.
|
Если в строке есть пустые ячейки (без параметров/текста) и все они имеют одинаковый формат — этот формат распознаётся как `rowStyle`, а пустые ячейки исключаются из вывода.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+132
-132
@@ -1,132 +1,132 @@
|
|||||||
---
|
---
|
||||||
name: mxl-info
|
name: mxl-info
|
||||||
description: Анализ структуры макета табличного документа (MXL) — области, параметры, наборы колонок. Используй при разработке печати — получить области и заполняемые параметры макета
|
description: Анализ структуры макета табличного документа (MXL) — области, параметры, наборы колонок. Используй при разработке печати — получить области и заполняемые параметры макета
|
||||||
argument-hint: <TemplatePath> или <ProcessorName> <TemplateName>
|
argument-hint: <TemplatePath> или <ProcessorName> <TemplateName>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /mxl-info — Анализ структуры макета
|
# /mxl-info — Анализ структуры макета
|
||||||
|
|
||||||
Читает Template.xml табличного документа и выводит компактную сводку: именованные области, параметры, наборы колонок. Заменяет необходимость читать тысячи строк XML.
|
Читает Template.xml табличного документа и выводит компактную сводку: именованные области, параметры, наборы колонок. Заменяет необходимость читать тысячи строк XML.
|
||||||
|
|
||||||
## Использование
|
## Использование
|
||||||
|
|
||||||
```
|
```
|
||||||
/mxl-info <TemplatePath>
|
/mxl-info <TemplatePath>
|
||||||
/mxl-info <ProcessorName> <TemplateName>
|
/mxl-info <ProcessorName> <TemplateName>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Обязательный | По умолчанию | Описание |
|
| Параметр | Обязательный | По умолчанию | Описание |
|
||||||
|---------------|:------------:|--------------|------------------------------------------|
|
|---------------|:------------:|--------------|------------------------------------------|
|
||||||
| TemplatePath | нет | — | Прямой путь к Template.xml |
|
| TemplatePath | нет | — | Прямой путь к Template.xml |
|
||||||
| ProcessorName | нет | — | Имя обработки (альтернатива пути) |
|
| ProcessorName | нет | — | Имя обработки (альтернатива пути) |
|
||||||
| TemplateName | нет | — | Имя макета (альтернатива пути) |
|
| TemplateName | нет | — | Имя макета (альтернатива пути) |
|
||||||
| SrcDir | нет | `src` | Каталог исходников |
|
| SrcDir | нет | `src` | Каталог исходников |
|
||||||
| Format | нет | `text` | Формат вывода: `text` или `json` |
|
| Format | нет | `text` | Формат вывода: `text` или `json` |
|
||||||
| WithText | нет | false | Включить статический текст и шаблоны |
|
| WithText | нет | false | Включить статический текст и шаблоны |
|
||||||
| MaxParams | нет | 10 | Макс. параметров в списке на область |
|
| MaxParams | нет | 10 | Макс. параметров в списке на область |
|
||||||
| Limit | нет | 150 | Макс. строк вывода (защита от переполнения) |
|
| Limit | нет | 150 | Макс. строк вывода (защита от переполнения) |
|
||||||
| Offset | нет | 0 | Пропустить N строк (для пагинации) |
|
| Offset | нет | 0 | Пропустить N строк (для пагинации) |
|
||||||
|
|
||||||
Укажите либо `-TemplatePath`, либо оба `-ProcessorName` и `-TemplateName`.
|
Укажите либо `-TemplatePath`, либо оба `-ProcessorName` и `-TemplateName`.
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-info.ps1" -TemplatePath "<путь>"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-info.ps1" -TemplatePath "<путь>"
|
||||||
```
|
```
|
||||||
|
|
||||||
Или по имени обработки/макета:
|
Или по имени обработки/макета:
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-info.ps1" -ProcessorName "<Имя>" -TemplateName "<Макет>" [-SrcDir "<каталог>"]
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-info.ps1" -ProcessorName "<Имя>" -TemplateName "<Макет>" [-SrcDir "<каталог>"]
|
||||||
```
|
```
|
||||||
|
|
||||||
Дополнительные флаги:
|
Дополнительные флаги:
|
||||||
```powershell
|
```powershell
|
||||||
... -WithText # включить текстовое содержимое ячеек
|
... -WithText # включить текстовое содержимое ячеек
|
||||||
... -Format json # JSON-вывод для программной обработки
|
... -Format json # JSON-вывод для программной обработки
|
||||||
... -MaxParams 20 # показать больше параметров на область
|
... -MaxParams 20 # показать больше параметров на область
|
||||||
... -Offset 150 # пагинация: пропустить первые 150 строк
|
... -Offset 150 # пагинация: пропустить первые 150 строк
|
||||||
```
|
```
|
||||||
|
|
||||||
## Чтение вывода
|
## Чтение вывода
|
||||||
|
|
||||||
### Области — сортировка сверху вниз
|
### Области — сортировка сверху вниз
|
||||||
|
|
||||||
Области перечислены в порядке документа (по позиции строки), а не по алфавиту. Это соответствует порядку вывода областей в коде заполнения — сверху вниз.
|
Области перечислены в порядке документа (по позиции строки), а не по алфавиту. Это соответствует порядку вывода областей в коде заполнения — сверху вниз.
|
||||||
|
|
||||||
```
|
```
|
||||||
--- Named areas ---
|
--- Named areas ---
|
||||||
Заголовок Rows rows 1-4 (1 params)
|
Заголовок Rows rows 1-4 (1 params)
|
||||||
Поставщик Rows rows 5-6 (1 params)
|
Поставщик Rows rows 5-6 (1 params)
|
||||||
Строка Rows rows 14-14 (8 params)
|
Строка Rows rows 14-14 (8 params)
|
||||||
Итого Rows rows 16-17 (1 params)
|
Итого Rows rows 16-17 (1 params)
|
||||||
```
|
```
|
||||||
|
|
||||||
Типы областей:
|
Типы областей:
|
||||||
- **Rows** — горизонтальная область (диапазон строк). Получение: `Макет.ПолучитьОбласть("Имя")`
|
- **Rows** — горизонтальная область (диапазон строк). Получение: `Макет.ПолучитьОбласть("Имя")`
|
||||||
- **Columns** — вертикальная область (диапазон колонок). Получение: `Макет.ПолучитьОбласть("Имя")`
|
- **Columns** — вертикальная область (диапазон колонок). Получение: `Макет.ПолучитьОбласть("Имя")`
|
||||||
- **Rectangle** — фиксированная область (строки + колонки). Обычно использует отдельный набор колонок.
|
- **Rectangle** — фиксированная область (строки + колонки). Обычно использует отдельный набор колонок.
|
||||||
- **Drawing** — именованный рисунок/штрихкод.
|
- **Drawing** — именованный рисунок/штрихкод.
|
||||||
|
|
||||||
### Пересечения
|
### Пересечения
|
||||||
|
|
||||||
Когда есть области и Rows, и Columns (этикетки, ценники), скрипт выводит пары пересечений:
|
Когда есть области и Rows, и Columns (этикетки, ценники), скрипт выводит пары пересечений:
|
||||||
|
|
||||||
```
|
```
|
||||||
--- Intersections (use with GetArea) ---
|
--- Intersections (use with GetArea) ---
|
||||||
ВысотаЭтикетки|ШиринаЭтикетки
|
ВысотаЭтикетки|ШиринаЭтикетки
|
||||||
```
|
```
|
||||||
|
|
||||||
В BSL: `Макет.ПолучитьОбласть("ВысотаЭтикетки|ШиринаЭтикетки")`
|
В BSL: `Макет.ПолучитьОбласть("ВысотаЭтикетки|ШиринаЭтикетки")`
|
||||||
|
|
||||||
### Параметры и detailParameter
|
### Параметры и detailParameter
|
||||||
|
|
||||||
Параметры перечислены по областям. Если у параметра есть `detailParameter` (расшифровка), он показан ниже:
|
Параметры перечислены по областям. Если у параметра есть `detailParameter` (расшифровка), он показан ниже:
|
||||||
|
|
||||||
```
|
```
|
||||||
--- Parameters by area ---
|
--- Parameters by area ---
|
||||||
Поставщик: ПредставлениеПоставщика
|
Поставщик: ПредставлениеПоставщика
|
||||||
detail: ПредставлениеПоставщика->Поставщик
|
detail: ПредставлениеПоставщика->Поставщик
|
||||||
Строка: НомерСтроки, Товар, Количество, Цена, Сумма, ... (+3)
|
Строка: НомерСтроки, Товар, Количество, Цена, Сумма, ... (+3)
|
||||||
detail: Товар->Номенклатура
|
detail: Товар->Номенклатура
|
||||||
```
|
```
|
||||||
|
|
||||||
Это означает: параметр `Товар` отображает значение, а при клике открывает `Номенклатура` (объект расшифровки).
|
Это означает: параметр `Товар` отображает значение, а при клике открывает `Номенклатура` (объект расшифровки).
|
||||||
|
|
||||||
### Параметры из шаблонов (суффикс `[tpl]`)
|
### Параметры из шаблонов (суффикс `[tpl]`)
|
||||||
|
|
||||||
Некоторые параметры встроены в шаблонный текст: `"Инв № [ИнвентарныйНомер]"`. Они заполняются через fillType=Template, а не fillType=Parameter. Скрипт всегда извлекает их и помечает суффиксом `[tpl]`:
|
Некоторые параметры встроены в шаблонный текст: `"Инв № [ИнвентарныйНомер]"`. Они заполняются через fillType=Template, а не fillType=Parameter. Скрипт всегда извлекает их и помечает суффиксом `[tpl]`:
|
||||||
|
|
||||||
```
|
```
|
||||||
НумерацияЛистов: Номер [tpl], Дата [tpl], НомерЛиста [tpl]
|
НумерацияЛистов: Номер [tpl], Дата [tpl], НомерЛиста [tpl]
|
||||||
```
|
```
|
||||||
|
|
||||||
В BSL шаблонные параметры заполняются так же, как обычные:
|
В BSL шаблонные параметры заполняются так же, как обычные:
|
||||||
```bsl
|
```bsl
|
||||||
Область.Параметры.Номер = НомерДокумента;
|
Область.Параметры.Номер = НомерДокумента;
|
||||||
Область.Параметры.Дата = ДатаДокумента;
|
Область.Параметры.Дата = ДатаДокумента;
|
||||||
```
|
```
|
||||||
|
|
||||||
Числовые подстановки вроде `[5]`, `[6]` (ссылки на сноски в официальных формах) игнорируются.
|
Числовые подстановки вроде `[5]`, `[6]` (ссылки на сноски в официальных формах) игнорируются.
|
||||||
|
|
||||||
### Текстовое содержимое (`-WithText`)
|
### Текстовое содержимое (`-WithText`)
|
||||||
|
|
||||||
Показывает статический текст (надписи, заголовки) и шаблонные строки с подстановками `[Параметр]`:
|
Показывает статический текст (надписи, заголовки) и шаблонные строки с подстановками `[Параметр]`:
|
||||||
|
|
||||||
```
|
```
|
||||||
--- Text content ---
|
--- Text content ---
|
||||||
ШапкаТаблицы:
|
ШапкаТаблицы:
|
||||||
Text: "№", "Товар", "Ед. изм.", "Кол-во", "Цена", "Сумма"
|
Text: "№", "Товар", "Ед. изм.", "Кол-во", "Цена", "Сумма"
|
||||||
Строка:
|
Строка:
|
||||||
Templates: "Инв № [ИнвентарныйНомер]"
|
Templates: "Инв № [ИнвентарныйНомер]"
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Text** — статические надписи (fillType=Text). Полезно для понимания назначения колонок.
|
- **Text** — статические надписи (fillType=Text). Полезно для понимания назначения колонок.
|
||||||
- **Templates** — текст с подстановками `[ИмяПараметра]` (fillType=Template). Параметр внутри `[]` заполняется программно.
|
- **Templates** — текст с подстановками `[ИмяПараметра]` (fillType=Template). Параметр внутри `[]` заполняется программно.
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,29 +1,29 @@
|
|||||||
---
|
---
|
||||||
name: mxl-validate
|
name: mxl-validate
|
||||||
description: Валидация макета табличного документа (MXL). Используй после создания или модификации макета для проверки корректности
|
description: Валидация макета табличного документа (MXL). Используй после создания или модификации макета для проверки корректности
|
||||||
argument-hint: <TemplatePath> [-Detailed] [-MaxErrors 20]
|
argument-hint: <TemplatePath> [-Detailed] [-MaxErrors 20]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /mxl-validate — валидация макета табличного документа (MXL)
|
# /mxl-validate — валидация макета табличного документа (MXL)
|
||||||
|
|
||||||
Проверяет Template.xml на структурные ошибки: индексы, ссылки на палитры, диапазоны именованных областей и объединений.
|
Проверяет Template.xml на структурные ошибки: индексы, ссылки на палитры, диапазоны именованных областей и объединений.
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Обяз. | Умолч. | Описание |
|
| Параметр | Обяз. | Умолч. | Описание |
|
||||||
|---------------|:-----:|---------|--------------------------------------------|
|
|---------------|:-----:|---------|--------------------------------------------|
|
||||||
| TemplatePath | да | — | Путь к макету (директория или Template.xml) |
|
| TemplatePath | да | — | Путь к макету (директория или Template.xml) |
|
||||||
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
||||||
| MaxErrors | нет | 20 | Остановиться после N ошибок |
|
| MaxErrors | нет | 20 | Остановиться после N ошибок |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-validate.ps1" -TemplatePath "Catalogs/Номенклатура/Templates/Макет"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-validate.ps1" -TemplatePath "Catalogs/Номенклатура/Templates/Макет"
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-validate.ps1" -TemplatePath "src/МояОбработка/Templates/ПечатнаяФорма"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-validate.ps1" -TemplatePath "src/МояОбработка/Templates/ПечатнаяФорма"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,423 +1,423 @@
|
|||||||
# mxl-validate v1.1 — Validate 1C spreadsheet
|
# mxl-validate v1.1 — Validate 1C spreadsheet
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Alias('Path')]
|
[Alias('Path')]
|
||||||
[string]$TemplatePath,
|
[string]$TemplatePath,
|
||||||
[string]$ProcessorName,
|
[string]$ProcessorName,
|
||||||
[string]$TemplateName,
|
[string]$TemplateName,
|
||||||
[string]$SrcDir = "src",
|
[string]$SrcDir = "src",
|
||||||
[switch]$Detailed,
|
[switch]$Detailed,
|
||||||
[int]$MaxErrors = 20
|
[int]$MaxErrors = 20
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Resolve template path ---
|
# --- Resolve template path ---
|
||||||
|
|
||||||
if (-not $TemplatePath) {
|
if (-not $TemplatePath) {
|
||||||
if (-not $ProcessorName -or -not $TemplateName) {
|
if (-not $ProcessorName -or -not $TemplateName) {
|
||||||
Write-Error "Specify -TemplatePath or both -ProcessorName and -TemplateName"
|
Write-Error "Specify -TemplatePath or both -ProcessorName and -TemplateName"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
$TemplatePath = Join-Path (Join-Path (Join-Path (Join-Path (Join-Path $SrcDir $ProcessorName) "Templates") $TemplateName) "Ext") "Template.xml"
|
$TemplatePath = Join-Path (Join-Path (Join-Path (Join-Path (Join-Path $SrcDir $ProcessorName) "Templates") $TemplateName) "Ext") "Template.xml"
|
||||||
}
|
}
|
||||||
|
|
||||||
# A: Directory → Ext/Template.xml
|
# A: Directory → Ext/Template.xml
|
||||||
if (Test-Path $TemplatePath -PathType Container) {
|
if (Test-Path $TemplatePath -PathType Container) {
|
||||||
$TemplatePath = Join-Path (Join-Path $TemplatePath "Ext") "Template.xml"
|
$TemplatePath = Join-Path (Join-Path $TemplatePath "Ext") "Template.xml"
|
||||||
}
|
}
|
||||||
# B1: Missing Ext/ (e.g. Templates/Макет/Template.xml → Templates/Макет/Ext/Template.xml)
|
# B1: Missing Ext/ (e.g. Templates/Макет/Template.xml → Templates/Макет/Ext/Template.xml)
|
||||||
if (-not (Test-Path $TemplatePath)) {
|
if (-not (Test-Path $TemplatePath)) {
|
||||||
$fn = [System.IO.Path]::GetFileName($TemplatePath)
|
$fn = [System.IO.Path]::GetFileName($TemplatePath)
|
||||||
if ($fn -eq "Template.xml") {
|
if ($fn -eq "Template.xml") {
|
||||||
$c = Join-Path (Join-Path (Split-Path $TemplatePath) "Ext") $fn
|
$c = Join-Path (Join-Path (Split-Path $TemplatePath) "Ext") $fn
|
||||||
if (Test-Path $c) { $TemplatePath = $c }
|
if (Test-Path $c) { $TemplatePath = $c }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# B2: Descriptor (Templates/Макет.xml → Templates/Макет/Ext/Template.xml)
|
# B2: Descriptor (Templates/Макет.xml → Templates/Макет/Ext/Template.xml)
|
||||||
if (-not (Test-Path $TemplatePath) -and $TemplatePath.EndsWith(".xml")) {
|
if (-not (Test-Path $TemplatePath) -and $TemplatePath.EndsWith(".xml")) {
|
||||||
$stem = [System.IO.Path]::GetFileNameWithoutExtension($TemplatePath)
|
$stem = [System.IO.Path]::GetFileNameWithoutExtension($TemplatePath)
|
||||||
$dir = Split-Path $TemplatePath
|
$dir = Split-Path $TemplatePath
|
||||||
$c = Join-Path (Join-Path (Join-Path $dir $stem) "Ext") "Template.xml"
|
$c = Join-Path (Join-Path (Join-Path $dir $stem) "Ext") "Template.xml"
|
||||||
if (Test-Path $c) { $TemplatePath = $c }
|
if (Test-Path $c) { $TemplatePath = $c }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $TemplatePath)) {
|
if (-not (Test-Path $TemplatePath)) {
|
||||||
Write-Error "File not found: $TemplatePath"
|
Write-Error "File not found: $TemplatePath"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Load XML ---
|
# --- Load XML ---
|
||||||
|
|
||||||
$xmlDoc = New-Object System.Xml.XmlDocument
|
$xmlDoc = New-Object System.Xml.XmlDocument
|
||||||
$xmlDoc.PreserveWhitespace = $false
|
$xmlDoc.PreserveWhitespace = $false
|
||||||
$xmlDoc.Load((Resolve-Path $TemplatePath).Path)
|
$xmlDoc.Load((Resolve-Path $TemplatePath).Path)
|
||||||
|
|
||||||
$nsMgr = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
|
$nsMgr = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
|
||||||
$nsMgr.AddNamespace("d", "http://v8.1c.ru/8.2/data/spreadsheet")
|
$nsMgr.AddNamespace("d", "http://v8.1c.ru/8.2/data/spreadsheet")
|
||||||
$nsMgr.AddNamespace("v8", "http://v8.1c.ru/8.1/data/core")
|
$nsMgr.AddNamespace("v8", "http://v8.1c.ru/8.1/data/core")
|
||||||
$nsMgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance")
|
$nsMgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance")
|
||||||
|
|
||||||
$root = $xmlDoc.DocumentElement
|
$root = $xmlDoc.DocumentElement
|
||||||
|
|
||||||
# --- Counters ---
|
# --- Counters ---
|
||||||
|
|
||||||
$errors = 0
|
$errors = 0
|
||||||
$warnings = 0
|
$warnings = 0
|
||||||
$stopped = $false
|
$stopped = $false
|
||||||
$script:okCount = 0
|
$script:okCount = 0
|
||||||
|
|
||||||
function Report-OK {
|
function Report-OK {
|
||||||
param([string]$msg)
|
param([string]$msg)
|
||||||
$script:okCount++
|
$script:okCount++
|
||||||
if ($Detailed) { Write-Host "[OK] $msg" }
|
if ($Detailed) { Write-Host "[OK] $msg" }
|
||||||
}
|
}
|
||||||
|
|
||||||
function Report-Error {
|
function Report-Error {
|
||||||
param([string]$msg)
|
param([string]$msg)
|
||||||
$script:errors++
|
$script:errors++
|
||||||
Write-Host "[ERROR] $msg"
|
Write-Host "[ERROR] $msg"
|
||||||
if ($script:errors -ge $MaxErrors) {
|
if ($script:errors -ge $MaxErrors) {
|
||||||
$script:stopped = $true
|
$script:stopped = $true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Report-Warn {
|
function Report-Warn {
|
||||||
param([string]$msg)
|
param([string]$msg)
|
||||||
$script:warnings++
|
$script:warnings++
|
||||||
Write-Host "[WARN] $msg"
|
Write-Host "[WARN] $msg"
|
||||||
}
|
}
|
||||||
|
|
||||||
$templateName = [System.IO.Path]::GetFileName([System.IO.Path]::GetDirectoryName([System.IO.Path]::GetDirectoryName($TemplatePath)))
|
$templateName = [System.IO.Path]::GetFileName([System.IO.Path]::GetDirectoryName([System.IO.Path]::GetDirectoryName($TemplatePath)))
|
||||||
if ($Detailed) {
|
if ($Detailed) {
|
||||||
Write-Host "=== Validation: $templateName ==="
|
Write-Host "=== Validation: $templateName ==="
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Collect palettes ---
|
# --- Collect palettes ---
|
||||||
|
|
||||||
$lineNodes = $root.SelectNodes("d:line", $nsMgr)
|
$lineNodes = $root.SelectNodes("d:line", $nsMgr)
|
||||||
$lineCount = $lineNodes.Count
|
$lineCount = $lineNodes.Count
|
||||||
|
|
||||||
$fontNodes = @()
|
$fontNodes = @()
|
||||||
foreach ($node in $root.ChildNodes) {
|
foreach ($node in $root.ChildNodes) {
|
||||||
if ($node.LocalName -eq "font") { $fontNodes += $node }
|
if ($node.LocalName -eq "font") { $fontNodes += $node }
|
||||||
}
|
}
|
||||||
$fontCount = $fontNodes.Count
|
$fontCount = $fontNodes.Count
|
||||||
|
|
||||||
$formatNodes = @()
|
$formatNodes = @()
|
||||||
foreach ($node in $root.ChildNodes) {
|
foreach ($node in $root.ChildNodes) {
|
||||||
if ($node.LocalName -eq "format") { $formatNodes += $node }
|
if ($node.LocalName -eq "format") { $formatNodes += $node }
|
||||||
}
|
}
|
||||||
$formatCount = $formatNodes.Count
|
$formatCount = $formatNodes.Count
|
||||||
|
|
||||||
$pictureNodes = $root.SelectNodes("d:picture", $nsMgr)
|
$pictureNodes = $root.SelectNodes("d:picture", $nsMgr)
|
||||||
$pictureCount = $pictureNodes.Count
|
$pictureCount = $pictureNodes.Count
|
||||||
|
|
||||||
# --- Collect column sets ---
|
# --- Collect column sets ---
|
||||||
|
|
||||||
$columnSets = @{} # id -> size
|
$columnSets = @{} # id -> size
|
||||||
$defaultColCount = 0
|
$defaultColCount = 0
|
||||||
|
|
||||||
foreach ($cols in $root.SelectNodes("d:columns", $nsMgr)) {
|
foreach ($cols in $root.SelectNodes("d:columns", $nsMgr)) {
|
||||||
$sizeNode = $cols.SelectSingleNode("d:size", $nsMgr)
|
$sizeNode = $cols.SelectSingleNode("d:size", $nsMgr)
|
||||||
$idNode = $cols.SelectSingleNode("d:id", $nsMgr)
|
$idNode = $cols.SelectSingleNode("d:id", $nsMgr)
|
||||||
$size = if ($sizeNode) { [int]$sizeNode.InnerText } else { 0 }
|
$size = if ($sizeNode) { [int]$sizeNode.InnerText } else { 0 }
|
||||||
|
|
||||||
if ($idNode) {
|
if ($idNode) {
|
||||||
$columnSets[$idNode.InnerText] = $size
|
$columnSets[$idNode.InnerText] = $size
|
||||||
} else {
|
} else {
|
||||||
$defaultColCount = $size
|
$defaultColCount = $size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Check 1: height vs actual rows ---
|
# --- Check 1: height vs actual rows ---
|
||||||
|
|
||||||
$rowNodes = $root.SelectNodes("d:rowsItem", $nsMgr)
|
$rowNodes = $root.SelectNodes("d:rowsItem", $nsMgr)
|
||||||
$heightNode = $root.SelectSingleNode("d:height", $nsMgr)
|
$heightNode = $root.SelectSingleNode("d:height", $nsMgr)
|
||||||
$docHeight = if ($heightNode) { [int]$heightNode.InnerText } else { 0 }
|
$docHeight = if ($heightNode) { [int]$heightNode.InnerText } else { 0 }
|
||||||
|
|
||||||
# Find max row index (not all rows have rowsItem - implicit rows are skipped)
|
# Find max row index (not all rows have rowsItem - implicit rows are skipped)
|
||||||
$maxRowIndex = -1
|
$maxRowIndex = -1
|
||||||
foreach ($ri in $rowNodes) {
|
foreach ($ri in $rowNodes) {
|
||||||
$idxNode = $ri.SelectSingleNode("d:index", $nsMgr)
|
$idxNode = $ri.SelectSingleNode("d:index", $nsMgr)
|
||||||
if ($idxNode) {
|
if ($idxNode) {
|
||||||
$idx = [int]$idxNode.InnerText
|
$idx = [int]$idxNode.InnerText
|
||||||
if ($idx -gt $maxRowIndex) { $maxRowIndex = $idx }
|
if ($idx -gt $maxRowIndex) { $maxRowIndex = $idx }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$expectedMinHeight = $maxRowIndex + 1
|
$expectedMinHeight = $maxRowIndex + 1
|
||||||
if ($docHeight -ge $expectedMinHeight) {
|
if ($docHeight -ge $expectedMinHeight) {
|
||||||
Report-OK "height ($docHeight) >= max row index + 1 ($expectedMinHeight), rowsItem count=$($rowNodes.Count)"
|
Report-OK "height ($docHeight) >= max row index + 1 ($expectedMinHeight), rowsItem count=$($rowNodes.Count)"
|
||||||
} else {
|
} else {
|
||||||
Report-Error "height=$docHeight but max row index=$maxRowIndex (need at least $expectedMinHeight)"
|
Report-Error "height=$docHeight but max row index=$maxRowIndex (need at least $expectedMinHeight)"
|
||||||
}
|
}
|
||||||
# --- Check 2: vgRows <= height ---
|
# --- Check 2: vgRows <= height ---
|
||||||
|
|
||||||
$vgRowsNode = $root.SelectSingleNode("d:vgRows", $nsMgr)
|
$vgRowsNode = $root.SelectSingleNode("d:vgRows", $nsMgr)
|
||||||
if ($vgRowsNode) {
|
if ($vgRowsNode) {
|
||||||
$vgRows = [int]$vgRowsNode.InnerText
|
$vgRows = [int]$vgRowsNode.InnerText
|
||||||
if ($vgRows -le $docHeight) {
|
if ($vgRows -le $docHeight) {
|
||||||
Report-OK "vgRows ($vgRows) <= height ($docHeight)"
|
Report-OK "vgRows ($vgRows) <= height ($docHeight)"
|
||||||
} else {
|
} else {
|
||||||
Report-Warn "vgRows ($vgRows) > height ($docHeight)"
|
Report-Warn "vgRows ($vgRows) > height ($docHeight)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Build row data for checks ---
|
# --- Build row data for checks ---
|
||||||
|
|
||||||
$maxFormatRef = 0
|
$maxFormatRef = 0
|
||||||
$maxFontRef = 0
|
$maxFontRef = 0
|
||||||
$maxLineRef = 0
|
$maxLineRef = 0
|
||||||
|
|
||||||
# Check format palette references in formats (font, border indices)
|
# Check format palette references in formats (font, border indices)
|
||||||
foreach ($fmt in $formatNodes) {
|
foreach ($fmt in $formatNodes) {
|
||||||
$fontIdx = $fmt.SelectSingleNode("d:font", $nsMgr)
|
$fontIdx = $fmt.SelectSingleNode("d:font", $nsMgr)
|
||||||
if ($fontIdx) {
|
if ($fontIdx) {
|
||||||
$val = [int]$fontIdx.InnerText
|
$val = [int]$fontIdx.InnerText
|
||||||
if ($val -gt $maxFontRef) { $maxFontRef = $val }
|
if ($val -gt $maxFontRef) { $maxFontRef = $val }
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($border in @("d:leftBorder", "d:topBorder", "d:rightBorder", "d:bottomBorder", "d:drawingBorder")) {
|
foreach ($border in @("d:leftBorder", "d:topBorder", "d:rightBorder", "d:bottomBorder", "d:drawingBorder")) {
|
||||||
$borderNode = $fmt.SelectSingleNode($border, $nsMgr)
|
$borderNode = $fmt.SelectSingleNode($border, $nsMgr)
|
||||||
if ($borderNode) {
|
if ($borderNode) {
|
||||||
$val = [int]$borderNode.InnerText
|
$val = [int]$borderNode.InnerText
|
||||||
if ($val -gt $maxLineRef) { $maxLineRef = $val }
|
if ($val -gt $maxLineRef) { $maxLineRef = $val }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Check 10: font indices in formats ---
|
# --- Check 10: font indices in formats ---
|
||||||
|
|
||||||
if ($fontCount -gt 0) {
|
if ($fontCount -gt 0) {
|
||||||
if ($maxFontRef -lt $fontCount) {
|
if ($maxFontRef -lt $fontCount) {
|
||||||
Report-OK "Font refs: max=$maxFontRef, palette size=$fontCount"
|
Report-OK "Font refs: max=$maxFontRef, palette size=$fontCount"
|
||||||
} else {
|
} else {
|
||||||
Report-Error "Font index $maxFontRef exceeds palette size ($fontCount)"
|
Report-Error "Font index $maxFontRef exceeds palette size ($fontCount)"
|
||||||
}
|
}
|
||||||
} elseif ($maxFontRef -gt 0) {
|
} elseif ($maxFontRef -gt 0) {
|
||||||
Report-Error "Font index $maxFontRef referenced but no fonts defined"
|
Report-Error "Font index $maxFontRef referenced but no fonts defined"
|
||||||
} else {
|
} else {
|
||||||
Report-OK "No font references"
|
Report-OK "No font references"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Check 11: line/border indices in formats ---
|
# --- Check 11: line/border indices in formats ---
|
||||||
|
|
||||||
if ($lineCount -gt 0) {
|
if ($lineCount -gt 0) {
|
||||||
if ($maxLineRef -lt $lineCount) {
|
if ($maxLineRef -lt $lineCount) {
|
||||||
Report-OK "Line/border refs: max=$maxLineRef, palette size=$lineCount"
|
Report-OK "Line/border refs: max=$maxLineRef, palette size=$lineCount"
|
||||||
} else {
|
} else {
|
||||||
Report-Error "Line index $maxLineRef exceeds palette size ($lineCount)"
|
Report-Error "Line index $maxLineRef exceeds palette size ($lineCount)"
|
||||||
}
|
}
|
||||||
} elseif ($maxLineRef -gt 0) {
|
} elseif ($maxLineRef -gt 0) {
|
||||||
Report-Error "Line index $maxLineRef referenced but no lines defined"
|
Report-Error "Line index $maxLineRef referenced but no lines defined"
|
||||||
} else {
|
} else {
|
||||||
Report-OK "No line/border references"
|
Report-OK "No line/border references"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Check 3, 4, 5, 6: row/cell checks ---
|
# --- Check 3, 4, 5, 6: row/cell checks ---
|
||||||
|
|
||||||
$maxCellFormatRef = 0
|
$maxCellFormatRef = 0
|
||||||
$maxRowFormatRef = 0
|
$maxRowFormatRef = 0
|
||||||
$maxDefaultColIdx = 0
|
$maxDefaultColIdx = 0
|
||||||
$rowIndex = 0
|
$rowIndex = 0
|
||||||
|
|
||||||
foreach ($ri in $rowNodes) {
|
foreach ($ri in $rowNodes) {
|
||||||
if ($stopped) { break }
|
if ($stopped) { break }
|
||||||
|
|
||||||
$idxNode = $ri.SelectSingleNode("d:index", $nsMgr)
|
$idxNode = $ri.SelectSingleNode("d:index", $nsMgr)
|
||||||
$rowIndex = if ($idxNode) { [int]$idxNode.InnerText } else { $rowIndex }
|
$rowIndex = if ($idxNode) { [int]$idxNode.InnerText } else { $rowIndex }
|
||||||
|
|
||||||
$row = $ri.SelectSingleNode("d:row", $nsMgr)
|
$row = $ri.SelectSingleNode("d:row", $nsMgr)
|
||||||
if (-not $row) { continue }
|
if (-not $row) { continue }
|
||||||
|
|
||||||
# Row formatIndex
|
# Row formatIndex
|
||||||
$rowFmtNode = $row.SelectSingleNode("d:formatIndex", $nsMgr)
|
$rowFmtNode = $row.SelectSingleNode("d:formatIndex", $nsMgr)
|
||||||
if ($rowFmtNode) {
|
if ($rowFmtNode) {
|
||||||
$val = [int]$rowFmtNode.InnerText
|
$val = [int]$rowFmtNode.InnerText
|
||||||
if ($val -gt $maxRowFormatRef) { $maxRowFormatRef = $val }
|
if ($val -gt $maxRowFormatRef) { $maxRowFormatRef = $val }
|
||||||
if ($val -gt $formatCount) {
|
if ($val -gt $formatCount) {
|
||||||
Report-Error "Row ${rowIndex}: formatIndex=$val > format palette size ($formatCount)"
|
Report-Error "Row ${rowIndex}: formatIndex=$val > format palette size ($formatCount)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check columnsID
|
# Check columnsID
|
||||||
$rowColsId = $null
|
$rowColsId = $null
|
||||||
$colsIdNode = $row.SelectSingleNode("d:columnsID", $nsMgr)
|
$colsIdNode = $row.SelectSingleNode("d:columnsID", $nsMgr)
|
||||||
if ($colsIdNode) {
|
if ($colsIdNode) {
|
||||||
$rowColsId = $colsIdNode.InnerText
|
$rowColsId = $colsIdNode.InnerText
|
||||||
if (-not $columnSets.ContainsKey($rowColsId)) {
|
if (-not $columnSets.ContainsKey($rowColsId)) {
|
||||||
Report-Error "Row ${rowIndex}: columnsID '$($rowColsId.Substring(0,8))...' not found in column sets"
|
Report-Error "Row ${rowIndex}: columnsID '$($rowColsId.Substring(0,8))...' not found in column sets"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Determine column count for this row
|
# Determine column count for this row
|
||||||
$rowColCount = $defaultColCount
|
$rowColCount = $defaultColCount
|
||||||
if ($rowColsId -and $columnSets.ContainsKey($rowColsId)) {
|
if ($rowColsId -and $columnSets.ContainsKey($rowColsId)) {
|
||||||
$rowColCount = $columnSets[$rowColsId]
|
$rowColCount = $columnSets[$rowColsId]
|
||||||
}
|
}
|
||||||
|
|
||||||
# Cell checks
|
# Cell checks
|
||||||
foreach ($cGroup in $row.SelectNodes("d:c", $nsMgr)) {
|
foreach ($cGroup in $row.SelectNodes("d:c", $nsMgr)) {
|
||||||
$iNode = $cGroup.SelectSingleNode("d:i", $nsMgr)
|
$iNode = $cGroup.SelectSingleNode("d:i", $nsMgr)
|
||||||
if ($iNode) {
|
if ($iNode) {
|
||||||
$colIdx = [int]$iNode.InnerText
|
$colIdx = [int]$iNode.InnerText
|
||||||
# Track max index for default column set only
|
# Track max index for default column set only
|
||||||
if (-not $rowColsId -and $colIdx -gt $maxDefaultColIdx) {
|
if (-not $rowColsId -and $colIdx -gt $maxDefaultColIdx) {
|
||||||
$maxDefaultColIdx = $colIdx
|
$maxDefaultColIdx = $colIdx
|
||||||
}
|
}
|
||||||
# Check against row's column count
|
# Check against row's column count
|
||||||
if ($rowColCount -gt 0 -and $colIdx -ge $rowColCount) {
|
if ($rowColCount -gt 0 -and $colIdx -ge $rowColCount) {
|
||||||
Report-Error "Row ${rowIndex}: column index $colIdx >= column count ($rowColCount)"
|
Report-Error "Row ${rowIndex}: column index $colIdx >= column count ($rowColCount)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$cell = $cGroup.SelectSingleNode("d:c", $nsMgr)
|
$cell = $cGroup.SelectSingleNode("d:c", $nsMgr)
|
||||||
if ($cell) {
|
if ($cell) {
|
||||||
$fNode = $cell.SelectSingleNode("d:f", $nsMgr)
|
$fNode = $cell.SelectSingleNode("d:f", $nsMgr)
|
||||||
if ($fNode) {
|
if ($fNode) {
|
||||||
$val = [int]$fNode.InnerText
|
$val = [int]$fNode.InnerText
|
||||||
if ($val -gt $maxCellFormatRef) { $maxCellFormatRef = $val }
|
if ($val -gt $maxCellFormatRef) { $maxCellFormatRef = $val }
|
||||||
if ($val -gt $formatCount) {
|
if ($val -gt $formatCount) {
|
||||||
Report-Error "Row ${rowIndex}: cell format index $val > format palette size ($formatCount)"
|
Report-Error "Row ${rowIndex}: cell format index $val > format palette size ($formatCount)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$rowIndex++
|
$rowIndex++
|
||||||
}
|
}
|
||||||
|
|
||||||
# Summary checks for format refs
|
# Summary checks for format refs
|
||||||
if (-not $stopped) {
|
if (-not $stopped) {
|
||||||
if ($maxCellFormatRef -le $formatCount -and $maxRowFormatRef -le $formatCount) {
|
if ($maxCellFormatRef -le $formatCount -and $maxRowFormatRef -le $formatCount) {
|
||||||
Report-OK "Format refs: max cell=$maxCellFormatRef, max row=$maxRowFormatRef, palette size=$formatCount"
|
Report-OK "Format refs: max cell=$maxCellFormatRef, max row=$maxRowFormatRef, palette size=$formatCount"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check column format indices
|
# Check column format indices
|
||||||
foreach ($cols in $root.SelectNodes("d:columns", $nsMgr)) {
|
foreach ($cols in $root.SelectNodes("d:columns", $nsMgr)) {
|
||||||
if ($stopped) { break }
|
if ($stopped) { break }
|
||||||
foreach ($ci in $cols.SelectNodes("d:columnsItem", $nsMgr)) {
|
foreach ($ci in $cols.SelectNodes("d:columnsItem", $nsMgr)) {
|
||||||
$col = $ci.SelectSingleNode("d:column", $nsMgr)
|
$col = $ci.SelectSingleNode("d:column", $nsMgr)
|
||||||
if ($col) {
|
if ($col) {
|
||||||
$fmtNode = $col.SelectSingleNode("d:formatIndex", $nsMgr)
|
$fmtNode = $col.SelectSingleNode("d:formatIndex", $nsMgr)
|
||||||
if ($fmtNode) {
|
if ($fmtNode) {
|
||||||
$val = [int]$fmtNode.InnerText
|
$val = [int]$fmtNode.InnerText
|
||||||
if ($val -gt $formatCount) {
|
if ($val -gt $formatCount) {
|
||||||
$colIdx = $ci.SelectSingleNode("d:index", $nsMgr).InnerText
|
$colIdx = $ci.SelectSingleNode("d:index", $nsMgr).InnerText
|
||||||
Report-Error "Column ${colIdx}: formatIndex=$val > format palette size ($formatCount)"
|
Report-Error "Column ${colIdx}: formatIndex=$val > format palette size ($formatCount)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Check 5: column index summary ---
|
# --- Check 5: column index summary ---
|
||||||
|
|
||||||
if (-not $stopped) {
|
if (-not $stopped) {
|
||||||
Report-OK "Column indices: max in default set=$maxDefaultColIdx, default column count=$defaultColCount"
|
Report-OK "Column indices: max in default set=$maxDefaultColIdx, default column count=$defaultColCount"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Check 7, 8: named areas ---
|
# --- Check 7, 8: named areas ---
|
||||||
|
|
||||||
foreach ($ni in $root.SelectNodes("d:namedItem", $nsMgr)) {
|
foreach ($ni in $root.SelectNodes("d:namedItem", $nsMgr)) {
|
||||||
if ($stopped) { break }
|
if ($stopped) { break }
|
||||||
|
|
||||||
$niType = $ni.GetAttribute("type", "http://www.w3.org/2001/XMLSchema-instance")
|
$niType = $ni.GetAttribute("type", "http://www.w3.org/2001/XMLSchema-instance")
|
||||||
$name = $ni.SelectSingleNode("d:name", $nsMgr).InnerText
|
$name = $ni.SelectSingleNode("d:name", $nsMgr).InnerText
|
||||||
|
|
||||||
if ($niType -like "*NamedItemCells*") {
|
if ($niType -like "*NamedItemCells*") {
|
||||||
$area = $ni.SelectSingleNode("d:area", $nsMgr)
|
$area = $ni.SelectSingleNode("d:area", $nsMgr)
|
||||||
$beginRow = [int]$area.SelectSingleNode("d:beginRow", $nsMgr).InnerText
|
$beginRow = [int]$area.SelectSingleNode("d:beginRow", $nsMgr).InnerText
|
||||||
$endRow = [int]$area.SelectSingleNode("d:endRow", $nsMgr).InnerText
|
$endRow = [int]$area.SelectSingleNode("d:endRow", $nsMgr).InnerText
|
||||||
|
|
||||||
# Check row bounds (skip -1 which means "all")
|
# Check row bounds (skip -1 which means "all")
|
||||||
if ($beginRow -ne -1 -and $beginRow -ge $docHeight) {
|
if ($beginRow -ne -1 -and $beginRow -ge $docHeight) {
|
||||||
Report-Error "Area '$name': beginRow=$beginRow >= height=$docHeight"
|
Report-Error "Area '$name': beginRow=$beginRow >= height=$docHeight"
|
||||||
}
|
}
|
||||||
if ($endRow -ne -1 -and $endRow -ge $docHeight) {
|
if ($endRow -ne -1 -and $endRow -ge $docHeight) {
|
||||||
Report-Error "Area '$name': endRow=$endRow >= height=$docHeight"
|
Report-Error "Area '$name': endRow=$endRow >= height=$docHeight"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check columnsID reference
|
# Check columnsID reference
|
||||||
$colsIdNode = $area.SelectSingleNode("d:columnsID", $nsMgr)
|
$colsIdNode = $area.SelectSingleNode("d:columnsID", $nsMgr)
|
||||||
if ($colsIdNode) {
|
if ($colsIdNode) {
|
||||||
$colsId = $colsIdNode.InnerText
|
$colsId = $colsIdNode.InnerText
|
||||||
if (-not $columnSets.ContainsKey($colsId)) {
|
if (-not $columnSets.ContainsKey($colsId)) {
|
||||||
Report-Error "Area '$name': columnsID '$($colsId.Substring(0,8))...' not found"
|
Report-Error "Area '$name': columnsID '$($colsId.Substring(0,8))...' not found"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Check 9: merge bounds ---
|
# --- Check 9: merge bounds ---
|
||||||
|
|
||||||
foreach ($merge in $root.SelectNodes("d:merge", $nsMgr)) {
|
foreach ($merge in $root.SelectNodes("d:merge", $nsMgr)) {
|
||||||
if ($stopped) { break }
|
if ($stopped) { break }
|
||||||
|
|
||||||
$r = [int]$merge.SelectSingleNode("d:r", $nsMgr).InnerText
|
$r = [int]$merge.SelectSingleNode("d:r", $nsMgr).InnerText
|
||||||
$c = [int]$merge.SelectSingleNode("d:c", $nsMgr).InnerText
|
$c = [int]$merge.SelectSingleNode("d:c", $nsMgr).InnerText
|
||||||
$wNode = $merge.SelectSingleNode("d:w", $nsMgr)
|
$wNode = $merge.SelectSingleNode("d:w", $nsMgr)
|
||||||
$hNode = $merge.SelectSingleNode("d:h", $nsMgr)
|
$hNode = $merge.SelectSingleNode("d:h", $nsMgr)
|
||||||
|
|
||||||
# r=-1 means all rows, skip bound check
|
# r=-1 means all rows, skip bound check
|
||||||
if ($r -ne -1 -and $r -ge $docHeight) {
|
if ($r -ne -1 -and $r -ge $docHeight) {
|
||||||
Report-Error "Merge at row=${r}, col=${c}: row >= height ($docHeight)"
|
Report-Error "Merge at row=${r}, col=${c}: row >= height ($docHeight)"
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($hNode -and $r -ne -1) {
|
if ($hNode -and $r -ne -1) {
|
||||||
$h = [int]$hNode.InnerText
|
$h = [int]$hNode.InnerText
|
||||||
if (($r + $h) -ge $docHeight) {
|
if (($r + $h) -ge $docHeight) {
|
||||||
Report-Error "Merge at row=${r}: extends to row $($r + $h) >= height ($docHeight)"
|
Report-Error "Merge at row=${r}: extends to row $($r + $h) >= height ($docHeight)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check columnsID in merge
|
# Check columnsID in merge
|
||||||
$colsIdNode = $merge.SelectSingleNode("d:columnsID", $nsMgr)
|
$colsIdNode = $merge.SelectSingleNode("d:columnsID", $nsMgr)
|
||||||
if ($colsIdNode) {
|
if ($colsIdNode) {
|
||||||
$colsId = $colsIdNode.InnerText
|
$colsId = $colsIdNode.InnerText
|
||||||
if (-not $columnSets.ContainsKey($colsId)) {
|
if (-not $columnSets.ContainsKey($colsId)) {
|
||||||
Report-Error "Merge at row=${r}, col=${c}: columnsID '$($colsId.Substring(0,8))...' not found"
|
Report-Error "Merge at row=${r}, col=${c}: columnsID '$($colsId.Substring(0,8))...' not found"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Check 12: drawing picture indices ---
|
# --- Check 12: drawing picture indices ---
|
||||||
|
|
||||||
foreach ($drawing in $root.SelectNodes("d:drawing", $nsMgr)) {
|
foreach ($drawing in $root.SelectNodes("d:drawing", $nsMgr)) {
|
||||||
if ($stopped) { break }
|
if ($stopped) { break }
|
||||||
|
|
||||||
$picIdxNode = $drawing.SelectSingleNode("d:pictureIndex", $nsMgr)
|
$picIdxNode = $drawing.SelectSingleNode("d:pictureIndex", $nsMgr)
|
||||||
if ($picIdxNode) {
|
if ($picIdxNode) {
|
||||||
$picIdx = [int]$picIdxNode.InnerText
|
$picIdx = [int]$picIdxNode.InnerText
|
||||||
if ($picIdx -gt $pictureCount) {
|
if ($picIdx -gt $pictureCount) {
|
||||||
$drawId = $drawing.SelectSingleNode("d:id", $nsMgr).InnerText
|
$drawId = $drawing.SelectSingleNode("d:id", $nsMgr).InnerText
|
||||||
Report-Error "Drawing id=${drawId}: pictureIndex=$picIdx > picture count ($pictureCount)"
|
Report-Error "Drawing id=${drawId}: pictureIndex=$picIdx > picture count ($pictureCount)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Summary ---
|
# --- Summary ---
|
||||||
|
|
||||||
$checks = $script:okCount + $errors + $warnings
|
$checks = $script:okCount + $errors + $warnings
|
||||||
|
|
||||||
if ($errors -eq 0 -and $warnings -eq 0 -and -not $Detailed) {
|
if ($errors -eq 0 -and $warnings -eq 0 -and -not $Detailed) {
|
||||||
Write-Host "=== Validation OK: Template.$templateName ($checks checks) ==="
|
Write-Host "=== Validation OK: Template.$templateName ($checks checks) ==="
|
||||||
} else {
|
} else {
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
|
|
||||||
if ($stopped) {
|
if ($stopped) {
|
||||||
Write-Host "Stopped after $MaxErrors errors. Fix and re-run."
|
Write-Host "Stopped after $MaxErrors errors. Fix and re-run."
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "=== Result: $errors errors, $warnings warnings ($checks checks) ==="
|
Write-Host "=== Result: $errors errors, $warnings warnings ($checks checks) ==="
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($errors -gt 0) {
|
if ($errors -gt 0) {
|
||||||
exit 1
|
exit 1
|
||||||
} else {
|
} else {
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,109 +1,109 @@
|
|||||||
---
|
---
|
||||||
name: role-compile
|
name: role-compile
|
||||||
description: Создание роли 1С из описания прав. Используй когда нужно создать новую роль с набором прав на объекты
|
description: Создание роли 1С из описания прав. Используй когда нужно создать новую роль с набором прав на объекты
|
||||||
argument-hint: <JsonPath> <OutputDir>
|
argument-hint: <JsonPath> <OutputDir>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Write
|
- Write
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /role-compile — генерация роли 1С из JSON DSL
|
# /role-compile — генерация роли 1С из JSON DSL
|
||||||
|
|
||||||
Принимает JSON-определение роли → генерирует `Roles/Имя.xml` (метаданные) и `Roles/Имя/Ext/Rights.xml` (права). UUID автоматически.
|
Принимает JSON-определение роли → генерирует `Roles/Имя.xml` (метаданные) и `Roles/Имя/Ext/Rights.xml` (права). UUID автоматически.
|
||||||
|
|
||||||
## Параметры и команда
|
## Параметры и команда
|
||||||
|
|
||||||
| Параметр | Описание |
|
| Параметр | Описание |
|
||||||
|----------|----------|
|
|----------|----------|
|
||||||
| `JsonPath` | Путь к JSON-определению роли |
|
| `JsonPath` | Путь к JSON-определению роли |
|
||||||
| `OutputDir` | Корень выгрузки конфигурации (где `Configuration.xml`, `Roles/` и т.д.) |
|
| `OutputDir` | Корень выгрузки конфигурации (где `Configuration.xml`, `Roles/` и т.д.) |
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-compile.ps1" -JsonPath "<json>" -OutputDir "<ConfigDir>"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-compile.ps1" -JsonPath "<json>" -OutputDir "<ConfigDir>"
|
||||||
```
|
```
|
||||||
|
|
||||||
Создаёт `{OutputDir}/Roles/Имя.xml` и `{OutputDir}/Roles/Имя/Ext/Rights.xml`. Регистрирует `<Role>` в `Configuration.xml`.
|
Создаёт `{OutputDir}/Roles/Имя.xml` и `{OutputDir}/Roles/Имя/Ext/Rights.xml`. Регистрирует `<Role>` в `Configuration.xml`.
|
||||||
|
|
||||||
## JSON DSL
|
## JSON DSL
|
||||||
|
|
||||||
### Структура
|
### Структура
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "name": "ИмяРоли", "synonym": "Отображаемое имя", "objects": [...], "templates": [...] }
|
{ "name": "ИмяРоли", "synonym": "Отображаемое имя", "objects": [...], "templates": [...] }
|
||||||
```
|
```
|
||||||
|
|
||||||
Необязательные: `comment` (""), `setForNewObjects` (false), `setForAttributesByDefault` (true), `independentRightsOfChildObjects` (false).
|
Необязательные: `comment` (""), `setForNewObjects` (false), `setForAttributesByDefault` (true), `independentRightsOfChildObjects` (false).
|
||||||
|
|
||||||
### Shorthand-строки и объектная форма
|
### Shorthand-строки и объектная форма
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"objects": [
|
"objects": [
|
||||||
"Catalog.Номенклатура: @view",
|
"Catalog.Номенклатура: @view",
|
||||||
"Document.Реализация: @edit",
|
"Document.Реализация: @edit",
|
||||||
"DataProcessor.Загрузка: @view",
|
"DataProcessor.Загрузка: @view",
|
||||||
"InformationRegister.Цены: Read, Update",
|
"InformationRegister.Цены: Read, Update",
|
||||||
{ "name": "Document.Продажа", "preset": "view", "rights": {"Delete": false}, "rls": {"Read": "#Шаблон(\"\")"} }
|
{ "name": "Document.Продажа", "preset": "view", "rights": {"Delete": false}, "rls": {"Read": "#Шаблон(\"\")"} }
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
- Shorthand: `"Тип.Имя: @пресет"` или `"Тип.Имя: Право1, Право2"`
|
- Shorthand: `"Тип.Имя: @пресет"` или `"Тип.Имя: Право1, Право2"`
|
||||||
- Объектная форма: `preset` + `rights` (переопределения) + `rls` (ограничения)
|
- Объектная форма: `preset` + `rights` (переопределения) + `rls` (ограничения)
|
||||||
|
|
||||||
### Пресеты
|
### Пресеты
|
||||||
|
|
||||||
| Пресет | Действие |
|
| Пресет | Действие |
|
||||||
|--------|----------|
|
|--------|----------|
|
||||||
| `@view` | Просмотр — Read, View (+InputByString для справочников/документов; Use+View для обработок/отчётов) |
|
| `@view` | Просмотр — Read, View (+InputByString для справочников/документов; Use+View для обработок/отчётов) |
|
||||||
| `@edit` | Полное редактирование — CRUD + Interactive* + Posting (документы) |
|
| `@edit` | Полное редактирование — CRUD + Interactive* + Posting (документы) |
|
||||||
|
|
||||||
`@` обязателен в shorthand. В объектной форме — `"preset": "view"` без `@`.
|
`@` обязателен в shorthand. В объектной форме — `"preset": "view"` без `@`.
|
||||||
|
|
||||||
Для сервисов (WebService, HTTPService, IntegrationService) пресеты не определены — используй явные права: `"WebService.Имя: Use"`.
|
Для сервисов (WebService, HTTPService, IntegrationService) пресеты не определены — используй явные права: `"WebService.Имя: Use"`.
|
||||||
|
|
||||||
### Русские синонимы
|
### Русские синонимы
|
||||||
|
|
||||||
Поддерживаются русские типы (`Справочник`→Catalog, `Документ`→Document) и права (`Чтение`→Read, `Просмотр`→View). Смешивание допустимо: `"Справочник.Контрагенты: Чтение, View"`.
|
Поддерживаются русские типы (`Справочник`→Catalog, `Документ`→Document) и права (`Чтение`→Read, `Просмотр`→View). Смешивание допустимо: `"Справочник.Контрагенты: Чтение, View"`.
|
||||||
|
|
||||||
### Шаблоны RLS
|
### Шаблоны RLS
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"templates": [{"name": "ДляОбъекта(Мод)", "condition": "ГДЕ Организация = &ТекОрг"}]
|
"templates": [{"name": "ДляОбъекта(Мод)", "condition": "ГДЕ Организация = &ТекОрг"}]
|
||||||
```
|
```
|
||||||
|
|
||||||
Ссылка в `rls`: `"#ДляОбъекта(\"\")"`. Символ `&` автоматически экранируется в XML.
|
Ссылка в `rls`: `"#ДляОбъекта(\"\")"`. Символ `&` автоматически экранируется в XML.
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
### Простая роль
|
### Простая роль
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "ЧтениеНоменклатуры", "synonym": "Чтение номенклатуры",
|
"name": "ЧтениеНоменклатуры", "synonym": "Чтение номенклатуры",
|
||||||
"objects": ["Catalog.Номенклатура: @view", "Catalog.Контрагенты: @view", "DataProcessor.Загрузка: @view"]
|
"objects": ["Catalog.Номенклатура: @view", "Catalog.Контрагенты: @view", "DataProcessor.Загрузка: @view"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Роль с RLS
|
### Роль с RLS
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "ЧтениеДокументовПоОрганизации",
|
"name": "ЧтениеДокументовПоОрганизации",
|
||||||
"synonym": "Чтение документов (ограничение по организации)",
|
"synonym": "Чтение документов (ограничение по организации)",
|
||||||
"objects": [
|
"objects": [
|
||||||
"Catalog.Организации: @view",
|
"Catalog.Организации: @view",
|
||||||
{"name": "Document.РеализацияТоваровУслуг", "preset": "view", "rls": {"Read": "#ДляОбъекта(\"\")"}}
|
{"name": "Document.РеализацияТоваровУслуг", "preset": "view", "rls": {"Read": "#ДляОбъекта(\"\")"}}
|
||||||
],
|
],
|
||||||
"templates": [{"name": "ДляОбъекта(Модификатор)", "condition": "ГДЕ Организация = &ТекущаяОрганизация"}]
|
"templates": [{"name": "ДляОбъекта(Модификатор)", "condition": "ГДЕ Организация = &ТекущаяОрганизация"}]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Подробные таблицы пресетов, русских синонимов и дополнительные примеры — в `dsl-reference.md`.
|
Подробные таблицы пресетов, русских синонимов и дополнительные примеры — в `dsl-reference.md`.
|
||||||
|
|
||||||
## Верификация
|
## Верификация
|
||||||
|
|
||||||
```
|
```
|
||||||
/role-validate <RightsPath> [MetadataPath] — проверка корректности XML, прав, RLS
|
/role-validate <RightsPath> [MetadataPath] — проверка корректности XML, прав, RLS
|
||||||
/role-info <RightsPath> — визуальная сводка структуры
|
/role-info <RightsPath> — визуальная сводка структуры
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,313 +1,313 @@
|
|||||||
# Role DSL — полная справка
|
# Role DSL — полная справка
|
||||||
|
|
||||||
Подробная справка по JSON DSL для `/role-compile`. Компактное описание — в [SKILL.md](SKILL.md).
|
Подробная справка по JSON DSL для `/role-compile`. Компактное описание — в [SKILL.md](SKILL.md).
|
||||||
|
|
||||||
## Структура верхнего уровня
|
## Структура верхнего уровня
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "ИмяРоли",
|
"name": "ИмяРоли",
|
||||||
"synonym": "Отображаемое имя роли",
|
"synonym": "Отображаемое имя роли",
|
||||||
"comment": "",
|
"comment": "",
|
||||||
"setForNewObjects": false,
|
"setForNewObjects": false,
|
||||||
"setForAttributesByDefault": true,
|
"setForAttributesByDefault": true,
|
||||||
"independentRightsOfChildObjects": false,
|
"independentRightsOfChildObjects": false,
|
||||||
"objects": [ ... ],
|
"objects": [ ... ],
|
||||||
"templates": [ ... ]
|
"templates": [ ... ]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- `name` — программное имя роли (обязательно)
|
- `name` — программное имя роли (обязательно)
|
||||||
- `synonym` — отображаемое имя (по умолчанию = name)
|
- `synonym` — отображаемое имя (по умолчанию = name)
|
||||||
- `comment` — комментарий (по умолчанию пусто)
|
- `comment` — комментарий (по умолчанию пусто)
|
||||||
- Глобальные флаги — по умолчанию `false`, `true`, `false`
|
- Глобальные флаги — по умолчанию `false`, `true`, `false`
|
||||||
|
|
||||||
## Объекты: два формата
|
## Объекты: два формата
|
||||||
|
|
||||||
Массив `objects` принимает строки (shorthand) и объекты (полная форма).
|
Массив `objects` принимает строки (shorthand) и объекты (полная форма).
|
||||||
|
|
||||||
### Строковый shorthand
|
### Строковый shorthand
|
||||||
|
|
||||||
```
|
```
|
||||||
"ОбъектМетаданных: @пресет"
|
"ОбъектМетаданных: @пресет"
|
||||||
"ОбъектМетаданных: Право1, Право2"
|
"ОбъектМетаданных: Право1, Право2"
|
||||||
```
|
```
|
||||||
|
|
||||||
Примеры:
|
Примеры:
|
||||||
```json
|
```json
|
||||||
"objects": [
|
"objects": [
|
||||||
"Catalog.Номенклатура: @view",
|
"Catalog.Номенклатура: @view",
|
||||||
"Document.Реализация: @edit",
|
"Document.Реализация: @edit",
|
||||||
"InformationRegister.Цены: Read, Update",
|
"InformationRegister.Цены: Read, Update",
|
||||||
"DataProcessor.Загрузка: @view"
|
"DataProcessor.Загрузка: @view"
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Объектная форма (для RLS и переопределений)
|
### Объектная форма (для RLS и переопределений)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "Document.Реализация",
|
"name": "Document.Реализация",
|
||||||
"preset": "view",
|
"preset": "view",
|
||||||
"rights": { "Delete": false },
|
"rights": { "Delete": false },
|
||||||
"rls": { "Read": "#ДляОбъекта(\"\")" }
|
"rls": { "Read": "#ДляОбъекта(\"\")" }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- `preset` — базовый набор прав (`"view"`, `"edit"`)
|
- `preset` — базовый набор прав (`"view"`, `"edit"`)
|
||||||
- `rights` — переопределения: dict `{"Right": true/false}` или массив `["Right1", "Right2"]`
|
- `rights` — переопределения: dict `{"Right": true/false}` или массив `["Right1", "Right2"]`
|
||||||
- `rls` — RLS-ограничения: `{"ИмяПрава": "текст условия"}`
|
- `rls` — RLS-ограничения: `{"ИмяПрава": "текст условия"}`
|
||||||
|
|
||||||
## Пресеты — подробные таблицы
|
## Пресеты — подробные таблицы
|
||||||
|
|
||||||
Пресеты обозначаются `@` в строковом формате. В объектной форме ключ `preset` без `@`.
|
Пресеты обозначаются `@` в строковом формате. В объектной форме ключ `preset` без `@`.
|
||||||
|
|
||||||
### `@view` — просмотр
|
### `@view` — просмотр
|
||||||
|
|
||||||
| Тип объекта | Права |
|
| Тип объекта | Права |
|
||||||
|-------------|-------|
|
|-------------|-------|
|
||||||
| Catalog, ExchangePlan, Document, ChartOfAccounts, ChartOfCharacteristicTypes, ChartOfCalculationTypes, BusinessProcess, Task | Read, View, InputByString |
|
| Catalog, ExchangePlan, Document, ChartOfAccounts, ChartOfCharacteristicTypes, ChartOfCalculationTypes, BusinessProcess, Task | Read, View, InputByString |
|
||||||
| InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister, Constant, DocumentJournal | Read, View |
|
| InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister, Constant, DocumentJournal | Read, View |
|
||||||
| Sequence | Read |
|
| Sequence | Read |
|
||||||
| CommonForm, CommonCommand, Subsystem, FilterCriterion, CommonAttribute | View |
|
| CommonForm, CommonCommand, Subsystem, FilterCriterion, CommonAttribute | View |
|
||||||
| DataProcessor, Report | Use, View |
|
| DataProcessor, Report | Use, View |
|
||||||
| SessionParameter | Get |
|
| SessionParameter | Get |
|
||||||
| Configuration | ThinClient, WebClient, Output, SaveUserData, MainWindowModeNormal |
|
| Configuration | ThinClient, WebClient, Output, SaveUserData, MainWindowModeNormal |
|
||||||
|
|
||||||
### `@edit` — полное редактирование
|
### `@edit` — полное редактирование
|
||||||
|
|
||||||
| Тип объекта | Права |
|
| Тип объекта | Права |
|
||||||
|-------------|-------|
|
|-------------|-------|
|
||||||
| Catalog, ExchangePlan, ChartOfAccounts, ChartOfCharacteristicTypes, ChartOfCalculationTypes | Read, Insert, Update, Delete, View, Edit, InputByString, InteractiveInsert, InteractiveSetDeletionMark, InteractiveClearDeletionMark |
|
| Catalog, ExchangePlan, ChartOfAccounts, ChartOfCharacteristicTypes, ChartOfCalculationTypes | Read, Insert, Update, Delete, View, Edit, InputByString, InteractiveInsert, InteractiveSetDeletionMark, InteractiveClearDeletionMark |
|
||||||
| Document | Read, Insert, Update, Delete, View, Edit, InputByString, Posting, UndoPosting, InteractiveInsert, InteractiveSetDeletionMark, InteractiveClearDeletionMark, InteractivePosting, InteractivePostingRegular, InteractiveUndoPosting, InteractiveChangeOfPosted |
|
| Document | Read, Insert, Update, Delete, View, Edit, InputByString, Posting, UndoPosting, InteractiveInsert, InteractiveSetDeletionMark, InteractiveClearDeletionMark, InteractivePosting, InteractivePostingRegular, InteractiveUndoPosting, InteractiveChangeOfPosted |
|
||||||
| BusinessProcess | Read, Insert, Update, Delete, View, Edit, InputByString, Start, InteractiveInsert, InteractiveSetDeletionMark, InteractiveClearDeletionMark, InteractiveActivate, InteractiveStart |
|
| BusinessProcess | Read, Insert, Update, Delete, View, Edit, InputByString, Start, InteractiveInsert, InteractiveSetDeletionMark, InteractiveClearDeletionMark, InteractiveActivate, InteractiveStart |
|
||||||
| Task | Read, Insert, Update, Delete, View, Edit, InputByString, Execute, InteractiveInsert, InteractiveSetDeletionMark, InteractiveClearDeletionMark, InteractiveActivate, InteractiveExecute |
|
| Task | Read, Insert, Update, Delete, View, Edit, InputByString, Execute, InteractiveInsert, InteractiveSetDeletionMark, InteractiveClearDeletionMark, InteractiveActivate, InteractiveExecute |
|
||||||
| InformationRegister, AccumulationRegister, AccountingRegister, Constant | Read, Update, View, Edit |
|
| InformationRegister, AccumulationRegister, AccountingRegister, Constant | Read, Update, View, Edit |
|
||||||
| DocumentJournal | Read, View |
|
| DocumentJournal | Read, View |
|
||||||
| Sequence | Read, Update |
|
| Sequence | Read, Update |
|
||||||
| SessionParameter | Get, Set |
|
| SessionParameter | Get, Set |
|
||||||
| CommonAttribute | View, Edit |
|
| CommonAttribute | View, Edit |
|
||||||
|
|
||||||
Для сервисов (WebService, HTTPService, IntegrationService) пресеты не определены — используй явные права: `"WebService.Имя: Use"`.
|
Для сервисов (WebService, HTTPService, IntegrationService) пресеты не определены — используй явные права: `"WebService.Имя: Use"`.
|
||||||
|
|
||||||
Если пресет не определён для типа объекта — предупреждение с подсказкой доступных.
|
Если пресет не определён для типа объекта — предупреждение с подсказкой доступных.
|
||||||
|
|
||||||
## Русские синонимы
|
## Русские синонимы
|
||||||
|
|
||||||
Скрипт автоматически транслирует русские имена в английские. Можно смешивать: `"Справочник.Контрагенты: Чтение, View"` — работает.
|
Скрипт автоматически транслирует русские имена в английские. Можно смешивать: `"Справочник.Контрагенты: Чтение, View"` — работает.
|
||||||
|
|
||||||
### Типы объектов
|
### Типы объектов
|
||||||
|
|
||||||
| Русский | English |
|
| Русский | English |
|
||||||
|---------|---------|
|
|---------|---------|
|
||||||
| `Справочник` | Catalog |
|
| `Справочник` | Catalog |
|
||||||
| `Документ` | Document |
|
| `Документ` | Document |
|
||||||
| `РегистрСведений` | InformationRegister |
|
| `РегистрСведений` | InformationRegister |
|
||||||
| `РегистрНакопления` | AccumulationRegister |
|
| `РегистрНакопления` | AccumulationRegister |
|
||||||
| `РегистрБухгалтерии` | AccountingRegister |
|
| `РегистрБухгалтерии` | AccountingRegister |
|
||||||
| `РегистрРасчета` | CalculationRegister |
|
| `РегистрРасчета` | CalculationRegister |
|
||||||
| `Константа` | Constant |
|
| `Константа` | Constant |
|
||||||
| `ПланСчетов` | ChartOfAccounts |
|
| `ПланСчетов` | ChartOfAccounts |
|
||||||
| `ПланВидовХарактеристик` | ChartOfCharacteristicTypes |
|
| `ПланВидовХарактеристик` | ChartOfCharacteristicTypes |
|
||||||
| `ПланВидовРасчета` | ChartOfCalculationTypes |
|
| `ПланВидовРасчета` | ChartOfCalculationTypes |
|
||||||
| `ПланОбмена` | ExchangePlan |
|
| `ПланОбмена` | ExchangePlan |
|
||||||
| `БизнесПроцесс` | BusinessProcess |
|
| `БизнесПроцесс` | BusinessProcess |
|
||||||
| `Задача` | Task |
|
| `Задача` | Task |
|
||||||
| `Обработка` | DataProcessor |
|
| `Обработка` | DataProcessor |
|
||||||
| `Отчет` | Report |
|
| `Отчет` | Report |
|
||||||
| `ОбщаяФорма` | CommonForm |
|
| `ОбщаяФорма` | CommonForm |
|
||||||
| `ОбщаяКоманда` | CommonCommand |
|
| `ОбщаяКоманда` | CommonCommand |
|
||||||
| `Подсистема` | Subsystem |
|
| `Подсистема` | Subsystem |
|
||||||
| `КритерийОтбора` | FilterCriterion |
|
| `КритерийОтбора` | FilterCriterion |
|
||||||
| `ЖурналДокументов` | DocumentJournal |
|
| `ЖурналДокументов` | DocumentJournal |
|
||||||
| `Последовательность` | Sequence |
|
| `Последовательность` | Sequence |
|
||||||
| `ВебСервис` | WebService |
|
| `ВебСервис` | WebService |
|
||||||
| `HTTPСервис` | HTTPService |
|
| `HTTPСервис` | HTTPService |
|
||||||
| `СервисИнтеграции` | IntegrationService |
|
| `СервисИнтеграции` | IntegrationService |
|
||||||
| `ПараметрСеанса` | SessionParameter |
|
| `ПараметрСеанса` | SessionParameter |
|
||||||
| `ОбщийРеквизит` | CommonAttribute |
|
| `ОбщийРеквизит` | CommonAttribute |
|
||||||
| `Конфигурация` | Configuration |
|
| `Конфигурация` | Configuration |
|
||||||
| `Перечисление` | Enum |
|
| `Перечисление` | Enum |
|
||||||
|
|
||||||
### Вложенные типы
|
### Вложенные типы
|
||||||
|
|
||||||
| Русский | English |
|
| Русский | English |
|
||||||
|---------|---------|
|
|---------|---------|
|
||||||
| `Реквизит` | Attribute |
|
| `Реквизит` | Attribute |
|
||||||
| `СтандартныйРеквизит` | StandardAttribute |
|
| `СтандартныйРеквизит` | StandardAttribute |
|
||||||
| `ТабличнаяЧасть` | TabularSection |
|
| `ТабличнаяЧасть` | TabularSection |
|
||||||
| `Измерение` | Dimension |
|
| `Измерение` | Dimension |
|
||||||
| `Ресурс` | Resource |
|
| `Ресурс` | Resource |
|
||||||
| `Команда` | Command |
|
| `Команда` | Command |
|
||||||
| `РеквизитАдресации` | AddressingAttribute |
|
| `РеквизитАдресации` | AddressingAttribute |
|
||||||
|
|
||||||
### Права (основные)
|
### Права (основные)
|
||||||
|
|
||||||
| Русский | English |
|
| Русский | English |
|
||||||
|---------|---------|
|
|---------|---------|
|
||||||
| `Чтение` | Read |
|
| `Чтение` | Read |
|
||||||
| `Добавление` | Insert |
|
| `Добавление` | Insert |
|
||||||
| `Изменение` | Update |
|
| `Изменение` | Update |
|
||||||
| `Удаление` | Delete |
|
| `Удаление` | Delete |
|
||||||
| `Просмотр` | View |
|
| `Просмотр` | View |
|
||||||
| `Редактирование` | Edit |
|
| `Редактирование` | Edit |
|
||||||
| `ВводПоСтроке` | InputByString |
|
| `ВводПоСтроке` | InputByString |
|
||||||
| `Проведение` | Posting |
|
| `Проведение` | Posting |
|
||||||
| `ОтменаПроведения` | UndoPosting |
|
| `ОтменаПроведения` | UndoPosting |
|
||||||
| `Использование` | Use |
|
| `Использование` | Use |
|
||||||
| `Получение` | Get |
|
| `Получение` | Get |
|
||||||
| `Установка` | Set |
|
| `Установка` | Set |
|
||||||
| `Старт` | Start |
|
| `Старт` | Start |
|
||||||
| `Выполнение` | Execute |
|
| `Выполнение` | Execute |
|
||||||
| `УправлениеИтогами` | TotalsControl |
|
| `УправлениеИтогами` | TotalsControl |
|
||||||
|
|
||||||
### Права (интерактивные)
|
### Права (интерактивные)
|
||||||
|
|
||||||
| Русский | English |
|
| Русский | English |
|
||||||
|---------|---------|
|
|---------|---------|
|
||||||
| `ИнтерактивноеДобавление` | InteractiveInsert |
|
| `ИнтерактивноеДобавление` | InteractiveInsert |
|
||||||
| `ИнтерактивнаяПометкаУдаления` | InteractiveSetDeletionMark |
|
| `ИнтерактивнаяПометкаУдаления` | InteractiveSetDeletionMark |
|
||||||
| `ИнтерактивноеСнятиеПометкиУдаления` | InteractiveClearDeletionMark |
|
| `ИнтерактивноеСнятиеПометкиУдаления` | InteractiveClearDeletionMark |
|
||||||
| `ИнтерактивноеУдаление` | InteractiveDelete |
|
| `ИнтерактивноеУдаление` | InteractiveDelete |
|
||||||
| `ИнтерактивноеУдалениеПомеченных` | InteractiveDeleteMarked |
|
| `ИнтерактивноеУдалениеПомеченных` | InteractiveDeleteMarked |
|
||||||
| `ИнтерактивноеПроведение` | InteractivePosting |
|
| `ИнтерактивноеПроведение` | InteractivePosting |
|
||||||
| `ИнтерактивноеПроведениеНеоперативное` | InteractivePostingRegular |
|
| `ИнтерактивноеПроведениеНеоперативное` | InteractivePostingRegular |
|
||||||
| `ИнтерактивнаяОтменаПроведения` | InteractiveUndoPosting |
|
| `ИнтерактивнаяОтменаПроведения` | InteractiveUndoPosting |
|
||||||
| `ИнтерактивноеИзменениеПроведенных` | InteractiveChangeOfPosted |
|
| `ИнтерактивноеИзменениеПроведенных` | InteractiveChangeOfPosted |
|
||||||
| `ИнтерактивныйСтарт` | InteractiveStart |
|
| `ИнтерактивныйСтарт` | InteractiveStart |
|
||||||
| `ИнтерактивнаяАктивация` | InteractiveActivate |
|
| `ИнтерактивнаяАктивация` | InteractiveActivate |
|
||||||
| `ИнтерактивноеВыполнение` | InteractiveExecute |
|
| `ИнтерактивноеВыполнение` | InteractiveExecute |
|
||||||
|
|
||||||
### Права (конфигурация)
|
### Права (конфигурация)
|
||||||
|
|
||||||
| Русский | English |
|
| Русский | English |
|
||||||
|---------|---------|
|
|---------|---------|
|
||||||
| `Администрирование` | Administration |
|
| `Администрирование` | Administration |
|
||||||
| `АдминистрированиеДанных` | DataAdministration |
|
| `АдминистрированиеДанных` | DataAdministration |
|
||||||
| `ТонкийКлиент` | ThinClient |
|
| `ТонкийКлиент` | ThinClient |
|
||||||
| `ТолстыйКлиент` | ThickClient |
|
| `ТолстыйКлиент` | ThickClient |
|
||||||
| `ВебКлиент` | WebClient |
|
| `ВебКлиент` | WebClient |
|
||||||
| `МобильныйКлиент` | MobileClient |
|
| `МобильныйКлиент` | MobileClient |
|
||||||
| `ВнешнееСоединение` | ExternalConnection |
|
| `ВнешнееСоединение` | ExternalConnection |
|
||||||
| `Вывод` | Output |
|
| `Вывод` | Output |
|
||||||
| `СохранениеДанныхПользователя` | SaveUserData |
|
| `СохранениеДанныхПользователя` | SaveUserData |
|
||||||
|
|
||||||
## Типы объектов без прав в ролях
|
## Типы объектов без прав в ролях
|
||||||
|
|
||||||
Следующие типы 1С **не могут** иметь права в ролях (не добавляются в `objects`):
|
Следующие типы 1С **не могут** иметь права в ролях (не добавляются в `objects`):
|
||||||
|
|
||||||
| Тип | Причина |
|
| Тип | Причина |
|
||||||
|-----|---------|
|
|-----|---------|
|
||||||
| Enum (Перечисление) | Права наследуются от конфигурации, явное назначение невозможно |
|
| Enum (Перечисление) | Права наследуются от конфигурации, явное назначение невозможно |
|
||||||
| CommonModule (ОбщийМодуль) | Не имеет собственных прав в роли |
|
| CommonModule (ОбщийМодуль) | Не имеет собственных прав в роли |
|
||||||
| DefinedType (ОпределяемыйТип) | Тип данных, не объект прав |
|
| DefinedType (ОпределяемыйТип) | Тип данных, не объект прав |
|
||||||
| CommonPicture (ОбщаяКартинка) | Ресурс, не объект прав |
|
| CommonPicture (ОбщаяКартинка) | Ресурс, не объект прав |
|
||||||
| CommonTemplate (ОбщийМакет) | Ресурс, не объект прав |
|
| CommonTemplate (ОбщийМакет) | Ресурс, не объект прав |
|
||||||
| Language (Язык) | Конфигурационный элемент |
|
| Language (Язык) | Конфигурационный элемент |
|
||||||
| FunctionalOption (ФункциональнаяОпция) | Не объект прав |
|
| FunctionalOption (ФункциональнаяОпция) | Не объект прав |
|
||||||
| FunctionalOptionsParameter | Не объект прав |
|
| FunctionalOptionsParameter | Не объект прав |
|
||||||
| EventSubscription (ПодпискаНаСобытие) | Не объект прав |
|
| EventSubscription (ПодпискаНаСобытие) | Не объект прав |
|
||||||
| ScheduledJob (РегламентноеЗадание) | Не объект прав |
|
| ScheduledJob (РегламентноеЗадание) | Не объект прав |
|
||||||
| StyleItem (ЭлементСтиля) | Ресурс оформления |
|
| StyleItem (ЭлементСтиля) | Ресурс оформления |
|
||||||
|
|
||||||
## Шаблоны ограничений (RLS templates)
|
## Шаблоны ограничений (RLS templates)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"templates": [
|
"templates": [
|
||||||
{
|
{
|
||||||
"name": "ДляОбъекта(Модификатор)",
|
"name": "ДляОбъекта(Модификатор)",
|
||||||
"condition": "// текст шаблона\nГДЕ 1=1\n&Модификатор"
|
"condition": "// текст шаблона\nГДЕ 1=1\n&Модификатор"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
- `&` в условии автоматически экранируется в `&` в XML
|
- `&` в условии автоматически экранируется в `&` в XML
|
||||||
- Ссылка на шаблон в `rls`: `"#ИмяШаблона(\"параметры\")"` — начинается с `#`
|
- Ссылка на шаблон в `rls`: `"#ИмяШаблона(\"параметры\")"` — начинается с `#`
|
||||||
- Параметры шаблона можно передавать пустыми: `#ДляОбъекта("")`
|
- Параметры шаблона можно передавать пустыми: `#ДляОбъекта("")`
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
### 1. Простая роль (только пресеты)
|
### 1. Простая роль (только пресеты)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "ЧтениеНоменклатуры",
|
"name": "ЧтениеНоменклатуры",
|
||||||
"synonym": "Чтение номенклатуры",
|
"synonym": "Чтение номенклатуры",
|
||||||
"objects": [
|
"objects": [
|
||||||
"Catalog.Номенклатура: @view",
|
"Catalog.Номенклатура: @view",
|
||||||
"Catalog.Контрагенты: @view",
|
"Catalog.Контрагенты: @view",
|
||||||
"DataProcessor.Загрузка: @view"
|
"DataProcessor.Загрузка: @view"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Роль для регламентного задания
|
### 2. Роль для регламентного задания
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "ОбновлениеЦен",
|
"name": "ОбновлениеЦен",
|
||||||
"synonym": "Обновление цен номенклатуры",
|
"synonym": "Обновление цен номенклатуры",
|
||||||
"objects": [
|
"objects": [
|
||||||
"Catalog.Номенклатура: Read",
|
"Catalog.Номенклатура: Read",
|
||||||
"Catalog.Валюты: Read",
|
"Catalog.Валюты: Read",
|
||||||
"InformationRegister.ЦеныНоменклатуры: Read, Update",
|
"InformationRegister.ЦеныНоменклатуры: Read, Update",
|
||||||
"Constant.ОсновнаяВалюта: Read"
|
"Constant.ОсновнаяВалюта: Read"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Роль с RLS
|
### 3. Роль с RLS
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "ЧтениеДокументовПоОрганизации",
|
"name": "ЧтениеДокументовПоОрганизации",
|
||||||
"synonym": "Чтение документов (ограничение по организации)",
|
"synonym": "Чтение документов (ограничение по организации)",
|
||||||
"objects": [
|
"objects": [
|
||||||
"Catalog.Организации: @view",
|
"Catalog.Организации: @view",
|
||||||
{
|
{
|
||||||
"name": "Document.РеализацияТоваровУслуг",
|
"name": "Document.РеализацияТоваровУслуг",
|
||||||
"preset": "view",
|
"preset": "view",
|
||||||
"rls": {
|
"rls": {
|
||||||
"Read": "#ДляОбъекта(\"\")"
|
"Read": "#ДляОбъекта(\"\")"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"templates": [
|
"templates": [
|
||||||
{
|
{
|
||||||
"name": "ДляОбъекта(Модификатор)",
|
"name": "ДляОбъекта(Модификатор)",
|
||||||
"condition": "ГДЕ Организация = &ТекущаяОрганизация"
|
"condition": "ГДЕ Организация = &ТекущаяОрганизация"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Роль с русскими синонимами
|
### 4. Роль с русскими синонимами
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "ПросмотрДанных",
|
"name": "ПросмотрДанных",
|
||||||
"synonym": "Просмотр данных",
|
"synonym": "Просмотр данных",
|
||||||
"objects": [
|
"objects": [
|
||||||
"Справочник.Контрагенты: @view",
|
"Справочник.Контрагенты: @view",
|
||||||
"Документ.Реализация: Чтение, Просмотр",
|
"Документ.Реализация: Чтение, Просмотр",
|
||||||
"РегистрСведений.Цены: @edit",
|
"РегистрСведений.Цены: @edit",
|
||||||
"Обработка.ЗагрузкаДанных: @view"
|
"Обработка.ЗагрузкаДанных: @view"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5. Роль с переопределением прав из пресета
|
### 5. Роль с переопределением прав из пресета
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "ОграниченноеРедактирование",
|
"name": "ОграниченноеРедактирование",
|
||||||
"synonym": "Редактирование без удаления",
|
"synonym": "Редактирование без удаления",
|
||||||
"objects": [
|
"objects": [
|
||||||
{
|
{
|
||||||
"name": "Catalog.Контрагенты",
|
"name": "Catalog.Контрагенты",
|
||||||
"preset": "edit",
|
"preset": "edit",
|
||||||
"rights": { "Delete": false }
|
"rights": { "Delete": false }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,44 +1,44 @@
|
|||||||
---
|
---
|
||||||
name: role-info
|
name: role-info
|
||||||
description: Компактная сводка прав роли 1С из Rights.xml — объекты, права, RLS, шаблоны ограничений. Используй для аудита прав — какие объекты и действия доступны, ограничения RLS
|
description: Компактная сводка прав роли 1С из Rights.xml — объекты, права, RLS, шаблоны ограничений. Используй для аудита прав — какие объекты и действия доступны, ограничения RLS
|
||||||
argument-hint: <RightsPath>
|
argument-hint: <RightsPath>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
---
|
---
|
||||||
|
|
||||||
# /role-info — анализ роли 1С
|
# /role-info — анализ роли 1С
|
||||||
|
|
||||||
Парсит `Rights.xml` роли и выдаёт компактную сводку: объекты сгруппированы по типу, показаны только разрешённые права. Сжатие: тысячи строк XML → 50–150 строк текста.
|
Парсит `Rights.xml` роли и выдаёт компактную сводку: объекты сгруппированы по типу, показаны только разрешённые права. Сжатие: тысячи строк XML → 50–150 строк текста.
|
||||||
|
|
||||||
## Использование
|
## Использование
|
||||||
|
|
||||||
```
|
```
|
||||||
/role-info <RightsPath>
|
/role-info <RightsPath>
|
||||||
```
|
```
|
||||||
|
|
||||||
**RightsPath** — путь к файлу `Rights.xml` роли (обычно `Roles/ИмяРоли/Ext/Rights.xml`).
|
**RightsPath** — путь к файлу `Rights.xml` роли (обычно `Roles/ИмяРоли/Ext/Rights.xml`).
|
||||||
|
|
||||||
## Запуск скрипта
|
## Запуск скрипта
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-info.ps1" -RightsPath <path> -OutFile <output.txt>
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-info.ps1" -RightsPath <path> -OutFile <output.txt>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры
|
### Параметры
|
||||||
|
|
||||||
| Параметр | Обязательный | Описание |
|
| Параметр | Обязательный | Описание |
|
||||||
|----------|:------------:|----------|
|
|----------|:------------:|----------|
|
||||||
| `-RightsPath` | да | Путь к Rights.xml |
|
| `-RightsPath` | да | Путь к Rights.xml |
|
||||||
| `-ShowDenied` | нет | Показать запрещённые права (по умолчанию скрыты) |
|
| `-ShowDenied` | нет | Показать запрещённые права (по умолчанию скрыты) |
|
||||||
| `-Limit` | нет | Макс. строк вывода (по умолчанию `150`). `0` = без ограничений |
|
| `-Limit` | нет | Макс. строк вывода (по умолчанию `150`). `0` = без ограничений |
|
||||||
| `-Offset` | нет | Пропустить N строк — для пагинации (по умолчанию `0`) |
|
| `-Offset` | нет | Пропустить N строк — для пагинации (по умолчанию `0`) |
|
||||||
| `-OutFile` | нет | Записать результат в файл (UTF-8 BOM). Без этого — вывод в консоль |
|
| `-OutFile` | нет | Записать результат в файл (UTF-8 BOM). Без этого — вывод в консоль |
|
||||||
|
|
||||||
**Важно:** Всегда используй `-OutFile` и читай результат через Read tool. Прямой вывод в консоль через bash ломает кириллицу.
|
**Важно:** Всегда используй `-OutFile` и читай результат через Read tool. Прямой вывод в консоль через bash ломает кириллицу.
|
||||||
|
|
||||||
Для большой роли при усечении вывода:
|
Для большой роли при усечении вывода:
|
||||||
```powershell
|
```powershell
|
||||||
... -Offset 150 # пагинация: пропустить первые 150 строк
|
... -Offset 150 # пагинация: пропустить первые 150 строк
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,305 +1,305 @@
|
|||||||
# role-info v1.1 — Analyze 1C role rights
|
# role-info v1.1 — Analyze 1C role rights
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$true)][Alias('Path')][string]$RightsPath,
|
[Parameter(Mandatory=$true)][Alias('Path')][string]$RightsPath,
|
||||||
[switch]$ShowDenied,
|
[switch]$ShowDenied,
|
||||||
[int]$Limit = 150,
|
[int]$Limit = 150,
|
||||||
[int]$Offset = 0,
|
[int]$Offset = 0,
|
||||||
[string]$OutFile
|
[string]$OutFile
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||||
|
|
||||||
# --- Output helper (always collect, paginate at the end) ---
|
# --- Output helper (always collect, paginate at the end) ---
|
||||||
$script:lines = @()
|
$script:lines = @()
|
||||||
function Out([string]$text) { $script:lines += $text }
|
function Out([string]$text) { $script:lines += $text }
|
||||||
|
|
||||||
# --- Resolve paths ---
|
# --- Resolve paths ---
|
||||||
if (-not [System.IO.Path]::IsPathRooted($RightsPath)) {
|
if (-not [System.IO.Path]::IsPathRooted($RightsPath)) {
|
||||||
$RightsPath = Join-Path (Get-Location).Path $RightsPath
|
$RightsPath = Join-Path (Get-Location).Path $RightsPath
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $RightsPath)) {
|
if (-not (Test-Path $RightsPath)) {
|
||||||
Write-Host "[ERROR] File not found: $RightsPath"
|
Write-Host "[ERROR] File not found: $RightsPath"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Try to find metadata file for role name/synonym ---
|
# --- Try to find metadata file for role name/synonym ---
|
||||||
$roleName = ""
|
$roleName = ""
|
||||||
$roleSynonym = ""
|
$roleSynonym = ""
|
||||||
$extDir = Split-Path $RightsPath # .../Ext
|
$extDir = Split-Path $RightsPath # .../Ext
|
||||||
$roleDir = Split-Path $extDir # .../RoleName
|
$roleDir = Split-Path $extDir # .../RoleName
|
||||||
$rolesDir = Split-Path $roleDir # .../Roles
|
$rolesDir = Split-Path $roleDir # .../Roles
|
||||||
$roleFolderName = Split-Path $roleDir -Leaf
|
$roleFolderName = Split-Path $roleDir -Leaf
|
||||||
$metaPath = Join-Path $rolesDir "$roleFolderName.xml"
|
$metaPath = Join-Path $rolesDir "$roleFolderName.xml"
|
||||||
|
|
||||||
if (Test-Path $metaPath) {
|
if (Test-Path $metaPath) {
|
||||||
try {
|
try {
|
||||||
[xml]$metaXml = Get-Content -Path $metaPath -Encoding UTF8
|
[xml]$metaXml = Get-Content -Path $metaPath -Encoding UTF8
|
||||||
$ns = New-Object System.Xml.XmlNamespaceManager($metaXml.NameTable)
|
$ns = New-Object System.Xml.XmlNamespaceManager($metaXml.NameTable)
|
||||||
$ns.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
|
$ns.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
|
||||||
$ns.AddNamespace("v8", "http://v8.1c.ru/8.1/data/core")
|
$ns.AddNamespace("v8", "http://v8.1c.ru/8.1/data/core")
|
||||||
$nameNode = $metaXml.SelectSingleNode("//md:Role/md:Properties/md:Name", $ns)
|
$nameNode = $metaXml.SelectSingleNode("//md:Role/md:Properties/md:Name", $ns)
|
||||||
if ($nameNode) { $roleName = $nameNode.InnerText }
|
if ($nameNode) { $roleName = $nameNode.InnerText }
|
||||||
$synNode = $metaXml.SelectSingleNode("//md:Role/md:Properties/md:Synonym/v8:item[v8:lang='ru']/v8:content", $ns)
|
$synNode = $metaXml.SelectSingleNode("//md:Role/md:Properties/md:Synonym/v8:item[v8:lang='ru']/v8:content", $ns)
|
||||||
if ($synNode) { $roleSynonym = $synNode.InnerText }
|
if ($synNode) { $roleSynonym = $synNode.InnerText }
|
||||||
} catch {
|
} catch {
|
||||||
# Ignore metadata parsing errors
|
# Ignore metadata parsing errors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not $roleName) { $roleName = $roleFolderName }
|
if (-not $roleName) { $roleName = $roleFolderName }
|
||||||
|
|
||||||
# --- Parse Rights.xml ---
|
# --- Parse Rights.xml ---
|
||||||
[xml]$xml = Get-Content -Path $RightsPath -Encoding UTF8
|
[xml]$xml = Get-Content -Path $RightsPath -Encoding UTF8
|
||||||
$root = $xml.DocumentElement
|
$root = $xml.DocumentElement
|
||||||
$rightsNs = "http://v8.1c.ru/8.2/roles"
|
$rightsNs = "http://v8.1c.ru/8.2/roles"
|
||||||
|
|
||||||
# Global flags
|
# Global flags
|
||||||
$setForNew = $root.setForNewObjects
|
$setForNew = $root.setForNewObjects
|
||||||
$setForAttrs = $root.setForAttributesByDefault
|
$setForAttrs = $root.setForAttributesByDefault
|
||||||
$independentChild = $root.independentRightsOfChildObjects
|
$independentChild = $root.independentRightsOfChildObjects
|
||||||
|
|
||||||
# --- Collect objects ---
|
# --- Collect objects ---
|
||||||
# Structure: grouped by type prefix, then by object short name
|
# Structure: grouped by type prefix, then by object short name
|
||||||
$allowed = [ordered]@{} # type -> [ordered]@{ shortName -> [list of rights] }
|
$allowed = [ordered]@{} # type -> [ordered]@{ shortName -> [list of rights] }
|
||||||
$denied = [ordered]@{} # type -> [ordered]@{ shortName -> [list of rights] }
|
$denied = [ordered]@{} # type -> [ordered]@{ shortName -> [list of rights] }
|
||||||
$rlsObjects = @()
|
$rlsObjects = @()
|
||||||
$totalAllowed = 0
|
$totalAllowed = 0
|
||||||
$totalDenied = 0
|
$totalDenied = 0
|
||||||
|
|
||||||
$objects = $root.GetElementsByTagName("object", $rightsNs)
|
$objects = $root.GetElementsByTagName("object", $rightsNs)
|
||||||
foreach ($obj in $objects) {
|
foreach ($obj in $objects) {
|
||||||
$objName = ""
|
$objName = ""
|
||||||
$rights = @()
|
$rights = @()
|
||||||
|
|
||||||
foreach ($child in $obj.ChildNodes) {
|
foreach ($child in $obj.ChildNodes) {
|
||||||
if ($child.LocalName -eq "name" -and $child.NamespaceURI -eq $rightsNs) {
|
if ($child.LocalName -eq "name" -and $child.NamespaceURI -eq $rightsNs) {
|
||||||
$objName = $child.InnerText
|
$objName = $child.InnerText
|
||||||
}
|
}
|
||||||
if ($child.LocalName -eq "right" -and $child.NamespaceURI -eq $rightsNs) {
|
if ($child.LocalName -eq "right" -and $child.NamespaceURI -eq $rightsNs) {
|
||||||
$rName = ""
|
$rName = ""
|
||||||
$rValue = ""
|
$rValue = ""
|
||||||
$hasRLS = $false
|
$hasRLS = $false
|
||||||
foreach ($rc in $child.ChildNodes) {
|
foreach ($rc in $child.ChildNodes) {
|
||||||
if ($rc.LocalName -eq "name") { $rName = $rc.InnerText }
|
if ($rc.LocalName -eq "name") { $rName = $rc.InnerText }
|
||||||
if ($rc.LocalName -eq "value") { $rValue = $rc.InnerText }
|
if ($rc.LocalName -eq "value") { $rValue = $rc.InnerText }
|
||||||
if ($rc.LocalName -eq "restrictionByCondition") { $hasRLS = $true }
|
if ($rc.LocalName -eq "restrictionByCondition") { $hasRLS = $true }
|
||||||
}
|
}
|
||||||
if ($rName -and $rValue) {
|
if ($rName -and $rValue) {
|
||||||
$rights += @{ name = $rName; value = $rValue; rls = $hasRLS }
|
$rights += @{ name = $rName; value = $rValue; rls = $hasRLS }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not $objName -or $rights.Count -eq 0) { continue }
|
if (-not $objName -or $rights.Count -eq 0) { continue }
|
||||||
|
|
||||||
# Split into type prefix and short name
|
# Split into type prefix and short name
|
||||||
$dotIdx = $objName.IndexOf(".")
|
$dotIdx = $objName.IndexOf(".")
|
||||||
if ($dotIdx -lt 0) { continue }
|
if ($dotIdx -lt 0) { continue }
|
||||||
$typePrefix = $objName.Substring(0, $dotIdx)
|
$typePrefix = $objName.Substring(0, $dotIdx)
|
||||||
$shortName = $objName.Substring($dotIdx + 1)
|
$shortName = $objName.Substring($dotIdx + 1)
|
||||||
|
|
||||||
foreach ($r in $rights) {
|
foreach ($r in $rights) {
|
||||||
if ($r.value -eq "true") {
|
if ($r.value -eq "true") {
|
||||||
$totalAllowed++
|
$totalAllowed++
|
||||||
if (-not $allowed.Contains($typePrefix)) {
|
if (-not $allowed.Contains($typePrefix)) {
|
||||||
$allowed[$typePrefix] = [ordered]@{}
|
$allowed[$typePrefix] = [ordered]@{}
|
||||||
}
|
}
|
||||||
if (-not $allowed[$typePrefix].Contains($shortName)) {
|
if (-not $allowed[$typePrefix].Contains($shortName)) {
|
||||||
$allowed[$typePrefix][$shortName] = @()
|
$allowed[$typePrefix][$shortName] = @()
|
||||||
}
|
}
|
||||||
$suffix = $r.name
|
$suffix = $r.name
|
||||||
if ($r.rls) {
|
if ($r.rls) {
|
||||||
$suffix += " [RLS]"
|
$suffix += " [RLS]"
|
||||||
$rlsObjects += "$typePrefix.$shortName ($($r.name))"
|
$rlsObjects += "$typePrefix.$shortName ($($r.name))"
|
||||||
}
|
}
|
||||||
$allowed[$typePrefix][$shortName] += $suffix
|
$allowed[$typePrefix][$shortName] += $suffix
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$totalDenied++
|
$totalDenied++
|
||||||
if (-not $denied.Contains($typePrefix)) {
|
if (-not $denied.Contains($typePrefix)) {
|
||||||
$denied[$typePrefix] = [ordered]@{}
|
$denied[$typePrefix] = [ordered]@{}
|
||||||
}
|
}
|
||||||
if (-not $denied[$typePrefix].Contains($shortName)) {
|
if (-not $denied[$typePrefix].Contains($shortName)) {
|
||||||
$denied[$typePrefix][$shortName] = @()
|
$denied[$typePrefix][$shortName] = @()
|
||||||
}
|
}
|
||||||
$denied[$typePrefix][$shortName] += $r.name
|
$denied[$typePrefix][$shortName] += $r.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Restriction templates ---
|
# --- Restriction templates ---
|
||||||
$templates = @()
|
$templates = @()
|
||||||
$tplNodes = $root.GetElementsByTagName("restrictionTemplate", $rightsNs)
|
$tplNodes = $root.GetElementsByTagName("restrictionTemplate", $rightsNs)
|
||||||
foreach ($tpl in $tplNodes) {
|
foreach ($tpl in $tplNodes) {
|
||||||
foreach ($child in $tpl.ChildNodes) {
|
foreach ($child in $tpl.ChildNodes) {
|
||||||
if ($child.LocalName -eq "name") {
|
if ($child.LocalName -eq "name") {
|
||||||
$tName = $child.InnerText
|
$tName = $child.InnerText
|
||||||
# Extract just the name part before parentheses
|
# Extract just the name part before parentheses
|
||||||
$parenIdx = $tName.IndexOf("(")
|
$parenIdx = $tName.IndexOf("(")
|
||||||
if ($parenIdx -gt 0) { $tName = $tName.Substring(0, $parenIdx) }
|
if ($parenIdx -gt 0) { $tName = $tName.Substring(0, $parenIdx) }
|
||||||
$templates += $tName
|
$templates += $tName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-SupportStatusForPath([string]$targetPath) {
|
function Get-SupportStatusForPath([string]$targetPath) {
|
||||||
try {
|
try {
|
||||||
$rp = (Resolve-Path $targetPath).Path
|
$rp = (Resolve-Path $targetPath).Path
|
||||||
$elemUuid = $null
|
$elemUuid = $null
|
||||||
$binPath = $null
|
$binPath = $null
|
||||||
# Reads the uuid of the first metadata element in an .xml file (or $null).
|
# Reads the uuid of the first metadata element in an .xml file (or $null).
|
||||||
function Get-RootUuid([string]$xmlPath) {
|
function Get-RootUuid([string]$xmlPath) {
|
||||||
if (-not (Test-Path $xmlPath)) { return $null }
|
if (-not (Test-Path $xmlPath)) { return $null }
|
||||||
try {
|
try {
|
||||||
[xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8
|
[xml]$mx = Get-Content -Path $xmlPath -Encoding UTF8
|
||||||
$el = $mx.DocumentElement.FirstChild
|
$el = $mx.DocumentElement.FirstChild
|
||||||
while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling }
|
while ($el -and $el.NodeType -ne 'Element') { $el = $el.NextSibling }
|
||||||
if ($el) { $u = $el.GetAttribute("uuid"); if ($u) { return $u } }
|
if ($el) { $u = $el.GetAttribute("uuid"); if ($u) { return $u } }
|
||||||
} catch {}
|
} catch {}
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
# The target file itself may be the element meta-xml (e.g. Subsystems/X.xml).
|
# The target file itself may be the element meta-xml (e.g. Subsystems/X.xml).
|
||||||
$elemUuid = Get-RootUuid $rp
|
$elemUuid = Get-RootUuid $rp
|
||||||
$d = [System.IO.Path]::GetDirectoryName($rp)
|
$d = [System.IO.Path]::GetDirectoryName($rp)
|
||||||
for ($i = 0; $i -lt 12 -and $d; $i++) {
|
for ($i = 0; $i -lt 12 -and $d; $i++) {
|
||||||
if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" }
|
if (-not $elemUuid) { $elemUuid = Get-RootUuid "$d.xml" }
|
||||||
if (-not $binPath) {
|
if (-not $binPath) {
|
||||||
$cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin"
|
$cand = Join-Path (Join-Path $d "Ext") "ParentConfigurations.bin"
|
||||||
if ((Test-Path $cand) -or (Test-Path (Join-Path $d "Configuration.xml"))) { $binPath = $cand }
|
if ((Test-Path $cand) -or (Test-Path (Join-Path $d "Configuration.xml"))) { $binPath = $cand }
|
||||||
}
|
}
|
||||||
if ($elemUuid -and $binPath) { break }
|
if ($elemUuid -and $binPath) { break }
|
||||||
$parent = [System.IO.Path]::GetDirectoryName($d)
|
$parent = [System.IO.Path]::GetDirectoryName($d)
|
||||||
if ($parent -eq $d) { break }
|
if ($parent -eq $d) { break }
|
||||||
$d = $parent
|
$d = $parent
|
||||||
}
|
}
|
||||||
if (-not $binPath -or -not (Test-Path $binPath)) { return "не на поддержке" }
|
if (-not $binPath -or -not (Test-Path $binPath)) { return "не на поддержке" }
|
||||||
$bytes = [System.IO.File]::ReadAllBytes($binPath)
|
$bytes = [System.IO.File]::ReadAllBytes($binPath)
|
||||||
if ($bytes.Length -le 32) { return "снято с поддержки (правки свободны)" }
|
if ($bytes.Length -le 32) { return "снято с поддержки (правки свободны)" }
|
||||||
$start = 0
|
$start = 0
|
||||||
if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { $start = 3 }
|
if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { $start = 3 }
|
||||||
$text = [System.Text.Encoding]::UTF8.GetString($bytes, $start, $bytes.Length - $start)
|
$text = [System.Text.Encoding]::UTF8.GetString($bytes, $start, $bytes.Length - $start)
|
||||||
$h = [regex]::Match($text, '^\{6,(\d+),(\d+),')
|
$h = [regex]::Match($text, '^\{6,(\d+),(\d+),')
|
||||||
if (-not $h.Success) { return "не на поддержке" }
|
if (-not $h.Success) { return "не на поддержке" }
|
||||||
$G = [int]$h.Groups[1].Value
|
$G = [int]$h.Groups[1].Value
|
||||||
$K = [int]$h.Groups[2].Value
|
$K = [int]$h.Groups[2].Value
|
||||||
if ($K -eq 0) { return "снято с поддержки (правки свободны)" }
|
if ($K -eq 0) { return "снято с поддержки (правки свободны)" }
|
||||||
if ($G -eq 1) { return "конфигурация read-only (возможность изменения выключена) — правки невозможны без включения" }
|
if ($G -eq 1) { return "конфигурация read-only (возможность изменения выключена) — правки невозможны без включения" }
|
||||||
if (-not $elemUuid) { return "не на поддержке" }
|
if (-not $elemUuid) { return "не на поддержке" }
|
||||||
$u = [regex]::Escape($elemUuid.ToLower())
|
$u = [regex]::Escape($elemUuid.ToLower())
|
||||||
$best = $null
|
$best = $null
|
||||||
foreach ($m in [regex]::Matches($text, "([0-2]),0,$u")) {
|
foreach ($m in [regex]::Matches($text, "([0-2]),0,$u")) {
|
||||||
$f1 = [int]$m.Groups[1].Value
|
$f1 = [int]$m.Groups[1].Value
|
||||||
if ($null -eq $best -or $f1 -lt $best) { $best = $f1 }
|
if ($null -eq $best -or $f1 -lt $best) { $best = $f1 }
|
||||||
}
|
}
|
||||||
if ($null -eq $best) { return "не на поддержке" }
|
if ($null -eq $best) { return "не на поддержке" }
|
||||||
switch ($best) {
|
switch ($best) {
|
||||||
0 { return "на замке — прямая правка сломает обновления; дорабатывай через cfe-* либо включи редактирование объекта" }
|
0 { return "на замке — прямая правка сломает обновления; дорабатывай через cfe-* либо включи редактирование объекта" }
|
||||||
1 { return "редактируется с сохранением поддержки" }
|
1 { return "редактируется с сохранением поддержки" }
|
||||||
2 { return "снято с поддержки (правки свободны)" }
|
2 { return "снято с поддержки (правки свободны)" }
|
||||||
}
|
}
|
||||||
return "не на поддержке"
|
return "не на поддержке"
|
||||||
} catch { return "не на поддержке" }
|
} catch { return "не на поддержке" }
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Output ---
|
# --- Output ---
|
||||||
$header = "=== Role: $roleName"
|
$header = "=== Role: $roleName"
|
||||||
if ($roleSynonym) { $header += " --- `"$roleSynonym`"" }
|
if ($roleSynonym) { $header += " --- `"$roleSynonym`"" }
|
||||||
$header += " ==="
|
$header += " ==="
|
||||||
Out $header
|
Out $header
|
||||||
Out "Поддержка: $(Get-SupportStatusForPath $RightsPath)"
|
Out "Поддержка: $(Get-SupportStatusForPath $RightsPath)"
|
||||||
Out ""
|
Out ""
|
||||||
|
|
||||||
Out "Properties: setForNewObjects=$setForNew, setForAttributesByDefault=$setForAttrs, independentRightsOfChildObjects=$independentChild"
|
Out "Properties: setForNewObjects=$setForNew, setForAttributesByDefault=$setForAttrs, independentRightsOfChildObjects=$independentChild"
|
||||||
Out ""
|
Out ""
|
||||||
|
|
||||||
# Helper: output group
|
# Helper: output group
|
||||||
function OutGroup($objMap, [string]$prefix, [switch]$isDenied) {
|
function OutGroup($objMap, [string]$prefix, [switch]$isDenied) {
|
||||||
foreach ($shortName in @($objMap.Keys)) {
|
foreach ($shortName in @($objMap.Keys)) {
|
||||||
if ($isDenied) {
|
if ($isDenied) {
|
||||||
$rightsList = ($objMap[$shortName] | ForEach-Object { "-$_" }) -join ", "
|
$rightsList = ($objMap[$shortName] | ForEach-Object { "-$_" }) -join ", "
|
||||||
} else {
|
} else {
|
||||||
$rightsList = $objMap[$shortName] -join ", "
|
$rightsList = $objMap[$shortName] -join ", "
|
||||||
}
|
}
|
||||||
Out " ${shortName}: $rightsList"
|
Out " ${shortName}: $rightsList"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Allowed rights grouped by type
|
# Allowed rights grouped by type
|
||||||
if ($allowed.Count -gt 0) {
|
if ($allowed.Count -gt 0) {
|
||||||
Out "Allowed rights:"
|
Out "Allowed rights:"
|
||||||
Out ""
|
Out ""
|
||||||
foreach ($typePrefix in $allowed.Keys) {
|
foreach ($typePrefix in $allowed.Keys) {
|
||||||
$objMap = $allowed[$typePrefix]
|
$objMap = $allowed[$typePrefix]
|
||||||
Out " $typePrefix ($($objMap.Count)):"
|
Out " $typePrefix ($($objMap.Count)):"
|
||||||
OutGroup $objMap $typePrefix
|
OutGroup $objMap $typePrefix
|
||||||
Out ""
|
Out ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Out "(no allowed rights)"
|
Out "(no allowed rights)"
|
||||||
Out ""
|
Out ""
|
||||||
}
|
}
|
||||||
|
|
||||||
# Denied rights
|
# Denied rights
|
||||||
if ($ShowDenied -and $denied.Count -gt 0) {
|
if ($ShowDenied -and $denied.Count -gt 0) {
|
||||||
Out "Denied rights:"
|
Out "Denied rights:"
|
||||||
Out ""
|
Out ""
|
||||||
foreach ($typePrefix in $denied.Keys) {
|
foreach ($typePrefix in $denied.Keys) {
|
||||||
$objMap = $denied[$typePrefix]
|
$objMap = $denied[$typePrefix]
|
||||||
Out " $typePrefix ($($objMap.Count)):"
|
Out " $typePrefix ($($objMap.Count)):"
|
||||||
OutGroup $objMap $typePrefix -isDenied
|
OutGroup $objMap $typePrefix -isDenied
|
||||||
Out ""
|
Out ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elseif ($totalDenied -gt 0) {
|
elseif ($totalDenied -gt 0) {
|
||||||
Out "Denied: $totalDenied rights (use -ShowDenied to list)"
|
Out "Denied: $totalDenied rights (use -ShowDenied to list)"
|
||||||
Out ""
|
Out ""
|
||||||
}
|
}
|
||||||
|
|
||||||
# RLS summary
|
# RLS summary
|
||||||
if ($rlsObjects.Count -gt 0) {
|
if ($rlsObjects.Count -gt 0) {
|
||||||
Out "RLS: $($rlsObjects.Count) restrictions"
|
Out "RLS: $($rlsObjects.Count) restrictions"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Templates
|
# Templates
|
||||||
if ($templates.Count -gt 0) {
|
if ($templates.Count -gt 0) {
|
||||||
Out "Templates: $($templates -join ', ')"
|
Out "Templates: $($templates -join ', ')"
|
||||||
}
|
}
|
||||||
|
|
||||||
Out ""
|
Out ""
|
||||||
Out "---"
|
Out "---"
|
||||||
Out "Total: $totalAllowed allowed, $totalDenied denied"
|
Out "Total: $totalAllowed allowed, $totalDenied denied"
|
||||||
|
|
||||||
# --- Pagination and output ---
|
# --- Pagination and output ---
|
||||||
$totalLines = $script:lines.Count
|
$totalLines = $script:lines.Count
|
||||||
$lines = $script:lines
|
$lines = $script:lines
|
||||||
|
|
||||||
if ($Offset -gt 0) {
|
if ($Offset -gt 0) {
|
||||||
if ($Offset -ge $totalLines) {
|
if ($Offset -ge $totalLines) {
|
||||||
Write-Host "[INFO] Offset $Offset exceeds total lines ($totalLines). Nothing to show."
|
Write-Host "[INFO] Offset $Offset exceeds total lines ($totalLines). Nothing to show."
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
$lines = $lines[$Offset..($totalLines - 1)]
|
$lines = $lines[$Offset..($totalLines - 1)]
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($Limit -gt 0 -and $lines.Count -gt $Limit) {
|
if ($Limit -gt 0 -and $lines.Count -gt $Limit) {
|
||||||
$shown = $lines[0..($Limit - 1)]
|
$shown = $lines[0..($Limit - 1)]
|
||||||
$remaining = $totalLines - $Offset - $Limit
|
$remaining = $totalLines - $Offset - $Limit
|
||||||
$shown += ""
|
$shown += ""
|
||||||
$shown += "[TRUNCATED] Shown $Limit of $totalLines lines. Use -Offset $($Offset + $Limit) to continue."
|
$shown += "[TRUNCATED] Shown $Limit of $totalLines lines. Use -Offset $($Offset + $Limit) to continue."
|
||||||
$lines = $shown
|
$lines = $shown
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($OutFile) {
|
if ($OutFile) {
|
||||||
if (-not [System.IO.Path]::IsPathRooted($OutFile)) {
|
if (-not [System.IO.Path]::IsPathRooted($OutFile)) {
|
||||||
$OutFile = Join-Path (Get-Location).Path $OutFile
|
$OutFile = Join-Path (Get-Location).Path $OutFile
|
||||||
}
|
}
|
||||||
$utf8 = New-Object System.Text.UTF8Encoding($true)
|
$utf8 = New-Object System.Text.UTF8Encoding($true)
|
||||||
[System.IO.File]::WriteAllLines($OutFile, $lines, $utf8)
|
[System.IO.File]::WriteAllLines($OutFile, $lines, $utf8)
|
||||||
Write-Host "Output written to $OutFile"
|
Write-Host "Output written to $OutFile"
|
||||||
} else {
|
} else {
|
||||||
foreach ($l in $lines) { Write-Host $l }
|
foreach ($l in $lines) { Write-Host $l }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
---
|
---
|
||||||
name: role-validate
|
name: role-validate
|
||||||
description: Валидация роли 1С. Используй после создания или модификации роли для проверки корректности
|
description: Валидация роли 1С. Используй после создания или модификации роли для проверки корректности
|
||||||
argument-hint: <RightsPath> [-Detailed] [-MaxErrors 30]
|
argument-hint: <RightsPath> [-Detailed] [-MaxErrors 30]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
---
|
---
|
||||||
|
|
||||||
# /role-validate — валидация роли 1С
|
# /role-validate — валидация роли 1С
|
||||||
|
|
||||||
Проверяет корректность `Rights.xml` роли: формат XML, namespace, глобальные флаги, типы объектов, имена прав, RLS-ограничения, шаблоны. Опционально проверяет метаданные роли (UUID, имя, синоним).
|
Проверяет корректность `Rights.xml` роли: формат XML, namespace, глобальные флаги, типы объектов, имена прав, RLS-ограничения, шаблоны. Опционально проверяет метаданные роли (UUID, имя, синоним).
|
||||||
|
|
||||||
## Параметры
|
## Параметры
|
||||||
|
|
||||||
| Параметр | Обяз. | Умолч. | Описание |
|
| Параметр | Обяз. | Умолч. | Описание |
|
||||||
|--------------|:-----:|---------|-------------------------------------------------|
|
|--------------|:-----:|---------|-------------------------------------------------|
|
||||||
| RightsPath | да | — | Путь к роли (директория или `Rights.xml`) |
|
| RightsPath | да | — | Путь к роли (директория или `Rights.xml`) |
|
||||||
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
| Detailed | нет | — | Подробный вывод (все проверки, включая успешные) |
|
||||||
| MaxErrors | нет | 30 | Макс. ошибок до остановки (по умолчанию 30) |
|
| MaxErrors | нет | 30 | Макс. ошибок до остановки (по умолчанию 30) |
|
||||||
| OutFile | нет | — | Записать результат в файл (UTF-8 BOM) |
|
| OutFile | нет | — | Записать результат в файл (UTF-8 BOM) |
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-validate.ps1" -RightsPath "Roles/МояРоль"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-validate.ps1" -RightsPath "Roles/МояРоль"
|
||||||
```
|
```
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+436
-436
@@ -1,436 +1,436 @@
|
|||||||
---
|
---
|
||||||
name: skd-compile
|
name: skd-compile
|
||||||
description: Компиляция схемы компоновки данных 1С (СКД) из компактного JSON-определения. Используй когда нужно создать СКД с нуля
|
description: Компиляция схемы компоновки данных 1С (СКД) из компактного JSON-определения. Используй когда нужно создать СКД с нуля
|
||||||
argument-hint: "[-DefinitionFile <json> | -Value <json-string>] -OutputPath <Template.xml>"
|
argument-hint: "[-DefinitionFile <json> | -Value <json-string>] -OutputPath <Template.xml>"
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Write
|
- Write
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /skd-compile — генерация СКД из JSON DSL
|
# /skd-compile — генерация СКД из JSON DSL
|
||||||
|
|
||||||
Принимает JSON-определение схемы компоновки данных → генерирует Template.xml (DataCompositionSchema).
|
Принимает JSON-определение схемы компоновки данных → генерирует Template.xml (DataCompositionSchema).
|
||||||
|
|
||||||
## Параметры и команда
|
## Параметры и команда
|
||||||
|
|
||||||
| Параметр | Описание |
|
| Параметр | Описание |
|
||||||
|----------|----------|
|
|----------|----------|
|
||||||
| `DefinitionFile` | Путь к JSON-файлу с определением СКД (взаимоисключающий с Value) |
|
| `DefinitionFile` | Путь к JSON-файлу с определением СКД (взаимоисключающий с Value) |
|
||||||
| `Value` | JSON-строка с определением СКД (взаимоисключающий с DefinitionFile) |
|
| `Value` | JSON-строка с определением СКД (взаимоисключающий с DefinitionFile) |
|
||||||
| `OutputPath` | Путь к выходному Template.xml |
|
| `OutputPath` | Путь к выходному Template.xml |
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Из файла
|
# Из файла
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-compile.ps1" -DefinitionFile "<json>" -OutputPath "<Template.xml>"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-compile.ps1" -DefinitionFile "<json>" -OutputPath "<Template.xml>"
|
||||||
|
|
||||||
# Из строки (без промежуточного файла)
|
# Из строки (без промежуточного файла)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-compile.ps1" -Value '<json-string>' -OutputPath "<Template.xml>"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-compile.ps1" -Value '<json-string>' -OutputPath "<Template.xml>"
|
||||||
```
|
```
|
||||||
|
|
||||||
## JSON DSL — краткий справочник
|
## JSON DSL — краткий справочник
|
||||||
|
|
||||||
Справочник ниже. Все примеры компилируемы как есть.
|
Справочник ниже. Все примеры компилируемы как есть.
|
||||||
|
|
||||||
### Корневая структура
|
### Корневая структура
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"dataSets": [...],
|
"dataSets": [...],
|
||||||
"calculatedFields": [...],
|
"calculatedFields": [...],
|
||||||
"totalFields": [...],
|
"totalFields": [...],
|
||||||
"parameters": [...],
|
"parameters": [...],
|
||||||
"templates": [...],
|
"templates": [...],
|
||||||
"groupTemplates": [...],
|
"groupTemplates": [...],
|
||||||
"dataSetLinks": [...],
|
"dataSetLinks": [...],
|
||||||
"settingsVariants": [...]
|
"settingsVariants": [...]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Умолчания: `dataSources` → авто `ИсточникДанных1/Local`; `settingsVariants` → авто "Основной" с деталями.
|
Умолчания: `dataSources` → авто `ИсточникДанных1/Local`; `settingsVariants` → авто "Основной" с деталями.
|
||||||
|
|
||||||
### Наборы данных
|
### Наборы данных
|
||||||
|
|
||||||
Тип по ключу: `query` → DataSetQuery, `objectName` → DataSetObject, `items` → DataSetUnion.
|
Тип по ключу: `query` → DataSetQuery, `objectName` → DataSetObject, `items` → DataSetUnion.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "name": "Продажи", "query": "ВЫБРАТЬ ...", "fields": [...] }
|
{ "name": "Продажи", "query": "ВЫБРАТЬ ...", "fields": [...] }
|
||||||
```
|
```
|
||||||
|
|
||||||
Запрос поддерживает `@file` — ссылку на внешний .sql файл вместо inline-текста: `"query": "@queries/sales.sql"`. Путь разрешается относительно JSON-файла, затем CWD.
|
Запрос поддерживает `@file` — ссылку на внешний .sql файл вместо inline-текста: `"query": "@queries/sales.sql"`. Путь разрешается относительно JSON-файла, затем CWD.
|
||||||
|
|
||||||
**DataSetObject** — внешний набор данных (без источника-запроса). Поля описываются явно; данные передаются вторым параметром `ПроцессорКомпоновкиДанных.Инициализировать(Макет, Новый Структура("<objectName>", ТЗ), ...)`.
|
**DataSetObject** — внешний набор данных (без источника-запроса). Поля описываются явно; данные передаются вторым параметром `ПроцессорКомпоновкиДанных.Инициализировать(Макет, Новый Структура("<objectName>", ТЗ), ...)`.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "name": "ЖурналОшибок", "objectName": "ЖурналОшибок", "fields": [
|
{ "name": "ЖурналОшибок", "objectName": "ЖурналОшибок", "fields": [
|
||||||
{ "field": "ТекстСообщения", "title": "Текст сообщения", "type": "string(150)" },
|
{ "field": "ТекстСообщения", "title": "Текст сообщения", "type": "string(150)" },
|
||||||
{ "field": "Расшифровка", "title": "Описание", "type": "CatalogRef.СтруктураПредприятия" }
|
{ "field": "Расшифровка", "title": "Описание", "type": "CatalogRef.СтруктураПредприятия" }
|
||||||
]}
|
]}
|
||||||
```
|
```
|
||||||
|
|
||||||
`name` — имя набора в схеме, `objectName` — ключ в структуре передачи данных.
|
`name` — имя набора в схеме, `objectName` — ключ в структуре передачи данных.
|
||||||
|
|
||||||
### Поля — shorthand и объектная форма
|
### Поля — shorthand и объектная форма
|
||||||
|
|
||||||
```
|
```
|
||||||
"Наименование" — просто имя
|
"Наименование" — просто имя
|
||||||
"Количество: decimal(15,2)" — имя + тип
|
"Количество: decimal(15,2)" — имя + тип
|
||||||
"Организация: CatalogRef.Организации @dimension" — + роль
|
"Организация: CatalogRef.Организации @dimension" — + роль
|
||||||
"Служебное: string #noFilter #noOrder" — + ограничения
|
"Служебное: string #noFilter #noOrder" — + ограничения
|
||||||
```
|
```
|
||||||
|
|
||||||
Объектная форма — когда нужен title или другие свойства:
|
Объектная форма — когда нужен title или другие свойства:
|
||||||
```json
|
```json
|
||||||
{ "field": "ОстатокНаНачалоПериода", "title": "Остаток на начало периода" }
|
{ "field": "ОстатокНаНачалоПериода", "title": "Остаток на начало периода" }
|
||||||
```
|
```
|
||||||
`dataPath` автоматически берётся из `field`, если не указан явно.
|
`dataPath` автоматически берётся из `field`, если не указан явно.
|
||||||
|
|
||||||
Многоязычный заголовок: `"title": { "ru": "...", "en": "..." }`. Применимо везде, где принимается title/presentation (поля, calculatedFields, parameters, settingsVariants, availableValues и пр.). Строка эквивалентна `{ "ru": "..." }`.
|
Многоязычный заголовок: `"title": { "ru": "...", "en": "..." }`. Применимо везде, где принимается title/presentation (поля, calculatedFields, parameters, settingsVariants, availableValues и пр.). Строка эквивалентна `{ "ru": "..." }`.
|
||||||
|
|
||||||
Типы: `string`, `string(N)`, `decimal`, `decimal(D)`, `decimal(D,F)`, `boolean`, `date`, `dateTime`, `CatalogRef.X`, `DocumentRef.X`, `EnumRef.X`, `StandardPeriod`. Ссылочные типы эмитируются с inline namespace `d5p1:` (`http://v8.1c.ru/8.1/data/enterprise/current-config`). Сборка EPF со ссылочными типами требует базу с соответствующей конфигурацией.
|
Типы: `string`, `string(N)`, `decimal`, `decimal(D)`, `decimal(D,F)`, `boolean`, `date`, `dateTime`, `CatalogRef.X`, `DocumentRef.X`, `EnumRef.X`, `StandardPeriod`. Ссылочные типы эмитируются с inline namespace `d5p1:` (`http://v8.1c.ru/8.1/data/enterprise/current-config`). Сборка EPF со ссылочными типами требует базу с соответствующей конфигурацией.
|
||||||
|
|
||||||
`decimal` без скобок = `10,2` (деньги по умолчанию), `decimal(N)` = `N,0` (целое); `,nonneg` в конце скобок → AllowedSign=Nonnegative.
|
`decimal` без скобок = `10,2` (деньги по умолчанию), `decimal(N)` = `N,0` (целое); `,nonneg` в конце скобок → AllowedSign=Nonnegative.
|
||||||
|
|
||||||
Составной тип (несколько типов значений) — массив в объектной форме: `"type": ["CatalogRef.A", "CatalogRef.B"]`. Квалификаторы (`(N)`, `(D,F)`) применяются к каждому элементу.
|
Составной тип (несколько типов значений) — массив в объектной форме: `"type": ["CatalogRef.A", "CatalogRef.B"]`. Квалификаторы (`(N)`, `(D,F)`) применяются к каждому элементу.
|
||||||
|
|
||||||
Роли (shorthand или объект):
|
Роли (shorthand или объект):
|
||||||
|
|
||||||
- `@`-флаги: `@dimension`, `@account`, `@balance`, `@period`, `@required`, `@autoOrder`, `@ignoreNullValues`
|
- `@`-флаги: `@dimension`, `@account`, `@balance`, `@period`, `@required`, `@autoOrder`, `@ignoreNullValues`
|
||||||
- KV: `balanceGroupName`, `balanceType` (`OpeningBalance`/`ClosingBalance`), `parentDimension`, `accountTypeExpression`, `expression`, `orderType` (`Asc`/`Desc`), `periodNumber`, `periodType`
|
- KV: `balanceGroupName`, `balanceType` (`OpeningBalance`/`ClosingBalance`), `parentDimension`, `accountTypeExpression`, `expression`, `orderType` (`Asc`/`Desc`), `periodNumber`, `periodType`
|
||||||
|
|
||||||
```
|
```
|
||||||
"Сумма: decimal(15,2) @balance balanceGroupName=Сумма balanceType=OpeningBalance"
|
"Сумма: decimal(15,2) @balance balanceGroupName=Сумма balanceType=OpeningBalance"
|
||||||
```
|
```
|
||||||
|
|
||||||
Ограничения: `#noField`, `#noFilter`, `#noGroup`, `#noOrder`.
|
Ограничения: `#noField`, `#noFilter`, `#noGroup`, `#noOrder`.
|
||||||
|
|
||||||
В объектной форме: `"useRestriction": { "field": true, "condition": true, "group": true, "order": true }` или `"restrict": ["noField", "noFilter"]`.
|
В объектной форме: `"useRestriction": { "field": true, "condition": true, "group": true, "order": true }` или `"restrict": ["noField", "noFilter"]`.
|
||||||
|
|
||||||
Дополнительные ключи объектной формы:
|
Дополнительные ключи объектной формы:
|
||||||
- `"presentationExpression": "<выражение>"` — что показывать вместо значения поля. Исходное значение остаётся «под капотом» для перехода/расшифровки.
|
- `"presentationExpression": "<выражение>"` — что показывать вместо значения поля. Исходное значение остаётся «под капотом» для перехода/расшифровки.
|
||||||
- `"appearance": { "<параметр>": "<значение>" }` — оформление колонки по умолчанию (применяется во всех вариантах настроек). Ключи — параметры платформы (`ГоризонтальноеПоложение`, `МинимальнаяШирина`, `Формат`, `Текст` и т.п.).
|
- `"appearance": { "<параметр>": "<значение>" }` — оформление колонки по умолчанию (применяется во всех вариантах настроек). Ключи — параметры платформы (`ГоризонтальноеПоложение`, `МинимальнаяШирина`, `Формат`, `Текст` и т.п.).
|
||||||
- `"orderExpression": { "expression": "<выражение>", "orderType": "Asc"/"Desc", "autoOrder": true/false }` — сортировка поля по выражению (например `ЕстьNULL(Поле.Порядок, 10000)`).
|
- `"orderExpression": { "expression": "<выражение>", "orderType": "Asc"/"Desc", "autoOrder": true/false }` — сортировка поля по выражению (например `ЕстьNULL(Поле.Порядок, 10000)`).
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "field": "Сумма", "title": "Сумма продажи", "type": "decimal(15,2)",
|
{ "field": "Сумма", "title": "Сумма продажи", "type": "decimal(15,2)",
|
||||||
"appearance": { "ГоризонтальноеПоложение": "Right", "МинимальнаяШирина": "80" } }
|
"appearance": { "ГоризонтальноеПоложение": "Right", "МинимальнаяШирина": "80" } }
|
||||||
```
|
```
|
||||||
|
|
||||||
### Вычисляемые поля (calculatedFields)
|
### Вычисляемые поля (calculatedFields)
|
||||||
|
|
||||||
Shorthand: `"Имя [Заголовок]: тип = Выражение #noField #noFilter #noGroup #noOrder"` — все части кроме имени опциональны.
|
Shorthand: `"Имя [Заголовок]: тип = Выражение #noField #noFilter #noGroup #noOrder"` — все части кроме имени опциональны.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"calculatedFields": [
|
"calculatedFields": [
|
||||||
"Маржа = Цена - Закупка",
|
"Маржа = Цена - Закупка",
|
||||||
"Наценка [Наценка, %]: decimal(10,2) = Маржа / Закупка * 100",
|
"Наценка [Наценка, %]: decimal(10,2) = Маржа / Закупка * 100",
|
||||||
"Служебное: string = \"\" #noField #noFilter #noGroup #noOrder"
|
"Служебное: string = \"\" #noField #noFilter #noGroup #noOrder"
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Объектная форма — когда нужна `appearance`:
|
Объектная форма — когда нужна `appearance`:
|
||||||
```json
|
```json
|
||||||
{ "name": "Маржа", "title": "Маржа", "expression": "Цена - Закупка", "type": "decimal(15,2)", "useRestriction": "#noField #noFilter" }
|
{ "name": "Маржа", "title": "Маржа", "expression": "Цена - Закупка", "type": "decimal(15,2)", "useRestriction": "#noField #noFilter" }
|
||||||
```
|
```
|
||||||
|
|
||||||
### Итоги (shorthand)
|
### Итоги (shorthand)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"totalFields": ["Количество: Сумма", "Стоимость: Сумма(Кол * Цена)"]
|
"totalFields": ["Количество: Сумма", "Стоимость: Сумма(Кол * Цена)"]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры (shorthand + @autoDates)
|
### Параметры (shorthand + @autoDates)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"parameters": [
|
"parameters": [
|
||||||
"Период [Отчетный период]: StandardPeriod = LastMonth @autoDates"
|
"Период [Отчетный период]: StandardPeriod = LastMonth @autoDates"
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Shorthand: `"Имя [Заголовок]: тип = значение @флаги"`. `[Заголовок]` опциональный — добавляет `<title>` (LocalStringType).
|
Shorthand: `"Имя [Заголовок]: тип = значение @флаги"`. `[Заголовок]` опциональный — добавляет `<title>` (LocalStringType).
|
||||||
|
|
||||||
Флаги shorthand:
|
Флаги shorthand:
|
||||||
- `@autoDates` — добавляет к параметру StandardPeriod пару дат `НачалоПериода`/`КонецПериода`, вычисляемых из него. Используй их в тексте запроса как `&НачалоПериода`/`&КонецПериода`; пользователь выбирает только сам период. По умолчанию сам параметр получает `use=Always` и `denyIncompleteValues=true` (чтобы производные даты всегда были заполнены); в объектной форме можно явно переопределить.
|
- `@autoDates` — добавляет к параметру StandardPeriod пару дат `НачалоПериода`/`КонецПериода`, вычисляемых из него. Используй их в тексте запроса как `&НачалоПериода`/`&КонецПериода`; пользователь выбирает только сам период. По умолчанию сам параметр получает `use=Always` и `denyIncompleteValues=true` (чтобы производные даты всегда были заполнены); в объектной форме можно явно переопределить.
|
||||||
- `@valueList` — `<valueListAllowed>true</valueListAllowed>` — разрешает передавать список значений (при значении-списке ниже подразумевается автоматически)
|
- `@valueList` — `<valueListAllowed>true</valueListAllowed>` — разрешает передавать список значений (при значении-списке ниже подразумевается автоматически)
|
||||||
- `@hidden` — скрытый параметр: `availableAsField=false` + исключается из `"dataParameters": "auto"`
|
- `@hidden` — скрытый параметр: `availableAsField=false` + исключается из `"dataParameters": "auto"`
|
||||||
|
|
||||||
Объектная форма: `title`, `hidden: true`, `valueListAllowed: true`, `availableAsField: false`, `denyIncompleteValues: true`, `use: "Always"`.
|
Объектная форма: `title`, `hidden: true`, `valueListAllowed: true`, `availableAsField: false`, `denyIncompleteValues: true`, `use: "Always"`.
|
||||||
|
|
||||||
Значение-список: несколько значений по умолчанию через запятую в `значение` (для запятой внутри значения — кавычки `'...'`). В объектной форме — массив в `value`.
|
Значение-список: несколько значений по умолчанию через запятую в `значение` (для запятой внутри значения — кавычки `'...'`). В объектной форме — массив в `value`.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"parameters": [
|
"parameters": [
|
||||||
"Виды: ChartOfCharacteristicTypesRef.ВидыСубконтоХозрасчетные = ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты, ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Договоры"
|
"Виды: ChartOfCharacteristicTypesRef.ВидыСубконтоХозрасчетные = ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты, ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Договоры"
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Если значения по умолчанию нет — пропусти `=` в shorthand или укажи `"value": null` в объектной форме.
|
Если значения по умолчанию нет — пропусти `=` в shorthand или укажи `"value": null` в объектной форме.
|
||||||
|
|
||||||
Список допустимых значений (availableValues):
|
Список допустимых значений (availableValues):
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "ПорядокОкругления",
|
"name": "ПорядокОкругления",
|
||||||
"type": "EnumRef.Округления",
|
"type": "EnumRef.Округления",
|
||||||
"value": "Перечисление.Округления.Окр1_00",
|
"value": "Перечисление.Округления.Окр1_00",
|
||||||
"use": "Always",
|
"use": "Always",
|
||||||
"denyIncompleteValues": true,
|
"denyIncompleteValues": true,
|
||||||
"availableValues": [
|
"availableValues": [
|
||||||
{"value": "Перечисление.Округления.Окр1_00", "presentation": "руб. коп"},
|
{"value": "Перечисление.Округления.Окр1_00", "presentation": "руб. коп"},
|
||||||
{"value": "Перечисление.Округления.Окр1", "presentation": "руб."},
|
{"value": "Перечисление.Округления.Окр1", "presentation": "руб."},
|
||||||
{"value": "Перечисление.Округления.Окр1000", "presentation": "тыс. руб"}
|
{"value": "Перечисление.Округления.Окр1000", "presentation": "тыс. руб"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
В варианте настроек `"dataParameters": "auto"` выводит все не-hidden параметры с `userSettingID`. Значения по умолчанию наследуются и остаются активными; параметры без значения по умолчанию отключаются (пользователь включит их в настройках).
|
В варианте настроек `"dataParameters": "auto"` выводит все не-hidden параметры с `userSettingID`. Значения по умолчанию наследуются и остаются активными; параметры без значения по умолчанию отключаются (пользователь включит их в настройках).
|
||||||
|
|
||||||
### Фильтры — shorthand
|
### Фильтры — shorthand
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"filter": [
|
"filter": [
|
||||||
"Организация = _ @off @user",
|
"Организация = _ @off @user",
|
||||||
"Дата >= 2024-01-01T00:00:00",
|
"Дата >= 2024-01-01T00:00:00",
|
||||||
"Статус filled"
|
"Статус filled"
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Формат: `"Поле оператор значение @флаги"`. Значение `_` = пустое (placeholder). Флаги: `@off` (use=false), `@user` (userSettingID=auto), `@quickAccess`, `@normal`, `@inaccessible`.
|
Формат: `"Поле оператор значение @флаги"`. Значение `_` = пустое (placeholder). Флаги: `@off` (use=false), `@user` (userSettingID=auto), `@quickAccess`, `@normal`, `@inaccessible`.
|
||||||
|
|
||||||
В объектной форме доступны: `viewMode`, `userSettingID`, `userSettingPresentation`.
|
В объектной форме доступны: `viewMode`, `userSettingID`, `userSettingPresentation`.
|
||||||
|
|
||||||
Группы фильтров (Or/And/Not):
|
Группы фильтров (Or/And/Not):
|
||||||
```json
|
```json
|
||||||
{ "group": "Or", "items": [
|
{ "group": "Or", "items": [
|
||||||
{ "group": "And", "items": [
|
{ "group": "And", "items": [
|
||||||
{ "field": "Статус", "op": "=", "value": "Активен" },
|
{ "field": "Статус", "op": "=", "value": "Активен" },
|
||||||
{ "field": "Сумма", "op": ">", "value": 1000 }
|
{ "field": "Сумма", "op": ">", "value": 1000 }
|
||||||
]},
|
]},
|
||||||
{ "field": "Количество", "op": "filled" }
|
{ "field": "Количество", "op": "filled" }
|
||||||
]}
|
]}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры данных — shorthand
|
### Параметры данных — shorthand
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"dataParameters": [
|
"dataParameters": [
|
||||||
"Период = LastMonth @user",
|
"Период = LastMonth @user",
|
||||||
"Организация @off @user"
|
"Организация @off @user"
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Формат: `"Имя [= значение] @флаги"`. Для StandardPeriod варианты (LastMonth, ThisYear и т.д.) распознаются автоматически.
|
Формат: `"Имя [= значение] @флаги"`. Для StandardPeriod варианты (LastMonth, ThisYear и т.д.) распознаются автоматически.
|
||||||
|
|
||||||
### Структура — string shorthand
|
### Структура — string shorthand
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"structure": "Организация > details"
|
"structure": "Организация > details"
|
||||||
"structure": "Организация > Номенклатура > details"
|
"structure": "Организация > Номенклатура > details"
|
||||||
```
|
```
|
||||||
|
|
||||||
`>` разделяет уровни группировки. `details` (или `детали`) = детальные записи. `selection` и `order` по умолчанию `["Auto"]` на каждом уровне.
|
`>` разделяет уровни группировки. `details` (или `детали`) = детальные записи. `selection` и `order` по умолчанию `["Auto"]` на каждом уровне.
|
||||||
|
|
||||||
Объектная форма — для сложных случаев (именованные группировки, selection/filter на уровне группировки, таблицы, диаграммы):
|
Объектная форма — для сложных случаев (именованные группировки, selection/filter на уровне группировки, таблицы, диаграммы):
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"structure": [
|
"structure": [
|
||||||
{
|
{
|
||||||
"name": "ПоОрганизациям",
|
"name": "ПоОрганизациям",
|
||||||
"groupFields": ["Организация"],
|
"groupFields": ["Организация"],
|
||||||
"selection": ["Организация", "Сумма", "Auto"],
|
"selection": ["Организация", "Сумма", "Auto"],
|
||||||
"children": [{ "groupFields": [] }]
|
"children": [{ "groupFields": [] }]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
`type` по умолчанию `"group"` (можно не указывать). `groupFields` — алиас для `groupBy`. Поддержка `name`, `selection`, `order`, `filter`, `outputParameters`, рекурсивных `children`.
|
`type` по умолчанию `"group"` (можно не указывать). `groupFields` — алиас для `groupBy`. Поддержка `name`, `selection`, `order`, `filter`, `outputParameters`, рекурсивных `children`.
|
||||||
|
|
||||||
### Варианты настроек
|
### Варианты настроек
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"settingsVariants": [{
|
"settingsVariants": [{
|
||||||
"name": "Основной",
|
"name": "Основной",
|
||||||
"title": "Продажи по организациям",
|
"title": "Продажи по организациям",
|
||||||
"settings": {
|
"settings": {
|
||||||
"selection": ["Номенклатура", "Количество", "Auto"],
|
"selection": ["Номенклатура", "Количество", "Auto"],
|
||||||
"filter": ["Организация = _ @off @user"],
|
"filter": ["Организация = _ @off @user"],
|
||||||
"order": ["Количество desc", "Auto"],
|
"order": ["Количество desc", "Auto"],
|
||||||
"conditionalAppearance": [
|
"conditionalAppearance": [
|
||||||
{
|
{
|
||||||
"filter": ["Просрочено = true"],
|
"filter": ["Просрочено = true"],
|
||||||
"appearance": { "ЦветТекста": "style:ПросроченныеДанныеЦвет" },
|
"appearance": { "ЦветТекста": "style:ПросроченныеДанныеЦвет" },
|
||||||
"presentation": "Выделять просроченные",
|
"presentation": "Выделять просроченные",
|
||||||
"viewMode": "Normal",
|
"viewMode": "Normal",
|
||||||
"userSettingID": "auto"
|
"userSettingID": "auto"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"outputParameters": { "Заголовок": "Мой отчёт" },
|
"outputParameters": { "Заголовок": "Мой отчёт" },
|
||||||
"dataParameters": ["Период = LastMonth @user"],
|
"dataParameters": ["Период = LastMonth @user"],
|
||||||
"structure": "Организация > details"
|
"structure": "Организация > details"
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Условное оформление (conditionalAppearance)
|
### Условное оформление (conditionalAppearance)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"conditionalAppearance": [
|
"conditionalAppearance": [
|
||||||
{
|
{
|
||||||
"selection": ["Поле1"],
|
"selection": ["Поле1"],
|
||||||
"filter": ["Поле1 notFilled"],
|
"filter": ["Поле1 notFilled"],
|
||||||
"appearance": { "Текст": "Не указано", "ЦветТекста": "style:XXX" },
|
"appearance": { "Текст": "Не указано", "ЦветТекста": "style:XXX" },
|
||||||
"presentation": "Описание",
|
"presentation": "Описание",
|
||||||
"viewMode": "Normal",
|
"viewMode": "Normal",
|
||||||
"userSettingID": "auto"
|
"userSettingID": "auto"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Типы значений appearance: `style:XXX`/`web:XXX`/`win:XXX` → Color, `true`/`false` → Boolean, параметр `Формат`/`Текст`/`Заголовок` → LocalStringType, прочее → String.
|
Типы значений appearance: `style:XXX`/`web:XXX`/`win:XXX` → Color, `true`/`false` → Boolean, параметр `Формат`/`Текст`/`Заголовок` → LocalStringType, прочее → String.
|
||||||
|
|
||||||
Типы значений фильтра: `Перечисление.*`/`Справочник.*`/`ПланСчетов.*`/`Документ.*` → DesignTimeValue (автодетект).
|
Типы значений фильтра: `Перечисление.*`/`Справочник.*`/`ПланСчетов.*`/`Документ.*` → DesignTimeValue (автодетект).
|
||||||
|
|
||||||
OrGroup в фильтре: `{"group": "Or", "items": ["условие1", "условие2"]}`.
|
OrGroup в фильтре: `{"group": "Or", "items": ["условие1", "условие2"]}`.
|
||||||
|
|
||||||
Folder в selection: `{"folder": "Поступление", "items": ["ПолеА", "ПолеБ"]}` → SelectedItemFolder с lwsTitle и placement=Auto.
|
Folder в selection: `{"folder": "Поступление", "items": ["ПолеА", "ПолеБ"]}` → SelectedItemFolder с lwsTitle и placement=Auto.
|
||||||
|
|
||||||
### Итоги с привязкой к группировкам
|
### Итоги с привязкой к группировкам
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"totalFields": [
|
"totalFields": [
|
||||||
{ "dataPath": "Кол", "expression": "Сумма(Кол)", "group": ["Группа1", "Группа1 Иерархия", "ОбщийИтог"] }
|
{ "dataPath": "Кол", "expression": "Сумма(Кол)", "group": ["Группа1", "Группа1 Иерархия", "ОбщийИтог"] }
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Шаблоны вывода — компактный DSL
|
### Шаблоны вывода — компактный DSL
|
||||||
|
|
||||||
Вместо raw XML (`template`) — табличное описание через `rows` + именованный стиль `style`:
|
Вместо raw XML (`template`) — табличное описание через `rows` + именованный стиль `style`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"templates": [
|
"templates": [
|
||||||
{
|
{
|
||||||
"name": "Макет1",
|
"name": "Макет1",
|
||||||
"style": "header",
|
"style": "header",
|
||||||
"widths": [36, 33, 16, 17],
|
"widths": [36, 33, 16, 17],
|
||||||
"minHeight": 24.75,
|
"minHeight": 24.75,
|
||||||
"rows": [
|
"rows": [
|
||||||
["Виды кассы", "Валюта", "Остаток на начало\nпериода", "Остаток на\nконец периода"],
|
["Виды кассы", "Валюта", "Остаток на начало\nпериода", "Остаток на\nконец периода"],
|
||||||
["|", "|", "|", "|"],
|
["|", "|", "|", "|"],
|
||||||
["К1", "К2", "К3", "К4"]
|
["К1", "К2", "К3", "К4"]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Макет2",
|
"name": "Макет2",
|
||||||
"style": "data",
|
"style": "data",
|
||||||
"widths": [36, 33, 16, 17],
|
"widths": [36, 33, 16, 17],
|
||||||
"rows": [["{ВидКассы}", "{Валюта}", "{Остаток}", "{ОстатокКонец}"]],
|
"rows": [["{ВидКассы}", "{Валюта}", "{Остаток}", "{ОстатокКонец}"]],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{ "name": "ВидКассы", "expression": "Представление(Счет)" },
|
{ "name": "ВидКассы", "expression": "Представление(Счет)" },
|
||||||
{ "name": "Остаток", "expression": "ОстатокНаНачалоПериода" }
|
{ "name": "Остаток", "expression": "ОстатокНаНачалоПериода" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Синтаксис ячеек: `"текст"` — статика, `"{Имя}"` — параметр, `"|"` — объединение с ячейкой выше, `">"` — объединение с ячейкой слева, `null` — пустая.
|
Синтаксис ячеек: `"текст"` — статика, `"{Имя}"` — параметр, `"|"` — объединение с ячейкой выше, `">"` — объединение с ячейкой слева, `null` — пустая.
|
||||||
|
|
||||||
Двухуровневая шапка с горизонтальным объединением:
|
Двухуровневая шапка с горизонтальным объединением:
|
||||||
```json
|
```json
|
||||||
"rows": [
|
"rows": [
|
||||||
["Вид актива", "Остаток начало", "Поступление", ">", ">", ">", "Выбытие", ">", ">", "Остаток конец"],
|
["Вид актива", "Остаток начало", "Поступление", ">", ">", ">", "Выбытие", ">", ">", "Остаток конец"],
|
||||||
["|", "|", "из произв.", "из п/ф", "со сч.40", "прочее", "Реализ.", "отгруж.", "прочее", "|"],
|
["|", "|", "из произв.", "из п/ф", "со сч.40", "прочее", "Реализ.", "отгруж.", "прочее", "|"],
|
||||||
["К1", "К2", "К3", "К4", "К5", "К6", "К7", "К8", "К9", "К10"]
|
["К1", "К2", "К3", "К4", "К5", "К6", "К7", "К8", "К9", "К10"]
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Встроенные стили: `header` (фон, центр, перенос), `data` (фон группы), `subheader` (без фона, центр), `total` (без фона). Все — Arial 10, рамки Solid 1px, цвета через стили платформы.
|
Встроенные стили: `header` (фон, центр, перенос), `data` (фон группы), `subheader` (без фона, центр), `total` (без фона). Все — Arial 10, рамки Solid 1px, цвета через стили платформы.
|
||||||
|
|
||||||
Пользовательские стили: файл `skd-styles.json` рядом с JSON-определением, в текущей директории, или в `presets/skills/skd/skd-styles.json` (поиск вверх от OutputPath). Первый найденный файл побеждает. Все допустимые ключи и формат цветов — в `examples/skd-styles.json`.
|
Пользовательские стили: файл `skd-styles.json` рядом с JSON-определением, в текущей директории, или в `presets/skills/skd/skd-styles.json` (поиск вверх от OutputPath). Первый найденный файл побеждает. Все допустимые ключи и формат цветов — в `examples/skd-styles.json`.
|
||||||
|
|
||||||
Raw XML (`"template": "<...>"`) остаётся как fallback. Детект: если есть `rows` — DSL, иначе — raw.
|
Raw XML (`"template": "<...>"`) остаётся как fallback. Детект: если есть `rows` — DSL, иначе — raw.
|
||||||
|
|
||||||
### Расшифровка (drilldown) в параметрах шаблона
|
### Расшифровка (drilldown) в параметрах шаблона
|
||||||
|
|
||||||
Ключ `drilldown` в параметре шаблона автоматически генерирует `DetailsAreaTemplateParameter` и привязку `Расшифровка` в appearance ячеек:
|
Ключ `drilldown` в параметре шаблона автоматически генерирует `DetailsAreaTemplateParameter` и привязку `Расшифровка` в appearance ячеек:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{ "name": "Сырье", "expression": "ПоступлениеСырья", "drilldown": "ПоступлениеСырья" }
|
{ "name": "Сырье", "expression": "ПоступлениеСырья", "drilldown": "ПоступлениеСырья" }
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Генерирует: `ExpressionAreaTemplateParameter` (обычный) + `DetailsAreaTemplateParameter` с именем `Расшифровка_ПоступлениеСырья`, `fieldExpression` по полю `ИмяРесурса`, `mainAction=DrillDown`. Ячейки `{Сырье}` автоматически получают appearance `Расшифровка = Расшифровка_ПоступлениеСырья`.
|
Генерирует: `ExpressionAreaTemplateParameter` (обычный) + `DetailsAreaTemplateParameter` с именем `Расшифровка_ПоступлениеСырья`, `fieldExpression` по полю `ИмяРесурса`, `mainAction=DrillDown`. Ячейки `{Сырье}` автоматически получают appearance `Расшифровка = Расшифровка_ПоступлениеСырья`.
|
||||||
|
|
||||||
### Привязки макетов к группировкам
|
### Привязки макетов к группировкам
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"groupTemplates": [
|
"groupTemplates": [
|
||||||
{ "groupName": "ДанныеОтчета", "templateType": "GroupHeader", "template": "Макет1" },
|
{ "groupName": "ДанныеОтчета", "templateType": "GroupHeader", "template": "Макет1" },
|
||||||
{ "groupField": "Счет", "templateType": "Header", "template": "Макет2" },
|
{ "groupField": "Счет", "templateType": "Header", "template": "Макет2" },
|
||||||
{ "groupField": "Счет", "templateType": "OverallHeader", "template": "Макет3" }
|
{ "groupField": "Счет", "templateType": "OverallHeader", "template": "Макет3" }
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
`groupField` — привязка к полю группировки, `groupName` — к именованной группировке в структуре варианта.
|
`groupField` — привязка к полю группировки, `groupName` — к именованной группировке в структуре варианта.
|
||||||
|
|
||||||
`templateType`: `Header` (строки данных) → `<groupTemplate>`, `OverallHeader` (итоги) → `<groupTemplate>`, `GroupHeader` (шапка) → `<groupHeaderTemplate>`.
|
`templateType`: `Header` (строки данных) → `<groupTemplate>`, `OverallHeader` (итоги) → `<groupTemplate>`, `GroupHeader` (шапка) → `<groupHeaderTemplate>`.
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
### Минимальный
|
### Минимальный
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"dataSets": [{
|
"dataSets": [{
|
||||||
"query": "ВЫБРАТЬ Номенклатура.Наименование КАК Наименование ИЗ Справочник.Номенклатура КАК Номенклатура",
|
"query": "ВЫБРАТЬ Номенклатура.Наименование КАК Наименование ИЗ Справочник.Номенклатура КАК Номенклатура",
|
||||||
"fields": ["Наименование"]
|
"fields": ["Наименование"]
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### С запросом из внешнего файла (@file)
|
### С запросом из внешнего файла (@file)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"dataSets": [{
|
"dataSets": [{
|
||||||
"query": "@queries/sales.sql",
|
"query": "@queries/sales.sql",
|
||||||
"fields": ["Номенклатура: СправочникСсылка.Номенклатура @dimension", "Количество: число(15,3)", "Сумма: число(15,2)"]
|
"fields": ["Номенклатура: СправочникСсылка.Номенклатура @dimension", "Количество: число(15,3)", "Сумма: число(15,2)"]
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### С ресурсами, параметрами и @autoDates
|
### С ресурсами, параметрами и @autoDates
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"dataSets": [{
|
"dataSets": [{
|
||||||
"query": "ВЫБРАТЬ Продажи.Организация, Продажи.Номенклатура, Продажи.КоличествоОборот КАК Количество, Продажи.СуммаОборот КАК Сумма ИЗ РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода) КАК Продажи",
|
"query": "ВЫБРАТЬ Продажи.Организация, Продажи.Номенклатура, Продажи.КоличествоОборот КАК Количество, Продажи.СуммаОборот КАК Сумма ИЗ РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода) КАК Продажи",
|
||||||
"fields": [
|
"fields": [
|
||||||
"Организация: СправочникСсылка.Организации @dimension",
|
"Организация: СправочникСсылка.Организации @dimension",
|
||||||
"Номенклатура: СправочникСсылка.Номенклатура @dimension",
|
"Номенклатура: СправочникСсылка.Номенклатура @dimension",
|
||||||
"Количество: число(15,3)",
|
"Количество: число(15,3)",
|
||||||
"Сумма: число(15,2)"
|
"Сумма: число(15,2)"
|
||||||
]
|
]
|
||||||
}],
|
}],
|
||||||
"totalFields": ["Количество: Сумма", "Сумма: Сумма"],
|
"totalFields": ["Количество: Сумма", "Сумма: Сумма"],
|
||||||
"parameters": ["Период: СтандартныйПериод = LastMonth @autoDates"],
|
"parameters": ["Период: СтандартныйПериод = LastMonth @autoDates"],
|
||||||
"settingsVariants": [{
|
"settingsVariants": [{
|
||||||
"name": "Основной",
|
"name": "Основной",
|
||||||
"settings": {
|
"settings": {
|
||||||
"selection": ["Организация", "Номенклатура", "Количество", "Сумма"],
|
"selection": ["Организация", "Номенклатура", "Количество", "Сумма"],
|
||||||
"filter": ["Организация = _ @off @user"],
|
"filter": ["Организация = _ @off @user"],
|
||||||
"dataParameters": "auto",
|
"dataParameters": "auto",
|
||||||
"structure": "Организация > details"
|
"structure": "Организация > details"
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Верификация
|
## Верификация
|
||||||
|
|
||||||
```
|
```
|
||||||
/skd-validate <OutputPath> — валидация структуры XML
|
/skd-validate <OutputPath> — валидация структуры XML
|
||||||
/skd-info <OutputPath> — визуальная сводка
|
/skd-info <OutputPath> — визуальная сводка
|
||||||
/skd-info <OutputPath> -Mode variant -Name 1 — проверка варианта настроек
|
/skd-info <OutputPath> -Mode variant -Name 1 — проверка варианта настроек
|
||||||
```
|
```
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+373
-373
@@ -1,373 +1,373 @@
|
|||||||
---
|
---
|
||||||
name: skd-edit
|
name: skd-edit
|
||||||
description: Точечное редактирование схемы компоновки данных 1С (СКД). Используй когда нужно модифицировать существующую СКД — добавить поля, итоги, фильтры, параметры, изменить текст запроса
|
description: Точечное редактирование схемы компоновки данных 1С (СКД). Используй когда нужно модифицировать существующую СКД — добавить поля, итоги, фильтры, параметры, изменить текст запроса
|
||||||
argument-hint: <TemplatePath> -Operation <op> -Value <value>
|
argument-hint: <TemplatePath> -Operation <op> -Value <value>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
- Write
|
- Write
|
||||||
- Glob
|
- Glob
|
||||||
---
|
---
|
||||||
|
|
||||||
# /skd-edit — точечное редактирование СКД (Template.xml)
|
# /skd-edit — точечное редактирование СКД (Template.xml)
|
||||||
|
|
||||||
Атомарные операции модификации существующей схемы компоновки данных: добавление, удаление и модификация полей, итогов, фильтров, параметров, настроек варианта, управление структурой, замена запроса.
|
Атомарные операции модификации существующей схемы компоновки данных: добавление, удаление и модификация полей, итогов, фильтров, параметров, настроек варианта, управление структурой, замена запроса.
|
||||||
|
|
||||||
## Параметры и команда
|
## Параметры и команда
|
||||||
|
|
||||||
| Параметр | Описание |
|
| Параметр | Описание |
|
||||||
|----------|----------|
|
|----------|----------|
|
||||||
| `TemplatePath` | Путь к Template.xml (или к папке — автодополнение Ext/Template.xml) |
|
| `TemplatePath` | Путь к Template.xml (или к папке — автодополнение Ext/Template.xml) |
|
||||||
| `Operation` | Операция (см. список ниже) |
|
| `Operation` | Операция (см. список ниже) |
|
||||||
| `Value` | Значение операции (shorthand-строка или текст запроса) |
|
| `Value` | Значение операции (shorthand-строка или текст запроса) |
|
||||||
| `DataSet` | (опц.) Имя набора данных (умолч. первый) |
|
| `DataSet` | (опц.) Имя набора данных (умолч. первый) |
|
||||||
| `Variant` | (опц.) Имя варианта настроек (умолч. первый) |
|
| `Variant` | (опц.) Имя варианта настроек (умолч. первый) |
|
||||||
| `NoSelection` | (опц.) Не добавлять поле в selection варианта |
|
| `NoSelection` | (опц.) Не добавлять поле в selection варианта |
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-edit.ps1" -TemplatePath "<path>" -Operation <op> -Value "<value>"
|
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-edit.ps1" -TemplatePath "<path>" -Operation <op> -Value "<value>"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Пакетный режим (batch)
|
## Пакетный режим (batch)
|
||||||
|
|
||||||
Несколько значений в одном вызове через разделитель `;;`:
|
Несколько значений в одном вызове через разделитель `;;`:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
-Operation add-field -Value "Цена: decimal(15,2) ;; Количество: decimal(15,3) ;; Сумма: decimal(15,2)"
|
-Operation add-field -Value "Цена: decimal(15,2) ;; Количество: decimal(15,3) ;; Сумма: decimal(15,2)"
|
||||||
```
|
```
|
||||||
|
|
||||||
Работает для всех операций кроме `set-query`, `set-structure` и `add-dataSet`.
|
Работает для всех операций кроме `set-query`, `set-structure` и `add-dataSet`.
|
||||||
|
|
||||||
## Операции
|
## Операции
|
||||||
|
|
||||||
### add-field — добавить поле в набор данных
|
### add-field — добавить поле в набор данных
|
||||||
|
|
||||||
Shorthand: `"Имя [Заголовок]: тип @роль #ограничение"`.
|
Shorthand: `"Имя [Заголовок]: тип @роль #ограничение"`.
|
||||||
|
|
||||||
```
|
```
|
||||||
"Цена: decimal(15,2)"
|
"Цена: decimal(15,2)"
|
||||||
"Организация [Орг-ция]: CatalogRef.Организации @dimension"
|
"Организация [Орг-ция]: CatalogRef.Организации @dimension"
|
||||||
"Служебное: string #noFilter #noOrder"
|
"Служебное: string #noFilter #noOrder"
|
||||||
```
|
```
|
||||||
|
|
||||||
Поле добавляется в набор и в selection варианта (если нет `-NoSelection`). Дубликат dataPath — предупреждение, пропуск.
|
Поле добавляется в набор и в selection варианта (если нет `-NoSelection`). Дубликат dataPath — предупреждение, пропуск.
|
||||||
|
|
||||||
Чтобы поле попало в selection не варианта, а конкретной группировки структуры — используй `-NoSelection` и затем `add-selection "Имя @group=ИмяГруппы"`.
|
Чтобы поле попало в selection не варианта, а конкретной группировки структуры — используй `-NoSelection` и затем `add-selection "Имя @group=ИмяГруппы"`.
|
||||||
|
|
||||||
### add-total — добавить итог
|
### add-total — добавить итог
|
||||||
|
|
||||||
Shorthand: `"<dataPath>: <выражение>"`. Если выражение — известная аггрегатная функция без скобок (`Сумма`, `Количество`, `Минимум`, `Максимум`, `Среднее`), оно автоматически оборачивается в `Func(dataPath)`. Если функция со скобками или произвольное выражение — используется как есть.
|
Shorthand: `"<dataPath>: <выражение>"`. Если выражение — известная аггрегатная функция без скобок (`Сумма`, `Количество`, `Минимум`, `Максимум`, `Среднее`), оно автоматически оборачивается в `Func(dataPath)`. Если функция со скобками или произвольное выражение — используется как есть.
|
||||||
|
|
||||||
```
|
```
|
||||||
"Цена: Среднее" # → Среднее(Цена)
|
"Цена: Среднее" # → Среднее(Цена)
|
||||||
"Стоимость: Сумма(Кол * Цена)" # → как есть
|
"Стоимость: Сумма(Кол * Цена)" # → как есть
|
||||||
"Проверка: Проверка" # identity: выражение = Проверка
|
"Проверка: Проверка" # identity: выражение = Проверка
|
||||||
```
|
```
|
||||||
|
|
||||||
### add-calculated-field — добавить вычисляемое поле
|
### add-calculated-field — добавить вычисляемое поле
|
||||||
|
|
||||||
Shorthand: `"Имя [Заголовок]: тип = Выражение #noFilter #noOrder #noGroup"`.
|
Shorthand: `"Имя [Заголовок]: тип = Выражение #noFilter #noOrder #noGroup"`.
|
||||||
|
|
||||||
```
|
```
|
||||||
"Маржа = Продажа - Закупка"
|
"Маржа = Продажа - Закупка"
|
||||||
"Наценка [Наценка, %]: decimal(10,2) = Маржа / Закупка * 100"
|
"Наценка [Наценка, %]: decimal(10,2) = Маржа / Закупка * 100"
|
||||||
"Служебное: string = \"\" #noFilter #noOrder #noGroup"
|
"Служебное: string = \"\" #noFilter #noOrder #noGroup"
|
||||||
```
|
```
|
||||||
|
|
||||||
`#noFilter`, `#noOrder`, `#noGroup`, `#noField` → `<useRestriction>` (аналогично add-field).
|
`#noFilter`, `#noOrder`, `#noGroup`, `#noField` → `<useRestriction>` (аналогично add-field).
|
||||||
|
|
||||||
Также добавляется в selection варианта.
|
Также добавляется в selection варианта.
|
||||||
|
|
||||||
### add-parameter — добавить параметр
|
### add-parameter — добавить параметр
|
||||||
|
|
||||||
```
|
```
|
||||||
"Период [Отчетный период]: StandardPeriod = LastMonth @autoDates"
|
"Период [Отчетный период]: StandardPeriod = LastMonth @autoDates"
|
||||||
"Организация: CatalogRef.Организации"
|
"Организация: CatalogRef.Организации"
|
||||||
```
|
```
|
||||||
|
|
||||||
Shorthand: `"Имя [Заголовок]: тип = значение [availableValue=список] [@флаги]"`. `[Заголовок]` опциональный — добавляет `<title>`.
|
Shorthand: `"Имя [Заголовок]: тип = значение [availableValue=список] [@флаги]"`. `[Заголовок]` опциональный — добавляет `<title>`.
|
||||||
|
|
||||||
Флаги:
|
Флаги:
|
||||||
- `@autoDates` — генерирует пару скрытых параметров `ДатаНачала`/`ДатаОкончания` для StandardPeriod-параметра.
|
- `@autoDates` — генерирует пару скрытых параметров `ДатаНачала`/`ДатаОкончания` для StandardPeriod-параметра.
|
||||||
- `@hidden` — скрывает параметр от пользовательских настроек (для параметров-констант, используемых в запросе).
|
- `@hidden` — скрывает параметр от пользовательских настроек (для параметров-констант, используемых в запросе).
|
||||||
- `@always` — параметр всегда подставляется в запрос. Часто вместе с `@hidden`, но используется и отдельно (для видимых обязательных параметров типа отчётного периода).
|
- `@always` — параметр всегда подставляется в запрос. Часто вместе с `@hidden`, но используется и отдельно (для видимых обязательных параметров типа отчётного периода).
|
||||||
- `@valueList` — разрешает передавать в параметр список значений (при значении-списке ниже подразумевается автоматически, отдельно указывать не обязательно).
|
- `@valueList` — разрешает передавать в параметр список значений (при значении-списке ниже подразумевается автоматически, отдельно указывать не обязательно).
|
||||||
|
|
||||||
Значение-список: несколько значений по умолчанию задаются через запятую в `значение`. Для запятой внутри одного значения — кавычки `'...'`.
|
Значение-список: несколько значений по умолчанию задаются через запятую в `значение`. Для запятой внутри одного значения — кавычки `'...'`.
|
||||||
|
|
||||||
```
|
```
|
||||||
"Виды [Виды субконто]: ChartOfCharacteristicTypesRef.ВидыСубконтоХозрасчетные = ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты, ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Договоры"
|
"Виды [Виды субконто]: ChartOfCharacteristicTypesRef.ВидыСубконтоХозрасчетные = ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты, ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Договоры"
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
"ПС: CatalogRef.Контрагенты = Справочник.Контрагенты.ПустаяСсылка @hidden"
|
"ПС: CatalogRef.Контрагенты = Справочник.Контрагенты.ПустаяСсылка @hidden"
|
||||||
"Период: StandardPeriod = LastMonth @always"
|
"Период: StandardPeriod = LastMonth @always"
|
||||||
"ПСчет: ChartOfAccountsRef.Хозрасчетный = ПланСчетов.Хозрасчетный.X @hidden @always"
|
"ПСчет: ChartOfAccountsRef.Хозрасчетный = ПланСчетов.Хозрасчетный.X @hidden @always"
|
||||||
"Округление: EnumRef.Округления = Окр1 availableValue=Перечисление.Округления.Окр1: руб., Перечисление.Округления.Окр1000: тыс."
|
"Округление: EnumRef.Округления = Окр1 availableValue=Перечисление.Округления.Окр1: руб., Перечисление.Округления.Окр1000: тыс."
|
||||||
```
|
```
|
||||||
|
|
||||||
`availableValue=` задаёт начальный список допустимых значений. Формат списка: `v1[: p1], v2[: p2], ...` — элементы через `,`, представление после `:`. Если в значении или представлении встречается `,` или `:` — оборачивай в одинарные кавычки `'...'`:
|
`availableValue=` задаёт начальный список допустимых значений. Формат списка: `v1[: p1], v2[: p2], ...` — элементы через `,`, представление после `:`. Если в значении или представлении встречается `,` или `:` — оборачивай в одинарные кавычки `'...'`:
|
||||||
|
|
||||||
```
|
```
|
||||||
"Округление: ... = Окр1 availableValue=Окр1_00: 'руб., коп.', Окр1: руб."
|
"Округление: ... = Окр1 availableValue=Окр1_00: 'руб., коп.', Окр1: руб."
|
||||||
```
|
```
|
||||||
|
|
||||||
### modify-parameter — изменить существующий параметр
|
### modify-parameter — изменить существующий параметр
|
||||||
|
|
||||||
Shorthand: `"ИмяПараметра [Заголовок] [ключ=значение]... [@флаги]"`. Находит параметр по имени, обновляет указанные свойства.
|
Shorthand: `"ИмяПараметра [Заголовок] [ключ=значение]... [@флаги]"`. Находит параметр по имени, обновляет указанные свойства.
|
||||||
|
|
||||||
```
|
```
|
||||||
"ПорядокОкругления use=Always"
|
"ПорядокОкругления use=Always"
|
||||||
"ПорядокОкругления [Округление сумм] denyIncompleteValues=true"
|
"ПорядокОкругления [Округление сумм] denyIncompleteValues=true"
|
||||||
"ПериодОтчета [Отчетный период]" # только title
|
"ПериодОтчета [Отчетный период]" # только title
|
||||||
"ПорядокОкругления availableValue=Перечисление.Округления.Окр1: руб., Перечисление.Округления.Окр1000: тыс."
|
"ПорядокОкругления availableValue=Перечисление.Округления.Окр1: руб., Перечисление.Округления.Окр1000: тыс."
|
||||||
"СчетПС value=ПланСчетов.Хозрасчетный.КассаПредприятия"
|
"СчетПС value=ПланСчетов.Хозрасчетный.КассаПредприятия"
|
||||||
"Виды value=ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты, ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Договоры"
|
"Виды value=ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты, ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Договоры"
|
||||||
"Контрагент @hidden @always"
|
"Контрагент @hidden @always"
|
||||||
```
|
```
|
||||||
|
|
||||||
`[Заголовок]` опциональный — устанавливает или заменяет `<title>`. Можно вызывать без других kv-пар, чтобы только обновить title.
|
`[Заголовок]` опциональный — устанавливает или заменяет `<title>`. Можно вызывать без других kv-пар, чтобы только обновить title.
|
||||||
|
|
||||||
`availableValue=` **заменяет весь список** допустимых значений (старые удаляются). Формат и кавычки — те же, что в `add-parameter`.
|
`availableValue=` **заменяет весь список** допустимых значений (старые удаляются). Формат и кавычки — те же, что в `add-parameter`.
|
||||||
|
|
||||||
`value=` заменяет значение параметра. Несколько значений через запятую → **список значений** (заменяет все прежние); для запятой внутри значения — кавычки `'...'`.
|
`value=` заменяет значение параметра. Несколько значений через запятую → **список значений** (заменяет все прежние); для запятой внутри значения — кавычки `'...'`.
|
||||||
|
|
||||||
Флаги `@hidden` / `@always` — те же, что и в `add-parameter`. Идемпотентны.
|
Флаги `@hidden` / `@always` — те же, что и в `add-parameter`. Идемпотентны.
|
||||||
|
|
||||||
### rename-parameter — переименовать параметр
|
### rename-parameter — переименовать параметр
|
||||||
|
|
||||||
Shorthand: `"OldName => NewName"`. Атомарно обновляет имя параметра, ссылки `&Имя` в выражениях других параметров (только полные совпадения, `&ПериодX` не задевается), и записи в `dataParameters` всех вариантов. Текст запроса не трогает — переименование строго в области параметров.
|
Shorthand: `"OldName => NewName"`. Атомарно обновляет имя параметра, ссылки `&Имя` в выражениях других параметров (только полные совпадения, `&ПериодX` не задевается), и записи в `dataParameters` всех вариантов. Текст запроса не трогает — переименование строго в области параметров.
|
||||||
|
|
||||||
```
|
```
|
||||||
"Период => ПериодОтчета"
|
"Период => ПериодОтчета"
|
||||||
```
|
```
|
||||||
|
|
||||||
### reorder-parameters — переставить параметры в указанном порядке
|
### reorder-parameters — переставить параметры в указанном порядке
|
||||||
|
|
||||||
Shorthand: `"Имя1, Имя2, Имя3"`. Частичный список — указанные параметры идут первыми в заданном порядке, остальные сохраняют исходный порядок и идут в конце. Параметры из списка, которых нет в схеме — warning, пропуск.
|
Shorthand: `"Имя1, Имя2, Имя3"`. Частичный список — указанные параметры идут первыми в заданном порядке, остальные сохраняют исходный порядок и идут в конце. Параметры из списка, которых нет в схеме — warning, пропуск.
|
||||||
|
|
||||||
```
|
```
|
||||||
"ПериодОтчета, НачалоПериода, КонецПериода"
|
"ПериодОтчета, НачалоПериода, КонецПериода"
|
||||||
```
|
```
|
||||||
|
|
||||||
### add-filter — добавить фильтр в вариант
|
### add-filter — добавить фильтр в вариант
|
||||||
|
|
||||||
Shorthand: `"Поле оператор значение @флаги"`. Флаги: `@off` (use=false), `@user` (userSettingID=auto), `@quickAccess`, `@normal`, `@inaccessible`.
|
Shorthand: `"Поле оператор значение @флаги"`. Флаги: `@off` (use=false), `@user` (userSettingID=auto), `@quickAccess`, `@normal`, `@inaccessible`.
|
||||||
|
|
||||||
```
|
```
|
||||||
"Номенклатура = _ @off @user"
|
"Номенклатура = _ @off @user"
|
||||||
"Дата >= 2024-01-01T00:00:00"
|
"Дата >= 2024-01-01T00:00:00"
|
||||||
"Статус filled"
|
"Статус filled"
|
||||||
```
|
```
|
||||||
|
|
||||||
### add-dataParameter — добавить параметр данных в вариант
|
### add-dataParameter — добавить параметр данных в вариант
|
||||||
|
|
||||||
Shorthand: `"Имя [= значение] @флаги"`.
|
Shorthand: `"Имя [= значение] @флаги"`.
|
||||||
|
|
||||||
```
|
```
|
||||||
"Период = LastMonth @user"
|
"Период = LastMonth @user"
|
||||||
"Организация @off @user"
|
"Организация @off @user"
|
||||||
```
|
```
|
||||||
|
|
||||||
### add-order — добавить сортировку
|
### add-order — добавить сортировку
|
||||||
|
|
||||||
Shorthand: `"Поле [desc]"`. По умолчанию asc. `Auto` — авто-элемент.
|
Shorthand: `"Поле [desc]"`. По умолчанию asc. `Auto` — авто-элемент.
|
||||||
|
|
||||||
```
|
```
|
||||||
"Количество desc"
|
"Количество desc"
|
||||||
"Auto"
|
"Auto"
|
||||||
```
|
```
|
||||||
|
|
||||||
### add-selection — добавить элемент выборки
|
### add-selection — добавить элемент выборки
|
||||||
|
|
||||||
```
|
```
|
||||||
"Номенклатура"
|
"Номенклатура"
|
||||||
"Auto"
|
"Auto"
|
||||||
"Folder(Поступление: ПолеА, ПолеБ, ПолеВ)"
|
"Folder(Поступление: ПолеА, ПолеБ, ПолеВ)"
|
||||||
```
|
```
|
||||||
|
|
||||||
`Folder(Название: поле1, поле2)` — группа полей (SelectedItemFolder) с заголовком и `placement=Auto`.
|
`Folder(Название: поле1, поле2)` — группа полей (SelectedItemFolder) с заголовком и `placement=Auto`.
|
||||||
|
|
||||||
`@group=ИмяГруппировки` — добавить в selection именованной группировки (вместо уровня варианта):
|
`@group=ИмяГруппировки` — добавить в selection именованной группировки (вместо уровня варианта):
|
||||||
|
|
||||||
```
|
```
|
||||||
"Folder(Поступление: ПолеА, ПолеБ) @group=ДанныеОтчета"
|
"Folder(Поступление: ПолеА, ПолеБ) @group=ДанныеОтчета"
|
||||||
```
|
```
|
||||||
|
|
||||||
### add-dataSetLink — добавить связь наборов данных
|
### add-dataSetLink — добавить связь наборов данных
|
||||||
|
|
||||||
Shorthand: `"Источник > Приёмник on ВырИсточника = ВырПриёмника [param Имя]"`.
|
Shorthand: `"Источник > Приёмник on ВырИсточника = ВырПриёмника [param Имя]"`.
|
||||||
|
|
||||||
```
|
```
|
||||||
"Набор1 > Набор2 on Поле1 = Поле2"
|
"Набор1 > Набор2 on Поле1 = Поле2"
|
||||||
"Набор1 > Набор2 on Поле1 = Поле2 [param Связь]"
|
"Набор1 > Набор2 on Поле1 = Поле2 [param Связь]"
|
||||||
```
|
```
|
||||||
|
|
||||||
### add-dataSet — добавить набор данных
|
### add-dataSet — добавить набор данных
|
||||||
|
|
||||||
Shorthand: `"Имя: ТЕКСТ_ЗАПРОСА"` или `"ТЕКСТ_ЗАПРОСА"` (авто-имя `НаборДанныхN`).
|
Shorthand: `"Имя: ТЕКСТ_ЗАПРОСА"` или `"ТЕКСТ_ЗАПРОСА"` (авто-имя `НаборДанныхN`).
|
||||||
|
|
||||||
```
|
```
|
||||||
"Доп: ВЫБРАТЬ 1 КАК Тест"
|
"Доп: ВЫБРАТЬ 1 КАК Тест"
|
||||||
"ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура"
|
"ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура"
|
||||||
"Продажи: @queries/sales.sql"
|
"Продажи: @queries/sales.sql"
|
||||||
```
|
```
|
||||||
|
|
||||||
`dataSource` берётся из первого существующего. Дубликат имени — предупреждение, пропуск. Не поддерживает пакетный режим (запрос может содержать `;;`).
|
`dataSource` берётся из первого существующего. Дубликат имени — предупреждение, пропуск. Не поддерживает пакетный режим (запрос может содержать `;;`).
|
||||||
|
|
||||||
### add-variant — добавить вариант настроек
|
### add-variant — добавить вариант настроек
|
||||||
|
|
||||||
Shorthand: `"Имя [Представление]"`. Представление опционально, по умолчанию = имя.
|
Shorthand: `"Имя [Представление]"`. Представление опционально, по умолчанию = имя.
|
||||||
|
|
||||||
```
|
```
|
||||||
"Детальный"
|
"Детальный"
|
||||||
"Детальный [Детальный отчёт]"
|
"Детальный [Детальный отчёт]"
|
||||||
```
|
```
|
||||||
|
|
||||||
Создаёт вариант с Auto selection + detail group. Дубликат имени — предупреждение, пропуск.
|
Создаёт вариант с Auto selection + detail group. Дубликат имени — предупреждение, пропуск.
|
||||||
|
|
||||||
### add-conditionalAppearance — добавить условное оформление
|
### add-conditionalAppearance — добавить условное оформление
|
||||||
|
|
||||||
Shorthand: `"Параметр = значение [when условие] [for Поле1, Поле2]"`. Блок `when` — синтаксис `add-filter` (Поле оператор значение).
|
Shorthand: `"Параметр = значение [when условие] [for Поле1, Поле2]"`. Блок `when` — синтаксис `add-filter` (Поле оператор значение).
|
||||||
|
|
||||||
```
|
```
|
||||||
"ЦветТекста = web:Red when Сумма < 0"
|
"ЦветТекста = web:Red when Сумма < 0"
|
||||||
"ЦветФона = web:LightGreen when Статус = Одобрен for Статус"
|
"ЦветФона = web:LightGreen when Статус = Одобрен for Статус"
|
||||||
"МинимальнаяШирина = 50 for Организация"
|
"МинимальнаяШирина = 50 for Организация"
|
||||||
"Формат = ЧДЦ=2 for Цена, Сумма"
|
"Формат = ЧДЦ=2 for Цена, Сумма"
|
||||||
```
|
```
|
||||||
|
|
||||||
Типы значений appearance (автодетект): `web:*`/`style:*`/`win:*` → Color, `true`/`false` → Boolean, параметр `Формат`/`Текст`/`Заголовок` → LocalStringType, иначе String.
|
Типы значений appearance (автодетект): `web:*`/`style:*`/`win:*` → Color, `true`/`false` → Boolean, параметр `Формат`/`Текст`/`Заголовок` → LocalStringType, иначе String.
|
||||||
|
|
||||||
Типы значений фильтра (автодетект): `Перечисление.*`/`Справочник.*`/`ПланСчетов.*`/`Документ.*` → DesignTimeValue, `true`/`false` → Boolean, дата → DateTime, числа → Decimal, иначе String.
|
Типы значений фильтра (автодетект): `Перечисление.*`/`Справочник.*`/`ПланСчетов.*`/`Документ.*` → DesignTimeValue, `true`/`false` → Boolean, дата → DateTime, числа → Decimal, иначе String.
|
||||||
|
|
||||||
OrGroup: несколько условий через ` or ` в `when` объединяются в FilterItemGroup/OrGroup:
|
OrGroup: несколько условий через ` or ` в `when` объединяются в FilterItemGroup/OrGroup:
|
||||||
|
|
||||||
```
|
```
|
||||||
"Формат = ЧЦ=15; ЧДЦ=0 when ПараметрыДанных.Округление = Перечисление.Округления.Окр1 or ПараметрыДанных.Округление = Перечисление.Округления.Окр1000"
|
"Формат = ЧЦ=15; ЧДЦ=0 when ПараметрыДанных.Округление = Перечисление.Округления.Окр1 or ПараметрыДанных.Округление = Перечисление.Округления.Окр1000"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Важно**: для параметров данных используйте префикс `ПараметрыДанных.` в поле фильтра.
|
**Важно**: для параметров данных используйте префикс `ПараметрыДанных.` в поле фильтра.
|
||||||
|
|
||||||
### add-drilldown — подключить расшифровку к ресурсам в шаблонах
|
### add-drilldown — подключить расшифровку к ресурсам в шаблонах
|
||||||
|
|
||||||
Value — имена ресурсов (как в полях/вычисляемых полях СКД) через запятую.
|
Value — имена ресурсов (как в полях/вычисляемых полях СКД) через запятую.
|
||||||
|
|
||||||
```
|
```
|
||||||
"ПоступлениеИзПроизводства, ВыбытиеПрочее"
|
"ПоступлениеИзПроизводства, ВыбытиеПрочее"
|
||||||
"Сумма_Дт83, Сумма_Дт99, Сумма_68, Сумма_84"
|
"Сумма_Дт83, Сумма_Дт99, Сумма_68, Сумма_84"
|
||||||
```
|
```
|
||||||
|
|
||||||
Подключает DrillDown по `ИмяРесурса` ко всем шаблонам, содержащим указанные ресурсы. Идемпотентно.
|
Подключает DrillDown по `ИмяРесурса` ко всем шаблонам, содержащим указанные ресурсы. Идемпотентно.
|
||||||
|
|
||||||
### set-query — заменить текст запроса
|
### set-query — заменить текст запроса
|
||||||
|
|
||||||
Не поддерживает пакетный режим. Value — полный текст запроса или `@path/to/file.sql` (ссылка на внешний файл). Путь разрешается относительно Template.xml, затем CWD.
|
Не поддерживает пакетный режим. Value — полный текст запроса или `@path/to/file.sql` (ссылка на внешний файл). Путь разрешается относительно Template.xml, затем CWD.
|
||||||
|
|
||||||
Когда что: **существенная переработка** (добавить поля, соединения, переписать пакет) → выгрузи запрос через `/skd-info <tpl> -Mode query -Name <набор> -Raw -OutFile file.sql`, отредактируй файл, верни `set-query @file`. `-Raw` отдаёт запрос целиком без декораций, поэтому выгрузка ↔ возврат точны (включая многопакетные запросы). **Точечная замена** (переименовать идентификатор, заменить подстроку) → выгрузка не нужна, используй `patch-query` ниже.
|
Когда что: **существенная переработка** (добавить поля, соединения, переписать пакет) → выгрузи запрос через `/skd-info <tpl> -Mode query -Name <набор> -Raw -OutFile file.sql`, отредактируй файл, верни `set-query @file`. `-Raw` отдаёт запрос целиком без декораций, поэтому выгрузка ↔ возврат точны (включая многопакетные запросы). **Точечная замена** (переименовать идентификатор, заменить подстроку) → выгрузка не нужна, используй `patch-query` ниже.
|
||||||
|
|
||||||
### patch-query — точечная замена в тексте запроса
|
### patch-query — точечная замена в тексте запроса
|
||||||
|
|
||||||
Shorthand: `"старое => новое [@once]"`. По умолчанию заменяет все вхождения подстроки. Поддерживает пакетный режим и `-DataSet`.
|
Shorthand: `"старое => новое [@once]"`. По умолчанию заменяет все вхождения подстроки. Поддерживает пакетный режим и `-DataSet`.
|
||||||
|
|
||||||
```
|
```
|
||||||
"СубконтоДт1) В => СубконтоКт1) В"
|
"СубконтоДт1) В => СубконтоКт1) В"
|
||||||
"КАК ВТ_СтароеИмя => КАК ВТ_НовоеИмя @once"
|
"КАК ВТ_СтароеИмя => КАК ВТ_НовоеИмя @once"
|
||||||
```
|
```
|
||||||
|
|
||||||
`@once` — упасть с ошибкой, если в запросе не **ровно одно** вхождение. Защищает от случайных замен в комментариях и однотипных идентификаторах.
|
`@once` — упасть с ошибкой, если в запросе не **ровно одно** вхождение. Защищает от случайных замен в комментариях и однотипных идентификаторах.
|
||||||
|
|
||||||
Многострочные подстроки поддерживаются.
|
Многострочные подстроки поддерживаются.
|
||||||
|
|
||||||
### set-outputParameter — установить параметр вывода
|
### set-outputParameter — установить параметр вывода
|
||||||
|
|
||||||
```
|
```
|
||||||
"Заголовок = Мой отчёт"
|
"Заголовок = Мой отчёт"
|
||||||
"ВыводитьЗаголовок = true"
|
"ВыводитьЗаголовок = true"
|
||||||
```
|
```
|
||||||
|
|
||||||
Если параметр уже существует — заменяет значение.
|
Если параметр уже существует — заменяет значение.
|
||||||
|
|
||||||
### set-structure — установить структуру варианта
|
### set-structure — установить структуру варианта
|
||||||
|
|
||||||
Shorthand: `"Поле1 > Поле2 > details"`. `>` — вложенный уровень группировки, `,` — несколько полей в одном уровне, `details` — детальные записи. **Заменяет всю структуру полностью** (включая Selection/order/filter/conditionalAppearance каждой группы). Для точечной модификации полей группировки с сохранением настроек — используй `modify-structure`. Не поддерживает пакетный режим.
|
Shorthand: `"Поле1 > Поле2 > details"`. `>` — вложенный уровень группировки, `,` — несколько полей в одном уровне, `details` — детальные записи. **Заменяет всю структуру полностью** (включая Selection/order/filter/conditionalAppearance каждой группы). Для точечной модификации полей группировки с сохранением настроек — используй `modify-structure`. Не поддерживает пакетный режим.
|
||||||
|
|
||||||
```
|
```
|
||||||
"Организация > Номенклатура > details"
|
"Организация > Номенклатура > details"
|
||||||
"Валюта, НаименованиеБанка, ИНН"
|
"Валюта, НаименованиеБанка, ИНН"
|
||||||
"details"
|
"details"
|
||||||
"СчетМеждународногоУчета @name=ДанныеОтчета"
|
"СчетМеждународногоУчета @name=ДанныеОтчета"
|
||||||
```
|
```
|
||||||
|
|
||||||
`@name=Имя` — присваивает имя группировке (`<dcsset:name>`). Используется для привязки шаблонов через `groupName`.
|
`@name=Имя` — присваивает имя группировке (`<dcsset:name>`). Используется для привязки шаблонов через `groupName`.
|
||||||
|
|
||||||
### modify-structure — изменить поля группировки существующей группы
|
### modify-structure — изменить поля группировки существующей группы
|
||||||
|
|
||||||
Тот же shorthand что и `set-structure`. Находит группу по `@name=`, заменяет только `<groupItems>` (поля группировки). Selection/order/filter/conditionalAppearance/outputParameters группы сохраняются. Без `@name=` — ошибка.
|
Тот же shorthand что и `set-structure`. Находит группу по `@name=`, заменяет только `<groupItems>` (поля группировки). Selection/order/filter/conditionalAppearance/outputParameters группы сохраняются. Без `@name=` — ошибка.
|
||||||
|
|
||||||
```
|
```
|
||||||
"Валюта @name=ДанныеОтчета"
|
"Валюта @name=ДанныеОтчета"
|
||||||
"Валюта, НаименованиеБанка @name=ДанныеОтчета"
|
"Валюта, НаименованиеБанка @name=ДанныеОтчета"
|
||||||
"details @name=ДанныеОтчета"
|
"details @name=ДанныеОтчета"
|
||||||
```
|
```
|
||||||
|
|
||||||
### modify-field — изменить существующее поле
|
### modify-field — изменить существующее поле
|
||||||
|
|
||||||
Тот же shorthand что и `add-field`. Находит по dataPath, объединяет свойства (непустые переопределяют), сохраняет позицию.
|
Тот же shorthand что и `add-field`. Находит по dataPath, объединяет свойства (непустые переопределяют), сохраняет позицию.
|
||||||
|
|
||||||
```
|
```
|
||||||
"Цена [Цена USD]: decimal(10,4) @dimension"
|
"Цена [Цена USD]: decimal(10,4) @dimension"
|
||||||
```
|
```
|
||||||
|
|
||||||
### set-field-role — установить роль поля
|
### set-field-role — установить роль поля
|
||||||
|
|
||||||
Shorthand: `"<dataPath> [@флаги] [kv=значение]"`. **Полностью заменяет** роль поля. Если в значении только dataPath без флагов/kv — удаляет роль.
|
Shorthand: `"<dataPath> [@флаги] [kv=значение]"`. **Полностью заменяет** роль поля. Если в значении только dataPath без флагов/kv — удаляет роль.
|
||||||
|
|
||||||
```
|
```
|
||||||
"Сумма" # снять роль полностью
|
"Сумма" # снять роль полностью
|
||||||
"СуммаОстаток @balance" # простая балансовая роль
|
"СуммаОстаток @balance" # простая балансовая роль
|
||||||
"СуммаНач @balance balanceGroupName=Сумма balanceType=OpeningBalance" # с уточнением
|
"СуммаНач @balance balanceGroupName=Сумма balanceType=OpeningBalance" # с уточнением
|
||||||
"Контрагент @dimension parentDimension=Группа"
|
"Контрагент @dimension parentDimension=Группа"
|
||||||
"Период @period" # роль периода
|
"Период @period" # роль периода
|
||||||
```
|
```
|
||||||
|
|
||||||
Флаги: `@balance`, `@dimension`, `@account`, `@period`, `@required`, `@autoOrder`, `@ignoreNullValues`.
|
Флаги: `@balance`, `@dimension`, `@account`, `@period`, `@required`, `@autoOrder`, `@ignoreNullValues`.
|
||||||
KV: `balanceGroupName`, `balanceType` (OpeningBalance/ClosingBalance), `parentDimension`, `accountTypeExpression`, `orderType` (Asc/Desc), `expression`, `periodNumber`, `periodType`.
|
KV: `balanceGroupName`, `balanceType` (OpeningBalance/ClosingBalance), `parentDimension`, `accountTypeExpression`, `orderType` (Asc/Desc), `expression`, `periodNumber`, `periodType`.
|
||||||
|
|
||||||
Поддерживает пакетный режим (`;;`).
|
Поддерживает пакетный режим (`;;`).
|
||||||
|
|
||||||
### modify-filter — изменить существующий фильтр
|
### modify-filter — изменить существующий фильтр
|
||||||
|
|
||||||
Тот же shorthand что и `add-filter`. Находит по полю, обновляет оператор/значение/флаги. См. правило для `<use>` ниже.
|
Тот же shorthand что и `add-filter`. Находит по полю, обновляет оператор/значение/флаги. См. правило для `<use>` ниже.
|
||||||
|
|
||||||
### modify-dataParameter — изменить параметр данных
|
### modify-dataParameter — изменить параметр данных
|
||||||
|
|
||||||
Тот же shorthand что и `add-dataParameter`. Находит по имени, обновляет значение/флаги. См. правило для `<use>` ниже.
|
Тот же shorthand что и `add-dataParameter`. Находит по имени, обновляет значение/флаги. См. правило для `<use>` ниже.
|
||||||
|
|
||||||
#### Правило `<use>` для modify-filter / modify-dataParameter
|
#### Правило `<use>` для modify-filter / modify-dataParameter
|
||||||
|
|
||||||
В отличие от `add-*`, в `modify-*` поле `<use>` обновляется **только если флаг задан явно**:
|
В отличие от `add-*`, в `modify-*` поле `<use>` обновляется **только если флаг задан явно**:
|
||||||
- `@off` — установить `<use>false</use>`
|
- `@off` — установить `<use>false</use>`
|
||||||
- `@on` — убрать существующий `<use>false</use>` (включить параметр)
|
- `@on` — убрать существующий `<use>false</use>` (включить параметр)
|
||||||
- ни `@off`, ни `@on` не задано — `<use>` не трогается, существующее значение сохраняется (важно: это значит, что отключённый параметр останется отключённым после модификации других свойств)
|
- ни `@off`, ни `@on` не задано — `<use>` не трогается, существующее значение сохраняется (важно: это значит, что отключённый параметр останется отключённым после модификации других свойств)
|
||||||
|
|
||||||
### remove-* и clear-*
|
### remove-* и clear-*
|
||||||
|
|
||||||
| Операция | Value | Действие |
|
| Операция | Value | Действие |
|
||||||
|----------|-------|----------|
|
|----------|-------|----------|
|
||||||
| `remove-field` | dataPath | Удаляет поле из набора + из selection варианта |
|
| `remove-field` | dataPath | Удаляет поле из набора + из selection варианта |
|
||||||
| `remove-total` | dataPath | Удаляет итог |
|
| `remove-total` | dataPath | Удаляет итог |
|
||||||
| `remove-calculated-field` | dataPath | Удаляет вычисляемое поле + из selection |
|
| `remove-calculated-field` | dataPath | Удаляет вычисляемое поле + из selection |
|
||||||
| `remove-parameter` | name | Удаляет параметр |
|
| `remove-parameter` | name | Удаляет параметр |
|
||||||
| `remove-filter` | поле | Удаляет первый фильтр с указанным полем |
|
| `remove-filter` | поле | Удаляет первый фильтр с указанным полем |
|
||||||
| `clear-selection` | `*` | Очищает все элементы selection |
|
| `clear-selection` | `*` | Очищает все элементы selection |
|
||||||
| `clear-order` | `*` | Очищает все элементы order |
|
| `clear-order` | `*` | Очищает все элементы order |
|
||||||
| `clear-filter` | `*` | Очищает все элементы filter |
|
| `clear-filter` | `*` | Очищает все элементы filter |
|
||||||
| `clear-conditionalAppearance` | `*` | Очищает все правила условного оформления |
|
| `clear-conditionalAppearance` | `*` | Очищает все правила условного оформления |
|
||||||
|
|
||||||
## Верификация
|
## Верификация
|
||||||
|
|
||||||
```
|
```
|
||||||
/skd-validate <TemplatePath> — валидация структуры после редактирования
|
/skd-validate <TemplatePath> — валидация структуры после редактирования
|
||||||
/skd-info <TemplatePath> — визуальная сводка
|
/skd-info <TemplatePath> — визуальная сводка
|
||||||
```
|
```
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user