Маркетинговые кампании

Сложный

Маркетинговая кампания (кампания) — комплекс маркетинговых мероприятий, которые объединены одной концепцией и направлены на достижение маркетинговой цели. Кампания проводится в определенный период времени для конкретной целевой аудитории. Кампании доступны в продуктах линейки Marketing Creatio.

Действия, которые позволяет выполнять Creatio в рамках кампании с помощью цепочек коммуникаций через email:

  • Взращивать потребности клиентов.
  • Информировать аудиторию (участников кампании) о мероприятиях в рамках кампаний.
  • Привлекать участников.
  • Взаимодействовать с заинтересованными контактами.

Работа с кампаниями в Creatio описана в блоке статей Маркетинговые кампании.

В процессе создания кампании настраивается ее схема. Для этого используется дизайнер кампаний. Инструкция по созданию кампании приведена в статье Создать кампанию.

Составляющие схемы кампании:

  • Элементы.
  • Переходы между элементами.
  • Общие настройки.

Действия, которые выполняются при запуске кампании:

  • Cоздается так называемая flow-схема выполнения кампании.
  • Элементы преобразуются в цепочку выполнения кампании.
  • Для каждого элемента рассчитывается время запуска. Подробнее читайте в пункте Запланировать следующий запуск кампании.

Обратите внимание, что flow-схема может значительно отличаться от схемы кампании в дизайнере.

Элементы кампании 

При создании кампании ее схема содержит перечень предустановленных элементов. Также Creatio позволяет реализовать пользовательские элементы.

Типы элементов кампании:

  • Синхронные — элементы, которые выполняются друг за другом в порядке, который установлен flow-схемой. Переход к следующим элементам выполняется после отработки элемента. При этом переход между элементами блокируется и ожидает завершения операции.
  • Асинхронные — элементы, выполнение которых требует ожидания завершения работы некоторых внешних систем, ресурсов, асинхронных сервисов, реакции пользователей или внешних систем (например, переход по ссылке из элемента Email-рассылка (Marketing email) кампании).

Тип элементов определяет их положение во flow-схеме выполнения кампании. Первыми выполняются элементы Добавление аудитории (Adding event audience) и Выход из кампании (Exit from campaign). Они определяют наполнение аудитории на текущем шаге. По стрелкам аудитория кампании переходит от выполненного элемента к следующему за ним. Если для перехода заданы условия, то фильтрация аудитории выполняется с учетом этих условий и определяется время выполнения следующего элемента.

Классы элементов кампании 

Для реализации элементов кампании используются JavaScript-классы и C#-классы.

JavaScript-классы элементов кампании 

JavaScript-классы, которые реализуют элементы кампании:

  • Terrasoft.manager.ProcessFlowElementSchema — базовый класс схемы элемента.
  • Terrasoft.manager.CampaignBaseCommunicationSchema — базовый класс схемы элемента коммуникаций.
  • Terrasoft.manager.CampaignBaseAudienceSchema — базовый класс схемы элемента аудитории.
  • Terrasoft.Configuration.BaseCampaignSchemaElementPage — базовая схема панели свойств элемента. Схеме элемента соответствует схема панели свойств. Каждая новая панель свойств элемента расширяет базовую схему.
  • Terrasoft.manager.CampaignSchemaManager — базовый класс, который позволяет управлять схемами доступных в приложении элементов. Наследует функциональность класса Terrasoft.manager.BaseSchemaManager.

С#-классы элементов кампании 

Виды С#-классов элементов кампании:

  • С#-классы простых элементов кампании.
  • С#-классы исполняемых элементов кампании.

С#-классы, которые реализуют простые элементы кампании:

  • Terrasoft.Core.Campaign.CampaignSchemaElement — базовый класс элемента схемы кампании. Родительский класс для элементов схемы кампании.
  • Terrasoft.Configuration.AddCampaignParticipantElement — класс элемента Добавление аудитории (Adding event audience).
  • Terrasoft.Configuration.ExitFromCampaignElement — класс элемента Выход из кампании (Exit from campaign).
  • Terrasoft.Configuration.MarketingEmailElement — класс элемента Email-рассылка (Marketing email).
  • Terrasoft.Configuration.EventConditionalTransitionElement — класс элемента Добавить из мероприятия (Add from event).
  • Terrasoft.Configuration.LandingConditionalTransitionElement — класс элемента Добавить с посадочной страницы (Add from landing).

С#-классы, которые реализуют исполняемые элементы кампании:

  • Terrasoft.Core.Campaign.CampaignProcessFlowElement — базовый класс исполняемого элемента кампании.
  • Terrasoft.Configuration.AddCampaignAudienceElement — класс элемента аудитории.
  • Terrasoft.Configuration.ExcludeCampaignAudienceElement — класс элемента выхода из аудитории.
  • Terrasoft.Configuration.BulkEmailCampaignElement — класс элемента Email-рассылка (Marketing email).

Реализовать пользовательский элемент кампании 

  1. Создать элемент маркетинговой кампании.
  2. Создать панель свойств элемента кампании.
  3. Добавить элемент в область элементов дизайнера кампании.
  4. Создать исполняемый элемент для элемента кампании.
  5. Реализовать back-end часть элемента кампании.
  6. Добавить пользовательскую логику для обработки событий кампании.

Для реализации пользовательской логики при обработке (сохранение, копирование, удаление, запуск и остановка) событий кампании Creatio предоставляет механизм событийных обработчиков.

Чтобы использовать механизм событийных обработчиков:

  1. Создайте публичный запечатанный (sealed) класс-обработчик.
  2. В качестве родительского укажите класс CampaignEventHandlerBase.
  3. В классе реализуйте один или несколько интерфейсов, которые описывают сигнатуры обработчиков событий.
  4. В классе реализуйте доступный по умолчанию конструктор. Класс не должен быть обобщенным.

Интерфейсы, которые позволяют описать сигнатуры обработчиков событий:

  • IOnCampaignBeforeSave — содержит метод, который вызывается перед сохранением кампании.
  • IOnCampaignAfterSave — содержит метод, который вызывается после сохранения кампании.
  • IOnCampaignDelete — содержит метод, который вызывается перед удалением кампании.
  • IOnCampaignStart — содержит метод, который вызывается перед стартом кампании.
  • IOnCampaignStop — содержит метод, который вызывается перед остановкой кампании.
  • IOnCampaignValidate — содержит метод, который вызывается при валидации кампании. При реализации интерфейса рекомендуется сохранять ошибки в схему кампании с помощью метода AddValidationInfo(string).
  • IOnCampaignCopy — содержит метод, который вызывается после копирования кампании.

Если после компиляции не обновилась библиотека конфигурации и созданные типы не попали в эту библиотеку, то при сохранении кампании возможно возникновение ошибки "Parameter 'type' cannot be null".

Чтобы исправить ошибку "Parameter 'type' cannot be null":

  1. Перекомпилируйте проект.
  2. Очистите хранилища с закэшированными данными.
  3. Очистите пул приложения.
  4. Перезапустите сайт в IIS.

Пример реализации пользовательского элемента кампании приведен в статье Реализовать пользовательский элемент кампании.

Переходы между элементами кампании 

Классы переходов между элементами кампании 

С#-классы, которые реализуют переходы между элементами кампании:

  • Terrasoft.Configuration.SequenceFlowElement — класс, который реализует безусловный переход.
  • Terrasoft.Configuration.ConditionalSequenceFlowElement — класс, который реализует условный переход.
  • Terrasoft.Configuration.EmailConditionalTransitionElement — класс, который реализует переход по откликам.

Реализовать пользовательский переход для элемента кампании 

  1. Создать схему перехода для элемента кампании.
  2. Создать панель свойств перехода для элемента кампании.
  3. Создать исполняемый элемент для перехода элемента кампании.
  4. Реализовать back-end часть перехода для элемента кампании.
  5. Реализовать логику работы перехода при изменении источника.
  6. Подключить логику работы перехода.

Пример реализации пользовательского перехода приведен в статье Реализовать пользовательский переход для элемента кампании.

Запланировать следующий запуск кампании 

  1. Создайте новую кампанию или откройте существующую. Чтобы создать кампанию, воспользуйтесь инструкцией, которая приведена в статье Создать кампанию.
  2. В поле Режим запуска (Start mode) выберите "в указанное время" ("at the specified time").
  3. В поле Дата запланированного запуска (Scheduled start date) выберите дату и, при необходимости, время следующего запуска кампании.

Действия, которые выполняются во время планирования следующего запуска кампании:

  1. Расчет времени следующего запуска элемента. Выполняется в зависимости от настроек задержки по времени перед выполнением следующего элемента. Для расчета используются формулы.
  2. Выбор времени следующего запуска кампании.

    • Сравнение значений времени запуска элементов.
    • Выбор ближайшего времени запуска кампании на основании сравнения.
    • Установка выбранного значения в качестве значения времени следующего запуска кампании.
  3. Формирование перечня элементов, которые необходимо выполнить при следующем запуске кампании. В перечень попадают все элементы, время запуска которых равно времени следующего запуска кампании.

Чтобы настроить задержку по времени перед выполнением следующего элемента:

  1. В поле Нужна ли задержка перед выполнением элемента? (Enable delay before executing an element?) выберите значение "Да, на указанный промежуток времени" ("Yes, for specified time period").
  2. В зависимости от необходимой для пользователя задержки (дни или часы), в поле Единицы задержки (Delay unit) выберите одно из значений "Дни" ("Days") или "Часы" ("Hours").
  3. В поле Количество (Quantity) укажите необходимое количество дней (часов) задержки.
  4. При необходимости укажите время запуска элемента. Для этого в поле Время запуска (Timer validity) установите признак В точное время (Exact time) и укажите необходимое время запуска.

