Многие программисты и пользователи 1С сталкиваются со следующей проблемой: онлайн-касса Штрих-М отлично печатает чеки продажи и чеки возврата день в день, но напрочь отказывается печатать чек "Возврат прихода", если покупатель возвращает товар на следующий день. Внешне это выглядит так: программа отправляет команду на фискальный регистратор (ФР), цикл по товарам проходит, но аппарат молчит, чек не выходит, а конфигурация не выдает явного сообщения об ошибке. Давайте подробно разберем эту ситуацию, проанализируем причины такого поведения ККТ и выясним, как правильно доработать обработку обслуживания для 1С 7.7.
Для начала рассмотрим методологическую сторону вопроса. До массового внедрения онлайн-касс возврат средств не в день покупки оформлялся исключительно из главной кассы предприятия через Расходный кассовый ордер (РКО). Пробивать чек по самому кассовому аппарату не требовалось.
С вступлением в силу требований 54-ФЗ логика кардинально изменилась. Сейчас кассовый чек с признаком расчета Возврат прихода необходимо пробивать на фискальном регистраторе всегда, вне зависимости от того, когда произошла покупка — час назад, вчера или месяц назад. В коде драйвера Штрих-М за этот тип операции отвечает свойство CheckType = 2. Если вы формируете возврат, это значение должно передаваться в драйвер кассы в обязательном порядке.
Перейдем к самой частой технической причине проблемы. Почему ФР просто не отбивает чек и не выдает никаких видимых ошибок? Разберем логику работы ККТ Штрих-М.
Кассовый аппарат ведет строгий аппаратный контроль наличности. Когда утром кассир открывает кассовую смену, счетчик наличных денег в ФР обнуляется. Если до момента возврата продаж за наличные еще не было (или их сумма меньше суммы возврата), касса считает, что в денежном ящике пусто. С точки зрения драйвера, вы пытаетесь выдать покупателю деньги, которых физически нет в кассе. Запрос блокируется оборудованием.
Как это исправить в рабочем процессе? Посмотрим на правильный алгоритм действий кассира:
Если касса "молчит", значит, ошибка все-таки возвращается драйвером, но ваш код в 1С ее скрывает от пользователя. Проанализируем стандартный кусок кода, который часто встречается в самописных или старых доработанных конфигурациях 1С 7.7 (ТиС):
Если Объект.ResultCode <> 0 Тогда
ОписаниеРезультата = ПолучитьОписаниеРезультата(Объект);
АннулированиеЧека(Объект, Пароль);
ОтключитьсяОтФР(Объект, Пароль, 0);
Возврат 0;
КонецЕсли;
Обратите внимание: метод ПолучитьОписаниеРезультата (или прямое обращение к свойству ResultDescription) получает текст ошибки от драйвера, записывает его в переменную, аннулирует чек и закрывает соединение. Однако вывода на экран нет. Пользователь остается в неведении.
Исправим этот участок кода, чтобы драйвер сам "сказал" нам, что пошло не так. Если проблема в пустом денежном ящике, драйвер вернет код 105 (Не хватает наличности в кассе) или аналогичный текст.
Если Объект.ResultCode <> 0 Тогда
ОписаниеРезультата = Объект.ResultDescription;
// Обязательно сообщаем кассиру причину отказа!
Сообщить("Ошибка печати чека: " + ОписаниеРезультата);
// Или используем модальное окно:
// Предупреждение("Ошибка ККТ: " + ОписаниеРезультата);
АннулированиеЧека(Объект, Пароль);
ОтключитьсяОтФР(Объект, Пароль, 0);
Возврат 0;
КонецЕсли;
Если клиент оплачивал покупку банковской картой, то и возврат должен осуществляться на карту по безналу. В этом случае ККТ не контролирует наличие наличных денег в ящике, ведь физически купюры не передаются.
Здесь важно строго следить за тем, в какие свойства драйвера передается сумма чека. В драйвере Штрих-М свойство Summ1 закреплено за оплатой наличными, а свойства Summ2 и Summ3 — за электронными средствами (банковскими картами). Проанализируем пример правильной передачи сумм:
// Док.птдБезнал - флаг того, что оплата/возврат идет по терминалу
Если Док.птдБезнал = 1 Тогда
Объект.Summ2 = СуммаЧека; // Записываем сумму в регистр электронных оплат
Объект.Summ1 = 0; // Наличные строго обнуляем
Объект.Summ3 = 0;
Иначе
// Если возврат наличными
Объект.Summ2 = 0;
Объект.Summ1 = СуммаЧека; // Записываем в наличные
Объект.Summ3 = 0;
КонецЕсли;
Если при возврате на карту в 1С программно допущена ошибка и сумма уходит в Summ1, ФР снова расценит это как выдачу наличных и выдаст ошибку "Не хватает наличности в кассе".
Особое внимание уделим ситуации, когда на другой день возвращается не весь чек, а лишь часть товаров (одна или несколько позиций). Фискальные регистраторы Штрих-М производят крайне жесткую математическую проверку перед тем, как закрыть чек методом FNCloseCheckEx.
Алгоритм кассы суммирует произведение цены на количество по каждой строке (Price * Quantity). Итоговая сумма по всем переданным позициям должна копейка в копейку совпадать со значением, переданным в Summ1 или Summ2. Посмотрим на код расчета цены из нашей задачи:
ЦенаСоСкд = ?(Кол=0, СписокТоваров.Цена, окр(СписокТоваров.Сумма / Кол, 2));
Объект.Price = ЦенаСоСкд;
Объект.Quantity = СписокТоваров.Количество;
Если в первичном документе была применена скидка, которая не делится ровно на количество товаров, функция окр() может дать погрешность округления. В итоге сумма позиций чека (просуммированная внутри кассового аппарата) разойдется с итоговой суммой документа в 1С на 1-2 копейки. В таком случае Штрих-М откажется пробивать чек, и операция прервется на этапе FNCloseCheckEx.
Для предотвращения этой проблемы программно контролируйте сходимость итогов перед отправкой сумм в драйвер. Разницу от округлений всегда "накидывайте" или вычитайте из цены последней товарной строки в чеке (с поправкой на ее количество), чтобы математика кассы сошлась идеально.