Почему в 1С:УНФ после обновления подарочные сертификаты показывают нулевой остаток при оплате и как это исправить?

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

После того как было выполнено обновление конфигурации с выносом доработок в расширение до последних версий и установки патчей, пользователи часто сталкиваются с критической проблемой: при попытке оплатить покупку подарочным сертификатом система выдает сообщение, что доступный остаток равен 0. При этом во всех стандартных отчетах и через консоль запросов остаток по сертификату отображается корректно. Чтобы убедиться в корректности данных, можно использовать специализированный внешний отчет по движениям подарочных сертификатов для УНФ. Рассмотрим подробно, почему это происходит и как программно вернуть работоспособность механизма оплаты.

Анализ причины проблемы: избыточная сложность типового запроса

Для начала разберем ситуацию. В новых релизах УНФ логика проверки остатков сертификатов была значительно усложнена. Теперь система учитывает не только прямые остатки в регистре накопления ПодарочныеСертификаты, но и множество дополнительных условий: сроки действия, частичное погашение, организацию-эмитента и данные так называемого "Сервера лояльности".

Проанализируем фрагмент типового запроса, который система использует для получения доступной суммы. Этот запрос проверяет данные сразу в нескольких временных таблицах (ВТ), включая ВТ_ПодарочныеСертификатыРезерв, ВТ_ОстатокНаТекущийМомент и данные регистра сведений СостояниеПодарочныхСертификатовСерверЛояльности. Любая ошибка или "зависшая" запись в этих служебных регистрах приводит к тому, что итоговый остаток обнуляется в коде, хотя фактически деньги на сертификате есть. Если данные в регистрах некорректны, может потребоваться универсальная корректировка и чтение остатков регистра накопления для исправления ошибочных записей.

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

Решение 1: Упрощение обновления данных сертификата

Если нам необходимо оперативно восстановить работу сертификатов, мы можем использовать механизм расширений. Первый шаг — переопределить процедуру ОбновитьДанныеСертификата. Рассмотрим пример кода, который заменяет сложный поиск остатка на прямой запрос к регистру накопления.

Разберем, как это реализовать в расширении:


&НаСервере
&После("ОбновитьДанныеСертификата")
Процедура ИспрСерт_ОбновитьДанныеСертификата()
    // Создаем запрос к остаткам регистра накопления напрямую
    Запрос = Новый Запрос;
    Запрос.УстановитьПараметр("ПодарочныйСертификат", ПодарочныйСертификат);
    Запрос.УстановитьПараметр("КонДата", ТекущаяДатаСеанса());
    
    Запрос.Текст = 
    "ВЫБРАТЬ
    |	ПодарочныеСертификатыОстатки.ПодарочныйСертификат КАК ПодарочныйСертификат,
    |	ПодарочныеСертификатыОстатки.СуммаОстаток КАК СуммаОстаток
    |ИЗ
    |	РегистрНакопления.ПодарочныеСертификаты.Остатки(&КонДата, ) КАК ПодарочныеСертификатыОстатки
    |ГДЕ
    |	ПодарочныеСертификатыОстатки.ПодарочныйСертификат = &ПодарочныйСертификат";
    
    Результат = Запрос.Выполнить().Выгрузить();
    
    Если Результат.Количество() > 0 Тогда
        // Принудительно устанавливаем доступную сумму и номинал
        ДоступноКОплате = Результат[0].СуммаОстаток;
        Номинал = Результат[0].СуммаОстаток;
    КонецЕсли;
КонецПроцедуры

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

Решение 2: Обход ограничений при проведении

Иногда после исправления визуального остатка документ все равно отказывается проводиться, выдавая ошибки контроля. В этом случае нам поможет вмешательство в процедуру ВыполнитьПроверкуОграниченийСертификатов. Если вы уверенны в корректности данных и вам нужно "протолкнуть" оплату, можно временно или постоянно отключать признак отказа.


&После("ВыполнитьПроверкуОграниченийСертификатов")
Процедура ИспрСерт_ВыполнитьПроверкуОграниченийСертификатов(Отказ)
    // Принудительно сбрасываем флаг отказа, если логика системы ошибочно блокирует оплату
    Отказ = Ложь;