Варианты запуска элемента приведены в таблице ниже.

Варианты запуска элемента
Вариант запуска
Поля настройки
Нужна ли задержка перед выполнением элемента?
(Enable delay before executing an element?)
Единицы задержки
(Delay unit)
Количество
(Quantity)
Без задержки
"Нет, выполнить сразу после предыдущего" ("No, execute after the previous one")
Поле недоступно
Поле недоступно
В течение дня
"Да, на указанный промежуток времени" ("Yes, for specified time period")
"Часы" ("Hours")
Указано количество часов задержки
Через несколько дней
"Да, на указанный промежуток времени" ("Yes, for specified time period")
"Дни" ("Days")
Указано количество дней задержки

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

Формулы расчета времени запуска элемента
Вариант запуска
Формулы расчета
Дата
Время
Без задержки
Ближайшая дата запуска кампании
Ближайшее время запуска кампании
В течение дня
Текущая дата
Текущее время + N минут/часов
Через несколько дней
Текущая дата + N дней
Указанное пользователем время

N — значение поля Количество (Quantity) для перехода от одного элемента кампании к другому, которое указано пользователем.

Реализовать пользовательский элемент кампании
Сложный

Пример реализован для продуктов линейки Marketing Creatio.

Пример. Создать пользовательский элемент Тестовое СМС (Test SMS) маркетинговой кампании. Элемент используется для отправки пользователем СМС-сообщений. Для отображения элемента в дизайнере кампаний используйте изображение, которое доступно по ссылке.

1. Создать элемент кампании 

  1. Перейдите в раздел Конфигурация (Configuration) и выберите пользовательский пакет, в который будет добавлена схема.
  2. На панели инструментов реестра раздела нажмите Добавить —> Модуль (Add —> Module).

  3. В дизайнере модуля заполните свойства схемы:

    • Код (Code) — "UsrTestSmsElementSchema".
    • Заголовок (Title) — "Схема элемента CMC" ("SMS element schema").

    Для применения изменений свойств нажмите Применить (Apply).

  4. Добавьте локализуемую строку с названием элемента кампании, который планируется добавить.

    1. В контекстном меню узла Локализуемые строки (Localizable strings) нажмите кнопку scr_add_button.png.
    2. Заполните свойства локализуемой строки:

      • Код (Code) — "SmsElementCaption".
      • Значение (Value) — "Тестовое CMC" ("Test SMS").
    3. Для добавления локализуемой строки нажмите Добавить (Add).
  5. Добавьте изображения элемента кампании, которые должны использоваться для отображения элемента в разных режимах дизайнера кампаний.

    1. В контекстном меню узла Изображения (Images) нажмите кнопку scr_add_button.png.
    2. Заполните свойства изображения:

      • Код (Code) — "SmallImage".
      • Описание (Caption) — "Тестовое СМС (маленькое изображение)" ("Test SMS (small image)").
      • Изображение (Image) — выберите файл, который указан в условиях примера.
    3. Для добавления изображения нажмите Добавить (Add).
    4. Аналогично добавьте изображения элемента кампании, которые должны использоваться для отображения элемента в других режимах дизайнера кампаний.

      Свойства изображений, которые необходимо добавить, приведены в таблице ниже.

      Значения свойств изображений
      Режим
      Свойство
      Значение свойства
      Изображение для отображения элемента в рабочей области дизайнера кампаний
      Код (Code)
      "LargeImage"
      Описание (Caption)
      "Тестовое СМС (большое изображение)" ("Test SMS (large image)")
      Изображение (Image)
      Выберите файл, который указан в условиях примера
      Изображение для отображения элемента на панели свойств дизайнера кампаний
      Код (Code)
      "TitleImage"
      Описание (Caption)
      "Тестовое СМС (изображение для заголовка)" ("Test SMS (title image)")
      Изображение (Image)
      Выберите файл, который указан в условиях примера
  6. В дизайнере модуля добавьте исходный код, который реализует внешний вид элемента кампании.

    Исходный код схемы модуля представлен ниже.

    UsrTestSmsElementSchema
    define("UsrTestSmsElementSchema", ["UsrTestSmsElementSchemaResources", "CampaignBaseCommunicationSchema"], function(resources) {
        Ext.define("Terrasoft.manager.UsrTestSmsElementSchema", {
            /* Родительская схема. */
            extend: "Terrasoft.CampaignBaseCommunicationSchema",
            alternateClassName: "Terrasoft.UsrTestSmsElementSchema",
            /* Уникальный идентификатор менеджера. */
            managerItemUId: "a1226f93-f3e3-4baa-89a6-11f2a9ab2d71",
            /* Подключаемые миксины. */
            mixins: {
                campaignElementMixin: "Terrasoft.CampaignElementMixin"
            },
            /* Название элемента. */
            name: "TestSms",
            /* Привязка ресурсов. */
            caption: resources.localizableStrings.SmsElementCaption,
            titleImage: resources.localizableImages.TitleImage,
            largeImage: resources.localizableImages.LargeImage,
            smallImage: resources.localizableImages.SmallImage,
            /* Имя схемы страницы элемента. */
            editPageSchemaName: "UsrTestSmsElementPropertiesPage",
            /* Тип элемента. */
            elementType: "TestSms",
            /* Полное имя класса, который соответствует текущей схеме. */
            typeName: "Terrasoft.Configuration.UsrTestSmsElement, Terrasoft.Configuration",
            /* Переопределение свойств стилей для отображения. */
            color: "rgba(249, 160, 27, 1)",
            width: 69,
            height: 55,
            /* Настройка специфических свойств элемента. */
            smsText: null,
            phoneNumber: null,
            /* Определение типов связей, которые исходят из элемента. */
            getConnectionUserHandles: function() {
                return ["CampaignSequenceFlow", "CampaignConditionalSequenceFlow"];
            },
            /* Расширение свойств для сериализации. */
            getSerializableProperties: function() {
                var baseSerializableProperties = this.callParent(arguments);
                return Ext.Array.push(baseSerializableProperties, ["smsText", "phoneNumber"]);
            },
            /* Настройка отображения иконок на диаграмме кампании. */
            getSmallImage: function() {
                return this.mixins.campaignElementMixin.getImage(this.smallImage);
            },
            getLargeImage: function() {
                return this.mixins.campaignElementMixin.getImage(this.largeImage);
            },
            getTitleImage: function() {
                return this.mixins.campaignElementMixin.getImage(this.titleImage);
            }
        });
        return Terrasoft.UsrTestSmsElementSchema;
    });
    

    managerItemUId — уникальное значение, которое не должно повторять значение этого свойства у существующих элементов.

    typeName — имя C#-класса, который соответствует элементу кампании. Этот класс выполняет сохранение и чтение свойств элемента из метаданных схемы.

  7. На панели инструментов дизайнера модуля нажмите Сохранить (Save).

