Как организовать хранение и визуализацию расписания событий в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При автоматизации бизнес-процессов часто возникает задача управления расписанием различных событий: запусков регламентных заданий, бронирования ресурсов, планирования визитов или выполнения цепочек технологических задач. В нашем случае перед нами стоит задача визуализировать и хранить расписание для примерно 150 событий (запусков регламентных заданий в 1С и СУБД), часть из которых должна выполняться строго последовательно друг за другом.

В этой статье мы подробно разберем, как решить эту задачу в среде 1С:Предприятие. Мы рассмотрим встроенный элемент формы «Планировщик», классическую Диаграмму Ганта, альтернативный современный подход с использованием JavaScript-библиотек через Поле HTML-документа, а также спроектируем оптимальную структуру хранения данных в базе 1С.

Решение 1: Использование встроенного объекта «Планировщик»

Начиная с версии платформы 8.3.6, в 1С появился мощный встроенный инструмент визуализации — элемент формы Планировщик. Он представляет собой интерактивный календарь (сетку расписания), очень похожий на интерфейсы MS Outlook или Google Calendar.

Критически важная особенность: Планировщик является исключительно визуальным элементом управления. Он существует только в оперативной памяти компьютера в рамках текущей сеансовой работы и не имеет физической таблицы в СУБД. Это означает, что разработчик должен самостоятельно реализовать механизмы чтения данных из базы при открытии формы и записи изменений обратно в базу при интерактивных действиях пользователя.

Рассмотрим по шагам, как настроить визуализацию через Планировщик.

Шаг 1. Наполнение планировщика данными из базы

Для отображения событий нам необходимо программно считать данные из СУБД (например, из справочника или регистра сведений) и заполнить коллекцию Планировщик.Элементы. Каждому событию обязательно требуются две даты: время начала и время окончания.

Проанализируем пример кода для инициализации и заполнения планировщика:


&НаСервере
Процедура ЗаполнитьПланировщикНаСервере()
    
    // Очищаем старые элементы перед заполнением
    ПланировщикФормы.Элементы.Очистить();
    
    // Задаем параметры отображения (например, интервал времени)
    ПланировщикФормы.ТекущийПериодОтображенияОкончание = КонецДня(ТекущаяДата());
    ПланировщикФормы.ТекущийПериодОтображенияНачало = НачалоДня(ТекущаяДата());
    
    // Выбираем данные из нашей таблицы хранения (справочника событий)
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   События.Наименование КАК Представление,
        |   События.ДатаНачала КАК Старт,
        |   События.ДатаОкончания КАК Финиш,
        |   События.Ссылка КАК СсылкаНаОбъект
        |ИЗ
        |   Справочник.СобытияРасписания КАК События";
    
    РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();
    
    Пока Выборка.Следующий() Цикл
        // Добавляем элемент планировщика с указанием времени начала и окончания
        НовыйЭлемент = ПланировщикФормы.Элементы.Добавить(Выборка.Старт, Выборка.Финиш);
        НовыйЭлемент.Текст = Выборка.Представление;
        
        // В свойство Значение сохраняем ссылку на объект БД, чтобы связать интерактивный блок с базой
        НовыйЭлемент.Значение = Выборка.СсылкаНаОбъект;
    КонецЦикла;
    
КонецПроцедуры

Шаг 2. Интерактивное управление (Drag-and-Drop)

Пользователи любят передвигать блоки расписания мышкой или изменять их длительность "растягиванием". Чтобы эти изменения сохранились в базе данных, необходимо перехватить событие формы ПриОкончанииРедактирования (или аналогичные интерактивные события планировщика):


&НаКлиенте
Процедура ПланировщикФормыПриОкончанииРедактирования(Элемент, НовыйЭлемент, ОтменаРедактирования)
    
    Если ОтменаРедактирования Тогда
        Возврат;
    КонецЕсли;
    
    // Получаем новые измененные границы времени и ссылку на наш элемент в БД
    НовоеНачало = НовыйЭлемент.Начало;
    НовыйКонец  = НовыйЭлемент.Конец;
    СсылкаНаБД  = НовыйЭлемент.Значение;
    
    // Записываем обновленные данные в СУБД
    ЗаписатьИзмененияСобытияНаСервере(СсылкаНаБД, НовоеНачало, НовыйКонец);
    
КонецПроцедуры

&НаСервере
Процедура ЗаписатьИзмененияСобытияНаСервере(СсылкаНаБД, НовоеНачало, НовыйКонец)
    
    Если ЗначениеЗаполнено(СсылкаНаБД) Тогда
        ОбъектСобытия = СсылкаНаБД.ПолучитьОбъект();
        ОбъектСобытия.ДатаНачала = НовоеНачало;
        ОбъектСобытия.ДатаОкончания = НовыйКонец;
        ОбъектСобытия.Записать();
    КонецЕсли;
    
