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