Как реализовать контроль остатков перед оплатой по карте в "Чек ККМ" без проведения документа?

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

Рассмотрим распространенную проблему, возникающую в розничной торговле при работе с конфигурацией «1С:Управление торговлей 10.3». Ситуация выглядит так: кассир добавляет товары в документ ЧекККМ и нажимает кнопку «Оплатить картой». В этот момент происходит обращение к банковскому терминалу, и с карты клиента списываются средства. Затем 1С пытается провести документ, но обнаруживает нехватку товара на складе по учетным данным и выдает ошибку проведения. В итоге деньги списаны, чек в 1С не проведен, фискальный чек не пробит, и кассиру приходится оформлять сложный возврат средств через банковский терминал в обход ККМ.

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

Разберем ошибочные подходы: временное проведение документа

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


Функция ПровестиДляПроверкиОстатков(Ответ, Отказ, ФормаДокумента) Экспорт
    Результат = Истина;
    Ответ = "";
    Попытка
        ФормаДокумента.ЗаписатьВФорме(РежимЗаписиДокумента.Проведение);
        ФормаДокумента.ЗаписатьВФорме(РежимЗаписиДокумента.ОтменаПроведения); 
    Исключение
        Ответ = "Ошибка при попытке проведения документа!";
        Отказ = Истина;
        Результат = Ложь;
    КонецПопытки;
    Возврат Результат;
КонецФункции

Затем этот код вызывается перед процедурой ОплатитьКартой(СуммаОплаты). Почему мы категорически не рекомендуем использовать этот метод?

  1. Риски фиктивного проведения: Если в момент между проведением и его отменой произойдет сбой (отключение электричества, обрыв сети, зависание компьютера кассира), документ останется проведенным в базе 1С, хотя оплата по карте не прошла и покупатель ушел. Это создаст серьезные расхождения между базой и реальными остатками.
  2. Транзакционная нагрузка: Проведение и последующая отмена создают совершенно ненужную нагрузку на сервер базы данных, пересчитывая итоги регистров туда и обратно. В многопользовательской среде это может вызывать блокировки таблиц.
  3. Сбои нумерации и прав: Для отмены проведения кассиру могут потребоваться дополнительные права, наделять которыми рядового сотрудника небезопасно.

Проанализируем работу стандартной процедуры контроля

В типовой конфигурации УТ 10.3 есть готовая процедура КонтрольОстатков. Многие пытаются вызвать ее напрямую из формы документа до его записи. Однако эта процедура разработана для работы внутри транзакции проведения (в обработчике ОбработкаПроведения модуля объекта). Она анализирует уже сформированные коллекции движений документа и сравнивает их с текущими остатками базы.

Если мы вызовем ее из открытой формы до проведения, она не увидит только что добавленных кассиром строк (поскольку они еще не записаны в базу данных как движения) и не сможет корректно проверить остатки. Поэтому вызывать типовую процедуру напрямую для решения нашей задачи нельзя.

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

Наиболее безопасный и правильный способ реализовать предварительный контроль — написать программный запрос к регистрам накопления, который будет анализировать данные табличной части открытой формы. Разберем этот процесс по шагам.

  1. Подготовка данных: В момент нажатия кнопки «Оплатить картой» мы берем табличную часть «Товары» из формы документа (или выгружаем ее в структуру/таблицу значений).
  2. Свертка строк: Обязательно группируем данные табличной части по реквизитам Номенклатура, ХарактеристикаНоменклатуры и СерияНоменклатуры. Это необходимо, так как кассир мог добавить один и тот же товар разными строками, и нам нужно проверять общее запрашиваемое количество.
  3. Построение запроса: Передаем свернутую таблицу в запрос в качестве параметра. В запросе выполняем левое соединение наших данных с виртуальной таблицей РегистрНакопления.ТоварыНаСкладах.Остатки. В параметрах виртуальной таблицы обязательно устанавливаем отбор по складу, который выбран в шапке проверяемого чека ККМ.
  4. Анализ результата: В выборке запроса вычисляем разницу между требуемым количеством и полем КоличествоОстаток. Если требуемое количество превышает остаток базы, формируем строку с сообщением об ошибке (какого именно товара не хватает) и возвращаем отказ.

Только в случае, если запрос подтверждает наличие всех позиций, мы вызываем стандартную процедуру ОплатитьКартой(СуммаОплаты).

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

При реализации запроса мы можем столкнуться с ограничениями платформы: у роли «Кассир» часто закрыты права на прямое чтение таблиц регистров накопления. Если кассир попытается выполнить наш запрос к ТоварыНаСкладах.Остатки, система выдаст ошибку нарушения прав доступа.

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

Когда код выполняется в привилегированном модуле, платформа временно игнорирует ограничения прав доступа текущего пользователя. Запрос успешно проверит остатки, вернет результат в форму чека (можно продавать или нет), и кассир не получит избыточных прав на просмотр отчетов по складу.

Учет типовых настроек конфигурации

Перед тем как внедрять жесткий программный запрет на оплату картой при минусовых остатках, проверим настройки самой базы. В УТ 10.3 логика работы розницы такова, что физическое наличие товара на полке важнее данных в программе. Поэтому часто контроль остатков для чеков отключают намеренно.

Посмотрим на типовую настройку. Зайдем в меню «Сервис» -> «Настройки пользователей», выберем пользователя и раскроем ветку «Другие настройки». Найдем параметр «Контролировать остатки товаров при оперативном проведении чеком ККМ».

Если для конкретного кассира эта настройка снята (разрешена продажа «в минус»), то наша самописная проверка перед оплатой по карте будет конфликтовать с общей учетной политикой магазина. Поэтому в нашей функции с запросом целесообразно сначала проверять значение этой настройки. Если контроль отключен — мы сразу возвращаем Истина и разрешаем оплату. Если контроль включен — выполняем запрос к регистрам и действуем по ситуации.

← На главную