Разрабатывая уже 21 год системы управления складами/производством/оборудованием в режиме реального времени (AllCtrl.SCADA, Кронос: WMS, MES), столкнулись с проблемой предоставления пользователю возможности выбора периода времени построения типовых отчетов (с и по какой ему необходимо получить отчет). Типовой подход 1С в библиотеке стандартных подсистем (БСП) позволяет указывать период с начала дня и по конец дня (СтандартныйПериод, СКД), однако для систем класса WMS, SCADA, MES это слишком большой интервал времени для анализа. Поэтому было решено немного подкорректировать типовой механизм/инструмент библиотеки стандартных подсистем.
Итак, вот результат, который мы получим для типового отчета Оборотно-сальдовая ведомость на СКД:
Логика наших изменений будет такая - вместо типовых полей по вводу даты стандартного периода добавим наши поля ввода дата+время, скорректируем процедуры изменения и установки интервала периода.
Форма всех отчетов типовой библиотеки стандартных подсистем (БСП 3.1) расположена в общих формах конфигурации и называется - ФормаОтчета. При создании формы на сервере нам необходимо:
1. Понять, какие поля стандартного периода у нас используются в отчете и вынесены на форму отчета (пользовательские настройки, быстрый доступ), запомнить, с какими параметрами схемы компоновки данных (СКД) отчета они связаны (например, НачалоПериода, КонецПериода), какие значения по умолчанию имеют.
2. Очистить выражения по заполнению параметров СКД
Давайте добавим функцию, которая сделает всё вышеописанное :
&НаСервере
Функция ПолучитьПоляСтандартногоПериода()
ПоляСтандартногоПериода = Новый Соответствие();
Для Каждого ПараметрСхемы Из ОтчетОбъект.СхемаКомпоновкиДанных.Параметры Цикл
Если НЕ ТипЗнч(ПараметрСхемы.Значение)=Тип("СтандартныйПериод") Тогда
Продолжить;
КонецЕсли;
ПоляСтандартногоПериода.Вставить(ПараметрСхемы.Имя, Новый Структура("ДатаНачалаПоУмолчанию, ДатаОкончанияПоУмолчанию", ПараметрСхемы.Значение.ДатаНачала, ПараметрСхемы.Значение.ДатаОкончания));
КонецЦикла;
Для Каждого ПараметрСхемы Из ОтчетОбъект.СхемаКомпоновкиДанных.Параметры Цикл
Если ПустаяСтрока(ПараметрСхемы.Выражение) Тогда
Продолжить;
КонецЕсли;
ОписаниеВыражения = СтрРазделить(ПараметрСхемы.Выражение, ".");
Если ОписаниеВыражения.Количество()<2 Тогда
Продолжить;
КонецЕсли;
ПервыйПараметр = СокрЛП(СтрЗаменить(ОписаниеВыражения[0], "&", ""));
ПолеПериода = ПоляСтандартногоПериода.Получить(ПервыйПараметр);
Если ПолеПериода=Неопределено Тогда
Продолжить;
КонецЕсли;
ЭлементСхемы = ОтчетОбъект.СхемаКомпоновкиДанных.НастройкиПоУмолчанию.ПараметрыДанных.Элементы.Найти(ПервыйПараметр);
Если ЭлементСхемы=Неопределено ИЛИ НЕ ЗначениеЗаполнено(ЭлементСхемы.ИдентификаторПользовательскойНастройки) Тогда
Продолжить;
КонецЕсли;
ПолеПериода.Вставить(ОписаниеВыражения[1], ПараметрСхемы.Имя);
ПараметрСхемы.Выражение = "";
КонецЦикла;
Возврат ПоляСтандартногоПериода;
КонецФункции
Далее, в стандартной функции заполнения настроек отчета добавим вызов нашей функции:
&НаСервере
Функция НастройкиОтчета(ОтчетОбъект, ОтчетМетаданные, ОтчетПолноеИмя, ПредопределенныеВарианты)
Настройки = ВариантыОтчетов.НастройкиФормыОтчета(Параметры.Отчет, КлючТекущегоВарианта, ОтчетОбъект);
Настройки.Вставить("РазрешеноВыбиратьВарианты", Истина);
//Кронос: WMS начало
//ИЗМЕНЕНО
//Настройки.Вставить("СхемаМодифицирована", Ложь);
//НА
НастройкиОтчета.Вставить("ПоляСтандартногоПериода", ПолучитьПоляСтандартногоПериода());
Настройки.Вставить("СхемаМодифицирована", Истина);
//Кронос: WMS конец
Настройки.Вставить("ПредопределенныеВарианты", ПредопределенныеВарианты);
Настройки.Вставить("АдресСхемы", АдресСхемыОтчета(ОтчетОбъект));
Настройки.Вставить("КлючСхемы", "");
Настройки.Вставить("Контекстный", ЗначениеЗаполнено(КонтекстВарианта));
Настройки.Вставить("ПолноеИмя", ОтчетПолноеИмя);
Настройки.Вставить("Наименование", СокрЛП(ОтчетМетаданные.Представление()));
Настройки.Вставить("ОтчетСсылка", Параметры.Отчет);
Настройки.Вставить("Подсистема", ФормаПараметры.Подсистема);
Настройки.Вставить("Внешний", ТипЗнч(Настройки.ОтчетСсылка) = Тип("Строка"));
Настройки.Вставить("Безопасный", БезопасныйРежим() <> Ложь);
Настройки.Вставить("ИспользуемыеТаблицы", ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(Параметры, "ИспользуемыеТаблицы"));
// Свойства для контекстной настройки отчета.
Настройки.Вставить("СвойстваРезультата", ВариантыОтчетовСлужебный.СвойстваРезультатаОтчета());
Возврат Настройки;
КонецФункции
Теперь создадим дубли полей Период1ДатаНачала, Период1ДатаОкончания,Период2ДатаНачала, Период2ДатаОкончания на форме, но с составом Дата+Время, пропишем к ним путь в типовых полях на форме:
Кстати, в более ранних БСП поля создавались программно и там нужно было изменить процедуру ВывестиЭлементыНастройки (общий модуль ОтчетСервер, если кому надо, то можем и для них подсказать как добавить время к дате стандартного периода).
//Кронос: WMS Добавлено
БыстрыеНастройкиДобавитьРеквизит(Прочее.ПараметрыЗаполнения, ЗначениеИмя+"_ДатаНачала", Новый ОписаниеТипов("Дата", Новый КвалификаторыДаты(ЧастиДаты.ДатаВремя)));
БыстрыеНастройкиДобавитьРеквизит(Прочее.ПараметрыЗаполнения, ЗначениеИмя+"_ДатаОкончания", Новый ОписаниеТипов("Дата", Новый КвалификаторыДаты(ЧастиДаты.ДатаВремя)));
Последнее, что осталось сделать, чтобы наши поля при изменении корректно меняли параметры отчета и наоборот при изменении стандартного периода отчета, чтобы менялись наши поля. В БСП 3.1 за это все отвечает процедура УстановитьПериод (общий модуль ОтчетСервер), подкорректируем её нужным образом:
Процедура УстановитьПериод(Форма, Знач Путь) Экспорт
КомпоновщикНастроек = Форма.Отчет.КомпоновщикНастроек;
//Кронос: WMS начало
ЭтоИзменениеПоля = Ложь;
//Кронос: WMS конец
Свойства = СтрРазделить("ДатаНачала, ДатаОкончания", ", ", Ложь);
Для Каждого Свойство Из Свойства Цикл
//Кронос: WMS начало
ЭтоИзменениеПоля = Макс(ЭтоИзменениеПоля, Найти(Путь, Свойство)>0);
//Кронос: WMS конец
Путь = СтрЗаменить(Путь, Свойство, "");
КонецЦикла;
Индекс = Форма.ПутьКДаннымЭлементов.ПоИмени[Путь];
Если Индекс = Неопределено Тогда
Путь = Путь + "Период";
Индекс = Форма.ПутьКДаннымЭлементов.ПоИмени[Путь];
КонецЕсли;
ЭлементПользовательскойНастройки = КомпоновщикНастроек.ПользовательскиеНастройки.Элементы[Индекс];
ЭлементПользовательскойНастройки.Использование = Истина;
Если ТипЗнч(ЭлементПользовательскойНастройки) = Тип("ЗначениеПараметраНастроекКомпоновкиДанных") Тогда
ЭлементПользовательскойНастройки.Значение = Форма[Путь];
Иначе // Элемент отбора.
ЭлементПользовательскойНастройки.ПравоеЗначение = Форма[Путь];
КонецЕсли;
//Кронос: WMS начало
Если НЕ ЭтоИзменениеПоля Тогда
Форма[Путь+"ДатаНачала"] = Форма[Путь].ДатаНачала;
Форма[Путь+"ДатаОкончания"] = Форма[Путь].ДатаОкончания;
Иначе
Форма[Путь].ДатаНачала = НачалоДня(Форма[Путь+"ДатаНачала"]);
Форма[Путь].ДатаОкончания = КонецДня(Форма[Путь+"ДатаОкончания"]);
КонецЕсли;
ОписаниеПараметровСКД = Форма.НастройкиОтчета.ПоляСтандартногоПериода.Получить(СокрЛП(ЭлементПользовательскойНастройки.Параметр));
Если ТипЗнч(ОписаниеПараметровСКД)=Тип("Структура") И ОписаниеПараметровСКД.Свойство("ДатаНачала") Тогда
ПараметрДатаНачала = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти(ОписаниеПараметровСКД.ДатаНачала);
ПараметрДатаНачала.Значение = Форма[Путь+"ДатаНачала"];
ПараметрДатаНачала.Использование = Истина;
ПараметрДатаОкончания = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти(ОписаниеПараметровСКД.ДатаОкончания);
ПараметрДатаОкончания.Значение = Форма[Путь+"ДатаОкончания"];
ПараметрДатаОкончания.Использование = Истина;
КонецЕсли;
//Кронос: WMS конец
ОтчетыКлиентСервер.ОповеститьОИзмененииНастроек(Форма);
КонецПроцедуры
UPD. Чтобы корректно при расшифровке указывался период (дата+время) в шапке отчете необходимо еще изменить функцию ИнициализироватьПериод (общий модуль ОтчетыСервер):
Процедура ИнициализироватьПериод(Форма, Индекс)
ПользовательскиеНастройки = Форма.Отчет.КомпоновщикНастроек.ПользовательскиеНастройки;
ЭлементНастройки = ПользовательскиеНастройки.Элементы[Индекс];
Путь = Форма.ПутьКДаннымЭлементов.ПоИндексу[Индекс];
Если ТипЗнч(ЭлементНастройки) = Тип("ЗначениеПараметраНастроекКомпоновкиДанных") Тогда
Форма[Путь] = ЭлементНастройки.Значение;
Иначе // Элемент отбора.
Форма[Путь] = ЭлементНастройки.ПравоеЗначение;
КонецЕсли;
//Кронос: WMS начало
ОписаниеПараметровСКД = Форма.НастройкиОтчета.ПоляСтандартногоПериода.Получить(СокрЛП(ЭлементНастройки.Параметр));
Если ТипЗнч(ОписаниеПараметровСКД)=Тип("Структура") И ОписаниеПараметровСКД.Свойство("ДатаНачала") Тогда
ПараметрДатаНачала = Форма.Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти(ОписаниеПараметровСКД.ДатаНачала);
Форма[Путь].ДатаНачала = НачалоДня(ПараметрДатаНачала.Значение);
Форма[Путь+"ДатаНачала"] = ПараметрДатаНачала.Значение;
ПараметрДатаОкончания = Форма.Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти(ОписаниеПараметровСКД.ДатаОкончания);
Форма[Путь].ДатаОкончания = КонецДня(ПараметрДатаОкончания.Значение);
Форма[Путь+"ДатаОкончания"] = ПараметрДатаОкончания.Значение;
КонецЕсли;
//Кронос: WMS конец
КонецПроцедуры
Вот собственно и всё, теперь у нас данные в любом отчете отбираются с учётом указанного времени в периоде, также осталась и удобная возможность использования типового указания варианта периода.
Надеюсь, моя публикация была Вам полезна и сэкономит Ваше время, ссылка на все публикации SizovE.
Подписывайтесь на мой канал (наверху), будет много интересного бесплатного контента :)