Как запретить печать непроведенного документа в 1С:Бухгалтерия 3.0

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

В практической работе любой организации часто возникает ситуация, когда пользователи пытаются распечатать документы до их официального проведения в системе. Для таких документов, как Реализация товаров и услуг, печать в непроведенном состоянии несет в себе серьезные экономические и юридические риски. Непроведенный документ не делает движений по регистрам учета, не списывает остатки со складов и не формирует проводки, однако выданная клиенту печатная форма (например, расходная накладная или УПД) может быть использована как подтверждение отгрузки.

В этой статье мы подробно разберем, как установить жесткий запрет или предупреждение при попытке печати непроведенных документов в конфигурации 1С:Бухгалтерия предприятия 3.0 (а также в других решениях на базе БСП, например, 1С:УНФ), используя как классическое изменение кода, так и современный безопасный механизм расширений.

Давайте проанализируем архитектуру печатных форм в современных конфигурациях 1С и найдем наиболее элегантные решения этой задачи.

Понимание механизма печати БСП (Библиотеки стандартных подсистем)

Прежде чем переходить к написанию кода, давайте разберем, как устроена подсистема печати под капотом. В управляемых формах 1С за формирование команд печати отвечает специальный объект — таблица команд печати, которая инициализируется в модуле менеджера каждого документа в процедуре ДобавитьКомандыПечати(КомандыПечати).

Каждая добавляемая команда описывается как строка таблицы КомандыПечати и обладает набором свойств. Одно из важнейших, но редко используемых свойств — это ПроверкаПроведенияПередПечатью. По умолчанию это свойство имеет значение Ложь, что позволяет свободно выводить печатные формы на экран для любых документов. Если же установить его в значение Истина, то платформа перед выполнением печати автоматически проверит статус документа:

  1. Если документ проведен, печатная форма сформируется в обычном режиме.
  2. Если документ не проведен, пользователю будет выведен стандартный диалог с предложением провести документ. При согласии система попытается провести документ и, в случае успеха, сразу выведет печатную форму. При отказе или ошибке проведения печать будет заблокирована.

Рассмотрим несколько практических способов реализации этой проверки в системе.

Способ 1. Прямая модификация модуля менеджера документа (классический вариант)

Этот способ подойдет в том случае, если ваша конфигурация уже снята с поддержки или вы сознательно вносите изменения непосредственно в основную конфигурацию. Нам потребуется внести изменения в модуль менеджера документа РеализацияТоваровИУслуг.

Разберем по шагам, как это сделать:

  1. Откройте конфигуратор вашей базы данных (предварительно обязательно сделайте резервную копию базы!).
  2. Найдите в дереве метаданных документ РеализацияТоваровИУслуг, нажмите на него правой кнопкой мыши и выберите Открыть модуль менеджера.
  3. Найдите экспортную процедуру ДобавитьКомандыПечати(КомандыПечати).
  4. Для каждой команды печати, которую вы хотите ограничить, добавьте строку установки свойства: КомандаПечати.ПроверкаПроведенияПередПечатью = Истина;.

Давайте посмотрим на пример кода, как будет выглядеть измененная процедура:


Процедура ДобавитьКомандыПечати(КомандыПечати) Экспорт

    // Расходная накладная
    КомандаПечати = КомандыПечати.Добавить();
    КомандаПечати.Идентификатор = "Накладная";
    КомандаПечати.Представление = НСтр("ru = 'Расходная накладная'");
    КомандаПечати.Обработчик = "УправлениеПечатьюБПКлиент.ВыполнитьКомандуПечати";
    КомандаПечати.СписокФорм = "ФормаСписка,ФормаВыбора,ФормаДокументаОбщая,ФормаДокументаТовары";
    // Внедряем проверку проведения перед печатью
    КомандаПечати.ПроверкаПроведенияПередПечатью = Истина;

    // Акт об оказании услуг
    КомандаПечати = КомандыПечати.Добавить();
    КомандаПечати.Идентификатор = "Акт";
    КомандаПечати.Представление = НСтр("ru = 'Акт об оказании услуг'");
    КомандаПечати.Обработчик = "УправлениеПечатьюБПКлиент.ВыполнитьКомандуПечати";
    КомандаПечати.СписокФорм = "ФормаСписка,ФормаВыбора,ФормаДокументаОбщая,ФормаДокументаУслуги";
    // Внедряем проверку проведения перед печатью
    КомандаПечати.ПроверкаПроведенияПередПечатью = Истина;

    // Универсальный передаточный документ (УПД)
    КомандаПечати = КомандыПечати.Добавить();
    КомандаПечати.Идентификатор = "УниверсальныйПередаточныйДокумент";
    КомандаПечати.Представление = НСтр("ru = 'Универсальный передаточный документ (УПД)'");
    КомандаПечати.Обработчик = "УчетНДСКлиент.ВыполнитьКомандуПечатиУниверсальныхПередаточныхДокументов";
    // Внедряем проверку проведения перед печатью
    КомандаПечати.ПроверкаПроведенияПередПечатью = Истина;

