Ошибка 'Несовместимые типы' при делении определяемых типов в запросах динамических списков в расширении 1С 8.3

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

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

Суть проблемы: несовместимость типов при арифметических операциях

Представим, что у нас есть запрос к регистру накопления ЗаказыКлиентовОстаткиИОбороты. Нам необходимо получить цену номенклатуры, рассчитав ее как отношение суммы к количеству: СуммаКонечныйОстаток / ЗаказаноКонечныйОстаток. При этом поле СуммаКонечныйОстаток имеет определяемый тип, например, ДенежнаяСуммаЛюбогоЗнака, а поле ЗаказаноКонечныйОстаток — обычный тип Число.

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

Даже если мы попытаемся явно привести тип с помощью функции ВЫРАЗИТЬ, как показано в примере ниже, ошибка остается:


ВЫБРАТЬ
    ЗаказыКлиентовОстаткиИОбороты.Номенклатура,
    ВЫРАЗИТЬ(ЗаказыКлиентовОстаткиИОбороты.СуммаКонечныйОстаток КАК ЧИСЛО) / ЗаказыКлиентовОстаткиИОбороты.ЗаказаноКонечныйОстаток КАК Цена
ИЗ
    РегистрНакопления.ЗаказыКлиентовОстаткиИОбороты КАК ЗаказыКлиентовОстаткиИОбороты

Или даже с указанием точности:


ВЫБРАТЬ
    ЗаказыКлиентовОстаткиИОбороты.Номенклатура,
    ВЫРАЗИТЬ(ЗаказыКлиентовОстаткиИОбороты.СуммаКонечныйОстаток КАК ЧИСЛО(15,2)) / ЗаказыКлиентовОстаткиИОбороты.ЗаказаноКонечныйОстаток КАК Цена
ИЗ
    РегистрНакопления.ЗаказыКлиентовОстаткиИОбороты КАК ЗаказыКлиентовОстаткиИОбороты

В чем же причина такого поведения? Функция ВЫРАЗИТЬ предназначена для явного приведения значения к указанному типу с заданием квалификаторов. Однако, платформа 1С может порой интерпретировать определяемые типы, особенно в контексте расширений и динамических списков, таким образом, что даже явное приведение к, казалось бы, совместимому типу ЧИСЛО оказывается невозможным из-за внутренних особенностей обработки метаданных. Это особенно актуально, когда речь идет о модификации типовых объектов или создании новых запросов в расширении.

Интересно, что тот же самый запрос, выполненный в консоли запросов (например, в «Инструментах разработчика»), может отрабатывать абсолютно корректно, что наводит на мысль о специфике ошибки, связанной именно с конфигуратором, динамическими списками и взаимодействием с расширениями.

Основное решение: повторное добавление определяемого типа в расширение

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

Для устранения ошибки нам необходимо выполнить следующие шаги:

  1. Откройте расширение: Запустите 1С:Предприятие в режиме конфигуратора. Перейдите в окно расширений и откройте то расширение, в котором возникает проблема.
  2. Найдите определяемый тип: В дереве объектов конфигурации расширения найдите раздел "ОпределяемыеТипы".
  3. Удалите определяемый тип (при необходимости): Если определяемый тип (например, ДенежнаяСуммаЛюбогоЗнака) уже присутствует в расширении, временно удалите его. Будьте внимательны: это действие не удаляет сам определяемый тип из основной конфигурации, а лишь убирает его из состава расширения.
  4. Повторно добавьте определяемый тип в расширение: Найдите определяемый тип в основной конфигурации (раздел "ОпределяемыеТипы") и добавьте его в ваше расширение (например, через контекстное меню "Добавить в расширение").
  5. Обновите конфигурацию базы данных: После добавления/передобавления определяемого типа обязательно обновите конфигурацию базы данных (F7).
  6. Проверьте запрос: Вернитесь к динамическому списку и запросу, вызывающему ошибку. Теперь арифметическая операция должна выполняться корректно.

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

Дополнительные методы диагностики и обходные пути

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

Проверка в консоли запросов

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

Программное формирование запроса

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

Пример (псевдокод для формы списка):


