Задача партионного учета и ее решение в 1С

22.10.26

Разработка - Механизмы платформы 1С

Учебный разбор регистра накопления остатков: от проведения прихода до отказа, если товара на складе меньше, чем в расходной накладной. Три поступления, одно списание, итог запроса и движения расхода разобраны на числах. Код рассчитан на свою конфигурацию с документами «Приходная накладная» и «Расходная накладная». Склад берется из шапки, услуги в регистр не пишутся. Полезно при разборе проведения, виртуальной таблицы остатков и итогов запроса.

Задача партионного учета и ее решение в 1С

Задача партионного учета состоит в том, чтобы по каждому списанию было видно, из какого поступления ушел товар и какая себестоимость при этом списана. В рассматриваемом примере партия хранится как ссылка на документ «Приходная накладная». Дата партии совпадает с датой этого документа. При расходе партии обходятся от более раннего поступления к более позднему.

На этой задаче удобно собрать несколько механизмов платформы, которые потом встречаются по отдельности: движения регистра накопления, чтение остатков на момент документа, итоги запроса и отказ в проведении.

 

Состав конфигурации

Учет ведется в регистре накопления «ОстаткиНаСкладах». Вид регистра - остатки.

Роль

Имя

Назначение

Измерения

Номенклатура, Склад, Партия

Партия имеет тип ДокументСсылка.ПриходнаяНакладная

Ресурсы

Количество, Себестоимость

Себестоимость относится к партии, а не к сумме продажи

     
     

Склад задан реквизитом шапки приходной и расходной накладных. В табличной части своего склада нет. Номенклатура делится на товары и услуги перечислением «ВидыНоменклатуры». Услуги в регистр не записываются.

Имена в коде дальше совпадают с именами в дереве конфигурации: табличная часть «Товары», регистр «ОстаткиНаСкладах», перечисление «ВидыНоменклатуры».

 

Поступление

Поступление оформляется документом «Приходная накладная». В строке указываются номенклатура, количество и сумма. Сумма строки в этом примере принимается за себестоимость партии. Отдельного номера партии в документе нет: в измерение «Партия» пишется ссылка на сам документ поступления.

Набор движений заполняется в обработке проведения. Запись набора выполняет платформа по окончании проведения, для этого у регистра устанавливается признак записи.

Процедура ОбработкаПроведения(Отказ, Режим)

       Движения.ОстаткиНаСкладах.Записывать = Истина;

       Для Каждого ТекСтрокаТовары Из Товары Цикл
              Если ТекСтрокаТовары.Номенклатура.ВидНоменклатуры
                    <> Перечисления.ВидыНоменклатуры.Товар Тогда
                    Продолжить;
             КонецЕсли;

             Движение = Движения.ОстаткиНаСкладах.Добавить();
             Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
             Движение.Период = Дата;
             Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
             Движение.Склад = Склад;
             Движение.Партия = Ссылка;
             Движение.Количество = ТекСтрокаТовары.Количество;
             Движение.Себестоимость = ТекСтрокаТовары.Сумма;
       КонецЦикла;
 
КонецПроцедуры

 

Строка с услугой пропускается. Остатка по ней не возникает, и при последующем списании она не участвует в проверке количества.

 

Списание

Списание оформляется документом «Расходная накладная». При проведении нужно получить товарные строки документа, прочитать остатки партий на момент этого документа, проверить достаточность остатка и записать расход по партиям в порядке даты поступления.

Запрос

Запрос собирает три выборки.

ВТ_Продать - строки документа, свернутые по номенклатуре и складу. Услуги отсекаются отбором. Количество здесь - количество к списанию. Сумма продажи в запрос не берется: в ресурс «Себестоимость» попадет стоимость партии, а не сумма расходной накладной.

ВТ_Остатки - остатки регистра на момент проводимого документа. Условие виртуальной таблицы ограничивает выборку парами «номенклатура и склад» из ВТ_Продать. Остаток той же номенклатуры на другом складе в расчет не попадает.

Итоговая выборка соединяет продажу с остатками по номенклатуре и по складу. Если соединить только по номенклатуре, партии двух складов попадут в одно списание. Левое соединение оставляет строку продажи и тогда, когда остатка нет: количество остатка в такой строке равно нулю, и нехватка видна до записи движений.

