Как автоматически заполнить дополнительные реквизиты в Реализации на основании Заказа клиента в 1С:УТ 11.4?

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

В процессе автоматизации работы в 1С:Управление торговлей 11.4 часто возникает задача наследования данных между документами. Одной из специфических задач является перенос значений дополнительных реквизитов (созданных пользователем в режиме «1С:Предприятие») из документа-основания (Заказ клиента) в подчиненный документ (Реализация товаров и услуг). Рассмотрим, как реализовать этот механизм программно, исправим типичные ошибки новичков и разберем наиболее эффективные методы работы с библиотекой стандартных подсистем (БСП).

Анализ исходной проблемы и типичных ошибок

Разберем ситуацию, представленную в вопросе. Автор пытается прописать код в модуле РеализацияТоваровУслугЛокализация в процедуре ПередЗаписью. Проанализируем основные ошибки в исходном коде:

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

Выбор правильного метода реализации

Для решения задачи «заполнить автоматом при создании» в 1С существует стандартный обработчик ОбработкаЗаполнения. Если мы напишем код там, данные из заказа перенесутся в реализацию один раз в момент нажатия кнопки «Создать на основании». Если же нам нужно, чтобы данные синхронизировались постоянно при каждом сохранении, тогда используется ПередЗаписью.

Проанализируем работу с механизмом дополнительных реквизитов БСП. Все они хранятся в табличной части документа под названием ДополнительныеРеквизиты. Каждая строка этой таблицы содержит два важных поля: Свойство (ссылка на план видов характеристик) и Значение.

Шаг 1. Получение значения из Заказа клиента

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


// Параметры функции:
// 1. Объект - ссылка на документ, из которого читаем (Заказ клиента)
// 2. Свойство - Имя свойства (строка) или ссылка на элемент ПВХ ДополнительныеРеквизитыИСведения
ЗначениеИсточник = УправлениеСвойствами.ЗначениеСвойства(Объект.ЗаказКлиента, "СпособДоставки");

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

Шаг 2. Запись значения в Реализацию товаров и услуг

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

Рассмотрим алгоритм заполнения:

  1. Найдем ссылку на дополнительный реквизит «Метод доставки» для документа Реализация.
  2. Проверим наличие строки с этим свойством в табличной части объекта.
  3. Если строка есть — обновим значение, если нет — добавим новую строку.

Посмотрим на пример кода, который реализует эту логику в процедуре ПередЗаписью (в расширении):


&После("ПередЗаписью")
Процедура ИмяПрефикс_ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    
    // Проверяем, заполнено ли основание
    Если ЗначениеЗаполнено(ЭтотОбъект.ЗаказКлиента) Тогда
        
        // 1. Получаем значение из заказа
        // "СпособДоставки" - имя доп. реквизита в Заказе
        ЗначениеИзЗаказа = УправлениеСвойствами.ЗначениеСвойства(ЭтотОбъект.ЗаказКлиента, "СпособДоставки");
        
        Если ЗначениеЗаполнено(ЗначениеИзЗаказа) Тогда
            
            // 2. Ищем ссылку на доп. реквизит "Метод доставки" для Реализации
            // В реальном коде лучше использовать кэширование или поиск по имени
            ИмяНужногоСвойства = "Метод доставки (Общие)"; // Укажите точное наименование
            СвойствоСсылка = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию(ИмяНужногоСвойства);
            
            Если Не СвойствоСсылка.Пустая() Тогда
                
                // 3. Работаем с табличной частью текущего объекта
                ПараметрыОтбора = Новый Структура("Свойство", СвойствоСсылка);
                НайденныеСтроки = ЭтотОбъект.ДополнительныеРеквизиты.НайтиСтроки(ПараметрыОтбора);
                
                Если НайденныеСтроки.Количество() > 0 Тогда
                    // Свойство уже есть в таблице, обновляем значение
                    НайденныеСтроки[0].Значение = ЗначениеИзЗаказа;
                Иначе
                    // Свойства еще нет, добавляем новую строку
                    НоваяСтрока = ЭтотОбъект.ДополнительныеРеквизиты.Добавить();
                    НоваяСтрока.Свойство = СвойствоСсылка;
                    НоваяСтрока.Значение = ЗначениеИзЗаказа;
                КонецЕсли;
                
            КонецЕсли;
            
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Нюансы работы с типами данных

Проанализируем ситуацию, когда дополнительный реквизит имеет тип «Дополнительное значение». Это не просто строка, а ссылка на элемент специального справочника, подчиненного конкретному свойству.

Важный момент: если свойства «Способ доставки» в заказе и «Метод доставки» в реализации используют разные списки значений (разные владельцы в ПВХ), то простое присваивание ЗначениеИзЗаказа может не сработать. Система не позволит записать в реквизит значение, которое принадлежит другому свойству. В этом случае придется искать соответствие по наименованию в списке значений целевого свойства.

Если же оба свойства ссылаются на один и тот же тип данных (например, общий справочник «Курьерские службы» или просто «Строка»), то приведенный выше код будет работать идеально.

Использование стандартных процедур БСП для записи

Если вы предпочитаете использовать готовые функции библиотеки, можно воспользоваться методом ЗаписатьСвойстваУОбъекта, но делать это нужно осторожно. Основная проблема автора темы была в передаче параметров. Рассмотрим, как это должно выглядеть правильно:


// Подготовим таблицу значений для записи
ТаблицаСвойств = Новый ТаблицаЗначений;
ТаблицаСвойств.Колонки.Добавить("Свойство"); // Здесь должна быть ССЫЛКА на ПВХ
ТаблицаСвойств.Колонки.Добавить("Значение");

НоваяСтрока = ТаблицаСвойств.Добавить();
НоваяСтрока.Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Метод доставки");
НоваяСтрока.Значение = k;

// Вызываем запись. Первый параметр - ССЫЛКА на объект, который уже есть в базе.
// ВНИМАНИЕ: если объект еще не записан (новый), этот метод может выдать ошибку.
УправлениеСвойствами.ЗаписатьСвойстваУОбъекта(ЭтотОбъект.Ссылка, ТаблицаСвойств);

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

Заключение

Мы выяснили, что для корректного заполнения метода доставки необходимо отказаться от правки типовых модулей локализации и использовать механизм расширений. Основной упор следует сделать на правильное обращение к табличной части ДополнительныеРеквизиты и корректное получение ссылок на элементы плана видов характеристик. Помните, что использование НайтиПоНаименованию — не самый производительный метод, и в крупных системах ссылки на нужные свойства лучше хранить в константах или находить один раз при запуске системы.

← На главную