Как выполнить арифметические операции с определяемым типом в запросе расширения 1С?

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

При разработке расширений для современных конфигураций 1С (таких как УТ 11, ERP 2 или КА 2) программисты часто сталкиваются с ситуацией, когда стандартные арифметические операции в запросах перестают работать. Особенно остро эта проблема проявляется при попытке умножить или сложить значения полей, имеющих тип ОпределяемыйТип.ДенежноеПолеНеотрицательное или аналогичные ему. Конструктор запроса выдает ошибку "Несовместимые типы", а Система компоновки данных (СКД) отказывается корректно обрабатывать такие поля. В рамках данной статьи мы подробно разберем, почему это происходит и как правильно настроить расширение, чтобы восстановить работоспособность запросов.

Суть проблемы: почему возникают ошибки типизации

Рассмотрим стандартную ситуацию: в типовой конфигурации «1С:Управление торговлей 11.4» ресурс "Цена" в регистре сведений "Цены номенклатуры" имеет тип ОпределяемыйТип.ДенежноеПолеНеотрицательное. В основной конфигурации этот тип базируется на примитивном типе Число(15, 2). Когда мы работаем в основной конфигурации, платформа прекрасно понимает, что за этим типом стоит обычное число, и позволяет выполнять любые математические действия.

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

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

Выясним главную причину ошибки, на которую указали участники обсуждения: отсутствие определяемого типа в составе объектов расширения. Даже если поле ресурса уже находится в расширении, этого недостаточно для полноценной работы типизации запросов.

Рассмотрим пошагово, как исправить ситуацию:

  1. Откроем дерево метаданных основной конфигурации.
  2. Найдем ветку ОпределяемыеТипы.
  3. Выберем тип, который используется в вашем поле (например, ДенежноеПолеНеотрицательное).
  4. Нажмем правую кнопку мыши и выберем команду "Добавить в расширение".

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

Альтернативное решение: Использование оператора ВЫРАЗИТЬ

Иногда возникают ситуации, когда по каким-то причинам заимствование типа нежелательно или не помогает (например, при работе со сложными составными типами). В этом случае мы можем принудительно заставить платформу трактовать поле как число. Разберем нюансы работы оператора ВЫРАЗИТЬ в языке запросов.

Важное ограничение: Вы не можете написать ВЫРАЗИТЬ(Цена КАК ОпределяемыйТип.ДенежноеПолеНеотрицательное). Оператор ВЫРАЗИТЬ предназначен для работы только с примитивными типами или ссылками на объекты метаданных.

Для выполнения расчета следует приводить поле к базовому типу Число. Посмотрим на пример кода в тексте запроса:


ВЫБРАТЬ
    ЦеныНоменклатурыСрезПоследних.Номенклатура КАК Номенклатура,
    ВЫРАЗИТЬ(ЦеныНоменклатурыСрезПоследних.Цена КАК ЧИСЛО(15, 2)) * &Коэффициент КАК ЦенаСНаценкой
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК ЦеныНоменклатурыСрезПоследних

Проанализируем этот подход. Используя ВЫРАЗИТЬ(... КАК ЧИСЛО(15, 2)), мы явно указываем типизацию для СУБД. Это снимает неопределенность на этапе компиляции запроса. Если поле в расширении ведет себя "капризно", такое явное преобразование типов в 99% случаев решает проблему несовместимости при умножении, делении или сложении.

Особенности работы в Системе компоновки данных (СКД)

Если ваша задача решается в рамках макета СКД (как упоминалось в сообщении №9), стоит обратить внимание на еще один аспект. СКД при генерации временных таблиц анализирует метаданные очень строго. Если тип не заимствован, СКД может назначить полю тип "ОписаниеТипов", который содержит в себе пустое значение. Это заблокирует расчеты в вычисляемых полях или ресурсах отчета.

Посмотрим, что нужно проверить в СКД:

Рекомендации по платформе и кэшированию

Выясним, почему иногда решение "не взлетает" сразу. Начиная с версии платформы 8.3.13, механизмы валидации типов стали жестче. Проанализируем ситуацию, когда тип заимствован, но ошибка сохраняется:

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

2. Тестирование и исправление: Хотя для расширений эта процедура менее актуальна, чем для основной базы, иногда полезно запустить "Синхронизацию данных с конфигурацией" или проверить целостность расширения через меню "Конфигурация - Расширения конфигурации - Проверить применимость".

3. Составные типы: Если ваш определяемый тип является составным (например, может содержать и Число, и Ссылку), то арифметические операции будут запрещены на уровне логики БД. В этом случае использование ВЫРАЗИТЬ является единственным законным способом совершить математическое действие, предварительно "отсеяв" нечисловые значения.

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

← На главную