При переходе на современные конфигурации семейства 1С:ERP (включая "1С:Управление торговлей 11" и "1С:Комплексная автоматизация 2") разработчики часто сталкиваются со специфическим поведением платформы при переносе остатков. Одна из самых болезненных тем — это перенос остатков в разрезе серий номенклатуры. Разработчик может потратить массу времени: перепроверить учетную политику, настроить политики учета серий на складах, заполнить табличную часть товаров и подчиненную таблицу серий, но при записи документа серии попросту «исчезают» или не отображаются в интерфейсе, а сам документ отказывается проводиться.
В этой статье мы подробно проанализируем, почему так происходит, разберем скрытые механизмы работы серийного учета в ERP-системах, выясним назначение загадочных числовых реквизитов в табличных частях и научимся правильно переносить остатки программным путем.
Рассмотрим проблему изнутри и разберем по шагам готовые решения.
В старых конфигурациях (например, в УТ 10.3) учет серий велся относительно просто: серия была обычным субконто или разрезом учета на складе, который достаточно было просто указать в соответствующей колонке табличной части. В управляемом интерфейсе УТ 11 / КА 2 / ERP 2 логика кардинально изменилась. При необходимости проконтролировать корректность распределения данных между складскими регистрами и себестоимостью можно использовать обработку для сверки остатков товаров по складам, организациям и себестоимости.
Теперь возможность и необходимость указания серий зависят от множества факторов:
Для управления видимостью колонок, доступностью ввода серий и контролем заполнения разработчики 1С ввели специальный служебный реквизит в табличную часть товаров. В зависимости от релиза и документа он может называться УказыватьСерии или СтатусУказанияСерий. Этот реквизит имеет тип данных Число с длиной 2. Именно он является главным "камнем преткновения" при программном создании документов.
Использование двузначного числа вместо классического перечисления или булевого флага часто вызывает недоумение у программистов. Однако у такого подхода со стороны разработчиков фирмы "1С" есть логичные технические причины:
Вся логика визуализации (отображение зеленых и красных пиктограмм в интерфейсе) и проведения документов завязана на четность этого числа:
Давайте проанализируем конкретные значения, которые может принимать реквизит УказыватьСерии (или СтатусУказанияСерий) в зависимости от настроек системы:
0 — серии указывать не требуется (серийный учет отключен или не используется для данной операции).1 (нечетное) / 2 (четное) — серии указываются справочно (без контроля остатков на складе).3 (нечетное) / 4 (четное) — ведется учет остатков серий, серии указываются по факту отбора (на ордерном складе — непосредственно в расходном ордере).5 (нечетное) / 6 (четное) — ведется учет остатков серий, серии указываются при планировании отбора и заполняются автоматически по методу FEFO (по срокам годности).7 (нечетное) / 8 (четное) — ведется учет остатков серий, серии указываются при планировании отбора (в самой накладной).9 (нечетное) / 10 (четное) — серии указываются при планировании отгрузки, по ним формируются движения по регистру "Свободные остатки".13 (нечетное) / 14 (четное) — по сериям ведется полноценный финансовый учет (учет себестоимости). При переносе остатков это один из самых частых статусов.Если при программном переносе остатков записать ТЧ товаров и подчиненную ТЧ серий, но оставить реквизит УказыватьСерии равным 0 (или пустой/нечетный статус), то система проигнорирует заполненную таблицу серий. Документ запишется без серий, либо выдаст ошибку проведения.
Рассмотрим, как решить эту проблему правильно и не прибегать к жесткому кодированию ("хардкоду") числовых статусов.
Если вы столкнулись с ситуацией, когда программно созданный документ ведет себя не так, как созданный вручную, используем классический и крайне эффективный прием разработчиков 1С. Выясним причину расхождений по шагам:
Этот простой метод наглядно покажет вам, какие именно служебные реквизиты (такие как КлючСвязи, СтатусУказанияСерий, УказыватьСерии) вы забыли заполнить или заполнили неверно в коде загрузки.
В УТ 11 табличная часть товаров и табличная часть серий связаны между собой не по номеру строки (так как строки товаров могут группироваться или сортироваться), а через специальный реквизит связи. Проанализируем это.
В ТЧ Товары присутствует реквизит КлючСвязи (тип Число). В подчиненной табличной части (в зависимости от документа это может быть ТЧ Серии или ТЧ ВыделенныеСерии) также есть реквизит КлючСвязи. Для того чтобы система поняла, к какому именно товару относится конкретная серия, эти ключи должны строго совпадать.
Посмотрим на пример правильного заполнения связей в коде:
// Пример программного заполнения связи между Товарами и Сериями
НоваяСтрокаТовара = ДокументОбъект.Товары.Добавить();
НоваяСтрокаТовара.Номенклатура = СсылкаНоменклатура;
НоваяСтрокаТовара.Количество = 10;
// Генерируем уникальный ключ связи для строки товара
НоваяСтрокаТовара.КлючСвязи = ДокументОбъект.Товары.Количество();
// Заполняем серию для этой строки товара
НоваяСтрокаСерии = ДокументОбъект.Серии.Добавить();
НоваяСтрокаСерии.Серия = СсылкаСерия;
НоваяСтрокаСерии.Количество = 10;
// Связываем строку серии со строкой товара через КлючСвязи
НоваяСтрокаСерии.КлючСвязи = НоваяСтрокаТовара.КлючСвязи;
Прописывать "магические числа" (например, жестко присваивать статус 14 или 2) в коде загрузки крайне не рекомендуется. Если завтра изменится учетная политика склада, обновится релиз конфигурации или пользователь поменяет настройки политики серий для номенклатуры — ваша обработка переноса начнет записывать некорректные статусы, что приведет к невозможности проведения документов.
Правильный путь — использовать стандартные экспортные процедуры общих модулей конфигурации. В УТ 11 за расчет и установку статусов серий отвечает общий модуль НоменклатураСервер (или в некоторых версиях специализированные процедуры в модулях менеджеров документов).
Давайте разберем по шагам, как заставить конфигурацию самой рассчитать правильные статусы указания серий на основе действующих настроек политики учета.
Для этого после программного заполнения табличных частей Товары и Серии (с установленными ключами связи) необходимо вызвать специализированный метод конфигурации. Рассмотрим пример кода:
// Вызываем процедуру пересчета статусов указания серий для документа ввода остатков.
// Параметры процедуры могут незначительно отличаться в зависимости от релиза УТ 11.
// Обычно метод принимает объект документа и имя заполняемой табличной части.
ПараметрыУказания = НоменклатураКлиентСервер.ПараметрыУказанияСерий();
ПараметрыУказания.ИмяТабличнойЧасти = "Товары";
ПараметрыУказания.ИмяТЧСерии = "Серии";
ПараметрыУказания.Документ = ДокументОбъект;
// Вызов стандартного метода БСП для расчета статусов в ТЧ "Товары"
НоменклатураСервер.ЗаполнитьСтатусыУказанияСерий(ДокументОбъект, ПараметрыУказания);
В более старых версиях УТ 11.4 или КА 2 расчет статусов можно инициировать через вызов процедур заполнения реквизитов табличной части в модуле менеджера или общего модуля:
// Альтернативный вариант для некоторых релизов УТ 11.4
СтруктураДействий = Новый Структура;
СтруктураДействий.Вставить("ЗаполнитьДубликатыЗависимыхРеквизитов", Истина);
СтруктураДействий.Вставить("ЗаполнитьСтатусыУказанияСерий", Истина);
// Пересчитываем реквизиты табличной части программно
НоменклатураСервер.ЗаполнитьТабличнуюЧасть(ДокументОбъект, "Товары", СтруктураДействий);
Этот метод самостоятельно проанализирует склады, учетные политики, сопоставит строки по КлючСвязи, посчитает количество указанных серий в подчиненной табличной части и автоматически проставит нужное четное число (например, 2, 4, 14) в реквизит УказыватьСерии. Документ станет корректным с точки зрения логики конфигурации и успешно проведется.
Объединим все полученные знания в одну готовую процедуру. Этот код можно использовать в качестве шаблона для вашей обработки переноса данных из внешних систем (например, при выгрузке из старой "1С:Управление торговлей 10.3" или "1С:Комплексная автоматизация 1.1").
Процедура СоздатьВводОстатковССериями(СтруктураДанных) Экспорт
// 1. Создаем объект документа ввода остатков
ДокОбъект = Документы.ВводНачальныхОстатков.СоздатьДокумент();
ДокОбъект.Дата = ТекущаяДата();
ДокОбъект.Организация = СтруктураДанных.Организация;
ДокОбъект.ХозяйственнаяОперация = Перечисления.ХозяйственныеОперации.ВводОстатковСобственныхТоваров;
ДокОбъект.ОтражатьВУчете = Истина;
ДокОбъект.ОтражатьВУправленческомУчете = Истина;
// Заполняем складской контур
ДокОбъект.Склад = СтруктураДанных.Склад;
// 2. Заполняем товары и подчиненные серии
Для Каждого СтрокаДанных Из СтруктураДанных.ТаблицаТоваров Цикл
// Добавляем строку в основную ТЧ Товары
НоваяСтрокаТовара = ДокОбъект.Товары.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрокаТовара, СтрокаДанных);
// Генерируем уникальный КлючСвязи
НоваяСтрокаТовара.КлючСвязи = ДокОбъект.Товары.Количество();
// Добавляем строки в ТЧ Серии (если у товара ведется серийный учет)
Если ЗначениеЗаполнено(СтрокаДанных.Серия) Тогда
НоваяСтрокаСерии = ДокОбъект.Серии.Добавить();
НоваяСтрокаСерии.Серия = СтрокаДанных.Серия;
НоваяСтрокаСерии.Количество = СтрокаДанных.Количество;
// Связываем с родителем
НоваяСтрокаСерии.КлючСвязи = НоваяСтрокаТовара.КлючСвязи;
КонецЕсли;
КонецЦикла;
// 3. Автоматически рассчитываем статусы указания серий через БСП
// Это избавит нас от необходимости вручную указывать числовые коды статусов
ПараметрыУказания = НоменклатураКлиентСервер.ПараметрыУказанияСерий();
ПараметрыУказания.ИмяТабличнойЧасти = "Товары";
ПараметрыУказания.ИмяТЧСерии = "Серии";
ПараметрыУказания.Документ = ДокОбъект;
НоменклатураСервер.ЗаполнитьСтатусыУказанияСерий(ДокОбъект, ПараметрыУказания);
// 4. Записываем и проводим документ
Попытка
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
Сообщить("Документ " + ДокОбъект.Ссылка + " успешно создан и проведен.");
Исключение
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);
ОбщегоНазначенияКлиентСервер.СообщитьОшибку(КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецПроцедуры
Подведем итоги нашего исследования. Для успешного переноса остатков по собственным товарам в разрезе серий в УТ 11.4 необходимо соблюдать три золотых правила:
КлючСвязи.УказыватьСерии вручную жестко прописанными числами в коде, если этого можно избежать. Применяйте вызовы процедур из общего модуля НоменклатураСервер.Используя эти рекомендации, вы сможете избежать многократных перегрузок данных, сэкономите рабочее время и обеспечите корректное ведение серийного и финансового учета в новой системе. Для проверки результатов загрузки и анализа складских остатков с ценами и суммами подойдёт отчёт по остаткам и доступности товаров с детализацией по сериям.