Найти основной договор
Теги: 1С,БП3

# Код реализации

```1c
&НаСервере
Функция ПолучитьОсновнойДоговор(Организация, Контрагент, ВидДоговора)

	Рез = Справочники.ДоговорыКонтрагентов.ПустаяСсылка();

	Запрос = Новый Запрос;
	Запрос.Текст =
		"ВЫБРАТЬ ПЕРВЫЕ 1
		|	ОсновныеДоговорыКонтрагента.Договор КАК Договор
		|ИЗ
		|	РегистрСведений.ОсновныеДоговорыКонтрагента КАК ОсновныеДоговорыКонтрагента
		|ГДЕ
		|	ОсновныеДоговорыКонтрагента.Организация = &Организация
		|	И ОсновныеДоговорыКонтрагента.Контрагент = &Контрагент
		|	И ОсновныеДоговорыКонтрагента.ВидДоговора = &ВидДоговора";

	Запрос.УстановитьПараметр("ВидДоговора", ВидДоговора);
	Запрос.УстановитьПараметр("Контрагент", Контрагент);
	Запрос.УстановитьПараметр("Организация", Организация);

	РезультатЗапроса = Запрос.Выполнить();

	ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();

	Если ВыборкаДетальныеЗаписи.Следующий() Тогда
		Рез = ВыборкаДетальныеЗаписи.Договор;
	КонецЕсли;

	//если основной договор не отмечен, то поищем среди всех договоров и если по данному виду он один и непомеченный на удаление, то возьмем его

	Если Рез.Пустая() Тогда
		Запрос.Текст =
			"ВЫБРАТЬ
			|	МАКСИМУМ(ДоговорыКонтрагентов.Ссылка) КАК Договор,
			|	КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ДоговорыКонтрагентов.Ссылка) КАК КоличествоДоговоров
			|ИЗ
			|	Справочник.ДоговорыКонтрагентов КАК ДоговорыКонтрагентов
			|ГДЕ
			|	ДоговорыКонтрагентов.Владелец = &Контрагент
			|	И ДоговорыКонтрагентов.ВидДоговора = &ВидДоговора
			|	И ДоговорыКонтрагентов.Организация = &Организация
			|	И НЕ ДоговорыКонтрагентов.ПометкаУдаления";

		Запрос.УстановитьПараметр("ВидДоговора", ВидДоговора);
		Запрос.УстановитьПараметр("Контрагент", Контрагент);
		Запрос.УстановитьПараметр("Организация", Организация);

		РезультатЗапроса = Запрос.Выполнить();
		ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();

		Если ВыборкаДетальныеЗаписи.Следующий() Тогда
			Если ВыборкаДетальныеЗаписи.КоличествоДоговоров=1 Тогда
				Рез = ВыборкаДетальныеЗаписи.Договор;
			ИначеЕсли ВыборкаДетальныеЗаписи.КоличествоДоговоров=0 Тогда
				Рез = СоздатьОсновнойДоговор(Организация, Контрагент, ВидДоговора);
			ИначеЕсли ВыборкаДетальныеЗаписи.КоличествоДоговоров>1 Тогда
				Рез = ВыборкаДетальныеЗаписи.Договор;
				ТекстОшибки = СтрШаблон("Для контрагента %1 подставлен первый договор из нескольких по виду %2 для организации %3", Контрагент, ВидДоговора, Организация);
				ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстОшибки);
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;

	Возврат Рез;

КонецФункции
```

# Примечания

- Думаяю что выборку из первого запроса можно не обходить, если сперва проверить результат первого запроса на пустату, ну и ИМХО я бы выполнил запросы в пакете, вроде как чтоб два раза на СУБД не обращатся.

- (1) tka4enk0.ilya, а мне два запроса читабельнее

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