Как реализовать печать чека ККМ из документа «Реализация» в 1С 7.7 (ТиС 9.2)

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

При работе в конфигурации «Торговля и Склад 7.7» (редакция 9.2) часто возникает необходимость пробить фискальный чек прямо из документа РеализацияТМЦ. Однако стандартный механизм «Ввод на основании» в данном случае не работает «из коробки», даже если проставить соответствующие галочки в Конфигураторе. Разберем подробно, почему возникает ошибка «Поле агрегатного объекта не обнаружено (Касса)» и как правильно реализовать эту задачу программно.

Анализ проблемы: почему не работает стандартный ввод на основании

Проанализируем ситуацию: когда мы пытаемся создать ЧекККМ на основании Реализации, платформа обращается к модулю формы нового документа. В типовом коде 1С 7.7 процедура ВводНаОсновании() ожидает, что у документа-основания есть реквизит Касса. Поскольку в документе Реализация этот реквизит отсутствует (так как это документ отгрузки, а не оплаты), система выдает ошибку:

{Документ.ЧекККМ.Форма.Модуль(879)}: Поле агрегатного объекта не обнаружено (Касса).

Простое добавление реквизита Касса в Реализацию не решит проблему полностью, так как возникнет конфликт бизнес-логики: в ТиС 9.2 и Реализация, и ЧекККМ делают движения по регистру ОстаткиТМЦ. Это приведет к двойному списанию товара со склада. Рассмотрим наиболее правильные способы решения этой задачи.

Способ 1: Программное создание документа ЧекККМ без проведения

Для того чтобы напечатать чек и при этом не нарушить складской учет, мы можем создать процедуру, которая программно сформирует ЧекККМ, заполнит его данными из реализации, но выполнит только функцию печати на фискальный регистратор. Рассмотрим пример кода, который можно разместить в модуле формы РеализацияТМЦ:


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

    // Переносим табличную часть
    ВыбратьСтроки();
    Пока (ПолучитьСтроку() = 1) Цикл
        ДокЧек.НоваяСтрока();
        ДокЧек.Номенклатура = Номенклатура;
        ДокЧек.Количество    = Количество;
        ДокЧек.Единица       = Единица;
        ДокЧек.Коэффициент   = Коэффициент;
        ДокЧек.Цена          = Цена;
        ДокЧек.Сумма         = Сумма;
    КонецЦикла;

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

В этом примере мы используем метод ОткрытьФорму() с параметром, чтобы форма чека при открытии знала, что ей нужно сразу отправить команду на кассовый аппарат.

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

Если вы все же решили модифицировать процедуру ВводНаОсновании в самом документе ЧекККМ, проанализируем, как сделать это максимально универсально, чтобы избежать ошибок при работе с разными типами документов-оснований. Используем проверку наличия реквизита через метаданные:


Если Метаданные.Документ(Вид()).РеквизитШапки("ДокументОснование").Выбран() <> 0 Тогда
    Если ТипЗначения(ДокументОснование) = 12 Тогда // Тип "Документ"
        Если ДокументОснование.Выбран() <> 0 Тогда
            // Проверяем, есть ли у документа-основания реквизит "Касса"
            Если Метаданные.Документ(ДокументОснование.Вид()).РеквизитШапки("Касса").Выбран() <> 0 Тогда
                Касса = ДокументОснование.Касса;
            Иначе
                // Если реквизита нет (как в Реализации), устанавливаем кассу по умолчанию
                Касса = глПользователь.КассаПоУмолчанию; 
            КонецЕсли;
        КонецЕсли;
    КонецЕсли;
КонецЕсли;

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

Решение проблемы «Объект заблокирован»

Часто при попытке записи номера чека обратно в Реализацию из внешней обработки возникает ошибка: «Объект заблокирован». Выясним причину: это происходит потому, что форма реализации в данный момент открыта пользователем, и объект находится в состоянии редактирования.

Рассмотрим пути обхода:

  1. Запись в комментарий: Если вам нужно просто сохранить информацию о чеке, записывайте её в текстовое поле Комментарий, которое часто доступно для записи без полной блокировки транзакции.
  2. Использование внешней печатной формы (ВПФ): Современные обработки для онлайн-касс под 1С 7.7 позволяют печатать чек как обычную печатную форму. В этом случае данные о кассовой операции лучше хранить в отдельном лог-файле или специализированном справочнике, чтобы не конфликтовать с открытыми формами документов.
  3. Закрытие формы: Перед пробитием чека программно вызывайте Форма.Закрыть(0), если это допустимо в вашем бизнес-процессе.

Рекомендованная методика работы (бизнес-логика)

Проанализируем стандартную логику 1С:Торговля и Склад. Правильный путь оплаты оптовой отгрузки (Реализации) выглядит так: Реализация -> Приходный кассовый ордер (ПКО).

В современных обновлениях ТиС, адаптированных под 54-ФЗ (онлайн-кассы), кнопка «Чек» добавлена именно в документ ПКО. Рассмотрим преимущества этого метода:

Если же ваша цель — розничная торговля, где момент оплаты совпадает с отгрузкой, рассмотрите возможность использования интерфейса «Рабочее место кассира» или документа ЧекККМ как первичного, не создавая на его основе Реализацию вручную.

← На главную