В процессе разработки и сопровождения конфигураций на платформе «1С:Предприятие 8» программисты иногда сталкиваются с крайне специфической проблемой: в проводках регистра бухгалтерии субконто заполнены и отображаются корректно, однако при формировании отчетов (например, «Оборотно-сальдовая ведомость») или при выполнении запросов к виртуальным таблицам остатков и оборотов аналитика по субконто полностью отсутствует. Данные выводятся пустой строкой, либо вообще не попадают в выборку.
В этой статье мы подробно разберем, почему возникает данная коллизия на уровне СУБД, проанализируем внутреннее устройство таблиц регистра бухгалтерии и предложим три практических способа решения этой проблемы: от простого обходного пути до исправления структуры данных на уровне SQL-сервера.
Чтобы понять суть проблемы, нам необходимо заглянуть под «капот» платформы 1С и СУБД. В регистрах бухгалтерии данные о движениях и итогах хранятся в нескольких физических таблицах СУБД. Основными из них являются:
_AccRgED): хранит конкретные значения аналитики для каждой проводки. Именно здесь записываются ссылки на физические лица, контрагентов, номенклатуру и т.д._AccRgAT, _AccRgCT): оптимизированные таблицы, в которых платформа хранит рассчитанные остатки и обороты в разрезе периодов, счетов и субконто для быстрого построения отчетов.Когда мы обращаемся к виртуальной таблице РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты, платформа выполняет сложный SQL-запрос со множественными левыми соединениями (LEFT JOIN) между таблицей итогов, таблицей настроек субконто счета и справочниками метаданных.
Если субконто на счете было создано некорректно (например, при программном переносе данных с отключенным контролем, динамическом обновлении конфигурации или сбое реструктуризации СУБД), в таблице значений субконто _AccRgED вместо пустой ссылки правильного типа (например, СправочникСсылка.ФизическиеЛица) может записаться системное значение Неопределено или NULL.
В итоге получается следующая картина:
NULL или Неопределено на уровне SQL) с типом, описанным в метаданных счета. Из-за этого левое соединение возвращает пустой результат, и в отчетах мы видим пустоту.Рассмотрим детально способы решения этой проблемы.
Если база данных работает в файловом режиме или у вас нет прямого доступа к СУБД SQL, самым быстрым и безопасным решением будет пересоздание счета. Рассмотрим этот процесс по шагам:
76.аналог), у которого вручную и безпешибочно зададим те же самые виды субконто (например, первое субконто — «Физические лица»).Если база данных развернута на сервере под управлением MS SQL Server или PostgreSQL, мы можем решить проблему на уровне базы данных, не прибегая к долгому процессу замены ссылок в документах (что особенно критично для крупных баз данных объемом в сотни гигабайт). Нам понадобится временно очистить таблицы итогов регистра бухгалтерии и инициировать их пересчет платформой с нуля.
Критически важно: Перед выполнением любых операций в SQL-консоли обязательно сделайте резервную копию (бэкап) базы данных!
Выполним следующие действия:
_AccRgAT (итоги по счетам с субконто) и _AccRgCT (итоги между счетами).
-- Очищаем таблицы итогов по счетам
TRUNCATE TABLE _AccRgAT024070; -- Итоги по счетам без субконто
TRUNCATE TABLE _AccRgAT124080; -- Итоги по счетам с Субконто 1
TRUNCATE TABLE _AccRgAT224081; -- Итоги по счетам с Субконто 2
-- Очищаем таблицы оборотов между счетами
TRUNCATE TABLE _AccRgCT24083;
После того как таблицы итогов очищены (физические записи проводок при этом не затрагиваются, они хранятся в основной таблице движений), необходимо запустить пересчет итогов средствами платформы «1С:Предприятие»:
Платформа заново считает все проводки из основной таблицы движений, правильно сопоставит типы данных и заполнит таблицы итогов корректными значениями. После этого субконто в отчетах начнут отображаться.
Если мы создаем проводки программно, необходимо внимательно следить за тем, как именно заполняется субконто. Типичной ошибкой является попытка записать значение в субконто без предварительной жесткой проверки доступных типов на данном счете.
Проанализируем пример безопасного заполнения субконто программным путем. Мы должны сначала убедиться, что тип передаваемого значения входит в массив допустимых типов для конкретного вида субконто этого счета:
// Проверяем, соответствует ли тип значения субконто настройкам счета
Если НоваяПроводка.СчетДт.ВидыСубконто.Количество() > 0 Тогда
ВидСубконтоПервый = НоваяПроводка.СчетДт.ВидыСубконто[0].ВидСубконто;
// Проверяем доступность типа значения (например, ФизическоеЛицо)
Если ВидСубконтоПервый.ТипЗначения.СодержитТип(ТипЗнч(СтрокаДанных.Сотрудник.Физлицо)) Тогда
// Заполняем субконто строго с указанием его вида в качестве ключа
НоваяПроводка.СубконтоДт.Вставить(ВидСубконтоПервый, СтрокаДанных.Сотрудник.Физлицо);
Иначе
// Если тип не совпадает, записываем пустую ссылку правильного типа, а не Неопределено
ПустаяСсылкаТипа = Новый(ВидСубконтоПервый.ТипЗначения.Типы()[0]);
НоваяПроводка.СубконтоДт.Вставить(ВидСубконтоПервый, ПустаяСсылкаТипа);
КонецЕсли;
КонецЕсли;
Если вы столкнулись с ситуацией, когда данные уже записаны неверно, можно написать небольшую внешнюю обработку, которая обойдет движения регистра бухгалтерии по нужному счету, определит тип субконто и перезапишет некорректные значения (значения с типом Неопределено) на пустые ссылки нужного типа метаданных. После выполнения такой обработки и перепроведения документов виртуальные таблицы итогов начнут функционировать в штатном режиме.