Регламентное задание 1С — процедура общего модуля, которую платформа сама вызывает по расписанию: ночью пересчитать себестоимость, каждые 15 минут выгрузить остатки на сайт, утром загрузить курсы валют. Ниже — чем предопределённое задание отличается от обычного, как создать регламентное задание программно с параметрами и ключом, собрать расписание, запустить задание вручную и сделать то же через БСП. Платформа 8.3, весь код серверный.
Объект метаданных создаётся в конфигураторе в ветке Общие → Регламентные задания. Главные свойства: Имя метода (какую процедуру вызывать), Предопределенное, Использование, Расписание, Ключ, количество и интервал повторов при аварийном завершении. Флажок «Предопределенное» меняет модель работы:
| Признак | Предопределённое | Непредопределённое |
|---|---|---|
| Сколько экземпляров | Один на объект метаданных, запись в базе создаёт платформа | Сколько угодно, создаёт код |
| Как получить в коде | РегламентныеЗадания.НайтиПредопределенное() | ПолучитьРегламентныеЗадания(Отбор), НайтиПоУникальномуИдентификатору() |
| Параметры процедуры | Обычно процедура без параметров | Свой массив Параметры у каждого экземпляра |
| Удаление | Нельзя, только снять Использование | Метод Удалить() |
| Начальное расписание | Задаётся в конфигураторе | Из кода или обработки администрирования |
Экземпляр один на всю базу — предопределённое. Количество заданий зависит от данных (складов, организаций, узлов обмена) — непредопределённое, экземпляры различаем по ключу.
Процедура задания должна быть экспортной и лежать в общем модуле с флажком «Сервер». Клиентские флажки не нужны: задание работает в фоновом сеансе на сервере, без форм и пользователя перед экраном. Число параметров процедуры должно совпадать с длиной массива Параметры, который мы передадим при создании экземпляра.
Пример: объект метаданных ВыгрузкаОстатковПоСкладу, флажок «Предопределенное» снят, в «Имя метода» выбрано ВыгрузкаОстатковЗадания.ВыгрузитьОстаткиПоСкладу.
// Общий модуль ВыгрузкаОстатковЗадания. Флажок «Сервер»,
// «Клиент», «Глобальный» и «Вызов сервера» не нужны.
// Обработчик регламентного задания ВыгрузкаОстатковПоСкладу.
// Склад приходит из массива Параметры конкретного экземпляра задания.
Процедура ВыгрузитьОстаткиПоСкладу(Склад) Экспорт
// В конфигурациях на БСП первой строкой:
// ОбщегоНазначения.ПриНачалеВыполненияРегламентногоЗадания(
// Метаданные.РегламентныеЗадания.ВыгрузкаОстатковПоСкладу);
Если Не ЗначениеЗаполнено(Склад) Тогда
ЗаписьЖурналаРегистрации("ВыгрузкаОстатков.Ошибка", УровеньЖурналаРегистрации.Ошибка,
Метаданные.РегламентныеЗадания.ВыгрузкаОстатковПоСкладу, ,
"В параметрах задания не указан склад");
Возврат;
КонецЕсли;
// Регистр условный: подставьте свой регистр остатков и его ресурс.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Остатки.Номенклатура КАК Номенклатура,
| Остатки.КоличествоОстаток КАК Количество
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(, Склад = &Склад) КАК Остатки";
Запрос.УстановитьПараметр("Склад", Склад);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Отправка остатка на сайт или маркетплейс.
КонецЦикла;
ЗаписьЖурналаРегистрации("ВыгрузкаОстатков.Выполнено", УровеньЖурналаРегистрации.Информация,
Метаданные.РегламентныеЗадания.ВыгрузкаОстатковПоСкладу, Склад,
"Выгружено позиций: " + Формат(Выборка.Количество(), "ЧН=0; ЧГ=0"));
КонецПроцедуры
Показать что-либо пользователю задание не может: Предупреждение() и Вопрос() в серверном модуле не скомпилируются, а текст из Сообщить() никто не увидит. Итоги и ошибки пишите в журнал регистрации — администратор найдёт их по имени события. Если процедура записывает несколько связанных объектов, оберните запись в транзакцию, чтобы после сбоя не осталось половины изменений.
Для каждого склада заводим свой экземпляр со своим расписанием. Код ищет задание по ключу и создаёт новое, только если не нашёл, — повторный вызов просто обновит расписание и параметры. Функции лежат в том же общем модуле, форма настроек вызывает их из своей процедуры &НаСервере.
// Ключ экземпляра задания: по нему отличаем задания разных складов.
Функция КлючЗадания(Склад)
Возврат Строка(Склад.УникальныйИдентификатор());
КонецФункции
// Возвращает регламентное задание склада или Неопределено.
Функция НайтиЗаданиеСклада(Склад) Экспорт
Отбор = Новый Структура;
Отбор.Вставить("Метаданные", Метаданные.РегламентныеЗадания.ВыгрузкаОстатковПоСкладу);
Отбор.Вставить("Ключ", КлючЗадания(Склад));
УстановитьПривилегированныйРежим(Истина);
Найденные = РегламентныеЗадания.ПолучитьРегламентныеЗадания(Отбор);
Если Найденные.Количество() = 0 Тогда
Возврат Неопределено;
КонецЕсли;
Возврат Найденные[0];
КонецФункции
// Каждый день с 8:00 до 22:00 с интервалом в минутах.
Функция РасписаниеСИнтервалом(ИнтервалМинут) Экспорт
Расписание = Новый РасписаниеРегламентногоЗадания;
Расписание.ПериодПовтораДней = 1;
Расписание.ПериодПовтораВТечениеДня = ИнтервалМинут * 60; // секунды
Расписание.ВремяНачала = '00010101080000';
Расписание.ВремяКонца = '00010101220000';
Возврат Расписание;
КонецФункции
// Создаёт задание для склада или обновляет существующее.
// Возвращает уникальный идентификатор задания.
Функция НастроитьЗаданиеСклада(Склад, ИнтервалМинут, Включить = Истина) Экспорт
УстановитьПривилегированныйРежим(Истина);
Задание = НайтиЗаданиеСклада(Склад);
Если Задание = Неопределено Тогда
Задание = РегламентныеЗадания.СоздатьРегламентноеЗадание(
Метаданные.РегламентныеЗадания.ВыгрузкаОстатковПоСкладу);
Задание.Ключ = КлючЗадания(Склад);
КонецЕсли;
ПараметрыМетода = Новый Массив;
ПараметрыМетода.Добавить(Склад);
Задание.Параметры = ПараметрыМетода;
Задание.Наименование = "Выгрузка остатков: " + Строка(Склад);
Задание.Расписание = РасписаниеСИнтервалом(ИнтервалМинут);
Задание.Использование = Включить;
Задание.КоличествоПовторовПриАварийномЗавершении = 3;
Задание.ИнтервалПовтораПриАварийномЗавершении = 120; // секунды
Задание.Записать();
Возврат Задание.УникальныйИдентификатор;
КонецФункции
// Удаляет задание склада, если оно есть.
Процедура УдалитьЗаданиеСклада(Склад) Экспорт
УстановитьПривилегированныйРежим(Истина);
Задание = НайтиЗаданиеСклада(Склад);
Если Задание <> Неопределено Тогда
Задание.Удалить();
КонецЕсли;
КонецПроцедуры
УстановитьПривилегированныйРежим(Истина) — менеджер РегламентныеЗадания требует права «Администрирование», а настройку может сохранять и кладовщик. Саму форму настроек закрывайте ролью.СоздатьРегламентноеЗадание() создаёт объект только в памяти, в базе он появится после Записать().Ключ — строка, по которой различаем экземпляры одного объекта метаданных. Следить за уникальностью ключа приходится самим, поэтому поиск перед созданием обязателен, иначе каждое сохранение настроек плодит копии. Берём уникальный идентификатор ссылки склада — он не меняется при переименовании.Параметры — массив, элементы передаются в процедуру по порядку. Массив хранится в базе вместе с заданием, поэтому кладите туда простые значения и ссылки, а не объекты и таблицы.ПериодПовтораДней = 1 — без этой строки расписание не будет повторяться каждый день. ПериодПовтораВТечениеДня задаётся в секундах, ВремяНачала и ВремяКонца — датой, у которой значимо только время.КоличествоПовторовПриАварийномЗавершении и ИнтервалПовтораПриАварийномЗавершении — если процедура упала с исключением, платформа повторит запуск через заданное число секунд, не дожидаясь следующего окна расписания.| Свойство РасписаниеРегламентногоЗадания | Что задаёт |
|---|---|
ПериодПовтораДней | Каждые N дней; 1 — ежедневно |
ПериодПовтораВТечениеДня | Повтор внутри дня, в секундах |
ПаузаПовтора | Пауза в секундах от завершения запуска до следующего старта |
ВремяНачала, ВремяКонца | Окно внутри суток |
ДниНедели | Массив номеров дней: 1 — понедельник, 7 — воскресенье |
Месяцы, ДеньВМесяце | Запуск в определённые месяцы и числа |
ДетальныеРасписанияДня | Несколько окон в сутки, каждое со своими настройками |
Чтобы выгрузка шла только по будням, заполните ДниНедели числами от 1 до 5. Текстовое описание расписания для формы даёт Строка(Задание.Расписание).
Предопределённое задание не создают и не удаляют — его находят и меняют. Типичный случай: в конфигураторе задание выключено, а включает его администратор флажком в форме настроек.
// Включает или выключает предопределённое задание ОчисткаЖурналаОбмена
// и ставит ежедневный запуск на 3:00.
Процедура НастроитьОчисткуЖурнала(Включить) Экспорт
УстановитьПривилегированныйРежим(Истина);
Задание = РегламентныеЗадания.НайтиПредопределенное(
Метаданные.РегламентныеЗадания.ОчисткаЖурналаОбмена);
Если Задание = Неопределено Тогда
Возврат;
КонецЕсли;
Расписание = Новый РасписаниеРегламентногоЗадания;
Расписание.ПериодПовтораДней = 1;
Расписание.ВремяНачала = '00010101030000';
Задание.Использование = Включить;
Задание.Расписание = Расписание;
Задание.Записать();
КонецПроцедуры
Если одному действию понадобились разные входные данные, делайте задание непредопределённым.
Метода «выполнить сейчас» у регламентного задания нет. Каждый запуск по расписанию — это фоновое задание, поэтому для ручного запуска берём имя метода и параметры экземпляра и запускаем фоновое задание сами:
// Запускает задание вне расписания отдельным фоновым заданием.
Функция ЗапуститьСейчас(ИдентификаторЗадания) Экспорт
УстановитьПривилегированныйРежим(Истина);
Задание = РегламентныеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания);
Если Задание = Неопределено Тогда
ВызватьИсключение "Регламентное задание не найдено";
КонецЕсли;
// Ключ заполнен всегда, даже у предопределённого задания с пустым свойством Ключ.
КлючФоновогоЗадания = Строка(Задание.УникальныйИдентификатор);
Фоновое = ФоновыеЗадания.Выполнить(Задание.Метаданные.ИмяМетода, Задание.Параметры,
КлючФоновогоЗадания, Задание.Наименование + " (вручную)");
Возврат Фоновое.УникальныйИдентификатор;
КонецФункции
// Строка о последнем запуске по расписанию — для формы настроек.
Функция ОписаниеПоследнегоЗапуска(ИдентификаторЗадания) Экспорт
УстановитьПривилегированныйРежим(Истина);
Задание = РегламентныеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания);
Если Задание = Неопределено Тогда
Возврат "Задание не найдено";
КонецЕсли;
Последнее = Задание.ПоследнееЗадание;
Если Последнее = Неопределено Тогда
Возврат "Сведений о запусках нет";
КонецЕсли;
Текст = Формат(Последнее.Начало, "ДФ='dd.MM.yyyy HH:mm'") + " — " + Строка(Последнее.Состояние);
Если Последнее.ИнформацияОбОшибке <> Неопределено Тогда
Текст = Текст + Символы.ПС + КраткоеПредставлениеОшибки(Последнее.ИнформацияОбОшибке);
КонецЕсли;
Возврат Текст;
КонецФункции
Ключом фонового задания служит строка с уникальным идентификатором регламентного задания. Свойство Ключ не годится: у предопределённых заданий оно пустое, а с пустым ключом платформа не проверяет, выполняется ли уже такое задание. С непустым ключом второй вызов при активном первом завершится исключением, и двойной щелчок по кнопке не запустит две выгрузки параллельно.
ПоследнееЗадание возвращает последнее фоновое задание, запущенное по расписанию, или Неопределено. Ручной запуск с регламентным заданием не связан, его состояние отслеживайте по возвращённому идентификатору.
Ручной запуск идёт от имени пользователя, нажавшего кнопку, а не от имени из ИмяПользователя регламентного задания. На привилегированный режим из ЗапуститьСейчас внутри фонового задания не рассчитывайте: если обработчику нужны права, которых у пользователя нет, включите привилегированный режим в самом обработчике или оставьте кнопку только администраторам.
В типовых конфигурациях на БСП (УТ 11, БП 3.0, КА 2, ERP, УНФ) менеджер РегламентныеЗадания напрямую лучше не трогать. Подсистема «Регламентные задания» даёт программный интерфейс в общем модуле РегламентныеЗаданияСервер: НайтиЗадания, Задание, ДобавитьЗадание, ИзменитьЗадание, УдалитьЗадание, УстановитьИспользованиеРегламентногоЗадания. Те же вызовы работают и в модели сервиса, где вместо регламентных заданий платформы — очередь заданий. Пример для БСП 3.x и обычной (не облачной) базы:
// Только для конфигураций на БСП 3.x, локальная (не облачная) база.
// КлючЗадания и РасписаниеСИнтервалом — из того же общего модуля.
Процедура НастроитьЗаданиеСкладаБСП(Склад, ИнтервалМинут, Включить = Истина) Экспорт
МетаданныеЗадания = Метаданные.РегламентныеЗадания.ВыгрузкаОстатковПоСкладу;
// Если настройку меняет пользователь без административных прав.
УстановитьПривилегированныйРежим(Истина);
Отбор = Новый Структура;
Отбор.Вставить("Метаданные", МетаданныеЗадания);
Отбор.Вставить("Ключ", КлючЗадания(Склад));
Найденные = РегламентныеЗаданияСервер.НайтиЗадания(Отбор);
ПараметрыМетода = Новый Массив;
ПараметрыМетода.Добавить(Склад);
Настройки = Новый Структура;
Настройки.Вставить("Использование", Включить);
Настройки.Вставить("Расписание", РасписаниеСИнтервалом(ИнтервалМинут));
Настройки.Вставить("Параметры", ПараметрыМетода);
Если Найденные.Количество() = 0 Тогда
Настройки.Вставить("Метаданные", МетаданныеЗадания);
Настройки.Вставить("Ключ", КлючЗадания(Склад));
Настройки.Вставить("Наименование", "Выгрузка остатков: " + Строка(Склад));
РегламентныеЗаданияСервер.ДобавитьЗадание(Настройки);
Иначе
РегламентныеЗаданияСервер.ИзменитьЗадание(Найденные[0].УникальныйИдентификатор, Настройки);
КонецЕсли;
КонецПроцедуры
Ещё две обязательные вещи в БСП-конфигурациях. Первая строка обработчика — ОбщегоНазначения.ПриНачалеВыполненияРегламентногоЗадания() с объектом метаданных задания: она проверяет, можно ли выполнять задание сейчас, например не требуется ли обновление базы, и при необходимости прерывает выполнение. Зависимость задания от функциональной опции и другие настройки описываются в РегламентныеЗаданияПереопределяемый.ПриОпределенииНастроекРегламентныхЗаданий. Состав методов и параметров меняется от версии к версии БСП — сверяйтесь с комментариями к методам в своей конфигурации.
Клиент-серверная база. Задания выполняет кластер серверов 1С, пользователям не нужно быть в базе. В свойствах информационной базы в консоли кластера есть флажок «Блокировка регламентных заданий включена»: пока он стоит, не выполнится ни одно задание. Его ставят на копиях рабочих баз, чтобы тестовая копия ничего не отправила на сайт или в банк, и иногда забывают снять на рабочей базе после переезда.
Файловая база. Отдельного планировщика нет: задания выполняет одно из запущенных приложений (автоматически — начиная с версии 8.3.3), очередь проверяется раз в минуту. Никто не открыл базу — задания не выполняются. На выбор приложения влияет параметр запуска /AllowExecuteScheduledJobs с ключом -Off (не выполнять) или -Force (выполнять обязательно).
Пользователь. Свойство ИмяПользователя задаёт, от чьего имени работает задание по расписанию: от этого зависят права доступа к данным и автор созданных документов.
Использование = Истина; расписание не пустое и заполнен ПериодПовтораДней; в консоли кластера не включена блокировка регламентных заданий; в файловой базе кто-то работает. В БСП-конфигурациях после копирования базы задания, работающие с внешними ресурсами, могут быть заблокированы до решения администратора.Параметры не совпадает с числом параметров процедуры — например, в процедуру добавили параметр, а старые экземпляры задания остались с прежним массивом. Ошибка видна в журнале регистрации и в ПоследнееЗадание.ИнформацияОбОшибке. Новые параметры делайте необязательными.&НаСервере или серверный общий модуль.Метаданные + Ключ. Добавьте поиск и удалите лишние экземпляры.Расписание.ПаузаПовтора, например 300 секунд, — тогда после каждого запуска у сервера будет гарантированный перерыв.Проще всего вызвать процедуру задания из серверной процедуры тестовой обработки — это обычная экспортная процедура. Чтобы поймать именно запуск по расписанию, включите в конфигураторе автоматическое подключение к предметам отладки типа «Фоновое задание». В клиент-серверной базе сервер должен работать с включённой отладкой — подробности в статье про отладку на сервере.
На клиенте есть стандартный диалог ДиалогРасписанияРегламентногоЗадания. Откройте его методом Показать() с описанием оповещения, а полученное расписание передайте в серверную процедуру и запишите в задание, как в примерах выше.
В клиент-серверной базе — да, если задание гарантированно укладывается в интервал и не мешает пользователям. В файловой базе очередь проверяется раз в минуту, чаще не получится.
В журнале регистрации — по событиям фоновых заданий и своим событиям обработчика. В БСП-конфигурациях удобнее форма «Регламентные и фоновые задания» в разделе администрирования: там видны состояние, время последнего запуска и текст ошибки.
Если задание нужно встроить в типовую конфигурацию без правки типовых модулей, связать с обменом или маркетплейсами, или разобраться, почему оно не запускается на рабочем сервере, — поручите это программисту. Посмотрите услуги по доработке 1С или разместите задачу: оценка бесплатная, ответ в течение рабочего дня.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.