Рассмотрим распространенную проблему, возникающую в розничной торговле при работе с конфигурацией «1С:Управление торговлей 10.3». Ситуация выглядит так: кассир добавляет товары в документ ЧекККМ и нажимает кнопку «Оплатить картой». В этот момент происходит обращение к банковскому терминалу, и с карты клиента списываются средства. Затем 1С пытается провести документ, но обнаруживает нехватку товара на складе по учетным данным и выдает ошибку проведения. В итоге деньги списаны, чек в 1С не проведен, фискальный чек не пробит, и кассиру приходится оформлять сложный возврат средств через банковский терминал в обход ККМ.
Чтобы избежать этой проблемы, нам необходимо контролировать остатки на складе строго до вызова процедуры оплаты картой, при этом не проводя сам документ, чтобы в случае отказа оплаты по вине банка (например, недостаточно средств) не пришлось отменять проведение в 1С. Проанализируем возможные варианты решения этой задачи и выберем наиболее оптимальный и безопасный.
Часто разработчики пытаются решить задачу «в лоб», используя следующий алгоритм: программно провести документ, проверить, возникла ли ошибка, и сразу же отменить проведение. Посмотрим на пример кода, который реализует такую логику:
Функция ПровестиДляПроверкиОстатков(Ответ, Отказ, ФормаДокумента) Экспорт
Результат = Истина;
Ответ = "";
Попытка
ФормаДокумента.ЗаписатьВФорме(РежимЗаписиДокумента.Проведение);
ФормаДокумента.ЗаписатьВФорме(РежимЗаписиДокумента.ОтменаПроведения);
Исключение
Ответ = "Ошибка при попытке проведения документа!";
Отказ = Истина;
Результат = Ложь;
КонецПопытки;
Возврат Результат;
КонецФункции
Затем этот код вызывается перед процедурой ОплатитьКартой(СуммаОплаты). Почему мы категорически не рекомендуем использовать этот метод?
В типовой конфигурации УТ 10.3 есть готовая процедура КонтрольОстатков. Многие пытаются вызвать ее напрямую из формы документа до его записи. Однако эта процедура разработана для работы внутри транзакции проведения (в обработчике ОбработкаПроведения модуля объекта). Она анализирует уже сформированные коллекции движений документа и сравнивает их с текущими остатками базы.
Если мы вызовем ее из открытой формы до проведения, она не увидит только что добавленных кассиром строк (поскольку они еще не записаны в базу данных как движения) и не сможет корректно проверить остатки. Поэтому вызывать типовую процедуру напрямую для решения нашей задачи нельзя.
Наиболее безопасный и правильный способ реализовать предварительный контроль — написать программный запрос к регистрам накопления, который будет анализировать данные табличной части открытой формы. Разберем этот процесс по шагам.
Номенклатура, ХарактеристикаНоменклатуры и СерияНоменклатуры. Это необходимо, так как кассир мог добавить один и тот же товар разными строками, и нам нужно проверять общее запрашиваемое количество.РегистрНакопления.ТоварыНаСкладах.Остатки. В параметрах виртуальной таблицы обязательно устанавливаем отбор по складу, который выбран в шапке проверяемого чека ККМ.КоличествоОстаток. Если требуемое количество превышает остаток базы, формируем строку с сообщением об ошибке (какого именно товара не хватает) и возвращаем отказ.Только в случае, если запрос подтверждает наличие всех позиций, мы вызываем стандартную процедуру ОплатитьКартой(СуммаОплаты).
При реализации запроса мы можем столкнуться с ограничениями платформы: у роли «Кассир» часто закрыты права на прямое чтение таблиц регистров накопления. Если кассир попытается выполнить наш запрос к ТоварыНаСкладах.Остатки, система выдаст ошибку нарушения прав доступа.
Чтобы обойти эту проблему, не расширяя полномочия кассира (что нарушает безопасность), создадим новую функцию контроля остатков и поместим ее в Общий модуль. В свойствах этого общего модуля обязательно устанавливаем флажок «Привилегированный».
Когда код выполняется в привилегированном модуле, платформа временно игнорирует ограничения прав доступа текущего пользователя. Запрос успешно проверит остатки, вернет результат в форму чека (можно продавать или нет), и кассир не получит избыточных прав на просмотр отчетов по складу.
Перед тем как внедрять жесткий программный запрет на оплату картой при минусовых остатках, проверим настройки самой базы. В УТ 10.3 логика работы розницы такова, что физическое наличие товара на полке важнее данных в программе. Поэтому часто контроль остатков для чеков отключают намеренно.
Посмотрим на типовую настройку. Зайдем в меню «Сервис» -> «Настройки пользователей», выберем пользователя и раскроем ветку «Другие настройки». Найдем параметр «Контролировать остатки товаров при оперативном проведении чеком ККМ».
Если для конкретного кассира эта настройка снята (разрешена продажа «в минус»), то наша самописная проверка перед оплатой по карте будет конфликтовать с общей учетной политикой магазина. Поэтому в нашей функции с запросом целесообразно сначала проверять значение этой настройки. Если контроль отключен — мы сразу возвращаем Истина и разрешаем оплату. Если контроль включен — выполняем запрос к регистрам и действуем по ситуации.