← Назад к вопросам

Реализация расчёта себестоимости по ФИФО

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 (из справочника Партии)
  • При поступлении создаём новую партию с датой
  • Регистр ПартииТоваров хранит остатки по партиям

Алгоритм ФИФО:

  • Сортируем партии по дате поступления (ПОРЯДОКПО Дата)
  • Списываем сначала из более ранних партий
  • Продолжаем до исчерпания количества

Себестоимость:

  • Берём цену из каждой партии
  • Умножаем на количество списанного
  • Суммируем по всем партиям

Движения документов:

  • При расходе создаём движение расхода по каждой партии
  • Отрицательное количество для расхода
  • Две таблицы: партийный учёт и сводный остаток

Отчёт:

  • Показывает все партии товара
  • Дату поступления каждой партии
  • Входящее количество и цену
  • Текущий остаток по партии