Сортировка идет по дате партии, затем по ссылке партии. Дата берется из приходной накладной. Сортировка по ссылке документа эту дату не гарантирует: порядок ссылок и порядок поступлений расходятся.

ВЫБРАТЬ
       ПродажаТовары.Номенклатура КАК Номенклатура,
       СУММА(ПродажаТовары.Количество) КАК Количество,
       ПродажаТовары.Ссылка.Склад КАК Склад
ПОМЕСТИТЬ ВТ_Продать
ИЗ
       Документ.РасходнаяНакладная.Товары КАК ПродажаТовары
ГДЕ
       ПродажаТовары.Ссылка = &НашДокумент
       И ПродажаТовары.Номенклатура.ВидНоменклатуры =
             ЗНАЧЕНИЕ(Перечисление.ВидыНоменклатуры.Товар)
СГРУППИРОВАТЬ ПО
       ПродажаТовары.Номенклатура,
       ПродажаТовары.Ссылка.Склад
;
////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ
       Остатки.Номенклатура КАК Номенклатура,
       Остатки.Склад КАК Склад,
       Остатки.Партия КАК Партия,
       Остатки.КоличествоОстаток КАК КоличествоОстаток,
       Остатки.СебестоимостьОстаток КАК СебестоимостьОстаток
ПОМЕСТИТЬ ВТ_Остатки
ИЗ
       РегистрНакопления.ОстаткиНаСкладах.Остатки(
                    &ДатаДокумента,
                    (Номенклатура, Склад) В
                           (ВЫБРАТЬ
                                  ВТ_Продать.Номенклатура,
                                  ВТ_Продать.Склад
                           ИЗ
                                  ВТ_Продать КАК ВТ_Продать)) КАК Остатки
;
////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ
       ВТ_Продать.Номенклатура КАК Номенклатура,
       ВТ_Продать.Склад КАК Склад,
       ВТ_Продать.Количество КАК Количество,
       ВТ_Остатки.Партия КАК Партия,
       ЕСТЬNULL(ВТ_Остатки.КоличествоОстаток, 0) КАК КоличествоОстаток,
       ЕСТЬNULL(ВТ_Остатки.СебестоимостьОстаток, 0) КАК СебестоимостьОстаток
ИЗ
       ВТ_Продать КАК ВТ_Продать
             ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Остатки КАК ВТ_Остатки
             ПО ВТ_Продать.Номенклатура = ВТ_Остатки.Номенклатура
                    И ВТ_Продать.Склад = ВТ_Остатки.Склад
УПОРЯДОЧИТЬ ПО
       ВТ_Остатки.Партия.Дата,
       ВТ_Остатки.Партия
ИТОГИ
       МАКСИМУМ(Количество),
       СУММА(КоличествоОстаток),
       СУММА(СебестоимостьОстаток)
ПО
       Номенклатура,
       Склад

Параметр ДатаДокумента получает МоментВремени() проводимого документа. Параметр НашДокумент получает ссылку на него.

Итоги запроса

После соединения количество к продаже повторяется в каждой строке партии. Сумма по этому полю умножила бы потребность на число партий. В итоге поэтому стоит МАКСИМУМ(Количество): значение во всех строках одно, максимум его не меняет.

КоличествоОстаток и СебестоимостьОстаток суммируются. В строке группировки видно, сколько товара есть на складе по всем партиям. Партия в группировке пустая: итог рассчитан по номенклатуре и складу.

На числах это выглядит так. К продаже 10 штук, на складе три поступления.

Строка

Партия

Дата

К продаже

Остаток

Себестоимость остатка

Партия

Поступление 05.12.2021

05.12.2021

10

4

4 000

Партия

Поступление 07.02.2022

07.02.2022

10

3

3 300

Партия

Поступление 13.02.2022

13.02.2022

10

8

9 600

Итог

 

 

10

15

16 900

           

Десять в колонке «К продаже» - одна и та же потребность документа. Пятнадцать в итоге - сумма остатков 4, 3 и 8. Десять не больше пятнадцати, товара хватает. Порядок строк совпадает с датами прихода: сначала декабрь 2021 года, затем 7 февраля 2022 года, затем 13 февраля.

Запись движений

Обход результата идет по группировкам. Сначала номенклатура, затем склад, затем строки партий. Сравнение потребности и остатка выполняется на группировке склада, до обхода партий.