КонецПроцедуры

Решение 2: Диаграмма Ганта для цепочек зависимостей

Если часть ваших 150 событий должна запускаться строго друг за другом (цепочки выполнения), обычного календаря может быть недостаточно. Здесь на сцену выходит классический инструмент 1С — ДиаграммаГанта.

Диаграмма Ганта отлично подходит для визуализации связей между задачами (отношения «предшественник — последователь»). В платформе 1С диаграмма Ганта поддерживает установку связей программным путем:


&НаСервере
Процедура ПостроитьДиаграммуГанта()
    
    Диаграмма.АвтоОпределениеПолногоИнтервала = Истина;
    Диаграмма.Очистить();
    
    // Добавляем точки (наши процессы/задания)
    Точка1 = Диаграмма.УстановитьТочку("Задание 1");
    Точка2 = Диаграмма.УстановитьТочку("Задание 2");
    
    // Добавляем серию (например, "Плановое время")
    СерияПланирования = Диаграмма.УстановитьСерию("План");
    
    // Задаем интервалы времени
    Значение1 = Диаграмма.ПолучитьЗначение(Точка1, СерияПланирования);
    Интервал1 = Значение1.Добавить();
    Интервал1.Начало = ТекущаяДата();
    Интервал1.Конец = ТекущаяДата() + 3600; // 1 час
    
    Значение2 = Диаграмма.ПолучитьЗначение(Точка2, СерияПланирования);
    Интервал2 = Значение2.Добавить();
    Интервал2.Начало = Интервал1.Конец; // Начинается сразу после первого
    Интервал2.Конец = Интервал2.Начало + 1800; // 30 минут
    
    // Устанавливаем связь между интервалами (Задание 2 зависит от Задания 1)
    Связь = Диаграмма.Связи.Добавить(Интервал1, Интервал2);
    Связь.ТипСвязи = ТипСвязиДиаграммыГанта.КонецНачало;
    
КонецПроцедуры

Решение 3: JS-библиотеки в Поле HTML-документа (WebKit)

Начиная с версии 1С 8.3.14, произошел важный технологический сдвиг: внутренний движок отображения HTML-форм был заменен на современный WebKit (вместо старого Internet Explorer). Это открыло разработчикам доступ к использованию мощнейших JavaScript-библиотек визуализации прямо внутри интерфейса 1С.

Если вам нужен современный, красивый и высокопроизводительный дизайн расписания, вы можете интегрировать сторонние библиотеки:

  1. FullCalendar — идеально подходит для сеток "день/неделя/месяц".
  2. DHTMLX Scheduler / Gantt — мощное интерактивное решение для построения таймлайнов, распределения ресурсов и выстраивания связей с Drag-and-Drop.
  3. Vis.js — великолепно справляется с интерактивными временными шкалами (Timeline).

Схема интеграции строится на передаче данных в формате JSON:


// Формируем JSON-строку для передачи в JavaScript-календарь
&НаСервере
Функция СформироватьJSONДляКалендаря() Экспорт
    
    МассивСобытий = Новый Массив;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   События.Ссылка КАК Ссылка,
        |   События.Наименование КАК Наименование,
        |   События.ДатаНачала КАК ДатаНачала,
        |   События.ДатаОкончания КАК ДатаОкончания
        |ИЗ
        |   Справочник.СобытияРасписания КАК События";
        
    Выборка = Запрос.Выполнить().Выбрать();
    Пока Выборка.Следующий() Цикл
        СтруктураСобытия = Новый Структура;
        // Передаем уникальный идентификатор для последующей связи
        СтруктураСобытия.Вставить("id", Строка(Выборка.Ссылка.УникальныйИдентификатор()));
        СтруктураСобытия.Вставить("title", Выборка.Наименование);
        СтруктураСобытия.Вставить("start", Формат(Выборка.ДатаНачала, "ДФ=yyyy-MM-ddTHH:mm:ss"));
        СтруктураСобытия.Вставить("end", Формат(Выборка.ДатаОкончания, "ДФ=yyyy-MM-ddTHH:mm:ss"));
        
        МассивСобытий.Добавить(СтруктураСобытия);
    КонецЦикла;
    
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    ЗаписатьJSON(ЗаписьJSON, МассивСобытий);
    Возврат ЗаписьJSON.Закрыть();
    
КонецФункции

Переданную строку JSON мы внедряем в HTML-код страницы в Поле HTML-документа, инициализируя JS-календарь. Обратная связь настраивается через перехват навигации или обработку внешних событий в 1С при совершении действий в браузере.

