Split totals into calculated and resources modes

Each concept now has its own mode with clear naming that matches
the overview labels. Overview now shows "Resources:" instead of
"Totals:" for consistency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-02-10 18:40:50 +03:00
parent 21dded4d1c
commit f211ffa2f0
2 changed files with 103 additions and 90 deletions
+30 -18
View File
@@ -1,7 +1,7 @@
--- ---
name: skd-info name: skd-info
description: Анализ структуры схемы компоновки данных 1С (СКД) — наборы, поля, параметры, варианты description: Анализ структуры схемы компоновки данных 1С (СКД) — наборы, поля, параметры, варианты
argument-hint: <TemplatePath> [-Mode overview|query|fields|links|totals|params|variant|trace] [-Name <dataset|variant|field>] argument-hint: <TemplatePath> [-Mode overview|query|fields|links|calculated|resources|params|variant|trace] [-Name <dataset|variant|field>]
allowed-tools: allowed-tools:
- Bash - Bash
- Read - Read
@@ -44,8 +44,10 @@ powershell.exe -NoProfile -File .claude\skills\skd-info\scripts\skd-info.ps1 -Te
... -Mode fields ... -Mode fields
... -Mode fields -Name НаборДанных1 ... -Mode fields -Name НаборДанных1
... -Mode links ... -Mode links
... -Mode totals ... -Mode calculated
... -Mode totals -Name СуммаНалога ... -Mode calculated -Name КоэффициентКи
... -Mode resources
... -Mode resources -Name СуммаНалога
... -Mode params ... -Mode params
... -Mode trace -Name КоэффициентКи ... -Mode trace -Name КоэффициентКи
... -Mode trace -Name "Коэффициент Ки" ... -Mode trace -Name "Коэффициент Ки"
@@ -73,7 +75,7 @@ Sources: ИсточникДанных1 (Local)
Datasets: Datasets:
[Query] НоменклатураСЦенами 7 fields, query 40 lines [Query] НоменклатураСЦенами 7 fields, query 40 lines
Calculated: 1 Calculated: 1
Totals: 1 Resources: 1
Templates: 1 templates, 1 group bindings Templates: 1 templates, 1 group bindings
Params: (none) Params: (none)
@@ -84,7 +86,8 @@ Variants:
Next: Next:
-Mode query query text -Mode query query text
-Mode fields field tables by dataset -Mode fields field tables by dataset
-Mode totals calculated fields + resources -Mode calculated calculated field expressions
-Mode resources resource aggregation
-Mode variant -Name <N> variant structure (1..2) -Mode variant -Name <N> variant structure (1..2)
``` ```
@@ -152,15 +155,30 @@ Params: 18 (7 visible, 11 hidden): Период, Ответственный, ...
Группирует по парам наборов. Показывает поля связи и параметры. Группирует по парам наборов. Показывает поля связи и параметры.
### totals — вычисляемые поля и ресурсы ### calculated — вычисляемые поля
Без `-Name` — карта: имена вычисляемых полей и ресурсов: Без `-Name` — карта: имена и заголовки:
``` ```
=== Calculated fields (23) === === Calculated fields (23) ===
ДоляСтоимости "Доля стоимости" ДоляСтоимости "Доля стоимости"
КоэффициентКи "Коэффициент Ки" КоэффициентКи "Коэффициент Ки"
... ...
```
С `-Name <поле>` — полное выражение:
```
=== Calculated: ДоляСтоимости ===
Expression:
ВЫБОР КОГДА ... ТОГДА "1" ИНАЧЕ ... КОНЕЦ
Title: Доля стоимости
Restrict: condition
```
### resources — ресурсы (итоги по группировкам)
Без `-Name` — карта: имена полей, `*` = есть формулы по группировкам:
```
=== Resources (51) === === Resources (51) ===
НалоговаяБаза НалоговаяБаза
КоэффициентКи * КоэффициентКи *
@@ -168,18 +186,11 @@ Params: 18 (7 visible, 11 hidden): Период, Ответственный, ...
* = has group-level formulas * = has group-level formulas
``` ```
С `-Name <поле>`полная формула (если поле есть и в calculated, и в resources — покажет обе части): С `-Name <поле>`формулы агрегации:
``` ```
=== Calculated: КоэффициентКи === === Resource: ДатаСостояния ===
Expression: [ОсновноеСредство] ЕстьNull(ДатаСостояния, "")
ВЫБОР КОГДА ... ТОГДА 0 ИНАЧЕ ... КОНЕЦ
Title: Коэффициент Ки
Restrict: condition
=== Resource: КоэффициентКи ===
[ОсновноеСредство] Сумма(КоэффициентКи)
``` ```
### params — параметры схемы ### params — параметры схемы
@@ -253,7 +264,8 @@ Resource:
- **Отладка данных**: query для просмотра текста запроса - **Отладка данных**: query для просмотра текста запроса
- **Модификация полей**: fields для списка с ролями по наборам - **Модификация полей**: fields для списка с ролями по наборам
- **Связи между наборами**: links для полей связи и параметров - **Связи между наборами**: links для полей связи и параметров
- **Формулы и ресурсы**: totals для вычисляемых полей и ресурсов - **Вычисляемые поля**: calculated для выражений вычисляемых полей
- **Ресурсы**: resources для формул агрегации по группировкам
- **Программный вызов**: params для списка параметров - **Программный вызов**: params для списка параметров
- **Изменение вывода**: variant для структуры группировок и фильтров - **Изменение вывода**: variant для структуры группировок и фильтров
- **Как считается колонка?**: trace для полной цепочки от заголовка до запроса - **Как считается колонка?**: trace для полной цепочки от заголовка до запроса
+73 -72
View File
@@ -1,7 +1,7 @@
param( param(
[Parameter(Mandatory=$true)] [Parameter(Mandatory=$true)]
[string]$TemplatePath, [string]$TemplatePath,
[ValidateSet("overview", "query", "fields", "links", "totals", "params", "variant", "trace")] [ValidateSet("overview", "query", "fields", "links", "calculated", "resources", "params", "variant", "trace")]
[string]$Mode = "overview", [string]$Mode = "overview",
[string]$Name, [string]$Name,
[int]$Batch = 0, [int]$Batch = 0,
@@ -385,9 +385,9 @@ if ($Mode -eq "overview") {
} }
$groupNote = if ($hasGrouped) { ", with group formulas" } else { "" } $groupNote = if ($hasGrouped) { ", with group formulas" } else { "" }
if ($uniquePaths.Count -eq $totalFields.Count) { if ($uniquePaths.Count -eq $totalFields.Count) {
$lines.Add("Totals: $($totalFields.Count)$groupNote") $lines.Add("Resources: $($totalFields.Count)$groupNote")
} else { } else {
$lines.Add("Totals: $($totalFields.Count) ($($uniquePaths.Count) fields$groupNote)") $lines.Add("Resources: $($totalFields.Count) ($($uniquePaths.Count) fields$groupNote)")
} }
} }
@@ -505,8 +505,11 @@ if ($Mode -eq "overview") {
} }
$calcCount = $root.SelectNodes("s:calculatedField", $ns).Count $calcCount = $root.SelectNodes("s:calculatedField", $ns).Count
$totalCount = $root.SelectNodes("s:totalField", $ns).Count $totalCount = $root.SelectNodes("s:totalField", $ns).Count
if ($calcCount -gt 0 -or $totalCount -gt 0) { if ($calcCount -gt 0) {
$hints += "-Mode totals calculated fields + resources" $hints += "-Mode calculated calculated field expressions ($calcCount)"
}
if ($totalCount -gt 0) {
$hints += "-Mode resources resource aggregation ($totalCount)"
} }
if ($params.Count -gt 0) { if ($params.Count -gt 0) {
$hints += "-Mode params parameter details" $hints += "-Mode params parameter details"
@@ -827,18 +830,15 @@ elseif ($Mode -eq "links") {
} }
# ============================================================ # ============================================================
# MODE: totals # MODE: calculated
# ============================================================ # ============================================================
elseif ($Mode -eq "totals") { elseif ($Mode -eq "calculated") {
$calcFields = $root.SelectNodes("s:calculatedField", $ns) $calcFields = $root.SelectNodes("s:calculatedField", $ns)
$totalFields = $root.SelectNodes("s:totalField", $ns) if ($calcFields.Count -eq 0) {
$lines.Add("(no calculated fields)")
if ($Name) { } elseif ($Name) {
# Detail for specific field
$found = $false $found = $false
# Search in calculated fields
foreach ($cf in $calcFields) { foreach ($cf in $calcFields) {
$cfPath = $cf.SelectSingleNode("s:dataPath", $ns).InnerText $cfPath = $cf.SelectSingleNode("s:dataPath", $ns).InnerText
if ($cfPath -eq $Name) { if ($cfPath -eq $Name) {
@@ -870,74 +870,75 @@ elseif ($Mode -eq "totals") {
break 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
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 (-not $found) { if (-not $found) {
Write-Error "Field '$Name' not found in calculated fields or resources" Write-Error "Calculated field '$Name' not found"
exit 1 exit 1
} }
} else { } else {
# Compact map # Map
if ($calcFields.Count -gt 0) { $lines.Add("=== Calculated fields ($($calcFields.Count)) ===")
$lines.Add("=== Calculated fields ($($calcFields.Count)) ===") foreach ($cf in $calcFields) {
foreach ($cf in $calcFields) { $cfPath = $cf.SelectSingleNode("s:dataPath", $ns).InnerText
$cfPath = $cf.SelectSingleNode("s:dataPath", $ns).InnerText $cfTitle = $cf.SelectSingleNode("s:title", $ns)
$cfTitle = $cf.SelectSingleNode("s:title", $ns) $titleStr = ""
$titleStr = "" if ($cfTitle) {
if ($cfTitle) { $t = Get-MLText $cfTitle
$t = Get-MLText $cfTitle if ($t -and $t -ne $cfPath) { $titleStr = " `"$t`"" }
if ($t -and $t -ne $cfPath) { $titleStr = " `"$t`"" }
}
$lines.Add(" $cfPath$titleStr")
} }
$lines.Add("") $lines.Add(" $cfPath$titleStr")
} }
$lines.Add("")
$lines.Add("Use -Name <field> for full expression.")
}
}
if ($totalFields.Count -gt 0) { # ============================================================
$lines.Add("=== Resources ($($totalFields.Count)) ===") # MODE: resources
# Collect unique field names with group info # ============================================================
$resMap = [ordered]@{} elseif ($Mode -eq "resources") {
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) { $totalFields = $root.SelectNodes("s:totalField", $ns)
$lines.Add("(no calculated fields or resources)") if ($totalFields.Count -eq 0) {
} else { $lines.Add("(no resources)")
$lines.Add("") } elseif ($Name) {
$lines.Add("Use -Name <field> for full expression.") $matched = @()
foreach ($tf in $totalFields) {
$tfPath = $tf.SelectSingleNode("s:dataPath", $ns).InnerText
if ($tfPath -eq $Name) { $matched += $tf }
} }
if ($matched.Count -eq 0) {
Write-Error "Resource '$Name' not found"
exit 1
}
$lines.Add("=== Resource: $Name ===")
$lines.Add("")
foreach ($tf in $matched) {
$tfExpr = $tf.SelectSingleNode("s:expression", $ns).InnerText
$tfGroup = $tf.SelectSingleNode("s:group", $ns)
$groupStr = "(overall)"
if ($tfGroup) { $groupStr = $tfGroup.InnerText }
$lines.Add(" [$groupStr] $tfExpr")
}
} else {
# Map
$lines.Add("=== Resources ($($totalFields.Count)) ===")
$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")
$lines.Add("")
$lines.Add("Use -Name <field> for full formula.")
} }
} }