mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-09-08 19:20:52 +03:00
feat(meta-validate): проверка ссылок на поля таблицы внешнего источника
Свойства таблицы ссылаются на её же поля шестичастным путём (ExternalDataSource.И.Table.Т.Field.П). Опечатка в имени поля даёт «Неизвестный объект метаданных» при загрузке, а глазами в таком пути её не видно. Проверка 21 разбирает форму пути, требует, чтобы таблица в ссылке была той же самой, и чтобы поле существовало — в сообщении перечисляются имеющиеся поля. Отдельно: таблица без ключевых полей даёт предупреждение, а не ошибку. Загрузку XML такой таблицы платформа принимает молча (измерено на 8.3.24.1691), Конфигуратор интерактивно требует ключ, а рабочие конфигурации без ключей существуют — значит это повод предупредить, а не отвергнуть. Закрыты последние пункты плана: раздел про внешние источники в docs/meta-dsl-spec.md (формой и связями с общими конвенциями, без дублирования таблицы свойств — она живёт в reference навыка) и кейсы meta-validate, включая негативный. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NBsZA5cr2WFThtgp7i5WVi
This commit is contained in:
co-authored by
Claude Opus 5
parent
24cfe6a0a6
commit
89ce1af9fa
@@ -1,4 +1,4 @@
|
||||
# meta-validate v1.26 — Validate 1C metadata object structure
|
||||
# meta-validate v1.27 — Validate 1C metadata object structure
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
[CmdletBinding(PositionalBinding=$false)]
|
||||
param(
|
||||
@@ -1836,6 +1836,60 @@ if (-not $isAdopted) {
|
||||
}
|
||||
}
|
||||
|
||||
# --- Check 21: таблица внешнего источника — ссылки на поля и наличие ключа ---
|
||||
# Свойства таблицы ссылаются на её же поля полным путём. Опечатка в имени поля даёт
|
||||
# «Неизвестный объект метаданных» при загрузке, а найти её глазами в шестичастном пути трудно.
|
||||
if ($mdType -eq "Table") {
|
||||
$fieldNames = @{}
|
||||
if ($childObjNode) {
|
||||
foreach ($f in $childObjNode.SelectNodes("md:Field/md:Properties/md:Name", $ns)) {
|
||||
$fieldNames[$f.InnerText] = $true
|
||||
}
|
||||
}
|
||||
$edsRefsChecked = 0
|
||||
$edsRefsBad = $false
|
||||
foreach ($spec in @(
|
||||
@("KeyFields", "xr:Field"), @("InputByString", "xr:Field"), @("DataLockFields", "xr:Field"),
|
||||
@("PresentationField", $null), @("ParentField", $null), @("DataVersionField", $null))) {
|
||||
$tag = $spec[0]
|
||||
$refs = @()
|
||||
if ($spec[1]) {
|
||||
foreach ($n in $propsNode.SelectNodes("md:$tag/$($spec[1])", $ns)) { $refs += $n.InnerText }
|
||||
} else {
|
||||
$n = $propsNode.SelectSingleNode("md:$tag", $ns)
|
||||
if ($n -and $n.InnerText) { $refs += $n.InnerText }
|
||||
}
|
||||
foreach ($ref in $refs) {
|
||||
$edsRefsChecked++
|
||||
$parts = $ref -split '\.'
|
||||
# Ожидается ExternalDataSource.<Источник>.Table.<Таблица>.Field.<Поле>
|
||||
if ($parts.Count -ne 6 -or $parts[0] -ne "ExternalDataSource" -or $parts[2] -ne "Table" -or $parts[4] -ne "Field") {
|
||||
Report-Error "21. $tag '$ref' — ожидается ExternalDataSource.<Источник>.Table.<Таблица>.Field.<Поле>"
|
||||
$edsRefsBad = $true
|
||||
continue
|
||||
}
|
||||
if ($parts[3] -ne $objName) {
|
||||
Report-Error "21. $tag '$ref' — ссылка на поле ЧУЖОЙ таблицы (эта: $objName)"
|
||||
$edsRefsBad = $true
|
||||
continue
|
||||
}
|
||||
if (-not $fieldNames.ContainsKey($parts[5])) {
|
||||
$known = if ($fieldNames.Count -gt 0) { ($fieldNames.Keys | Sort-Object) -join ", " } else { "полей нет" }
|
||||
Report-Error "21. $tag '$ref' — поля '$($parts[5])' нет в таблице (есть: $known)"
|
||||
$edsRefsBad = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($edsRefsChecked -gt 0 -and -not $edsRefsBad) { Report-OK "21. Field refs: $edsRefsChecked resolved" }
|
||||
|
||||
# Ключ: загрузка XML таблицу без ключа принимает (проверено на платформе), а Конфигуратор
|
||||
# интерактивно требует. Отсюда предупреждение, а не ошибка: рабочие конфигурации без ключа есть.
|
||||
$keyNodes = @($propsNode.SelectNodes("md:KeyFields/xr:Field", $ns))
|
||||
if ($keyNodes.Count -eq 0) {
|
||||
Report-Warn "21. KeyFields пуст — платформа такую таблицу загрузит, но форма записи и набор записей будут недоступны"
|
||||
}
|
||||
}
|
||||
|
||||
# --- Final output ---
|
||||
|
||||
& $finalize
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# meta-validate v1.26 — Validate 1C metadata object structure (Python port)
|
||||
# meta-validate v1.27 — Validate 1C metadata object structure (Python port)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import os
|
||||
@@ -1778,6 +1778,48 @@ if not is_adopted:
|
||||
if form_refs_checked > 0 and not form_ref_bad:
|
||||
report_ok(f"20. Form refs: {form_refs_checked} resolved")
|
||||
|
||||
# ── Check 21: таблица внешнего источника — ссылки на поля и наличие ключа ──
|
||||
# Свойства таблицы ссылаются на её же поля полным путём. Опечатка в имени поля даёт
|
||||
# «Неизвестный объект метаданных» при загрузке, а найти её глазами в шестичастном пути трудно.
|
||||
if md_type == "Table":
|
||||
field_names = set()
|
||||
if child_obj_node is not None:
|
||||
for f in find_all(child_obj_node, "md:Field/md:Properties/md:Name"):
|
||||
field_names.add(inner_text(f))
|
||||
eds_refs_checked = 0
|
||||
eds_refs_bad = False
|
||||
for tag, is_list in (("KeyFields", True), ("InputByString", True), ("DataLockFields", True),
|
||||
("PresentationField", False), ("ParentField", False), ("DataVersionField", False)):
|
||||
if is_list:
|
||||
refs = [inner_text(n) for n in find_all(props_node, f"md:{tag}/xr:Field")]
|
||||
else:
|
||||
n = find(props_node, f"md:{tag}")
|
||||
refs = [inner_text(n)] if n is not None and inner_text(n) else []
|
||||
for ref in refs:
|
||||
eds_refs_checked += 1
|
||||
parts = ref.split(".")
|
||||
# Ожидается ExternalDataSource.<Источник>.Table.<Таблица>.Field.<Поле>
|
||||
if len(parts) != 6 or parts[0] != "ExternalDataSource" or parts[2] != "Table" or parts[4] != "Field":
|
||||
report_error(f"21. {tag} '{ref}' — ожидается ExternalDataSource.<Источник>.Table.<Таблица>.Field.<Поле>")
|
||||
eds_refs_bad = True
|
||||
continue
|
||||
if parts[3] != obj_name:
|
||||
report_error(f"21. {tag} '{ref}' — ссылка на поле ЧУЖОЙ таблицы (эта: {obj_name})")
|
||||
eds_refs_bad = True
|
||||
continue
|
||||
if parts[5] not in field_names:
|
||||
known = ", ".join(sorted(field_names)) if field_names else "полей нет"
|
||||
report_error(f"21. {tag} '{ref}' — поля '{parts[5]}' нет в таблице (есть: {known})")
|
||||
eds_refs_bad = True
|
||||
if eds_refs_checked > 0 and not eds_refs_bad:
|
||||
report_ok(f"21. Field refs: {eds_refs_checked} resolved")
|
||||
|
||||
# Ключ: загрузка XML таблицу без ключа принимает (проверено на платформе), а Конфигуратор
|
||||
# интерактивно требует. Отсюда предупреждение, а не ошибка: рабочие конфигурации без ключа есть.
|
||||
if not find_all(props_node, "md:KeyFields/xr:Field"):
|
||||
report_warn("21. KeyFields пуст — платформа такую таблицу загрузит, но форма записи и набор записей будут недоступны")
|
||||
|
||||
|
||||
# ── Final output ──────────────────────────────────────────────
|
||||
|
||||
finalize()
|
||||
|
||||
Reference in New Issue
Block a user