В процессе разработки в 1С:Бухгалтерия 3.0 часто возникает задача кастомизации типовых механизмов проведения документов. Одной из таких задач является изменение счетов учета (например, забалансовых счетов МЦ.04 на МЦ.05) в зависимости от определенных признаков номенклатуры. Рассмотрим подробнее, как реализовать проверку номенклатуры в источнике через запрос и корректно изменить данные с использованием механизма подписок на события.
Представим ситуацию: в документе ПередачаМатериаловВЭксплуатацию необходимо проверить всю номенклатуру. Если у позиции номенклатуры в дополнительных сведениях установлен признак СчетМЦ05, то в проводках (или в самом документе) должен использоваться соответствующий счет.
Для реализации такой логики лучше всего подходит Подписка на событие. Однако важно определиться с самим событием:
Документ ПередачаМатериаловВЭксплуатацию имеет специфическую структуру — в нем три основные табличные части: Спецодежда, Спецоснастка и ИнвентарьИХозяйственныеПринадлежности. Чтобы проверить всю номенклатуру, нам необходимо объединить данные из всех этих таблиц. Проанализируем, как составить эффективный запрос для этой цели.
Рассмотрим пример кода запроса, который собирает всю номенклатуру из документа и сразу проверяет наличие дополнительного реквизита:
ТекстЗапроса =
"ВЫБРАТЬ
| ТЧ.Номенклатура КАК Номенклатура
|ПОМЕСТИТЬ ВТ_НоменклатураДокумента
|ИЗ
| (ВЫБРАТЬ
| Спецодежда.Номенклатура КАК Номенклатура
| ИЗ
| Документ.ПередачаМатериаловВЭксплуатацию.Спецодежда КАК Спецодежда
| ГДЕ
| Спецодежда.Ссылка = &Ссылка
|
| ОБЪЕДИНИТЬ ВСЕ
|
| ВЫБРАТЬ
| Спецоснастка.Номенклатура
| ИЗ
| Документ.ПередачаМатериаловВЭксплуатацию.Спецоснастка КАК Спецоснастка
| ГДЕ
| Спецоснастка.Ссылка = &Ссылка
|
| ОБЪЕДИНИТЬ ВСЕ
|
| ВЫБРАТЬ
| Инвентарь.Номенклатура
| ИЗ
| Документ.ПередачаМатериаловВЭксплуатацию.ИнвентарьИХозяйственныеПринадлежности КАК Инвентарь
| ГДЕ
| Инвентарь.Ссылка = &Ссылка) КАК ТЧ
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ РАЗЛИЧНЫЕ
| ВТ_НоменклатураДокумента.Номенклатура КАК Номенклатура
|ИЗ
| ВТ_НоменклатураДокумента КАК ВТ_НоменклатураДокумента
|ГДЕ
| ВТ_НоменклатураДокумента.Номенклатура.ДополнительныеРеквизиты.Значение = &ЗначениеИстина
| И ВТ_НоменклатураДокумента.Номенклатура.ДополнительныеРеквизиты.Свойство.Наименование ПОДОБНО ""%СчетМЦ05%""";
В данном запросе мы используем конструкцию ОБЪЕДИНИТЬ ВСЕ для сбора данных из разных таблиц в одну временную таблицу ВТ_НоменклатураДокумента. После этого мы фильтруем результат, обращаясь к табличной части ДополнительныеРеквизиты объекта Номенклатура.
Проанализируем ситуацию, если признак хранится не в реквизитах (внутри объекта), а в сведениях (в отдельном регистре). В 1С:БСП дополнительные сведения хранятся в регистре сведений ДополнительныеСведения. Если ваш признак "СчетМЦ05" — это именно сведение, запрос должен быть другим:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДополнительныеСведения.Объект КАК Номенклатура
|ИЗ
| РегистрСведений.ДополнительныеСведения КАК ДополнительныеСведения
|ГДЕ
| ДополнительныеСведения.Объект В (ВЫБРАТЬ Номенклатура ИЗ ВТ_НоменклатураДокумента)
| И ДополнительныеСведения.Свойство = &Свойство
| И ДополнительныеСведения.Значение = ИСТИНА";
Запрос.УстановитьПараметр("Свойство", ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("СчетМЦ05"));
Выясним причину частой ошибки начинающих — "Не задано значение параметра Ссылка". При работе в подписке на событие, переменная Источник (которая является самим документом) должна быть передана в запрос. Если мы работаем в событии ПередЗаписью, объект еще может не иметь ссылки в базе (если это новое создание), поэтому важно проверять Источник.Ссылка или использовать Источник напрямую, если платформа позволяет неявное приведение.
Посмотрим на пример правильной инициализации параметров запроса в общем модуле:
Процедура ПриОбработкеПроведенияСчетМЦ(Источник, Отказ, РежимПроведения) Экспорт
Запрос = Новый Запрос;
Запрос.Текст = "...(текст запроса описанный выше)...";
// Установка ссылки на документ из Источника
Запрос.УстановитьПараметр("Ссылка", Источник.Ссылка);
// Если используем проверку через Значение в ТЧ доп. реквизитов
Запрос.УстановитьПараметр("ЗначениеИстина", Истина);
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
// Здесь описываем логику замены счета
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Обработка данных
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Если мы решили работать в событии ОбработкаПроведения, нам нужно перебрать движения по регистру бухгалтерии Хозрасчетный. Проанализируем этот процесс: после того как типовой механизм сформировал движения, мы "вклиниваемся" и подменяем счета в коллекции Движения.
ТаблицаНужнойНоменклатуры = РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("Номенклатура");
Для Каждого Проводка Из Источник.Движения.Хозрасчетный Цикл
// Проверяем, что в проводке участвует нужная номенклатура
// Обычно номенклатура находится в Субконто1 или Субконто2 в зависимости от настройки счета
Если ТаблицаНужнойНоменклатуры.Найти(Проводка.СубконтоДт[ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Номенклатура]) <> Неопределено Тогда
// Если текущий счет забалансовый МЦ.04, меняем его на МЦ.05
Если Проводка.СчетДт = ПланыСчетов.Хозрасчетный.ИнвентарьИХозяйственныеПринадлежностиВЭксплуатации Тогда // МЦ.04
Проводка.СчетДт = ПланыСчетов.Хозрасчетный.НайтиПоКоду("МЦ.05");
КонецЕсли;
КонецЕсли;
КонецЦикла;
Рассмотрим несколько советов, которые помогут сделать код более надежным:
УправлениеСвойствами.ЗначениеСвойства(Объект, Свойство). Это избавит от необходимости писать сложные запросы к регистру.НайтиПоНаименованию("СчетМЦ05") прямо в коде. Правильнее вынести это свойство в настройки или хотя бы обернуть в проверку на ПустуюСсылку().ПередЗаписью всегда проверяйте Источник.ОбменДанными.Загрузка. Если идет загрузка данных (например, через обмен), обработку логики лучше пропустить, чтобы не нарушать целостность данных.Таким образом, комбинируя правильный запрос к табличным частям и понимание того, где хранятся свойства номенклатуры (в реквизитах или сведениях), можно гибко управлять учетной политикой документа без изменения типовой конфигурации.