Как программно изменить счет учета в документе Передача материалов в эксплуатацию на основе дополнительных сведений

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

В процессе разработки в 1С:Бухгалтерия 3.0 часто возникает задача кастомизации типовых механизмов проведения документов. Одной из таких задач является изменение счетов учета (например, забалансовых счетов МЦ.04 на МЦ.05) в зависимости от определенных признаков номенклатуры. Рассмотрим подробнее, как реализовать проверку номенклатуры в источнике через запрос и корректно изменить данные с использованием механизма подписок на события.

Постановка задачи и выбор события

Представим ситуацию: в документе ПередачаМатериаловВЭксплуатацию необходимо проверить всю номенклатуру. Если у позиции номенклатуры в дополнительных сведениях установлен признак СчетМЦ05, то в проводках (или в самом документе) должен использоваться соответствующий счет.

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

  1. ОбработкаПроведения: позволяет изменять уже сформированные движения в регистре бухгалтерии.
  2. ПередЗаписью: позволяет изменить данные в самой табличной части документа до того, как начнут формироваться проводки. Для стажеров и начинающих разработчиков этот метод предпочтительнее, так как типовой механизм проведения сам подхватит измененные счета и сформирует корректные записи в регистре.

Разбор запроса к табличным частям документа

Документ ПередачаМатериаловВЭксплуатацию имеет специфическую структуру — в нем три основные табличные части: Спецодежда, Спецоснастка и ИнвентарьИХозяйственныеПринадлежности. Чтобы проверить всю номенклатуру, нам необходимо объединить данные из всех этих таблиц. Проанализируем, как составить эффективный запрос для этой цели.

Рассмотрим пример кода запроса, который собирает всю номенклатуру из документа и сразу проверяет наличие дополнительного реквизита:


