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