Как программно перенести остатки по сериям номенклатуры в УТ 11.4 (КА 2, ERP 2) и правильно заполнить статус указания серий?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет IT и автоматизация бизнеса
← На главную

При переходе на современные конфигурации семейства 1С:ERP (включая "1С:Управление торговлей 11" и "1С:Комплексная автоматизация 2") разработчики часто сталкиваются со специфическим поведением платформы при переносе остатков. Одна из самых болезненных тем — это перенос остатков в разрезе серий номенклатуры. Разработчик может потратить массу времени: перепроверить учетную политику, настроить политики учета серий на складах, заполнить табличную часть товаров и подчиненную таблицу серий, но при записи документа серии попросту «исчезают» или не отображаются в интерфейсе, а сам документ отказывается проводиться.

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

Рассмотрим проблему изнутри и разберем по шагам готовые решения.

В чем причина проблемы: архитектура серийного учета в УТ 11

В старых конфигурациях (например, в УТ 10.3) учет серий велся относительно просто: серия была обычным субконто или разрезом учета на складе, который достаточно было просто указать в соответствующей колонке табличной части. В управляемом интерфейсе УТ 11 / КА 2 / ERP 2 логика кардинально изменилась. При необходимости проконтролировать корректность распределения данных между складскими регистрами и себестоимостью можно использовать обработку для сверки остатков товаров по складам, организациям и себестоимости.

Теперь возможность и необходимость указания серий зависят от множества факторов:

Для управления видимостью колонок, доступностью ввода серий и контролем заполнения разработчики 1С ввели специальный служебный реквизит в табличную часть товаров. В зависимости от релиза и документа он может называться УказыватьСерии или СтатусУказанияСерий. Этот реквизит имеет тип данных Число с длиной 2. Именно он является главным "камнем преткновения" при программном создании документов.

Почему используется числовой статус вместо перечисления?

Использование двузначного числа вместо классического перечисления или булевого флага часто вызывает недоумение у программистов. Однако у такого подхода со стороны разработчиков фирмы "1С" есть логичные технические причины:

  1. Высокая производительность при проведении. Проверка числовых флагов в запросах СУБД при проведении документов и контроле остатков происходит значительно быстрее, чем анализ текстовых строк или сложных логических условий с участием нескольких таблиц.
  2. Многозадачность флага. Одно число способно кодировать одновременно несколько сущностей: политику учета серий, место указания серий (в накладной или в ордере) и текущее состояние заполнения (совпадает ли количество товара с количеством указанных серий в подчиненной табличной части).

Расшифровка "магических чисел" (числовых статусов)

Вся логика визуализации (отображение зеленых и красных пиктограмм в интерфейсе) и проведения документов завязана на четность этого числа:

Давайте проанализируем конкретные значения, которые может принимать реквизит УказыватьСерии (или СтатусУказанияСерий) в зависимости от настроек системы:

Если при программном переносе остатков записать ТЧ товаров и подчиненную ТЧ серий, но оставить реквизит УказыватьСерии равным 0 (или пустой/нечетный статус), то система проигнорирует заполненную таблицу серий. Документ запишется без серий, либо выдаст ошибку проведения.

Рассмотрим, как решить эту проблему правильно и не прибегать к жесткому кодированию ("хардкоду") числовых статусов.

Решение 1. Метод сравнения объектов (Компаративный анализ)

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

  1. Создаем один тестовый документ ввода остатков вручную в пользовательском интерфейсе. Заполняем его точно такими же данными: той же номенклатурой, тем же складом и теми же сериями. Проводим документ и убеждаемся, что серии успешно записались (горит зеленая пиктограмма).
  2. Создаем второй документ программно (с помощью вашей обработки переноса), но пока не проводим его.
  3. Используем внешнюю обработку "Консоль запросов" или пишем простой код для выгрузки структуры табличных частей обоих документов в формат XML или JSON.
  4. Сравниваем полученные файлы в любом текстовом дифференцикаторе (например, Notepad++, WinMerge или встроенном сравнении файлов в платформе 1С).

