diff --git a/.claude/skills/skd-info/SKILL.md b/.claude/skills/skd-info/SKILL.md index 525420ba..98a0f39d 100644 --- a/.claude/skills/skd-info/SKILL.md +++ b/.claude/skills/skd-info/SKILL.md @@ -25,7 +25,7 @@ allowed-tools: |--------------|:------------:|--------------|---------------------------------------------------| | TemplatePath | да | — | Путь к Template.xml или каталогу макета | | Mode | нет | `overview` | Режим: `overview`, `query`, `fields`, `links`, `totals`, `params`, `variant` | -| Name | нет | — | Имя набора (query/fields) или варианта (variant) | +| Name | нет | — | Имя набора (query/fields), поля (totals) или варианта (variant) | | Batch | нет | `0` | Номер пакета запроса (0 = все). Только для query | | Limit | нет | `150` | Макс. строк вывода (защита от переполнения) | | Offset | нет | `0` | Пропустить N строк (для пагинации) | @@ -118,18 +118,25 @@ Params: 18 (7 visible, 11 hidden): Период, Ответственный, ... Фильтр по номеру батча: `-Batch 3` покажет только 3-й пакет. -### fields — таблица полей наборов данных +### fields — поля наборов данных +Без `-Name` — карта: имена полей по наборам: ``` -=== Fields: НоменклатураСЦенами [Query] (7) === +=== Fields map === +СостояниеОС [Query] (3): Организация, ОсновноеСредство, ДатаСостояния +РасчетНалогаНаИмущество [Union] (52): ДоляСтоимостиЧислитель, ... + РасчетНалогаНаИмущество [Query] (51): КадастроваяСтоимость, ... +``` + +С `-Name <набор>` — полная таблица: +``` +=== Fields: СостояниеОС [Query] (3) === dataPath title role restrict format - Номенклатура - - - - - Номенклатура.Артикул "Артикул" - - - - Цена - - - ЧГ=0 + Организация - - - - + ОсновноеСредство Объект - - - + ДатаСостояния Дата ввода в эксплуатацию - - ДФ=dd.MM.yyyy ``` -Без `-Name` — поля всех наборов. С `-Name <набор>` — только указанного. - ### links — связи наборов данных ``` @@ -144,13 +151,32 @@ Params: 18 (7 visible, 11 hidden): Период, Ответственный, ... ### totals — вычисляемые поля и ресурсы +Без `-Name` — карта: имена вычисляемых полей и ресурсов: ``` -=== Calculated fields (3) === - УИД = БухгалтерскиеОтчеты.ПолучитьУИДСсылкиСтрокой(Номенклатура) restrict:cond,grp,ord +=== Calculated fields (23) === + ДоляСтоимости "Доля стоимости" + КоэффициентКи "Коэффициент Ки" + ... -=== Resources (2) === - Цена = Максимум(Цена) - ПравоИнтерактивное = Максимум(ПравоИнтерактивное) [group:ОбъектМетаданных] +=== Resources (51) === + НалоговаяБаза + КоэффициентКи * + ... + * = has group-level formulas +``` + +С `-Name <поле>` — полная формула (если поле есть и в calculated, и в resources — покажет обе части): +``` +=== Calculated: КоэффициентКи === + +Expression: + ВЫБОР КОГДА ... ТОГДА 0 ИНАЧЕ ... КОНЕЦ +Title: Коэффициент Ки +Restrict: condition + +=== Resource: КоэффициентКи === + + [ОсновноеСредство] Сумма(КоэффициентКи) ``` ### params — параметры схемы diff --git a/.claude/skills/skd-info/scripts/skd-info.ps1 b/.claude/skills/skd-info/scripts/skd-info.ps1 index 1836755f..26d855ea 100644 --- a/.claude/skills/skd-info/scripts/skd-info.ps1 +++ b/.claude/skills/skd-info/scripts/skd-info.ps1 @@ -755,21 +755,37 @@ elseif ($Mode -eq "fields") { exit 1 } } else { - # Show all datasets - $first = $true - foreach ($ds in $dataSets) { - if (-not $first) { $lines.Add("") } - $first = $false - Show-DataSetFields $ds + # Compact map: field names per dataset + $lines.Add("=== Fields map ===") + function Show-DataSetFieldMap($dsNode, $indent) { + $dsType = Get-DataSetType $dsNode + $dsNameStr = $dsNode.SelectSingleNode("s:name", $ns).InnerText + $fields = $dsNode.SelectNodes("s:field", $ns) + $fieldNames = @() + foreach ($f in $fields) { + $dp = $f.SelectSingleNode("s:dataPath", $ns) + if ($dp) { $fieldNames += $dp.InnerText } + } + $nameList = $fieldNames -join ", " + if ($nameList.Length -gt 100) { + $nameList = $nameList.Substring(0, 97) + "..." + } + $lines.Add("$indent$dsNameStr [$dsType] ($($fields.Count)): $nameList") + } + + foreach ($ds in $dataSets) { + Show-DataSetFieldMap $ds "" $dsType = Get-DataSetType $ds if ($dsType -eq "Union") { foreach ($subDs in $ds.SelectNodes("s:item", $ns)) { - $lines.Add("") - Show-DataSetFields $subDs + Show-DataSetFieldMap $subDs " " } } } + + $lines.Add("") + $lines.Add("Use -Name for full field table.") } } @@ -814,52 +830,113 @@ elseif ($Mode -eq "links") { # ============================================================ elseif ($Mode -eq "totals") { - # Calculated fields $calcFields = $root.SelectNodes("s:calculatedField", $ns) - if ($calcFields.Count -gt 0) { - $lines.Add("=== Calculated fields ($($calcFields.Count)) ===") + $totalFields = $root.SelectNodes("s:totalField", $ns) + + if ($Name) { + # Detail for specific field + $found = $false + + # Search in calculated fields foreach ($cf in $calcFields) { $cfPath = $cf.SelectSingleNode("s:dataPath", $ns).InnerText - $cfExpr = $cf.SelectSingleNode("s:expression", $ns).InnerText - $cfTitle = $cf.SelectSingleNode("s:title", $ns) - $titleStr = "" - if ($cfTitle) { - $t = Get-MLText $cfTitle - if ($t) { $titleStr = " `"$t`"" } - } + if ($cfPath -eq $Name) { + $lines.Add("=== Calculated: $cfPath ===") + $lines.Add("") - $cfRestrict = $cf.SelectSingleNode("s:useRestriction", $ns) - $restrictStr = "" - if ($cfRestrict) { - $parts = @() - foreach ($child in $cfRestrict.ChildNodes) { - if ($child.NodeType -eq "Element" -and $child.InnerText -eq "true") { - $parts += $child.LocalName.Substring(0, [Math]::Min(4, $child.LocalName.Length)) - } + $cfExpr = $cf.SelectSingleNode("s:expression", $ns).InnerText + $lines.Add("Expression:") + foreach ($el in ($cfExpr -split "`n")) { $lines.Add(" $($el.TrimEnd())") } + + $cfTitle = $cf.SelectSingleNode("s:title", $ns) + if ($cfTitle) { + $t = Get-MLText $cfTitle + if ($t) { $lines.Add("Title: $t") } } - if ($parts.Count -gt 0) { $restrictStr = " restrict:" + ($parts -join ",") } - } - $lines.Add(" $cfPath = $cfExpr$restrictStr$titleStr") - } - $lines.Add("") - } - # Total fields (resources) - $totalFields = $root.SelectNodes("s:totalField", $ns) - if ($totalFields.Count -gt 0) { - $lines.Add("=== Resources ($($totalFields.Count)) ===") + $cfRestrict = $cf.SelectSingleNode("s:useRestriction", $ns) + if ($cfRestrict) { + $parts = @() + foreach ($child in $cfRestrict.ChildNodes) { + if ($child.NodeType -eq "Element" -and $child.InnerText -eq "true") { + $parts += $child.LocalName + } + } + if ($parts.Count -gt 0) { $lines.Add("Restrict: $($parts -join ', ')") } + } + + $found = $true + break + } + } + + # Search in resources (also show if already found in calculated — field can be both) + $matchedResources = @() foreach ($tf in $totalFields) { $tfPath = $tf.SelectSingleNode("s:dataPath", $ns).InnerText - $tfExpr = $tf.SelectSingleNode("s:expression", $ns).InnerText - $tfGroup = $tf.SelectSingleNode("s:group", $ns) - $groupStr = "" - if ($tfGroup) { $groupStr = " [group:$($tfGroup.InnerText)]" } - $lines.Add(" $tfPath = $tfExpr$groupStr") + if ($tfPath -eq $Name) { $matchedResources += $tf } + } + if ($matchedResources.Count -gt 0) { + if ($found) { $lines.Add("") } + $lines.Add("=== Resource: $Name ===") + $lines.Add("") + foreach ($tf in $matchedResources) { + $tfExpr = $tf.SelectSingleNode("s:expression", $ns).InnerText + $tfGroup = $tf.SelectSingleNode("s:group", $ns) + $groupStr = "(overall)" + if ($tfGroup) { $groupStr = $tfGroup.InnerText } + $lines.Add(" [$groupStr] $tfExpr") + } + $found = $true } - } - if ($calcFields.Count -eq 0 -and $totalFields.Count -eq 0) { - $lines.Add("(no calculated fields or resources)") + if (-not $found) { + Write-Error "Field '$Name' not found in calculated fields or resources" + exit 1 + } + } else { + # Compact map + if ($calcFields.Count -gt 0) { + $lines.Add("=== Calculated fields ($($calcFields.Count)) ===") + foreach ($cf in $calcFields) { + $cfPath = $cf.SelectSingleNode("s:dataPath", $ns).InnerText + $cfTitle = $cf.SelectSingleNode("s:title", $ns) + $titleStr = "" + if ($cfTitle) { + $t = Get-MLText $cfTitle + if ($t -and $t -ne $cfPath) { $titleStr = " `"$t`"" } + } + $lines.Add(" $cfPath$titleStr") + } + $lines.Add("") + } + + if ($totalFields.Count -gt 0) { + $lines.Add("=== Resources ($($totalFields.Count)) ===") + # Collect unique field names with group info + $resMap = [ordered]@{} + foreach ($tf in $totalFields) { + $tfPath = $tf.SelectSingleNode("s:dataPath", $ns).InnerText + $tfGroup = $tf.SelectSingleNode("s:group", $ns) + if (-not $resMap.Contains($tfPath)) { + $resMap[$tfPath] = @{ hasGroup = $false } + } + if ($tfGroup) { $resMap[$tfPath].hasGroup = $true } + } + foreach ($key in $resMap.Keys) { + $groupMark = if ($resMap[$key].hasGroup) { " *" } else { "" } + $lines.Add(" $key$groupMark") + } + $lines.Add("") + $lines.Add(" * = has group-level formulas") + } + + if ($calcFields.Count -eq 0 -and $totalFields.Count -eq 0) { + $lines.Add("(no calculated fields or resources)") + } else { + $lines.Add("") + $lines.Add("Use -Name for full expression.") + } } }