При разработке и доработке конфигураций 1С мы часто сталкиваемся с задачами, требующими гибкого хранения и отображения данных. Одна из таких задач – необходимость добавить атрибут, например, СпособРасчетов, для каждого контрагента в табличной части документа, при этом значение этого атрибута может меняться от документа к документу. Изначально этот атрибут мог быть реализован как дополнительный реквизит справочника Контрагенты. Давайте разберем, как правильно реализовать такую функциональность, чтобы обеспечить удобство использования и корректное хранение данных.
Прежде чем углубляться в решения, нам важно понять, как работает стандартный механизм дополнительных реквизитов в 1С, который часто реализуется с помощью Библиотеки стандартных подсистем (БСП).
Стандартный механизм дополнительных реквизитов предназначен для хранения свойств объекта в целом. Например, если мы добавляем дополнительный реквизит ВидДеятельности для справочника Контрагенты, это свойство будет характеризовать контрагента в целом и иметь одно значение для каждого элемента справочника. Значения таких дополнительных реквизитов хранятся непосредственно в самом объекте (часто в его специальной табличной части) и отображаются на его форме как его неотъемлемые характеристики.
Выясним, почему такой подход не подходит для нашей задачи, где СпособРасчетов должен быть свойством каждой строки табличной части документа и, более того, может меняться для одного и того же контрагента в разных документах. Если бы мы просто отобразили дополнительный реквизит контрагента из справочника в табличной части, он всегда бы показывал одно и то же значение, хранящееся в самом контрагенте, без возможности изменить его для конкретной строки документа. Нам же нужна возможность указывать свойство, уникальное для данной записи в табличной части.
Это самый прямой, стандартный и надежный способ решения данной задачи. Мы напрямую интегрируем нужный атрибут в структуру документа, делая его полноценным реквизитом строки табличной части.
Разберем по шагам, как это сделать:
РеализацияТоваровУслуг).
Покупатели или Товары).
СпособРасчетовДокумента. Выбираем подходящий тип данных. Если у нас уже есть перечисление СпособыРасчетов, то устанавливаем тип Перечисление.СпособыРасчетов. Это обеспечит корректный выбор из предопределенного списка значений.
СпособРасчетовДокумента. Устанавливаем свойства колонки: заголовок, ширину, режим редактирования.
СпособРасчетовДокумента автоматически заполнялось значением из дополнительного реквизита справочника Контрагенты (если такой реквизит все еще нужен для хранения значения по умолчанию). Для этого мы можем использовать обработчик события ПриИзменении для поля Контрагент в табличной части.
Посмотрим на пример кода для обработчика события ПриИзменении поля Контрагент в табличной части:
&НаКлиенте
Процедура ПокупателиКонтрагентПриИзменении(Элемент)
// Получаем текущую строку табличной части
ТекущиеДанные = Элемент.ТекущиеДанные;
// Проверяем, что контрагент выбран
Если Не ТекущиеДанные.Контрагент.Пустая() Тогда
// Получаем значение дополнительного реквизита "СпособРасчетов" из справочника Контрагенты
// Это может быть запрос к базе данных или обращение к кэшированным данным,
// в зависимости от реализации доп. реквизитов (БСП или самописные).
// Предположим, что доп. реквизит контрагента называется "СпособРасчетов"
// Для демонстрации, как получить доп. реквизит, если он хранится стандартно в БСП:
// Нам понадобится серверный вызов, чтобы получить дополнительные реквизиты объекта.
// Или, если это просто обычный реквизит, то:
// СпособРасчетовПоУмолчанию = ТекущиеДанные.Контрагент.СпособРасчетов;
// Если доп. реквизит из БСП, то придется получать его так (пример):
ЗначениеДопРеквизита = ПолучитьЗначениеДопРеквизитаКонтрагента(ТекущиеДанные.Контрагент, "СпособРасчетов");
// Устанавливаем полученное значение в реквизит табличной части
Если ЗначениеЗаполнено(ЗначениеДопРеквизита) Тогда
ТекущиеДанные.СпособРасчетовДокумента = ЗначениеДопРеквизита;
КонецЕсли;
КонецЕсли;
КонецПроцедудры
&НаСервереБезКонтекста
Функция ПолучитьЗначениеДопРеквизитаКонтрагента(КонтрагентСсылка, ИмяДопРеквизита)
// Пример получения значения доп. реквизита из БСП, если он хранится в РегистреСведений.ДополнительныеСведения
// В реальной БСП функционал может быть сложнее, например, через функции БСП
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ДополнительныеСведения.Значение
|ИЗ
| РегистрСведений.ДополнительныеСведения КАК ДополнительныеСведения
|ГДЕ
| ДополнительныеСведения.Объект = &Объект
| И ДополнительныеСведения.Свойство.Имя = &ИмяСвойства";
Запрос.УстановитьПараметр("Объект", КонтрагентСсылка);
Запрос.УстановитьПараметр("ИмяСвойства", ИмяДопРеквизита);
РезультатЗапроса = Запрос.Выполнить().Выбрать();
Если РезультатЗапроса.Следующий() Тогда
Возврат РезультатЗапроса.Значение;
Иначе
Возврат Неопределено;
КонецЕсли;
КонецФункции
Преимущества Решения 1:
Недостатки Решения 1:
Проанализируем ситуацию, озвученную в исходной теме: "Для одного Контрагента в разных документах способ расчета может меняться". Это критический момент, который указывает на возможную архитектурную ошибку в первоначальном подходе.
Если значение СпособРасчетов может меняться для одного и того же Контрагента в разных документах, то это свойство не должно быть дополнительным реквизитом самого справочника Контрагенты. Дополнительный реквизит справочника предполагает, что это свойство *присуще* контрагенту, является его постоянной или редко меняющейся характеристикой. Если же оно контекстно и зависит от документа, то это свойство скорее относится к *отношению* между документом и контрагентом, а не к контрагенту как таковому.
Разберем логику: СпособРасчетов в данном контексте — это параметр конкретной сделки (документа) с контрагентом. Поэтому ему самое место непосредственно в документе, возможно, с заполнением по умолчанию из какой-либо более общей настройки.
Предлагаем следующие шаги для рефакторинга:
Контрагенты (опционально). Если все же существует некий "стандартный" или "предпочтительный" способ расчетов для контрагента, который может служить значением по умолчанию, то можно создать обычный реквизит (не дополнительный) СпособРасчетовПоУмолчанию в справочнике Контрагенты с типом Перечисление.СпособыРасчетов. Это будет значение, которое система будет предлагать при выборе контрагента.
СпособРасчетовДокумента в нужную табличную часть документа с типом Перечисление.СпособыРасчетов. Это будет фактическое поле для выбора и хранения значения в конкретном документе.
СпособРасчетовДокумента значением из СпособРасчетовПоУмолчанию контрагента. Пользователь при необходимости сможет изменить это значение вручную.
СпособРасчетов в справочнике Контрагенты использовался только для этой цели и теперь его функции перенесены, его можно удалить. Предварительно необходимо перенести данные из него в новый реквизит справочника СпособРасчетовПоУмолчанию, если это необходимо.
Преимущества Решения 2:
Недостатки Решения 2:
Для тех, кто стремится максимально сохранить конфигурацию на поддержке и минимизировать прямые изменения, существует более продвинутый подход, основанный на использовании расширений 1С. Этот метод позволяет добавить функциональность, имитирующую дополнительные реквизиты в табличных частях, без изменения основной конфигурации.
Рассмотрим, как это работает в общих чертах. Стандартный механизм дополнительных реквизитов БСП не предназначен для табличных частей. Однако можно разработать свой собственный механизм. Расширение позволяет:
Такие решения обычно создают свою структуру для хранения данных, имитируя поведение дополнительных реквизитов. Например, расширение может добавить в документ новую табличную часть (ДополнительныеРеквизитыСтрок), в которой для каждой строки основной табличной части будут храниться связанные с ней дополнительные свойства. Либо же данные могут храниться в отдельном регистре сведений, где измерениями будут ссылка на документ, номер строки табличной части и ссылка на "свойство" (аналог предопределенного свойства дополнительного реквизита).
Как это работает в общих чертах:
Документ, НомерСтроки, ИмяРеквизита).
Этот подход достаточно гибок, поскольку позволяет определить, какие реквизиты могут быть добавлены, какие типы данных они могут хранить, и даже настроить их видимость и обязательность. Однако он значительно сложнее в реализации, чем первые два решения.
Преимущества Решения 3:
Недостатки Решения 3:
Важно не путать "дополнительные реквизиты" со "дополнительными сведениями". Хотя они оба служат для расширения свойств объектов, их предназначение и реализация различны.
Дополнительные сведения (также функционал БСП) предназначены для хранения информации об объекте, которая не является его неотъемлемой частью. Они обычно хранятся в отдельном регистре сведений и редактируются в отдельной карточке или вкладке, а не прямо на форме объекта. Они не спроектированы для построчного заполнения в табличной части документа и не могут быть напрямую привязаны к конкретной строке. Поэтому для нашей задачи, где требуется указывать уникальное значение для каждой строки документа, механизм дополнительных сведений является менее подходящим.
Мы рассмотрели несколько подходов к решению задачи по добавлению изменяемого дополнительного реквизита контрагента в табличную часть документа в 1С. Каждый из них имеет свои преимущества и недостатки.
Подводя итог, мы можем сформулировать следующие рекомендации:
Важно всегда анализировать, является ли свойство неотъемлемой частью объекта (справочника, документа в целом) или относится к контексту его использования (конкретной строке табличной части, конкретному документу). Правильный выбор подхода на этапе проектирования значительно упростит дальнейшую разработку и поддержку системы.