В 1C:EDT
страницаВ 1C:EDT
Откройте модуль документа ОказаниеУслуги и найдите в нем обработчик события ОбработкаПроведения.
Удалите все комментарии конструктора движений. Теперь вы будете формировать движения документа самостоятельно с помощью запроса к табличной части документа.
Все данные, связанные с номенклатурой, которая содержится в табличной части документа, вы будете получать с помощью запроса к базе данных. А данные, связанные с самим документом (например, дата документа, склад), вы по-прежнему будете получать из документа. Такой подход позволит вам читать только нужные данные и за счет этого максимально ускорить проведение документа.
Итак, запросом вы будете получать:
- номенклатуру,
- вид номенклатуры,
- количество.
Из документа вы возьмете следующие данные:
- дата,
- клиент,
- мастер,
- склад.
Хотя вы уже знакомы с языком запросов, проще и быстрее создать запрос с помощью конструктора запроса, а не писать его с нуля. А потом, если понадобится, вы можете вручную отредактировать текст запроса, который создал для вас конструктор.
Причем с помощью конструктора можно не только создать текст запроса, но и получить синтаксически правильный фрагмент встроенного языка, включающий в себя шаблон для обхода результата запроса. Последним вариантом вам и нужно сейчас воспользоваться.
В процедуре обработки проведения установите курсор перед циклом обхода табличной части документа и в контекстном меню нажмите Конструктор запроса с обработкой результата (рис. 12.4).

Рис. 12.4. Вызов конструктора запроса
В конструкторе запросов перейдите на закладку Таблицы и поля и выберите таблицу ОказаниеУслугиПереченьНоменклатуры – это табличная часть документа ОказаниеУслуги.
Из этой таблицы выберите поля Номенклатура, Номенклатура.ВидНоменклатуры, Количество(рис. 12.5).

Рис. 12.5. Выбранные поля
Но вам нужны не все записи этой таблицы, а только те, которые относятся к вашему документу.
Поэтому на закладке Условия задайте условие отбора из таблицы документа только строк проводимого документа.
Для этого перетащите поле Ссылка в список условий запроса (листинг 12.4).
**Листинг 1****2.**4. Условие отбора из таблицы документа
ОказаниеУслугиПереченьНоменклатуры.Ссылка = &Ссылка
Ссылку на этот документ вы передадите в параметр запроса Ссылка (рис. 12.6).

Рис. 12.6. Условие отбора из таблицы документа
Также следует учесть, что в табличной части документа одна и та же номенклатура может встречаться несколько раз.
Поэтому на закладке Группировка перетащите поля Номенклатура и Номенклатура.ВидНоменклатуры в список Поле группировки, а поле Количество – в список Суммируемое поле.
Благодаря этому в результате запроса значения номенклатуры повторяться не будут, и для каждого из них будут посчитаны суммарные значения по полю Количество, если в табличной части документа содержится несколько строк с одинаковой номенклатурой (рис. 12.7).

Рис. 12.7. Группировка строк таблицы документа
На закладке Объединения/Псевдонимы задайте псевдонимы для полей Количество – КоличествоВДокументе, а для поля Номенклатура.ВидНоменклатуры задайте псевдоним ВидНоменклатуры просто для облегчения чтения запроса (рис. 12.8).

