Здравствуйте, создал внешнюю обработку, которая позволяет отобрать документы за указанный пользователем период. Теперь надо сделать кнопку, которая позволяет перерасчитать скидку в документах, выбранных флажком и перепровести их. Столкнулся с большим количеством ошибок. Прошу помочь доделать код. Прикрепляю скриншот с формой и мой код:

```1c
    &НаКлиенте
    Процедура Сформировать(Команда)

    СформироватьНаСервере();
    КонецПроцедуры

    &НаСервере
    Процедура СформироватьНаСервере ()
    Запрос=Новый Запрос;

    Запрос.УстановитьПараметр("ДатаНачала",НачалоДня(ДатаНачала));
    Запрос.УстановитьПараметр("ДатаОкончания",КонецДня(ДатаОкончания));

    Запрос.Текст="ВЫБРАТЬ
    | ОказаниеУслуги.Ссылка КАК Ссылка
    |ИЗ
    | Документ.ОказаниеУслуги КАК ОказаниеУслуги
    |ГДЕ
    | ОказаниеУслуги.Дата >= &ДатаНачала
    | И ОказаниеУслуги.Дата <= &ДатаОкончания";

    Результат = Запрос.Выполнить();
    ТаблицаДокументов = Результат.Выгрузить();
    Наименования.Загрузить(ТаблицаДокументов);

    КонецПроцедуры

    &НаСервере
    Процедура ПерерасчетСкидкиНаСервере()

    Для каждого Стр Из Наименования Цикл
    ГалочкаДаНет = Стр.Галочка;
    Если ГалочкаДаНет = истина Тогда
    ДокОбъект = Стр.Ссылка.ПолучитьОбъект();
    ДокОбъект.Скидка = РаботаСоСправочниками.РассчетСкидки(ДокОбъект.Клиент);
    Если ДокОбъект.Скидка <> 0 Тогда
    ДокОбъект.Сумма = ДокОбъект.Сумма*(100 - ДокОбъект.Скидка)/100;
    КонецЕсли
    КонецЕсли

    КонецЦикла;

    КонецПроцедуры

    &НаКлиенте
    Процедура ПерерасчетСкидки(Команда)
    ПерерасчетСкидкиНаСервере();
    КонецПроцедуры
```

На этом этапе столкнулся с тем, что поле объекта скидка не обнаружено, хотя оно является табличной частью документа ОказаниеУслуги. Также не уверен в правильности передавания фукции значения поля клиент. Заранее спасибо!
---
Null - это отдельный тип. Добро пожаловать в программирование!))))
---
Покажите какие там реквизиты и табличные части в документе ОказаниеУслуги (можно скрин)
---
Ясно. У документа нет реквизитов Скидка и сумма, они в табличной части. То есть надо в цикле к каждой строке ТЧ ПереченьНоменклатуры обращаться и там прописывать сумму и скидку. Примерно так:

```1c
    Скидка = РаботаСоСправочниками.РассчетСкидки(ДокОбъект.Клиент);
    Для Каждого Стр Из ПереченьНоменклатуры Цикл
    Стр.Скидка = Скидка;
    Если Скидка <> 0 Тогда
    Стр.Сумма = (Стр.Цена*Стр.Количество) *(100 - Скидка)/100;
    КонецЕсли
    КонецЦикла;
```

Обратите внимание, в коде пересчитал сумму заново, чтобы при повторном назначении скидки она у вас не уехала.
---
Потому что Вы вычислили выражение ДокОбъект = Стр.Ссылка.ПолучитьОбъект() , надо было смотреть просто ДокОбъект и точку ставить после присвоения.
---
```1c
    Для Каждого Стр Из ДокОбъект.ПереченьНоменклатуры Цикл
```
---
Не понял, что привести к числовому типу? Скидку?
---
Ок, допустим цена и сумма - это числа (но все равно проверьте в конфигураторе). Что со скидкой? Код функции РаботаСоСправочниками.РассчетСкидки в студию.
---
Вроде норм, хотя скидки лучше было делать периодическим регистром сведений. Если Стр.Цена,Стр.Количество и Скидка - числа, то не понятно что там ещё преобразовывать, а в отладке если вычислить (Стр.Цена*Стр.Количество) *(100 - Скидка)/100 ? Поиграйте в отладчике с этим выражением, может поймете в чем ошибка...
---
Понял, возможно выборка пустая. Попробуйте