ТекстЗапроса = 
"ВЫБРАТЬ
|	ТЧ.Номенклатура КАК Номенклатура
|ПОМЕСТИТЬ ВТ_НоменклатураДокумента
|ИЗ
|	(ВЫБРАТЬ
|		Спецодежда.Номенклатура КАК Номенклатура
|	ИЗ
|		Документ.ПередачаМатериаловВЭксплуатацию.Спецодежда КАК Спецодежда
|	ГДЕ
|		Спецодежда.Ссылка = &Ссылка
|
|	ОБЪЕДИНИТЬ ВСЕ
|
|	ВЫБРАТЬ
|		Спецоснастка.Номенклатура
|	ИЗ
|		Документ.ПередачаМатериаловВЭксплуатацию.Спецоснастка КАК Спецоснастка
|	ГДЕ
|		Спецоснастка.Ссылка = &Ссылка
|
|	ОБЪЕДИНИТЬ ВСЕ
|
|	ВЫБРАТЬ
|		Инвентарь.Номенклатура
|	ИЗ
|		Документ.ПередачаМатериаловВЭксплуатацию.ИнвентарьИХозяйственныеПринадлежности КАК Инвентарь
|	ГДЕ
|		Инвентарь.Ссылка = &Ссылка) КАК ТЧ
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ РАЗЛИЧНЫЕ
|	ВТ_НоменклатураДокумента.Номенклатура КАК Номенклатура
|ИЗ
|	ВТ_НоменклатураДокумента КАК ВТ_НоменклатураДокумента
|ГДЕ
|	ВТ_НоменклатураДокумента.Номенклатура.ДополнительныеРеквизиты.Значение = &ЗначениеИстина
|	И ВТ_НоменклатураДокумента.Номенклатура.ДополнительныеРеквизиты.Свойство.Наименование ПОДОБНО ""%СчетМЦ05%""";

В данном запросе мы используем конструкцию ОБЪЕДИНИТЬ ВСЕ для сбора данных из разных таблиц в одну временную таблицу ВТ_НоменклатураДокумента. После этого мы фильтруем результат, обращаясь к табличной части ДополнительныеРеквизиты объекта Номенклатура.

Важное различие: Дополнительные реквизиты vs Дополнительные сведения

Проанализируем ситуацию, если признак хранится не в реквизитах (внутри объекта), а в сведениях (в отдельном регистре). В 1С:БСП дополнительные сведения хранятся в регистре сведений ДополнительныеСведения. Если ваш признак "СчетМЦ05" — это именно сведение, запрос должен быть другим:


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|	ДополнительныеСведения.Объект КАК Номенклатура
|ИЗ
|	РегистрСведений.ДополнительныеСведения КАК ДополнительныеСведения
|ГДЕ
|	ДополнительныеСведения.Объект В (ВЫБРАТЬ Номенклатура ИЗ ВТ_НоменклатураДокумента)
|	И ДополнительныеСведения.Свойство = &Свойство
|	И ДополнительныеСведения.Значение = ИСТИНА";

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

Реализация в модуле: передача параметров

Выясним причину частой ошибки начинающих — "Не задано значение параметра Ссылка". При работе в подписке на событие, переменная Источник (которая является самим документом) должна быть передана в запрос. Если мы работаем в событии ПередЗаписью, объект еще может не иметь ссылки в базе (если это новое создание), поэтому важно проверять Источник.Ссылка или использовать Источник напрямую, если платформа позволяет неявное приведение.

Посмотрим на пример правильной инициализации параметров запроса в общем модуле:


Процедура ПриОбработкеПроведенияСчетМЦ(Источник, Отказ, РежимПроведения) Экспорт

    Запрос = Новый Запрос;
    Запрос.Текст = "...(текст запроса описанный выше)...";
    
    // Установка ссылки на документ из Источника
    Запрос.УстановитьПараметр("Ссылка", Источник.Ссылка);
    
    // Если используем проверку через Значение в ТЧ доп. реквизитов
    Запрос.УстановитьПараметр("ЗначениеИстина", Истина);
    
    РезультатЗапроса = Запрос.Выполнить();
    Если Не РезультатЗапроса.Пустой() Тогда
        // Здесь описываем логику замены счета
        Выборка = РезультатЗапроса.Выбрать();
        Пока Выборка.Следующий() Цикл
            // Обработка данных
        КонецЦикла;
    КонецЕсли;

КонецПроцедуры

Как изменить счет в движениях (проводках)

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


ТаблицаНужнойНоменклатуры = РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("Номенклатура");

Для Каждого Проводка Из Источник.Движения.Хозрасчетный Цикл
    // Проверяем, что в проводке участвует нужная номенклатура
    // Обычно номенклатура находится в Субконто1 или Субконто2 в зависимости от настройки счета
    Если ТаблицаНужнойНоменклатуры.Найти(Проводка.СубконтоДт[ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Номенклатура]) <> Неопределено Тогда
        
        // Если текущий счет забалансовый МЦ.04, меняем его на МЦ.05
        Если Проводка.СчетДт = ПланыСчетов.Хозрасчетный.ИнвентарьИХозяйственныеПринадлежностиВЭксплуатации Тогда // МЦ.04
             Проводка.СчетДт = ПланыСчетов.Хозрасчетный.НайтиПоКоду("МЦ.05");
        КонецЕсли;
        
    КонецЕсли;
КонецЦикла;

Рекомендации по оптимизации

Рассмотрим несколько советов, которые помогут сделать код более надежным:

  1. Использование функций БСП: если в конфигурации используется Библиотека Стандартных Подсистем (а в БП 3.0 это так), для получения доп. сведений лучше использовать функцию УправлениеСвойствами.ЗначениеСвойства(Объект, Свойство). Это избавит от необходимости писать сложные запросы к регистру.
  2. Типизация параметров: старайтесь не искать свойство по наименованию НайтиПоНаименованию("СчетМЦ05") прямо в коде. Правильнее вынести это свойство в настройки или хотя бы обернуть в проверку на ПустуюСсылку().
  3. Проверка режима записи: в подписках ПередЗаписью всегда проверяйте Источник.ОбменДанными.Загрузка. Если идет загрузка данных (например, через обмен), обработку логики лучше пропустить, чтобы не нарушать целостность данных.

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

← На главную