Введение
Представленная статья посвящена некоторым особенностям и нюансам разработки доп. расширений для публикации в 1С:Фреш. Надеюсь, кому‑то из читателей информация в статье будет полезна и сэкономит время на прохождение аудита при публикации своего решения во Фреше.
Помимо разработки функционала для «коробочных» 1С бывает потребность разработки и для облачных сервисов. Есть несколько различных облачных сервисов для пользования 1С, в статье рассмотрена публикация в магазине расширений 1С:Фреш. 1С:Фреш — облачное решение для работы с 1С без использования своего «железа», покупки лицензий и т. д. Нужно просто оплатить, залить свою базу и можно пользоваться. Т.к. сервис облачный, то имеются некоторые ограничения и требования к публикуемым решениям. Естественно, во Фреше и на ИТС (информационно техническое сопровождение) есть ряд статей и рекомендаций для успешного прохождения аудита, но в некоторых особенностях сразу все равно не разобраться. В статье раскрыты нюансы (с которыми столкнулся автор) работы с регламентными заданиями, добавления новых объектов для хранения данных, запроса разрешений на выполнение небезопасных операций, повторной отправки расширения на аудит, удаления объектов, использования «попытка исключение».
Использование регламентных заданий расширением во Фреше
Перечислять весь список возникших вопросов и сложностей не имеет смысла, поэтому лучше начать с примера. В первую очередь, стоит рассмотреть один из вариантов работы с регламентным заданием, когда его использование не подразумевается во Фреше.
Создание и запуск регламентного задания
Если РегламентныеЗаданияСервер.Задание(Объект.ИдентификаторРегламентногоЗадания) = Неопределено Тогда
ИменаИспользуемыхРеглЗаданий = ОбменЗаявками_ОбщегоНазначения.ПолучитьИменаИспользуемыхРеглЗаданий();
СтруктураРеглЗаданий = ОбменЗаявками_ОбщегоНазначения.ПолучитьИспользуемыеРеглЗадания();
ПараметрыЗапуска = Новый Массив();
ПараметрыЗапуска.Добавить(СтруктураРеглЗаданий.ВыполнениеСинхронизацииСБитрикс24ПоРасписанию);
ПараметрыЗапуска.Добавить(Объект.Ссылка);
ПараметрыЗадания = Новый Структура();
ПараметрыЗадания.Вставить("Метаданные", Метаданные.РегламентныеЗадания.ЗапускДополнительныхОбработок);
ПараметрыЗадания.Вставить("Наименование", ИменаИспользуемыхРеглЗаданий.ВыполнениеСинхронизацииСБитрикс24ПоРасписанию + Наименование);
ПараметрыЗадания.Вставить("Ключ", ИменаИспользуемыхРеглЗаданий.ВыполнениеСинхронизацииСБитрикс24ПоРасписанию + Наименование);
ПараметрыЗадания.Вставить("Использование", Истина);
ПараметрыЗадания.Вставить("ЭксклюзивноеВыполнение", Ложь);
ПараметрыЗадания.Вставить("Параметры", ПараметрыЗапуска);
ПараметрыЗадания.Вставить("ИнтервалПовтораПриАварийномЗавершении", 0);
ПараметрыЗадания.Вставить("КоличествоПовторовПриАварийномЗавершении", 0);
ПараметрыЗадания.Вставить("Расписание", РасписаниеРегламентногоЗадания);
Объект.ИдентификаторРегламентногоЗадания = РегламентныеЗаданияСервер.ДобавитьЗадание(ПараметрыЗадания).УникальныйИдентификатор;
РегламентныеЗаданияСервер.УстановитьИспользованиеРегламентногоЗадания(Объект.ИдентификаторРегламентногоЗадания, Ложь);
РегламентныеЗаданияСервер.УстановитьИспользованиеРегламентногоЗадания(Объект.ИдентификаторРегламентногоЗадания, Истина);
Иначе
РегламентныеЗаданияСервер.УстановитьИспользованиеРегламентногоЗадания(Объект.ИдентификаторРегламентногоЗадания, Истина);
РегламентныеЗаданияСервер.УстановитьРасписаниеРегламентногоЗадания(Объект.ИдентификаторРегламентногоЗадания, РасписаниеРегламентногоЗадания);
КонецЕсли;
Выше представлен один из вариантов кода, который может создавать и/или запускать регламентные задания методами БСП. Если такой код отправить на аудит во Фреш, то он, скорее всего, пройден не будет, во всяком случае в таком исполнении регламентные задания работать не будут. Дело в том, что во Фреше регламентные задания добавляются с помощью Команды расширения [1]. А они в свою очередь запускаются механизмом очереди заданий в модели сервиса, у которого свои рег. задания. Т. е. прямо в коде не выйдет создавать и/или запускать регламентные задания. Сходу из статьи [1] можно не понять, как правильно нужно реализовывать работу регламентных заданий для Фреша, поэтому далее рассмотрим это более подробно.Упомянутый ранее код по созданию и запуску рег. заданий можно заменить на проверку заполненности расписания регламентного задания. Далее, как описано в статье, действительно, необходимо создать команду расширения, внутри которой и будет исполняемый код.
ПрефиксРасширения_КомандаРасширения
Процедура ВыполнитьКоманду() Экспорт
ВыборкаНастроек = Справочники.НастройкиСинхронизации.Выбрать();
Пока ВыборкаНастроек.Следующий() Цикл
Если ВыборкаНастроек.РежимСинхронизации = Перечисления.РежимыСинхронизации.ПоРасписанию
И ВыборкаНастроек.ОбменЗапущен И ВыборкаНастроек.Расписание.Получить() <> Неопределено Тогда
Выполнять = ВыборкаНастроек.Расписание.Получить().ТребуетсяВыполнение(, ВыборкаНастроек.ПоследняяДатаВыполнения);
Если Выполнять Тогда
ИнтеграцияСБ24_Синхронизация.ВыполнитьСинхронизациюПоРасписанию(ВыборкаНастроек.Ссылка, Ложь);
УстановитьПривилегированныйРежим(Истина);
ОбъектНастроек = ВыборкаНастроек.ПолучитьОбъект();
ОбъектНастроек.ПоследняяДатаВыполнения = ТекущаяДатаСеанса();
ОбъектНастроек.Записать();
УстановитьПривилегированныйРежим(Ложь);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
В общем модуле представлен код для выполнения команды расширения. Его можно так и назвать: «КомандаРасширения» (само собой добавится префикс расширения). В свойствах данного модуля проставлена галка «Сервер». В статье [1] сказано, что при добавлении расширения в свою базу будет доступна настройка расписания для каждой команды расширения, т.е. пользователь при пользовании расширением не сможет легко и просто управлять расписанием регламентного задания. Также важно, что минимальный период выполнения, который можно выставить, равен 300 секундам. Вариант решения первой проблемы есть.
Была оставлена возможность в расширении задать (не при добавлении расширения в базу, а непосредственно при его использовании) расписание регламентного задания. Для команды расширения при его добавлении в базу была выставлена минимальная периодичность (300 секунд) и признак активности. Из кода выше видно, что регламентное задание (на самом деле это фоновое, порожденное регламентным) команды расширения получает то расписание, которое установил пользователь при пользовании расширением и определяет, нужно ли его выполнять или время еще не настало. Стоит обратить внимание на то, что приходится хранить последнюю дату выполнения регламентного задания.
Таким образом получилось не просто адаптировать работу кода по регламентному заданию во Фреше, но и оставить возможность пользователю управлять расписанием внутри расширения (а не в его настройках). Единственное, что отличается от кода для коробочных решений: минимальный период исполнения регламентного задания - 300 секунд.
Добавление новых объектов для хранения данных
Если в расширении используются свои объекты для хранения данных (обычно, это касается справочников и регистров, а также документов), то без определенных манипуляций аудит пройден не будет и расширение вернут на доработку примерно со следующим замечанием:

