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

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

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

Архитектурные ограничения компоненты «Оперативный учет» в 1С 7.7

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

У объектов типа Регистр в 1С 7.7 отсутствуют методы прямой модификации вроде Записать(). Механизм оперативного учета жестко завязан на понятиях точки актуальности (ТА) и таблицах итогов:

  1. Физически данные разделены на таблицы движений (префикс RA) и таблицы итогов (префикс RG).
  2. Попытка изменить данные напрямую через базу данных или обойти проведение документа нарушает целостность ТА и таблицы итогов, что неизбежно приводит к сбоям в расчете остатков и критическим ошибкам системы.
  3. Регистры делятся на регистры остатков и регистры оборотов. Обнулить текущее сальдо можно только у регистров с признаком «Остатки». Оборотные регистры хранят периодическую историю совершенных действий и сальдо не образуют.

Таким образом, выполнить оператор вида «Регистр.Записать()» из модуля формы списка или элемента справочника невозможно в силу ограничений платформы.

Способ 1. Создание специализированного документа замены карты

Разберем классический, архитектурно правильный подход, который обеспечивает прозрачность учета и сохраняет целостность регистров. Создадим отдельный документ, фиксирующий факт хозяйственной операции (например, ЗаменаДисконтнойКарты).

В структуре документа предусмотрим реквизиты шапки:

  1. СтараяКарта (тип: Справочник.ДисконтныеКарты);
  2. НоваяКарта (тип: Справочник.ДисконтныеКарты).

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


Процедура ОбработкаПроведения()
    // Создаем объект регистра для получения актуального остатка
    Рег = СоздатьОбъект("Регистр.ДисконтныеКарты");
    Рег.УстановитьЗначениеФильтра("ДисконтнаяКарта", СтараяКарта);
    ОстатокСуммы = Рег.СводныйОстаток(СтараяКарта, "Сумма");

    Если ОстатокСуммы > 0 Тогда
        // Списываем накопленный остаток со старой карты
        ПривязкаСтроки(1);
        Расход.ДисконтныеКарты(СтараяКарта, ОстатокСуммы);

        // Зачисляем баланс на новую карту, если она указана
        Если ПустоеЗначение(НоваяКарта) = 0 Тогда
            Приход.ДисконтныеКарты(НоваяКарта, ОстатокСуммы);
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

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

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

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

Разберем по шагам код вызова, который можно поместить в обработчик кнопки справочника:


Процедура ЗаменитьКартуНаНовую()
    Если ПустоеЗначение(ВыбраннаяНоваяКарта) = 1 Тогда
        Предупреждение("Не выбрана новая дисконтная карта!");
        Возврат;
    КонецЕсли;

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

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

Альтернативные архитектурные решения

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

  1. Перенос аналитики на владельца (Контрагента/Физлицо). Если в качестве измерения регистра выступает не сама пластиковая карта, а клиент (справочник Контрагенты или ФизическиеЛица), смена физического носителя не требует корректировки регистров. В этом случае в карточке новой дисконтной карты просто указывается тот же владелец, а старая карта помечается как заблокированная или удаляется. Все накопления автоматически сохраняются за покупателем.
  2. Изменение реквизитов карты вместо выпуска нового элемента. Если произошла механическая замена поврежденной карты или смена типа штрихкода, в ряде учетных систем достаточно просто обновить реквизит номера или штрихкода в текущем элементе справочника, не создавая новый элемент.
  3. Использование периодических реквизитов справочника. Если цель регистра состояла исключительно в фиксации текущего процента скидки (а не финансового остатка), правильнее отказаться от регистра и использовать периодический реквизит справочника, значение которого можно устанавливать на определенную дату напрямую методом УстановитьРеквизит().
← На главную