В процессе разработки механизмов оплаты подарочными сертификатами программисты часто сталкиваются с ситуацией, когда типовой или самописный запрос возвращает странные цифры. Например, при номинале сертификата в 300 рублей система показывает остаток 900 или даже больше. В этой статье мы подробно разберем, почему возникает такая ошибка, проанализируем логику работы регистров 1С и найдем оптимальные пути решения проблемы.
Рассмотрим ситуацию, когда в системе реализовано несколько подарочных сертификатов одного вида. Проблема проявляется в тот момент, когда мы пытаемся получить остаток по конкретному сертификату для его погашения. Проанализируем фрагмент запроса, который часто становится «виновником» некорректных данных:
ВЫБРАТЬ
ПогашениеПодарочныхСертификатов.ПодарочныйСертификат КАК ПодарочныйСертификат,
ПогашениеПодарочныхСертификатов.СерийныйНомер КАК СерийныйНомер,
СУММА(ЕСТЬNULL(ПодарочныеСертификатыОстатки.СуммаОстаток,
ВЫБОР
КОГДА НЕ ПогашениеПодарочныхСертификатов.ПодарочныйСертификат.ЧастичноеПогашение
ТОГДА ПогашениеПодарочныхСертификатов.ПодарочныйСертификат.Номинал
ИНАЧЕ 0
КОНЕЦ)) КАК Остаток,
СУММА(ПогашениеПодарочныхСертификатов.СуммаПогашенияСертификата) КАК СуммаПогашенияСертификата
ПОМЕСТИТЬ ПогашениеПоОрганизациям
ИЗ
ПогашениеПодарочныхСертификатов КАК ПогашениеПодарочныхСертификатов
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПодарочныеСертификаты.Остатки КАК ПодарочныеСертификатыОстатки
ПО ПогашениеПодарочныхСертификатов.ПодарочныйСертификат = ПодарочныеСертификатыОстатки.ПодарочныйСертификат
И ПогашениеПодарочныхСертификатов.СерийныйНомер = ПодарочныеСертификатыОстатки.НомерСертификата
СГРУППИРОВАТЬ ПО
ПогашениеПодарочныхСертификатов.ПодарочныйСертификат,
ПогашениеПодарочныхСертификатов.СерийныйНомер;
На первый взгляд запрос выглядит логично: мы берем данные из временной таблицы погашения и соединяем их с остатками по регистру ПодарочныеСертификаты. Однако именно здесь кроется ловушка. Если сертификат с номиналом 300 рублей был продан в трех разных документах реализации без указания серийного номера, то в регистре накопления образуются три записи. Поскольку измерение НомерСертификата пустое, запрос суммирует все остатки по данной номенклатуре, превращая 300 рублей в 900.
Давайте разберем, как 1С хранит данные в регистре ПодарочныеСертификаты. Основными измерениями в типовых конфигурациях (таких как «Управление торговлей», «Розница» или «ERP») являются:
Если в настройках вида номенклатуры не включен обязательный учет по серийным номерам, программа позволяет продавать неограниченное количество сертификатов с пустым номером. Для системы это выглядит так, будто вы продаете обычный товар, например, хлеб. Но подарочный сертификат — это не просто товар, это финансовое обязательство организации (аванс). Если номера не заполнены, 1С не может отличить «Сертификат №1» от «Сертификата №2», и при обращении к виртуальной таблице остатков она честно суммирует весь долг перед покупателями по этой позиции.
Это самый правильный путь с точки зрения методологии учета в 1С. Рассмотрим шаги, которые необходимо предпринять:
В этом случае наш запрос будет работать корректно, так как соединение будет происходить по конкретному уникальному номеру, и СуммаОстаток всегда будет соответствовать номиналу одного конкретного бланка.
Рассмотрим альтернативный вариант, который предложили участники обсуждения: использовать в запросе просто номинал из справочника вместо остатка по регистру. Проанализируем код:
// Вместо СуммаОстаток используем реквизит Номинал
ВЫБРАТЬ
ПогашениеПодарочныхСертификатов.ПодарочныйСертификат.Номинал КАК Остаток
ИЗ
ПогашениеПодарочныхСертификатов
Внимание! У этого метода есть серьезные недостатки:
Если бизнес-процесс уже запущен и сертификаты без номеров уже проданы, временным решением может стать расшифровка данных в разрезе документов-регистраторов (Реализаций). Если мы добавим поле Регистратор в соединение и группировку, то увидим сумму 300 рублей в привязке к каждой конкретной продаже.
Посмотрим на пример логики исправления:
ВЫБРАТЬ
ПодарочныеСертификатыОстатки.Регистратор КАК ДокументПродажи,
ПодарочныеСертификатыОстатки.СуммаОстаток КАК СуммаПоДокументу
ИЗ
РегистрНакопления.ПодарочныеСертификаты.Остатки( , ) КАК ПодарочныеСертификатыОстатки
Однако помните, что при оплате в чеке ККМ покупатель не предъявляет «Реализацию», он предъявляет «Карточку». Поэтому без серийного номера система все равно не будет знать, из какой именно реализации (из тех трех по 300 рублей) нужно списать остаток.
Проанализировав ситуацию, мы приходим к выводу, что проблема «900 вместо 300» — это не ошибка кода 1С, а следствие нарушения логики учета. Подарочный сертификат — это уникальный объект учета.
Наши действия для исправления:
Политики учета серий.Корректировка регистров разнести общую сумму остатка по уникальным серийным номерам.ПодарочныйСертификат + СерийныйНомер как единственный ключ уникальности.Соблюдение этих правил позволит избежать путаницы в расчетах с покупателями и обеспечит корректную работу типовых механизмов гашения сертификатов в любых конфигурациях на платформе 1С:Предприятие 8.