2. Создать панель свойств элемента кампании 

  1. Перейдите в раздел Конфигурация (Configuration) и выберите пользовательский пакет, в который будет добавлена схема.
  2. На панели инструментов реестра раздела нажмите Добавить —> Модель представления страницы (Add —> Page view model).

  3. Заполните свойства схемы:

    • Код (Code) — "UsrTestSmsElementPropertiesPage" (название совпадает со значением свойства editPageSchemaName схемы клиентского модуля UsrSmsElementSchema).
    • Заголовок (Title) — "Панель свойств элемента Тестовое СМС" ("Properties panel of the Test SMS element").
    • Родительский объект (Parent object) — выберите "BaseCampaignSchemaElementPage".
  4. Добавьте локализуемую строку с телефонным номером отправителя СМС-сообщения.

    1. В контекстном меню узла Локализуемые строки (Localizable strings) нажмите кнопку scr_add_button.png.
    2. Заполните свойства локализуемой строки:

      • Код (Code) — "PhoneNumberCaption".
      • Значение (Value) — "Номер телефона отправителя" ("Sender phone number").
    3. Для добавления локализуемой строки нажмите Добавить (Add).
  5. Аналогично добавьте локализуемые строки:

    • С текстом СМС-сообщения.
    • С названием блока свойств СМС-сообщения.

    Свойства локализуемых строк, которые необходимо добавить, приведены в таблице ниже.

    Значения свойств локализуемых строк
    Код
    (Code)
    Значение
    (Value)
    "SmsTextCaption"
    "Текст сообщения" ("Message")
    "TestSmsText"
    "Какое СМС-сообщение отправить?" ("Which SMS text to send?")
  6. Настройте панель свойств элемента кампании.

    1. В свойство attributes добавьте атрибуты:

      • PhoneNumber — хранит информацию о номере телефона.
      • SmsText — хранит информацию о тексте сообщения.
    2. В свойстве methods реализуйте методы:

      • init() — инициализирует модуль.
      • getContextHelpCode() — возвращает код элемента для генерации ссылки на контекстную справку.
      • initParameters() — инициализирует атрибуты текущими значениями свойств схемы.
      • saveValues() — сохраняет свойства схемы.
      • getPhoneNumber() — вычитывает текущее значение из атрибута PhoneNumber.
      • getSmsText() — вычитывает текущее значение из атрибута SmsText.
    3. В массив модификаций diff добавьте конфигурационные объекты с настройками расположения:

      • Контейнера на странице.
      • Основной подписи элемента.
      • Подписи для текстового поля ввода номера отправителя.
      • Текстового поля для ввода телефонного номера.
      • Подписи для текстового поля ввода текста сообщения.
      • Текстового поля для ввода текста сообщения.

    Исходный код схемы модели представления панели свойств представлен ниже.

    UsrTestSmsElementPropertiesPage
    define("UsrTestSmsElementPropertiesPage", [], function() {
        return {
            /* Атрибуты, которые соответствуют специфическим свойствам схемы элемента. */
            attributes: {
                /* Название атрибута модели представления. */
                "PhoneNumber": {
                    /* Тип данных колонки модели представления. */
                    "dataValueType": this.Terrasoft.DataValueType.TEXT,
                    "type": this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN
                },
                "SmsText": {
                    "dataValueType": this.Terrasoft.DataValueType.TEXT,
                    "type": this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN
                }
            },
            /* Методы модели представления страницы. */
            methods: {
                /* Инициализирует модуль. */
                init: function() {
                    this.callParent(arguments);
                    this.initAcademyUrl(this.onAcademyUrlInitialized, this);
                },
                /* Возвращает код элемента для генерации ссылки на контекстную справку. */
                getContextHelpCode: function() {
                    return "CampaignTestSmsElement";
                },
                /* Инициализирует атрибуты текущими значениями свойств схемы. */
                initParameters: function(element) {
                    this.callParent(arguments);
                    this.set("SmsText", element.smsText);
                    this.set("PhoneNumber", element.phoneNumber);
                },
                /* Сохраняет свойства схемы. */
                saveValues: function() {
                    this.callParent(arguments);
                    var element = this.get("ProcessElement");
                    element.smsText = this.getSmsText();
                    element.phoneNumber = this.getPhoneNumber();
    
                },
                /* Вычитывает текущее значение из атрибута PhoneNumber. */
                getPhoneNumber: function() {
                    var number = this.get("PhoneNumber");
                    return number ? number : "";
                },
                /* Вычитывает текущее значение из атрибута SmsText. */
                getSmsText: function() {
                    var smsText = this.get("SmsText");
                    return smsText ? smsText : "";
                }
            },
            /* Отображение свойств. */
            diff: [
                /* Метаданные для добавления на страницу контейнера. */
                {
                    /* Выполняется операция добавления элемента на страницу. */
                    "operation": "insert",
                    /* Мета-имя добавляемого контейнера. */
                    "name": "ContentContainer",
                    /* Контейнер добавляется в коллекцию элементов родительского элемента. */
                    "propertyName": "items",
                    /* Мета-имя родительского контейнера, в который добавляется текущий контейнер. */
                    "parentName": "EditorsContainer",
                    "className": "Terrasoft.GridLayoutEdit",
                    /* Свойства, передаваемые в конструктор элемента. */
                    "values": {
                        "itemType": Terrasoft.ViewItemType.GRID_LAYOUT,
                        "items": []
                    }
                },
                /* Основная подпись элемента. */
                {
                    "operation": "insert",
                    "name": "TestSmsLabel",
                    "parentName": "ContentContainer",
                    "propertyName": "items",
                    "values": {
                        "layout": {
                            "column": 0,
                            "row": 0,
                            "colSpan": 24
                        },
                        "itemType": this.Terrasoft.ViewItemType.LABEL,
                        "caption": {
                            "bindTo": "Resources.Strings.TestSmsText"
                        },
                        "classes": {
                            "labelClass": ["t-title-label-proc"]
                        }
                    }
                },
                /* Подпись для текстового поля ввода номера отправителя. */
                {
                    "operation": "insert",
                    "name": "PhoneNumberLabel",
                    "parentName": "ContentContainer",
                    "propertyName": "items",
                    "values": {
                        "layout": {
                            "column": 0,
                            "row": 1,
                            "colSpan": 24
                        },
                        "itemType": this.Terrasoft.ViewItemType.LABEL,
                        "caption": {
                            "bindTo": "Resources.Strings.PhoneNumberCaption"
                        },
                        "classes": {
                            "labelClass": ["label-small"]
                        }
                    }
                },
                /* Текстовое поле для ввода телефонного номера. */
                {
                    "operation": "insert",
                    "name": "PhoneNumber",
                    "parentName": "ContentContainer",
                    "propertyName": "items",
                    "values": {
                        "labelConfig": {
                            "visible": false
                        },
                        "layout": {
                            "column": 0,
                            "row": 2,
                            "colSpan": 24
                        },
                        "itemType": this.Terrasoft.ViewItemType.TEXT,
                        "classes": {
                            "labelClass": ["feature-item-label"]
                        },
                        "controlConfig": { "tag": "PhoneNumber" }
                    }
                },
                /* Подпись для текстового поля ввода текста сообщения. */
                {
                    "operation": "insert",
                    "name": "SmsTextLabel",
                    "parentName": "ContentContainer",
                    "propertyName": "items",
                    "values": {
                        "layout": {
                            "column": 0,
                            "row": 3,
                            "colSpan": 24
                        },
                        "classes": {
                            "labelClass": ["label-small"]
                        },
                        "itemType": this.Terrasoft.ViewItemType.LABEL,
                        "caption": {
                            "bindTo": "Resources.Strings.SmsTextCaption"
                        }
                    }
                },
                /* Текстовое поле для ввода текста сообщения. */
                {
                    "operation": "insert",
                    "name": "SmsText",
                    "parentName": "ContentContainer",
                    "propertyName": "items",
                    "values": {
                        "labelConfig": {
                            "visible": false
                        },
                        "layout": {
                            "column": 0,
                            "row": 4,
                            "colSpan": 24
                        },
                        "itemType": this.Terrasoft.ViewItemType.TEXT,
                        "classes": {
                            "labelClass": ["feature-item-label"]
                        },
                        "controlConfig": { "tag": "SmsText" }
                    }
                }
            ]
        };
    });
    
  7. На панели инструментов дизайнера модуля нажмите Сохранить (Save).

3. Добавить элемент в область элементов дизайнера кампании 

  1. Перейдите в раздел Конфигурация (Configuration) и выберите пользовательский пакет, в который будет добавлена схема.
  2. На панели инструментов реестра раздела нажмите Добавить —> Замещающая модель представления (Add —> Replacing view model).

  3. Заполните свойства схемы:

    • Код (Code) — "CampaignElementSchemaManagerEx".
    • Заголовок (Title) — "Область элементов дизайнера кампании" ("Campaign element manager").
    • Родительский объект (Parent object) — выберите "CampaignElementSchemaManagerEx".
  4. Добавьте элемент в область элементов дизайнера кампании.

    Исходный код схемы модели представления области элементов кампании представлен ниже.

    UsrTestSmsElementSchemaManagerEx
    require(["CampaignElementSchemaManager", "UsrTestSmsElementSchema"], function() {
        /* Добавление новой схемы в список доступных схем элементов в дизайнере кампании. */
        var coreElementClassNames = Terrasoft.CampaignElementSchemaManager.coreElementClassNames;
        coreElementClassNames.push({
            itemType: "Terrasoft.UsrTestSmsElementSchema"
        });
    });
    
  5. На панели инструментов дизайнера модуля нажмите Сохранить (Save).

4. Создать исполняемый элемент для элемента кампании 

  1. Перейдите в раздел Конфигурация (Configuration) и выберите пользовательский пакет, в который будет добавлена схема.
  2. На панели инструментов реестра раздела нажмите Добавить —> Исходный код (Add —> Source code).

  3. В дизайнере исходного кода заполните свойства схемы:

    • Код (Code) — "UsrTestSmsCampaignProcessElement".
    • Заголовок (Title) — "Элемент процесса "Тестовое СМС"" ("Test SMS process element").

    Для применения изменений свойств нажмите Применить (Apply).

  4. Реализуйте исполняемый элемент для элемента кампании, который позволяет выполнять необходимую логику поведения создаваемого элемента.

    1. Создайте класс, который является наследником класса CampaignFlowElement.
    2. Переопределите методы:

      • SingleExecute() — позволяет механизму выполнения кампании вызывать необходимую логику поведения элемента.
      • GetAudienceQuery() — определяет обрабатываемую аудиторию для элемента.

    Исходный код схемы исходного кода представлен ниже.

    UsrTestSmsCampaignProcessElement
    namespace Terrasoft.Configuration
    {
        using Terrasoft.Core.Campaign;
        using Terrasoft.Core.DB;
        
        public class UsrTestSmsCampaignProcessElement : CampaignFlowElement
        {
            public UsrTestSmsCampaignProcessElement() {
            }
            /* Cпецифические для СМС свойства. Передаются от экземпляра класса UsrTestSmsElement. */
            public string PhoneNumber {
                get;
                set;
            }
            public string SmsText {
                get;
                set;
            }
            /* Определяет аудиторию, которую необходимо обработать элементу. 
            Если не переопределить этот метод, то по умолчанию базовый класс берет всю аудиторию из текущего шага с признаком "Шаг не выполнен" и статусом "Участвует в кампании". */
            protected override Query GetAudienceQuery() =>
                new Select(UserConnection)
                    .Column("Id")
                    .From(CampaignParticipantTable)
                    .Where("CampaignItemId").IsEqual(Column.Parameter(CampaignItemId))
                    .And("StatusId").IsEqual(Column.Parameter(CampaignConstants.CampaignParticipantParticipatingStatusId))
                    .And("StepCompleted").IsEqual(Column.Parameter(0));
    
            /* Реализация метода выполнения элемента.
            Если не переопределить этот метод, то по умолчанию базовый класс возьмет запрос audienceQuery и для всех, кто подпадает под эту выборку, проставит "Шаг выполнен" без какой-либо дополнительной логики. */
            protected override int SingleExecute(Query audienceQuery) {
                /* Реализация логику отправки СМС-сообщений. 
                Текущий шаг для аудитории устанавливается как выполненный. */
                return SetItemCompleted(audienceQuery as Select);
            }
        }
    }
    
  5. На панели инструментов дизайнера исходного кода нажмите Сохранить (Save) для временного сохранения изменений в метаданных схемы.
  6. На панели инструментов дизайнера исходного кода нажмите Опубликовать (Publish) для выполнения изменений на уровне базы данных.

