Небольшая вводная часть
В статье описывается реальная задача доработки политики учета серий "Учет себестоимости по сериям". Приведенный программный код не является стопроцентно рабочим решением, а представляет собой общее описание подхода решения данной задачи.
Доработки тестировались на конфигурации 1С:ERP Управление предприятием 2, релиз 2.4.13.103. Но особенности данной политики указания серий также справедливы для конфигураций УТ11 и КА2. Про общие механизмы учета товаров по сериям в типовых конфигурациях УТ 11, КА 2.4, ЕРП 2.4 можно прочитать здесь и здесь. Про политику "Учет себестоимости по сериям" также подробно описано здесь, если вкратце, то в данной политике серия наравне с номенклатурой и характеристикой является не только складским, но и финансовым разрезом.
При оформлении заказов, система требует обязательный ввод серий для номенклатурных позиций с видом номенклатуры, в котором указана политика учета серий "Учет себестоимости по сериям" и видом обеспечения "Отгрузить", однако менеджер на момент оформления заказов, зачастую, не имеет сведений о серии реализуемой продукции, информация о сериях будет известна только сотруднику склада при создании накладной. Проблема очень старая, о которой известно, как минимум, с 2015г. На Партнерском форуме можно найти не одну тему, связанную с ней. Например, почитать можно здесь. Официальная позиция вендора отражена следующим образом: "Такой принцип указания серий в документах обусловлен тем, что серии непосредственно связаны с финансовыми показателями, а значит, находятся в зоне ответственности менеджера или технолога", "если менеджер не делает осознанного выбора между сериями, то по ним не нужно считать себестоимость". Однако, на практике возникает значительное количество случаев, когда заказчик требует отключить заполнении серии номенклатуры в заказах.
Практическая часть
В формализованном виде задача звучала следующим образом: Отключить для номенклатурных позиций обязательность заполнения серий в документе "Заказ клиента" при политике учета серий "Учет себестоимости по сериям". Адресное хранение и ордерная схема поступления и отгрузки не используется.
I/I
Правила заполнения серий в документе "Заказ клиента" определяются на основании числового реквизита "СтатусЗаполненияСерий", который хранится в ТЧ "Товары" документа "Заказ клиента" и заполняется с использованием функции модуля менеджера "ТекстЗапросаЗаполненияСтатусовУказанияСерий", в котором и хранятся правила заполнения статусов указания серий. Необходимо заменить кусок запроса, в котором определяются статусы заполнения серий для интересующей нас политики:
СтарыйКусокЗапроса =
" КОГДА ПолитикиУчетаСерий.ПолитикаУчетаСерий.УчитыватьСебестоимостьПоСериям
| ТОГДА ВЫБОР
| КОГДА Товары.Серия <> ЗНАЧЕНИЕ(Справочник.СерииНоменклатуры.ПустаяСсылка)
| ТОГДА 14
| КОГДА Товары.ВариантОбеспечения = ЗНАЧЕНИЕ(Перечисление.ВариантыОбеспечения.СоСклада)
| ТОГДА 15
| ИНАЧЕ 13
| КОНЕЦ";
НовыйКусокЗапроса =
" КОГДА ПолитикиУчетаСерий.ПолитикаУчетаСерий.УчитыватьСебестоимостьПоСериям
| ТОГДА 0
| КОНЕЦ";
Расшифровка статусов указания серий:
0 — серии указывать не требуется;
13 — количество по сериям не совпадает с количеством товаров или серии не указаны (красная картинка);
14 — количество по сериям совпадает с количеством товаров (зеленая картинка);
15 — серии не указаны, их можно указывать, а можно и не указывать (синяя картинка);
(Полный список статусов и их значения можно посмотреть в описании к процедуре "НоменклатураСервер.ЗаполнитьСтатусыУказанияСерий")
Что было: Если серия заполнена, то всё хорошо — количество по сериям совпадает с количеством товаров (статус 14). Если вариант обеспечения - "Со склада", то можно указывать, а можно не указывать серию (статус 15), иначе — указание серии обязательно (статус 13).
Что стало: Если установлена политика "Учитывать себестоимость по сериям", то серия не указывается.
I/II.
Далее оказалось, что отключить указание серии нужно не только в документе "Заказ клиента", но и в документе "Заказ давальца", а в перспективе этот список может расшириться и другими документами, например, "Заказ материалов в производство", "Заказ на внутреннее потребление", "Заказ на перемещение", "Заказ на сборку". Во всех этих документах необходимо было отредактировать одинаковым образом функцию модуля менеджера "ТекстЗапросаЗаполненияСтатусовУказанияСерий". Чтобы не править каждый из документов, решено было сделать общий масштабируемый механизм и разместить его в одном месте. Для этого пришлось доработать функцию "НоменклатураСервер.ВыборкаИзЗапросаРасчетаСтатусовУказанияСерий", в которой вызывать дописанную процедуру "ВыполнитьКорректировкуСтатусовСерийВЗаказах".
Скриншот функции "НоменклатураСервер.ВыборкаИзЗапросаРасчетаСтатусовУказанияСерий":
Текст процедуры, выполняющей корректировку серий:
Процедура ВыполнитьКорректировкуСтатусовСерийВЗаказах(ТекстЗапроса, Знач ПараметрыУказанияСерий) Экспорт
ИмяДокумента = СтрЗаменить(ПараметрыУказанияСерий.ПолноеИмяОбъекта, "Документ.", "");
МассивИменДокументов = Новый Массив;
МассивИменДокументов.Добавить("ЗаказДавальца");
МассивИменДокументов.Добавить("ЗаказКлиента");
//МассивИменДокументов.Добавить("ЗаказМатериаловВПроизводство");
//МассивИменДокументов.Добавить("ЗаказНаВнутреннееПотребление");
//МассивИменДокументов.Добавить("ЗаказНаПеремещение");
//МассивИменДокументов.Добавить("ЗаказНаСборку");
//МассивИменДокументов.Добавить("..."); в это место можно добавить необходимые документы
Если МассивИменДокументов.Найти(ИмяДокумента) <> Неопределено Тогда
СтарыйКусокЗапроса =
" КОГДА ПолитикиУчетаСерий.ПолитикаУчетаСерий.УчитыватьСебестоимостьПоСериям
| ТОГДА ВЫБОР
| КОГДА Товары.Серия <> ЗНАЧЕНИЕ(Справочник.СерииНоменклатуры.ПустаяСсылка)
| ТОГДА 14
| КОГДА Товары.ВариантОбеспечения = ЗНАЧЕНИЕ(Перечисление.ВариантыОбеспечения.СоСклада)
| ТОГДА 15
| ИНАЧЕ 13
| КОНЕЦ";
НовыйКусокЗапроса =
" КОГДА ПолитикиУчетаСерий.ПолитикаУчетаСерий.УчитыватьСебестоимостьПоСериям
| ТОГДА 0
| КОНЕЦ";
Иначе
Возврат;
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, СтарыйКусокЗапроса, НовыйКусокЗапроса);
КонецПроцедуры
После вышеописанных доработок, для заказов, указанных в массиве "МассивИменДокументов", указание серии будет недоступно для политики "Учет себестоимости по сериям". Если планируется в будущем расширение списка документов, то перед добавлением документа в массив, необходимо проверять текст запроса получения серий "ТекстЗапросаЗаполненияСтатусовУказанияСерий", т.к. для некоторых документов текст запроса может отличаться.
II/I
После вышеописанных манипуляций заказы будут проводиться корректно и выполнять движения по регистрам с пустой серией, однако документы реализации также требуют доработки, чтобы они формировали корректные движения по регистрам (иначе в документах реализации будут движения в разрезе серий, а в заказах — без серий). Регистров, в которых участвуют документы реализации, большое количество, из-за этого было принято решение также разработать универсальный механизм, который будет очищать значения серий для данной политики учета. Для этого в процедуру "ПроведениеДокументов.ИнициализироватьДанныеДокументаДляПроведения" были внесены следующие изменения:
Текст процедуры "ВыполнитьКорректировкуСерийВДвиженияхПоРегистрам":
Процедура ВыполнитьКорректировкуСерийВДвиженияхПоРегистрам (Параметры, ТаблицыДляДвижений) Экспорт
Если НЕ ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(Параметры, "Ссылка") Тогда
Возврат;
КонецЕсли;
ИмяДокумента = Параметры.Ссылка.Метаданные().Имя;
СтруктураДокументов = Новый Структура;
МассивИменТаблиц = Новый Массив;
МассивИменТаблиц.Добавить("ТаблицаЗаказыКлиентов");
МассивИменТаблиц.Добавить("ТаблицаТоварыКОтгрузке");
СтруктураДокументов.Вставить("ПередачаДавальцу", МассивИменТаблиц);
МассивИменТаблиц = Новый Массив;
МассивИменТаблиц.Добавить("ТаблицаЗаказыКлиентов");
МассивИменТаблиц.Добавить("ТаблицаТоварыКОтгрузке");
СтруктураДокументов.Вставить("РеализацияТоваровУслуг", МассивИменТаблиц);
//МассивИменТаблиц = Новый Массив; в это место можно добавить необходимые регистры
//МассивИменТаблиц.Добавить("...");
//МассивИменТаблиц.Добавить("...");
//СтруктураДокументов.Вставить("...", МассивИменТаблиц); в это место можно добавить необходимые документы
Если НЕ СтруктураДокументов.Свойство(ИмяДокумента) Тогда
Возврат;
КонецЕсли;
КорректируемыеТаблицы = СтруктураДокументов[ИмяДокумента];
Для каждого ИмяТаблицы из КорректируемыеТаблицы Цикл
Если ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(ТаблицыДляДвижений, ИмяТаблицы) Тогда
ТаблицаДвижения = ТаблицыДляДвижений[ИмяТаблицы];
КолонкаСерия = ТаблицаДвижения.Колонки.Найти("Серия");
КолонкаСерия.Имя = "СтараяСерия";
Запрос = Новый Запрос;
ТекстЗапроса =
"ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_ТаблицаДвижения ИЗ &ТЗ_ТаблицаДвижения КАК ТЗ_ТаблицаДвижения" +
ОбщегоНазначения.РазделительПакетаЗапросов() +
"ВЫБРАТЬ ВТ_ТаблицаДвижения.*,
|ВЫБОР
| КОГДА НЕ ПолитикиУчетаСерий.ПолитикаУчетаСерий.УчитыватьСебестоимостьПоСериям
| ТОГДА ВТ_ТаблицаДвижения.СтараяСерия
| ИНАЧЕ ЗНАЧЕНИЕ(Справочник.СерииНоменклатуры.ПустаяСсылка)
| КОНЕЦ КАК Серия
|ИЗ ВТ_ТаблицаДвижения КАК ВТ_ТаблицаДвижения
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыНоменклатуры.ПолитикиУчетаСерий КАК ПолитикиУчетаСерий
| ПО (ПолитикиУчетаСерий.Склад = &ПараметрСклад)
| И ВЫРАЗИТЬ(ВТ_ТаблицаДвижения.Номенклатура КАК Справочник.Номенклатура).ВидНоменклатуры = ПолитикиУчетаСерий.Ссылка";
Если Параметры.Свойство("СкладОтправитель") Тогда
Запрос.УстановитьПараметр("ПараметрСклад", Параметры.СкладОтправитель);
Иначе
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ПараметрСклад", "ВТ_ТаблицаДвижения.Склад");
КонецЕсли;
Запрос.Текст = ТекстЗапроса;
Запрос.УстановитьПараметр("ТЗ_ТаблицаДвижения", ТаблицаДвижения);
ТаблицаДвижения = Запрос.Выполнить().Выгрузить();
ТаблицаДвижения.Колонки.Удалить("СтараяСерия");
ТаблицыДляДвижений[ИмяТаблицы] = ТаблицаДвижения;
КонецЕсли;
КонецЦикла
КонецПроцедуры
Документы, для которых необходимо выполнить корректировку движений, добавляются в структуру "СтруктураДокументов", где Ключ - Имя документа, Значение - массив регистров, по которым необходимо выполнить корректировку движений. Имя регистра вводится в формате "Таблица + "ИмяРегистра".
II/II
В предыдущих пунктах была рассмотрена модификация для неордерных складов. Что делать в случае, если используется ордерные склады, серия указывается в расходном ордере и на момент проведения реализация еще не известна? Серия в данной политике является разрезом финансового учета (заполняется значение поля "Серия" измерения "Ключи аналитики номенклатуры"), следовательно в документах реализации указание серии необходимо, т.к. именно данные документы совершают движения по регистрам "Себестоимость товаров", "Выручка и себестоимость продаж". (В теории, возможно программно заполнять серию в документах реализации на основании складских ордеров, но это выходит за рамки текущей заметки).
Заключение
Выше приведена одна из методик доработки политики учета серий "Учет себестоимости по сериям" с целью отключения обязательного указания серий в заказах. Для этого потребуется отредактировать два общих модуля "НоменклатураСервер" и "ПроведениеСервер", производить программное изменение движений документов, что скажется на производительности и в перспективе может привести к не самым лучшим последствиям при обновлении. Впрочем, конечное решение о доработке принимает каждый разработчик самостоятельно.