From c2348b6b68740bf3c685ffbe0731655327da80c1 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sat, 7 Feb 2026 21:48:43 +0300 Subject: [PATCH] Add BSP skills for additional processors/reports registration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New skills for working with BSP (Standard Subsystems Library) mechanism: - epf-bsp-init: adds СведенияОВнешнейОбработке() to object module - epf-bsp-add-command: adds commands to existing BSP processor Both skills use code templates in SKILL.md (no PowerShell scripts) — Claude modifies BSL code directly via Read/Edit. Co-Authored-By: Claude Opus 4.6 --- .claude/skills/epf-bsp-add-command/SKILL.md | 197 ++++++++++++++++++ .claude/skills/epf-bsp-init/SKILL.md | 208 ++++++++++++++++++++ README.md | 16 +- 3 files changed, 420 insertions(+), 1 deletion(-) create mode 100644 .claude/skills/epf-bsp-add-command/SKILL.md create mode 100644 .claude/skills/epf-bsp-init/SKILL.md diff --git a/.claude/skills/epf-bsp-add-command/SKILL.md b/.claude/skills/epf-bsp-add-command/SKILL.md new file mode 100644 index 00000000..3e521b2b --- /dev/null +++ b/.claude/skills/epf-bsp-add-command/SKILL.md @@ -0,0 +1,197 @@ +--- +name: epf-bsp-add-command +description: Добавить команду в дополнительную обработку БСП +argument-hint: <Идентификатор> [ТипКоманды] [Представление] +allowed-tools: + - Read + - Edit + - Glob + - Grep +--- + +# /epf-bsp-add-command — Добавление команды БСП + +Добавляет команду в существующую функцию `СведенияОВнешнейОбработке()` и генерирует соответствующий обработчик. + +Предварительно обработка должна быть инициализирована через `/epf-bsp-init`. + +## Usage + +``` +/epf-bsp-add-command <Идентификатор> [ТипКоманды] [Представление] +``` + +| Параметр | Обязательный | По умолчанию | Описание | +|---------------|:------------:|-----------------------|--------------------------------------------| +| ProcessorName | да | — | Имя обработки | +| Идентификатор | да | — | Внутреннее имя команды (латиница) | +| ТипКоманды | нет | из вида обработки | Тип запуска команды (см. маппинг ниже) | +| Представление | нет | = Идентификатор | Отображаемое имя команды для пользователя | +| SrcDir | нет | `src` | Каталог исходников | + +## Маппинг типов команд + +Пользователь может указать тип в свободной форме: + +| Пользователь пишет | ТипКоманды | +|---------------------------------------|-----------------------------------------------------| +| открыть форму, форма | `ТипКомандыОткрытиеФормы()` | +| клиентский метод, на клиенте | `ТипКомандыВызовКлиентскогоМетода()` | +| серверный метод, на сервере | `ТипКомандыВызовСерверногоМетода()` | +| заполнение формы, заполнить форму | `ТипКомандыЗаполнениеФормы()` | +| сценарий, безопасный режим | `ТипКомандыСценарийВБезопасномРежиме()` | + +Если пользователь не указал тип — определи по виду обработки из существующего кода `СведенияОВнешнейОбработке()`: + +| Вид обработки (из кода) | ТипКоманды по умолчанию | +|----------------------------|-------------------------------------------| +| ДополнительнаяОбработка | `ТипКомандыОткрытиеФормы()` | +| ДополнительныйОтчет | `ТипКомандыОткрытиеФормы()` | +| ЗаполнениеОбъекта | `ТипКомандыВызовСерверногоМетода()` | +| Отчет | `ТипКомандыОткрытиеФормы()` | +| ПечатнаяФорма | `ТипКомандыВызовСерверногоМетода()` | +| СозданиеСвязанныхОбъектов | `ТипКомандыВызовСерверногоМетода()` | + +## Шаблон добавления команды + +Вставляется в `СведенияОВнешнейОбработке()` **перед** строкой `Возврат ПараметрыРегистрации`: + +```bsl + НоваяКоманда = ПараметрыРегистрации.Команды.Добавить(); + НоваяКоманда.Представление = НСтр("ru = '{{Представление}}'"); + НоваяКоманда.Идентификатор = "{{Идентификатор}}"; + НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.{{ТипКоманды}}; + НоваяКоманда.ПоказыватьОповещение = Ложь; +``` + +Для печатных форм (ВидОбработкиПечатнаяФорма) добавь также: + +```bsl + НоваяКоманда.Модификатор = "ПечатьMXL"; +``` + +Примечание: в отличие от первой команды (из `/epf-bsp-init`), дополнительные команды используют строковые литералы `НСтр("ru = '...'")` для представления и строку для идентификатора, а не `Метаданные()`. + +## Шаблоны обработчиков + +### ВызовСерверногоМетода — если обработчик уже есть + +Если процедура `ВыполнитьКоманду` уже существует в модуле объекта, добавь ветку перед `КонецЕсли`: + +```bsl + ИначеЕсли ИдентификаторКоманды = "{{Идентификатор}}" Тогда + // TODO: Реализация {{Идентификатор}} +``` + +### ВызовСерверногоМетода — если обработчика нет + +Для глобальных обработок (без `ОбъектыНазначения`): + +```bsl +Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполненияКоманды) Экспорт + + Если ИдентификаторКоманды = "{{Идентификатор}}" Тогда + // TODO: Реализация {{Идентификатор}} + КонецЕсли; + +КонецПроцедуры +``` + +Для назначаемых обработок (с `ОбъектыНазначения`): + +```bsl +Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения, ПараметрыВыполненияКоманды) Экспорт + + Если ИдентификаторКоманды = "{{Идентификатор}}" Тогда + // TODO: Реализация {{Идентификатор}} + КонецЕсли; + +КонецПроцедуры +``` + +### ПечатнаяФорма — если процедура Печать уже есть + +Добавь блок перед `КонецПроцедуры`: + +```bsl + ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "{{Идентификатор}}"); + Если ПечатнаяФорма <> Неопределено Тогда + ПечатнаяФорма.ТабличныйДокумент = Сформировать{{Идентификатор}}(МассивОбъектов, ОбъектыПечати); + ПечатнаяФорма.СинонимМакета = НСтр("ru = '{{Представление}}'"); + КонецЕсли; +``` + +### ПечатнаяФорма — если процедуры Печать нет + +```bsl +Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт + + ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "{{Идентификатор}}"); + Если ПечатнаяФорма <> Неопределено Тогда + ПечатнаяФорма.ТабличныйДокумент = Сформировать{{Идентификатор}}(МассивОбъектов, ОбъектыПечати); + ПечатнаяФорма.СинонимМакета = НСтр("ru = '{{Представление}}'"); + КонецЕсли; + +КонецПроцедуры +``` + +### ВызовКлиентскогоМетода + +Добавляется в **модуль формы** (`Forms//Ext/Form/Module.bsl`): + +Для глобальных обработок: + +```bsl +&НаКлиенте +Процедура ВыполнитьКоманду(ИдентификаторКоманды) Экспорт + + Если ИдентификаторКоманды = "{{Идентификатор}}" Тогда + // TODO: Реализация {{Идентификатор}} + КонецЕсли; + +КонецПроцедуры +``` + +Для назначаемых обработок: + +```bsl +&НаКлиенте +Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт + + Если ИдентификаторКоманды = "{{Идентификатор}}" Тогда + // TODO: Реализация {{Идентификатор}} + КонецЕсли; + +КонецПроцедуры +``` + +Если процедура уже есть — добавь ветку `ИначеЕсли`. + +## Инструкции + +1. Найди и прочитай `ObjectModule.bsl` через Glob: `src/{{ProcessorName}}/Ext/ObjectModule.bsl` +2. Убедись что `СведенияОВнешнейОбработке()` существует. Если нет — предложи вызвать `/epf-bsp-init` +3. Определи вид обработки из существующего кода (найди строку с `ВидОбработки...()`) +4. Вставь блок команды **перед** `Возврат ПараметрыРегистрации` +5. Добавь обработчик: + - Для серверных обработчиков — в `ObjectModule.bsl`, область `ПрограммныйИнтерфейс` + - Для клиентских обработчиков — в модуль формы (найти через Glob: `src/{{ProcessorName}}/Forms/*/Ext/Form/Module.bsl`) +6. Если обработчик (`ВыполнитьКоманду` / `Печать`) уже есть — добавь ветку, не создавай дубль процедуры +7. Используй табы для отступов + +## Пример + +Пользователь: `/epf-bsp-add-command МояОбработка ЗаказПокупателя серверный "Заказ покупателя"` + +В `СведенияОВнешнейОбработке()` перед `Возврат` добавится: + +```bsl + НоваяКоманда = ПараметрыРегистрации.Команды.Добавить(); + НоваяКоманда.Представление = НСтр("ru = 'Заказ покупателя'"); + НоваяКоманда.Идентификатор = "ЗаказПокупателя"; + НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода(); + НоваяКоманда.ПоказыватьОповещение = Ложь; + НоваяКоманда.Модификатор = "ПечатьMXL"; +``` + +И в существующую процедуру `Печать` добавится блок обработки. diff --git a/.claude/skills/epf-bsp-init/SKILL.md b/.claude/skills/epf-bsp-init/SKILL.md new file mode 100644 index 00000000..230c9870 --- /dev/null +++ b/.claude/skills/epf-bsp-init/SKILL.md @@ -0,0 +1,208 @@ +--- +name: epf-bsp-init +description: Добавить функцию регистрации БСП (СведенияОВнешнейОбработке) в модуль объекта обработки +argument-hint: <Вид> +allowed-tools: + - Read + - Edit + - Glob + - Grep +--- + +# /epf-bsp-init — Регистрация обработки в БСП + +Добавляет в модуль объекта обработки функцию `СведенияОВнешнейОбработке()`, необходимую для регистрации в подсистеме «Дополнительные отчёты и обработки» БСП. + +## Usage + +``` +/epf-bsp-init <Вид> [Назначение...] +``` + +| Параметр | Обязательный | По умолчанию | Описание | +|---------------|:------------:|--------------|---------------------------------------------------------| +| ProcessorName | да | — | Имя обработки (должна быть создана через `/epf-init`) | +| Вид | да | — | Вид обработки (см. маппинг ниже) | +| Назначение | * | — | Объекты метаданных для назначаемых видов | +| SrcDir | нет | `src` | Каталог исходников | + +\* Назначение обязательно для видов: ЗаполнениеОбъекта, Отчет, ПечатнаяФорма, СозданиеСвязанныхОбъектов. + +## Маппинг вида обработки + +Пользователь может указать вид в свободной форме. Определи нужный по контексту: + +| Пользователь пишет | Вид | API-метод | +|-------------------------------------------|----------------------------|----------------------------------------------| +| доп обработка, обработка, глобальная | ДополнительнаяОбработка | `ВидОбработкиДополнительнаяОбработка()` | +| доп отчёт, глобальный отчёт | ДополнительныйОтчет | `ВидОбработкиДополнительныйОтчет()` | +| заполнение, заполнить | ЗаполнениеОбъекта | `ВидОбработкиЗаполнениеОбъекта()` | +| отчёт (назначаемый, для объекта) | Отчет | `ВидОбработкиОтчет()` | +| печатная форма, печать | ПечатнаяФорма | `ВидОбработкиПечатнаяФорма()` | +| создание связанных объектов | СозданиеСвязанныхОбъектов | `ВидОбработкиСозданиеСвязанныхОбъектов()` | + +## Тип команды по умолчанию + +| Вид | ТипКоманды по умолчанию | +|----------------------------|-------------------------------------------| +| ДополнительнаяОбработка | `ТипКомандыОткрытиеФормы()` | +| ДополнительныйОтчет | `ТипКомандыОткрытиеФормы()` | +| ЗаполнениеОбъекта | `ТипКомандыВызовСерверногоМетода()` | +| Отчет | `ТипКомандыОткрытиеФормы()` | +| ПечатнаяФорма | `ТипКомандыВызовСерверногоМетода()` | +| СозданиеСвязанныхОбъектов | `ТипКомандыВызовСерверногоМетода()` | + +## Шаблон: СведенияОВнешнейОбработке + +Базовый шаблон — одинаковый для всех видов, отличаются только вызовы API-методов и условные секции. + +```bsl +Функция СведенияОВнешнейОбработке() Экспорт + + МетаданныеОбработки = Метаданные(); + + ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1"); + ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.{{ВидОбработки}}; + ПараметрыРегистрации.Версия = "1.0"; + + {{СЕКЦИЯ_НАЗНАЧЕНИЕ}} + + НоваяКоманда = ПараметрыРегистрации.Команды.Добавить(); + НоваяКоманда.Представление = МетаданныеОбработки.Представление(); + НоваяКоманда.Идентификатор = МетаданныеОбработки.Имя; + НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.{{ТипКоманды}}; + НоваяКоманда.ПоказыватьОповещение = Ложь; + {{СЕКЦИЯ_МОДИФИКАТОР}} + + Возврат ПараметрыРегистрации; + +КонецФункции +``` + +### Подстановки + +- `{{ВидОбработки}}` — API-метод из таблицы маппинга вида +- `{{ТипКоманды}}` — API-метод из таблицы типа команды по умолчанию + +### Условные секции + +**`{{СЕКЦИЯ_НАЗНАЧЕНИЕ}}`** — только для назначаемых видов (ЗаполнениеОбъекта, Отчет, ПечатнаяФорма, СозданиеСвязанныхОбъектов). Одна строка на каждый объект: + +```bsl + ПараметрыРегистрации.Назначение.Добавить("Документ.СчетНаОплату"); +``` + +Формат имени объекта: `ИмяКлассаОбъектаМетаданного.ИмяОбъекта` (например `Документ.СчетНаОплату`, `Справочник.Контрагенты`). + +Для глобальных видов (ДополнительнаяОбработка, ДополнительныйОтчет) — секция не нужна, удалить вместе с пустой строкой. + +**`{{СЕКЦИЯ_МОДИФИКАТОР}}`** — только для ПечатнаяФорма: + +```bsl + НоваяКоманда.Модификатор = "ПечатьMXL"; +``` + +Для остальных видов — удалить вместе с пустой строкой. + +## Шаблоны серверных обработчиков + +Для видов с типом команды `ВызовСерверногоМетода` добавь соответствующую процедуру-обработчик в ту же область `ПрограммныйИнтерфейс`, после `СведенияОВнешнейОбработке`. + +### Для ЗаполнениеОбъекта / СозданиеСвязанныхОбъектов + +```bsl +Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения, ПараметрыВыполненияКоманды) Экспорт + + // TODO: Реализация + +КонецПроцедуры +``` + +### Для ПечатнаяФорма + +```bsl +Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт + + // TODO: Реализация + +КонецПроцедуры +``` + +### Для ДополнительнаяОбработка / ДополнительныйОтчет (с ВызовСерверногоМетода) + +Если пользователь явно выбрал серверный метод вместо открытия формы: + +```bsl +Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполненияКоманды) Экспорт + + // TODO: Реализация + +КонецПроцедуры +``` + +Обрати внимание: у глобальных обработок нет параметра `ОбъектыНазначения`. + +## Инструкции + +1. Найди `ObjectModule.bsl` через Glob: `src/{{ProcessorName}}/Ext/ObjectModule.bsl` +2. Прочитай файл +3. Если `СведенияОВнешнейОбработке` уже есть — сообщи пользователю и не дублируй +4. Если файл не найден — предложи сначала вызвать `/epf-init` +5. Найди область `#Область ПрограммныйИнтерфейс` ... `#КонецОбласти` +6. Вставь функцию `СведенияОВнешнейОбработке()` внутрь этой области +7. Если вид требует серверный обработчик — вставь его тоже в эту область, после функции +8. Используй табы для отступов (как в исходном файле) + +## Пример + +Пользователь: `/epf-bsp-init МояОбработка печатная форма для Документ.СчетНаОплату` + +Результат в `ObjectModule.bsl`: + +```bsl +#Область ОписаниеПеременных + +#КонецОбласти + +#Область ПрограммныйИнтерфейс + +Функция СведенияОВнешнейОбработке() Экспорт + + МетаданныеОбработки = Метаданные(); + + ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1"); + ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиПечатнаяФорма(); + ПараметрыРегистрации.Версия = "1.0"; + + ПараметрыРегистрации.Назначение.Добавить("Документ.СчетНаОплату"); + + НоваяКоманда = ПараметрыРегистрации.Команды.Добавить(); + НоваяКоманда.Представление = МетаданныеОбработки.Представление(); + НоваяКоманда.Идентификатор = МетаданныеОбработки.Имя; + НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода(); + НоваяКоманда.ПоказыватьОповещение = Ложь; + НоваяКоманда.Модификатор = "ПечатьMXL"; + + Возврат ПараметрыРегистрации; + +КонецФункции + +Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт + + // TODO: Реализация + +КонецПроцедуры + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +#КонецОбласти +``` + +## Дальнейшие шаги + +- Добавить ещё команду: `/epf-bsp-add-command` +- Добавить форму: `/epf-add-form` +- Добавить макет: `/epf-add-template` +- Собрать EPF: `/epf-build` diff --git a/README.md b/README.md index 5bc3aebe..3c319912 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ | `/epf-remove-template` | ` ` | Удалить макет | | `/epf-build` | `` | Собрать EPF из XML (документация команды 1cv8.exe) | | `/epf-dump` | `` | Разобрать EPF в XML (документация команды 1cv8.exe) | +| `/epf-bsp-init` | ` <Вид>` | Добавить регистрацию БСП (СведенияОВнешнейОбработке) | +| `/epf-bsp-add-command` | ` <Идентификатор>` | Добавить команду в обработку БСП | Навыки удаления (`epf-remove-*`) не вызываются Claude автоматически — только по явной команде пользователя. @@ -25,6 +27,15 @@ > /epf-build МояОбработка ``` +### Обработка БСП (дополнительная печатная форма) + +``` +> /epf-init МояПечатнаяФорма "Моя печатная форма" +> /epf-bsp-init МояПечатнаяФорма печатная форма для Документ.СчетНаОплату +> /epf-add-template МояПечатнаяФорма СчетНаОплату SpreadsheetDocument +> /epf-build МояПечатнаяФорма +``` + Первая добавленная форма автоматически становится основной (DefaultForm). Флаг `--main` нужен только для переназначения основной формы на другую. После `/epf-init` создаётся структура: @@ -85,7 +96,9 @@ src/ ├── epf-remove-form/ # SKILL.md + scripts/remove-form.ps1 ├── epf-remove-template/ # SKILL.md + scripts/remove-template.ps1 ├── epf-build/ # SKILL.md (только документация) -└── epf-dump/ # SKILL.md (только документация) +├── epf-dump/ # SKILL.md (только документация) +├── epf-bsp-init/ # SKILL.md (шаблоны кода, без скриптов) +└── epf-bsp-add-command/ # SKILL.md (шаблоны кода, без скриптов) docs/ ├── 1c-xml-format-spec.md # Спецификация XML-формата выгрузки └── build-spec.md # Спецификация команд сборки/разборки @@ -104,3 +117,4 @@ docs/ - ClassId обработки фиксирован: `c3831ec8-d8d5-4f93-8a22-f9bfae07327f` - Порядок элементов в `ChildObjects`: TabularSections → Forms → Templates - Первая форма автоматически назначается основной (DefaultForm) +- BSP-навыки (`epf-bsp-*`) не используют скрипты — Claude модифицирует код напрямую через Read/Edit