Как внести корректировки в чек в 1С Розница 2.3 перед его фискализацией и избежать ошибок?

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

При работе с программным обеспечением 1С:Розница 2.3 может возникнуть необходимость внести изменения в данные чека непосредственно перед его фискализацией. Эта задача требует глубокого понимания механики обмена данными между 1С, контрольно-кассовой техникой (ККТ) и Оператором Фискальных Данных (ОФД). Мы рассмотрим, как устроен этот процесс, как найти нужную точку для внедрения корректировок и какие могут возникнуть сложности, в частности, ошибка "неверная сумма налога".

Понимание процесса передачи данных и фискализации

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

  1. Формирование пакета данных в 1С. На начальном этапе программа 1С:Розница формирует XML-пакет, который содержит все необходимые сведения о чеке (позиции товаров, цены, суммы, данные об оплате и т.д.). Этот пакет является своего рода "черновиком" чека.

  2. Передача данных через драйвер ККТ. Сформированный XML-пакет передается из 1С в драйвер ККТ. Драйвер является посредником между 1С и физическим фискальным регистратором. Важно понимать, что в этот момент данные еще не фискализированы.

  3. Фискализация в ККТ и запись в ФН. Драйвер ККТ отправляет полученные данные непосредственно в контрольно-кассовую технику. ККТ регистрирует (фискализирует) операцию, то есть присваивает ей фискальный признак, и записывает эти данные в фискальный накопитель (ФН). Фискальный накопитель — это защищенное устройство, которое хранит все фискальные данные.

  4. Отправка данных в ОФД. После успешной записи данных в ФН, сам фискальный накопитель формирует пакет данных для отправки Оператору Фискальных Данных (ОФД). Отправка происходит через интернет-соединение, настроенное в ККТ (или через подключение ККТ к компьютеру с доступом в интернет). Таким образом, именно ККТ (точнее, ФН внутри ККТ) самостоятельно передает данные в ОФД через встроенные параметры, а затем ОФД перенаправляет их в ФНС.

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

Идентификация точки для корректировки данных

Для внесения изменений в данные чека перед фискализацией нам необходимо найти соответствующую процедуру в конфигурации 1С, которая отвечает за подготовку этих данных. Изначально мы можем искать процедуру по названию, например, СформироватьXMLПакетДляФискализацияЧека, но она может отсутствовать или иметь другое название в зависимости от версии библиотеки подключаемого оборудования (БПО).

В конфигурации 1С:Розница 2.3 (и аналогичных конфигурациях, использующих БПО) ключевой точкой для перехвата и модификации данных является процедура ПодготовитьДанныеОперации. Эта процедура находится в общем модуле ОборудованиеЧекопечатающиеУстройстваВызовСервера. Она отвечает за окончательную подготовку структуры данных, которая будет передана в драйвер ККТ для фискализации. Ее расположение может зависеть от версии БПО, которую можно посмотреть в регистре сведений "Версии подсистем".

Пример реализации корректировки через расширение

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

Мы будем изменять процедуру ПодготовитьДанныеОперации в общем модуле ОборудованиеЧекопечатающиеУстройстваВызовСервера с использованием директивы &ИзменениеИКонтроль.

Шаг 1: Создание или модификация расширения

Откройте конфигурацию в режиме "Конфигуратор", создайте новое расширение или откройте существующее. В расширении добавьте общий модуль ОборудованиеЧекопечатающиеУстройстваВызовСервера (если его там нет) и переопределите функцию ПодготовитьДанныеОперации.

Шаг 2: Внесение кода для изменения цен и сумм

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