5. Реализовать back-end часть элемента кампании 

  1. Перейдите в раздел Конфигурация (Configuration) и выберите пользовательский пакет, в который будет добавлена схема.
  2. На панели инструментов реестра раздела нажмите Добавить —> Исходный код (Add —> Source code).

  3. В дизайнере исходного кода заполните свойства схемы:

    • Код (Code) — "UsrTestSmsElement".
    • Заголовок (Title) — "Элемент "Тестовое СМС"" ("Test SMS element").

    Для применения изменений свойств нажмите Применить (Apply).

  4. Реализуйте back-end часть элемента кампании, которая предоставляет возможность сохранения базовых и пользовательских свойств элемента кампании.

    1. Создайте класс, который является наследником класса CampaignSchemaElement.
    2. Переопределите методы:

      • ApplyMetaDataValue() — при вычитке добавляет присвоенные значения созданным свойствам.
      • WriteMetaData() — при записи данных записывает текущие значения новых свойств.

    Исходный код схемы исходного кода представлен ниже.

    UsrTestSmsElement
    namespace Terrasoft.Configuration
    {
        using System;
        using System.Collections.Generic;
        using Terrasoft.Common;
        using Terrasoft.Core;
        using Terrasoft.Core.Campaign;
        using Terrasoft.Core.Process;
    
        /* Описание новых свойств. */
        [DesignModeProperty(Name = "PhoneNumber", UsageType = DesignModeUsageType.NotVisible, MetaPropertyName = PhoneNumberPropertyName)]
        [DesignModeProperty(Name = "SmsText", UsageType = DesignModeUsageType.NotVisible, MetaPropertyName = SmsTextPropertyName)]
        public class UsrTestSmsElement : CampaignSchemaElement
        {
            /* Текстовое представление названий свойств. */
            private const string PhoneNumberPropertyName = "PhoneNumber";
            private const string SmsTextPropertyName = "SmsText";
            public UsrTestSmsElement() {
                /* Задает тип элемента (СМС - асинхронный элемент). */
                ElementType = CampaignSchemaElementType.AsyncTask;
            }
            
            public UsrTestSmsElement(UsrTestSmsElement source) : this(source, null, null) {
            }
      
            public UsrTestSmsElement(UsrTestSmsElement source, Dictionary<Guid, Guid> dictToRebind, Core.Campaign.CampaignSchema parentSchema) : base(source, dictToRebind, parentSchema) {
                /* При копировании переносит значения свойств исходного объекта. */
                ElementType = source.ElementType;
                PhoneNumber = source.PhoneNumber;
                SmsText = source.SmsText;
            }
    
            /* Метод для отображения в логе кампании и т. п. */
            protected override Guid Action {
                get {
                    return CampaignConsts.CampaignLogTypeMailing;
                }
            }
    
            /* Новое свойство элемента СМС. Guid генерируется уникальный (для каждого свойства свой). */
            [MetaTypeProperty("{A67950E7-FFD7-483D-9E67-3C9A30A733C0}")]
            public string PhoneNumber {
                get;
                set;
            }
            /* Новое свойство элемента СМС. */
            [MetaTypeProperty("{05F86DF2-B9FB-4487-B7BE-F3955703527C}")]
            public string SmsText {
                get;
                set;
            }
            /* При вычитке добавляет присвоенные значения созданным свойствам. */
            protected override void ApplyMetaDataValue(DataReader reader) {
                base.ApplyMetaDataValue(reader);
                switch (reader.CurrentName) {
                    /* Для PhoneNumber. */
                    case PhoneNumberPropertyName:
                        PhoneNumber = reader.GetValue<string>();
                        break;
                    /* Для SmsText. */
                    case SmsTextPropertyName:
                        SmsText = reader.GetValue<string>();
                        break;
                }
            }
    
            /* При записи данных записывает текущие значения новых свойств. */
            public override void WriteMetaData(DataWriter writer) {
                base.WriteMetaData(writer);
                /* Для PhoneNumber. */
                writer.WriteValue(PhoneNumberPropertyName, PhoneNumber, string.Empty);
                /* Для SmsText. */
                writer.WriteValue(SmsTextPropertyName, SmsText, string.Empty);
            }
            
            /* Копирует элемент. */
            public override object Clone() {
                return new UsrTestSmsElement(this);
            }
            public override object Copy(Dictionary<Guid, Guid> dictToRebind, Core.Campaign.CampaignSchema parentSchema) {
                return new UsrTestSmsElement(this, dictToRebind, parentSchema);
            }
    
            /* Создает исполняемый элемент для текущего элемента схемы (СМС). */
            public override ProcessFlowElement CreateProcessFlowElement(UserConnection userConnection) {
                var executableElement = new UsrTestSmsCampaignProcessElement {
                    UserConnection = userConnection,
                    SmsText = SmsText,
                    PhoneNumber = PhoneNumber
                };
                InitializeCampaignProcessFlowElement(executableElement);
                return executableElement;
            }
        }
    }
    
  5. На панели инструментов дизайнера исходного кода нажмите Сохранить (Save) для временного сохранения изменений в метаданных схемы.
  6. На панели инструментов дизайнера исходного кода нажмите Опубликовать (Publish) для выполнения изменений на уровне базы данных.

Результат выполнения примера 

Чтобы посмотреть результат выполнения примера:

  1. Настройте соединение с СМС-шлюзом. Предполагается, что проверка соединения, состояние счета и других параметров выполняется при валидации кампании, а отправка тестового СМС-сообщения — при ее старте.

    1. Перейдите в раздел Конфигурация (Configuration) и выберите пользовательский пакет, в который будет добавлена схема.
    2. На панели инструментов реестра раздела нажмите Добавить —> Исходный код (Add —> Source code).

    3. В дизайнере исходного кода заполните свойства схемы:

      • Код (Code) — "UsrTestSmsEventHandler".
      • Заголовок (Title) — "Обработчик тестового СМС-сообщения" ("Test SMS handler").

      Для применения изменений свойств нажмите Применить (Apply).

    4. Настройте соединение с СМС-шлюзом.

      Исходный код схемы исходного кода представлен ниже.

      UsrTestSmsEventHandler
      namespace Terrasoft.Configuration
      {
          using System;
          using Terrasoft.Core.Campaign.EventHandler;
          
          public sealed class UsrTestSmsEventHandler : CampaignEventHandlerBase, IOnCampaignValidate, IOnCampaignStart
          {
              /* Реализация обработчика события старта кампании. */
              public void OnStart() {
                  /* Реализация логики отправки тестового СМС-сообщения. */
              }
              /* Реализация обработчика события валидации кампании. */
              public void OnValidate() {
                  try {
                      /* Реализация логики валидации соединения с СМС-шлюзом. */
                  } catch (Exception ex) {
                      /* При наличии ошибки, добавляет ее в схему кампании. */
                      CampaignSchema.AddValidationInfo(ex.Message);
                  }
              }
          }
      }
      
    5. На панели инструментов дизайнера исходного кода нажмите Сохранить (Save) для временного сохранения изменений в метаданных схемы.
    6. На панели инструментов дизайнера исходного кода нажмите Опубликовать (Publish) для выполнения изменений на уровне базы данных.
  2. Выполните компиляцию приложения. Для этого воспользуйтесь инструкцией, которая приведена в статье Операции в Creatio IDE.
  3. Очистите кэш браузера.
  4. Перейдите в рабочее место Маркетинг (Marketing).
  5. Создайте кампанию. Для этого воспользуйтесь инструкцией, которая приведена в статье Создать кампанию.

В результате выполнения примера в меню элементов кампании добавлен новый элемент Тестовое СМС (Test SMS). При добавлении элемента Тестовое СМС (Test SMS) на рабочую область дизайнера кампаний отображается панель свойств элемента.

Реализовать переход для пользовательского элемента кампании
Сложный

Пример реализован для продуктов линейки Marketing Creatio.

Пример. Для пользовательского элемента Тестовое СМС (Test SMS) маркетинговой кампании создать пользовательский переход.

Варианты выполнения перехода:

  • Не учитывать отклики по СМС-рассылке.
  • Учитывать отклики по СМС-рассылке. В этом случае укажите отклики, которые необходимо учитывать.
  • Учитывать наличие откликов по СМС-рассылке, независимо от их значения.

1. Создать пользовательский элемент кампании 

Чтобы создать пользовательский элемент Тестовое СМС (Test SMS) кампании, выполните пример Добавить пользовательский элемент кампании.

2. Создать схему перехода для элемента кампании 

