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