Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ПИС.-All in one =). 1С.doc
Скачиваний:
32
Добавлен:
13.11.2018
Размер:
9.75 Mб
Скачать

3.13. Оптимизация документа "ОказаниеУслуги"

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

Кроме того, средства 1С:Предприятие 8.1 позволяют вам управлять скоростью выполнения процедуры проведения документа, за счет использования механизма запросов.

Таким образом, оптимизация документа ОказаниеУслуги, преследует две цели:

  • определение стоимости расходуемых материалов при проведении документа;

  • повышение скорости выполнения процедуры проведения документа.

Удалите в документе ОказаниеУслуги реквизит табличной части Стоимость, который больше не понадобится. Также удалите соответствующую колонку из табличного поля, расположенного в форме документа ОказаниеУслуги.

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

Запрос = Новый Запрос;

Если Режим = РежимПроведенияДокумента.Оперативный Тогда

Запрос.Текст =

;

Иначе

Запрос.Текст =

;

КонецЕсли;

Сначала составьте запрос, который будет выполняться при оперативном проведении документа. Значение переменной Запрос.Текст будет сформировано автоматически. Для этого установите курсор перед точкой с запятой, вызовите контекстное меню, нажав правую кнопку мыши, и выберите пункт Конструктор запроса. Согласитесь с созданием нового запроса. На экране появится диалоговое окно "Конструктор запроса". Раскройте таблицу ПереченьНоменклатуры табличной части документа ОказаниеУслуги и выберите из нее поля:

  • Номенклатура;

  • Количество;

  • Номенклатура.ВидНоменклатуры;

  • Сумма.

Эти поля будут нужны для задания значений измерений регистров и их ресурсов. Кроме того, поле ВидНоменклатуры понадобится вам для анализа того, чем является номенклатура, указанная в документе: материалом или услугой (рис. 172).

Рис. 172. Выбранные поля

Для указания значений ресурса Стоимость регистров СтоимостьМатериалов и Продажи вам понадобится рассчитать текущую стоимость номенклатуры как частное стоимости остатка этого материала и его оставшегося количества.

Поэтому добавьте к списку выбранных таблиц еще две (рис. 173).

РегистрНакопления.СтоимостьМатериалов.Остатки;

РегистрНакопления.ОстаткиМатериалов.Остатки.

Рис. 173. Выбранные таблицы

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

Условие получения данных указывает, что остатки должны быть получены только по тем позициям номенклатуры, которые содержатся в проводимом документе (перед выполнением запроса в параметр СписокНоменклатурыДокумента необходимо передать список всех позиций номенклатуры, содержащихся в проводимом документе) – рис. 174.

Рис. 174. Параметры виртуальных таблиц

Такие же параметры установите для второй виртуальной таблицы СтоимостьМатериаловОстатки. Далее выберите из этих виртуальных таблиц поля СтоимостьОстаток и КоличествоОстаток (рис. 175).

Рис. 175. Выбранные поля

Выберите еще раз виртуальную таблицу регистра накопления ОстаткиМатериаловОстатки и переименуйте ее в ОстаткиМатериаловОстаткиНаСкладе (рис. 176).

Рис. 176. Выбранные таблицы

Для этой виртуальной таблицы также укажите параметр МоментВремени, а в условии напишите, что материал должен находиться в списке номенклатуры и склад должен быть равен складу, указанному в документе (рис. 177).

Рис. 177. Параметры таблицы ОстаткиМатериаловОстаткиНаСкладе

Теперь из этой виртуальной таблицы выберите поле КоличествоОстаток (рис. 178).

Рис. 178. Выбранные поля

На этом формирование списка выбранных полей закончено, и можно перейти к заданию условий связи между выбранными таблицами. Для этого перейдите на закладку Связи. Каждую из виртуальных таблиц необходимо связать с таблицей документа таким образом, что для всех записей таблицы документа должны подбираться имеющиеся записи виртуальной таблицы, причем номенклатура в таблице документа должна быть равна материалу из виртуальной таблицы (рис. 179, а–б).

Рис. 179а. Выбранные таблицы

Рис. 179б. Условия связи между таблицами

Теперь перейдите на закладку Дополнительно и установите флаг Для изменения. Флаг Для изменения позволяет заблаговременно заблокировать чтение указанных данных (которые могут читаться транзакцией другого соединения) уже при считывании, чтобы исключить взаимные блокировки при записи. Это предложение дает возможность указать в запросе таблицы, считываемые данные которых предполагается изменять.

Поскольку вы планируете выполнить запись регистров накопления ОстаткиМатериалов и СтоимостьМатериалов, укажите таблицы этих регистров в качестве таблиц для изменения (рис. 180).