1. Создать справочник статуса отправки СМС-сообщения 

  1. Создайте объект справочника Статус отправки СМС-сообщения (SMS sending status).

    1. Перейдите в раздел Конфигурация (Configuration) и выберите пользовательский пакет, в который будет добавлена схема.
    2. На панели инструментов реестра раздела нажмите Добавить —> Объект (Add —> Object).

    3. В дизайнере объекта заполните свойства схемы:

      • Код (Code) — "UsrSmsSendingStatus".
      • Заголовок (Title) — "Статус отправки СМС-сообщения" ("SMS sending status").
      • Родительский объект (Parent object) — выберите "BaseLookup".
    4. На панели инструментов дизайнера объекта нажмите Опубликовать (Publish) для создания соответствующей таблицы в базе данных.
  2. Заполните справочник Статус отправки СМС-сообщения (SMS sending status).

    1. Перейдите в дизайнер системы по кнопке . В блоке Настройка системы (System setup) перейдите по ссылке Справочники (Lookups).
    2. Для Creatio версии 8.0.0 зарегистрируйте справочник. Начиная с версии 8.0.1 справочник регистрируется автоматически.

      1. На панели инструментов раздела Справочники (Lookups) нажмите Добавить справочник (New lookup) и заполните свойства справочника:

        • Название (Name) — "Статус отправки СМС-сообщения" ("SMS sending status").
        • Объект (Object) — выберите "Статус отправки СМС-сообщения" ("SMS sending status").
      2. На панели инструментов страницы настройки справочника нажмите Сохранить (Save) для сохранения справочника.
    3. Откройте справочник Статус отправки СМС-сообщения (SMS sending status).
    4. На панели инструментов страницы настройки справочника нажмите Добавить (New) и заполните значения справочника:

      • "Доставлено" ("Delivered").
      • "Отменено" ("Canceled").
      • "Ошибка доставки" ("Error while receiving").

      Идентификаторы статусов отправки СМС-сообщения используются в коде панели свойств условного перехода из СМС-рассылки.

2. Создать объект получателя СМС-сообщения 

  1. Перейдите в раздел Конфигурация (Configuration) и выберите пользовательский пакет, в который будет добавлена схема.
  2. На панели инструментов реестра раздела нажмите Добавить —> Объект (Add —> Object).

  3. В дизайнере объекта заполните свойства схемы:

    • Код (Code) — "UsrSmsRecipient".
    • Заголовок (Title) — "Получатель СМС" ("SMS recipient").
    • Родительский объект (Parent object) — выберите "BaseEntity".
  4. В схему объекта добавьте колонку, которая хранит номер телефона.

    1. На панели свойств в контекстном меню узла Колонки (Columns) нажмите —> Строка —> Строка (50 символов) (Text —> Text (50 characters)).

    2. В дизайнере объекта заполните свойства колонки:

      • Код (Code) — "UsrPhoneNumber".
      • Заголовок (Title) — "Номер телефона" ("Phone number").
  5. Аналогично добавьте другие колонки.

    Свойства колонок, которые необходимо добавить, приведены в таблице ниже.

    Значения свойств колонок
    Колонка
    Свойство
    Значение свойства
    Колонка, которая хранит информацию о тексте СМС-сообщения
    Тип данных
    (Data type)
    "Строка (50 символов)" ("Text (50 characters)")
    Код
    (Code)
    "UsrSmsText"
    Заголовок
    (Title)
    "Текст СМС-сообщения" ("SMS text")
    Колонка, которая хранит информацию о получателе СМС-сообщения
    Тип данных
    (Data type)
    "Справочник" ("Lookup")
    Код
    (Code)
    "UsrContactLookup"
    Заголовок
    (Title)
    "Контакт" ("Contact")
    Справочник
    (Lookup)
    Выберите "Contact"
    Колонка, которая хранит информацию о статусе отправки СМС-сообщения
    Тип данных
    (Data type)
    "Справочник" ("Lookup")
    Код
    (Code)
    "UsrSmsSendingStatusLookup"
    Заголовок
    (Title)
    "Статус отправки СМС-сообщения" ("SMS sending status")
    Справочник
    (Lookup)
    Выберите "UsrSmsSendingStatus"
  6. На панели инструментов дизайнера объекта нажмите Опубликовать (Publish) для создания соответствующей таблицы в базе данных.

3. Создать объект отклика на СМС-сообщение 

  1. Перейдите в раздел Конфигурация (Configuration) и выберите пользовательский пакет, в который будет добавлена схема.
  2. На панели инструментов реестра раздела нажмите Добавить —> Объект (Add —> Object).

  3. В дизайнере объекта заполните свойства схемы:

    • Код (Code) — "UsrSmsResponses".
    • Заголовок (Title) — "Отклики по СМС-рассылке" ("SMS responses").
    • Родительский объект (Parent object) — выберите "BaseEntity".
  4. В схему объекта добавьте колонку, которая хранит ответ на СМС-сообщение.

    1. На панели свойств в контекстном меню узла Колонки (Columns) нажмите —> Строка —> Строка (50 символов) (Text —> Text (50 characters)).

    2. В дизайнере объекта заполните свойства колонки:

      • Код (Code) — "UsrResponse".
      • Заголовок (Title) — "Отклик" ("Response").
  5. На панели инструментов дизайнера объекта нажмите Опубликовать (Publish) для создания соответствующей таблицы в базе данных.

4. Создать переход для элемента кампании 

  1. Перейдите в раздел Конфигурация (Configuration) и выберите пользовательский пакет, в который будет добавлена схема.
  2. На панели инструментов реестра раздела нажмите Добавить —> Модуль (Add —> Module).

  3. В дизайнере модуля заполните свойства схемы:

    • Код (Code) — "UsrProcessTestSmsConditionalTransitionSchema".
    • Заголовок (Title) — "Схема условного перехода для элемента" ("Element conditional transition schema").

    Для применения изменений свойств нажмите Применить (Apply).

  4. В дизайнере модуля добавьте исходный код, который реализует условия перехода.

    Исходный код схемы модуля представлен ниже.

    UsrProcessTestSmsConditionalTransitionSchema
    define("UsrProcessTestSmsConditionalTransitionSchema", ["CampaignEnums", "UsrProcessTestSmsConditionalTransitionSchemaResources", "ProcessCampaignConditionalSequenceFlowSchema"], function(CampaignEnums) {
        Ext.define("Terrasoft.manager.UsrProcessTestSmsConditionalTransitionSchema", {
            extend: "Terrasoft.ProcessCampaignConditionalSequenceFlowSchema",
            alternateClassName: "Terrasoft.UsrProcessTestSmsConditionalTransitionSchema",
            managerItemUId: "4b5e70b0-a631-458e-ab22-856ddc913444",
            mixins: {
                parametrizedProcessSchemaElement: "Terrasoft.ParametrizedProcessSchemaElement"
            },
            /* Полное имя типа связанного элемента стрелки. */
            typeName: "Terrasoft.Configuration.UsrTestSmsConditionalTransitionElement, Terrasoft.Configuration",
            /* Имя элемента стрелки для привязки к элементам кампании. */
            connectionUserHandleName: "TestSmsConditionalTransition",
            /* Имя панели свойств стрелки. */
            editPageSchemaName: "UsrTestSmsConditionalTransitionPropertiesPage",
            elementType: CampaignEnums.CampaignSchemaElementTypes.CONDITIONAL_TRANSITION,
            /* Коллекция откликов по СМС-рассылке. */
            testSmsResponseId: null,
            /* Признак, который учитывает условие откликов при переводе контактов. */
            isResponseBasedStart: false,
            getSerializableProperties: function() {
                var baseSerializableProperties = this.callParent(arguments);
                /* Свойства для сериализации и передачи в back-end часть при сохранении. */
                Ext.Array.push(baseSerializableProperties, ["testSmsResponseId", "isResponseBasedStart"]);
                return baseSerializableProperties;
            }
        });
        return Terrasoft.UsrProcessTestSmsConditionalTransitionSchema;
    });
    

    managerItemUId — уникальное значение, которое не должно повторять значение этого свойства у существующих элементов.

    typeName — имя C#-класса, который соответствует переходу для элемента кампании. Этот класс выполняет сохранение и чтение свойств элемента из метаданных схемы.

  5. На панели инструментов дизайнера модуля нажмите Сохранить (Save).

