Что такое объект "Операция" в 1С 7.7 и как он соотносится с запросами по регистру бухгалтерии в 1С 8?

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

Переход разработчиков с платформы 1С:Предприятие 8 на «семерку» (или наоборот) часто вызывает вопросы из-за кардинальных различий в архитектуре метаданных. Одним из таких камней преткновения является механизм работы с бухгалтерскими итогами. В этой статье мы подробно разберем, как устроен обход проводок в 1С 7.7, выясним назначение объекта Операция и проведем детальную аналогию с запросами к физическим таблицам регистров бухгалтерии в 1С 8.

Анализ исходного кода на 1С 7.7

Рассмотрим фрагмент кода, который вызвал вопросы у разработчика, привыкшего к механизмам «восьмерки»:


Ит.ВыполнитьЗапрос(ВыбНачПериода, ВыбКонПериода, ВыбСчет,,, 1, "Проводка", "С");    
Ит.ВыбратьПериоды();
Пока Ит.ПолучитьПериод() = 1 Цикл
     Опер = Ит.Операция; 
КонецЦикла;

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

Обратим особое внимание на параметры метода:

  1. "Проводка" (седьмой параметр) — указывает платформе уровень периодичности выборки. В данном случае мы требуем детализацию до самой мелкой составляющей бухгалтерского учета — конкретной проводки. Без этого параметра метод ПолучитьПериод() не позволил бы нам спозиционироваться на детальных движениях.
  2. "С" (восьмой параметр) — определяет тип рассчитываемой суммы. Символ «С» (в русской раскладке) означает расчет рублевой суммы (суммы учета). Альтернативно здесь могли быть указаны параметры «В» (валютная сумма) или «К» (количество).

После выполнения запроса мы открываем выборку периодов с помощью Ит.ВыбратьПериоды(). Цикл Пока Ит.ПолучитьПериод() = 1 последовательно обходит каждую проводку, попавшую в условия фильтрации. На каждом шаге цикла свойство Ит.Операция возвращает специальный системный объект — Операция.

Что представляет собой объект "Операция" в 1С 7.7?

В платформе 1С 7.7 проводки не могут существовать обособленно. Каждая проводка жестко подчинена объекту типа Операция. В свою очередь, операция всегда неразрывно связана с конкретным документом-регистратором (или создается вручную через специализированный интерфейс ручных операций, который под капотом также генерирует документ «Операция»).

Проанализируем структуру хранения данных в SQL-версии 1С 7.7. Операции хранятся в физической таблице 1SOPER, а сами проводки — в таблице 1SENTRY. Связь между ними осуществляется по уникальным внутренним идентификаторам.

Когда мы пишем:


Опер = Ит.Операция;

мы получаем доступ к контексту операции, которая породила текущую проводку в цикле. Через этот объект мы можем обратиться к реквизитам самой операции, а также к аналитике конкретной проводки:

Важная особенность: Метод ТекущийДокумент()

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


РеальныйДокумент = Опер.Документ.ТекущийДокумент();

Выясним причину, почему нельзя написать просто Опер.Документ. Дело в том, что свойство Опер.Документ возвращает обобщенный объект типа «Документ». Из-за архитектурных ограничений типизации «семерки» у этого обобщенного объекта нет доступа к специфическим реквизитам конкретного вида документа (например, к реквизитам «Склад» или «Контрагент» документа «РасходнаяНакладная»).

Метод ТекущийДокумент() выполняет приведение типов. Он определяет реальный вид документа-регистратора и возвращает ссылку на конкретный объект метаданных, позволяя программисту без ограничений считывать любые его реквизиты и табличные части.

Сравнение с механизмами 1С 8

Отвечая на вопрос автора темы: да, этот код концептуально решает ту же задачу, что и прямой запрос к физической таблице регистра бухгалтерии в 1С 8 без использования виртуальных таблиц оборотов и остатков.

В платформе 1С 8 архитекторы отказались от сущности Операция. Записи регистра бухгалтерии (движения) подчинены напрямую документу-регистратору через стандартный реквизит Регистратор. Ручные операции в «восьмерке» — это обычные документы конфигурации (например, документ «ОперацияБух»), которые делают записи в регистр напрямую.

Посмотрим на пример аналогичного запроса в 1С 8. Если бы нам потребовалось получить список проводок с их реквизитами напрямую, мы бы обратились к физической таблице движений РегистрБухгалтерии.Хозрасчетный:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Хозрасчетный.Регистратор КАК Документ,
    |	Хозрасчетный.СчетДт КАК СчетДт,
    |	Хозрасчетный.СчетКт КАК СчетКт,
    |	Хозрасчетный.Сумма КАК Сумма
    |ИЗ
    |	РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
    |ГДЕ
    |	Хозрасчетный.Период МЕЖДУ &НачПериода И &КонПериода
    |	И (Хозрасчетный.СчетДт = &ВыбСчет ИЛИ Хозрасчетный.СчетКт = &ВыбСчет)";

Запрос.УстановитьПараметр("НачПериода", ВыбНачПериода);
Запрос.УстановитьПараметр("КонПериода", ВыбКонПериода);
Запрос.УстановитьПараметр("ВыбСчет", ВыбСчет);

Результат = Запрос.Выполнить();

Этот запрос в 1С 8 выполняет абсолютно то же самое действие, что и метод ВыполнитьЗапрос(..., "Проводка") в 1С 7.7. Мы получаем сырые, неагрегированные данные по проводкам за указанный период, отфильтрованные по конкретному счету.

Проблема производительности в 1С 7.7

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

Именно поэтому опытные разработчики в «семерке» при необходимости обойти миллионы проводок часто отказывались от штатных БухгалтерскихИтогов и писали «прямые запросы» к SQL-таблицам 1SENTRY и 1SOPER с помощью внешних компонент (таких как 1С++ или через интерфейс ADO). В 1С 8 благодаря декларативному языку запросов и СУБД-ориентированной архитектуре эта проблема больше не стоит так остро, поскольку СУБД самостоятельно строит оптимальный план выполнения запроса к регистру.

← На главную