Делал как-то подобное
В регистр остатки товаров добавил реквизит "Партии", при проведении поступлений пишу в него ссылку на этот документ поступления
при реализации, следующий запрос высчитывает остатки по документам поступления и списывает по FiFO
Код 1C v 8.3 //Получение партии
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ТоварыНаСкладахОстатки.Склад КАК Склад,
| ТоварыНаСкладахОстатки.Товар КАК Товар,
| ТоварыНаСкладахОстатки.Партия КАК Партия,
| ТоварыНаСкладахОстатки.КоличествоОстаток КАК КоличествоОстаток,
| ТоварыНаСкладахОстатки.СуммаПоступленияОстаток КАК СуммаПоступленияОстаток
|ИЗ
| РегистрНакопления.ТоварныеЗапасы.Остатки(
| &ДатаДокумента,
| Товар В (&СписокТоваров)
| И Склад =Склад) КАК ТоварыНаСкладахОстатки
|
|УПОРЯДОЧИТЬ ПО
| Партия
|АВТОУПОРЯДОЧИВАНИЕ";
Запрос.УстановитьПараметр("ДатаДокумента", Дата);
Запрос.УстановитьПараметр("Склад", Склад);
Запрос.УстановитьПараметр("СписокТоваров", Товары.ВыгрузитьКолонку("Товар"));
тзПартии = Запрос.Выполнить().Выгрузить();
ЦенаПоступления=0; Ошибка="";
Для Каждого ТекСтрокаТовары Из Товары Цикл
Если ТекСтрокаТовары.Товар.Вид = Перечисления.ВидыТоваров.Услуга Тогда
Движение = Движения.Продажи.Добавить();
Движение.Период = Дата;
Движение.Склад = Склад;
Движение.Покупатель = Покупатель;
Движение.Товар = ТекСтрокаТовары.Товар;
Движение.Количество = ТекСтрокаТовары.Количество;
Движение.ЦенаПоступления = ТекСтрокаТовары.Цена;
Движение.ЦенаПродажи = ТекСтрокаТовары.Цена;
Движение.Сумма = Движение.Количество*ТекСтрокаТовары.Цена;
Движение.Менеджер = Ответственный;
Иначе //Товар
найдМассив=тзПартии.НайтиСтроки(Новый Структура("Товар", ТекСтрокаТовары.Товар));
Если найдМассив.Количество()>0 Тогда //Будет разбивка по партиям
итКолВо = ТекСтрокаТовары.Количество;
Для Каждого стр из найдМассив Цикл
Если итКолВо=0 Тогда Прервать; КонецЕсли;
колСписания = ?(итКолВо>стр.КоличествоОстаток, стр.КоличествоОстаток,итКолВо);
итКолВо=итКолВо-колСписания;
текЦенаПоступления = стр.СуммаПоступленияОстаток/?(стр.КоличествоОстаток=0,1,стр.КоличествоОстаток);
Движение = Движения.ТоварныеЗапасы.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Период = Дата;
Движение.Склад = Склад;
Движение.Товар = ТекСтрокаТовары.Товар;
Движение.Партия = стр.Партия;
Движение.Количество = колСписания;
Движение.СуммаПоступления = текЦенаПоступления*колСписания;
Движение.СуммаПродажи = ТекСтрокаТовары.Сумма;
Движение = Движения.Продажи.Добавить();
Движение.Период = Дата;
Движение.Склад = Склад;
Движение.Покупатель = Покупатель;
Движение.Товар = ТекСтрокаТовары.Товар;
Движение.Количество = колСписания;
Движение.ЦенаПоступления = текЦенаПоступления;
Движение.ЦенаПродажи = ТекСтрокаТовары.Цена;
Движение.Сумма = Движение.Количество*ТекСтрокаТовары.Цена;
Движение.Менеджер = Ответственный;
КонецЦикла;
Если итКолВо>0 Тогда Ошибка=Ошибка+"Нет доступного остатка "+Строка(ТекСтрокаТовары.Товар)+" на складе "+Строка(Склад)+", сверх остатка: "+Строка(итКолВо)+Символы.ПС; Отказ=Истина; КонецЕсли;
Иначе //НЕТ партий, сумма Поступление по нулям
Движение = Движения.ТоварныеЗапасы.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Период = Дата;
Движение.Склад = Склад;
Движение.Товар = ТекСтрокаТовары.Товар;
//Движение.Партия = стр.Партия;
Движение.Количество = ТекСтрокаТовары.Количество;
Движение.СуммаПоступления = 0;
Движение.СуммаПродажи = ТекСтрокаТовары.Сумма;
Движение = Движения.Продажи.Добавить();
Движение.Период = Дата;
Движение.Склад = Склад;
Движение.Покупатель = Покупатель;
Движение.Товар = ТекСтрокаТовары.Товар;
Движение.Количество = ТекСтрокаТовары.Количество;
Движение.ЦенаПоступления = 0;
Движение.ЦенаПродажи = ТекСтрокаТовары.Цена;
Движение.Сумма = ТекСтрокаТовары.Сумма;
Движение.Менеджер = Ответственный;
КонецЕсли;
КонецЕсли;
КонецЦикла;