КонецПроцедуры

Такой подход надежно закроет возможность печати документов "в обход" проведения. Однако у него есть существенный минус — при обновлении конфигурации эти изменения могут быть затерты стандартным обновлением поставщика. Чтобы избежать этого, рассмотрим более современный и безопасный способ.

Способ 2. Использование расширения конфигурации (Рекомендуемый метод)

Расширения конфигурации позволяют внедрять собственный код в существующие процедуры без изменения типовой конфигурации. База данных остается на полной поддержке, а процесс обновлений проходит быстро и безболезненно.

Для реализации проверки проведения через расширение выполните следующие действия:

  1. Перейдите в меню Конфигурация — Расширения конфигурации и добавьте новое расширение (например, с именем ЗапретПечатиНепроведенных). Назначение расширения укажите как Адаптация.
  2. В дереве объектов расширения добавьте документ РеализацияТоваровИУслуг (нажмите правой кнопкой мыши на документ в основной конфигурации и выберите "Добавить в расширение").
  3. Откройте модуль менеджера документа в расширении и добавьте перехватчик для процедуры ДобавитьКомандыПечати с директивой выполнения &После.

Вместо того чтобы вручную прописывать свойство для каждой команды отдельно (как мы делали в первом способе), мы можем элегантно обойти всю коллекцию уже сформированных команд в цикле и установить нужное свойство для всех команд разом. Проанализируем пример кода:


&После("ДобавитьКомандыПечати")
Процедура ТМ_ДобавитьКомандыПечати(КомандыПечати)
    
    // Перебираем все сформированные типовые команды печати данного документа
    Для Каждого ТекущаяКоманда ИЗ КомандыПечати Цикл
        
        // Для реестра документов или специфических справок можно сделать исключение,
        // но для основных товарно-сопроводительных документов включаем проверку жестко
        Если ТекущаяКоманда.Идентификатор <> "Реестр" Тогда
            ТекущаяКоманда.ПроверкаПроведенияПередПечатью = Истина;
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

Этот код автоматически применит проверку ко всем печатным формам документа "Реализация товаров и услуг", включая расходную накладную, ТОРГ-12, Акт, УПД и счет-фактуру. Ваша типовая конфигурация при этом останется абсолютно чистой!

Способ 3. Глобальный запрет печати для всей информационной базы

Что делать, если руководство компании требует запретить печать непроведенных документов абсолютно для всех видов документов в системе (Поступления, Реализации, Перемещения, ПКО, РКО и т.д.)? Прописывать расширение для каждого менеджера документа вручную крайне трудозатратно.

К счастью, в БСП существует централизованная точка сбора всех команд печати. Мы можем использовать общий переопределяемый модуль УправлениеПечатьюПереопределяемый и его процедуру ПередДобавлениемКомандПечати. Этот модуль можно перехватить в нашем расширении.

Давайте посмотрим, как реализовать глобальный запрет:

  1. Добавьте в созданное ранее расширение общий модуль УправлениеПечатьюПереопределяемый.
  2. Создайте в модуле расширения процедуру-перехватчик:

&После("ПередДобавлениемКомандПечати")
Процедура ИмяПрефикса_ПередДобавлениемКомандПечати(ИмяФормы, КомандыПечати, СтандартнаяОбработка)
    
    // Данный цикл сработает при открытии любой формы, где формируются команды печати БСП
    Для Каждого СтрокаКоманды Из КомандыПечати Цикл
        
        // Устанавливаем проверку проведения для всех команд в системе
        СтрокаКоманды.ПроверкаПроведенияПередПечатью = Истина;
        
    КонецЦикла;
    
КонецПроцедуры

Этот простой шаг позволит централизованно защитить всю базу данных от печати черновиков документов, значительно повысив дисциплину пользователей в системе.

Способ 4. Реализация кастомного жесткого запрета (без предложения провести)

Как мы уже выяснили, стандартное поведение БСП при включенном флаге ПроверкаПроведенияПередПечатью предлагает пользователю провести документ. Но что, если вам нужен бескомпромиссный вариант — "Если документ не проведен, печать полностью заблокирована, кнопка выдает ошибку и проведение на лету запрещено"?

В этом случае нам потребуется перехватить процедуру открытия печатных форм на стороне клиента. Лучше всего сделать это через расширение общего клиентского модуля УправлениеПечатьюСлужебныйКлиент. Разберем пример реализации:


