Почему в 1С искажается итоговая сумма при создании реализации на основании заказа со скидкой, рассчитанной от суммы?

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

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

Проблема кроется в типовой методологии 1С. Система стремится сохранить логическую целостность данных по формуле: (Цена × Количество) - Скидка = Сумма. Когда вы в заказе меняете сумму, система вычисляет процент скидки. Часто этот процент оказывается бесконечной дробью (например, 16,666...%). Система округляет его и сохраняет в таком виде. При создании документа "на основании" 1С не просто копирует итоговую сумму, а выполняет перерасчет, используя ключевые параметры: цену, количество и тот самый округленный процент скидки. Из-за этой погрешности в округлении и возникает разница в итоговых суммах.

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

Рассмотрим несколько способов решения: от простого организационного до полноценной программной доработки.

Решение 1: Организационный обходной путь

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

  1. Отключите настройку. В настройках пользователя измените параметр на "При изменении суммы пересчитывать цену, а не скидку".

  2. Объясните пользователям. Проведите инструктаж для менеджеров, объяснив, что система не позволяет точно работать с итоговой суммой таким образом. Им придется оперировать процентом скидки или ценой.

Плюсы: быстро, не требует программирования, не ломает типовой механизм.

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

Решение 2: Программная доработка (рекомендуемый)

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

Вариант А: Изменение модуля документа "Реализация товаров и услуг"

Этот подход предполагает точечное изменение логики заполнения только одного документа, что является наиболее безопасным.

Шаги:

  1. Откройте в конфигураторе модуль объекта документа "РеализацияТоваровУслуг".

  2. Найдите процедуру ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка). Эта процедура выполняется при создании документа на основании.

  3. Внутри этой процедуры, после выполнения стандартного заполнения, необходимо добавить код, который скорректирует суммы в табличной части "Товары". Логика должна быть следующей: для каждой строки созданной реализации найти соответствующую строку в заказе-основании и принудительно установить сумму из заказа.

Сложности и как их решать:

Вариант Б: Модификация общего модуля "ОбработкаТабличныхЧастей"

На форуме было предложено вмешаться в общий модуль ОбработкаТабличныхЧастей и его процедуру РассчитатьСуммуТабЧасти(). Этот модуль используется многими документами, поэтому изменения в нем требуют особой осторожности.

Идея:

Внутри процедуры РассчитатьСуммуТабЧасти() добавить отдельную ветку кода. В ней нужно проверять условия: если документ создается на основании заказа покупателя, и у пользователя включена нужная нам настройка, то не выполнять стандартный пересчет, а брать сумму напрямую.

Риски:

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

Вариант В: Использование дополнительных реквизитов для передачи суммы

Это элегантный и достаточно безопасный способ, который позволяет избежать правки сложной логики типовых механизмов.

Шаги:

  1. Добавьте в табличную часть "Товары" документов "Заказ покупателя" и "Реализация товаров и услуг" новый реквизит, например, СуммаСтрокиДляПереноса (тип Число).

  2. В модуле "Заказа покупателя" при проведении документа (или при изменении строки) заполняйте этот реквизит точным значением итоговой суммы по строке.

  3. В процедуре ОбработкаЗаполнения документа "Реализация товаров и услуг" измените логику так, чтобы при создании на основании заказа, сумма для каждой строки бралась из этого нового реквизита СуммаСтрокиДляПереноса, а не пересчитывалась.

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

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

← На главную