&ИзменениеИКонтроль("ПодготовитьДанныеОперации")
Функция склад_ПодготовитьДанныеОперации(ПараметрыПодключения, Команда, ПараметрыОперации)
    
    ДанныеОперации = Новый Структура;
    ДанныеОперации.Вставить("Результат", Истина);
    ДанныеОперации.Вставить("ТекстОшибки");
    
    #Вставка 
    // Меняем цену
    Если ТипЗнч(ПараметрыОперации.ДокументОснование) = Тип("ДокументСсылка.ЧекККМ") Тогда
        СуммаЧекаНовая = 0;
        Для Каждого товар Из ПараметрыОперации.ПозицииЧека Цикл
            Процент13 = (товар.Цена / 100) * 13;
            товар.Цена = товар.Цена - Процент13;
            товар.ЦенаСоСкидками = товар.Цена;
            товар.Сумма = товар.Количество * товар.Цена;
            СуммаЧекаНовая = СуммаЧекаНовая + товар.Сумма;
        КонецЦикла;
        // Корректируем сумму оплаты, предполагая одну позицию в ТаблицеОплат
        Если ПараметрыОперации.ТаблицаОплат.Количество() > 0 Тогда
            ПараметрыОперации.ТаблицаОплат[0].Сумма = СуммаЧекаНовая;
        КонецЕсли;
    КонецЕсли;
    #КонецВставки 
    
    // ... Остальной типовой код процедуры ПодготовитьДанныеОперации ...
    // В данном примере мы приводим только часть для вставки,
    // но в реальности нужно вызывать типовую реализацию
    // или полностью переписывать процедуру, что менее предпочтительно.
    // Если вы используете &ИзменениеИКонтроль, то ваш код будет выполнен
    // перед или после (в зависимости от местоположения директивы)
    // выполнения типовой процедуры. В данном случае это будет "до" ее основного исполнения.

    // Для полного функционала нужно будет вызвать типовую реализацию
    // Если вы полностью переопределяете, то нужно скопировать весь типовой код
    // и вставить свои модификации.
    // Правильнее было бы использовать &Перед или &После
    // или как сделано в примере с #Вставка, но только если типовая процедура
    // имеет аналогичную структуру для такого рода вставок.
    
    // Для простоты примера, представим, что это полный перехват и дальше идет
    // вызов оригинальной функции с уже модифицированными параметрами.
    // В случае &ИзменениеИКонтроль обычно подразумевается, что мы вставляем свой код
    // в определенное место или полностью заменяем часть функции.
    // Если это вставка, то после нашей #Вставки должен идти вызов типовой процедуры
    // или ее скопированная часть, которая использует модифицированные ПараметрыОперации.
    
    // В контексте использования &ИзменениеИКонтроль обычно подразумевается,
    // что мы ДОПОЛНЯЕМ функционал, а не полностью переопределяем всю процедуру.
    // Если мы хотим изменить параметры ДО вызова типовой логики, то код выше
    // вполне подходит. Затем мы должны вызвать типовую логику,
    // передав ей уже измененные параметры.
    
    // Предполагается, что после нашей #Вставки, исходная процедура
    // (или ее часть, если используется &ИзменениеИКонтроль для вставки)
    // будет использовать модифицированные ПараметрыОперации.
    
    // ВНИМАНИЕ: Для реальной работы с &ИзменениеИКонтроль необходимо
    // либо тщательно скопировать и интегрировать ваш код в тело типовой процедуры,
    // либо использовать более простые &Перед / &После, если это возможно
    // и позволяет достичь цели.
    // Приведенный выше код подразумевает, что модификации вносятся в структуру
    // ПараметрыОперации, которая затем будет обработана основной логикой.
    
    Возврат ДанныеОперации; // Этот возврат может быть лишним или изменен в зависимости от полной реализации.
                           // Если это действительно &ИзменениеИКонтроль, то он должен вернуть результат
                           // либо типовой функции, либо свой, после обработки.
                           // В данном случае, это скорее пример изменения объекта ПараметрыОперации "по ссылке".
    
КонецФункции

В этом примере мы делаем следующее:

  1. Создаем новую структуру ДанныеОперации для возврата результата.
  2. Проверяем, что ДокументОснование имеет тип ДокументСсылка.ЧекККМ, чтобы выполнять изменения только для чеков ККМ.
  3. Итерируем по каждой позиции чека в ПараметрыОперации.ПозицииЧека.
  4. Вычисляем 13% от исходной цены и вычитаем их из товар.Цена.
  5. Обновляем товар.ЦенаСоСкидками и товар.Сумма.
  6. Накапливаем новую общую сумму чека в СуммаЧекаНовая.
  7. Корректируем сумму в ПараметрыОперации.ТаблицаОплат[0].Сумма, которая передается как сумма оплаты. Мы предполагаем, что существует хотя бы одна запись в таблице оплат.