КонецПроцедуры

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

Решение 3: Глобальное переопределение функции допустимых сумм

Наиболее полное решение заключается в замене логики функции ДопустимыеСуммыОплатыСертификатами. Рассмотрим вариант, когда мы используем &Вместо, чтобы внедрить собственный алгоритм расчета. Это позволит избежать влияния типовых патчей, которые ломают запрос.

Выясним причину, почему это эффективно: мы создаем структуру ОписаниеСертификатов вручную и наполняем её данными из прямого запроса к остаткам, при этом сохраняя совместимость с ожидаемым форматом данных УНФ. Также стоит проверить, не используется ли в вашей системе расширение для повторного использования подарочных сертификатов, так как оно вносит свои коррективы в алгоритмы гашения.


&Вместо("ДопустимыеСуммыОплатыСертификатами")
Функция ИспрСерт_ДопустимыеСуммыОплатыСертификатами(ТаблицаОплатыСертификатами, ОрганизацииПродажи, ТаблицаТоваров)
    
    ОписаниеСертификатов = ПустаяТаблицаОписанияДоступныхСуммПоСертификатам();
    
    // Если в таблице есть сертификат, выполняем наш упрощенный поиск
    Если ТаблицаОплатыСертификатами.Количество() > 0 И ЗначениеЗаполнено(ТаблицаОплатыСертификатами[0].ПодарочныйСертификат) Тогда
        
        ПодарочныйСертификат = ТаблицаОплатыСертификатами[0].ПодарочныйСертификат;
        
        Запрос = Новый Запрос;
        Запрос.УстановитьПараметр("ПодарочныйСертификат", ПодарочныйСертификат);
        Запрос.УстановитьПараметр("КонДата", ТекущаяДатаСеанса());
        Запрос.Текст = 
        "ВЫБРАТЬ
        |	ПодарочныеСертификатыОстатки.СуммаОстаток КАК СуммаОстаток
        |ИЗ
        |	РегистрНакопления.ПодарочныеСертификаты.Остатки(&КонДата, ПодарочныйСертификат = &ПодарочныйСертификат) КАК ПодарочныеСертификатыОстатки";
        
        Результат = Запрос.Выполнить().Выгрузить();
        
        Если Результат.Количество() > 0 Тогда
            Нстр = ОписаниеСертификатов.Добавить();
            Нстр.ПодарочныйСертификат = ПодарочныйСертификат;
            Нстр.Остаток = Результат[0].СуммаОстаток;
            Нстр.ДоступнаяСумма = Результат[0].СуммаОстаток;
            Нстр.Заблокирован = Ложь;
            Нстр.СработалиОграничения = Ложь;
            Возврат ОписаниеСертификатов;
        КонецЕсли;
    КонецЕсли;
    
    // Если наш упрощенный поиск не дал результатов, можно вызвать основную логику 
    // или вернуть пустую таблицу.
    Возврат ОписаниеСертификатов;
    
КонецФункции

Рекомендации по диагностике без программирования

Если вы не готовы вносить изменения в код, проанализируйте следующие моменты в настройках программы:

  1. Проверка регистра "Сервера лояльности": Посмотрите через "Все функции" (или "Функции для технического специалиста") содержимое регистра сведений СостояниеПодарочныхСертификатовСерверЛояльности. Если сертификат находится в статусе, отличном от "Продан", типовой запрос его не увидит.
  2. Контроль организации: В карточке категории сертификата проверьте флаг "Принимать к оплате только в организации-эмитенте". После обновления этот механизм стал работать жестче. Если сертификат был продан по одной организации, а оплата принимается по другой — остаток будет 0. Попробуйте снять этот флаг для проверки.
  3. Срок действия: Проанализируйте дату продажи сертификата. В новых версиях запрос пытается найти дату активации в регистре СерииНоменклатуры. Если сертификат введен остатками, дата может определиться неверно, и программа посчитает его просроченным.

Таким образом, мы выяснили, что проблема кроется не в физическом отсутствии остатков, а в чрезмерно "умных" фильтрах запроса в последних патчах УНФ. Использование расширения для прямого обращения к регистру ПодарочныеСертификаты является самым быстрым и надежным способом восстановить продажи.

← На главную