← Назад к вопросам
Реализация расчёта себестоимости по ФИФО
3.0 Senior🔥 131 комментариев
#Конфигурации и типовые#Регистры
Условие
Доработайте конфигурацию складского учёта — добавьте расчёт себестоимости списания по методу ФИФО (First In, First Out).
Требования:
- Партионный учёт товаров
- При расходе товара списывать сначала самые ранние партии
- Формирование отчёта по движению партий
Пример
Поступления:
- 01.01: 10 шт. по 100 руб.
- 05.01: 15 шт. по 120 руб.
Расход 12 шт. 10.01:
- Списано 10 шт. по 100 руб. = 1000 руб.
- Списано 2 шт. по 120 руб. = 240 руб.
- Итого себестоимость: 1240 руб.
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение
Для реализации ФИФО нужен партионный учёт и алгоритм списания первых партий.
Часть 1: Регистр для партионного учёта
// В конфигурации создаём регистр накопления "ПартииТоваров"
// Тип: Остатки
// Измерения:
// - Номенклатура
// - Партия (новое поле для ID партии)
// Ресурсы:
// - Количество
// - Цена
// - СуммаОстатков
Часть 2: Процедура списания по ФИФО
Функция СписатьПоФИФО(Номенклатура, КоличествоКСписанию)
СписанныеПартии = Новый Массив();
// Получаем все остатки партий в порядке ФИФО
Запрос = Новый Запрос();
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Запрос.УстановитьПараметр("Дата", ТекущаяДата());
Запрос.Текст =
"""ВЫБРАТЬ
Остатки.Партия,
Остатки.Количество КАК Остаток,
Остатки.Цена,
Остатки.Партия.Дата КАК ДатаПартии
ИЗ
РегистрНакопления.ПартииТоваров.Остатки(
@Дата,
Номенклатура,
Партия
) КАС Остатки
ГДЕ
Остатки.Номенклатура = @Номенклатура
И Остатки.Количество > 0
ПОРЯДОКПО
ДатаПартии,
Остатки.Партия
""";
Таблица = Запрос.Выполнить().Выгрузить();
Оставшееся = КоличествоКСписанию;
// Проходим по партиям в порядке ФИФО
Для Каждого Партия Из Таблица Цикл
Если Оставшееся = 0 Тогда
Прервать;
КонецЕсли;
// Определяем, сколько списываем из этой партии
КоличествоИзПартии = Мин(Оставшееся, Партия.Остаток);
// Добавляем в результат
НоваяПартия = Новая Структура();
НоваяПартия.Партия = Партия.Партия;
НоваяПартия.Количество = КоличествоИзПартии;
НоваяПартия.Цена = Партия.Цена;
НоваяПартия.Сумма = КоличествоИзПартии * Партия.Цена;
СписанныеПартии.Добавить(НоваяПартия);
Оставшееся = Оставшееся - КоличествоИзПартии;
КонецЦикла;
Возврат СписанныеПартии;
КонецФункции
Часть 3: Создание движений при расходе товара
Процедура ОбработатьРасходТовара(ДокументРазходности)
Для Каждого СтрокаРасхода Из ДокументРазходности.Товары Цикл
// Получаем партии по ФИФО
СписанныеПартии = СписатьПоФИФО(
СтрокаРасхода.Номенклатура,
СтрокаРасхода.Количество
);
// Создаём движения для каждой партии
Для Каждого ПартияДанные Из СписанныеПартии Цикл
// Создаём движение расхода по партии
Движение = ДокументРазходности.ПартииТоваров.Добавить();
Движение.Номенклатура = СтрокаРасхода.Номенклатура;
Движение.Партия = ПартияДанные.Партия;
Движение.Количество = -ПартияДанные.Количество; // Минус для расхода
// Если нужна себестоимость
СтрокаРасхода.Себестоимость = СтрокаРасхода.Себестоимость + ПартияДанные.Сумма;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Часть 4: Документ расходования с партиями
// При проведении документа РасходТоваров
Процедура ОбработкаПроведения(Отмена, РежимПроведения)
// Создаём движение в регистр остатков
Для Каждого Строка Из Товары Цикл
Движение = Движения.ПартииТоваров.Добавить();
Движение.Период = Дата;
Движение.Номенклатура = Строка.Номенклатура;
Движение.Партия = Строка.Партия;
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Количество = Строка.Количество;
КонецЦикла;
// Также создаём движение в регистр остатков по номенклатуре
Для Каждого Строка Из Товары Цикл
Движение = Движения.ОстаткиТоваров.Добавить();
Движение.Период = Дата;
Движение.Номенклатура = Строка.Номенклатура;
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Количество = Строка.Количество;
КонецЦикла;
КонецПроцедуры
Часть 5: Отчёт по движению партий
Функция ПолучитьОтчётПартий(Номенклатура, ДатаНачала, ДатаОкончания)
Запрос = Новый Запрос();
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Запрос.УстановитьПараметр("ДатаНачала", ДатаНачала);
Запрос.УстановитьПараметр("ДатаОкончания", ДатаОкончания);
Запрос.Текст =
"""ВЫБРАТЬ
Партии.Дата КАК ДатаПартии,
Партии.Ссылка КАС Партия,
ПартииДвижения.Номенклатура,
ПартииДвижения.Количество КАС КолВходящее,
ПартииДвижения.Цена,
ПартииДвижения.СуммаОстатков КАС СуммаПоступления,
Остатки.Количество КАС КолОстаток
ИЗ
РегистрНакопления.ПартииТоваров КАС ПартииДвижения
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Партии КАС Партии
ПО ПартииДвижения.Партия = Партии.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваров.Остатки(
@ДатаОкончания,
Номенклатура,
Партия
) КАС Остатки
ПО ПартииДвижения.Партия = Остатки.Партия
И ПартииДвижения.Номенклатура = Остатки.Номенклатура
ГДЕ
ПартииДвижения.Номенклатура = @Номенклатура
И Партии.Дата >= @ДатаНачала
И Партии.Дата <= @ДатаОкончания
ПОРЯДОКПО
Партии.Дата,
Партия
""";
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Ключевые моменты ФИФО:
Партионный учёт:
- Каждой партии товара присваиваем ID (из справочника Партии)
- При поступлении создаём новую партию с датой
- Регистр ПартииТоваров хранит остатки по партиям
Алгоритм ФИФО:
- Сортируем партии по дате поступления (ПОРЯДОКПО Дата)
- Списываем сначала из более ранних партий
- Продолжаем до исчерпания количества
Себестоимость:
- Берём цену из каждой партии
- Умножаем на количество списанного
- Суммируем по всем партиям
Движения документов:
- При расходе создаём движение расхода по каждой партии
- Отрицательное количество для расхода
- Две таблицы: партийный учёт и сводный остаток
Отчёт:
- Показывает все партии товара
- Дату поступления каждой партии
- Входящее количество и цену
- Текущий остаток по партии