Initial commit

This commit is contained in:
2025-01-13 19:14:18 +00:00
commit 2889314a6c
20 changed files with 1914 additions and 0 deletions

140
assets/js/hubtel_sms.js Normal file
View File

@ -0,0 +1,140 @@
// Initialize components on document ready
$(function() {
// Initialize tooltips
$('[data-toggle="tooltip"]').tooltip();
// Initialize select2 for dropdowns
$('.select2').select2();
// Initialize client groups select2
$('#client_groups').select2({
placeholder: app.lang.select_client_groups,
allowClear: true
});
// Handle message character count
function updateCharCount(textarea, charCount, msgCount) {
var chars = $(textarea).val().length;
$(charCount).text(chars);
$(msgCount).text(Math.ceil(chars / 160));
}
$('#message').on('keyup', function() {
updateCharCount(this, '#char_count', '#messages_count');
});
$('#message_bulk').on('keyup', function() {
updateCharCount(this, '#char_count_bulk', '#messages_count_bulk');
});
// Handle client groups selection
$('#client_groups').on('change', function() {
var selectedGroups = $(this).val();
if (selectedGroups) {
$.get(admin_url + 'hubtel_sms/get_recipients_preview', {
groups: selectedGroups
}, function(response) {
$('#recipients_preview').html(response.html);
$('#recipients_count').text(response.count);
}, 'json');
} else {
$('#recipients_preview').html('');
$('#recipients_count').text('0');
}
});
// Handle template selection for single SMS
$('#template_id').on('change', function() {
var templateId = $(this).val();
if (templateId) {
$.get(admin_url + 'hubtel_sms/get_template/' + templateId, function(response) {
if (response.success) {
$('#message').val(response.template.template);
updateCharCount('#message', '#char_count', '#messages_count');
}
}, 'json');
}
});
// Handle template selection for bulk SMS
$('#template_id_bulk').on('change', function() {
var templateId = $(this).val();
if (templateId) {
$.get(admin_url + 'hubtel_sms/get_template/' + templateId, function(response) {
if (response.success) {
$('#message_bulk').val(response.template.template);
updateCharCount('#message_bulk', '#char_count_bulk', '#messages_count_bulk');
}
}, 'json');
}
});
// Handle form submissions
$('#sms-form').on('submit', function() {
var $btn = $('#sendSmsBtn').prop('disabled', true);
$btn.html('<i class="fa fa-spinner fa-spin"></i> ' + app.lang.sending);
});
$('#bulk-sms-form').on('submit', function() {
if (!confirm(app.lang.bulk_sms_confirm)) {
return false;
}
var $btn = $('#sendBulkSmsBtn').prop('disabled', true);
$btn.html('<i class="fa fa-spinner fa-spin"></i> ' + app.lang.sending);
});
});
// Function to show send SMS modal
function send_sms_modal() {
$('#send_sms_modal').modal('show');
$('#send_sms_modal').find('form')[0].reset();
$('#template_id').val('').trigger('change');
$('#char_count').text('0');
$('#messages_count').text('1');
}
// Function to show bulk SMS modal
function bulk_sms_modal() {
$('#bulk_sms_modal').modal('show');
$('#bulk_sms_modal').find('form')[0].reset();
$('#client_groups').val('').trigger('change');
$('#template_id_bulk').val('').trigger('change');
$('#char_count_bulk').text('0');
$('#messages_count_bulk').text('1');
$('#recipients_preview').html('');
$('#recipients_count').text('0');
}
// Function to view message details
function view_message(id) {
$('#message_details').html('<div class="text-center"><i class="fa fa-spinner fa-spin fa-2x"></i></div>');
$('#view_message_modal').modal('show');
$.get(admin_url + 'hubtel_sms/view_message/' + id, function(response) {
$('#message_details').html(response);
});
}
// Function to preview template
function preview_template(id) {
$('#template_preview').html('<div class="text-center"><i class="fa fa-spinner fa-spin fa-2x"></i></div>');
$('#preview_template_modal').modal('show');
$.get(admin_url + 'hubtel_sms/preview_template/' + id, function(response) {
$('#template_preview').html(response);
});
}
// Function to resend SMS
function resend_sms(id) {
if (confirm(app.lang.confirm_action_prompt)) {
$.get(admin_url + 'hubtel_sms/resend/' + id, function(response) {
if (response.success) {
alert_float('success', response.message);
location.reload();
} else {
alert_float('danger', response.message);
}
}, 'json');
}
}

0
config.php Normal file
View File

221
controllers/Hubtel_sms.php Normal file
View File

@ -0,0 +1,221 @@
<?php
defined('BASEPATH') or exit('No direct script access allowed');
class Hubtel_sms extends AdminController
{
public function __construct()
{
parent::__construct();
$this->load->helper('hubtel_sms/hubtel_sms');
$this->load->model('hubtel_sms_model');
$this->load->library('hubtel_sms/hubtel_api');
}
public function index()
{
if (!has_permission('hubtel_sms', '', 'view')) {
access_denied('Hubtel SMS');
}
if (!is_hubtel_sms_enabled()) {
set_alert('warning', _l('hubtel_sms_module_disabled'));
redirect(admin_url());
}
$data['title'] = _l('hubtel_sms');
// Get statistics
$data['total_messages'] = $this->hubtel_sms_model->get_total_messages();
$data['sent_messages'] = $this->hubtel_sms_model->get_total_messages('sent');
$data['failed_messages'] = $this->hubtel_sms_model->get_total_messages('failed');
$data['total_cost'] = $this->hubtel_sms_model->get_total_cost();
// Get messages and templates
$data['messages'] = $this->hubtel_sms_model->get_messages();
$data['templates'] = $this->hubtel_sms_model->get_templates();
// Load client groups for bulk SMS
$this->load->model('client_groups_model');
$data['client_groups'] = $this->client_groups_model->get_groups();
$this->load->view('hubtel_sms/manage', $data);
}
public function send_sms()
{
if (!has_permission('hubtel_sms', '', 'create')) {
access_denied('Send SMS');
}
if ($this->input->post()) {
$response = $this->hubtel_sms_model->send_sms(
$this->input->post('to'),
$this->input->post('message'),
$this->input->post('template_id')
);
if ($response['success']) {
set_alert('success', _l('sms_sent_successfully'));
} else {
set_alert('danger', $response['message']);
}
}
redirect(admin_url('hubtel_sms'));
}
public function send_bulk_sms()
{
if (!has_permission('hubtel_sms', '', 'create')) {
access_denied('Send Bulk SMS');
}
if ($this->input->post()) {
$client_groups = $this->input->post('client_groups');
$message = $this->input->post('message');
$template_id = $this->input->post('template_id');
$success = 0;
$failed = 0;
$total_recipients = 0;
if (!empty($client_groups)) {
$this->load->model('clients_model');
foreach ($client_groups as $group_id) {
$clients = $this->clients_model->get_clients_by_group($group_id);
foreach ($clients as $client) {
if (!empty($client['phonenumber'])) {
$total_recipients++;
$response = $this->hubtel_sms_model->send_sms(
$client['phonenumber'],
$message,
$template_id
);
if ($response['success']) {
$success++;
} else {
$failed++;
}
}
}
}
}
set_alert('info', sprintf(
_l('bulk_sms_sent_info'),
$total_recipients,
$success,
$failed
));
}
redirect(admin_url('hubtel_sms'));
}
public function view_message($id)
{
if (!has_permission('hubtel_sms', '', 'view')) {
access_denied('View Message');
}
$message = $this->hubtel_sms_model->get_messages($id);
$logs = $this->hubtel_sms_model->get_message_logs($message->message_id);
echo $this->load->view('hubtel_sms/message_details', [
'message' => $message,
'logs' => $logs
], true);
}
public function preview_template($id)
{
if (!has_permission('hubtel_sms', '', 'view')) {
access_denied('Preview Template');
}
$template = $this->hubtel_sms_model->get_template($id);
echo $this->load->view('hubtel_sms/template_preview', [
'template' => $template
], true);
}
public function get_template($id)
{
if (!has_permission('hubtel_sms', '', 'view')) {
access_denied('Get Template');
}
$template = $this->hubtel_sms_model->get_template($id);
if ($template) {
echo json_encode([
'success' => true,
'template' => $template
]);
} else {
echo json_encode([
'success' => false,
'message' => _l('template_not_found')
]);
}
}
public function resend($id)
{
if (!has_permission('hubtel_sms', '', 'create')) {
access_denied('Resend SMS');
}
$message = $this->hubtel_sms_model->get_messages($id);
if ($message) {
$response = $this->hubtel_sms_model->send_sms(
$message->to,
$message->message
);
echo json_encode($response);
} else {
echo json_encode([
'success' => false,
'message' => _l('message_not_found')
]);
}
}
public function get_recipients_preview()
{
if (!has_permission('hubtel_sms', '', 'view')) {
access_denied('Get Recipients Preview');
}
$groups = $this->input->get('groups');
$recipients = [];
if (!empty($groups)) {
$this->load->model('clients_model');
foreach ($groups as $group_id) {
$clients = $this->clients_model->get_clients_by_group($group_id);
$group_name = $this->client_groups_model->get_group($group_id)->name;
foreach ($clients as $client) {
if (!empty($client['phonenumber'])) {
$recipients[] = [
'company' => $client['company'],
'phonenumber' => $client['phonenumber'],
'group_name' => $group_name
];
}
}
}
}
echo json_encode([
'success' => true,
'html' => $this->load->view('hubtel_sms/recipients_preview', [
'recipients' => $recipients
], true),
'count' => count($recipients)
]);
}
}

