Как составить прямой SQL-запрос к бухгалтерским итогам и проводкам в 1С 7.7 через 1С++?

Программист 1С v7.7 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При оптимизации быстродействия отчетов и алгоритмов проведения в 1С:Предприятии 7.7 разработчики часто прибегают к прямому чтению базы данных с помощью внешней компоненты 1С++. Однако при попытке составить прямой запрос к бухгалтерской подсистеме многие сталкиваются с трудностями: в платформе 1С 7.7 нет понятия «Регистр бухгалтерии», появившегося только в восьмой версии, а структура хранения бухгалтерских данных значительно отличается от оперативного учета. Разберем детально, как устроена бухгалтерская база в 7.7 и как правильно строить прямые запросы к проводкам и сальдо.

Особенности архитектуры бухгалтерского контура 1С 7.7

Для корректного составления SQL-запросов проанализируем, где и как 1С 7.7 сохраняет бухгалтерские операции:

  1. Разделение операций и проводок: заголовочные данные хранятся отдельно от самих проводок. Таблица операций связывает проводку с документом-регистратором или ручной операцией, а таблица проводок фиксирует сам факт движения (дебет, кредит, сумма, количество, валюта).
  2. Таблицы итогов: чтобы не пересчитывать баланс с момента создания базы, платформа рассчитывает и сохраняет агрегированные данные помесячно в отдельных таблицах итогов (отдельно по счетам и отдельно по счетам с субконто).
  3. Полиморфный тип субконто: аналитика в таблицах итогов и проводок имеет составной тип данных. Значение субконто хранится в виде строки, содержащей префикс типа метаданных и идентификатор самого объекта, поэтому для соединения со справочниками требуется либо отсечение префикса, либо использование встроенного макропарсера метаданных 1С++.
  4. Забалансовые счета: учет на забалансовых счетах ведется без принципа двойной записи, поэтому в проводке может присутствовать только счет дебета либо только счет кредита.

Подходы к чтению данных: классы и прямые SQL-запросы

Рассмотрим два основных пути выборки данных бухгалтерского учета через 1С++:

  1. Использование специализированных классов: в сообществе разработчиков 1С++ классическим стандартом для работы с проводками и итогами является класс AccountRecordSet (авторство И. Берездецкого). Данный класс инкапсулирует в себе сложные алгоритмы парсинга полиморфных полей и механизм расчета остатков на контрольные даты, освобождая разработчика от ручного написания многостраничных SQL-запросов.
  2. Формирование прямых SQL-запросов вручную: прямое обращение через объект ODBCRecordSet к таблицам проводок и итогов. Этот подход дает максимальный контроль над производительностью, но требует глубокого понимания логики расчета сальдо.

Алгоритм расчета оборотов и остатков через прямой запрос

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

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

Важные ограничения при работе напрямую с базой

Выясним причины возможных расхождений прямых запросов со штатными отчетами 1С:

  1. Развернутое сальдо на активно-пассивных счетах: если просто сложить дебет и кредит по всему счету, получится «свернутое» сальдо, что грубо искажает учетную картину. Корректное сальдо для активно-пассивных счетов требует обязательной группировки по всем уровням субконто счета и вычисления знака остатка для каждого элемента аналитики отдельно.
  2. Точка актуальности итогов: таблицы итогов содержат корректные цифры только в том случае, если расчет бухгалтерских итогов в базе актуален. Если границы итогов не сдвинуты регламентно, запрос к итогам вернет устаревшие данные.
  3. Сложность учета по позиции: если требуется остаток строго на момент проведения документа внутри дня, выборку проводок необходимо фильтровать не просто по дате, а по составному полю позиции документа (дата, время и идентификатор документа в журнале).

Посмотрим на пример базовой структуры обращения к базе через 1С++ при использовании макроподстановок метаданных:


Запрос = СоздатьОбъект("ODBCRecordSet");
ТекстЗапроса = "
|SELECT 
|    ЖРН.DATE_TIME_IDDOC,
|    ПРВ.Debet,
|    ПРВ.Kredit,
|    ПРВ.Sum
|FROM 
|    $Операция AS ОПЕР
|INNER JOIN 
|    $Проводки AS ПРВ ON ПРВ.DOCID = ОПЕР.DOCID
|INNER JOIN 
|    _1SJOURN AS ЖРН ON ЖРН.IDDOC = ОПЕР.DOCID
|WHERE 
|    ЖРН.DATE_TIME_IDDOC >= :НачДата AND ЖРН.DATE_TIME_IDDOC <= :КонДата
|";
Запрос.УстановитьТекстовыйПараметр("НачДата", ПозицияНачалаПериода);
Запрос.УстановитьТекстовыйПараметр("КонДата", ПозицияКонцаПериода);
ТЗ = Запрос.ВыполнитьИнструкцию(ТекстЗапроса);

Если задача требует получения сложных разрезов с развернутыми сальдо по субконто и валютам, а опыт написания сложных SQL-агрегаций ограничен, рекомендуется использовать проверенный класс AccountRecordSet или стандартный платформенный объект БухгалтерскиеИтоги, который автоматически учитывает все нюансы активно-пассивных и забалансовых счетов.

← На главную