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