Шаг 3: Улучшение кода для предотвращения ошибок при закрытии смены

Важно учесть, что процедура ПодготовитьДанныеОперации может вызываться не только для фискализации чека, но и для других операций, например, при закрытии смены (формировании Z-отчета). В таких случаях объект ПараметрыОперации может не содержать свойства ДокументОснование или ПозицииЧека. Если мы не предусмотрим такую проверку, наш код может вызвать ошибку. Добавим проверку на наличие свойства ДокументОснование.


&ИзменениеИКонтроль("ПодготовитьДанныеОперации")
Функция склад_ПодготовитьДанныеОперации(ПараметрыПодключения, Команда, ПараметрыОперации)
    
    ДанныеОперации = Новый Структура;
    ДанныеОперации.Вставить("Результат", Истина);
    ДанныеОперации.Вставить("ТекстОшибки");
    
    #Вставка 
    // Меняем цену
    // Делаем проверку, что это не закрытие смены и другие операции
    Если ПараметрыОперации.Свойство("ДокументОснование") Тогда
        Если ТипЗнч(ПараметрыОперации.ДокументОснование) = Тип("ДокументСсылка.ЧекККМ") Тогда
            СуммаЧекаНовая = 0;
            Для Каждого товар Из ПараметрыОперации.ПозицииЧека Цикл
                // Убедимся, что товар.Цена является числом, чтобы избежать ошибок
                Если ТипЗнч(товар.Цена) = Тип("Число") Тогда
                    Процент13 = (товар.Цена / 100) * 13;
                    товар.Цена = товар.Цена - Процент13;
                    товар.ЦенаСоСкидками = товар.Цена;
                    товар.Сумма = товар.Количество * товар.Цена;
                    СуммаЧекаНовая = СуммаЧекаНовая + товар.Сумма;
                    
                    // !!! КРИТИЧНО: Коррекция налоговых полей
                    // Если ККТ рассчитывает налоги, то нам нужно
                    // либо обнулить их, либо пересчитать.
                    // Если драйвер ожидает поля типа СуммаНалога,
                    // их также нужно скорректировать.
                    // Пример: Если есть поле СуммаНалога, нужно его пересчитать.
                    // Если товар.Свойство("СуммаНалога") Тогда
                    //     товар.СуммаНалога = ... // Пересчет НДС для новой цены
                    // КонецЕсли;
                    // Если ККТ рассчитывает НДС по ставке, то достаточно,
                    // чтобы СтавкаНДС была корректной для позиции.
                КонецЕсли;
            КонецЦикла;
            // Корректируем сумму оплаты, предполагая одну позицию в ТаблицеОплат
            Если ПараметрыОперации.ТаблицаОплат.Количество() > 0 Тогда
                ПараметрыОперации.ТаблицаОплат[0].Сумма = СуммаЧекаНовая;
            КонецЕсли;
        КонецЕсли;
    КонецЕсли;
    #КонецВставки 
    
    // ... Остальной типовой код процедуры ПодготовитьДанныеОперации ...
    // В данном случае, мы предполагаем, что наша вставка изменяет параметры,
    // которые затем будут использованы типовой логикой.
    
    Возврат ДанныеОперации;
    
КонецФункции

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

Анализ и решение ошибки "Неверная сумма налога"

После реализации модификации кода, вы можете столкнуться с ошибкой "неверная сумма налога" на реальном ККТ, хотя на эмуляторе все работает корректно. Это одна из наиболее частых проблем при программной корректировке фискальных данных. Давайте выясним причины и способы ее решения.

Причины возникновения ошибки "Неверная сумма налога"