View File

@ -0,0 +1,21 @@
<?php
defined('BASEPATH') or exit('No direct script access allowed');
/**
* Check if Hubtel SMS module is enabled
* @return boolean
*/
function is_hubtel_sms_enabled()
{
return get_option('hubtel_sms_enabled') == 1;
}
/**
* Get Hubtel SMS setting
* @param string $name setting name
* @return mixed
*/
function get_hubtel_sms_setting($name)
{
return get_option('hubtel_sms_' . $name);
}

72
hubtel_sms.php Normal file
View File

@ -0,0 +1,72 @@
<?php
defined('BASEPATH') or exit('No direct script access allowed');
/*
Module Name: Hubtel SMS API
Description: SMS Integration with Hubtel
Version: 1.0.0
Requires at least: 2.3.*
Author: Emmanuel K. Sackey
*/
define('HUBTEL_SMS_MODULE_NAME', 'hubtel_sms');
// Add routes for the module
$route['admin/hubtel_sms'] = 'hubtel_sms/index';
$route['admin/hubtel_sms/settings'] = 'hubtel_sms/settings';
$route['admin/hubtel_sms/template/(:num)'] = 'hubtel_sms/template/$1';
$route['admin/hubtel_sms/template'] = 'hubtel_sms/template';
$route['admin/hubtel_sms/send_sms'] = 'hubtel_sms/send_sms';
$route['admin/hubtel_sms/delete_template/(:num)'] = 'hubtel_sms/delete_template/$1';
// Register hooks (removed duplicates)
hooks()->add_action('admin_init', 'hubtel_sms_module_init_menu_items');
hooks()->add_action('admin_init', 'hubtel_sms_permissions');
hooks()->add_action('admin_navbar_start', 'hubtel_sms_load_helper');
function hubtel_sms_module_init_menu_items()
{
$CI = &get_instance();
if (has_permission('hubtel_sms', '', 'view')) {
$CI->app_menu->add_sidebar_menu_item('hubtel-sms', [
'name' => _l('hubtel_sms'),
'href' => admin_url('hubtel_sms'),
'icon' => 'fa fa-envelope',
'position' => 30,
]);
}
}
function hubtel_sms_permissions()
{
$capabilities = [];
$capabilities['capabilities'] = [
'view' => _l('permission_hubtel_sms_view'),
'create' => _l('permission_hubtel_sms_create'),
'edit' => _l('permission_hubtel_sms_edit'),
'delete' => _l('permission_hubtel_sms_delete')
];
register_staff_capabilities('hubtel_sms', $capabilities, _l('hubtel_sms'));
}
/**
* Register language files, must be registered if the module is using languages
*/
register_language_files(HUBTEL_SMS_MODULE_NAME, [HUBTEL_SMS_MODULE_NAME]);
function hubtel_sms_activation_hook()
{
require_once(__DIR__ . '/install.php');
}
// Load helper using hook instead of direct loading
function hubtel_sms_load_helper()
{
$CI = &get_instance();
$CI->load->helper('hubtel_sms/hubtel_sms');
}

63
install.php Normal file
View File

