| Код &НаКлиенте Процедура ОсновноеКонтактноеЛицоПриИзменении(Элемент) Если НЕ ПроверитьЗаполнениеРеквизита() Тогда Сообщить("Выбранное контактное лицо, "+Объект.ОсновноеКонтактноеЛицо+",не работает у контрагента."); КонецЕсли; КонецПроцедуры 
 &НаСервере Функция ПроверитьЗаполнениеРеквизита() Возврат (Объект.ОсновноеКонтактноеЛицо.ПредставительРаботает); КонецФункции &НаСервере Процедура УстановитьНомерПредставителя() 
 Объект.ТелефонКонтактногоЛица=Объект.ОсновноеКонтактноеЛицо.КонтактныеСведения; КонецПроцедуры При проверке выдает ошибку: {Справочник.Контрагенты.Форма.ФормаСписка.Форма(12,11)}: Переменная не определена (Объект) 
 работаю на версии 1С:Предприятие 8.3 (8.3.10.2650) | 
Оборотные регистры накопления, последовательности, нумераторы, регистры сведений
Займемся теперь кодом модуля РассчитатьНаСервере(). Воспользуемся конструктором запросов с обработкой результатов для того, чтобы перенести сформированный в консоли текст запроса в код модуля.
В итоге задачу заполнения табличной части данными мы решили следующим образом:
&НаКлиенте
Процедура РассчитатьСебестоимостьИОстатки(Команда)
  Режим=РежимДиалогаВопрос.ДаНет;
  Ответ=Вопрос("Для продолжения нужно записать документ. Сделать это?",Режим,0);
  Если Ответ=КодВозвратаДиалога.Да Тогда
    Записать();
    РассчитатьНаСервере();
    Предупреждение("Табличная часть заполнена");
  Иначе
    Предупреждение("Табличная часть не заполнена");
  КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура РассчитатьНаСервере()
  Запрос = Новый Запрос;
  Запрос.Текст = 
    "ВЫБРАТЬ
    |  ДокМ.Номенклатура,
    |  ЕСТЬNULL(ОстМ.КоличествоОстаток, 0) КАК КоличествоОстатков,
    |  ЕСТЬNULL(ОстМ.СуммаОстаток, 0) КАК СуммаОстатков,
    |  ДокМ.Количество,
    |  ДокМ.ЦенаПродажи,
    |  ДокМ.Выручка
        |ИЗ
    |  Документ.РеализацияМатериалов.Материалы КАК ДокМ
    |    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиМатериалов.Остатки(&МоментВремени, ОтветственныйСотрудник = &ОтвСотр) КАК ОстМ
    |    ПО ДокМ.Номенклатура = ОстМ.Номенклатура
    |ГДЕ
    |  ДокМ.Ссылка = &Ссылка";
  Запрос.УстановитьПараметр("МоментВремени", Объект.Ссылка.МоментВремени());
  Запрос.УстановитьПараметр("ОтвСотр", Объект.ОтветственныйСотрудник);
  Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);
  Результат = Запрос.Выполнить();
  
  ВыборкаДетальныеЗаписи = Результат.Выбрать();
  
  Объект.Материалы.Очистить();
  Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    СтрокаТЧ=Объект.Материалы.Добавить();
    СтрокаТЧ.Номенклатура = ВыборкаДетальныеЗаписи.Номенклатура;
    Если НЕ  ВыборкаДетальныеЗаписи.КоличествоОстатков=0 Тогда
      СтрокаТЧ.Себестоимость=ВыборкаДетальныеЗаписи.СуммаОстатков/
      ВыборкаДетальныеЗаписи.КоличествоОстатков;
    КонецЕсли;
    СтрокаТЧ.Остаток=ВыборкаДетальныеЗаписи.КоличествоОстатков;
    СтрокаТЧ.Количество=ВыборкаДетальныеЗаписи.Количество;
    СтрокаТЧ.ЦенаПродажи=ВыборкаДетальныеЗаписи.ЦенаПродажи;
    СтрокаТЧ.Выручка=ВыборкаДетальныеЗаписи.Выручка;
  КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура РассчитатьСумму()
  ТекущаяСтрока=Элементы.Материалы.ТекущиеДанные;
  ТекущаяСтрока.Выручка=ТекущаяСтрока.Количество*ТекущаяСтрока.ЦенаПродажи;
КонецПроцедуры
&НаКлиенте
Процедура МатериалыКоличествоПриИзменении(Элемент)
  РассчитатьСумму();
КонецПроцедуры
&НаКлиенте
Процедура МатериалыЦенаПродажиПриИзменении(Элемент)
  РассчитатьСумму();