3. Создать панель свойств перехода для элемента кампании 

  1. Перейдите в раздел Конфигурация (Configuration) и выберите пользовательский пакет, в который будет добавлена схема.
  2. На панели инструментов реестра раздела нажмите Добавить —> Модель представления страницы (Add —> Page view model).

  3. Заполните свойства схемы:

    • Код (Code) — "UsrTestSmsConditionalTransitionPropertiesPage" (название совпадает со значением свойства editPageSchemaName схемы клиентского модуля UsrProcessTestSmsConditionalTransitionSchema).
    • Заголовок (Title) — "Панель свойств перехода для элемента Тестовое СМС" ("Properties panel of the transition Test SMS element").
    • Родительский объект (Parent object) — выберите "CampaignConditionalSequenceFlowPropertiesPage".
  4. Добавьте локализуемую строку с результатом шага перехода.

    1. В контекстном меню узла Локализуемые строки (Localizable strings) нажмите кнопку scr_add_button.png.
    2. Заполните свойства локализуемой строки:

      • Код (Code) — "ReactionModeCaption".
      • Значение (Value) — "Результат {0} шага?" ("What is the result of the {0} step?").
    3. Для добавления локализуемой строки нажмите Добавить (Add).
  5. Аналогично добавьте другие локализуемые строки.

    Свойства локализуемых строк, которые необходимо добавить, приведены в таблице ниже.

    Значения свойств локализуемых строк
    Код
    (Code)
    Значение
    (Value)
    "ReactionModeDefault"
    "Передача участников независимо от их ответа" ("Transfer participants regardless of their response")
    "ReactionModeWithCondition"
    "Настройка ответов для передачи участников" ("Set up responses for transferring participants")
    "IsTestSmsDelivered"
    "Тестовое сообщение доставлено" ("Test SMS delivered")
    "IsErrorWhileReceiving"
    "Ошибка при получении" ("Error while receiving")
  6. Настройте панель свойств перехода для элемента кампании.

    1. В свойство attributes добавьте атрибуты:

      • ReactionModeEnum — хранит информацию о перечне участников.
      • ReactionMode — хранит информацию об ответах участников.
      • IsTestSmsDelivered — хранит информацию о доставке СМС-сообщения.
      • IsErrorWhileReceiving — хранит информацию о получении ошибки во время доставки СМС-сообщения.
    2. В свойство rules добавьте бизнес-правило, которое обрабатывает значение атрибута ReactionMode.
    3. В свойстве methods реализуйте методы:

      • getResponseConfig() — формирует соответствие откликов по СМС-рассылке (на основании справочника Статус отправки СМС-сообщения (SMS sending status)). Предполагается, что справочник Статус отправки СМС-сообщения (SMS sending status) содержит значения "Доставлено" ("Delivered") и "Ошибка доставки" ("Error while receiving"). Идентификаторы этих статусов используются в коде панели свойств условного перехода из СМС-рассылки. Уникальный идентификатор содержится в соответствующей колонке строки записи справочника Статус отправки СМС-сообщения (SMS sending status). Чтобы отобразить колонку Id в реестре справочника Статус отправки СМС-сообщения (SMS sending status), воспользуйтесь инструкцией, которая описана в статье Реестр раздела.
      • subscribeEvents() — привязывает обработчик к событию изменения значения атрибута ReactionMode.
      • onReactionModeLookupChanged() — обрабатывает событие изменения атрибута ReactionMode.
      • initParameters() — инициализирует свойства ViewModel для отображения карточки при открытии.
      • cutString() — обрезает строку до указанной длины и добавляет троеточие в конце. Вспомогательный метод.
      • initIsTestSmsDelivered() — устанавливает значение статуса Доставлено (Delivered).
      • initIsErrorWhileReceiving() — устанавливает значение статуса Ошибка доставки (Error while receiving).
      • initTestSmsResponses() — инициализирует выбранные отклики при открытии карточки.
      • getIds() — извлекает массив идентификаторов из входящего JSON-параметра. Вспомогательный метод.
      • saveValues() — сохраняет значения откликов и настройку, добавлять условия откликов или нет.
      • getTestSmsResponseId() — получает сериализированные id выбранных откликов.
      • getQuestionCaption() — подставляет в текст название элемента, из которого выходит стрелка.
    4. В массив модификаций diff добавьте конфигурационные объекты с настройками расположения:

      • Контейнера на странице.
      • Заголовка.
      • Перечня.
      • Элемента перечня.

    Исходный код схемы модели представления панели свойств представлен ниже.

    UsrTestSmsConditionalTransitionPropertiesPage
    define("UsrTestSmsConditionalTransitionPropertiesPage", ["BusinessRuleModule"], function(BusinessRuleModule) {
        return {
            messages: {},
            /* Атрибуты, которые соответствуют специфическим свойствам схемы элемента. */
            attributes: {
                /* Название атрибута модели представления. */
                "ReactionModeEnum": {
                    /* Тип данных колонки модели представления. */
                    dataValueType: this.Terrasoft.DataValueType.CUSTOM_OBJECT,
                    type: this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
                    value: {
                        Default: {
                            value: "0",
                            captionName: "Resources.Strings.ReactionModeDefault"
                        },
                        WithCondition: {
                            value: "1",
                            captionName: "Resources.Strings.ReactionModeWithCondition"
                        }
                    }
                },
                "ReactionMode": {
                    "dataValueType": this.Terrasoft.DataValueType.LOOKUP,
                    "type": this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
                    "isRequired": true
                },
                "IsTestSmsDelivered": {
                    "dataValueType": this.Terrasoft.DataValueType.BOOLEAN,
                    "type": this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN
                },
                "IsErrorWhileReceiving": {
                    "dataValueType": this.Terrasoft.DataValueType.BOOLEAN,
                    "type": this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN
                }
            },
            /* Бизнес-правила модели представления страницы. */
            rules:
            {
                "ReactionConditionDecision": {
                    "BindReactionConditionDecisionRequiredToReactionMode": {
                        "ruleType": BusinessRuleModule.enums.RuleType.BINDPARAMETER,
                        "property": BusinessRuleModule.enums.Property.REQUIRED,
                        "conditions": [{
                            "leftExpression": {
                                "type": BusinessRuleModule.enums.ValueType.ATTRIBUTE,
                                "attribute": "ReactionMode"
                            },
                            "comparisonType": this.Terrasoft.ComparisonType.EQUAL,
                            "rightExpression": {
                                "type": BusinessRuleModule.enums.ValueType.CONSTANT,
                                "value": "1"
                            }
                        }]
                    }
                }
            },
            /* Методы модели представления страницы. */
            methods: {
                /* Формирует соответствие смс-откликов (на основании справочника UsrSmsSendingStatus). Предполагается, что в системе присутствует справочник UsrSmsSendingStatus с записями Delivered и Error while receiving. */
                getResponseConfig: function() {
                    return {
                        "IsTestSmsDelivered": "83389cd3-2dff-489b-aaa9-f3dd196777e1",
                        "IsErrorWhileReceiving": "69f29da1-eb09-44f6-8e0c-697dd05d8ccc"
                    };
                },
    
                subscribeEvents: function() {
                    this.callParent(arguments);
                    /* Привязывает обработчик к событию изменения значения атрибута ReactionMode. */
                    this.on("change:ReactionMode", this.onReactionModeLookupChanged, this);
                },
    
                /* Обрабатывает событие изменения атрибута ReactionMode. */
                onReactionModeLookupChanged: function() {
                    var reactionModeEnum = this.get("ReactionModeEnum");
                    var reactionMode = this.get("ReactionMode");
                    var decisionModeEnabled = (reactionMode && reactionMode.value === reactionModeEnum.WithCondition.value);
                    if (!decisionModeEnabled) {
                        this.set("ReactionConditionDecision", null);
                    }
                },
    
                /* Инициализирует свойства viewModel для отображения карточки при открытии. */
                initParameters: function(element) {
                    this.callParent(arguments);
                    var isResponseBasedStart = element.isResponseBasedStart;
                    this.initReactionMode(isResponseBasedStart);
                    this.initTestSmsResponses(element.testSmsResponseId);
                },
    
                /* Обрезает строку до указанной длины и добавляет троеточие в конце. Вспомогательный метод. */
                cutString: function(strValue, strLength) {
                    var ellipsis = Ext.String.ellipsis(strValue.substring(strLength), 0);
                    return strValue.substring(0, strLength) + ellipsis;
                },
    
                /* Устанавливает значение статуса "СМС доставлено". */
                initIsTestSmsDelivered: function(value) {
                    if (value === undefined) {
                        value = this.get("IsTestSmsDelivered");
                    }
                    this.set("IsTestSmsDelivered", value);
                },
    
                /* Устанавливает значение статуса "Ошибка при получении". */
                initIsErrorWhileReceiving: function(value) {
                    if (value === undefined) {
                        var isErrorWhileReceiving = this.get("IsErrorWhileReceiving");
                        value = isErrorWhileReceiving;
                    }
                    this.set("IsErrorWhileReceiving", value);
                },
    
                /* Инициализирует выбранные отклики при открытии карточки. */
                initTestSmsResponses: function(responseIdsJson) {
                    if (!responseIdsJson) {
                        return;
                    }
                    var responseIds = JSON.parse(responseIdsJson);
                    var config = this.getResponseConfig();
                    Terrasoft.each(config, function(propValue, propName) {
                        if (responseIds.indexOf(propValue) > -1) {
                            this.set(propName, true);
                        }
                    }, this);
                },
    
                initReactionMode: function(value) {
                    var isDefault = !value;
                    this.setLookupValue(isDefault, "ReactionMode", "WithCondition", this);
                },
    
                /* Извлекает массив идентификаторов из входящего JSON-параметра. Вспомогательный метод. */
                getIds: function(idsJson) {
                    if (idsJson) {
                        try {
                            var ids = JSON.parse(idsJson);
                            if (this.Ext.isArray(ids)) {
                                return ids;
                            }
                        } catch (error) {
                            return [];
                        }
                    }
                    return [];
                },
    
                onPrepareReactionModeList: function(filter, list) {
                    this.prepareList("ReactionModeEnum", list, this);
                },
    
                /* Сохраняет значения откликов и настройку, добавлять условия откликов или нет. */
                saveValues: function() {
                    this.callParent(arguments);
                    var element = this.get("ProcessElement");
                    var isResponseBasedStart = this.getIsReactionModeWithConditions();
                    element.isResponseBasedStart = isResponseBasedStart;
                    element.testSmsResponseId = this.getTestSmsResponseId(isResponseBasedStart);
                },
    
                /* Получает сериализированные id выбранных откликов. */
                getTestSmsResponseId: function(isResponseActive) {
                    var responseIds = [];
                    if (isResponseActive) {
                        var config = this.getResponseConfig();
                        Terrasoft.each(config, function(propValue, propName) {
                            var attrValue = this.get(propName);
                            if (attrValue && propValue) {
                                responseIds.push(propValue);
                            }
                        }, this);
                    }
                    return JSON.stringify(responseIds);
                },
    
                getLookupValue: function(parameterName) {
                    var value = this.get(parameterName);
                    return value ? value.value : null;
                },
    
                getContextHelpCode: function() {
                    return "CampaignConditionalSequenceFlow";
                },
    
                getIsReactionModeWithConditions: function() {
                    return this.isLookupValueEqual("ReactionMode", "1", this);
                },
    
                getSourceElement: function() {
                    var flowElement = this.get("ProcessElement");
                    if (flowElement) {
                        return flowElement.findSourceElement();
                    }
                    return null;
                },
                /* Подставляет в текст название элемента, из которого выходит стрелка. */
                getQuestionCaption: function() {
                    var caption = this.get("Resources.Strings.ReactionModeCaption");
                    caption = this.Ext.String.format(caption, this.getSourceElement().getCaption());
                    return caption;
                }
            },
            /* Отображение свойств. */
            diff: /**SCHEMA_DIFF*/[
                /* Метаданные для добавления на страницу контейнера. */
                {
                    /* Выполняется операция добавления элемента на страницу. */
                    "operation": "insert",
                    /* Мета-имя добавляемого контейнера. */
                    "name": "ReactionContainer",
                    /* Контейнер добавляется в коллекцию элементов родительского элемента. */
                    "propertyName": "items",
                    /* Мета-имя родительского контейнера, в который добавляется текущий контейнер. */
                    "parentName": "ContentContainer",
                    "className": "Terrasoft.GridLayoutEdit",
                    /* Свойства, передаваемые в конструктор элемента. */
                    "values":
                    {
                        "layout":
                        {
                            "column": 0,
                            "row": 2,
                            "colSpan": 24
                        },
                        "itemType": this.Terrasoft.ViewItemType.GRID_LAYOUT,
                        "items": []
                    }
                },
                /* Заголовок. */
                {
                    "operation": "insert",
                    "name": "ReactionModeLabel",
                    "parentName": "ReactionContainer",
                    "propertyName": "items",
                    "values":
                    {
                        "layout":
                        {
                            "column": 0,
                            "row": 0,
                            "colSpan": 24
                        },
                        "itemType": this.Terrasoft.ViewItemType.LABEL,
                        "caption":
                        {
                            "bindTo": "getQuestionCaption"
                        },
                        "classes":
                        {
                            "labelClass": ["t-title-label-proc"]
                        }
                    }
                },
                /* Перечень. */
                {
                    "operation": "insert",
                    "name": "ReactionMode",
                    "parentName": "ReactionContainer",
                    "propertyName": "items",
                    "values":
                    {
                        "contentType": this.Terrasoft.ContentType.ENUM,
                        "controlConfig":
                        {
                            "prepareList":
                            {
                                "bindTo": "onPrepareReactionModeList"
                            }
                        },
                        "isRequired": true,
                        "layout":
                        {
                            "column": 0,
                            "row": 1,
                            "colSpan": 24
                        },
                        "labelConfig":
                        {
                            "visible": false
                        },
                        "wrapClass": ["no-caption-control"]
                    }
                },
                /* Элемент перечня. */
                {
                    "operation": "insert",
                    "parentName": "ReactionContainer",
                    "propertyName": "items",
                    "name": "IsTestSmsDelivered",
                    "values":
                    {
                        "wrapClass": ["t-checkbox-control"],
                        "visible":
                        {
                            "bindTo": "ReactionMode",
                            "bindConfig":
                            {
                                converter: "getIsReactionModeWithConditions"
                            }
                        },
                        "caption":
                        {
                            "bindTo": "Resources.Strings.IsTestSmsDelivered"
                        },
                        "layout":
                        {
                            "column": 0,
                            "row": 2,
                            "colSpan": 22
                        }
                    }
                },
                /* Элемент перечня. */
                {
                    "operation": "insert",
                    "parentName": "ReactionContainer",
                    "propertyName": "items",
                    "name": "IsErrorWhileReceiving",
                    "values":
                    {
                        "wrapClass": ["t-checkbox-control"],
                        "visible":
                        {
                            "bindTo": "ReactionMode",
                            "bindConfig":
                            {
                                converter: "getIsReactionModeWithConditions"
                            }
                        },
                        "caption":
                        {
                            "bindTo": "Resources.Strings.IsErrorWhileReceiving"
                        },
                        "layout":
                        {
                            "column": 0,
                            "row": 3,
                            "colSpan": 22
                        }
                    }
                }
            ]/**SCHEMA_DIFF*/
        };
    });
    
  7. На панели инструментов дизайнера модуля нажмите Сохранить (Save).

