Как правильно получить актуальные данные из регистра сведений «СрезПоследних», если договор уже расторгнут?

Программист 1С v8.3 (Обычные формы) Управленческий учет Финансы и профессиональные услуги
← На главную

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

Механика работы виртуальной таблицы «СрезПоследних»

Прежде всего, нам необходимо проанализировать, как именно 1С формирует таблицу среза. Многие ошибочно полагают, что СрезПоследних — это некий «фильтр актуальности». На самом деле, это запрос, который находит последнюю по времени запись для каждой уникальной комбинации измерений, дата которой меньше или равна указанному периоду.

Проанализируем ситуацию: если в регистре были измерения Помещение и ДоговорКонтрагента, и по ним была сделана запись от 01.01.2023, то для системы эта запись будет «последней» и в феврале 2023, и в декабре 2025 года, если не появится новая запись с точно такими же измерениями. Тот факт, что договор физически расторгнут или срок его действия истек, платформа игнорирует, так как она оперирует только записями в таблице БД.

Решение 1. Фильтрация по реквизиту «ДатаОкончания»

В конфигурациях на базе решений «БИТ» (например, «БИТ.Аренда») в регистре сведений бит_АрендуемыеПлощади часто присутствует реквизит ДатаОкончания. Рассмотрим, как использовать его для отсечения неактуальных данных. Выясним причину: если запись в регистре является последней, но дата окончания в ней меньше текущей даты, значит, правоотношения прекращены.

Разберем по шагам, как изменить запрос. Нам нужно добавить условие в блок ГДЕ. Обратите внимание, что условие на реквизиты нельзя ставить в параметры виртуальной таблицы (там можно фильтровать только по измерениям для оптимизации).

Посмотрим на пример правильного запроса:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    АрендуемыеПлощади.Помещение КАК Помещение,
    АрендуемыеПлощади.Площадь КАК Площадь,
    АрендуемыеПлощади.Ставка КАК Ставка,
    АрендуемыеПлощади.ДатаОкончания КАК ДатаОкончания
ИЗ
    РегистрСведений.бит_АрендуемыеПлощади.СрезПоследних(&Дата, ДоговорКонтрагента = &ДоговорКонтрагента) КАК АрендуемыеПлощади
ГДЕ
    (АрендуемыеПлощади.ДатаОкончания >= &Дата 
     ИЛИ АрендуемыеПлощади.ДатаОкончания = ДАТАВРЕМЯ(1, 1, 1))

В данном примере мы проверяем два условия: либо дата окончания еще не наступила (сравниваем с параметром &Дата), либо дата окончания не заполнена (пустая дата), что в логике многих систем означает «бессрочно».

Решение 2. Использование Регистров Накопления (Остатки)

Если задача стоит в получении оперативных данных (сколько площади занято прямо сейчас), использование регистра сведений может быть не самым оптимальным путем. В учетных системах часто параллельно ведется регистр накопления (например, бит_ЗанятостьПомещений).

Проанализируем ситуацию: в регистре накопления движения строятся по принципу «Приход» (заняли площадь) и «Расход» (освободили при расторжении). В отличие от регистра сведений, где запись «висит» вечно, остаток в регистре накопления при расторжении превращается в ноль. Рассмотрим вариант запроса к остаткам:


ВЫБРАТЬ
    Занятость.Помещение КАК Помещение,
    Занятость.ПлощадьОстаток КАК Площадь
ИЗ
    РегистрНакопления.бит_ЗанятостьПомещений.Остатки(&Дата, Договор = &Договор) КАК Занятость
ГДЕ
    Занятость.ПлощадьОстаток > 0

Если этот запрос возвращает пустой результат, значит, по данному договору за арендатором ничего не числится. Это наиболее надежный способ для оперативного учета.

Решение 3. Соединение со срезом состояний договоров

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

Предположим, у нас есть регистр бит_СостоянияДоговоровАренды. Нам нужно получить только те площади, договоры по которым на текущий момент не находятся в состоянии «Расторгнут».


ВЫБРАТЬ
    Площади.Помещение,
    Площади.Площадь,
    Состояния.Состояние
ИЗ
    РегистрСведений.бит_АрендуемыеПлощади.СрезПоследних(&Дата, ) КАК Площади
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.бит_СостоянияДоговоровАренды.СрезПоследних(&Дата, ) КАК Состояния
    ПО Площади.ДоговорКонтрагента = Состояния.ДоговорКонтрагента
ГДЕ
    Состояния.Состояние <> ЗНАЧЕНИЕ(Перечисление.бит_СостоянияДоговоровАренды.Расторгнут)

Важный нюанс: использование ВНУТРЕННЕЕ СОЕДИНЕНИЕ гарантирует, что в выборку попадут только те помещения, по которым есть зафиксированное состояние. Если же состояние может быть не указано, следует использовать ЛЕВОЕ СОЕДИНЕНИЕ и обрабатывать NULL.

Общие рекомендации при проектировании запросов к СрезуПоследних

Чтобы избежать подобных трудностей в будущем, придерживайтесь следующих правил при разработке на платформе 1С:Предприятие 8:

  1. Определяйте измерения правильно. Если вы хотите, чтобы при смене статуса старая запись «перекрывалась», измерения в новой записи должны полностью совпадать с измерениями в старой.
  2. Используйте «закрывающие записи». Хорошей практикой в регистрах сведений считается внесение записи с нулевыми ресурсами при прекращении действия события. Например, при расторжении договора можно программно создать запись в регистр сведений с нулевой площадью. В этом случае СрезПоследних вернет ноль, что и будет ожидаемым результатом.
  3. Различайте срез на дату и срез на момент времени. Если документ расторжения и запрос формируются в одну и ту же секунду, используйте объект Граница, чтобы точно определить, должны ли движения документа попасть в выборку.
  4. Параметры виртуальной таблицы. Всегда старайтесь передавать условия по измерениям (например, ДоговорКонтрагента) в параметры виртуальной таблицы &ПараметрыСеанса или напрямую, а не в блок ГДЕ. Это значительно ускоряет работу запроса на больших объемах данных, так как платформа отсекает лишнее еще на уровне СУБД до формирования итогового среза.

Подводя итог, отметим: если ваш запрос возвращает данные по расторгнутому договору, это не ошибка программы, а следствие специфики хранения данных в регистрах сведений. Выбирайте наиболее подходящий метод фильтрации (по дате окончания, по статусу или через регистр накопления) исходя из архитектуры вашей конфигурации.

← На главную