При адаптации типовой конфигурации «Управление торговлей 10.3» под нужды бизнеса часто возникает задача: добавить в табличную часть документа (например, РеализацияТоваровУслуг) новое поле и сделать так, чтобы его значение записывалось в регистр накопления при проведении. На первый взгляд задача кажется простой, но новички часто сталкиваются с тем, что данные либо не записываются, либо создают лишние строки в регистре, либо «затирают» друг друга.
В этой статье мы подробно разберем, почему стандартные подходы через НаборЗаписей могут не работать, и как правильно внедрить свой код в типовой механизм проведения УТ 10.3.
Рассмотрим ситуацию: вы добавили колонку Бонус_Добавленно в табличную часть Товары и аналогичный реквизит в регистр накопления Продажи. Попытка записать данные через прямое обращение к набору записей в подписке на событие или в конце процедуры ОбработкаПроведения часто выглядит так:
Для каждого Запись из НаборЗаписей Цикл
Запись.Бонус_Добавленно = Объект.Товары[НомерСтроки].Бонус_Добавленно;
КонецЦикла;
Выясним причину, почему это плохой подход:
Продажи может появиться всего одна строка с суммарным количеством. Прямой индекс [НомерСтроки] приведет к ошибке или записи неверных данных.Движения.Продажи (как в Коде №1 из вопроса), система создаст дополнительную строку, не связанную с основной продажей товара. Это исказит отчеты: в одной строке будет количество и выручка, а в другой — только ваш бонус.В конфигурации УТ 10.3 движения формируются не «в лоб», а через подготовку специальных временных таблиц. Проанализируем путь данных. Основная логика сосредоточена в процедуре ДвиженияПоРегистрамУпр. Чтобы ваша колонка попала в регистр автоматически, нужно изменить место формирования исходной таблицы.
Рассмотрим по шагам, как это сделать:
Шаг 1. Поиск запроса подготовки данных. В модуле документа РеализацияТоваровУслуг найдите функцию или процедуру, которая собирает данные из табличных частей. Обычно это процедура ПодготовитьТаблицуТоваров (или аналогичная внутри ДвиженияПоРегистрамУпр). В ней текст запроса собирает поля: Номенклатура, Количество, Сумма и так далее.
Шаг 2. Модификация запроса. Нам нужно добавить нашу колонку Бонус_Добавленно в текст запроса. Найдите место, где описываются поля выбора:
| ТЧТовары.Номенклатура КАК Номенклатура,
| ТЧТовары.Количество КАК Количество,
| ТЧТовары.Бонус_Добавленно КАК Бонус_Добавленно, // Добавляем наше поле
Шаг 3. Группировка данных. Поскольку движения могут сворачиваться, определите, как должен вести себя бонус. Если это числовой ресурс (сумма бонуса), его нужно добавить в секцию СУММА:
|СУММА(Бонус_Добавленно) КАК Бонус_Добавленно
Если же бонус — это признак (например, категория), его нужно добавить в СГРУППИРОВАТЬ ПО.
Шаг 4. Автоматическая запись. В УТ 10.3 используется механизм, при котором, если имя колонки в подготовленной таблице совпадает с именем ресурса/реквизита в регистре, система сама переносит данные. Вам даже не придется писать Запись.Бонус = Строка.Бонус.
Если вы все же решили использовать подписку на событие ОбработкаПроведения (чтобы не менять типовой модуль документа), разберем, как сделать это правильно, избегая «г@внокода».
Проблема автора в Сообщении №11 заключалась в двойном цикле, который просто затирал значения. Проанализируем правильный алгоритм сопоставления:
Источник.Движения.Продажи.Записывать = Истина.Номенклатура, Склад, Характеристика).Пример правильной логики в подписке:
Процедура ОбработкаПроведения_Подписка(Источник, Отказ, РежимПроведения) Экспорт
// Движения уже сформированы стандартным кодом документа
ТаблицаТоваров = Источник.Товары.Выгрузить();
// Индексируем таблицу для быстрого поиска
ТаблицаТоваров.Индексы.Добавить("Номенклатура");
Для Каждого Движение Из Источник.Движения.Продажи Цикл
// Ищем соответствующую строку в документе
// Внимание: если строки сворачивались, логика поиска должна быть сложнее (через запрос)
ПараметрыОтбора = Новый Структура("Номенклатура", Движение.Номенклатура);
НайденныеСтроки = ТаблицаТоваров.НайтиСтроки(ПараметрыОтбора);
Если НайденныеСтроки.Количество() > 0 Тогда
// Если строк несколько (была группировка), решаем, как распределить бонус
// В простом случае берем из первой найденной строки
Движение.Бонус_Добавленно = НайденныеСтроки[0].Бонус_Добавленно;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Рассмотрим вопросы из Сообщения №20: как рассчитывается Стоимость и СтоимостьБезСкидки?
В типовых конфигурациях эти суммы рассчитываются в общих модулях (например, ЗаполнениеУправленческогоУчета). Система учитывает:
Совет: никогда не пытайтесь пересчитать эти суммы вручную в своем коде. Если вам нужно получить уже рассчитанную стоимость для вашего бонуса, используйте данные из таблицы ТаблицаПоТоварам, которая передается в процедуру ДвиженияПоРегистрамУпр. Там все числа уже «чистые» и финальные.
Если вы видите, что Запись.Бонус_Добавленно «не принимает значение» (как писал автор в Сообщении №13), проверьте следующие моменты:
Число 15, 2) с типом в регистре?НаборомЗаписей вне документа, не забывайте метод НаборЗаписей.Записать(). Но лучше работать внутри проведения с коллекцией Движения.ЗначениеБонуса действительно содержит число, а не Неопределено (что бывает, если строка в ТЧ не найдена).Подведем итог: самый правильный и «чистый» путь для 1С v8.3 на обычных формах (УТ 10.3) — это интеграция в запрос функции ПодготовитьТаблицуТоваров. Это обеспечит целостность данных, правильную группировку строк и высокую скорость работы системы.