Одной из классических задач при разработке систем складского учета на платформе 1С является реализация различных алгоритмов списания себестоимости. Перед разработчиком часто встает дилемма: как спроектировать архитектуру регистров так, чтобы она была универсальной для методов FIFO (First In, First Out), LIFO (Last In, First Out) и по средней стоимости, особенно если эти настройки могут меняться пользователем в процессе эксплуатации системы.
Рассмотрим основные подходы, технические сложности и способы их решения, опираясь на лучшие практики программирования в среде 1С.
Для реализации партионного учета (FIFO/LIFO) в регистре накопления ОстаткиТоваров (тип «Остатки») обязательно должно присутствовать измерение Партия (обычно это ссылка на документ поступления). Это позволяет системе «видеть», какой товар пришел раньше, а какой позже, и по какой цене.
Однако при методе «по средней» аналитика по партиям для расчета себестоимости не требуется — нам важна общая стоимость остатка номенклатуры, разделенная на ее общее количество. Если мы просто перестанем заполнять измерение Партия при выборе метода «по средней», мы столкнемся с серьезной проблемой: регистр перестанет закрываться в ноль по измерениям. Например, товар пришел на конкретную партию «Приход 1», а списался «по пустой партии». В итоге в разрезе номенклатуры остаток будет нулевой, но в разрезе партий зависнут положительные остатки на «Приходе 1» и отрицательные на «Пустой партии».
Проанализируем ситуацию, когда мы всегда ведем приход в разрезе партий, независимо от настроек учетной политики. Разберем по шагам, как в этом случае работает списание:
Остатки регистра накопления. В параметрах виртуальной таблицы мы указываем отбор по Номенклатура, а в поле «Группировка» (или просто выбирая поля) указываем Партия. Далее сортируем результат по моменту времени документа партии (Партия.МоментВремени) по возрастанию (для FIFO) или убыванию (для LIFO).Остатки, но не используем измерение Партия в списке выбираемых полей или группировок запроса. Платформа 1С автоматически просуммирует количество и стоимость по всем партиям этой номенклатуры, выдав нам единый средний показатель.Однако здесь кроется главный подвох: при списании «по средней» нам все равно нужно указать, с каких именно партий в регистре мы снимаем остаток, чтобы измерения закрылись корректно. Если мы этого не сделаем, возникнет ситуация перекоса остатков, описанная выше.
Это наиболее профессиональный подход, который часто встречается в типовых решениях. Выясним, как обеспечить чистоту данных при переходе с одного метода на другой.
Рассмотрим алгоритм действий:
Этот метод гарантирует, что Количество и Стоимость в регистре всегда будут корректны в разрезе тех измерений, которые важны для текущего метода учета.
Посмотрим на пример современных конфигураций. Там часто разделяют оперативный учет и финансовый учет. Оперативно (в момент проведения документа реализации) товар списывается либо просто количественно, либо по примерной (скользящей) себестоимости. Окончательный расчет по методу FIFO или «Средневзвешенной» происходит в конце месяца специальной обработкой «Закрытие месяца».
Для реализации такой схемы в своей конфигурации можно использовать следующий программный код в обработке проведения:
// Пример логики выбора метода списания
УчетнаяПолитика = ПолучитьУчетнуюПолитику(Дата);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Остатки.Партия КАК Партия,
| Остатки.КоличествоОстаток КАК Количество,
| Остатки.СтоимостьОстаток КАК Стоимость
|ИЗ
| РегистрНакопления.ОстаткиТоваров.Остатки(&МоментВремени, Номенклатура = &Номенклатура) КАК Остатки";
Если УчетнаяПолитика.МетодСписания = Перечисления.МетодыСписания.FIFO Тогда
Запрос.Текст = Запрос.Текст + " УПОРЯДОЧИТЬ ПО Остатки.Партия.МоментВремени ВОЗР";
ИначеЕсли УчетнаяПолитика.МетодСписания = Перечисления.МетодыСписания.LIFO Тогда
Запрос.Текст = Запрос.Текст + " УПОРЯДОЧИТЬ ПО Остатки.Партия.МоментВремени УБЫВ";
КонецЕсли;
В случае метода «По средней» (скользящая средняя) программисту необходимо в коде самостоятельно рассчитать долю стоимости, приходящуюся на списываемое количество, и распределить ее по имеющимся партиям (чтобы «закрыть» их) или списать все с одной «пустой» партии, если система была предварительно «свернута».
Проанализируем еще несколько критических моментов:
DataLock блокируйте только Номенклатуру, этого достаточно для защиты итогов.ПустаяСсылка документа партии корректно обрабатывалась в запросах. В языке запросов 1С пустая ссылка имеет минимальное значение момента времени, поэтому при FIFO она будет списываться самой первой, что нам и нужно при переходе со средней цены.Таким образом, наиболее надежным и масштабируемым решением является использование одного регистра накопления с измерением Партия. При этом учетная политика регулирует не структуру данных, а алгоритм выборки этих данных и правила закрытия партий. При смене метода списания обязательно используйте регламентный документ для выравнивания (свертки) партионных остатков, чтобы избежать ситуации «зависших» стоимостей на старых измерениях.