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