Как исправить ошибку «Неверный тип значения» при записи движений в расширении после обновления 1С:ERP

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

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

Проанализируем ситуацию и выявим причину

Ошибка обычно возникает в модуле объекта документа (чаще всего в процедуре &После("ОбработкаПроведения")) при выполнении следующей строки кода:

НаборЗаписей.Отбор.Регистратор.Значение = ЭтотОбъект.Ссылка;

Выясним основную причину такого поведения. С обновлением конфигурации ERP до версии 2.5.12 обязательным условием является повышение режима совместимости до 8.3.21. В этом режиме платформа 1С начинает гораздо строже контролировать типы данных. Поле Регистратор у регистра накопления имеет составной тип. Если в метаданных (особенно в расширении) документ не указан как регистратор для этого регистра, то ссылка на этот документ физически не входит в составной тип поля Регистратор. В результате попытка присвоить ссылку приводит к ошибке Неверный тип значения, так как для системы этот тип является «чужеродным».

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

Шаг 1. Проверка и настройка метаданных в расширении

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

  1. Откроем конфигуратор и перейдем в управление расширениями.
  2. Найдем нужное расширение и раскроем ветку Регистры накопления.
  3. Выберем наш регистр (в примере это ую_ЧасыРаспоряженийПоЗаданиямНаПеревозку) и откроем его свойства.
  4. Перейдем на закладку Регистраторы.
  5. В списке всех документов найдем ЗаказПоставщику. Скорее всего, после обновления флаг («галочка») напротив него будет снят или документ вовсе не будет добавлен в расширение.
  6. Важный момент: если документа нет в списке, его нужно добавить в расширение (нажать правой кнопкой на документ в основной конфигурации — «Добавить в расширение»).
  7. Установим флаг напротив документа в списке регистраторов регистра накопления.

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

Шаг 2. Использование метода Установить()

Проанализируем альтернативный способ установки отбора. Вместо прямого присвоения свойства Значение рекомендуется использовать метод Установить(). Рассмотрим пример:


// Вместо этого:
// НаборЗаписей.Отбор.Регистратор.Значение = ЭтотОбъект.Ссылка;

// Используем это:
НаборЗаписей.Отбор.Регистратор.Установить(ЭтотОбъект.Ссылка);

Хотя этот метод также выдаст ошибку, если типы не совпадают, он является более предпочтительным с точки зрения стандартов разработки 1С, так как одновременно устанавливает и значение, и флаг использования отбора (Использование = Истина).

Шаг 3. Переход на работу через коллекцию Движения

Посмотрим на код из примера более критично. В ERP принято работать с движениями документа через коллекцию ЭтотОбъект.Движения, а не создавать наборы записей вручную через менеджер регистра. Это позволяет платформе корректно управлять транзакциями и блокировками.

Если при попытке обратиться к ЭтотОбъект.Движения.ИмяВашегоРегистра система выдает ошибку Поле объекта не обнаружено, это стопроцентное подтверждение того, что в метаданных документ не назначен регистратором для этого регистра.

Рассмотрим, как должен выглядеть правильный код в расширении после исправления метаданных:


&После("ОбработкаПроведения")
Процедура ую_ОбработкаПроведения(Отказ, РежимПроведения)
    
    // Проверяем дату, если это необходимо по логике бизнес-процесса
    Если НачалоДня(ЭтотОбъект.Дата) < Дата(2021, 07, 01) Тогда
        Возврат;
    КонецЕсли;

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

    РезультатЗапроса = Запрос.Выполнить();
    Если Не РезультатЗапроса.Пустой() Тогда
        Выборка = РезультатЗапроса.Выбрать();
        
        Пока Выборка.Следующий() Цикл
            // Добавляем новую запись в набор
            НоваяЗапись = НаборЗаписей.ДобавитьРасход();
            НоваяЗапись.Период = ЭтотОбъект.Дата;
            
            // Заполняем измерения и ресурсы из выборки запроса
            ЗаполнитьЗначенияСвойств(НоваяЗапись, Выборка);
        КонецЦикла;
    КонецЕсли;

    // Важно: в ОбработкаПроведения не нужно вызывать НаборЗаписей.Записать(), 
    // если установлен флаг Записывать = Истина. Платформа запишет всё сама в конце транзакции.
    
КонецПроцедуры

Почему это важно для стабильности системы?

Разберем, почему ручное управление набором записей через СоздатьНаборЗаписей() внутри проведения — это плохая практика:

Таким образом, для исправления ошибки Неверный тип значения после обновления ERP, вам достаточно обновить расширение, убедиться в наличии флага регистратора у документа и перевести код на использование стандартной коллекции Движения. Это не только решит текущую проблему, но и сделает вашу конфигурацию более устойчивой к будущим обновлениям платформы.

← На главную