Этот простой метод наглядно покажет вам, какие именно служебные реквизиты (такие как КлючСвязи, СтатусУказанияСерий, УказыватьСерии) вы забыли заполнить или заполнили неверно в коде загрузки.

Решение 2. Правильная связь табличных частей через КлючСвязи

В УТ 11 табличная часть товаров и табличная часть серий связаны между собой не по номеру строки (так как строки товаров могут группироваться или сортироваться), а через специальный реквизит связи. Проанализируем это.

В ТЧ Товары присутствует реквизит КлючСвязи (тип Число). В подчиненной табличной части (в зависимости от документа это может быть ТЧ Серии или ТЧ ВыделенныеСерии) также есть реквизит КлючСвязи. Для того чтобы система поняла, к какому именно товару относится конкретная серия, эти ключи должны строго совпадать.

Посмотрим на пример правильного заполнения связей в коде:


// Пример программного заполнения связи между Товарами и Сериями
НоваяСтрокаТовара = ДокументОбъект.Товары.Добавить();
НоваяСтрокаТовара.Номенклатура = СсылкаНоменклатура;
НоваяСтрокаТовара.Количество   = 10;
// Генерируем уникальный ключ связи для строки товара
НоваяСтрокаТовара.КлючСвязи    = ДокументОбъект.Товары.Количество(); 

// Заполняем серию для этой строки товара
НоваяСтрокаСерии = ДокументОбъект.Серии.Добавить();
НоваяСтрокаСерии.Серия     = СсылкаСерия;
НоваяСтрокаСерии.Количество = 10;
// Связываем строку серии со строкой товара через КлючСвязи
НоваяСтрокаСерии.КлючСвязи  = НоваяСтрокаТовара.КлючСвязи;

Решение 3. Использование программного интерфейса БСП (Без "хардкода" чисел)

Прописывать "магические числа" (например, жестко присваивать статус 14 или 2) в коде загрузки крайне не рекомендуется. Если завтра изменится учетная политика склада, обновится релиз конфигурации или пользователь поменяет настройки политики серий для номенклатуры — ваша обработка переноса начнет записывать некорректные статусы, что приведет к невозможности проведения документов.

Правильный путь — использовать стандартные экспортные процедуры общих модулей конфигурации. В УТ 11 за расчет и установку статусов серий отвечает общий модуль НоменклатураСервер (или в некоторых версиях специализированные процедуры в модулях менеджеров документов).

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

Для этого после программного заполнения табличных частей Товары и Серии (с установленными ключами связи) необходимо вызвать специализированный метод конфигурации. Рассмотрим пример кода:


// Вызываем процедуру пересчета статусов указания серий для документа ввода остатков.
// Параметры процедуры могут незначительно отличаться в зависимости от релиза УТ 11.
// Обычно метод принимает объект документа и имя заполняемой табличной части.

ПараметрыУказания = НоменклатураКлиентСервер.ПараметрыУказанияСерий();
ПараметрыУказания.ИмяТабличнойЧасти = "Товары";
ПараметрыУказания.ИмяТЧСерии        = "Серии";
ПараметрыУказания.Документ          = ДокументОбъект;

// Вызов стандартного метода БСП для расчета статусов в ТЧ "Товары"
НоменклатураСервер.ЗаполнитьСтатусыУказанияСерий(ДокументОбъект, ПараметрыУказания);

В более старых версиях УТ 11.4 или КА 2 расчет статусов можно инициировать через вызов процедур заполнения реквизитов табличной части в модуле менеджера или общего модуля:


// Альтернативный вариант для некоторых релизов УТ 11.4
СтруктураДействий = Новый Структура;
СтруктураДействий.Вставить("ЗаполнитьДубликатыЗависимыхРеквизитов", Истина);
СтруктураДействий.Вставить("ЗаполнитьСтатусыУказанияСерий", Истина);

