Работа с регистрами накопления — одна из самых частых задач при разработке в среде 1С. Часто возникают ситуации, когда необходимо скорректировать движения документа «на лету» или изменить записи регистра программно, не затрагивая при этом стандартную процедуру проведения документа. В данной статье мы подробно разберем, как управлять записями регистра накопления, используя различные механизмы платформы.
Если ваша задача — добавить или изменить строки регистра именно в момент, когда пользователь нажимает кнопку «Провести», то самым правильным и безопасным способом будет работа с коллекцией Движения. В модуле документа (в процедуре ОбработкаПроведения) платформа предоставляет прямой доступ к наборам записей всех регистров, по которым данный документ может делать движения.
Рассмотрим стандартный алгоритм действий:
Движения.ИмяРегистра.Записывать в значение Истина.Проанализируем пример кода:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// Добавляем новую запись в регистр накопления "Продажи"
НоваяЗапись = Движения.Продажи.Добавить();
НоваяЗапись.ВидДвижения = ВидДвиженияНакопления.Приход;
НоваяЗапись.Период = Дата;
НоваяЗапись.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию("Товар");
НоваяЗапись.Количество = 10;
// Важно сообщить платформе, что этот набор нужно сохранить в БД
Движения.Продажи.Записывать = Истина;
КонецПроцедуры
Обратите внимание: в процедуре ОбработкаПроведения крайне не рекомендуется вызывать метод Движения.ИмяРегистра.Записать() явно. Платформа сама запишет все наборы, у которых флаг Записывать установлен в Истина, в конце транзакции. Явный вызов может привести к избыточным блокировкам и снижению производительности системы.
Бывают случаи, когда документ уже проведен, и нам нужно программно (например, из внешней обработки) изменить его движения, не перепроводя сам документ. Для этого используется объект РегистрНакопленияНаборЗаписей. Это самостоятельная сущность, которая позволяет работать с записями регистра как с таблицей.
Разберем по шагам методику «прочитать — изменить — записать»:
Прочитать(). Это загрузит существующие в базе данных строки этого документа в оперативную память.Записать().Посмотрим на пример кода:
НаборЗаписей = РегистрыНакопления.ОстаткиТоваров.СоздатьНаборЗаписей();
// Устанавливаем отбор по конкретному документу
НаборЗаписей.Отбор.Регистратор.Установить(СсылкаНаДокумент);
// Читаем текущие движения документа из базы
НаборЗаписей.Прочитать();
// Перебираем существующие строки и меняем количество
Для Каждого Запись Из НаборЗаписей Цикл
Если Запись.Количество > 100 Тогда
Запись.Количество = 100; // Ограничиваем количество
КонецЕсли;
КонецЦикла;
// Добавляем совершенно новую строку в этот же регистратор
НоваяСтрока = НаборЗаписей.Добавить();
НоваяСтрока.Регистратор = СсылкаНаДокумент;
НоваяСтрока.Период = СсылкаНаДокумент.Дата;
НоваяСтрока.Номенклатура = НужныйТовар;
НоваяСтрока.Количество = 5;
// Записываем измененный набор в базу данных
НаборЗаписей.Записать();
Внимание: Если вы пропустите шаг Прочитать() и сразу вызовете Записать(), система очистит все старые движения этого документа по данному регистру и запишет только те строки, которые вы добавили в набор программно. Это критически важный момент, о котором часто забывают начинающие разработчики.
Если вы работаете с типовой конфигурацией (например, 1С:ERP или 1С:Бухгалтерия) и не хотите менять код самого документа, чтобы не снимать его с поддержки, используйте Подписки на события.
Для модификации движений идеально подходят два события:
ОбработкаПроведения (для документа): Здесь вы можете получить доступ к Источник.Движения и добавить свои записи.ПередЗаписью (для набора записей регистра): Это событие срабатывает непосредственно перед тем, как данные попадут в таблицу базы данных. Здесь можно проверить корректность данных или принудительно изменить измерения/ресурсы для любых типов документов-регистраторов.Выясним причину, почему «ручные» правки могут исчезнуть. Любое стандартное перепроведение документа пользователем (через форму документа или список) инициирует стандартный механизм: платформа удаляет старые движения и формирует новые согласно коду в модуле документа. Если вы внесли изменения «со стороны» через НаборЗаписей, но не продублировали эту логику в ОбработкеПроведения, то при первом же перепроведении ваши изменения будут стерты.
Работа с блокировками данных. При ручном изменении регистров в высоконагруженных системах (где одновременно работают сотни пользователей) обязательно используйте объект БлокировкаДанных. Это предотвратит чтение неактуальных остатков другими процессами в тот момент, когда вы записываете свои изменения. Помните, что запись набора записей регистра накопления всегда инициирует автоматический пересчет итогов, что может временно замедлить работу системы.
Влияние на последовательности. Если документ входит в какую-либо последовательность (например, партионный учет), изменение его движений может привести к тому, что граница последовательности «уйдет назад». Это потребует последующего восстановления последовательности, чтобы отчеты показывали корректные данные.
Таким образом, мы рассмотрели основные способы изменения регистра накопления. Выбор метода зависит от вашей архитектурной задачи: для постоянной логики используйте модуль документа или подписки, для разовых корректировок или внешних инструментов — объект НаборЗаписей с обязательной установкой отбора по регистратору.