Как реализовать автоматическое добавление связанной номенклатуры с расчетом количества по коэффициенту в 1С:Бухгалтерия 3.0

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

В практике автоматизации на платформе 1С часто возникает задача, когда при выборе определенного товара в документе необходимо автоматически добавить сопутствующую услугу или материал. Типичный пример: при продаже товара "А" в количестве N единиц, должна автоматически добавиться услуга "Б", количество которой рассчитывается как N * 1.3. Рассмотрим, как реализовать такую логику в конфигурации 1С:Бухгалтерия предприятия 3.0, сохранив при этом возможность легкого обновления программы.

Шаг 1. Организация хранения настроек (Связи и Коэффициенты)

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

Разберем, как это настроить:

  1. Перейдем в раздел Администрирование – Общие настройки – Дополнительные реквизиты и сведения.
  2. В списке Дополнительные сведения найдем объект Номенклатура.
  3. Добавим два новых сведения:
    • СвязаннаяНоменклатура (тип значения: СправочникСсылка.Номенклатура).
    • КоэффициентДляРасчета (тип значения: Число, точность 3 знака).

Теперь в карточке номенклатуры "А" на вкладке "Дополнительные сведения" мы сможем указать, что для нее связана номенклатура "Б" и задать коэффициент (например, 1.3). Это позволит гибко настраивать зависимости без изменения программного кода при добавлении новых пар товаров.

Шаг 2. Использование расширения для реализации логики

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

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

Шаг 3. Написание программного кода в расширении

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


&НаКлиенте
Процедура Расш1_ТоварыНоменклатураПриИзмененииПосле(Элемент)
    
    ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
    Если ТекущаяСтрока = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Получаем связанные данные с сервера
    ДанныеСвязи = ПолучитьДанныеСвязаннойНоменклатуры(ТекущаяСтрока.Номенклатура);
    
    Если ДанныеСвязи.Найдено Тогда
        // Проверяем, нет ли уже этой номенклатуры в табличной части, чтобы избежать дублей
        ПараметрыПоиска = Новый Структура("Номенклатура", ДанныеСвязи.НоменклатураБ);
        НайденныеСтроки = Объект.Товары.НайтиСтроки(ПараметрыПоиска);
        
        Если НайденныеСтроки.Количество() = 0 Тогда
            НоваяСтрока = Объект.Товары.Добавить();
            НоваяСтрока.Номенклатура = ДанныеСвязи.НоменклатураБ;
            НоваяСтрока.Количество = ТекущаяСтрока.Количество * ДанныеСвязи.Коэффициент;
            
            // Вызываем типовые механизмы пересчета цен и сумм
            ОбработатьИзменениеНоменклатурыНаСервере(НоваяСтрока.НомерСтроки);
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

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


&НаСервереБезКонтекста
Функция ПолучитьДанныеСвязаннойНоменклатуры(НоменклатураА)
    
    Результат = Новый Структура("Найдено, НоменклатураБ, Коэффициент", Ложь, Неопределено, 0);
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	ДополнительныеСведения.Значение КАК Значение,
        |	ДополнительныеСведения.Свойство КАК Свойство
        |ИЗ
        |	РегистрСведений.ДополнительныеСведения КАК ДополнительныеСведения
        |ГДЕ
        |	ДополнительныеСведения.Объект = &НоменклатураА
        |	И (ДополнительныеСведения.Свойство.Наименование = ""СвязаннаяНоменклатура""
        |		ИЛИ ДополнительныеСведения.Свойство.Наименование = ""КоэффициентДляРасчета"")";
    
    Запрос.УстановитьПараметр("НоменклатураА", НоменклатураА);
    Выборка = Запрос.Выполнить().Выбрать();
    
    Пока Выборка.Следующий() Цикл
        Если Выборка.Свойство.Наименование = "СвязаннаяНоменклатура" Тогда
            Результат.НоменклатураБ = Выборка.Значение;
            Результат.Найдено = Истина;
        ИначеЕсли Выборка.Свойство.Наименование = "КоэффициентДляРасчета" Тогда
            Результат.Коэффициент = Выборка.Значение;
        КонецЕсли;
    КонецЦикла;
    
    Возврат Результат;
    
КонецФункции

Шаг 4. Контроль зацикливания и синхронизация

Важный момент, который мы должны проанализировать — это зацикливание. Если для номенклатуры "А" задана связь с "Б", а для "Б" случайно установлена обратная связь с "А", система может начать бесконечно добавлять строки, пока документ не "взорвется" или программа не зависнет.

Для предотвращения этой ситуации мы применили проверку Объект.Товары.НайтиСтроки(). Если номенклатура "Б" уже присутствует в табличной части, повторное добавление не производится. Также стоит рассмотреть ситуацию, когда пользователь меняет количество у основного товара "А" спустя время. В этом случае количество в строке "Б" само не изменится. Чтобы решить эту проблему, необходимо добавить код в событие КоличествоПриИзменении, который будет находить связанную строку и обновлять ее значение.

Шаг 5. Особенности округления и точности

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

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

← На главную