Модуль менеджера есть, а БСП его не видит: пропавшая кнопка «Печать» и варианты отчетов
Разработка - БСП (Библиотека стандартных подсистем)
В прошлой статье (Claude Code + EDT на БП КОРП: три месяца, 328 коммитов и 40 правил) я рассказывал, как мы ведем доработки БП КОРП 3.0 с ИИ-агентом в EDT. Эта статья про другое: про две истории с БСП, где объект собран правильно, а система его не замечает. Обе закончились несколькими строками регистрации. Обе стоили времени, потому что ни EDT, ни платформа ни разу не сказали, что что-то не так.
Агент здесь появляется один раз. Впервые мы наступили на эту граблю, когда он сделал модуль менеджера документа по всем правилам БСП. Валидация прошла, база обновилась, а кнопки печати не было. Модуль был ни при чем: не хватало строки в другом модуле, о котором в задаче не было ни слова. С вариантами отчетов вышло так же, только итераций было около восьми.
Симптом: печати нет нигде
Документ нашего блока. В модуле менеджера есть ПриОпределенииНастроекПечати, ДобавитьКомандыПечати и Печать, макет на месте. EDT-валидация чистая, конфигурация базы обновлена, сеанс перезапущен. Кнопки «Печать» нет ни в форме списка, ни в форме документа, в меню «Еще» тоже пусто. Ошибок нет ни в журнале регистрации, ни в окне сообщений.
Первое подозрение падает на синхронизацию EDT с базой. Это ложный след. На самом деле БСП просто не дошла до модуля менеджера.
Где обрывается цепочка
Форма с подключаемыми командами запрашивает команды печати, и для объекта метаданных БСП вызывает УправлениеПечатью.КомандыПечатиОбъекта. Решающее место в ней выглядит так (код БСП из нашей конфигурации):
ДобавляемыеКомандыПечати = СоздатьКоллекциюКомандПечати();
Если НастройкиПечатиОбъекта(Источник.Менеджер).ПриДобавленииКомандПечати Тогда
Источник.Менеджер.ДобавитьКомандыПечати(ДобавляемыеКомандыПечати);
КонецЕсли;
Функция НастройкиПечатиОбъекта начинает с ПриДобавленииКомандПечати = Ложь и проверяет два списка объектов. Первый собирается в УправлениеПечатьюПереопределяемый.ПриОпределенииНастроекПечати, в коллекции Настройки.ОбъектыПечати. Если объект там есть, БСП вызывает ПриОпределенииНастроекПечати модуля менеджера, и флаг ставит уже сам модуль. Второй список, для обратной совместимости, собирается в УправлениеПечатьюПереопределяемый.ПриОпределенииОбъектовСКомандамиПечати. Если объект в нем, флаг сразу становится Истина, а ПриОпределенииНастроекПечати менеджера не вызывается вовсе.
Объекта нет ни в одном списке, значит флаг остается Ложь. ДобавитьКомандыПечати не вызывается, кнопки нет, и никакой ошибки тоже нет: с точки зрения БСП у объекта просто нет печати.
Отсюда главный вывод. Процедура ПриОпределенииНастроекПечати в модуле менеджера выглядит как выключатель («включить команды печати»), но сама по себе она ничего не включает. БСП вызовет ее только для объекта, который уже числится в списке.
Оба списка кешируются в УправлениеПечатьюПовтИсп на сеанс. Добавили объект в список и проверяете в том же сеансе? Кнопки не будет и теперь. Формы тоже кешируются в сессии, так что после обновления базы нужен новый сеанс.
Четыре части рабочей печати
Рабочая печать встроенного документа складывается из четырех частей, и нужны все. Речь именно об объекте конфигурации; у внешней обработки с СведенияОВнешнейОбработке механизм другой.
Модуль менеджера. Три экспортные процедуры в области БСП:
Процедура ПриОпределенииНастроекПечати(Настройки) Экспорт
Настройки.ПриДобавленииКомандПечати = Истина;
КонецПроцедуры
Процедура ДобавитьКомандыПечати(КомандыПечати) Экспорт
КомандаПечати = КомандыПечати.Добавить();
КомандаПечати.Идентификатор = "ПРЕФ_ПечатьДокумента";
КомандаПечати.Представление = НСтр("ru = 'Печать'");
КомандаПечати.Обработчик = "УправлениеПечатьюБПКлиент.ВыполнитьКомандуПечати";
КомандаПечати.Порядок = 100;
КонецПроцедуры
Процедура Печать(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "ПРЕФ_ПечатьДокумента") Тогда
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм, "ПРЕФ_ПечатьДокумента", НСтр("ru = 'Заголовок печатной формы'"),
СформироватьПечатнуюФорму(МассивОбъектов), , "Документ.ПРЕФ_Документ.Печать");
КонецЕсли;
ОбщегоНазначенияБП.ЗаполнитьДополнительныеПараметрыПечати(
МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода);
КонецПроцедуры
Сигнатура Печать строго из пяти параметров, в этом порядке. Обработчик команды в БП именно УправлениеПечатьюБПКлиент.ВыполнитьКомандуПечати: так сделан типовой АвансовыйОтчет, который печатает по тому же пути. СформироватьПечатнуюФорму здесь ваша функция, которая заполняет табличный документ по макету.
Макет. Templates/Печать/Template.mxlx с областями шапки, заголовка таблицы, строки и подписи. Ширины колонок и границы лучше править в конструкторе макета: в XML результат не увидеть.
Регистрация в списке объектов печати. Та самая строка, которую забывают. Мы добавили документ в УправлениеПечатьюПереопределяемый.ПриОпределенииОбъектовСКомандамиПечати, с маркерами модификации, чтобы правку было видно при обновлении типовой:
Процедура ПриОпределенииОбъектовСКомандамиПечати(СписокОбъектов) Экспорт
// <<Наш блок: регистрация печати документов
СписокОбъектов.Добавить(Документы.ПРЕФ_Документ);
// >>Наш блок
СписокОбъектов.Добавить(Справочники.БанковскиеСчета);
// ... дальше типовой список, в нем и Документы.АвансовыйОтчет
Переопределяемый модуль для этого и существует, правка в нем штатная. В нашей версии БСП эта процедура лежит в области устаревших, с пометкой «использовать ПриОпределенииНастроекПечати». Мы выбрали ее сознательно: здесь зарегистрирован типовой АвансовыйОтчет, и на нашем документе этот путь проверен: после регистрации кнопка появилась. Основной путь, через Настройки.ОбъектыПечати, мы в этом проекте не проверяли. Если пойдете им, флаг в ПриОпределенииНастроекПечати менеджера становится обязательным, потому что тогда его ставит именно модуль.
Еще одна ловушка из нашего проекта. В конфигурации нашлась копия переопределяемого модуля с префиксом, которую никто не вызывает. Документы, «зарегистрированные» в ней, не печатали. Прежде чем куда-то добавлять строку, найдите поиском, кто вызывает процедуру. Должна найтись УправлениеПечатью или УправлениеПечатьюПовтИсп.
Форма и объект. Форма должна работать через подключаемые команды: ПодключаемыеКоманды.ПриСозданииНаСервере(ЭтотОбъект) в ПриСозданииНаСервере и диспетчеры Подключаемый_*. У стандартных форм документа это уже есть. У самого объекта должно стоять useStandardCommands = true.
После правки: обновить конфигурацию базы, закрыть сеанс, открыть новый. Только тогда проверять кнопку в списке и в документе.
Варианты отчетов: четыре условия
С отчетами история той же природы, только условий больше. Мы добавили в схему компоновки несколько вариантов, а пользователь видел либо один отчет, либо список вариантов с одинаковыми названиями. Вариант в схеме компоновки нужен, но этого мало.
| # | Что | Где | Симптом без этого |
|---|---|---|---|
| 1 | ПриОпределенииНастроек и НастроитьВариантыОтчета |
модуль менеджера отчета | у вариантов нет своих имен и описаний |
| 2 | регистрация отчета | ПРЕФ_ОбщегоНазначения.НастроитьВариантыОтчетов |
БСП не опрашивает модуль менеджера |
| 3 | регистрация раздела | наше расширение, перехват ОпределитьРазделыСВариантамиОтчетов |
панели отчетов у раздела нет вовсе |
| 4 | перестроение справочника вариантов | запуск клиента с /CЗапуститьОбновлениеИнформационнойБазы |
список вариантов остается прежним |
Не хватает обычно всех четырех сразу, поэтому исправление по одному пункту ничего не меняет, и кажется, что ищешь не там.
Модуль менеджера отчета:
Процедура ПриОпределенииНастроек(Настройки) Экспорт
Настройки.НастроитьВариантыОтчета = Истина;
КонецПроцедуры
Процедура НастроитьВариантыОтчета(Настройки, НастройкиОтчета) Экспорт
НастройкиВарианта = ВариантыОтчетов.ОписаниеВарианта(Настройки, НастройкиОтчета, "ОстаткиПоСкладам");
НастройкиВарианта.Наименование = НСтр("ru = 'Хранение: остатки по складам'");
НастройкиВарианта.Описание = НСтр("ru = 'Остатки на конец периода по номенклатуре; диаграмма.'");
// и так для каждого ключа варианта из схемы
КонецПроцедуры
Пункты 2 и 3 мы держим в расширении. Типовой ВариантыОтчетовПереопределяемый при обновлении БП перезапишется вместе с правкой, а перехват в расширении переживает обновление:
&После("ОпределитьРазделыСВариантамиОтчетов")
Процедура ПРЕФ_ОпределитьРазделыСВариантамиОтчетов(Разделы)
Разделы.Добавить(Метаданные.Подсистемы.ПРЕФ_Аналитика, НСтр("ru = 'Отчеты аналитики'"));
КонецПроцедуры
&После("НастроитьВариантыОтчетов")
Процедура ПРЕФ_НастроитьВариантыОтчетов(Настройки)
ПРЕФ_ОбщегоНазначения.НастроитьВариантыОтчетов(Настройки);
КонецПроцедуры
А сама процедура в общем модуле конфигурации просто перечисляет отчеты:
Процедура НастроитьВариантыОтчетов(Настройки) Экспорт
// Только отчеты, у которых ЕСТЬ модуль менеджера с ПриОпределенииНастроек.
ВариантыОтчетов.НастроитьОтчетВМодулеМенеджера(Настройки, Метаданные.Отчеты.ПРЕФ_ХранениеОстатки);
ВариантыОтчетов.НастроитьОтчетВМодулеМенеджера(Настройки, Метаданные.Отчеты.ПРЕФ_ПродажиПоМесяцам);
КонецПроцедуры
Имена вариантов и отчет без модуля менеджера
Без явного НастройкиВарианта.Наименование БСП подставляет каждому варианту синоним отчета. В списке все варианты выглядят одинаково, и различить их нельзя. Задавать имя через <dcsset:presentation> в схеме бесполезно: во всей конфигурации, включая типовые отчеты БП, он пустой, и БСП берет имя не оттуда. Мы стали писать в имени префикс группы («Хранение: ...», «Баланс: ...»): в общей панели раздела так проще понять, к какому отчету относится вариант.
Вторая грабля коварнее. ВариантыОтчетов.НастроитьОтчетВМодулеМенеджера обращается к модулю менеджера отчета. Если в списке оказался отчет без такого модуля, вызов обрывает настройку всех остальных отчетов процедуры. Молча, без ошибки в EDT. Достаточно добавить в список новый отчет и забыть ему модуль, чтобы пропали варианты у отчетов, которые до этого работали.
Поэтому перед правкой списка мы прогоняем проверку по папке отчетов:
cd <проект>/src/Reports
for r in ПРЕФ_*; do
[ -f "$r/ManagerModule.bsl" ] || { echo "НЕТ МОДУЛЯ: $r"; continue; }
grep -q "Процедура ПриОпределенииНастроек" "$r/ManagerModule.bsl" || echo "БЕЗ ПриОпределенииНастроек: $r"
done
Пустой вывод означает, что в список можно включать все. Отчет, попавший в вывод, сначала получает модуль менеджера, потом строку в списке.
Кеш вариантов, панель раздела и отчет, который зависает
Почему не помогает «Обновить конфигурацию базы данных». БСП хранит варианты в справочнике ВариантыОтчетов и перезаполняет его только при обновлении информационной базы. Обновление ИБ запускается по смене версии конфигурации, а не по обновлению структуры. Обработчики с Версия = "*" у нас были, но без запуска обновления ИБ они не выполнялись. Рабочий способ: запустить клиент с ключом /CЗапуститьОбновлениеИнформационнойБазы. Наименования вариантов тоже живут в этом справочнике, так что после переименования нужен тот же запуск.
Второе недоразумение связано с тем, куда смотреть. Панель отчетов раздела и навигация раздела устроены по-разному. В навигации отчет всегда показан одной строкой, вариантов там не бывает. Варианты видны в панели, которая открывается командой «Отчеты» раздела. Если проверять результат в навигации, легко решить, что правка не сработала.
Там же, в панели отчетов, отчет можно выделить жирным. В модуле менеджера:
НастройкиВарианта.Размещение.Вставить(Метаданные.Подсистемы.ПРЕФ_Аналитика.Подсистемы.ПРЕФ_Урожай, "Важный");
В меню функций раздела жирного шрифта для отчетов нет, там только порядок.
Третий случай, от 2026-09-13, самый неприятный. Форма одного из наших отчетов зависала при открытии. Не при формировании, а еще до нажатия «Сформировать». Схема и запрос были чистые, validate_query замечаний не дал, в коде причины не нашлось. От всех работающих отчетов проекта он отличался ровно тремя вещами: не было модуля менеджера, не было строки в ПРЕФ_ОбщегоНазначения.НастроитьВариантыОтчетов и не было variantsStorage в .mdo. После добавления всех трех отчет открылся и сформировался.
Какая из трех вещей была причиной, мы не выясняли и выяснять не стали: у работающих отчетов есть все три. Теперь новый отчет добавляем сразу с ними, а variantsStorage выставляем значением SettingsStorage.ХранилищеВариантовОтчетов. Симптом «отчет висит при открытии» у нас теперь означает: сначала проверить регистрацию по таблице выше, и только потом включать технологический журнал.
Порядок диагностики
Если нет кнопки «Печать»:
- Есть ли объект в
ПриОпределенииОбъектовСКомандамиПечатиили вНастройки.ОбъектыПечатипереопределяемого модуля? Проверять модуль, который реально вызывает БСП, а не похожую копию. - Есть ли в модуле менеджера
ДобавитьКомандыПечатииПечатьс пятью параметрами, и указан ли обработчикУправлениеПечатьюБПКлиент.ВыполнитьКомандуПечати? - Подключены ли в форме
ПодключаемыеКоманды, стоит ли у объектаuseStandardCommands? - Открыт ли новый сеанс после обновления базы?
- Только после этого смотреть на синхронизацию EDT с базой.
Если не видно вариантов отчета:
- Есть ли у отчета модуль менеджера с
ПриОпределенииНастроекиНастроитьВариантыОтчета, заданы лиНаименованиеу вариантов? - Есть ли отчет в
ПРЕФ_ОбщегоНазначения.НастроитьВариантыОтчетов, и нет ли в этом списке отчета без модуля менеджера? - Есть ли раздел в
ОпределитьРазделыСВариантамиОтчетов? - Запускалось ли обновление ИБ после последней правки?
- Смотрим ли мы в панель отчетов раздела, а не в навигацию?
Обе истории сводятся к одному. БСП не ищет объекты по метаданным, она опрашивает только то, что перечислено в переопределяемых модулях. Корректный модуль менеджера без строки регистрации для нее не существует, и ни валидация EDT, ни платформа об этом не предупредят. Поэтому на ревью доработки с печатью или отчетом мы теперь первым делом спрашиваем не «правильно ли написан модуль», а «где он зарегистрирован».
Если вы встречали другие места, где БСП так же молча игнорирует объект (рассылки, дополнительные реквизиты, подключаемые команды заполнения), напишите в комментариях, что было и где нашлась строка регистрации. Соберу их в общий список проверок.
Вступайте в нашу телеграмм-группу Инфостарт
Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.