Решение 4: Проектирование схемы хранения данных в СУБД

Чтобы эффективно управлять 150 событиями, важно заложить правильную архитектуру базы данных. Рассмотрим наиболее оптимальные паттерны проектирования в 1С.

Вариант А. Накопление конкретных запусков (Регистр сведений)

Для хранения фактической сетки запусков на конкретные дни лучше всего подходит периодический или непериодический Регистр сведений (например, РегистрСведений.РасписаниеЗапусков). Его структура:

Вариант Б. Хранение правил повторений (Сериализация настроек)

Часто события происходят периодически (например, «каждый вторник в 14:00»). Вместо ручного создания тысяч записей на годы вперед, вы можете хранить правила генерации расписания с помощью встроенного объекта РасписаниеРегламентногоЗадания. Этот объект можно настроить через стандартное платформенное диалоговое окно, а затем сериализовать в XML-строку для удобного хранения в реквизите справочника.

Разберем, как реализовать сохранение и чтение такого расписания:


// Сериализуем объект расписания 1С в строку XML для записи в БД
&НаСервере
Функция СериализоватьРасписаниеВСтроку(ОбъектРасписание) Экспорт
    
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.УстановитьСтроку();
    ЗаписатьXML(ЗаписьXML, ОбъектРасписание);
    Возврат ЗаписьXML.Закрыть();
    
КонецФункции

// Восстанавливаем объект расписания для редактирования или расчета точек запуска
&НаСервере
Функция ДесериализоватьРасписаниеИзСтроки(СтрокаXML) Экспорт
    
    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.УстановитьСтроку(СтрокаXML);
    ОбъектРасписание = ПрочитатьXML(ЧтениеXML);
    Возврат ОбъектРасписание;
    
КонецФункции

Используя десериализованное расписание, мы можем программно с помощью метода ПолучитьДатыЗапуска() "развернуть" периодические события на выбранный пользователем интервал (например, на неделю вперед) и отобразить их в планировщике, не создавая лишних физических записей в БД.

Вариант В. Реализация последовательных цепочек (Граф зависимостей)

Если некоторые задачи должны идти строго друг за другом, мы проектируем структуру справочника СобытияРасписания с реквизитом самоссылки: ПредыдущееСобытие (Тип: СправочникСсылка.СобытияРасписания).

В этом случае при изменении времени старта корневого задания система должна динамически пересчитывать времена старта последующих звеньев цепи:


&НаСервере
Процедура РассчитатьИЗаписатьЦепочкуВремени(КорневоеСобытие, НовоеВремяСтарта)
    
    // 1. Обновляем корневое событие
    ОбъектКорня = КорневоеСобытие.ПолучитьОбъект();
    Длительность = ОбъектКорня.Длительность; // Длительность в секундах
    ОбъектКорня.ДатаНачала = НовоеВремяСтарта;
    ОбъектКорня.ДатаОкончания = НовоеВремяСтарта + Длительность;
    ОбъектКорня.Записать();
    
    // 2. Рекурсивно или в цикле находим все зависимые события
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   События.Ссылка КАК Ссылка,
        |   События.Длительность КАК Длительность
        |ИЗ
        |   Справочник.СобытияРасписания КАК События
        |ГДЕ
        |   События.ПредыдущееСобытие = &ПредыдущееСобытие";
        
    Запрос.УстановитьПараметр("ПредыдущееСобытие", КорневоеСобытие);
    Результат = Запрос.Выполнить().Выбрать();
    
    ТекущийСтартДляЗависимых = ОбъектКорня.ДатаОкончания;
    
    Пока Результат.Следующий() Цикл
        // Рекурсивно пересчитываем время для каждого зависимого элемента
        РассчитатьИЗаписатьЦепочкуВремени(Результат.Ссылка, ТекущийСтартДляЗависимых);
    КонецЦикла;
    
КонецПроцедуры

Вариант Г. Использование «Очереди заданий» БСП

Если ваша конечная цель состоит не просто в отрисовке красивой схемы, а в реальном запуске процедур 1С по сложным цепочкам, мы настоятельно рекомендуем использовать готовую подсистему Библиотеки стандартных подсистем (БСП) — «Очередь заданий». Она уже содержит в себе протестированные механизмы СУБД для управления потоками выполнения, обработки ошибок, повторных запусков при сбоях и гибкого планирования.

Резюме

Для быстрого старта и простых сценариев используйте встроенный интерактивный Планировщик 1С с хранением данных в регистре сведений. Если перед вами стоит задача управления зависимостями — выбирайте Диаграмму Ганта. Для создания высокотехнологичного и современного интерфейса задействуйте Поле HTML-документа с подключением библиотеки FullCalendar или DHTMLX через формат JSON.

← На главную