Рис. 180. Укажите таблицы для изменения

Перейдите на закладку Условия и задайте условие отбора из таблицы документа только строк проводимого документа (ссылка на него будет передана в параметр запроса Ссылка) – рис. 181. Для этого дважды щелкните левой кнопкой мыши по полю Ссылка.

Рис. 181. Условие отбора из таблицы документа

Перейдите на закладку Объединения/Псевдонимы и задайте следующие псевдонимы полей: НоменклатураВидНоменклатуры –> ВидНоменклатуры; КоличествоОстаток1 –> КоличествоНаСкладе.

Нажмите кнопку "ОK" и посмотрите, какой текст запроса сформировал конструктор (значение переменной Запрос.Текст):

ВЫБРАТЬ

ОказаниеУслугиПереченьНоменклатуры.Номенклатура,

ОказаниеУслугиПереченьНоменклатуры.Количество,

ОказаниеУслугиПереченьНоменклатуры.Номенклатура.ВидНоменклатуры КАК ВидНоменклатуры,

ОказаниеУслугиПереченьНоменклатуры.Сумма,

СтоимостьМатериаловОстатки.СтоимостьОстаток,

ОстаткиМатериаловОстатки.КоличествоОстаток,

ОстаткиМатериаловОстаткиНаСкладе.КоличествоОстаток КАК КоличествоНаСкладе

ИЗ

Документ.ОказаниеУслуги.ПереченьНоменклатуры КАК ОказаниеУслугиПереченьНоменклатуры

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.СтоимостьМатериалов.Остатки(&МоментВремени, Материал В (&СписокНоменклатурыДокумента)) КАК СтоимостьМатериаловОстатки

ПО ОказаниеУслугиПереченьНоменклатуры.Номенклатура =

СтоимостьМатериаловОстатки.Материал

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиМатериалов.Остатки(&МоментВремени, Материал В (&СписокНоменклатурыДокумента)) КАК ОстаткиМатериаловОстатки

ПО ОказаниеУслугиПереченьНоменклатуры.Номенклатура =

ОстаткиМатериаловОстатки.Материал

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиМатериалов.Остатки(&МоментВремени,

Материал В (&СписокНоменклатурыДокумента) И Склад = &СкладВДокументе)

КАК ОстаткиМатериаловОстаткиНаСкладе

ПО ОказаниеУслугиПереченьНоменклатуры.Номенклатура =

ОстаткиМатериаловОстаткиНаСкладе.Материал

ГДЕ

ОказаниеУслугиПереченьНоменклатуры.Ссылка = &Ссылка

ДЛЯ ИЗМЕНЕНИЯ

РегистрНакопления.СтоимостьМатериалов.Остатки,

РегистрНакопления.ОстаткиМатериалов.Остатки

Текст запроса для случая неоперативного проведения документа будет практически таким же, за исключением того, что в нем будет отсутствовать третье левое соединение и, соответственно, поле КоличествоНаСкладе, т.к. проверку остатков в этом случае выполнять не надо. Установите курсор перед точкой с запятой, расположенной в секции Иначе (см. стр. 135), и вставьте следующий текст запроса:

ВЫБРАТЬ

ОказаниеУслугиПереченьНоменклатуры.Номенклатура,

ОказаниеУслугиПереченьНоменклатуры.Количество,

ОказаниеУслугиПереченьНоменклатуры.Номенклатура.ВидНоменклатуры КАК

ВидНоменклатуры,

ОказаниеУслугиПереченьНоменклатуры.Сумма,

ОстаткиМатериаловОстатки.КоличествоОстаток,

СтоимостьМатериаловОстатки.СтоимостьОстаток

ИЗ

Документ.ОказаниеУслуги.ПереченьНоменклатуры КАК ОказаниеУслугиПереченьНоменклатуры

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.СтоимостьМатериалов.Остатки(&МоментВремени, Материал В (&СписокНоменклатурыДокумента))

КАК СтоимостьМатериаловОстатки

ПО ОказаниеУслугиПереченьНоменклатуры.Номенклатура =

СтоимостьМатериаловОстатки.Материал

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиМатериалов.Остатки(&МоментВремени,

Материал В (&СписокНоменклатурыДокумента))

КАК ОстаткиМатериаловОстатки

ПО ОказаниеУслугиПереченьНоменклатуры.Номенклатура =

ОстаткиМатериаловОстатки.Материал

ГДЕ

ОказаниеУслугиПереченьНоменклатуры.Ссылка = &Ссылка

ДЛЯ ИЗМЕНЕНИЯ

РегистрНакопления.ОстаткиМатериалов.Остатки,

РегистрНакопления.СтоимостьМатериалов.Остатки;

