При разработке конфигураций для автоматизации гостиничного бизнеса или систем бронирования одной из самых сложных и интересных задач является визуализация занятости ресурсов. Чаще всего для этого используется Диаграмма Ганта. В этой статье мы подробно разберем, как правильно построить такой отчет, избежав типичных ошибок производительности, и как связать нетиповые документы в единую структуру подчиненности.
Рассмотрим ситуацию: нам необходимо вывести график загрузки номерного фонда, где по вертикали (в точках) отображается иерархия «Номер — Комната — Койка», а по горизонтали (на шкале времени) — периоды проживания гостей. В исходном коде автора мы видим использование объекта ДиаграммаГанта и попытку заполнить её данными из регистра сведений ЗагруженностьНФ.
Проанализируем представленный код и выявим критическую проблему: выполнение запроса внутри цикла. Процедура ПосмотретьНаСервере обращается к базе данных на каждой итерации обхода комнат и коек. Если в гостинице 100 номеров, отчет может формироваться недопустимо долго. Кроме того, возникают сложности с управлением цветами интервалов, которые визуально сливаются или отображаются некорректно.
Для того чтобы отчет работал мгновенно, нам необходимо собрать все данные одним запросом. Мы будем использовать ЛЕВОЕ СОЕДИНЕНИЕ справочника номерного фонда с регистром занятости и группировку ИТОГИ ПО. Это позволит нам получить древовидную структуру данных сразу из результата запроса.
Рассмотрим пример правильного построения запроса:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Койки.Владелец.Владелец КАК НомерОбъект,
| Койки.Владелец КАК КомнатаОбъект,
| Койки.Ссылка КАК КойкаОбъект,
| Загруженность.ДатаЗаселения КАК ДатаНачала,
| Загруженность.ДатаВыезда КАК ДатаОкончания,
| Загруженность.Статус КАК Статус
|ИЗ
| Справочник.Койки КАК Койки
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗагруженностьНФ КАК Загруженность
| ПО Койки.Ссылка = Загруженность.КойкаПроживания
|ГДЕ
| (Загруженность.Период МЕЖДУ &НачалоПериода И &КонецПериода ИЛИ Загруженность.Период ЕСТЬ NULL)
|УПОРЯДОЧИТЬ ПО
| НомерОбъект.Наименование,
| КомнатаОбъект.Наименование,
| КойкаОбъект.Наименование
|ИТОГИ ПО
| НомерОбъект,
| КомнатаОбъект,
| КойкаОбъект";
Запрос.УстановитьПараметр("НачалоПериода", Отчет.Период.ДатаНачала);
Запрос.УстановитьПараметр("КонецПериода", Отчет.Период.ДатаОкончания);
РезультатЗапроса = Запрос.Выполнить();
Теперь, когда у нас есть оптимизированная выборка, разберем, как правильно перенести эти данные на диаграмму. Важно помнить, что ДиаграммаГанта состоит из трех основных сущностей: Точки (строки), Серии (легенда/категории) и Значения (сами полоски интервалов).
Выясним причину проблем с цветами. В 1С цвета могут назначаться автоматически, если они не заданы явно для каждого интервала. Чтобы добиться четкого разделения (например, бронь — бирюзовый, проживание — морская волна), нужно управлять свойством Цвет конкретного интервала.
Рассмотрим алгоритм заполнения с иерархией:
Процедура ЗаполнитьДиаграмму(РезультатЗапроса)
ДГ.Очистить();
ДГ.АвтоОпределениеПолногоИнтервала = Ложь;
ДГ.УстановитьПолныйИнтервал(Отчет.Период.ДатаНачала, Отчет.Период.ДатаОкончания);
СерияЗанято = ДГ.УстановитьСерию("Проживание");
ВыборкаНомер = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаНомер.Следующий() Цикл
ТочкаНомер = ДГ.УстановитьТочку(ВыборкаНомер.НомерОбъект);
ВыборкаКомната = ВыборкаНомер.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаКомната.Следующий() Цикл
ТочкаКомната = ТочкаНомер.Точки.Добавить();
ТочкаКомната.Значение = ВыборкаКомната.КомнатаОбъект;
ТочкаКомната.Текст = Строка(ВыборкаКомната.КомнатаОбъект);
ВыборкаКойка = ВыборкаКомната.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаКойка.Следующий() Цикл
ТочкаКойка = ТочкаКомната.Точки.Добавить();
ТочкаКойка.Значение = ВыборкаКойка.КойкаОбъект;
ВыборкаДанные = ВыборкаКойка.Выбрать();
Пока ВыборкаДанные.Следующий() Цикл
Если ВыборкаДанные.ДатаНачала = NULL Тогда Продолжить; КонецЕсли;
// Устанавливаем интервал для конкретной койки
Значение = ДГ.ПолучитьЗначение(ТочкаКойка, СерияЗанято);
Интервал = Значение.Добавить();
Интервал.Начало = ВыборкаДанные.ДатаНачала;
Интервал.Конец = ВыборкаДанные.ДатаОкончания;
Интервал.Цвет = WebЦвета.ЦветМорскойВолны;
Интервал.Текст = "Гость: " + ВыборкаДанные.Статус;
КонецЦикла;
КонецЦикла;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Когда мы работаем с самописными документами (например, «Заселение» или «Бронирование»), стандартная кнопка «Структура подчиненности» может не работать. Разберем два способа решения этой задачи.
Способ А: Использование Критериев отбора.
Это наиболее простой платформенный механизм. Выполним следующие действия в конфигураторе:
СвязанныеДокументы.После этого платформа автоматически сможет строить дерево связей, используя этот критерий.
Способ Б: Внедрение через БСП (Библиотека стандартных подсистем).
Если ваша конфигурация использует БСП, выполним настройку программно:
ОбъектСвязи.СтруктураПодчиненности.Чтобы отчет был не просто «картинкой», а рабочим инструментом, добавим возможность открывать документы прямо из диаграммы. Проанализируем событие Выбор (или ПриНажатии в зависимости от версии платформы) элемента формы ДиаграммаГанта.
При двойном клике на полоску интервала мы можем получить данные:
&НаКлиенте
Процедура ДГВыбор(Элемент, Точка, Серия, Значение, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Если в расшифровке мы передали ссылку на документ
Если ТипЗнч(Значение) = Тип("ДиаграммаГантаЗначение") Тогда
// Получаем текущий интервал (если их несколько)
Интервал = Элемент.ТекущийИнтервал;
Если Интервал <> Неопределено Тогда
ПоказатьЗначение(, Интервал.Значение); // Откроет документ
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Мы проанализировали основные этапы создания сложной визуализации в 1С. Главный секрет успеха — подготовка данных на стороне сервера одним запросом и четкое управление иерархией точек в ДиаграммаГанта. Использование критериев отбора позволит вашим пользователям легко ориентироваться в цепочках документов, обеспечивая прозрачность управленческого учета в вашей системе.