Если потребность больше остатка, процедура сообщает номенклатуру, склад, нужное количество и остаток, устанавливает Отказ и завершается. Документ либо проводится целиком, либо не проводится. Движения при отказе платформа не записывает.

Пока потребность не закрыта, партии берутся в порядке выборки. Строка с нулевым остатком пропускается, делить на нее себестоимость не потребуется. Если в партии товара меньше, чем еще нужно списать, списывается вся партия и вся ее себестоимость. Если партия больше потребности, списывается оставшаяся потребность, а себестоимость - доля стоимости партии.

В движение попадают номенклатура, склад и партия из строки выборки.

Процедура ОбработкаПроведения(Отказ, Режим)

       Движения.ОстаткиНаСкладах.Записывать = Истина;

       Запрос = Новый Запрос;
       Запрос.Текст = ТекстЗапросаСписания();
       Запрос.УстановитьПараметр("ДатаДокумента", МоментВремени());
       Запрос.УстановитьПараметр("НашДокумент", Ссылка);

       РезультатЗапроса = Запрос.Выполнить();
       ВыборкаНоменклатура = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

       Пока ВыборкаНоменклатура.Следующий() Цикл
             ВыборкаСклад = ВыборкаНоменклатура.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
             Пока ВыборкаСклад.Следующий() Цикл
                    Если ВыборкаСклад.Количество > ВыборкаСклад.КоличествоОстаток Тогда
                           Сообщить("Не хватает товара " + ВыборкаСклад.Номенклатура
                                  + " на складе " + ВыборкаСклад.Склад
                                  + ". Нужно " + ВыборкаСклад.Количество
                                  + ", в остатке " + ВыборкаСклад.КоличествоОстаток);
                           Отказ = Истина;
                           Возврат;
                    КонецЕсли;
                    ОсталосьПродать = ВыборкаСклад.Количество;
                    ВыборкаЗаписей = ВыборкаСклад.Выбрать();
                    Пока ВыборкаЗаписей.Следующий() И ОсталосьПродать > 0 Цикл
                           Если ВыборкаЗаписей.КоличествоОстаток <= 0 Тогда
                                  Продолжить;
                           КонецЕсли;
                           Если ОсталосьПродать >= ВыборкаЗаписей.КоличествоОстаток Тогда
                                  КоличествоКСписанию = ВыборкаЗаписей.КоличествоОстаток;
                                  СуммаКСписанию = ВыборкаЗаписей.СебестоимостьОстаток;
                                  ОсталосьПродать = ОсталосьПродать - КоличествоКСписанию;
                           Иначе
                                  КоличествоКСписанию = ОсталосьПродать;
                                  СебестоимостьЕдиницы = ВыборкаЗаписей.СебестоимостьОстаток
                                        / ВыборкаЗаписей.КоличествоОстаток;
                                  СуммаКСписанию = СебестоимостьЕдиницы * КоличествоКСписанию;
                                  ОсталосьПродать = 0;
                           КонецЕсли;

                           Движение = Движения.ОстаткиНаСкладах.Добавить();
                           Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
                           Движение.Период = Дата;
                           Движение.Номенклатура = ВыборкаЗаписей.Номенклатура;
                           Движение.Склад = ВыборкаЗаписей.Склад;
                           Движение.Партия = ВыборкаЗаписей.Партия;
                           Движение.Количество = КоличествоКСписанию;
                           Движение.Себестоимость = СуммаКСписанию;
                    КонецЦикла;
             КонецЦикла;
       КонецЦикла;
КонецПроцедуры

Текст запроса вынесен в функцию ТекстЗапросаСписания() того же модуля.

По таблице выше получаются три строки расхода.

Партия

Количество

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

Откуда сумма

Поступление 05.12.2021

4

4 000

Списана вся партия

Поступление 07.02.2022

3

3 300

Списана вся партия

Поступление 13.02.2022

3

3 600

9 600 / 8 x 3

Итого

10

10 900

 

       
       

Потребность закрыта. В поступлении от 13.02.2022 остается 5 штук и 6 000 себестоимости. Если к продаже указать 16 при остатке 15, процедура завершится с отказом и не запишет ни одной из этих строк.

 

Повторное проведение

Остатки читаются на МоментВремени() документа. Движения этого документа в такой остаток не входят. Новый набор формируется в процедуре. Записывает его платформа в конце проведения, поскольку у регистра установлен признак записи. Прежние записи регистратора заменяются новым набором.

