Доброго времени суток всем участников данного форума!

Пишу самописную конфу, в 1с ещё новичок, но стараюсь.
Конфа для учёта медикаментов.
Есть регистр сведений, который хранит наименование препарата, номер партии, цену за штуку и цену за упаковку.
Есть документ прихода на склад. Где при выборе номенклатуры должна подтягиваться цена из регистра, подскажите как грамотнее реализовать?
Чот сильно туплю с запросом... Срез последних тут не нужен, т.к. цена фиксируется документом-регистратором, он же "документ основание". Т.е. для каждого документа хранится его цена по номенклатуре, временной отбор тут тоже не требуется.
Не пойму как связать регистратор, номерПартии и Наименование в запросе по каждой номенклатурной позиции...

Пока делаю так:

```1c
    &НаКлиенте
    Процедура НоменклатураНаименованиеПриИзменении(Элемент)
    СтрокаТЧ = Элементы.Номенклатура.ТекущиеДанные;
    СтрокаТЧ.ШтукВУпаковке = ПолучитьШтукВУпаковке(СтрокаТЧ.Наименование);
    СтрокаТЧ.ЦенаЭталон = ПолучитьЦенуИзРегистра(СтрокаТЧ.Наименование);
    КонецПроцедуры
```

и далее тупняк:

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

С запросами пока что плоховато дружу, ибо на просторах все всё делают по разному, а где изучить досканально синтаксис не знаю...

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

Всем заранее спасибо за помощь!
---
Вам нужна связь не только по номенклатуре но и по партии, поэтому в функцию должно быть три параметра, затем в запросе где связь тоже должна быть связь с партией

При этом Наименование - это ссылка на справочник а не строка!!!!!

```1c
    СтрокаТЧ.ЦенаЭталон = ПолучитьЦенуИзРегистра(СтрокаТЧ.Наименование, СтрокаТЧ.Партия, Объект.ДокументОснование);
```

```1c
    &НаСервереБезКонтекста
    Функция ПолучитьЦенуИзРегистра(Номенклатура, Партия, ДокументОснования)
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
    | Цена.Номенклатура,
    |Цена.Партия,
    |Цена.Регистратор,
    |Цена.ЦенаУпаковки
    | ИЗ РегистрСведений.ЦеныНоменклатуры КАК Цена
    |ГДЕ
    | Цена.Номенклатура = &Номенклатура И Цена.Партия = &Партия И Цена.Регистратор = &Регистратор"
    Запрос.УстановитьПараметры("Номенклатура", Номенклатура);
    Запрос.УстановитьПараметры("партия", Партия);
    Запрос.УстановитьПараметры("Регистратор", Регистратор);
    ВыборкаДетальныеЗаписи = Запрос.Выполнить().Выбрать();
    Если ВыборкаДетальныеЗаписи.Количество() = 0 Тогда
    Возврат 0
    ИНаче
    ВыборкаДетальныеЗаписи.Следубщий()
    Возврат ВыборкаДетальныеЗаписи.ЦенаУпаковки
    Конецесли
    КонецФункции
```
---
При выборе номенклатуры в тч, необходимо заполнить ее цену? так?
Если да то, необходимо из регистра сведений получать цену, при этом в запрос передать Значение номенклатуры из тч.
Примерно так.

```1c
    |Где РегситрСведений.Номенклатура = &номенкатура
    запрос.установитьпараметр("номенклатура" ТЧ.номенклатура)
```
---
Вам нужна связь не только по номенклатуре но и по партии, поэтому в функцию должно быть три параметра, затем в запросе где связь тоже должна быть связь с партией

При этом Наименование - это ссылка на справочник а не строка!!!!!

```1c
    СтрокаТЧ.ЦенаЭталон = ПолучитьЦенуИзРегистра(СтрокаТЧ.Наименование, СтрокаТЧ.Партия, Объект.ДокументОснование);
```

```1c
    &НаСервереБезКонтекста
    Функция ПолучитьЦенуИзРегистра(Номенклатура, Партия, ДокументОснования)
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
    | Цена.Номенклатура,
    |Цена.Партия,
    |Цена.Регистратор,
    |Цена.ЦенаУпаковки
    | ИЗ РегистрСведений.ЦеныНоменклатуры КАК Цена
    |ГДЕ
    | Цена.Номенклатура = &Номенклатура И Цена.Партия = &Партия И Цена.Регистратор = &Регистратор"
    Запрос.УстановитьПараметры("Номенклатура", Номенклатура);
    Запрос.УстановитьПараметры("партия", Партия);
    Запрос.УстановитьПараметры("Регистратор", Регистратор);
    ВыборкаДетальныеЗаписи = Запрос.Выполнить().Выбрать();
    Если ВыборкаДетальныеЗаписи.Количество() = 0 Тогда
    Возврат 0
    ИНаче
    ВыборкаДетальныеЗаписи.Следубщий()
    Возврат ВыборкаДетальныеЗаписи.ЦенаУпаковки
    Конецесли
    КонецФункции
```
---
Огромное спасибо за помощь!

