При обновлении конфигураций «1С:Управление торговлей» (начиная с релизов 11.4.12.71, 11.4.12.77 и выше) и выполнении регулярной синхронизации с «1С:Бухгалтерия предприятия 3.0» пользователи часто сталкиваются с неприятным сбоем. Процесс выгрузки данных аварийно прерывается, а в журнале регистрации фиксируется критическая ошибка выполнения обработчика ПриОбработкеПОД для документа ВнутреннееПотреблениеТоваров (или других товарных документов). Сообщение об ошибке выглядит следующим образом:
Преобразование значения к типу Булево не может быть выполнено {ОбщийМодуль.МенеджерОбменаЧерезУниверсальныйФормат.Модуль(47324)}: Если Строка.ВыгружатьУпаковки И ЗначениеЗаполнено(Строка.УпаковкаСсылка) Тогда
Давайте подробно разберем, почему возникает это поведение системы, проанализируем исходный код конфигурации и рассмотрим несколько практических способов решения данной проблемы, включая правильное исправление запроса и создание безопасного расширения.
Для того чтобы понять природу ошибки, обратимся к общему модулю МенеджерОбменаЧерезУниверсальныйФормат. Ошибка происходит в момент выполнения проверки строки табличной части документа. Платформа пытается вычислить логическое выражение:
Если Строка.ВыгружатьУпаковки И ЗначениеЗаполнено(Строка.УпаковкаСсылка) Тогда
Для того чтобы такое условие успешно отработало, свойство Строка.ВыгружатьУпаковки обязательно должно содержать значение булевого типа (Истина или Ложь). Однако в проблемных релизах конфигурации при определенных условиях туда записывается значение NULL (в системе 1С представленное как DbNull). При попытке применить логическое «И» к значению NULL платформа выдает ошибку приведения типов, так как не может неявно преобразовать NULL в Булево.
Посмотрим на источник формирования этого значения. Свойство заполняется результатом запроса, текст которого генерируется в функции ПолучитьТекстЗапросаУпаковки. В проблемных релизах этот код выглядит следующим образом:
Функция ПолучитьТекстЗапросаУпаковки(КомпонентыОбмена, НаименованиеИсточника, КоличественныеПоказатели = Истина)
// ... Сокращено для удобства
Иначе
ТекстЗапроса =
" НЕ &Источник.Упаковка = ЗНАЧЕНИЕ(Справочник.УпаковкиЕдиницыИзмерения.ПустаяСсылка) КАК ВыгружатьУпаковки,
| &Источник.Упаковка.Владелец КАК УпаковкаВладелец,
| &Источник.Упаковка.ТипИзмеряемойВеличины КАК УпаковкаТипИзмеряемойВеличины,
| &Источник.Упаковка КАК УпаковкаСсылка,
// ... Продолжение текста запроса
Проанализируем выражение НЕ &Источник.Упаковка = ЗНАЧЕНИЕ(Справочник.УпаковкиЕдиницыИзмерения.ПустаяСсылка) КАК ВыгружатьУпаковки. Если в документе выгружается строка, в которой не указана упаковка (например, товар отгружается в базовых единицах или выгружается услуга, у которой в принципе нет и не может быть упаковок), реквизит Упаковка в базе данных равен NULL.
По правилам работы СУБД и трехзначной логики SQL:
NULL возвращает NULL. Выражение NULL = ПустаяСсылка дает результат NULL.НЕ (NULL) также возвращает NULL.В результате СУБД возвращает значение NULL в поле ВыгружатьУпаковки, что и приводит к падению всей синхронизации. Фирма «1С» зарегистрировала эту проблему как официальную ошибку с кодом 00-00307618.
Если вам необходимо срочно закрыть период и передать данные в бухгалтерию, а вносить изменения в конфигурацию нет возможности (например, закрыты права доступа или база находится на строгом аудите), выполните следующие действия:
00УР-000109).Важно: Этот способ является временной полумерой и не решает проблему системно, так как при появлении новых аналогичных документов ошибка повторится. При необходимости быстро исключать отдельные объекты из выгрузки можно использовать расширение для выборочного переноса документов из УТ.
Если ваша конфигурация снята с поддержки (разрешено изменение) или вы готовы внести исправления непосредственно в основную конфигурацию, нам необходимо скорректировать функцию ПолучитьТекстЗапросаУпаковки общего модуля МенеджерОбменаЧерезУниверсальныйФормат.
Рассмотрим, как правильно переписать проблемный участок запроса, чтобы СУБД гарантированно возвращала логическое значение Ложь вместо NULL. Мы можем использовать один из двух подходов.
Подход А (Рекомендуемый, с использованием конструкции ВЫБОР):
Этот вариант наиболее нагляден и полностью соответствует стандартам разработки «1С».
// Заменяем проблемную строку на конструкцию ВЫБОР
ТекстЗапроса =
" ВЫБОР
| КОГДА &Источник.Упаковка ЕСТЬ NULL
| ИЛИ &Источник.Упаковка = ЗНАЧЕНИЕ(Справочник.УпаковкиЕдиницыИзмерения.ПустаяСсылка)
| ТОГДА Ложь
| ИНАЧЕ Истина
| КОНЕЦ КАК ВыгружатьУпаковки,
| &Источник.Упаковка.Владелец КАК УпаковкаВладелец,
// Далее код функции без изменений
Подход Б (Свертка через функцию ЕСТЬNULL):
Этот вариант лаконичнее и подменяет значение NULL на пустую ссылку перед непосредственным сравнением.
ТекстЗапроса =
" НЕ ЕСТЬNULL(&Источник.Упаковка, ЗНАЧЕНИЕ(Справочник.УпаковкиЕдиницыИзмерения.ПустаяСсылка)) = ЗНАЧЕНИЕ(Справочник.УпаковкиЕдиницыИзмерения.ПустаяСсылка) КАК ВыгружатьУпаковки,
| &Источник.Упаковка.Владелец КАК УпаковкаВладелец,
// Далее код функции без изменений
При использовании любого из этих подходов поле ВыгружатьУпаковки всегда будет содержать либо Истина, либо Ложь, что позволит платформе корректно выполнить проверку условий в коде обмена.
Для того чтобы не снимать типовую конфигурацию с поддержки и сохранить возможность простого автоматического обновления в будущем, правильнее всего применить механизм расширений. Разберем этот процесс по шагам: для автоматического обновления нескольких баз в тихом режиме можно использовать программу для автоматизации обслуживания и обновления 1С.
ИсправлениеОшибкиСинхронизации) и назначьте ему назначение Адаптация.МенеджерОбменаЧерезУниверсальныйФормат, нажмите на него правой кнопкой мыши и выберите пункт Добавить в расширение.&Вместо, полностью заменяющую логику исходной функции.Посмотрим на готовый код модуля расширения:
&Вместо("ПолучитьТекстЗапросаУпаковки")
Функция ИСПР_ПолучитьТекстЗапросаУпаковки(КомпонентыОбмена, НаименованиеИсточника, КоличественныеПоказатели = Истина)
Если ВерсияФорматаЧислом(КомпонентыОбмена.ВерсияФорматаОбмена) < ВерсияФорматаЧислом("1.6") Тогда
ТекстЗапроса = " Ложь КАК ВыгружатьУпаковки, | &Источник.Упаковка КАК УпаковкаСсылка";
ТекстЗапросаКоличественныеПоказатели = " | ,&Источник.Количество КАК КоличествоУпаковок";
Иначе
// Применяем исправленный вариант с конструкцией ВЫБОР для исключения NULL
ТекстЗапроса =
" ВЫБОР
| КОГДА &Источник.Упаковка ЕСТЬ NULL
| ИЛИ &Источник.Упаковка = ЗНАЧЕНИЕ(Справочник.УпаковкиЕдиницыИзмерения.ПустаяСсылка)
| ТОГДА Ложь
| ИНАЧЕ Истина
| КОНЕЦ КАК ВыгружатьУпаковки,
| &Источник.Упаковка.Владелец КАК УпаковкаВладелец,
| &Источник.Упаковка.ТипИзмеряемойВеличины КАК УпаковкаТипИзмеряемойВеличины,
| &Источник.Упаковка КАК УпаковкаСсылка,
| ЕСТЬNULL(&Источник.Упаковка.Владелец, ЗНАЧЕНИЕ(Справочник.НаборыУпаковок.ПустаяСсылка)) ССЫЛКА Справочник.Номенклатура КАК УпаковкаНоменклатуры,
| &Источник.Упаковка.Наименование КАК УпаковкаНаименование,
| &Источник.Упаковка.ЕдиницаИзмерения КАК УпаковкаЕдиницаИзмерения,
| &Источник.Упаковка.Высота КАК УпаковкаВысота,
| &Источник.Упаковка.Глубина КАК УпаковкаГлубина,
| &Источник.Упаковка.Объем КАК УпаковкаОбъем,
| &Источник.Упаковка.Ширина КАК УпаковкаШирина,
| &Источник.Упаковка.Знаменатель КАК УпаковкаЗнаменатель,
| &Источник.Упаковка.Числитель КАК УпаковкаЧислитель";
ТекстЗапросаКоличественныеПоказатели = " | ,&Источник.КоличествоУпаковок КАК КоличествоУпаковок";
КонецЕсли;
Если КоличественныеПоказатели Тогда
ТекстЗапроса = ТекстЗапроса + ТекстЗапросаКоличественныеПоказатели;
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&Источник", НаименованиеИсточника);
Возврат ТекстЗапроса;
КонецФункции
Сохраните расширение и запустите информационную базу в режиме «1С:Предприятие». После применения расширения вы можете запустить синхронизацию повторно — она пройдет без ошибок в штатном режиме, корректно обработав все документы, независимо от наличия или отсутствия в них упаковок. Чтобы убедиться в отсутствии расхождений после возобновления обмена, можно запустить автоматическое сравнение проводок в базах 1С.