Неканонический способ спускания параметра нижестоящим процедурам
UPDATE: лучше спускать параметры через параметры сеанса, но во Fresh они недоступны в расширениях, поэтому там через регистр сведений с измерение по пользователям. Потому что код в этом примере в многопользовательском режиме может привести к коллизиям, когда оба пользователя запишут в один справочник.
Дорабатывал одному клиенту модуль по расчету зарплаты в УТ от Codestar. Модуль ставится как добавка в конфигурацию, ставится через сравнение-объединение.
И вот я делал изменения уже в свою очередь через расширение, чтобы не потерять обновления, которые будут от этого поставщика.
В самом модуле нет видов времени. Т.е. чтобы рассчитать аванс, нужно использовать плановое время, вообще-то.
Ну не суть, в общем, мне нужно было при расчете базы начисления учитывать, плановое это время или фактическое.
Я добавил реквизит «Вид рабочего времени» в документ «Начисление зарплаты».
Но столкнулся с тем, что мне нужно было его передавать по стеку через несколько функций в функцию расчета базы.
Для этого пришлось бы каждую функцию добавлять в расширение и существенно их менять. Причем модули были большими, пришлось бы их передавать через расширение с контролем и изменением. Сама ссылка на документ в расчет не передавалась.
Я было попытался начать. Вот первая процедура:

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

На этом этапе я отказался от этой сложной конструкции и применил другой, не канонический способ, но простой и надежный, как АК-47.
Я создал в расширении справочник дор_ЗПСлужебный с единственным реквизитом Значение типа «Хранилище значения».
Написал две функции по установке и выдаче его значения по идентификатору:
Процедура ПоместитьВСлужебныйСправочник(Имя, Значение) Экспорт УстановитьПривилегированныйРежим(Истина); ТекИмя = Лев(Имя, 150); СправочникСсылка = Справочники.дор_ЗПСлужебный.НайтиПоНаименованию(ТекИмя); Если ЗначениеЗаполнено(СправочникСсылка) Тогда СправочникОбъект = СправочникСсылка.ПолучитьОбъект(); Иначе СправочникОбъект = Справочники.дор_ЗПСлужебный.СоздатьЭлемент(); СправочникОбъект.Наименование = ТекИмя; КонецЕсли; СправочникОбъект.Значение = Новый ХранилищеЗначения(Значение); СправочникОбъект.Записать(); КонецПроцедуры Функция ПолучитьИзСлужебногоСправочника(Имя) Экспорт УстановитьПривилегированныйРежим(Истина); ТекИмя = Лев(Имя, 150); СправочникСсылка = Справочники.дор_ЗПСлужебный.НайтиПоНаименованию(ТекИмя); Если ЗначениеЗаполнено(СправочникСсылка) Тогда Возврат СправочникСсылка.Значение.Получить(); Иначе Возврат Неопределено; КонецЕсли; КонецФункции
Теперь перед расчетом я устанавливаю значение вида времени:
&НаСервере &Перед("РассчитатьНаСервере") Процедура дор_РассчитатьНаСервере() дор_ЗПСервер.ПоместитьВСлужебныйСправочник("ВидРабочегоВремени", Объект.ВидРабочегоВремени); КонецПроцедуры
А в процессе получения базы получаю значение вида времени:
&Вместо("ПолучитьБазуДляРасчетаТарифа") Функция дор_ПолучитьБазуДляРасчетаТарифа(НачалоПериода, КонецПериода, Сотрудник, Показатель) Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | естьNULL(СУММА(_ОтработанноеВремяОбороты."+Показатель+"Оборот),0) КАК Результат |ИЗ | РегистрНакопления._ОтработанноеВремя.Обороты(&НачалоПериода, &КонецПериода, , Сотрудник = &Сотрудник) КАК _ОтработанноеВремяОбороты"; //Осипов 2021-08-24 только факт считаем +++ Запрос.Текст = Запрос.Текст + " ГДЕ _ОтработанноеВремяОбороты.ВидРабочегоВремени = &ВидРабочегоВремени"; ВидРабочегоВремени = дор_ЗПСервер.ПолучитьИзСлужебногоСправочника("ВидРабочегоВремени"); Запрос.УстановитьПараметр("ВидРабочегоВремени", ВидРабочегоВремени); //--- Запрос.УстановитьПараметр("НачалоПериода", НачалоПериода); Запрос.УстановитьПараметр("КонецПериода", КонецПериода); Запрос.УстановитьПараметр("Сотрудник", Сотрудник); Выборка = Запрос.Выполнить().Выбрать(); Если Выборка.Следующий() Тогда Результат = Выборка.Результат; Иначе Результат = 0; КонецЕсли; Возврат Результат; КонецФункции
Касательно этого метода хочу сказать, что большинство его не одобрят, т.к. он не очень прозрачный. Это как оператор GOTO, при злоупотреблении можно нарваться на проблемы, но в гомеопатических дозах — то, что нужно. Конкретно описанную мною задачу решает замечательно!
Ну и еще хочу похвастаться аккуратными добавленными мною полями:

Вот код:
&НаСервере Процедура дор_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка) ПередЭлемент = Элементы.ГруппаСтраницы; ТекГруппа = Элементы.Вставить("дор_Группа", Тип("ГруппаФормы"), ПередЭлемент.Родитель, ПередЭлемент); ТекГруппа.Вид = ВидГруппыФормы.ОбычнаяГруппа; ТекГруппа.Группировка = ГруппировкаПодчиненныхЭлементовФормы.ГоризонтальнаяВсегда; Элемент = Элементы.Добавить("ВидРабочегоВремени", Тип("ПолеФормы"), ТекГруппа); Элемент.Вид = ВидПоляФормы.ПолеВвода; Элемент.ПутьКДанным = "Объект.ВидРабочегоВремени"; Элемент.Вид = ВидПоляФормы.ПолеВвода; Элемент.АвтоМаксимальнаяШирина = ложь; Элемент.РастягиватьПоГоризонтали = ложь; Элемент.Ширина = 10; Элемент = Элементы.Добавить("ПроцентУменьшения", Тип("ПолеФормы"), ТекГруппа); Элемент.Вид = ВидПоляФормы.ПолеВвода; Элемент.ПутьКДанным = "Объект.ПроцентУменьшения"; Элемент.Вид = ВидПоляФормы.ПолеВвода; Элемент.АвтоМаксимальнаяШирина = ложь; Элемент.РастягиватьПоГоризонтали = ложь; Элемент.Ширина = 10; ПередЭлемент = Элементы.НачисленияДепозит; Элемент = Элементы.Вставить("Начально", Тип("ПолеФормы"), ПередЭлемент.Родитель, ПередЭлемент); Элемент.Вид = ВидПоляФормы.ПолеВвода; Элемент.ПутьКДанным = "Объект.Начисления.Начально"; Элемент.ТолькоПросмотр = истина; Элемент.Ширина = 10; Если Не ЗначениеЗаполнено(Объект.ВидРабочегоВремени) Тогда Объект.ВидРабочегоВремени = Справочники._ВидыРабочегоВремени.Факт; КонецЕсли; КонецПроцедуры
Среда: 11.4.13.46. Объем факт: 1 час.
