Сравнительный WoW-анализ (Week-over-Week) входящего потока товарных позиций в заказах клиентов по сквозным неделям
Учетные задачи - Логистика, склад и ТМЦ
Файлы
ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.
Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний
Оформите подписку на компанию для решения рабочих задач
Оформить подписку и скачать решение со скидкойВы можете заказать платную доработку или адаптацию этой разработки под вашу конфигурацию на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.
Этот график — не просто очередная задача, а часть огромного, сложного отчета, который мне пришлось разрабатывать в условиях жесточайшего дедлайна и стресса. Время поджимало, требования бизнеса менялись на ходу. Мне требовался особый сдвиг дат в начале месяца, чтобы графики начинались не строго с 1-го числа, а захватывали «хвост» предыдущей недели для контекста.
В стрессовых условиях был написан календарь через временные таблицы с хитрым расчетом сдвига дней недели.
Вот этот ключевой кусок запроса для формирования сдвига дат:
ВЫБРАТЬ
ВЫБОР
КОГДА ДЕНЬНЕДЕЛИ(&НачалоПрМесяца) = 1
ТОГДА ДОБАВИТЬКДАТЕ(&НачалоПрМесяца, ДЕНЬ, -4)
КОГДА ДЕНЬНЕДЕЛИ(&НачалоПрМесяца) = 2
ТОГДА ДОБАВИТЬКДАТЕ(&НачалоПрМесяца, ДЕНЬ, -5)
КОГДА ДЕНЬНЕДЕЛИ(&НачалоПрМесяца) = 3
ТОГДА ДОБАВИТЬКДАТЕ(&НачалоПрМесяца, ДЕНЬ, -6)
КОГДА ДЕНЬНЕДЕЛИ(&НачалоПрМесяца) = 4
ТОГДА ДОБАВИТЬКДАТЕ(&НачалоПрМесяца, ДЕНЬ, 0)
КОГДА ДЕНЬНЕДЕЛИ(&НачалоПрМесяца) = 5
ТОГДА ДОБАВИТЬКДАТЕ(&НачалоПрМесяца, ДЕНЬ, -1)
КОГДА ДЕНЬНЕДЕЛИ(&НачалоПрМесяца) = 6
ТОГДА ДОБАВИТЬКДАТЕ(&НачалоПрМесяца, ДЕНЬ, -2)
КОГДА ДЕНЬНЕДЕЛИ(&НачалоПрМесяца) = 7
ТОГДА ДОБАВИТЬКДАТЕ(&НачалоПрМесяца, ДЕНЬ, -3)
КОНЕЦ КАК ДН,
НАЧАЛОПЕРИОДА(&НачалоПрМесяца, МЕСЯЦ) КАК МесяцЗД
ПОМЕСТИТЬ ДополнДаты
ОБЪЕДИНИТЬ ВСЕ
Этот код выполнил свою задачу, отчет был сдан, но такое решение не давало мне покоя. Мне хотелось сделать алгоритм более изящным и быстродействующим. И алгоритм был переписан на новый, более красивый и стабильный вариант уже после того, как я покинула компанию. Возвращаясь к своим старым наработкам свежим взглядом, всегда находишь, что улучшить.
Новый вариант написан уже под УТ 11, но главное тут — переписан алгоритм расчета сдвига даты, и его можно объединять с любой необходимой вам выборкой для вывода. Чтобы СКД не ругалась на разные типы данных ссылок и технологических строк в сериях, я привела их к единому строковому знаменателю в финальном пакете.
В параметрах отчета достаточно указать всего одну дату (любой день интересующего месяца) — система самостоятельно рассчитает границы периодов и сформирует наглядную панель строго за 3 смежных месяца (выбранный, прошлый и позапрошлый).
ВЫБРАТЬ
ПредИтог.КоличествоЗаявок КАК КоличествоЗаявок,
ВЫБОР
КОГДА ПредИтог.ТипКонтрагента = ЗНАЧЕНИЕ(Перечисление.ЮрФизЛицо.ЮрЛицо)
ТОГДА "Юридическое лицо"
КОГДА ПредИтог.ТипКонтрагента = ЗНАЧЕНИЕ(Перечисление.ЮрФизЛицо.ФизЛицо)
ТОГДА "Физическое лицо"
ИНАЧЕ "Не указан"
КОНЕЦ КАК ТипКонтрагента,
ПредИтог.ДеньДиаграмма КАК ДеньДиаграмма,
ПредИтог.МесяцДиаграмма КАК МесяцДиаграмма
ИЗ
ПредИтог КАК ПредИтог
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ЕСТЬNULL(ТаблицаСреднееПоМесяцам.Среднее, 0),
"Среднее",
ДополнДаты.ДН,
ДополнДаты.МесяцЗД
ИЗ
ДополнДаты КАК ДополнДаты
ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаСреднееПоМесяцам КАК ТаблицаСреднееПоМесяцам
ПО ДополнДаты.МесяцЗД = ТаблицаСреднееПоМесяцам.МесяцДиаграмма
Программная пост-обработка макета
Стандартный вывод диаграмм в СКД имеет жесткие ограничения — графики расползаются на весь экран, а между ними остаются огромные пустые строки скрытой таблицы.
В финальном решении вывод сделан через пост-обработку готового документа. Мы позволяем СКД сформировать отчет одной командой, а затем одним циклом перебираем коллекцию Рисунки, жестко задавая координаты Верх и Лево. Графики ложатся впритык друг под друга с идеальным выравниванием осей Х.
Также решена проблема цифр над линией тренда «Среднее»: с помощью свойства Серия.ФорматЗначенийВПодписях = "ЧФ=' '" я подменила числовые подписи невидимыми пробелами, оставив график чистым.
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Отключаем стандартный вывод, чтобы управлять им вручную
СтандартнаяОбработка = Ложь;
// Стандартный сквозной вывод всего отчета в ДокументРезультат
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.ПолучитьНастройки(), ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
// Сформируем отчет полностью штатными средствами
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
ГлобальныйМаксимум = 0;
Для Каждого ТекРисунок Из ДокументРезультат.Рисунки Цикл
Если ТекРисунок.ТипРисунка = ТипРисункаТабличногоДокумента.Диаграмма Тогда
// Перебираем все фактические значения на графике, чтобы найти самую высокую точку
Для Каждого Серия Из ТекРисунок.Объект.Серии Цикл
// Пропускаем техническую серию "Среднее", ищем только реальные продажи
Если Серия.Текст = "Среднее" Или Найти(Серия.Текст, "Среднее:") > 0 Тогда
Продолжить;
КонецЕсли;
Для Каждого Точка Из ТекРисунок.Объект.Точки Цикл
ЗначениеД = ТекРисунок.Объект.ПолучитьЗначение(Точка, Серия);
Если ЗначениеД <> Неопределено И ЗначениеД.Значение<>Null И ЗначениеД.Значение > ГлобальныйМаксимум Тогда
ГлобальныйМаксимум = ЗначениеД.Значение;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЕсли;
КонецЦикла;
Если ГлобальныйМаксимум = 0 Тогда
ГлобальныйМаксимум = 10;
Иначе
// Делаем округление вверх (запас 10%), чтобы столбцы не упирались в потолок
ГлобальныйМаксимум = Цел(ГлобальныйМаксимум * 1.1);
КонецЕсли;
НомерДиаграммы = 0;
ТекущийВерх = 0;
КоэффициентСжатия = 3;
// Перебираем готовые рисунки
Для Каждого ТекРисунок Из ДокументРезультат.Рисунки Цикл
Если ТекРисунок.ТипРисунка = ТипРисункаТабличногоДокумента.Диаграмма Тогда
Попытка
ТекРисунок.Объект.ПоложениеПодписей=ПоложениеПодписейКДиаграмме.Край;
Исключение КонецПопытки;
НомерДиаграммы = НомерДиаграммы + 1;
Для каждого серия из ТекРисунок.Объект.Серии Цикл
Если Серия.Текст = "Среднее" Тогда
Серия.Индикатор = Истина;
Серия.ФорматЗначенийВПодписях = "ЧФ=' '";
ЧислоЗначениеСр = 0;
Если ТекРисунок.Объект.Точки.Количество() > 0 Тогда
ТочкаНоль = ТекРисунок.Объект.Точки[0]; // Берем объект первой точки
ЗначениеСр = ТекРисунок.Объект.ПолучитьЗначение(ТочкаНоль, Серия);
Если ЗначениеСр <> Неопределено Тогда
ЧислоЗначениеСр = ЗначениеСр.Значение;
КонецЕсли;
КонецЕсли;
Для Каждого Точка Из ТекРисунок.Объект.Точки Цикл
ТекРисунок.Объект.УстановитьЗначение(Точка, Серия, ЧислоЗначениеСр);
КонецЦикла;
Серия.Текст = "Среднее: " + Строка(ЧислоЗначениеСр);
КонецЕсли;
КонецЦикла;
Попытка
ТекРисунок.Объект.ОсьЗначений.СпособОпределенияМаксимальногоЗначения = СпособОпределенияОграничивающегоЗначенияДиаграммы.ИспользоватьЗначение;
ТекРисунок.Объект.ОсьЗначений.МаксимальноеЗначение = ГлобальныйМаксимум;
Исключение
КонецПопытки;
Если НомерДиаграммы = 1 Тогда
ТекущийВерх = ТекРисунок.Верх;
КонецЕсли;
// Принудительно устанавливаем Верх для ВСЕХ диаграмм
ТекРисунок.Верх = ТекущийВерх;
ТекРисунок.Ширина = 300;
ТекРисунок.Высота = ТекРисунок.Высота / КоэффициентСжатия;
ТекущийВерх = ТекРисунок.Верх + ТекРисунок.Высота + 3;
ТекРисунок.Лево = 2;
// Если вывели пачку из 3-х штук, сбрасываемся для следующей
Если НомерДиаграммы % 3 = 0 Тогда
ТекущийВерх = 0;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Полную структуру оптимизированного запроса со всеми промежуточными временными таблицами (ПредИтог, ЗапросыМесяцы и др.) вы можете изучить непосредственно в схеме СКД, скачав файл отчета ниже.
Заключение
Это моя самая первая публикация на Инфостарте, поэтому прошу строго не судить. Отчет прошел долгий путь оптимизации, и буду очень рада, если этот готовые куски кода помогут кому-нибудь в решении аналогичных задач на проектах.
Если будут предложения по его улучшению — обязательно пишите в комментарии, буду рада обратной связи!
Проверено на следующих конфигурациях и релизах:
- Управление торговлей, редакция 11, релизы 11.5.12.232
Вступайте в нашу телеграмм-группу Инфостарт