После обновления конфигурации "1С:Управление нашей фирмой" (УНФ) до релиза 3.0.6.126 пользователи столкнулись с неприятной проблемой: система начала некорректно применять автоматические скидки. В частности, скидки, настроенные с условием "За накопленный объем продаж по дисконтной карте", стали предоставляться всем покупателям, даже если дисконтная карта не была указана в документе продажи. Это приводит к финансовым потерям и нарушению логики системы лояльности.
Проанализируем ситуацию и разберем, как можно исправить эту ошибку. Выясним, что это известная проблема, и рассмотрим два способа ее решения: официальный и временный (с помощью доработки).
Прежде всего, важно понимать, что данная ситуация — это не ошибка в настройках, а подтвержденный баг в релизе 1С:УНФ 3.0.6.126. Компания "1С" официально зарегистрировала эту ошибку под кодом 10250669. Суть ошибки заключается в том, что при расчете автоматических скидок в документах розничных продаж не проверяется наличие указанной дисконтной карты, из-за чего условия, привязанные к ней, срабатывают для всех без исключения.
Зная причину, мы можем выбрать наиболее подходящий путь решения.
Самый правильный и надежный способ исправить ошибку — установить более свежий релиз конфигурации, в котором она уже исправлена. Разработчики устранили данную проблему в версии 1С:УНФ 3.0.6.136 и последующих.
Порядок действий:
После обновления логика расчета скидок вернется в штатный режим, и скидки по картам будут применяться только при их фактическом указании в документе. Этот способ гарантирует стабильность системы и получение всех последующих исправлений от разработчиков.
Если по каким-либо причинам вы не можете оперативно обновиться (например, из-за наличия других доработок или необходимости дождаться планового окна для обновления), можно применить временное исправление. Оно заключается в создании небольшого расширения, которое скорректирует поведение программы, не изменяя основную конфигурацию.
Разберем по шагам, как это сделать. Нам нужно "перехватить" момент расчета скидок и добавить недостающую проверку.
Откройте вашу базу в режиме "Конфигуратор". В дереве конфигурации найдите ветку "Расширения", нажмите на нее правой кнопкой мыши и выберите "Добавить". Задайте имя расширению, например, ИсправлениеСкидокУНФ, и префикс.
Нам необходимо доработать логику, которая находится в общем модуле РозничныеПродажиСервер. Найдите этот модуль в основной конфигурации, нажмите на него правой кнопкой мыши и выберите "Добавить в расширение".
В открывшемся расширении найдите заимствованный модуль РозничныеПродажиСервер. Нас интересует процедура РассчитатьСкидкиНаценкиНаСервере. Нажмите на нее правой кнопкой мыши и выберите опцию для создания обработчика "Перед". Это позволит выполнить наш код непосредственно перед вызовом основной процедуры.
В созданном обработчике в модуле расширения необходимо разместить код, который будет проверять, заполнена ли дисконтная карта в форме. Если карта не указана, скидки, связанные с ней, не должны рассчитываться. В контексте форума был предложен более прямой подход — модифицировать сам вызов, добавив проверку. Мы реализуем это через обработчик.
Логика такова: оригинальная процедура РассчитатьСкидкиНаценкиНаСервере принимает в качестве одного из параметров структуру пФорма, через которую можно получить доступ к объекту документа. Нам нужно проверить реквизит Объект.ДисконтнаяКарта.
Вот примерный код, который можно адаптировать. Поскольку прямое прерывание расчета скидок для конкретных видов из обработчика "Перед" затруднительно, более надежный вариант — создать обработчик "Вместо" и скопировать туда код исходной процедуры, добавив проверку.
Давайте рассмотрим более простой вариант, предложенный на форуме, который подразумевает добавление проверки в копию процедуры. Суть в том, чтобы обернуть логику расчета накопительных скидок в условие.
Представим, что мы скопировали тело процедуры РассчитатьСкидкиНаценкиНаСервере в обработчик "Вместо". Нам нужно найти блок, отвечающий за расчет скидок, и добавить проверку:
&НаСервере
Процедура Расширение_РассчитатьСкидкиНаценкиНаСервере(пФорма, Команда)
// Добавляем проверку перед вызовом основной логики
Если ЗначениеЗаполнено(пФорма.Объект.ДисконтнаяКарта) Тогда
// Здесь мы вызываем стандартную процедуру, если карта есть.
// Для этого нужно будет переименовать ее в расширении
// и вызвать с префиксом.
// Либо, как говорилось выше, скопировать ее код сюда.
// Например, если мы скопировали весь код оригинальной процедуры:
// ...
// [Код оригинальной процедуры расчета скидок]
// ...
Иначе
// Если дисконтной карты нет, то нам нужно рассчитать только те скидки,
// которые не зависят от карты.
// Либо, если таких нет, просто очистить таблицу скидок.
пФорма.Объект.СкидкиНаценки.Очистить();
КонецЕсли;
// После этого нужно пересчитать итоги документа
РассчитатьСуммуДокумента(пФорма.Объект, пФорма);
ПродолжитьВызов(пФорма, Команда); // Это для обработчика "Перед", для "Вместо" не нужно
EndProcedure
Важный момент: работа с обработчиками "Вместо" требует аккуратности, так как вы берете на себя ответственность за полное воспроизведение логики типовой процедуры. При последующих обновлениях вам придется актуализировать код в расширении. Поэтому, если это возможно, всегда отдавайте предпочтение обновлению конфигурации.
После добавления кода сохраните конфигурацию расширения и снимите флажок "Безопасный режим". Перезапустите программу в режиме "Предприятие". Ошибка должна быть исправлена.
В заключение, подчеркнем: столкнувшись с подобной проблемой, первым делом проверьте информацию о зарегистрированных ошибках на сайте 1С. Зачастую решение уже существует в виде официального патча или обновления. Использование расширений — мощный инструмент для срочных исправлений, но он требует понимания логики системы и последующего сопровождения.