Сделал так:

```1c
    &НаСервереБезКонтекста
    Функция ПолучитьЦенуИзРегистра(Номенклатура, Партия, Основание)
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
    | Цена.Номенклатура,
    |Цена.НомерПартии,
    |Цена.Регистратор,
    |Цена.ЦенаУпаковки
    | ИЗ РегистрСведений.ЦеныНоменклатуры КАК Цена
    |ГДЕ
    | Цена.Номенклатура = &Номенклатура И Цена.НомерПартии = &Партия И Цена.Регистратор = &Регистратор" ;
    Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
    Запрос.УстановитьПараметр("партия", Партия);
    Запрос.УстановитьПараметр("Регистратор", Основание);
    ВыборкаДетальныеЗаписи = Запрос.Выполнить().Выбрать();
    Если ВыборкаДетальныеЗаписи.Количество() = 0 Тогда
    Возврат 0
    ИНаче
    ВыборкаДетальныеЗаписи.Следующий();
    Возврат ВыборкаДетальныеЗаписи.ЦенаУпаковки
    Конецесли
    КонецФункции
```

Теперь хоть заполнил пробелы в знаниях по объявлению и сбору параметров!
---
У вас немного не понятный подход.
Документ поставки записывает цену покупки, он не должен формировать цену продажи.
Продажная цена обычно формируется совершенно отдельным документом, УстановкаЦенНоменклатуры, в котором указывается цена , по которой товар будет продаваться, заполняется этот документ вполне и по закупочным ценам , скажем определённой наценкой.
Но цены закупки и продажи должны быть разделены. Иначе у вас будет один и тот же товар иметь совершенно различную цену в кассе, что является абсурдом.
То есть 1 бутылка за 100р вторая такая же за 200 а третья такая же за 50.
Покупатель будет счастлив
---
согласен, подход не понятный, сейчас поясню:
мы ничего не продаём, организация - больница.
нам нужен учёт между отделениями/постами/складом и заказ по ШК.

цена привязывается к документуОснованию, в нём она статична у каждой номенклатурной позиции.
Кассы у нас нет, цену я хочу подтянуть для сравнения в документах прихода.
Чтобы она не расходилась со спецификацией в контракте на поставку и в документах прихода. Поставщики так любят чудить, а ещё они любят в одну спецификацию хреначить одинаковую номенклатуру по разной цене(для этого и сделана разбивка на партии).

Нужно ещё какую-то схему проверки цен замутить в этом документе, не решил ещё как...
---
Но вы можете и без запроса все это сделать (только в том случае если документ основание - это измерение)

Отбор = Новый Структура("Номенклатура, Партия, ДокументОснование", СтрокаТЧ.Наименование, СтрокаТЧ.Партия, Объект.ДокументОснование);
СрезПоследний = РегистрыСведений.ЦеныНоменклатуры.СрезПоследних(Дата, Отбор);
Цена = СрезПоследний.ЦенаЗаУпаковку;
---
нет, документ основание является регистратором(решил что не к чему плодить колонки с одинаковыми данными)
---
Ну тут возможно даже и проще будет

```1c
    Выборка = РегистрыСведений.РегистрСведений1.ВыбратьПоРегистратору(Объект.ДокументОснование);
    Пока Выборка.Следующий() Цикл
    Отбор = Новый Структура("Номенклатура, Партия, ", СтрокаТЧ.Наименование, СтрокаТЧ.Партия);
    СтрокиТаблицы = Объект.ТабличнаяЧасть.НайтиСтроки(Отбор);
    Для Каждого СтрокаТаблицы Из СтрокиТаблицы Цикл
    ЦенаУпаковки = СтрокаТаблицы.ЦенаУпаковки
    Конеццикла
    Конеццикла
```

Соответственно можно все запросом сделать, установив параметры на номенклатуру, партию, регистратор
---
это просто в тело процедуры можно поместить? не совсем не пойму куда...
---
Ну вот смотрите у вас событие возникает когда вы меняете номенклатуру

Первый вариант

