Overview
An SMS campaign is a form of marketing that allows you to interact with your customers via text. It is faster and easier to create since it requires no creative other than an initial campaign to get your customers’ numbers, and your 160 character message
There are two different kinds of SMS Campaigns
- Promotional
- Transactional
Promotional SMS campaigns can be used to reach out more than one client. For example If organization wants promote some product or organization wants to give heads up for their loan repayment dates. Transactional SMS campaigns can be used to reach out a targeted client. For example message about loan repayment successful or message about CR/DR transactions on client's savings account.
In fineract, promotional SMS campaigns are further divided into two groups.
- Direct - If organization wants to send an SMS one time, it has to create Direct SMS Campaigns
- Scheduled - If organization wants to send an SMS recurrently, then it has to create Scheduled SMS Campaigns
High Level Component Diagram
Requirements/User Stories
# | Title | User Story | Notes |
---|---|---|---|
1 | Create SMS Campaign | As a user I should be able to create DIRECT SMS Campaign | |
2 | Update SMS Campaign | As a user I should be able to update message in SMS Campaign | |
3 | Activate SMS Campaign | As a user I should be able to activate SMS Campaigns | |
4 | Close SMS Campaign | As a user I should be able to close/deactivate SMS Campaign | |
5 | Reactivate SMS Campaign | As a user I should be able to reactivate already closed SMS Campagin | |
6 | Schedule job configuration | As a user I should be able to configure schedule job to send direct and scheduled SMS campaigns | |
7 | Schedule job configuration | As a user I should be able to configure schedule job to receive SMS delivery report | |
8 | Transactional SMS | As a user I should have a support for transactional SMS when loan is approved, loan rejected, loan repayment is done, client is activated, client is rejected, savings account is activated, savings account is rejected, amount is deposited from savings account, amount is withdrawn from savings account |
Business Rule
While creating an SMS campaign, user has to attach a business rule which is nothing but a stretchy report from the platform. This business rule will be used to filter the clients. The template parameters associated to each business rule can be used to format a message for the SMS campaign. The business rules are divided into two categories.
- Triggered - For transactional messages
- Non-Triggered - For Promotional messages
Users are free to add new SMS (Non-Triggered) type stretchy reports to support their requirements. These newly added stretchy reports can be attached while creating Direct, Scheduled SMS Campaigns and should not be attached to Triggered SMS Campaigns. We are going to support following trigger type business rules.
- Client Activated - Should be used to send SMS on client activation
- Client Rejected - Should be used to send SMS on client rejection
- Loan Approved - Should be used to send SMS on loan approval
- Loan Rejected - Should be used to send SMS on loan rejection
- Loan Repayment - Should be used to send SMS on loan repayment
- Savings Activated - Should be used to send SMS on savings account activation
- Savings Rejected - Should be used to send SMS on savings account rejection
- Savings Withdrawal - Should be used to send SMS on amount withdrawal from savings account
- Savings Deposit - Should be used to send SMS on amount deposit in savings account
Functionality Enhancements
DB Schema
We need to add two tables to store SMS Campaign details and Outbound message details. The tables are described below.
sms_campaign
Name | Datatype | Length | Remarks | Description |
---|---|---|---|---|
id | BIGINT | 20 | PRIMARY KEY & AUTO INCREMENT | |
campaign_name | VARCHAR | 100 | NOT NULL | |
campaign_type | INT | 3 | NOT NULL | by default SMS. In future it can be used for MAIL |
campaign_trigger_type | INT | 3 | NOT NULL | DIRECT / SCHEDULED / TRIGGERED |
report_id | INT | 5 | NOT NULL | Business rule ID |
provider_id | INT | 20 | NOT NULL | SMS gateway bridge Identifier |
param_value | VARCHAR | TEXT | NULL | Business rule parameters |
status_enum | INT | 3 | NOT NULL | PENDING(100), ACTIVE(300), CLOSED(600) |
message | TEXT | NOT NULL | Parameterized message | |
submittedon_date | DATE | NOT NULL | ||
submittedon_userid | BIGINT | 20 | NOT NULL | Created user id |
approvedon_date | DATE | NULL DEFAULT NULL | ||
approvedon_userid | BIGINT | 20 | NULL DEFAULT NULL | Approved user id |
closedon_date | DATE | NULL DEFAULT NULL | ||
closedon_userid | BIGINT | 20 | NULL DEFAULT NULL | |
recurrence | VARCHAR | 100 | NULL DEFAULT NULL | For scheduled campaigns, this value defines the recurrence details |
next_trigger_date | DATETIME | NULL DEFAULT NULL | Date on which SMS is sent again | |
last_trigger_date | DATETIME | NULL DEFAULT NULL | Date on which SMS was sent last time | |
recurrence_start_date | DATETIME | NULL DEFAULT NULL | ||
is_visible | TINYINT | 1 | NULL DEFAULT '1' | Soft delete |
sms_messages_outbound
Name | Datatype | Length | Remarks | Description |
---|---|---|---|---|
id | BIGINT | 20 | PRIMARY KEY & AUTO INCREMENT | |
group_id | BIGINT | 20 | NULL DEFAULT NULL | |
client_id | BIGINT | 20 | NULL DEFAULT NULL | |
staff_id | BIGINT | 20 | NULL DEFAULT NULL | |
status_enum | INT | 5 | NOT NULL DEFAULT '100' | |
mobile_no | VARCHAR | 20 | NOT NULL | |
message | VARCHAR | 1024 | NOT NULL | |
campaign_id | BIGINT | 20 | NOT NULL & FOREIGN KEY | |
external_id | VARCHAR | 100 | NULL DEFAULT NULL | |
submittedon_date | DATETIME | NOT NULL | ||
delivered_on_date | DATETIME | NULL DEFAULT NULL |
Changes/Enhancements to Batch Jobs
We have to define 3 new jobs.
- Send messages to SMS gateway -> Send all pending DIRECT and SCHEDULED SMS messages to message gateway
- Update Sms Outbound with campaign message -> Create and save SMS outbound messages for all schedule campaigns
- Get delivery reports from SMS gateway -> Get delivery reports for all SENT messages
User interaction and design
- Create SMS Campaign - Wizard implementation
Rest API(s)
Create SMS Campaign : https://Domain Name/api/v1/smscampaigns
- Method: POST
- Headers:
- Fineract-Platform-TenantId:abcd
- Fineract-Tenant-App-Key:tenantAppKey
Content-Type:
application/json
Request Body:
{"campaignName": "Savings Deposit Campaign", "campaignType": "SMS", "triggerType": 3, "providerId": 2, "runReportId": 180, "paramValue": "{"officeId":1,"loanOfficerId":-1,"transactionId":1,"reportName":"Savings Deposit"}", "message": "Hello {fullName} your account is credited with {depositAmount} on {transactionDate}"
}
- Response: {"resourceId": 1 }
Update message in existing SMS Campaign : https://Domain Name/api/v1/smscampaigns/{campaignId}
{campaignId}
- Method: PUT
- Headers:
- Fineract-Platform-TenantId:abcd
- Fineract-Tenant-App-Key:tenantAppKey
- Content-Type:
application/json
Request
Body: {"message": "Hello your savings account {savingsAccountNo} debited with {withdrawAmount}"
}- Response: {
"resourceId": 1, "changes": { "message": "Hello your savings account {savingsAccountNo} debited with {withdrawAmount}" }
}
Delete existing SMS Campaign:https://DomainName/api/v1/smscampaigns/{campaignId}
- Method: DELETE
- Headers:
- Fineract-Platform-TenantId:abcd
- Fineract-Tenant-App-Key:tenantAppKey
- Content-Type: application/json
- Request Body: N/A
- Response: {
"resourceId": 1, "changes": {}
}
Get list of SMS Campaigns: https://Domain Name/api/v1/smscampaigns
- Method: GET
- Headers:
- Fineract-Platform-TenantId:abcd
- Fineract-Tenant-App-Key:tenantAppKey
- Content-Type: application/json
- Request Body: N/A
- Response:
[{ "id": 1,
"campaignName": "Savings Deposit Campaign",
"campaignType": "SMS",
"triggerType": 3,
"providerId": 2,
"runReportId": 180,
"reportName" : "Savings Deposit",
"paramValue": "{"officeId":1,"loanOfficerId":-1,"transactionId":1,"reportName":"Savings Deposit"}",
"message": "Hello {fullName} your account is credited with {depositAmount} on {transactionDate}",
"status" : { "id":"","code":"","value":""}
}]
Retrieve One SMS Campaign: https://Domain Name/api/v1/smscampaigns/{campaignId}
- Method: GET
- Headers:
- Fineract-Platform-TenantId:abcd
- Fineract-Tenant-App-Key:tenantAppKey
- Content-Type: application/json
- Request Body: N/A
- Response:
{ "id": 1,
"campaignName": "Savings Deposit Campaign",
"campaignType": "SMS",
"triggerType": 3,
"providerId": 2,
"runReportId": 180,
"reportName" : "Savings Deposit",
"paramValue": "{"officeId":1,"loanOfficerId":-1,"transactionId":1,"reportName":"Savings Deposit"}",
"message": "Hello {fullName} your account is credited with {depositAmount} on {transactionDate}",
"status" : { "id":"","code":"","value":""}
}
In case of Scheduled Campaign
{ "id": 1, "campaignName": "Savings Deposit Campaign" "campaignType": "SMS", "triggerType": 3, "providerId": 2, "runReportId": 180, "reportName" : "Savings Deposit", "paramValue": "{"officeId":1,"loanOfficerId":-1,"transactionId":1,"reportName":"Savings Deposit"}", "message": "Hello {fullName} your account is credited with {depositAmount} on {transactionDate}", "status" : { "id":"","code":"","value":""}, "nextTriggerDate": "22 Jan 2017", "lastTriggerDate": "22 Jan 2016", "recurrenceStartDate":"22 Jan 2016", "recurrence": "YEARLY" }
Activate SMS Campaign: https://Domain Name/api/v1/smscampaigns/{campaignId}?command=activate
- Method: POST
- Headers:
- Fineract-Platform-TenantId:abcd
- Fineract-Tenant-App-Key:tenantAppKey
- Content-Type: application/json
- Request Body:
{ "activationDate":"01 May 2016", "locale":"en", "dateFormat":"dd MMMM yyyy" }
- Response:
{"resourceId": 1, "changes": { "status": { "id": 300, "code": "smsCampaignStatus.active", "value": "active", }, "locale": "en", "dateFormat": "dd MMMM yyyy", "activationDate": "01 May 2016" }
Deactivate SMS Campaign: https://Domain Name/api/v1/smscampaigns/{campaignId}?command=close
- Method: POST
- Headers:
- Fineract-Platform-TenantId:abcd
- Fineract-Tenant-App-Key:tenantAppKey
- Content-Type: application/json
- Request Body:
{ "
closureDate
":"01 May 2016", "locale":"en", "dateFormat":"dd MMMM yyyy" } - Response:
{"resourceId": 1, "changes": { "status": { "id": 600, "code": "smsCampaignStatus.closed
", "value": "closed
", }, "locale": "en", "dateFormat": "dd MMMM yyyy", "closureDate
": "01 May 2016" }
Reactivates SMS Campaign: https://Domain Name/api/v1/smscampaigns/{campaignId}?command=reactivate
- Method: POST
- Headers:
- Fineract-Platform-TenantId:abcd
- Fineract-Tenant-App-Key:tenantAppKey
- Content-Type: application/json
- Request Body:
{ "
activationDate
":"01 May 2016", "locale":"en", "dateFormat":"dd MMMM yyyy" } - Response:
{"resourceId": 1, "changes": { "status": { "id": 300, "code": "smsCampaignStatus.active
", "value": "active
", }, "locale": "en", "dateFormat": "dd MMMM yyyy", "activationDate
": "01 May 2016" }
Message Gateway
Message gateway is independent deployable component which is having support for Twilio and Infobip SMS providers.
Note: Message-Gateway is not bundled with Apache Fineract. You need to download the source code, build and run it separately.
Rest API(s)
Create a tenant: http://hostName:9191/tenants/
- Method: POST
- Content-Type: application/json
- Request Body:
"tenantId":"default" , "description": "Some description"{
}
- Response:
{"123456543234abdkdkdkd"}
On tenant creation, it will return a unique app key (passphrase). This key should be used as header parameter on subsequent requests
Create an SMS bridge: http://localhost:9191/smsbridges
- Method: POST
- Headers:
- Fineract-Platform-TenantId:abcd
- Fineract-Tenant-App-Key:tenantAppKey
- Content-Type: application/json
- Request Body:
{
"phoneNo": "+xxxxxxxxxx",
"providerName": "Twilio SMS Provider",
"providerDescription": "Twilio SMS Provider",
"providerKey":"Twilio",
"countryCode":"+91",
"bridgeConfigurations": [
{"configName":"Provider_Account_Id",
"configValue":"username/account id"},
{"configName":"Provider_Auth_Token",
"configValue":"accountkey/passphrase"}]}
- Response:
{1}
Note: While creating a SMS bridge providerKey should be either 'Twilio' or 'InfoBip'
Send SMS: http://localhost:9191/sms/
- Method: POST
- Headers:
- Fineract-Platform-TenantId:abcd
- Fineract-Tenant-App-Key:tenantAppKey
- Content-Type: application/json
- Request Body:
[{
"internalId":"55",
"mobileNumber":"+xxxxxxxxxxxx",
"message":"Hello from Staging",
"providerId":"2"
}]
- Response: Response Status ACCEPTED
DB Schema
m_tenants - This table is used to save tenant id, tenant app key
Name | Datatype | Length | Remarks |
---|---|---|---|
id | BIGINT | 20 | PRIMARY KEY & AUTO INCREMENT |
tenant_id | VARCHAR | 32 | NOT NULL |
tenant_app_key | VARCHAR | 100 | NOT NULL |
description | VARCHAR | 500 | NULL DEFAULT NULL |
m_sms_bridge - This table is used to save Provider details for a tenant
Name | Datatype | Length | Remarks |
---|---|---|---|
id | BIGINT | 20 | PRIMARY KEY & AUTO INCREMENT |
tenant_id | BIGINT | 20 | NOT NULL & FOREIGN KEY |
tenant_phone_no | VARCHAR | 20 | NOT NULL |
country_code | VARCHAR | 5 | NOT NULL |
provider_name | VARCHAR | 100 | NOT NULL |
provider_key | VARCHAR | 100 | NOT NULL |
description | VARCHAR | 200 | NULL DEFAULT NULL |
created_on | TIMESTAMP | NULL DEFAULT NULL | |
last_modified_on | TIMESTAMP | NULL DEFAULT NULL |
m_sms_bridge_configuration - This table is used to save provider account confiuration
Name | Datatype | Length | Remarks |
---|---|---|---|
id | BIGINT | 20 | PRIMARY KEY & AUTO INCREMENT |
sms_bridge_id | BIGINT | 20 | NOT NULL |
config_name | VARCHAR | 100 | NOT NULL |
config_value | VARCHAR | 100 | NOT NULL |
m_outbound_messages - This table is used to save all outbound short messages
Name | Datatype | Length | Remarks |
---|---|---|---|
id | BIGINT | 20 | PRIMARY KEY & AUTO INCREMENT |
tenant_id | VARCHAR | 32 | NOT NULL & FOREIGN KEY |
external_id | VARCHAR | 100 | NULL DEFAULT NULL |
internal_id | VARCHAR | 100 | NOT NULL |
delivery_error_message | VARCHAR | 500 | NULL DEFAULT NULL |
source_address | VARCHAR | 100 | NULL DEFAULT NULL |
sms_bridge_id | BIGINT | 20 | NOT NULL |
mobile_number | VARCHAR | 20 | NOT NULL |
message | VARCHAR | 4096 | NOT NULL |
delivery_status | INT | 3 | NOT NULL |
submitted_on_date | TIMESTAMP | NOT NULL DEFAULT CURRENT_TIMESTAMP | |
delivered_on_date | TIMESTAMP | NULL DEFAULT NULL |