Опубликован: 06.12.2011 | Уровень: для всех | Доступ: свободно
Лекция 9:

Оборотные регистры накопления, последовательности, нумераторы, регистры сведений

Займемся теперь кодом модуля РассчитатьНаСервере(). Воспользуемся конструктором запросов с обработкой результатов для того, чтобы перенести сформированный в консоли текст запроса в код модуля.

В итоге задачу заполнения табличной части данными мы решили следующим образом:

&НаКлиенте
Процедура РассчитатьСебестоимостьИОстатки(Команда)
  Режим=РежимДиалогаВопрос.ДаНет;
  Ответ=Вопрос("Для продолжения нужно записать документ. Сделать это?",Режим,0);
  Если Ответ=КодВозвратаДиалога.Да Тогда
    Записать();
    РассчитатьНаСервере();
    Предупреждение("Табличная часть заполнена");
  Иначе
    Предупреждение("Табличная часть не заполнена");
  КонецЕсли;
КонецПроцедуры

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

  Запрос.УстановитьПараметр("МоментВремени", Объект.Ссылка.МоментВремени());
  Запрос.УстановитьПараметр("ОтвСотр", Объект.ОтветственныйСотрудник);
  Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);

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

  Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    СтрокаТЧ=Объект.Материалы.Добавить();
    СтрокаТЧ.Номенклатура = ВыборкаДетальныеЗаписи.Номенклатура;
    Если НЕ  ВыборкаДетальныеЗаписи.КоличествоОстатков=0 Тогда
      СтрокаТЧ.Себестоимость=ВыборкаДетальныеЗаписи.СуммаОстатков/
      ВыборкаДетальныеЗаписи.КоличествоОстатков;
    КонецЕсли;
    СтрокаТЧ.Остаток=ВыборкаДетальныеЗаписи.КоличествоОстатков;
    СтрокаТЧ.Количество=ВыборкаДетальныеЗаписи.Количество;
    СтрокаТЧ.ЦенаПродажи=ВыборкаДетальныеЗаписи.ЦенаПродажи;
    СтрокаТЧ.Выручка=ВыборкаДетальныеЗаписи.Выручка;
  КонецЦикла;
КонецПроцедуры

&НаКлиенте
Процедура РассчитатьСумму()
  ТекущаяСтрока=Элементы.Материалы.ТекущиеДанные;
  ТекущаяСтрока.Выручка=ТекущаяСтрока.Количество*ТекущаяСтрока.ЦенаПродажи;
КонецПроцедуры

&НаКлиенте
Процедура МатериалыКоличествоПриИзменении(Элемент)
  РассчитатьСумму();
КонецПроцедуры

&НаКлиенте
Процедура МатериалыЦенаПродажиПриИзменении(Элемент)
  РассчитатьСумму();
КонецПроцедуры

В методе, работающем на клиенте, мы, сразу после запуска, сообщаем пользователю о том, что для правильной работы системы нужно сначала записать документ. Если он отвечает утвердительно – записываем документ и вызываем серверную процедуру. Для задавания подобных вопросов в виде диалоговых окон с кнопками-вариантами вопроса ( рис. 8.4.), используется метод Вопрос().

Вопрос пользователю

Рис. 8.4. Вопрос пользователю

В серверной процедуре мы выбираем с помощью запроса данные из табличной части нашего документа и из регистра ОстаткиМатериалов. Когда данные получены, мы просто очищаем табличную часть и заполняем ее снова, теперь уже с использованием новых данных.

В итоге, после того, как пользователь заполнил табличную часть документа и нажал на кнопку Рассчитать себестоимость и остатки, он получит примерно следующее, рис. 8.5.

Результат автоматического заполнения табличной части

увеличить изображение
Рис. 8.5. Результат автоматического заполнения табличной части

Поля Остаток и Себестоимость в данном случае играют лишь вспомогательную роль, позволяя пользователю сразу, при заполнении документа, понять, каково состояние дел с остатками материалов.

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

Создадим новый регистр накопления, назовем его Продажи. Вид регистра установим в значение Обороты, рис. 8.6. Включим его в состав подсистемы ОперативныйУчетМатериалов.

Создание регистра накопления

Рис. 8.6. Создание регистра накопления

В состав данных регистра, рис. 8.7., внесем следующие:

Измерения:

Имя: Контрагент, тип: СправочникСсылка.Контрагенты

Имя: ОтветственныйСотрудник, тип: СправочникСсылка.Сотрудники

Имя: Номенклатура, тип: СправочникСсылка.Номенклатура

Ресурсы:

Имя: Себестоимость, тип: Число, длина 10, точность 2

Имя: Количество, тип: Число, длина 10, точность 3

Имя: Выручка, тип: Число, длина 10, точность 2

Настройка данных регистра накопления

Рис. 8.7. Настройка данных регистра накопления

В качестве регистратора для данного регистра выберем документ РеализацияМатериалов.

Теперь займемся проведением этого документа. Он должен формировать движения по двум регистрам – по регистру ОстаткиМатериалов, и по регистру Продажи.

Добавим в модуль объекта документа процедуру ОбработкаПроведения. При конструировании этой процедуры мы можем воспользоваться уже отработанными при проведении документа ОтпускМатериаловМастеру механизмами.

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

  Запрос.УстановитьПараметр("МоментВремени", МоментВремени());
  Запрос.УстановитьПараметр("ОтвСотр", ОтветственныйСотрудник);
  Запрос.УстановитьПараметр("Ссылка", Ссылка);

  Результат = Запрос.Выполнить();
  ВыборкаДЗ = Результат.Выбрать();
  Движения.ОстаткиМатериалов.Записывать=Истина;
  Движения.Продажи.Записывать=Истина;

  Пока ВыборкаДЗ.Следующий() Цикл
    Если ВыборкаДЗ.Количество>ВыборкаДЗ.КоличествоОстатков Тогда
      Сообщить("Недостаточное количество товара "+ВыборкаДЗ.Номенклатура
      +", необходимо "+ВыборкаДЗ.Количество+", в наличии "
      +ВыборкаДЗ.КоличествоОстатков);
      Отказ=Истина;
      Движения.ОстаткиМатериалов.Записывать=Ложь;
      Движения.Продажи.Записывать=Ложь;
    КонецЕсли;
    
    Если Отказ Тогда
      Продолжить;
    КонецЕсли;
    
    Движение=Движения.ОстаткиМатериалов.Добавить();
    Движение.ВидДвижения=ВидДвиженияНакопления.Расход;
    Движение.Период=Дата;
    Движение.Номенклатура=ВыборкаДЗ.Номенклатура;
    Движение.Количество=ВыборкаДЗ.Количество;
    Движение.Сумма=ВыборкаДЗ.Количество*ВыборкаДЗ.СуммаОстатков/ВыборкаДЗ.КоличествоОстатков;
    Движение.ОтветственныйСотрудник=ОтветственныйСотрудник;
        
    Движение=Движения.Продажи.Добавить();
    Движение.Период=Дата;
    Движение.Номенклатура=ВыборкаДЗ.Номенклатура;
    Движение.Количество=ВыборкаДЗ.Количество;
    Движение.Себестоимость=ВыборкаДЗ.Количество*ВыборкаДЗ.СуммаОстатков/ВыборкаДЗ.КоличествоОстатков;
    Движение.Выручка=ВыборкаДЗ.Выручка;
    Движение.ОтветственныйСотрудник=ОтветственныйСотрудник;
    Движение.Контрагент=Покупатель;
  КонецЦикла;
КонецПроцедуры

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

Дальше все идет по уже знакомому вам плану – мы сверяем количество материалов, которое пользователь хочет продать с количеством остатков и принимаем решение либо о продолжении работы, либо – об отмене процедуры проведения документа.

После того, как у нас есть хранилище данных о продажах, мы построим соответствующий отчет. На базе тех данных, которые у нас есть, можно построить различные отчеты – все зависит от того, какие именно данные нас интересуют. Предположим, мы заинтересованы в сведениях о продажах по контрагентам. Нас интересует количественный показатель продажи номенклатурной позиции и прибыль от продажи.

Лариса Дятчина
Лариса Дятчина
Почему не работает код
максим матасов
максим матасов
Нам нужно создать новый документ типа ПоступлениеМатериалов. Какой программной конструкцией можно воспользоваться
Александр Палий
Александр Палий
Россия, Москва
Константин Гераськов
Константин Гераськов
Россия, Новосибирск