// Пересчитываем реквизиты табличной части программно
НоменклатураСервер.ЗаполнитьТабличнуюЧасть(ДокументОбъект, "Товары", СтруктураДействий);

Этот метод самостоятельно проанализирует склады, учетные политики, сопоставит строки по КлючСвязи, посчитает количество указанных серий в подчиненной табличной части и автоматически проставит нужное четное число (например, 2, 4, 14) в реквизит УказыватьСерии. Документ станет корректным с точки зрения логики конфигурации и успешно проведется.

Полный пример программного создания документа ввода остатков с сериями

Объединим все полученные знания в одну готовую процедуру. Этот код можно использовать в качестве шаблона для вашей обработки переноса данных из внешних систем (например, при выгрузке из старой "1С:Управление торговлей 10.3" или "1С:Комплексная автоматизация 1.1").


Процедура СоздатьВводОстатковССериями(СтруктураДанных) Экспорт

    // 1. Создаем объект документа ввода остатков
    ДокОбъект = Документы.ВводНачальныхОстатков.СоздатьДокумент();
    ДокОбъект.Дата = ТекущаяДата();
    ДокОбъект.Организация = СтруктураДанных.Организация;
    ДокОбъект.ХозяйственнаяОперация = Перечисления.ХозяйственныеОперации.ВводОстатковСобственныхТоваров;
    ДокОбъект.ОтражатьВУчете = Истина;
    ДокОбъект.ОтражатьВУправленческомУчете = Истина;
    
    // Заполняем складской контур
    ДокОбъект.Склад = СтруктураДанных.Склад;
    
    // 2. Заполняем товары и подчиненные серии
    Для Каждого СтрокаДанных Из СтруктураДанных.ТаблицаТоваров Цикл
        
        // Добавляем строку в основную ТЧ Товары
        НоваяСтрокаТовара = ДокОбъект.Товары.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрокаТовара, СтрокаДанных);
        
        // Генерируем уникальный КлючСвязи
        НоваяСтрокаТовара.КлючСвязи = ДокОбъект.Товары.Количество();
        
        // Добавляем строки в ТЧ Серии (если у товара ведется серийный учет)
        Если ЗначениеЗаполнено(СтрокаДанных.Серия) Тогда
            НоваяСтрокаСерии = ДокОбъект.Серии.Добавить();
            НоваяСтрокаСерии.Серия = СтрокаДанных.Серия;
            НоваяСтрокаСерии.Количество = СтрокаДанных.Количество;
            
            // Связываем с родителем
            НоваяСтрокаСерии.КлючСвязи = НоваяСтрокаТовара.КлючСвязи;
        КонецЕсли;
        
    КонецЦикла;
    
    // 3. Автоматически рассчитываем статусы указания серий через БСП
    // Это избавит нас от необходимости вручную указывать числовые коды статусов
    ПараметрыУказания = НоменклатураКлиентСервер.ПараметрыУказанияСерий();
    ПараметрыУказания.ИмяТабличнойЧасти = "Товары";
    ПараметрыУказания.ИмяТЧСерии        = "Серии";
    ПараметрыУказания.Документ          = ДокОбъект;
    
    НоменклатураСервер.ЗаполнитьСтатусыУказанияСерий(ДокОбъект, ПараметрыУказания);
    
    // 4. Записываем и проводим документ
    Попытка
        ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
        Сообщить("Документ " + ДокОбъект.Ссылка + " успешно создан и проведен.");
    Исключение
        ДокОбъект.Записать(РежимЗаписиДокумента.Запись);
        ОбщегоНазначенияКлиентСервер.СообщитьОшибку(КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;

КонецПроцедуры

Резюме и рекомендации

Подведем итоги нашего исследования. Для успешного переноса остатков по собственным товарам в разрезе серий в УТ 11.4 необходимо соблюдать три золотых правила:

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

← На главную