Как получить остатки по временным регистрам для нескольких фирм в 1С 7.7?

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

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

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

Выясняем причину: как работают фильтры временных расчетов

Для оптимизации проведения документов в типовых решениях 1С 7.7 используется механизм временного расчета регистров. При подготовке движений вызывается глобальная функция глФильтрДолгов (или аналогичный локальный алгоритм), которая накладывает жесткие отборы на объект регистра:

глФильтрДолгов(Контекст, Договор, СписокПараметров, ВремПокупатели);

Внутри этой процедуры для временного регистра вызывается метод УстановитьЗначениеФильтра. Код выглядит следующим образом:


ВремВзаим.УстановитьЗначениеФильтра("Фирма", Фирма, 1);
ВремВзаим.УстановитьЗначениеФильтра("Договор", Договор, 1);

Главная особенность платформы 1С 7.7 заключается в том, что после установки фильтра с третьим параметром, равным 1 (прямое равенство), объект регистра «намертво» ограничивает свою выборку указанным значением. Даже если вы попытаетесь вызвать метод ВремПокупатели.СводныйОстаток(Фирма2, ..., "СуммаВал"), база данных вернет пустое значение, поскольку Фирма2 не проходит через предварительно наложенный фильтр по Фирма1.

---

Решение №1: Использование списка значений в качестве фильтра

Самый простой способ получить остатки по двум фирмам в рамках одного объекта регистра — это передать в качестве фильтра не конкретный элемент справочника, а специальный объект типа СписокЗначений. В этом случае фильтр будет работать по условию «В списке».

Проанализируем пример реализации этого подхода по шагам:

  1. Создадим список фирм, по которым нам необходимо получить данные.
  2. Заполним этот список нужными фирмами (например, текущей фирмой документа и дополнительной фирмой).
  3. Установим фильтр на регистр, передав в качестве третьего параметра число 2 (что означает отбор по списку значений).

Рассмотрим пример кода:


// Создаем список фирм для фильтрации
СписокФирм = СоздатьОбъект("СписокЗначений");
СписокФирм.ДобавитьЗначение(Фирма1);
СписокФирм.ДобавитьЗначение(Фирма2);

// Устанавливаем фильтр по списку фирм (режим 2 - поиск в списке)
ВремПокупатели.УстановитьЗначениеФильтра("Фирма", СписокФирм, 2);

// Для корректного получения остатков по договорам также нужно снять 
// жесткий фильтр по конкретному договору или передать список договоров
ВремПокупатели.УстановитьЗначениеФильтра("Договор", , 0); // 0 - отключает фильтр по измерению

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


ТекущийДолг1 = ВремПокупатели.СводныйОстаток(Фирма1, , , , , "СуммаВал");
ТекущийДолг2 = ВремПокупатели.СводныйОстаток(Фирма2, , , , , "СуммаВал");

---

Решение №2: Использование второго независимого объекта временных регистров

Если внесение изменений в штатный фильтр основного регистра нежелательно (так как это может затронуть другие алгоритмы проведения документа), правильным решением будет создание второго, полностью независимого объекта временных регистров.

При этом важно помнить, что в регистре Покупатели аналитика ведется в разрезе договоров. Если мы просто создадим второй объект и укажем в нем Контрагент.ОсновнойДоговор, система может вернуть пустые остатки. Это связано с тем, что основной договор контрагента чаще всего привязан к первой (основной) фирме. Для второй фирмы нам необходимо найти соответствующий договор.

Пропишем алгоритм поиска договора и инициализации второго регистра:


// 1. Ищем договор контрагента, который заключен со второй фирмой
ДоговорФирмы2 = ПолучитьПустоеЗначение("Справочник.Договоры");
спрДоговоры = СоздатьОбъект("Справочник.Договоры");
спрДоговоры.ИспользоватьВладельца(Контрагент);
спрДоговоры.ВыбратьДоговоры();
Пока спрДоговоры.ПолучитьДоговор() = 1 Цикл
    Если спрДоговоры.ТекущийЭлемент().Фирма = Фирма2 Тогда
        ДоговорФирмы2 = спрДоговоры.ТекущийЭлемент();
        Прервать;
    КонецЕсли;
КонецЦикла;

// 2. Создаем отдельный объект временных регистров
ВремРегистры2 = СоздатьОбъект("Регистры");
ВремПокупатели2 = ВремРегистры2.Покупатели;

// 3. Включаем временный расчет, если итоги не актуальны
Если ИтогиАктуальны() = 0 Тогда
    ВремПокупатели2.ВременныйРасчет(1);
КонецЕсли;

// 4. Накладываем индивидуальные фильтры для второй фирмы
ВремПокупатели2.УстановитьЗначениеФильтра("Фирма", Фирма2, 1);
ВремПокупатели2.УстановитьЗначениеФильтра("Договор", ДоговорФирмы2, 1);

// Выполняем расчет на момент текущего документа
ВремРегистры2.РассчитатьРегистрыНа(ТекущийДокумент());

// 5. Получаем очищенный остаток по второй фирме
ТекущийДолг2 = ВремПокупатели2.СводныйОстаток(Фирма2, ДоговорФирмы2, , , , "СуммаВал");

---

Исправление частых синтаксических ошибок

При реализации ручного управления временным расчетом разработчики часто допускают типичные ошибки компиляции. Разберем наиболее популярную из них:


// ОШИБКА: Ожидается логическое выражение
Если 0 = Контекст.ИтогиАктуальны() Тогда
    ВремПокупатели2.ВременныйРасчет();
КонецЕсли;

Эта ошибка возникает по двум причинам:

  1. Использование ключевого слова Контекст внутри модуля самого документа является избыточным. Все методы контекста документа доступны в его модуле напрямую.
  2. Метод ВременныйРасчет() в 1С 7.7 требует обязательного передачи числового параметра (1 — включить расчет, 0 — выключить).

Правильный вариант написания данной конструкции выглядит так:


Если ИтогиАктуальны() = 0 Тогда
    ВремПокупатели2.ВременныйРасчет(1);
КонецЕсли;

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

← На главную