/////////////////////////////////////////////////////////////////////////////////////////////////////// // Copyright (c) 2023, ООО 1С-Софт // Все права защищены. Эта программа и сопроводительные материалы предоставляются // в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0) // Текст лицензии доступен по ссылке: // https://creativecommons.org/licenses/by/4.0/legalcode /////////////////////////////////////////////////////////////////////////////////////////////////////// #Область СлужебныйПрограммныйИнтерфейс //////////////////////////////////////////////////////////////////////////////// // Обработчики событий подсистем конфигурации. // См. ОбщегоНазначенияПереопределяемый.ПриДобавленииПараметровРаботыКлиентаПриЗапуске. Процедура ПриДобавленииПараметровРаботыКлиентаПриЗапуске(Параметры) Экспорт Если Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда Возврат; КонецЕсли; ИспользоватьНапоминания = ПолучитьНастройкиНапоминаний().ИспользоватьНапоминания; СписокТекущихНапоминаний = ?(ИспользоватьНапоминания, СписокТекущихНапоминанийПользователя(), Новый Массив); Результат = Новый Структура; Результат.Вставить("ИспользоватьНапоминания", ИспользоватьНапоминания); Результат.Вставить("СписокТекущихНапоминаний", СписокТекущихНапоминаний); Параметры.Вставить("НастройкиНапоминаний", Новый ФиксированнаяСтруктура(Результат)); КонецПроцедуры // См. ОбщегоНазначенияПереопределяемый.ПриДобавленииСерверныхОповещений Процедура ПриДобавленииСерверныхОповещений(Оповещения) Экспорт Оповещение = СерверныеОповещения.НовоеСерверноеОповещение( НапоминанияПользователяКлиентСервер.ИмяСерверногоОповещения()); Оповещение.ИмяМодуляОтправки = "НапоминанияПользователяСлужебный"; Оповещение.ИмяМодуляПолучения = "НапоминанияПользователяКлиент"; Оповещения.Вставить(Оповещение.Имя, Оповещение); КонецПроцедуры // См. СтандартныеПодсистемыСервер.ПриОтправкеСерверногоОповещения Процедура ПриОтправкеСерверногоОповещения(ИмяОповещения, ВариантыПараметров) Экспорт Если Не ПолучитьФункциональнуюОпцию("ИспользоватьНапоминанияПользователя") Тогда Возврат; КонецЕсли; // Добавление оповещений выполняется при записи регистра сведений НапоминанияПользователя. // Периодическое оповещение требуется для гарантии доставки добавленных оповещений и // для актуализации списка напоминаний всех пользователей. АктуализироватьСписокНапоминаний(Ложь); КонецПроцедуры // См. ОбщегоНазначенияПереопределяемый.ПриДобавленииПереименованийОбъектовМетаданных. Процедура ПриДобавленииПереименованийОбъектовМетаданных(Итог) Экспорт Библиотека = "СтандартныеПодсистемы"; СтароеИмя = "Роль.ИспользованиеНапоминаний"; НовоеИмя = "Роль.ДобавлениеИзменениеНапоминаний"; ОбщегоНазначения.ДобавитьПереименование(Итог, "2.3.3.11", СтароеИмя, НовоеИмя, Библиотека); КонецПроцедуры // См. УправлениеДоступомПереопределяемый.ПриЗаполненииСписковСОграничениемДоступа. Процедура ПриЗаполненииСписковСОграничениемДоступа(Списки) Экспорт Списки.Вставить(Метаданные.РегистрыСведений.НапоминанияПользователя, Истина); КонецПроцедуры // Изменить текст напоминаний по предмету. // // Параметры: // Предмет - ЛюбаяСсылка - предмет напоминания; // Идентификатор - Строка - уточняет предмет напоминания, например, "ДеньРождения". // НовыйТекст - Строка - текст напоминания; // Процедура ИзменитьТекстНапоминанийПоПредмету(Предмет, Идентификатор, НовыйТекст) Экспорт Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | НапоминанияПользователя.Пользователь, | НапоминанияПользователя.ВремяСобытия, | НапоминанияПользователя.Источник |ИЗ | РегистрСведений.НапоминанияПользователя КАК НапоминанияПользователя |ГДЕ | НапоминанияПользователя.Идентификатор = &Идентификатор | И НапоминанияПользователя.Источник = &Источник"; Запрос.УстановитьПараметр("Идентификатор", Идентификатор); Запрос.УстановитьПараметр("Источник", Предмет); РезультатЗапроса = Запрос.Выполнить(); ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать(); Пока ВыборкаДетальныеЗаписи.Следующий() Цикл МенеджерЗаписи = РегистрыСведений.НапоминанияПользователя.СоздатьМенеджерЗаписи(); ЗаполнитьЗначенияСвойств(МенеджерЗаписи, ВыборкаДетальныеЗаписи); МенеджерЗаписи.Прочитать(); МенеджерЗаписи.Описание = НовыйТекст; МенеджерЗаписи.Записать(); КонецЦикла; КонецПроцедуры #КонецОбласти #Область СлужебныеПроцедурыИФункции Функция НастройкиПодсистемы() Экспорт Настройки = Новый Структура; Настройки.Вставить("Расписания", ПолучитьСтандартныеРасписанияДляНапоминания()); Настройки.Вставить("СтандартныеИнтервалы", СтандартныеИнтервалыОповещения()); НапоминанияПользователяПереопределяемый.ПриОпределенииНастроек(Настройки); Возврат Настройки; КонецФункции Функция СтандартныеИнтервалыОповещения() Результат = Новый Массив; Результат.Добавить(НСтр("ru = '5 минут'")); Результат.Добавить(НСтр("ru = '10 минут'")); Результат.Добавить(НСтр("ru = '15 минут'")); Результат.Добавить(НСтр("ru = '30 минут'")); Результат.Добавить(НСтр("ru = '1 час'")); Результат.Добавить(НСтр("ru = '2 часа'")); Результат.Добавить(НСтр("ru = '4 часа'")); Результат.Добавить(НСтр("ru = '8 часов'")); Результат.Добавить(НСтр("ru = '1 день'")); Результат.Добавить(НСтр("ru = '2 дня'")); Результат.Добавить(НСтр("ru = '3 дня'")); Результат.Добавить(НСтр("ru = '1 неделю'")); Результат.Добавить(НСтр("ru = '2 недели'")); Возврат Результат; КонецФункции // Возвращает стандартные расписания для периодических напоминаний. Функция ПолучитьСтандартныеРасписанияДляНапоминания() Результат = Новый Соответствие; // по понедельникам в 9:00 Расписание = Новый РасписаниеРегламентногоЗадания; Расписание.ПериодПовтораДней = 1; Расписание.ПериодНедель = 1; Расписание.ВремяНачала = '00010101090000'; ДниНедели = Новый Массив; ДниНедели.Добавить(1); Расписание.ДниНедели = ДниНедели; Результат.Вставить(НСтр("ru = 'по понедельникам, в 9:00'"), Расписание); // по пятницам в 15:00 Расписание = Новый РасписаниеРегламентногоЗадания; Расписание.ПериодПовтораДней = 1; Расписание.ПериодНедель = 1; Расписание.ВремяНачала = '00010101150000'; ДниНедели = Новый Массив; ДниНедели.Добавить(5); Расписание.ДниНедели = ДниНедели; Результат.Вставить(НСтр("ru = 'по пятницам, в 15:00'"), Расписание); // каждый день в 9:00 Расписание = Новый РасписаниеРегламентногоЗадания; Расписание.ПериодПовтораДней = 1; Расписание.ПериодНедель = 1; Расписание.ВремяНачала = '00010101090000'; Результат.Вставить(НСтр("ru = 'каждый день, в 9:00'"), Расписание); Возврат Результат; КонецФункции // Возвращает структуру настроек напоминаний пользователя. Функция ПолучитьНастройкиНапоминаний() Результат = Новый Структура; Результат.Вставить("ИспользоватьНапоминания", ЕстьПравоИспользованияНапоминаний() И ПолучитьФункциональнуюОпцию("ИспользоватьНапоминанияПользователя")); Возврат Результат; КонецФункции // Проверяет наличие права изменения РС НапоминанияПользователя. // // Возвращаемое значение: // Булево - Истина, если право есть. // Функция ЕстьПравоИспользованияНапоминаний() Возврат ПравоДоступа("Изменение", Метаданные.РегистрыСведений.НапоминанияПользователя); КонецФункции // Возвращает ближайшую дату по расписанию относительно даты, переданной в параметре. // // Параметры: // Расписание - РасписаниеРегламентногоЗадания - любое расписание. // ПредыдущаяДата - Дата - дата предыдущего события по расписанию. // ИскатьТолькоБудущиеДаты - Булево - Ложь, если требуется найти дату в прошлом. // // Возвращаемое значение: // Дата - дата и время следующего события по расписанию. // Функция ПолучитьБлижайшуюДатуСобытияПоРасписанию(Расписание, ПредыдущаяДата = '000101010000', ИскатьТолькоБудущиеДаты = Истина) Экспорт Результат = Неопределено; ТекущаяДатаСеанса = ТекущаяДатаСеанса(); ДатаОтсчета = ПредыдущаяДата; Если Не ЗначениеЗаполнено(ДатаОтсчета) Тогда ДатаОтсчета = ТекущаяДатаСеанса; КонецЕсли; Если ИскатьТолькоБудущиеДаты Тогда ДатаОтсчета = Макс(ДатаОтсчета, ТекущаяДатаСеанса); КонецЕсли; Календарь = ПолучитьКалендарьНаБудущее(365*4+1, ДатаОтсчета, Расписание.ДатаНачала, Расписание.ПериодПовтораДней, Расписание.ПериодНедель); ДниНедели = Расписание.ДниНедели; Если ДниНедели.Количество() = 0 Тогда ДниНедели = Новый Массив; Для День = 1 По 7 Цикл ДниНедели.Добавить(День); КонецЦикла; КонецЕсли; Месяцы = Расписание.Месяцы; Если Месяцы.Количество() = 0 Тогда Месяцы = Новый Массив; Для Месяц = 1 По 12 Цикл Месяцы.Добавить(Месяц); КонецЦикла; КонецЕсли; Запрос = Новый Запрос; Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц; Запрос.Текст = "ВЫБРАТЬ * ПОМЕСТИТЬ Календарь ИЗ &Календарь КАК Календарь"; Запрос.УстановитьПараметр("Календарь", Календарь); Запрос.Выполнить(); Запрос.УстановитьПараметр("ДатаНачала", Расписание.ДатаНачала); Запрос.УстановитьПараметр("ДатаКонца", Расписание.ДатаКонца); Запрос.УстановитьПараметр("ДниНедели", ДниНедели); Запрос.УстановитьПараметр("Месяцы", Месяцы); Запрос.УстановитьПараметр("ДеньВМесяце", Расписание.ДеньВМесяце); Запрос.УстановитьПараметр("ДеньНеделиВМесяце", Расписание.ДеньНеделиВМесяце); Запрос.УстановитьПараметр("ПериодПовтораДней", ?(Расписание.ПериодПовтораДней = 0,1,Расписание.ПериодПовтораДней)); Запрос.УстановитьПараметр("ПериодНедель", ?(Расписание.ПериодНедель = 0,1,Расписание.ПериодНедель)); Запрос.Текст = "ВЫБРАТЬ | Календарь.Дата, | Календарь.НомерМесяца, | Календарь.НомерДняНеделиВМесяце, | Календарь.НомерДняНеделиСКонцаМесяца, | Календарь.НомерДняВМесяце, | Календарь.НомерДняВМесяцеСКонцаМесяца, | Календарь.НомерДняВНеделе, | Календарь.НомерДняВПериоде, | Календарь.НомерНеделиВПериоде |ИЗ | Календарь КАК Календарь |ГДЕ | ВЫБОР | КОГДА &ДатаНачала = ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0) | ТОГДА ИСТИНА | ИНАЧЕ Календарь.Дата >= &ДатаНачала | КОНЕЦ | И ВЫБОР | КОГДА &ДатаКонца = ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0) | ТОГДА ИСТИНА | ИНАЧЕ Календарь.Дата <= &ДатаКонца | КОНЕЦ | И Календарь.НомерДняВНеделе В(&ДниНедели) | И Календарь.НомерМесяца В(&Месяцы) | И ВЫБОР | КОГДА &ДеньВМесяце = 0 | ТОГДА ИСТИНА | ИНАЧЕ ВЫБОР | КОГДА &ДеньВМесяце > 0 | ТОГДА Календарь.НомерДняВМесяце = &ДеньВМесяце | ИНАЧЕ Календарь.НомерДняВМесяцеСКонцаМесяца = -&ДеньВМесяце | КОНЕЦ | КОНЕЦ | И ВЫБОР | КОГДА &ДеньНеделиВМесяце = 0 | ТОГДА ИСТИНА | ИНАЧЕ ВЫБОР | КОГДА &ДеньНеделиВМесяце > 0 | ТОГДА Календарь.НомерДняНеделиВМесяце = &ДеньНеделиВМесяце | ИНАЧЕ Календарь.НомерДняНеделиСКонцаМесяца = -&ДеньНеделиВМесяце | КОНЕЦ | КОНЕЦ | И Календарь.НомерДняВПериоде = &ПериодПовтораДней | И Календарь.НомерНеделиВПериоде = &ПериодНедель"; Выборка = Запрос.Выполнить().Выбрать(); Если Выборка.Следующий() Тогда БлижайшаяДата = Выборка.Дата; ВремяОтсчета = '00010101'; Если НачалоДня(БлижайшаяДата) = НачалоДня(ДатаОтсчета) Тогда ВремяОтсчета = ВремяОтсчета + (ДатаОтсчета-НачалоДня(ДатаОтсчета)); КонецЕсли; БлижайшееВремя = ПолучитьБлижайшееВремяИзРасписания(Расписание, ВремяОтсчета); Если БлижайшееВремя <> Неопределено Тогда Результат = БлижайшаяДата + (БлижайшееВремя - '00010101'); Иначе Если Выборка.Следующий() Тогда Время = ПолучитьБлижайшееВремяИзРасписания(Расписание); Результат = Выборка.Дата + (Время - '00010101'); КонецЕсли; КонецЕсли; КонецЕсли; Возврат Результат; КонецФункции Функция ПолучитьКалендарьНаБудущее(КоличествоДнейКалендаря, ДатаОтсчета, Знач ДатаНачалаПериодичности = Неопределено, Знач ПериодДней = 1, Знач ПериодНедель = 1) Если ПериодНедель = 0 Тогда ПериодНедель = 1; КонецЕсли; Если ПериодДней = 0 Тогда ПериодДней = 1; КонецЕсли; Если Не ЗначениеЗаполнено(ДатаНачалаПериодичности) Тогда ДатаНачалаПериодичности = ДатаОтсчета; КонецЕсли; Календарь = Новый ТаблицаЗначений; Календарь.Колонки.Добавить("Дата", Новый ОписаниеТипов("Дата",,,Новый КвалификаторыДаты())); Календарь.Колонки.Добавить("НомерМесяца", Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(2,0,ДопустимыйЗнак.Неотрицательный))); Календарь.Колонки.Добавить("НомерДняНеделиВМесяце", Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(1,0,ДопустимыйЗнак.Неотрицательный))); Календарь.Колонки.Добавить("НомерДняНеделиСКонцаМесяца", Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(1,0,ДопустимыйЗнак.Неотрицательный))); Календарь.Колонки.Добавить("НомерДняВМесяце", Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(2,0,ДопустимыйЗнак.Неотрицательный))); Календарь.Колонки.Добавить("НомерДняВМесяцеСКонцаМесяца", Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(2,0,ДопустимыйЗнак.Неотрицательный))); Календарь.Колонки.Добавить("НомерДняВНеделе", Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(2,0,ДопустимыйЗнак.Неотрицательный))); Календарь.Колонки.Добавить("НомерДняВПериоде", Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(3,0,ДопустимыйЗнак.Неотрицательный))); Календарь.Колонки.Добавить("НомерНеделиВПериоде", Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(3,0,ДопустимыйЗнак.Неотрицательный))); Дата = НачалоДня(ДатаОтсчета); ДатаНачалаПериодичности = НачалоДня(ДатаНачалаПериодичности); НомерДняВПериоде = 0; НомерНеделиВПериоде = 0; Если ДатаНачалаПериодичности <= Дата Тогда КоличествоДней = (Дата - ДатаНачалаПериодичности)/60/60/24; НомерДняВПериоде = КоличествоДней - Цел(КоличествоДней/ПериодДней)*ПериодДней; КоличествоНедель = Цел(КоличествоДней / 7); НомерНеделиВПериоде = КоличествоНедель - Цел(КоличествоНедель/ПериодНедель)*ПериодНедель; КонецЕсли; Если НомерДняВПериоде = 0 Тогда НомерДняВПериоде = ПериодДней; КонецЕсли; Если НомерНеделиВПериоде = 0 Тогда НомерНеделиВПериоде = ПериодНедель; КонецЕсли; Для Счетчик = 0 По КоличествоДнейКалендаря - 1 Цикл Дата = НачалоДня(ДатаОтсчета) + Счетчик * 60*60*24; НоваяСтрока = Календарь.Добавить(); НоваяСтрока.Дата = Дата; НоваяСтрока.НомерМесяца = Месяц(Дата); НоваяСтрока.НомерДняНеделиВМесяце = Цел((Дата - НачалоМесяца(Дата))/60/60/24/7) + 1; НоваяСтрока.НомерДняНеделиСКонцаМесяца = Цел((КонецМесяца(НачалоДня(Дата)) - Дата)/60/60/24/7) + 1; НоваяСтрока.НомерДняВМесяце = День(Дата); НоваяСтрока.НомерДняВМесяцеСКонцаМесяца = День(КонецМесяца(НачалоДня(Дата))) - День(Дата) + 1; НоваяСтрока.НомерДняВНеделе = ДеньНедели(Дата); Если ДатаНачалаПериодичности <= Дата Тогда НоваяСтрока.НомерДняВПериоде = НомерДняВПериоде; НоваяСтрока.НомерНеделиВПериоде = НомерНеделиВПериоде; НомерДняВПериоде = ?(НомерДняВПериоде+1 > ПериодДней, 1, НомерДняВПериоде+1); Если НоваяСтрока.НомерДняВНеделе = 1 Тогда НомерНеделиВПериоде = ?(НомерНеделиВПериоде+1 > ПериодНедель, 1, НомерНеделиВПериоде+1); КонецЕсли; КонецЕсли; КонецЦикла; Возврат Календарь; КонецФункции Функция ПолучитьБлижайшееВремяИзРасписания(Расписание, Знач ВремяОтсчета = '000101010000') Результат = Неопределено; СписокЗначений = Новый СписокЗначений; Если Расписание.ДетальныеРасписанияДня.Количество() = 0 Тогда СписокЗначений.Добавить(Расписание.ВремяНачала); Иначе Для Каждого РасписаниеДня Из Расписание.ДетальныеРасписанияДня Цикл СписокЗначений.Добавить(РасписаниеДня.ВремяНачала); КонецЦикла; КонецЕсли; СписокЗначений.СортироватьПоЗначению(НаправлениеСортировки.Возр); Для Каждого ВремяДня Из СписокЗначений Цикл Если ВремяОтсчета <= ВремяДня.Значение Тогда Результат = ВремяДня.Значение; Прервать; КонецЕсли; КонецЦикла; Возврат Результат; КонецФункции // Параметры: // Расписание - РасписаниеРегламентногоЗадания // НачалоПериода - Дата // КонецПериода - Дата // Возвращаемое значение: // Массив из Дата // Функция ГрафикСобытия(Расписание, НачалоПериода, КонецПериода) Результат = Неопределено; ДатаОтсчета = НачалоПериода; Календарь = ПолучитьКалендарьНаБудущее((НачалоДня(КонецПериода) - НачалоДня(НачалоПериода)) / (60*60*24) + 1, ДатаОтсчета, Расписание.ДатаНачала, Расписание.ПериодПовтораДней, Расписание.ПериодНедель); ДниНедели = Расписание.ДниНедели; Если ДниНедели.Количество() = 0 Тогда ДниНедели = Новый Массив; Для День = 1 По 7 Цикл ДниНедели.Добавить(День); КонецЦикла; КонецЕсли; Месяцы = Расписание.Месяцы; Если Месяцы.Количество() = 0 Тогда Месяцы = Новый Массив; Для Месяц = 1 По 12 Цикл Месяцы.Добавить(Месяц); КонецЦикла; КонецЕсли; Запрос = Новый Запрос; Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц; Запрос.Текст = "ВЫБРАТЬ * ПОМЕСТИТЬ Календарь ИЗ &Календарь КАК Календарь"; Запрос.УстановитьПараметр("Календарь", Календарь); Запрос.Выполнить(); Запрос.УстановитьПараметр("ДатаНачала", Расписание.ДатаНачала); Запрос.УстановитьПараметр("ДатаКонца", Расписание.ДатаКонца); Запрос.УстановитьПараметр("ДниНедели", ДниНедели); Запрос.УстановитьПараметр("Месяцы", Месяцы); Запрос.УстановитьПараметр("ДеньВМесяце", Расписание.ДеньВМесяце); Запрос.УстановитьПараметр("ДеньНеделиВМесяце", Расписание.ДеньНеделиВМесяце); Запрос.УстановитьПараметр("ПериодПовтораДней", ?(Расписание.ПериодПовтораДней = 0,1,Расписание.ПериодПовтораДней)); Запрос.УстановитьПараметр("ПериодНедель", ?(Расписание.ПериодНедель = 0,1,Расписание.ПериодНедель)); Запрос.Текст = "ВЫБРАТЬ | Календарь.Дата, | Календарь.НомерМесяца, | Календарь.НомерДняНеделиВМесяце, | Календарь.НомерДняНеделиСКонцаМесяца, | Календарь.НомерДняВМесяце, | Календарь.НомерДняВМесяцеСКонцаМесяца, | Календарь.НомерДняВНеделе, | Календарь.НомерДняВПериоде, | Календарь.НомерНеделиВПериоде |ИЗ | Календарь КАК Календарь |ГДЕ | ВЫБОР | КОГДА &ДатаНачала = ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0) | ТОГДА ИСТИНА | ИНАЧЕ Календарь.Дата >= &ДатаНачала | КОНЕЦ | И ВЫБОР | КОГДА &ДатаКонца = ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0) | ТОГДА ИСТИНА | ИНАЧЕ Календарь.Дата <= &ДатаКонца | КОНЕЦ | И Календарь.НомерДняВНеделе В(&ДниНедели) | И Календарь.НомерМесяца В(&Месяцы) | И ВЫБОР | КОГДА &ДеньВМесяце = 0 | ТОГДА ИСТИНА | ИНАЧЕ ВЫБОР | КОГДА &ДеньВМесяце > 0 | ТОГДА Календарь.НомерДняВМесяце = &ДеньВМесяце | ИНАЧЕ Календарь.НомерДняВМесяцеСКонцаМесяца = -&ДеньВМесяце | КОНЕЦ | КОНЕЦ | И ВЫБОР | КОГДА &ДеньНеделиВМесяце = 0 | ТОГДА ИСТИНА | ИНАЧЕ ВЫБОР | КОГДА &ДеньНеделиВМесяце > 0 | ТОГДА Календарь.НомерДняНеделиВМесяце = &ДеньНеделиВМесяце | ИНАЧЕ Календарь.НомерДняНеделиСКонцаМесяца = -&ДеньНеделиВМесяце | КОНЕЦ | КОНЕЦ | И Календарь.НомерДняВПериоде = &ПериодПовтораДней | И Календарь.НомерНеделиВПериоде = &ПериодНедель"; Выборка = Запрос.Выполнить().Выбрать(); Результат = Новый Массив; Пока Выборка.Следующий() Цикл БлижайшаяДата = Выборка.Дата; ВремяОтсчета = '00010101'; Если НачалоДня(БлижайшаяДата) = НачалоДня(ДатаОтсчета) Тогда ВремяОтсчета = ВремяОтсчета + (ДатаОтсчета-НачалоДня(ДатаОтсчета)); КонецЕсли; ДатаИВремя = Неопределено; БлижайшееВремя = ПолучитьБлижайшееВремяИзРасписания(Расписание, ВремяОтсчета); Если БлижайшееВремя <> Неопределено Тогда ДатаИВремя = БлижайшаяДата + (БлижайшееВремя - '00010101'); Иначе Если Выборка.Следующий() Тогда Время = ПолучитьБлижайшееВремяИзРасписания(Расписание); ДатаИВремя = Выборка.Дата + (Время - '00010101'); КонецЕсли; КонецЕсли; Если ЗначениеЗаполнено(ДатаИВремя) И ДатаИВремя <= КонецПериода Тогда Результат.Добавить(ДатаИВремя); КонецЕсли; КонецЦикла; Возврат Результат; КонецФункции // Проверяет изменения реквизитов предметов, на которые есть пользовательская подписка, // изменяет срок напоминания в случае необходимости. // Процедура ОбновитьНапоминанияПоПредметам(Предметы) Экспорт УстановитьПривилегированныйРежим(Истина); ТаблицаРезультата = НапоминанияПоПредметам(Предметы); Для Каждого СтрокаТаблицы Из ТаблицаРезультата Цикл ДатаПредмета = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СтрокаТаблицы.Источник, СтрокаТаблицы.ИмяРеквизитаИсточника); Если (ДатаПредмета - СтрокаТаблицы.ИнтервалВремениНапоминания) <> СтрокаТаблицы.ВремяСобытия Тогда // @skip-check query-in-loop - запись данных набором с чтением в цикле. ОтключитьНапоминание(СтрокаТаблицы, Ложь); СтрокаТаблицы.СрокНапоминания = ДатаПредмета - СтрокаТаблицы.ИнтервалВремениНапоминания; СтрокаТаблицы.ВремяСобытия = ДатаПредмета; Если СтрокаТаблицы.Расписание.Получить() <> Неопределено Тогда СтрокаТаблицы.ПовторятьЕжегодно = Истина; КонецЕсли; ПараметрыНапоминания = ОбщегоНазначения.СтрокаТаблицыЗначенийВСтруктуру(СтрокаТаблицы); ПараметрыНапоминания.Расписание = СтрокаТаблицы.Расписание.Получить(); // @skip-check query-in-loop - запись данных набором с чтением в цикле. Напоминание = СоздатьНапоминание(ПараметрыНапоминания); ПодключитьНапоминание(Напоминание); КонецЕсли; КонецЦикла; КонецПроцедуры // Параметры: // Предметы - Массив из ЛюбаяСсылка // // Возвращаемое значение: // ТаблицаЗначений: // * Пользователь - СправочникСсылка.Пользователи // * ВремяСобытия - Дата // * Источник - ОпределяемыйТип.ПредметНапоминания // * СрокНапоминания - Дата // * Описание - Строка // * СпособУстановкиВремениНапоминания - ПеречислениеСсылка.СпособыУстановкиВремениНапоминания // * ИнтервалВремениНапоминания - Число // * ИмяРеквизитаИсточника - Строка // * Расписание - ХранилищеЗначения // * ПовторятьЕжегодно - Булево // Функция НапоминанияПоПредметам(Знач Предметы) Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | Напоминания.Пользователь, | Напоминания.ВремяСобытия, | Напоминания.Источник, | Напоминания.СрокНапоминания, | Напоминания.Описание, | Напоминания.СпособУстановкиВремениНапоминания, | Напоминания.ИнтервалВремениНапоминания, | Напоминания.ИмяРеквизитаИсточника, | Напоминания.Расписание, | Напоминания.Идентификатор, | ЛОЖЬ КАК ПовторятьЕжегодно |ИЗ | РегистрСведений.НапоминанияПользователя КАК Напоминания |ГДЕ | Напоминания.СпособУстановкиВремениНапоминания = ЗНАЧЕНИЕ(Перечисление.СпособыУстановкиВремениНапоминания.ОтносительноВремениПредмета) | И Напоминания.Источник В(&Предметы)"; Запрос.УстановитьПараметр("Предметы", Предметы); ТаблицаРезультата = Запрос.Выполнить().Выгрузить(); Возврат ТаблицаРезультата КонецФункции // Обработчик подписки на событие ПриЗаписи объекта, по поводу которого можно создавать напоминания. Процедура ПроверитьИзмененияДатВПредметеПриЗаписи(Источник, Отказ) Экспорт Если Источник.ОбменДанными.Загрузка Тогда Возврат; КонецЕсли; Если СтандартныеПодсистемыСервер.ЭтоИдентификаторОбъектаМетаданных(Источник) Тогда Возврат; КонецЕсли; Если ПолучитьФункциональнуюОпцию("ИспользоватьНапоминанияПользователя") Тогда ОбновитьНапоминанияПоПредметам(ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(Источник.Ссылка)); КонецЕсли; КонецПроцедуры // Создает напоминание пользователя. Если по объекту уже есть напоминание, то сдвигает время напоминания на секунды вперед. Процедура ПодключитьНапоминание(ПараметрыНапоминания, ОбновитьСрокНапоминания = Ложь, БезОповещенияКлиента = Ложь) Экспорт НаборЗаписей = РегистрыСведений.НапоминанияПользователя.СоздатьНаборЗаписей(); Если БезОповещенияКлиента Тогда НаборЗаписей.ДополнительныеСвойства.Вставить("БезОповещенияКлиента"); КонецЕсли; НаборЗаписей.Отбор.Пользователь.Установить(ПараметрыНапоминания.Пользователь); НаборЗаписей.Отбор.Источник.Установить(ПараметрыНапоминания.Источник); Блокировка = Новый БлокировкаДанных; ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.НапоминанияПользователя"); ЭлементБлокировки.УстановитьЗначение("Пользователь", ПараметрыНапоминания.Пользователь); ЭлементБлокировки.УстановитьЗначение("Источник", ПараметрыНапоминания.Источник); Если ОбновитьСрокНапоминания Тогда НаборЗаписей.Отбор.ВремяСобытия.Установить(ПараметрыНапоминания.ВремяСобытия); ЭлементБлокировки.УстановитьЗначение("ВремяСобытия", ПараметрыНапоминания.ВремяСобытия); КонецЕсли; НачатьТранзакцию(); Попытка Блокировка.Заблокировать(); НаборЗаписей.Прочитать(); Если ОбновитьСрокНапоминания Тогда Для Каждого Запись Из НаборЗаписей Цикл ЗаполнитьЗначенияСвойств(Запись, ПараметрыНапоминания); КонецЦикла; Иначе Если НаборЗаписей.Количество() > 0 Тогда ЗанятоеВремя = НаборЗаписей.Выгрузить(,"ВремяСобытия").ВыгрузитьКолонку("ВремяСобытия"); Пока ЗанятоеВремя.Найти(ПараметрыНапоминания.ВремяСобытия) <> Неопределено Цикл ПараметрыНапоминания.ВремяСобытия = ПараметрыНапоминания.ВремяСобытия + 1; КонецЦикла; КонецЕсли; НоваяЗапись = НаборЗаписей.Добавить(); ЗаполнитьЗначенияСвойств(НоваяЗапись, ПараметрыНапоминания); КонецЕсли; Если НаборЗаписей.Количество() > 0 Тогда НаборЗаписей.Записать(); КонецЕсли; ЗафиксироватьТранзакцию(); Исключение ОтменитьТранзакцию(); ВызватьИсключение; КонецПопытки; КонецПроцедуры // Отключает напоминание, если оно есть. Если напоминание периодическое, подключает его на ближайшую дату по расписанию. Процедура ОтключитьНапоминание(ПараметрыНапоминания, ПодключатьПоРасписанию = Истина, БезОповещенияКлиента = Ложь) Экспорт ТекстЗапроса = "ВЫБРАТЬ | НапоминанияПользователя.Пользователь КАК Пользователь, | НапоминанияПользователя.ВремяСобытия КАК ВремяСобытия, | НапоминанияПользователя.Источник КАК Источник, | НапоминанияПользователя.СрокНапоминания КАК СрокНапоминания, | НапоминанияПользователя.Описание КАК Описание, | НапоминанияПользователя.СпособУстановкиВремениНапоминания КАК СпособУстановкиВремениНапоминания, | НапоминанияПользователя.Расписание КАК Расписание, | НапоминанияПользователя.ИнтервалВремениНапоминания КАК ИнтервалВремениНапоминания, | НапоминанияПользователя.ИмяРеквизитаИсточника КАК ИмяРеквизитаИсточника, | НапоминанияПользователя.Идентификатор КАК Идентификатор |ИЗ | РегистрСведений.НапоминанияПользователя КАК НапоминанияПользователя |ГДЕ | НапоминанияПользователя.Пользователь = &Пользователь | И НапоминанияПользователя.ВремяСобытия = &ВремяСобытия | И НапоминанияПользователя.Источник = &Источник"; Запрос = Новый Запрос(ТекстЗапроса); Запрос.УстановитьПараметр("Пользователь", ПараметрыНапоминания.Пользователь); Запрос.УстановитьПараметр("ВремяСобытия", ПараметрыНапоминания.ВремяСобытия); Запрос.УстановитьПараметр("Источник", ПараметрыНапоминания.Источник); Блокировка = Новый БлокировкаДанных; ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.НапоминанияПользователя"); ЭлементБлокировки.УстановитьЗначение("Пользователь", ПараметрыНапоминания.Пользователь); ЭлементБлокировки.УстановитьЗначение("Источник", ПараметрыНапоминания.Источник); ЭлементБлокировки.УстановитьЗначение("ВремяСобытия", ПараметрыНапоминания.ВремяСобытия); НачатьТранзакцию(); Попытка Блокировка.Заблокировать(); РезультатЗапроса = Запрос.Выполнить().Выгрузить(); Напоминание = Неопределено; Если РезультатЗапроса.Количество() > 0 Тогда Напоминание = РезультатЗапроса[0]; КонецЕсли; // Удаляем существующую запись. НаборЗаписей = РегистрыСведений.НапоминанияПользователя.СоздатьНаборЗаписей(); Если БезОповещенияКлиента Тогда НаборЗаписей.ДополнительныеСвойства.Вставить("БезОповещенияКлиента"); КонецЕсли; НаборЗаписей.Отбор.Пользователь.Установить(ПараметрыНапоминания.Пользователь); НаборЗаписей.Отбор.Источник.Установить(ПараметрыНапоминания.Источник); НаборЗаписей.Отбор.ВремяСобытия.Установить(ПараметрыНапоминания.ВремяСобытия); НаборЗаписей.Записать(); // Подключаем следующее напоминание по расписанию. СледующаяДатаПоРасписанию = Неопределено; ОпределенаСледующаяДатаПоРасписанию = Ложь; Если ПодключатьПоРасписанию И Напоминание <> Неопределено Тогда Расписание = Напоминание.Расписание.Получить(); Если Расписание <> Неопределено Тогда Если Расписание.ПериодПовтораДней > 0 Тогда СледующаяДатаПоРасписанию = ПолучитьБлижайшуюДатуСобытияПоРасписанию(Расписание, ПараметрыНапоминания.ВремяСобытия + 1); КонецЕсли; ОпределенаСледующаяДатаПоРасписанию = СледующаяДатаПоРасписанию <> Неопределено; КонецЕсли; Если ОпределенаСледующаяДатаПоРасписанию Тогда Напоминание.ВремяСобытия = СледующаяДатаПоРасписанию; Напоминание.СрокНапоминания = Напоминание.ВремяСобытия - Напоминание.ИнтервалВремениНапоминания; ПодключитьНапоминание(Напоминание, , БезОповещенияКлиента); КонецЕсли; КонецЕсли; ЗафиксироватьТранзакцию(); Исключение ОтменитьТранзакцию(); ВызватьИсключение; КонецПопытки; КонецПроцедуры // Возвращаемое значение: // Структура: // * Пользователь - СправочникСсылка.Пользователи // * ВремяСобытия - Дата // * Источник - ОпределяемыйТип.ПредметНапоминания // * СрокНапоминания - Дата // * Описание - Строка // * СпособУстановкиВремениНапоминания - ПеречислениеСсылка.СпособыУстановкиВремениНапоминания // * ИнтервалВремениНапоминания - Число // * ИмяРеквизитаИсточника - Строка // * Расписание - ХранилищеЗначения - значение типа РасписаниеРегламентногоЗадания // * ПредставлениеИсточника - Строка // * Идентификатор - Строка // Функция ПодключитьПроизвольноеНапоминание(Текст, ВремяСобытия, ИнтервалДоСобытия = 0, Предмет = Неопределено, Идентификатор = Неопределено) Экспорт ПараметрыНапоминания = Новый Структура; ПараметрыНапоминания.Вставить("Описание", Текст); Если ТипЗнч(ВремяСобытия) = Тип("РасписаниеРегламентногоЗадания") Тогда ПараметрыНапоминания.Вставить("Расписание", ВремяСобытия); ИначеЕсли ТипЗнч(ВремяСобытия) = Тип("Строка") Тогда ПараметрыНапоминания.Вставить("ИмяРеквизитаИсточника", ВремяСобытия); Иначе ПараметрыНапоминания.Вставить("ВремяСобытия", ВремяСобытия); КонецЕсли; ПараметрыНапоминания.Вставить("ИнтервалВремениНапоминания", ИнтервалДоСобытия); ПараметрыНапоминания.Вставить("Источник", Предмет); ПараметрыНапоминания.Вставить("Идентификатор", Идентификатор); Напоминание = СоздатьНапоминание(ПараметрыНапоминания); ПодключитьНапоминание(Напоминание); Возврат Напоминание; КонецФункции Функция ПодключитьНапоминаниеДоВремениПредмета(Текст, Интервал, Предмет, ИмяРеквизита, ПовторятьЕжегодно = Ложь) Экспорт ПараметрыНапоминания = Новый Структура; ПараметрыНапоминания.Вставить("Описание", Текст); ПараметрыНапоминания.Вставить("Источник", Предмет); ПараметрыНапоминания.Вставить("ИмяРеквизитаИсточника", ИмяРеквизита); ПараметрыНапоминания.Вставить("ИнтервалВремениНапоминания", Интервал); ПараметрыНапоминания.Вставить("ПовторятьЕжегодно", ПовторятьЕжегодно); Напоминание = СоздатьНапоминание(ПараметрыНапоминания); ПодключитьНапоминание(Напоминание); Возврат Напоминание; КонецФункции // Возвращает структуру нового напоминания для последующего подключения. Функция СоздатьНапоминание(ПараметрыНапоминания) Напоминание = НапоминанияПользователяКлиентСервер.ОписаниеНапоминания(ПараметрыНапоминания, Истина); Если Не ЗначениеЗаполнено(Напоминание.Пользователь) Тогда Напоминание.Пользователь = Пользователи.ТекущийПользователь(); КонецЕсли; Если Не ЗначениеЗаполнено(Напоминание.СпособУстановкиВремениНапоминания) Тогда Если ЗначениеЗаполнено(Напоминание.Источник) И Не ПустаяСтрока(Напоминание.ИмяРеквизитаИсточника) Тогда Напоминание.СпособУстановкиВремениНапоминания = Перечисления.СпособыУстановкиВремениНапоминания.ОтносительноВремениПредмета; ИначеЕсли Напоминание.Расписание <> Неопределено Тогда Напоминание.СпособУстановкиВремениНапоминания = Перечисления.СпособыУстановкиВремениНапоминания.Периодически; ИначеЕсли Не ЗначениеЗаполнено(Напоминание.ВремяСобытия) Тогда Напоминание.СпособУстановкиВремениНапоминания = Перечисления.СпособыУстановкиВремениНапоминания.ОтносительноТекущегоВремени; Иначе Напоминание.СпособУстановкиВремениНапоминания = Перечисления.СпособыУстановкиВремениНапоминания.ВУказанноеВремя; КонецЕсли; КонецЕсли; Если Напоминание.СпособУстановкиВремениНапоминания = Перечисления.СпособыУстановкиВремениНапоминания.ОтносительноВремениПредмета Тогда Напоминание.ВремяСобытия = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Напоминание.Источник, Напоминание.ИмяРеквизитаИсточника); Напоминание.СрокНапоминания = Напоминание.ВремяСобытия - ?(ЗначениеЗаполнено(Напоминание.ВремяСобытия), Напоминание.ИнтервалВремениНапоминания, 0); ИначеЕсли Напоминание.СпособУстановкиВремениНапоминания = Перечисления.СпособыУстановкиВремениНапоминания.ОтносительноТекущегоВремени Тогда Напоминание.СпособУстановкиВремениНапоминания = Перечисления.СпособыУстановкиВремениНапоминания.ВУказанноеВремя; Напоминание.ВремяСобытия = ТекущаяДатаСеанса() + Напоминание.ИнтервалВремениНапоминания; ИначеЕсли Напоминание.СпособУстановкиВремениНапоминания = Перечисления.СпособыУстановкиВремениНапоминания.ВУказанноеВремя Тогда Напоминание.СрокНапоминания = Напоминание.ВремяСобытия - Напоминание.ИнтервалВремениНапоминания; КонецЕсли; Если Не ЗначениеЗаполнено(Напоминание.СрокНапоминания) Тогда Напоминание.СрокНапоминания = Напоминание.ВремяСобытия; КонецЕсли; Если Напоминание.ПовторятьЕжегодно Тогда Если ЗначениеЗаполнено(Напоминание.ВремяСобытия) Тогда Напоминание.Расписание = НапоминанияПользователяКлиентСервер.ЕжегодноеРасписание(Напоминание.ВремяСобытия); КонецЕсли; КонецЕсли; Если Напоминание.Расписание <> Неопределено Тогда Напоминание.ВремяСобытия = ПолучитьБлижайшуюДатуСобытияПоРасписанию(Напоминание.Расписание); Если Напоминание.ВремяСобытия = Неопределено Тогда Напоминание.ВремяСобытия = '00010101'; КонецЕсли; Напоминание.СрокНапоминания = Напоминание.ВремяСобытия - Напоминание.ИнтервалВремениНапоминания; КонецЕсли; Напоминание.Расписание = Новый ХранилищеЗначения(Напоминание.Расписание, Новый СжатиеДанных(9)); Возврат Напоминание; КонецФункции // Возвращаемое значение: // Структура: // * Добавленные - см. СписокТекущихНапоминанийПользователя // * Удаленные - см. СписокТекущихНапоминанийПользователя // Функция НовыеИзмененныеНапоминания() Экспорт Возврат Новый Структура("Добавленные, Удаленные", Новый Массив, Новый Массив); КонецФункции // Прекращает просроченные периодические напоминания. Процедура АктуализироватьСписокНапоминаний(ПриЗапуске) ТекстЗапроса = "ВЫБРАТЬ РАЗРЕШЕННЫЕ | Напоминания.Пользователь КАК Пользователь, | Напоминания.ВремяСобытия КАК ВремяСобытия, | Напоминания.Источник КАК Источник, | Напоминания.СрокНапоминания КАК СрокНапоминания, | Напоминания.Описание КАК Описание, | Напоминания.СпособУстановкиВремениНапоминания КАК СпособУстановкиВремениНапоминания, | Напоминания.ИнтервалВремениНапоминания КАК ИнтервалВремениНапоминания, | Напоминания.ИмяРеквизитаИсточника КАК ИмяРеквизитаИсточника, | Напоминания.Расписание КАК Расписание, | Напоминания.ПредставлениеИсточника КАК ПредставлениеИсточника, | Напоминания.Идентификатор КАК Идентификатор |ИЗ | РегистрСведений.НапоминанияПользователя КАК Напоминания |ГДЕ | Напоминания.ВремяСобытия <= &ТекущаяДата | И &ОтборПоПользователю"; Запрос = Новый Запрос(ТекстЗапроса); Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДатаСеанса()); Если ПриЗапуске Тогда Запрос.УстановитьПараметр("Пользователь", Пользователи.ТекущийПользователь()); Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ОтборПоПользователю", "Напоминания.Пользователь = &Пользователь"); Иначе Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ОтборПоПользователю", "ИСТИНА"); КонецЕсли; УстановитьПривилегированныйРежим(Истина); СписокНапоминаний = Запрос.Выполнить().Выгрузить(); УстановитьПривилегированныйРежим(Ложь); Для Каждого Напоминание Из СписокНапоминаний Цикл Расписание = Напоминание.Расписание.Получить(); Если Расписание = Неопределено Тогда Продолжить; КонецЕсли; // @skip-check query-in-loop - нет обращения к данным ИБ в запросе. ГрафикСобытияНаГод = ГрафикСобытия(Расписание, Напоминание.ВремяСобытия, ДобавитьМесяц(Напоминание.ВремяСобытия, 12) - 1); // @skip-check query-in-loop - нет обращения к данным ИБ в запросе. ПодошедшееВремяСобытия = ГрафикСобытия(Расписание, Напоминание.ВремяСобытия + 1, ТекущаяДатаСеанса()); ВремяСобытия = Напоминание.ВремяСобытия; ТребуетсяПереподключитьПоРасписанию = Ложь; НапоминаниеПросрочено = Ложь; // - подошло следующее время события по расписанию; Если ПодошедшееВремяСобытия.Количество() > 0 Тогда ВремяСобытия = ПодошедшееВремяСобытия[ПодошедшееВремяСобытия.ВГраница()]; ТребуетсяПереподключитьПоРасписанию = Истина; КонецЕсли; // - указано "Время завершения" в расписании регламентного задания и оно просрочено; Если ЗначениеЗаполнено(Расписание.ВремяЗавершения) И ТекущаяДатаСеанса() > (ВремяСобытия + (Расписание.ВремяЗавершения - Расписание.ВремяНачала)) // - напоминание ежегодное, но уже прошел месяц со времени события; Или ГрафикСобытияНаГод.Количество() = 1 И ТекущаяДатаСеанса() > ДобавитьМесяц(ВремяСобытия, 1) // - напоминание ежемесячное, но уже прошла неделя со времени события. Или ГрафикСобытияНаГод.Количество() = 12 И ТекущаяДатаСеанса() > ВремяСобытия + 60*60*24*7 Тогда НапоминаниеПросрочено = Истина; КонецЕсли; Если ТребуетсяПереподключитьПоРасписанию Тогда НачатьТранзакцию(); Попытка // @skip-check query-in-loop - запись данных набором с чтением в цикле. ОтключитьНапоминание(Напоминание, НапоминаниеПросрочено, ПриЗапуске); Если Не НапоминаниеПросрочено Тогда ПараметрыНапоминания = ОбщегоНазначения.СтрокаТаблицыЗначенийВСтруктуру(Напоминание); ПараметрыНапоминания.Расписание = Напоминание.Расписание.Получить(); // @skip-check query-in-loop - запись данных набором с чтением в цикле. Напоминание = СоздатьНапоминание(ПараметрыНапоминания); Напоминание.ВремяСобытия = ВремяСобытия; Напоминание.СрокНапоминания = Напоминание.ВремяСобытия - Напоминание.ИнтервалВремениНапоминания; ПодключитьНапоминание(Напоминание,, ПриЗапуске); КонецЕсли; ЗафиксироватьТранзакцию(); Исключение ОтменитьТранзакцию(); ЗаписьЖурналаРегистрации(НСтр("ru = 'Напоминания пользователя'", ОбщегоНазначения.КодОсновногоЯзыка()), УровеньЖурналаРегистрации.Ошибка, Метаданные.РегистрыСведений.НапоминанияПользователя, , ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())); КонецПопытки; КонецЕсли; КонецЦикла; КонецПроцедуры // Выполняет запрос по напоминаниям для текущего пользователя на 30 минут вперед от текущего времени. // Момент времени смещен от текущего для того, чтобы данные были актуальны в течение жизни кэша. // При обработке результата выполнения функции необходимо учитывать эту особенность. // // Возвращаемое значение: // Массив из Структура: // * Пользователь - СправочникСсылка.Пользователи // * ВремяСобытия - Дата // * Источник - ОпределяемыйТип.ПредметНапоминания // * СрокНапоминания - Дата // * Описание - Строка // * ИндексКартинки - Число // Функция СписокТекущихНапоминанийПользователя() Экспорт АктуализироватьСписокНапоминаний(Истина); Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ РАЗРЕШЕННЫЕ | Напоминания.Пользователь КАК Пользователь, | Напоминания.ВремяСобытия КАК ВремяСобытия, | Напоминания.Источник КАК Источник, | Напоминания.СрокНапоминания КАК СрокНапоминания, | Напоминания.Описание КАК Описание, | 2 КАК ИндексКартинки |ИЗ | РегистрСведений.НапоминанияПользователя КАК Напоминания |ГДЕ | Напоминания.СрокНапоминания <= &ГраницаСрокаНапоминания | И Напоминания.Пользователь = &Пользователь | |УПОРЯДОЧИТЬ ПО | ВремяСобытия"; Запрос.УстановитьПараметр("ГраницаСрокаНапоминания", ТекущаяДатаСеанса() + ЗапасВремениНапоминанийДляКэша()); Запрос.УстановитьПараметр("Пользователь", Пользователи.ТекущийПользователь()); УстановитьПривилегированныйРежим(Истина); Результат = ОбщегоНазначения.ТаблицаЗначенийВМассив(Запрос.Выполнить().Выгрузить()); Возврат Результат; КонецФункции Функция ЗапасВремениНапоминанийДляКэша() Экспорт Возврат 30*60; КонецФункции // См. НапоминанияПользователя.ПриЧтенииНаСервере Процедура ПриСозданииНаСервере(Форма, ПараметрыРазмещения) Экспорт Если Не ПолучитьФункциональнуюОпцию("ИспользоватьНапоминанияПользователя") Тогда Возврат; КонецЕсли; Если Не ПравоДоступа("Редактирование", Метаданные.РегистрыСведений.НапоминанияПользователя) Тогда Возврат; КонецЕсли; Если Не ЗначениеЗаполнено(ПараметрыРазмещения.ИмяРеквизитаСДатойСобытия) Тогда Возврат; КонецЕсли; Объект = Неопределено; Для Каждого Реквизит Из Форма.ПолучитьРеквизиты() Цикл Если ТипЗнч(Форма[Реквизит.Имя]) = Тип("ДанныеФормыСтруктура") Тогда Объект = Форма[Реквизит.Имя]; Прервать; КонецЕсли; КонецЦикла; Если Объект = Неопределено Тогда Возврат; КонецЕсли; ИмяРеквизитаСДатойСобытия = ПараметрыРазмещения.ИмяРеквизитаСДатойСобытия; Предмет = Объект.Ссылка; ОбъектМетаданных = Предмет.Метаданные(); РеквизитСДатой = ОбъектМетаданных.Реквизиты.Найти(ИмяРеквизитаСДатойСобытия); Если РеквизитСДатой = Неопределено Тогда ЗначенияСвойств = Новый Структура("ИмяРеквизитаСДатойСобытия"); ЗаполнитьЗначенияСвойств(ЗначенияСвойств, ОбъектМетаданных.СтандартныеРеквизиты); РеквизитСДатой = ЗначенияСвойств.ИмяРеквизитаСДатойСобытия; КонецЕсли; Если РеквизитСДатой = Неопределено Тогда Возврат; КонецЕсли; ВыводитьКороткиеИнтервалы = Истина; ОписаниеТипаДата = РеквизитСДатой.Тип; // ОписаниеТипов Если ОписаниеТипаДата.КвалификаторыДаты.ЧастиДаты = ЧастиДаты.Дата Тогда ВыводитьКороткиеИнтервалы = Ложь; КонецЕсли; ИмяПоляНастройкиНапоминания = НапоминанияПользователяКлиентСервер.ИмяПоляНастройкиНапоминания(); ИмяГруппыЭлементов = "НастройкаНапоминания"; ИмяПоляИнтервалВремениНапоминания = НапоминанияПользователяКлиентСервер.ИмяПоляИнтервалВремениНапоминания(); ИмяПоляНапоминатьОСобытии = ИмяПоляНапоминатьОСобытии(); НастройкиНапоминания = ПараметрыРазмещения(); НастройкиНапоминания.Удалить("Группа"); ЗаполнитьЗначенияСвойств(НастройкиНапоминания, ПараметрыРазмещения); НастройкиНапоминания.Вставить("Предмет", Предмет); Если Форма.Элементы.Найти(ИмяГруппыЭлементов) = Неопределено Тогда ДобавляемыеРеквизиты = Новый Массив; ДобавляемыеРеквизиты.Добавить(Новый РеквизитФормы(ИмяПоляНастройкиНапоминания, Новый ОписаниеТипов)); ДобавляемыеРеквизиты.Добавить(Новый РеквизитФормы(ИмяПоляНапоминатьОСобытии, Новый ОписаниеТипов("Булево"), , НСтр("ru = 'Напомнить'"), Истина)); ДобавляемыеРеквизиты.Добавить(Новый РеквизитФормы(ИмяПоляИнтервалВремениНапоминания, Новый ОписаниеТипов("Строка"), , НСтр("ru = 'Интервал времени напоминания'"), Истина)); Форма.ИзменитьРеквизиты(ДобавляемыеРеквизиты); Группа = Форма.Элементы.Добавить(ИмяГруппыЭлементов, Тип("ГруппаФормы"), ПараметрыРазмещения.Группа); Группа.Вид = ВидГруппыФормы.ОбычнаяГруппа; Группа.ОтображатьЗаголовок = Ложь; Группа.Заголовок = НСтр("ru = 'Настройка напоминания'"); Группа.Отображение = ОтображениеОбычнойГруппы.Нет; Если НастройкиНапоминания.ДобавлятьФлажок Тогда Флажок = Форма.Элементы.Добавить(ИмяПоляНапоминатьОСобытии, Тип("ПолеФормы"), Группа); Флажок.ПутьКДанным = ИмяПоляНапоминатьОСобытии; Флажок.Вид = ВидПоляФормы.ПолеФлажка; Флажок.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Право; Флажок.Заголовок = НСтр("ru = 'Напомнить:'"); КонецЕсли; ПолеВвода = Форма.Элементы.Добавить(ИмяПоляИнтервалВремениНапоминания, Тип("ПолеФормы"), Группа); ПолеВвода.ПутьКДанным = ИмяПоляИнтервалВремениНапоминания; ПолеВвода.Вид = ВидПоляФормы.ПолеВвода; ПолеВвода.Подсказка = НСтр("ru = 'Время, за которое необходимо напомнить о событии'"); Если НастройкиНапоминания.ДобавлятьФлажок Тогда ПолеВвода.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет; Иначе ПолеВвода.Заголовок = НСтр("ru = 'Напомнить'"); КонецЕсли; ПолеВвода.УстановитьДействие("ПриИзменении", "Подключаемый_ПриИзмененииНастройкиНапоминания"); ПолеВвода.ОбновлениеТекстаРедактирования = ОбновлениеТекстаРедактирования.ПриИзмененииЗначения; ПолеВвода.КнопкаВыпадающегоСписка = Истина; ПолеВвода.Ширина = 12; ПолеВвода.РастягиватьПоГоризонтали = Ложь; НастройкиПодсистемы = НастройкиПодсистемы(); ИнтервалыВремени = НастройкиПодсистемы.СтандартныеИнтервалы; ПолеВвода.СписокВыбора.Очистить(); Если Не НастройкиНапоминания.ДобавлятьФлажок Тогда ПолеВвода.СписокВыбора.Добавить(НапоминанияПользователяКлиентСервер.ПредставлениеПеречисленияНеНапоминать()); КонецЕсли; ПолеВвода.СписокВыбора.Добавить(НапоминанияПользователяКлиентСервер.ПредставлениеПеречисленияПриНаступлении()); Для Каждого Интервал Из ИнтервалыВремени Цикл Если Не ВыводитьКороткиеИнтервалы И ИнтервалВремениИзСтроки(Интервал) < 24*60*60 Тогда Продолжить; КонецЕсли; ПолеВвода.СписокВыбора.Добавить(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр("ru = 'за %1'"), Интервал)); КонецЦикла; Если НастройкиНапоминания.ИнтервалВремениНапоминания = Неопределено Тогда НастройкиНапоминания.ИнтервалВремениНапоминания = 0; КонецЕсли; Если НастройкиНапоминания.ДобавлятьФлажок Тогда Если НастройкиНапоминания.ИнтервалВремениНапоминания = 0 Тогда Форма[ИмяПоляИнтервалВремениНапоминания] = НапоминанияПользователяКлиентСервер.ПредставлениеПеречисленияПриНаступлении(); Иначе Форма[ИмяПоляИнтервалВремениНапоминания] = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр("ru = 'за %1'"), ПредставлениеВремени(НастройкиНапоминания.ИнтервалВремениНапоминания, , Ложь)); КонецЕсли; Иначе Форма[ИмяПоляИнтервалВремениНапоминания] = НапоминанияПользователяКлиентСервер.ПредставлениеПеречисленияНеНапоминать(); КонецЕсли; Форма[ИмяПоляНастройкиНапоминания] = НастройкиНапоминания; КонецЕсли; Если Не ЗначениеЗаполнено(Предмет) Тогда Возврат; КонецЕсли; ПрочитатьНастройкиНапоминанияПоПредмету(Форма, Предмет); КонецПроцедуры // См. НапоминанияПользователя.ПриЧтенииНаСервере Процедура ПриЧтенииНаСервере(Форма, ТекущийОбъект) Экспорт Если Не ПолучитьФункциональнуюОпцию("ИспользоватьНапоминанияПользователя") Тогда Возврат; КонецЕсли; Если Не ПравоДоступа("Редактирование", Метаданные.РегистрыСведений.НапоминанияПользователя) Тогда Возврат; КонецЕсли; НастройкиНапоминания = НапоминанияПользователяКлиентСервер.НастройкиНапоминанияВФорме(Форма); Если НастройкиНапоминания = Неопределено Тогда Возврат; КонецЕсли; Предмет = ТекущийОбъект.Ссылка; ПрочитатьНастройкиНапоминанияПоПредмету(Форма, Предмет); КонецПроцедуры Процедура ПриЗаписиНаСервере(Форма, Отказ, ТекущийОбъект, ПараметрыЗаписи, Знач ТекстНапоминания) Экспорт Если Не ПолучитьФункциональнуюОпцию("ИспользоватьНапоминанияПользователя") Тогда Возврат; КонецЕсли; Если Не ПравоДоступа("Редактирование", Метаданные.РегистрыСведений.НапоминанияПользователя) Тогда Возврат; КонецЕсли; НастройкиНапоминания = НапоминанияПользователяКлиентСервер.НастройкиНапоминанияВФорме(Форма); НапоминаниеВключено = Форма[ИмяПоляНапоминатьОСобытии()]; Предмет = ТекущийОбъект.Ссылка; НастройкиНапоминания.Вставить("Предмет", Предмет); ИмяРеквизитаСДатойСобытия = НастройкиНапоминания.ИмяРеквизитаСДатойСобытия; ИнтервалВремениНапоминания = НастройкиНапоминания.ИнтервалВремениНапоминания; Текст = ТекстНапоминания; Если Не ЗначениеЗаполнено(Текст) Тогда Текст = ОбщегоНазначения.ПредметСтрокой(Предмет); КонецЕсли; Если НапоминаниеВключено Тогда ПереустановитьНапоминаниеПоПредмету(Предмет, ИмяРеквизитаСДатойСобытия, ИнтервалВремениНапоминания, Текст); Иначе УдалитьНапоминанияПоПредмету(Предмет, ИмяРеквизитаСДатойСобытия) КонецЕсли; КонецПроцедуры // См. НапоминанияПользователя.ПараметрыРазмещения Функция ПараметрыРазмещения() Экспорт Результат = Новый Структура; Результат.Вставить("Группа"); Результат.Вставить("ИмяРеквизитаСДатойСобытия"); Результат.Вставить("ИнтервалВремениНапоминания"); Результат.Вставить("ДобавлятьФлажок", Ложь); Возврат Результат; КонецФункции // См. НапоминанияПользователяКлиентСервер.ПредставлениеВремени Функция ПредставлениеВремени(Знач Время, ПолноеПредставление = Истина, ВыводитьСекунды = Истина) Возврат НапоминанияПользователяКлиентСервер.ПредставлениеВремени(Время, ПолноеПредставление, ВыводитьСекунды); КонецФункции Процедура УдалитьНапоминанияПоПредмету(Предмет, ИмяРеквизита) НапоминанияПоПредмету = НапоминанияПользователя.НайтиНапоминания(Предмет); Для Каждого Напоминание Из НапоминанияПоПредмету Цикл Если НРег(Напоминание.ИмяРеквизитаИсточника) = НРег(ИмяРеквизита) Тогда // @skip-check query-in-loop - запись данных набором с чтением в цикле. ОтключитьНапоминание(Напоминание, Ложь); КонецЕсли; КонецЦикла; КонецПроцедуры Процедура ПереустановитьНапоминаниеПоПредмету(Предмет, ИмяРеквизита, ИнтервалВремениНапоминания, Текст) УдалитьНапоминанияПоПредмету(Предмет, ИмяРеквизита); ПодключитьПроизвольноеНапоминание(Текст, ИмяРеквизита, ИнтервалВремениНапоминания, Предмет); КонецПроцедуры // См. НапоминанияПользователяКлиентСервер.ИнтервалВремениИзСтроки Функция ИнтервалВремениИзСтроки(Знач СтрокаСоВременем) Экспорт Возврат НапоминанияПользователяКлиентСервер.ИнтервалВремениИзСтроки(СтрокаСоВременем); КонецФункции Функция ИмяПоляНапоминатьОСобытии() Экспорт Возврат НапоминанияПользователяКлиентСервер.ИмяПоляНапоминатьОСобытии(); КонецФункции Процедура ПрочитатьНастройкиНапоминанияПоПредмету(Форма, Предмет) НастройкиНапоминания = НапоминанияПользователяКлиентСервер.НастройкиНапоминанияВФорме(Форма); Если НастройкиНапоминания = Неопределено Тогда Возврат; КонецЕсли; НастройкиНапоминания.Вставить("Предмет", Предмет); НапоминанияПоПредмету = НапоминанияПользователя.НайтиНапоминания(Предмет); Для Каждого Напоминание Из НапоминанияПоПредмету Цикл Если НРег(Напоминание.ИмяРеквизитаИсточника) = НРег(НастройкиНапоминания.ИмяРеквизитаСДатойСобытия) Тогда ИмяПоляНапоминатьОСобытии = ИмяПоляНапоминатьОСобытии(); ИмяПоляИнтервалВремениНапоминания = НапоминанияПользователяКлиентСервер.ИмяПоляИнтервалВремениНапоминания(); Форма[ИмяПоляНапоминатьОСобытии] = Истина; Форма[ИмяПоляИнтервалВремениНапоминания] = НапоминанияПользователяКлиентСервер.ПредставлениеСрокаНапоминания(Напоминание); Прервать; КонецЕсли; КонецЦикла; КонецПроцедуры #КонецОбласти