Как программно изменить записи регистра накопления в 1С:Предприятие 8?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Вариант 1: Изменение движений внутри модуля документа

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

Рассмотрим стандартный алгоритм действий:

  1. Обратимся к коллекции движений конкретного регистра через Движения.ИмяРегистра.
  2. Заполним необходимые поля (Период, Ресурс, Измерение).
  3. Установим свойство Записывать в значение Истина.

Проанализируем пример кода:


Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    // Добавляем новую запись в регистр накопления "Продажи"
    НоваяЗапись = Движения.Продажи.Добавить();
    НоваяЗапись.ВидДвижения = ВидДвиженияНакопления.Приход;
    НоваяЗапись.Период = Дата;
    НоваяЗапись.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию("Товар");
    НоваяЗапись.Количество = 10;
    
    // Важно сообщить платформе, что этот набор нужно сохранить в БД
    Движения.Продажи.Записывать = Истина;
КонецПроцедуры

Обратите внимание: в процедуре ОбработкаПроведения крайне не рекомендуется вызывать метод Движения.ИмяРегистра.Записать() явно. Платформа сама запишет все наборы, у которых флаг Записывать установлен в Истина, в конце транзакции. Явный вызов может привести к избыточным блокировкам и снижению производительности системы.

Вариант 2: Изменение регистра «со стороны» через НаборЗаписей

Бывают случаи, когда документ уже проведен, и нам нужно программно (например, из внешней обработки) изменить его движения, не перепроводя сам документ. Для этого используется объект РегистрНакопленияНаборЗаписей. Это самостоятельная сущность, которая позволяет работать с записями регистра как с таблицей.

Разберем по шагам методику «прочитать — изменить — записать»:

  1. Создание набора: Сначала мы создаем пустой объект набора записей для конкретного регистра.
  2. Установка фильтра: Для регистров накопления установка фильтра по регистратору является обязательным условием. Без этого платформа не позволит прочитать или записать данные.
  3. Чтение: Вызываем метод Прочитать(). Это загрузит существующие в базе данных строки этого документа в оперативную память.
  4. Модификация: Редактируем строки в полученной таблице или добавляем новые.
  5. Запись: Вызываем метод Записать().

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


НаборЗаписей = РегистрыНакопления.ОстаткиТоваров.СоздатьНаборЗаписей();
// Устанавливаем отбор по конкретному документу
НаборЗаписей.Отбор.Регистратор.Установить(СсылкаНаДокумент);

// Читаем текущие движения документа из базы
НаборЗаписей.Прочитать();

// Перебираем существующие строки и меняем количество
Для Каждого Запись Из НаборЗаписей Цикл
    Если Запись.Количество > 100 Тогда
        Запись.Количество = 100; // Ограничиваем количество
    КонецЕсли;
КонецЦикла;

// Добавляем совершенно новую строку в этот же регистратор
НоваяСтрока = НаборЗаписей.Добавить();
НоваяСтрока.Регистратор = СсылкаНаДокумент;
НоваяСтрока.Период = СсылкаНаДокумент.Дата;
НоваяСтрока.Номенклатура = НужныйТовар;
НоваяСтрока.Количество = 5;

// Записываем измененный набор в базу данных
НаборЗаписей.Записать();

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

Вариант 3: Использование подписок на события

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

Для модификации движений идеально подходят два события:

Риски и важные нюансы

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

Работа с блокировками данных. При ручном изменении регистров в высоконагруженных системах (где одновременно работают сотни пользователей) обязательно используйте объект БлокировкаДанных. Это предотвратит чтение неактуальных остатков другими процессами в тот момент, когда вы записываете свои изменения. Помните, что запись набора записей регистра накопления всегда инициирует автоматический пересчет итогов, что может временно замедлить работу системы.

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

Таким образом, мы рассмотрели основные способы изменения регистра накопления. Выбор метода зависит от вашей архитектурной задачи: для постоянной логики используйте модуль документа или подписки, для разовых корректировок или внешних инструментов — объект НаборЗаписей с обязательной установкой отбора по регистратору.

← На главную