diff --git a/.claude/skills/skd-compile/scripts/skd-compile.ps1 b/.claude/skills/skd-compile/scripts/skd-compile.ps1 index ed5824f6..a23ac423 100644 --- a/.claude/skills/skd-compile/scripts/skd-compile.ps1 +++ b/.claude/skills/skd-compile/scripts/skd-compile.ps1 @@ -886,6 +886,33 @@ function Emit-SingleParam { X "`t`ttrue" } + # AvailableValues + if ($p -isnot [string] -and $p.availableValues) { + foreach ($av in $p.availableValues) { + $avVal = "$($av.value)" + $avType = "xs:string" + if ($avVal -match '^(Перечисление|Справочник|ПланСчетов|Документ|ПланВидовХарактеристик|ПланВидовРасчета)\.') { + $avType = "dcscor:DesignTimeValue" + } + X "`t`t" + X "`t`t`t$(Esc-Xml $avVal)" + if ($av.presentation) { + X "`t`t`t" + X "`t`t`t`t" + X "`t`t`t`t`tru" + X "`t`t`t`t`t$(Esc-Xml "$($av.presentation)")" + X "`t`t`t`t" + X "`t`t`t" + } + X "`t`t" + } + } + + # DenyIncompleteValues + if ($p -isnot [string] -and $p.denyIncompleteValues -eq $true) { + X "`t`ttrue" + } + # Use if ($p -isnot [string] -and $p.use) { X "`t`t$(Esc-Xml "$($p.use)")" diff --git a/.claude/skills/skd-compile/scripts/skd-compile.py b/.claude/skills/skd-compile/scripts/skd-compile.py index 624ee429..cf7e3441 100644 --- a/.claude/skills/skd-compile/scripts/skd-compile.py +++ b/.claude/skills/skd-compile/scripts/skd-compile.py @@ -754,6 +754,28 @@ def emit_single_param(lines, p, parsed): if parsed.get('valueListAllowed'): lines.append('\t\ttrue') + # AvailableValues + if p is not None and not isinstance(p, str) and p.get('availableValues'): + for av in p['availableValues']: + av_val = str(av.get('value', '')) + av_type = 'xs:string' + if re.match(r'^(Перечисление|Справочник|ПланСчетов|Документ|ПланВидовХарактеристик|ПланВидовРасчета)\.', av_val): + av_type = 'dcscor:DesignTimeValue' + lines.append('\t\t') + lines.append(f'\t\t\t{esc_xml(av_val)}') + if av.get('presentation'): + lines.append('\t\t\t') + lines.append('\t\t\t\t') + lines.append('\t\t\t\t\tru') + lines.append(f'\t\t\t\t\t{esc_xml(str(av["presentation"]))}') + lines.append('\t\t\t\t') + lines.append('\t\t\t') + lines.append('\t\t') + + # DenyIncompleteValues + if p is not None and not isinstance(p, str) and p.get('denyIncompleteValues') is True: + lines.append('\t\ttrue') + # Use if p is not None and not isinstance(p, str) and p.get('use'): lines.append(f'\t\t{esc_xml(str(p["use"]))}') diff --git a/.claude/skills/skd-edit/scripts/skd-edit.ps1 b/.claude/skills/skd-edit/scripts/skd-edit.ps1 index 1c5beb19..abc9c1ca 100644 --- a/.claude/skills/skd-edit/scripts/skd-edit.ps1 +++ b/.claude/skills/skd-edit/scripts/skd-edit.ps1 @@ -10,7 +10,7 @@ param( "add-dataParameter","add-order","add-selection","add-dataSetLink", "add-dataSet","add-variant","add-conditionalAppearance", "set-query","patch-query","set-outputParameter","set-structure", - "modify-field","modify-filter","modify-dataParameter", + "modify-field","modify-filter","modify-dataParameter","modify-parameter", "clear-selection","clear-order","clear-filter", "remove-field","remove-total","remove-calculated-field","remove-parameter","remove-filter")] [string]$Operation, @@ -1655,6 +1655,109 @@ switch ($Operation) { } } + "modify-parameter" { + foreach ($val in $values) { + # Parse: "ParamName key=value key=value" + $parts = $val -split '\s+', 2 + $paramName = $parts[0].Trim() + $rest = if ($parts.Count -gt 1) { $parts[1].Trim() } else { "" } + + # Find parameter element + $paramEl = Find-ElementByChildValue $xmlDoc.DocumentElement "parameter" "name" $paramName $schNs + if (-not $paramEl) { + Write-Host "[WARN] Parameter `"$paramName`" not found — skipped" + continue + } + + $childIndent = Get-ChildIndent $paramEl + + # Parse key=value pairs (special handling for availableValue) + if ($rest -match '^availableValue=(.+)') { + $avRest = $rest -replace '^availableValue=', '' + # Parse: "Перечисление...X presentation=текст" + $avParts = $avRest -split '\s+presentation=', 2 + $avValue = $avParts[0].Trim() + $avPresentation = if ($avParts.Count -gt 1) { $avParts[1].Trim() } else { "" } + + # Detect value type + $avType = "xs:string" + if ($avValue -match '^(Перечисление|Справочник|ПланСчетов|Документ|ПланВидовХарактеристик|ПланВидовРасчета)\.') { + $avType = "dcscor:DesignTimeValue" + } + + $avLines = @() + $avLines += "$childIndent" + $avLines += "$childIndent`t$(Esc-Xml $avValue)" + if ($avPresentation) { + $avLines += "$childIndent`t" + $avLines += "$childIndent`t`t" + $avLines += "$childIndent`t`t`tru" + $avLines += "$childIndent`t`t`t$(Esc-Xml $avPresentation)" + $avLines += "$childIndent`t`t" + $avLines += "$childIndent`t" + } + $avLines += "$childIndent" + $fragXml = $avLines -join "`r`n" + + # Insert before denyIncompleteValues/use or at end + $refNode = $null + foreach ($tag in @("denyIncompleteValues","use")) { + $found = $paramEl.SelectSingleNode($tag) + if ($found) { $refNode = $found; break } + } + $nodes = Import-Fragment $xmlDoc $fragXml + foreach ($node in $nodes) { + Insert-BeforeElement $paramEl $node $refNode $childIndent + } + Write-Host "[OK] Parameter `"$paramName`": availableValue added" + } else { + # Simple key=value pairs: use=Always, denyIncompleteValues=true + $kvPairs = [regex]::Matches($rest, '(\w+)=(\S+)') + foreach ($kv in $kvPairs) { + $key = $kv.Groups[1].Value + $value = $kv.Groups[2].Value + + $existing = $paramEl.SelectSingleNode($key) + if ($existing) { + $existing.InnerText = $value + Write-Host "[OK] Parameter `"$paramName`": $key updated to $value" + } else { + # Determine insertion order + $afterTags = switch ($key) { + "denyIncompleteValues" { @("availableValue","useRestriction","availableAsField","expression","value","valueType","title","name") } + "use" { @("denyIncompleteValues","availableValue","useRestriction","availableAsField","expression","value","valueType","title","name") } + default { @("name") } + } + $refNode = $null + foreach ($tag in @("denyIncompleteValues","use")) { + if ($tag -eq $key) { continue } + $found = $paramEl.SelectSingleNode($tag) + if ($found -and ($afterTags -contains $tag -eq $false)) { + $refNode = $found; break + } + } + + $fragXml = "$childIndent<$key>$(Esc-Xml $value)" + $nodes = Import-Fragment $xmlDoc $fragXml + foreach ($node in $nodes) { + # Append before closing tag (last whitespace child) + $lastChild = $paramEl.LastChild + if ($lastChild.NodeType -eq 'Whitespace' -or $lastChild.NodeType -eq 'SignificantWhitespace') { + $paramEl.InsertBefore($node, $lastChild) | Out-Null + } else { + $paramEl.AppendChild($node) | Out-Null + } + } + # Add trailing whitespace + $ws = $xmlDoc.CreateWhitespace("`r`n$($childIndent -replace '`t$','')") + $paramEl.AppendChild($ws) | Out-Null + Write-Host "[OK] Parameter `"$paramName`": $key=$value added" + } + } + } + } + } + "add-filter" { $settings = Resolve-VariantSettings $varName = Get-VariantName diff --git a/.claude/skills/skd-edit/scripts/skd-edit.py b/.claude/skills/skd-edit/scripts/skd-edit.py index 2c596f3e..27123fac 100644 --- a/.claude/skills/skd-edit/scripts/skd-edit.py +++ b/.claude/skills/skd-edit/scripts/skd-edit.py @@ -18,7 +18,7 @@ VALID_OPS = [ "add-dataParameter", "add-order", "add-selection", "add-dataSetLink", "add-dataSet", "add-variant", "add-conditionalAppearance", "set-query", "patch-query", "set-outputParameter", "set-structure", - "modify-field", "modify-filter", "modify-dataParameter", + "modify-field", "modify-filter", "modify-dataParameter", "modify-parameter", "clear-selection", "clear-order", "clear-filter", "remove-field", "remove-total", "remove-calculated-field", "remove-parameter", "remove-filter", ] @@ -1435,6 +1435,68 @@ elif operation == "add-parameter": if parsed.get("autoDates"): print('[OK] Auto-parameters "\u0414\u0430\u0442\u0430\u041d\u0430\u0447\u0430\u043b\u0430", "\u0414\u0430\u0442\u0430\u041e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f" added') +elif operation == "modify-parameter": + for val in values: + parts = val.split(None, 1) + param_name = parts[0].strip() + rest = parts[1].strip() if len(parts) > 1 else "" + + param_el = find_element_by_child_value(xml_doc, "parameter", "name", param_name, SCH_NS) + if param_el is None: + print(f'[WARN] Parameter "{param_name}" not found -- skipped') + continue + + child_indent = get_child_indent(param_el) + + if rest.startswith("availableValue="): + av_rest = rest[len("availableValue="):] + av_parts = av_rest.split(" presentation=", 1) + av_value = av_parts[0].strip() + av_presentation = av_parts[1].strip() if len(av_parts) > 1 else "" + + av_type = "xs:string" + if re.match(r'^(Перечисление|Справочник|ПланСчетов|Документ|ПланВидовХарактеристик|ПланВидовРасчета)\.', av_value): + av_type = "dcscor:DesignTimeValue" + + av_lines = [f"{child_indent}"] + av_lines.append(f'{child_indent}\t{esc_xml(av_value)}') + if av_presentation: + av_lines.append(f'{child_indent}\t') + av_lines.append(f"{child_indent}\t\t") + av_lines.append(f"{child_indent}\t\t\tru") + av_lines.append(f"{child_indent}\t\t\t{esc_xml(av_presentation)}") + av_lines.append(f"{child_indent}\t\t") + av_lines.append(f"{child_indent}\t") + av_lines.append(f"{child_indent}") + frag_xml = "\r\n".join(av_lines) + + ref_node = None + for tag in ["denyIncompleteValues", "use"]: + found = param_el.find(tag) + if found is not None: + ref_node = found + break + nodes = import_fragment(xml_doc, frag_xml) + for node in nodes: + insert_before_element(param_el, node, ref_node, child_indent) + print(f'[OK] Parameter "{param_name}": availableValue added') + else: + for m in re.finditer(r'(\w+)=(\S+)', rest): + key, value = m.group(1), m.group(2) + existing = param_el.find(key) + if existing is not None: + existing.text = value + print(f'[OK] Parameter "{param_name}": {key} updated to {value}') + else: + frag_xml = f"{child_indent}<{key}>{esc_xml(value)}" + nodes = import_fragment(xml_doc, frag_xml) + for node in nodes: + last_child = list(param_el)[-1] if len(param_el) else None + if last_child is not None: + last_child.tail = (last_child.tail or "") + "\r\n" + child_indent + param_el.append(node) + print(f'[OK] Parameter "{param_name}": {key}={value} added') + elif operation == "add-filter": settings = resolve_variant_settings() var_name = get_variant_name()