&НаСервере
Процедура ПриСозданииНаСервере(Отказ)
    // ...
    ТекстЗапроса = "
    |ВЫБРАТЬ
    |    ЗаказыКлиентовОстаткиИОбороты.Номенклатура КАК Номенклатура,
    |    ЗаказыКлиентовОстаткиИОбороты.СуммаКонечныйОстаток / ЗаказыКлиентовОстаткиИОбороты.ЗаказаноКонечныйОстаток КАК Цена
    |ИЗ
    |    РегистрНакопления.ЗаказыКлиентовОстаткиИОбороты КАК ЗаказыКлиентовОстаткиИОбороты
    |";
    Элементы.Список.ТекстЗапроса = ТекстЗапроса;
    // ...
КонецПроцедуры

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

Обработка деления на ноль и NULL

Хотя в нашем случае автор утверждал, что поля не должны быть нулевыми или NULL из-за логики проведения документов, это всегда важный аспект, который следует учитывать при любых операциях деления. Деление на ноль или NULL всегда приведет к ошибке выполнения запроса. Для безопасного расчета цены мы можем использовать оператор ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ:


ВЫБРАТЬ
    ЗаказыКлиентовОстаткиИОбороты.Номенклатура,
    ВЫБОР
        КОГДА ЗаказыКлиентовОстаткиИОбороты.ЗаказаноКонечныйОстаток = 0
            ТОГДА 0 // или NULL, или другое значение по умолчанию
        ИНАЧЕ ЗаказыКлиентовОстаткиИОбороты.СуммаКонечныйОстаток / ЗаказыКлиентовОстаткиИОбороты.ЗаказаноКонечныйОстаток
    КОНЕЦ КАК Цена
ИЗ
    РегистрНакопления.ЗаказыКлиентовОстаткиИОбороты КАК ЗаказыКлиентовОстаткиИОбороты

Этот подход гарантирует, что запрос не завершится с ошибкой даже при наличии некорректных данных в базе.

Определение фактического типа с помощью ТИПЗНАЧЕНИЯ()

Для глубокой диагностики того, какой тип данных платформа фактически "видит" в полях, мы можем использовать функцию ТИПЗНАЧЕНИЯ() непосредственно в запросе. Это поможет нам подтвердить или опровергнуть подозрения на составной тип или на некорректное определение типа:


ВЫБРАТЬ
    ТИПЗНАЧЕНИЯ(ЗаказыКлиентовОстаткиИОбороты.СуммаКонечныйОстаток) КАК ТипСуммы,
    ТИПЗНАЧЕНИЯ(ЗаказыКлиентовОстаткиИОбороты.ЗаказаноКонечныйОстаток) КАК ТипЗаказано
ИЗ
    РегистрНакопления.ЗаказыКлиентовОстаткиИОбороты КАК ЗаказыКлиентовОстаткиИОБОРОТЫ
ЛИМИТ 10

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

Актуальность платформы и режим совместимости

Иногда подобные ошибки являются следствием багов платформы, которые исправляются в новых релизах. Всегда рекомендуется работать на актуальной, стабильной версии 1С:Предприятия. Также стоит проверить режим совместимости вашей конфигурации (и расширения, если применимо). Если режим совместимости установлен на очень старую версию (например, ниже 8.3.3, где определяемые типы могли обрабатываться иначе), это также может стать причиной проблем.

Заключение

Проблема "Несовместимые типы" при арифметических операциях с определяемыми типами в запросах динамических списков, особенно в расширениях, является специфической особенностью платформы 1С. Мы выяснили, что наиболее частая и эффективная причина ее возникновения — это некорректная синхронизация метаданных определяемых типов в расширении. Повторное добавление определяемого типа в расширение, как правило, устраняет эту проблему. В случаях, когда это не помогает, или для более глубокого понимания ситуации, мы используем диагностические инструменты, такие как консоль запросов и функция ТИПЗНАЧЕНИЯ(), а также обходные пути, включая программное формирование запросов и обработку исключительных ситуаций деления на ноль. Мы призываем всегда внимательно относиться к работе с типами данных, особенно в модифицированных конфигурациях и расширениях.

← На главную