При разработке мобильных приложений на платформе 1С часто возникает задача создания системы напоминаний, которая должна работать автономно, без постоянного соединения с центральной базой и без использования регламентных заданий, которые недоступны в мобильном клиенте. В данной статье мы подробно разберем, как использовать объект ДоставляемоеУведомление для реализации периодических задач, таких как уведомления каждый вторник или каждое 5-е число месяца.
Для начала проанализируем, почему мы используем именно локальные уведомления. В отличие от Push-уведомлений, локальные уведомления планируются внутри самого устройства и срабатывают даже в том случае, если приложение закрыто или отсутствует интернет-соединение. За их выполнение отвечает операционная система (Android или iOS). Рассмотрим базовый программный код для создания простого уведомления:
&НаКлиенте
Процедура СоздатьПростоеУведомление()
#Если МобильноеПриложениеКлиент Тогда
Уведомление = Новый ДоставляемоеУведомление;
Уведомление.Заголовок = "Напоминание";
Уведомление.Текст = "Пора выполнить задачу!";
Уведомление.ДатаПоявленияУниверсальноеВремя = УниверсальноеВремя(ТекущаяДата() + 60); // Через минуту
Уведомление.ЗвуковоеОповещение = ЗвуковоеОповещение.ПоУмолчанию;
ДоставляемыеУведомления.ДобавитьЛокальноеУведомление(Уведомление);
#КонецЕсли
КонецПроцедуры
Разберем ситуацию, когда нам нужно, чтобы уведомление срабатывало каждый вторник в 10:00. Для этого нам необходимо решить две задачи: вычислить дату ближайшего вторника и установить правильный интервал повтора. Выясним, как вычислить дату ближайшего нужного дня недели, используя функцию ДеньНедели().
Допустим, сегодня четверг. Чтобы найти ближайший вторник, мы можем использовать следующий алгоритм:
// НужныйДень - число от 1 (понедельник) до 7 (воскресенье)
НужныйДень = 2; // Вторник
ТекущийДень = ДеньНедели(ТекущаяДата());
Если ТекущийДень < НужныйДень Тогда
РазницаДней = НужныйДень - ТекущийДень;
ИначеЕсли ТекущийДень > НужныйДень Тогда
РазницаДней = 7 - (ТекущийДень - НужныйДень);
Иначе // Сегодня вторник
Если Час(ТекущаяДата()) < 10 Тогда
РазницаДней = 0; // Сработает сегодня
Иначе
РазницаДней = 7; // Сработает на следующей неделе
КонецЕсли;
КонецЕсли;
ДатаСрабатывания = НачалоДня(ТекущаяДата()) + (РазницаДней * 86400) + (10 * 3600); // 10:00 утра
После того как мы определили ДатаСрабатывания, установим свойство ИнтервалПовтора. Для еженедельного повторения это значение составляет 604 800 секунд (7 дней * 24 часа * 3600 секунд). Посмотрим на итоговый код:
Уведомление.ДатаПоявленияУниверсальноеВремя = УниверсальноеВремя(ДатаСрабатывания);
Уведомление.ИнтервалПовтора = 86400 * 7;
ДоставляемыеУведомления.ДобавитьЛокальноеУведомление(Уведомление);
Рассмотрим более сложный случай: уведомление должно приходить каждое 5-е число месяца. Основная сложность заключается в том, что в месяцах разное количество дней (28, 29, 30 или 31). Если мы просто укажем интервал в секундах (например, 30 * 86400), то дата уведомления неизбежно «поплывет».
Решение 1: Серия уведомлений. Проанализируем стратегию создания очереди. Поскольку 1С и мобильные ОС позволяют планировать множество уведомлений вперед, мы можем создать цикл на 12 месяцев:
БазоваяДата = '20191205100000'; // 5 декабря 10:00
Для Счетчик = 0 По 11 Цикл
Уведомление = Новый ДоставляемоеУведомление;
ДатаМесяца = ДобавитьМесяц(БазоваяДата, Счетчик);
Уведомление.ДатаПоявленияУниверсальноеВремя = УниверсальноеВремя(ДатаМесяца);
Уведомление.Текст = "Ежемесячный отчет за " + Формат(ДатаМесяца, "ДФ='ММММ гггг'");
ДоставляемыеУведомления.ДобавитьЛокальноеУведомление(Уведомление);
КонецЦикла;
Решение 2: Пересчет при срабатывании. Мы можем запрограммировать систему так, чтобы при получении текущего уведомления она автоматически планировала следующее. Для этого используется обработчик в модуле управляемого приложения.
Чтобы система знала, что делать при активации уведомления пользователем или при его получении, нам нужно подключить обработчик. Это делается в процедуре ПриНачалеРаботыСистемы:
Процедура ПриНачалеРаботыСистемы()
#Если МобильноеПриложениеКлиент Тогда
ДоставляемыеУведомления.ПодключитьОбработчикУведомлений("ПриПолученииУведомления");
#КонецЕсли
КонецПроцедуры
Процедура ПриПолученииУведомления(Уведомление, Локальное, Показано, Параметры) Экспорт
Если Локальное Тогда
// Здесь можно реализовать логику перепланирования следующего уведомления
// Или открыть конкретную форму документа/задачи
Сообщить("Сработало напоминание: " + Уведомление.Текст);
КонецЕсли;
КонецПроцедуры
При работе с уведомлениями необходимо учитывать специфику мобильных платформ:
УниверсальноеВремя(), чтобы избежать сдвигов из-за часовых поясов.Имя объекта ДоставляемоеУведомление как уникальный ключ.Таким образом, мы выяснили, что наиболее надежным способом реализации сложных периодических напоминаний в 1С является сочетание точного расчета даты первого срабатывания и планирование серии уведомлений либо использование логики «цепочки», где каждое следующее уведомление создается программно в момент обработки предыдущего.