4. Создать исполняемый элемент для перехода элемента кампании 

  1. Перейдите в раздел Конфигурация (Configuration) и выберите пользовательский пакет, в который будет добавлена схема.
  2. На панели инструментов реестра раздела нажмите Добавить —> Исходный код (Add —> Source code).

  3. В дизайнере исходного кода заполните свойства схемы:

    • Код (Code) — "UsrTestSmsConditionalTransitionFlowElement".
    • Заголовок (Title) — "Условный переход элемента процесса "Тестовое СМС"" ("Conditional transition of the Test SMS process element").

    Для применения изменений свойств нажмите Применить (Apply).

  4. Реализуйте исполняемый элемент для перехода элемента кампании, который позволяет выполнять учет условия откликов по СМС-рассылке. Для этого создайте класс, который является наследником класса ConditionalTransitionFlowElement.

    Исходный код схемы исходного кода представлен ниже.

    UsrTestSmsConditionalTransitionFlowElement
    namespace Terrasoft.Configuration
    {
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using Terrasoft.Common;
        using Terrasoft.Core.DB;
        
        public class UsrTestSmsConditionalTransitionFlowElement : ConditionalTransitionFlowElement
        {
        
            public string SmsText { get; set; }
        
            public string PhoneNumber { get; set; }
        
            public IEnumerable<Guid> TestSmsResponses { get; set; }
        
            private void ExtendWithResponses() {
                TransitionQuery.CheckArgumentNull("TransitionQuery");
                if (TestSmsResponses.Any()) {
                    Query responseSelect = GetSelectByParticipantResponses();
                    TransitionQuery.And("ContactId").In(responseSelect);
                }
            }
        
            private Query GetSelectByParticipantResponses() {
                var responseSelect = new Select(UserConnection)
                    .Column("ContactId")
                    .From("UsrSmsRecipient")
                    .Where("SmsText").IsEqual(Column.Parameter(SmsText))
                        .And("PhoneNumber").IsEqual(Column.Parameter(PhoneNumber))
                        .And("TestSmsResponseId")
                            .In(Column.Parameters(TestSmsResponses)) as Select;
                responseSelect.SpecifyNoLockHints(true);
                return responseSelect;
            }
        
            protected override void CreateQuery() {
                base.CreateQuery();
                ExtendWithResponses();
            }
        }
    }
    
  5. На панели инструментов дизайнера исходного кода нажмите Сохранить (Save) для временного сохранения изменений в метаданных схемы.
  6. На панели инструментов дизайнера исходного кода нажмите Опубликовать (Publish) для выполнения изменений на уровне базы данных.