```1c
    ...
    Результат = Запрос.Выполнить();
    Если Результат.Пустой() Тогда
    Возврат 0;
    КонецЕсли;
    Выборка = Результат.Выбрать();
    ...
```
---
ДокОбъект.Записать(РежимзаписиДокумента.Проведение); Это после цикла изменения табличной части. Выше строчку ДокОбъект.Записать(); надо убрать.
---
поле объекта скидка не обнаружено, хотя оно является табличной частью документа ОказаниеУслуги

оно является табличной частью документа или реквизитом табличной части документа? Если это табличная часть, то странно сравнивать её потом с нулём
---
скорее всего не обнаруженное поле - это реквизит формы, который важен для расчетов на клиенте, а в самом объекте такого реквизита нет.
---
Так расчеты же на сервере происходят, и я в саму форму же не хочу ничего вносить, а только влезть в документы, которые она отобрала.
---
мне лень вести дискуссию с тем - кто не понимает с чем он имеет дело.
---
Можете пожалуйста подсказать, где поискать информацию, чтобы восполнить пробел?
---
извините, я могу только с ...вертухи
---
Можно использовать отладчик.
Поставить точку остановки на строке ДокОбъект = Стр.Ссылка.ПолучитьОбъект();
и потом просмотреть значение ДокОбъект и всех реквизитов этого объекта. Там можно определить что есть и чего нет и так далее
---
Мда, вам сначала курить самые основы работы с объектами БД и их табличными частями, которые собственно тоже объекты, а не внешние обработки.
---
Да я знаю, недели 2 1с занимаюсь, на работе дали книгу и решать задачки посадили, а то, что не понимаю не объясняют(
---
это такой метод обучения дать задачи и ничего не объяснить, примерно как в спецназе,
в кино видел....
кинут в с вертухи в море километров за 20 от берегов и кто приплыл - тот и сдал зачет.
---
С каждым днем мне становиться очевидно, что развитие технологий идет быстрее чем массово "зреют" мозги
для их использования.

Рано или поздно это приведет к краху самих технологий (в) типа Ванга
---
Покажите какие там реквизиты и табличные части в документе ОказаниеУслуги (можно скрин)
---
Ясно. У документа нет реквизитов Скидка и сумма, они в табличной части. То есть надо в цикле к каждой строке ТЧ ПереченьНоменклатуры обращаться и там прописывать сумму и скидку. Примерно так:

```1c
    Скидка = РаботаСоСправочниками.РассчетСкидки(ДокОбъект.Клиент);
    Для Каждого Стр Из ПереченьНоменклатуры Цикл
    Стр.Скидка = Скидка;
    Если Скидка <> 0 Тогда
    Стр.Сумма = (Стр.Цена*Стр.Количество) *(100 - Скидка)/100;
    КонецЕсли
    КонецЦикла;
```

Обратите внимание, в коде пересчитал сумму заново, чтобы при повторном назначении скидки она у вас не уехала.
---
```1c
    &НаСервере
    Процедура ПерерасчетСкидкиНаСервере()

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

    Стр.Скидка = Скидка;
    Если Скидка <> 0 Тогда
    Стр.Сумма = (Стр.Цена*Стр.Количество) *(100 - Скидка)/100;
    КонецЕсли
    КонецЦикла;

    КонецЕсли

    КонецЦикла;

    КонецПроцедуры
```

Не определяет теперь переменную переченьНоменклатуры(
---
```1c
    Для Каждого Стр Из ДокОбъект.ПереченьНоменклатуры Цикл
```
---
Теперь все вычисляется, но не может привестись к числовому типу, везде булево почему то
---
Не понял, что привести к числовому типу? Скидку?
---
Просмотрел с помощью точки останова все и оказалось на этом моменте получается значение ложь.

```1c
    ДокОбъект = Стр.Ссылка.ПолучитьОбъект();
```
---
Потому что Вы вычислили выражение ДокОбъект = Стр.Ссылка.ПолучитьОбъект() , надо было смотреть просто ДокОбъект и точку ставить после присвоения.
---
Вот такую ошибку выдает просто
---
Ок, допустим цена и сумма - это числа (но все равно проверьте в конфигураторе). Что со скидкой? Код функции РаботаСоСправочниками.РассчетСкидки в студию.
---
Проверил, тип у всех 3 число вот функция:

```1c
    ФУНКЦИЯ РассчетСкидки(Клиент) экспорт
    ДатаНачала = НачалоМесяца(ДобавитьМесяц(ТекущаяДата(), -1));
    ДатаОкончания = КонецМесяца(ДобавитьМесяц(ТекущаяДата(), -1));
    ОборотКлиента = РегистрыНакопления.Продажи.Обороты(ДатаНачала, ДатаОкончания, Новый Структура("Клиент", Клиент),"Клиент","Выручка");
    //{{КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
    // Данный фрагмент построен конструктором.
    // При повторном использовании конструктора, внесенные вручную изменения будут утеряны!!!
    Если ОборотКлиента.Количество() <> 0 Тогда
    ЗначениеОборота = ОборотКлиента[0].Выручка;
    Иначе
    ЗначениеОборота = 0;
    КонецЕсли;
    Запрос = Новый Запрос;
    Запрос.УстановитьПараметр("ОЗ",ЗначениеОборота);
    Запрос.Текст ="ВЫБРАТЬ ПЕРВЫЕ 1
    | Скидки.ОбъемЗакупки КАК ОбъемЗакупки,
    | Скидки.ПроцентСкидки КАК ПроцентСкидки
    |ИЗ
    | Справочник.Скидки КАК Скидки
    |ГДЕ
    | Скидки.ОбъемЗакупки <= &ОЗ
    |
    |УПОРЯДОЧИТЬ ПО
    | ОбъемЗакупки УБЫВ";

    Выборка = Запрос.Выполнить().Выбрать();
    Выборка.Следующий();
    ЗначениеПроцентаСкидки = Выборка.ПроцентСкидки;
    Возврат ЗначениеПроцентаСкидки;
    КонецФункции
```
---
Вроде норм, хотя скидки лучше было делать периодическим регистром сведений. Если Стр.Цена,Стр.Количество и Скидка - числа, то не понятно что там ещё преобразовывать, а в отладке если вычислить (Стр.Цена*Стр.Количество) *(100 - Скидка)/100 ? Поиграйте в отладчике с этим выражением, может поймете в чем ошибка...
---
Понял, возможно выборка пустая. Попробуйте

```1c
    ...
    Результат = Запрос.Выполнить();
    Если Результат.Пустой() Тогда
    Возврат 0;
    КонецЕсли;
    Выборка = Результат.Выбрать();
    ...
```
---
(24
(25) Если Результат.Пустой() Тогда
Возврат 0;
КонецЕсли;

Подставил условие, вылезла ошибка, что процедура не может возвращать 0. А все не туда подставил извиняюсь
---
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Возврат 0;
КонецЕсли;
Выборка = Результат.Выбрать();

Дааааа получилось, спасибо большое, а это было потому что Null не является типом число?
---
Null - это отдельный тип. Добро пожаловать в программирование!))))
---
Можете еще 1 подсказочку дать пожалуйста, осталось сделать только перепроведение, но я понятия не имею, что надо написать для этого)
---
ДокОбъект.Записать(РежимзаписиДокумента.Проведение); Это после цикла изменения табличной части. Выше строчку ДокОбъект.Записать(); надо убрать.
---
Спасибо огромное - очень помогли разобраться!
---
Отладчик рекомендую использовать для просмотра состояния переменных исполнения и объектов и так далее
Ставьте точки остановки в тексте модулей и потом пошагово выполняйте текст программы и просматривайте состояние переменных