Рис. 12.8. Псевдонимы полей
Нажмите ОК. В результате конструктор поместит следующий фрагмент в процедуру обработки проведения документа (листинг 12.5).
Листинг 1****2.5. Текст запроса с обходом результата
// {{КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
// Данный фрагмент построен конструктором.
// При повторном использовании конструктора внесенные вручную изменения будут утеряны!
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ОказаниеУслугиПереченьНоменклатуры.Номенклатура,
| ОказаниеУслугиПереченьНоменклатуры.Номенклатура.ВидНоменклатуры КАК ВидНоменклатуры,
| СУММА(ОказаниеУслугиПереченьНоменклатуры.Количество) КАК КоличествоВДокументе
|ИЗ
| Документ.ОказаниеУслуги.ПереченьНоменклатуры КАК ОказаниеУслугиПереченьНоменклатуры
|ГДЕ
| ОказаниеУслугиПереченьНоменклатуры.Ссылка = &Ссылка
|СГРУППИРОВАТЬ ПО
| ОказаниеУслугиПереченьНоменклатуры.Номенклатура,
| ОказаниеУслугиПереченьНоменклатуры.Номенклатура.ВидНоменклатуры";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
// Вставить обработку выборки ВыборкаДетальныеЗаписи
КонецЦикла;
//}}КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
Комментарии конструктора запроса в начале и конце фрагмента можно удалить.
Поскольку для построения запроса вы использовали Конструктор запроса с обработкой результата, конструктор написал за вас код для выполнения и обхода записей запроса.
После создания запроса в переменной Запрос сначала устанавливается собственно текст запроса, а затем устанавливается значение параметра запроса &Ссылка как ссылка на тот документ, в модуле которого вы сейчас находитесь (листинг 12.6).
Листинг 1****2.6. Установка параметра запроса
Запрос.УстановитьПараметр("Ссылка", Ссылка);
В результате выполнения запроса в переменную ВыборкаДетальныеЗаписи помещается выборка записей из результата запроса.
Далее, используя метод выборки Следующий() (ВыборкаДетальныеЗаписи.Следующий()), вы будете в цикле обходить выборку записей запроса.
Чтобы в цикле получить значение какого-либо поля выборки из результата запроса, вы будете обращаться к полям запроса через точку от переменной ВыборкаДетальныеЗаписи, которая содержит текущую строку выборки запроса. Например, так: ВыборкаДетальныеЗаписи.Номенклатура.
Таким образом, обходя выборку результата запроса, вы пошагово получаете доступ к строкам табличной части документа ПереченьНоменклатуры, сгруппированным по номенклатуре.
Теперь вам осталось перенести существовавшие ранее в процедуре проведения документа строки, описывающие движения регистра ОстаткиМатериалов, внутрь цикла обхода результата запроса вместо комментария «// Вставить обработку выборки ВыборкаДетальныеЗаписи» (листинг 12.7).
Листинг 1****2.7. Цикл обхода записей запроса
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
// регистр ОстаткиМатериалов – Расход
Движение = Движения.ОстаткиМатериалов.Добавить();
Движение.Период = Дата;
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Материал = ТекСтрокаПереченьНоменклатуры.Номенклатура;
Движение.Склад = Склад;
Движение.Количество = ТекСтрокаПереченьНоменклатуры.Количество;
КонецЦикла;
Поскольку вы находитесь теперь не в цикле обхода записей табличной части документа, а в цикле обхода результата запроса, вам нужно заменить обращение ТекСтрокаПереченьНоменклатуры на ВыборкаДетальныеЗаписи (листинг 12.8).
Листинг 1****2.8. Формирование движений регистра
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
// регистр ОстаткиМатериалов – Расход
Движение = Движения.ОстаткиМатериалов.Добавить();
Движение.Период = Дата;
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Материал = ВыборкаДетальныеЗаписи.Номенклатура;
Движение.Склад = Склад;
Движение.Количество = ВыборкаДетальныеЗаписи.Количество;
КонецЦикла;
ПРИМЕЧАНИЕ
Для упрощения восприятия новый текст в листингах выделен жирным шрифтом.
Не забудьте, что для поля Количество вы задали псевдоним в запросе, поэтому замените его на КоличествоВДокументе (листинг 12.9).
Листинг 1****2.9. Формирование движений регистра
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
// регистр ОстаткиМатериалов – Расход
Движение = Движения.ОстаткиМатериалов.Добавить();
Движение.Период = Дата;
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Материал = ВыборкаДетальныеЗаписи.Номенклатура;
Движение.Склад = Склад;
Движение.Количество = ВыборкаДетальныеЗаписи.КоличествоВДокументе;
КонецЦикла;
Теперь почти все готово. Но вам нужно исключить выполнение операторов цикла для тех записей выборки, в которых номенклатура не является материалом (листинг 12.10).
Листинг 1****2.10. Формирование движений регистра только для материалов
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Если ВыборкаДетальныеЗаписи.ВидНоменклатуры = Перечисления.ВидыНоменклатуры.Материал Тогда
// регистр ОстаткиМатериалов – Расход
Движение = Движения.ОстаткиМатериалов.Добавить();
Движение.Период = Дата;
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Материал = ВыборкаДетальныеЗаписи.Номенклатура;
Движение.Склад = Склад;
Движение.Количество = ВыборкаДетальныеЗаписи.КоличествоВДокументе;
КонецЕсли**;**
КонецЦикла;
Используя обращение ВыборкаДетальныеЗаписи.ВидНоменклатуры, вы можете проанализировать значение реквизита ВидНоменклатуры для номенклатуры, содержащейся в текущей записи результата запроса.
Полученное значение вы сравниваете со значением Материал перечисления ВидыНоменклатуры (Перечисления.ВидыНоменклатуры.Материал).
Если значения совпадают, операторы цикла выполняются. Если нет, исполнение кода переходит к следующей итерации цикла.
Оставшийся цикл обхода табличной части можно удалить (листинг 12.11).
Листинг 1****2.11. Ненужные строки
Для Каждого ТекСтрокаПереченьНоменклатуры Из ПереченьНоменклатуры Цикл
КонецЦикла;
В результате процедура проведения примет следующий вид (листинг 12.12).
Листинг 1****2.12. Процедура «ОбработкаПроведения()»
Процедура ОбработкаПроведения(Отказ,Режим)
Движения.ОстаткиМатериалов.Записывать = Истина;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ОказаниеУслугиПереченьНоменклатуры.Номенклатура,
| ОказаниеУслугиПереченьНоменклатуры.Номенклатура.ВидНоменклатуры КАК ВидНоменклатуры,
| СУММА(ОказаниеУслугиПереченьНоменклатуры.Количество) КАК КоличествоВДокументе
|ИЗ
| Документ.ОказаниеУслуги.ПереченьНоменклатуры КАК ОказаниеУслугиПереченьНоменклатуры
|ГДЕ
| ОказаниеУслугиПереченьНоменклатуры.Ссылка = &Ссылка
|СГРУППИРОВАТЬ ПО
| ОказаниеУслугиПереченьНоменклатуры.Номенклатура,
| ОказаниеУслугиПереченьНоменклатуры.Номенклатура.ВидНоменклатуры";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Если ВыборкаДетальныеЗаписи.ВидНоменклатуры = Перечисления.ВидыНоменклатуры.Материал Тогда
// регистр ОстаткиМатериалов – Расход
Движение = Движения.ОстаткиМатериалов.Добавить();
Движение.Период = Дата;
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Материал = ВыборкаДетальныеЗаписи.Номенклатура;
Движение.Склад = Склад;
Движение.Количество = ВыборкаДетальныеЗаписи.КоличествоВДокументе;
КонецЕсли;
КонецЦикла;
КонецПроцедуры