Рекомендация из рисунка выше полностью рабочая. На рисунке ниже продемонстрировано выполнение указанных рекомендаций.
Запрос разрешений на выполнение небезопасных операций
Все расширения, отчеты и обработки добавляемые во Фреш должны быть полностью работоспособными в безопасном режиме [2]. Один из важных вопросов касается того, как будет реализован обмен данными с внешним сервисом. В нашем случае были использованы http запросы. При добавлении расширения для прохождения аудита указываются адреса ресурсов, с которыми планируется соединение, порты и протоколы. А что делать в случае, когда неизвестно заранее, с каким ресурсом будет обмениваться данными пользователь? Да, кейсы бывают разными и в этом случае пользователь сам указывает адрес ресурса для обмена данными. Если верить статье [3] на ИТС, то есть возможность указывать, что необходим доступ сразу ко всем интернет ресурсам, что решает упомянутую проблему. К сожалению, этот вопрос при общении со специалистами Фреша довести до конца не удалось. Было предложено 2 варианта: отправлять запрос с клиента (там ограничений нет) или использовать прокси. Первый вариант был отвергнут, потому что большинство кода исполняется на сервере, а клиент с сервера нельзя вызвать, поэтому был реализован второй вариант.
Для тех, кто не понял, стоит более подробно пояснить. В 1С указывается подключение только к одному ресурсу, т.е. к прокси, а он в свою очередь делает запрос на нужный ресурс уже без участия Фреша, что полностью закрывает текущую задачу. Таким образом пользователь может указывать любой ресурс для соединения и обмениваться с ним данными без указания этого ресурса в профилях безопасности, но прокси указать придется.
Повторная отправка расширения на аудит
Вполне вероятно, что может потребоваться дополнительная отправка расширения на аудит. Например, из за внесения правок по итогам предыдущего аудита. При повторной отправке на аудит необходимо указать новую версию расширения конфигурации (указывается в свойствах расширения конфигурации), иначе его не получится загрузить для прохождения аудита.
Удаление объектов
Отдельное внимание стоит уделить удалению объектов с помощью расширения, например, элементов справочников. Даже если Вы сильно уверены в том, что при удалении объекта не будет нарушена ссылочная целостность, такие манипуляции без контроля ссылочной целостности не пройдут аудит, т. е. контроль ссылочной целостности при удалении объектов во Фреше обязателен. Ниже представлен пример кода, который удаляет нужные объекты с контролем ссылочной целостности.
Удаление объектов с контролем ссылочной целостности
// Удаляет логи, которые хранятся больше заданного времени, в справочнике ЖурналЛогов.
// Если количество дней не задано, то удаляет все логи по указанной настройке синхронизации.
//
// Параметры:
// Дни - Число - количество дней хранения логов, значение по умолчанию 0.
// НастройкаСинхронизации - СправочникСсылка.НастройкиСинхронизации - ссылка на настройку синхронизации.
//
Процедура УдалитьЛоги(Дни=0, НастройкаСинхронизации) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЖурналЛогов.Ссылка КАК Ссылка
|ИЗ
| Справочник.ЖурналЛогов КАК ЖурналЛогов
|ГДЕ
| ЖурналЛогов.НастройкаСинхронизации = &НастройкаСинхронизации
| И РАЗНОСТЬДАТ(ЖурналЛогов.Время, &ТекущаяДата, ДЕНЬ) > &КоличествоДней";
Если Дни=0 Тогда
Запрос.Текст = СтрЗаменить(Запрос.Текст, "И РАЗНОСТЬДАТ(ЖурналЛогов.Время, &ТекущаяДата, ДЕНЬ) > &КоличествоДней", "");
Иначе
Запрос.УстановитьПараметр("КоличествоДней", Дни);
КонецЕсли;
Запрос.УстановитьПараметр("НастройкаСинхронизации", НастройкаСинхронизации);
Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДатаСеанса());
УстановитьПривилегированныйРежим(Истина);
РезультатЗапроса = Запрос.Выполнить();
УстановитьПривилегированныйРежим(Ложь);
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
УстановитьПривилегированныйРежим(Истина);
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Объект = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
Объект.ПометкаУдаления = Истина;
Объект.Записать();
КонецЦикла;
ВключенныеОбъекты = Новый Массив;
ВключенныеОбъекты.Добавить("Справочник.ЖурналЛогов");
Помеченные = НайтиПомеченныеНаУдаление(, ВключенныеОбъекты);
УдалитьПомеченные(Помеченные);
УстановитьПривилегированныйРежим(Ложь);
КонецПроцедуры
// Удаляет помеченные объекты с контролем ссылочной целостности без монопольного режима.
// Использует штатную обработку УдалениеПомеченныхОбъектов.
//
// Параметры:
// Помеченные - Массив - Массив со списком ссылок помеченных на удаление объектов.
//
Процедура УдалитьПомеченные(Помеченные) Экспорт
ПараметрыУдаления = Обработки.УдалениеПомеченныхОбъектов.ПараметрыУдаления();
ПараметрыУдаления.ПользовательскиеОбъекты = Помеченные;
Обработки.УдалениеПомеченныхОбъектов.УдалитьПомеченныеОбъекты(ПараметрыУдаления);
КонецПроцедуры
Из кода видно, что сначала удаляемые объекты необходимо пометить на удаление, а потом получить список помеченных объектов с помощью функции НайтиПомеченныеНаУдаление с указанием нужных объектов метаданных. Просто так удалить помеченные объекты с контролем ссылочной целостности не выйдет, т. к. для этого необходим монопольный режим. Вероятно, при каждом таком процессе пользователи будут недовольны невозможности работы с базой. По этим причинам в представленном примере используется специальная штатная обработка для удаления помеченных объектов без использования монопольного режима.
Привилегированный режим и использование «попытка исключение»
Осталось рассмотреть пару небольших и тоже важных моментов. При операциях, связанных с получением доступа к данным, например, выполнение запроса или получение объекта по ссылке, рекомендуется использование привилегированногорежима. Это связано с тем, что у пользователя, от имени которого запущен код, может не быть прав на получение данных, используемых в коде. Чтобы потом не разбираться с правами каждого такого пользователя, стоит использовать этот режим, также важно не забывать его отключать.
Если при разработке расширения есть код, который обернут в «попытку исключение» для того, чтобы код не упал по ошибке, то такое расширение тоже не пройдет аудит. Будет получена формулировка о том, что недопустимо использование «попытки исключения» без информирования пользователя о произошедшей ошибке. Поэтому при использовании данной конструкции всегда нужно делать обработку ошибок.
Заключение
В статье были описаны ключевые сложности, которые могут возникнуть при разработке расширения для облачного сервиса 1С:Фреш. Важно, что часть рассмотренных рекомендаций вы можете не найти в статьях на просторах интернета — они основаны на обратной связи после неудачных аудитов. Надеюсь, данный опыт Вам поможет сэкономить время на прохождение аудита во Фреше (и не только, есть и другие подобные облачные сервисы, но у них могут отличаться требования). Если в будущем мы соберем достаточно новых кейсов по теме, то обязательно выпустим новую статью.
Список источников
ООО «1С‑Софт». Расширения конфигурации, запускающие регламентные задания: [Электронный ресурс]., 2020 // URL: https://1cfresh.com/articles/so_confext_job. (Дата обращения: 30.05.2025).
ООО «1С‑Софт». Рекомендации по подготовке расширений конфигурации, дополнительных отчетов и обработок: [Электронный ресурс]., 2017 // URL: https://1cfresh.com/articles/so_addprocess_fastaudit. (Дата обращения: 30.05.2025).
ООО «1С‑Софт». Облачная подсистема Фреш: [Электронный ресурс]., 2020 // URL: https://its.1c.ru/db/freshpub#content:3599:hdoc:issogl2_42.4.3.3_%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D0%B3%D0%BE_%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0_%D0%B8_%D0%BF%D1%80%D0%BE%D1%84%D0%B8%D0%BB%D0%B5%D0%B9_%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D1%81%D1%82%D0%B8. (Дата обращения: 30.05.2025).
Из кода видно, что сначала удаляемые объекты необходимо пометить на удаление, а потом получить список помеченных объектов с помощью функции НайтиПомеченныеНаУдаление с указанием нужных объектов метаданных. Просто так удалить помеченные объекты с контролем ссылочной целостности не выйдет, т. к. для этого необходим монопольный режим. Вероятно, при каждом таком процессе пользователи будут недовольны невозможности работы с базой. По этим причинам в представленном примере используется специальная штатная обработка для удаления помеченных объектов без использования монопольного режима.
Привилегированный режим и использование «попытка исключение»
Осталось рассмотреть пару небольших и тоже важных моментов. При операциях, связанных с получением доступа к данным, например, выполнение запроса или получение объекта по ссылке, рекомендуется использование привилегированного режима. Это связано с тем, что у пользователя, от имени которого запущен код, может не быть прав на получение данных, используемых в коде. Чтобы потом не разбираться с правами каждого такого пользователя, стоит использовать этот режим, также важно не забывать его отключать.
Если при разработке расширения есть код, который обернут в «попытку исключение» для того, чтобы код не упал по ошибке, то такое расширение тоже не пройдет аудит. Будет получена формулировка о том, что недопустимо использование «попытки исключения» без информирования пользователя о произошедшей ошибке. Поэтому при использовании данной конструкции всегда нужно делать обработку ошибок.
Заключение
В статье были описаны ключевые сложности, которые могут возникнуть при разработке расширения для облачного сервиса 1С:Фреш. Важно, что часть рассмотренных рекомендаций вы можете не найти в статьях на просторах интернета - они основаны на обратной связи после неудачных аудитов. Надеюсь, данный опыт Вам поможет сэкономить время на прохождение аудита во Фреше (и не только, есть и другие подобные облачные сервисы, но у них могут отличаться требования). Если в будущем мы соберем достаточно новых кейсов по теме, то обязательно выпустим новую статью.

Скакунов Игорь
1С разработчик ООО «Эм Си Арт РУС»