Как программно изменить индивидуальное соглашение на типовое в 1С:УТ 11.5?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

Довольно часто в практике программиста 1С возникает задача массовой или точечной корректировки данных. Рассмотрим интересную ситуацию: необходимо программно изменить вид соглашения с клиентом с «индивидуального» на «типовое» в конфигурациях 1С:Управление торговлей 11.5, 1С:Комплексная автоматизация 2.5 или 1С:ERP 2.5. На первый взгляд задача кажется тривиальной, но при ее решении можно столкнуться с неочевидными архитектурными особенностями системы.

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

Анализ неудачной попытки изменения соглашения

Посмотрим на пример кода, который часто пытаются использовать для решения данной задачи. Логика разработчика понятна: найти реквизиты, отвечающие за вид соглашения, установить им значение «Типовое», включить загрузку без проверок и сохранить объект.


Объект = СсылкаНаСоглашение.ПолучитьОбъект();
Объект.ОбменДанными.Загрузка = Истина;
Объект.ВидСоглашенияДляОграниченияЧтения = Перечисления.ВидыСоглашенийСКлиентамиДляОграниченияЧтения.Типовые;
Объект.ВидСоглашенияДляОграниченияИзменения = Перечисления.ВидыСоглашенийСКлиентамиДляОграниченияИзменения.Типовые;
Объект.Записать();

Выясним причину, почему этот код не дает нужного результата. Разработчик попытался изменить реквизиты ВидСоглашенияДляОграниченияЧтения и ВидСоглашенияДляОграниченияИзменения. Однако эти поля в справочнике СоглашенияСКлиентами являются сугубо служебными. Они используются исключительно подсистемой прав доступа (RLS) для разграничения видимости на уровне записей. Архитектура программы не опирается на них для определения фактического статуса и логики работы самого соглашения. Интерфейс и бизнес-логика конфигурации все равно будут видеть объект как индивидуальное соглашение.

Правильный алгоритм программного преобразования

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

  1. Изменение базового реквизита. В структуре справочника тип соглашения определяется не перечислениями RLS, а базовым логическим (булевым) реквизитом Типовое. При программном изменении именно его необходимо установить в значение Истина.
  2. Очистка привязки к контрагенту и партнеру. Главное системное отличие индивидуального соглашения заключается в том, что оно всегда заключается с конкретным клиентом. Типовые же соглашения действуют для широкого круга лиц. Поэтому мы обязаны принудительно очистить реквизиты Партнер и Контрагент. Если форма 1С при открытии увидит заполненного партнера, она автоматически переключится в режим работы с индивидуальным соглашением.
  3. Очистка родительского соглашения. Индивидуальные соглашения почти всегда создаются на базе правил продаж какого-либо типового соглашения. Следовательно, у них заполнен реквизит ТиповоеСоглашение. Архитектура 1С не предполагает, что одно типовое соглашение подчинено другому типовому таким образом. Этот реквизит необходимо обнулить.
  4. Заполнение сегмента партнеров. Поскольку мы удалили конкретного партнера, соглашение начало действовать для абсолютно всех клиентов базы. Чтобы сохранить задуманную логику продаж и ограничить действие типовых условий, рекомендуется программно заполнить реквизит СегментПартнеров (например, указать сегмент «Оптовые клиенты» или «Дилеры»).

Пример корректного рабочего кода

Соберем все описанные правила в единый скрипт. Рассмотрим подробнее, как должен выглядеть рабочий код для корректной трансформации:


Объект = СсылкаНаИндивидуальноеСоглашение.ПолучитьОбъект();

// Включаем загрузку, чтобы избежать лишних проверок при записи
Объект.ОбменДанными.Загрузка = Истина;

// 1. Устанавливаем признак типового соглашения
Объект.Типовое = Истина;

// 2. Корректируем служебные реквизиты RLS (для целостности данных)
Объект.ВидСоглашенияДляОграниченияЧтения = Перечисления.ВидыСоглашенийСКлиентамиДляОграниченияЧтения.Типовые;
Объект.ВидСоглашенияДляОграниченияИзменения = Перечисления.ВидыСоглашенийСКлиентамиДляОграниченияИзменения.Типовые;

// 3. Отвязываем соглашение от конкретного клиента
Объект.Партнер = Справочники.Партнеры.ПустаяСсылка();
Объект.Контрагент = Справочники.Контрагенты.ПустаяСсылка();

// 4. Очищаем ссылку на базовое типовое соглашение
Объект.ТиповоеСоглашение = Справочники.СоглашенияСКлиентами.ПустаяСсылка();

// 5. Опционально: назначаем сегмент партнеров
Объект.СегментПартнеров = Справочники.СегментыПартнеров.НайтиПоНаименованию("Оптовые клиенты");

// Записываем изменения
Объект.Записать();

Важное замечание: При массовой обработке данных всегда тестируйте подобный код на копии базы. Использование свойства ОбменДанными.Загрузка отключает многие проверки модуля объекта, что позволяет быстро записать элемент, но возлагает всю ответственность за ссылочную целостность на плечи программиста.

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

Если задача носит разовый характер, проще всего поступить так, как было сделано в итоге: пометить текущее индивидуальное соглашение на удаление и создать новое типовое соглашение руками пользователя.

Для пользователей, которым регулярно требуется менять вид соглашения, существуют готовые решения. В сообществе программистов 1С разработаны расширения конфигурации, которые добавляют в подменю «Еще» карточки соглашения кнопку «Преобразовать соглашение в типовое / индивидуальное». Такие расширения под капотом используют ровно тот же алгоритм, который мы рассмотрели выше: они автоматически подменяют служебные поля, очищают контрагентов и перезаписывают объект, избавляя от необходимости писать скрипты и внешние обработки вручную.

← На главную