@ -0,0 +1,63 @@
<?php
defined('BASEPATH') or exit('No direct script access allowed');
// Get CI instance
$CI = &get_instance();
// Add module options
add_option('hubtel_sms_client_id', '');
add_option('hubtel_sms_client_secret', '');
add_option('hubtel_sms_sender_id', '');
add_option('hubtel_sms_enabled', 1);
add_option('hubtel_sms_show_in_clients_menu', 1);
add_option('hubtel_sms_show_in_staff_menu', 1);
// Create messages table
if (!$CI->db->table_exists(db_prefix() . 'hubtel_sms_messages')) {
$CI->db->query('CREATE TABLE `' . db_prefix() . "hubtel_sms_messages` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`to` varchar(15) NOT NULL,
`message` text NOT NULL,
`rate` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
`status` varchar(20) DEFAULT NULL,
`date_sent` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`sent_by` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=" . $CI->db->char_set . ';');
}
// Create templates table
if (!$CI->db->table_exists(db_prefix() . 'hubtel_sms_templates')) {
$CI->db->query('CREATE TABLE `' . db_prefix() . "hubtel_sms_templates` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`template` text NOT NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=" . $CI->db->char_set . ';');
}
// Create logs table
if (!$CI->db->table_exists(db_prefix() . 'hubtel_sms_logs')) {
$CI->db->query('CREATE TABLE `' . db_prefix() . "hubtel_sms_logs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`message_id` int(11) NOT NULL,
`response` text,
`status` varchar(20) DEFAULT NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=" . $CI->db->char_set . ';');
}
// Check if new columns exist and add them if they don't
$CI->db->query("SHOW COLUMNS FROM `" . db_prefix() . "hubtel_sms_messages` LIKE 'response_code'");
if ($CI->db->affected_rows() == 0) {
$CI->db->query("ALTER TABLE `" . db_prefix() . "hubtel_sms_messages`
ADD COLUMN `response_code` varchar(10) DEFAULT NULL,
ADD COLUMN `rate` decimal(10,2) DEFAULT NULL,
ADD COLUMN `network_id` varchar(50) DEFAULT NULL,
ADD COLUMN `response_message` text DEFAULT NULL,
ADD COLUMN `message_id` varchar(50) DEFAULT NULL");
}

View File

@ -0,0 +1,109 @@
<?php
defined('BASEPATH') or exit('No direct script access allowed');
# Module
$lang['hubtel_sms'] = 'Hubtel SMS';
$lang['hubtel_sms_enable_module'] = 'Enable Hubtel SMS Module';
$lang['hubtel_sms_settings'] = 'Hubtel SMS Settings';
$lang['hubtel_sms_module_disabled'] = 'Hubtel SMS module is disabled';
# Dashboard
$lang['total_messages'] = 'Total Messages';
$lang['sent_messages'] = 'Sent Messages';
$lang['failed_messages'] = 'Failed Messages';
$lang['total_cost'] = 'Total Cost';
$lang['message_logs'] = 'Message Logs';
# Settings
$lang['hubtel_client_id'] = 'Client ID';
$lang['hubtel_client_secret'] = 'Client Secret';
$lang['hubtel_sender_id'] = 'Sender ID';
$lang['hubtel_sender_id_help'] = 'This is the name that appears as the sender of the SMS (max 11 alpha-numeric characters)';
$lang['hubtel_account_info'] = 'Account Information';
$lang['balance'] = 'Balance';
# SMS
$lang['new_sms'] = 'New SMS';
$lang['bulk_sms'] = 'Bulk SMS';
$lang['sms_messages'] = 'SMS Messages';
$lang['to'] = 'To';
$lang['message'] = 'Message';
$lang['status'] = 'Status';
$lang['date_sent'] = 'Date Sent';
$lang['sent_by'] = 'Sent By';
$lang['send'] = 'Send';
$lang['send_bulk_sms'] = 'Send Bulk SMS';
$lang['sms_sent_successfully'] = 'SMS sent successfully';
$lang['bulk_sms_sent_info'] = 'Bulk SMS sent to %s recipients (%s successful, %s failed)';
$lang['phone_placeholder'] = 'Enter phone number in international format (e.g., +233...)';
$lang['characters'] = 'characters';
$lang['messages'] = 'messages';
$lang['message_preview'] = 'Message Preview';
$lang['recipients_preview'] = 'Recipients Preview';
$lang['no_recipients_found'] = 'No recipients found';
$lang['sending'] = 'Sending...';
$lang['bulk_sms_confirm'] = 'Are you sure you want to send this SMS to all selected recipients?';
$lang['bulk_sms_info'] = 'Select client groups to send bulk SMS. Only clients with valid phone numbers will receive the message.';
# Templates
$lang['sms_templates'] = 'SMS Templates';
$lang['new_template'] = 'New Template';
$lang['template_name'] = 'Template Name';
$lang['template_content'] = 'Template Content';
$lang['template'] = 'Template';
$lang['edit_template'] = 'Edit Template';
$lang['template_added'] = 'SMS template added successfully';
$lang['template_updated'] = 'SMS template updated successfully';
$lang['template_deleted'] = 'SMS template deleted successfully';
$lang['template_preview'] = 'Template Preview';
$lang['sample_preview'] = 'Sample Preview';
$lang['available_merge_fields'] = 'Available Merge Fields';
$lang['template_not_found'] = 'Template not found';
# Message Details
$lang['message_details'] = 'Message Details';
$lang['message_id'] = 'Message ID';
$lang['response_code'] = 'Response Code';
$lang['response_message'] = 'Response Message';
$lang['rate'] = 'Rate';
$lang['network'] = 'Network';
$lang['message_not_found'] = 'Message not found';
# Status
$lang['pending'] = 'Pending';
$lang['sent'] = 'Sent';
$lang['failed'] = 'Failed';
$lang['delivered'] = 'Delivered';
# Client Fields
$lang['client_fields'] = 'Client Fields';
$lang['invoice_fields'] = 'Invoice Fields';
$lang['client'] = 'Client';
$lang['phone_number'] = 'Phone Number';
$lang['group'] = 'Group';
$lang['client_groups'] = 'Client Groups';
$lang['select_client_groups'] = 'Select Client Groups';
$lang['recipients'] = 'recipients';
# Permissions
$lang['permission_hubtel_sms_view'] = 'View SMS Messages';
$lang['permission_hubtel_sms_create'] = 'Send SMS Messages';
$lang['permission_hubtel_sms_edit'] = 'Edit SMS Templates';
$lang['permission_hubtel_sms_delete'] = 'Delete SMS Templates';
$lang['permission_hubtel_sms_admin'] = 'Module Admin';
# Menu
$lang['hubtel_sms_menu_icon'] = 'fa fa-envelope';
$lang['hubtel_sms_menu_name'] = 'SMS';
# Others
$lang['none'] = 'None';
$lang['options'] = 'Options';
$lang['id'] = 'ID';
$lang['name'] = 'Name';
$lang['last_updated'] = 'Last Updated';
$lang['preview'] = 'Preview';
$lang['edit'] = 'Edit';
$lang['delete'] = 'Delete';
$lang['close'] = 'Close';
$lang['confirm_action_prompt'] = 'Are you sure you want to perform this action?';

172
libraries/Hubtel_api.php Normal file
View File

@ -0,0 +1,172 @@
<?php
defined('BASEPATH') or exit('No direct script access allowed');
class Hubtel_api
{
private $client_id;
private $client_secret;
private $CI;
private $api_endpoint = 'https://smsc.hubtel.com/v1/messages/send';
public function __construct()
{
$this->CI = &get_instance();
// Load Hubtel credentials from options
$this->client_id = get_option('hubtel_sms_client_id');
$this->client_secret = get_option('hubtel_sms_client_secret');
}
/**
* Send SMS using Hubtel API
*
* @param string $to Recipient phone number (E164 format)
* @param string $message Message content (max 160 characters)
* @param string $from Sender ID (max 11 alpha-numeric characters)
* @return array Response with success status and message
*/
public function send_sms($to, $message, $from)
{
// Validate credentials
if (empty($this->client_id) || empty($this->client_secret)) {
return [
'success' => false,
'message' => 'API credentials not configured'
];
}
// Validate sender ID (must be 11 alpha-numeric characters or less)
if (strlen($from) > 11 || !preg_match('/^[a-zA-Z0-9]+$/', $from)) {
return [
'success' => false,
'message' => 'Invalid Sender ID. Must be 11 alpha-numeric characters or less.'
];
}
// Check message length
if (strlen($message) > 160) {
return [
'success' => false,
'message' => 'Message content exceeds 160 characters'
];
}
// Prepare the request URL with parameters
$params = [
'clientid' => $this->client_id,
'clientsecret' => $this->client_secret,
'from' => $from,
'to' => $to,
'content' => $message
];
$url = $this->api_endpoint . '?' . http_build_query($params);
// Set up cURL request
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HTTPGET, true); // Using GET method as per API spec
// Execute the request
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curl_error = curl_error($ch);
curl_close($ch);
// Handle cURL errors
if ($curl_error) {
return [
'success' => false,
'message' => 'cURL Error: ' . $curl_error
];
}
// Parse response
$result = json_decode($response, true);
// Handle API response
if ($http_code === 200) {
return [
'success' => true,
'message' => $result['message'] ?? 'Message sent',
'responseCode' => $result['responseCode'] ?? '',
'data' => [
'rate' => $result['data']['rate'] ?? 0,
'messageId' => $result['data']['messageId'] ?? '',
'status' => $result['data']['status'] ?? 0,
'networkId' => $result['data']['networkId'] ?? ''
]
];
}
return [
'success' => false,
'message' => $result['message'] ?? 'Failed to send SMS',
'responseCode' => $result['responseCode'] ?? '',
'data' => $result['data'] ?? null
];
}
/**
* Get account balance
*
* @return array Response with account balance
*/
public function get_balance()
{
if (empty($this->client_id) || empty($this->client_secret)) {
return [
'success' => false,
'message' => 'API credentials not configured'
];
}
$params = [
'clientid' => $this->client_id,
'clientsecret' => $this->client_secret
];
$url = 'https://smsc.hubtel.com/v1/accounts/balance?' . http_build_query($params);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HTTPGET, true);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curl_error = curl_error($ch);
curl_close($ch);
if ($curl_error) {
return [
'success' => false,
'message' => 'cURL Error: ' . $curl_error
];
}
$result = json_decode($response, true);
if ($http_code === 200) {
return [
'success' => true,
'balance' => $result['data']['balance'] ?? 0,
'currency' => $result['data']['currency'] ?? 'GHS',
'responseCode' => $result['responseCode'] ?? '',
'response' => $result
];
}
return [
'success' => false,
'message' => $result['message'] ?? 'Failed to get balance',
'responseCode' => $result['responseCode'] ?? '',
'response' => $result
];
}
}

287
models/Hubtel_sms_model.php Normal file
View File

@ -0,0 +1,287 @@
<?php
defined('BASEPATH') or exit('No direct script access allowed');
class Hubtel_sms_model extends App_Model
{
public function __construct()
{
parent::__construct();
}
public function get_messages($id = '')
{
if (is_numeric($id)) {
$this->db->where('id', $id);
return $this->db->get(db_prefix() . 'hubtel_sms_messages')->row();
}
return $this->db->get(db_prefix() . 'hubtel_sms_messages')->result_array();
}
public function get_template($id)
{
$this->db->where('id', $id);
return $this->db->get(db_prefix() . 'hubtel_sms_templates')->row();
}
public function get_templates()
{
return $this->db->get(db_prefix() . 'hubtel_sms_templates')->result_array();
}
public function add_template($data)
{
$this->db->insert(db_prefix() . 'hubtel_sms_templates', [
'name' => $data['name'],
'template' => $data['template']
]);
return $this->db->insert_id();
}
public function update_template($id, $data)
{
$this->db->where('id', $id);
$this->db->update(db_prefix() . 'hubtel_sms_templates', [
'name' => $data['name'],
'template' => $data['template'],
'updated_at' => date('Y-m-d H:i:s')
]);
return $this->db->affected_rows() > 0;
}
public function delete_template($id)
{
$this->db->where('id', $id);
$this->db->delete(db_prefix() . 'hubtel_sms_templates');
return $this->db->affected_rows() > 0;
}
public function send_sms($to, $message, $template_id = null)
{
// Get Hubtel API credentials
$client_id = get_option('hubtel_sms_client_id');
$client_secret = get_option('hubtel_sms_client_secret');
$sender_id = get_option('hubtel_sms_sender_id');
if (empty($client_id) || empty($client_secret) || empty($sender_id)) {
return [
'success' => false,
'message' => 'Hubtel API credentials not configured'
];
}
// If template is provided, get the message from template
if ($template_id) {
$template = $this->get_template($template_id);
if ($template) {
$message = $template->template;
}
}
// Record the message in database
$message_data = [
'to' => $to,
'message' => $message,
'status' => 'pending',
'sent_by' => get_staff_user_id()
];
$this->db->insert(db_prefix() . 'hubtel_sms_messages', $message_data);
$message_id = $this->db->insert_id();
// Send SMS using Hubtel API
$response = $this->hubtel_api->send_sms($to, $message, $sender_id);
// Update message status and log the response
$this->db->where('id', $message_id);
$this->db->update(db_prefix() . 'hubtel_sms_messages', [
'status' => $response['success'] ? 'sent' : 'failed'
]);
// Log the response
$this->db->insert(db_prefix() . 'hubtel_sms_logs', [
'message_id' => $message_id,
'response' => json_encode($response),
'status' => $response['success'] ? 'success' : 'failed'
]);
return $response;
}
public function get_total_messages($status = '')
{
if ($status !== '') {
$this->db->where('status', $status);
}
return $this->db->count_all_results(db_prefix() . 'hubtel_sms_messages');
}
public function get_total_cost()
{
$this->db->select_sum('rate');
$this->db->where('status', 'sent');
$query = $this->db->get(db_prefix() . 'hubtel_sms_messages');
return $query->row()->rate ?? 0;
}
// public function get_messages($id = '')
// {
// if (is_numeric($id)) {
// $this->db->where('id', $id);
// return $this->db->get(db_prefix() . 'hubtel_sms_messages')->row();
// }
// $this->db->order_by('date_sent', 'desc');
// return $this->db->get(db_prefix() . 'hubtel_sms_messages')->result_array();
// }
// public function get_template($id)
// {
// $this->db->where('id', $id);
// return $this->db->get(db_prefix() . 'hubtel_sms_templates')->row();
// }
// public function get_templates()
// {
// $this->db->order_by('name', 'asc');
// return $this->db->get(db_prefix() . 'hubtel_sms_templates')->result_array();
// }
// public function add_template($data)
// {
// $this->db->insert(db_prefix() . 'hubtel_sms_templates', [
// 'name' => $data['name'],
// 'template' => $data['template']
// ]);
// return $this->db->insert_id();
// }
// public function update_template($id, $data)
// {
// $this->db->where('id', $id);
// $this->db->update(db_prefix() . 'hubtel_sms_templates', [
// 'name' => $data['name'],
// 'template' => $data['template'],
// 'updated_at' => date('Y-m-d H:i:s')
// ]);
// return $this->db->affected_rows() > 0;
// }
// public function delete_template($id)
// {
// $this->db->where('id', $id);
// $this->db->delete(db_prefix() . 'hubtel_sms_templates');
// return $this->db->affected_rows() > 0;
// }
public function get_message_logs($message_id)
{
$this->db->where('message_id', $message_id);
$this->db->order_by('created_at', 'desc');
return $this->db->get(db_prefix() . 'hubtel_sms_logs')->result_array();
}
// public function send_sms($to, $message, $template_id = null)
// {
// // Get Hubtel API credentials
// $sender_id = get_option('hubtel_sms_sender_id');
// // Validate credentials
// if (!$this->validate_credentials()) {
// return [
// 'success' => false,
// 'message' => 'Hubtel API credentials not configured'
// ];
// }
// // Process template if provided
// if ($template_id) {
// $template = $this->get_template($template_id);
// if ($template) {
// $message = $this->process_template_merge_fields($template->template);
// }
// }
// // Record initial message in database
// $message_data = [
// 'to' => $to,
// 'message' => $message,
// 'status' => 'pending',
// 'sent_by' => get_staff_user_id(),
// 'date_sent' => date('Y-m-d H:i:s')
// ];
// $this->db->insert(db_prefix() . 'hubtel_sms_messages', $message_data);
// $message_id = $this->db->insert_id();
// // Send SMS using Hubtel API
// $response = $this->hubtel_api->send_sms($to, $message, $sender_id);
// // Update message with API response
// $update_data = [
// 'status' => $response['success'] ? 'sent' : 'failed',
// 'message_id' => $response['data']['messageId'] ?? null,
// 'rate' => $response['data']['rate'] ?? null,
// 'network_id' => $response['data']['networkId'] ?? null,
// 'response_code' => $response['responseCode'] ?? null,
// 'response_message' => $response['message'] ?? null
// ];
// $this->db->where('id', $message_id);
// $this->db->update(db_prefix() . 'hubtel_sms_messages', $update_data);
// // Log the complete response
// $this->db->insert(db_prefix() . 'hubtel_sms_logs', [
// 'message_id' => $response['data']['messageId'] ?? null,
// 'response_code' => $response['responseCode'] ?? null,
// 'response_message' => $response['message'] ?? null,
// 'rate' => $response['data']['rate'] ?? null,
// 'network_id' => $response['data']['networkId'] ?? null,
// 'status' => $response['success'] ? 'success' : 'failed',
// 'created_at' => date('Y-m-d H:i:s')
// ]);
// return [
// 'success' => $response['success'],
// 'message' => $response['message'],
// 'messageId' => $response['data']['messageId'] ?? null,
// 'rate' => $response['data']['rate'] ?? null,
// 'responseCode' => $response['responseCode'] ?? null
// ];
// }
private function validate_credentials()
{
$client_id = get_option('hubtel_sms_client_id');
$client_secret = get_option('hubtel_sms_client_secret');
$sender_id = get_option('hubtel_sms_sender_id');
return !empty($client_id) && !empty($client_secret) && !empty($sender_id);
}
private function process_template_merge_fields($template)
{
// Add merge field processing here
// Example: Replace {contact_firstname} with actual value
$CI = &get_instance();
// Load necessary models
$CI->load->model('clients_model');
$CI->load->model('invoices_model');
// Process client fields
$client_id = get_client_user_id();
if ($client_id) {
$client = $CI->clients_model->get($client_id);
$template = str_replace('{contact_firstname}', $client->firstname ?? '', $template);
$template = str_replace('{contact_lastname}', $client->lastname ?? '', $template);
$template = str_replace('{client_company}', $client->company ?? '', $template);
$template = str_replace('{client_phonenumber}', $client->phonenumber ?? '', $template);
}
return $template;
}
}

10
uninstall.php Normal file
View File

@ -0,0 +1,10 @@
<?php
defined('BASEPATH') or exit('No direct script access allowed');
// Delete options
$CI->db->query("DELETE FROM " . db_prefix() . "options WHERE name LIKE 'hubtel_sms_%'");
// Drop module tables
$CI->db->query("DROP TABLE IF EXISTS " . db_prefix() . "hubtel_sms_messages");
$CI->db->query("DROP TABLE IF EXISTS " . db_prefix() . "hubtel_sms_templates");
$CI->db->query("DROP TABLE IF EXISTS " . db_prefix() . "hubtel_sms_logs");

View File

@ -0,0 +1,76 @@
<div class="modal fade" id="bulk_sms_modal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title"><?php echo _l('bulk_sms'); ?></h4>
</div>
<?php echo form_open(admin_url('hubtel_sms/send_bulk_sms'), ['id' => 'bulk-sms-form']); ?>
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="alert alert-info">
<p><?php echo _l('bulk_sms_info'); ?></p>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="client_groups"><?php echo _l('client_groups'); ?></label>
<select class="form-control" id="client_groups" name="client_groups[]" multiple>
<?php foreach($client_groups as $group) { ?>
<option value="<?php echo $group['id']; ?>"><?php echo $group['name']; ?></option>
<?php } ?>
</select>
</div>
<div class="form-group">
<label for="template_id_bulk"><?php echo _l('template'); ?></label>
<select class="form-control" id="template_id_bulk" name="template_id">
<option value=""><?php echo _l('none'); ?></option>
<?php foreach ($templates as $template) { ?>
<option value="<?php echo $template['id']; ?>"><?php echo $template['name']; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="message_bulk"><?php echo _l('message'); ?></label>
<textarea class="form-control" id="message_bulk" name="message" rows="8" required
maxlength="160"></textarea>
<div class="text-muted mtop5">
<span id="char_count_bulk">0</span>/160 <?php echo _l('characters'); ?> |
<span id="messages_count_bulk">1</span> <?php echo _l('messages'); ?>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="panel panel-info">
<div class="panel-heading">
<div class="row">
<div class="col-md-6">
<?php echo _l('recipients_preview'); ?>
</div>
<div class="col-md-6 text-right">
<span class="label label-info" id="recipients_count">0</span> <?php echo _l('recipients'); ?>
</div>
</div>
</div>
<div class="panel-body">
<div id="recipients_preview" style="max-height: 200px; overflow-y: auto;"></div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><?php echo _l('close'); ?></button>
<button type="submit" class="btn btn-info" id="sendBulkSmsBtn">
<i class="fa fa-paper-plane"></i> <?php echo _l('send_bulk_sms'); ?>
</button>
</div>
<?php echo form_close(); ?>
</div>
</div>
</div>

View File

@ -0,0 +1,42 @@
<div class="modal fade" id="preview_template_modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title"><?php echo _l('template_preview'); ?></h4>
</div>
<div class="modal-body">
<div id="template_preview">
<!-- Content will be loaded dynamically -->
</div>
<hr>
<div class="alert alert-info">
<h5><?php echo _l('available_merge_fields'); ?></h5>
<div class="row">
<div class="col-md-6">
<strong><?php echo _l('client_fields'); ?>:</strong>
<ul class="mtop10">
<li>{contact_firstname}</li>
<li>{contact_lastname}</li>
<li>{client_company}</li>
<li>{client_phonenumber}</li>
</ul>
</div>
<div class="col-md-6">
<strong><?php echo _l('invoice_fields'); ?>:</strong>
<ul class="mtop10">
<li>{invoice_number}</li>
<li>{invoice_duedate}</li>
<li>{invoice_total}</li>
<li>{invoice_status}</li>
</ul>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><?php echo _l('close'); ?></button>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,55 @@
<div class="modal fade" id="send_sms_modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title"><?php echo _l('new_sms'); ?></h4>
</div>
<?php echo form_open(admin_url('hubtel_sms/send_sms'), ['id' => 'sms-form']); ?>
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label for="to"><?php echo _l('to'); ?> <small class="text-muted">(+233...)</small></label>
<input type="text" class="form-control" id="to" name="to" required
placeholder="<?php echo _l('phone_placeholder'); ?>">
</div>
<div class="form-group">
<label for="template_id"><?php echo _l('template'); ?></label>
<select class="form-control" id="template_id" name="template_id">
<option value=""><?php echo _l('none'); ?></option>
<?php foreach ($templates as $template) { ?>
<option value="<?php echo $template['id']; ?>"><?php echo $template['name']; ?></option>
<?php } ?>
</select>
</div>
<div class="form-group">
<label for="message"><?php echo _l('message'); ?></label>
<textarea class="form-control" id="message" name="message" rows="6" required
maxlength="160"></textarea>
<div class="text-muted mtop5">
<span id="char_count">0</span>/160 <?php echo _l('characters'); ?> |
<span id="messages_count">1</span> <?php echo _l('messages'); ?>
</div>
</div>
<div class="panel panel-info">
<div class="panel-heading">
<?php echo _l('message_preview'); ?>
</div>
<div class="panel-body">
<div id="message_preview"></div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><?php echo _l('close'); ?></button>
<button type="submit" class="btn btn-info" id="sendSmsBtn">
<i class="fa fa-paper-plane"></i> <?php echo _l('send'); ?>
</button>
</div>
<?php echo form_close(); ?>
</div>
</div>
</div>

View File

@ -0,0 +1,18 @@
<div class="modal fade" id="view_message_modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title"><?php echo _l('message_details'); ?></h4>
</div>
<div class="modal-body">
<div id="message_details">
<!-- Content will be loaded dynamically -->
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><?php echo _l('close'); ?></button>
</div>
</div>
</div>
</div>

301
views/manage.php Normal file
View File

@ -0,0 +1,301 @@
<?php defined('BASEPATH') or exit('No direct script access allowed'); ?>
<?php init_head(); ?>
<div id="wrapper">
<div class="content">
<div class="row">
<div class="col-md-12">
<!-- Quick Stats -->
<div class="row">
<div class="col-md-3">
<div class="panel_s">
<div class="panel-body">
<h3 class="text-muted _total"><?php echo $total_messages; ?></h3>
<span class="text-muted"><?php echo _l('total_messages'); ?></span>
</div>
</div>
</div>
<div class="col-md-3">
<div class="panel_s">
<div class="panel-body">
<h3 class="text-success _total"><?php echo $sent_messages; ?></h3>
<span class="text-success"><?php echo _l('sent_messages'); ?></span>
</div>
</div>
</div>
<div class="col-md-3">
<div class="panel_s">
<div class="panel-body">
<h3 class="text-danger _total"><?php echo $failed_messages; ?></h3>
<span class="text-danger"><?php echo _l('failed_messages'); ?></span>
</div>
</div>
</div>
<div class="col-md-3">
<div class="panel_s">
<div class="panel-body">
<h3 class="text-info _total"><?php echo app_format_money($total_cost, get_base_currency()); ?></h3>
<span class="text-info"><?php echo _l('total_cost'); ?></span>
</div>
</div>
</div>
</div>
<div class="panel_s">
<div class="panel-body">
<div class="_buttons">
<?php if (has_permission('hubtel_sms', '', 'create')) { ?>
<a href="#" class="btn btn-primary pull-left display-block" onclick="send_sms_modal();">
<i class="fa fa-paper-plane"></i> <?php echo _l('new_sms'); ?>
</a>
<a href="<?php echo admin_url('hubtel_sms/template'); ?>" class="btn btn-success pull-left display-block mleft5">
<i class="fa fa-plus"></i> <?php echo _l('new_template'); ?>
</a>
<!-- Bulk SMS Button -->
<a href="#" class="btn btn-info pull-left display-block mleft5" onclick="bulk_sms_modal();">
<i class="fa fa-users"></i> <?php echo _l('bulk_sms'); ?>
</a>
<?php } ?>
<?php if (has_permission('hubtel_sms', '', 'edit')) { ?>
<a href="<?php echo admin_url('hubtel_sms/settings'); ?>" class="btn btn-default pull-right">
<i class="fa fa-cog"></i> <?php echo _l('settings'); ?>
</a>
<?php } ?>
</div>
<div class="clearfix"></div>
<hr class="hr-panel-heading" />
<!-- Tabs -->
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active">
<a href="#messages" aria-controls="messages" role="tab" data-toggle="tab">
<?php echo _l('sms_messages'); ?>
</a>
</li>
<li role="presentation">
<a href="#templates" aria-controls="templates" role="tab" data-toggle="tab">
<?php echo _l('sms_templates'); ?>
</a>
</li>
</ul>
<!-- Tab Content -->
<div class="tab-content">
<!-- Messages Tab -->
<div role="tabpanel" class="tab-pane active" id="messages">
<div class="row mtop15">
<div class="col-md-12">
<!-- SMS Messages Table -->
<table class="table dt-table" data-order-col="4" data-order-type="desc">
<thead>
<tr>
<th><?php echo _l('id'); ?></th>
<th><?php echo _l('to'); ?></th>
<th><?php echo _l('message'); ?></th>
<th><?php echo _l('status'); ?></th>
<th><?php echo _l('response_code'); ?></th>
<th><?php echo _l('rate'); ?></th>
<th><?php echo _l('network'); ?></th>
<th><?php echo _l('date_sent'); ?></th>
<th><?php echo _l('sent_by'); ?></th>
<th><?php echo _l('options'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($messages as $message) { ?>
<tr>
<td><?php echo $message['id']; ?></td>
<td><?php echo $message['to']; ?></td>
<td>
<span class="text-wrap"><?php echo htmlspecialchars($message['message']); ?></span>
</td>
<td>
<?php
$status_badge = 'info';
if ($message['status'] == 'sent') {
$status_badge = 'success';
} elseif ($message['status'] == 'failed') {
$status_badge = 'danger';
}
?>
<span class="badge badge-<?php echo $status_badge; ?>">
<?php echo _l($message['status']); ?>
</span>
</td>
<td><?php echo isset($message['response_code']) ? $message['response_code'] : '-'; ?></td>
<td><?php echo isset($message['rate']) ? app_format_money($message['rate'], get_base_currency()) : '-'; ?></td>
<td><?php echo isset($message['network_id']) ? $message['network_id'] : '-'; ?></td>
<td data-order="<?php echo strtotime($message['date_sent']); ?>">
<?php echo _dt($message['date_sent']); ?>
</td>
<td><?php echo get_staff_full_name($message['sent_by']); ?></td>
<td>
<div class="btn-group">
<a href="#" class="btn btn-default btn-icon" onclick="view_message(<?php echo $message['id']; ?>)"
data-toggle="tooltip" title="<?php echo _l('view'); ?>">
<i class="fa fa-eye"></i>
</a>
<?php if ($message['status'] == 'failed') { ?>
<a href="#" class="btn btn-info btn-icon" onclick="resend_sms(<?php echo $message['id']; ?>)"
data-toggle="tooltip" title="<?php echo _l('resend'); ?>">
<i class="fa fa-refresh"></i>
</a>
<?php } ?>
</div>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- Templates Tab -->
<div role="tabpanel" class="tab-pane" id="templates">
<div class="row mtop15">
<div class="col-md-12">
<table class="table dt-table">
<thead>
<tr>
<th><?php echo _l('id'); ?></th>
<th><?php echo _l('name'); ?></th>
<th><?php echo _l('template'); ?></th>
<th><?php echo _l('last_updated'); ?></th>
<th><?php echo _l('options'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($templates as $template) { ?>
<tr>
<td><?php echo $template['id']; ?></td>
<td><?php echo $template['name']; ?></td>
<td>
<span class="text-wrap"><?php echo htmlspecialchars($template['template']); ?></span>
</td>
<td data-order="<?php echo strtotime($template['updated_at'] ?? $template['created_at']); ?>">
<?php echo _dt($template['updated_at'] ?? $template['created_at']); ?>
</td>
<td>
<div class="btn-group">
<?php if (has_permission('hubtel_sms', '', 'edit')) { ?>
<a href="<?php echo admin_url('hubtel_sms/template/' . $template['id']); ?>"
class="btn btn-default btn-icon" data-toggle="tooltip" title="<?php echo _l('edit'); ?>">
<i class="fa fa-pencil"></i>
</a>
<?php } ?>
<a href="#" class="btn btn-info btn-icon" onclick="preview_template(<?php echo $template['id']; ?>)"
data-toggle="tooltip" title="<?php echo _l('preview'); ?>">
<i class="fa fa-eye"></i>
</a>
<?php if (has_permission('hubtel_sms', '', 'delete')) { ?>
<a href="<?php echo admin_url('hubtel_sms/delete_template/' . $template['id']); ?>"
class="btn btn-danger btn-icon _delete" data-toggle="tooltip" title="<?php echo _l('delete'); ?>">
<i class="fa fa-remove"></i>
</a>
<?php } ?>
</div>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Include Modals -->
<?php $this->load->view('hubtel_sms/modals/send_sms'); ?>
<?php $this->load->view('hubtel_sms/modals/bulk_sms'); ?>
<?php $this->load->view('hubtel_sms/modals/view_message'); ?>
<?php $this->load->view('hubtel_sms/modals/preview_template'); ?>
<?php init_tail(); ?>
<script src="<?php echo module_dir_url('hubtel_sms', 'assets/js/hubtel_sms.js'); ?>"></script>
<script>
$(function() {
// Initialize tooltips
$('[data-toggle="tooltip"]').tooltip();
// Initialize select2 for template selection
$('#template_id').select2();
});
// Function to handle sending SMS
function send_sms_modal() {
$('#send_sms_modal').modal('show');
$('#send_sms_modal').find('form')[0].reset();
$('#template_id').trigger('change');
}
// Function to handle bulk SMS
function bulk_sms_modal() {
$('#bulk_sms_modal').modal('show');
$('#bulk_sms_modal').find('form')[0].reset();
}
// Function to view message details
function view_message(id) {
$.get(admin_url + 'hubtel_sms/view_message/' + id, function(response) {
$('#message_details').html(response);
$('#view_message_modal').modal('show');
});
}
// Function to preview template
function preview_template(id) {
$.get(admin_url + 'hubtel_sms/preview_template/' + id, function(response) {
$('#template_preview').html(response);
$('#preview_template_modal').modal('show');
});
}
// Function to resend SMS
function resend_sms(id) {
if (confirm(app.lang.confirm_action_prompt)) {
$.get(admin_url + 'hubtel_sms/resend/' + id, function(response) {
if (response.success) {
alert_float('success', response.message);
location.reload();
} else {
alert_float('danger', response.message);
}
}, 'json');
}
}
// Handle template selection
$('#template_id').on('change', function() {
var templateId = $(this).val();
if (templateId) {
$.get(admin_url + 'hubtel_sms/get_template/' + templateId, function(response) {
if (response.success) {
$('#message').val(response.template.template);
init_message_preview();
}
}, 'json');
}
});
// Initialize message preview
function init_message_preview() {
var message = $('#message').val();
var previewHtml = message ? message : app.lang.no_message_preview;
$('#message_preview').html(previewHtml);
}
// Update character count
$('#message').on('keyup', function() {
var chars = $(this).val().length;
$('#char_count').text(chars);
$('#messages_count').text(Math.ceil(chars / 160));
init_message_preview();
});
</script>

103
views/message_details.php Normal file
View File

@ -0,0 +1,103 @@
<?php defined('BASEPATH') or exit('No direct script access allowed'); ?>
<div class="row">
<div class="col-md-12">
<div class="table-responsive">
<table class="table table-striped">
<tbody>
<tr>
<td class="bold"><?php echo _l('to'); ?>:</td>
<td><?php echo $message->to; ?></td>
</tr>
<tr>
<td class="bold"><?php echo _l('message'); ?>:</td>
<td><?php echo htmlspecialchars($message->message); ?></td>
</tr>
<tr>
<td class="bold"><?php echo _l('status'); ?>:</td>
<td>
<?php
$status_badge = 'info';
if ($message->status == 'sent') {
$status_badge = 'success';
} elseif ($message->status == 'failed') {
$status_badge = 'danger';
}
?>
<span class="badge badge-<?php echo $status_badge; ?>">
<?php echo _l($message->status); ?>
</span>
</td>
</tr>
<tr>
<td class="bold"><?php echo _l('message_id'); ?>:</td>
<td><?php echo $message->message_id; ?></td>
</tr>
<tr>
<td class="bold"><?php echo _l('response_code'); ?>:</td>
<td><?php echo $message->response_code; ?></td>
</tr>
<tr>
<td class="bold"><?php echo _l('rate'); ?>:</td>
<td><?php echo app_format_money($message->rate, get_base_currency()); ?></td>
</tr>
<tr>
<td class="bold"><?php echo _l('network'); ?>:</td>
<td><?php echo $message->network_id; ?></td>
</tr>
<tr>
<td class="bold"><?php echo _l('sent_by'); ?>:</td>
<td><?php echo get_staff_full_name($message->sent_by); ?></td>
</tr>
<tr>
<td class="bold"><?php echo _l('date_sent'); ?>:</td>
<td><?php echo _dt($message->date_sent); ?></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<?php if (!empty($logs)) { ?>
<div class="row mtop15">
<div class="col-md-12">
<h4 class="bold"><?php echo _l('message_logs'); ?></h4>
<hr />
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th><?php echo _l('status'); ?></th>
<th><?php echo _l('response_code'); ?></th>
<th><?php echo _l('response_message'); ?></th>
<th><?php echo _l('date'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($logs as $log) { ?>
<tr>
<td>
<?php
$status_badge = 'info';
if ($log['status'] == 'success') {
$status_badge = 'success';
} elseif ($log['status'] == 'failed') {
$status_badge = 'danger';
}
?>
<span class="badge badge-<?php echo $status_badge; ?>">
<?php echo _l($log['status']); ?>
</span>
</td>
<td><?php echo $log['response_code']; ?></td>
<td><?php echo $log['response_message']; ?></td>
<td><?php echo _dt($log['created_at']); ?></td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
</div>
<?php } ?>

View File

@ -0,0 +1,26 @@
<?php defined('BASEPATH') or exit('No direct script access allowed'); ?>
<?php if (!empty($recipients)) { ?>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th><?php echo _l('client'); ?></th>
<th><?php echo _l('phone_number'); ?></th>
<th><?php echo _l('group'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($recipients as $recipient) { ?>
<tr>
<td><?php echo $recipient['company']; ?></td>
<td><?php echo $recipient['phonenumber']; ?></td>
<td><?php echo $recipient['group_name']; ?></td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
<?php } else { ?>
<p class="text-muted text-center"><?php echo _l('no_recipients_found'); ?></p>
<?php } ?>

87
views/settings.php Normal file
View File

@ -0,0 +1,87 @@
<?php defined('BASEPATH') or exit('No direct script access allowed'); ?>
<?php init_head(); ?>
<div id="wrapper">
<div class="content">
<div class="row">
<div class="col-md-12">
<div class="panel_s">
<div class="panel-body">
<h4 class="no-margin"><?php echo _l('hubtel_sms_settings'); ?></h4>
<hr class="hr-panel-heading" />
<?php echo form_open(admin_url('hubtel_sms/settings')); ?>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="client_id"><?php echo _l('hubtel_client_id'); ?></label>
<input type="text" class="form-control" id="client_id" name="client_id"
value="<?php echo get_option('hubtel_sms_client_id'); ?>" required>
</div>
<div class="form-group">
<label for="client_secret"><?php echo _l('hubtel_client_secret'); ?></label>
<input type="password" class="form-control" id="client_secret" name="client_secret"
value="<?php echo get_option('hubtel_sms_client_secret'); ?>" required>
</div>
<div class="form-group">
<label for="sender_id"><?php echo _l('hubtel_sender_id'); ?></label>
<input type="text" class="form-control" id="sender_id" name="sender_id"
value="<?php echo get_option('hubtel_sms_sender_id'); ?>" required>
<small class="text-muted"><?php echo _l('hubtel_sender_id_help'); ?></small>
</div>
<div class="form-group">
<label for="enabled"><?php echo _l('settings_yes'); ?> / <?php echo _l('settings_no'); ?></label>
<div class="form-group">
<?php $checked = (get_option('hubtel_sms_enabled') == 1) ? 'checked' : ''; ?>
<div class="checkbox checkbox-primary">
<input type="checkbox" name="enabled" id="enabled" value="1" <?php echo $checked; ?>>
<label for="enabled"><?php echo _l('hubtel_sms_enable_module'); ?></label>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<?php if (get_option('hubtel_sms_client_id') && get_option('hubtel_sms_client_secret')) { ?>
<div class="panel panel-info">
<div class="panel-heading">
<?php echo _l('hubtel_account_info'); ?>
</div>
<div class="panel-body" id="hubtel_account_info">
<!-- Account balance will be loaded here via AJAX -->
<div class="text-center">
<div class="spinner-border text-primary" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
</div>
</div>
<?php } ?>
</div>
</div>
<div class="row">
<div class="col-md-12">
<button type="submit" class="btn btn-info pull-right"><?php echo _l('submit'); ?></button>
</div>
</div>
<?php echo form_close(); ?>
</div>
</div>
</div>
</div>
</div>
</div>
<?php init_tail(); ?>
<script>
$(function() {
// Load account info if credentials are set
<?php if (get_option('hubtel_sms_client_id') && get_option('hubtel_sms_client_secret')) { ?>
$.get(admin_url + 'hubtel_sms/get_account_info', function(response) {
if (response.success) {
var html = '<p><strong><?php echo _l('balance'); ?>:</strong> ' + response.balance + ' ' + response.currency + '</p>';
$('#hubtel_account_info').html(html);
} else {
$('#hubtel_account_info').html('<div class="alert alert-danger">' + response.message + '</div>');
}
});
<?php } ?>
});
</script>

75
views/template.php Normal file
View File

@ -0,0 +1,75 @@
<?php defined('BASEPATH') or exit('No direct script access allowed'); ?>
<?php init_head(); ?>
<div id="wrapper">
<div class="content">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel_s">
<div class="panel-body">
<h4 class="no-margin">
<?php echo $title; ?>
<a href="<?php echo admin_url('hubtel_sms'); ?>" class="btn btn-default pull-right">
<i class="fa fa-arrow-left"></i> <?php echo _l('back'); ?>
</a>
</h4>
<hr class="hr-panel-heading" />
<?php echo form_open(admin_url('hubtel_sms/template/' . (isset($template) ? $template->id : ''))); ?>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label for="name"><?php echo _l('template_name'); ?></label>
<input type="text" class="form-control" id="name" name="name"
value="<?php echo (isset($template) ? $template->name : ''); ?>" required>
</div>
<div class="form-group">
<label for="template"><?php echo _l('template_content'); ?></label>
<textarea class="form-control" id="template" name="template" rows="8" required><?php echo (isset($template) ? $template->template : ''); ?></textarea>
</div>
<div class="panel panel-info mtop20">
<div class="panel-heading"><?php echo _l('available_merge_fields'); ?></div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
<p><strong><?php echo _l('client_fields'); ?>:</strong></p>
<p>{contact_firstname}</p>
<p>{contact_lastname}</p>
<p>{client_company}</p>
<p>{client_phonenumber}</p>
</div>
<div class="col-md-6">
<p><strong><?php echo _l('invoice_fields'); ?>:</strong></p>
<p>{invoice_number}</p>
<p>{invoice_duedate}</p>
<p>{invoice_total}</p>
<p>{invoice_status}</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<button type="submit" class="btn btn-info pull-right"><?php echo _l('submit'); ?></button>
</div>
</div>
<?php echo form_close(); ?>
</div>
</div>
</div>
</div>
</div>
</div>
<?php init_tail(); ?>
<script>
$(function() {
// Add merge field to template content
$('.panel-body p').not(':first-child').on('click', function() {
var mergeField = $(this).text();
var template = $('#template');
template.val(template.val() + ' ' + mergeField);
});
});
</script>

View File

@ -0,0 +1,36 @@
<?php defined('BASEPATH') or exit('No direct script access allowed'); ?>
<div class="row">
<div class="col-md-12">
<h4 class="bold"><?php echo $template->name; ?></h4>
<hr />
<div class="preview-content">
<?php echo htmlspecialchars($template->template); ?>
</div>
</div>
</div>
<div class="row mtop15">
<div class="col-md-12">
<div class="panel panel-info">
<div class="panel-heading">
<h4 class="panel-title"><?php echo _l('sample_preview'); ?></h4>
</div>
<div class="panel-body">
<?php
// Replace merge fields with sample data
$preview = $template->template;
$preview = str_replace('{contact_firstname}', 'John', $preview);
$preview = str_replace('{contact_lastname}', 'Doe', $preview);
$preview = str_replace('{client_company}', 'Sample Company Ltd', $preview);
$preview = str_replace('{client_phonenumber}', '+233123456789', $preview);
$preview = str_replace('{invoice_number}', 'INV-2025-001', $preview);
$preview = str_replace('{invoice_duedate}', date('Y-m-d', strtotime('+7 days')), $preview);
$preview = str_replace('{invoice_total}', app_format_money(1000, get_base_currency()), $preview);
$preview = str_replace('{invoice_status}', _l('invoice_status_unpaid'), $preview);
echo htmlspecialchars($preview);
?>
</div>
</div>
</div>
</div>