5. Реализовать back-end часть перехода для элемента кампании 

  1. Перейдите в раздел Конфигурация (Configuration) и выберите пользовательский пакет, в который будет добавлена схема.
  2. На панели инструментов реестра раздела нажмите Добавить —> Исходный код (Add —> Source code).

  3. В дизайнере исходного кода заполните свойства схемы:

    • Код (Code) — "UsrTestSmsConditionalTransitionElement".
    • Заголовок (Title) — "Переход элемента "Тестовое СМС"" ("Transition the Test SMS element").

    Для применения изменений свойств нажмите Применить (Apply).

  4. Реализуйте back-end часть элемента кампании, которая предоставляет возможность сохранения базовых и пользовательских свойств элемента кампании. Для этого создайте класс, который является наследником класса ConditionalSequenceFlowElement.

    Исходный код схемы исходного кода представлен ниже.

    UsrTestSmsConditionalTransitionElement
    namespace Terrasoft.Configuration
    {
        using System;
        using System.Collections.Generic;
        using System.Collections.ObjectModel;
        using System.Globalization;
        using System.Linq;
        using Newtonsoft.Json;
        using Terrasoft.Common;
        using Terrasoft.Core;
        using Terrasoft.Core.Campaign;
        using Terrasoft.Core.DB;
        using Terrasoft.Core.Process;
        
        /* Описание новых свойств. */
        [DesignModeProperty(Name = "TestSmsResponseId", UsageType = DesignModeUsageType.NotVisible, MetaPropertyName = TestSmsResponseIdPropertyName)]
        [DesignModeProperty(Name = "IsResponseBasedStart", UsageType = DesignModeUsageType.Advanced, MetaPropertyName = IsResponseBasedStartPropertyName)]
        public class UsrTestSmsConditionalTransitionElement : ConditionalSequenceFlowElement
        {
        
            /* Текстовое представление названий свойств. */
            private const string TestSmsResponseIdPropertyName = "TestSmsResponseId";
            private const string IsResponseBasedStartPropertyName = "IsResponseBasedStart";
            
            public UsrTestSmsConditionalTransitionElement() {}
            
            public UsrTestSmsConditionalTransitionElement(UsrTestSmsConditionalTransitionElement source)
                : this(source, null, null) {}
        
            public UsrTestSmsConditionalTransitionElement(UsrTestSmsConditionalTransitionElement source,
                Dictionary<Guid, Guid> dictToRebind, Core.Campaign.CampaignSchema parentSchema)
                : base(source, dictToRebind, parentSchema) {
                IsResponseBasedStart = source.IsResponseBasedStart;
                _testSmsResponseIdJson = JsonConvert.SerializeObject(source.TestSmsResponseId);
            }
        
            private string _testSmsResponseIdJson;
            
            private IEnumerable<Guid> Responses {
                get {
                    return TestSmsResponseId;
                }
            }
        
            [MetaTypeProperty("{DC597899-B831-458A-A58E-FB43B1E266AC}")]
            public IEnumerable<Guid> TestSmsResponseId {
                get {
                    return !string.IsNullOrWhiteSpace(_testSmsResponseIdJson)
                        ? JsonConvert.DeserializeObject<IEnumerable<Guid>>(_testSmsResponseIdJson)
                        : Enumerable.Empty(Guid)();
                }
            }
            
            [MetaTypeProperty("{3FFA4EA0-62CC-49A8-91FF-4096AEC561F6}",
        IsExtraProperty = true, IsUserProperty = true)]
            public virtual bool IsResponseBasedStart {
                get;
                set;
            }
            
            protected override void ApplyMetaDataValue(DataReader reader) {
                base.ApplyMetaDataValue(reader);
                switch (reader.CurrentName) {
                    case TestSmsResponseIdPropertyName:
                        _testSmsResponseIdJson = reader.GetValue<string>();
                        break;
                    case IsResponseBasedStartPropertyName:
                        IsResponseBasedStart = reader.GetBoolValue();
                        break;
                    default:
                        break;
                }
            }
            
            public override void WriteMetaData(DataWriter writer) {
                base.WriteMetaData(writer);
                writer.WriteValue(IsResponseBasedStartPropertyName, IsResponseBasedStart, false);
                writer.WriteValue(TestSmsResponseIdPropertyName, _testSmsResponseIdJson, null);
            }
            
            public override object Clone() {
                return new UsrTestSmsConditionalTransitionElement(this);
            }
            
            public override object Copy(Dictionary<Guid, Guid> dictToRebind, Core.Campaign.CampaignSchema parentSchema) {
                return new UsrTestSmsConditionalTransitionElement(this, dictToRebind, parentSchema);
            }
            
            /* Переопределяет фабричный метод по созданию исполняемого элемента. Возвращает элемент с типом UsrTestSmsConditionalTransitionFlowElement */
            public override ProcessFlowElement CreateProcessFlowElement(UserConnection userConnection) {
                var sourceElement = SourceRef as TestSmsElement;
                var executableElement = new UsrTestSmsConditionalTransitionFlowElement {
                    UserConnection = userConnection,
                    TestSmsResponses = TestSmsResponseId,
                    PhoneNumber = sourceElement.PhoneNumber,
                    SmsText = sourceElement.SmsText
                };
                InitializeCampaignProcessFlowElement(executableElement);
                InitializeCampaignTransitionFlowElement(executableElement);
                InitializeConditionalTransitionFlowElement(executableElement);
                InitializeAudienceSchemaInfo(executableElement, userConnection);
                return executableElement;
            } 
        }  
    }
    
  5. На панели инструментов дизайнера исходного кода нажмите Сохранить (Save) для временного сохранения изменений в метаданных схемы.
  6. На панели инструментов дизайнера исходного кода нажмите Опубликовать (Publish) для выполнения изменений на уровне базы данных.

6. Реализовать логику работы перехода при изменении источника 

  1. Перейдите в раздел Конфигурация (Configuration) и выберите пользовательский пакет, в который будет добавлена схема.
  2. На панели инструментов реестра раздела нажмите Добавить —> Модуль (Add —> Module).

  3. В дизайнере модуля заполните свойства схемы:

    • Код (Code) — "UsrTestSmsCampaignConnectorManager".
    • Заголовок (Title) — "Менеджер подключения элемента "Тестовое СМС"" ("Test SMS campaign connector manager").
  4. В дизайнере модуля добавьте исходный код.

    Исходный код схемы замещающей модели представления представлен ниже.

    UsrTestSmsCampaignConnectorManager
    define("UsrTestSmsCampaignConnectorManager", [], function() {
        Ext.define("Terrasoft.UsrTestSmsCampaignConnectorManager", {
            /* Указываем, что замещаем модуль CampaignConnectorManager. */
            override: "Terrasoft.CampaignConnectorManager",
        
            /* Добавляем маппинг название схема-элемента источника для стрелки - тип стрелки (full name). */
            initMappingCollection: function() {
                this.callParent(arguments);
                this.connectorTypesMappingCollection.addIfNotExists("UsrTestSmsElementSchema",
                    "Terrasoft.UsrProcessTestSmsConditionalTransitionSchema");
            },
        
            /* Виртуальный метод для перегрузки.
            Логика для процессинга стрелки перед ее подменой стрелкой с новым типом. */
            additionalBeforeChange: function(prevTransition, sourceItem, targetItem) {
                /* Реализация логики. */
            },
        
            /* Виртуальный метод для перегрузки.
            Заполняет специфические поля созданной стрелки на основе предыдущей стрелки. */
            fillAdditionalProperties: function(prevElement, newElement) {
                if (newElement.getTypeInfo().typeName === "UsrProcessTestSmsConditionalTransitionSchema") {
                    /* Переносит настроенные отклики, если предыдущая стрелка такого же типа. */
                    newElement.testSmsResponseId = prevElement.testSmsResponseId ? prevElement.testSmsResponseId : null;
                    /* Так же переносим и настройку учета откликов. */
                    newElement.isResponseBasedStart = prevElement.isResponseBasedStart ? prevElement.isResponseBasedStart : false;
                }
            }
        });
    });
    
  5. На панели инструментов дизайнера модуля нажмите Сохранить (Save).

7. Подключить логику работы перехода 

  1. Перейдите в раздел Конфигурация (Configuration) и выберите пользовательский пакет, в который будет добавлена схема.
  2. На панели инструментов реестра раздела нажмите Добавить —> Замещающая модель представления (Add —> Replacing view model).

  3. В дизайнере модуля заполните свойство схемы Родительский объект (Parent object) — выберите "BootstrapModulesV2".

  4. В дизайнере модуля добавьте исходный код.

    Исходный код схемы замещающей модели представления представлен ниже.

    UsrTestSmsCampaignConnectorManager
    /* Добавляем в зависимости созданный ранее модуль UsrTestSmsCampaignConnectorManager. */
    define("BootstrapModulesV2", ["UsrTestSmsCampaignConnectorManager","UsrProcessTestSmsConditionalTransitionSchema"], function() {});
    
  5. На панели инструментов дизайнера модуля нажмите Сохранить (Save).

Результат выполнения примера 

Чтобы посмотреть результат выполнения примера:

  1. Перейдите в рабочее место Маркетинг (Marketing).
  2. Создайте кампанию. Для этого воспользуйтесь инструкцией, которая приведена в статье Создать кампанию.
  3. На рабочую область дизайнера кампаний добавьте элемент Тестовое СМС (Test SMS).
  4. На рабочую область дизайнера кампаний добавьте любой другой элемент (например, Выход из кампании (Exit from campaign)).
  5. Добавьте переход от элемента Тестовое СМС (Test SMS) к элементу Выход из кампании (Exit from campaign) кампании.

В результате выполнения примера отображается панель свойств перехода.

Варианты выполнения перехода (Результат Тестовое СМС 1 шага? (What is the result of the Test SMS 1 step?)), которые позволяет настроить панель свойств:

  • Не учитывать отклики по СМС-рассылке (Передача участников независимо от их ответа (Transfer participants regardless of their response)).

  • Учитывать отклики по СМС-рассылке (Настройка ответов для передачи участников (Set up responses for transferring participants)). Можно настроить учет откликов, когда СМС-сообщение было доставлено (Тестовое сообщение доставлено (Test SMS delivered)) и/или когда были получены ошибки во время доставки СМС-сообщения (Ошибка доставки (Error while receiving)).

  • Учитывать наличие откликов по СМС-рассылке, независимо от их значения (Настройка ответов для передачи участников (Set up responses for transferring participants)).

В реальном примере желательно создать отдельную схему объекта СМС-рассылка (SMS mailing, код UsrSmsMailing). В этом случае объекты Элемент "Тестовое СМС" (Test SMS element, код UsrTestSmsElement) и Переход элемент "Тестовое СМС" (Transition the Test SMS element, код UsrTestSmsConditionalTransitionElement) должны содержать идентификаторы объекта СМС-рассылка (SMS mailing), а не поля Текст СМС-сообщения (SMS text, код UsrSmsText), Номер телефона (Phone number, код UsrPhoneNumber) и т. д. Исполняемый элемент Элемент процесса "Тестовое СМС" (Test SMS process element, код UsrTestSmsCampaignProcessElement) в методе Execute() должен содержать логику по добавлению контактов в аудиторию СМС-рассылки. Отдельный механизм (или несколько механизмов) должны выполнить отправку СМС-рассылки, а затем зафиксировать отклики участников. На основании этих откликов выполняется логика работы стрелки по перемещению аудитории кампании на следующий шаг.