Отдельно очищать регистр вызовом Записать() в начале процедуры не нужно: граница чтения уже задана моментом документа. При отказе проведение отменяется вместе с набором, собранным в памяти. Прежние движения документа в базе сохраняются.

 

Если переносить пример дальше

В примере блокировка данных не устанавливается. В рабочей базе перед чтением остатков ставится исключительная блокировка по номенклатуре и складу. Без нее два расходных документа могут списать одну и ту же партию.

При полном списании партии в движение уходит весь остаток ее себестоимости, и сумма партии закрывается. При частичном списании доля «себестоимость остатка / количество остатка x количество к списанию» может оставить на партии копейку. Ее относят на последнее списание этой партии.

Смысл измерения «Партия» в задаче можно заменить. На то же место встают срок годности или проект оплаты. Приход записывает новое значение, расход читает остатки на момент документа и забирает количество в том порядке, который для этого значения уже задан. Для срока годности это дата годности, для проекта - порядок, принятый в учете оплат. Сама схема проведения остается прежней: остаток на момент документа, проверка достаточности, запись расхода и замена прежних движений регистратора платформой.

Вступайте в нашу телеграмм-группу Инфостарт

партионный учет ФИФО регистр накопления остатки проведение момент времени итоги запроса себестоимость приходная накладная расходная накладная

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

Механизмы платформы 1С Разработчик Бесплатно (free)

Разберем 15 мифов о работе платформы «1С:Предприятие 8» – как распространенных, так и малоизвестных. Начнем с классики: «Код, написанный в одну строку, работает быстрее, чем многострочный». Так ли это на самом деле?

16.07.2025    45672    TitanLuchs    109    

156

Работа с интерфейсом WEB-интеграция Механизмы платформы 1С Бесплатно (free)

Веб-интерфейсы повышают качество внешнего вида приложений 1С, предсказуемы с точки зрения верстки, позволяют организовать удобные и высокопроизводительные рабочие места для пользователей. Расскажем об особенностях разработки веб-интерфейсов на React внутри 1С, двустороннем взаимодействии 1С и JavaScript, а также сборке веб-приложения в одностраничный файл.

19.06.2025    18686    zeegin    15    

64

Механизмы платформы 1С Работа с интерфейсом Разработчик Стажер 1С:Предприятие 8 Бесплатно (free)

Про ООП в 1С и о том, как сделать свой код более кратким и выразительным при помощи использования текучего интерфейса (fluent interface).

03.02.2025    26032    bayselonarrend    127    

68

Механизмы платформы 1С Разработчик 1С:Предприятие 8 Бесплатно (free)

В этой статье подробно рассматривается работа с JSON в XDTO в 1С:Предприятие. Вы узнаете, как сериализовать и десериализовать объекты XDTO в JSON, интегрировать 1С с веб-сервисами и API, а также корректно обрабатывать данные при обмене. Разбираются особенности работы с коллекциями, использование функций восстановления и частые ошибки при работе с JSON и XDTO.

30.01.2025    33312    user2122906    10    

69

Механизмы платформы 1С Файловый обмен (TXT, XML, DBF), FTP Разработчик 1С:Предприятие 8 Бесплатно (free)

Этот материал познакомит вас с механизмом XDTO (XML Data Transfer Objects) в 1С и научит эффективно использовать его возможности. Мы разберёмся, как работать с XML-схемами, создавать модели данных, манипулировать объектами XDTO, а также сериализовать и десериализовать их в XML. Вы узнаете, как использовать XDTO для интеграции с внешними системами, избегать типичных ошибок и оптимизировать код. К концу вы будете уверенно применять XDTO для решения сложных задач обмена данными и автоматизации процессов.

17.01.2025    55789    user2122906    13    

63

Механизмы платформы 1С WEB-интеграция Разработчик 1С:Предприятие 8 Бесплатно (free)

В платформе 8.3.27 появилась возможность использовать WebSocket-клиент. Давайте посмотрим, как это все устроено и чем оно нам полезно.

14.01.2025    46791    dsdred    110    

160

Механизмы платформы 1С Разработчик Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Эта небольшая статья - некоторого рода шпаргалка по файловым потокам: как и зачем с ними работать, какие преимущества это дает.

23.06.2024    40459    bayselonarrend    24    

180
Для отправки сообщения требуется регистрация/авторизация