Метод средневзвешенной скользящей оценки является одной из базовых задач при разработке учетных систем на платформе 1С. Часто у начинающих разработчиков возникает путаница: где именно производить расчет — в форме документа или при его проведении, и как соотносится цена продажи с рассчитанной себестоимостью. В рамках этой статьи мы подробно разберем методологию и техническую реализацию этого механизма.
Для начала проанализируем саму суть метода. Средневзвешенная скользящая стоимость (Moving Average) рассчитывается непосредственно в момент совершения операции выбытия товара (продажи, списания). В отличие от периодической средней, которая считается один раз в конце отчетного периода, скользящая средняя учитывает только те поступления, которые физически произошли до текущей продажи.
Рассмотрим формулу, по которой определяется сумма списания:
СуммаСписания = (СуммаОстаткаВРегистре / КоличествоОстаткаВРегистре) * КоличествоКсписанию
Выясним важный методологический момент, который часто вызывает споры. В документе РасходнаяНакладная в табличной части указываются Цена и Сумма реализации. Это те значения, по которым мы продаем товар покупателю. Они определяют нашу выручку и задолженность контрагента.
Себестоимость же, рассчитанная по методу средней, — это внутренняя учетная величина. Она не должна подставляться в колонку «Цена» табличной части документа. Покупатель не должен видеть нашу закупочную стоимость. Расчет средней стоимости выполняется «невидимо» для пользователя в момент нажатия кнопки Провести. Результат этого расчета записывается только в движения регистра накопления ОстаткиТоваров (или Продажи), уменьшая суммовой остаток склада.
Разберем, почему расчет нельзя делать в модуле формы при событии ПриИзменении количества. Программисты должны понимать следующие риски:
ОбработкаПроведения мы можем гарантировать, что данные регистра не изменятся в процессе расчета.Таким образом, правильное место для кода — процедура ОбработкаПроведения в модуле объекта документа.
Рассмотрим по шагам, как должна выглядеть программная логика реализации этого метода в 1С.
Шаг 1. Установка управляемых блокировок.
Прежде чем читать остатки из регистра, необходимо заблокировать данные по тем позициям номенклатуры, которые указаны в документе. Это предотвратит ситуацию, когда два одновременно проводимых документа уводят остаток в минус.
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ОстаткиТоваров");
ЭлементБлокировки.УстановитьЗначение("Номенклатура", СписокНоменклатурыДокумента);
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();
Шаг 2. Получение текущих остатков.
Используем запрос к виртуальной таблице Остатки регистра накопления. Важно получать данные на МоментВремени документа. Если документ проводится оперативно, платформа сама подставит актуальные значения.
Шаг 3. Цикл по табличной части и расчет.
В цикле обработки результатов запроса и строк документа выполняем проверку на наличие товара. Если товара достаточно, применяем формулу средней стоимости.
Проанализируем типичную ошибку: расчет цены единицы с последующим округлением. Если вы разделите 100 рублей на 3 штуки, получите 33.333... Округление до 33.33 даст ошибку при умножении обратно на количество.
Правило: Всегда рассчитывайте итоговую сумму списания, а не цену единицы. Если списывается весь остаток товара по данной позиции, то сумма списания должна быть равна всей сумме остатка в регистре без всяких вычислений. Это гарантирует, что в регистре не «зависнут» копейки при нулевом количестве.
Посмотрим на пример кода логики расчета:
Для Каждого СтрокаТЧ Из СписокНоменклатуры Цикл
// Предположим, ИзРегистра мы получили КолОстаток и СумОстаток
Если СтрокаТЧ.Количество < КолОстаток Тогда
СуммаСписания = (СумОстаток / КолОстаток) * СтрокаТЧ.Количество;
ИначеЕсли СтрокаТЧ.Количество = КолОстаток Тогда
СуммаСписания = СумОстаток; // Списываем всё в ноль
Иначе
// Обработка нехватки товара
КонецЕсли;
КонецЦикла;
Проанализируем ситуацию: что делать, если в системе разрешено списание «в минус»? В этом случае метод средней стоимости корректно работать не может, так как знаменатель в формуле может стать нулевым или отрицательным. Обычно в таких задачах накладывается условие: расчет себестоимости производится только при наличии положительного остатка. Если товара нет, сумма списания может оставаться нулевой (с последующей корректировкой при поступлении) или рассчитываться по последней известной цене закупки.
Подведем итоги нашего исследования:
ОбработкаПроведения.БлокировкаДанных для обеспечения целостности.Запрос к виртуальной таблице Остатки с фильтром по массиву номенклатуры из документа.Соблюдение этих правил позволит реализовать надежный и методологически верный механизм учета запасов по средневзвешенной скользящей стоимости.