Compare commits

..

1 Commits

Author SHA1 Message Date
github-actions[bot] a2c0109bdd Auto-build: claude-code (python) from e473d6c 2026-07-12 11:42:48 +00:00
2464 changed files with 11775 additions and 181912 deletions
-32
View File
@@ -1,32 +0,0 @@
{
"name": "cc-1c-skills",
"interface": {
"displayName": "1C Skills"
},
"plugins": [
{
"name": "1c-skills",
"source": {
"source": "url",
"url": "https://github.com/Nikolay-Shirokov/cc-1c-skills.git",
"ref": "port-codex"
},
"policy": {
"installation": "AVAILABLE"
},
"category": "Development"
},
{
"name": "1c-skills-py",
"source": {
"source": "url",
"url": "https://github.com/Nikolay-Shirokov/cc-1c-skills.git",
"ref": "port-codex-py"
},
"policy": {
"installation": "AVAILABLE"
},
"category": "Development"
}
]
}
-24
View File
@@ -1,24 +0,0 @@
{
"$schema": "https://json.schemastore.org/claude-code-marketplace-manifest.json",
"name": "cc-1c-skills",
"description": "Маркетплейс навыков для разработки на платформе 1С:Предприятие",
"owner": {
"name": "Nikolay Shirokov"
},
"plugins": [
{
"name": "1c-skills",
"source": "./",
"description": "[PowerShell] Навыки для разработки на 1С:Предприятие 8.3 — абстракции над XML-форматами и CLI конфигуратора, плюс глаза и руки для тестирования через веб-клиент."
},
{
"name": "1c-skills-py",
"source": {
"source": "github",
"repo": "Nikolay-Shirokov/cc-1c-skills",
"ref": "port-claude-code-py"
},
"description": "[Python] То же — для Linux/Mac или когда PowerShell недоступен."
}
]
}
+2 -2
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "1c-skills",
"description": "[PowerShell] Навыки для разработки на 1С:Предприятие 8.3 — абстракции над XML-форматами и CLI конфигуратора, плюс глаза и руки для тестирования через веб-клиент.",
"name": "1c-skills-py",
"description": "[Python] Навыки для разработки на 1С:Предприятие 8.3 — абстракции над XML-форматами и CLI конфигуратора, плюс глаза и руки для тестирования через веб-клиент. Linux/Mac или когда PowerShell недоступен.",
"author": {
"name": "Nikolay Shirokov"
},
+1 -1
View File
@@ -24,7 +24,7 @@ allowed-tools:
| `NoValidate` | Пропустить авто-валидацию |
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-edit.ps1" -ConfigPath '<path>' -Operation modify-property -Value 'Version=1.0.0.1'
python "${CLAUDE_SKILL_DIR}/scripts/cf-edit.py" -ConfigPath '<path>' -Operation modify-property -Value 'Version=1.0.0.1'
```
## Операции
+4 -3
View File
@@ -1,4 +1,4 @@
# cf-edit v1.7 — Edit 1C configuration root (Configuration.xml)
# cf-edit v1.8 — Edit 1C configuration root (Configuration.xml)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)][Alias('Path')][string]$ConfigPath,
@@ -196,7 +196,7 @@ Info "Configuration: $($script:objName)"
$script:typeOrder = @(
"Language","Subsystem","StyleItem","Style",
"CommonPicture","SessionParameter","Role","CommonTemplate",
"FilterCriterion","CommonModule","CommonAttribute","ExchangePlan",
"FilterCriterion","CommonModule","Bot","CommonAttribute","ExchangePlan",
"XDTOPackage","WebService","HTTPService","WSReference",
"EventSubscription","ScheduledJob","SettingsStorage","FunctionalOption",
"FunctionalOptionsParameter","DefinedType","CommonCommand","CommandGroup",
@@ -212,7 +212,7 @@ $script:typeOrder = @(
$script:typeToDir = @{
"Language"="Languages"; "Subsystem"="Subsystems"; "StyleItem"="StyleItems"; "Style"="Styles"
"CommonPicture"="CommonPictures"; "SessionParameter"="SessionParameters"; "Role"="Roles"; "CommonTemplate"="CommonTemplates"
"FilterCriterion"="FilterCriteria"; "CommonModule"="CommonModules"; "CommonAttribute"="CommonAttributes"; "ExchangePlan"="ExchangePlans"
"FilterCriterion"="FilterCriteria"; "CommonModule"="CommonModules"; "Bot"="Bots"; "CommonAttribute"="CommonAttributes"; "ExchangePlan"="ExchangePlans"
"XDTOPackage"="XDTOPackages"; "WebService"="WebServices"; "HTTPService"="HTTPServices"; "WSReference"="WSReferences"
"EventSubscription"="EventSubscriptions"; "ScheduledJob"="ScheduledJobs"; "SettingsStorage"="SettingsStorages"; "FunctionalOption"="FunctionalOptions"
"FunctionalOptionsParameter"="FunctionalOptionsParameters"; "DefinedType"="DefinedTypes"; "CommonCommand"="CommonCommands"; "CommandGroup"="CommandGroups"
@@ -700,6 +700,7 @@ $script:ruTypeMap = @{
"регистррасчёта" = "CalculationRegister"
"бизнеспроцесс" = "BusinessProcess"
"задача" = "Task"
"бот" = "Bot"
"планобмена" = "ExchangePlan"
"хранилищенастроек" = "SettingsStorage"
}
+4 -3
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# cf-edit v1.7 — Edit 1C configuration root (Configuration.xml)
# cf-edit v1.8 — Edit 1C configuration root (Configuration.xml)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -182,7 +182,7 @@ XS_NS = "http://www.w3.org/2001/XMLSchema"
TYPE_ORDER = [
"Language", "Subsystem", "StyleItem", "Style",
"CommonPicture", "SessionParameter", "Role", "CommonTemplate",
"FilterCriterion", "CommonModule", "CommonAttribute", "ExchangePlan",
"FilterCriterion", "CommonModule", "Bot", "CommonAttribute", "ExchangePlan",
"XDTOPackage", "WebService", "HTTPService", "WSReference",
"EventSubscription", "ScheduledJob", "SettingsStorage", "FunctionalOption",
"FunctionalOptionsParameter", "DefinedType", "CommonCommand", "CommandGroup",
@@ -198,7 +198,7 @@ TYPE_ORDER = [
TYPE_TO_DIR = {
"Language": "Languages", "Subsystem": "Subsystems", "StyleItem": "StyleItems", "Style": "Styles",
"CommonPicture": "CommonPictures", "SessionParameter": "SessionParameters", "Role": "Roles", "CommonTemplate": "CommonTemplates",
"FilterCriterion": "FilterCriteria", "CommonModule": "CommonModules", "CommonAttribute": "CommonAttributes", "ExchangePlan": "ExchangePlans",
"FilterCriterion": "FilterCriteria", "CommonModule": "CommonModules", "Bot": "Bots", "CommonAttribute": "CommonAttributes", "ExchangePlan": "ExchangePlans",
"XDTOPackage": "XDTOPackages", "WebService": "WebServices", "HTTPService": "HTTPServices", "WSReference": "WSReferences",
"EventSubscription": "EventSubscriptions", "ScheduledJob": "ScheduledJobs", "SettingsStorage": "SettingsStorages", "FunctionalOption": "FunctionalOptions",
"FunctionalOptionsParameter": "FunctionalOptionsParameters", "DefinedType": "DefinedTypes", "CommonCommand": "CommonCommands", "CommandGroup": "CommandGroups",
@@ -771,6 +771,7 @@ def main():
"регистррасчета": "CalculationRegister",
"регистррасчёта": "CalculationRegister",
"бизнеспроцесс": "BusinessProcess",
"бот": "Bot",
"задача": "Task", "планобмена": "ExchangePlan",
"хранилищенастроек": "SettingsStorage",
}
+1 -1
View File
@@ -23,7 +23,7 @@ allowed-tools:
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-info.ps1" -ConfigPath "<путь>"
python "${CLAUDE_SKILL_DIR}/scripts/cf-info.py" -ConfigPath "<путь>"
```
## Три режима
+3 -2
View File
@@ -1,4 +1,4 @@
# cf-info v1.3 — Compact summary of 1C configuration root
# cf-info v1.4 — Compact summary of 1C configuration root
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory=$true)][Alias('Path')][string]$ConfigPath,
@@ -89,7 +89,7 @@ function Get-PropML([string]$propName) {
$typeOrder = @(
"Language","Subsystem","StyleItem","Style",
"CommonPicture","SessionParameter","Role","CommonTemplate",
"FilterCriterion","CommonModule","CommonAttribute","ExchangePlan",
"FilterCriterion","CommonModule","Bot","CommonAttribute","ExchangePlan",
"XDTOPackage","WebService","HTTPService","WSReference",
"EventSubscription","ScheduledJob","SettingsStorage","FunctionalOption",
"FunctionalOptionsParameter","DefinedType","CommonCommand","CommandGroup",
@@ -105,6 +105,7 @@ $typeRuNames = @{
"Language"="Языки"; "Subsystem"="Подсистемы"; "StyleItem"="Элементы стиля"; "Style"="Стили"
"CommonPicture"="Общие картинки"; "SessionParameter"="Параметры сеанса"; "Role"="Роли"
"CommonTemplate"="Общие макеты"; "FilterCriterion"="Критерии отбора"; "CommonModule"="Общие модули"
"Bot"="Боты"
"CommonAttribute"="Общие реквизиты"; "ExchangePlan"="Планы обмена"; "XDTOPackage"="XDTO-пакеты"
"WebService"="Веб-сервисы"; "HTTPService"="HTTP-сервисы"; "WSReference"="WS-ссылки"
"EventSubscription"="Подписки на события"; "ScheduledJob"="Регламентные задания"
+3 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# cf-info v1.3 — Compact summary of 1C configuration root
# cf-info v1.4 — Compact summary of 1C configuration root
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -95,7 +95,7 @@ def get_prop_ml(prop_name):
type_order = [
"Language", "Subsystem", "StyleItem", "Style",
"CommonPicture", "SessionParameter", "Role", "CommonTemplate",
"FilterCriterion", "CommonModule", "CommonAttribute", "ExchangePlan",
"FilterCriterion", "CommonModule", "Bot", "CommonAttribute", "ExchangePlan",
"XDTOPackage", "WebService", "HTTPService", "WSReference",
"EventSubscription", "ScheduledJob", "SettingsStorage", "FunctionalOption",
"FunctionalOptionsParameter", "DefinedType", "CommonCommand", "CommandGroup",
@@ -111,6 +111,7 @@ type_ru_names = {
"Language": "Языки", "Subsystem": "Подсистемы", "StyleItem": "Элементы стиля", "Style": "Стили",
"CommonPicture": "Общие картинки", "SessionParameter": "Параметры сеанса", "Role": "Роли",
"CommonTemplate": "Общие макеты", "FilterCriterion": "Критерии отбора", "CommonModule": "Общие модули",
"Bot": "Боты",
"CommonAttribute": "Общие реквизиты", "ExchangePlan": "Планы обмена", "XDTOPackage": "XDTO-пакеты",
"WebService": "Веб-сервисы", "HTTPService": "HTTP-сервисы", "WSReference": "WS-ссылки",
"EventSubscription": "Подписки на события", "ScheduledJob": "Регламентные задания",
+1 -1
View File
@@ -24,7 +24,7 @@ allowed-tools:
| `CompatibilityMode` | Режим совместимости (default: `Version8_3_24`) |
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-init.ps1" -Name "МояКонфигурация"
python "${CLAUDE_SKILL_DIR}/scripts/cf-init.py" -Name "МояКонфигурация"
```
## Примеры
+2 -2
View File
@@ -24,6 +24,6 @@ allowed-tools:
## Команда
```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/Configuration.xml"
python "${CLAUDE_SKILL_DIR}/scripts/cf-validate.py" -ConfigPath "upload/cfempty"
python "${CLAUDE_SKILL_DIR}/scripts/cf-validate.py" -ConfigPath "upload/cfempty/Configuration.xml"
```
@@ -1,4 +1,4 @@
# cf-validate v1.3 — Validate 1C configuration root structure
# cf-validate v1.4 — Validate 1C configuration root structure
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -104,11 +104,11 @@ $validClassIds = @(
"fb282519-d103-4dd3-bc12-cb271d631dfc" # home page / client app interface
)
# 44 types in canonical order
# 45 types in canonical order
$childObjectTypes = @(
"Language","Subsystem","StyleItem","Style",
"CommonPicture","SessionParameter","Role","CommonTemplate",
"FilterCriterion","CommonModule","CommonAttribute","ExchangePlan",
"FilterCriterion","CommonModule","Bot","CommonAttribute","ExchangePlan",
"XDTOPackage","WebService","HTTPService","WSReference",
"EventSubscription","ScheduledJob","SettingsStorage","FunctionalOption",
"FunctionalOptionsParameter","DefinedType","CommonCommand","CommandGroup",
@@ -125,6 +125,7 @@ $childTypeDirMap = @{
"Language"="Languages"; "Subsystem"="Subsystems"; "StyleItem"="StyleItems"; "Style"="Styles"
"CommonPicture"="CommonPictures"; "SessionParameter"="SessionParameters"; "Role"="Roles"
"CommonTemplate"="CommonTemplates"; "FilterCriterion"="FilterCriteria"; "CommonModule"="CommonModules"
"Bot"="Bots"
"CommonAttribute"="CommonAttributes"; "ExchangePlan"="ExchangePlans"; "XDTOPackage"="XDTOPackages"
"WebService"="WebServices"; "HTTPService"="HTTPServices"; "WSReference"="WSReferences"
"EventSubscription"="EventSubscriptions"; "ScheduledJob"="ScheduledJobs"
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# cf-validate v1.3 — Validate 1C configuration XML structure
# cf-validate v1.4 — Validate 1C configuration XML structure
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
"""Validates Configuration.xml: root structure, InternalInfo, properties, ChildObjects, languages."""
import sys, os, argparse, re
@@ -33,11 +33,11 @@ VALID_CLASS_IDS = [
'fb282519-d103-4dd3-bc12-cb271d631dfc', # home page / client app interface
]
# 44 types in canonical order
# 45 types in canonical order
CHILD_OBJECT_TYPES = [
'Language', 'Subsystem', 'StyleItem', 'Style',
'CommonPicture', 'SessionParameter', 'Role', 'CommonTemplate',
'FilterCriterion', 'CommonModule', 'CommonAttribute', 'ExchangePlan',
'FilterCriterion', 'CommonModule', 'Bot', 'CommonAttribute', 'ExchangePlan',
'XDTOPackage', 'WebService', 'HTTPService', 'WSReference',
'EventSubscription', 'ScheduledJob', 'SettingsStorage', 'FunctionalOption',
'FunctionalOptionsParameter', 'DefinedType', 'CommonCommand', 'CommandGroup',
@@ -54,6 +54,7 @@ CHILD_TYPE_DIR_MAP = {
'Language': 'Languages', 'Subsystem': 'Subsystems', 'StyleItem': 'StyleItems', 'Style': 'Styles',
'CommonPicture': 'CommonPictures', 'SessionParameter': 'SessionParameters', 'Role': 'Roles',
'CommonTemplate': 'CommonTemplates', 'FilterCriterion': 'FilterCriteria', 'CommonModule': 'CommonModules',
'Bot': 'Bots',
'CommonAttribute': 'CommonAttributes', 'ExchangePlan': 'ExchangePlans', 'XDTOPackage': 'XDTOPackages',
'WebService': 'WebServices', 'HTTPService': 'HTTPServices', 'WSReference': 'WSReferences',
'EventSubscription': 'EventSubscriptions', 'ScheduledJob': 'ScheduledJobs',
+1 -1
View File
@@ -71,7 +71,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-borrow.ps1" -ExtensionPath src -ConfigPath C:\cfsrc\erp -Object "Catalog.Контрагенты"
python "${CLAUDE_SKILL_DIR}/scripts/cfe-borrow.py" -ExtensionPath src -ConfigPath C:\cfsrc\erp -Object "Catalog.Контрагенты"
```
## Примеры
+1 -1
View File
@@ -23,7 +23,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-diff.ps1" -ExtensionPath src -ConfigPath C:\cfsrc\erp -Mode A
python "${CLAUDE_SKILL_DIR}/scripts/cfe-diff.py" -ExtensionPath src -ConfigPath C:\cfsrc\erp -Mode A
```
## Mode A — обзор расширения
+1 -1
View File
@@ -44,7 +44,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-init.ps1" -Name "МоёРасширение"
python "${CLAUDE_SKILL_DIR}/scripts/cfe-init.py" -Name "МоёРасширение"
```
## Примеры
+1 -1
View File
@@ -51,7 +51,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-patch-method.ps1" -ExtensionPath src -ModulePath "Catalog.Контрагенты.ObjectModule" -MethodName "ПриЗаписи" -InterceptorType Before
python "${CLAUDE_SKILL_DIR}/scripts/cfe-patch-method.py" -ExtensionPath src -ModulePath "Catalog.Контрагенты.ObjectModule" -MethodName "ПриЗаписи" -InterceptorType Before
```
## Примеры
+2 -2
View File
@@ -24,6 +24,6 @@ allowed-tools:
## Команда
```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/Configuration.xml"
python "${CLAUDE_SKILL_DIR}/scripts/cfe-validate.py" -ExtensionPath "src"
python "${CLAUDE_SKILL_DIR}/scripts/cfe-validate.py" -ExtensionPath "src/Configuration.xml"
```
+5 -5
View File
@@ -31,7 +31,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" <параметры>
python "${CLAUDE_SKILL_DIR}/scripts/db-create.py" <параметры>
```
### Параметры скрипта
@@ -57,14 +57,14 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" <п
```powershell
# Создать файловую базу
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB"
python "${CLAUDE_SKILL_DIR}/scripts/db-create.py" -InfoBasePath "C:\Bases\NewDB"
# Создать серверную базу
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test"
python "${CLAUDE_SKILL_DIR}/scripts/db-create.py" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test"
# Создать из шаблона CF
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB" -UseTemplate "C:\Templates\config.cf"
python "${CLAUDE_SKILL_DIR}/scripts/db-create.py" -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 "Новая база"
python "${CLAUDE_SKILL_DIR}/scripts/db-create.py" -InfoBasePath "C:\Bases\NewDB" -AddToList -ListName "Новая база"
```
+4 -4
View File
@@ -35,7 +35,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" <параметры>
python "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.py" <параметры>
```
### Параметры скрипта
@@ -58,11 +58,11 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" <п
```powershell
# Выгрузка конфигурации (файловая база)
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "C:\backup\config.cf"
python "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.py" -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"
python "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.py" -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 "МоёРасширение"
python "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.py" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "ext.cfe" -Extension "МоёРасширение"
```
+3 -3
View File
@@ -38,7 +38,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.ps1" <параметры>
python "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.py" <параметры>
```
### Параметры скрипта
@@ -59,10 +59,10 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.ps1" <п
```powershell
# Выгрузка ИБ (файловая база)
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "C:\backup\base.dt"
python "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.py" -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"
python "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.py" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -OutputFile "base.dt"
```
## Связанные навыки
+6 -6
View File
@@ -37,7 +37,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" <параметры>
python "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.py" <параметры>
```
### Параметры скрипта
@@ -74,17 +74,17 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" <
```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
python "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.py" -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
python "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.py" -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 "Справочник.Номенклатура,Документ.Заказ"
python "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.py" -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
python "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.py" -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 "МоёРасширение"
python "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.py" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\ext_src" -Mode Full -Extension "МоёРасширение"
```
+4 -4
View File
@@ -36,7 +36,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" <параметры>
python "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.py" <параметры>
```
### Параметры скрипта
@@ -63,11 +63,11 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" <п
```powershell
# Файловая база
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "C:\backup\config.cf"
python "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.py" -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"
python "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.py" -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 "МоёРасширение"
python "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.py" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "ext.cfe" -Extension "МоёРасширение"
```
+3 -3
View File
@@ -52,7 +52,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.ps1" <параметры>
python "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.py" <параметры>
```
### Параметры скрипта
@@ -80,10 +80,10 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.ps1" <п
```powershell
# Файловая база
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "C:\backup\base.dt"
python "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.py" -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
python "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.py" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test" -UserName "Admin" -Password "secret" -InputFile "base.dt" -JobsCount 4
```
## Связанные навыки
+3 -3
View File
@@ -38,7 +38,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" <параметры>
python "${CLAUDE_SKILL_DIR}/scripts/db-load-git.py" <параметры>
```
### Параметры скрипта
@@ -70,8 +70,8 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" <
```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
python "${CLAUDE_SKILL_DIR}/scripts/db-load-git.py" -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"
python "${CLAUDE_SKILL_DIR}/scripts/db-load-git.py" -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\WS\cfsrc" -Source Commit -CommitRange "HEAD~3..HEAD"
```
+5 -5
View File
@@ -38,7 +38,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" <параметры>
python "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.py" <параметры>
```
### Параметры скрипта
@@ -88,14 +88,14 @@ Documents/Заказ/Forms/ФормаДокумента.xml
```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
python "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.py" -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"
python "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.py" -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 "МоёРасширение"
python "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.py" -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
python "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.py" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full -UpdateDB
```
+5 -5
View File
@@ -36,7 +36,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" <параметры>
python "${CLAUDE_SKILL_DIR}/scripts/db-run.py" <параметры>
```
### Параметры скрипта
@@ -63,14 +63,14 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" <пар
```powershell
# Простой запуск
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
python "${CLAUDE_SKILL_DIR}/scripts/db-run.py" -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"
python "${CLAUDE_SKILL_DIR}/scripts/db-run.py" -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/Справочник.Номенклатура"
python "${CLAUDE_SKILL_DIR}/scripts/db-run.py" -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 "ЗапуститьОбновление"
python "${CLAUDE_SKILL_DIR}/scripts/db-run.py" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -CParam "ЗапуститьОбновление"
```
+4 -4
View File
@@ -35,7 +35,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" <параметры>
python "${CLAUDE_SKILL_DIR}/scripts/db-update.py" <параметры>
```
### Параметры скрипта
@@ -76,11 +76,11 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" <п
```powershell
# Обычное обновление (файловая база)
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
python "${CLAUDE_SKILL_DIR}/scripts/db-update.py" -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 "+"
python "${CLAUDE_SKILL_DIR}/scripts/db-update.py" -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 "МоёРасширение"
python "${CLAUDE_SKILL_DIR}/scripts/db-update.py" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -Extension "МоёРасширение"
```
+3 -3
View File
@@ -40,7 +40,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" <параметры>
python "${CLAUDE_SKILL_DIR}/scripts/epf-build.py" <параметры>
```
### Параметры скрипта
@@ -62,8 +62,8 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" <п
```powershell
# Сборка обработки (файловая база)
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" -InfoBasePath "C:\Bases\MyDB" -SourceFile "src/МояОбработка.xml" -OutputFile "build/МояОбработка.epf"
python "${CLAUDE_SKILL_DIR}/scripts/epf-build.py" -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"
python "${CLAUDE_SKILL_DIR}/scripts/epf-build.py" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -SourceFile "src/МояОбработка.xml" -OutputFile "build/МояОбработка.epf"
```
+3 -3
View File
@@ -39,7 +39,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" <параметры>
python "${CLAUDE_SKILL_DIR}/scripts/epf-dump.py" <параметры>
```
### Параметры скрипта
@@ -62,8 +62,8 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" <па
```powershell
# Разборка обработки (файловая база)
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" -InfoBasePath "C:\Bases\MyDB" -InputFile "build/МояОбработка.epf" -OutputDir "src"
python "${CLAUDE_SKILL_DIR}/scripts/epf-dump.py" -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"
python "${CLAUDE_SKILL_DIR}/scripts/epf-dump.py" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -InputFile "build/МояОбработка.epf" -OutputDir "src"
```
+1 -1
View File
@@ -30,7 +30,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/init.ps1" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"]
python "${CLAUDE_SKILL_DIR}/scripts/init.py" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"]
```
## Дальнейшие шаги
+2 -2
View File
@@ -24,7 +24,7 @@ allowed-tools:
## Команда
```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/МояОбработка/МояОбработка.xml"
python "${CLAUDE_SKILL_DIR}/scripts/epf-validate.py" -ObjectPath "src/МояОбработка"
python "${CLAUDE_SKILL_DIR}/scripts/epf-validate.py" -ObjectPath "src/МояОбработка/МояОбработка.xml"
```
+3 -3
View File
@@ -42,7 +42,7 @@ allowed-tools:
Используй общий скрипт из epf-build:
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.ps1" <параметры>
python "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.py" <параметры>
```
### Параметры скрипта
@@ -64,8 +64,8 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-bu
```powershell
# Сборка отчёта (файловая база)
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.ps1" -InfoBasePath "C:\Bases\MyDB" -SourceFile "src/МойОтчёт.xml" -OutputFile "build/МойОтчёт.erf"
python "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.py" -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"
python "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.py" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -SourceFile "src/МойОтчёт.xml" -OutputFile "build/МойОтчёт.erf"
```
+3 -3
View File
@@ -41,7 +41,7 @@ allowed-tools:
Используй общий скрипт из epf-dump:
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.ps1" <параметры>
python "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.py" <параметры>
```
### Параметры скрипта
@@ -64,8 +64,8 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dum
```powershell
# Разборка отчёта (файловая база)
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.ps1" -InfoBasePath "C:\Bases\MyDB" -InputFile "build/МойОтчёт.erf" -OutputDir "src"
python "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.py" -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"
python "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.py" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -InputFile "build/МойОтчёт.erf" -OutputDir "src"
```
+1 -1
View File
@@ -31,7 +31,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/init.ps1" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-WithSKD]
python "${CLAUDE_SKILL_DIR}/scripts/init.py" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-WithSKD]
```
## Дальнейшие шаги
+2 -2
View File
@@ -26,7 +26,7 @@ allowed-tools:
## Команда
```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/МойОтчёт/МойОтчёт.xml"
python "${CLAUDE_SKILL_DIR}/../epf-validate/scripts/epf-validate.py" -ObjectPath "src/МойОтчёт"
python "${CLAUDE_SKILL_DIR}/../epf-validate/scripts/epf-validate.py" -ObjectPath "src/МойОтчёт/МойОтчёт.xml"
```
+1 -1
View File
@@ -32,7 +32,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-add.ps1" -ObjectPath "<ObjectPath>" -FormName "<FormName>" [-Purpose "<Purpose>"] [-Synonym "<Synonym>"] [-SetDefault]
python "${CLAUDE_SKILL_DIR}/scripts/form-add.py" -ObjectPath "<ObjectPath>" -FormName "<FormName>" [-Purpose "<Purpose>"] [-Synonym "<Synonym>"] [-SetDefault]
```
## Purpose — назначение формы
+2 -2
View File
@@ -1,4 +1,4 @@
# form-add v1.7 — Add managed form to 1C config object
# form-add v1.8 — Add managed form to 1C config object
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -195,7 +195,7 @@ $supportedTypes = @(
"Document", "Catalog", "DataProcessor", "Report",
"ExternalDataProcessor", "ExternalReport",
"InformationRegister", "AccumulationRegister", "ChartOfAccounts", "ChartOfCharacteristicTypes",
"ExchangePlan", "BusinessProcess", "Task"
"ExchangePlan", "BusinessProcess", "Task", "DocumentJournal"
)
$objectType = $null
+2 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# form-add v1.7 — Add managed form to 1C config object
# form-add v1.8 — Add managed form to 1C config object
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -256,7 +256,7 @@ def main():
"Document", "Catalog", "DataProcessor", "Report",
"ExternalDataProcessor", "ExternalReport",
"InformationRegister", "AccumulationRegister", "ChartOfAccounts", "ChartOfCharacteristicTypes",
"ExchangePlan", "BusinessProcess", "Task",
"ExchangePlan", "BusinessProcess", "Task", "DocumentJournal",
]
object_type = None
+2 -2
View File
@@ -29,10 +29,10 @@ allowed-tools:
```powershell
# Режим JSON DSL
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-compile.ps1" -JsonPath "<json>" -OutputPath "<Form.xml>"
python "${CLAUDE_SKILL_DIR}/scripts/form-compile.py" -JsonPath "<json>" -OutputPath "<Form.xml>"
# Режим from-object (объект и purpose выводятся из OutputPath; Document и Catalog)
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-compile.ps1" -FromObject -OutputPath "<.../TypePlural/ObjectName/Forms/FormName/Ext/Form.xml>"
python "${CLAUDE_SKILL_DIR}/scripts/form-compile.py" -FromObject -OutputPath "<.../TypePlural/ObjectName/Forms/FormName/Ext/Form.xml>"
```
## JSON DSL — справка
+1 -1
View File
@@ -31,7 +31,7 @@ allowed-tools:
| `OutputPath` | Путь к выходному JSON. Если не задан — JSON в stdout |
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-decompile.ps1" -FormPath "<Form.xml>" -OutputPath "<out.json>"
python "${CLAUDE_SKILL_DIR}/scripts/form-decompile.py" -FormPath "<Form.xml>" -OutputPath "<out.json>"
```
## Что получаешь
+1 -1
View File
@@ -29,7 +29,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-edit.ps1" -FormPath "<путь>" -JsonPath "<путь>"
python "${CLAUDE_SKILL_DIR}/scripts/form-edit.py" -FormPath "<путь>" -JsonPath "<путь>"
```
## JSON формат
+1 -1
View File
@@ -15,7 +15,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-info.ps1" -FormPath "<путь к Form.xml>"
python "${CLAUDE_SKILL_DIR}/scripts/form-info.py" -FormPath "<путь к Form.xml>"
```
## Параметры
+1 -1
View File
@@ -31,7 +31,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/remove-form.ps1" -ObjectName "<ObjectName>" -FormName "<FormName>" [-SrcDir "<SrcDir>"]
python "${CLAUDE_SKILL_DIR}/scripts/remove-form.py" -ObjectName "<ObjectName>" -FormName "<FormName>" [-SrcDir "<SrcDir>"]
```
## Что удаляется
+2 -2
View File
@@ -23,7 +23,7 @@ allowed-tools:
## Команда
```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 "src/МояОбработка/Forms/Форма/Ext/Form.xml"
python "${CLAUDE_SKILL_DIR}/scripts/form-validate.py" -FormPath "Catalogs/Номенклатура/Forms/ФормаЭлемента"
python "${CLAUDE_SKILL_DIR}/scripts/form-validate.py" -FormPath "src/МояОбработка/Forms/Форма/Ext/Form.xml"
```
+1 -1
View File
@@ -30,7 +30,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/add-help.ps1" -ObjectName "<ObjectName>" [-Lang "<Lang>"] [-SrcDir "<SrcDir>"]
python "${CLAUDE_SKILL_DIR}/scripts/add-help.py" -ObjectName "<ObjectName>" [-Lang "<Lang>"] [-SrcDir "<SrcDir>"]
```
## Что делает скрипт
+2 -2
View File
@@ -29,13 +29,13 @@ allowed-tools:
### Inline mode
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/interface-edit.ps1" -CIPath '<path>' -Operation hide -Value '<cmd>'
python "${CLAUDE_SKILL_DIR}/scripts/interface-edit.py" -CIPath '<path>' -Operation hide -Value '<cmd>'
```
### JSON mode
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/interface-edit.ps1" -CIPath '<path>' -DefinitionFile '<json>'
python "${CLAUDE_SKILL_DIR}/scripts/interface-edit.py" -CIPath '<path>' -DefinitionFile '<json>'
```
## Операции
+2 -2
View File
@@ -24,6 +24,6 @@ allowed-tools:
## Команда
```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/Продажи/Ext/CommandInterface.xml"
python "${CLAUDE_SKILL_DIR}/scripts/interface-validate.py" -CIPath "Subsystems/Продажи"
python "${CLAUDE_SKILL_DIR}/scripts/interface-validate.py" -CIPath "Subsystems/Продажи/Ext/CommandInterface.xml"
```
+78 -62
View File
@@ -9,111 +9,127 @@ allowed-tools:
- Glob
---
# /meta-compile — генерация объектов метаданных из JSON DSL
# /meta-compile — генерация объектов метаданных из JSON
Принимает JSON-определение объекта метаданных → генерирует XML + модули в структуре выгрузки конфигурации + регистрирует в Configuration.xml.
Принимает JSON-определение объекта → генерирует XML + модули в структуре выгрузки конфигурации и
регистрирует объект в `Configuration.xml`.
## Порядок работы
1. Составь JSON по синтаксису и примерам ниже → запиши во временный файл
2. Запусти скрипт meta-compile
3. Если нужно изменить созданный объект — `/meta-edit`
4. Если нужно проверить — `/meta-validate`
## Команда
1. Составь JSON по синтаксису ниже → запиши во временный файл.
2. Запусти скрипт.
3. Изменить созданный объект — `/meta-edit`; проверить — `/meta-validate`.
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-compile.ps1" -JsonPath "<json>" -OutputDir "<ConfigDir>"
python "${CLAUDE_SKILL_DIR}/scripts/meta-compile.py" -JsonPath "<json>" -OutputDir "<ConfigDir>"
```
| Параметр | Описание |
|----------|----------|
| `JsonPath` | Путь к JSON-файлу (один объект `{...}` или массив `[{...}, ...]`) |
| `OutputDir` | Корень выгрузки конфигурации (где `Configuration.xml`, `Catalogs/`, `Documents/` и т.д.) |
| `JsonPath` | Путь к JSON-файлу |
| `OutputDir` | Корень выгрузки конфигурации (где `Configuration.xml`, `Catalogs/`, `Documents/`, …) |
## JSON DSL
## Формат JSON
### Общая структура
**Один объект** `{ ... }` или **массив** объектов `[{ ... }, { ... }]` (batch — несколько объектов за прогон).
```json
{ "type": "Catalog", "name": "Номенклатура", ...свойства типа... }
{ "type": "Catalog", "name": "Номенклатура", "...свойства типа...": "..." }
```
`type` и `name` — обязательные. `synonym` генерируется из `name` автоматически (CamelCase → слова через пробел). Можно задать явно: `"synonym": "Мой синоним"`.
`type` и `name` — обязательные. Остальное — по типу (см. индекс ниже). `synonym` по умолчанию выводится из
`name` (CamelCase → слова через пробел); можно задать явно строкой или мультиязычно: `"synonym": { "ru": "…", "en": "…" }`.
### Shorthand реквизитов
## Реквизиты (shorthand)
Используется в `attributes`, `dimensions`, `resources`, `tabularSections`:
Массивы `attributes`, `dimensions`, `resources` и колонки в `tabularSections` задаются строками:
```
"ИмяРеквизита" → String(10) по умолчанию
"ИмяРеквизита: Тип" → с типом
"ИмяРеквизита: Тип | req, index" → с флагами
"Имя" → String(10)
"Имя: Тип" → с типом
"Имя: Тип | req, index" с флагами
```
Типы: `String(100)`, `Number(15,2)`, `Boolean`, `Date`, `DateTime`, `CatalogRef.Xxx`, `DocumentRef.Xxx`, `EnumRef.Xxx`, `DefinedType.Xxx` и др. ссылочные.
**Типы:** `String(100)`, `String(10, fixed)` (фикс. длина), `Number(15,2)`, `Boolean`, `Date`, `DateTime`,
`Time`, ссылочные `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` | обязательное заполнение | attributes, dimensions, resources |
| `index` | индексировать | attributes, dimensions |
| `indexAdditional` | индекс с доп. упорядочиванием | attributes |
| `multiline` | многострочное поле | attributes |
| `nonneg` | неотрицательное (Number) | attributes, resources |
| `master` | ведущее измерение | dimensions (регистры) |
| `mainFilter` | основной отбор | dimensions (регистры) |
| `denyIncomplete` | запрет незаполненных | dimensions |
| `useInTotals` | использовать в итогах | dimensions (регистр накопления) |
### Свойства по типам
Реквизиту нужны свойства сверх shorthand (значение заполнения, параметры выбора, формат, подсказка, …) —
задаётся **объектной формой**, см. `reference/attributes.md`.
Примеров и shorthand-синтаксиса выше достаточно для типовых задач. Если нужны свойства типа, не показанные в примерах, и их допустимые значения — см. reference-файл:
- `reference/types-basic.md` — Catalog, Document, Enum, Constant, DefinedType, Report, DataProcessor
- `reference/types-registers.md` — InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister, ChartOfAccounts, ChartOfCharacteristicTypes, ChartOfCalculationTypes
- `reference/types-process.md` — BusinessProcess, Task, ExchangePlan, CommonModule, ScheduledJob, EventSubscription, DocumentJournal
- `reference/types-web.md` — HTTPService, WebService
Эта инструкция и reference-файлы — полная документация для генерации. Не ищи примеры XML в выгрузках конфигураций.
## Примеры паттернов DSL
### Минимальный объект
## Табличные части
```json
{ "type": "Catalog", "name": "Валюты" }
"tabularSections": { "Товары": ["Номенклатура: CatalogRef.Номенклатура", "Количество: Number(15,3)"] }
```
### С реквизитами
Ключ — имя ТЧ, значение — массив колонок (shorthand) ЛИБО объект со свойствами ТЧ (см. `reference/attributes.md`).
## Индекс: свойства по типам
Для каждого типа — свой reference-файл со свойствами, дефолтами и допустимыми значениями:
| Тип(ы) | Файл |
|--------|------|
| Catalog (справочник) | `reference/catalog.md` |
| Document, DocumentJournal, Sequence, DocumentNumerator | `reference/document.md` |
| InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister | `reference/registers.md` |
| ChartOfAccounts, ChartOfCharacteristicTypes, ChartOfCalculationTypes | `reference/charts.md` |
| ExchangePlan | `reference/exchangeplan.md` |
| BusinessProcess, Task | `reference/process.md` |
| Report, DataProcessor | `reference/report-dataprocessor.md` |
| CommonModule, ScheduledJob, EventSubscription | `reference/code.md` |
| HTTPService, WebService | `reference/web.md` |
| Enum, Constant, DefinedType | `reference/simple.md` |
| FunctionalOption, FilterCriterion, SettingsStorage, CommonForm, CommonPicture, CommonTemplate, служебные | `reference/other-types.md` |
Кросс-типовые детали:
- **`reference/attributes.md`** — объектная форма реквизита и колонки ТЧ (значение заполнения, параметры
выбора, формат, подсказка, границы, …) + свойства самой ТЧ.
- **`reference/blocks.md`** — блоки объекта: представления, команды (+ характеристики/стандартные реквизиты).
Эта инструкция и reference-файлы — полная документация. Не ищи примеры XML в выгрузках конфигураций.
## Примеры
Справочник с реквизитами:
```json
{
"type": "Catalog", "name": "Организации",
"descriptionLength": 100,
"attributes": ["ИНН: String(12)", "КПП: String(9)", "Директор: CatalogRef.ФизическиеЛица"]
}
{ "type": "Catalog", "name": "Организации", "descriptionLength": 100,
"attributes": ["ИНН: String(12)", "КПП: String(9)", "Директор: CatalogRef.ФизическиеЛица"] }
```
### С табличной частью
Документ с движениями и ТЧ:
```json
{
"type": "Document", "name": "ПриходнаяНакладная",
{ "type": "Document", "name": "ПриходнаяНакладная",
"registerRecords": ["AccumulationRegister.ОстаткиТоваров"],
"attributes": ["Организация: CatalogRef.Организации", "Контрагент: CatalogRef.Контрагенты"],
"tabularSections": { "Товары": ["Номенклатура: CatalogRef.Номенклатура", "Количество: Number(15,3)", "Цена: Number(15,2)"] }
}
"tabularSections": { "Товары": ["Номенклатура: CatalogRef.Номенклатура", "Количество: Number(15,3)", "Цена: Number(15,2)"] } }
```
### Регистровый паттерн (измерения + ресурсы)
Регистр сведений:
```json
{
"type": "InformationRegister", "name": "КурсыВалют", "periodicity": "Day",
{ "type": "InformationRegister", "name": "КурсыВалют", "periodicity": "Day",
"dimensions": ["Валюта: CatalogRef.Валюты | master, mainFilter, denyIncomplete"],
"resources": ["Курс: Number(15,4)", "Кратность: Number(10,0)"]
}
"resources": ["Курс: Number(15,4)", "Кратность: Number(10,0)"] }
```
### Batch — несколько объектов в одном файле
Batch:
```json
[
{ "type": "Enum", "name": "Статусы", "values": ["Новый", "Закрыт"] },
[ { "type": "Enum", "name": "Статусы", "values": ["Новый", "Закрыт"] },
{ "type": "Catalog", "name": "Валюты" },
{ "type": "Constant", "name": "ОсновнаяВалюта", "valueType": "CatalogRef.Валюты" }
]
{ "type": "Constant", "name": "ОсновнаяВалюта", "valueType": "CatalogRef.Валюты" } ]
```
@@ -0,0 +1,139 @@
# Объектная форма реквизита и табличной части
Когда реквизиту (в `attributes` / `dimensions` / `resources` / колонках ТЧ) нужны свойства сверх
shorthand — вместо строки задаётся объект:
```json
{ "name": "Цена", "type": "Number(15,2)", "tooltip": "Цена за единицу", "fillValue": 0 }
```
`name` и `type` обязательны (тип можно задать и раздельно: `"type": "Number", "length": 15, "precision": 2`).
Остальные ключи — ниже, все со значением по умолчанию (не задавать, если устраивает дефолт).
## Свойства реквизита
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `synonym` | из имени | ML (строка или `{ru,en}`) |
| `tooltip` | пусто | ML |
| `comment` | пусто | строка |
| `fillChecking` | `DontCheck` | `DontCheck` / `ShowError` / `ShowWarning` (то же, что флаг `req`) |
| `fullTextSearch` | `Use` | `Use` / `DontUse` |
| `fillFromFillingValue` | `false` | bool |
| `fillValue` | по типу (см. ниже) | значение заполнения |
| `createOnInput` | `Auto` | `Auto` / `Use` / `DontUse` |
| `quickChoice` | `Auto` | `Auto` / `Use` / `DontUse` |
| `choiceHistoryOnInput` | `Auto` | `Auto` / `DontUse` |
| `dataHistory` | `Use` | `Use` / `DontUse` |
| `use` | `ForItem` | `ForItem` / `ForFolder` / `ForFolderAndItem` (реквизит иерархического справочника) |
| `passwordMode` | `false` | bool |
| `multiLine` | `false` | bool (то же, что флаг `multiline`) |
| `extendedEdit` | `false` | bool (расширенное редактирование — многострочный ввод) |
| `mask` | пусто | строка маски ввода |
| `format` / `editFormat` | пусто | форматная строка 1С (ML) |
| `markNegatives` | `false` | bool (выделять отрицательные, для Number) |
| `minValue` / `maxValue` | не задано | граница диапазона (см. ниже) |
| `choiceParameterLinks` | пусто | связи параметров выбора (см. ниже) |
| `choiceParameters` | пусто | параметры выбора (см. ниже) |
| `choiceForm` | пусто | ссылка на форму выбора `Тип.Объект.Form.ИмяФормы` |
| `choiceFoldersAndItems` | `Items` | `Items` / `Folders` / `FoldersAndItems` (что выбирать в иерарх. справочнике) |
Индексирование задаётся флагом `index` / `indexAdditional` в shorthand, либо в объекте — как и в строковой форме,
через `"type": "… | index"`.
### `fillValue` — значение заполнения
Пустое значение по типу компилятор подставляет сам — ключ **не задают**:
| Тип реквизита | Пустое значение |
|---------------|-----------------|
| String | пустая строка |
| Number | `0` |
| Boolean, Date, ссылочный, составной | не задано (nil) |
Ключ `fillValue` задают для **конкретного** значения — интерпретируется по типу реквизита:
- **Boolean** — `true` / `false`.
- **Number** — число (`21`, `1.5`).
- **String** — строка.
- **Date** — ISO-строка `"2020-01-01T00:00:00"`.
- **Ссылочный** — путь: `"Catalog.Валюты.EmptyRef"` (пустая ссылка), `"Enum.Периодичность.EnumValue.Месяц"`
(значение перечисления), `"Catalog.СтраныМира.Россия"` (предопределённый элемент).
- **`null`** — явно «значение не задано» (nil), когда нужно перекрыть непустой дефолт типа.
- **`{ "emptyRef": true }`** — пустая ссылка для реквизита типа `DefinedType.X` (когда тип из пути не выводится).
> Пустая ссылка (`EmptyRef`) и `null` — разное: платформа хранит их отдельно.
### `minValue` / `maxValue` — границы диапазона
Число → числовая граница; строка → строковая (напр. год `"2000"`). Без ключа — граница не задана.
### `choiceParameterLinks` — связи параметров выбора
Связывают параметр выбора этого реквизита с другим реквизитом объекта. Массив строк или объектов:
```json
"choiceParameterLinks": ["Отбор.Организация=Организация", "Отбор.Договор=Договор:DontChange"]
"choiceParameterLinks": [{ "name": "Отбор.Организация", "dataPath": "Организация", "valueChange": "Clear" }]
```
- `dataPath` — реквизит **того же объекта**: имя обычного реквизита (`"Организация"`) или стандартного
(`"Владелец"`, `"Ссылка"`).
- `valueChange``Clear` (по умолчанию) / `DontChange`.
### `choiceParameters` — параметры выбора
Фиксируют параметр выбора значением. Массив строк или объектов:
```json
"choiceParameters": ["Отбор.ЭтоГруппа=false"]
"choiceParameters": [{ "name": "Отбор.Владелец", "value": "Catalog.Организации.EmptyRef" }]
```
- `value` — bool / число / строка / ссылочный путь (несёт тип) ИЛИ массив (список фиксированных значений).
- Для набора голых имён-значений добавьте `type` (тип поля-фильтра), чтобы они стали ссылками:
`{ "name": "Отбор.Тип", "type": "EnumRef.ТипыВЕТИС", "value": ["EmptyRef", "ТТН"] }`.
### Редкие ключи
`linkByType` — связь по типу (тип реквизита-Характеристики берётся из другого реквизита):
`{ "dataPath": "Свойство", "linkItem": 0 }` или строка-путь. Применяется для реквизитов-характеристик.
---
## Табличная часть — объектная форма
Значение в `tabularSections` — массив колонок ЛИБО объект со свойствами самой ТЧ:
```json
"tabularSections": {
"Товары": {
"synonym": { "ru": "Товары", "en": "Goods" },
"tooltip": "Строки заказа",
"fillChecking": "ShowError",
"attributes": ["Номенклатура: CatalogRef.Номенклатура", "Количество: Number(15,3)"]
}
}
```
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `synonym` | из имени | ML |
| `tooltip` | пусто | ML |
| `comment` | пусто | строка |
| `fillChecking` | `DontCheck` | `DontCheck` / `ShowError` / `ShowWarning` (обязательность заполнения ТЧ) |
| `use` | `ForItem` | `ForItem` / `ForFolder` / `ForFolderAndItem` (только Catalog / ChartOfCharacteristicTypes) |
| `attributes` | `[]` | колонки (shorthand или объектная форма реквизита) |
| `lineNumber` | — | кастомизация стандартного реквизита НомерСтроки (см. ниже) |
### `lineNumber` — стандартный реквизит НомерСтроки
У каждой ТЧ есть стандартный реквизит НомерСтроки. По умолчанию все его свойства типовые. Ключ `lineNumber`
на объектной форме ТЧ их переопределяет:
```json
"Строки": { "lineNumber": { "synonym": "Номер п/п", "fullTextSearch": "DontUse" }, "attributes": [...] }
```
Переопределяемые: `synonym`, `comment`, `fullTextSearch` (`Use`/`DontUse`), `tooltip`, `format`, `editFormat`,
`choiceHistoryOnInput` (`Auto`/`DontUse`).
@@ -0,0 +1,109 @@
# Блоки объекта
Кросс-типовые блоки уровня объекта (применимы к ссылочным типам — Catalog, Document, ChartOf*, ExchangePlan,
BusinessProcess, Task и др.).
## Представления
Тексты представления объекта в интерфейсе (ML — строка или `{ru,en}`, по умолчанию пусто):
| Ключ | Смысл |
|------|-------|
| `objectPresentation` | представление объекта |
| `extendedObjectPresentation` | расширенное представление объекта |
| `listPresentation` | представление списка |
| `extendedListPresentation` | расширенное представление списка |
| `explanation` | пояснение |
Набор доступных ключей зависит от типа (у списочных без формы объекта нет `objectPresentation` и т.п.).
```json
"listPresentation": "Организации", "objectPresentation": { "ru": "Организация", "en": "Company" }
```
## Команды
Команды объекта. Ключ — имя команды, значение — объект свойств (map `имя → объект` или массив `[{name, …}]`).
Для каждой команды создаётся заготовка модуля с обработчиком `ОбработкаКоманды`.
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `synonym` | из имени | ML |
| `tooltip` | пусто | ML |
| `comment` | пусто | строка |
| `group` | **обязательно** | группа размещения (см. ниже) |
| `commandParameterType` | пусто | тип параметра (напр. `CatalogRef.Номенклатура`) — **только для групп формы** |
| `parameterUseMode` | `Single` | `Single` / `Multiple` |
| `modifiesData` | `false` | bool |
| `representation` | `Auto` | вид отображения |
| `picture` | пусто | ссылка на картинку (`StdPicture.Print`, `CommonPicture.Загрузка`) |
| `shortcut` | пусто | сочетание клавиш |
```json
"commands": {
"ПечатьЭтикеток": { "synonym": "Печать этикеток", "group": "FormCommandBarImportant",
"commandParameterType": "CatalogRef.Номенклатура", "picture": "StdPicture.Print" }
}
```
**Группа (`group`) обязательна** — каждая команда размещается в группе командного интерфейса:
- **Командный интерфейс раздела** (панель навигации / панель действий; `commandParameterType` **недоступен**):
`NavigationPanelImportant` / `NavigationPanelOrdinary` / `NavigationPanelSeeAlso`,
`ActionsPanelCreate` / `ActionsPanelReports` / `ActionsPanelTools`.
- **Командный интерфейс формы** (`commandParameterType` допустим): `FormCommandBarImportant` /
`FormCommandBarCreateBasedOn`, `FormNavigationPanelImportant` / `FormNavigationPanelGoTo` / `FormNavigationPanelSeeAlso`.
- **Кастомная группа:** `CommandGroup.<Имя>` (параметр допустим).
Группа раздела вместе с `commandParameterType` → ошибка.
## `inputByString` / `dataLockFields` / `basedOn`
Списки полей/объектов уровня объекта. Поля — по имени реквизита объекта (обычного или стандартного).
- **`inputByString`** — поля быстрого ввода по строке. По умолчанию выводятся из Кода/Наименования — ключ не нужен;
задать при другом наборе/порядке, либо `[]` для отключения.
```json
"inputByString": ["Код", "Наименование", "Контрагент"]
```
- **`dataLockFields`** — поля управляемой блокировки данных (по умолчанию пусто).
```json
"dataLockFields": ["Организация", "Контрагент"]
```
- **`basedOn`** — «ввод на основании»: список ссылок на объекты метаданных (по умолчанию пусто).
```json
"basedOn": ["Catalog.Контрагенты", "Document.ЗаказПоставщику"]
```
## `standardAttributes` — кастомизация стандартных реквизитов
Стандартные реквизиты объекта (Наименование, Код, Владелец, …) переопределяются блоком
`standardAttributes` — объект `{ ИмяРеквизита: { переопределения } }`. Имена — как в 1С: `Description`, `Code`,
`Owner`, `Parent`, `DeletionMark`, `Ref` и т.д. (для Document — `Date`, `Number`, `Posted`).
Переопределяемые поля — как у обычного реквизита (`synonym`, `tooltip`, `fillChecking`, `fillValue`,
`choiceParameters`, `comment`, `mask`, `choiceForm`; полный набор — `attributes.md`).
```json
"standardAttributes": {
"Description": { "synonym": "Наименование контрагента" },
"Code": { "fillChecking": "ShowError" }
}
```
## `characteristics` — «Дополнительные реквизиты и сведения»
Привязка плана видов характеристик. Массив; каждый элемент связывает **источник типов** (где определены
характеристики) и **источник значений** (где хранятся значения).
```json
"characteristics": [{
"types": { "from": "Catalog.НаборыДопРеквизитов.ДополнительныеРеквизиты",
"key": "Свойство", "filterField": "Ссылка", "filterValue": "Справочник_Организации" },
"values": { "from": "Catalog.Организации.TabularSection.ДополнительныеРеквизиты",
"object": "Ссылка", "type": "Свойство", "value": "Значение" }
}]
```
- `from` — таблица-источник; `key`/`filterField`/`object`/`type`/`value` — поля источника (по имени реквизита).
- `filterValue` — значение фильтра типов: имя предопределённого набора (строка) или путь к элементу.
@@ -0,0 +1,71 @@
# Catalog (Справочник)
```json
{ "type": "Catalog", "name": "Организации", "descriptionLength": 100,
"attributes": ["ИНН: String(12)", "КПП: String(9)"] }
```
## Свойства
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `comment` | пусто | строка |
| `hierarchical` | `false` | bool |
| `hierarchyType` | `HierarchyFoldersAndItems` | `HierarchyFoldersAndItems` / `HierarchyOfItems` |
| `limitLevelCount` | `false` | bool (ограничивать кол-во уровней) |
| `levelCount` | `2` | число уровней (при `limitLevelCount`) |
| `foldersOnTop` | `true` | bool (группы сверху) |
| `owners` | `[]` | массив ссылок-владельцев: `["CatalogRef.Контрагенты"]` |
| `subordinationUse` | `ToItems` | `ToItems` / `ToFolders` / `ToFoldersAndItems` (кому подчинён) |
| `codeLength` | `9` | длина кода (0 — без кода) |
| `codeType` | `String` | `String` / `Number` |
| `codeAllowedLength` | `Variable` | `Variable` / `Fixed` |
| `codeSeries` | `WholeCatalog` | `WholeCatalog` / `WithinSubordination` / `WithinOwnerSubordination` |
| `autonumbering` | `true` | bool (автонумерация) |
| `checkUnique` | `false` | bool (контроль уникальности кода) |
| `descriptionLength` | `25` | длина наименования |
| `defaultPresentation` | `AsDescription` | `AsDescription` / `AsCode` |
| `quickChoice` | `true` | bool (быстрый выбор) |
| `choiceMode` | `BothWays` | `BothWays` / `QuickChoice` / `FromForm` |
| `editType` | `InDialog` | `InDialog` / `InList` / `BothWays` |
| `createOnInput` | `Use` | `Auto` / `Use` / `DontUse` |
| `choiceHistoryOnInput` | `Auto` | `Auto` / `DontUse` |
| `fullTextSearch` | `Use` | `Use` / `DontUse` |
| `fullTextSearchOnInputByString` | `DontUse` | `Use` / `DontUse` |
| `searchStringModeOnInputByString` | `Begin` | `Begin` / `AnyPart` |
| `predefinedDataUpdate` | `Auto` | `Auto` / `DontAutoUpdate` / `AutoUpdate` |
| `dataLockControlMode` | `Managed` | `Automatic` / `Managed` |
| `useStandardCommands` | `true` | bool |
| `includeHelpInContents` | `false` | bool |
| `attributes` | `[]` | реквизиты (shorthand / объектная форма) |
| `tabularSections` | `{}` | табличные части |
**Формы.** Ссылка на форму — `Тип.Объект.Form.ИмяФормы` (напр. `Catalog.Организации.Form.ФормаЭлемента`).
Слоты основных форм: `defaultObjectForm`, `defaultFolderForm`, `defaultListForm`, `defaultChoiceForm`,
`defaultFolderChoiceForm`; вспомогательных — те же имена с префиксом `auxiliary` (`auxiliaryObjectForm`, …).
## `predefined` — предопределённые элементы
Массив предопределённых элементов → `Ext/Predefined.xml`. Элемент — строка (плоский случай) или объект (иерархия).
**Строка:** `"(Код) Имя [Наименование]"``Имя` обязательно; `(Код)` и `[Наименование]` опциональны.
Без `[...]` наименование выводится из имени; `[]` — пустое; `[текст]` — заданное.
```json
"predefined": [
"Основной",
"(1) ДокументОПриемке [Документ о приемке]",
{ "name": "Группа1", "isFolder": true, "description": "Прочие",
"childItems": ["Факс", "(7) Скайп"] }
]
```
**Объект:** `name` (обязательно), `code`, `description` (наименование), `isFolder` (признак группы),
`childItems` (вложенные, рекурсивно). Тип кода — по свойству `codeType`.
## Дополнительно
- Свойства реквизитов и табличных частей — `attributes.md`.
- Представления (`objectPresentation`, `listPresentation`, …), команды объекта, характеристики
(«ДопРеквизиты и сведения»), кастомизация стандартных реквизитов, `inputByString` / `dataLockFields` /
`basedOn``blocks.md`.
@@ -0,0 +1,105 @@
# Планы: ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes
Все три — ссылочные типы (наследуют слой Catalog: коды, `standardAttributes`, `characteristics`, `inputByString`,
формы, представления — см. `catalog.md` / `attributes.md` / `blocks.md`) с предопределёнными элементами и своими
специальными свойствами.
## ChartOfCharacteristicTypes (План видов характеристик)
Хранит определения характеристик (видов). Иерархический (папки+элементы).
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `valueType` | любой примитив | тип значения характеристики (составной — строка `"A + B"` или массив `valueTypes`) |
| `characteristicExtValues` | пусто | ссылка на справочник доп. значений |
| `hierarchical` | `false` | bool |
| `foldersOnTop` | `true` | bool |
| `codeLength` | `9` | длина кода |
| `descriptionLength` | `100` | длина наименования |
| `checkUnique` | `true` | bool |
| `autonumbering` | `true` | bool |
| `codeSeries` | `WholeCharacteristicKind` | серия кодов |
| `createOnInput` | `DontUse` | `Auto` / `Use` / `DontUse` |
| `dataLockControlMode` | `Managed` | `Automatic` / `Managed` |
| `predefined` | `[]` | предопределённые виды (несут тип значения — см. ниже) |
| `attributes` / `tabularSections` | `[]` / `{}` | реквизиты / табличные части |
**Предопределённые виды** несут **тип значения на элемент** — короткой строкой после `:`
(`"(Код) Имя [Наименование]: Тип"`, составной через `+`) или объектной формой с ключом `type`:
```json
"predefined": [
"(000001) Цвет: CatalogRef.Цвета",
"(000002) Размер [Размер одежды]: String(50) + Number(3,0)",
{ "name": "Группа", "isFolder": true, "type": "" }
]
```
## ChartOfAccounts (План счетов)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `extDimensionTypes` | пусто | ссылка на ПВХ видов субконто `ChartOfCharacteristicTypes.X` |
| `maxExtDimensionCount` | `0` (без ПВХ) / `3` (с ПВХ) | макс. число субконто |
| `codeMask` | пусто | маска кода счёта (напр. `"@@@.@@"`) |
| `codeLength` | `9` | длина кода |
| `descriptionLength` | `25` | длина наименования |
| `checkUnique` | `true` | bool |
| `codeSeries` | `WholeChartOfAccounts` | серия кодов |
| `defaultPresentation` | `AsCode` | `AsCode` / `AsDescription` |
| `autoOrderByCode` | `true` | bool |
| `orderLength` | `9` | длина строки упорядочивания |
| `createOnInput` | `DontUse` | `Auto` / `Use` / `DontUse` |
| `dataLockControlMode` | `Managed` | `Automatic` / `Managed` |
| `accountingFlags` | `[]` | признаки учёта (как реквизиты, тип по умолчанию Boolean; массив имён/реквизитов) |
| `extDimensionAccountingFlags` | `[]` | признаки учёта субконто (как реквизиты) |
| `predefined` | `[]` | предопределённые счета (см. ниже) |
**Предопределённый счёт** (объектная форма):
| Поле | Умолчание | Значения |
|------|-----------|----------|
| `name` | — | имя (обязательно) |
| `code` | пусто | код счёта |
| `description` | из имени | наименование |
| `accountType` | `ActivePassive` | `Active` / `Passive` / `ActivePassive` |
| `offBalance` | `false` | bool (забалансовый) |
| `order` | — | строка сортировки |
| `flags` | `[]` | включённые признаки учёта (только TRUE) |
| `subconto` | `[]` | виды субконто (см. ниже) |
| `childItems` | `[]` | подчинённые счета |
`subconto` — строка `"Вид | Признак1, Признак2"` (после `|` — включённые признаки учёта субконто; токен `Turnover`
«только обороты») или объект `{ type, turnover, flags }`. `Вид` — имя предопределённого вида из ПВХ `extDimensionTypes`.
```json
"predefined": [
{ "name": "ОсновныеСредства", "code": "01", "accountType": "Active", "order": " 01",
"flags": ["Количественный"], "subconto": ["Номенклатура | Суммовой, Валютный"],
"childItems": [ { "name": "ОСВОрганизации", "code": "01.01", "accountType": "Active", "order": " 01.01" } ] }
]
```
## ChartOfCalculationTypes (План видов расчёта)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `codeLength` | `5` | длина кода |
| `descriptionLength` | `100` | длина наименования |
| `codeAllowedLength` | `Variable` | `Variable` / `Fixed` |
| `dependenceOnCalculationTypes` | `DontUse` | `DontUse` / `OnPeriod` / `OnActionPeriod` |
| `baseCalculationTypes` | `[]` | базовые виды расчёта (список ссылок `ChartOfCalculationTypes.X`) |
| `actionPeriodUse` | `false` | bool (использовать период действия) |
| `createOnInput` | `DontUse` | `Auto` / `Use` / `DontUse` |
| `dataLockControlMode` | `Managed` | `Automatic` / `Managed` |
| `predefined` | `[]` | предопределённые виды расчёта (см. ниже) |
**Предопределённый вид расчёта** — плоский: строка `"(Код) Имя [Наименование]"` или объект
`{ name, code, description, actionPeriodIsBase }` (`actionPeriodIsBase` — bool, по умолчанию `false`).
```json
"predefined": [ "(00001) Оклад [Оклад по дням]", { "name": "Премия", "code": "00002", "actionPeriodIsBase": true } ]
```
> **ChartOfAccounts** ссылается на ПВХ через `extDimensionTypes`. Регистр бухгалтерии/расчёта требует
> соответствующий план (см. `registers.md`).
@@ -0,0 +1,56 @@
# CommonModule, ScheduledJob, EventSubscription (объекты, привязанные к коду)
## CommonModule (Общий модуль)
Флаги контекста выполнения (все bool, по умолчанию `false`). Создаёт пустой `Ext/Module.bsl`.
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `context` | — | шорткат флагов (см. ниже) |
| `global` | `false` | bool |
| `server` | `false` | bool |
| `serverCall` | `false` | bool (вызов сервера) |
| `clientManagedApplication` | `false` | bool (клиент управляемого приложения) |
| `clientOrdinaryApplication` | `false` | bool (клиент обычного приложения) |
| `externalConnection` | `false` | bool |
| `privileged` | `false` | bool |
| `returnValuesReuse` | `DontUse` | `DontUse` / `DuringRequest` / `DuringSession` |
Шорткат `context`: `"server"` → Server+ServerCall; `"client"` → ClientManagedApplication;
`"serverClient"` → Server+ClientManagedApplication.
```json
{ "type": "CommonModule", "name": "ОбменДаннымиСервер", "context": "server", "returnValuesReuse": "DuringRequest" }
```
## ScheduledJob (Регламентное задание)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `methodName` | пусто | метод-обработчик `"МодульСервер.Процедура"` (дополняется до `CommonModule.…`) |
| `description` | пусто | наименование задания |
| `key` | пусто | ключ |
| `use` | `false` | bool (использование) |
| `predefined` | `false` | bool (предопределённое) |
| `restartCountOnFailure` | `3` | число повторов при сбое |
| `restartIntervalOnFailure` | `10` | интервал повтора, сек |
```json
{ "type": "ScheduledJob", "name": "ОбменДанными", "methodName": "ОбменДаннымиСервер.Выполнить", "use": true }
```
## EventSubscription (Подписка на событие)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `source` | `[]` | объекты-источники: `["CatalogObject.Контрагенты", "DocumentObject.Реализация"]` |
| `event` | `BeforeWrite` | `BeforeWrite` / `OnWrite` / `BeforeDelete` / `OnReadAtServer` / `FillCheckProcessing` … |
| `handler` | пусто | метод-обработчик `"МодульСервер.Процедура"` (дополняется до `CommonModule.…`) |
```json
{ "type": "EventSubscription", "name": "ПередЗаписьюКонтрагента",
"source": ["CatalogObject.Контрагенты"], "event": "BeforeWrite",
"handler": "ОбщегоНазначенияСервер.ПередЗаписьюКонтрагента" }
```
> Процедура-обработчик (`methodName` / `handler`) должна существовать в указанном общем модуле (экспортная).
@@ -0,0 +1,79 @@
# Document, DocumentJournal, Sequence, DocumentNumerator
## Document (Документ)
```json
{ "type": "Document", "name": "ПриходнаяНакладная",
"registerRecords": ["AccumulationRegister.ОстаткиТоваров"],
"attributes": ["Организация: CatalogRef.Организации"],
"tabularSections": { "Товары": ["Номенклатура: CatalogRef.Номенклатура", "Количество: Number(15,3)"] } }
```
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `comment` | пусто | строка |
| `numerator` | пусто | ссылка на нумератор `DocumentNumerator.X` |
| `numberType` | `String` | `String` / `Number` |
| `numberLength` | `11` | длина номера |
| `numberAllowedLength` | `Variable` | `Variable` / `Fixed` |
| `numberPeriodicity` | `Year` | `Nonperiodical` / `Day` / `Month` / `Quarter` / `Year` |
| `checkUnique` | `true` | bool |
| `autonumbering` | `true` | bool |
| `posting` | `Allow` | `Allow` / `Deny` (проведение) |
| `realTimePosting` | `Deny` | `Allow` / `Deny` (оперативное проведение) |
| `registerRecordsDeletion` | `AutoDelete` | `AutoDelete` / `AutoDeleteOnUnpost` / `AutoDeleteOff` |
| `registerRecordsWritingOnPost` | `WriteSelected` | `WriteModified` / `WriteSelected` / `WriteAll` |
| `sequenceFilling` | `AutoFill` | заполнение последовательностей |
| `postInPrivilegedMode` | `true` | bool |
| `unpostInPrivilegedMode` | `true` | bool |
| `createOnInput` | `Use` | `Auto` / `Use` / `DontUse` |
| `dataLockControlMode` | `Managed` | `Automatic` / `Managed` |
| `fullTextSearch` | `Use` | `Use` / `DontUse` |
| `dataHistory` | `DontUse` | `Use` / `DontUse` |
| `registerRecords` | `[]` | движения: список ссылок `["AccumulationRegister.ОстаткиТоваров", "InformationRegister.Цены"]` |
| `useStandardCommands` | `true` | bool |
| `includeHelpInContents` | `false` | bool |
| `attributes` / `tabularSections` | `[]` / `{}` | реквизиты / табличные части |
Формы: `defaultObjectForm`, `defaultListForm`, `defaultChoiceForm`, `auxiliary*` (см. `catalog.md`).
Реквизиты и ТЧ — `attributes.md`. Представления, команды, характеристики, `basedOn`, `standardAttributes`,
`inputByString`, `dataLockFields``blocks.md`.
## DocumentJournal (Журнал документов)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `registeredDocuments` | `[]` | документы журнала: `["Document.Встреча", "Document.Звонок"]` |
| `columns` | `[]` | графы журнала (см. ниже) |
Графа — строка `"Имя"` или объект `{ name, synonym, indexing, references }`, где `indexing``Index`/`DontIndex`,
`references` — пути к реквизитам документов, отображаемым в графе.
```json
{ "type": "DocumentJournal", "name": "Взаимодействия",
"registeredDocuments": ["Document.Встреча", "Document.Звонок"],
"columns": [{ "name": "Организация", "indexing": "Index",
"references": ["Document.Встреча.Attribute.Организация"] }] }
```
## Sequence (Последовательность документов)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `moveBoundaryOnPosting` | `DontMove` | сдвиг границы при проведении |
| `documents` | `[]` | документы последовательности (список ссылок) |
| `registerRecords` | `[]` | движения (список ссылок) |
| `dataLockControlMode` | `Managed` | `Automatic` / `Managed` |
| `dimensions` | `[]` | измерения `{name, type, documentMap[], registerRecordsMap[]}` |
`documentMap` / `registerRecordsMap` — пути к реквизитам документов / движениям, соответствующим измерению.
## DocumentNumerator (Нумератор документов)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `numberType` | `String` | `String` / `Number` |
| `numberLength` | `11` | длина номера |
| `numberAllowedLength` | `Variable` | `Variable` / `Fixed` |
| `numberPeriodicity` | `Year` | `Nonperiodical` / `Day` / … / `Year` |
| `checkUnique` | `true` | bool |
@@ -0,0 +1,41 @@
# ExchangePlan (План обмена)
Близок к справочнику (без иерархии/владельцев), плюс состав объектов обмена. Наследует слой Catalog:
`codeLength`, `codeAllowedLength`, `descriptionLength`, `defaultPresentation`, `editType`, `quickChoice`,
`choiceMode`, формы, `standardAttributes`, `characteristics`, `inputByString`, `basedOn`, представления —
см. `catalog.md` / `attributes.md` / `blocks.md`.
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `comment` | пусто | строка |
| `distributedInfoBase` | `false` | bool (распределённая ИБ — РИБ) |
| `includeConfigurationExtensions` | `false` | bool (включать расширения конфигурации) |
| `descriptionLength` | `150` | длина наименования |
| `createOnInput` | `DontUse` | `Auto` / `Use` / `DontUse` |
| `dataLockControlMode` | `Managed` | `Automatic` / `Managed` |
| `dataHistory` | `DontUse` | `Use` / `DontUse` |
| `useStandardCommands` | `true` | bool |
| `content` | `[]` | состав обмена (см. ниже) |
| `attributes` / `tabularSections` | `[]` / `{}` | реквизиты / табличные части |
## `content` — состав плана обмена
Список объектов-участников обмена; у каждого — признак авторегистрации изменений (по умолчанию выключена).
Элемент — ссылка на объект метаданных (строка) или объект с признаком:
```json
"content": [
"Catalog.Организации", // авторегистрация выключена
"InformationRegister.Курсы: autoRecord", // авторегистрация включена (токен)
{ "metadata": "Document.РеализацияТоваров", "autoRecord": true }
]
```
- Строка `"Тип.Имя"` — авторегистрация выключена; суффикс `: autoRecord` — включена.
- Объект: `metadata` (ссылка), `autoRecord` (bool или `Allow`/`Deny`).
```json
{ "type": "ExchangePlan", "name": "ОбменССайтом", "distributedInfoBase": false,
"content": ["Catalog.Номенклатура: autoRecord", "Catalog.Контрагенты: autoRecord"],
"attributes": ["АдресСервера: String(200)"] }
```
@@ -0,0 +1,90 @@
# Прочие типы
Редкие/служебные объекты. Каждый — минимальный набор свойств.
## FunctionalOption (Функциональная опция)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `location` | пусто | где хранится значение: `Constant.X` / `InformationRegister.X.Resource.Y` / `<Тип>.X.Attribute.Y` |
| `content` | `[]` | реквизиты/измерения/ресурсы, зависящие от опции (полные пути к объектам) |
| `privilegedGetMode` | `true` | bool |
| `comment` | пусто | строка |
```json
{ "type": "FunctionalOption", "name": "ВестиУчетПоСкладам", "location": "Constant.ВестиУчетПоСкладам",
"content": ["Document.РеализацияТоваров.TabularSection.Товары.Attribute.Склад"] }
```
## FilterCriterion (Критерий отбора)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `valueType` | — | тип значения отбора (составной через `+`) |
| `content` | `[]` | реквизиты, по которым идёт отбор (пути к объектам) |
| `useStandardCommands` | `true` | bool |
| `defaultForm` / `auxiliaryForm` | пусто | формы |
| `comment` | пусто | строка |
```json
{ "type": "FilterCriterion", "name": "ДокументыПоКонтрагенту", "valueType": "CatalogRef.Контрагенты",
"content": ["Document.Реализация.Attribute.Контрагент"] }
```
## SettingsStorage (Хранилище настроек)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `defaultSaveForm` / `defaultLoadForm` | пусто | формы сохранения / загрузки |
| `auxiliarySaveForm` / `auxiliaryLoadForm` | пусто | вспомогательные формы |
| `comment` | пусто | строка |
## CommonForm (Общая форма)
Создаёт метаданные + заготовку формы. Содержимое формы наполняется `/form-compile` или `/form-edit`.
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `formType` | `Managed` | тип формы |
| `usePurposes` | `[PlatformApplication, MobilePlatformApplication]` | назначение (массив) |
| `useStandardCommands` | `false` | bool |
| `includeHelpInContents` | `false` | bool |
| `comment` | пусто | строка |
```json
{ "type": "CommonForm", "name": "НастройкиОбмена", "usePurposes": ["PlatformApplication"] }
```
## CommonPicture / CommonTemplate (Общие картинки и макеты)
Только метаданные + регистрация; содержимое (`Ext/Picture*`, `Ext/Template.*`) импортируется отдельно
(для табличного макета — `/mxl-compile`).
- **CommonPicture** — `availabilityForChoice` / `availabilityForAppearance` (bool, по умолчанию `false`).
- **CommonTemplate** — `templateType` (`SpreadsheetDocument` по умолчанию / `TextDocument` / `HTMLDocument` /
`BinaryData` / `AddIn` / `DataCompositionSchema` / `DataCompositionAppearanceTemplate` / `GraphicalSchema`).
```json
{ "type": "CommonTemplate", "name": "ПечатьЗаказа", "templateType": "SpreadsheetDocument" }
```
## Служебные типы
- **SessionParameter** (параметр сеанса) — `valueType` (тип значения, составной через `+`).
- **FunctionalOptionsParameter** (параметр функциональной опции) — `use` (массив измерений/реквизитов).
- **WSReference** (WS-ссылка) — `locationURL` (URL WSDL).
- **CommandGroup** (группа команд) — `category` (по умолч. `NavigationPanel`) — где размещается группа:
`NavigationPanel` / `ActionsPanel` (командный интерфейс раздела) или `FormCommandBar` / `FormNavigationPanel`
(командный интерфейс формы); `representation` (`Auto`), `tooltip` (ML), `picture`. Команды объекта ссылаются на
группу через `group: "CommandGroup.<Имя>"` (см. `blocks.md`).
- **CommonCommand** (общая команда) — `group`, `representation`, `tooltip`, `picture`, `shortcut`,
`commandParameterType`, `parameterUseMode` (`Single`/`Multiple`), `modifiesData`, `includeHelpInContents`.
Создаёт `Ext/CommandModule.bsl`.
- **CommonAttribute** (общий реквизит) — `valueType` (по умолчанию `String(0)`) + свойства реквизита
(`attributes.md`) + `content` (объекты, куда входит реквизит) + свойства разделения данных
(`dataSeparation`, `separatedDataUse`, `usersSeparation`, … — по умолчанию `DontUse`/`Independently`).
```json
{ "type": "CommonAttribute", "name": "Организация", "valueType": "CatalogRef.Организации",
"autoUse": "Use", "content": ["Document.РеализацияТоваров", "Document.ПоступлениеТоваров"] }
```
@@ -0,0 +1,49 @@
# BusinessProcess, Task (Бизнес-процессы и Задачи)
Ссылочные типы. Наследуют слой Catalog (нумерация, формы, `standardAttributes`, `characteristics`, `basedOn`,
представления — см. `catalog.md` / `attributes.md` / `blocks.md`). Бизнес-процесс всегда связан с задачей.
## BusinessProcess (Бизнес-процесс)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `task` | пусто | ссылка на задачу `Task.X` (обязательна для рабочего БП) |
| `numberType` | `String` | `String` / `Number` |
| `numberLength` | `11` | длина номера |
| `checkUnique` | `true` | bool |
| `autonumbering` | `true` | bool |
| `createOnInput` | `DontUse` | `Auto` / `Use` / `DontUse` |
| `dataLockControlMode` | `Managed` | `Automatic` / `Managed` |
| `attributes` / `tabularSections` | `[]` / `{}` | реквизиты / табличные части |
Создаётся с картой маршрута (`Ext/Flowchart.xml`) и модулем объекта.
```json
{ "type": "BusinessProcess", "name": "Согласование", "task": "Task.ЗадачаИсполнителя",
"attributes": ["Документ: DocumentRef.ЗаявкаНаРасход"] }
```
## Task (Задача)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `numberType` | `String` | `String` / `Number` |
| `numberLength` | `14` | длина номера |
| `checkUnique` | `true` | bool |
| `autonumbering` | `true` | bool |
| `descriptionLength` | `150` | длина наименования |
| `addressing` | пусто | ссылка на регистр сведений адресации `InformationRegister.X` |
| `mainAddressingAttribute` | пусто | основной реквизит адресации (имя реквизита адресации) |
| `currentPerformer` | пусто | реквизит текущего исполнителя |
| `createOnInput` | `DontUse` | `Auto` / `Use` / `DontUse` |
| `dataLockControlMode` | `Managed` | `Automatic` / `Managed` |
| `addressingAttributes` | `[]` | реквизиты адресации (см. ниже) |
| `attributes` / `tabularSections` | `[]` / `{}` | реквизиты / табличные части |
**Реквизит адресации** — shorthand `"Имя: Тип"` или объект `{ name, type, addressingDimension }`
(`addressingDimension` — измерение регистра адресации).
```json
{ "type": "Task", "name": "ЗадачаИсполнителя",
"addressingAttributes": ["Исполнитель: CatalogRef.Пользователи", "Роль: CatalogRef.Роли"] }
```
@@ -0,0 +1,76 @@
# Регистры: Information, Accumulation, Accounting, Calculation
**Измерения и ресурсы** задаются как реквизиты (shorthand `"Имя: Тип | флаги"` или объектная форма, см.
`attributes.md`). Флаги измерений: `master`, `mainFilter`, `denyIncomplete`, `useInTotals` (регистр накопления).
```json
"dimensions": ["Организация: CatalogRef.Организации | master, mainFilter"],
"resources": ["Сумма: Number(15,2)"]
```
## InformationRegister (Регистр сведений)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `writeMode` | `Independent` | `Independent` / `RecorderSubordinate` |
| `periodicity` | `Nonperiodical` | `Nonperiodical` / `Second` / `Day` / `Month` / `Quarter` / `Year` / `RecorderPosition` |
| `mainFilterOnPeriod` | `false` | bool (основной отбор по периоду) |
| `dataLockControlMode` | `Managed` | `Automatic` / `Managed` |
| `dimensions` / `resources` / `attributes` | `[]` | измерения / ресурсы / реквизиты |
```json
{ "type": "InformationRegister", "name": "КурсыВалют", "periodicity": "Day",
"dimensions": ["Валюта: CatalogRef.Валюты | master, mainFilter, denyIncomplete"],
"resources": ["Курс: Number(15,4)", "Кратность: Number(10,0)"] }
```
## AccumulationRegister (Регистр накопления)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `registerType` | `Balance` | `Balance` (остатки) / `Turnovers` (обороты) |
| `enableTotalsSplitting` | `true` | bool (разделение итогов) |
| `dataLockControlMode` | `Managed` | `Automatic` / `Managed` |
| `dimensions` / `resources` / `attributes` | `[]` | измерения / ресурсы / реквизиты |
```json
{ "type": "AccumulationRegister", "name": "ОстаткиТоваров", "registerType": "Balance",
"dimensions": ["Номенклатура: CatalogRef.Номенклатура", "Склад: CatalogRef.Склады"],
"resources": ["Количество: Number(15,3)"] }
```
## AccountingRegister (Регистр бухгалтерии)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `chartOfAccounts` | — | **обязательно**: ссылка на план счетов `ChartOfAccounts.X` |
| `correspondence` | `false` | bool (корреспонденция) |
| `periodAdjustmentLength` | `0` | длина периода корректировки |
| `dataLockControlMode` | `Managed` | `Automatic` / `Managed` |
| `dimensions` / `resources` / `attributes` | `[]` | измерения / ресурсы / реквизиты |
```json
{ "type": "AccountingRegister", "name": "Хозрасчетный",
"chartOfAccounts": "ChartOfAccounts.Хозрасчетный",
"dimensions": ["Организация: CatalogRef.Организации"], "resources": ["Сумма: Number(15,2)"] }
```
## CalculationRegister (Регистр расчёта)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `chartOfCalculationTypes` | — | **обязательно**: ссылка на ПВР `ChartOfCalculationTypes.X` |
| `periodicity` | `Month` | периодичность |
| `actionPeriod` | `false` | bool (период действия) |
| `basePeriod` | `false` | bool (базовый период) |
| `schedule` | пусто | ссылка на регистр сведений графиков |
| `dataLockControlMode` | `Managed` | `Automatic` / `Managed` |
| `dimensions` / `resources` / `attributes` | `[]` | измерения / ресурсы / реквизиты |
```json
{ "type": "CalculationRegister", "name": "Начисления",
"chartOfCalculationTypes": "ChartOfCalculationTypes.Начисления", "periodicity": "Month",
"dimensions": ["Сотрудник: CatalogRef.Сотрудники"], "resources": ["Сумма: Number(15,2)"] }
```
> **AccountingRegister** требует план счетов, **CalculationRegister** — план видов расчёта (и оба — документ-регистратор).
@@ -0,0 +1,45 @@
# Report, DataProcessor (Отчёты и Обработки)
Почти идентичны по составу: реквизиты, табличные части, формы, макеты, команды. Модуль объекта — `Ext/ObjectModule.bsl`.
Реквизиты и ТЧ — `attributes.md`; команды — `blocks.md`.
Ссылки на формы/схемы/хранилища пишутся **как есть** (имя формы может быть буквально «Форма»).
## Report (Отчёт)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `comment` | пусто | строка |
| `useStandardCommands` | `true` | bool (доступность через стандартный командный интерфейс) |
| `mainDataCompositionSchema` | пусто | основной макет СКД (`Report.X.Template.ОсновнаяСхемаКомпоновкиДанных`) |
| `defaultForm` / `auxiliaryForm` | пусто | основная / вспомогательная форма |
| `defaultSettingsForm` / `auxiliarySettingsForm` / `defaultVariantForm` | пусто | формы настроек / вариантов |
| `variantsStorage` / `settingsStorage` | пусто | хранилища вариантов / настроек (`SettingsStorage.X`) |
| `extendedPresentation` / `explanation` | пусто | представление / пояснение (ML) |
| `includeHelpInContents` | `false` | bool |
| `attributes` / `tabularSections` | `[]` / `{}` | реквизиты / табличные части |
```json
{ "type": "Report", "name": "АнализПродаж", "useStandardCommands": false,
"mainDataCompositionSchema": "Report.АнализПродаж.Template.ОсновнаяСхемаКомпоновкиДанных",
"attributes": ["Период: StandardPeriod"] }
```
## DataProcessor (Обработка)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `comment` | пусто | строка |
| `useStandardCommands` | `true` | bool |
| `defaultForm` / `auxiliaryForm` | пусто | основная / вспомогательная форма |
| `extendedPresentation` / `explanation` | пусто | представление / пояснение (ML) |
| `includeHelpInContents` | `false` | bool |
| `attributes` / `tabularSections` | `[]` / `{}` | реквизиты / табличные части |
```json
{ "type": "DataProcessor", "name": "ЗагрузкаТаблиц", "useStandardCommands": false,
"attributes": [{ "name": "Таблица", "type": "ValueTree" }, { "name": "Произвольные", "type": "" }] }
```
> Реквизиты отчётов/обработок допускают платформенные типы-коллекции: `ValueTable`, `ValueTree`, `ValueList`,
> `StandardPeriod`, `SpreadsheetDocument` и др., а также `"type": ""` — реквизит без типа.
@@ -0,0 +1,40 @@
# Enum, Constant, DefinedType
## Enum (Перечисление)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `values` | `[]` | значения перечисления (массив имён или объектов) |
Значение — строка `"ИмяЗначения"` или объект `{ name, synonym }`.
```json
{ "type": "Enum", "name": "Статусы", "values": ["Новый", "ВРаботе", "Закрыт"] }
```
## Constant (Константа)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `valueType` | `String` | тип значения (shorthand типа) |
| `dataLockControlMode` | `Managed` | `Automatic` / `Managed` |
`valueType` принимает shorthand: `"String(100)"`, `"Number(15,2)"`, `"Boolean"`, `"CatalogRef.Валюты"`,
составной через `+`.
```json
{ "type": "Constant", "name": "ОсновнаяВалюта", "valueType": "CatalogRef.Валюты" }
```
## DefinedType (Определяемый тип)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `valueTypes` | `[]` | состав типа (массив shorthand-типов) |
| `valueType` | — | то же одной строкой (`"A + B"`) или строкой одного типа |
```json
{ "type": "DefinedType", "name": "ДенежныеСредства",
"valueTypes": ["CatalogRef.БанковскиеСчета", "CatalogRef.Кассы"] }
{ "type": "DefinedType", "name": "ФлагАктивности", "valueType": "Boolean" }
```
@@ -1,116 +0,0 @@
# Базовые типы: Catalog, Document, Enum, Constant, DefinedType, Report, DataProcessor
## Catalog
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `hierarchical` | `false` | Hierarchical |
| `hierarchyType` | `HierarchyFoldersAndItems` | HierarchyType |
| `limitLevelCount` | `false` | LimitLevelCount |
| `levelCount` | `2` | LevelCount |
| `foldersOnTop` | `true` | FoldersOnTop |
| `codeLength` | `9` | CodeLength |
| `codeType` | `String` | CodeType |
| `codeAllowedLength` | `Variable` | CodeAllowedLength |
| `codeSeries` | `WholeCatalog` | CodeSeries |
| `descriptionLength` | `25` | DescriptionLength |
| `autonumbering` | `true` | Autonumbering |
| `checkUnique` | `false` | CheckUnique |
| `defaultPresentation` | `AsDescription` | DefaultPresentation |
| `subordinationUse` | `ToItems` | SubordinationUse |
| `quickChoice` | `false` | QuickChoice |
| `choiceMode` | `BothWays` | ChoiceMode |
| `owners` | `[]` | Owners |
| `attributes` | `[]` | → Attribute в ChildObjects |
| `tabularSections` | `{}` | → TabularSection в ChildObjects |
```json
{ "type": "Catalog", "name": "Организации", "attributes": ["ИНН: String(12)", "КПП: String(9)"] }
```
## Document
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `numberType` | `String` | NumberType |
| `numberLength` | `11` | NumberLength |
| `numberAllowedLength` | `Variable` | NumberAllowedLength |
| `numberPeriodicity` | `Year` | NumberPeriodicity |
| `checkUnique` | `true` | CheckUnique |
| `autonumbering` | `true` | Autonumbering |
| `posting` | `Allow` | Posting |
| `realTimePosting` | `Deny` | RealTimePosting |
| `registerRecordsDeletion` | `AutoDelete` | RegisterRecordsDeletion |
| `registerRecordsWritingOnPost` | `WriteModified` | RegisterRecordsWritingOnPost |
| `postInPrivilegedMode` | `true` | PostInPrivilegedMode |
| `unpostInPrivilegedMode` | `true` | UnpostInPrivilegedMode |
| `registerRecords` | `[]` | RegisterRecords |
| `attributes` | `[]` | → Attribute в ChildObjects |
| `tabularSections` | `{}` | → TabularSection в ChildObjects |
RegisterRecords — массив строк: `"AccumulationRegister.Продажи"`, `"InformationRegister.Цены"`.
```json
{
"type": "Document", "name": "ПриходнаяНакладная",
"registerRecords": ["AccumulationRegister.ОстаткиТоваров"],
"attributes": ["Организация: CatalogRef.Организации", "Контрагент: CatalogRef.Контрагенты"],
"tabularSections": { "Товары": ["Номенклатура: CatalogRef.Номенклатура", "Количество: Number(15,3)"] }
}
```
## Enum
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `values` | `[]` | → EnumValue в ChildObjects |
```json
{ "type": "Enum", "name": "Статусы", "values": ["Новый", "ВРаботе", "Закрыт"] }
```
## Constant
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `valueType` | `String` | Type |
`valueType` принимает shorthand типа: `"String(100)"`, `"Number(15,2)"`, `"Boolean"`, `"CatalogRef.Валюты"`.
```json
{ "type": "Constant", "name": "ОсновнаяВалюта", "valueType": "CatalogRef.Валюты" }
```
## DefinedType
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `valueTypes` | `[]` | Type (составной тип) |
| `valueType` | — | Алиас для `valueTypes` (строка или массив) |
```json
{ "type": "DefinedType", "name": "ДенежныеСредства", "valueTypes": ["CatalogRef.БанковскиеСчета", "CatalogRef.Кассы"] }
{ "type": "DefinedType", "name": "ФлагАктивности", "valueType": "Boolean" }
```
## Report
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `attributes` | `[]` | → Attribute в ChildObjects |
| `tabularSections` | `{}` | → TabularSection в ChildObjects |
```json
{ "type": "Report", "name": "ОстаткиТоваров" }
```
## DataProcessor
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `attributes` | `[]` | → Attribute в ChildObjects |
| `tabularSections` | `{}` | → TabularSection в ChildObjects |
```json
{ "type": "DataProcessor", "name": "ЗагрузкаДанных", "attributes": ["ПутьКФайлу: String(500)"] }
```
@@ -1,136 +0,0 @@
# Процессы и сервисные: BusinessProcess, Task, ExchangePlan, CommonModule, ScheduledJob, EventSubscription, DocumentJournal
## BusinessProcess
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `task` | `""` | Task (ссылка `Task.XXX`) |
| `numberType` | `String` | NumberType |
| `numberLength` | `11` | NumberLength |
| `checkUnique` | `true` | CheckUnique |
| `autonumbering` | `true` | Autonumbering |
| `attributes` | `[]` | → Attribute |
| `tabularSections` | `{}` | → TabularSection |
Модули: `Ext/ObjectModule.bsl`, `Ext/Flowchart.xml`.
```json
{ "type": "BusinessProcess", "name": "Задание", "task": "Task.ЗадачаИсполнителя", "attributes": ["Описание: String(200)"] }
```
## Task
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `numberType` | `String` | NumberType |
| `numberLength` | `14` | NumberLength |
| `checkUnique` | `true` | CheckUnique |
| `autonumbering` | `true` | Autonumbering |
| `descriptionLength` | `150` | DescriptionLength |
| `addressing` | `""` | Addressing (ссылка на РС адресации) |
| `mainAddressingAttribute` | `""` | MainAddressingAttribute |
| `currentPerformer` | `""` | CurrentPerformer |
| `attributes` | `[]` | → Attribute |
| `tabularSections` | `{}` | → TabularSection |
| `addressingAttributes` | `[]` | → AddressingAttribute (shorthand или объект) |
AddressingAttribute — shorthand `"Имя: Тип"` или объект `{ "name", "type", "addressingDimension" }`.
```json
{
"type": "Task", "name": "ЗадачаИсполнителя",
"addressingAttributes": ["Исполнитель: CatalogRef.Пользователи"]
}
```
## ExchangePlan
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `codeLength` | `9` | CodeLength |
| `descriptionLength` | `100` | DescriptionLength |
| `distributedInfoBase` | `false` | DistributedInfoBase |
| `attributes` | `[]` | → Attribute |
| `tabularSections` | `{}` | → TabularSection |
Модули: `Ext/ObjectModule.bsl`, `Ext/Content.xml`.
```json
{ "type": "ExchangePlan", "name": "ОбменССайтом", "attributes": ["АдресСервера: String(200)"] }
```
## CommonModule
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `context` | — | Шорткат (см. ниже) |
| `global` | `false` | Global |
| `server` | `false` | Server |
| `serverCall` | `false` | ServerCall |
| `clientManagedApplication` | `false` | ClientManagedApplication |
| `externalConnection` | `false` | ExternalConnection |
| `privileged` | `false` | Privileged |
| `returnValuesReuse` | `DontUse` | ReturnValuesReuse |
Шорткаты `context`: `"server"` → Server+ServerCall, `"client"` → ClientManagedApplication, `"serverClient"` → Server+ClientManagedApplication.
```json
{ "type": "CommonModule", "name": "ОбщиеФункции", "context": "serverClient" }
```
## ScheduledJob
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `methodName` | `""` | MethodName |
| `description` | = synonym | Description |
| `use` | `false` | Use |
| `predefined` | `false` | Predefined |
| `restartCountOnFailure` | `3` | RestartCountOnFailure |
| `restartIntervalOnFailure` | `10` | RestartIntervalOnFailure |
Формат `methodName`: `"МодульСервер.Процедура"` — авто-дополняется до `CommonModule.МодульСервер.Процедура`.
```json
{ "type": "ScheduledJob", "name": "ОбменДанными", "methodName": "ОбменДаннымиСервер.Выполнить" }
```
## EventSubscription
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `source` | `[]` | Source (массив, формат `XxxObject.Name`) |
| `event` | `BeforeWrite` | Event |
| `handler` | `""` | Handler |
Формат `handler`: `"МодульСервер.Процедура"` — авто-дополняется до `CommonModule.МодульСервер.Процедура`.
Значения `event`: `BeforeWrite`, `OnWrite`, `BeforeDelete`, `OnReadAtServer`, `FillCheckProcessing`.
Формат `source`: `"CatalogObject.Xxx"`, `"DocumentObject.Xxx"`.
```json
{ "type": "EventSubscription", "name": "ПередЗаписью", "source": ["CatalogObject.Контрагенты"], "event": "BeforeWrite", "handler": "ОбщиеФункции.ПередЗаписью" }
```
## DocumentJournal
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `registeredDocuments` | `[]` | RegisteredDocuments (массив `"Document.Xxx"`) |
| `columns` | `[]` | → Column |
Колонки — строка `"Имя"` или объект `{ "name", "synonym", "indexing": "Index"/"DontIndex", "references": ["Document.Xxx.Attribute.Yyy"] }`.
```json
{
"type": "DocumentJournal", "name": "Взаимодействия",
"registeredDocuments": ["Document.Встреча", "Document.Звонок"],
"columns": [{ "name": "Организация", "indexing": "Index", "references": ["Document.Встреча.Attribute.Организация"] }]
}
```
## Зависимости
- **ScheduledJob/EventSubscription** — процедура-обработчик должна существовать в модуле (экспортная)
- **BusinessProcess** → `Task` (задача должна существовать)
@@ -1,174 +0,0 @@
# Регистры и планы: InformationRegister, AccumulationRegister, AccountingRegister, CalculationRegister, ChartOfAccounts, ChartOfCharacteristicTypes, ChartOfCalculationTypes
## Измерения и ресурсы (общее)
Синтаксис аналогичен реквизитам (shorthand `"Имя: Тип | флаги"`).
Флаги измерений: `master`, `mainFilter`, `denyIncomplete`, `useInTotals` (AccumulationRegister only, default `true`).
```json
"dimensions": ["Организация: CatalogRef.Организации | master, mainFilter, denyIncomplete"],
"resources": ["Сумма: Number(15,2)"]
```
---
## InformationRegister
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `writeMode` | `Independent` | WriteMode |
| `periodicity` | `Nonperiodical` | InformationRegisterPeriodicity |
| `mainFilterOnPeriod` | авто* | MainFilterOnPeriod |
| `dimensions` | `[]` | → Dimension |
| `resources` | `[]` | → Resource |
| `attributes` | `[]` | → Attribute |
\* `mainFilterOnPeriod` = `true` если `periodicity` != `Nonperiodical`.
```json
{
"type": "InformationRegister", "name": "КурсыВалют", "periodicity": "Day",
"dimensions": ["Валюта: CatalogRef.Валюты | master, mainFilter, denyIncomplete"],
"resources": ["Курс: Number(15,4)", "Кратность: Number(10,0)"]
}
```
## AccumulationRegister
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `registerType` | `Balance` | RegisterType (`Balance` / `Turnovers`) |
| `enableTotalsSplitting` | `true` | EnableTotalsSplitting |
| `dimensions` | `[]` | → Dimension |
| `resources` | `[]` | → Resource |
| `attributes` | `[]` | → Attribute |
```json
{
"type": "AccumulationRegister", "name": "ОстаткиТоваров", "registerType": "Balance",
"dimensions": ["Номенклатура: CatalogRef.Номенклатура"],
"resources": ["Количество: Number(15,3)"]
}
```
## AccountingRegister
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `chartOfAccounts` | `""` | ChartOfAccounts (**обязательная** ссылка на план счетов) |
| `correspondence` | `false` | Correspondence |
| `periodAdjustmentLength` | `0` | PeriodAdjustmentLength |
| `dimensions` | `[]` | → Dimension |
| `resources` | `[]` | → Resource |
| `attributes` | `[]` | → Attribute |
```json
{
"type": "AccountingRegister", "name": "Хозрасчетный",
"chartOfAccounts": "ChartOfAccounts.Хозрасчетный",
"dimensions": ["Организация: CatalogRef.Организации"],
"resources": ["Сумма: Number(15,2)"]
}
```
## CalculationRegister
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `chartOfCalculationTypes` | `""` | ChartOfCalculationTypes (**обязательная** ссылка на ПВР) |
| `periodicity` | `Month` | Periodicity |
| `actionPeriod` | `false` | ActionPeriod |
| `basePeriod` | `false` | BasePeriod |
| `schedule` | `""` | Schedule (ссылка на РС графиков) |
| `dimensions` | `[]` | → Dimension |
| `resources` | `[]` | → Resource |
| `attributes` | `[]` | → Attribute |
```json
{
"type": "CalculationRegister", "name": "Начисления",
"chartOfCalculationTypes": "ChartOfCalculationTypes.Начисления",
"periodicity": "Month",
"dimensions": ["Сотрудник: CatalogRef.Сотрудники"],
"resources": ["Сумма: Number(15,2)"]
}
```
---
## ChartOfCharacteristicTypes
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `codeLength` | `9` | CodeLength |
| `descriptionLength` | `25` | DescriptionLength |
| `autonumbering` | `true` | Autonumbering |
| `checkUnique` | `false` | CheckUnique |
| `characteristicExtValues` | `""` | CharacteristicExtValues |
| `valueTypes` | авто* | Type (составной тип значений характеристик) |
| `hierarchical` | `false` | Hierarchical |
| `attributes` | `[]` | → Attribute |
| `tabularSections` | `{}` | → TabularSection |
\* По умолчанию: Boolean, String(100), Number(15,2), DateTime.
```json
{
"type": "ChartOfCharacteristicTypes", "name": "ВидыСубконто",
"valueTypes": ["CatalogRef.Номенклатура", "CatalogRef.Контрагенты", "Boolean", "String", "Number(15,2)"]
}
```
## ChartOfAccounts
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `extDimensionTypes` | `""` | ExtDimensionTypes (ссылка на ПВХ) |
| `maxExtDimensionCount` | `3` | MaxExtDimensionCount |
| `codeMask` | `""` | CodeMask |
| `codeLength` | `8` | CodeLength |
| `descriptionLength` | `120` | DescriptionLength |
| `codeSeries` | `WholeChartOfAccounts` | CodeSeries |
| `autoOrderByCode` | `true` | AutoOrderByCode |
| `orderLength` | `5` | OrderLength |
| `hierarchical` | `false` | Hierarchical |
| `accountingFlags` | `[]` | → AccountingFlag (Boolean-тип, массив имён) |
| `extDimensionAccountingFlags` | `[]` | → ExtDimensionAccountingFlag (Boolean-тип, массив имён) |
| `attributes` | `[]` | → Attribute |
| `tabularSections` | `{}` | → TabularSection |
```json
{
"type": "ChartOfAccounts", "name": "Хозрасчетный",
"extDimensionTypes": "ChartOfCharacteristicTypes.ВидыСубконто", "maxExtDimensionCount": 3,
"codeLength": 8, "codeMask": "@@@.@@.@",
"accountingFlags": ["Валютный", "Количественный"],
"extDimensionAccountingFlags": ["Суммовой", "Валютный"]
}
```
## ChartOfCalculationTypes
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `codeLength` | `9` | CodeLength |
| `descriptionLength` | `25` | DescriptionLength |
| `autonumbering` | `true` | Autonumbering |
| `checkUnique` | `false` | CheckUnique |
| `dependenceOnCalculationTypes` | `DontUse` | DependenceOnCalculationTypes |
| `actionPeriodUse` | `false` | ActionPeriodUse |
| `attributes` | `[]` | → Attribute |
| `tabularSections` | `{}` | → TabularSection |
`dependenceOnCalculationTypes`: `DontUse`, `OnActionPeriod`.
```json
{ "type": "ChartOfCalculationTypes", "name": "Начисления", "dependenceOnCalculationTypes": "OnActionPeriod" }
```
## Зависимости
- **AccountingRegister** требует `ChartOfAccounts` (и документ-регистратор)
- **CalculationRegister** требует `ChartOfCalculationTypes` (и документ-регистратор)
- **ChartOfAccounts** ссылается на `ChartOfCharacteristicTypes` через `extDimensionTypes`
@@ -1,103 +0,0 @@
# Веб-сервисы: HTTPService, WebService
## HTTPService
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `rootURL` | `= name.toLower()` | RootURL |
| `reuseSessions` | `DontUse` | ReuseSessions |
| `sessionMaxAge` | `20` | SessionMaxAge |
| `urlTemplates` | `{}` | → URLTemplate |
Модули: `Ext/Module.bsl`.
### urlTemplates — вложенная структура
`urlTemplates` — объект `{ "TemplateName": templateDef, ... }`.
Каждый `templateDef`:
- Строка — URL-шаблон: `"/v1/users"` (без методов)
- Объект:
| Поле | Умолчание | Описание |
|------|----------|----------|
| `template` | `"/templatename"` | URL-путь (с параметрами `{id}`) |
| `methods` | `{}` | Методы: `{ "MethodName": "HTTPMethod" }` |
Допустимые HTTPMethod: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`, `CONNECT`, `TRACE`, `MERGE`.
Обработчик метода генерируется автоматически: `{TemplateName}{MethodName}` — должен быть реализован в `Ext/Module.bsl`.
```json
{
"type": "HTTPService", "name": "API", "rootURL": "api",
"urlTemplates": {
"Users": {
"template": "/v1/users/{id}",
"methods": { "Get": "GET", "Create": "POST", "Update": "PUT", "Delete": "DELETE" }
},
"Health": "/health"
}
}
```
## WebService
| Поле JSON | Умолчание | XML элемент |
|-----------|----------|-------------|
| `namespace` | `""` | Namespace (URI пространства имён WSDL) |
| `xdtoPackages` | `""` | XDTOPackages |
| `reuseSessions` | `DontUse` | ReuseSessions |
| `sessionMaxAge` | `20` | SessionMaxAge |
| `operations` | `{}` | → Operation |
Модули: `Ext/Module.bsl`.
### operations — вложенная структура
`operations` — объект `{ "OperationName": operationDef, ... }`.
Каждый `operationDef`:
- Строка — тип возврата: `"xs:boolean"` (параметров нет, обработчик = имя операции)
- Объект:
| Поле | Умолчание | Описание |
|------|----------|----------|
| `returnType` | `xs:string` | XDTO-тип возврата |
| `nillable` | `false` | Может ли вернуть null |
| `transactioned` | `false` | Выполнять в транзакции |
| `handler` | `= operationName` | Имя процедуры в модуле |
| `parameters` | `{}` | Параметры операции |
### parameters — параметры операции
`parameters` — объект `{ "ParamName": paramDef, ... }`.
Каждый `paramDef`:
- Строка — XDTO-тип: `"xs:string"` (direction = In, nillable = true)
- Объект:
| Поле | Умолчание | Описание |
|------|----------|----------|
| `type` | `xs:string` | XDTO-тип параметра |
| `nillable` | `true` | Может ли быть null |
| `direction` | `In` | Направление: `In`, `Out`, `InOut` |
Стандартные XDTO-типы: `xs:string`, `xs:boolean`, `xs:int`, `xs:long`, `xs:decimal`, `xs:dateTime`, `xs:base64Binary`.
```json
{
"type": "WebService", "name": "DataExchange",
"namespace": "http://www.1c.ru/DataExchange",
"operations": {
"TestConnection": {
"returnType": "xs:boolean",
"handler": "ПроверкаПодключения",
"parameters": {
"ErrorMessage": { "type": "xs:string", "direction": "Out" }
}
},
"GetVersion": "xs:string"
}
}
```
@@ -0,0 +1,57 @@
# HTTPService, WebService (Веб-сервисы)
Модуль обоих — `Ext/Module.bsl`, в нём реализуются обработчики.
## HTTPService (HTTP-сервис)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `rootURL` | `= name` (в нижнем регистре) | корневой URL |
| `reuseSessions` | `DontUse` | `DontUse` / `AutoUse` |
| `sessionMaxAge` | `20` | время жизни сессии, сек |
| `urlTemplates` | `{}` | шаблоны URL (см. ниже) |
`urlTemplates` — объект `{ "ИмяШаблона": def }`, где `def`:
- строка — URL-путь без методов: `"/health"`;
- объект: `template` (путь с параметрами `{id}`, по умолчанию `/имяшаблона`), `methods``{ "ИмяМетода": "HTTPMethod" }`.
HTTP-методы: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`, `CONNECT`, `TRACE`, `MERGE`.
Обработчик метода в модуле именуется `{ИмяШаблона}{ИмяМетода}`.
```json
{ "type": "HTTPService", "name": "API", "rootURL": "api",
"urlTemplates": {
"Users": { "template": "/v1/users/{id}", "methods": { "Get": "GET", "Create": "POST", "Delete": "DELETE" } },
"Health": "/health"
} }
```
## WebService (Веб-сервис, SOAP)
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `namespace` | пусто | URI пространства имён WSDL |
| `xdtoPackages` | пусто | XDTO-пакеты |
| `reuseSessions` | `DontUse` | `DontUse` / `AutoUse` |
| `sessionMaxAge` | `20` | время жизни сессии, сек |
| `operations` | `{}` | операции (см. ниже) |
`operations` — объект `{ "ИмяОперации": def }`, где `def`:
- строка — XDTO-тип возврата без параметров: `"xs:string"`;
- объект: `returnType` (по умолчанию `xs:string`), `nillable` (bool), `transactioned` (bool),
`handler` (имя процедуры, по умолчанию = имя операции), `parameters`.
`parameters` — объект `{ "ИмяПараметра": def }`, где `def`:
- строка — XDTO-тип (`direction` = `In`);
- объект: `type` (по умолчанию `xs:string`), `nillable` (bool, по умолчанию `true`), `direction` (`In` / `Out` / `InOut`).
XDTO-типы: `xs:string`, `xs:boolean`, `xs:int`, `xs:long`, `xs:decimal`, `xs:dateTime`, `xs:base64Binary`.
```json
{ "type": "WebService", "name": "DataExchange", "namespace": "http://www.1c.ru/DataExchange",
"operations": {
"TestConnection": { "returnType": "xs:boolean", "handler": "ПроверкаПодключения",
"parameters": { "ErrorMessage": { "type": "xs:string", "direction": "Out" } } },
"GetVersion": "xs:string"
} }
```
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+52
View File
@@ -0,0 +1,52 @@
---
name: meta-decompile
description: Декомпиляция объекта метаданных 1С в JSON-заготовку формата meta-compile. Используй когда нужно получить черновик DSL-описания нового объекта по образцу другого. Не сохраняет UUID/модули/формы.
argument-hint: <ObjectPath> [-OutputPath <out.json>]
disable-model-invocation: true
allowed-tools:
- Bash
- Read
- Write
- Glob
---
# /meta-decompile — DSL-заготовка из XML объекта метаданных
Читает XML объекта метаданных (`Catalogs/Имя.xml` и т.п.) и эмитит компактный JSON в формате `/meta-compile`. Назначение — **взять существующий объект образцом и собрать по нему НОВЫЙ**: декомпилировать → поправить → скомпилировать под другим именем.
## ⚠️ Главное: это НЕ обратимая выгрузка
Компиляция черновика создаёт **новый объект с новой идентичностью**, а не копию исходного. В JSON **не** попадают: UUID (идентичность самого объекта и всех дочерних), тела модулей, формы, макеты, права. Захватываются только структура и свойства.
Отсюда правило: **никогда не компилируй черновик поверх объекта-источника и не выдавай его за «реимпорт»** — у пересобранного объекта другие UUID, поэтому все ссылки на исходный объект (из кода, других объектов, состава подсистем, предопределённых данных) сломаются, а код модулей и формы пропадут.
## Когда использовать
**Собрать новый объект по образцу существующего** — получить DSL-заготовку рабочего объекта, переименовать и адаптировать состав, скомпилировать в новый. Быстрее, чем писать DSL с нуля для богатого объекта.
## Когда **не** использовать
- **Точечная правка существующего объекта** (добавить реквизит, ТЧ, свойство) → `/meta-edit`. Цикл decompile→compile тут вреден: даёт объект с новой идентичностью и теряет модули/формы.
- **Сохранить / восстановить / перенести тот же объект** (бэкап, миграция между конфигурациями с сохранением ссылок) → штатная выгрузка 1С (`/db-dump-xml``/db-load-xml`, CF), а не decompile.
- **Просто понять структуру** объекта (реквизиты, ТЧ, типы) без пересборки → `/meta-info` (дешевле, не плодит файл).
## Параметры
| Параметр | Описание |
|----------|----------|
| `ObjectPath` | Путь к XML объекта (`Catalogs/Имя.xml`), обязательный |
| `OutputPath` | Путь к выходному JSON. Если не задан — JSON в stdout |
```powershell
python "${CLAUDE_SKILL_DIR}/scripts/meta-decompile.py" -ObjectPath "<Объект.xml>" -OutputPath "<out.json>"
```
Неподдерживаемый тип объекта или не-`MetaDataObject` root → ненулевой код выхода и сообщение в stderr.
## Workflow (сборка нового объекта по образцу)
1. `/meta-decompile <Образец.xml> -OutputPath draft.json` — получить заготовку.
2. В `draft.json` **сменить `name`** на имя нового объекта и адаптировать состав (реквизиты/ТЧ/свойства). Ссылки на *другие* объекты (владельцы, ввод на основании, типы) — по имени, сохраняются как есть.
3. `/meta-compile -JsonPath draft.json -OutputDir <ConfigDir>` — собрать (объект получит свежие UUID).
4. `/meta-validate` + `/meta-info` — проверить.
5. Модули, формы, макеты, права — добавить отдельно (в черновик они не попадают).
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+5 -2
View File
@@ -18,13 +18,13 @@ allowed-tools:
### Inline mode (простые операции)
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-edit.ps1" -ObjectPath "<path>" -Operation <op> -Value "<val>"
python "${CLAUDE_SKILL_DIR}/scripts/meta-edit.py" -ObjectPath "<path>" -Operation <op> -Value "<val>"
```
### JSON mode (сложные/комбинированные)
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-edit.ps1" -DefinitionFile "<json>" -ObjectPath "<path>"
python "${CLAUDE_SKILL_DIR}/scripts/meta-edit.py" -DefinitionFile "<json>" -ObjectPath "<path>"
```
| Параметр | Описание |
@@ -59,6 +59,9 @@ Batch через `;;` во всех операциях. Подробный си
Позиционная вставка: `"Склад: CatalogRef.Склады >> after Организация"`.
`modify-attribute` умеет и структурные свойства реквизита — формат/подсказку, форму и параметры выбора,
значение заполнения, границы (`Format`, `ChoiceForm`, `ChoiceParameters`, `FillValue`, `MinValue`/`MaxValue` и др.).
### Свойства объекта — [properties-reference.md](properties-reference.md)
| Операция | Формат Value | Пример |
+48 -3
View File
@@ -11,7 +11,7 @@
**Shorthand-формат** реквизитов: `ИмяРеквизита: Тип | флаги`
Флаги: `req` (FillChecking=ShowError), `index` (Indexing=Index), `master` (Master=true, только dimensions), `mainFilter` (MainFilterOperand, только dimensions).
Флаги: `req` — обязательное заполнение; `index` — индексировать; `master` — ведущее измерение (только dimensions); `mainFilter` — основной отбор (только dimensions).
**Позиционная вставка**: `>> after ИмяЭлемента` или `<< before ИмяЭлемента`:
```powershell
@@ -84,6 +84,27 @@ Batch через `;;` — можно указать разные ТЧ: `"Тов
Формат аналогичен `modify-attribute`: `ИмяТЧ: ключ=значение, ключ=значение`.
## add-predefined
Добавить предопределённые элементы (Catalog, ChartOfCharacteristicTypes). Существующие элементы и их
идентификаторы сохраняются, новые получают свежий id.
Inline — строка `(Код) Имя [Наименование]` (batch через `;;`; `[Наименование]` необязательно — иначе авто из имени):
```powershell
-Operation add-predefined -Value "(001) Основной ;; (002) Резервный [Резервный склад]"
```
JSON — строки и/или объекты (для групп с вложенными):
```json
{ "add": { "predefined": [
"(001) Основной",
{ "name": "Группа", "isFolder": true, "childItems": ["(002) Вложенный"] }
] } }
```
Ключи объекта: `name`, `code`, `description`, `isFolder`, `childItems` (дерево). Тип кода (строковый/числовой)
берётся из объекта автоматически.
## add-enumValue / add-form / add-template / add-command
Просто имена (batch через `;;`):
@@ -107,10 +128,34 @@ Batch через `;;` — можно указать разные ТЧ: `"Тов
Формат: `ИмяЭлемента: ключ=значение, ключ=значение`
Ключи: `name` (rename), `type`, `synonym`, `indexing`, `fillChecking`, `use` и др.
**Спец-операции** (строчные ключи): `name` (переименование), `type` (смена типа), `synonym`.
**Свойства** задавайте по имени свойства 1С (PascalCase, как в конфигураторе): `Indexing`, `FillChecking`,
`Use`, `FullTextSearch`, `DataHistory`, `PasswordMode`, `MultiLine`, `Mask`, `CreateOnInput`, `QuickChoice` и др.
Свойство можно задать, даже если у реквизита оно ещё не выставлено. Опечатка в имени свойства → ошибка
(правка не теряется молча).
```powershell
-Operation modify-attribute -Value "СтароеИмя: name=НовоеИмя, type=Строка(500)"
-Operation modify-attribute -Value "Комментарий: indexing=Index"
-Operation modify-attribute -Value "Комментарий: Indexing=Index, FullTextSearch=Use"
-Operation modify-enumValue -Value "СтароеЗначение: name=НовоеЗначение"
```
### Структурные свойства реквизита
Свойства со сложным значением задавайте через JSON DSL (`{ "modify": { "attributes": { "Имя": { ... } } } }`):
| Ключ | Значение | Пример (JSON) |
|------|----------|---------------|
| `Format` / `EditFormat` / `ToolTip` | строка (мультиязычная) | `"Format": "ДФ=dd.MM.yyyy"` |
| `ChoiceForm` | путь формы выбора | `"ChoiceForm": "Catalog.Товары.Form.ФормаВыбора"` |
| `MinValue` / `MaxValue` | число или строка | `"MinValue": 0, "MaxValue": 100` |
| `FillValue` | значение заполнения | `"FillValue": "EmptyRef"` · `true` · `10` · `{"nil": true}` |
| `LinkByType` | `{dataPath, linkItem?}` | `"LinkByType": {"dataPath": "Вид", "linkItem": 0}` |
| `ChoiceParameterLinks` | `[{name, dataPath, valueChange?}]` | `["Отбор.Организация=Организация"]` |
| `ChoiceParameters` | `[{name, type?, value?}]` | `[{"name": "Отбор.ЭтоГруппа", "value": false}]` |
- `FillValue`: `"EmptyRef"` — пустая ссылка по типу реквизита; `{"emptyRef": true}` / `{"nil": true}` — явные маркеры.
- `ChoiceParameters` value — булево/число/строка/ссылочный путь или массив; укажите `type` (напр.
`EnumRef.СтавкиНДС`), чтобы задавать значения короткими именами (`"Оптовая"` вместо полного пути).
- В путях данных (`LinkByType`/`ChoiceParameterLinks`) можно писать короткое имя реквизита вместо полного пути.
+1 -1
View File
@@ -3,7 +3,7 @@
Для сложных и комбинированных операций используйте JSON-файл вместо inline-режима.
```powershell
powershell.exe -NoProfile -File .claude/skills/meta-edit/scripts/meta-edit.ps1 -DefinitionFile "<json>" -ObjectPath "<path>"
python .claude/skills/meta-edit/scripts/meta-edit.py -DefinitionFile "<json>" -ObjectPath "<path>"
```
## add — добавить элементы
@@ -1,18 +1,22 @@
# Свойства объекта и complex properties
# Свойства объекта и свойства-списки
Справочник операций для скалярных свойств объекта и свойств со вложенной XML-структурой (Owners, RegisterRecords, BasedOn, InputByString).
Справочник операций для обычных свойств объекта и свойств-списков (Owners, RegisterRecords, BasedOn, InputByString).
## modify-property
Изменение скалярных свойств объекта. Формат: `Ключ=Значение` (batch через `;;`):
Изменение свойств объекта по имени свойства 1С (PascalCase, как в конфигураторе). Формат: `Ключ=Значение`
(batch через `;;`):
```powershell
-Operation modify-property -Value "CodeLength=11 ;; DescriptionLength=150"
-Operation modify-property -Value "Hierarchical=true"
```
## Complex properties
Свойство можно задать, даже если оно ещё не выставлено у объекта (например `FullTextSearch`, `DataHistory`).
Опечатка в имени свойства → ошибка (правка не теряется молча). Допустимы имена свойств соответствующего типа объекта.
Свойства со вложенной XML-структурой. Поддерживаются через inline `add-*` / `remove-*` / `set-*` и через JSON `modify.properties`.
## Свойства-списки
Свойства, значение которых — список ссылок. Управляются через inline `add-*` / `remove-*` / `set-*` и через JSON `modify.properties`.
| Свойство | Объекты | Inline-значение |
|----------|---------|-----------------|
@@ -20,31 +24,36 @@
| RegisterRecords | Document | `AccumulationRegister.XXX` |
| BasedOn | Document, Catalog, BP, Task | `Document.XXX` |
| InputByString | Catalog, ChartOf*, Task | `StandardAttribute.Description` |
| DataLockFields | Catalog, Document, регистры и др. | `Организация` (короткое имя реквизита → полный путь) |
| RegisteredDocuments | DocumentJournal | `Document.XXX` |
### add-owner / add-registerRecord / add-basedOn
### add-owner / add-registerRecord / add-basedOn / add-registeredDocument
Полное имя метаданных `MetaType.Name`:
```powershell
-Operation add-owner -Value "Catalog.Контрагенты ;; Catalog.Организации"
-Operation add-registerRecord -Value "AccumulationRegister.ОстаткиТоваров"
-Operation add-basedOn -Value "Document.ЗаказКлиента"
-Operation add-registeredDocument -Value "Document.РасходныйОрдер"
```
### add-inputByString
### add-inputByString / add-dataLockField
Пути полей (префикс `MetaType.Name.` добавляется автоматически):
Пути полей (короткое имя реквизита разворачивается в полный путь автоматически):
```powershell
-Operation add-inputByString -Value "StandardAttribute.Description ;; StandardAttribute.Code"
-Operation add-dataLockField -Value "Организация ;; Контрагент"
```
### remove-owner / remove-registerRecord / remove-basedOn / remove-inputByString
### remove-owner / remove-registerRecord / remove-basedOn / remove-inputByString / remove-dataLockField / remove-registeredDocument
```powershell
-Operation remove-owner -Value "Catalog.Контрагенты"
-Operation remove-inputByString -Value "Catalog.МойСпр.StandardAttribute.Code"
-Operation remove-dataLockField -Value "Организация"
```
### set-owners / set-registerRecords / set-basedOn / set-inputByString
### set-owners / set-registerRecords / set-basedOn / set-inputByString / set-dataLockFields / set-registeredDocuments
Заменяют **весь список** (в отличие от add/remove):
```powershell
+643 -12
View File
@@ -1,4 +1,4 @@
# meta-edit v1.9 — Edit existing 1C metadata object XML (inline mode + complex properties + TS attribute ops + modify-ts)
# meta-edit v1.19 — Edit existing 1C metadata object XML (+add-predefined предопределённые Ext/Predefined.xml)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[string]$DefinitionFile,
@@ -12,14 +12,17 @@ param(
"add-attribute", "add-ts", "add-dimension", "add-resource",
"add-enumValue", "add-column", "add-form", "add-template", "add-command",
"add-owner", "add-registerRecord", "add-basedOn", "add-inputByString",
"add-dataLockField", "add-registeredDocument", "add-predefined",
"remove-attribute", "remove-ts", "remove-dimension", "remove-resource",
"remove-enumValue", "remove-column", "remove-form", "remove-template", "remove-command",
"remove-owner", "remove-registerRecord", "remove-basedOn", "remove-inputByString",
"remove-dataLockField", "remove-registeredDocument",
"add-ts-attribute", "remove-ts-attribute", "modify-ts-attribute", "modify-ts",
"modify-attribute", "modify-dimension", "modify-resource",
"modify-enumValue", "modify-column",
"modify-property",
"set-owners", "set-registerRecords", "set-basedOn", "set-inputByString"
"set-owners", "set-registerRecords", "set-basedOn", "set-inputByString",
"set-dataLockFields", "set-registeredDocuments"
)]
[string]$Operation,
[string]$Value,
@@ -78,7 +81,7 @@ $script:validEnumValues = @{
"Posting" = @("Allow","Deny")
"RealTimePosting" = @("Allow","Deny")
"EditType" = @("InDialog","InList","BothWays")
"HierarchyType" = @("HierarchyFoldersAndItems","HierarchyItemsOnly")
"HierarchyType" = @("HierarchyFoldersAndItems","HierarchyOfItems")
"CodeType" = @("String","Number")
"CodeAllowedLength" = @("Variable","Fixed")
"NumberType" = @("String","Number")
@@ -607,6 +610,8 @@ function Import-Fragment([string]$xmlString) {
xmlns:v8="http://v8.1c.ru/8.1/data/core"
xmlns:xr="http://v8.1c.ru/8.3/xcf/readable"
xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config"
xmlns:app="http://v8.1c.ru/8.2/managed-application/core"
xmlns:ent="http://v8.1c.ru/8.1/data/enterprise"
xmlns:xs="http://www.w3.org/2001/XMLSchema">$xmlString</_W>
"@
$frag = New-Object System.Xml.XmlDocument
@@ -890,20 +895,33 @@ $script:reservedAttrNames = @{
"Account"="Счет"; "ValueType"="ТипЗначения"; "ActionPeriodIsBasic"="ПериодДействияБазовый"
}
# Стандартные реквизиты по типу объекта (ключи из reservedAttrNames). Имя реквизита, совпадающее
# с ними (англ. ИЛИ рус.), платформа не позволит — жёсткий отказ. Контексты вне карты → предупреждение.
$script:reservedByContext = @{
"catalog" = @("Ref","DeletionMark","Predefined","PredefinedDataName","Code","Description","Owner","Parent","IsFolder")
"document" = @("Ref","DeletionMark","Date","Number","Posted")
}
function Build-AttributeFragment {
param($parsed, [string]$context, [string]$indent)
if (-not $context) { $context = Get-AttributeContext }
# Check reserved attribute names
# Check reserved attribute names (типозависимо: catalog/document — жёсткий отказ; прочее — предупреждение)
$attrName = $parsed.name
if ($script:reservedAttrNames.ContainsKey($attrName)) {
$ctxReserved = $script:reservedByContext[$context]
if ($ctxReserved) {
foreach ($en in $ctxReserved) {
$ru = $script:reservedAttrNames[$en]
if (($attrName -ieq $en) -or ($ru -and $attrName -ieq $ru)) {
Write-Error "Имя реквизита '$attrName' зарезервировано стандартным реквизитом ($en/$ru) объекта '$context'. Выберите другое имя."
exit 1
}
}
} elseif ($context -notin @("tabular", "processor-tabular") -and
($script:reservedAttrNames.ContainsKey($attrName) -or ($script:reservedAttrNames.Values -contains $attrName))) {
Write-Warning "Attribute '$attrName' conflicts with a standard attribute name. This may cause errors when loading into 1C."
}
$ruValues = $script:reservedAttrNames.Values
if ($ruValues -contains $attrName) {
Write-Warning "Attribute '$attrName' conflicts with a standard attribute name (Russian). This may cause errors when loading into 1C."
}
$uuid = New-Guid-String
$sb = New-Object System.Text.StringBuilder
@@ -1475,6 +1493,8 @@ function Convert-InlineToDefinition([string]$operation, [string]$value) {
"registerRecord" = "RegisterRecords"; "registerRecords" = "RegisterRecords"
"basedOn" = "BasedOn"
"inputByString" = "InputByString"
"dataLockField" = "DataLockFields"; "dataLockFields" = "DataLockFields"
"registeredDocument" = "RegisteredDocuments"; "registeredDocuments" = "RegisteredDocuments"
}
if ($complexTargetMap.ContainsKey($target)) {
@@ -1499,6 +1519,16 @@ function Convert-InlineToDefinition([string]$operation, [string]$value) {
return $def
}
# Предопределённые (Ext/Predefined.xml) — отдельный файл; строим { <op>: { predefined: [...] } }.
if ($target -eq 'predefined') {
$items = @($value -split ';;' | ForEach-Object { $_.Trim() } | Where-Object { $_ })
$inner = New-Object PSCustomObject
$inner | Add-Member -NotePropertyName 'predefined' -NotePropertyValue $items
$def = New-Object PSCustomObject
$def | Add-Member -NotePropertyName $op -NotePropertyValue $inner
return $def
}
# TS attribute operations: dot notation "TSName.AttrDef"
if ($target -eq "ts-attribute") {
$items = @($value -split ';;' | ForEach-Object { $_.Trim() } | Where-Object { $_ })
@@ -1741,6 +1771,10 @@ function Process-Add($addDef) {
$addDef.PSObject.Properties | ForEach-Object {
$rawKey = $_.Name
$items = $_.Value
if ($rawKey -in @('predefined','предопределенные','предопределённые')) {
Add-PredefinedItems $items
return
}
$childType = Resolve-ChildTypeKey $rawKey
if (-not $childType) {
@@ -1961,8 +1995,19 @@ function Modify-Properties($propsDef) {
}
if (-not $propEl) {
Warn "Property '$propName' not found in Properties"
return
# create-if-missing: известное свойство создаём (порядок 1С терпит — append); неизвестное → ошибка (опечатка)
if ($script:knownObjectProps -notcontains $propName) {
Write-Error "modify-property: неизвестное свойство '$propName' — нет такого свойства объекта (опечатка?)"
exit 1
}
$newNodes = Import-Fragment "<$propName/>"
if ($newNodes.Count -gt 0) {
Insert-PropertyInOrder $script:propertiesEl $newNodes[0] $null $propName
$propEl = $newNodes[0]
} else {
Warn "Property '$propName': could not create element"
return
}
}
# Complex property: Owners, RegisterRecords, BasedOn, InputByString
@@ -2216,6 +2261,56 @@ function Modify-ChildElements($modifyDef, [string]$childType) {
Info "Changed synonym of $xmlTag '$elemName': $changeValue"
$script:modifyCount++
}
"Format" {
if (Set-AttrPropertyElement $propsEl "Format" (Build-MLTextXml (Get-ChildIndent $propsEl) "Format" "$changeValue")) {
Info "Set $xmlTag '$elemName'.Format"; $script:modifyCount++
}
}
"EditFormat" {
if (Set-AttrPropertyElement $propsEl "EditFormat" (Build-MLTextXml (Get-ChildIndent $propsEl) "EditFormat" "$changeValue")) {
Info "Set $xmlTag '$elemName'.EditFormat"; $script:modifyCount++
}
}
"ToolTip" {
if (Set-AttrPropertyElement $propsEl "ToolTip" (Build-MLTextXml (Get-ChildIndent $propsEl) "ToolTip" "$changeValue")) {
Info "Set $xmlTag '$elemName'.ToolTip"; $script:modifyCount++
}
}
"ChoiceForm" {
if (Set-AttrPropertyElement $propsEl "ChoiceForm" "<ChoiceForm>$(Esc-Xml "$changeValue")</ChoiceForm>") {
Info "Set $xmlTag '$elemName'.ChoiceForm"; $script:modifyCount++
}
}
"MinValue" {
if (Set-AttrPropertyElement $propsEl "MinValue" (Build-MinMaxValueXml "MinValue" $changeValue)) {
Info "Set $xmlTag '$elemName'.MinValue"; $script:modifyCount++
}
}
"MaxValue" {
if (Set-AttrPropertyElement $propsEl "MaxValue" (Build-MinMaxValueXml "MaxValue" $changeValue)) {
Info "Set $xmlTag '$elemName'.MaxValue"; $script:modifyCount++
}
}
"LinkByType" {
if (Set-AttrPropertyElement $propsEl "LinkByType" (Build-LinkByTypeXml (Get-ChildIndent $propsEl) $changeValue)) {
Info "Set $xmlTag '$elemName'.LinkByType"; $script:modifyCount++
}
}
"ChoiceParameterLinks" {
if (Set-AttrPropertyElement $propsEl "ChoiceParameterLinks" (Build-ChoiceParameterLinksXml (Get-ChildIndent $propsEl) $changeValue)) {
Info "Set $xmlTag '$elemName'.ChoiceParameterLinks"; $script:modifyCount++
}
}
"ChoiceParameters" {
if (Set-AttrPropertyElement $propsEl "ChoiceParameters" (Build-ChoiceParametersXml (Get-ChildIndent $propsEl) $changeValue)) {
Info "Set $xmlTag '$elemName'.ChoiceParameters"; $script:modifyCount++
}
}
"FillValue" {
if (Set-AttrPropertyElement $propsEl "FillValue" (Build-FillValueExplicitXml (Get-AttrTypeStrFromXml $propsEl) $changeValue)) {
Info "Set $xmlTag '$elemName'.FillValue"; $script:modifyCount++
}
}
default {
# Scalar property change (Indexing, FillChecking, Use, etc.)
$scalarEl = $null
@@ -2235,7 +2330,23 @@ function Modify-ChildElements($modifyDef, [string]$childType) {
Info "Modified $xmlTag '$elemName'.$changeProp = $valueStr"
$script:modifyCount++
} else {
Warn "$xmlTag '$elemName': property '$changeProp' not found"
# create-if-missing: известное свойство создаём в позиции; неизвестное → ошибка (опечатка)
if ($script:knownChildProps -notcontains $changeProp) {
Write-Error "modify: неизвестное свойство '$changeProp' у $xmlTag '$elemName' (опечатка?)"
exit 1
}
$valueStr = "$changeValue"
if ($changeValue -is [bool]) {
$valueStr = if ($changeValue) { "true" } else { "false" }
} else {
$valueStr = Normalize-EnumValue $changeProp $valueStr
}
$newNodes = Import-Fragment "<$changeProp>$(Esc-Xml $valueStr)</$changeProp>"
if ($newNodes.Count -gt 0) {
Insert-PropertyInOrder $propsEl $newNodes[0] $script:attrPropOrder $changeProp
Info "Created $xmlTag '$elemName'.$changeProp = $valueStr"
$script:modifyCount++
}
}
}
}
@@ -2271,6 +2382,433 @@ $script:complexPropertyMap = @{
"RegisterRecords" = @{ tag = "xr:Item"; attr = 'xsi:type="xr:MDObjectRef"' }
"BasedOn" = @{ tag = "xr:Item"; attr = 'xsi:type="xr:MDObjectRef"' }
"InputByString" = @{ tag = "xr:Field"; attr = $null }
"DataLockFields" = @{ tag = "xr:Field"; attr = $null; expand = $true }
"RegisteredDocuments" = @{ tag = "xr:Item"; attr = 'xsi:type="xr:MDObjectRef"' }
}
# Известные свойства объекта (union по корпусу acc+erp 8.3.24) — allowlist для modify-property.
# Известное отсутствующее свойство create-if-missing создаётся; неизвестное (опечатка) → ошибка.
$script:knownObjectProps = @(
'ActionPeriod','ActionPeriodUse','Addressing','AutoOrderByCode','Autonumbering','AuxiliaryChoiceForm',
'AuxiliaryFolderChoiceForm','AuxiliaryFolderForm','AuxiliaryForm','AuxiliaryListForm','AuxiliaryObjectForm',
'AuxiliaryRecordForm','AuxiliarySettingsForm','BaseCalculationTypes','BasePeriod','BasedOn',
'CharacteristicExtValues','Characteristics','ChartOfAccounts','ChartOfCalculationTypes','CheckUnique',
'ChoiceDataGetModeOnInputByString','ChoiceFoldersAndItems','ChoiceForm','ChoiceHistoryOnInput','ChoiceMode',
'ChoiceParameterLinks','ChoiceParameters','CodeAllowedLength','CodeLength','CodeMask','CodeSeries','CodeType',
'Comment','Correspondence','CreateOnInput','CreateTaskInPrivilegedMode','CurrentPerformer','DataHistory',
'DataLockControlMode','DataLockFields','DefaultChoiceForm','DefaultFolderChoiceForm','DefaultFolderForm',
'DefaultForm','DefaultListForm','DefaultObjectForm','DefaultPresentation','DefaultRecordForm','DefaultSettingsForm',
'DefaultVariantForm','DependenceOnCalculationTypes','DescriptionLength','DistributedInfoBase','EditFormat',
'EditType','EnableTotalsSliceFirst','EnableTotalsSliceLast','EnableTotalsSplitting',
'ExecuteAfterWriteDataHistoryVersionProcessing','Explanation','ExtDimensionTypes','ExtendedEdit',
'ExtendedListPresentation','ExtendedObjectPresentation','ExtendedPresentation','ExtendedRecordPresentation',
'FillChecking','FoldersOnTop','Format','FullTextSearch','FullTextSearchOnInputByString','Hierarchical',
'HierarchyType','IncludeConfigurationExtensions','IncludeHelpInContents','InformationRegisterPeriodicity',
'InputByString','LevelCount','LimitLevelCount','LinkByType','ListPresentation','MainAddressingAttribute',
'MainDataCompositionSchema','MainFilterOnPeriod','MarkNegatives','Mask','MaxExtDimensionCount','MaxValue',
'MinValue','MultiLine','Name','NumberAllowedLength','NumberLength','NumberPeriodicity','NumberType','Numerator',
'ObjectPresentation','OrderLength','Owners','PasswordMode','PeriodAdjustmentLength','Periodicity',
'PostInPrivilegedMode','Posting','PredefinedDataUpdate','QuickChoice','RealTimePosting','RecordPresentation',
'RegisterRecords','RegisterRecordsDeletion','RegisterRecordsWritingOnPost','RegisterType','RegisteredDocuments',
'Schedule','ScheduleDate','ScheduleValue','SearchStringModeOnInputByString','SequenceFilling','SettingsStorage',
'StandardAttributes','StandardTabularSections','SubordinationUse','Synonym','Task','TaskNumberAutoPrefix',
'ToolTip','Type','UnpostInPrivilegedMode','UpdateDataHistoryImmediatelyAfterWrite','UseStandardCommands',
'VariantsStorage','WriteMode'
)
# Известные свойства дочерних элементов (union Attribute/Dimension/Resource по корпусу) — allowlist default-ветки
# modify-attribute/-dimension/-resource.
$script:knownChildProps = @(
'AccountingFlag','Balance','BaseDimension','ChoiceFoldersAndItems','ChoiceForm','ChoiceHistoryOnInput',
'ChoiceParameterLinks','ChoiceParameters','Comment','CreateOnInput','DataHistory','DenyIncompleteValues',
'DocumentMap','EditFormat','ExtDimensionAccountingFlag','ExtendedEdit','FillChecking','FillFromFillingValue',
'FillValue','Format','FullTextSearch','Indexing','LinkByType','MainFilter','MarkNegatives','Mask','Master',
'MaxValue','MinValue','MultiLine','Name','PasswordMode','QuickChoice','RegisterRecordsMap','ScheduleLink',
'Synonym','ToolTip','Type','Use','UseInTotals'
)
# Канонический порядок свойств реквизита (последовательность Build-AttributeFragment) — для вставки в позицию.
# Порядок 1С терпит (cert), но держим канонический для консистентности с meta-compile.
$script:attrPropOrder = @(
'Name','Synonym','Comment','Type','PasswordMode','Format','EditFormat','ToolTip','MarkNegatives','Mask',
'MultiLine','ExtendedEdit','MinValue','MaxValue','FillFromFillingValue','FillValue','FillChecking',
'ChoiceFoldersAndItems','ChoiceParameterLinks','ChoiceParameters','QuickChoice','CreateOnInput','ChoiceForm',
'LinkByType','ChoiceHistoryOnInput','Use','Indexing','FullTextSearch','DataHistory'
)
# Вставить новый элемент свойства в Properties в канонической позиции (по orderArray); если свойства нет в
# orderArray (или orderArray пуст) — append. Порядок 1С терпит, канонический — для консистентности/снапшотов.
function Insert-PropertyInOrder($propsEl, $newNode, $orderArray, $propName) {
$childIndent = "$(Get-ChildIndent $propsEl)"
$refNode = $null
$idx = if ($orderArray) { [array]::IndexOf($orderArray, $propName) } else { -1 }
if ($idx -ge 0) {
foreach ($ch in $propsEl.ChildNodes) {
if ($ch.NodeType -eq 'Element') {
$ci = [array]::IndexOf($orderArray, $ch.LocalName)
if ($ci -gt $idx) { $refNode = $ch; break }
}
}
}
Insert-BeforeElement $propsEl $newNode $refNode $childIndent
}
# Заменить существующий элемент свойства реквизита новым фрагментом (по образцу ветки type),
# либо создать в канонической позиции, если его нет. Возвращает $true при успехе.
function Set-AttrPropertyElement($propsEl, $propName, $fragmentXml) {
$newNodes = Import-Fragment $fragmentXml
if ($newNodes.Count -eq 0) { return $false }
$existing = $null
foreach ($ch in $propsEl.ChildNodes) {
if ($ch.NodeType -eq 'Element' -and $ch.LocalName -eq $propName) { $existing = $ch; break }
}
if ($existing) {
# InsertBefore+RemoveChild сохраняет ведущий/хвостовой whitespace позиции existing
# (InsertAfter+Remove-NodeWithWhitespace склеил бы: удаляет ведущий ws как отдельный узел).
$propsEl.InsertBefore($newNodes[0], $existing) | Out-Null
$propsEl.RemoveChild($existing) | Out-Null
} else {
Insert-PropertyInOrder $propsEl $newNodes[0] $script:attrPropOrder $propName
}
return $true
}
# MinValue/MaxValue — типизированное значение (порт Emit-MinMaxValue): nil / xs:string / xs:decimal.
function Build-MinMaxValueXml([string]$tag, $val) {
if ($null -eq $val -or "$val" -eq '') { return "<$tag xsi:nil=`"true`"/>" }
$t = if ($val -is [string]) { 'xs:string' } else { 'xs:decimal' }
return "<$tag xsi:type=`"$t`">$(Esc-Xml "$val")</$tag>"
}
# --- Порт из meta-compile: развёртка путей данных + связи выбора / тип по ссылке (structural modify) ---
# Свойство из dict/PSCustomObject по списку синонимов (первый найденный, иначе $null).
function Get-ChElProp($obj, [string[]]$names) {
if ($null -eq $obj) { return $null }
foreach ($n in $names) {
if ($obj -is [System.Collections.IDictionary]) { if ($obj.Contains($n)) { return $obj[$n] } }
elseif ($obj.PSObject -and $obj.PSObject.Properties[$n]) { return $obj.PSObject.Properties[$n].Value }
}
return $null
}
# Стандартный реквизит рус/англ → английский (для Catalog/Document); использует существующие reserved-карты.
function Resolve-StdAttrEn([string]$name) {
$ctx = switch ("$script:objType") { 'Catalog' { 'catalog' } 'Document' { 'document' } default { $null } }
if (-not $ctx) { return $null }
$stdSet = $script:reservedByContext[$ctx]
foreach ($en in $stdSet) {
$ru = $script:reservedAttrNames[$en]
if (($name -ieq $en) -or ($ru -and $name -ieq $ru)) { return $en }
}
return $null
}
# Прощающий ввод пути данных: короткое имя реквизита → полный путь объекта (порт Expand-DataPath).
function Expand-DataPath([string]$dp) {
if (-not $dp) { return $dp }
$s = "$dp"
if ($s -match '[:/]') { return $s }
if ($s -match '^-?\d+$') { return $s }
if ($s -match '^(StandardAttribute|Attribute)\.') { return "$($script:objType).$($script:objName).$s" }
if (-not $s.Contains('.')) {
$en = Resolve-StdAttrEn $s
if ($en) { return "$($script:objType).$($script:objName).StandardAttribute.$en" }
return "$($script:objType).$($script:objName).Attribute.$s"
}
return $s
}
# Shorthand "name=path" | "name=path:Clear|DontChange" → {name, dataPath, valueChange?}.
function ConvertFrom-ChLinkShorthand([string]$s) {
$eq = $s.IndexOf('=')
if ($eq -lt 0) { return @{ name = $s.Trim() } }
$o = @{ name = $s.Substring(0, $eq).Trim() }; $rest = $s.Substring($eq + 1).Trim()
if ($rest -match '^(.*):(?i:(Clear|DontChange|очистить|неизменять))$') { $o['dataPath'] = $matches[1].Trim(); $o['valueChange'] = $matches[2] }
else { $o['dataPath'] = $rest }
return $o
}
# LinkByType — {dataPath, linkItem?} (порт Emit-LinkByType). Строка → dataPath, linkItem=0.
function Build-LinkByTypeXml([string]$indent, $spec) {
if (-not $spec) { return "$indent<LinkByType/>" }
if ($spec -is [string]) { $dp = "$spec"; $li = 0 }
else {
$dp = "$(Get-ChElProp $spec @('dataPath','path','путь'))"
$liRaw = Get-ChElProp $spec @('linkItem','элементСвязи')
$li = if ($null -ne $liRaw) { $liRaw } else { 0 }
}
if (-not $dp) { return "$indent<LinkByType/>" }
$dp = Expand-DataPath $dp
$lines = @(
"$indent<LinkByType>"
"$indent`t<xr:DataPath>$(Esc-Xml "$dp")</xr:DataPath>"
"$indent`t<xr:LinkItem>$li</xr:LinkItem>"
"$indent</LinkByType>"
)
return $lines -join "`r`n"
}
# ChoiceParameterLinks — [{name, dataPath, valueChange?}] (порт Emit-ChoiceParameterLinks). valueChange дефолт Clear.
function Build-ChoiceParameterLinksXml([string]$indent, $cpl) {
if (-not $cpl -or @($cpl).Count -eq 0) { return "$indent<ChoiceParameterLinks/>" }
$sb = New-Object System.Text.StringBuilder
$sb.Append("$indent<ChoiceParameterLinks>") | Out-Null
foreach ($lk in @($cpl)) {
if ($lk -is [string]) { $lk = ConvertFrom-ChLinkShorthand $lk }
$name = Get-ChElProp $lk @('name','имя')
$dp = Expand-DataPath (Get-ChElProp $lk @('dataPath','path','путь'))
$vcRaw = Get-ChElProp $lk @('valueChange','режимИзменения')
$vc = 'Clear'
if ($vcRaw) {
$vc = switch -Regex ("$vcRaw".ToLower()) {
'^(clear|очистить|очистка)$' { 'Clear'; break }
'^(dontchange|неизменять|неменять|нет)$' { 'DontChange'; break }
default { "$vcRaw" }
}
}
$sb.Append("`r`n$indent`t<xr:Link>") | Out-Null
$sb.Append("`r`n$indent`t`t<xr:Name>$(Esc-Xml "$name")</xr:Name>") | Out-Null
$sb.Append("`r`n$indent`t`t<xr:DataPath xsi:type=`"xs:string`">$(Esc-Xml "$dp")</xr:DataPath>") | Out-Null
$sb.Append("`r`n$indent`t`t<xr:ValueChange>$vc</xr:ValueChange>") | Out-Null
$sb.Append("`r`n$indent`t</xr:Link>") | Out-Null
}
$sb.Append("`r`n$indent</ChoiceParameterLinks>") | Out-Null
return $sb.ToString()
}
# --- Порт из meta-compile: значения параметров выбора (ChoiceParameters) ---
$script:fillRefRoots = @{
'перечисление'='Enum'; 'справочник'='Catalog'; 'документ'='Document';
'плансчетов'='ChartOfAccounts'; 'планвидовхарактеристик'='ChartOfCharacteristicTypes';
'планвидоврасчета'='ChartOfCalculationTypes'; 'планвидоврасчёта'='ChartOfCalculationTypes';
'планобмена'='ExchangePlan'; 'бизнеспроцесс'='BusinessProcess'; 'задача'='Task';
'enum'='Enum'; 'catalog'='Catalog'; 'document'='Document'; 'chartofaccounts'='ChartOfAccounts';
'chartofcharacteristictypes'='ChartOfCharacteristicTypes'; 'chartofcalculationtypes'='ChartOfCalculationTypes';
'exchangeplan'='ExchangePlan'; 'businessprocess'='BusinessProcess'; 'task'='Task'
}
$script:fillEmptyRefWords = @('emptyref','пустаяссылка')
$script:fillEnumValWords = @('enumvalue','значениеперечисления')
$script:accountTypeValues = @('Active','Passive','ActivePassive')
$script:fillRefKindRoot = @{
'catalogref'='Catalog'; 'documentref'='Document'; 'enumref'='Enum';
'chartofaccountsref'='ChartOfAccounts'; 'chartofcharacteristictypesref'='ChartOfCharacteristicTypes';
'chartofcalculationtypesref'='ChartOfCalculationTypes'; 'exchangeplanref'='ExchangePlan';
'businessprocessref'='BusinessProcess'; 'taskref'='Task'
}
function ConvertTo-ChScalar([string]$s) {
$t = "$s".Trim()
if ($t -match '^(?i:true|истина)$') { return $true }
if ($t -match '^(?i:false|ложь)$') { return $false }
if ($t -match '^-?\d+$') { return [int]$t }
if ($t -match '^-?\d+\.\d+$') { return [double]::Parse($t, [System.Globalization.CultureInfo]::InvariantCulture) }
return $t
}
function Format-FillNum($n) {
if ($n -is [double] -or $n -is [decimal]) { return $n.ToString([System.Globalization.CultureInfo]::InvariantCulture) }
return "$n"
}
function Normalize-FillRef([string]$s) {
if ([string]::IsNullOrEmpty($s)) { return $null }
if ($s -match '^[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}\.[0-9a-fA-F-]+$') { return $s }
$parts = $s -split '\.'
if ($parts.Count -lt 2) { return $null }
$root = $script:fillRefRoots[$parts[0].ToLower()]
if (-not $root) { return $null }
$typeName = $parts[1]
if ($root -eq 'Enum') {
if ($parts.Count -eq 2) { return $null }
if ($parts.Count -eq 3) {
if ($script:fillEmptyRefWords -contains $parts[2].ToLower()) { return "Enum.$typeName.EmptyRef" }
return "Enum.$typeName.EnumValue.$($parts[2])"
}
$member = $parts[2]
if ($script:fillEnumValWords -contains $member.ToLower()) { $rest = $parts[3..($parts.Count-1)] -join '.' }
else { $rest = $parts[2..($parts.Count-1)] -join '.' }
return "Enum.$typeName.EnumValue.$rest"
}
$tail = @($parts[1..($parts.Count-1)])
for ($i = 0; $i -lt $tail.Count; $i++) {
if ($script:fillEmptyRefWords -contains $tail[$i].ToLower()) { $tail[$i] = 'EmptyRef' }
}
return "$root." + ($tail -join '.')
}
function Expand-ChoiceRefValue([string]$value, [string]$typeStr) {
if (-not $typeStr) { return $null }
$t = Resolve-TypeStr $typeStr
$root = $null; $tn = $null
if ($t -match '^(\w+Ref)\.(.+)$') { $root = $script:fillRefKindRoot[$Matches[1].ToLower()]; $tn = $Matches[2] }
elseif ($t -match '^([^.]+)\.(.+)$') { $root = $script:fillRefRoots[$Matches[1].ToLower()]; $tn = $Matches[2] }
if (-not $root) { return $null }
if ($script:fillEmptyRefWords -contains "$value".ToLower()) { return "$root.$tn.EmptyRef" }
if ($root -eq 'Enum') { return "Enum.$tn.EnumValue.$value" }
return "$root.$tn.$value"
}
function Normalize-ChoiceValue($value) {
if ($value -is [bool]) { return @{ XsiType='xs:boolean'; Text=$(if ($value) { 'true' } else { 'false' }) } }
if ($value -is [int] -or $value -is [long] -or $value -is [double] -or $value -is [decimal]) {
return @{ XsiType='xs:decimal'; Text=(Format-FillNum $value) }
}
$s = "$value"
if ($s -eq '') { return @{ XsiType='xs:string'; Text='' } }
if ($s -match '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$') { return @{ XsiType='xs:dateTime'; Text=$s } }
$ref = Normalize-FillRef $s
if ($ref) { return @{ XsiType='xr:DesignTimeRef'; Text=$ref } }
if ($script:accountTypeValues -contains $s) { return @{ XsiType='ent:AccountType'; Text=$s } }
return @{ XsiType='xs:string'; Text=$s }
}
function Normalize-ChoiceValueT($value, [string]$typeStr) {
if ($typeStr -and ($value -is [string]) -and (-not "$value".Contains('.'))) {
$ex = Expand-ChoiceRefValue "$value" $typeStr
if ($ex) { return @{ XsiType='xr:DesignTimeRef'; Text=$ex } }
}
return Normalize-ChoiceValue $value
}
function ConvertFrom-ChParamShorthand([string]$s) {
$eq = $s.IndexOf('=')
if ($eq -lt 0) { return @{ name = $s.Trim() } }
$name = $s.Substring(0, $eq).Trim(); $rest = $s.Substring($eq + 1)
if ($rest -match ',') {
$vals = @(); foreach ($p in ($rest -split ',')) { $vals += ,(ConvertTo-ChScalar $p) }
return @{ name = $name; value = $vals }
}
return @{ name = $name; value = (ConvertTo-ChScalar $rest) }
}
# ChoiceParameters — [{name, type?, value?}] (порт Emit-ChoiceParameters). Значение на app:value (xsi:type=тип);
# массив → v8:FixedArray с v8:Value; без value → nil. Требует xmlns:app в Import-Fragment.
function Build-ChoiceParametersXml([string]$indent, $cp) {
if (-not $cp -or @($cp).Count -eq 0) { return "$indent<ChoiceParameters/>" }
$sb = New-Object System.Text.StringBuilder
$sb.Append("$indent<ChoiceParameters>") | Out-Null
foreach ($item in @($cp)) {
if ($item -is [string]) { $item = ConvertFrom-ChParamShorthand $item }
$name = Get-ChElProp $item @('name','имя')
$ptype = Get-ChElProp $item @('type','тип')
$hasVal = $false; $val = $null
if ($item -is [System.Collections.IDictionary]) {
if ($item.Contains('value')) { $hasVal = $true; $val = $item['value'] }
elseif ($item.Contains('значение')) { $hasVal = $true; $val = $item['значение'] }
} elseif ($item.PSObject) {
if ($item.PSObject.Properties['value']) { $hasVal = $true; $val = $item.PSObject.Properties['value'].Value }
elseif ($item.PSObject.Properties['значение']) { $hasVal = $true; $val = $item.PSObject.Properties['значение'].Value }
}
$valIsArray = ($val -is [System.Array]) -or ($val -is [System.Collections.IList] -and $val -isnot [string])
$sb.Append("`r`n$indent`t<app:item name=`"$(Esc-Xml "$name")`">") | Out-Null
if (-not $hasVal) {
$sb.Append("`r`n$indent`t`t<app:value xsi:nil=`"true`"/>") | Out-Null
} elseif ($valIsArray) {
$sb.Append("`r`n$indent`t`t<app:value xsi:type=`"v8:FixedArray`">") | Out-Null
foreach ($v in $val) {
$norm = Normalize-ChoiceValueT $v $ptype
if ([string]::IsNullOrEmpty($norm.Text)) { $sb.Append("`r`n$indent`t`t`t<v8:Value xsi:type=`"$($norm.XsiType)`"/>") | Out-Null }
else { $sb.Append("`r`n$indent`t`t`t<v8:Value xsi:type=`"$($norm.XsiType)`">$(Esc-Xml $norm.Text)</v8:Value>") | Out-Null }
}
$sb.Append("`r`n$indent`t`t</app:value>") | Out-Null
} else {
$norm = Normalize-ChoiceValueT $val $ptype
if ([string]::IsNullOrEmpty($norm.Text)) { $sb.Append("`r`n$indent`t`t<app:value xsi:type=`"$($norm.XsiType)`"/>") | Out-Null }
else { $sb.Append("`r`n$indent`t`t<app:value xsi:type=`"$($norm.XsiType)`">$(Esc-Xml $norm.Text)</app:value>") | Out-Null }
}
$sb.Append("`r`n$indent`t</app:item>") | Out-Null
}
$sb.Append("`r`n$indent</ChoiceParameters>") | Out-Null
return $sb.ToString()
}
# --- Порт из meta-compile: явное значение заполнения (FillValue) ---
$script:fillBoolTrue = @('true','истина','да')
$script:fillBoolFalse = @('false','ложь','нет')
function Esc-XmlText([string]$s) { return $s.Replace('&','&amp;').Replace('<','&lt;').Replace('>','&gt;') }
function Get-FillTypeCategory([string]$typeStr) {
if (-not $typeStr) { return 'String' }
if ($typeStr -match '\+') { return 'Other' }
$t = Resolve-TypeStr $typeStr
if ($t -match '^Boolean$') { return 'Boolean' }
if ($t -match '^String(\(|$)') { return 'String' }
if ($t -match '^Number(\(|$)') { return 'Number' }
if ($t -match '^(Date|DateTime)$') { return 'Date' }
return 'Other'
}
function Expand-FillShortRef([string]$s, [string]$typeStr) {
if (-not $typeStr) { return $null }
if ($typeStr -match '\+') { return $null }
$t = Resolve-TypeStr $typeStr
if ($t -notmatch '^(\w+Ref)\.(.+)$') { return $null }
$root = $script:fillRefKindRoot[$Matches[1].ToLower()]
if (-not $root) { return $null }
$typeName = $Matches[2]
if ($script:fillEmptyRefWords -contains $s.ToLower()) { return "$root.$typeName.EmptyRef" }
if ($root -eq 'Enum') { return "Enum.$typeName.EnumValue.$s" }
return "$root.$typeName.$s"
}
function Resolve-FillValueSpec([string]$s, [string]$typeStr) {
$cat = Get-FillTypeCategory $typeStr
if ($s -eq '') { return @{ XsiType='xs:string'; Text='' } }
if ($cat -eq 'String') { return @{ XsiType='xs:string'; Text=$s } }
if ($cat -eq 'Boolean' -or ($script:fillBoolTrue -contains $s.ToLower()) -or ($script:fillBoolFalse -contains $s.ToLower())) {
if ($script:fillBoolTrue -contains $s.ToLower()) { return @{ XsiType='xs:boolean'; Text='true' } }
if ($script:fillBoolFalse -contains $s.ToLower()) { return @{ XsiType='xs:boolean'; Text='false' } }
}
if ($cat -eq 'Number') { return @{ XsiType='xs:decimal'; Text=$s } }
if ($cat -eq 'Date' -or $s -match '^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2})?$') {
if ($s -match '^\d{4}-\d{2}-\d{2}$') { $s = "${s}T00:00:00" }
return @{ XsiType='xs:dateTime'; Text=$s }
}
$ref = Normalize-FillRef $s
if ($ref) { return @{ XsiType='xr:DesignTimeRef'; Text=$ref } }
$short = Expand-FillShortRef $s $typeStr
if ($short) { return @{ XsiType='xr:DesignTimeRef'; Text=$short } }
return @{ XsiType='xs:string'; Text=$s }
}
# Извлечь тип реквизита из XML (<Type>/<v8:Type>) → DSL-typeStr для категоризации FillValue.
function Get-AttrTypeStrFromXml($propsEl) {
$typeEl = $null
foreach ($ch in $propsEl.ChildNodes) { if ($ch.NodeType -eq 'Element' -and $ch.LocalName -eq 'Type') { $typeEl = $ch; break } }
if (-not $typeEl) { return "" }
$mapped = @()
foreach ($ch in $typeEl.ChildNodes) {
if ($ch.NodeType -eq 'Element' -and $ch.LocalName -eq 'Type') {
$t = $ch.InnerText.Trim()
$colon = $t.IndexOf(':'); if ($colon -ge 0) { $t = $t.Substring($colon + 1) }
switch -Regex ($t) {
'^string$' { $mapped += 'String'; break }
'^decimal$' { $mapped += 'Number'; break }
'^boolean$' { $mapped += 'Boolean'; break }
'^dateTime$' { $mapped += 'Date'; break }
default { $mapped += $t }
}
}
}
if ($mapped.Count -eq 0) { return "" }
if ($mapped.Count -gt 1) { return ($mapped -join ' + ') }
return $mapped[0]
}
# FillValue — явное значение (порт Emit-FillValue, ветка hasSpec). Маркеры {nil}/{emptyRef}; иначе по типу.
function Build-FillValueExplicitXml([string]$typeStr, $spec) {
if ($null -eq $spec) { return "<FillValue xsi:nil=`"true`"/>" }
if ($spec -is [bool]) { return "<FillValue xsi:type=`"xs:boolean`">$(if ($spec) { 'true' } else { 'false' })</FillValue>" }
if ($spec -is [int] -or $spec -is [long] -or $spec -is [double] -or $spec -is [decimal]) { return "<FillValue xsi:type=`"xs:decimal`">$(Format-FillNum $spec)</FillValue>" }
if ((Get-ChElProp $spec @('nil')) -eq $true) { return "<FillValue xsi:nil=`"true`"/>" }
if ((Get-ChElProp $spec @('emptyRef','пустаяссылка')) -eq $true) { return "<FillValue xsi:type=`"xr:DesignTimeRef`"/>" }
$r = Resolve-FillValueSpec "$spec" $typeStr
if ($r.Text -eq '' -and $r.XsiType -eq 'xs:string') { return "<FillValue xsi:type=`"xs:string`"/>" }
return "<FillValue xsi:type=`"$($r.XsiType)`">$(Esc-XmlText $r.Text)</FillValue>"
}
function Find-PropertyElement([string]$propName) {
@@ -2295,6 +2833,7 @@ function Get-ComplexPropertyValues([System.Xml.XmlElement]$propEl) {
function Add-ComplexPropertyItem([string]$propertyName, [string[]]$values) {
$mapEntry = $script:complexPropertyMap[$propertyName]
if (-not $mapEntry) { Warn "Unknown complex property: $propertyName"; return }
if ($mapEntry.expand) { $values = @($values | ForEach-Object { Expand-DataPath "$_" }) }
$propEl = Find-PropertyElement $propertyName
if (-not $propEl) {
@@ -2342,6 +2881,8 @@ function Add-ComplexPropertyItem([string]$propertyName, [string[]]$values) {
}
function Remove-ComplexPropertyItem([string]$propertyName, [string[]]$values) {
$mapEntry = $script:complexPropertyMap[$propertyName]
if ($mapEntry -and $mapEntry.expand) { $values = @($values | ForEach-Object { Expand-DataPath "$_" }) }
$propEl = Find-PropertyElement $propertyName
if (-not $propEl) {
Warn "Property element '$propertyName' not found in Properties"
@@ -2379,6 +2920,7 @@ function Remove-ComplexPropertyItem([string]$propertyName, [string[]]$values) {
function Set-ComplexProperty([string]$propertyName, [string[]]$values) {
$mapEntry = $script:complexPropertyMap[$propertyName]
if (-not $mapEntry) { Warn "Unknown complex property: $propertyName"; return }
if ($mapEntry.expand) { $values = @($values | ForEach-Object { Expand-DataPath "$_" }) }
$propEl = Find-PropertyElement $propertyName
if (-not $propEl) {
@@ -2428,6 +2970,95 @@ function Set-ComplexProperty([string]$propertyName, [string[]]$values) {
# Section 13: Main processing
# ============================================================
# ============================================================
# Predefined data (Ext/Predefined.xml) — add предопределённых (Catalog/ChartOfCharacteristicTypes).
# Существующие <Item id=GUID> сохраняются побайтово (текстовый append), новые получают свежий GUID —
# инвариант «не менять id существующей сущности».
# ============================================================
$script:predefXsiTypeByObj = @{
'Catalog' = 'CatalogPredefinedItems'
'ChartOfCharacteristicTypes' = 'PlanOfCharacteristicKindPredefinedItems'
}
function Get-PredefinedPath {
$objDir = Join-Path (Split-Path $resolvedPath) $script:objName
return (Join-Path (Join-Path $objDir "Ext") "Predefined.xml")
}
function Get-ObjectCodeType {
foreach ($ch in $script:propertiesEl.ChildNodes) {
if ($ch.NodeType -eq 'Element' -and $ch.LocalName -eq 'CodeType') { return $ch.InnerText.Trim() }
}
return 'String'
}
# Элемент DSL: строка "(Код) Имя [Наименование]" ЛИБО объект {name,code,description,isFolder,childItems}.
function Resolve-PredefItem($val) {
if ($val -is [string]) {
$s = "$val"; $descRaw = $null; $hasDesc = $false
if ($s -match '\[(.*)\]') { $descRaw = $Matches[1]; $hasDesc = $true; $s = $s -replace '\s*\[.*\]', '' }
$m = [regex]::Match($s.Trim(), '^\s*(?:\(([^)]*)\)\s*)?(\S+)\s*$')
$name = $m.Groups[2].Value
$code = if ($m.Groups[1].Success) { $m.Groups[1].Value } else { '' }
$desc = if ($hasDesc) { $descRaw } else { Split-CamelCase $name }
return @{ name = $name; code = $code; desc = $desc; isFolder = $false; children = @() }
}
$gv = { param($o, [string[]]$keys) foreach ($k in $keys) { if ($o.PSObject.Properties[$k]) { return $o.$k } } return $null }
$name = "$(& $gv $val @('name','имя'))"
$codeV = & $gv $val @('code','код'); $code = if ($null -ne $codeV) { "$codeV" } else { '' }
$hasDesc = $val.PSObject.Properties['description'] -or $val.PSObject.Properties['наименование']
$descV = & $gv $val @('description','наименование')
$desc = if ($hasDesc) { "$descV" } else { Split-CamelCase $name }
$isFolder = ((& $gv $val @('isFolder','группа')) -eq $true)
$subs = & $gv $val @('childItems','подчиненные')
return @{ name = $name; code = $code; desc = $desc; isFolder = $isFolder; children = @(if ($subs) { @($subs) } else { @() }) }
}
function Build-PredefItemXml([string]$indent, $val, [string]$codeType) {
$r = Resolve-PredefItem $val
$sb = New-Object System.Text.StringBuilder
[void]$sb.Append("$indent<Item id=`"$(New-Guid-String)`">`r`n")
[void]$sb.Append("$indent`t<Name>$(Esc-XmlText $r.name)</Name>`r`n")
if (-not $r.code) { [void]$sb.Append("$indent`t<Code/>`r`n") }
elseif ($codeType -eq 'Number') { [void]$sb.Append("$indent`t<Code xsi:type=`"xs:decimal`">$(Esc-XmlText $r.code)</Code>`r`n") }
else { [void]$sb.Append("$indent`t<Code>$(Esc-XmlText $r.code)</Code>`r`n") }
if ($r.desc -eq '') { [void]$sb.Append("$indent`t<Description/>`r`n") }
else { [void]$sb.Append("$indent`t<Description>$(Esc-XmlText $r.desc)</Description>`r`n") }
[void]$sb.Append("$indent`t<IsFolder>$(if ($r.isFolder) { 'true' } else { 'false' })</IsFolder>`r`n")
if ($r.children.Count -gt 0) {
[void]$sb.Append("$indent`t<ChildItems>`r`n")
foreach ($c in $r.children) { [void]$sb.Append((Build-PredefItemXml "$indent`t`t" $c $codeType)) }
[void]$sb.Append("$indent`t</ChildItems>`r`n")
}
[void]$sb.Append("$indent</Item>`r`n")
return $sb.ToString()
}
function Add-PredefinedItems($items) {
$xsiType = $script:predefXsiTypeByObj[$script:objType]
if (-not $xsiType) { Write-Error "add-predefined: тип объекта '$($script:objType)' не поддержан (только Catalog, ChartOfCharacteristicTypes)"; exit 1 }
$codeType = Get-ObjectCodeType
$version = $script:xmlDoc.DocumentElement.GetAttribute("version")
$path = Get-PredefinedPath
$itemsXml = ""
foreach ($it in @($items)) { $itemsXml += (Build-PredefItemXml "`t" $it $codeType) }
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
if (Test-Path $path) {
$text = [System.IO.File]::ReadAllText($path, $utf8Bom)
$text = $text.Replace("</PredefinedData>", "$itemsXml</PredefinedData>")
} else {
$extDir = Split-Path $path
if (-not (Test-Path $extDir)) { New-Item -ItemType Directory -Path $extDir -Force | Out-Null }
$hdr = "<?xml version=`"1.0`" encoding=`"UTF-8`"?>`r`n<PredefinedData xmlns=`"http://v8.1c.ru/8.3/xcf/predef`" xmlns:v8=`"http://v8.1c.ru/8.1/data/core`" 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`" xsi:type=`"$xsiType`" version=`"$version`">`r`n"
$text = "$hdr$itemsXml</PredefinedData>`r`n"
}
[System.IO.File]::WriteAllText($path, $text, $utf8Bom)
$n = @($items).Count
Info "Added $n predefined item(s) → $path"
$script:addCount += $n
}
# --- Inline mode conversion ---
if ($Operation) {
$def = Convert-InlineToDefinition $Operation $Value
+742 -8
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# meta-edit v1.9 — Edit existing 1C metadata object XML (inline mode + complex properties + TS attribute ops + modify-ts)
# meta-edit v1.19 — Edit existing 1C metadata object XML (+add-predefined предопределённые Ext/Predefined.xml)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -203,6 +203,7 @@ md_ns = ""
properties_el = None
child_objects_el = None
obj_name = ""
resolved_path = ""
add_count = 0
remove_count = 0
@@ -285,7 +286,7 @@ valid_enum_values = {
'Posting': ['Allow', 'Deny'],
'RealTimePosting': ['Allow', 'Deny'],
'EditType': ['InDialog', 'InList', 'BothWays'],
'HierarchyType': ['HierarchyFoldersAndItems', 'HierarchyItemsOnly'],
'HierarchyType': ['HierarchyFoldersAndItems', 'HierarchyOfItems'],
'CodeType': ['String', 'Number'],
'CodeAllowedLength': ['Variable', 'Fixed'],
'NumberType': ['String', 'Number'],
@@ -567,6 +568,8 @@ def import_fragment(xml_string):
f' xmlns:v8="{V8_NS}"'
f' xmlns:xr="{XR_NS}"'
f' xmlns:cfg="{CFG_NS}"'
f' xmlns:app="http://v8.1c.ru/8.2/managed-application/core"'
f' xmlns:ent="http://v8.1c.ru/8.1/data/enterprise"'
f' xmlns:xs="{XS_NS}">'
f"{xml_string}</_W>"
)
@@ -861,14 +864,43 @@ RESERVED_ATTR_NAMES_RU = {
}
# Стандартные реквизиты по типу объекта (EN + RU). Совпадение имени реквизита с ними платформа
# не позволит — жёсткий отказ. Контексты вне карты → предупреждение по плоскому списку.
RESERVED_BY_CONTEXT = {
'catalog': {
'ref', 'ссылка',
'deletionmark', 'пометкаудаления',
'predefined', 'предопределенный',
'predefineddataname', 'имяпредопределенныхданных',
'code', 'код',
'description', 'наименование',
'owner', 'владелец',
'parent', 'родитель',
'isfolder', 'этогруппа',
},
'document': {
'ref', 'ссылка',
'deletionmark', 'пометкаудаления',
'date', 'дата',
'number', 'номер',
'posted', 'проведен',
},
}
def build_attribute_fragment(parsed, context, indent):
"""Build XML fragment string for an Attribute element."""
if not context:
context = get_attribute_context()
# Check reserved attribute names
# Check reserved attribute names (типозависимо: catalog/document — отказ; прочее — предупреждение)
attr_name = parsed['name']
if attr_name in RESERVED_ATTR_NAMES or attr_name in RESERVED_ATTR_NAMES_RU:
ctx_reserved = RESERVED_BY_CONTEXT.get(context)
if ctx_reserved is not None:
if attr_name.lower() in ctx_reserved:
print(f"meta-edit: имя реквизита '{attr_name}' зарезервировано стандартным реквизитом объекта '{context}'. Выберите другое имя.", file=sys.stderr)
sys.exit(1)
elif context not in ('tabular', 'processor-tabular') and (attr_name in RESERVED_ATTR_NAMES or attr_name in RESERVED_ATTR_NAMES_RU):
print(f"WARNING: Attribute '{attr_name}' conflicts with a standard attribute name. This may cause errors when loading into 1C.", file=sys.stderr)
uid = new_uuid()
@@ -1399,6 +1431,8 @@ def convert_inline_to_definition(operation, value):
"registerRecord": "RegisterRecords", "registerRecords": "RegisterRecords",
"basedOn": "BasedOn",
"inputByString": "InputByString",
"dataLockField": "DataLockFields", "dataLockFields": "DataLockFields",
"registeredDocument": "RegisteredDocuments", "registeredDocuments": "RegisteredDocuments",
}
if target in complex_target_map:
@@ -1425,6 +1459,11 @@ def convert_inline_to_definition(operation, value):
complex_action = "set" if op == "set" else op
return {"_complex": [{"action": complex_action, "property": prop_name, "values": values}]}
# Предопределённые (Ext/Predefined.xml) — отдельный файл; строим { <op>: { predefined: [...] } }.
if target == "predefined":
items = [v.strip() for v in value.split(";;") if v.strip()]
return {op: {"predefined": items}}
# TS attribute operations: dot notation "TSName.AttrDef"
if target == "ts-attribute":
items = [v.strip() for v in value.split(";;") if v.strip()]
@@ -1634,6 +1673,9 @@ def process_add(add_def):
global add_count
for raw_key, items in add_def.items():
if raw_key in ('predefined', 'предопределенные', 'предопределённые'):
add_predefined_items(items)
continue
child_type = resolve_child_type_key(raw_key)
if not child_type:
@@ -1829,8 +1871,17 @@ def modify_properties(props_def):
break
if prop_el is None:
warn(f"Property '{prop_name}' not found in Properties")
continue
# create-if-missing: известное свойство создаём (порядок 1С терпит); неизвестное → ошибка (опечатка)
if prop_name not in known_object_props:
print(f"meta-edit: modify-property: неизвестное свойство '{prop_name}' — нет такого свойства объекта (опечатка?)", file=sys.stderr)
sys.exit(1)
new_nodes = import_fragment(f"<{prop_name}/>")
if new_nodes:
insert_property_in_order(properties_el, new_nodes[0], None, prop_name)
prop_el = new_nodes[0]
else:
warn(f"Property '{prop_name}': could not create element")
continue
# Complex property: Owners, RegisterRecords, BasedOn, InputByString
if prop_name in complex_property_map:
@@ -2051,6 +2102,47 @@ def modify_child_elements(modify_def, child_type):
info(f"Changed synonym of {xml_tag} '{elem_name}': {change_value}")
modify_count += 1
elif change_prop == "Format":
if set_attr_property_element(props_el, "Format", build_mltext_xml(get_child_indent(props_el), "Format", str(change_value))):
info(f"Set {xml_tag} '{elem_name}'.Format")
modify_count += 1
elif change_prop == "EditFormat":
if set_attr_property_element(props_el, "EditFormat", build_mltext_xml(get_child_indent(props_el), "EditFormat", str(change_value))):
info(f"Set {xml_tag} '{elem_name}'.EditFormat")
modify_count += 1
elif change_prop == "ToolTip":
if set_attr_property_element(props_el, "ToolTip", build_mltext_xml(get_child_indent(props_el), "ToolTip", str(change_value))):
info(f"Set {xml_tag} '{elem_name}'.ToolTip")
modify_count += 1
elif change_prop == "ChoiceForm":
if set_attr_property_element(props_el, "ChoiceForm", f"<ChoiceForm>{esc_xml(str(change_value))}</ChoiceForm>"):
info(f"Set {xml_tag} '{elem_name}'.ChoiceForm")
modify_count += 1
elif change_prop == "MinValue":
if set_attr_property_element(props_el, "MinValue", build_min_max_value_xml("MinValue", change_value)):
info(f"Set {xml_tag} '{elem_name}'.MinValue")
modify_count += 1
elif change_prop == "MaxValue":
if set_attr_property_element(props_el, "MaxValue", build_min_max_value_xml("MaxValue", change_value)):
info(f"Set {xml_tag} '{elem_name}'.MaxValue")
modify_count += 1
elif change_prop == "LinkByType":
if set_attr_property_element(props_el, "LinkByType", build_link_by_type_xml(get_child_indent(props_el), change_value)):
info(f"Set {xml_tag} '{elem_name}'.LinkByType")
modify_count += 1
elif change_prop == "ChoiceParameterLinks":
if set_attr_property_element(props_el, "ChoiceParameterLinks", build_choice_parameter_links_xml(get_child_indent(props_el), change_value)):
info(f"Set {xml_tag} '{elem_name}'.ChoiceParameterLinks")
modify_count += 1
elif change_prop == "ChoiceParameters":
if set_attr_property_element(props_el, "ChoiceParameters", build_choice_parameters_xml(get_child_indent(props_el), change_value)):
info(f"Set {xml_tag} '{elem_name}'.ChoiceParameters")
modify_count += 1
elif change_prop == "FillValue":
if set_attr_property_element(props_el, "FillValue", build_fill_value_explicit_xml(get_attr_type_str_from_xml(props_el), change_value)):
info(f"Set {xml_tag} '{elem_name}'.FillValue")
modify_count += 1
else:
# Scalar property change (Indexing, FillChecking, Use, etc.)
scalar_el = None
@@ -2071,7 +2163,20 @@ def modify_child_elements(modify_def, child_type):
info(f"Modified {xml_tag} '{elem_name}'.{change_prop} = {value_str}")
modify_count += 1
else:
warn(f"{xml_tag} '{elem_name}': property '{change_prop}' not found")
# create-if-missing: известное свойство создаём в позиции; неизвестное → ошибка (опечатка)
if change_prop not in known_child_props:
print(f"meta-edit: modify: неизвестное свойство '{change_prop}' у {xml_tag} '{elem_name}' (опечатка?)", file=sys.stderr)
sys.exit(1)
value_str = str(change_value)
if isinstance(change_value, bool):
value_str = "true" if change_value else "false"
else:
value_str = normalize_enum_value(change_prop, value_str)
new_nodes = import_fragment(f"<{change_prop}>{esc_xml(value_str)}</{change_prop}>")
if new_nodes:
insert_property_in_order(props_el, new_nodes[0], attr_prop_order, change_prop)
info(f"Created {xml_tag} '{elem_name}'.{change_prop} = {value_str}")
modify_count += 1
def process_modify(modify_def):
@@ -2097,8 +2202,519 @@ complex_property_map = {
"RegisterRecords": {"tag": "xr:Item", "attr": 'xsi:type="xr:MDObjectRef"'},
"BasedOn": {"tag": "xr:Item", "attr": 'xsi:type="xr:MDObjectRef"'},
"InputByString": {"tag": "xr:Field", "attr": None},
"DataLockFields": {"tag": "xr:Field", "attr": None, "expand": True},
"RegisteredDocuments": {"tag": "xr:Item", "attr": 'xsi:type="xr:MDObjectRef"'},
}
# Известные свойства объекта (union по корпусу acc+erp 8.3.24) — allowlist для modify-property.
# Известное отсутствующее свойство create-if-missing создаётся; неизвестное (опечатка) → ошибка.
known_object_props = {
'ActionPeriod', 'ActionPeriodUse', 'Addressing', 'AutoOrderByCode', 'Autonumbering', 'AuxiliaryChoiceForm',
'AuxiliaryFolderChoiceForm', 'AuxiliaryFolderForm', 'AuxiliaryForm', 'AuxiliaryListForm', 'AuxiliaryObjectForm',
'AuxiliaryRecordForm', 'AuxiliarySettingsForm', 'BaseCalculationTypes', 'BasePeriod', 'BasedOn',
'CharacteristicExtValues', 'Characteristics', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'CheckUnique',
'ChoiceDataGetModeOnInputByString', 'ChoiceFoldersAndItems', 'ChoiceForm', 'ChoiceHistoryOnInput', 'ChoiceMode',
'ChoiceParameterLinks', 'ChoiceParameters', 'CodeAllowedLength', 'CodeLength', 'CodeMask', 'CodeSeries', 'CodeType',
'Comment', 'Correspondence', 'CreateOnInput', 'CreateTaskInPrivilegedMode', 'CurrentPerformer', 'DataHistory',
'DataLockControlMode', 'DataLockFields', 'DefaultChoiceForm', 'DefaultFolderChoiceForm', 'DefaultFolderForm',
'DefaultForm', 'DefaultListForm', 'DefaultObjectForm', 'DefaultPresentation', 'DefaultRecordForm', 'DefaultSettingsForm',
'DefaultVariantForm', 'DependenceOnCalculationTypes', 'DescriptionLength', 'DistributedInfoBase', 'EditFormat',
'EditType', 'EnableTotalsSliceFirst', 'EnableTotalsSliceLast', 'EnableTotalsSplitting',
'ExecuteAfterWriteDataHistoryVersionProcessing', 'Explanation', 'ExtDimensionTypes', 'ExtendedEdit',
'ExtendedListPresentation', 'ExtendedObjectPresentation', 'ExtendedPresentation', 'ExtendedRecordPresentation',
'FillChecking', 'FoldersOnTop', 'Format', 'FullTextSearch', 'FullTextSearchOnInputByString', 'Hierarchical',
'HierarchyType', 'IncludeConfigurationExtensions', 'IncludeHelpInContents', 'InformationRegisterPeriodicity',
'InputByString', 'LevelCount', 'LimitLevelCount', 'LinkByType', 'ListPresentation', 'MainAddressingAttribute',
'MainDataCompositionSchema', 'MainFilterOnPeriod', 'MarkNegatives', 'Mask', 'MaxExtDimensionCount', 'MaxValue',
'MinValue', 'MultiLine', 'Name', 'NumberAllowedLength', 'NumberLength', 'NumberPeriodicity', 'NumberType', 'Numerator',
'ObjectPresentation', 'OrderLength', 'Owners', 'PasswordMode', 'PeriodAdjustmentLength', 'Periodicity',
'PostInPrivilegedMode', 'Posting', 'PredefinedDataUpdate', 'QuickChoice', 'RealTimePosting', 'RecordPresentation',
'RegisterRecords', 'RegisterRecordsDeletion', 'RegisterRecordsWritingOnPost', 'RegisterType', 'RegisteredDocuments',
'Schedule', 'ScheduleDate', 'ScheduleValue', 'SearchStringModeOnInputByString', 'SequenceFilling', 'SettingsStorage',
'StandardAttributes', 'StandardTabularSections', 'SubordinationUse', 'Synonym', 'Task', 'TaskNumberAutoPrefix',
'ToolTip', 'Type', 'UnpostInPrivilegedMode', 'UpdateDataHistoryImmediatelyAfterWrite', 'UseStandardCommands',
'VariantsStorage', 'WriteMode',
}
# Известные свойства дочерних элементов (union Attribute/Dimension/Resource) — allowlist default-ветки modify-child.
known_child_props = {
'AccountingFlag', 'Balance', 'BaseDimension', 'ChoiceFoldersAndItems', 'ChoiceForm', 'ChoiceHistoryOnInput',
'ChoiceParameterLinks', 'ChoiceParameters', 'Comment', 'CreateOnInput', 'DataHistory', 'DenyIncompleteValues',
'DocumentMap', 'EditFormat', 'ExtDimensionAccountingFlag', 'ExtendedEdit', 'FillChecking', 'FillFromFillingValue',
'FillValue', 'Format', 'FullTextSearch', 'Indexing', 'LinkByType', 'MainFilter', 'MarkNegatives', 'Mask', 'Master',
'MaxValue', 'MinValue', 'MultiLine', 'Name', 'PasswordMode', 'QuickChoice', 'RegisterRecordsMap', 'ScheduleLink',
'Synonym', 'ToolTip', 'Type', 'Use', 'UseInTotals',
}
# Канонический порядок свойств реквизита (последовательность build_attribute_fragment) — для вставки в позицию.
attr_prop_order = [
'Name', 'Synonym', 'Comment', 'Type', 'PasswordMode', 'Format', 'EditFormat', 'ToolTip', 'MarkNegatives', 'Mask',
'MultiLine', 'ExtendedEdit', 'MinValue', 'MaxValue', 'FillFromFillingValue', 'FillValue', 'FillChecking',
'ChoiceFoldersAndItems', 'ChoiceParameterLinks', 'ChoiceParameters', 'QuickChoice', 'CreateOnInput', 'ChoiceForm',
'LinkByType', 'ChoiceHistoryOnInput', 'Use', 'Indexing', 'FullTextSearch', 'DataHistory',
]
def insert_property_in_order(props_el, new_node, order_array, prop_name):
"""Вставить новое свойство в Properties в канонической позиции (по order_array); иначе append."""
child_indent = get_child_indent(props_el)
ref_node = None
idx = order_array.index(prop_name) if (order_array and prop_name in order_array) else -1
if idx >= 0:
for ch in props_el:
cl = localname(ch)
if cl in order_array and order_array.index(cl) > idx:
ref_node = ch
break
insert_before_element(props_el, new_node, ref_node, child_indent)
def set_attr_property_element(props_el, prop_name, fragment_xml):
"""Заменить существующий элемент свойства реквизита новым фрагментом, либо создать в позиции."""
new_nodes = import_fragment(fragment_xml)
if not new_nodes:
return False
existing = None
for ch in props_el:
if localname(ch) == prop_name:
existing = ch
break
if existing is not None:
idx = list(props_el).index(existing)
new_nodes[0].tail = existing.tail
props_el.insert(idx + 1, new_nodes[0])
remove_node_with_whitespace(existing)
else:
insert_property_in_order(props_el, new_nodes[0], attr_prop_order, prop_name)
return True
def build_min_max_value_xml(tag, val):
"""MinValue/MaxValue — типизированное значение (порт Emit-MinMaxValue): nil / xs:string / xs:decimal."""
if val is None or str(val) == '':
return f'<{tag} xsi:nil="true"/>'
t = 'xs:string' if isinstance(val, str) else 'xs:decimal'
return f'<{tag} xsi:type="{t}">{esc_xml(str(val))}</{tag}>'
# --- Порт из meta-compile: развёртка путей данных + связи выбора / тип по ссылке (structural modify) ---
def get_ch_el_prop(obj, names):
"""Свойство из dict по списку синонимов (первый найденный, иначе None)."""
if obj is None:
return None
if isinstance(obj, dict):
for n in names:
if n in obj:
return obj[n]
return None
# Пары EN↔RU стандартных реквизитов Catalog/Document (для resolve_std_attr_en; py-карты плоские, восстанавливаем).
_STD_ATTR_BY_CTX = {
'Catalog': [('Ref', 'Ссылка'), ('DeletionMark', 'ПометкаУдаления'), ('Predefined', 'Предопределенный'),
('PredefinedDataName', 'ИмяПредопределенныхДанных'), ('Code', 'Код'), ('Description', 'Наименование'),
('Owner', 'Владелец'), ('Parent', 'Родитель'), ('IsFolder', 'ЭтоГруппа')],
'Document': [('Ref', 'Ссылка'), ('DeletionMark', 'ПометкаУдаления'), ('Date', 'Дата'),
('Number', 'Номер'), ('Posted', 'Проведен')],
}
def resolve_std_attr_en(name):
"""Стандартный реквизит рус/англ → английский (Catalog/Document)."""
pairs = _STD_ATTR_BY_CTX.get(obj_type)
if not pairs:
return None
nl = str(name).lower()
for en, ru in pairs:
if nl == en.lower() or nl == ru.lower():
return en
return None
def expand_data_path(dp):
"""Прощающий ввод пути данных: короткое имя реквизита → полный путь объекта (порт Expand-DataPath)."""
if not dp:
return dp
s = str(dp)
if re.search(r'[:/]', s):
return s
if re.match(r'^-?\d+$', s):
return s
if re.match(r'^(StandardAttribute|Attribute)\.', s):
return f"{obj_type}.{obj_name}.{s}"
if '.' not in s:
en = resolve_std_attr_en(s)
if en:
return f"{obj_type}.{obj_name}.StandardAttribute.{en}"
return f"{obj_type}.{obj_name}.Attribute.{s}"
return s
def convert_from_ch_link_shorthand(s):
"""Shorthand "name=path" | "name=path:Clear|DontChange"{name, dataPath, valueChange?}."""
eq = s.find('=')
if eq < 0:
return {'name': s.strip()}
o = {'name': s[:eq].strip()}
rest = s[eq + 1:].strip()
m = re.match(r'^(.*):(Clear|DontChange|очистить|неизменять)$', rest, re.IGNORECASE)
if m:
o['dataPath'] = m.group(1).strip()
o['valueChange'] = m.group(2)
else:
o['dataPath'] = rest
return o
def build_link_by_type_xml(indent, spec):
"""LinkByType — {dataPath, linkItem?} (порт Emit-LinkByType)."""
if not spec:
return f"{indent}<LinkByType/>"
if isinstance(spec, str):
dp = spec
li = 0
else:
dp = str(get_ch_el_prop(spec, ['dataPath', 'path', 'путь']) or '')
li_raw = get_ch_el_prop(spec, ['linkItem', 'элементСвязи'])
li = li_raw if li_raw is not None else 0
if not dp:
return f"{indent}<LinkByType/>"
dp = expand_data_path(dp)
return "\r\n".join([
f"{indent}<LinkByType>",
f"{indent}\t<xr:DataPath>{esc_xml(str(dp))}</xr:DataPath>",
f"{indent}\t<xr:LinkItem>{li}</xr:LinkItem>",
f"{indent}</LinkByType>",
])
def build_choice_parameter_links_xml(indent, cpl):
"""ChoiceParameterLinks — [{name, dataPath, valueChange?}] (порт Emit-ChoiceParameterLinks)."""
items = cpl if isinstance(cpl, list) else ([cpl] if cpl else [])
if not items:
return f"{indent}<ChoiceParameterLinks/>"
parts = [f"{indent}<ChoiceParameterLinks>"]
for lk in items:
if isinstance(lk, str):
lk = convert_from_ch_link_shorthand(lk)
name = get_ch_el_prop(lk, ['name', 'имя'])
dp = expand_data_path(get_ch_el_prop(lk, ['dataPath', 'path', 'путь']))
vc_raw = get_ch_el_prop(lk, ['valueChange', 'режимИзменения'])
vc = 'Clear'
if vc_raw:
low = str(vc_raw).lower()
if re.match(r'^(clear|очистить|очистка)$', low):
vc = 'Clear'
elif re.match(r'^(dontchange|неизменять|неменять|нет)$', low):
vc = 'DontChange'
else:
vc = str(vc_raw)
parts.append(f"{indent}\t<xr:Link>")
parts.append(f"{indent}\t\t<xr:Name>{esc_xml(str(name) if name is not None else '')}</xr:Name>")
parts.append(f'{indent}\t\t<xr:DataPath xsi:type="xs:string">{esc_xml(str(dp) if dp is not None else "")}</xr:DataPath>')
parts.append(f"{indent}\t\t<xr:ValueChange>{vc}</xr:ValueChange>")
parts.append(f"{indent}\t</xr:Link>")
parts.append(f"{indent}</ChoiceParameterLinks>")
return "\r\n".join(parts)
# --- Порт из meta-compile: значения параметров выбора (ChoiceParameters) ---
fill_ref_roots = {
'перечисление': 'Enum', 'справочник': 'Catalog', 'документ': 'Document',
'плансчетов': 'ChartOfAccounts', 'планвидовхарактеристик': 'ChartOfCharacteristicTypes',
'планвидоврасчета': 'ChartOfCalculationTypes', 'планвидоврасчёта': 'ChartOfCalculationTypes',
'планобмена': 'ExchangePlan', 'бизнеспроцесс': 'BusinessProcess', 'задача': 'Task',
'enum': 'Enum', 'catalog': 'Catalog', 'document': 'Document', 'chartofaccounts': 'ChartOfAccounts',
'chartofcharacteristictypes': 'ChartOfCharacteristicTypes', 'chartofcalculationtypes': 'ChartOfCalculationTypes',
'exchangeplan': 'ExchangePlan', 'businessprocess': 'BusinessProcess', 'task': 'Task',
}
fill_empty_ref_words = {'emptyref', 'пустаяссылка'}
fill_enum_val_words = {'enumvalue', 'значениеперечисления'}
account_type_values = ('Active', 'Passive', 'ActivePassive')
fill_ref_kind_root = {
'catalogref': 'Catalog', 'documentref': 'Document', 'enumref': 'Enum',
'chartofaccountsref': 'ChartOfAccounts', 'chartofcharacteristictypesref': 'ChartOfCharacteristicTypes',
'chartofcalculationtypesref': 'ChartOfCalculationTypes', 'exchangeplanref': 'ExchangePlan',
'businessprocessref': 'BusinessProcess', 'taskref': 'Task',
}
def convert_to_ch_scalar(s):
t = str(s).strip()
if re.match(r'^(true|истина)$', t, re.IGNORECASE):
return True
if re.match(r'^(false|ложь)$', t, re.IGNORECASE):
return False
if re.match(r'^-?\d+$', t):
return int(t)
if re.match(r'^-?\d+\.\d+$', t):
return float(t)
return t
def format_fill_num(n):
if isinstance(n, float):
return str(int(n)) if n == int(n) else repr(n)
return str(n)
def normalize_fill_ref(s):
if not s:
return None
if re.match(r'^[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}\.[0-9a-fA-F-]+$', s):
return s
parts = s.split('.')
if len(parts) < 2:
return None
root = fill_ref_roots.get(parts[0].lower())
if not root:
return None
type_name = parts[1]
if root == 'Enum':
if len(parts) == 2:
return None
if len(parts) == 3:
if parts[2].lower() in fill_empty_ref_words:
return f"Enum.{type_name}.EmptyRef"
return f"Enum.{type_name}.EnumValue.{parts[2]}"
member = parts[2]
rest = '.'.join(parts[3:]) if member.lower() in fill_enum_val_words else '.'.join(parts[2:])
return f"Enum.{type_name}.EnumValue.{rest}"
tail = list(parts[1:])
for i in range(len(tail)):
if tail[i].lower() in fill_empty_ref_words:
tail[i] = 'EmptyRef'
return f"{root}." + '.'.join(tail)
def expand_choice_ref_value(value, type_str):
if not type_str:
return None
t = resolve_type_str(type_str)
root = None
tn = None
m = re.match(r'^(\w+Ref)\.(.+)$', t)
if m:
root = fill_ref_kind_root.get(m.group(1).lower())
tn = m.group(2)
else:
m2 = re.match(r'^([^.]+)\.(.+)$', t)
if m2:
root = fill_ref_roots.get(m2.group(1).lower())
tn = m2.group(2)
if not root:
return None
if str(value).lower() in fill_empty_ref_words:
return f"{root}.{tn}.EmptyRef"
if root == 'Enum':
return f"Enum.{tn}.EnumValue.{value}"
return f"{root}.{tn}.{value}"
def normalize_choice_value(value):
if isinstance(value, bool):
return {'XsiType': 'xs:boolean', 'Text': 'true' if value else 'false'}
if isinstance(value, (int, float)):
return {'XsiType': 'xs:decimal', 'Text': format_fill_num(value)}
s = str(value)
if s == '':
return {'XsiType': 'xs:string', 'Text': ''}
if re.match(r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$', s):
return {'XsiType': 'xs:dateTime', 'Text': s}
ref = normalize_fill_ref(s)
if ref:
return {'XsiType': 'xr:DesignTimeRef', 'Text': ref}
if s in account_type_values:
return {'XsiType': 'ent:AccountType', 'Text': s}
return {'XsiType': 'xs:string', 'Text': s}
def normalize_choice_value_t(value, type_str):
if type_str and isinstance(value, str) and '.' not in str(value):
ex = expand_choice_ref_value(value, type_str)
if ex:
return {'XsiType': 'xr:DesignTimeRef', 'Text': ex}
return normalize_choice_value(value)
def convert_from_ch_param_shorthand(s):
eq = s.find('=')
if eq < 0:
return {'name': s.strip()}
name = s[:eq].strip()
rest = s[eq + 1:]
if ',' in rest:
return {'name': name, 'value': [convert_to_ch_scalar(p) for p in rest.split(',')]}
return {'name': name, 'value': convert_to_ch_scalar(rest)}
def build_choice_parameters_xml(indent, cp):
"""ChoiceParameters — [{name, type?, value?}] (порт Emit-ChoiceParameters). Требует xmlns:app в import_fragment."""
items = cp if isinstance(cp, list) else ([cp] if cp else [])
if not items:
return f"{indent}<ChoiceParameters/>"
parts = [f"{indent}<ChoiceParameters>"]
for item in items:
if isinstance(item, str):
item = convert_from_ch_param_shorthand(item)
name = get_ch_el_prop(item, ['name', 'имя'])
ptype = get_ch_el_prop(item, ['type', 'тип'])
has_val = False
val = None
if isinstance(item, dict):
if 'value' in item:
has_val = True
val = item['value']
elif 'значение' in item:
has_val = True
val = item['значение']
val_is_array = isinstance(val, list)
parts.append(f'{indent}\t<app:item name="{esc_xml(str(name) if name is not None else "")}">')
if not has_val:
parts.append(f'{indent}\t\t<app:value xsi:nil="true"/>')
elif val_is_array:
parts.append(f'{indent}\t\t<app:value xsi:type="v8:FixedArray">')
for v in val:
norm = normalize_choice_value_t(v, ptype)
if not norm['Text']:
parts.append(f'{indent}\t\t\t<v8:Value xsi:type="{norm["XsiType"]}"/>')
else:
parts.append(f'{indent}\t\t\t<v8:Value xsi:type="{norm["XsiType"]}">{esc_xml(norm["Text"])}</v8:Value>')
parts.append(f'{indent}\t\t</app:value>')
else:
norm = normalize_choice_value_t(val, ptype)
if not norm['Text']:
parts.append(f'{indent}\t\t<app:value xsi:type="{norm["XsiType"]}"/>')
else:
parts.append(f'{indent}\t\t<app:value xsi:type="{norm["XsiType"]}">{esc_xml(norm["Text"])}</app:value>')
parts.append(f'{indent}\t</app:item>')
parts.append(f"{indent}</ChoiceParameters>")
return "\r\n".join(parts)
# --- Порт из meta-compile: явное значение заполнения (FillValue) ---
fill_bool_true = {'true', 'истина', 'да'}
fill_bool_false = {'false', 'ложь', 'нет'}
def esc_xml_text(s):
return s.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
def get_fill_type_category(type_str):
if not type_str:
return 'String'
if '+' in type_str:
return 'Other'
t = resolve_type_str(type_str)
if re.match(r'^Boolean$', t):
return 'Boolean'
if re.match(r'^String(\(|$)', t):
return 'String'
if re.match(r'^Number(\(|$)', t):
return 'Number'
if re.match(r'^(Date|DateTime)$', t):
return 'Date'
return 'Other'
def expand_fill_short_ref(s, type_str):
if not type_str or '+' in type_str:
return None
t = resolve_type_str(type_str)
m = re.match(r'^(\w+Ref)\.(.+)$', t)
if not m:
return None
root = fill_ref_kind_root.get(m.group(1).lower())
if not root:
return None
type_name = m.group(2)
if s.lower() in fill_empty_ref_words:
return f"{root}.{type_name}.EmptyRef"
if root == 'Enum':
return f"Enum.{type_name}.EnumValue.{s}"
return f"{root}.{type_name}.{s}"
def resolve_fill_value_spec(s, type_str):
cat = get_fill_type_category(type_str)
if s == '':
return {'XsiType': 'xs:string', 'Text': ''}
if cat == 'String':
return {'XsiType': 'xs:string', 'Text': s}
if cat == 'Boolean' or s.lower() in fill_bool_true or s.lower() in fill_bool_false:
if s.lower() in fill_bool_true:
return {'XsiType': 'xs:boolean', 'Text': 'true'}
if s.lower() in fill_bool_false:
return {'XsiType': 'xs:boolean', 'Text': 'false'}
if cat == 'Number':
return {'XsiType': 'xs:decimal', 'Text': s}
if cat == 'Date' or re.match(r'^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2})?$', s):
if re.match(r'^\d{4}-\d{2}-\d{2}$', s):
s = s + 'T00:00:00'
return {'XsiType': 'xs:dateTime', 'Text': s}
ref = normalize_fill_ref(s)
if ref:
return {'XsiType': 'xr:DesignTimeRef', 'Text': ref}
short = expand_fill_short_ref(s, type_str)
if short:
return {'XsiType': 'xr:DesignTimeRef', 'Text': short}
return {'XsiType': 'xs:string', 'Text': s}
def get_attr_type_str_from_xml(props_el):
"""Извлечь тип реквизита из XML (<Type>/<v8:Type>) → DSL-typeStr для категоризации FillValue."""
type_el = None
for ch in props_el:
if localname(ch) == 'Type':
type_el = ch
break
if type_el is None:
return ""
mapped = []
for ch in type_el:
if localname(ch) == 'Type':
t = (ch.text or '').strip()
colon = t.find(':')
if colon >= 0:
t = t[colon + 1:]
if t == 'string':
mapped.append('String')
elif t == 'decimal':
mapped.append('Number')
elif t == 'boolean':
mapped.append('Boolean')
elif t == 'dateTime':
mapped.append('Date')
else:
mapped.append(t)
if not mapped:
return ""
if len(mapped) > 1:
return ' + '.join(mapped)
return mapped[0]
def build_fill_value_explicit_xml(type_str, spec):
"""FillValue — явное значение (порт Emit-FillValue, ветка hasSpec)."""
if spec is None:
return '<FillValue xsi:nil="true"/>'
if isinstance(spec, bool):
return f'<FillValue xsi:type="xs:boolean">{"true" if spec else "false"}</FillValue>'
if isinstance(spec, (int, float)):
return f'<FillValue xsi:type="xs:decimal">{format_fill_num(spec)}</FillValue>'
if get_ch_el_prop(spec, ['nil']) is True:
return '<FillValue xsi:nil="true"/>'
if get_ch_el_prop(spec, ['emptyRef', 'пустаяссылка']) is True:
return '<FillValue xsi:type="xr:DesignTimeRef"/>'
r = resolve_fill_value_spec(str(spec), type_str)
if r['Text'] == '' and r['XsiType'] == 'xs:string':
return '<FillValue xsi:type="xs:string"/>'
return f'<FillValue xsi:type="{r["XsiType"]}">{esc_xml_text(r["Text"])}</FillValue>'
def find_property_element(prop_name):
for child in properties_el:
@@ -2121,6 +2737,8 @@ def add_complex_property_item(property_name, values):
if not map_entry:
warn(f"Unknown complex property: {property_name}")
return
if map_entry.get("expand"):
values = [expand_data_path(str(v)) for v in values]
prop_el = find_property_element(property_name)
if prop_el is None:
@@ -2160,6 +2778,9 @@ def add_complex_property_item(property_name, values):
def remove_complex_property_item(property_name, values):
global remove_count
map_entry = complex_property_map.get(property_name)
if map_entry and map_entry.get("expand"):
values = [expand_data_path(str(v)) for v in values]
prop_el = find_property_element(property_name)
if prop_el is None:
warn(f"Property element '{property_name}' not found in Properties")
@@ -2190,6 +2811,8 @@ def set_complex_property(property_name, values):
if not map_entry:
warn(f"Unknown complex property: {property_name}")
return
if map_entry.get("expand"):
values = [expand_data_path(str(v)) for v in values]
prop_el = find_property_element(property_name)
if prop_el is None:
@@ -2258,25 +2881,136 @@ def save_xml(tree, path):
# Main
# ============================================================
# ============================================================
# Predefined data (Ext/Predefined.xml) — add предопределённых (Catalog/ChartOfCharacteristicTypes).
# Существующие <Item id=GUID> сохраняются побайтово (текстовый append), новые получают свежий GUID.
# ============================================================
predef_xsi_type_by_obj = {
'Catalog': 'CatalogPredefinedItems',
'ChartOfCharacteristicTypes': 'PlanOfCharacteristicKindPredefinedItems',
}
def get_predefined_path():
return os.path.join(os.path.dirname(resolved_path), obj_name, "Ext", "Predefined.xml")
def get_object_code_type():
for ch in properties_el:
if localname(ch) == 'CodeType':
return (ch.text or '').strip()
return 'String'
def resolve_predef_item(val):
if isinstance(val, str):
s = val
desc_raw = None
has_desc = False
m = re.search(r'\[(.*)\]', s)
if m:
desc_raw = m.group(1)
has_desc = True
s = re.sub(r'\s*\[.*\]', '', s)
mm = re.match(r'^\s*(?:\(([^)]*)\)\s*)?(\S+)\s*$', s.strip())
name = mm.group(2) if mm else s.strip()
code = mm.group(1) if (mm and mm.group(1) is not None) else ''
desc = desc_raw if has_desc else split_camel_case(name)
return {'name': name, 'code': code, 'desc': desc, 'isFolder': False, 'children': []}
def gv(o, keys):
for k in keys:
if isinstance(o, dict) and k in o:
return o[k]
return None
name = str(gv(val, ['name', 'имя']) or '')
code_v = gv(val, ['code', 'код'])
code = str(code_v) if code_v is not None else ''
has_desc = isinstance(val, dict) and ('description' in val or 'наименование' in val)
desc_v = gv(val, ['description', 'наименование'])
desc = str(desc_v) if has_desc else split_camel_case(name)
is_folder = gv(val, ['isFolder', 'группа']) is True
subs = gv(val, ['childItems', 'подчиненные'])
return {'name': name, 'code': code, 'desc': desc if desc is not None else '',
'isFolder': is_folder, 'children': list(subs) if subs else []}
def build_predef_item_xml(indent, val, code_type):
r = resolve_predef_item(val)
parts = [f'{indent}<Item id="{new_uuid()}">']
parts.append(f'{indent}\t<Name>{esc_xml_text(r["name"])}</Name>')
if not r['code']:
parts.append(f'{indent}\t<Code/>')
elif code_type == 'Number':
parts.append(f'{indent}\t<Code xsi:type="xs:decimal">{esc_xml_text(r["code"])}</Code>')
else:
parts.append(f'{indent}\t<Code>{esc_xml_text(r["code"])}</Code>')
if r['desc'] == '':
parts.append(f'{indent}\t<Description/>')
else:
parts.append(f'{indent}\t<Description>{esc_xml_text(r["desc"])}</Description>')
parts.append(f'{indent}\t<IsFolder>{"true" if r["isFolder"] else "false"}</IsFolder>')
if r['children']:
parts.append(f'{indent}\t<ChildItems>')
for c in r['children']:
parts.append(build_predef_item_xml(indent + '\t\t', c, code_type).rstrip('\r\n'))
parts.append(f'{indent}\t</ChildItems>')
parts.append(f'{indent}</Item>')
return '\r\n'.join(parts) + '\r\n'
def add_predefined_items(items):
global add_count
xsi_type = predef_xsi_type_by_obj.get(obj_type)
if not xsi_type:
print(f"add-predefined: тип объекта '{obj_type}' не поддержан (только Catalog, ChartOfCharacteristicTypes)", file=sys.stderr)
sys.exit(1)
code_type = get_object_code_type()
version = xml_root.get("version")
path = get_predefined_path()
item_list = items if isinstance(items, list) else [items]
items_xml = ''.join(build_predef_item_xml('\t', it, code_type) for it in item_list)
if os.path.exists(path):
with open(path, 'r', encoding='utf-8-sig') as f:
text = f.read()
text = text.replace('</PredefinedData>', items_xml + '</PredefinedData>')
else:
os.makedirs(os.path.dirname(path), exist_ok=True)
hdr = ('<?xml version="1.0" encoding="UTF-8"?>\r\n<PredefinedData xmlns="http://v8.1c.ru/8.3/xcf/predef" '
'xmlns:v8="http://v8.1c.ru/8.1/data/core" 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" '
f'xsi:type="{xsi_type}" version="{version}">\r\n')
text = hdr + items_xml + '</PredefinedData>\r\n'
with open(path, 'wb') as f:
f.write(b'\xef\xbb\xbf')
f.write(text.encode('utf-8'))
info(f"Added {len(item_list)} predefined item(s) -> {path}")
add_count += len(item_list)
def main():
sys.stdout.reconfigure(encoding="utf-8")
sys.stderr.reconfigure(encoding="utf-8")
global xml_tree, xml_root, obj_element, obj_type, md_ns
global properties_el, child_objects_el, obj_name
global properties_el, child_objects_el, obj_name, resolved_path
global add_count, remove_count, modify_count, warn_count
valid_operations = [
"add-attribute", "add-ts", "add-dimension", "add-resource",
"add-enumValue", "add-column", "add-form", "add-template", "add-command",
"add-owner", "add-registerRecord", "add-basedOn", "add-inputByString",
"add-dataLockField", "add-registeredDocument", "add-predefined",
"remove-attribute", "remove-ts", "remove-dimension", "remove-resource",
"remove-enumValue", "remove-column", "remove-form", "remove-template", "remove-command",
"remove-owner", "remove-registerRecord", "remove-basedOn", "remove-inputByString",
"remove-dataLockField", "remove-registeredDocument",
"add-ts-attribute", "remove-ts-attribute", "modify-ts-attribute", "modify-ts",
"modify-attribute", "modify-dimension", "modify-resource",
"modify-enumValue", "modify-column",
"modify-property",
"set-owners", "set-registerRecords", "set-basedOn", "set-inputByString",
"set-dataLockFields", "set-registeredDocuments",
]
parser = argparse.ArgumentParser(description="Edit existing 1C metadata object XML", allow_abbrev=False)
+1 -1
View File
@@ -23,7 +23,7 @@ allowed-tools:
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-info.ps1" -ObjectPath "<путь>"
python "${CLAUDE_SKILL_DIR}/scripts/meta-info.py" -ObjectPath "<путь>"
```
## Три режима
+1 -1
View File
@@ -32,7 +32,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-remove.ps1" -ConfigDir "<путь>" -Object "Catalog.Товары"
python "${CLAUDE_SKILL_DIR}/scripts/meta-remove.py" -ConfigDir "<путь>" -Object "Catalog.Товары"
```
## Поддерживаемые типы
+2 -2
View File
@@ -24,6 +24,6 @@ allowed-tools:
## Команда
```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/Банки|Documents/Заказ"
python "${CLAUDE_SKILL_DIR}/scripts/meta-validate.py" -ObjectPath "Catalogs/Номенклатура/Номенклатура.xml"
python "${CLAUDE_SKILL_DIR}/scripts/meta-validate.py" -ObjectPath "Catalogs/Банки|Documents/Заказ"
```
@@ -1,4 +1,4 @@
# meta-validate v1.4 — Validate 1C metadata object structure
# meta-validate v1.9 — Validate 1C metadata object structure
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -65,6 +65,12 @@ if (Test-Path $ObjectPath -PathType Container) {
}
}
# File not found — прощающий ввод для плоских объектов (SessionParameter, CommonAttribute,
# DefinedType, WSReference, … — один .xml без папки): дописать .xml к голому имени
if (-not (Test-Path $ObjectPath) -and -not [System.IO.Path]::HasExtension($ObjectPath)) {
if (Test-Path "$ObjectPath.xml") { $ObjectPath = "$ObjectPath.xml" }
}
# File not found — check Dir/Name/Name.xml → Dir/Name.xml
if (-not (Test-Path $ObjectPath)) {
$fileName = [System.IO.Path]::GetFileNameWithoutExtension($ObjectPath)
@@ -162,6 +168,15 @@ $validTypes = @(
"HTTPService","WebService","DefinedType"
)
# Валидные типы метаданных без глубоких правил валидации — раньше падали как "Unrecognized"
# (ложная ошибка на валидном объекте). Для них выполняется базовая структурная проверка (root/uuid/Name).
$structuralOnlyTypes = @(
"Subsystem","Role","CommonForm","CommonCommand","CommandGroup","CommonAttribute",
"CommonTemplate","CommonPicture","SessionParameter","SettingsStorage","FilterCriterion",
"FunctionalOption","FunctionalOptionsParameter","Language","Style","StyleItem",
"WSReference","XDTOPackage","DocumentNumerator","Sequence"
)
# GeneratedType categories by type
$generatedTypeCategories = @{
"Catalog" = @("Object","Ref","Selection","List","Manager")
@@ -240,6 +255,11 @@ $childObjectRules = @{
"EventSubscription" = @()
}
# Группы командного интерфейса (зеркало meta-compile): раздела — без commandParameterType; формы — с параметром.
$sectionCommandGroups = @("NavigationPanelImportant","NavigationPanelOrdinary","NavigationPanelSeeAlso","ActionsPanelCreate","ActionsPanelReports","ActionsPanelTools")
$formCommandGroups = @("FormCommandBarImportant","FormCommandBarCreateBasedOn","FormNavigationPanelImportant","FormNavigationPanelGoTo","FormNavigationPanelSeeAlso")
$validCommandGroups = $sectionCommandGroups + $formCommandGroups
# Valid enum property values
$validPropertyValues = @{
"CodeType" = @("String","Number")
@@ -253,7 +273,7 @@ $validPropertyValues = @{
"DataLockControlMode" = @("Automatic","Managed")
"FullTextSearch" = @("Use","DontUse")
"DefaultPresentation" = @("AsDescription","AsCode")
"HierarchyType" = @("HierarchyFoldersAndItems","HierarchyItemsOnly")
"HierarchyType" = @("HierarchyFoldersAndItems","HierarchyOfItems")
"EditType" = @("InDialog","InList","BothWays")
"WriteMode" = @("Independent","RecorderSubordinate")
"InformationRegisterPeriodicity" = @("Nonperiodical","Second","Day","Month","Quarter","Year","RecorderPosition")
@@ -350,7 +370,7 @@ if ($childElements.Count -eq 0) {
$typeNode = $childElements[0]
$mdType = $typeNode.LocalName
if ($validTypes -notcontains $mdType) {
if (($validTypes -notcontains $mdType) -and ($structuralOnlyTypes -notcontains $mdType)) {
Report-Error "1. Unrecognized metadata type: $mdType"
& $finalize
exit 1
@@ -378,6 +398,20 @@ if ($check1Ok) {
Report-OK "1. Root structure: MetaDataObject/$mdType, version $version"
}
# --- Structural-only types: базовая проверка (Name), без type-specific правил ---
if ($structuralOnlyTypes -contains $mdType) {
if ($objName -eq "(unknown)") {
Report-Error "3. Properties: missing or empty Name"
} elseif ($objName -notmatch $identPattern) {
Report-Error "3. Properties: Name '$objName' is not a valid 1C identifier"
} else {
Report-OK "3. Properties: Name=`"$objName`" (базовая структурная проверка для $mdType)"
}
& $finalize
if ($script:errors -gt 0) { exit 1 }
exit 0
}
if ($script:stopped) { & $finalize; exit 1 }
# --- Check 2: InternalInfo ---
@@ -699,17 +733,31 @@ if ($childObjNode) {
if ($script:stopped) { & $finalize; exit 1 }
# --- Check 7b: Reserved attribute names ---
# --- Check 7b: Reserved attribute names (типозависимо: стандартные реквизиты ДАННОГО типа, EN+RU) ---
# Совпадение имени собственного реквизита со стандартным (англ. или рус.) платформа не примет → ошибка.
$reservedAttrNames = @(
"Ref","DeletionMark","Code","Description","Date","Number","Posted","Parent","Owner",
"IsFolder","Predefined","PredefinedDataName","Recorder","Period","LineNumber","Active",
"Order","Type","OffBalance","Started","Completed","HeadTask","Executed","RoutePoint",
"BusinessProcess","ThisNode","SentNo","ReceivedNo","CalculationType","RegistrationPeriod",
"ReversingEntry","Account","ValueType","ActionPeriodIsBasic"
)
$reservedEnRu = @{
"Ref"="Ссылка"; "DeletionMark"="ПометкаУдаления"; "Code"="Код"; "Description"="Наименование"
"Date"="Дата"; "Number"="Номер"; "Posted"="Проведен"; "Parent"="Родитель"; "Owner"="Владелец"
"IsFolder"="ЭтоГруппа"; "Predefined"="Предопределенный"; "PredefinedDataName"="ИмяПредопределенныхДанных"
"Recorder"="Регистратор"; "Period"="Период"; "LineNumber"="НомерСтроки"; "Active"="Активность"
"Order"="Порядок"; "Type"="Тип"; "OffBalance"="Забалансовый"; "RecordType"="ВидДвижения"
"Started"="Стартован"; "Completed"="Завершен"; "HeadTask"="ВедущаяЗадача"
"Executed"="Выполнена"; "RoutePoint"="ТочкаМаршрута"; "BusinessProcess"="БизнесПроцесс"
"ThisNode"="ЭтотУзел"; "SentNo"="НомерОтправленного"; "ReceivedNo"="НомерПринятого"
"CalculationType"="ВидРасчета"; "RegistrationPeriod"="ПериодРегистрации"; "ReversingEntry"="СторноЗапись"
"Account"="Счет"; "ValueType"="ТипЗначения"; "ActionPeriodIsBasic"="ПериодДействияБазовый"
}
if ($childObjNode) {
$stdForType = $standardAttributesByType[$mdType]
if ($childObjNode -and $stdForType) {
# Множество зарезервированных имён (EN + RU) в нижнем регистре.
$reservedSet = @{}
foreach ($en in $stdForType) {
$reservedSet[$en.ToLower()] = $true
$ru = $reservedEnRu[$en]
if ($ru) { $reservedSet[$ru.ToLower()] = $true }
}
$check7bOk = $true
$attrNodes = $childObjNode.SelectNodes("md:Attribute", $ns)
foreach ($attrNode in $attrNodes) {
@@ -718,8 +766,8 @@ if ($childObjNode) {
$attrNameNode = $attrProps.SelectSingleNode("md:Name", $ns)
if ($attrNameNode -and $attrNameNode.InnerText) {
$an = $attrNameNode.InnerText
if ($reservedAttrNames -contains $an) {
Report-Warn "7b. Attribute '$an' conflicts with a standard attribute name"
if ($reservedSet.ContainsKey($an.ToLower())) {
Report-Error "7b. Attribute '$an' conflicts with a standard attribute of $mdType"
$check7bOk = $false
}
}
@@ -728,6 +776,8 @@ if ($childObjNode) {
if ($check7bOk) {
Report-OK "7b. Reserved attribute names: no conflicts"
}
} elseif ($childObjNode) {
Report-OK "7b. Reserved attribute names: no conflicts (no standard set for $mdType)"
}
if ($script:stopped) { & $finalize; exit 1 }
@@ -1330,6 +1380,99 @@ if ($mdType -eq "DocumentJournal" -and $childObjNode) {
}
}
if ($script:stopped) { & $finalize; exit 1 }
# --- Check 15: Commands — Group обязателен/валиден; секц.группа несовместима с CommandParameterType ---
if ($childObjNode) {
$commands = $childObjNode.SelectNodes("md:Command", $ns)
$check15Ok = $true
$cmdCount = 0
foreach ($cmd in $commands) {
if ($script:stopped) { break }
$cmdCount++
$cuuid = $cmd.GetAttribute("uuid")
$cmdProps = $cmd.SelectSingleNode("md:Properties", $ns)
$cmdNameNode = if ($cmdProps) { $cmdProps.SelectSingleNode("md:Name", $ns) } else { $null }
$cmdName = if ($cmdNameNode -and $cmdNameNode.InnerText) { $cmdNameNode.InnerText } else { "(unnamed)" }
if (-not $cuuid -or $cuuid -notmatch $guidPattern) {
Report-Error "15. Command '$cmdName': missing or invalid uuid"; $check15Ok = $false
}
if ($cmdName -eq "(unnamed)") {
Report-Error "15. Command (uuid=$cuuid): missing or empty Name"; $check15Ok = $false
}
$groupNode = if ($cmdProps) { $cmdProps.SelectSingleNode("md:Group", $ns) } else { $null }
$groupVal = if ($groupNode) { $groupNode.InnerText.Trim() } else { "" }
if (-not $groupVal) {
Report-Error "15. Command '$cmdName': не задана группа (Group) — 1С отвергает при загрузке"; $check15Ok = $false
} elseif (($validCommandGroups -notcontains $groupVal) -and ($groupVal -notmatch '^CommandGroup\.')) {
Report-Error "15. Command '$cmdName': неизвестная группа '$groupVal'. Валидные: $($validCommandGroups -join ', '); либо CommandGroup.<Имя>"; $check15Ok = $false
} elseif ($sectionCommandGroups -contains $groupVal) {
$cptNode = if ($cmdProps) { $cmdProps.SelectSingleNode("md:CommandParameterType", $ns) } else { $null }
$hasCpt = $cptNode -and (($cptNode.SelectNodes("v8:Type", $ns).Count -gt 0) -or ($cptNode.SelectNodes("v8:TypeSet", $ns).Count -gt 0))
if ($hasCpt) {
Report-Error "15. Command '$cmdName': тип параметра (CommandParameterType) недоступен для команд командного интерфейса раздела ('$groupVal')"; $check15Ok = $false
}
}
}
if ($check15Ok -and $cmdCount -gt 0) {
Report-OK "15. Commands: $cmdCount command(s), groups valid"
}
}
# --- Check 16: Reference type existence — типы вида CatalogRef.X должны разрешаться в объекты конфигурации ---
# WARN-уровень: ложное срабатывание на частичных выгрузках хуже пропуска. Расширения (CFE) пропускаем —
# их типы ссылаются на объекты базовой конфигурации, которых нет в выгрузке расширения.
if ($script:configDir) {
$isExtension = $false
$cfgXmlPath = Join-Path $script:configDir "Configuration.xml"
if (Test-Path $cfgXmlPath) {
$cfgContent = [System.IO.File]::ReadAllText($cfgXmlPath, [System.Text.Encoding]::UTF8)
if ($cfgContent.Contains("ConfigurationExtensionPurpose")) { $isExtension = $true }
}
if (-not $isExtension) {
$refDirMap = @{
"CatalogRef"="Catalogs"; "DocumentRef"="Documents"; "EnumRef"="Enums"
"ChartOfAccountsRef"="ChartsOfAccounts"; "ChartOfCharacteristicTypesRef"="ChartsOfCharacteristicTypes"
"ChartOfCalculationTypesRef"="ChartsOfCalculationTypes"; "BusinessProcessRef"="BusinessProcesses"
"ExchangePlanRef"="ExchangePlans"; "TaskRef"="Tasks"; "DefinedType"="DefinedTypes"
}
$typeNodes = $xmlDoc.SelectNodes("//v8:Type", $ns)
$checkedRefs = @{} # refKey -> $true если найден; для OK-условия
$missingRefs = @{} # refKey -> refDir
foreach ($tn in $typeNodes) {
$tv = $tn.InnerText.Trim()
if (-not $tv) { continue }
$colonIdx = $tv.IndexOf(':')
if ($colonIdx -ge 0) { $tv = $tv.Substring($colonIdx + 1) }
$dotIdx = $tv.IndexOf('.')
if ($dotIdx -lt 0) { continue }
$refCat = $tv.Substring(0, $dotIdx)
$refName = $tv.Substring($dotIdx + 1)
$refDir = $refDirMap[$refCat]
if (-not $refDir -or -not $refName) { continue }
$refKey = "$refCat.$refName"
if ($checkedRefs.ContainsKey($refKey)) { continue }
$refFolder = Join-Path $script:configDir (Join-Path $refDir $refName)
$refFile = Join-Path $script:configDir (Join-Path $refDir "$refName.xml")
if ((Test-Path $refFolder) -or (Test-Path $refFile)) {
$checkedRefs[$refKey] = $true
} else {
$checkedRefs[$refKey] = $false
$missingRefs[$refKey] = $refDir
}
}
if ($missingRefs.Count -gt 0) {
foreach ($mk in ($missingRefs.Keys | Sort-Object)) {
Report-Warn "16. Ссылочный тип '$mk' не найден в конфигурации ($($missingRefs[$mk])/) — при загрузке будет ошибка неизвестного типа"
}
} elseif ($checkedRefs.Count -gt 0) {
Report-OK "16. Reference types: $($checkedRefs.Count) resolved"
}
}
}
# --- Final output ---
& $finalize
@@ -1,4 +1,4 @@
# meta-validate v1.4 — Validate 1C metadata object structure (Python port)
# meta-validate v1.9 — Validate 1C metadata object structure (Python port)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import os
@@ -70,6 +70,12 @@ if os.path.isdir(object_path):
print(f"[ERROR] No XML file found in directory: {object_path}")
sys.exit(1)
# File not found -- прощающий ввод для плоских объектов (SessionParameter, CommonAttribute,
# DefinedType, WSReference, ... -- один .xml без папки): дописать .xml к голому имени
if not os.path.exists(object_path) and not os.path.splitext(object_path)[1]:
if os.path.exists(object_path + ".xml"):
object_path = object_path + ".xml"
# File not found -- check Dir/Name/Name.xml -> Dir/Name.xml
if not os.path.exists(object_path):
file_name = os.path.splitext(os.path.basename(object_path))[0]
@@ -162,6 +168,15 @@ valid_types = (
"HTTPService", "WebService", "DefinedType",
)
# Валидные типы метаданных без глубоких правил валидации — раньше падали как "Unrecognized"
# (ложная ошибка на валидном объекте). Для них выполняется базовая структурная проверка (root/uuid/Name).
structural_only_types = (
"Subsystem", "Role", "CommonForm", "CommonCommand", "CommandGroup", "CommonAttribute",
"CommonTemplate", "CommonPicture", "SessionParameter", "SettingsStorage", "FilterCriterion",
"FunctionalOption", "FunctionalOptionsParameter", "Language", "Style", "StyleItem",
"WSReference", "XDTOPackage", "DocumentNumerator", "Sequence",
)
# GeneratedType categories by type
generated_type_categories = {
"Catalog": ["Object", "Ref", "Selection", "List", "Manager"],
@@ -240,6 +255,13 @@ child_object_rules = {
"EventSubscription": [],
}
# Группы командного интерфейса (зеркало meta-compile): раздела — без commandParameterType; формы — с параметром.
SECTION_COMMAND_GROUPS = ["NavigationPanelImportant", "NavigationPanelOrdinary", "NavigationPanelSeeAlso",
"ActionsPanelCreate", "ActionsPanelReports", "ActionsPanelTools"]
FORM_COMMAND_GROUPS = ["FormCommandBarImportant", "FormCommandBarCreateBasedOn",
"FormNavigationPanelImportant", "FormNavigationPanelGoTo", "FormNavigationPanelSeeAlso"]
VALID_COMMAND_GROUPS = SECTION_COMMAND_GROUPS + FORM_COMMAND_GROUPS
# Valid enum property values
valid_property_values = {
"CodeType": ["String", "Number"],
@@ -253,7 +275,7 @@ valid_property_values = {
"DataLockControlMode": ["Automatic", "Managed"],
"FullTextSearch": ["Use", "DontUse"],
"DefaultPresentation": ["AsDescription", "AsCode"],
"HierarchyType": ["HierarchyFoldersAndItems", "HierarchyItemsOnly"],
"HierarchyType": ["HierarchyFoldersAndItems", "HierarchyOfItems"],
"EditType": ["InDialog", "InList", "BothWays"],
"WriteMode": ["Independent", "RecorderSubordinate"],
"InformationRegisterPeriodicity": ["Nonperiodical", "Second", "Day", "Month", "Quarter", "Year", "RecorderPosition"],
@@ -372,7 +394,7 @@ elif len(child_elements) > 1:
type_node = child_elements[0]
md_type = local_name(type_node)
if md_type not in valid_types:
if md_type not in valid_types and md_type not in structural_only_types:
report_error(f"1. Unrecognized metadata type: {md_type}")
finalize()
sys.exit(1)
@@ -397,6 +419,17 @@ output_lines.insert(0, f"=== Validation: {md_type}.{obj_name} ===")
if check1_ok:
report_ok(f"1. Root structure: MetaDataObject/{md_type}, version {version}")
# ── Structural-only types: базовая проверка (Name), без type-specific правил ──
if md_type in structural_only_types:
if obj_name == "(unknown)":
report_error("3. Properties: missing or empty Name")
elif not ident_pattern.match(obj_name):
report_error(f"3. Properties: Name '{obj_name}' is not a valid 1C identifier")
else:
report_ok(f'3. Properties: Name="{obj_name}" (базовая структурная проверка для {md_type})')
finalize()
sys.exit(1 if errors > 0 else 0)
if stopped:
finalize()
sys.exit(1)
@@ -676,18 +709,30 @@ if stopped:
finalize()
sys.exit(1)
# ── Check 7b: Reserved attribute names ───────────────────────
# ── Check 7b: Reserved attribute names (типозависимо: стандартные ДАННОГО типа, EN+RU) ───────
# Совпадение имени собственного реквизита со стандартным (англ. или рус.) платформа не примет → ошибка.
RESERVED_ATTR_NAMES = {
'Ref', 'DeletionMark', 'Code', 'Description', 'Date', 'Number', 'Posted',
'Parent', 'Owner', 'IsFolder', 'Predefined', 'PredefinedDataName',
'Recorder', 'Period', 'LineNumber', 'Active', 'Order', 'Type', 'OffBalance',
'Started', 'Completed', 'HeadTask', 'Executed', 'RoutePoint', 'BusinessProcess',
'ThisNode', 'SentNo', 'ReceivedNo', 'CalculationType', 'RegistrationPeriod',
'ReversingEntry', 'Account', 'ValueType', 'ActionPeriodIsBasic',
RESERVED_EN_RU = {
'Ref': 'Ссылка', 'DeletionMark': 'ПометкаУдаления', 'Code': 'Код', 'Description': 'Наименование',
'Date': 'Дата', 'Number': 'Номер', 'Posted': 'Проведен', 'Parent': 'Родитель', 'Owner': 'Владелец',
'IsFolder': 'ЭтоГруппа', 'Predefined': 'Предопределенный', 'PredefinedDataName': 'ИмяПредопределенныхДанных',
'Recorder': 'Регистратор', 'Period': 'Период', 'LineNumber': 'НомерСтроки', 'Active': 'Активность',
'Order': 'Порядок', 'Type': 'Тип', 'OffBalance': 'Забалансовый', 'RecordType': 'ВидДвижения',
'Started': 'Стартован', 'Completed': 'Завершен', 'HeadTask': 'ВедущаяЗадача',
'Executed': 'Выполнена', 'RoutePoint': 'ТочкаМаршрута', 'BusinessProcess': 'БизнесПроцесс',
'ThisNode': 'ЭтотУзел', 'SentNo': 'НомерОтправленного', 'ReceivedNo': 'НомерПринятого',
'CalculationType': 'ВидРасчета', 'RegistrationPeriod': 'ПериодРегистрации', 'ReversingEntry': 'СторноЗапись',
'Account': 'Счет', 'ValueType': 'ТипЗначения', 'ActionPeriodIsBasic': 'ПериодДействияБазовый',
}
if child_obj_node is not None:
std_for_type = standard_attributes_by_type.get(md_type)
if child_obj_node is not None and std_for_type:
reserved_set = set()
for en in std_for_type:
reserved_set.add(en.lower())
ru = RESERVED_EN_RU.get(en)
if ru:
reserved_set.add(ru.lower())
check7b_ok = True
for attr_node in find_all(child_obj_node, 'md:Attribute'):
attr_props = find(attr_node, 'md:Properties')
@@ -695,11 +740,13 @@ if child_obj_node is not None:
attr_name_node = find(attr_props, 'md:Name')
if attr_name_node is not None and inner_text(attr_name_node):
an = inner_text(attr_name_node)
if an in RESERVED_ATTR_NAMES:
report_warn(f"7b. Attribute '{an}' conflicts with a standard attribute name")
if an.lower() in reserved_set:
report_error(f"7b. Attribute '{an}' conflicts with a standard attribute of {md_type}")
check7b_ok = False
if check7b_ok:
report_ok("7b. Reserved attribute names: no conflicts")
elif child_obj_node is not None:
report_ok(f"7b. Reserved attribute names: no conflicts (no standard set for {md_type})")
if stopped:
finalize()
@@ -1238,6 +1285,104 @@ if md_type == "DocumentJournal" and child_obj_node is not None:
elif col_count == 0:
report_ok("14. DocumentJournal Columns: none")
if stopped:
finalize()
sys.exit(1)
# ── Check 15: Commands — Group обязателен/валиден; секц.группа несовместима с CommandParameterType ──
if child_obj_node is not None:
commands = find_all(child_obj_node, "md:Command")
check15_ok = True
cmd_count = 0
for cmd in commands:
if stopped:
break
cmd_count += 1
cuuid = cmd.get("uuid", "")
cmd_props = find(cmd, "md:Properties")
cmd_name_node = find(cmd_props, "md:Name") if cmd_props is not None else None
cmd_name = inner_text(cmd_name_node) if (cmd_name_node is not None and inner_text(cmd_name_node)) else "(unnamed)"
if not cuuid or not guid_pattern.match(cuuid):
report_error(f"15. Command '{cmd_name}': missing or invalid uuid")
check15_ok = False
if cmd_name == "(unnamed)":
report_error(f"15. Command (uuid={cuuid}): missing or empty Name")
check15_ok = False
group_node = find(cmd_props, "md:Group") if cmd_props is not None else None
group_val = inner_text(group_node).strip() if group_node is not None else ""
if not group_val:
report_error(f"15. Command '{cmd_name}': не задана группа (Group) — 1С отвергает при загрузке")
check15_ok = False
elif group_val not in VALID_COMMAND_GROUPS and not group_val.startswith("CommandGroup."):
report_error(f"15. Command '{cmd_name}': неизвестная группа '{group_val}'. "
f"Валидные: {', '.join(VALID_COMMAND_GROUPS)}; либо CommandGroup.<Имя>")
check15_ok = False
elif group_val in SECTION_COMMAND_GROUPS:
cpt_node = find(cmd_props, "md:CommandParameterType") if cmd_props is not None else None
has_cpt = cpt_node is not None and (len(find_all(cpt_node, "v8:Type")) > 0 or len(find_all(cpt_node, "v8:TypeSet")) > 0)
if has_cpt:
report_error(f"15. Command '{cmd_name}': тип параметра (CommandParameterType) недоступен "
f"для команд командного интерфейса раздела ('{group_val}')")
check15_ok = False
if check15_ok and cmd_count > 0:
report_ok(f"15. Commands: {cmd_count} command(s), groups valid")
# ── Check 16: Reference type existence — типы вида CatalogRef.X должны разрешаться в объекты конфигурации ──
# WARN-уровень: ложное срабатывание на частичных выгрузках хуже пропуска. Расширения (CFE) пропускаем —
# их типы ссылаются на объекты базовой конфигурации, которых нет в выгрузке расширения.
if config_dir:
is_extension = False
cfg_xml_path = os.path.join(config_dir, "Configuration.xml")
if os.path.exists(cfg_xml_path):
try:
with open(cfg_xml_path, "r", encoding="utf-8") as f:
cfg_content = f.read()
if "ConfigurationExtensionPurpose" in cfg_content:
is_extension = True
except Exception:
pass
if not is_extension:
ref_dir_map = {
"CatalogRef": "Catalogs", "DocumentRef": "Documents", "EnumRef": "Enums",
"ChartOfAccountsRef": "ChartsOfAccounts", "ChartOfCharacteristicTypesRef": "ChartsOfCharacteristicTypes",
"ChartOfCalculationTypesRef": "ChartsOfCalculationTypes", "BusinessProcessRef": "BusinessProcesses",
"ExchangePlanRef": "ExchangePlans", "TaskRef": "Tasks", "DefinedType": "DefinedTypes",
}
checked_refs = {} # ref_key -> найден ли; для условия OK
missing_refs = {} # ref_key -> ref_dir
for tn in find_all(root, ".//v8:Type"):
tv = inner_text(tn).strip()
if not tv:
continue
colon_idx = tv.find(":")
if colon_idx >= 0:
tv = tv[colon_idx + 1:]
dot_idx = tv.find(".")
if dot_idx < 0:
continue
ref_cat = tv[:dot_idx]
ref_name = tv[dot_idx + 1:]
ref_dir = ref_dir_map.get(ref_cat)
if not ref_dir or not ref_name:
continue
ref_key = f"{ref_cat}.{ref_name}"
if ref_key in checked_refs:
continue
ref_folder = os.path.join(config_dir, ref_dir, ref_name)
ref_file = os.path.join(config_dir, ref_dir, ref_name + ".xml")
if os.path.exists(ref_folder) or os.path.exists(ref_file):
checked_refs[ref_key] = True
else:
checked_refs[ref_key] = False
missing_refs[ref_key] = ref_dir
if missing_refs:
for mk in sorted(missing_refs):
report_warn(f"16. Ссылочный тип '{mk}' не найден в конфигурации ({missing_refs[mk]}/) — при загрузке будет ошибка неизвестного типа")
elif checked_refs:
report_ok(f"16. Reference types: {len(checked_refs)} resolved")
# ── Final output ──────────────────────────────────────────────
finalize()
+1 -1
View File
@@ -29,7 +29,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-compile.ps1" -JsonPath "<путь>.json" -OutputPath "<путь>/Template.xml"
python "${CLAUDE_SKILL_DIR}/scripts/mxl-compile.py" -JsonPath "<путь>.json" -OutputPath "<путь>/Template.xml"
```
## Рабочий процесс
+1 -1
View File
@@ -29,7 +29,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-decompile.ps1" -TemplatePath "<путь>/Template.xml" [-OutputPath "<путь>.json"]
python "${CLAUDE_SKILL_DIR}/scripts/mxl-decompile.py" -TemplatePath "<путь>/Template.xml" [-OutputPath "<путь>.json"]
```
## Рабочий процесс
+2 -2
View File
@@ -38,12 +38,12 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-info.ps1" -TemplatePath "<путь>"
python "${CLAUDE_SKILL_DIR}/scripts/mxl-info.py" -TemplatePath "<путь>"
```
Или по имени обработки/макета:
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-info.ps1" -ProcessorName "<Имя>" -TemplateName "<Макет>" [-SrcDir "<каталог>"]
python "${CLAUDE_SKILL_DIR}/scripts/mxl-info.py" -ProcessorName "<Имя>" -TemplateName "<Макет>" [-SrcDir "<каталог>"]
```
Дополнительные флаги:
+2 -2
View File
@@ -23,7 +23,7 @@ allowed-tools:
## Команда
```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 "src/МояОбработка/Templates/ПечатнаяФорма"
python "${CLAUDE_SKILL_DIR}/scripts/mxl-validate.py" -TemplatePath "Catalogs/Номенклатура/Templates/Макет"
python "${CLAUDE_SKILL_DIR}/scripts/mxl-validate.py" -TemplatePath "src/МояОбработка/Templates/ПечатнаяФорма"
```
+1 -1
View File
@@ -21,7 +21,7 @@ allowed-tools:
| `OutputDir` | Корень выгрузки конфигурации (где `Configuration.xml`, `Roles/` и т.д.) |
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-compile.ps1" -JsonPath "<json>" -OutputDir "<ConfigDir>"
python "${CLAUDE_SKILL_DIR}/scripts/role-compile.py" -JsonPath "<json>" -OutputDir "<ConfigDir>"
```
Создаёт `{OutputDir}/Roles/Имя.xml` и `{OutputDir}/Roles/Имя/Ext/Rights.xml`. Регистрирует `<Role>` в `Configuration.xml`.
+1 -1
View File
@@ -22,7 +22,7 @@ allowed-tools:
## Запуск скрипта
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-info.ps1" -RightsPath <path> -OutFile <output.txt>
python "${CLAUDE_SKILL_DIR}/scripts/role-info.py" -RightsPath <path> -OutFile <output.txt>
```
### Параметры
+1 -1
View File
@@ -23,5 +23,5 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-validate.ps1" -RightsPath "Roles/МояРоль"
python "${CLAUDE_SKILL_DIR}/scripts/role-validate.py" -RightsPath "Roles/МояРоль"
```
+2 -2
View File
@@ -23,10 +23,10 @@ allowed-tools:
```powershell
# Из файла
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-compile.ps1" -DefinitionFile "<json>" -OutputPath "<Template.xml>"
python "${CLAUDE_SKILL_DIR}/scripts/skd-compile.py" -DefinitionFile "<json>" -OutputPath "<Template.xml>"
# Из строки (без промежуточного файла)
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-compile.ps1" -Value '<json-string>' -OutputPath "<Template.xml>"
python "${CLAUDE_SKILL_DIR}/scripts/skd-compile.py" -Value '<json-string>' -OutputPath "<Template.xml>"
```
## JSON DSL — краткий справочник
+1 -1
View File
@@ -31,7 +31,7 @@ allowed-tools:
| `OutputPath` | Путь к выходному JSON. Если не задан — JSON в stdout |
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-decompile.ps1" -TemplatePath "<Template.xml>" -OutputPath "<out.json>"
python "${CLAUDE_SKILL_DIR}/scripts/skd-decompile.py" -TemplatePath "<Template.xml>" -OutputPath "<out.json>"
```
## Что получаешь
+1 -1
View File
@@ -25,7 +25,7 @@ allowed-tools:
| `NoSelection` | (опц.) Не добавлять поле в selection варианта |
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-edit.ps1" -TemplatePath "<path>" -Operation <op> -Value "<value>"
python "${CLAUDE_SKILL_DIR}/scripts/skd-edit.py" -TemplatePath "<path>" -Operation <op> -Value "<value>"
```
## Пакетный режим (batch)
+1 -1
View File
@@ -25,7 +25,7 @@ allowed-tools:
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-info.ps1" -TemplatePath "<путь>"
python "${CLAUDE_SKILL_DIR}/scripts/skd-info.py" -TemplatePath "<путь>"
```
С указанием режима:
+2 -2
View File
@@ -24,6 +24,6 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-validate.ps1" -TemplatePath "src/МойОтчёт/Templates/ОсновнаяСхема"
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-validate.ps1" -TemplatePath "Catalogs/Номенклатура/Templates/СКД/Ext/Template.xml"
python "${CLAUDE_SKILL_DIR}/scripts/skd-validate.py" -TemplatePath "src/МойОтчёт/Templates/ОсновнаяСхема"
python "${CLAUDE_SKILL_DIR}/scripts/skd-validate.py" -TemplatePath "Catalogs/Номенклатура/Templates/СКД/Ext/Template.xml"
```
+1 -1
View File
@@ -24,7 +24,7 @@ allowed-tools:
| `NoValidate` | Пропустить авто-валидацию |
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/subsystem-compile.ps1" -Value '<json>' -OutputDir '<ConfigDir>'
python "${CLAUDE_SKILL_DIR}/scripts/subsystem-compile.py" -Value '<json>' -OutputDir '<ConfigDir>'
```
## JSON-определение
+1 -1
View File
@@ -24,7 +24,7 @@ allowed-tools:
| `NoValidate` | Пропустить авто-валидацию |
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/subsystem-edit.ps1" -SubsystemPath '<path>' -Operation add-content -Value 'Catalog.Товары'
python "${CLAUDE_SKILL_DIR}/scripts/subsystem-edit.py" -SubsystemPath '<path>' -Operation add-content -Value 'Catalog.Товары'
```
## Операции
+1 -1
View File
@@ -23,7 +23,7 @@ allowed-tools:
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/subsystem-info.ps1" -SubsystemPath "<путь>"
python "${CLAUDE_SKILL_DIR}/scripts/subsystem-info.py" -SubsystemPath "<путь>"
```
## Пять режимов
+2 -2
View File
@@ -24,6 +24,6 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/subsystem-validate.ps1" -SubsystemPath "Subsystems/Продажи"
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/subsystem-validate.ps1" -SubsystemPath "Subsystems/Продажи.xml"
python "${CLAUDE_SKILL_DIR}/scripts/subsystem-validate.py" -SubsystemPath "Subsystems/Продажи"
python "${CLAUDE_SKILL_DIR}/scripts/subsystem-validate.py" -SubsystemPath "Subsystems/Продажи.xml"
```
+1 -1
View File
@@ -28,7 +28,7 @@ allowed-tools:
`-Path` — тот же путь, который отклонил `support-guard` (объект, форма, макет или каталог дампа).
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/support-edit.ps1" -Path "Catalogs/Контрагенты.xml" -Set editable
python "${CLAUDE_SKILL_DIR}/scripts/support-edit.py" -Path "Catalogs/Контрагенты.xml" -Set editable
```
## editable или off-support?
+2 -2
View File
@@ -33,7 +33,7 @@ allowed-tools:
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/add-template.ps1" -ObjectName "<ObjectName>" -TemplateName "<TemplateName>" -TemplateType "<TemplateType>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-SetMainSKD]
python "${CLAUDE_SKILL_DIR}/scripts/add-template.py" -ObjectName "<ObjectName>" -TemplateName "<TemplateName>" -TemplateType "<TemplateType>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-SetMainSKD]
```
## Пример
@@ -41,7 +41,7 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/add-template.ps1" -
Добавить основную СКД к отчёту в расширении:
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/add-template.ps1" -ObjectName "ОтчётПродажи" -TemplateName "ОсновнаяСхемаКомпоновкиДанных" -TemplateType "DataCompositionSchema" -SrcDir "src/cfe/МоёРасширение/Reports"
python "${CLAUDE_SKILL_DIR}/scripts/add-template.py" -ObjectName "ОтчётПродажи" -TemplateName "ОсновнаяСхемаКомпоновкиДанных" -TemplateType "DataCompositionSchema" -SrcDir "src/cfe/МоёРасширение/Reports"
```
## Маппинг типов

Some files were not shown because too many files have changed in this diff Show More