При разработке учетных механизмов в 1С часто возникает задача расчета тарифа или стоимости услуг в зависимости от параметров отправления: тарифной зоны, срочности и суммарного веса позиций в документе. Разберем типичные ошибки, возникающие при подсчете итогов по табличной части и составлении условий проверки числовых диапазонов во встроенном языке 1С, а также рассмотрим правильные способы реализации такой логики.
Если вес указывается для каждой отдельной строки документа, перед определением итогового тарифа необходимо сложить значения по всей колонке. Для этого во встроенном языке 1С предназначен метод Итог().
Метод применяется напрямую к объекту табличной части и принимает в качестве параметра строковое имя колонки, по которой нужно получить сумму:
// Пример для модуля формы
Объект.ОбщийВес = Объект.ВидОтправления.Итог("Вес");
Обратите внимание на важные особенности работы с методом Итог():
Вес) обязательно должна иметь числовой тип данных. Если тип реквизита составной или строковый, метод не сможет корректно выполнить суммирование.Объект.ИмяТабличнойЧасти используется в модулях управляемых форм. Если расчет выполняется на стороне сервера в модуле объекта (например, в процедуре ОбработкаПроведения), обращение к табличной части происходит напрямую по имени реквизита или через ключевое слово ЭтотОбъект:
// Пример для модуля объекта
ОбщийВес = ЭтотОбъект.ВидОтправления.Итог("Вес");
Проанализируем распространенную логическую ошибку при проверке вхождения числа в диапазон. Запись вида Объект.ОбщийВес > 1 <= 5 или ОбщийВес 1 5 10 <= 30 является синтаксически и логически некорректной.
Во встроенном языке 1С составные математические неравенства вычисляются последовательно слева направо. Выражение ОбщийВес > 1 сначала возвращает булево значение (Истина или Ложь). Далее платформа пытается сравнить полученное булево значение со следующим числом, неявно приводя Истина к 1, а Ложь к 0. В результате условие 1 <= 5 или 0 <= 5 всегда возвращает Истина, нарушая всю логику работы алгоритма.
Для правильной проверки диапазона необходимо явно разделять условия логическим оператором И:
Если ОбщийВес > 1 И ОбщийВес <= 5 Тогда
Сумма = 50;
КонецЕсли;
Также удобно использовать каскадную конструкцию Если ... ИначеЕсли, проверяя значения по возрастанию верхней границы. Это избавляет от необходимости дважды указывать переменные:
Если ОбщийВес <= 1 Тогда
Сумма = 25;
ИначеЕсли ОбщийВес <= 5 Тогда
Сумма = 50;
ИначеЕсли ОбщийВес <= 30 Тогда
Сумма = 189;
Иначе
// Обработка веса свыше 30 кг
Сумма = 250;
КонецЕсли;
В исходном коде часто встречается условие проверки реквизитов по их названию: Объект.ЗонаДоставки.Наименование = "Междугородняя". Проверка по строкам считается плохой практикой в 1С по следующим причинам:
Для надежной фиксации условий используйте один из следующих подходов:
Перечисление. Сравнение выполняется через ссылку: Объект.СкоростьДоставки = Перечисления.СкоростиДоставки.Обычная.Объект.ЗонаДоставки = Справочники.ЗоныДоставки.Междугородняя.Соберем все правила воедино и посмотрим на корректный пример реализации функции расчета стоимости:
Функция РассчитатьСтоимостьДоставки(ДокументОбъект) Экспорт
// 1. Получаем суммарный вес по табличной части
ОбщийВес = ДокументОбъект.ВидОтправления.Итог("Вес");
// 2. Инициализируем базовое значение суммы
Стоимость = 0;
// 3. Проверяем параметры доставки и рассчитываем тариф
Если ДокументОбъект.ЗонаДоставки = Справочники.ЗоныДоставки.Междугородняя
И ДокументОбъект.СкоростьДоставки = Перечисления.СкоростиДоставки.Обычная Тогда
Если ОбщийВес <= 1 Тогда
Стоимость = 25;
ИначеЕсли ОбщийВес > 1 И ОбщийВес <= 5 Тогда
Стоимость = 50;
ИначеЕсли ОбщийВес > 5 И ОбщийВес <= 30 Тогда
Стоимость = 189;
Иначе
Стоимость = 300;
КонецЕсли;
КонецЕсли;
Возврат Стоимость;
КонецФункции
Если шкала тарифов часто меняется, жестко прописывать числовые значения в коде через Если ... ИначеЕсли не рекомендуется. Оптимальным решением будет создание непериодического или периодического регистра сведений (например, ТарифыДоставки) со следующей структурой:
ЗонаДоставки (Справочник), СкоростьДоставки (Перечисление), ПорогВеса (Число).Стоимость (Число).В таком случае поиск цены под конкретный вес выполняется через простой запрос с условием ГДЕ ПорогВеса >= &ВесОтправления УПОРЯДОЧИТЬ ПО ПорогВеса ВОЗР и выборкой первой записи (ВЫБРАТЬ ПЕРВЫЕ 1). Это позволит пользователям гибко настраивать сетку тарифов в режиме «1С:Предприятие» без доработки конфигурации.