Заполнение реквизита табличной части документа в расширении: разбор ошибок доступа к объекту и работы с перечислениями

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

При разработке расширений для типовых конфигураций (например, УНФ или Розница) часто возникает задача: перенести дополнительные данные из первичных документов (чеков ККМ) в сводный документ (Отчет о розничных продажах). Рассмотрим ситуацию, когда необходимо добавить признак безналичной оплаты в табличную часть «Запасы» документа «Отчет о розничных продажах» и заполнить его автоматически при закрытии смены.

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

Постановка задачи

В документ ОтчетОРозничныхПродажах (ОРП) через расширение добавлен булевый реквизит табличной части «Запасы» — ОплатаБезналом (или аналогичный). При формировании ОРП на основании чеков необходимо:

  1. Проанализировать форму оплаты каждого чека.
  2. Если оплата была безналичной — установить значение Истина.
  3. Если наличной — Ложь.

Типичная ошибка: «Поле объекта недоступно для записи»

Часто при попытке перебрать строки табличной части и установить значение, начинающие разработчики пишут код, подобный этому:


Для Каждого СтрокаТЧ Из Запасы Цикл
    Если СтрокаТЧ.ФормаОплаты = "Наличные" Тогда
        // ОШИБКА ЗДЕСЬ:
        ОтчетОРозничныхПродажахОбъект.Ссылка.Запасы.ОплатаБезналом = Ложь;
    Иначе
        ОтчетОРозничныхПродажахОбъект.Ссылка.Запасы.ОплатаБезналом = Истина;
    КонецЕсли;
КонецЦикла;

При выполнении этого кода система выдает ошибку: «Поле объекта недоступно для записи». Давайте разберемся, почему это происходит.

В платформе 1С существует четкое разделение между Объектом (ДокументОбъект) и Ссылкой (ДокументСсылка).

В приведенном выше ошибочном примере используется конструкция ОтчетОРозничныхПродажахОбъект.Ссылка.Запасы.... Фактически, вы пытаетесь записать данные не в текущий редактируемый документ, а обратиться к базе данных через ссылку, что запрещено в данном контексте.

Ошибка сравнения типов: Строка vs Перечисление

Вторая распространенная ошибка касается проверки условия. В коде часто встречается:


Если СтрокаТЧ.ФормаОплаты = "Наличные" Тогда ...

В типовых конфигурациях 1С реквизит ФормаОплаты обычно имеет тип ПеречислениеСсылка (например, Перечисление.СпособыОплаты или Перечисление.ТипыОплатЧекаККМ). Строка "Наличные" никогда не будет равна ссылке на перечисление, даже если название совпадает. Такое условие всегда будет возвращать Ложь (или работать непредсказуемо).

Правильное решение

Чтобы код работал корректно, нам нужно:

  1. Работать непосредственно со строкой коллекции, которую мы перебираем в цикле. Переменная цикла (итератор) уже содержит ссылку на строку табличной части объекта.
  2. Использовать предопределенные значения перечислений для сравнения.

Предположим, что вы используете расширение метода заполнения (например, через аннотацию &ИзменениеИКонтроль или &После) и у вас есть доступ к объекту документа ОтчетОРозничныхПродажахОбъект.

Правильный алгоритм будет выглядеть следующим образом:


// Перебираем строки табличной части "Запасы" текущего ОБЪЕКТА документа
Для Каждого СтрокаТЧ Из ОтчетОРозничныхПродажахОбъект.Запасы Цикл
    
    // Предполагаем, что колонка "ФормаОплаты" была добавлена в таблицу "Запасы" 
    // на этапе выполнения запроса (как было показано в исходной задаче)
    
    // Правильное сравнение с Перечислением
    // Важно: имя перечисления "ТипыОплатЧекаККМ" может отличаться в вашей конфигурации, 
    // проверьте точное имя в дереве метаданных.
    Если СтрокаТЧ.ФормаОплаты = Перечисления.ТипыОплатЧекаККМ.Безналичные Тогда
        
        // Присваиваем значение непосредственно свойству СТРОКИ
        СтрокаТЧ.ОплатаБезналом = Истина;
        
    Иначе
        
        СтрокаТЧ.ОплатаБезналом = Ложь;
        
    КонецЕсли;
    
КонецЦикла;

Или более компактный вариант записи того же условия:


Для Каждого СтрокаТЧ Из ОтчетОРозничныхПродажахОбъект.Запасы Цикл
    СтрокаТЧ.ОплатаБезналом = (СтрокаТЧ.ФормаОплаты = Перечисления.ТипыОплатЧекаККМ.Безналичные);
КонецЦикла;

Важные нюансы реализации

1. Подготовка данных в запросе
Чтобы код выше сработал, поле ФормаОплаты должно присутствовать в данных, которыми заполняется табличная часть. Если вы модифицируете запрос (как в исходном сообщении темы), убедитесь, что вы выбираете это поле из чеков и помещаете его во временную таблицу или выборку, которая затем загружается в Запасы.

Если вы используете метод ЗаполнитьЗначенияСвойств, то имена колонок в выборке запроса должны совпадать с именами реквизитов ТЧ. Например, если в запросе сразу вычислить поле:


ВЫБОР 
    КОГДА Чек.ФормаОплаты = ЗНАЧЕНИЕ(Перечисление.ТипыОплатЧекаККМ.Безналичные) ТОГДА ИСТИНА 
    ИНАЧЕ ЛОЖЬ 
КОНЕЦ КАК ОплатаБезналом

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

2. Смешанная оплата
В теме обсуждался вопрос: что делать, если чек оплачен частично наличными, частично картой? В рамках простой логики (Товар -> Истина/Ложь) это сложный момент. Обычно в таких случаях либо весь чек считается безналичным, если есть хоть копейка безнала, либо требуется более сложная логика распределения оплат. Однако для учебной задачи или при строгом разделении чеков, приведенное выше решение с булевым флагом является рабочим.

← На главную