При разработке и кастомизации конфигураций на платформе «1С:Предприятие 8.3» (в частности, «1С:Бухгалтерия предприятия 3.0») программисты часто сталкиваются с задачей изменения печатных форм документов. Одна из наиболее распространенных задач — управление выводом префиксов организации и информационной базы в номерах документов при выводе на печать.
Например, нам необходимо сделать так, чтобы у документов СчетФактураВыданный префикс при печати полностью убирался, а у остальных документов (таких как Реализации, Поступления и т.д.) нумерация оставалась в стандартном виде. В этой статье мы подробно разберем, почему возникает ошибка неопределенности контекста при обращении к метаданным в общих модулях, как правильно передать ссылку на объект в клиент-серверный модуль и какие архитектурные подходы Библиотеки стандартных подсистем (БСП) лучше всего использовать для решения этой задачи.
---
Попытка написать внутри функции общего модуля код вида:
Если Документы.СчетФактураВыданный Тогда
// Действие...
КонецЕсли;
приводит к ошибке компиляции: «Переменная не определена (Документы)». Выясним причину этой ошибки.
Общий модуль ПрефиксацияОбъектовКлиентСервер имеет свойства «Клиент (управляемое приложение)» и «Сервер». Это означает, что код модуля компилируется в двух разных контекстах. Менеджеры объектов (такие как коллекция Документы, Справочники, РегистрыСведений) физически существуют и доступны только на сервере. Когда платформа компилирует этот модуль для работы на клиенте, она не находит глобальную переменную Документы, что и вызывает критическую ошибку.
Кроме того, сама стандартная функция НомерНаПечать имеет следующую сигнатуру:
Функция НомерНаПечать(Знач НомерОбъекта, УдалитьПрефиксИнформационнойБазы = Ложь, УдалитьПользовательскийПрефикс = Ложь) Экспорт
В эту функцию передается исключительно строковая переменная — непосредственно сам номер (например, "ФР00-000015"). Физической ссылки на документ, к которому принадлежит этот номер, внутри функции нет. Следовательно, мы не можем «на лету» определить, для какого именно типа документа сейчас форматируется номер.
---
Проанализируем самый очевидный способ решения проблемы «в лоб» — расширение сигнатуры стандартной функции общего модуля. Мы добавим в параметры функции необязательный параметр, в который будем передавать ссылку на документ-источник.
Рассмотрим по шагам реализацию этого механизма:
ПрефиксацияОбъектовКлиентСервер и найдем функцию НомерНаПечать.Источник (по умолчанию установим его в значение Неопределено, чтобы не сломать вызовы этой функции из других участков системы, где передаются только три параметра).ТипЗнч.Посмотрим на пример измененного кода функции в общем модуле:
Функция НомерНаПечать(Знач НомерОбъекта, УдалитьПрефиксИнформационнойБазы = Ложь, УдалитьПользовательскийПрефикс = Ложь, Источник = Неопределено) Экспорт
// {Обработчик: ПриПолученииНомераНаПечать} Начало
СтандартнаяОбработка = Истина;
ПрефиксацияОбъектовКлиентСерверПереопределяемый.ПриПолученииНомераНаПечать(НомерОбъекта, СтандартнаяОбработка,
УдалитьПрефиксИнформационнойБазы, УдалитьПользовательскийПрефикс);
Если СтандартнаяОбработка = Ложь Тогда
Возврат НомерОбъекта;
КонецЕсли;
// {Обработчик: ПриПолученииНомераНаПечать} Окончание
НомерОбъекта = СокрЛП(НомерОбъекта);
// Проверяем тип источника. Если это Счет-фактура выданный, переопределяем правила удаления префиксов
Если Источник <> Неопределено Тогда
Если ТипЗнч(Источник) = Тип("ДокументСсылка.СчетФактураВыданный") Тогда
УдалитьПрефиксИнформационнойБазы = Истина;
УдалитьПользовательскийПрефикс = Ложь; // Важно для авансовых счетов-фактур!
КонецЕсли;
КонецЕсли;
// Удаляем пользовательские префиксы из номера объекта (если включен флаг)
Если УдалитьПользовательскийПрефикс Тогда
НомерОбъекта = УдалитьПользовательскиеПрефиксыИзНомераОбъекта(НомерОбъекта);
КонецЕсли;
// Удаляем лидирующие нули из номера объекта.
НомерОбъекта = УдалитьЛидирующиеНулиИзНомераОбъекта(НомерОбъекта);
// Удаляем префикс организации и префикс информационной базы из номера объекта.
НомерОбъекта = УдалитьПрефиксыИзНомераОбъекта(НомерОбъекта, Истина, УдалитьПрефиксИнформационнойБазы);
Возврат НомерОбъекта;
КонецФункции
Важное примечание по авансовым счетам-фактурам: Обратите внимание, что для счетов-фактур на аванс в системе 1С используется специальный пользовательский префикс «А» (например, номер выглядит как ФР0Г-А000123). Согласно требованиям налогового законодательства РФ, символ «А» должен обязательно присутствовать в номере печатной формы (на печать должно выходить «А123»). Именно поэтому параметр УдалитьПользовательскийПрефикс для документов СФ должен принудительно устанавливаться в значение Ложь.
---
Для того чтобы не вносить изменения непосредственно в ядро функций БСП (что усложнит последующие обновления конфигурации 1С), разработчики Библиотеки стандартных подсистем предусмотрели специальные «переопределяемые» модули.
Проанализируем работу общего модуля ПрефиксацияОбъектовКлиентСерверПереопределяемый. В нем присутствует процедура-обработчик ПриПолученииНомераНаПечать. Мы можем внедрить логику анализа номера именно туда.
Поскольку ссылка на документ туда по-прежнему не передается напрямую в параметрах, мы можем выполнить синтаксический анализ самого номера объекта. Если структура номера или его длина характерны исключительно для счетов-фактур (или если мы передаем специфический текстовый маркер номера из менеджера печати СФ), мы можем переопределить параметры форматирования «на лету»:
Процедура ПриПолученииНомераНаПечать(НомерОбъекта, СтандартнаяОбработка, УдалитьПрефиксИнформационнойБазы, УдалитьПользовательскийПрефикс) Экспорт
// Пример: Если в номере присутствует разделитель авансового СФ ("-А")
Если Найти(НомерОбъекта, "-А") > 0 Тогда
УдалитьПрефиксИнформационнойБазы = Истина;
УдалитьПользовательскийПрефикс = Ложь; // оставляем литеру "А"
// Отключаем стандартную обработку, если хотим полностью взять форматирование на себя
// СтандартнаяОбработка = Ложь;
КонецЕсли;
КонецПроцедуры
---
Если перед вами стоит задача решить проблему без изменения типовой конфигурации (чтобы база оставалась на полной поддержке), наилучшим решением будет использование механизма Расширений.
Разберем по шагам, как перехватить печать номера конкретно для Счета-фактуры через расширение:
СчетФактураВыданный и общий модуль, отвечающий за его печать (обычно это модуль менеджера документа или специализированный модуль печати документов НДС, например, УчетНДСПереопределяемый).&После или &Вместо перехватываем этот метод. Вместо стандартного вызова функции получения номера, мы явно вызываем функцию форматирования префиксов с нужными нам флагами:
&Вместо("ПроцедураПодготовкиПараметровПечати")
Процедура Расш1_ПроцедураПодготовкиПараметровПечати(ПараметрыДокумента)
// Вызываем оригинальный метод для заполнения основных данных
ПродолжитьВызов(ПараметрыДокумента);
// Переопределяем конкретное поле номера для печатной формы счета-фактуры
// Принудительно очищаем префиксы ИБ (передавая Истина вторым параметром)
ПараметрыДокумента.НомерНаПечать = ПрефиксацияОбъектовКлиентСервер.НомерНаПечать(ПараметрыДокумента.Номер, Истина, Ложь);
КонецПроцедуры
Этот способ является наиболее чистым с точки зрения архитектуры 1С:Предприятия. Он изолирует доработки, не влияет на обновление других документов конфигурации и гарантирует, что префиксы будут убираться только у необходимых нам счетов-фактур, не затрагивая алгоритмы работы накладных, актов и других документов информационной базы.