Как реализовать частичную оплату чека ККМ через драйвер АТОЛ в 1С?

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

При прямой интеграции торгового оборудования с 1С через драйвер ККТ часто возникает вопрос: как правильно пробить чек, если клиент вносит только часть суммы? Если с полной оплатой все достаточно просто — касса сама автоматически подсчитывает итог по позициям и закрывает чек, — то при частичной оплате стандартный алгоритм вызывает ошибку ККТ. Драйвер не позволяет закрыть чек, если сумма переданных оплат меньше суммарной стоимости товаров.

В этой статье мы подробно разберем, как устроена логика частичной оплаты в ККТ АТОЛ (на примере драйвера версии 8), какие реквизиты необходимо передавать для ФФД 1.05 и как правильно использовать методы драйвера для успешного закрытия чека. При необходимости можно воспользоваться готовым рабочим местом кассира с поддержкой онлайн-касс АТОЛ.

В чем заключается основная проблема?

Проанализируем ситуацию: в чеке содержатся товарные позиции на общую сумму 5000 рублей. Покупатель вносит наличными только 2000 рублей, а оставшиеся 3000 рублей обязуется доплатить позже. Если мы просто укажем в чеке позиции на 5000 рублей, передадим признак способа расчета «Частичный расчет» и попытаемся закрыть чек передав оплату в 2000 рублей, ККТ выдаст ошибку несоответствия сумм. Касса «ожидает», что вся сумма чека будет полностью распределена по типам оплаты.

Выясним причину этой логики. Согласно требованиям Федерального закона № 54-ФЗ и форматам фискальных документов (ФФД), общая сумма всех видов плат в чеке должна до копейки совпадать с суммой всех зарегистрированных товарных позиций. Чтобы решить эту задачу, нам необходимо использовать не только фактическую оплату (наличные или безналичные), но и неденежные типы оплат, такие как Кредит (Постоплата).

Шаг 1. Настройка признака способа расчета для позиций (Тег 1214)

Для каждой позиции в чеке мы должны правильно указать признак способа расчета. В драйвере АТОЛ 8 за это отвечает свойство PaymentMode. Рассмотрим основные значения этого свойства:

  1. 1 — Предоплата 100% (полная предварительная оплата до передачи товара).
  2. 2 — Предоплата частичная (внесение части средств до передачи товара).
  3. 3 — Аванс (когда список товаров еще не определен окончательно).
  4. 4 — Полный расчет (полная оплата в момент передачи товара — стандартный режим).
  5. 5 — Частичный расчет и кредит (применяется, когда клиент вносит часть суммы в момент получения товара).
  6. 6 — Передача в кредит (отпуск товара полностью в долг без первоначального взноса).
  7. 7 — Оплата кредита (когда клиент приносит оставшиеся деньги за ранее полученный товар).

В нашем случае для каждой строки номенклатуры перед завершением регистрации позиции необходимо установить значение 5:


ECR.PaymentMode = 5; // Частичный расчет и кредит
ECR.EndItem();

Шаг 2. Разделение типов оплаты чека (Тег 1081)

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

Каждый вызов метода Payment() регистрирует оплату определенного типа на указанную сумму. За тип оплаты отвечает свойство TypeClose:

Важное правило: Сумма всех вызванных методов Payment() должна в точности равняться сумме всех позиций в чеке!

Шаг 3. Реализация алгоритма в коде 1С

Рассмотрим по шагам, как должен выглядеть финальный блок кода закрытия чека при частичной оплате. Допустим, общая сумма товаров составляет 1333 рубля, а клиент вносит наличными только 1000 рублей. Оставшиеся 333 рубля мы обязаны закрыть видом оплаты «Кредит» (тип закрытия 3).

Проанализируем пример кода на языке 1С:


// Переменные для расчетов
СуммаЧека = 1333;
ФактическиОплачено = 1000;
СуммаКредита = СуммаЧека - ФактическиОплачено;

// 1. Регистрируем оплату наличными (1000 рублей)
ECR.TypeClose = 0; // Наличные
ECR.PointPosition = 2; // Количество знаков после запятой
ECR.Summ = ФактическиОплачено;
ECR.Payment();

// 2. Регистрируем оставшуюся сумму как Кредит/Постоплату (333 рубля)
ECR.TypeClose = 3; // Кредит / Последующая оплата
ECR.PointPosition = 2;
ECR.Summ = СуммаКредита;
ECR.Payment();

// 3. Закрываем чек на кассе
ECR.CloseCheck();

Если бы клиент оплачивал часть картой, мы бы изменили ECR.TypeClose для первой оплаты на 1 (Электронные). Такой подход позволяет кассовому аппарату корректно сопоставить суммы и закрыть чек без зависаний драйвера.