&Перед("ВыполнитьОткрытиеПечатнойФормы")
Процедура ИмяПрефикса_ВыполнитьОткрытиеПечатнойФормы(ИсточникДанных, ИдентификаторКоманды, ОбъектыНазначения, Форма, СтандартнаяОбработка)
    
    Для Каждого ДокументСсылка Из ОбъектыНазначения Цикл
        
        // Проверяем статус проведения документа через стандартный общий модуль
        Если Не ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ДокументСсылка, "Проведен") Тогда
            
            // Вызываем исключение, которое прерывает выполнение печати и сообщает пользователю о запрете
            Предупреждение = "Внимание! Печать непроведенного документа '" + Строка(ДокументСсылка) + "' строго запрещена политикой безопасности компании!";
            ВызватьИсключение Предупреждение;
            
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

При использовании такого кода пользователь не сможет обойти систему и провести документ в процессе отправки на печать — программа выдаст информационное сообщение об ошибке и полностью прекратит операцию печати.

Способ 5. Настройка проверки во Внешних печатных формах (ВПФ)

Если вы используете внешнюю печатную форму, подключенную через справочник Дополнительные отчеты и обработки, то изменения в конфигурации или расширении могут не затронуть ее выполнение. Нам нужно прописать это поведение непосредственно внутри самой внешней обработки.

В модуле внешней обработки найдите функцию СведенияОВнешнейОбработке(). При описании параметров команд добавьте новое свойство в таблицу команд:


// Функция возвращает сведения о внешней печатной форме
Функция СведенияОВнешнейОбработке() Экспорт
    
    ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОПараметрахРегистрации();
    
    // ... описание стандартных параметров (Наименование, Версия и т.д.) ...
    
    // Создаем таблицу команд
    Команды = ПолучитьТаблицуКоманд();
    
    // Добавляем команду печати
    НоваяКоманда = Команды.Добавить();
    НоваяКоманда.Представление = "Внешняя расходная накладная";
    НоваяКоманда.Идентификатор = "ВнешняяНакладная";
    НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипЗапускаВызовСерверногоМетода();
    
    // Явно указываем БСП на необходимость проверки проведения перед печатью внешней формы
    НоваяКоманда.Вставить("ПроверкаПроведенияПередПечатью", Истина);
    
    ПараметрыРегистрации.Команды = Команды;
    
    Возврат ПараметрыРегистрации;
    
КонецФункции

После перезагрузки файла внешней печатной формы в справочнике дополнительных обработок БСП автоматически применит к ней алгоритм контроля проведения перед отправкой на принтер или экран.

Способ 6. Что делать в конфигурации "1С:Управление нашей фирмой" (УНФ)?

Конфигурация 1С:УНФ также построена на современной технологической платформе и использует механизмы БСП. Описанный выше Способ 2 (через Расширение) будет работать там абсолютно идентично для всех новых документов.

Однако в старых релизах УНФ или при использовании сильно кастомизированных, самописных печатных форм, процедура вызова печати может происходить в обход стандартной БСП-команды. В таком случае проверку нужно встраивать прямо в тело функции формирования табличного документа.

Проанализируем пример доработки функции формирования печатной формы в УНФ:


Функция ПечатнаяФорма(МассивОбъектов, ОбъектыПечати) Экспорт
    
    ТабличныйДокумент = Новый ТабличныйДокумент;
    ПервыйДокумент = Истина;
    
    Для каждого ТекущийДокумент Из МассивОбъектов Цикл
        
        // Ручная проверка проведения каждого документа из переданного списка
        Если Не ТекущийДокумент.Проведен Тогда
            
            // Если документ не проведен, выводим предупреждение на экран
            ТекстОшибки = "Документ " + Строка(ТекущийДокумент) + " не проведен! Печать невозможна.";
            ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстОшибки);
            
            // Переходим к следующему документу или прерываем выполнение
            Продолжить; 
            
        КонецЕсли;
        
        // ... далее следует стандартный типовой код формирования макета ...
        
    КонецЦикла;
    
    Возврат ТабличныйДокумент;
    
КонецФункции

Этот способ гарантирует, что даже при вызове печати из нестандартных интерфейсных окон программа сначала проверит статус проведения конкретного объекта базы данных.

Важные технические нюансы

Реализуя подобные доработки, обязательно учитывайте архитектурные особенности крупных баз данных:

Мы детально разобрали все доступные и безопасные способы ограничения печати непроведенных документов. Рекомендуем использовать метод создания расширения (Способ 2) как наиболее гибкий и не влияющий на процесс последующих обновлений программы.

← На главную