Почему возникает ошибка «Преобразование значения к типу Дата не может быть выполнено» при распределении РБП в 1С:ERP?

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

При работе в конфигурации «1С:ERP Управление предприятием» (в частности, на релизах линейки 2.5.8) пользователи могут столкнуться с критической ошибкой при создании документа распределения расходов будущих периодов (РБП). Ошибка возникает при переходе в меню «Финансовый результат и контроллинг» — «Распределение РБП» — «Распределить расходы».

Система прерывает работу со следующим сообщением:


Ошибка при выполнении обработчика - 'ОбработкаЗаполнения'
по причине:
{Документ.РаспределениеРасходовБудущихПериодов.МодульМенеджера(290)}: Преобразование значения к типу Дата не может быть выполнено

Разберем детально, почему возникает эта проблема, как диагностировать ее причину и какие шаги предпринять для устранения сбоя.

Проанализируем техническую причину ошибки

Давайте посмотрим на исходный код типовой конфигурации, в котором происходит падение. Отладчик приводит нас в функцию ПолучитьДатуВозникновенияРБП. Внутри этой функции выполняется объемный запрос к регистрам накопления ПрочиеРасходы и СебестоимостьТоваров.

Суть запроса сводится к поиску максимальной даты возникновения расхода по определенной статье:


ВЫБРАТЬ
    МАКСИМУМ(ДатыРасходов.Период) КАК Период
ИЗ
    (ВЫБРАТЬ ПрочиеРасходы.Период ... ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ СебестоимостьТоваров.Период ...) КАК ДатыРасходов

После выполнения запроса код пытается получить результат и вернуть начало дня найденной даты:


Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();

Если Выборка.Следующий() Тогда 
    Возврат НачалоДня(Выборка.Период); // ВОТ ЗДЕСЬ ПРОИСХОДИТ ПАДЕНИЕ
КонецЕсли;

Возврат КонецМесяца(ДанныеЗаполнения.Период);

В чем же здесь подвох? Выясним механику работы агрегатной функции языка запросов 1С. Когда внутренний подзапрос не находит ни одной подходящей записи (база данных пуста по заданным фильтрам), внешняя агрегатная функция МАКСИМУМ() не возвращает пустой результат запроса. Согласно стандартам SQL, она вернет ровно одну строку, в которой значением колонки Период будет NULL.

В результате условие Выборка.Следующий() отрабатывает как истина (ведь строка есть!), и система пытается выполнить встроенную функцию НачалоДня(NULL). Платформа 1С не умеет преобразовывать значение NULL в тип Дата, что и вызывает немедленный вылет с ошибкой.

Выясним, почему запрос не находит данные в регистрах

Часто разработчики и аналитики недоумевают: по одной статье РБП документ создается без проблем, а по другой вылетает ошибка, хотя в регистрах визуально присутствуют движения по обеим статьям. Рассмотрим подробнее условия отбора в запросе (секция ГДЕ):


ГДЕ
    ПрочиеРасходы.Организация = &Организация
    И ПрочиеРасходы.Подразделение = &Подразделение
    И ПрочиеРасходы.АналитикаРасходов = &АналитикаРасходов
    И ПрочиеРасходы.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
    И ПрочиеРасходы.Активность
    И ПрочиеРасходы.Период МЕЖДУ НАЧАЛОПЕРИОДА(&Период, МЕСЯЦ) И КОНЕЦПЕРИОДА(&Период, МЕСЯЦ)

Обратите пристальное внимание на последнюю строку отбора. Это скрытый фильтр по месяцу! Запрос ищет дату возникновения расходов будущих периодов строго в том месяце, за который сейчас создается документ распределения.

Если первичные расходы были проведены в системе месяцем или годом ранее, этот запрос физически их не увидит. Подзапрос вернет 0 строк, агрегатная функция вернет NULL, и программа упадет.

Кроме того, запрос требует полного и идеального совпадения всех аналитик. Иногда визуально пустая колонка в регистре содержит значение типа Неопределено, а в параметры передается пустая ссылка типа СправочникСсылка. Для запроса это разные значения, и он отсеет такие записи.

Лайфхак: как быстро отладить сложный типовой запрос

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

  1. Поставьте точку останова в конфигураторе сразу после того, как все параметры запроса установлены (перед строкой Результат = Запрос.Выполнить()).
  2. Откройте табло отладчика (Shift + F9).
  3. Впишите туда выражение: ОбщегоНазначения.ЗапросВСтрокуXML(Запрос) и нажмите Enter.
  4. Скопируйте полученную длинную строку в формате XML.
  5. Откройте любую современную консоль запросов в режиме предприятия. В меню «Ещё» (или в командной панели параметров) найдите кнопку «Заполнить из XML» (или аналогичную по смыслу).
  6. Вставьте вашу строку. Консоль сама восстановит текст запроса и, самое главное, идеально заполнит все параметры нужными типами и значениями из текущего контекста отладки.

Теперь вы можете запускать запрос и удалять условия из блока ГДЕ по одному, пока не поймете, какой именно фильтр отсекает ваши данные.

Варианты решения проблемы

Проанализируем ситуацию и рассмотрим несколько путей решения, в зависимости от ваших прав на изменение базы и релизной политики компании.

Решение 1. Программное исправление через расширение конфигурации (Рекомендуется)

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

Используйте аннотацию &Вместо, чтобы модифицировать блок с получением результата:


&Вместо("ПолучитьДатуВозникновенияРБП")
Функция Расш1_ПолучитьДатуВозникновенияРБП(ДанныеЗаполнения) Экспорт
    // ... здесь идет оригинальный текст запроса и установка параметров ...
    
    Результат = Запрос.Выполнить();
    Выборка = Результат.Выбрать();
    
    // ВАЖНО: Добавляем проверку ЗначениеЗаполнено()
    Если Выборка.Следующий() И ЗначениеЗаполнено(Выборка.Период) Тогда 
        Возврат НачалоДня(Выборка.Период);
    КонецЕсли;
    
    Возврат КонецМесяца(ДанныеЗаполнения.Период);
КонецФункции

Благодаря функции ЗначениеЗаполнено(), если в выборку попадет NULL, условие не выполнится. Алгоритм спокойно перейдет к следующей строке и вернет дату по умолчанию (конец месяца периода заполнения). Документ будет создан без ошибок.

Решение 2. Организационная корректировка данных

Если программиста под рукой нет, проверьте исходные данные в пользовательском режиме. Вам необходимо убедиться, что:

  1. Первичный документ, зафиксировавший расход на статье РБП, проведен именно в том периоде (месяце), за который вы сейчас пытаетесь создать документ распределения.
  2. В первичном документе (например, "Приобретение услуг и прочих активов" или "Внутреннее потребление товаров") досконально заполнены все те же аналитики и подразделения, что и в настройках РБП.

Если расход возник в прошлом периоде, возможно, нужно изменить логику закрытия прошлого месяца или скорректировать дату начала распределения в параметрах статьи.

Решение 3. Обновление конфигурации

Стоит отметить, что разработчики фирмы 1С признали эту особенность кода в релизах ветки 2.5.8. В последующих обновлениях и накопительных патчах (начиная с релизов 2.5.9 и выше) алгоритм обработки РБП был доработан. В типовой код была штатно внедрена проверка на пустые значения при обработке агрегатных функций. Поэтому, если у вас есть возможность планово обновить 1С:ERP, это решит проблему автоматически.

← На главную