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

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

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

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

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

Основные ошибки, которые допускают разработчики при решении этой задачи:

  1. Некорректное обращение к дополнительным реквизитам в запросе: Попытка обратиться через точку к табличной части (Номенклатура.ДополнительныеРеквизиты.Значение) в условии запроса приведет к ошибке или пустому результату, так как это коллекция данных.
  2. Неправильный поиск счета: Использование метода НайтиПоНаименованию является крайне ненадежным, так как наименование счета может измениться пользователем или отличаться в разных версиях конфигурации.
  3. Принудительная запись движений: Вызов метода Источник.Движения.Хозрасчетный.Записать() внутри подписки на событие ОбработкаПроведения может привести к конфликтам блокировок или затиранию данных стандартными механизмами конфигурации.

Шаг 1. Разработка корректного запроса к дополнительным реквизитам

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

Проанализируем следующий текст запроса:


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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ.Номенклатура
ИЗ
    ВТ_НоменклатураДокумента КАК ВТ
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты
    ПО ВТ.Номенклатура = ДопРеквизиты.Ссылка
ГДЕ
    ДопРеквизиты.Свойство.Заголовок = &ИмяРеквизита
    И ДопРеквизиты.Значение = ИСТИНА

В данном запросе мы сначала собираем всю уникальную номенклатуру из документа во временную таблицу, а затем соединяем ее с таблицей дополнительных реквизитов. Обратите внимание, что фильтрацию лучше делать по Свойство.Заголовок или по ссылке на сам объект свойства из плана видов характеристик.

Шаг 2. Работа с Планом счетов

Для определения счета учета МЦ.05 следует использовать либо поиск по коду, либо обращение к предопределенным значениям, если они существуют. В 1С:Бухгалтерии счет МЦ.05 часто не является предопределенным в метаданных, но имеет фиксированный код.

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


СчетМЦ05 = ПланыСчетов.Хозрасчетный.НайтиПоКоду("МЦ.05");
Если СчетМЦ05.Пустая() Тогда
    // Обработка исключения, если счет не найден в базе
    Возврат;
КонецЕсли;

Шаг 3. Корректировка движений в подписке на событие

Теперь перейдем к реализации самой процедуры в общем модуле. Подписка должна быть назначена на событие ОбработкаПроведения документа ПередачаМатериаловВЭксплуатацию. Важный нюанс: в БП 3.0 движения могут формироваться в фоновом режиме или перетираться после выполнения кода подписки, если не соблюдать правила работы с коллекцией Движения.

Посмотрим на пример правильной реализации логики:


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

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

Важные замечания по механизму проведения

Проанализируем ситуацию с записью движений. В современных конфигурациях 1С крайне нежелательно вызывать Движения.Записать() вручную внутри транзакции проведения. Вместо этого мы устанавливаем свойство Записывать = Истина. Это гарантирует, что система запишет наши изменения в самом конце процесса проведения, когда все стандартные алгоритмы уже отработали.

Также стоит учитывать, что в БП 3.0 существует штатный механизм настройки счетов учета — регистр сведений СчетаУчетаНоменклатуры. Прежде чем писать программный код, убедитесь, что задачу нельзя решить стандартными средствами, просто добавив запись в этот регистр для нужных позиций номенклатуры. Это позволит избежать лишних доработок и сохранит типовую логику системы.

Если же бизнес-логика требует именно динамического определения счета через дополнительные реквизиты, используйте предложенный выше метод с тщательной проверкой типов субконто и установкой флага записи коллекции движений.

← На главную