Ошибка "неверная сумма налога" обычно возникает из-за расхождений между тем, как сумма налогов рассчитана в 1С (после наших модификаций), и тем, что ожидает или рассчитывает сама ККТ. Мы проанализируем основные причины:

  1. Автоматический расчет НДС в ККТ. Большинство современных ККТ (например, АТОЛ) рассчитывают итоговую сумму НДС по чеку автоматически. Они делают это исходя из ставок НДС, указанных для каждой позиции товара в чеке, а не получают готовую сумму НДС для всего чека из 1С. Ваш код изменяет поля товар.Цена, товар.ЦенаСоСкидками, товар.Сумма и ПараметрыОперации.ТаблицаОплат[0].Сумма, но при этом может не затрагивать явно информацию о налогах для каждой позиции (например, товар.СуммаНалога или товар.СтавкаНДС). Это приводит к тому, что ККТ видит измененную цену и сумму товара, но ожидает другую сумму НДС, соответствующую оригинальной цене, или некорректно рассчитывает НДС по новой цене из-за отсутствия явных указаний.

  2. Несоответствие ставок НДС. Убедитесь, что ставки НДС, указанные в 1С для каждой позиции товара, соответствуют ставкам, настроенным непосредственно в ККТ. При изменении цен крайне важно также пересчитывать соответствующие суммы НДС для каждой позиции чека, если ККТ не способна самостоятельно корректно это сделать или если драйвер ожидает, что эти данные будут переданы из 1С.

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

  4. Актуальность прошивки и драйверов. Для корректной работы с налоговыми ставками (например, с новыми ставками, которые периодически вводятся) критически важно, чтобы прошивка вашей ККТ и драйвер были актуальными и поддерживали требуемые форматы фискальных документов (ФФД). Обновления программного обеспечения ККТ и драйверов часто включают изменения, касающиеся расчета и передачи НДС.

  5. Свойство СтавкаНДС и СуммаНалога. При изменении цены товара в процедуре ПодготовитьДанныеОперации вам, вероятно, потребуется также скорректировать поля, связанные с налогом, для каждой позиции в ПараметрыОперации.ПозицииЧека. Если в структуре ПозицииЧека есть поля, явно указывающие ставку НДС (СтавкаНДС) или сумму налога (СуммаНалога) для данной позиции, то их также следует пересчитать в соответствии с вашей новой ценой и логикой налогообложения. Тег 1199, обозначающий ставку налога, является обязательным для каждого предмета расчета во всех версиях ФФД.

Рекомендуемые действия для исправления ошибки "Неверная сумма налога"

Для устранения этой распространенной ошибки мы рекомендуем следующий комплексный подход:

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

  2. Коррекция налоговых полей. Попробуйте явно пересчитывать и изменять поля, отвечающие за НДС для каждой позиции в ПараметрыОперации.ПозицииЧека. Если в структуре ПозицииЧека присутствуют поля СуммаНалога или СтавкаНДС, их необходимо обновить в соответствии с новой ценой и выбранной налоговой ставкой. Например, если вы уменьшаете цену, то и сумма НДС, рассчитанная от этой цены, должна быть соответствующим образом уменьшена. Если таких полей нет, и ККТ рассчитывает НДС по ставке, убедитесь, что СтавкаНДС для каждой позиции установлена корректно и соответствует налоговой ставке для новой цены.

  3. Обновление ПО. Проверьте и при необходимости обновите прошивку ККТ и версию драйвера до актуальных, сертифицированных 1С версий. Производители ККТ регулярно выпускают обновления, исправляющие ошибки в расчетах налогов и поддерживающие новые требования ФНС и ФФД.

  4. Проверка настроек ККТ. Убедитесь, что настройки налоговых ставок в самой ККТ (через ее утилиту или меню) соответствуют тем, что используются в 1С. Расхождения здесь могут быть источником проблемы.

  5. Чек коррекции. В случае, если чек уже пробит с ошибкой и покупатель покинул торговую точку, стандартным способом исправления является оформление чека коррекции. 1С:Розница 2.3 поддерживает создание чеков коррекции на основании ошибочно пробитого чека ККМ. Это позволяет скорректировать фискальные данные без повторного взаимодействия с покупателем и уведомить ФНС о допущенной ошибке.

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

← На главную