Уважаемые коллеги, при разработке функционала в 1С мы часто сталкиваемся с задачей расширения возможностей типовых объектов без изменения основной конфигурации. Одна из таких задач — необходимость заставить существующий документ из основной конфигурации формировать движения по регистру сведений, который также находится в основной конфигурации, но все изменения должны быть внесены исключительно через расширение. Эта ситуация особенно актуальна, когда регистр сведений является подчиненным регистратору, и документ изначально не входит в список его регистраторов.
Изначально такая задача может показаться нетривиальной, поскольку попытки напрямую программно добавить движения или найти соответствующие настройки в расширении могут вызывать затруднения. В данном материале мы подробно разберем, как решить эту проблему, используя стандартные механизмы расширений 1С.
С платформы 1С версии 8.3.12 появилась возможность напрямую указать в расширении, по каким регистрам будет делать движения заимствованный документ из основной конфигурации. Это наиболее простой и рекомендуемый способ, если ваш регистр не является оборотным регистром накопления с включенными агрегатами.
Давайте рассмотрим пошагово, как это сделать:
После выполнения этих шагов платформа 1С будет "знать", что ваш заимствованный документ имеет право формировать движения по указанному регистру. Теперь вы можете использовать стандартный объект Движения в модуле проведения документа, чтобы программно добавлять записи.
Например, в замещенной или дополненной процедуре проведения документа вы можете использовать следующий код:
&Вместо("ОбработкаПроведения")
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// ... ваш код до стандартного проведения ...
// Выполнение стандартного проведения, если это необходимо
// ПродолжитьВыполнениеПроцедуры("ОбработкаПроведения", Отказ, РежимПроведения);
// Пример формирования движений по новому регистру
Если Не Отказ Тогда
Движения.ВторойРегистр.Записывать = Истина;
// Очистка существующих записей для данного регистратора
Движения.ВторойРегистр.Очистить();
// Создание новой записи
Запись = Движения.ВторойРегистр.Добавить();
Запись.Период = Дата;
Запись.Регистратор = Ссылка;
// ... заполнение других полей записи ...
КонецЕсли;
// ... ваш код после стандартного проведения ...
КонецеПроцедуры
Или, если вы используете аннотацию &После для добавления своей логики после стандартного проведения:
&После("ОбработкаПроведения")
Процедура ОбработкаПроведенияПосле(Отказ, РежимПроведения)
Если Не Отказ Тогда
// Формирование движений по второму регистру
Движения.ВторойРегистр.Записывать = Истина;
Движения.ВторойРегистр.Очистить(); // Очищаем старые записи
Запись = Движения.ВторойРегистр.Добавить();
Запись.Период = Дата;
Запись.Регистратор = Ссылка;
// ... заполнение других полей записи ...
КонецЕсли;
КонецПроцедуры
Важно: Если вы столкнулись с ошибкой "Нет такого движения", это означает, что вы либо не включили регистр в свойствах движений документа, либо платформа, на которой вы работаете, старее версии 8.3.12, где эта функциональность была ограничена.
В некоторых случаях, когда необходимо более тонкое управление записями регистра (например, при отмене проведения, или если регистр не подчинен регистратору, но нужно работать с его данными из модуля документа), можно использовать механизм набора записей регистра сведений. Автор темы также пытался применить этот подход, но столкнулся с ошибкой "не установлен отбор по регистратору". Давайте разберем правильный порядок действий.
НаборЗаписей для нужного регистра. Выполним это с помощью метода РегистрыСведений.<ИмяРегистра>.СоздатьНаборЗаписей().Регистратор. Это позволяет работать только с записями, которые относятся к текущему документу. Используем НаборЗаписей.Отбор.Регистратор.Установить(Ссылка), где Ссылка — это ссылка на текущий документ.НаборЗаписей.Прочитать().НаборЗаписей.Добавить() или модифицировать уже прочитанные. Не забудьте указать Регистратор для каждой добавляемой записи.Записать() для объекта НаборЗаписей. По умолчанию, этот метод выполняет замещение, то есть все записи для установленного отбора по регистратору будут удалены, а затем будут записаны текущие записи из набора. Если необходимо добавить записи без удаления существующих (что редко применимо для подчиненного регистра), потребуется более сложная логика.Пример корректного кода для работы с набором записей в модуле документа:
&После("ОбработкаПроведения")
Процедура ОбработкаПроведенияПосле(Отказ, РежимПроведения)
Если Не Отказ Тогда
НаборЗаписей = РегистрыСведений.ВторойРегистр.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(Ссылка);
// Если нужно прочитать существующие записи для изменения или удаления
// НаборЗаписей.Прочитать();
// Очищаем набор, если нужно записать новые записи вместо старых
// Это важно, так как Записать() по умолчанию делает замещение
НаборЗаписей.Очистить();
Запись = НаборЗаписей.Добавить();
Запись.Регистратор = Ссылка;
Запись.Период = Дата;
// ... Заполните остальные поля записи ...
НаборЗаписей.Записать();
КонецЕсли;
КонецПроцедуры
Автор в первом сообщении получил ошибку "не установлен отбор по регистратору" потому что, вероятно, он пытался добавить запись до того, как установил отбор, или пытался вызвать Прочитать() без отбора, что для подчиненного регистра недопустимо без предварительного указания регистратора. Отбор по регистратору критически важен при работе с подчиненными регистрами сведений через НаборЗаписей.
Используя этот подход, мы обходим прямое использование объекта Движения и работаем с регистром как с независимым объектом, но с обязательным условием привязки к регистратору.
Для полного понимания обсуждаемой проблемы и её решения, давайте вспомним ключевые особенности подчиненных регистратору регистров сведений:
Движения: В модулях проведения документов, которые являются регистраторами для подчиненного регистра, для работы с записями используется специальный объект Движения.<ИмяРегистра>. Этот объект автоматически управляет связью с регистратором и обеспечивает корректное удаление/запись при проведении/отмене проведения.Понимание этих особенностей помогает осознанно применять предложенные решения и избегать типовых ошибок.
При работе с расширениями, особенно в контексте взаимодействия с типовыми объектами конфигурации, следует учитывать ряд важных моментов:
ОбработкаПроведения) используйте аннотации &После, &До и &Вместо. Это позволяет точечно модифицировать логику без изменения исходного кода типовой конфигурации и облегчает поддержку.Помните, что механизм расширений является мощным инструментом, но требует внимательного и осознанного подхода к разработке. Для проверки состава расширений и поиска ошибок при заимствовании объектов можно использовать конфигурацию для анализа расширений на наличие ошибок.
Таким образом, мы видим, что задача движения по другому регистру в расширении вполне решаема, особенно с учетом развития платформы 1С. Предпочтительным методом является настройка свойства "Движения" заимствованного документа, но и программная работа с наборами записей также остается эффективным инструментом в арсенале разработчика. Используя эти подходы, вы сможете гибко адаптировать типовые конфигурации под свои нужды, сохраняя при этом возможность удобного обновления.