КонецПроцедурыВ методе, работающем на клиенте, мы, сразу после запуска, сообщаем пользователю о том, что для правильной работы системы нужно сначала записать документ. Если он отвечает утвердительно – записываем документ и вызываем серверную процедуру. Для задавания подобных вопросов в виде диалоговых окон с кнопками-вариантами вопроса ( рис. 8.4.), используется метод Вопрос().
В серверной процедуре мы выбираем с помощью запроса данные из табличной части нашего документа и из регистра ОстаткиМатериалов. Когда данные получены, мы просто очищаем табличную часть и заполняем ее снова, теперь уже с использованием новых данных.
В итоге, после того, как пользователь заполнил табличную часть документа и нажал на кнопку Рассчитать себестоимость и остатки, он получит примерно следующее, рис. 8.5.
Поля Остаток и Себестоимость в данном случае играют лишь вспомогательную роль, позволяя пользователю сразу, при заполнении документа, понять, каково состояние дел с остатками материалов.
Форму документа, да и процедуру заполнения, можно дорабатывать и оптимизировать, но свои основные функции они выполняют, поэтому теперь займемся конструированием оборотного регистра накопления, в котором мы собираемся хранить сведения о продажах. А именно, нас интересуют данные о номенклатуре, о контрагенте, об ответственном лице, продавшем материалы, о количестве, себестоимости и цене материалов.
Создадим новый регистр накопления, назовем его Продажи. Вид регистра установим в значение Обороты, рис. 8.6. Включим его в состав подсистемы ОперативныйУчетМатериалов.
В состав данных регистра, рис. 8.7., внесем следующие:
Измерения:
Имя: Контрагент, тип: СправочникСсылка.Контрагенты
Имя: ОтветственныйСотрудник, тип: СправочникСсылка.Сотрудники
Имя: Номенклатура, тип: СправочникСсылка.Номенклатура
Ресурсы:
Имя: Себестоимость, тип: Число, длина 10, точность 2
Имя: Количество, тип: Число, длина 10, точность 3
Имя: Выручка, тип: Число, длина 10, точность 2
В качестве регистратора для данного регистра выберем документ РеализацияМатериалов.
Теперь займемся проведением этого документа. Он должен формировать движения по двум регистрам – по регистру ОстаткиМатериалов, и по регистру Продажи.
Добавим в модуль объекта документа процедуру ОбработкаПроведения. При конструировании этой процедуры мы можем воспользоваться уже отработанными при проведении документа ОтпускМатериаловМастеру механизмами.
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
  Запрос = Новый Запрос;
  Запрос.Текст = 
    "ВЫБРАТЬ
    |  ДокМ.Номенклатура,
    |  СУММА(ДокМ.Количество) КАК Количество,
    |  СУММА(ДокМ.Выручка) КАК Выручка,
    |  МАКСИМУМ(ЕСТЬNULL(ОстМ.КоличествоОстаток, 0)) КАК КоличествоОстатков,
    |  МАКСИМУМ(ЕСТЬNULL(ОстМ.СуммаОстаток, 0)) КАК СуммаОстатков
    |ИЗ
    |  Документ.РеализацияМатериалов.Материалы КАК ДокМ
    |    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиМатериалов.Остатки(&МоментВремени, ОтветственныйСотрудник = &ОтвСотр) КАК ОстМ
    |    ПО ДокМ.Номенклатура = ОстМ.Номенклатура
    |ГДЕ
    |  ДокМ.Ссылка = &Ссылка
    |
    |СГРУППИРОВАТЬ ПО
    |  ДокМ.Номенклатура";
  Запрос.УстановитьПараметр("МоментВремени", МоментВремени());
  Запрос.УстановитьПараметр("ОтвСотр", ОтветственныйСотрудник);
  Запрос.УстановитьПараметр("Ссылка", Ссылка);
  Результат = Запрос.Выполнить();
  ВыборкаДЗ = Результат.Выбрать();
  Движения.ОстаткиМатериалов.Записывать=Истина;
  Движения.Продажи.Записывать=Истина;
  Пока ВыборкаДЗ.Следующий() Цикл
    Если ВыборкаДЗ.Количество>ВыборкаДЗ.КоличествоОстатков Тогда
      Сообщить("Недостаточное количество товара "+ВыборкаДЗ.Номенклатура
      +", необходимо "+ВыборкаДЗ.Количество+", в наличии "
      +ВыборкаДЗ.КоличествоОстатков);
      Отказ=Истина;
      Движения.ОстаткиМатериалов.Записывать=Ложь;
      Движения.Продажи.Записывать=Ложь;
    КонецЕсли;
    
    Если Отказ Тогда
      Продолжить;
    КонецЕсли;
    
    Движение=Движения.ОстаткиМатериалов.Добавить();
    Движение.ВидДвижения=ВидДвиженияНакопления.Расход;
    Движение.Период=Дата;
    Движение.Номенклатура=ВыборкаДЗ.Номенклатура;
    Движение.Количество=ВыборкаДЗ.Количество;
    Движение.Сумма=ВыборкаДЗ.Количество*ВыборкаДЗ.СуммаОстатков/ВыборкаДЗ.КоличествоОстатков;
    Движение.ОтветственныйСотрудник=ОтветственныйСотрудник;
        
    Движение=Движения.Продажи.Добавить();
    Движение.Период=Дата;
    Движение.Номенклатура=ВыборкаДЗ.Номенклатура;
    Движение.Количество=ВыборкаДЗ.Количество;
    Движение.Себестоимость=ВыборкаДЗ.Количество*ВыборкаДЗ.СуммаОстатков/ВыборкаДЗ.КоличествоОстатков;
    Движение.Выручка=ВыборкаДЗ.Выручка;
    Движение.ОтветственныйСотрудник=ОтветственныйСотрудник;
    Движение.Контрагент=Покупатель;
  КонецЦикла;
КонецПроцедурыТак, здесь мы, во-первых, проверим достаточность материалов для списания – ранее заполненная табличная часть, служит лишь подсказкой пользователю, к тому же, он может, в процессе работы, получать сведения об остатках и себестоимости единицы, а может и не получать, оставляя соответствующие поля табличной части пустыми, поэтому при проведении документа мы получим с помощью запроса нужные данные из базы.
Дальше все идет по уже знакомому вам плану – мы сверяем количество материалов, которое пользователь хочет продать с количеством остатков и принимаем решение либо о продолжении работы, либо – об отмене процедуры проведения документа.
После того, как у нас есть хранилище данных о продажах, мы построим соответствующий отчет. На базе тех данных, которые у нас есть, можно построить различные отчеты – все зависит от того, какие именно данные нас интересуют. Предположим, мы заинтересованы в сведениях о продажах по контрагентам. Нас интересует количественный показатель продажи номенклатурной позиции и прибыль от продажи.
 
                             




