Разработка и отладка внешних скидок (наценок) и условий их предоставления в современных конфигурациях 1С (таких как «Управление торговлей 11», «ERP Управление предприятием» или «Комплексная автоматизация») часто вызывает трудности у разработчиков. Это связано с тем, что механизмы Библиотеки Стандартных Подсистем (БСП) подключают внешние обработки в безопасном режиме и используют объектную модель работы через временное хранилище, минуя создание физических файлов на диске. В результате стандартные точки останова в конфигураторе просто не срабатывают.
В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем типичные ошибки в коде условий предоставления скидок и рассмотрим четыре эффективных практических метода отладки внешних скидок в управляемом приложении.
В старых конфигурациях на обычных формах (в толстом клиенте) внешние обработки физически записывались во временный каталог на жестком диске пользователя, после чего запускались. В этом случае отладчик легко находил файл и останавливался на точках останова. В управляемом приложении (тонкий клиент) механизм БСП работает принципиально иначе.
При вызове скидки двоичные данные обработки считываются из справочника «Дополнительные отчеты и обработки» и помещаются во временное хранилище. Затем с помощью метода Менеджер.Подключить() обработка регистрируется в системе под уникальным именем. Сразу после этого двоичные данные могут удаляться, а сама обработка выполняется в изолированном контексте. Отладчик конфигуратора «не видит» этот динамически созданный объект, поэтому точки останова игнорируются.
Кроме того, если внешняя обработка запущена в безопасном режиме, платформа накладывает жесткие ограничения на выполнение кода, что также блокирует механизмы отладки.
Давайте проанализируем реальный пример кода, представленный в обсуждении темы. Разработчик пытается реализовать условие скидки по конкретному партнеру (контрагенту) и сталкивается с тем, что скидка не срабатывает. Посмотрим на этот фрагмент кода:
Для Каждого СтрокаТовара Из СтрокаДереваСкидок Цикл
Если ПартнерДокумента = ПараметрыВнешнейОбработки.Контрагент Тогда
СтрокаТовара.УсловиеПоСтрокеВыполнено = Истина;
ТекущееУсловиеВыполнено = Истина;
КонецЕсли;
КонецЦикла;
В данном фрагменте содержатся сразу две критические ошибки:
СтрокаДереваСкидок представляет собой строку дерева значений (или структуру с описанием текущей строки дерева скидок), а не коллекцию строк. Попытка применить к ней цикл Для Каждого приводит к аварийному завершению выполнения кода платформой.СтрокаДереваСкидок.СтруктураДополнительныхДанных.ТаблицаТоваровПоСегментам или аналогичные коллекции.Давайте исправим эту логику и напишем корректный шаблон функции ПроверитьУсловие, который будет устойчив к ошибкам и пригоден для дальнейшей отладки:
Функция ПроверитьУсловие(Условие, СтрокаДереваСкидок, ПараметрыВнешнейОбработки, ПараметрыРасчета) Экспорт
РезультатПроверки = Новый Структура;
ТекущееУсловиеВыполнено = Ложь;
// Проверяем наличие параметров расчета и самого партнера
Если ПараметрыРасчета = Неопределено Или Не ПараметрыРасчета.Свойство("Партнер") Тогда
РезультатПроверки.Вставить("ТекущееУсловиеВыполнено", Ложь);
Возврат РезультатПроверки;
КонецЕсли;
ПартнерДокумента = ПараметрыРасчета.Partner;
ЦелевойКонтрагент = ПараметрыВнешнейОбработки.Контрагент;
// Если партнер документа совпадает с настроенным в скидке контрагентом
Если ЗначениеЗаполнено(ПартнерДокумента) И ПартнерДокумента = ЦелевойКонтрагент Тогда
// Пытаемся получить таблицу товаров для установки признака выполнения по строкам
ТаблицаТоваров = Неопределено;
Если СтрокаДереваСкидок.Свойство("СтруктураДополнительныхДанных") Тогда
СтрокаДереваСкидок.СтруктураДополнительныхДанных.Свойство("ТаблицаТоваровПоСегментам", ТаблицаТоваров);
КонецЕсли;
Если ТаблицаТоваров <> Неопределено Тогда
Для Каждого СтрокаТовара Из ТаблицаТоваров Цикл
СтрокаТовара.УсловиеПоСтрокеВыполнено = Истина;
КонецЦикла;
КонецЕсли;
ТекущееУсловиеВыполнено = Истина;
КонецЕсли;
РезультатПроверки.Вставить("ТекущееУсловиеВыполнено", ТекущееУсловиеВыполнено);
Возврат РезультатПроверки;
КонецФункции
Теперь, когда код исправлен и структурирован, разберем по шагам, какими способами мы можем его отладить.
Это наиболее простой и популярный метод, который позволяет использовать стандартный механизм отладки без изменения кода конфигурации. Суть метода заключается в том, чтобы «заставить» платформу ассоциировать выполняемый код с файлом обработки на вашем диске.
Выполним следующие шаги:
УсловиеСкидкиПоКонтрагенту.epf), лежащий на локальном диске.ПроверитьУсловие).Если первый способ по каким-то причинам не сработал (например, особенности релиза платформы не позволяют сопоставить файлы), мы можем пойти «от обратного» и начать отладку со стороны самой конфигурации. Все вызовы внешних обработок скидок проходят через общий модуль серверной части расчета скидок.
Рассмотрим этот процесс пошагово:
СкидкиНаценкиСервер.ВыполнитьПроверкуУсловийПредоставления или ПроверитьУсловиеВнешнейОбработки.Результат = ВнешнийОбъект.ПроверитьУсловие(Параметры...);.ПроверитьУсловие.Этот способ является наиболее профессиональным и безопасным, так как он полностью исключает необходимость интерактивной работы с реальными документами в интерфейсе и позволяет тестировать код изолированно. Мы создаем небольшую вспомогательную внешнюю обработку, которая будет программно вызывать наше условие скидки.
Давайте разберем, как устроен этот тестовый стенд. Создадим новую внешнюю обработку и назовем ее ТестированиеСкидки.epf. На форму обработки вынесем реквизит ДокументСсылка с типом, например, ДокументСсылка.ЗаказКлиента и кнопку «Запустить тест».
В модуле формы обработки-стартера напишем следующий код:
&НаСервере
Процедура ЗапуститьТестНаСервере()
// 1. Подключаем тестируемую обработку напрямую с диска
ПутьКОбработке = "C:\Debug\УсловиеСкидкиПоКонтрагенту.epf";
ОбработкаОбъект = ВнешниеОбработки.Создать(ПутьКОбработке, Ложь);
// 2. Инициализируем структуру параметров расчета, имитируя поведение БСП
ПараметрыРасчета = Новый Структура;
ПараметрыРасчета.Вставить("Партнер", ДокументСсылка.Партнер);
ПараметрыРасчета.Вставить("Контрагент", ДокументСсылка.Контрагент);
// 3. Создаем тестовую структуру строки дерева скидок
СтрокаДереваСкидок = Новый Структура;
СтруктураДополнительныхДанных = Новый Структура;
// Создаем пустую таблицу товаров для теста обхода строк
ТаблицаТоваров = Новый ТаблицаЗначений;
ТаблицаТоваров.Колонки.Добавить("Номенклатура");
ТаблицаТоваров.Колонки.Добавить("УсловиеПоСтрокеВыполнено", Новый ОписаниеТипов("Булево"));
// Заполняем тестовую строку товара
НоваяСтрока = ТаблицаТоваров.Добавить();
НоваяСтрока.Номенклатура = Справочники.Номенклатура.ПустаяСсылка();
НоваяСтрока.УсловиеПоСтрокеВыполнено = Ложь;
СтруктураДополнительныхДанных.Вставить("ТаблицаТоваровПоСегментам", ТаблицаТоваров);
СтрокаДереваСкидок.Вставить("СтруктураДополнительныхДанных", СтруктураДополнительныхДанных);
// 4. Задаем настройки внешней обработки (имитация заполненных реквизитов)
ПараметрыВнешнейОбработки = Новый Структура;
ПараметрыВнешнейОбработки.Вставить("Контрагент", ДокументСсылка.Контрагент);
// 5. Вызываем функцию проверки условия
Результат = ОбработкаОбъект.ПроверитьУсловие(
Неопределено,
СтрокаДереваСкидок,
ПараметрыВнешнейОбработки,
ПараметрыРасчета
);
// Выводим результат в окно сообщений
Сообщить("Результат проверки условия: " + Результат.ТекущееУсловиеВыполнено);
КонецПроцедуры
&НаКлиенте
Процедура ЗапуститьТест(Команда)
ЗапуститьТестНаСервере();
КонецПроцедуры
Теперь мы можем открыть эту обработку-стартер через меню Файл -> Открыть в режиме Предприятия, выбрать нужный документ и нажать кнопку. Любые точки останова, установленные в файле УсловиеСкидкиПоКонтрагенту.epf, будут гарантированно и стабильно срабатывать, так как обработка создается непосредственно из файла на диске с отключенным безопасным режимом.
Часто разработчики выполняют все шаги верно, но отладчик все равно игнорирует точки останова. Проанализируем ключевые системные настройки, которые необходимо проверить:
-debug.Используя предложенные методики и исправив логику работы с коллекциями строк дерева скидок, вы сможете быстро локализовать любую ошибку в алгоритмах расчета внешних скидок и обеспечить их стабильную работу в вашей системе.