При работе с регистрами бухгалтерии в 1С:Предприятие разработчики часто сталкиваются с ситуацией, когда стандартная сортировка по периоду выдает некорректный результат. Особенно остро эта проблема проявляется при восстановлении последовательности расчетов на счетах 60 «Расчеты с поставщиками и подрядчиками» или 62 «Расчеты с покупателями и заказчиками». Если несколько документов попадают в одну и ту же секунду, система может выстроить их в произвольном порядке, что приведет к появлению «красного» сальдо по субконто «Документы расчетов».
В этой статье мы подробно разберем, почему возникает эта ошибка и как составить запрос так, чтобы документы всегда следовали в строгой хронологической последовательности, идентичной той, что мы видим в стандартных бухгалтерских отчетах (например, в «Карточке счета»).
Рассмотрим ситуацию, представленную в исходном запросе. Разработчик использует виртуальную таблицу ХозрасчетныйОбороты и пытается упорядочить данные по полю Период. На первый взгляд, это кажется логичным, но давайте проанализируем, что происходит на уровне базы данных.
Поле Период в регистре бухгалтерии хранит дату и время с точностью до секунды. Если в течение одной секунды было проведено два и более документа (например, при групповом перепроведении или загрузке из внешней системы), то для СУБД эти записи имеют одинаковое значение сортировки. В результате порядок их выдачи становится неопределенным. Для бухгалтерского учета это критично: если «Поступление товаров и услуг» и «Списание с расчетного счета» имеют одно время, но в запросе оплата встанет раньше поступления, алгоритм расчета авансов отработает неверно, и мы получим развернутое сальдо на субсчетах.
Самый простой и зачастую эффективный способ — использование зарезервированного слова АВТОУПОРЯДОЧИВАНИЕ в конце запроса. Рассмотрим, как изменится наш код:
Запрос.Текст =
"ВЫБРАТЬ
| ХозрасчетныйОбороты.Регистратор КАК Регистратор,
| ХозрасчетныйОбороты.Период КАК Период
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.Обороты(&ДатаНачала, &ДатаОкончания, Регистратор, , , , , ) КАК ХозрасчетныйОбороты
|УПОРЯДОЧИТЬ ПО
| Регистратор
|АВТОУПОРЯДОЧИВАНИЕ";
Как это работает: Когда мы указываем АВТОУПОРЯДОЧИВАНИЕ и выбираем поле типа ДокументСсылка (в данном случае Регистратор), платформа 1С не просто сортирует данные по ссылке. Она неявно добавляет в запрос дополнительные поля для сортировки:
Важно помнить, что АВТОУПОРЯДОЧИВАНИЕ работает только в том случае, если в списке выборки или в условиях упорядочивания присутствует ссылка на объект (Регистратор). Однако у этого метода есть минус: он может работать медленнее на больших объемах данных, так как платформа генерирует более сложный SQL-запрос.
Если нам нужно обеспечить максимальную производительность и предсказуемость, мы можем явно указать поля для сортировки. Для регистра бухгалтерии золотым стандартом является связка Период + Регистратор.
Проанализируем исправленный вариант запроса:
Запрос.Текст =
"ВЫБРАТЬ
| ХозрасчетныйОбороты.Регистратор КАК Регистратор,
| ХозрасчетныйОбороты.Период КАК Период,
| ХозрасчетныйОбороты.Счет КАК Счет
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.Обороты(&ДатаНачала, &ДатаОкончания, Регистратор, , , , , ) КАК ХозрасчетныйОбороты
|ГДЕ
| ХозрасчетныйОбороты.Счет В ИЕРАРХИИ(&МассивСчетов)
|УПОРЯДОЧИТЬ ПО
| Период,
| Регистратор";
Почему это надежно? В СУБД ссылка (Регистратор) представлена уникальным идентификатором. Даже если периоды записей совпадают до секунды, идентификаторы документов всегда разные. Система выстроит их в порядке возрастания GUID. Хотя этот порядок может не совпадать с визуальным порядком в журнале документов (созданных «руками» в той же секунде), он будет строго детерминированным. Это значит, что при каждом запуске запроса вы будете получать один и тот же результат, что позволит корректно закрывать остатки при последовательной обработке.
В некоторых случаях виртуальной таблицы Обороты бывает недостаточно. Например, если один и тот же документ делает несколько движений по одному счету и аналитике (допустим, разбиение по ставкам НДС или разным статьям затрат). Виртуальная таблица может «схлопнуть» эти движения, если не указана соответствующая периодичность.
Для максимально детального анализа и восстановления последовательности лучше использовать физическую таблицу РегистрБухгалтерии.Хозрасчетный. Посмотрим на пример:
Запрос.Текст =
"ВЫБРАТЬ
| Хозрасчетный.Регистратор КАК Регистратор,
| Хозрасчетный.Период КАК Период,
| Хозрасчетный.НомерСтроки КАК НомерСтроки
|ИЗ
| РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
|ГДЕ
| Хозрасчетный.Счет В ИЕРАРХИИ(&МассивСчетов)
| И Хозрасчетный.Период МЕЖДУ &ДатаНачала И &ДатаОкончания
|УПОРЯДОЧИТЬ ПО
| Период,
| Регистратор,
| НомерСтроки";
Разберем преимущества этого подхода:
Обороты.Часто в обсуждениях всплывает рекомендация использовать МоментВремени. Нужно понимать техническое ограничение: объект МоментВремени существует в объектной модели (в коде 1С:Предприятие), но его нет как поля в базе данных. В языке запросов вы не можете написать УПОРЯДОЧИТЬ ПО Регистратор.МоментВремени.
Когда вы используете УПОРЯДОЧИТЬ ПО Регистратор вместе с АВТОУПОРЯДОЧИВАНИЕ, система фактически эмулирует сортировку по моменту времени. Если же вы работаете с физической таблицей, то комбинация Период, Регистратор является наиболее близким аналогом Момента времени для целей упорядочивания документов.
Выясним причину, по которой данные в вашем запросе могут не совпадать с типовой «Карточкой счета». Типовые отчеты используют сложные механизмы компоновки данных. Если вы программно перепроводите документы по списку из вашего запроса, а их порядок отличается от того, который использует типовой механизм проведения (который ориентируется на границу последовательности или актуальные итоги), возникнут расхождения.
Рекомендация: При перепроведении документов для восстановления взаиморасчетов (60, 62 счета) всегда используйте сортировку Период, Регистратор. Это гарантирует, что оплата, введенная позже поступления в той же секунде, будет обработана именно как оплата долга, а не как аванс (при условии, что ссылка на оплату была создана позже).
Для корректного упорядочивания документов в запросе к регистру бухгалтерии придерживаемся следующих правил:
Период.Регистратор в список полей УПОРЯДОЧИТЬ ПО.АВТОУПОРЯДОЧИВАНИЕ, если вам нужна логика платформы по умолчанию.НомерСтроки.Регистратор.Дата) в условиях упорядочивания может значительно замедлить выполнение запроса, так как вызовет дополнительное соединение (LEFT JOIN) с таблицей документа.Соблюдение этих структурных правил позволит вам строить надежные алгоритмы перепроведения документов и формирования отчетности без досадных ошибок в бухгалтерских итогах.