Как автоматически создавать Счет-фактуру на основании Расходной накладной в УНФ 1.6 через расширение

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

В типовой практике ведения учета в конфигурации «1С:Управление нашей фирмой» (УНФ) часто возникает задача автоматизации рутинных операций. Одной из таких задач является автоматическое создание и проведение документа Счет-фактура (СФ) сразу после того, как пользователь провел документ Расходная накладная (РТУ). Это позволяет избежать забывчивости сотрудников и гарантирует наличие всех необходимых документов для налогового учета.

Рассмотрим, как реализовать этот механизм с помощью расширения, разберем типичные ошибки в коде запросов и выясним, почему расширение может «не подхватываться» системой.

Анализ исходной задачи и выбор события

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

Проанализируем структуру процедуры. Нам важно убедиться, что:

  1. Документ-основание (РТУ) успешно проведен.
  2. Счет-фактура для данной накладной еще не была создана ранее (чтобы избежать дублирования).
  3. Новый документ корректно заполняется на основании данных РТУ.

Типичные ошибки в запросе к базе данных

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


ГДЕ
    РасходнаяНакладная.Проведен = &Проведен
    И СчетФактура.Ссылка ЕСТЬ NULL
    И РасходнаяНакладная.Ссылка = &Ссылка

Проанализируем ситуацию: в языке запросов 1С поле Проведен является булевым. Передача параметра &Проведен излишня и часто ведет к ошибке, если разработчик забыл установить этот параметр в коде 1С. Правильнее использовать прямое обращение к полю.

Исправленный вариант условия запроса должен выглядеть так:


ГДЕ
    РасходнаяНакладная.Проведен
    И СчетФактура.Ссылка ЕСТЬ NULL
    И РасходнаяНакладная.Ссылка = &Ссылка

Здесь условие РасходнаяНакладная.Проведен само по себе возвращает Истина или Ложь, что является корректным для секции ГДЕ.

Проблема связи документов через табличные части

В 1С:УНФ и других современных конфигурациях связь между Счетом-фактурой и основанием часто реализуется через табличную часть ДокументыОснования. При написании запроса с ЛЕВОЕ СОЕДИНЕНИЕ важно правильно указать условие связи. Если мы просто соединяем документы, мы можем получить пустой результат или, наоборот, дубли. Рассмотрим правильный способ проверки существования подчиненного документа:


Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |    СчетФактура.Ссылка КАК Ссылка
    |ИЗ
    |    Документ.СчетФактура КАК СчетФактура
    |ГДЕ
    |    СчетФактура.ДокументыОснования.ДокументОснование = &Ссылка
    |    И НЕ СчетФактура.ПометкаУдаления";

Такой запрос гораздо эффективнее: он ищет хотя бы один существующий и не помеченный на удаление документ СчетФактура, в табличной части которого указана наша накладная.

Реализация программного создания Счета-фактуры

Когда мы убедились, что Счет-фактура отсутствует, перейдем к ее созданию. Разберем по шагам процесс заполнения данных. Важно помнить, что в УНФ для корректного заполнения СФ недостаточно просто создать объект, нужно вызвать процедуру Заполнить(), которая инициализирует параметры на основании переданной структуры или объекта-основания.

Посмотрим на пример правильной реализации процедуры в расширении:


&НаСервере
Процедура СА_АФСФ_ПослеЗаписиНаСервереПосле(ТекущийОбъект, ПараметрыЗаписи)
    
    // Проверяем, что документ проведен. 
    // Используем ТекущийОбъект, так как это расширение формы, и объект уже записан.
    Если Не ТекущийОбъект.Проведен Тогда
        Возврат;
    КонецЕсли;

    // Проверяем наличие существующего СФ
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |    СчетФактура.Ссылка КАК Ссылка
        |ИЗ
        |    Документ.СчетФактура КАК СчетФактура
        |ГДЕ
        |    СчетФактура.ДокументыОснования.ДокументОснование = &Основание
        |    И НЕ СчетФактура.ПометкаУдаления";
    
    Запрос.УстановитьПараметр("Основание", ТекущийОбъект.Ссылка);
    РезультатЗапроса = Запрос.Выполнить();
    
    Если Не РезультатЗапроса.Пустой() Тогда
        // СФ уже существует, выходим
        Возврат;
    КонецЕсли;

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

Почему расширение не работает: диагностика

Если код написан верно, но результат (созданный СФ) отсутствует, выясним причину с помощью последовательной диагностики.

1. Проверка активности расширения. Убедитесь, что в списке расширений у вашего расширения снята галочка Безопасный режим. В безопасном режиме работа с запросами к некоторым объектам метаданных и запись новых объектов могут быть ограничены программно.

2. Метод «Сообщить». Если отладчик не останавливается на точках останова в расширении (что часто бывает в клиент-серверных вариантах или при отсутствии ключа -debug на сервере), воспользуйтесь старым проверенным способом. Добавьте в начало процедуры строку Сообщить("Код расширения запущен!");. Если при нажатии кнопки «Провести и закрыть» сообщение не появляется — значит, событие расширения вообще не вызывается.

3. Проверка параметров отладки. В файловых базах отладка обычно работает сразу. В серверных базах убедитесь, что:

Рекомендация по использованию Критериев отбора

Вместо прямого запроса к табличным частям документа СчетФактура, профессиональным подходом считается использование Критериев отбора. В типовых конфигурациях существует критерий СвязанныеДокументы. Проверка через него работает быстрее, так как индексы платформы оптимизированы под эти задачи.

Проанализируем, как это упрощает код. Вместо написания текста SQL-запроса вы можете вызвать метод критерия отбора, передав туда ссылку на вашу Расходную накладную. Если в возвращаемом массиве (или таблице) есть документы типа СчетФактура, значит, создание нового документа не требуется.

Заключение

Мы рассмотрели процесс автоматизации создания Счета-фактуры в УНФ 1.6 через механизмы расширения. Основное внимание стоит уделять корректности запросов (особенно работе с булевыми полями и проверке на NULL) и настройкам безопасности самого расширения. Помните, что использование блока Попытка...Исключение при записи документа является обязательным стандартом разработки, так как проведение подчиненного документа может сорваться из-за нехватки прав доступа или незаполненных обязательных реквизитов.

← На главную