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