feat(meta-compile): создание внешних источников данных

Вид ExternalDataSource навыки meta-* не поддерживали вовсе: в корпусе выгрузок его нет
ни одного, формат был неизвестен. Разведан на стенде (PostgreSQL в Docker + база 8.3.24)
и по реальной выгрузке рабочего проекта.

meta-compile собирает источник целиком одним JSON: сам источник, его таблицы с полями
и функции. Единственный вид, у которого объект складывается более чем из одного XML —
файл источника плюс по файлу на таблицу в <Источник>/Tables/.

DSL без новых конвенций: tables — dict имя → массив полей ЛИБО объект (как tabularSections),
поле — обычный реквизит плюс три своих ключа (nameInDataSource/readOnly/allowNull),
ссылки на поля короткими именами (как inputByString у справочника), functions — dict
имя → строка ИЛИ объект (как urlTemplates). Параметры функций не объекты метаданных:
они живут в самом выражении как &1, &2.

Инструкция под каскадом: в SKILL.md строка индекса, вся специфика — в
reference/external-data-source.md.

meta-validate принимает ExternalDataSource и Table, знает их наборы GeneratedType,
состав ChildObjects и шестичастную ссылку на форму таблицы. Проверено на выгрузке
платформы и на чужой рабочей выгрузке из другого проекта — обе проходят чисто.

Раундтрип на платформе 8.3.24.1691: наш эмит → загрузка → выгрузка даёт файлы,
идентичные поданным (с точностью до uuid). Два поведения платформы пришлось воспроизвести
явно, оба измерены: ввод по строке выводится из поля представления, а заданное значение
незаполненного родителя платформа при загрузке XML сбрасывает в пустую строку — задать
его можно только интерактивно.

