Как преобразовать ставку НДС из перечисления в число и рассчитать цену с НДС?

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

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

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

Причина ошибки и разница типов данных

Рассмотрим природу проблемы. В конфигурации для хранения возможных вариантов ставок создается объект метаданных Перечисление (например, СтавкиНДС или НДС), содержащий значения Процент20, Процент10, БезНДС. В строке табличной части реквизит с таким типом хранит именно ссылку на элемент перечисления.

Распространенная ошибка заключается в попытке выполнить операцию вида:

СтрокаТабличнойЧасти.ЦенаСНДС = СтрокаТабличнойЧасти.Цена * СтрокаТабличнойЧасти.НДС;

Платформа 1С не умеет автоматически приводить ссылочный тип к числу. Нельзя также просто перезаписать числовое значение в этот же реквизит — если у поля задан тип перечисления, записать число туда не удастся. Для выполнения вычислений необходимо сопоставить каждому элементу перечисления соответствующий числовой процент с помощью отдельного алгоритма.

Реализация функции получения ставки НДС

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

В управляемых формах такую функцию рекомендуется объявлять с директивой &НаКлиентеНаСервереБезКонтекста либо выносить в общий модуль. Это позволяет вызывать алгоритм на клиенте без передачи контекста формы на сервер и без снижения производительности интерфейса.


&НаКлиентеНаСервереБезКонтекста
Функция ПолучитьСтавкуНДС(СтавкаНДС)
    Если СтавкаНДС = ПредопределенноеЗначение("Перечисление.НДС.Процент20") Тогда
        Возврат 20;
    ИначеЕсли СтавкаНДС = ПредопределенноеЗначение("Перечисление.НДС.Процент10") Тогда
        Возврат 10;
    ИначеЕсли СтавкаНДС = ПредопределенноеЗначение("Перечисление.НДС.БезНДС") Тогда
        Возврат 0;
    КонецЕсли;
    
    Возврат 0;
КонецФункции

Если код выполняется в контексте формы, где доступна работа с менеджерами перечислений, можно использовать прямую проверку:


&НаКлиенте
Функция ПолучитьСтавкуНДС(СтавкаНДС)
    Если СтавкаНДС = Перечисления.НДС.Процент20 Тогда
        Возврат 20;
    ИначеЕсли СтавкаНДС = Перечисления.НДС.Процент10 Тогда
        Возврат 10;
    ИначеЕсли СтавкаНДС = Перечисления.НДС.Процент18 Тогда
        Возврат 18;
    КонецЕсли;
    
    Возврат 0;
КонецФункции

Расчет цены и сумм в табличной части

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

Посмотрим на пример обработчика ПриИзменении для колонки выбора ставки НДС:


&НаКлиенте
Процедура ЗаказанныйТоварНДСПриИзменении(Элемент)
    СтрокаТабличнойЧасти = Элементы.ЗаказанныйТовар.ТекущиеДанные;
    Если СтрокаТабличнойЧасти = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    ЧисловаяСтавка = ПолучитьСтавкуНДС(СтрокаТабличнойЧасти.НДС);
    
    // Формула расчета: ЦенаСНДС = Цена + (Цена * Ставка / 100)
    СтрокаТабличнойЧасти.ЦенаСНДС = Окр(СтрокаТабличнойЧасти.Цена * (100 + ЧисловаяСтавка) / 100, 2, РежимОкругления.15как20);
КонецПроцедуры

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

Получение ставки НДС в запросах 1С

Если пересчет сумм или вывод ставки в числовом виде требуется реализовать не на форме, а внутри запроса (например, при проведении документа или формировании отчета), механизм будет другим. В языке запросов нельзя вызвать пользовательскую функцию, поэтому применяется конструкция ВЫБОР КОГДА.

Проанализируем фрагмент запроса:


ВЫБРАТЬ
    Таблица.Номенклатура КАК Номенклатура,
    Таблица.Цена КАК Цена,
    ВЫБОР
        КОГДА Таблица.НДС = ЗНАЧЕНИЕ(Перечисление.НДС.Процент20) ТОГДА 20
        КОГДА Таблица.НДС = ЗНАЧЕНИЕ(Перечисление.НДС.Процент10) ТОГДА 10
        КОГДА Таблица.НДС = ЗНАЧЕНИЕ(Перечисление.НДС.Процент18) ТОГДА 18
        ИНАЧЕ 0
    КОНЕЦ КАК СтавкаЧислом
ИЗ
    Документ.ЗаказКлиента.Товары КАК Таблица

Альтернативный архитектурный подход

Рассмотрим более гибкое решение, которое часто применяется в типовых конфигурациях. Использование перечисления имеет существенный недостаток: при изменении налогового законодательства или введении расчетных ставок (например, 20/120) разработчик вынужден вносить изменения в структуру конфигурации через конфигуратор.

Вместо объекта Перечисление архитектурно удобнее использовать Справочник (например, «Ставки НДС»). Добавив в справочник числовой реквизит Ставка, мы получаем ряд преимуществ:

  1. Числовое значение можно считывать напрямую через точку от ссылки: СтрокаТабличнойЧасти.СтавкаНДС.Ставка без написания условий Если ... ИначеЕсли.
  2. Пользователи в режиме «1С:Предприятие» могут самостоятельно добавлять новые элементы и редактировать значения ставок без участия программиста.
← На главную