fix(form-compile): skip ValueStorage attributes in --from-object mode

ValueStorage is a non-displayable type that cannot be bound to form
elements. Filter it out in all generators: catalog item, catalog/document
list columns, document item (unclaimed + footer).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-04-12 19:02:31 +03:00
co-authored by Claude Opus 4.6
parent a41897a966
commit 97a2ef91d5
2 changed files with 28 additions and 3 deletions
@@ -268,6 +268,16 @@ function Load-Preset([string]$PresetName, [string]$ScriptDir) {
} }
# --- Helper: build a field element DSL entry --- # --- Helper: build a field element DSL entry ---
# Non-displayable types — cannot be bound to form elements
$script:nonDisplayableTypes = @('v8:ValueStorage', 'ValueStorage', 'ХранилищеЗначения')
function Test-DisplayableType([string]$typeStr) {
foreach ($nd in $script:nonDisplayableTypes) {
if ($typeStr -match [regex]::Escape($nd)) { return $false }
}
return $true
}
function New-FieldElement { function New-FieldElement {
param([string]$attrName, [string]$dataPath, [string]$attrType, [hashtable]$fieldDefaults, [hashtable]$extraProps) param([string]$attrName, [string]$dataPath, [string]$attrType, [hashtable]$fieldDefaults, [hashtable]$extraProps)
@@ -352,6 +362,7 @@ function Generate-CatalogListDSL($meta, [hashtable]$p) {
} }
# Custom attributes # Custom attributes
foreach ($attr in $meta.Attributes) { foreach ($attr in $meta.Attributes) {
if (-not (Test-DisplayableType $attr.Type)) { continue }
$columns += [ordered]@{ labelField = $attr.Name; path = "Список.$($attr.Name)" } $columns += [ordered]@{ labelField = $attr.Name; path = "Список.$($attr.Name)" }
} }
# Hidden ref # Hidden ref
@@ -467,6 +478,7 @@ function Generate-CatalogItemDSL($meta, [hashtable]$p, [hashtable]$fd) {
foreach ($attr in $meta.Attributes) { foreach ($attr in $meta.Attributes) {
if ($footerFieldNames -contains $attr.Name) { continue } if ($footerFieldNames -contains $attr.Name) { continue }
if (-not (Test-DisplayableType $attr.Type)) { continue }
$headerChildren += (New-FieldElement -attrName $attr.Name -dataPath "Объект.$($attr.Name)" -attrType $attr.Type -fieldDefaults $fd -extraProps @{}) $headerChildren += (New-FieldElement -attrName $attr.Name -dataPath "Объект.$($attr.Name)" -attrType $attr.Type -fieldDefaults $fd -extraProps @{})
} }
@@ -555,6 +567,7 @@ function Generate-DocumentListDSL($meta, [hashtable]$p) {
$columns = @() $columns = @()
# All custom attributes as labelField # All custom attributes as labelField
foreach ($attr in $meta.Attributes) { foreach ($attr in $meta.Attributes) {
if (-not (Test-DisplayableType $attr.Type)) { continue }
$columns += [ordered]@{ labelField = $attr.Name; path = "Список.$($attr.Name)" } $columns += [ordered]@{ labelField = $attr.Name; path = "Список.$($attr.Name)" }
} }
# Hidden ref # Hidden ref
@@ -629,7 +642,7 @@ function Generate-DocumentItemDSL($meta, [hashtable]$p, [hashtable]$fd) {
$unclaimed = @() $unclaimed = @()
foreach ($attr in $meta.Attributes) { foreach ($attr in $meta.Attributes) {
if (-not $claimed.ContainsKey($attr.Name)) { $unclaimed += $attr } if (-not $claimed.ContainsKey($attr.Name) -and (Test-DisplayableType $attr.Type)) { $unclaimed += $attr }
} }
# Distribute unclaimed # Distribute unclaimed
@@ -698,7 +711,7 @@ function Generate-DocumentItemDSL($meta, [hashtable]$p, [hashtable]$fd) {
$footerElements = @() $footerElements = @()
foreach ($fn in $footerFields) { foreach ($fn in $footerFields) {
$fAttr = $meta.Attributes | Where-Object { $_.Name -eq $fn } $fAttr = $meta.Attributes | Where-Object { $_.Name -eq $fn }
if ($fAttr) { if ($fAttr -and (Test-DisplayableType $fAttr.Type)) {
$footerElements += (New-FieldElement -attrName $fAttr.Name -dataPath "Объект.$($fAttr.Name)" -attrType $fAttr.Type -fieldDefaults $fd -extraProps @{}) $footerElements += (New-FieldElement -attrName $fAttr.Name -dataPath "Объект.$($fAttr.Name)" -attrType $fAttr.Type -fieldDefaults $fd -extraProps @{})
} }
} }
@@ -255,6 +255,12 @@ def load_preset(preset_name, script_dir, out_path_resolved):
return defaults return defaults
# Non-displayable types — cannot be bound to form elements
NON_DISPLAYABLE_TYPES = ('ValueStorage', 'v8:ValueStorage', 'ХранилищеЗначения')
def is_displayable_type(type_str):
return not any(nd in type_str for nd in NON_DISPLAYABLE_TYPES)
def new_field_element(attr_name, data_path, attr_type, field_defaults, extra_props=None): def new_field_element(attr_name, data_path, attr_type, field_defaults, extra_props=None):
"""Build a field element DSL entry.""" """Build a field element DSL entry."""
is_ref = bool(re.search(r'Ref\.', attr_type)) is_ref = bool(re.search(r'Ref\.', attr_type))
@@ -339,6 +345,8 @@ def generate_catalog_list_dsl(meta, p):
columns.append(OrderedDict([('labelField', '\u041a\u043e\u0434'), ('path', '\u0421\u043f\u0438\u0441\u043e\u043a.Code')])) columns.append(OrderedDict([('labelField', '\u041a\u043e\u0434'), ('path', '\u0421\u043f\u0438\u0441\u043e\u043a.Code')]))
# Custom attributes # Custom attributes
for attr in meta['Attributes']: for attr in meta['Attributes']:
if not is_displayable_type(attr['Type']):
continue
columns.append(OrderedDict([('labelField', attr['Name']), ('path', f"\u0421\u043f\u0438\u0441\u043e\u043a.{attr['Name']}")])) columns.append(OrderedDict([('labelField', attr['Name']), ('path', f"\u0421\u043f\u0438\u0441\u043e\u043a.{attr['Name']}")]))
# Hidden ref # Hidden ref
if p.get('hiddenRef', True) is not False: if p.get('hiddenRef', True) is not False:
@@ -444,6 +452,8 @@ def generate_catalog_item_dsl(meta, p, fd):
for attr in meta['Attributes']: for attr in meta['Attributes']:
if attr['Name'] in footer_field_names: if attr['Name'] in footer_field_names:
continue continue
if not is_displayable_type(attr['Type']):
continue
header_children.append(new_field_element(attr['Name'], f"\u041e\u0431\u044a\u0435\u043a\u0442.{attr['Name']}", attr['Type'], fd)) header_children.append(new_field_element(attr['Name'], f"\u041e\u0431\u044a\u0435\u043a\u0442.{attr['Name']}", attr['Type'], fd))
# Build root elements # Build root elements
@@ -520,6 +530,8 @@ def generate_document_list_dsl(meta, p):
columns = [] columns = []
# All custom attributes as labelField # All custom attributes as labelField
for attr in meta['Attributes']: for attr in meta['Attributes']:
if not is_displayable_type(attr['Type']):
continue
columns.append(OrderedDict([('labelField', attr['Name']), ('path', f"\u0421\u043f\u0438\u0441\u043e\u043a.{attr['Name']}")])) columns.append(OrderedDict([('labelField', attr['Name']), ('path', f"\u0421\u043f\u0438\u0441\u043e\u043a.{attr['Name']}")]))
# Hidden ref # Hidden ref
if p.get('hiddenRef', True): if p.get('hiddenRef', True):
@@ -596,7 +608,7 @@ def generate_document_item_dsl(meta, p, fd):
for fn in add_right: for fn in add_right:
claimed[fn] = 'additional.right' claimed[fn] = 'additional.right'
unclaimed = [attr for attr in meta['Attributes'] if attr['Name'] not in claimed] unclaimed = [attr for attr in meta['Attributes'] if attr['Name'] not in claimed and is_displayable_type(attr['Type'])]
# Distribute unclaimed # Distribute unclaimed
left_attrs = [] left_attrs = []