```1c
    &НаКлиенте
    Процедура НоменклатураНаименованиеПриИзменении(Элемент)
    СтрокаТЧ = Элементы.Номенклатура.ТекущиеДанные;
    СтрокаТЧ.ШтукВУпаковке = ПолучитьШтукВУпаковке(СтрокаТЧ.Наименование);
    СтрокаТЧ.ЦенаЭталон = ПолучитьЦенуИзРегистра(СтрокаТЧ.Наименование, СтрокаТЧ.Партия);
    КонецПроцедуры

    &НаСервереБезКонтекста
    Функция ПолучитьЦенуИзРегистра(Номенклатура, Партия)
    Цена = 0;
    Выборка = РегистрыСведений.РегистрСведений1.ВыбратьПоРегистратору(Объект.ДокументОснование);
    Пока Выборка.Следующий() Цикл
    Если Выборка.Номенклатура = Номенклатура И Выборка.Партия = Партия Тогда
    Цена = Выборка.ЦенаУпаковки;
    Прервать
    Конеццикла
    Возврат Цена

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

Второй вариант

```1c
    &НаКлиенте
    Процедура НоменклатураНаименованиеПриИзменении(Элемент)
    СтрокаТЧ = Элементы.Номенклатура.ТекущиеДанные;
    СтрокаТЧ.ШтукВУпаковке = ПолучитьШтукВУпаковке(СтрокаТЧ.Наименование);
    СтрокаТЧ.ЦенаЭталон = ПолучитьЦенуИзРегистра(СтрокаТЧ.Наименование, СтрокаТЧ.Партия, Объект.ДокументОснование);
    КонецПроцедуры

    &НаСервереБезКонтекста
    Функция ПолучитьЦенуИзРегистра(Номенклатура, Партия, ДокументОснования)
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
    | Цена.Номенклатура,
    |Цена.Партия,
    |Цена.Регистратор,
    |Цена.ЦенаУпаковки
    | ИЗ РегистрСведений.ЦеныНоменклатуры КАК Цена
    |ГДЕ
    | Цена.Номенклатура = &Номенклатура И Цена.Партия = &Партия И Цена.Регистратор = &Регистратор"
    Запрос.УстановитьПараметры("Номенклатура", Номенклатура);
    Запрос.УстановитьПараметры("партия", Партия);
    Запрос.УстановитьПараметры("Регистратор", ДокументОснования);
    ВыборкаДетальныеЗаписи = Запрос.Выполнить().Выбрать();
    Если ВыборкаДетальныеЗаписи.Количество() = 0 Тогда
    Возврат 0
    ИНаче
    ВыборкаДетальныеЗаписи.Следубщий()
    Возврат ВыборкаДетальныеЗаписи.ЦенаУпаковки
    Конецесли
    КонецФункции
```
---
круто, даже и не знал что можно без запроса, спасибо за ликбез!

Может подскажете ещё как лучше сделать сравнение эталонной цены с тем, что оператор вобьёт?

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

Сделал вот так проверку:

```1c
    &НаСервере
    Процедура ОбработкаПроверкиЗаполненияНаСервере(Отказ, ПроверяемыеРеквизиты)
    Для Каждого ТекСтрока из Объект.Номенклатура Цикл
    Если ТекСтрока.ЦенаВерна = Ложь Тогда
    Отказ = Истина;
    Сообщить("Цена в спецификации отличается от цены прихода!");
    КонецЕсли
    КонецЦикла
    КонецПроцедуры
```
---
Ведь вам нужно всего лишь сделать проверку. В хорошем ведь случае когда все хорошо данный реквизит будет иметь постоянное значение ЦенаВерна - истина. Если вам нужно только лишь для проверки то лучше не добавлять все таки реквизит а проверять. Вот представьте вам нужно проверить реквизит ДокументоОснования - вы ведь для этого не будете делать доп. реквизит ДокументОснованиеЗаполнено с типом булево. Так что смотрите как вам будет удобнее. Конечно можно и с реквизитом и без реквизита
---
я не делаю реквизит документа, я делаю реквизит формы, по сути он нигде не хранится, а нужен только для отображения корректности цены по текущей строке
---
аааа ну если так,то я думаю как бы да тоже не плохой и при этом наглядный вариант - то есть пользователь видит верна цена или нет
---
спасибо )
---
Сделал так пока что:

```1c
    &НаКлиенте
    Процедура НоменклатураСтоимостьОднойУпаковкиПриИзменении(Элемент)
    СтрокаТЧ = Элементы.Номенклатура.ТекущиеДанные;
    СтрокаТЧ.Сумма = СтрокаТЧ.СтоимостьОднойУпаковки * СтрокаТЧ.КоличествоУпаковок;
    Если СтрокаТЧ.СтоимостьОднойУпаковки = СтрокаТЧ.ЦенаЭталон Тогда
    СтрокаТЧ.ЦенаВерна = Истина
    Иначе
    СтрокаТЧ.ЦенаВерна = Ложь
    КонецЕсли
    КонецПроцедуры
```
---
В типовой есть скидка, обычно ее меняют при фиксированной цене прайс листа. Цену со скидкой можно вычислять в отдельной колонке.
---
мы не торгуем, а соответственно скидки не вводим, поэтому не актуально...