При разработке расширений для современных конфигураций 1С (таких как УТ 11, ERP 2 или КА 2) программисты часто сталкиваются с ситуацией, когда стандартные арифметические операции в запросах перестают работать. Особенно остро эта проблема проявляется при попытке умножить или сложить значения полей, имеющих тип ОпределяемыйТип.ДенежноеПолеНеотрицательное или аналогичные ему. Конструктор запроса выдает ошибку "Несовместимые типы", а Система компоновки данных (СКД) отказывается корректно обрабатывать такие поля. В рамках данной статьи мы подробно разберем, почему это происходит и как правильно настроить расширение, чтобы восстановить работоспособность запросов.
Рассмотрим стандартную ситуацию: в типовой конфигурации «1С:Управление торговлей 11.4» ресурс "Цена" в регистре сведений "Цены номенклатуры" имеет тип ОпределяемыйТип.ДенежноеПолеНеотрицательное. В основной конфигурации этот тип базируется на примитивном типе Число(15, 2). Когда мы работаем в основной конфигурации, платформа прекрасно понимает, что за этим типом стоит обычное число, и позволяет выполнять любые математические действия.
Однако, как только мы переносим разработку в расширение, механизм работы с метаданными меняется. Если мы заимствуем только регистр, но забываем заимствовать сам определяемый тип, платформа теряет логическую связь между полем регистра и его базовым числовым представлением. Для системы в контексте расширения поле становится объектом с неопределенной структурой. Проанализируем, к каким последствиям это приводит:
ВЫРАЗИТЬ может выдавать ошибку при попытке прямого приведения.Выясним главную причину ошибки, на которую указали участники обсуждения: отсутствие определяемого типа в составе объектов расширения. Даже если поле ресурса уже находится в расширении, этого недостаточно для полноценной работы типизации запросов.
Рассмотрим пошагово, как исправить ситуацию:
ОпределяемыеТипы.ДенежноеПолеНеотрицательное).После того как определяемый тип появится в вашем расширении, платформа «прокинет» связь до физической структуры данных. Теперь конструктор запроса поймет, что поле является числовым, и позволит выполнять арифметические операции без дополнительных манипуляций. Это самый правильный и чистый способ решения проблемы с точки зрения архитектуры 1С.
Иногда возникают ситуации, когда по каким-то причинам заимствование типа нежелательно или не помогает (например, при работе со сложными составными типами). В этом случае мы можем принудительно заставить платформу трактовать поле как число. Разберем нюансы работы оператора ВЫРАЗИТЬ в языке запросов.
Важное ограничение: Вы не можете написать ВЫРАЗИТЬ(Цена КАК ОпределяемыйТип.ДенежноеПолеНеотрицательное). Оператор ВЫРАЗИТЬ предназначен для работы только с примитивными типами или ссылками на объекты метаданных.
Для выполнения расчета следует приводить поле к базовому типу Число. Посмотрим на пример кода в тексте запроса:
ВЫБРАТЬ
ЦеныНоменклатурыСрезПоследних.Номенклатура КАК Номенклатура,
ВЫРАЗИТЬ(ЦеныНоменклатурыСрезПоследних.Цена КАК ЧИСЛО(15, 2)) * &Коэффициент КАК ЦенаСНаценкой
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК ЦеныНоменклатурыСрезПоследних
Проанализируем этот подход. Используя ВЫРАЗИТЬ(... КАК ЧИСЛО(15, 2)), мы явно указываем типизацию для СУБД. Это снимает неопределенность на этапе компиляции запроса. Если поле в расширении ведет себя "капризно", такое явное преобразование типов в 99% случаев решает проблему несовместимости при умножении, делении или сложении.
Если ваша задача решается в рамках макета СКД (как упоминалось в сообщении №9), стоит обратить внимание на еще один аспект. СКД при генерации временных таблиц анализирует метаданные очень строго. Если тип не заимствован, СКД может назначить полю тип "ОписаниеТипов", который содержит в себе пустое значение. Это заблокирует расчеты в вычисляемых полях или ресурсах отчета.
Посмотрим, что нужно проверить в СКД:
Число (или соответствующий определяемый тип, если он заимствован).Цена * 1.1 не работает, используйте функции языка выражений СКД для приведения типов.Выясним, почему иногда решение "не взлетает" сразу. Начиная с версии платформы 8.3.13, механизмы валидации типов стали жестче. Проанализируем ситуацию, когда тип заимствован, но ошибка сохраняется:
1. Очистка кэша: Платформа 1С активно кэширует структуру метаданных расширений. Иногда после добавления определяемого типа в расширение конфигуратор продолжает "помнить" старую структуру. Рекомендуется перезапустить конфигуратор, а в идеале — очистить локальный кэш конфигурации.
2. Тестирование и исправление: Хотя для расширений эта процедура менее актуальна, чем для основной базы, иногда полезно запустить "Синхронизацию данных с конфигурацией" или проверить целостность расширения через меню "Конфигурация - Расширения конфигурации - Проверить применимость".
3. Составные типы: Если ваш определяемый тип является составным (например, может содержать и Число, и Ссылку), то арифметические операции будут запрещены на уровне логики БД. В этом случае использование ВЫРАЗИТЬ является единственным законным способом совершить математическое действие, предварительно "отсеяв" нечисловые значения.
Подводя итог нашему разбору, можно с уверенностью сказать: шанс произвести арифметическую операцию в запросе с определяемым типом не просто есть — это штатная возможность платформы. Главное правило — соблюдать полноту описания метаданных в вашем расширении и не забывать о заимствовании базовых типов, на которых строятся ваши данные.