Почему при программном создании документа в 1С поле Количество остается пустым и как это исправить?

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

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

Разберем причину: Количество против Количества упаковок

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

Проанализируем структуру табличной части Товары. В большинстве современных типовых решений для каждой строки хранения предусмотрено несколько реквизитов:

  1. КоличествоУпаковок — это именно тот реквизит, который пользователь видит на форме. Он связан с выбранной упаковкой (единицей измерения) и отображает количество в этих самых упаковках.
  2. Количество — скрытый технический реквизит, в котором хранится количество товара в базовых единицах измерения. Он используется для проведения по регистрам накопления.
  3. Коэффициент — множитель, связывающий эти два поля.

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

Решение №1: Ручное исправление заполнения табличной части

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


&НаСервере
Процедура СоздатьДокументыПередачиНаСервере(МассивЗаказов)
    
    Для Каждого ЗаказКлиента Из МассивЗаказов Цикл
        // Создаем новый документ
        НовыйДокумент = Документы.ПередачаТоваровХранителю.СоздатьДокумент();
        НовыйДокумент.Дата = ТекущаяДата();
        
        // Заполняем шапку
        НовыйДокумент.Партнер = ЗаказКлиента.Партнер; 
        НовыйДокумент.Менеджер = ЗаказКлиента.Менеджер;
        НовыйДокумент.Подразделение = ЗаказКлиента.Подразделение;
        
        // Заполняем табличную часть "Товары"
        Для Каждого СтрокаТоваров Из ЗаказКлиента.Товары Цикл
            НоваяСтрока = НовыйДокумент.Товары.Добавить();
            НоваяСтрока.Номенклатура = СтрокаТоваров.Номенклатура; 
            
            // ВАЖНО: Используем правильный реквизит для отображения на форме
            НоваяСтрока.КоличествоУпаковок = СтрокаТоваров.КоличествоУпаковок;
            
            // Если требуется заполнить базовое количество, заполняем и его
            НоваяСтрока.Количество = СтрокаТоваров.Количество;
            
            НоваяСтрока.Цена = СтрокаТоваров.Цена; 
            НоваяСтрока.Сумма = СтрокаТоваров.Сумма;
        КонецЦикла;
        
        НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);    
    КонецЦикла;
КонецПроцедуры

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

Решение №2: Использование стандартного метода Заполнить()

Проанализируем более эффективный и правильный способ создания документов "на основании". В платформе 1С реализован мощный механизм — метод Заполнить(). Он автоматически вызывает процедуру ОбработкаЗаполнения в модуле объекта создаваемого документа.

Почему это лучше ручного кода? Рассмотрим преимущества:

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


&НаСервере
Процедура СоздатьДокументыПередачиНаСервере(МассивЗаказов)
    
    Для Каждого ЗаказКлиента Из МассивЗаказов Цикл
        НовыйДокумент = Документы.ПередачаТоваровХранителю.СоздатьДокумент();
        НовыйДокумент.Дата = ТекущаяДата();
        
        // Вызываем стандартный механизм заполнения на основании
        // Система сама найдет правила переноса данных из Заказа клиента
        НовыйДокумент.Заполнить(ЗаказКлиента);
        
        // Если какие-то поля нужно дозаполнить специфично, делаем это после
        НовыйДокумент.Менеджер = ПараметрыСеанса.ТекущийПользователь;
        
        Попытка
            НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);
        Исключение
            ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ОписаниеОшибки());
        КонецПопытки;
    КонецЦикла;
    
КонецПроцедуры

Важные нюансы при программной работе с документами

Разберем дополнительные факторы, которые могут влиять на результат проведения документа и видимость данных. Простая запись объекта не всегда гарантирует его корректность с точки зрения бизнес-логики.

1. Пересчет зависимых реквизитов. Если вы все же заполняете данные вручную, обязательно вызывайте экспортные процедуры из общих модулей типовой конфигурации. Например, после заполнения номенклатуры и количества в ERP/УТ11, рекомендуется использовать механизмы для расчета суммы и НДС. Это могут быть процедуры типа РассчитатьСуммуТабличнойЧасти, расположенные в общих модулях (точное имя зависит от версии вашей конфигурации).

2. Склады и статусы. Документ Передача товаров хранителю часто требует указания конкретного склада и статуса (например, "К передаче"). Если склад в Заказе клиента указан в табличной части, а в новом документе вы его не заполнили (или не перенесли в шапку), документ может не провестись по регистрам остатков, даже если визуально "количество" заполнено.

3. Использование транзакций. Рассмотрим ситуацию, когда вы обрабатываете массив из 50 заказов. Если на 40-м заказе произойдет ошибка (например, не хватит товара на складе), выполнение прервется. В базе останется 39 созданных документов, а остальные 11 не будут созданы. Чтобы обеспечить целостность данных, рекомендуется оборачивать цикл в транзакцию:


НачатьТранзакцию();
Попытка
    // Ваш цикл создания документов
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    ЗаписатьЛогОшибки(ОписаниеОшибки());
КонецПопытки;

4. Проверка прав доступа. Помните, что при выполнении кода &НаСервере проверка прав доступа может работать иначе, чем в интерфейсе. Если у пользователя нет прав на создание документа ПередачаТоваровХранителю, метод Записать() вызовет исключение. Всегда обрабатывайте такие моменты через блоки Попытка...Исключение.

Резюме

Подведем итоги. Если у вас не переносится поле Количество:

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

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

← На главную