Merge pull request #142 from Focuslinkstech/Development
bulk SMS/WA message improvement
This commit is contained in:
commit
11d97c153f
@ -95,124 +95,144 @@ EOT;
|
|||||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent', 'Sales'])) {
|
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent', 'Sales'])) {
|
||||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||||
}
|
}
|
||||||
$ui->display('message-bulk.tpl');
|
|
||||||
break;
|
|
||||||
case 'send_bulk-post':
|
|
||||||
// Check user permissions
|
|
||||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent', 'Sales'])) {
|
|
||||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get form data
|
// Get form data
|
||||||
$group = $_POST['group'];
|
$group = $_POST['group'];
|
||||||
$message = $_POST['message'];
|
$message = $_POST['message'];
|
||||||
$via = $_POST['via'];
|
$via = $_POST['via'];
|
||||||
|
$test = isset($_POST['test']) && $_POST['test'] === 'on' ? 'yes' : 'no';
|
||||||
|
$batch = $_POST['batch'];
|
||||||
|
$delay = $_POST['delay'];
|
||||||
|
|
||||||
// Initialize counters
|
// Initialize counters
|
||||||
$successCount = 0;
|
$totalSMSSent = 0;
|
||||||
$failCount = 0;
|
$totalSMSFailed = 0;
|
||||||
$successMessages = [];
|
$totalWhatsappSent = 0;
|
||||||
$failMessages = [];
|
$totalWhatsappFailed = 0;
|
||||||
|
$batchStatus = [];
|
||||||
|
|
||||||
// Check if fields are empty
|
if (_req('send') == 'now') {
|
||||||
if ($group == '' or $message == '' or $via == '') {
|
// Check if fields are empty
|
||||||
r2(U . 'message/send_bulk', 'e', Lang::T('All fields are required'));
|
if ($group == '' || $message == '' || $via == '') {
|
||||||
} else {
|
r2(U . 'message/send_bulk', 'e', Lang::T('All fields are required'));
|
||||||
// Get customer details from the database based on the selected group
|
|
||||||
if ($group == 'all') {
|
|
||||||
$customers = ORM::for_table('tbl_customers')->find_many();
|
|
||||||
} elseif ($group == 'new') {
|
|
||||||
// Get customers created just a month ago
|
|
||||||
$customers = ORM::for_table('tbl_customers')->where_raw("DATE(created_at) >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)")->find_many();
|
|
||||||
} elseif ($group == 'expired') {
|
|
||||||
// Get expired user recharges where status is 'off'
|
|
||||||
$expired = ORM::for_table('tbl_user_recharges')->where('status', 'off')->find_many();
|
|
||||||
$customer_ids = [];
|
|
||||||
foreach ($expired as $recharge) {
|
|
||||||
$customer_ids[] = $recharge->customer_id;
|
|
||||||
}
|
|
||||||
$customers = ORM::for_table('tbl_customers')->where_in('id', $customer_ids)->find_many();
|
|
||||||
} elseif ($group == 'active') {
|
|
||||||
// Get active user recharges where status is 'on'
|
|
||||||
$active = ORM::for_table('tbl_user_recharges')->where('status', 'on')->find_many();
|
|
||||||
$customer_ids = [];
|
|
||||||
foreach ($active as $recharge) {
|
|
||||||
$customer_ids[] = $recharge->customer_id;
|
|
||||||
}
|
|
||||||
$customers = ORM::for_table('tbl_customers')->where_in('id', $customer_ids)->find_many();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop through customers and send messages
|
|
||||||
foreach ($customers as $customer) {
|
|
||||||
// Create a copy of the original message for each customer and save it as currentMessage
|
|
||||||
$currentMessage = $message;
|
|
||||||
|
|
||||||
// Replace placeholders in the message with actual values for each customer
|
|
||||||
$currentMessage = str_replace('[[name]]', $customer['fullname'], $currentMessage);
|
|
||||||
$currentMessage = str_replace('[[user_name]]', $customer['username'], $currentMessage);
|
|
||||||
$currentMessage = str_replace('[[phone]]', $customer['phonenumber'], $currentMessage);
|
|
||||||
$currentMessage = str_replace('[[company_name]]', $config['CompanyName'], $currentMessage);
|
|
||||||
|
|
||||||
// Send the message based on the selected method
|
|
||||||
if ($via == 'sms' || $via == 'both') {
|
|
||||||
$smsSent = Message::sendSMS($customer['phonenumber'], $currentMessage);
|
|
||||||
if ($smsSent) {
|
|
||||||
$successCount++;
|
|
||||||
$successMessages[] = "SMS sent to {$customer['fullname']}: {$customer['phonenumber']}";
|
|
||||||
} else {
|
|
||||||
$failCount++;
|
|
||||||
$failMessages[] = "Failed to send SMS to {$customer['fullname']}: {$customer['phonenumber']}";
|
|
||||||
}
|
|
||||||
// Introduce a delay of 5 seconds between each SMS
|
|
||||||
sleep(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($via == 'wa' || $via == 'both') {
|
|
||||||
$waSent = Message::sendWhatsapp($customer['phonenumber'], $currentMessage);
|
|
||||||
if ($waSent) {
|
|
||||||
$successCount++;
|
|
||||||
$successMessages[] = "WhatsApp message sent to {$customer['fullname']}: {$customer['phonenumber']}";
|
|
||||||
} else {
|
|
||||||
$failCount++;
|
|
||||||
$failMessages[] = "Failed to send WhatsApp message to {$customer['fullname']}: {$customer['phonenumber']}";
|
|
||||||
}
|
|
||||||
// Introduce a delay of 5 seconds between each WhatsApp message
|
|
||||||
sleep(5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$responseMessage = '';
|
|
||||||
|
|
||||||
if ($successCount > 0) {
|
|
||||||
$responseMessage .= "Messages Sent Successfully: {$successCount}<br>";
|
|
||||||
$responseMessage .= "<ul>";
|
|
||||||
foreach ($successMessages as $successMessage) {
|
|
||||||
$responseMessage .= "<li>{$successMessage}</li>";
|
|
||||||
}
|
|
||||||
$responseMessage .= "</ul>";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($failCount > 0) {
|
|
||||||
$responseMessage .= "Failed to send messages: {$failCount}<br>";
|
|
||||||
$responseMessage .= "<ul>";
|
|
||||||
foreach ($failMessages as $failMessage) {
|
|
||||||
$responseMessage .= "<li>{$failMessage}</li>";
|
|
||||||
}
|
|
||||||
$responseMessage .= "</ul>";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($responseMessage != '') {
|
|
||||||
r2(U . 'message/send_bulk', 's', $responseMessage);
|
|
||||||
} else {
|
} else {
|
||||||
r2(U . 'message/send_bulk', 'e', Lang::T('No messages sent'));
|
// Get customer details from the database based on the selected group
|
||||||
|
if ($group == 'all') {
|
||||||
|
$customers = ORM::for_table('tbl_customers')->find_many()->as_array();
|
||||||
|
} elseif ($group == 'new') {
|
||||||
|
// Get customers created just a month ago
|
||||||
|
$customers = ORM::for_table('tbl_customers')->where_raw("DATE(created_at) >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)")->find_many()->as_array();
|
||||||
|
} elseif ($group == 'expired') {
|
||||||
|
// Get expired user recharges where status is 'off'
|
||||||
|
$expired = ORM::for_table('tbl_user_recharges')->where('status', 'off')->find_many();
|
||||||
|
$customer_ids = [];
|
||||||
|
foreach ($expired as $recharge) {
|
||||||
|
$customer_ids[] = $recharge->customer_id;
|
||||||
|
}
|
||||||
|
$customers = ORM::for_table('tbl_customers')->where_in('id', $customer_ids)->find_many()->as_array();
|
||||||
|
} elseif ($group == 'active') {
|
||||||
|
// Get active user recharges where status is 'on'
|
||||||
|
$active = ORM::for_table('tbl_user_recharges')->where('status', 'on')->find_many();
|
||||||
|
$customer_ids = [];
|
||||||
|
foreach ($active as $recharge) {
|
||||||
|
$customer_ids[] = $recharge->customer_id;
|
||||||
|
}
|
||||||
|
$customers = ORM::for_table('tbl_customers')->where_in('id', $customer_ids)->find_many()->as_array();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the batch size
|
||||||
|
$batchSize = $batch;
|
||||||
|
|
||||||
|
// Calculate the number of batches
|
||||||
|
$totalCustomers = count($customers);
|
||||||
|
$totalBatches = ceil($totalCustomers / $batchSize);
|
||||||
|
|
||||||
|
// Loop through batches
|
||||||
|
for ($batchIndex = 0; $batchIndex < $totalBatches; $batchIndex++) {
|
||||||
|
// Get the starting and ending index for the current batch
|
||||||
|
$start = $batchIndex * $batchSize;
|
||||||
|
$end = min(($batchIndex + 1) * $batchSize, $totalCustomers);
|
||||||
|
$batchCustomers = array_slice($customers, $start, $end - $start);
|
||||||
|
|
||||||
|
// Loop through customers in the current batch and send messages
|
||||||
|
foreach ($batchCustomers as $customer) {
|
||||||
|
// Create a copy of the original message for each customer and save it as currentMessage
|
||||||
|
$currentMessage = $message;
|
||||||
|
$currentMessage = str_replace('[[name]]', $customer['fullname'], $currentMessage);
|
||||||
|
$currentMessage = str_replace('[[user_name]]', $customer['username'], $currentMessage);
|
||||||
|
$currentMessage = str_replace('[[phone]]', $customer['phonenumber'], $currentMessage);
|
||||||
|
$currentMessage = str_replace('[[company_name]]', $config['CompanyName'], $currentMessage);
|
||||||
|
|
||||||
|
// Send the message based on the selected method
|
||||||
|
if ($test === 'yes') {
|
||||||
|
// Only for testing, do not send messages to customers
|
||||||
|
$batchStatus[] = [
|
||||||
|
'name' => $customer['fullname'],
|
||||||
|
'phone' => $customer['phonenumber'],
|
||||||
|
'message' => $currentMessage,
|
||||||
|
'status' => 'Test Mode - Message not sent'
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
// Send the actual messages
|
||||||
|
if ($via == 'sms' || $via == 'both') {
|
||||||
|
$smsSent = Message::sendSMS($customer['phonenumber'], $currentMessage);
|
||||||
|
if ($smsSent) {
|
||||||
|
$totalSMSSent++;
|
||||||
|
$batchStatus[] = [
|
||||||
|
'name' => $customer['fullname'],
|
||||||
|
'phone' => $customer['phonenumber'],
|
||||||
|
'message' => $currentMessage,
|
||||||
|
'status' => 'SMS Message Sent'
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$totalSMSFailed++;
|
||||||
|
$batchStatus[] = [
|
||||||
|
'name' => $customer['fullname'],
|
||||||
|
'phone' => $customer['phonenumber'],
|
||||||
|
'message' => $currentMessage,
|
||||||
|
'status' => 'SMS Message Failed'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($via == 'wa' || $via == 'both') {
|
||||||
|
$waSent = Message::sendWhatsapp($customer['phonenumber'], $currentMessage);
|
||||||
|
if ($waSent) {
|
||||||
|
$totalWhatsappSent++;
|
||||||
|
$batchStatus[] = [
|
||||||
|
'name' => $customer['fullname'],
|
||||||
|
'phone' => $customer['phonenumber'],
|
||||||
|
'message' => $currentMessage,
|
||||||
|
'status' => 'WhatsApp Message Sent'
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$totalWhatsappFailed++;
|
||||||
|
$batchStatus[] = [
|
||||||
|
'name' => $customer['fullname'],
|
||||||
|
'phone' => $customer['phonenumber'],
|
||||||
|
'message' => $currentMessage,
|
||||||
|
'status' => 'WhatsApp Message Failed'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Introduce a delay between each batch
|
||||||
|
if ($batchIndex < $totalBatches - 1) {
|
||||||
|
sleep($delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$ui->assign('batchStatus', $batchStatus);
|
||||||
|
$ui->assign('totalSMSSent', $totalSMSSent);
|
||||||
|
$ui->assign('totalSMSFailed', $totalSMSFailed);
|
||||||
|
$ui->assign('totalWhatsappSent', $totalWhatsappSent);
|
||||||
|
$ui->assign('totalWhatsappFailed', $totalWhatsappFailed);
|
||||||
|
$ui->display('message-bulk.tpl');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
r2(U . 'message/send_sms', 'e', 'action not defined');
|
r2(U . 'message/send_sms', 'e', 'action not defined');
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
{include file="sections/header.tpl"}
|
{include file="sections/header.tpl"}
|
||||||
|
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.11.3/css/jquery.dataTables.min.css">
|
||||||
|
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12 col-md-12">
|
<div class="col-sm-12 col-md-12">
|
||||||
<div class="panel panel-primary panel-hovered panel-stacked mb30">
|
<div class="panel panel-primary panel-hovered panel-stacked mb30">
|
||||||
<div class="panel-heading">{Lang::T('Send Bulk Message')}</div>
|
<div class="panel-heading">{Lang::T('Send Bulk Message')}</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<form class="form-horizontal" method="post" role="form" action="{$_url}message/send_bulk-post">
|
<form class="form-horizontal" method="post" role="form" id="bulkMessageForm" action="">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-2 control-label">{Lang::T('Group')}</label>
|
<label class="col-md-2 control-label">{Lang::T('Group')}</label>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
@ -27,11 +29,39 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('Message per time')}</label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<select class="form-control" name="batch" id="batch">
|
||||||
|
<option value="5">{Lang::T('5 Messages')}</option>
|
||||||
|
<option value="10" selected>{Lang::T('10 Messages')}</option>
|
||||||
|
<option value="15">{Lang::T('15 Messages')}</option>
|
||||||
|
<option value="20">{Lang::T('20 Messages')}</option>
|
||||||
|
<option value="20">{Lang::T('30 Messages')}</option>
|
||||||
|
<option value="20">{Lang::T('40 Messages')}</option>
|
||||||
|
<option value="20">{Lang::T('50 Messages')}</option>
|
||||||
|
<option value="20">{Lang::T('60 Messages')}</option>
|
||||||
|
</select>{Lang::T('Use 20 and above if you are sending to all customers to avoid server time out')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('Delay')}</label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<select class="form-control" name="delay" id="delay">
|
||||||
|
<option value="0" selected>{Lang::T('No Delay')}</option>
|
||||||
|
<option value="5">{Lang::T('5 Seconds')}</option>
|
||||||
|
<option value="10">{Lang::T('10 Seconds')}</option>
|
||||||
|
<option value="15">{Lang::T('15 Seconds')}</option>
|
||||||
|
<option value="20">{Lang::T('20 Seconds')}</option>
|
||||||
|
</select>{Lang::T('Use at least 5 secs if you are sending to all customers to avoid being banned by your message provider')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-2 control-label">{Lang::T('Message')}</label>
|
<label class="col-md-2 control-label">{Lang::T('Message')}</label>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<textarea class="form-control" id="message" name="message"
|
<textarea class="form-control" id="message" name="message"
|
||||||
placeholder="{Lang::T('Compose your message...')}" rows="5"></textarea>
|
placeholder="{Lang::T('Compose your message...')}" rows="5"></textarea>
|
||||||
|
<input name="test" type="checkbox"> {Lang::T('Testing [if checked no real message is sent]')}
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block col-md-4">
|
<p class="help-block col-md-4">
|
||||||
{Lang::T('Use placeholders:')}
|
{Lang::T('Use placeholders:')}
|
||||||
@ -45,10 +75,10 @@
|
|||||||
<b>[[company_name]]</b> - {Lang::T('Your Company Name')}
|
<b>[[company_name]]</b> - {Lang::T('Your Company Name')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-lg-offset-2 col-lg-10">
|
<div class="col-lg-offset-2 col-lg-10">
|
||||||
<button class="btn btn-success" type="submit">{Lang::T('Send Message')}</button>
|
<button class="btn btn-success" type="submit" name=send value=now>
|
||||||
|
{Lang::T('Send Message')}</button>
|
||||||
<a href="{$_url}dashboard" class="btn btn-default">{Lang::T('Cancel')}</a>
|
<a href="{$_url}dashboard" class="btn btn-default">{Lang::T('Cancel')}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -59,5 +89,54 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{if $batchStatus}
|
||||||
|
<p><span class="label label-success">Total SMS Sent: {$totalSMSSent}</span> <span class="label label-danger">Total SMS
|
||||||
|
Failed: {$totalSMSFailed}</span> <span class="label label-success">Total WhatsApp Sent:
|
||||||
|
{$totalWhatsappSent}</span> <span class="label label-danger">Total WhatsApp Failed:
|
||||||
|
{$totalWhatsappFailed}</span></p>
|
||||||
|
{/if}
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header">
|
||||||
|
<h3 class="box-title">Message Results</h3>
|
||||||
|
</div>
|
||||||
|
<!-- /.box-header -->
|
||||||
|
<div class="box-body">
|
||||||
|
<table id="messageResultsTable" class="table table-bordered table-striped table-condensed">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Phone</th>
|
||||||
|
<th>Message</th>
|
||||||
|
<th>Status</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{foreach $batchStatus as $customer}
|
||||||
|
<tr>
|
||||||
|
<td>{$customer.name}</td>
|
||||||
|
<td>{$customer.phone}</td>
|
||||||
|
<td>{$customer.message}</td>
|
||||||
|
<td>{$customer.status}</td>
|
||||||
|
</tr>
|
||||||
|
{/foreach}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!-- /.box-body -->
|
||||||
|
</div>
|
||||||
|
<!-- /.box -->
|
||||||
|
|
||||||
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
|
<script src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js"></script>
|
||||||
|
<script>
|
||||||
|
var $j = jQuery.noConflict();
|
||||||
|
|
||||||
|
$j(document).ready(function () {
|
||||||
|
$j('#messageResultsTable').DataTable();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{include file="sections/footer.tpl"}
|
{include file="sections/footer.tpl"}
|
Loading…
x
Reference in New Issue
Block a user