Implement a custom campaign element
To implement the example:
- Create a campaign element. Read more >>>
- Create a property panel for the campaign element. Read more >>>
- Add the campaign element to the Campaign Designer. Read more >>>
- Create an executable element for the campaign element. Read more >>>
- Implement the business logic of the campaign element. Read more >>>
Create a custom SMS campaign element to send SMS to specific users. Add the element to the Campaign Designer. Use the icon provided via the link.
1. Create a campaign element
-
Open the Configuration section. Instructions: Open the Configuration section.
-
Create a
sdkCustomCampaignElement
package. Instructions: Create a user-made package using Configuration section. -
Change the current package to
sdkCustomCampaignElement
. Instructions: Change the current package. -
Click Add → Module.
-
Fill out the schema properties.
For this example, use the following schema properties.
Property
Property value
Code
UsrSmsElement
Title
SMS element
-
Add a localizable string that stores the campaign element name.
-
Create a localizable string. Instructions: Add a localizable string.
-
Fill out the localizable string parameters.
Parameter
Parameter value
Code
SmsElementCaption
Value
SMS
-
Click Add.
-
-
Add icons that represent the campaign element in different Campaign Designer modes.
For this example, use the icon provided via the link.
-
Go to the properties area → Images → click
.
-
Fill out the image properties.
Property
Property value
Code
TitleImage
Image
Click
→ select the icon provided via the link.
-
Click Add.
-
Repeat steps i–iii for both
SmallImage
andLargeImage
resources.
-
-
Add source code that implements the appearance of the campaign element. To do this, link the uploaded image to the
TitleImage
,LargeImage
andSmallImage
properties.UsrSmsElementdefine("UsrSmsElement", ["UsrSmsElementResources",
"CampaignBaseCommunicationSchema"], function(resources) {
Ext.define("Terrasoft.manager.UsrSmsElement", {
/* Parent schema. */
extend: "Terrasoft.CampaignBaseCommunicationSchema",
/* Alternative class name. */
alternateClassName: "Terrasoft.UsrSmsElement",
/* ID of the new campaign element. */
managerItemUId: "a1226f93-f3e3-4baa-89a6-11f2a9ab2d71",
/* Mixins that extend functionality. */
mixins: {
campaignElementMixin: "Terrasoft.CampaignElementMixin"
},
/* Element code. */
name: "Sms",
/* Localizable strings. */
caption: resources.localizableStrings.SmsElementCaption,
titleImage: resources.localizableImages.TitleImage,
largeImage: resources.localizableImages.LargeImage,
smallImage: resources.localizableImages.SmallImage,
/* Schema code of the record page. */
editPageSchemaName: "UsrSmsElementPropertiesPanel",
/* Element type. */
elementType: "Sms",
/* Full name of the class that implements the campaign element logic.
This class saves and reads the element properties from the schema
properties. Since the class is placed in the regular package, use the
"Terrasoft.Configuration.UsrSmsElement, Terrasoft.Configuration"
typeName. If the class is placed in the assembly package, use
typeName: "Terrasoft.Configuration.UsrSmsElement,
SomeAssemblyPackageName" */
typeName: "Terrasoft.Configuration.UsrSmsElement, " +
"Terrasoft.Configuration",
/* CSS styles. */
color: "rgba(249, 160, 27, 1)",
width: 69,
height: 55,
/* Custom element properties. */
smsText: null,
phoneNumber: null,
/* Define the types of outbound connections supported by this element. */
getConnectionUserHandles: function() {
return ["CampaignSequenceFlow", "CampaignConditionalSequenceFlow"];
},
/* Include custom properties in serialization. */
getSerializableProperties: function() {
var baseSerializableProperties = this.callParent(arguments);
return Ext.Array.push(baseSerializableProperties, ["smsText",
"phoneNumber"]);
},
/* Configure the element icons that are displayed on the campaign diagram. */
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.UsrSmsElement;
}); -
Click Save.
2. Create a property panel for the campaign element
-
Click Add → Page view model.
-
Fill out the schema properties.
For this example, use the following schema properties.
Property
Property value
Code
UsrSmsElementPropertiesPanel
Title
Properties panel for the SMS element
Parent object
BaseCampaignSchemaElementPage
-
Add the localizable strings that include the field names.
-
Create a localizable string. Instructions: Add a localizable string.
-
Fill out the localizable string parameters.
Code
Value
PhoneNumberCaption
Sender phone
SmsTextCaption
Message
SmsText
Which SMS text to send?
-
-
Implement the business logic of the campaign element.
UsrSmsElementPropertiesPaneldefine("UsrSmsElementPropertiesPanel", [], function() {
return {
/* Schema attributes. */
attributes: {
/* Attribute that stores data about the phone number. */
"PhoneNumber": {
"dataValueType": this.Terrasoft.DataValueType.TEXT,
"type": this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN
},
/* Attribute that stores data about the message text. */
"SmsText": {
"dataValueType": this.Terrasoft.DataValueType.TEXT,
"type": this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN
}
},
/* Schema methods. */
methods: {
/* Initialize the module. */
init: function() {
this.callParent(arguments);
this.initAcademyUrl(this.onAcademyUrlInitialized, this);
},
/* Return the context help code for linking to help documentation. */
getContextHelpCode: function() {
return "CampaignSmsElement";
},
/* Initialize the attributes using values from the campaign element schema. */
initParameters: function(element) {
this.callParent(arguments);
this.set("SmsText", element.smsText);
this.set("PhoneNumber", element.phoneNumber);
},
/* Save attribute values back to the campaign element schema. */
saveValues: function() {
this.callParent(arguments);
var element = this.get("ProcessElement");
element.smsText = this.getSmsText();
element.phoneNumber = this.getPhoneNumber();
},
/* Receive the "PhoneNumber" attribute value. */
getPhoneNumber: function() {
var number = this.get("PhoneNumber");
return number ? number : "";
},
/* Receive the "SmsText" attribute value. */
getSmsText: function() {
var smsText = this.get("SmsText");
return smsText ? smsText : "";
}
},
/* The schema view description. */
diff: [
/* The page container. */
{
"operation": "insert",
"name": "ContentContainer",
"propertyName": "items",
"parentName": "EditorsContainer",
"className": "Terrasoft.GridLayoutEdit",
"values": {
"itemType": Terrasoft.ViewItemType.GRID_LAYOUT,
"items": []
}
},
/* The element caption. */
{
"operation": "insert",
"name": "SmsLabel",
"parentName": "ContentContainer",
"propertyName": "items",
"values": {
"layout": {
"column": 0,
"row": 0,
"colSpan": 24
},
"itemType": this.Terrasoft.ViewItemType.LABEL,
"caption": {
"bindTo": "Resources.Strings.SmsText"
},
"classes": {
"labelClass": ["t-title-label-proc"]
}
}
},
/* The caption of the "Text" type field to enter the sender number. */
{
"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"]
}
}
},
/* The "Text" type field to enter the phone number. */
{
"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" }
}
},
/* The caption of the "Text" type field to enter the message text. */
{
"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"
}
}
},
/* The "Text" type field to enter the message text. */
{
"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" }
}
}
]
};
}); -
Click Save.
3. Add the campaign element to the Campaign Designer
-
Click Add → Replacing view model.
-
Fill out the schema properties.
For this example, use the following schema properties.
Property
Property value
Parent object
CampaignElementSchemaManagerEx
-
Add the source code.
CampaignElementSchemaManagerExrequire(["CampaignElementSchemaManager", "UsrSmsElement"],
function() {
/* Register the "UsrSmsElement" in the Campaign Designer. */
var coreElementClassNames = Terrasoft.CampaignElementSchemaManager.coreElementClassNames;
/* Add the custom schema to the list of available schemas. */
coreElementClassNames.push({
itemType: "Terrasoft.UsrSmsElement"
});
}
); -
Click Save.
4. Create an executable element for the campaign element
-
Click Add → Source code.
-
Fill out the schema properties.
For this example, use the following schema properties.
Property
Property value
Code
UsrSmsCampaignProcessElement
Title
SMS process element
-
Implement an executable element that executes the business logic of the created element.
-
Specify the
CampaignFlowElement
class as a parent class. -
Override the methods.
Query GetAudienceQuery()
SingleExecute(Query audienceQuery)
UsrSmsCampaignProcessElementnamespace Terrasoft.Configuration
{
using Terrasoft.Core.Campaign;
using Terrasoft.Core.DB;
/* Define a custom campaign element. */
public class UsrSmsCampaignProcessElement : CampaignFlowElement
{
public UsrSmsCampaignProcessElement() {
}
/* Assign the "PhoneNumber" attribute value in the class. */
public string PhoneNumber {
get;
set;
}
/* Assign the "SmsText" attribute value in the class. */
public string SmsText {
get;
set;
}
/* Define the campaign audience for the element. */
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));
/* Execute the campaign step logic for the selected audience. */
protected override int SingleExecute(Query audienceQuery) {
return SetItemCompleted(audienceQuery as Select);
}
}
} -
-
Click Save and publish.
5. Implement the business logic of the campaign element
-
Click Add → Source code.
-
Fill out the schema properties.
For this example, use the following schema properties.
Property
Property value
Code
UsrSmsElement
Title
SMS element
-
Specify the
CampaignSchemaElement
class as a parent class. -
Override the methods.
Guid Action
ApplyMetaDataValue(DataReader reader)
WriteMetaData(DataWriter writer)
Clone()
Copy(Dictionary<Guid, Guid> dictToRebind, Core.Campaign.CampaignSchema parentSchema)
ProcessFlowElement CreateProcessFlowElement(UserConnection userConnection)
UsrSmsElementnamespace Terrasoft.Configuration
{
using System;
using System.Collections.Generic;
using Terrasoft.Common;
using Terrasoft.Core;
using Terrasoft.Core.Campaign;
using Terrasoft.Core.Process;
/* Define the campaign schema element (metadata) for the custom campaign element.
This class describes the element in the campaign schema and handles metadata persistence. */
[DesignModeProperty(
Name = "PhoneNumber",
UsageType = DesignModeUsageType.NotVisible,
MetaPropertyName = PhoneNumberPropertyName
)]
[DesignModeProperty(
Name = "SmsText",
UsageType = DesignModeUsageType.NotVisible,
MetaPropertyName = SmsTextPropertyName
)]
public class UsrSmsElement : CampaignSchemaElement
{
/* Constants for property names used in metadata serialization. */
private const string PhoneNumberPropertyName = "PhoneNumber";
private const string SmsTextPropertyName = "SmsText";
public UsrSmsElement() {
ElementType = CampaignSchemaElementType.AsyncTask;
}
/* Default constructor: defines the element type as an async task. */
public UsrSmsElement(UsrSmsElement source) : this(source, null, null) {
}
/* Copy constructors for cloning the element in schema operations. */
public UsrSmsElement(
UsrSmsElement source,
Dictionary<Guid, Guid> dictToRebind,
Core.Campaign.CampaignSchema parentSchema
) : base(source, dictToRebind, parentSchema) {
ElementType = source.ElementType;
PhoneNumber = source.PhoneNumber;
SmsText = source.SmsText;
}
/* Define the campaign log action type associated with this element. */
protected override Guid Action {
get {
return CampaignConsts.CampaignLogTypeMailing;
}
}
[MetaTypeProperty("{A67950E7-FFD7-483D-9E67-3C9A30A733C0}")]
/* Assign the "PhoneNumber" attribute value in the class. */
public string PhoneNumber {
get;
set;
}
[MetaTypeProperty("{05F86DF2-B9FB-4487-B7BE-F3955703527C}")]
/* Assign the "SmsText" attribute value in the class. */
public string SmsText {
get;
set;
}
/* Read element metadata from the schema definition during deserialization. */
protected override void ApplyMetaDataValue(DataReader reader) {
base.ApplyMetaDataValue(reader);
switch (reader.CurrentName) {
case PhoneNumberPropertyName:
PhoneNumber = reader.GetValue<string>();
break;
case SmsTextPropertyName:
SmsText = reader.GetValue<string>();
break;
}
}
/* Write element metadata to the schema definition during serialization. */
public override void WriteMetaData(DataWriter writer) {
base.WriteMetaData(writer);
writer.WriteValue(PhoneNumberPropertyName, PhoneNumber, string.Empty);
writer.WriteValue(SmsTextPropertyName, SmsText, string.Empty);
}
/* Create a clone of the schema element. */
public override object Clone() {
return new UsrSmsElement(this);
}
/* Create a copy of the element using rebind support for schema references. */
public override object Copy(
Dictionary<Guid, Guid> dictToRebind,
Core.Campaign.CampaignSchema parentSchema
) {
return new UsrSmsElement(this, dictToRebind, parentSchema);
}
/* Create the runtime process flow element that will be executed in the campaign.
Pass metadata values to the executable process element. */
public override ProcessFlowElement CreateProcessFlowElement(
UserConnection userConnection
) {
var executableElement = new UsrSmsCampaignProcessElement {
UserConnection = userConnection,
SmsText = SmsText,
PhoneNumber = PhoneNumber
};
InitializeCampaignProcessFlowElement(executableElement);
return executableElement;
}
}
} -
Click Save and publish.
View the result
-
Click Add → Source code.
-
Fill out the schema properties.
For this example, use the following schema properties.
Property
Property value
Code
UsrSmsEventHandler
Title
SMS handler
-
Set up the connection to the SMS gateway.
For this example, check the connection, account status, and other parameters when validating the campaign, and send a test SMS when starting the campaign.
UsrSmsEventHandlernamespace Terrasoft.Configuration
{
using System;
using Terrasoft.Core.Campaign.EventHandler;
/* Define a custom event handler for the campaign element.
Implement the logic for campaign start and validation events. */
public sealed class UsrSmsEventHandler :
CampaignEventHandlerBase,
IOnCampaignValidate,
IOnCampaignStart
{
/* Handler for the campaign start event. This method is executed
when the campaign starts. */
public void OnStart() {
/* Implement the SMS sending logic.*/
}
/* Handler for the campaign validation event. This method is executed
when the campaign is validated before starting. Use it to check the
SMS gateway connection, account status, and other parameters. */
public void OnValidate() {
try {
/* Implement the SMS gateway connection validation logic. */
} catch (Exception ex) {
/* If validation fails, add the error information to the
campaign schema. */
CampaignSchema.AddValidationInfo(ex.Message);
}
}
}
} -
Click Save and publish.
-
Compile the app. Instructions: Compile the configuration.
-
Clear browser cache.
-
Open the Campaigns section.
-
Create a campaign that has arbitrary parameters. Instructions: Add a campaign (user documentation).
-
Click Edit campaign flow.
-
Add the SMS element to the canvas.
As a result, Creatio will display a custom SMS element of a marketing campaign in the Campaign Designer. You will be able to use the element in the campaign diagram. When the element is selected, Creatio will display its record page. View the result >>>
Source code
- UsrSmsElement
- UsrSmsElementPropertiesPanel
- CampaignElementSchemaManagerEx
- UsrSmsCampaignProcessElement
- UsrSmsElement
- UsrSmsEventHandler
define("UsrSmsElement", ["UsrSmsElementResources",
"CampaignBaseCommunicationSchema"], function(resources) {
Ext.define("Terrasoft.manager.UsrSmsElement", {
/* Parent schema. */
extend: "Terrasoft.CampaignBaseCommunicationSchema",
/* Alternative class name. */
alternateClassName: "Terrasoft.UsrSmsElement",
/* ID of the new campaign element. */
managerItemUId: "a1226f93-f3e3-4baa-89a6-11f2a9ab2d71",
/* Mixins that extend functionality. */
mixins: {
campaignElementMixin: "Terrasoft.CampaignElementMixin"
},
/* Element code. */
name: "Sms",
/* Localizable strings. */
caption: resources.localizableStrings.SmsElementCaption,
titleImage: resources.localizableImages.TitleImage,
largeImage: resources.localizableImages.LargeImage,
smallImage: resources.localizableImages.SmallImage,
/* Schema code of the record page. */
editPageSchemaName: "UsrSmsElementPropertiesPanel",
/* Element type. */
elementType: "Sms",
/* Full name of the class that implements the campaign element logic.
This class saves and reads the element properties from the schema
properties. Since the class is placed in the regular package, use the
"Terrasoft.Configuration.UsrSmsElement, Terrasoft.Configuration"
typeName. If the class is placed in the assembly package, use
typeName: "Terrasoft.Configuration.UsrSmsElement,
SomeAssemblyPackageName" */
typeName: "Terrasoft.Configuration.UsrSmsElement, " +
"Terrasoft.Configuration",
/* CSS styles. */
color: "rgba(249, 160, 27, 1)",
width: 69,
height: 55,
/* Custom element properties. */
smsText: null,
phoneNumber: null,
/* Define the types of outbound connections supported by this element. */
getConnectionUserHandles: function() {
return ["CampaignSequenceFlow", "CampaignConditionalSequenceFlow"];
},
/* Include custom properties in serialization. */
getSerializableProperties: function() {
var baseSerializableProperties = this.callParent(arguments);
return Ext.Array.push(baseSerializableProperties, ["smsText",
"phoneNumber"]);
},
/* Configure the element icons that are displayed on the campaign diagram. */
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.UsrSmsElement;
});
define("UsrSmsElementPropertiesPanel", [], function() {
return {
/* Schema attributes. */
attributes: {
/* Attribute that stores data about the phone number. */
"PhoneNumber": {
"dataValueType": this.Terrasoft.DataValueType.TEXT,
"type": this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN
},
/* Attribute that stores data about the message text. */
"SmsText": {
"dataValueType": this.Terrasoft.DataValueType.TEXT,
"type": this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN
}
},
/* Schema methods. */
methods: {
/* Initialize the module. */
init: function() {
this.callParent(arguments);
this.initAcademyUrl(this.onAcademyUrlInitialized, this);
},
/* Return the context help code for linking to help documentation. */
getContextHelpCode: function() {
return "CampaignSmsElement";
},
/* Initialize the attributes using values from the campaign element schema. */
initParameters: function(element) {
this.callParent(arguments);
this.set("SmsText", element.smsText);
this.set("PhoneNumber", element.phoneNumber);
},
/* Save attribute values back to the campaign element schema. */
saveValues: function() {
this.callParent(arguments);
var element = this.get("ProcessElement");
element.smsText = this.getSmsText();
element.phoneNumber = this.getPhoneNumber();
},
/* Receive the "PhoneNumber" attribute value. */
getPhoneNumber: function() {
var number = this.get("PhoneNumber");
return number ? number : "";
},
/* Receive the "SmsText" attribute value. */
getSmsText: function() {
var smsText = this.get("SmsText");
return smsText ? smsText : "";
}
},
/* The schema view description. */
diff: [
/* The page container. */
{
"operation": "insert",
"name": "ContentContainer",
"propertyName": "items",
"parentName": "EditorsContainer",
"className": "Terrasoft.GridLayoutEdit",
"values": {
"itemType": Terrasoft.ViewItemType.GRID_LAYOUT,
"items": []
}
},
/* The element caption. */
{
"operation": "insert",
"name": "SmsLabel",
"parentName": "ContentContainer",
"propertyName": "items",
"values": {
"layout": {
"column": 0,
"row": 0,
"colSpan": 24
},
"itemType": this.Terrasoft.ViewItemType.LABEL,
"caption": {
"bindTo": "Resources.Strings.SmsText"
},
"classes": {
"labelClass": ["t-title-label-proc"]
}
}
},
/* The caption of the "Text" type field to enter the sender number. */
{
"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"]
}
}
},
/* The "Text" type field to enter the phone number. */
{
"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" }
}
},
/* The caption of the "Text" type field to enter the message text. */
{
"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"
}
}
},
/* The "Text" type field to enter the message text. */
{
"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" }
}
}
]
};
});
require(["CampaignElementSchemaManager", "UsrSmsElement"],
function() {
/* Register the "UsrSmsElement" in the Campaign Designer. */
var coreElementClassNames = Terrasoft.CampaignElementSchemaManager.coreElementClassNames;
/* Add the custom schema to the list of available schemas. */
coreElementClassNames.push({
itemType: "Terrasoft.UsrSmsElement"
});
}
);
namespace Terrasoft.Configuration
{
using Terrasoft.Core.Campaign;
using Terrasoft.Core.DB;
/* Define a custom campaign element. */
public class UsrSmsCampaignProcessElement : CampaignFlowElement
{
public UsrSmsCampaignProcessElement() {
}
/* Assign the "PhoneNumber" attribute value in the class. */
public string PhoneNumber {
get;
set;
}
/* Assign the "SmsText" attribute value in the class. */
public string SmsText {
get;
set;
}
/* Define the campaign audience for the element. */
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));
/* Execute the campaign step logic for the selected audience. */
protected override int SingleExecute(Query audienceQuery) {
return SetItemCompleted(audienceQuery as Select);
}
}
}
namespace Terrasoft.Configuration
{
using System;
using System.Collections.Generic;
using Terrasoft.Common;
using Terrasoft.Core;
using Terrasoft.Core.Campaign;
using Terrasoft.Core.Process;
/* Define the campaign schema element (metadata) for the custom campaign element.
This class describes the element in the campaign schema and handles metadata persistence. */
[DesignModeProperty(
Name = "PhoneNumber",
UsageType = DesignModeUsageType.NotVisible,
MetaPropertyName = PhoneNumberPropertyName
)]
[DesignModeProperty(
Name = "SmsText",
UsageType = DesignModeUsageType.NotVisible,
MetaPropertyName = SmsTextPropertyName
)]
public class UsrSmsElement : CampaignSchemaElement
{
/* Constants for property names used in metadata serialization. */
private const string PhoneNumberPropertyName = "PhoneNumber";
private const string SmsTextPropertyName = "SmsText";
public UsrSmsElement() {
ElementType = CampaignSchemaElementType.AsyncTask;
}
/* Default constructor: defines the element type as an async task. */
public UsrSmsElement(UsrSmsElement source) : this(source, null, null) {
}
/* Copy constructors for cloning the element in schema operations. */
public UsrSmsElement(
UsrSmsElement source,
Dictionary<Guid, Guid> dictToRebind,
Core.Campaign.CampaignSchema parentSchema
) : base(source, dictToRebind, parentSchema) {
ElementType = source.ElementType;
PhoneNumber = source.PhoneNumber;
SmsText = source.SmsText;
}
/* Define the campaign log action type associated with this element. */
protected override Guid Action {
get {
return CampaignConsts.CampaignLogTypeMailing;
}
}
[MetaTypeProperty("{A67950E7-FFD7-483D-9E67-3C9A30A733C0}")]
/* Assign the "PhoneNumber" attribute value in the class. */
public string PhoneNumber {
get;
set;
}
[MetaTypeProperty("{05F86DF2-B9FB-4487-B7BE-F3955703527C}")]
/* Assign the "SmsText" attribute value in the class. */
public string SmsText {
get;
set;
}
/* Read element metadata from the schema definition during deserialization. */
protected override void ApplyMetaDataValue(DataReader reader) {
base.ApplyMetaDataValue(reader);
switch (reader.CurrentName) {
case PhoneNumberPropertyName:
PhoneNumber = reader.GetValue<string>();
break;
case SmsTextPropertyName:
SmsText = reader.GetValue<string>();
break;
}
}
/* Write element metadata to the schema definition during serialization. */
public override void WriteMetaData(DataWriter writer) {
base.WriteMetaData(writer);
writer.WriteValue(PhoneNumberPropertyName, PhoneNumber, string.Empty);
writer.WriteValue(SmsTextPropertyName, SmsText, string.Empty);
}
/* Create a clone of the schema element. */
public override object Clone() {
return new UsrSmsElement(this);
}
/* Create a copy of the element using rebind support for schema references. */
public override object Copy(
Dictionary<Guid, Guid> dictToRebind,
Core.Campaign.CampaignSchema parentSchema
) {
return new UsrSmsElement(this, dictToRebind, parentSchema);
}
/* Create the runtime process flow element that will be executed in the campaign.
Pass metadata values to the executable process element. */
public override ProcessFlowElement CreateProcessFlowElement(
UserConnection userConnection
) {
var executableElement = new UsrSmsCampaignProcessElement {
UserConnection = userConnection,
SmsText = SmsText,
PhoneNumber = PhoneNumber
};
InitializeCampaignProcessFlowElement(executableElement);
return executableElement;
}
}
}
namespace Terrasoft.Configuration
{
using System;
using Terrasoft.Core.Campaign.EventHandler;
/* Define a custom event handler for the campaign element.
Implement the logic for campaign start and validation events. */
public sealed class UsrSmsEventHandler :
CampaignEventHandlerBase,
IOnCampaignValidate,
IOnCampaignStart
{
/* Handler for the campaign start event. This method is executed
when the campaign starts. */
public void OnStart() {
/* Implement the SMS sending logic.*/
}
/* Handler for the campaign validation event. This method is executed
when the campaign is validated before starting. Use it to check the
SMS gateway connection, account status, and other parameters. */
public void OnValidate() {
try {
/* Implement the SMS gateway connection validation logic. */
} catch (Exception ex) {
/* If validation fails, add the error information to the
campaign schema. */
CampaignSchema.AddValidationInfo(ex.Message);
}
}
}
}