Как изменить значение реквизита справочника при проведении документа?

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

В практике разработки на платформе 1С:Предприятие часто возникает задача: при проведении определенного документа необходимо автоматически обновить данные в связанном справочнике. Например, изменить статус клиента, обновить контактную информацию или установить признак активности. Несмотря на кажущуюся простоту, эта задача таит в себе множество нюансов — от банальных синтаксических ошибок до архитектурных вопросов целостности данных.

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

Разбор типичной ошибки: Ссылка vs Объект

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


// Ошибочный код
Спр = Справочники.Клиенты.НайтиПоНаименованию("Обычный"); 
СтатусКлиента = Спр.ПолучитьОбъект(); 
СтатусКлиента.СтатусКлиента = "Постоянный"; 
Спр.Записать(); // Ошибка!

Давайте выясним причину возникновения ошибки. В системе 1С существует строгое разделение на Ссылку (указатель на запись в базе данных) и Объект (данные, загруженные в оперативную память для редактирования).

  1. Метод НайтиПоНаименованию возвращает именно Ссылку (СправочникСсылка).
  2. Метод ПолучитьОбъект() создает на основании ссылки Объект (СправочникОбъект), который можно изменять.
  3. Метод Записать() существует только у Объекта. Попытка вызвать его у ссылки (переменная Спр в примере выше) приведет к ошибке выполнения.

Чтобы исправить ситуацию, нам нужно вызывать запись именно у той переменной, в которую мы получили объект. Давайте посмотрим на исправленный вариант:


// Исправленный базовый код
СсылкаНаКлиента = Справочники.Клиенты.НайтиПоНаименованию("Обычный"); 

Если Не СсылкаНаКлиента.Пустая() Тогда
    ОбъектКлиента = СсылкаНаКлиента.ПолучитьОбъект();
    ОбъектКлиента.СтатусКлиента = "Постоянный";
    ОбъектКлиента.Записать();
КонецЕсли;

Шаг 1: Поиск элемента и проверка на пустую ссылку

Проанализируем ситуацию: что произойдет, если элемент с наименованием "Обычный" не будет найден? В этом случае метод НайтиПоНаименованию вернет пустую ссылку. Если мы сразу попытаемся вызвать ПолучитьОбъект() от пустой ссылки, система выдаст ошибку "Элемент не выбран".

Важное правило: всегда делайте проверку Если Не Ссылка.Пустая() Тогда. Это предотвратит аварийное завершение работы программы при отсутствии нужных данных в базе.

Также стоит заметить, что поиск по наименованию — это "хрупкое" решение. Пользователь может легко переименовать элемент, и код перестанет работать. Рассмотрим альтернативные варианты поиска:

Шаг 2: Оптимизация записи и производительность

Процедура Записать() — это ресурсозатратная операция. При ее вызове 1С обновляет индексы в базе данных, выполняет проверки в модуле справочника и запускает подписки на события. Если документ проводится часто, лишние записи могут существенно замедлить работу системы.

Рассудим логически: нужно ли перезаписывать объект, если реквизит уже имеет нужное нам значение? Конечно, нет. Давайте добавим условие:


Если ОбъектКлиента.СтатусКлиента <> "Постоянный" Тогда
    ОбъектКлиента.СтатусКлиента = "Постоянный";
    ОбъектКлиента.Записать();
КонецЕсли;

Этот простой блок Если...Тогда может значительно снизить нагрузку на сервер БД, особенно при массовом перепроведении документов.

Шаг 3: Проблема отмены проведения (распроведения)

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

Это может привести к нарушению логики учета. Если документ "присвоил" статус, а потом был удален или отменен, клиент так и останется "Постоянным".

Профессиональное решение: Регистры сведений

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

Преимущества этого подхода:

  1. История изменений: Вы всегда видите, когда и каким документом был изменен статус.
  2. Автоматическая очистка: Если сделать регистр "Подчиненным регистратору", то при отмене проведения документа запись в регистре удалится автоматически, и система вернет "предыдущее" актуальное значение (на дату более ранней записи).
  3. Отсутствие блокировок справочника: Вам не нужно открывать и записывать весь объект "Справочник", что критично в многопользовательской среде.

Рассмотрим пример кода для записи в регистр сведений при проведении документа:


Движение = РегистрыСведений.ИсторияСтатусовКлиентов.СоздатьМенеджерЗаписи();
Движение.Период = Дата;
Движение.Клиент = СсылкаНаКлиента;
Движение.Статус = Перечисления.СтатусыКлиентов.Постоянный;
Движение.Записать();

Транзакции и блокировки

Разберем еще один критический момент. Проведение документа всегда происходит внутри транзакции. Это значит, что если при записи справочника произойдет ошибка (например, сработает проверка заполнения другого обязательного поля), то документ тоже не проведется. Вся операция "откатится".

Также важно помнить о правах доступа. Если у пользователя есть права на проведение документа, но нет прав на редактирование справочника "Клиенты", выполнение кода ОбъектКлиента.Записать() вызовет исключение. В таких случаях запись стоит выносить в привилегированный общий модуль.

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

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

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

← На главную