Как перенести розничные цены и остатки товаров при свертке базы 1С 7.7

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

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

Почему розничные цены обнуляются при свертке

Разберем типичную ошибку при попытке получить цены через запрос к регистрам. Если в конфигурации учет розничных цен ведется не в ресурсах регистра накопления, а в справочнике номенклатуры (например, периодический реквизит Розн_Цена), то попытка применить к нему агрегатную функцию регистра приводит к ошибке логики:


// Ошибочная конструкция в тексте запроса:
|Розн_Цена = Регистр.ОстаткиТоваров.Товар.Розн_Цена;
|Функция ОстатокРозн_Цена = КонОст(Розн_Цена);

Функция КонОст() в языке запросов платформы 1С 7.7 предназначена исключительно для получения остатков по числовым ресурсам регистров остатков. Она не может вычислять срез значений реквизитов связанных справочников.

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

Способ 1. Установка периодического значения через документ ввода остатков

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

Посмотрим на пример правильного заполнения движений регистра и периодических реквизитов в модуле документа:


Процедура ОбработкаПроведения(Режим)
    ВыбратьСтроки();
    Пока ПолучитьСтроку() = 1 Цикл
        // Фиксируем периодический реквизит справочника от имени текущего документа
        УстановитьРеквизитСправочника(Товар, "Розн_Цена", Розн_Цена, ДатаДок);
        
        // Формируем движения по регистру остатков
        Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
        Если ОстатокТовара >= 0 Тогда
            Регистр.ОстаткиТоваров.ДвижениеПриход(Товар, Склад, БазоваяСтоимость, ВалютнаяСтоимость, ОстатокТовара, ФлагУчета);
        Иначе
            Регистр.ОстаткиТоваров.ДвижениеРасход(Товар, Склад, -БазоваяСтоимость, -ВалютнаяСтоимость, -ОстатокТовара, ФлагУчета);
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

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

Способ 2. Фиксация независимой истории через объект Периодический

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

Разберем алгоритм по шагам:

  1. Считываем актуальное значение цены на дату свертки перед удалением документов.
  2. Записываем полученную цену на дату начала нового периода как ручную запись без привязки к документу.

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


мПериод = СоздатьОбъект("Периодический");
мСпрТовары = СоздатьОбъект("Справочник.Товары");

мСпрТовары.ВыбратьЭлементы();
Пока мСпрТовары.ПолучитьЭлемент() = 1 Цикл
    Если мСпрТовары.ЭтоГруппа() = 0 Тогда
        // Считываем цену на дату окончания старого периода
        мПериод.ИспользоватьОбъект("Розн_Цена", мСпрТовары.ТекущийЭлемент());
        АктуальнаяЦена = мПериод.ЗначениеНаДату(ДатаКонцаПериода);
        
        // Если цена установлена, записываем ее на дату свертки
        Если АктуальнаяЦена > 0 Тогда
            мПериод.ДатаЗнач = ДатаКонцаПериода + 1;
            мПериод.Значение = АктуальнаяЦена;
            мПериод.Записать();
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

Оптимизация свертки регистров с помощью ВыгрузитьИтоги

Для ускорения процедуры свертки регистров в 1С 7.7 рекомендуется отказаться от тяжелых запросов в пользу прямого метода ВыгрузитьИтоги(). Это стандартный метод объекта Регистр, который мгновенно выгружает все актуальные остатки в ТаблицаЗначений.

Рассмотрим пример быстрой выборки остатков регистра:


ТабОстатков = СоздатьОбъект("ТаблицаЗначений");
Рег = СоздатьОбъект("Регистр.ОстаткиТоваров");

// При необходимости устанавливаем расчет на дату свертки
Рег.ВременныйРасчет(1);
РассчитатьРегистрыНа(ДатаКонцаПериода);

// Выгружаем итоги напрямую в таблицу
Рег.ВыгрузитьИтоги(ТабОстатков, 1, 1);

// Таблица готова для циклического переноса в табличную часть документа ввода остатков

Использование связки метода ВыгрузитьИтоги() для количественно-суммового учета и фиксации периодических реквизитов через УстановитьРеквизитСправочника или объект Периодический позволяет провести свертку базы без потери цен и искажения аналитических данных.

← На главную