В процессе разработки конфигураций на платформе 1С:Предприятие 8.3 часто возникает задача автоматизации расчетов. Типичный пример — изменение стоимости услуги в зависимости от выбранной категории срочности. В этой статье мы подробно разберем, как правильно реализовать эту логику, избежав распространенных ошибок, таких как «бесконечное» увеличение цены или лишние серверные вызовы.
Представим ситуацию: у нас есть документ, в котором пользователь выбирает значение из перечисления Срочность. Если выбрано значение Сверхсрочный, цена должна увеличиться на 1000 единиц. Проанализируем самый простой способ реализации через обработчик события ПриИзменении.
Для начала нам необходимо создать обработчик для поля формы, где выбирается срочность. Мы будем использовать событие ПриИзменении, так как оно срабатывает сразу после того, как пользователь выбрал новое значение.
Рассмотрим пример кода для управляемой формы:
&НаКлиенте
Процедура СрочностьПриИзменении(Элемент)
СтрокаТЧ = Элементы.Товары.ТекущиеДанные;
Если СтрокаТЧ.Срочность = ПредопределенноеЗначение("Перечисление.Срочность.Сверхсрочный") Тогда
СтрокаТЧ.Цена = СтрокаТЧ.Цена + 1000;
КонецЕсли;
КонецПроцедуры
В данном примере мы обращаемся к ТекущиеДанные табличной части. Это позволяет нам изменять реквизиты именно той строки, с которой сейчас взаимодействует пользователь. Однако, этот подход имеет существенный недостаток, о котором стоит поговорить подробнее.
Выясним причину, по которой опытные разработчики не рекомендуют изменять напрямую основное поле Цена. Проанализируем ситуацию: пользователь выбрал Сверхсрочный — цена увеличилась на 1000. Затем он случайно перевыбрал это же значение или переключился на Срочный и обратно. При каждом срабатывании кода цена будет расти на 1000 снова и снова.
Более того, система «забывает», была ли уже добавлена надбавка. Чтобы решить эту проблему, рассмотрим два профессиональных подхода:
НаценкаЗаСрочность. Тогда итоговая цена всегда рассчитывается как ЦенаБазовая + НаценкаЗаСрочность.ЦенаБезСрочности. При изменении статуса мы всегда берем за основу это поле и прибавляем к нему нужную сумму.Разберем по шагам, как реализовать надежный механизм расчета, который не будет ошибаться при повторных изменениях. Посмотрим на пример кода, который учитывает очистку значения и возврат к исходной цене:
&НаКлиенте
Процедура СрочностьПриИзменении(Элемент)
ТекущаяСтрока = Элементы.Услуги.ТекущиеДанные;
// Определяем размер надбавки
Надбавка = 0;
Если ТекущаяСтрока.Срочность = ПредопределенноеЗначение("Перечисление.Срочность.Сверхсрочный") Тогда
Надбавка = 1000;
ИначеЕсли ТекущаяСтрока.Срочность = ПредопределенноеЗначение("Перечисление.Срочность.Срочный") Тогда
Надбавка = 0; // Для наглядности
КонецЕсли;
// Рассчитываем итоговую цену от базовой
// Предполагается, что БазоваяЦена заполнилась при выборе услуги
ТекущаяСтрока.Цена = ТекущаяСтрока.БазоваяЦена + Надбавка;
// Вызываем пересчет суммы строки, если это необходимо
ПересчитатьСуммуСтроки(ТекущаяСтрока);
КонецПроцедуры
Использование ПредопределенноеЗначение позволяет нам выполнять проверку на стороне клиента без обращения к серверу, что значительно ускоряет работу интерфейса, особенно при медленном интернет-соединении.
Проанализируем вопрос производительности. В сообщениях форума часто обсуждается, стоит ли делать серверный вызов для таких вычислений. Если логика ограничивается простым прибавлением числа, серверный вызов (директива &НаСервере) будет избыточным и замедлит отклик формы.
Однако, если сумма надбавки хранится не в коде, а в специальном регистре сведений или константе, нам потребуется серверный контекст. В таком случае рекомендуется использовать &НаСервереБезКонтекста, чтобы передавать на сервер только необходимые данные, а не всю форму целиком.
&НаСервереБезКонтекста
Функция ПолучитьАктуальнуюНадбавку(ЗначениеСрочности)
// Здесь может быть запрос к Регистру Сведений или Константе
Возврат РегистрыСведений.НастройкиПродаж.ПолучитьНадбавку(ЗначениеСрочности);
КонецФункции
Рассмотрим ситуацию, когда завтра руководство решает добавить третий уровень срочности — «Молниеносный» — с надбавкой 5000. Если вы использовали Перечисление и «захардкодили» сумму 1000 в тексте программы, вам придется вносить изменения в конфигурацию и обновлять базу данных всех пользователей.
Правильный подход: использовать Справочник.ВидыСрочности. В самом справочнике можно добавить числовой реквизит СуммаНадбавки. В этом случае программист пишет код один раз, а менеджер может самостоятельно добавлять новые виды срочности и менять цены в пользовательском режиме без участия разработчика.
Посмотрим, как изменится код при использовании справочника:
&НаКлиенте
Процедура СрочностьПриИзменении(Элемент)
ТекущаяСтрока = Элементы.Услуги.ТекущиеДанные;
// Получаем надбавку напрямую из реквизита справочника
// Для этого может потребоваться получение объекта или использование данных выбора
Надбавка = ТекущаяСтрока.Срочность.СуммаНадбавки;
ТекущаяСтрока.Цена = ТекущаяСтрока.БазоваяЦена + Надбавка;
КонецПроцедуры
Для повышения удобства работы (UX) мы рекомендуем использовать Условное оформление формы. Выясним, как это помогает в работе: когда пользователь выбирает «Сверхсрочный», цена не просто меняется, а может подсвечиваться другим цветом. Это дает визуальное подтверждение того, что система применила надбавку. Настроить это можно в свойствах формы на закладке «Условное оформление», задав условие Объект.Товары.Срочность Равно Сверхсрочный и установив формат цвета текста или фона для поля Цена.
Подводя итог, при реализации автозаполнения полей в 1С придерживайтесь следующих правил:
ПредопределенноеЗначение.Неопределено или ПустаяСсылка).