Спека: раздел «Внешние источники данных» в 1c-config-objects-spec.md, формат ссылок,
наборы GeneratedType, строка в индексе спек.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NBsZA5cr2WFThtgp7i5WVi
This commit is contained in:
Nick Shirokov
2026-09-05 20:53:37 +03:00
co-authored by Claude Opus 5
parent c1f07f96ad
commit 6dde36a690
20 changed files with 2071 additions and 39 deletions
+1
View File
@@ -98,6 +98,7 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-compile.ps1" -
| CommonModule, ScheduledJob, EventSubscription | `reference/code.md` | | CommonModule, ScheduledJob, EventSubscription | `reference/code.md` |
| HTTPService, WebService | `reference/web.md` | | HTTPService, WebService | `reference/web.md` |
| Enum, Constant, DefinedType | `reference/simple.md` | | Enum, Constant, DefinedType | `reference/simple.md` |
| ExternalDataSource (внешний источник данных) | `reference/external-data-source.md` |
| FunctionalOption, FilterCriterion, SettingsStorage, CommonForm, CommonPicture, CommonTemplate, служебные | `reference/other-types.md` | | FunctionalOption, FilterCriterion, SettingsStorage, CommonForm, CommonPicture, CommonTemplate, служебные | `reference/other-types.md` |
Кросс-типовые детали: Кросс-типовые детали:
@@ -0,0 +1,137 @@
# ExternalDataSource (внешний источник данных)
Источник описывается **одним JSON целиком**: сам источник, его таблицы с полями и функции.
Компилятор пишет несколько файлов — `ExternalDataSources/<Имя>.xml` и по файлу на таблицу
в `ExternalDataSources/<Имя>/Tables/`.
Параметров соединения в конфигурации нет: строка соединения, пользователь, пароль и тип СУБД
задаются в режиме «Предприятие» и хранятся в базе. В DSL их указывать негде и не нужно.
```json
{
"type": "ExternalDataSource",
"name": "PG",
"tables": {
"prices": ["product_id: Number(10,0)", "period: Date", "price: Number(15,2)"],
"products": {
"nameInDataSource": "eds.public.products",
"tableDataType": "ObjectData",
"keyFields": ["id"],
"presentationField": "name",
"fields": [
"id: Number(10,0)",
"name: String(150)",
"article: String(50) | nullable",
"parent_id: ExternalDataSourceTableRef.PG.products | nullable"
]
}
},
"functions": {
"total": { "expression": "public.f_total(&1, &2)", "returns": "Number(15,2)" }
}
}
```
## Свойства источника
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `dataLockControlMode` | `Automatic` | `Automatic` / `Managed` / `AutomaticAndManaged` |
| `tables` | `{}` | таблицы (см. ниже) |
| `functions` | `{}` | функции (см. ниже) |
При `AutomaticAndManaged` режим блокировок решает каждая таблица сама; при конкретном значении
одноимённое свойство таблицы игнорируется платформой.
## Таблицы
Ключ — имя таблицы в конфигурации. Значение — **массив полей** либо **объект** со свойствами
и ключом `fields` (та же двойственность, что у `tabularSections` справочника).
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `nameInDataSource` | = имя таблицы | имя физической таблицы; у платформы это `<база>.<схема>.<таблица>` |
| `tableType` | `Table` | `Table` — таблица или представление; `Expression` — табличная функция |
| `expressionInDataSource` | пусто | выражение для `Expression`, напр. `public.f_by_parent(&1)`; имя базы не указывается |
| `tableDataType` | `NonobjectData` | `ObjectData` (запись определяется одним полем) / `NonobjectData` |
| `keyFields` | `[]` | имена ключевых полей |
| `presentationField` | пусто | имя поля представления (только `ObjectData`) |
| `parentField` | пусто | имя поля родителя; его тип должен быть ссылкой на эту же таблицу |
| `unfilledParentValue` | `null` | значение «нет родителя»; `null` → NULL, число/строка → «Заданное значение» |
| `inputByString` | `[]` | имена полей ввода по строке |
| `dataVersionField` | пусто | имя поля версии данных |
| `dataLockFields` | `[]` | имена полей блокировки |
| `readOnly` | `false` | запрет записи |
| `transactionsIsolationLevel` | `Auto` | `Auto` / `ReadUncommitted` / `ReadCommitted` / `RepeatableRead` / `Serializable` |
| `dataLockControlMode` | `Automatic` | `Automatic` / `Managed` / `AutomaticAndManaged` |
| `basedOn` | `[]` | ввод на основании, ссылки вида `Catalog.Контрагенты` |
| `useStandardCommands` | `true` | bool |
| `quickChoice` | `false` | bool |
| `editType` | `InDialog` | `InDialog` / `InList` |
| `fields` | `[]` | поля (см. ниже); синоним — `columns` |
Ссылки на поля (`keyFields`, `presentationField`, `parentField`, `dataVersionField`,
`inputByString`, `dataLockFields`) задаются **короткими именами** — компилятор разворачивает их
в полный путь `ExternalDataSource.<Источник>.Table.<Таблица>.Field.<Поле>`.
Прочие свойства — представления (`objectPresentation`, `listPresentation`, …), формы по умолчанию
(`defaultObjectForm`, `defaultListForm`, …), `characteristics`, `explanation`,
`includeHelpInContents` — как у справочника.
## Поля
Строковая и объектная форма — те же, что у реквизитов (см. `attributes.md`). Своих ключа три:
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `nameInDataSource` | = имя поля | имя колонки; в одинарных кавычках уходит в SQL как есть |
| `readOnly` | `false` | поле не записывается (вычисляемые, автоинкрементные) |
| `allowNull` | `false` | допускает `NULL` |
Флаги строковой формы: `readonly`, `nullable`.
```json
"fields": [
"id: Number(10,0) | readonly",
{ "name": "article", "type": "String(50)", "nameInDataSource": "art_code", "allowNull": true }
]
```
Допустимые типы: `Number`, `String`, `Date`, `Boolean`, `UUID`, `BinaryData` и ссылка на таблицу
внешнего источника — `ExternalDataSourceTableRef.<Источник>.<Таблица>`.
**Составной тип запрещён платформой** — она отвергает загрузку с ошибкой «Поле не может иметь
составной тип», поэтому компилятор отказывает сразу.
## Функции
Ключ — имя функции. Значение — строка (интерпретируется как `expression`) либо объект.
| Ключ | Умолчание | Значения |
|------|-----------|----------|
| `expression` | — | выражение в источнике, обязательный |
| `returns` | `String` | тип возвращаемого значения |
| `returnValue` | `true` | `false` — процедура, тип не пишется |
Параметры функции **не являются объектами метаданных**: они записываются прямо в выражении как
`&1`, `&2`. Необязательные — в фигурных скобках `f(&1{, &2})`, переменное число — `&n[]`
(только последним).
```json
"functions": {
"nextKey": "NEXT VALUE FOR dbo.SimpleSequence",
"total": { "expression": "public.f_total(&1, &2)", "returns": "Number(15,2)" }
}
```
## Чего компилятор не делает
- **Кубы OLAP** (`Cube`, `DimensionTable`, `Dimension`, `Resource`) не поддерживаются.
- **Формы и модули** таблиц не создаются — как и у прочих объектов, для форм есть `form-add`
и `form-compile`.
## Пустой ключ таблицы — предупреждение, не ошибка
Конфигуратор интерактивно требует `keyFields`, а загрузка XML принимает таблицу без ключа молча.
Рабочие конфигурации без ключей существуют, поэтому компилятор такую таблицу собирает, а
`meta-validate` предупреждает. Без ключа недоступны форма записи и набор записей.
@@ -1,4 +1,4 @@
# meta-compile v1.104 — Compile 1C metadata object from JSON # meta-compile v1.105 — Compile 1C metadata object from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
[CmdletBinding(PositionalBinding=$false)] [CmdletBinding(PositionalBinding=$false)]
param( param(
@@ -279,6 +279,7 @@ $script:objectTypeSynonyms = @{
"ВебСервис" = "WebService" "ВебСервис" = "WebService"
"ОпределяемыйТип" = "DefinedType" "ОпределяемыйТип" = "DefinedType"
"ФункциональнаяОпция" = "FunctionalOption" "ФункциональнаяОпция" = "FunctionalOption"
"ВнешнийИсточникДанных" = "ExternalDataSource"
} }
# Enum property value synonyms — model often gets these slightly wrong # Enum property value synonyms — model often gets these slightly wrong
@@ -320,7 +321,9 @@ $script:validEnumValues = @{
"WriteMode" = @("Independent","RecorderSubordinate") "WriteMode" = @("Independent","RecorderSubordinate")
"InformationRegisterPeriodicity" = @("Nonperiodical","Second","Day","Month","Quarter","Year","RecorderPosition") "InformationRegisterPeriodicity" = @("Nonperiodical","Second","Day","Month","Quarter","Year","RecorderPosition")
"DependenceOnCalculationTypes" = @("DontUse","OnActionPeriod") "DependenceOnCalculationTypes" = @("DontUse","OnActionPeriod")
"DataLockControlMode" = @("Automatic","Managed") # AutomaticAndManaged — только у внешнего источника данных и его таблиц: там режим может
# решаться на уровне таблицы, у прочих объектов такого значения нет.
"DataLockControlMode" = @("Automatic","Managed","AutomaticAndManaged")
"FullTextSearch" = @("Use","DontUse") "FullTextSearch" = @("Use","DontUse")
"DataHistory" = @("Use","DontUse") "DataHistory" = @("Use","DontUse")
"DefaultPresentation" = @("AsDescription","AsCode") "DefaultPresentation" = @("AsDescription","AsCode")
@@ -472,7 +475,7 @@ $validTypes = @("Catalog","Document","Enum","Constant","InformationRegister","Ac
"HTTPService","WebService","DefinedType","FunctionalOption", "HTTPService","WebService","DefinedType","FunctionalOption",
"Sequence","FilterCriterion","DocumentNumerator","SettingsStorage","CommonForm", "Sequence","FilterCriterion","DocumentNumerator","SettingsStorage","CommonForm",
"SessionParameter","CommonCommand","CommandGroup","CommonAttribute","FunctionalOptionsParameter","WSReference", "SessionParameter","CommonCommand","CommandGroup","CommonAttribute","FunctionalOptionsParameter","WSReference",
"CommonPicture","CommonTemplate") "CommonPicture","CommonTemplate","ExternalDataSource")
# -notin регистронезависим, поэтому "catalog" проходил проверку и дальше шёл в ИМЯ ТЕГА и в # -notin регистронезависим, поэтому "catalog" проходил проверку и дальше шёл в ИМЯ ТЕГА и в
# Configuration.xml как есть — выгрузка получалась с <catalog>, которую платформа не принимает. # Configuration.xml как есть — выгрузка получалась с <catalog>, которую платформа не принимает.
# Прощаем регистр, но приводим к канону списка. # Прощаем регистр, но приводим к канону списка.
@@ -638,6 +641,7 @@ $script:typeSynonyms["планвидовхарактеристикссылка"]
$script:typeSynonyms["планвидоврасчётассылка"] = "ChartOfCalculationTypesRef" $script:typeSynonyms["планвидоврасчётассылка"] = "ChartOfCalculationTypesRef"
$script:typeSynonyms["планвидоврасчетассылка"] = "ChartOfCalculationTypesRef" $script:typeSynonyms["планвидоврасчетассылка"] = "ChartOfCalculationTypesRef"
$script:typeSynonyms["планобменассылка"] = "ExchangePlanRef" $script:typeSynonyms["планобменассылка"] = "ExchangePlanRef"
$script:typeSynonyms["внешнийисточникданныхтаблицассылка"] = "ExternalDataSourceTableRef"
$script:typeSynonyms["бизнеспроцессссылка"] = "BusinessProcessRef" $script:typeSynonyms["бизнеспроцессссылка"] = "BusinessProcessRef"
$script:typeSynonyms["задачассылка"] = "TaskRef" $script:typeSynonyms["задачассылка"] = "TaskRef"
$script:typeSynonyms["определяемыйтип"] = "DefinedType" $script:typeSynonyms["определяемыйтип"] = "DefinedType"
@@ -856,7 +860,9 @@ function Emit-TypeContent {
# $script:cfgPrefix = $null означает «пишем файл, корень которого cfg НЕ объявляет» # $script:cfgPrefix = $null означает «пишем файл, корень которого cfg НЕ объявляет»
# (Ext/Predefined.xml — его шапка это predef/v8/xr/xs/xsi). Там платформа сама уходит # (Ext/Predefined.xml — его шапка это predef/v8/xr/xs/xsi). Там платформа сама уходит
# на локальную форму: в корпусе `<v8:Type xmlns:d6p1="…current-config">d6p1:CatalogRef.Валюты`. # на локальную форму: в корпусе `<v8:Type xmlns:d6p1="…current-config">d6p1:CatalogRef.Валюты`.
if ($typeStr -match '^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|ExchangePlanRef|BusinessProcessRef|BusinessProcessRoutePointRef|TaskRef)\.(.+)$') { # ExternalDataSourceTableRef — единственный ссылочный тип с ДВУМЯ частями после префикса
# (Источник.Таблица), поэтому `(.+)$` здесь существенно.
if ($typeStr -match '^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|ExchangePlanRef|BusinessProcessRef|BusinessProcessRoutePointRef|TaskRef|ExternalDataSourceTableRef)\.(.+)$') {
if ($script:cfgPrefix) { if ($script:cfgPrefix) {
X "$indent<v8:Type>$($script:cfgPrefix):$typeStr</v8:Type>" X "$indent<v8:Type>$($script:cfgPrefix):$typeStr</v8:Type>"
} else { } else {
@@ -1186,6 +1192,10 @@ function Parse-AttributeShorthand {
# Режим приведения типов измерения РС (формат 2.18). Ключ обязан доехать до эмиттера: # Режим приведения типов измерения РС (формат 2.18). Ключ обязан доехать до эмиттера:
# без него не-дефолтное значение (Deny / DeleteData) молча заменялось на TransformValues. # без него не-дефолтное значение (Deny / DeleteData) молча заменялось на TransformValues.
typeReductionMode = $val.typeReductionMode typeReductionMode = $val.typeReductionMode
# Поле внешнего источника данных (контекст eds-field).
nameInDataSource = if ($val.nameInDataSource) { "$($val.nameInDataSource)" } else { "" }
readOnly = if ($val.readOnly -eq $true) { $true } else { $false }
allowNull = if ($val.allowNull -eq $true) { $true } else { $false }
} }
} }
@@ -2056,7 +2066,7 @@ function Emit-Attribute {
exit 1 exit 1
} }
} }
} elseif ($context -notin @("tabular", "processor-tabular") -and } elseif ($context -notin @("tabular", "processor-tabular", "eds-field") -and
($script:reservedAttrNames.ContainsKey($attrName) -or $script:reservedAttrNames.ContainsValue($attrName))) { ($script:reservedAttrNames.ContainsKey($attrName) -or $script:reservedAttrNames.ContainsValue($attrName))) {
Write-Warning "Attribute '$attrName' conflicts with a standard attribute name. This may cause errors when loading into 1C." Write-Warning "Attribute '$attrName' conflicts with a standard attribute name. This may cause errors when loading into 1C."
} }
@@ -2120,18 +2130,34 @@ function Emit-Attribute {
if ($parsed.fillChecking) { $fillChecking = $parsed.fillChecking } if ($parsed.fillChecking) { $fillChecking = $parsed.fillChecking }
X "$indent`t`t<FillChecking>$fillChecking</FillChecking>" X "$indent`t`t<FillChecking>$fillChecking</FillChecking>"
X "$indent`t`t<ChoiceFoldersAndItems>$(if ($parsed.choiceFoldersAndItems) { "$($parsed.choiceFoldersAndItems)" } else { 'Items' })</ChoiceFoldersAndItems>" # Поле внешнего источника (eds-field) не имеет ChoiceFoldersAndItems и LinkByType, а ChoiceForm
# у него стоит ПОСЛЕ ChoiceHistoryOnInput, а не перед — порядок снят с выгрузки платформы.
if ($context -ne "eds-field") {
X "$indent`t`t<ChoiceFoldersAndItems>$(if ($parsed.choiceFoldersAndItems) { "$($parsed.choiceFoldersAndItems)" } else { 'Items' })</ChoiceFoldersAndItems>"
}
Emit-ChoiceParameterLinks "$indent`t`t" $parsed.choiceParameterLinks Emit-ChoiceParameterLinks "$indent`t`t" $parsed.choiceParameterLinks
Emit-ChoiceParameters "$indent`t`t" $parsed.choiceParameters Emit-ChoiceParameters "$indent`t`t" $parsed.choiceParameters
$qc = if ($parsed.quickChoice) { $parsed.quickChoice } else { "Auto" } $qc = if ($parsed.quickChoice) { $parsed.quickChoice } else { "Auto" }
X "$indent`t`t<QuickChoice>$qc</QuickChoice>" X "$indent`t`t<QuickChoice>$qc</QuickChoice>"
$coi = if ($parsed.createOnInput) { $parsed.createOnInput } else { "Auto" } $coi = if ($parsed.createOnInput) { $parsed.createOnInput } else { "Auto" }
X "$indent`t`t<CreateOnInput>$coi</CreateOnInput>" X "$indent`t`t<CreateOnInput>$coi</CreateOnInput>"
if ($parsed.choiceForm) { X "$indent`t`t<ChoiceForm>$(Esc-XmlText "$($parsed.choiceForm)")</ChoiceForm>" } else { X "$indent`t`t<ChoiceForm/>" } if ($context -ne "eds-field") {
Emit-LinkByType "$indent`t`t" $parsed.linkByType if ($parsed.choiceForm) { X "$indent`t`t<ChoiceForm>$(Esc-XmlText "$($parsed.choiceForm)")</ChoiceForm>" } else { X "$indent`t`t<ChoiceForm/>" }
Emit-LinkByType "$indent`t`t" $parsed.linkByType
}
$chi = if ($parsed.choiceHistoryOnInput) { $parsed.choiceHistoryOnInput } else { "Auto" } $chi = if ($parsed.choiceHistoryOnInput) { $parsed.choiceHistoryOnInput } else { "Auto" }
X "$indent`t`t<ChoiceHistoryOnInput>$chi</ChoiceHistoryOnInput>" X "$indent`t`t<ChoiceHistoryOnInput>$chi</ChoiceHistoryOnInput>"
if ($context -eq "eds-field") {
if ($parsed.choiceForm) { X "$indent`t`t<ChoiceForm>$(Esc-XmlText "$($parsed.choiceForm)")</ChoiceForm>" } else { X "$indent`t`t<ChoiceForm/>" }
$nids = if ($parsed.nameInDataSource) { "$($parsed.nameInDataSource)" } else { $parsed.name }
X "$indent`t`t<NameInDataSource>$(Esc-XmlText $nids)</NameInDataSource>"
$ro = if ($parsed.readOnly -eq $true -or $parsed.flags -contains "readonly") { "true" } else { "false" }
X "$indent`t`t<ReadOnly>$ro</ReadOnly>"
$an = if ($parsed.allowNull -eq $true -or $parsed.flags -contains "nullable") { "true" } else { "false" }
X "$indent`t`t<AllowNull>$an</AllowNull>"
}
# Измерение регистра сведений: Master/MainFilter/DenyIncompleteValues (между ChoiceHistoryOnInput и Indexing). # Измерение регистра сведений: Master/MainFilter/DenyIncompleteValues (между ChoiceHistoryOnInput и Indexing).
if ($elemTag -eq "Dimension" -and $context -eq "register-info") { if ($elemTag -eq "Dimension" -and $context -eq "register-info") {
$master = if ($parsed.master -eq $true -or $parsed.flags -contains "master") { "true" } else { "false" } $master = if ($parsed.master -eq $true -or $parsed.flags -contains "master") { "true" } else { "false" }
@@ -2185,7 +2211,8 @@ function Emit-Attribute {
} }
# Indexing/FullTextSearch/DataHistory — not for non-stored objects (processor, processor-tabular) # Indexing/FullTextSearch/DataHistory — not for non-stored objects (processor, processor-tabular)
if ($context -notin @("processor", "processor-tabular")) { # и не для полей внешнего источника: индексами и полнотекстовым поиском чужой таблицы 1С не владеет.
if ($context -notin @("processor", "processor-tabular", "eds-field")) {
# Признаки учёта ПС (account-flag) не имеют <Indexing>/<FullTextSearch>, но имеют <DataHistory>. # Признаки учёта ПС (account-flag) не имеют <Indexing>/<FullTextSearch>, но имеют <DataHistory>.
if ($context -ne "account-flag") { if ($context -ne "account-flag") {
# Ресурс регистра накопления/расчёта/бухгалтерии НЕ имеет <Indexing> (только <FullTextSearch>); измерение/реквизит — имеют. # Ресурс регистра накопления/расчёта/бухгалтерии НЕ имеет <Indexing> (только <FullTextSearch>); измерение/реквизит — имеют.
@@ -4321,6 +4348,223 @@ function Emit-AddressingAttribute {
Emit-Attribute $indent $parsed "task-addressing" "AddressingAttribute" Emit-Attribute $indent $parsed "task-addressing" "AddressingAttribute"
} }
# --- 13h. Внешние источники данных ---
# Источник пишется в один файл, каждая его таблица — в свой. Функции живут ВНУТРИ файла источника
# полными узлами, наравне со списком имён таблиц: так их выгружает платформа.
# Таблицы: dict имя → массив полей ЛИБО объект со свойствами и ключом fields/columns.
# Нормализуем в [ordered]@{ имя = @{ props; fields } } — форма зеркальна tabularSections.
function Get-EdsTables {
param($val)
$tables = [ordered]@{}
if (-not $val) { return $tables }
function New-EdsTableEntry { param($v)
if ($v -is [array] -or $v.GetType().Name -eq 'Object[]') {
return @{ props = $null; fields = @($v) }
}
$f = if ($null -ne $v.fields) { @($v.fields) } elseif ($null -ne $v.columns) { @($v.columns) } else { @() }
return @{ props = $v; fields = $f }
}
if ($val -is [array] -or $val.GetType().Name -eq 'Object[]') {
foreach ($t in $val) { $tables["$($t.name)"] = New-EdsTableEntry $t }
} else {
$val.PSObject.Properties | ForEach-Object { $tables[$_.Name] = New-EdsTableEntry $_.Value }
}
return $tables
}
# Ссылка на поле таблицы: в DSL короткое имя, в XML — полный путь.
function Get-EdsFieldRef {
param([string]$srcName, [string]$tableName, [string]$fieldName)
if (-not $fieldName) { return "" }
if ($fieldName -like "ExternalDataSource.*") { return $fieldName }
return "ExternalDataSource.$srcName.Table.$tableName.Field.$fieldName"
}
function Emit-EdsFieldRefList {
param([string]$indent, [string]$tag, $names, [string]$srcName, [string]$tableName)
$list = @($names | Where-Object { $_ })
if ($list.Count -eq 0) { X "$indent<$tag/>"; return }
X "$indent<$tag>"
foreach ($n in $list) {
X "$indent`t<xr:Field>$(Esc-XmlText (Get-EdsFieldRef $srcName $tableName "$n"))</xr:Field>"
}
X "$indent</$tag>"
}
function Emit-EdsFieldRefScalar {
param([string]$indent, [string]$tag, $name, [string]$srcName, [string]$tableName)
if (-not $name) { X "$indent<$tag/>"; return }
X "$indent<$tag>$(Esc-XmlText (Get-EdsFieldRef $srcName $tableName "$name"))</$tag>"
}
function Emit-ExternalDataSourceProperties {
param([string]$indent)
$i = $indent
X "$i<Name>$(Esc-XmlText $objName)</Name>"
Emit-MLText $i "Synonym" $synonym
if ($def.comment) { X "$i<Comment>$(Esc-XmlText $def.comment)</Comment>" } else { X "$i<Comment/>" }
$dlcm = Get-EnumProp "DataLockControlMode" "dataLockControlMode" "Automatic"
X "$i<DataLockControlMode>$dlcm</DataLockControlMode>"
}
# Функция внешнего источника. Параметров как объектов метаданных нет: они записаны прямо
# в выражении как &1, &2 (см. reference/external-data-source.md).
function Emit-EdsFunction {
param([string]$indent, [string]$fnName, $val)
$expr = ""
$returns = ""
$returnValue = $true
$fnSynonym = $null
$fnComment = ""
if ($val -is [string]) {
$expr = "$val"
} else {
$expr = if ($val.expression) { "$($val.expression)" } elseif ($val.expressionInDataSource) { "$($val.expressionInDataSource)" } else { "" }
$returns = if ($val.returns) { "$($val.returns)" } elseif ($val.returnType) { "$($val.returnType)" } else { "" }
if ($null -ne $val.returnValue) { $returnValue = ($val.returnValue -eq $true) }
$fnSynonym = $val.synonym
$fnComment = if ($val.comment) { "$($val.comment)" } else { "" }
}
if (-not $expr) {
Write-Error "Функция '$fnName' внешнего источника данных: не задано выражение (ключ expression)."
exit 1
}
$uuid = New-Guid-String
X "$indent<Function uuid=`"$uuid`">"
X "$indent`t<Properties>"
X "$indent`t`t<Name>$(Esc-XmlText $fnName)</Name>"
Emit-MLText "$indent`t`t" "Synonym" $fnSynonym
if ($fnComment) { X "$indent`t`t<Comment>$(Esc-XmlText $fnComment)</Comment>" } else { X "$indent`t`t<Comment/>" }
X "$indent`t`t<ReturnValue>$(if ($returnValue) { 'true' } else { 'false' })</ReturnValue>"
if ($returnValue) {
Emit-ValueType "$indent`t`t" $(if ($returns) { $returns } else { "String" })
} else {
X "$indent`t`t<Type/>"
}
X "$indent`t`t<ExpressionInDataSource>$(Esc-XmlText $expr)</ExpressionInDataSource>"
X "$indent`t</Properties>"
X "$indent</Function>"
}
# Свойства таблицы: 38 узлов в порядке выгрузки платформы.
function Emit-EdsTableProperties {
param([string]$indent, [string]$srcName, [string]$tableName, $t)
$i = $indent
$tblSynonym = if ($t -and $null -ne $t.synonym) { $t.synonym } else { Split-CamelCase $tableName }
X "$i<Name>$(Esc-XmlText $tableName)</Name>"
Emit-MLText $i "Synonym" $tblSynonym
if ($t -and $t.comment) { X "$i<Comment>$(Esc-XmlText "$($t.comment)")</Comment>" } else { X "$i<Comment/>" }
$tableType = if ($t -and $t.tableType) { "$($t.tableType)" } else { "Table" }
X "$i<TableType>$tableType</TableType>"
# Имя в источнике по умолчанию равно имени объекта — так поступает и платформа.
$nids = if ($t -and $t.nameInDataSource) { "$($t.nameInDataSource)" } elseif ($tableType -eq "Expression") { "" } else { $tableName }
if ($nids) { X "$i<NameInDataSource>$(Esc-XmlText $nids)</NameInDataSource>" } else { X "$i<NameInDataSource/>" }
$expr = if ($t -and $t.expressionInDataSource) { "$($t.expressionInDataSource)" } elseif ($t -and $t.expression) { "$($t.expression)" } else { "" }
if ($expr) { X "$i<ExpressionInDataSource>$(Esc-XmlText $expr)</ExpressionInDataSource>" } else { X "$i<ExpressionInDataSource/>" }
$dataType = if ($t -and $t.tableDataType) { "$($t.tableDataType)" } else { "NonobjectData" }
X "$i<TableDataType>$dataType</TableDataType>"
Emit-EdsFieldRefList $i "KeyFields" $(if ($t) { $t.keyFields } else { $null }) $srcName $tableName
Emit-EdsFieldRefScalar $i "PresentationField" $(if ($t) { $t.presentationField } else { $null }) $srcName $tableName
Emit-EdsFieldRefScalar $i "ParentField" $(if ($t) { $t.parentField } else { $null }) $srcName $tableName
# Признака незаполненного родителя отдельным узлом нет: NULL против «Заданного значения»
# различаются формой самого значения (xsi:nil против типизированного).
# ВАЖНО: платформа при загрузке XML сбрасывает заданное значение в пустую строку — проверено
# на её собственной выгрузке. Задать его можно только интерактивно, поэтому дефолт у таблицы
# с полем родителя — пустая строка (как после загрузки), а без него — nil.
$upv = if ($t) { $t.unfilledParentValue } else { $null }
$hasParent = ($t -and $t.parentField)
if ($null -ne $upv) { Emit-MinMaxValue $i "UnfilledParentValue" $upv }
elseif ($hasParent) { X "$i<UnfilledParentValue xsi:type=`"xs:string`"/>" }
else { X "$i<UnfilledParentValue xsi:nil=`"true`"/>" }
Emit-Characteristics $i $(if ($t) { $t.characteristics } else { $null })
X "$i<UseStandardCommands>$(if ($t -and $t.useStandardCommands -eq $false) { 'false' } else { 'true' })</UseStandardCommands>"
X "$i<QuickChoice>$(if ($t -and $t.quickChoice -eq $true) { 'true' } else { 'false' })</QuickChoice>"
# Ввод по строке: ключа нет → выводим из поля представления (так делает платформа при загрузке).
# Явный список, в том числе пустой, уважаем как есть — отсюда presence-aware проверка.
$ibsGiven = ($t -and $t.PSObject -and $t.PSObject.Properties -and ($t.PSObject.Properties.Name -contains 'inputByString'))
$ibs = if ($ibsGiven) { $t.inputByString } elseif ($t -and $t.presentationField) { @($t.presentationField) } else { $null }
Emit-EdsFieldRefList $i "InputByString" $ibs $srcName $tableName
X "$i<CreateOnInput>$(if ($t -and $t.createOnInput) { "$($t.createOnInput)" } else { 'Auto' })</CreateOnInput>"
X "$i<SearchStringModeOnInputByString>$(if ($t -and $t.searchStringModeOnInputByString) { "$($t.searchStringModeOnInputByString)" } else { 'Begin' })</SearchStringModeOnInputByString>"
X "$i<ChoiceDataGetModeOnInputByString>$(if ($t -and $t.choiceDataGetModeOnInputByString) { "$($t.choiceDataGetModeOnInputByString)" } else { 'Directly' })</ChoiceDataGetModeOnInputByString>"
X "$i<ChoiceHistoryOnInput>$(if ($t -and $t.choiceHistoryOnInput) { "$($t.choiceHistoryOnInput)" } else { 'Auto' })</ChoiceHistoryOnInput>"
foreach ($formTag in @("DefaultObjectForm","DefaultRecordForm","DefaultListForm","DefaultChoiceForm")) {
$key = $formTag.Substring(0,1).ToLower() + $formTag.Substring(1)
Emit-FormRef $i $formTag $(if ($t) { $t.$key } else { $null })
}
foreach ($presTag in @("ObjectPresentation","ExtendedObjectPresentation","RecordPresentation",
"ExtendedRecordPresentation","ListPresentation","ExtendedListPresentation","Explanation")) {
$key = $presTag.Substring(0,1).ToLower() + $presTag.Substring(1)
Emit-MLText $i $presTag $(if ($t) { $t.$key } else { $null })
}
X "$i<IncludeHelpInContents>$(if ($t -and $t.includeHelpInContents -eq $true) { 'true' } else { 'false' })</IncludeHelpInContents>"
X "$i<ReadOnly>$(if ($t -and $t.readOnly -eq $true) { 'true' } else { 'false' })</ReadOnly>"
X "$i<TransactionsIsolationLevel>$(if ($t -and $t.transactionsIsolationLevel) { "$($t.transactionsIsolationLevel)" } else { 'Auto' })</TransactionsIsolationLevel>"
Emit-EdsFieldRefScalar $i "DataVersionField" $(if ($t) { $t.dataVersionField } else { $null }) $srcName $tableName
X "$i<EditType>$(if ($t -and $t.editType) { "$($t.editType)" } else { 'InDialog' })</EditType>"
Emit-MDRefList $i "BasedOn" $(if ($t) { $t.basedOn } else { $null })
Emit-EdsFieldRefList $i "DataLockFields" $(if ($t) { $t.dataLockFields } else { $null }) $srcName $tableName
X "$i<DataLockControlMode>$(if ($t -and $t.dataLockControlMode) { "$($t.dataLockControlMode)" } else { 'Automatic' })</DataLockControlMode>"
}
# Отдельный XML-документ таблицы. Возвращает строку: X пишет в общий StringBuilder,
# поэтому «перехват» — запомнить длину, отдать эмиттерам, вырезать добавленное
# (тот же приём, что у составного типа).
function Build-EdsTableXml {
param([string]$srcName, [string]$tableName, $entry)
$before = $script:xml.Length
$tableUuid = New-Guid-String
X '<?xml version="1.0" encoding="UTF-8"?>'
X "<MetaDataObject $($script:xmlnsDecl) version=`"$($script:formatVersion)`">"
X "`t<Table uuid=`"$tableUuid`">"
# InternalInfo у таблицы эмитится здесь, а не через $script:generatedTypes: имя элемента
# трёхчастное (Префикс.Источник.Таблица), общая карта такой формы не знает.
X "`t`t<InternalInfo>"
foreach ($pair in @(
@("ExternalDataSourceTableManager", "Manager"),
@("ExternalDataSourceTableObject", "Object"),
@("ExternalDataSourceTableRef", "Ref"),
@("ExternalDataSourceTableList", "List"),
@("ExternalDataSourceTableRecord", "Record"),
@("ExternalDataSourceTableRecordSet", "RecordSet"),
@("ExternalDataSourceTableRecordKey", "RecordKey"),
@("ExternalDataSourceTableRecordManager", "RecordManager"))) {
X "`t`t`t<xr:GeneratedType name=`"$($pair[0]).$srcName.$tableName`" category=`"$($pair[1])`">"
X "`t`t`t`t<xr:TypeId>$(New-Guid-String)</xr:TypeId>"
X "`t`t`t`t<xr:ValueId>$(New-Guid-String)</xr:ValueId>"
X "`t`t`t</xr:GeneratedType>"
}
X "`t`t</InternalInfo>"
X "`t`t<Properties>"
Emit-EdsTableProperties "`t`t`t" $srcName $tableName $entry.props
X "`t`t</Properties>"
$fields = @($entry.fields)
if ($fields.Count -gt 0) {
X "`t`t<ChildObjects>"
foreach ($f in $fields) {
$parsed = Parse-AttributeShorthand $f
Emit-Attribute "`t`t`t" $parsed "eds-field" "Field"
}
X "`t`t</ChildObjects>"
} else {
X "`t`t<ChildObjects/>"
}
X "`t</Table>"
X "</MetaDataObject>"
$chunk = $script:xml.ToString($before, $script:xml.Length - $before)
[void]$script:xml.Remove($before, $script:xml.Length - $before)
return $chunk
}
# --- 14. Namespaces --- # --- 14. Namespaces ---
$script:xmlnsDecl = 'xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' $script:xmlnsDecl = 'xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
@@ -4464,6 +4708,7 @@ switch ($objType) {
"Task" { Emit-TaskProperties "`t`t`t" } "Task" { Emit-TaskProperties "`t`t`t" }
"HTTPService" { Emit-HTTPServiceProperties "`t`t`t" } "HTTPService" { Emit-HTTPServiceProperties "`t`t`t" }
"WebService" { Emit-WebServiceProperties "`t`t`t" } "WebService" { Emit-WebServiceProperties "`t`t`t" }
"ExternalDataSource" { Emit-ExternalDataSourceProperties "`t`t`t" }
} }
X "`t`t</Properties>" X "`t`t</Properties>"
@@ -4761,6 +5006,29 @@ if ($objType -eq "WebService") {
} }
} }
# --- ExternalDataSource: Tables (именами) + Functions (полными узлами) ---
$script:edsTables = [ordered]@{}
if ($objType -eq "ExternalDataSource") {
$script:edsTables = Get-EdsTables $def.tables
$functions = [ordered]@{}
if ($def.functions) {
$def.functions.PSObject.Properties | ForEach-Object { $functions[$_.Name] = $_.Value }
}
if ($script:edsTables.Count -gt 0 -or $functions.Count -gt 0) {
$hasChildren = $true
X "`t`t<ChildObjects>"
foreach ($tblName in $script:edsTables.Keys) {
X "`t`t`t<Table>$(Esc-XmlText $tblName)</Table>"
}
foreach ($fnName in $functions.Keys) {
Emit-EdsFunction "`t`t`t" $fnName $functions[$fnName]
}
X "`t`t</ChildObjects>"
} else {
X "`t`t<ChildObjects/>"
}
}
# --- CommonModule: no ChildObjects --- # --- CommonModule: no ChildObjects ---
X "`t</$objType>" X "`t</$objType>"
@@ -4809,6 +5077,7 @@ $script:typePluralMap = @{
"WSReference" = "WSReferences" "WSReference" = "WSReferences"
"CommonPicture" = "CommonPictures" "CommonPicture" = "CommonPictures"
"CommonTemplate" = "CommonTemplates" "CommonTemplate" = "CommonTemplates"
"ExternalDataSource" = "ExternalDataSources"
} }
$typePlural = $script:typePluralMap[$objType] $typePlural = $script:typePluralMap[$objType]
@@ -5043,6 +5312,20 @@ function Write-XmlFileKeepEol([string]$path, [string]$text, $encoding) {
Write-XmlFileKeepEol $mainXmlPath $metadataXml $enc Write-XmlFileKeepEol $mainXmlPath $metadataXml $enc
# Таблицы внешнего источника — отдельными файлами в <Источник>/Tables/.
# Единственный вид, у которого объект складывается более чем из одного XML.
$edsTablesCreated = @()
if ($objType -eq "ExternalDataSource" -and $script:edsTables.Count -gt 0) {
$tablesDir = Join-Path $objSubDir "Tables"
if (-not (Test-Path $tablesDir)) { New-Item -ItemType Directory -Path $tablesDir -Force | Out-Null }
foreach ($tblName in $script:edsTables.Keys) {
$tableXml = Build-EdsTableXml $objName $tblName $script:edsTables[$tblName]
$tablePath = Join-Path $tablesDir "$tblName.xml"
Write-XmlFileKeepEol $tablePath $tableXml $enc
$edsTablesCreated += $tablePath
}
}
# Module files # Module files
$modulesCreated = @() $modulesCreated = @()
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# meta-compile v1.104 — Compile 1C metadata object from JSON # meta-compile v1.105 — Compile 1C metadata object from JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
@@ -497,6 +497,7 @@ object_type_synonyms = {
'ВебСервис': 'WebService', 'ВебСервис': 'WebService',
'ОпределяемыйТип': 'DefinedType', 'ОпределяемыйТип': 'DefinedType',
'ФункциональнаяОпция': 'FunctionalOption', 'ФункциональнаяОпция': 'FunctionalOption',
'ВнешнийИсточникДанных': 'ExternalDataSource',
} }
# Enum property value synonyms — model often gets these slightly wrong # Enum property value synonyms — model often gets these slightly wrong
@@ -542,7 +543,9 @@ valid_enum_values = {
'WriteMode': ['Independent', 'RecorderSubordinate'], 'WriteMode': ['Independent', 'RecorderSubordinate'],
'InformationRegisterPeriodicity': ['Nonperiodical', 'Second', 'Day', 'Month', 'Quarter', 'Year', 'RecorderPosition'], 'InformationRegisterPeriodicity': ['Nonperiodical', 'Second', 'Day', 'Month', 'Quarter', 'Year', 'RecorderPosition'],
'DependenceOnCalculationTypes': ['DontUse', 'OnActionPeriod'], 'DependenceOnCalculationTypes': ['DontUse', 'OnActionPeriod'],
'DataLockControlMode': ['Automatic', 'Managed'], # AutomaticAndManaged — только у внешнего источника данных и его таблиц: там режим может
# решаться на уровне таблицы, у прочих объектов такого значения нет.
'DataLockControlMode': ['Automatic', 'Managed', 'AutomaticAndManaged'],
'FullTextSearch': ['Use', 'DontUse'], 'FullTextSearch': ['Use', 'DontUse'],
'DataHistory': ['Use', 'DontUse'], 'DataHistory': ['Use', 'DontUse'],
'DefaultPresentation': ['AsDescription', 'AsCode'], 'DefaultPresentation': ['AsDescription', 'AsCode'],
@@ -692,7 +695,7 @@ valid_types = [
'Sequence', 'FilterCriterion', 'DocumentNumerator', 'SettingsStorage', 'Sequence', 'FilterCriterion', 'DocumentNumerator', 'SettingsStorage',
'CommonForm', 'CommonForm',
'SessionParameter', 'CommonCommand', 'CommandGroup', 'CommonAttribute', 'FunctionalOptionsParameter', 'WSReference', 'SessionParameter', 'CommonCommand', 'CommandGroup', 'CommonAttribute', 'FunctionalOptionsParameter', 'WSReference',
'CommonPicture', 'CommonTemplate', 'CommonPicture', 'CommonTemplate', 'ExternalDataSource',
] ]
# Регистр имени вида — как в PS (-contains регистронезависим): приводим к канону списка # Регистр имени вида — как в PS (-contains регистронезависим): приводим к канону списка
obj_type = next((t for t in valid_types if t.lower() == obj_type.lower()), obj_type) obj_type = next((t for t in valid_types if t.lower() == obj_type.lower()), obj_type)
@@ -745,6 +748,7 @@ type_synonyms = {
'планвидоврасчётассылка': 'ChartOfCalculationTypesRef', 'планвидоврасчётассылка': 'ChartOfCalculationTypesRef',
'планвидоврасчетассылка': 'ChartOfCalculationTypesRef', 'планвидоврасчетассылка': 'ChartOfCalculationTypesRef',
'планобменассылка': 'ExchangePlanRef', 'планобменассылка': 'ExchangePlanRef',
'внешнийисточникданныхтаблицассылка': 'ExternalDataSourceTableRef',
'бизнеспроцессссылка': 'BusinessProcessRef', 'бизнеспроцессссылка': 'BusinessProcessRef',
'задачассылка': 'TaskRef', 'задачассылка': 'TaskRef',
'определяемыйтип': 'DefinedType', 'определяемыйтип': 'DefinedType',
@@ -969,7 +973,9 @@ def emit_type_content(indent, type_str):
# cfg_prefix = None означает «пишем файл, корень которого cfg НЕ объявляет» # cfg_prefix = None означает «пишем файл, корень которого cfg НЕ объявляет»
# (Ext/Predefined.xml — его шапка это predef/v8/xr/xs/xsi). Там платформа сама уходит # (Ext/Predefined.xml — его шапка это predef/v8/xr/xs/xsi). Там платформа сама уходит
# на локальную форму: в корпусе `<v8:Type xmlns:d6p1="…current-config">d6p1:CatalogRef.Валюты`. # на локальную форму: в корпусе `<v8:Type xmlns:d6p1="…current-config">d6p1:CatalogRef.Валюты`.
m = re.match(r'^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|ExchangePlanRef|BusinessProcessRef|BusinessProcessRoutePointRef|TaskRef)\.(.+)$', type_str) # ExternalDataSourceTableRef — единственный ссылочный тип с ДВУМЯ частями после префикса
# (Источник.Таблица), поэтому `(.+)$` здесь существенно.
m = re.match(r'^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|ExchangePlanRef|BusinessProcessRef|BusinessProcessRoutePointRef|TaskRef|ExternalDataSourceTableRef)\.(.+)$', type_str)
if m: if m:
if cfg_prefix: if cfg_prefix:
X(f'{indent}<v8:Type>{cfg_prefix}:{type_str}</v8:Type>') X(f'{indent}<v8:Type>{cfg_prefix}:{type_str}</v8:Type>')
@@ -1293,6 +1299,10 @@ def parse_attribute_shorthand(val):
# Режим приведения типов измерения РС (формат 2.18). Ключ обязан доехать до эмиттера: # Режим приведения типов измерения РС (формат 2.18). Ключ обязан доехать до эмиттера:
# без него не-дефолтное значение (Deny / DeleteData) молча заменялось на TransformValues. # без него не-дефолтное значение (Deny / DeleteData) молча заменялось на TransformValues.
'typeReductionMode': val.get('typeReductionMode'), 'typeReductionMode': val.get('typeReductionMode'),
# Поле внешнего источника данных (контекст eds-field).
'nameInDataSource': str(val['nameInDataSource']) if val.get('nameInDataSource') else '',
'readOnly': val.get('readOnly') is True,
'allowNull': val.get('allowNull') is True,
} }
def parse_enum_value_shorthand(val): def parse_enum_value_shorthand(val):
@@ -2285,15 +2295,28 @@ def emit_attribute(indent, parsed, context, elem_tag='Attribute'):
if parsed.get('fillChecking'): if parsed.get('fillChecking'):
fill_checking = parsed['fillChecking'] fill_checking = parsed['fillChecking']
X(f'{indent}\t\t<FillChecking>{fill_checking}</FillChecking>') X(f'{indent}\t\t<FillChecking>{fill_checking}</FillChecking>')
X(f'{indent}\t\t<ChoiceFoldersAndItems>{parsed.get("choiceFoldersAndItems") or "Items"}</ChoiceFoldersAndItems>') # Поле внешнего источника (eds-field) не имеет ChoiceFoldersAndItems и LinkByType, а ChoiceForm
# у него стоит ПОСЛЕ ChoiceHistoryOnInput, а не перед — порядок снят с выгрузки платформы.
if context != 'eds-field':
X(f'{indent}\t\t<ChoiceFoldersAndItems>{parsed.get("choiceFoldersAndItems") or "Items"}</ChoiceFoldersAndItems>')
emit_choice_parameter_links(f'{indent}\t\t', parsed.get('choiceParameterLinks')) emit_choice_parameter_links(f'{indent}\t\t', parsed.get('choiceParameterLinks'))
emit_choice_parameters(f'{indent}\t\t', parsed.get('choiceParameters')) emit_choice_parameters(f'{indent}\t\t', parsed.get('choiceParameters'))
X(f'{indent}\t\t<QuickChoice>{parsed.get("quickChoice") or "Auto"}</QuickChoice>') X(f'{indent}\t\t<QuickChoice>{parsed.get("quickChoice") or "Auto"}</QuickChoice>')
X(f'{indent}\t\t<CreateOnInput>{parsed.get("createOnInput") or "Auto"}</CreateOnInput>') X(f'{indent}\t\t<CreateOnInput>{parsed.get("createOnInput") or "Auto"}</CreateOnInput>')
X(f'{indent}\t\t<ChoiceForm>{esc_xml_text(str(parsed["choiceForm"]))}</ChoiceForm>' if parsed.get('choiceForm') else f'{indent}\t\t<ChoiceForm/>') if context != 'eds-field':
emit_link_by_type(f'{indent}\t\t', parsed.get('linkByType')) X(f'{indent}\t\t<ChoiceForm>{esc_xml_text(str(parsed["choiceForm"]))}</ChoiceForm>' if parsed.get('choiceForm') else f'{indent}\t\t<ChoiceForm/>')
emit_link_by_type(f'{indent}\t\t', parsed.get('linkByType'))
chi = parsed.get('choiceHistoryOnInput') or 'Auto' chi = parsed.get('choiceHistoryOnInput') or 'Auto'
X(f'{indent}\t\t<ChoiceHistoryOnInput>{chi}</ChoiceHistoryOnInput>') X(f'{indent}\t\t<ChoiceHistoryOnInput>{chi}</ChoiceHistoryOnInput>')
if context == 'eds-field':
X(f'{indent}\t\t<ChoiceForm>{esc_xml_text(str(parsed["choiceForm"]))}</ChoiceForm>' if parsed.get('choiceForm') else f'{indent}\t\t<ChoiceForm/>')
nids = parsed.get('nameInDataSource') or parsed['name']
X(f'{indent}\t\t<NameInDataSource>{esc_xml_text(str(nids))}</NameInDataSource>')
ro = 'true' if (parsed.get('readOnly') is True or 'readonly' in parsed.get('flags', [])) else 'false'
X(f'{indent}\t\t<ReadOnly>{ro}</ReadOnly>')
an = 'true' if (parsed.get('allowNull') is True or 'nullable' in parsed.get('flags', [])) else 'false'
X(f'{indent}\t\t<AllowNull>{an}</AllowNull>')
# Измерение регистра сведений: Master/MainFilter/DenyIncompleteValues (между ChoiceHistoryOnInput и Indexing). # Измерение регистра сведений: Master/MainFilter/DenyIncompleteValues (между ChoiceHistoryOnInput и Indexing).
if elem_tag == 'Dimension' and context == 'register-info': if elem_tag == 'Dimension' and context == 'register-info':
master = 'true' if (parsed.get('master') is True or 'master' in parsed.get('flags', [])) else 'false' master = 'true' if (parsed.get('master') is True or 'master' in parsed.get('flags', [])) else 'false'
@@ -2341,7 +2364,8 @@ def emit_attribute(indent, parsed, context, elem_tag='Attribute'):
use_value = parsed.get("use") or "ForItem" use_value = parsed.get("use") or "ForItem"
if context == 'catalog': if context == 'catalog':
X(f'{indent}\t\t<Use>{use_value}</Use>') X(f'{indent}\t\t<Use>{use_value}</Use>')
if context not in ('processor', 'processor-tabular'): # и не для полей внешнего источника: индексами и полнотекстовым поиском чужой таблицы 1С не владеет.
if context not in ('processor', 'processor-tabular', 'eds-field'):
# Признаки учёта ПС (account-flag) не имеют <Indexing>/<FullTextSearch>, но имеют <DataHistory>. # Признаки учёта ПС (account-flag) не имеют <Indexing>/<FullTextSearch>, но имеют <DataHistory>.
if context != 'account-flag': if context != 'account-flag':
# Ресурс регистра накопления НЕ имеет <Indexing> (только <FullTextSearch>); измерение/реквизит — имеют. # Ресурс регистра накопления НЕ имеет <Indexing> (только <FullTextSearch>); измерение/реквизит — имеют.
@@ -4313,6 +4337,237 @@ def emit_addressing_attribute(indent, addr_def):
parsed = parse_attribute_shorthand(addr_def) parsed = parse_attribute_shorthand(addr_def)
emit_attribute(indent, parsed, 'task-addressing', 'AddressingAttribute') emit_attribute(indent, parsed, 'task-addressing', 'AddressingAttribute')
# ---------------------------------------------------------------------------
# 13h. Внешние источники данных
# ---------------------------------------------------------------------------
# Источник пишется в один файл, каждая его таблица — в свой. Функции живут ВНУТРИ файла источника
# полными узлами, наравне со списком имён таблиц: так их выгружает платформа.
def get_eds_tables(val):
"""Таблицы: dict имя → массив полей ЛИБО объект со свойствами и ключом fields/columns."""
tables = {}
if not val:
return tables
def entry(v):
if isinstance(v, list):
return {'props': None, 'fields': list(v)}
f = v.get('fields') if v.get('fields') is not None else v.get('columns')
return {'props': v, 'fields': list(f) if f else []}
if isinstance(val, list):
for t in val:
tables[str(t.get('name'))] = entry(t)
else:
for k, v in val.items():
tables[k] = entry(v)
return tables
def get_eds_field_ref(src_name, table_name, field_name):
"""Ссылка на поле таблицы: в DSL короткое имя, в XML — полный путь."""
if not field_name:
return ''
if str(field_name).startswith('ExternalDataSource.'):
return str(field_name)
return f'ExternalDataSource.{src_name}.Table.{table_name}.Field.{field_name}'
def emit_eds_field_ref_list(indent, tag, names, src_name, table_name):
items = [n for n in (names or []) if n]
if not items:
X(f'{indent}<{tag}/>')
return
X(f'{indent}<{tag}>')
for n in items:
X(f'{indent}\t<xr:Field>{esc_xml_text(get_eds_field_ref(src_name, table_name, n))}</xr:Field>')
X(f'{indent}</{tag}>')
def emit_eds_field_ref_scalar(indent, tag, name, src_name, table_name):
if not name:
X(f'{indent}<{tag}/>')
return
X(f'{indent}<{tag}>{esc_xml_text(get_eds_field_ref(src_name, table_name, name))}</{tag}>')
def emit_external_data_source_properties(indent):
i = indent
X(f'{i}<Name>{esc_xml_text(obj_name)}</Name>')
emit_mltext(i, 'Synonym', synonym)
if defn.get('comment'):
X(f'{i}<Comment>{esc_xml_text(str(defn["comment"]))}</Comment>')
else:
X(f'{i}<Comment/>')
dlcm = get_enum_prop('DataLockControlMode', 'dataLockControlMode', 'Automatic')
X(f'{i}<DataLockControlMode>{dlcm}</DataLockControlMode>')
def emit_eds_function(indent, fn_name, val):
"""Функция внешнего источника. Параметров как объектов метаданных нет: они записаны прямо
в выражении как &1, &2 (см. reference/external-data-source.md)."""
fn_synonym = None
fn_comment = ''
returns = ''
return_value = True
if isinstance(val, str):
expr = val
else:
expr = str(val.get('expression') or val.get('expressionInDataSource') or '')
returns = str(val.get('returns') or val.get('returnType') or '')
if val.get('returnValue') is not None:
return_value = val.get('returnValue') is True
fn_synonym = val.get('synonym')
fn_comment = str(val['comment']) if val.get('comment') else ''
if not expr:
print(f"ERROR: Функция '{fn_name}' внешнего источника данных: не задано выражение (ключ expression).",
file=sys.stderr)
sys.exit(1)
X(f'{indent}<Function uuid="{new_uuid()}">')
X(f'{indent}\t<Properties>')
X(f'{indent}\t\t<Name>{esc_xml_text(fn_name)}</Name>')
emit_mltext(f'{indent}\t\t', 'Synonym', fn_synonym)
if fn_comment:
X(f'{indent}\t\t<Comment>{esc_xml_text(fn_comment)}</Comment>')
else:
X(f'{indent}\t\t<Comment/>')
X(f'{indent}\t\t<ReturnValue>{"true" if return_value else "false"}</ReturnValue>')
if return_value:
emit_value_type(f'{indent}\t\t', returns or 'String')
else:
X(f'{indent}\t\t<Type/>')
X(f'{indent}\t\t<ExpressionInDataSource>{esc_xml_text(expr)}</ExpressionInDataSource>')
X(f'{indent}\t</Properties>')
X(f'{indent}</Function>')
def emit_eds_table_properties(indent, src_name, table_name, t):
"""Свойства таблицы: 38 узлов в порядке выгрузки платформы."""
i = indent
t = t or {}
tbl_synonym = t['synonym'] if t.get('synonym') is not None else split_camel_case(table_name)
X(f'{i}<Name>{esc_xml_text(table_name)}</Name>')
emit_mltext(i, 'Synonym', tbl_synonym)
if t.get('comment'):
X(f'{i}<Comment>{esc_xml_text(str(t["comment"]))}</Comment>')
else:
X(f'{i}<Comment/>')
table_type = str(t.get('tableType') or 'Table')
X(f'{i}<TableType>{table_type}</TableType>')
# Имя в источнике по умолчанию равно имени объекта — так поступает и платформа.
if t.get('nameInDataSource'):
nids = str(t['nameInDataSource'])
elif table_type == 'Expression':
nids = ''
else:
nids = table_name
X(f'{i}<NameInDataSource>{esc_xml_text(nids)}</NameInDataSource>' if nids else f'{i}<NameInDataSource/>')
expr = str(t.get('expressionInDataSource') or t.get('expression') or '')
X(f'{i}<ExpressionInDataSource>{esc_xml_text(expr)}</ExpressionInDataSource>' if expr else f'{i}<ExpressionInDataSource/>')
X(f'{i}<TableDataType>{t.get("tableDataType") or "NonobjectData"}</TableDataType>')
emit_eds_field_ref_list(i, 'KeyFields', t.get('keyFields'), src_name, table_name)
emit_eds_field_ref_scalar(i, 'PresentationField', t.get('presentationField'), src_name, table_name)
emit_eds_field_ref_scalar(i, 'ParentField', t.get('parentField'), src_name, table_name)
# Признака незаполненного родителя отдельным узлом нет: NULL против «Заданного значения»
# различаются формой самого значения (xsi:nil против типизированного).
# ВАЖНО: платформа при загрузке XML сбрасывает заданное значение в пустую строку — проверено
# на её собственной выгрузке. Задать его можно только интерактивно, поэтому дефолт у таблицы
# с полем родителя — пустая строка (как после загрузки), а без него — nil.
upv = t.get('unfilledParentValue')
if upv is not None:
emit_min_max_value(i, 'UnfilledParentValue', upv)
elif t.get('parentField'):
X(f'{i}<UnfilledParentValue xsi:type="xs:string"/>')
else:
X(f'{i}<UnfilledParentValue xsi:nil="true"/>')
emit_characteristics(i, t.get('characteristics'))
X(f'{i}<UseStandardCommands>{"false" if t.get("useStandardCommands") is False else "true"}</UseStandardCommands>')
X(f'{i}<QuickChoice>{"true" if t.get("quickChoice") is True else "false"}</QuickChoice>')
# Ввод по строке: ключа нет → выводим из поля представления (так делает платформа при загрузке).
# Явный список, в том числе пустой, уважаем как есть — отсюда presence-aware проверка.
if 'inputByString' in t:
ibs = t.get('inputByString')
elif t.get('presentationField'):
ibs = [t['presentationField']]
else:
ibs = None
emit_eds_field_ref_list(i, 'InputByString', ibs, src_name, table_name)
X(f'{i}<CreateOnInput>{t.get("createOnInput") or "Auto"}</CreateOnInput>')
X(f'{i}<SearchStringModeOnInputByString>{t.get("searchStringModeOnInputByString") or "Begin"}</SearchStringModeOnInputByString>')
X(f'{i}<ChoiceDataGetModeOnInputByString>{t.get("choiceDataGetModeOnInputByString") or "Directly"}</ChoiceDataGetModeOnInputByString>')
X(f'{i}<ChoiceHistoryOnInput>{t.get("choiceHistoryOnInput") or "Auto"}</ChoiceHistoryOnInput>')
for form_tag in ('DefaultObjectForm', 'DefaultRecordForm', 'DefaultListForm', 'DefaultChoiceForm'):
key = form_tag[0].lower() + form_tag[1:]
emit_form_ref(i, form_tag, t.get(key))
for pres_tag in ('ObjectPresentation', 'ExtendedObjectPresentation', 'RecordPresentation',
'ExtendedRecordPresentation', 'ListPresentation', 'ExtendedListPresentation', 'Explanation'):
key = pres_tag[0].lower() + pres_tag[1:]
emit_mltext(i, pres_tag, t.get(key))
X(f'{i}<IncludeHelpInContents>{"true" if t.get("includeHelpInContents") is True else "false"}</IncludeHelpInContents>')
X(f'{i}<ReadOnly>{"true" if t.get("readOnly") is True else "false"}</ReadOnly>')
X(f'{i}<TransactionsIsolationLevel>{t.get("transactionsIsolationLevel") or "Auto"}</TransactionsIsolationLevel>')
emit_eds_field_ref_scalar(i, 'DataVersionField', t.get('dataVersionField'), src_name, table_name)
X(f'{i}<EditType>{t.get("editType") or "InDialog"}</EditType>')
emit_md_ref_list(i, 'BasedOn', t.get('basedOn'))
emit_eds_field_ref_list(i, 'DataLockFields', t.get('dataLockFields'), src_name, table_name)
X(f'{i}<DataLockControlMode>{t.get("dataLockControlMode") or "Automatic"}</DataLockControlMode>')
EDS_TABLE_GENERATED_TYPES = (
('ExternalDataSourceTableManager', 'Manager'),
('ExternalDataSourceTableObject', 'Object'),
('ExternalDataSourceTableRef', 'Ref'),
('ExternalDataSourceTableList', 'List'),
('ExternalDataSourceTableRecord', 'Record'),
('ExternalDataSourceTableRecordSet', 'RecordSet'),
('ExternalDataSourceTableRecordKey', 'RecordKey'),
('ExternalDataSourceTableRecordManager', 'RecordManager'),
)
def build_eds_table_xml(src_name, table_name, entry):
"""Отдельный XML-документ таблицы. Возвращает строку: X пишет в общий список строк,
поэтому «перехват» запомнить длину, отдать эмиттерам, срезать добавленное
(в ps1-порте тот же приём выражен через StringBuilder различие рантаймов, не логики)."""
before = len(lines)
X('<?xml version="1.0" encoding="UTF-8"?>')
X(f'<MetaDataObject {xmlns_decl} version="{format_version}">')
X(f'\t<Table uuid="{new_uuid()}">')
# InternalInfo у таблицы эмитится здесь, а не через generated_types: имя элемента
# трёхчастное (Префикс.Источник.Таблица), общая карта такой формы не знает.
X('\t\t<InternalInfo>')
for prefix, category in EDS_TABLE_GENERATED_TYPES:
X(f'\t\t\t<xr:GeneratedType name="{prefix}.{src_name}.{table_name}" category="{category}">')
X(f'\t\t\t\t<xr:TypeId>{new_uuid()}</xr:TypeId>')
X(f'\t\t\t\t<xr:ValueId>{new_uuid()}</xr:ValueId>')
X('\t\t\t</xr:GeneratedType>')
X('\t\t</InternalInfo>')
X('\t\t<Properties>')
emit_eds_table_properties('\t\t\t', src_name, table_name, entry['props'])
X('\t\t</Properties>')
fields = entry['fields']
if fields:
X('\t\t<ChildObjects>')
for f in fields:
emit_attribute('\t\t\t', parse_attribute_shorthand(f), 'eds-field', 'Field')
X('\t\t</ChildObjects>')
else:
X('\t\t<ChildObjects/>')
X('\t</Table>')
X('</MetaDataObject>')
chunk = '\r\n'.join(lines[before:])
del lines[before:]
return chunk
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# 14. Namespaces # 14. Namespaces
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@@ -4453,6 +4708,7 @@ property_emitters = {
'Task': emit_task_properties, 'Task': emit_task_properties,
'HTTPService': emit_http_service_properties, 'HTTPService': emit_http_service_properties,
'WebService': emit_web_service_properties, 'WebService': emit_web_service_properties,
'ExternalDataSource': emit_external_data_source_properties,
} }
property_emitters[obj_type]('\t\t\t') property_emitters[obj_type]('\t\t\t')
@@ -4726,6 +4982,25 @@ if obj_type == 'WebService':
else: else:
X('\t\t<ChildObjects/>') X('\t\t<ChildObjects/>')
# --- ExternalDataSource: Tables (именами) + Functions (полными узлами) ---
eds_tables = {}
if obj_type == 'ExternalDataSource':
eds_tables = get_eds_tables(defn.get('tables'))
functions = {}
if defn.get('functions'):
for k, v in defn['functions'].items():
functions[k] = v
if eds_tables or functions:
has_children = True
X('\t\t<ChildObjects>')
for tbl_name in eds_tables:
X(f'\t\t\t<Table>{esc_xml_text(tbl_name)}</Table>')
for fn_name, fn_val in functions.items():
emit_eds_function('\t\t\t', fn_name, fn_val)
X('\t\t</ChildObjects>')
else:
X('\t\t<ChildObjects/>')
# --- CommonModule: no ChildObjects --- # --- CommonModule: no ChildObjects ---
X(f'\t</{obj_type}>') X(f'\t</{obj_type}>')
@@ -4775,6 +5050,7 @@ type_plural_map = {
'WSReference': 'WSReferences', 'WSReference': 'WSReferences',
'CommonPicture': 'CommonPictures', 'CommonPicture': 'CommonPictures',
'CommonTemplate': 'CommonTemplates', 'CommonTemplate': 'CommonTemplates',
'ExternalDataSource': 'ExternalDataSources',
} }
type_plural = type_plural_map[obj_type] type_plural = type_plural_map[obj_type]
@@ -4795,6 +5071,18 @@ if obj_type not in types_no_sub_dir:
write_xml_file_keep_eol(main_xml_path, metadata_xml) write_xml_file_keep_eol(main_xml_path, metadata_xml)
# Таблицы внешнего источника — отдельными файлами в <Источник>/Tables/.
# Единственный вид, у которого объект складывается более чем из одного XML.
eds_tables_created = []
if obj_type == 'ExternalDataSource' and eds_tables:
tables_dir = os.path.join(obj_sub_dir, 'Tables')
os.makedirs(tables_dir, exist_ok=True)
for tbl_name in eds_tables:
table_xml = build_eds_table_xml(obj_name, tbl_name, eds_tables[tbl_name])
table_path = os.path.join(tables_dir, f'{tbl_name}.xml')
write_xml_file_keep_eol(table_path, table_xml)
eds_tables_created.append(table_path)
# Module files # Module files
modules_created = [] modules_created = []
@@ -1,4 +1,4 @@
# meta-edit v1.42 — Edit existing 1C metadata object XML # meta-edit v1.43 — Edit existing 1C metadata object XML
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
[CmdletBinding(PositionalBinding=$false)] [CmdletBinding(PositionalBinding=$false)]
param( param(
@@ -139,7 +139,8 @@ $script:validEnumValues = @{
"WriteMode" = @("Independent","RecorderSubordinate") "WriteMode" = @("Independent","RecorderSubordinate")
"InformationRegisterPeriodicity" = @("Nonperiodical","Second","Day","Month","Quarter","Year","RecorderPosition") "InformationRegisterPeriodicity" = @("Nonperiodical","Second","Day","Month","Quarter","Year","RecorderPosition")
"DependenceOnCalculationTypes" = @("DontUse","OnActionPeriod") "DependenceOnCalculationTypes" = @("DontUse","OnActionPeriod")
"DataLockControlMode" = @("Automatic","Managed") # AutomaticAndManaged — только у внешнего источника данных и его таблиц.
"DataLockControlMode" = @("Automatic","Managed","AutomaticAndManaged")
"FullTextSearch" = @("Use","DontUse") "FullTextSearch" = @("Use","DontUse")
"DataHistory" = @("Use","DontUse") "DataHistory" = @("Use","DontUse")
"DefaultPresentation" = @("AsDescription","AsCode") "DefaultPresentation" = @("AsDescription","AsCode")
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# meta-edit v1.42 — Edit existing 1C metadata object XML # meta-edit v1.43 — Edit existing 1C metadata object XML
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
@@ -427,7 +427,8 @@ valid_enum_values = {
'WriteMode': ['Independent', 'RecorderSubordinate'], 'WriteMode': ['Independent', 'RecorderSubordinate'],
'InformationRegisterPeriodicity': ['Nonperiodical', 'Second', 'Day', 'Month', 'Quarter', 'Year', 'RecorderPosition'], 'InformationRegisterPeriodicity': ['Nonperiodical', 'Second', 'Day', 'Month', 'Quarter', 'Year', 'RecorderPosition'],
'DependenceOnCalculationTypes': ['DontUse', 'OnActionPeriod'], 'DependenceOnCalculationTypes': ['DontUse', 'OnActionPeriod'],
'DataLockControlMode': ['Automatic', 'Managed'], # AutomaticAndManaged — только у внешнего источника данных и его таблиц.
'DataLockControlMode': ['Automatic', 'Managed', 'AutomaticAndManaged'],
'FullTextSearch': ['Use', 'DontUse'], 'FullTextSearch': ['Use', 'DontUse'],
'DataHistory': ['Use', 'DontUse'], 'DataHistory': ['Use', 'DontUse'],
'DefaultPresentation': ['AsDescription', 'AsCode'], 'DefaultPresentation': ['AsDescription', 'AsCode'],
@@ -1,4 +1,4 @@
# meta-validate v1.25 — Validate 1C metadata object structure # meta-validate v1.26 — Validate 1C metadata object structure
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
[CmdletBinding(PositionalBinding=$false)] [CmdletBinding(PositionalBinding=$false)]
param( param(
@@ -179,7 +179,9 @@ $validTypes = @(
"BusinessProcess","Task","ExchangePlan","DocumentJournal", "BusinessProcess","Task","ExchangePlan","DocumentJournal",
"Report","DataProcessor", "Report","DataProcessor",
"CommonModule","ScheduledJob","EventSubscription", "CommonModule","ScheduledJob","EventSubscription",
"HTTPService","WebService","DefinedType" "HTTPService","WebService","DefinedType",
# Внешний источник данных и его таблица (корень файла таблицы — <Table>).
"ExternalDataSource","Table"
) )
# Валидные типы метаданных без глубоких правил валидации — раньше падали как "Unrecognized" # Валидные типы метаданных без глубоких правил валидации — раньше падали как "Unrecognized"
@@ -213,6 +215,9 @@ $generatedTypeCategories = @{
"DataProcessor" = @("Object","Manager") "DataProcessor" = @("Object","Manager")
"DefinedType" = @("DefinedType") "DefinedType" = @("DefinedType")
"ExternalDataSource" = @("Manager","TablesManager","CubesManager") "ExternalDataSource" = @("Manager","TablesManager","CubesManager")
# Таблица внешнего источника: имя элемента трёхчастное (Префикс.Источник.Таблица),
# но проверка «имя оканчивается на .ИмяОбъекта» на нём работает как есть.
"Table" = @("Manager","Object","Ref","List","Record","RecordSet","RecordKey","RecordManager")
} }
# Types that have NO InternalInfo / GeneratedType # Types that have NO InternalInfo / GeneratedType
@@ -274,6 +279,9 @@ $childObjectRules = @{
"DocumentJournal" = @("Column","Form","Template","Command") "DocumentJournal" = @("Column","Form","Template","Command")
"HTTPService" = @("URLTemplate") "HTTPService" = @("URLTemplate")
"WebService" = @("Operation") "WebService" = @("Operation")
# Внешний источник: таблицы перечислены именами, функции лежат полными узлами.
"ExternalDataSource" = @("Table","Function","Cube")
"Table" = @("Field","Form","Template","Command")
"Constant" = @("Form") "Constant" = @("Form")
"DefinedType" = @() "DefinedType" = @()
"CommonModule" = @() "CommonModule" = @()
@@ -296,7 +304,8 @@ $validPropertyValues = @{
"RealTimePosting" = @("Allow","Deny") "RealTimePosting" = @("Allow","Deny")
"RegisterRecordsDeletion" = @("AutoDelete","AutoDeleteOnUnpost","AutoDeleteOff") "RegisterRecordsDeletion" = @("AutoDelete","AutoDeleteOnUnpost","AutoDeleteOff")
"RegisterRecordsWritingOnPost" = @("WriteModified","WriteSelected","WriteAll") "RegisterRecordsWritingOnPost" = @("WriteModified","WriteSelected","WriteAll")
"DataLockControlMode" = @("Automatic","Managed") # AutomaticAndManaged — только у внешнего источника данных и его таблиц.
"DataLockControlMode" = @("Automatic","Managed","AutomaticAndManaged")
"FullTextSearch" = @("Use","DontUse") "FullTextSearch" = @("Use","DontUse")
"DefaultPresentation" = @("AsDescription","AsCode") "DefaultPresentation" = @("AsDescription","AsCode")
"HierarchyType" = @("HierarchyFoldersAndItems","HierarchyOfItems") "HierarchyType" = @("HierarchyFoldersAndItems","HierarchyOfItems")
@@ -1762,6 +1771,13 @@ if (-not $isAdopted) {
continue continue
} }
# Ссылка на форму таблицы внешнего источника — шестичастная:
# ExternalDataSource.<Источник>.Table.<Таблица>.Form.<Форма>. Сводим её к четырём частям
# (вид = Table, объект = имя таблицы), дальше проверка общая.
if ($parts.Count -eq 6 -and $parts[0] -eq "ExternalDataSource" -and $parts[2] -eq "Table" -and $parts[4] -eq "Form") {
$parts = @("Table", $parts[3], "Form", $parts[5])
}
if ($parts.Count -ne 4 -or $parts[2] -ne "Form") { if ($parts.Count -ne 4 -or $parts[2] -ne "Form") {
Report-Warn "20. $tag '$ref' — неожиданный вид ссылки на форму (ожидается 'CommonForm.Имя' или '<Вид>.<Объект>.Form.<Форма>')" Report-Warn "20. $tag '$ref' — неожиданный вид ссылки на форму (ожидается 'CommonForm.Имя' или '<Вид>.<Объект>.Form.<Форма>')"
continue continue
@@ -1,4 +1,4 @@
# meta-validate v1.25 — Validate 1C metadata object structure (Python port) # meta-validate v1.26 — Validate 1C metadata object structure (Python port)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
import os import os
@@ -226,6 +226,8 @@ valid_types = (
"Report", "DataProcessor", "Report", "DataProcessor",
"CommonModule", "ScheduledJob", "EventSubscription", "CommonModule", "ScheduledJob", "EventSubscription",
"HTTPService", "WebService", "DefinedType", "HTTPService", "WebService", "DefinedType",
# Внешний источник данных и его таблица (корень файла таблицы — <Table>).
"ExternalDataSource", "Table",
) )
# Валидные типы метаданных без глубоких правил валидации — раньше падали как "Unrecognized" # Валидные типы метаданных без глубоких правил валидации — раньше падали как "Unrecognized"
@@ -259,6 +261,9 @@ generated_type_categories = {
"DataProcessor": ["Object", "Manager"], "DataProcessor": ["Object", "Manager"],
"DefinedType": ["DefinedType"], "DefinedType": ["DefinedType"],
"ExternalDataSource": ["Manager", "TablesManager", "CubesManager"], "ExternalDataSource": ["Manager", "TablesManager", "CubesManager"],
# Таблица внешнего источника: имя элемента трёхчастное (Префикс.Источник.Таблица),
# но проверка «имя оканчивается на .ИмяОбъекта» на нём работает как есть.
"Table": ["Manager", "Object", "Ref", "List", "Record", "RecordSet", "RecordKey", "RecordManager"],
} }
# Types that have NO InternalInfo / GeneratedType # Types that have NO InternalInfo / GeneratedType
@@ -320,6 +325,9 @@ child_object_rules = {
"DocumentJournal": ["Column", "Form", "Template", "Command"], "DocumentJournal": ["Column", "Form", "Template", "Command"],
"HTTPService": ["URLTemplate"], "HTTPService": ["URLTemplate"],
"WebService": ["Operation"], "WebService": ["Operation"],
# Внешний источник: таблицы перечислены именами, функции лежат полными узлами.
"ExternalDataSource": ["Table", "Function", "Cube"],
"Table": ["Field", "Form", "Template", "Command"],
"Constant": ["Form"], "Constant": ["Form"],
"DefinedType": [], "DefinedType": [],
"CommonModule": [], "CommonModule": [],
@@ -344,7 +352,8 @@ valid_property_values = {
"RealTimePosting": ["Allow", "Deny"], "RealTimePosting": ["Allow", "Deny"],
"RegisterRecordsDeletion": ["AutoDelete", "AutoDeleteOnUnpost", "AutoDeleteOff"], "RegisterRecordsDeletion": ["AutoDelete", "AutoDeleteOnUnpost", "AutoDeleteOff"],
"RegisterRecordsWritingOnPost": ["WriteModified", "WriteSelected", "WriteAll"], "RegisterRecordsWritingOnPost": ["WriteModified", "WriteSelected", "WriteAll"],
"DataLockControlMode": ["Automatic", "Managed"], # AutomaticAndManaged — только у внешнего источника данных и его таблиц.
"DataLockControlMode": ["Automatic", "Managed", "AutomaticAndManaged"],
"FullTextSearch": ["Use", "DontUse"], "FullTextSearch": ["Use", "DontUse"],
"DefaultPresentation": ["AsDescription", "AsCode"], "DefaultPresentation": ["AsDescription", "AsCode"],
"HierarchyType": ["HierarchyFoldersAndItems", "HierarchyOfItems"], "HierarchyType": ["HierarchyFoldersAndItems", "HierarchyOfItems"],
@@ -1707,6 +1716,13 @@ if not is_adopted:
form_ref_bad = True form_ref_bad = True
continue continue
# Ссылка на форму таблицы внешнего источника — шестичастная:
# ExternalDataSource.<Источник>.Table.<Таблица>.Form.<Форма>. Сводим её к четырём частям
# (вид = Table, объект = имя таблицы), дальше проверка общая.
if (len(parts) == 6 and parts[0] == "ExternalDataSource"
and parts[2] == "Table" and parts[4] == "Form"):
parts = ["Table", parts[3], "Form", parts[5]]
if len(parts) != 4 or parts[2] != "Form": if len(parts) != 4 or parts[2] != "Form":
report_warn(f"20. {tag} '{ref}' — неожиданный вид ссылки на форму " report_warn(f"20. {tag} '{ref}' — неожиданный вид ссылки на форму "
f"(ожидается 'CommonForm.Имя' или '<Вид>.<Объект>.Form.<Форма>')") f"(ожидается 'CommonForm.Имя' или '<Вид>.<Объект>.Form.<Форма>')")
+191 -6
View File
@@ -1696,7 +1696,181 @@ XML-элемент: `<WebService>`. Трёхуровневая вложенно
--- ---
## 26. Различия версий платформы ## 26. Внешние источники данных (ExternalDataSources)
XML-элемент: `<ExternalDataSource>`. Двухуровневая вложенность: источник → таблица → поле,
но **уровней каталогов только два**:
```
ExternalDataSources/PG.xml источник
ExternalDataSources/PG/Tables/products.xml таблица (поля — внутри этого файла)
ExternalDataSources/PG/Tables/products/Ext/ManagerModule.bsl
ExternalDataSources/PG/Tables/products/Forms/ФормаСписка.xml (+ Forms/<Форма>/Ext/Form.xml)
```
Модули таблицы — `ObjectModule.bsl`, `RecordSetModule.bsl`, `ManagerModule.bsl`; в выгрузку попадают
только непустые. Формы — как у справочника.
**Параметров соединения в метаданных нет.** Строка соединения, пользователь, пароль и тип СУБД
задаются в режиме «Предприятие» (стандартная функция «Управление внешними источниками данных») и
хранятся в информационной базе. В конфигурации у источника всего четыре свойства.
### 26.1. Свойства источника
```xml
<Properties>
<Name>PG</Name>
<Synonym>...</Synonym>
<Comment/>
<DataLockControlMode>AutomaticAndManaged</DataLockControlMode>
</Properties>
```
`DataLockControlMode`: `Automatic` | `Managed` | `AutomaticAndManaged`. При конкретном значении
одноимённое свойство таблицы игнорируется; `AutomaticAndManaged` отдаёт решение таблицам.
### 26.2. ChildObjects источника: Table (именем) + Function (целиком)
Смешанный список: таблицы перечислены **именами** (их содержимое — в отдельных файлах), функции
лежат **полными узлами** прямо здесь.
```xml
<ChildObjects>
<Table>products</Table>
<Table>prices</Table>
<Function uuid="...">
<Properties>
<Name>total</Name>
<Synonym/>
<Comment/>
<ReturnValue>true</ReturnValue>
<Type>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>...</v8:NumberQualifiers>
</Type>
<ExpressionInDataSource>public.f_total(&amp;1, &amp;2)</ExpressionInDataSource>
</Properties>
</Function>
</ChildObjects>
```
Свойств у функции шесть. **Параметров как объектов метаданных не существует**: формальные параметры
записываются прямо в выражении как `&1`, `&2`; необязательные — в фигурных скобках (`f(&1{, &2})`),
переменное число — `&n[]` (последним в списке). `ReturnValue=false` описывает процедуру, тогда
`<Type/>` пуст.
Куб (`<Cube>`) — четвёртый вид дочернего объекта источника, здесь не описан.
### 26.3. Свойства таблицы
38 свойств в фиксированном порядке:
`Name`, `Synonym`, `Comment`, `TableType`, `NameInDataSource`, `ExpressionInDataSource`,
`TableDataType`, `KeyFields`, `PresentationField`, `ParentField`, `UnfilledParentValue`,
`Characteristics`, `UseStandardCommands`, `QuickChoice`, `InputByString`, `CreateOnInput`,
`SearchStringModeOnInputByString`, `ChoiceDataGetModeOnInputByString`, `ChoiceHistoryOnInput`,
`DefaultObjectForm`, `DefaultRecordForm`, `DefaultListForm`, `DefaultChoiceForm`,
`ObjectPresentation`, `ExtendedObjectPresentation`, `RecordPresentation`,
`ExtendedRecordPresentation`, `ListPresentation`, `ExtendedListPresentation`, `Explanation`,
`IncludeHelpInContents`, `ReadOnly`, `TransactionsIsolationLevel`, `DataVersionField`, `EditType`,
`BasedOn`, `DataLockFields`, `DataLockControlMode`.
Специфичные для внешнего источника:
| Свойство | Тип | Описание |
|---|---|---|
| `TableType` | enum | `Table` — реальная таблица или представление; `Expression` — табличная функция/выражение |
| `NameInDataSource` | string | Имя физической таблицы. Три части: `<база>.<схема>.<таблица>`. У `TableType=Expression`**пусто** |
| `ExpressionInDataSource` | string | Выражение для `TableType=Expression`, напр. `public.f_by_parent(&1)`. Здесь имя базы **не указывается** |
| `TableDataType` | enum | `ObjectData` — запись идентифицируется одним полем; `NonobjectData` — составным ключом |
| `KeyFields` | список | Ключевые поля, `<xr:Field>` с полным путём |
| `PresentationField` | скаляр | Поле представления (только `ObjectData`) |
| `ParentField` | скаляр | Поле родителя для иерархии; тип поля должен быть ссылкой на эту же таблицу |
| `UnfilledParentValue` | значение | Значение «нет родителя», типизировано (`xsi:type`) |
| `ReadOnly` | boolean | Запрет записи. Платформа сама ставит `true` представлениям и таблицам вида `Expression` |
| `TransactionsIsolationLevel` | enum | `Auto` \| `ReadUncommitted` \| `ReadCommitted` \| `RepeatableRead` \| `Serializable` |
| `DataVersionField` | скаляр | Поле, растущее при каждой записи, — по нему ловится конкурентное изменение |
| `DataLockFields` | список | Поля управляемой блокировки |
`BasedOn`, `Characteristics`, `EditType`, представления и формы — как у справочника.
**Признака незаполненного родителя отдельным узлом нет.** «NULL» против «Заданное значение»
различаются формой самого `UnfilledParentValue`:
```xml
<UnfilledParentValue xsi:nil="true"/> <!-- NULL -->
<UnfilledParentValue xsi:type="xs:decimal">0</UnfilledParentValue> <!-- Заданное значение -->
```
Тип значения — тип **ключевого** поля таблицы, а не ссылочный тип поля родителя.
### 26.4. Скаляры против списков
Путь внутри одинаковый, оборачивание разное:
```xml
<PresentationField>ExternalDataSource.PG.Table.products.Field.name</PresentationField>
<KeyFields>
<xr:Field>ExternalDataSource.PG.Table.products.Field.id</xr:Field>
</KeyFields>
```
Скаляры: `PresentationField`, `ParentField`, `DataVersionField`.
Списки `<xr:Field>`: `KeyFields`, `InputByString`, `DataLockFields`.
### 26.5. Поле таблицы
26 свойств: канонический блок реквизита (см. §6.1) без `ChoiceFoldersAndItems`, `LinkByType`,
`Indexing`, `Use`, `FullTextSearch`, `DataHistory`, плюс три своих в конце:
| Свойство | Тип | Описание |
|---|---|---|
| `NameInDataSource` | string | Имя колонки. В одинарных кавычках попадает в SQL как есть, без них — экранируется двойными при спецсимволах |
| `ReadOnly` | boolean | Поле не записывается (вычисляемые, автоинкрементные) |
| `AllowNull` | boolean | Допускает `NULL`; в форме показывается как «Не заполнено» |
Типы поля: `Число`, `Строка`, `Дата`, `Булево`, `УникальныйИдентификатор`, `ДвоичныеДанные` и
ссылка на таблицу внешнего источника:
```xml
<Type><v8:Type>cfg:ExternalDataSourceTableRef.PG.products</v8:Type></Type>
```
Префикс корневой `cfg:` (объявлен в шапке `MetaDataObject`), квалификаторов у ссылки нет.
**Составной тип платформой запрещён.** Документация «Руководства разработчика» (17.5.2.3.4)
разрешает составной тип из Числа/Строки/Даты/Булева, но 8.3.24 отвергает загрузку:
«Поле не может иметь составной тип».
### 26.6. Расхождения Конфигуратора и загрузки XML
Интерактивный редактор строже загрузчика. Измерено на 8.3.24.1691:
| Ситуация | Конфигуратор | Загрузка XML |
|---|---|---|
| Таблица без `KeyFields` | ошибка «Не указано ни одного поля ключа» | принимает молча, обновление БД проходит |
| Составной тип поля | галочки «Составной тип» нет | явная ошибка при загрузке |
Первое означает, что валидатор не должен считать пустой ключ ошибкой: рабочие конфигурации с
таблицами без ключа существуют.
### 26.7. Что платформа заполняет сама
Конструктор загрузки структуры из СУБД:
- `TableDataType``ObjectData` при первичном ключе из одного поля, иначе `NonobjectData`;
- `KeyFields` — из первичного ключа СУБД (у представления его нет → пусто);
- `ReadOnly` таблицы — `true` для представлений и таблиц вида `Expression`;
- `AllowNull` поля — из `NOT NULL` колонки;
- ссылочный тип поля — из внешнего ключа СУБД;
- имя объекта — `<база>_<схема>_<объект>` (точки заменяются подчёркиваниями).
Кроме того, при задании `PresentationField` платформа добавляет это поле в `InputByString`.
---
## 27. Различия версий платформы
### 26.1. Лестница версий ### 26.1. Лестница версий
@@ -1750,7 +1924,7 @@ XML-элемент: `<WebService>`. Трёхуровневая вложенно
--- ---
## 27. Сводная таблица: свойства по типам объектов ## 28. Сводная таблица: свойства по типам объектов
| Свойство | Cat | Doc | Enum | Const | InfoReg | AccReg | AcctReg | CalcReg | CoA | CoCT | CoCaT | BP | Task | EP | DJ | Rep | DP | | Свойство | Cat | Doc | Enum | Const | InfoReg | AccReg | AcctReg | CalcReg | CoA | CoCT | CoCaT | BP | Task | EP | DJ | Rep | DP |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| |---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1782,9 +1956,11 @@ XML-элемент: `<WebService>`. Трёхуровневая вложенно
Сокращения: Cat=Справочник, Doc=Документ, Const=Константа, InfoReg=РегСведений, AccReg=РегНакопления, AcctReg=РегБухгалтерии, CalcReg=РегРасчёта, CoA=ПланСчетов, CoCT=ПВХ, CoCaT=ПВР, BP=БизнесПроцесс, EP=ПланОбмена, DJ=ЖурналДокументов, Rep=Отчёт, DP=Обработка. Сокращения: Cat=Справочник, Doc=Документ, Const=Константа, InfoReg=РегСведений, AccReg=РегНакопления, AcctReg=РегБухгалтерии, CalcReg=РегРасчёта, CoA=ПланСчетов, CoCT=ПВХ, CoCaT=ПВР, BP=БизнесПроцесс, EP=ПланОбмена, DJ=ЖурналДокументов, Rep=Отчёт, DP=Обработка.
Внешний источник данных в матрицу не вошёл: набор его свойств не пересекается с колонками (ни кода с наименованием, ни реквизитов, ни табличных частей — вместо них таблицы и поля). См. § 26.
--- ---
## 28. Формат ссылок на объекты метаданных ## 29. Формат ссылок на объекты метаданных
В свойствах типа `DefaultObjectForm`, `InputByString`, `RegisterRecords`, `DataLockFields` и др. используется формат ссылок: В свойствах типа `DefaultObjectForm`, `InputByString`, `RegisterRecords`, `DataLockFields` и др. используется формат ссылок:
@@ -1800,13 +1976,18 @@ XML-элемент: `<WebService>`. Трёхуровневая вложенно
{ВидОбъекта}.{ИмяОбъекта}.Resource.{ИмяРесурса} # На ресурс регистра {ВидОбъекта}.{ИмяОбъекта}.Resource.{ИмяРесурса} # На ресурс регистра
{ВидОбъекта}.{ИмяОбъекта}.AddressingAttribute.{Имя} # На реквизит адресации {ВидОбъекта}.{ИмяОбъекта}.AddressingAttribute.{Имя} # На реквизит адресации
{ВидОбъекта}.{ИмяОбъекта}.EnumValue.{ИмяЗначения} # На значение перечисления {ВидОбъекта}.{ИмяОбъекта}.EnumValue.{ИмяЗначения} # На значение перечисления
ExternalDataSource.{Источник}.Table.{Таблица} # На таблицу внешнего источника
ExternalDataSource.{Источник}.Table.{Таблица}.Field.{Поле} # На поле таблицы
ExternalDataSource.{Источник}.Table.{Таблица}.Form.{Форма} # На форму таблицы
``` ```
Виды объектов в ссылках: `Catalog`, `Document`, `Enum`, `InformationRegister`, `AccumulationRegister`, `AccountingRegister`, `CalculationRegister`, `ChartOfAccounts`, `ChartOfCharacteristicTypes`, `ChartOfCalculationTypes`, `BusinessProcess`, `Task`, `ExchangePlan`, `DocumentJournal`, `Report`, `DataProcessor`, `CommonForm`, `CommonPicture`, `SessionParameter`, `Constant`. Виды объектов в ссылках: `Catalog`, `Document`, `Enum`, `InformationRegister`, `AccumulationRegister`, `AccountingRegister`, `CalculationRegister`, `ChartOfAccounts`, `ChartOfCharacteristicTypes`, `ChartOfCalculationTypes`, `BusinessProcess`, `Task`, `ExchangePlan`, `DocumentJournal`, `Report`, `DataProcessor`, `CommonForm`, `CommonPicture`, `SessionParameter`, `Constant`, `ExternalDataSource`.
Ссылки на внешний источник — единственные **шестичастные**: между видом и подчинённой сущностью стоит имя источника. Разбор с конца (как в ролях) на них не работает — считать надо с начала.
--- ---
## 29. GeneratedType категории ## 30. GeneratedType категории
Каждый объект метаданных содержит блок `<InternalInfo>` с элементами `<GeneratedType>`, описывающими платформенные типы. Ниже — эталонная таблица категорий по типам объектов (источник: выгрузки ACC 8.3.24, ERP 8.3.24). Каждый объект метаданных содержит блок `<InternalInfo>` с элементами `<GeneratedType>`, описывающими платформенные типы. Ниже — эталонная таблица категорий по типам объектов (источник: выгрузки ACC 8.3.24, ERP 8.3.24).
@@ -1830,14 +2011,18 @@ XML-элемент: `<WebService>`. Трёхуровневая вложенно
| Report | Object, Manager | | Report | Object, Manager |
| DataProcessor | Object, Manager | | DataProcessor | Object, Manager |
| DefinedType | DefinedType | | DefinedType | DefinedType |
| ExternalDataSource | Manager, TablesManager, CubesManager |
| ExternalDataSource → Table | Manager, Object, Ref, List, Record, RecordSet, RecordKey, RecordManager |
Формат `name` в XML: `{Prefix}.{ObjectName}`, где Prefix = `{MetaType}{Category}` (например `CatalogObject.Номенклатура`, `AccountingRegisterExtDimensions.Хозрасчетный`). Формат `name` в XML: `{Prefix}.{ObjectName}`, где Prefix = `{MetaType}{Category}` (например `CatalogObject.Номенклатура`, `AccountingRegisterExtDimensions.Хозрасчетный`).
Исключение — таблица внешнего источника: имя **трёхчастное**, `{Prefix}.{Источник}.{Таблица}` (`ExternalDataSourceTableRef.PG.products`), а префикс строится от `ExternalDataSourceTable`, а не от имени вида. У `<Field>` и `<Function>` блока `InternalInfo` нет вовсе — только атрибут `uuid`.
Примечание: TabularSection/TabularSectionRow генерируются динамически для каждой табличной части. ChartOfAccounts может иметь условные ExtDimensionTypes/ExtDimensionTypesRow (зависит от наличия `extDimensionTypes`). Примечание: TabularSection/TabularSectionRow генерируются динамически для каждой табличной части. ChartOfAccounts может иметь условные ExtDimensionTypes/ExtDimensionTypesRow (зависит от наличия `extDimensionTypes`).
--- ---
## 30. Кодировка ## 31. Кодировка
Все XML-файлы используют кодировку UTF-8 с BOM (байты `EF BB BF`): Все XML-файлы используют кодировку UTF-8 с BOM (байты `EF BB BF`):
+6 -5
View File
@@ -318,12 +318,13 @@ ClassId — фиксированные идентификаторы классо
| `WSReference` | `WSReferenceManager`/Manager | | `WSReference` | `WSReferenceManager`/Manager |
| `DefinedType` | `DefinedType`/DefinedType | | `DefinedType` | `DefinedType`/DefinedType |
| `ExternalDataSource` | `ExternalDataSourceManager`/Manager, `ExternalDataSourceTablesManager`/TablesManager, `ExternalDataSourceCubesManager`/CubesManager | | `ExternalDataSource` | `ExternalDataSourceManager`/Manager, `ExternalDataSourceTablesManager`/TablesManager, `ExternalDataSourceCubesManager`/CubesManager |
| `ExternalDataSource``Table` | `ExternalDataSourceTableManager`/Manager, `ExternalDataSourceTableObject`/Object, `ExternalDataSourceTableRef`/Ref, `ExternalDataSourceTableList`/List, `ExternalDataSourceTableRecord`/Record, `ExternalDataSourceTableRecordSet`/RecordSet, `ExternalDataSourceTableRecordKey`/RecordKey, `ExternalDataSourceTableRecordManager`/RecordManager | | `Table` | `ExternalDataSourceTableManager`/Manager, `ExternalDataSourceTableObject`/Object, `ExternalDataSourceTableRef`/Ref, `ExternalDataSourceTableList`/List, `ExternalDataSourceTableRecord`/Record, `ExternalDataSourceTableRecordSet`/RecordSet, `ExternalDataSourceTableRecordKey`/RecordKey, `ExternalDataSourceTableRecordManager`/RecordManager |
Таблица внешнего источника — единственный подчинённый объект со своим `<InternalInfo>` в отдельном файле; `Table` — корневой элемент файла таблицы внешнего источника (`ExternalDataSources/<Источник>/Tables/<Имя>.xml`),
имя элемента у неё **трёхчастное**: `<префикс>.<ИмяИсточника>.<ИмяТаблицы>` (например единственный подчинённый объект со своим `<InternalInfo>` в отдельном файле. Имя элемента у него
`ExternalDataSourceTableRef.PG.eds_public_products`). У `<Field>` и `<Function>` блока `InternalInfo` нет — **трёхчастное**: `<префикс>.<ИмяИсточника>.<ИмяТаблицы>` (например
только атрибут `uuid`. `ExternalDataSourceTableRef.PG.eds_public_products`), поэтому навыки-эмиттеры строят его инлайном,
а не из карты «вид → набор». У `<Field>` и `<Function>` блока `InternalInfo` нет — только атрибут `uuid`.
Табличные части объектов несут собственную пару в своём `<InternalInfo>`: `<Тип>TabularSection.<Объект>.<ТЧ>`/TabularSection и `<Тип>TabularSectionRow.<Объект>.<ТЧ>`/TabularSectionRow. Табличные части объектов несут собственную пару в своём `<InternalInfo>`: `<Тип>TabularSection.<Объект>.<ТЧ>`/TabularSection и `<Тип>TabularSectionRow.<Объект>.<ТЧ>`/TabularSectionRow.
+3 -2
View File
@@ -53,6 +53,7 @@
| `WebService` | `WebServices/` | Веб-сервисы | [1c-config-objects-spec.md § 25](1c-config-objects-spec.md#25-веб-сервисы-webservices) | | `WebService` | `WebServices/` | Веб-сервисы | [1c-config-objects-spec.md § 25](1c-config-objects-spec.md#25-веб-сервисы-webservices) |
| `HTTPService` | `HTTPServices/` | HTTP-сервисы | [1c-config-objects-spec.md § 24](1c-config-objects-spec.md#24-http-сервисы-httpservices) | | `HTTPService` | `HTTPServices/` | HTTP-сервисы | [1c-config-objects-spec.md § 24](1c-config-objects-spec.md#24-http-сервисы-httpservices) |
| `WSReference` | `WSReferences/` | WS-ссылки | [1c-configuration-spec.md § 6.15](1c-configuration-spec.md#615-wsreference--ws-ссылка) | | `WSReference` | `WSReferences/` | WS-ссылки | [1c-configuration-spec.md § 6.15](1c-configuration-spec.md#615-wsreference--ws-ссылка) |
| `ExternalDataSource` | `ExternalDataSources/` | Внешние источники данных | [1c-config-objects-spec.md § 26](1c-config-objects-spec.md#26-внешние-источники-данных-externaldatasources) |
| `IntegrationService` | `IntegrationServices/` | Сервисы интеграции | [1c-configuration-spec.md § 6.13](1c-configuration-spec.md#613-integrationservice--сервис-интеграции) | | `IntegrationService` | `IntegrationServices/` | Сервисы интеграции | [1c-configuration-spec.md § 6.13](1c-configuration-spec.md#613-integrationservice--сервис-интеграции) |
### Поведение и параметризация ### Поведение и параметризация
@@ -157,8 +158,8 @@
| Общие свойства Properties | [1c-config-objects-spec.md § 4](1c-config-objects-spec.md#4-общие-элементы-properties) | | Общие свойства Properties | [1c-config-objects-spec.md § 4](1c-config-objects-spec.md#4-общие-элементы-properties) |
| Стандартные реквизиты | [1c-config-objects-spec.md § 5](1c-config-objects-spec.md#5-стандартные-реквизиты-standardattributes) | | Стандартные реквизиты | [1c-config-objects-spec.md § 5](1c-config-objects-spec.md#5-стандартные-реквизиты-standardattributes) |
| Дочерние объекты (Attribute, TabularSection, Form, Template, Command) | [1c-config-objects-spec.md § 6](1c-config-objects-spec.md#6-дочерние-объекты-childobjects) | | Дочерние объекты (Attribute, TabularSection, Form, Template, Command) | [1c-config-objects-spec.md § 6](1c-config-objects-spec.md#6-дочерние-объекты-childobjects) |
| Формат ссылок на объекты | [1c-config-objects-spec.md § 28](1c-config-objects-spec.md#28-формат-ссылок-на-объекты-метаданных) | | Формат ссылок на объекты | [1c-config-objects-spec.md § 29](1c-config-objects-spec.md#29-формат-ссылок-на-объекты-метаданных) |
| Различия версий формата 2.17 → 2.18 → 2.19 → 2.20 | [1c-config-objects-spec.md § 26](1c-config-objects-spec.md#26-различия-версий-платформы) | | Различия версий формата 2.17 → 2.18 → 2.19 → 2.20 | [1c-config-objects-spec.md § 27](1c-config-objects-spec.md#27-различия-версий-платформы) |
--- ---
@@ -0,0 +1,71 @@
{
"name": "Внешний источник данных: таблицы, поля, функция",
"input": {
"type": "ExternalDataSource",
"name": "PG",
"dataLockControlMode": "AutomaticAndManaged",
"tables": {
"prices": ["product_id: Number(10,0)", "period: Date", "price: Number(15,2)"],
"products": {
"nameInDataSource": "eds.public.products",
"tableDataType": "ObjectData",
"keyFields": ["id"],
"presentationField": "name",
"parentField": "parent_id",
"dataVersionField": "row_ver",
"transactionsIsolationLevel": "ReadUncommitted",
"dataLockFields": ["id"],
"fields": [
"id: Number(10,0)",
"name: String(150)",
"article: String(50) | nullable",
"parent_id: ExternalDataSourceTableRef.PG.products | nullable",
"row_ver: Number(19,0) | readonly"
]
},
"byParent": {
"tableType": "Expression",
"expressionInDataSource": "public.f_products_by_parent(&1)",
"fields": ["id: Number(10,0)", "name: String(150)"]
}
},
"functions": {
"total": { "expression": "public.f_total(&1, &2)", "returns": "Number(15,2)" },
"nextKey": "NEXT VALUE FOR public.seq_key"
}
},
"validatePath": "ExternalDataSources/PG",
"expect": {
"files": [
"ExternalDataSources/PG.xml",
"ExternalDataSources/PG/Tables/products.xml",
"ExternalDataSources/PG/Tables/prices.xml",
"ExternalDataSources/PG/Tables/byParent.xml"
],
"fileContains": [
{
"file": "ExternalDataSources/PG/Tables/products.xml",
"text": [
"<v8:Type>cfg:ExternalDataSourceTableRef.PG.products</v8:Type>",
"<xr:Field>ExternalDataSource.PG.Table.products.Field.id</xr:Field>",
"<PresentationField>ExternalDataSource.PG.Table.products.Field.name</PresentationField>",
"<UnfilledParentValue xsi:type=\"xs:string\"/>",
"<TransactionsIsolationLevel>ReadUncommitted</TransactionsIsolationLevel>",
"<NameInDataSource>eds.public.products</NameInDataSource>"
]
},
{
"file": "ExternalDataSources/PG/Tables/byParent.xml",
"text": ["<TableType>Expression</TableType>", "<NameInDataSource/>", "public.f_products_by_parent(&amp;1)"]
},
{
"file": "ExternalDataSources/PG.xml",
"text": [
"<DataLockControlMode>AutomaticAndManaged</DataLockControlMode>",
"<Table>products</Table>",
"<ExpressionInDataSource>public.f_total(&amp;1, &amp;2)</ExpressionInDataSource>"
]
}
]
}
}
@@ -0,0 +1,252 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
<Configuration uuid="UUID-001">
<InternalInfo>
<xr:ContainedObject>
<xr:ClassId>UUID-002</xr:ClassId>
<xr:ObjectId>UUID-003</xr:ObjectId>
</xr:ContainedObject>
<xr:ContainedObject>
<xr:ClassId>UUID-004</xr:ClassId>
<xr:ObjectId>UUID-005</xr:ObjectId>
</xr:ContainedObject>
<xr:ContainedObject>
<xr:ClassId>UUID-006</xr:ClassId>
<xr:ObjectId>UUID-007</xr:ObjectId>
</xr:ContainedObject>
<xr:ContainedObject>
<xr:ClassId>UUID-008</xr:ClassId>
<xr:ObjectId>UUID-009</xr:ObjectId>
</xr:ContainedObject>
<xr:ContainedObject>
<xr:ClassId>UUID-010</xr:ClassId>
<xr:ObjectId>UUID-011</xr:ObjectId>
</xr:ContainedObject>
<xr:ContainedObject>
<xr:ClassId>UUID-012</xr:ClassId>
<xr:ObjectId>UUID-013</xr:ObjectId>
</xr:ContainedObject>
<xr:ContainedObject>
<xr:ClassId>UUID-014</xr:ClassId>
<xr:ObjectId>UUID-015</xr:ObjectId>
</xr:ContainedObject>
</InternalInfo>
<Properties>
<Name>TestConfig</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>TestConfig</v8:content>
</v8:item>
</Synonym>
<Comment/>
<NamePrefix/>
<ConfigurationExtensionCompatibilityMode>Version8_3_24</ConfigurationExtensionCompatibilityMode>
<DefaultRunMode>ManagedApplication</DefaultRunMode>
<UsePurposes>
<v8:Value xsi:type="app:ApplicationUsePurpose">PlatformApplication</v8:Value>
</UsePurposes>
<ScriptVariant>Russian</ScriptVariant>
<DefaultRoles/>
<Vendor/>
<Version/>
<UpdateCatalogAddress/>
<IncludeHelpInContents>false</IncludeHelpInContents>
<UseManagedFormInOrdinaryApplication>false</UseManagedFormInOrdinaryApplication>
<UseOrdinaryFormInManagedApplication>false</UseOrdinaryFormInManagedApplication>
<AdditionalFullTextSearchDictionaries/>
<CommonSettingsStorage/>
<ReportsUserSettingsStorage/>
<ReportsVariantsStorage/>
<FormDataSettingsStorage/>
<DynamicListsUserSettingsStorage/>
<URLExternalDataStorage/>
<Content/>
<DefaultReportForm/>
<DefaultReportVariantForm/>
<DefaultReportSettingsForm/>
<DefaultReportAppearanceTemplate/>
<DefaultDynamicListSettingsForm/>
<DefaultSearchForm/>
<DefaultDataHistoryChangeHistoryForm/>
<DefaultDataHistoryVersionDataForm/>
<DefaultDataHistoryVersionDifferencesForm/>
<DefaultCollaborationSystemUsersChoiceForm/>
<RequiredMobileApplicationPermissions/>
<UsedMobileApplicationFunctionalities>
<app:functionality>
<app:functionality>Biometrics</app:functionality>
<app:use>true</app:use>
</app:functionality>
<app:functionality>
<app:functionality>Location</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>BackgroundLocation</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>BluetoothPrinters</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>WiFiPrinters</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>Contacts</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>Calendars</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>PushNotifications</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>LocalNotifications</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>InAppPurchases</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>PersonalComputerFileExchange</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>Ads</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>NumberDialing</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>CallProcessing</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>CallLog</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>AutoSendSMS</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>ReceiveSMS</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>SMSLog</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>Camera</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>Microphone</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>MusicLibrary</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>PictureAndVideoLibraries</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>AudioPlaybackAndVibration</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>BackgroundAudioPlaybackAndVibration</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>InstallPackages</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>OSBackup</app:functionality>
<app:use>true</app:use>
</app:functionality>
<app:functionality>
<app:functionality>ApplicationUsageStatistics</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>BarcodeScanning</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>BackgroundAudioRecording</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>AllFilesAccess</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>Videoconferences</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>NFC</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>DocumentScanning</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>SpeechToText</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>Geofences</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>IncomingShareRequests</app:functionality>
<app:use>false</app:use>
</app:functionality>
<app:functionality>
<app:functionality>AllIncomingShareRequestsTypesProcessing</app:functionality>
<app:use>false</app:use>
</app:functionality>
</UsedMobileApplicationFunctionalities>
<StandaloneConfigurationRestrictionRoles/>
<MobileApplicationURLs/>
<AllowedIncomingShareRequestTypes/>
<MainClientApplicationWindowMode>Normal</MainClientApplicationWindowMode>
<DefaultInterface/>
<DefaultStyle/>
<DefaultLanguage>Language.Русский</DefaultLanguage>
<BriefInformation/>
<DetailedInformation/>
<Copyright/>
<VendorInformationAddress/>
<ConfigurationInformationAddress/>
<DataLockControlMode>Managed</DataLockControlMode>
<ObjectAutonumerationMode>NotAutoFree</ObjectAutonumerationMode>
<ModalityUseMode>DontUse</ModalityUseMode>
<SynchronousPlatformExtensionAndAddInCallUseMode>DontUse</SynchronousPlatformExtensionAndAddInCallUseMode>
<InterfaceCompatibilityMode>TaxiEnableVersion8_2</InterfaceCompatibilityMode>
<DatabaseTablespacesUseMode>DontUse</DatabaseTablespacesUseMode>
<CompatibilityMode>Version8_3_24</CompatibilityMode>
<DefaultConstantsForm/>
</Properties>
<ChildObjects>
<Language>Русский</Language>
<ExternalDataSource>PG</ExternalDataSource>
</ChildObjects>
</Configuration>
</MetaDataObject>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<ClientApplicationInterface xmlns="http://v8.1c.ru/8.2/managed-application/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="InterfaceLayouter">
<top>
<panel id="UUID-001">
<uuid>UUID-002</uuid>
</panel>
</top>
<left>
<panel id="UUID-003">
<uuid>UUID-004</uuid>
</panel>
</left>
<panelDef id="UUID-004"/>
<panelDef id="UUID-005"/>
<panelDef id="UUID-006"/>
<panelDef id="UUID-002"/>
<panelDef id="UUID-007"/>
</ClientApplicationInterface>
@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
<ExternalDataSource uuid="UUID-001">
<InternalInfo>
<xr:GeneratedType name="ExternalDataSourceManager.PG" category="Manager">
<xr:TypeId>UUID-002</xr:TypeId>
<xr:ValueId>UUID-003</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTablesManager.PG" category="TablesManager">
<xr:TypeId>UUID-004</xr:TypeId>
<xr:ValueId>UUID-005</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceCubesManager.PG" category="CubesManager">
<xr:TypeId>UUID-006</xr:TypeId>
<xr:ValueId>UUID-007</xr:ValueId>
</xr:GeneratedType>
</InternalInfo>
<Properties>
<Name>PG</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>PG</v8:content>
</v8:item>
</Synonym>
<Comment/>
<DataLockControlMode>AutomaticAndManaged</DataLockControlMode>
</Properties>
<ChildObjects>
<Table>prices</Table>
<Table>products</Table>
<Table>byParent</Table>
<Function uuid="UUID-008">
<Properties>
<Name>total</Name>
<Synonym/>
<Comment/>
<ReturnValue>true</ReturnValue>
<Type>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>15</v8:Digits>
<v8:FractionDigits>2</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
</Type>
<ExpressionInDataSource>public.f_total(&amp;1, &amp;2)</ExpressionInDataSource>
</Properties>
</Function>
<Function uuid="UUID-009">
<Properties>
<Name>nextKey</Name>
<Synonym/>
<Comment/>
<ReturnValue>true</ReturnValue>
<Type>
<v8:Type>xs:string</v8:Type>
<v8:StringQualifiers>
<v8:Length>10</v8:Length>
<v8:AllowedLength>Variable</v8:AllowedLength>
</v8:StringQualifiers>
</Type>
<ExpressionInDataSource>NEXT VALUE FOR public.seq_key</ExpressionInDataSource>
</Properties>
</Function>
</ChildObjects>
</ExternalDataSource>
</MetaDataObject>
@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
<Table uuid="UUID-001">
<InternalInfo>
<xr:GeneratedType name="ExternalDataSourceTableManager.PG.byParent" category="Manager">
<xr:TypeId>UUID-002</xr:TypeId>
<xr:ValueId>UUID-003</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableObject.PG.byParent" category="Object">
<xr:TypeId>UUID-004</xr:TypeId>
<xr:ValueId>UUID-005</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableRef.PG.byParent" category="Ref">
<xr:TypeId>UUID-006</xr:TypeId>
<xr:ValueId>UUID-007</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableList.PG.byParent" category="List">
<xr:TypeId>UUID-008</xr:TypeId>
<xr:ValueId>UUID-009</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableRecord.PG.byParent" category="Record">
<xr:TypeId>UUID-010</xr:TypeId>
<xr:ValueId>UUID-011</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableRecordSet.PG.byParent" category="RecordSet">
<xr:TypeId>UUID-012</xr:TypeId>
<xr:ValueId>UUID-013</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableRecordKey.PG.byParent" category="RecordKey">
<xr:TypeId>UUID-014</xr:TypeId>
<xr:ValueId>UUID-015</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableRecordManager.PG.byParent" category="RecordManager">
<xr:TypeId>UUID-016</xr:TypeId>
<xr:ValueId>UUID-017</xr:ValueId>
</xr:GeneratedType>
</InternalInfo>
<Properties>
<Name>byParent</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>by parent</v8:content>
</v8:item>
</Synonym>
<Comment/>
<TableType>Expression</TableType>
<NameInDataSource/>
<ExpressionInDataSource>public.f_products_by_parent(&amp;1)</ExpressionInDataSource>
<TableDataType>NonobjectData</TableDataType>
<KeyFields/>
<PresentationField/>
<ParentField/>
<UnfilledParentValue xsi:nil="true"/>
<Characteristics/>
<UseStandardCommands>true</UseStandardCommands>
<QuickChoice>false</QuickChoice>
<InputByString/>
<CreateOnInput>Auto</CreateOnInput>
<SearchStringModeOnInputByString>Begin</SearchStringModeOnInputByString>
<ChoiceDataGetModeOnInputByString>Directly</ChoiceDataGetModeOnInputByString>
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
<DefaultObjectForm/>
<DefaultRecordForm/>
<DefaultListForm/>
<DefaultChoiceForm/>
<ObjectPresentation/>
<ExtendedObjectPresentation/>
<RecordPresentation/>
<ExtendedRecordPresentation/>
<ListPresentation/>
<ExtendedListPresentation/>
<Explanation/>
<IncludeHelpInContents>false</IncludeHelpInContents>
<ReadOnly>false</ReadOnly>
<TransactionsIsolationLevel>Auto</TransactionsIsolationLevel>
<DataVersionField/>
<EditType>InDialog</EditType>
<BasedOn/>
<DataLockFields/>
<DataLockControlMode>Automatic</DataLockControlMode>
</Properties>
<ChildObjects>
<Field uuid="UUID-018">
<Properties>
<Name>id</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>id</v8:content>
</v8:item>
</Synonym>
<Comment/>
<Type>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>10</v8:Digits>
<v8:FractionDigits>0</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
</Type>
<PasswordMode>false</PasswordMode>
<Format/>
<EditFormat/>
<ToolTip/>
<MarkNegatives>false</MarkNegatives>
<Mask/>
<MultiLine>false</MultiLine>
<ExtendedEdit>false</ExtendedEdit>
<MinValue xsi:nil="true"/>
<MaxValue xsi:nil="true"/>
<FillFromFillingValue>false</FillFromFillingValue>
<FillValue xsi:type="xs:decimal">0</FillValue>
<FillChecking>DontCheck</FillChecking>
<ChoiceParameterLinks/>
<ChoiceParameters/>
<QuickChoice>Auto</QuickChoice>
<CreateOnInput>Auto</CreateOnInput>
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
<ChoiceForm/>
<NameInDataSource>id</NameInDataSource>
<ReadOnly>false</ReadOnly>
<AllowNull>false</AllowNull>
</Properties>
</Field>
<Field uuid="UUID-019">
<Properties>
<Name>name</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>name</v8:content>
</v8:item>
</Synonym>
<Comment/>
<Type>
<v8:Type>xs:string</v8:Type>
<v8:StringQualifiers>
<v8:Length>150</v8:Length>
<v8:AllowedLength>Variable</v8:AllowedLength>
</v8:StringQualifiers>
</Type>
<PasswordMode>false</PasswordMode>
<Format/>
<EditFormat/>
<ToolTip/>
<MarkNegatives>false</MarkNegatives>
<Mask/>
<MultiLine>false</MultiLine>
<ExtendedEdit>false</ExtendedEdit>
<MinValue xsi:nil="true"/>
<MaxValue xsi:nil="true"/>
<FillFromFillingValue>false</FillFromFillingValue>
<FillValue xsi:type="xs:string"/>
<FillChecking>DontCheck</FillChecking>
<ChoiceParameterLinks/>
<ChoiceParameters/>
<QuickChoice>Auto</QuickChoice>
<CreateOnInput>Auto</CreateOnInput>
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
<ChoiceForm/>
<NameInDataSource>name</NameInDataSource>
<ReadOnly>false</ReadOnly>
<AllowNull>false</AllowNull>
</Properties>
</Field>
</ChildObjects>
</Table>
</MetaDataObject>
@@ -0,0 +1,210 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
<Table uuid="UUID-001">
<InternalInfo>
<xr:GeneratedType name="ExternalDataSourceTableManager.PG.prices" category="Manager">
<xr:TypeId>UUID-002</xr:TypeId>
<xr:ValueId>UUID-003</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableObject.PG.prices" category="Object">
<xr:TypeId>UUID-004</xr:TypeId>
<xr:ValueId>UUID-005</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableRef.PG.prices" category="Ref">
<xr:TypeId>UUID-006</xr:TypeId>
<xr:ValueId>UUID-007</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableList.PG.prices" category="List">
<xr:TypeId>UUID-008</xr:TypeId>
<xr:ValueId>UUID-009</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableRecord.PG.prices" category="Record">
<xr:TypeId>UUID-010</xr:TypeId>
<xr:ValueId>UUID-011</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableRecordSet.PG.prices" category="RecordSet">
<xr:TypeId>UUID-012</xr:TypeId>
<xr:ValueId>UUID-013</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableRecordKey.PG.prices" category="RecordKey">
<xr:TypeId>UUID-014</xr:TypeId>
<xr:ValueId>UUID-015</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableRecordManager.PG.prices" category="RecordManager">
<xr:TypeId>UUID-016</xr:TypeId>
<xr:ValueId>UUID-017</xr:ValueId>
</xr:GeneratedType>
</InternalInfo>
<Properties>
<Name>prices</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>prices</v8:content>
</v8:item>
</Synonym>
<Comment/>
<TableType>Table</TableType>
<NameInDataSource>prices</NameInDataSource>
<ExpressionInDataSource/>
<TableDataType>NonobjectData</TableDataType>
<KeyFields/>
<PresentationField/>
<ParentField/>
<UnfilledParentValue xsi:nil="true"/>
<Characteristics/>
<UseStandardCommands>true</UseStandardCommands>
<QuickChoice>false</QuickChoice>
<InputByString/>
<CreateOnInput>Auto</CreateOnInput>
<SearchStringModeOnInputByString>Begin</SearchStringModeOnInputByString>
<ChoiceDataGetModeOnInputByString>Directly</ChoiceDataGetModeOnInputByString>
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
<DefaultObjectForm/>
<DefaultRecordForm/>
<DefaultListForm/>
<DefaultChoiceForm/>
<ObjectPresentation/>
<ExtendedObjectPresentation/>
<RecordPresentation/>
<ExtendedRecordPresentation/>
<ListPresentation/>
<ExtendedListPresentation/>
<Explanation/>
<IncludeHelpInContents>false</IncludeHelpInContents>
<ReadOnly>false</ReadOnly>
<TransactionsIsolationLevel>Auto</TransactionsIsolationLevel>
<DataVersionField/>
<EditType>InDialog</EditType>
<BasedOn/>
<DataLockFields/>
<DataLockControlMode>Automatic</DataLockControlMode>
</Properties>
<ChildObjects>
<Field uuid="UUID-018">
<Properties>
<Name>product_id</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>product_id</v8:content>
</v8:item>
</Synonym>
<Comment/>
<Type>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>10</v8:Digits>
<v8:FractionDigits>0</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
</Type>
<PasswordMode>false</PasswordMode>
<Format/>
<EditFormat/>
<ToolTip/>
<MarkNegatives>false</MarkNegatives>
<Mask/>
<MultiLine>false</MultiLine>
<ExtendedEdit>false</ExtendedEdit>
<MinValue xsi:nil="true"/>
<MaxValue xsi:nil="true"/>
<FillFromFillingValue>false</FillFromFillingValue>
<FillValue xsi:type="xs:decimal">0</FillValue>
<FillChecking>DontCheck</FillChecking>
<ChoiceParameterLinks/>
<ChoiceParameters/>
<QuickChoice>Auto</QuickChoice>
<CreateOnInput>Auto</CreateOnInput>
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
<ChoiceForm/>
<NameInDataSource>product_id</NameInDataSource>
<ReadOnly>false</ReadOnly>
<AllowNull>false</AllowNull>
</Properties>
</Field>
<Field uuid="UUID-019">
<Properties>
<Name>period</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>period</v8:content>
</v8:item>
</Synonym>
<Comment/>
<Type>
<v8:Type>xs:dateTime</v8:Type>
<v8:DateQualifiers>
<v8:DateFractions>Date</v8:DateFractions>
</v8:DateQualifiers>
</Type>
<PasswordMode>false</PasswordMode>
<Format/>
<EditFormat/>
<ToolTip/>
<MarkNegatives>false</MarkNegatives>
<Mask/>
<MultiLine>false</MultiLine>
<ExtendedEdit>false</ExtendedEdit>
<MinValue xsi:nil="true"/>
<MaxValue xsi:nil="true"/>
<FillFromFillingValue>false</FillFromFillingValue>
<FillValue xsi:nil="true"/>
<FillChecking>DontCheck</FillChecking>
<ChoiceParameterLinks/>
<ChoiceParameters/>
<QuickChoice>Auto</QuickChoice>
<CreateOnInput>Auto</CreateOnInput>
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
<ChoiceForm/>
<NameInDataSource>period</NameInDataSource>
<ReadOnly>false</ReadOnly>
<AllowNull>false</AllowNull>
</Properties>
</Field>
<Field uuid="UUID-020">
<Properties>
<Name>price</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>price</v8:content>
</v8:item>
</Synonym>
<Comment/>
<Type>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>15</v8:Digits>
<v8:FractionDigits>2</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
</Type>
<PasswordMode>false</PasswordMode>
<Format/>
<EditFormat/>
<ToolTip/>
<MarkNegatives>false</MarkNegatives>
<Mask/>
<MultiLine>false</MultiLine>
<ExtendedEdit>false</ExtendedEdit>
<MinValue xsi:nil="true"/>
<MaxValue xsi:nil="true"/>
<FillFromFillingValue>false</FillFromFillingValue>
<FillValue xsi:type="xs:decimal">0</FillValue>
<FillChecking>DontCheck</FillChecking>
<ChoiceParameterLinks/>
<ChoiceParameters/>
<QuickChoice>Auto</QuickChoice>
<CreateOnInput>Auto</CreateOnInput>
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
<ChoiceForm/>
<NameInDataSource>price</NameInDataSource>
<ReadOnly>false</ReadOnly>
<AllowNull>false</AllowNull>
</Properties>
</Field>
</ChildObjects>
</Table>
</MetaDataObject>
@@ -0,0 +1,295 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
<Table uuid="UUID-001">
<InternalInfo>
<xr:GeneratedType name="ExternalDataSourceTableManager.PG.products" category="Manager">
<xr:TypeId>UUID-002</xr:TypeId>
<xr:ValueId>UUID-003</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableObject.PG.products" category="Object">
<xr:TypeId>UUID-004</xr:TypeId>
<xr:ValueId>UUID-005</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableRef.PG.products" category="Ref">
<xr:TypeId>UUID-006</xr:TypeId>
<xr:ValueId>UUID-007</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableList.PG.products" category="List">
<xr:TypeId>UUID-008</xr:TypeId>
<xr:ValueId>UUID-009</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableRecord.PG.products" category="Record">
<xr:TypeId>UUID-010</xr:TypeId>
<xr:ValueId>UUID-011</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableRecordSet.PG.products" category="RecordSet">
<xr:TypeId>UUID-012</xr:TypeId>
<xr:ValueId>UUID-013</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableRecordKey.PG.products" category="RecordKey">
<xr:TypeId>UUID-014</xr:TypeId>
<xr:ValueId>UUID-015</xr:ValueId>
</xr:GeneratedType>
<xr:GeneratedType name="ExternalDataSourceTableRecordManager.PG.products" category="RecordManager">
<xr:TypeId>UUID-016</xr:TypeId>
<xr:ValueId>UUID-017</xr:ValueId>
</xr:GeneratedType>
</InternalInfo>
<Properties>
<Name>products</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>products</v8:content>
</v8:item>
</Synonym>
<Comment/>
<TableType>Table</TableType>
<NameInDataSource>eds.public.products</NameInDataSource>
<ExpressionInDataSource/>
<TableDataType>ObjectData</TableDataType>
<KeyFields>
<xr:Field>ExternalDataSource.PG.Table.products.Field.id</xr:Field>
</KeyFields>
<PresentationField>ExternalDataSource.PG.Table.products.Field.name</PresentationField>
<ParentField>ExternalDataSource.PG.Table.products.Field.parent_id</ParentField>
<UnfilledParentValue xsi:type="xs:string"/>
<Characteristics/>
<UseStandardCommands>true</UseStandardCommands>
<QuickChoice>false</QuickChoice>
<InputByString>
<xr:Field>ExternalDataSource.PG.Table.products.Field.name</xr:Field>
</InputByString>
<CreateOnInput>Auto</CreateOnInput>
<SearchStringModeOnInputByString>Begin</SearchStringModeOnInputByString>
<ChoiceDataGetModeOnInputByString>Directly</ChoiceDataGetModeOnInputByString>
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
<DefaultObjectForm/>
<DefaultRecordForm/>
<DefaultListForm/>
<DefaultChoiceForm/>
<ObjectPresentation/>
<ExtendedObjectPresentation/>
<RecordPresentation/>
<ExtendedRecordPresentation/>
<ListPresentation/>
<ExtendedListPresentation/>
<Explanation/>
<IncludeHelpInContents>false</IncludeHelpInContents>
<ReadOnly>false</ReadOnly>
<TransactionsIsolationLevel>ReadUncommitted</TransactionsIsolationLevel>
<DataVersionField>ExternalDataSource.PG.Table.products.Field.row_ver</DataVersionField>
<EditType>InDialog</EditType>
<BasedOn/>
<DataLockFields>
<xr:Field>ExternalDataSource.PG.Table.products.Field.id</xr:Field>
</DataLockFields>
<DataLockControlMode>Automatic</DataLockControlMode>
</Properties>
<ChildObjects>
<Field uuid="UUID-018">
<Properties>
<Name>id</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>id</v8:content>
</v8:item>
</Synonym>
<Comment/>
<Type>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>10</v8:Digits>
<v8:FractionDigits>0</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
</Type>
<PasswordMode>false</PasswordMode>
<Format/>
<EditFormat/>
<ToolTip/>
<MarkNegatives>false</MarkNegatives>
<Mask/>
<MultiLine>false</MultiLine>
<ExtendedEdit>false</ExtendedEdit>
<MinValue xsi:nil="true"/>
<MaxValue xsi:nil="true"/>
<FillFromFillingValue>false</FillFromFillingValue>
<FillValue xsi:type="xs:decimal">0</FillValue>
<FillChecking>DontCheck</FillChecking>
<ChoiceParameterLinks/>
<ChoiceParameters/>
<QuickChoice>Auto</QuickChoice>
<CreateOnInput>Auto</CreateOnInput>
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
<ChoiceForm/>
<NameInDataSource>id</NameInDataSource>
<ReadOnly>false</ReadOnly>
<AllowNull>false</AllowNull>
</Properties>
</Field>
<Field uuid="UUID-019">
<Properties>
<Name>name</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>name</v8:content>
</v8:item>
</Synonym>
<Comment/>
<Type>
<v8:Type>xs:string</v8:Type>
<v8:StringQualifiers>
<v8:Length>150</v8:Length>
<v8:AllowedLength>Variable</v8:AllowedLength>
</v8:StringQualifiers>
</Type>
<PasswordMode>false</PasswordMode>
<Format/>
<EditFormat/>
<ToolTip/>
<MarkNegatives>false</MarkNegatives>
<Mask/>
<MultiLine>false</MultiLine>
<ExtendedEdit>false</ExtendedEdit>
<MinValue xsi:nil="true"/>
<MaxValue xsi:nil="true"/>
<FillFromFillingValue>false</FillFromFillingValue>
<FillValue xsi:type="xs:string"/>
<FillChecking>DontCheck</FillChecking>
<ChoiceParameterLinks/>
<ChoiceParameters/>
<QuickChoice>Auto</QuickChoice>
<CreateOnInput>Auto</CreateOnInput>
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
<ChoiceForm/>
<NameInDataSource>name</NameInDataSource>
<ReadOnly>false</ReadOnly>
<AllowNull>false</AllowNull>
</Properties>
</Field>
<Field uuid="UUID-020">
<Properties>
<Name>article</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>article</v8:content>
</v8:item>
</Synonym>
<Comment/>
<Type>
<v8:Type>xs:string</v8:Type>
<v8:StringQualifiers>
<v8:Length>50</v8:Length>
<v8:AllowedLength>Variable</v8:AllowedLength>
</v8:StringQualifiers>
</Type>
<PasswordMode>false</PasswordMode>
<Format/>
<EditFormat/>
<ToolTip/>
<MarkNegatives>false</MarkNegatives>
<Mask/>
<MultiLine>false</MultiLine>
<ExtendedEdit>false</ExtendedEdit>
<MinValue xsi:nil="true"/>
<MaxValue xsi:nil="true"/>
<FillFromFillingValue>false</FillFromFillingValue>
<FillValue xsi:type="xs:string"/>
<FillChecking>DontCheck</FillChecking>
<ChoiceParameterLinks/>
<ChoiceParameters/>
<QuickChoice>Auto</QuickChoice>
<CreateOnInput>Auto</CreateOnInput>
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
<ChoiceForm/>
<NameInDataSource>article</NameInDataSource>
<ReadOnly>false</ReadOnly>
<AllowNull>true</AllowNull>
</Properties>
</Field>
<Field uuid="UUID-021">
<Properties>
<Name>parent_id</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>parent_id</v8:content>
</v8:item>
</Synonym>
<Comment/>
<Type>
<v8:Type>cfg:ExternalDataSourceTableRef.PG.products</v8:Type>
</Type>
<PasswordMode>false</PasswordMode>
<Format/>
<EditFormat/>
<ToolTip/>
<MarkNegatives>false</MarkNegatives>
<Mask/>
<MultiLine>false</MultiLine>
<ExtendedEdit>false</ExtendedEdit>
<MinValue xsi:nil="true"/>
<MaxValue xsi:nil="true"/>
<FillFromFillingValue>false</FillFromFillingValue>
<FillValue xsi:nil="true"/>
<FillChecking>DontCheck</FillChecking>
<ChoiceParameterLinks/>
<ChoiceParameters/>
<QuickChoice>Auto</QuickChoice>
<CreateOnInput>Auto</CreateOnInput>
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
<ChoiceForm/>
<NameInDataSource>parent_id</NameInDataSource>
<ReadOnly>false</ReadOnly>
<AllowNull>true</AllowNull>
</Properties>
</Field>
<Field uuid="UUID-022">
<Properties>
<Name>row_ver</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>row_ver</v8:content>
</v8:item>
</Synonym>
<Comment/>
<Type>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>19</v8:Digits>
<v8:FractionDigits>0</v8:FractionDigits>
<v8:AllowedSign>Any</v8:AllowedSign>
</v8:NumberQualifiers>
</Type>
<PasswordMode>false</PasswordMode>
<Format/>
<EditFormat/>
<ToolTip/>
<MarkNegatives>false</MarkNegatives>
<Mask/>
<MultiLine>false</MultiLine>
<ExtendedEdit>false</ExtendedEdit>
<MinValue xsi:nil="true"/>
<MaxValue xsi:nil="true"/>
<FillFromFillingValue>false</FillFromFillingValue>
<FillValue xsi:type="xs:decimal">0</FillValue>
<FillChecking>DontCheck</FillChecking>
<ChoiceParameterLinks/>
<ChoiceParameters/>
<QuickChoice>Auto</QuickChoice>
<CreateOnInput>Auto</CreateOnInput>
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
<ChoiceForm/>
<NameInDataSource>row_ver</NameInDataSource>
<ReadOnly>true</ReadOnly>
<AllowNull>false</AllowNull>
</Properties>
</Field>
</ChildObjects>
</Table>
</MetaDataObject>
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
<Language uuid="UUID-001">
<Properties>
<Name>Русский</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Русский</v8:content>
</v8:item>
</Synonym>
<Comment/>
<LanguageCode>ru</LanguageCode>
</Properties>
</Language>
</MetaDataObject>
+3
View File
@@ -83,17 +83,20 @@ const MAPS = [
{ {
skill: 'cfe-borrow', file: 'cfe-borrow', kind: 'gentypes', skill: 'cfe-borrow', file: 'cfe-borrow', kind: 'gentypes',
py: 'GENERATED_TYPES', ps1: '$script:generatedTypes', py: 'GENERATED_TYPES', ps1: '$script:generatedTypes',
exclude: { Table: 'навык не работает с таблицами внешних источников' },
}, },
{ {
skill: 'meta-compile', file: 'meta-compile', kind: 'gentypes', skill: 'meta-compile', file: 'meta-compile', kind: 'gentypes',
py: 'generated_types', ps1: '$script:generatedTypes', py: 'generated_types', ps1: '$script:generatedTypes',
exclude: { exclude: {
IntegrationService: 'навык не создаёт объекты этого вида — генерируемых типов для него нет', IntegrationService: 'навык не создаёт объекты этого вида — генерируемых типов для него нет',
Table: 'InternalInfo таблицы строится инлайном: имя элемента трёхчастное (префикс.Источник.Таблица), карта «вид → набор» такой формы не выражает',
}, },
}, },
{ {
skill: 'cfe-validate', file: 'cfe-validate', kind: 'gencats', skill: 'cfe-validate', file: 'cfe-validate', kind: 'gencats',
py: 'GENERATED_TYPE_CATEGORIES', ps1: '$generatedTypeCategories', py: 'GENERATED_TYPE_CATEGORIES', ps1: '$generatedTypeCategories',
exclude: { Table: 'навык не работает с таблицами внешних источников' },
}, },
{ {
skill: 'meta-validate', file: 'meta-validate', kind: 'gencats', skill: 'meta-validate', file: 'meta-validate', kind: 'gencats',