Теперь добавьте в текст обработчика задание параметров запроса (добавляйте в соответствующие строки только те команды, которые выделены жирным шрифтом):

Запрос = Новый Запрос;

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

Если Режим = РежимПроведенияДокумента.Оперативный Тогда

....

Иначе

Запрос.Текст =

"ВЫБРАТЬ

| РегистрНакопления.СтоимостьМатериалов.Остатки";

КонецЕсли;

Запрос.УстановитьПараметр("МоментВремени", МоментВремени());

Запрос.УстановитьПараметр("СписокНоменклатурыДокумента",

ПереченьНоменклатуры.ВыгрузитьКолонку("Номенклатура"));

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

Обратите внимание, что для формирования списка номенклатуры документа используется метод ВыгрузитьКолонку() объекта ДокументТабличнаяЧасть. ОказаниеУслуги.ПереченьНоменклатуры.

После этого добавьте получение результата запроса и цикл его обхода:

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

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

Пока ВыборкаРезультатаЗапроса.Следующий() Цикл

КонецЦикла;

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

Теперь, прежде чем начать формирование движений по регистрам, необходимо проверить наличие на складе достаточного количества номенклатуры в цикле обхода результата запроса:

Пока ВыборкаРезультатаЗапроса.Следующий() Цикл

// Проверить остаток при оперативном проведении.

Если Режим = РежимПроведенияДокумента.Оперативный Тогда

Если ВыборкаРезультатаЗапроса.ВидНоменклатуры =

Перечисления.ВидыНоменклатуры.Материал Тогда

Остаток = ?(ВыборкаРезультатаЗапроса.КоличествоНаСкладе = Null, 0,

ВыборкаРезультатаЗапроса.КоличествоНаСкладе);

Если Остаток < ВыборкаРезультатаЗапроса.Количество Тогда

Сообщить("Материала" + СокрЛП(ВыборкаРезультатаЗапроса.Номенклатура) + "имеется только" + Остаток);

Отказ = Истина;

Возврат;

КонецЕсли;

КонецЕсли;

КонецЕсли;

КонецЦикла;

И в заключение, после проверки остатков на складе, перед самым концом цикла, добавьте формирование движений по регистрам накопления:

КонецЕсли;

// Сформировать движения.

Если ВыборкаРезультатаЗапроса.ВидНоменклатуры =

Перечисления.ВидыНоменклатуры.Материал Тогда

// Регистр ОстаткиМатериалов Расход

Движение = Движения.ОстаткиМатериалов.Добавить();

Движение.ВидДвижения = ВидДвиженияНакопления.Расход;

Движение.Период = Дата;

Движение.Материал = ВыборкаРезультатаЗапроса.Номенклатура;

Движение.Склад = Склад;

Движение.Количество = ВыборкаРезультатаЗапроса.Количество;

// Регистр СтоимостьМатериалов Расход.

Движение = Движения.СтоимостьМатериалов.Добавить();

Движение.ВидДвижения = ВидДвиженияНакопления.Расход;

Движение.Период = Дата;

Движение.Материал = ВыборкаРезультатаЗапроса.Номенклатура;

// Рассчитать стоимость материала.

СтоимостьМатериала = ?(ВыборкаРезультатаЗапроса.КоличествоОстаток = Null, 0,

ВыборкаРезультатаЗапроса.СтоимостьОстаток /

ВыборкаРезультатаЗапроса.КоличествоОстаток);

Движение.Стоимость = СтоимостьМатериала * ВыборкаРезультатаЗапроса.Количество;

КонецЕсли;

// Регистр Продажи

Движение = Движения.Продажи.Добавить();

Движение.Период = Дата;

Движение.Номенклатура = ВыборкаРезультатаЗапроса.Номенклатура;

Движение.Клиент = Клиент;

Движение.Мастер = Мастер;

Движение.Количество = ВыборкаРезультатаЗапроса.Количество;

Движение.Выручка = ВыборкаРезультатаЗапроса.Сумма;

Если ВыборкаРезультатаЗапроса.ВидНоменклатуры =

Перечисления.ВидыНоменклатуры.Материал Тогда

Движение.Стоимость = СтоимостьМатериала * ВыборкаРезультатаЗапроса.Количество;

Иначе

Движение.Стоимость = 0;

КонецЕсли;

КонецЦикла;

А сразу после цикла добавьте запись движений регистров:

КонецЦикла;

// Записать движения регистров

Движения.ОстаткиМатериалов.Записать();

Движения.СтоимостьМатериалов.Записать();

Движения.Продажи.Записать();

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

Запустите 1С:Предприятие в режиме отладки и проверьте работу нового обработчика события ОбработкаПроведения, перепроведя все документы Оказание услуги.

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