Комплексный пример интеграции частичной оплаты

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


Процедура ПробитьЧекЧастичнойОплаты(ДокументРеализация, ФактическаяОплатаКлиента)
    
    ECR.DeviceEnabled = 1;
    Если ECR.ResultCode <> 0 Тогда
        Предупреждение("ККМ не подключена!");
        Возврат;
    КонецЕсли;
    
    ECR.Password = "1";
    
    // Входим в режим регистрации
    ECR.Mode = 1;
    Если ECR.SetMode() <> 0 Тогда
        Предупреждение("Касса не смогла войти в режим регистрации чеков!");
        Возврат;
    КонецЕсли;
    
    // Кассир (Тег 1021)
    ECR.AttrNumber = 1021; 
    ECR.AttrValue = "Иванов И.И."; 
    ECR.WriteAttribute(); 
    
    ECR.CheckType = 1; // Приход денег
    ECR.CheckMode = 1; // Печатать на ленте
    ECR.OpenCheck(); 
    
    ОбщаяСуммаЧека = 0;
    
    // Цикл по товарным позициям
    Для Каждого Стр Из ДокументРеализация.Товары Цикл  
        ECR.BeginItem();
        ECR.StreamFormat = 5;
        
        ECR.Name = Стр.Номенклатура.Наименование + " шт"; 
        ECR.Price = Стр.Цена; 
        ECR.Quantity = Стр.Количество;
        
        СтоимостьПозиции = Стр.Цена * Стр.Количество;
        ECR.Summ = СтоимостьПозиции;
        ОбщаяСуммаЧека = ОбщаяСуммаЧека + СтоимостьПозиции;
        
        // Указываем тип налога
        ECR.TaxTypeNumber = 4; // Без НДС
        ECR.Tax = 4;
        
        // Указываем признак способа расчета - Частичная оплата и кредит
        ECR.PaymentMode = 5; 
        
        ECR.EndItem();
    КонецЦикла;
    
    // Расчет сумм оплат
    Если ФактическаяОплатаКлиента > ОбщаяСуммаЧека Тогда
        ФактическаяОплатаКлиента = ОбщаяСуммаЧека; // Исключаем переплату
    КонецЕсли;
    
    СуммаПостоплаты = ОбщаяСуммаЧека - ФактическаяОплатаКлиента;
    
    // Пробиваем фактическую оплату (например, Наличными)
    Если ФактическаяОплатаКлиента > 0 Тогда
        ECR.TypeClose = 0; // 0 - Наличные, 1 - Безналичные
        ECR.PointPosition = 2;
        ECR.Summ = ФактическаяОплатаКлиента;
        ECR.Payment();
    КонецЕсли;
    
    // Пробиваем сумму, уходящую в долг (Кредит)
    Если СуммаПостоплаты > 0 Тогда
        ECR.TypeClose = 3; // Последующая оплата (Кредит)
        ECR.PointPosition = 2;
        ECR.Summ = СуммаПостоплаты;
        ECR.Payment();
    КонецЕсли;
    
    // Окончательное закрытие чека
    ECR.CloseCheck();
    
КонецПроцедуры

Важные рекомендации при работе с частичной оплатой

Рассмотрим несколько критически важных моментов, с которыми вы можете столкнуться при практическом внедрении этого механизма:

  1. Проблема округления и копеек. Если вы распределяете частичную оплату по нескольким позициям чека вручную в вашей учетной системе, всегда проверяйте итоговые суммы. Касса не примет чек, если математический расчет стоимости позиций разойдется с суммой оплат хотя бы на одну копейку. Рекомендуется закрывать возможные погрешности округления на последней позиции чека.
  2. Второй чек (Погашение кредита). Помните, что частичная оплата (признак способа расчета 5) обязывает вас в будущем пробить второй чек, когда клиент принесет оставшиеся деньги. Во втором чеке признак способа расчета должен быть равен 7 (Оплата кредита), а тип оплаты — Наличные или Безналичные (в зависимости от того, как клиент доплачивает долг). При этом сам товар повторно в чек не заносится в качестве отгрузки, а оформляется именно как платеж по кредиту.
  3. Переход на драйвер версии 10. Драйвер АТОЛ 8-й версии давно признан устаревшим. В современных реалиях настоятельно рекомендуется переходить на 10-й драйвер. В 10-й версии работа с оплатами реализована гораздо удобнее через JSON-задания. Вам больше не придется вызывать метод Payment() по отдельности в цикле — достаточно будет передать массив оплат в едином структурированном запросе, что сводит к минимуму вероятность зависания ККТ в полузакрытом состоянии.
← На главную