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

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

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

Рассмотрим подробно, как заставить механизм ВременныйРасчет видеть свежезаписанные движения и почему стандартные методы иногда ведут себя непредсказуемо.

Механизм временных расчетов и актуальность итогов

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

Проанализируем стандартную последовательность команд:


// Создаем объект для работы с временными расчетами
ВремРегистры = СоздатьОбъект("Регистры");
ВремПартии = ВремРегистры.ПартииНаличие;

// Включаем режим временного расчета
ВремПартии.ВременныйРасчет(1);
ВремРегистры.Актуальность(1); // Ключевой флаг для учета новых движений

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

Метод Актуальность(1) теоретически должен обеспечивать то, что каждое вызванное в коде ДвижениеПриход() или ДвижениеРасход() сразу же меняет состояние временных итогов. Однако при проведении "задним числом" (когда документ находится до ТА) разработчики часто сталкиваются с тем, что ВыгрузитьИтоги() во второй или третьей строке документа не видит изменений от первой строки.

Разница между методами РассчитатьРегистрыНа и РассчитатьРегистрыПо

Выясним причину возможной путаницы между этими методами, так как от них зависит точка отсчета для временного расчета:

  1. РассчитатьРегистрыНа(Документ): Система рассчитывает итоги на состояние непосредственно перед первым движением указанного документа. Если в начале модуля проведения вы вызываете ОчиститьДвижения(), то входящий остаток будет одинаковым для обоих методов, но РассчитатьРегистрыНа является более логичным стандартом для формирования новых движений "с нуля".
  2. РассчитатьРегистрыПо(Документ): Итоги рассчитываются на состояние после всех движений документа. Этот метод чаще используется для отчетов или проверок уже проведенных документов.

Важно понимать: если вы используете Актуальность(1), то даже при старте с точки "НА", каждое новое движение должно математически добавляться к результату. Если этого не происходит, проблема кроется в особенностях кэширования или наложения фильтров.

Почему итоги могут «не подхватываться» в цикле

Проанализируем ситуацию, когда в цикле по номенклатуре используется УстановитьЗначениеФильтра(). В 1С 7.7 временный расчет — это динамическая структура в оперативной памяти (или временных таблицах БД). Когда вы меняете фильтр по Номенклатура, система выполняет перепозиционирование во временных итогах.

Если внутри цикла последовательность строк выглядит так:
1. Номенклатура А — Расход
2. Номенклатура Б — Приход
3. Номенклатура А — Расход
То при обработке третьей строки (снова А) фильтр накладывается заново. В некоторых версиях движка 1С 7.7 (особенно на SQL-версиях) происходит сброс курсора временной таблицы, и движения, которые еще не были физически записаны в базу данных (транзакция ведь не завершена), могут выпасть из области видимости метода ВыгрузитьИтоги().

Надежное решение: ручная корректировка таблицы итогов

Как отмечают опытные разработчики, полагаться на 100% корректность Актуальность(1) внутри сложного цикла проведения опасно. Рассмотрим более надежный и производительный метод, который часто применяется в высоконагруженных системах на 7.7.

Суть метода заключается в том, чтобы не обращаться к регистру за итогами на каждой итерации цикла, а работать с локальной Таблицей Значений. Разберем этот алгоритм по шагам:

  1. Перед началом цикла проведения выгружаем все остатки по всей номенклатуре, присутствующей в документе, в одну общую Таблицу Значений (ТЗ).
  2. Внутри цикла ищем нужные остатки в этой ТЗ (используя метод НайтиЗначение() или предварительную индексацию).
  3. После того как программно сформировано движение по регистру (например, списана партия), мы вручную обновляем строку в нашей ТЗ (уменьшаем количество/сумму).

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


// 1. Подготовка данных
ТаблНоменклатурыДокумента.Выгрузить(СписокНоменклатуры, "Номенклатура");

// 2. Получаем остатки один раз на весь документ
ВремРегистры.РассчитатьРегистрыНа(ТекущийДокумент());
ВремПартии.УстановитьЗначениеФильтра("Номенклатура", СписокНоменклатуры, 2); // Фильтр по списку
ВремПартии.ВыгрузитьИтоги(ТЗ_Остатки, 1, 1);

// 3. Основной цикл
ТаблНоменклатурыДокумента.ВыбратьСтроки();
Пока ТаблНоменклатурыДокумента.ПолучитьСтроку() = 1 Цикл
    // Ищем остаток в ТЗ_Остатки вместо обращения к регистру
    СтрокаОст = 0;
    Если ТЗ_Остатки.НайтиЗначение(ТаблНоменклатурыДокумента.Номенклатура, СтрокаОст, "Номенклатура") = 1 Тогда
        ТЗ_Остатки.ПолучитьСтрокуПоНомеру(СтрокаОст);
        
        // Распределяем и формируем движения...
        // Регистр.ПартииНаличие.ДвижениеРасход(...);
        
        // 4. ВАЖНО: Сразу корректируем нашу ТЗ
        ТЗ_Остатки.Количество = ТЗ_Остатки.Количество - СписанноеКолво;
    КонецЕсли;
КонецЦикла;

Преимущества ручной корректировки

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

Резюме

Для корректной работы с движениями текущего документа в 1С 7.7:

1. Всегда используйте ВремРегистры.Актуальность(1), если пытаетесь работать через стандартные методы регистров.

2. Помните, что РассчитатьРегистрыНа(ТекДок) при очищенных движениях — это точка "ноль" для вашего документа.

3. Если вы сталкиваетесь с необъяснимым поведением итогов при проведении задним числом, переходите на алгоритм с единоразовой выгрузкой остатков в Таблицу Значений и их ручной корректировкой в процессе обработки строк. Это классический прием, который гарантирует точность партионного учета в любых условиях.

← На главную