mirror of
https://github.com/hotspotbilling/phpnuxbill.git
synced 2025-07-09 17:44:23 +02:00
feat: enhance notification system with plan change and expiry edit messages
This commit is contained in:
parent
5513990edd
commit
62d94d1756
5 changed files with 224 additions and 43 deletions
|
@ -549,7 +549,7 @@ switch ($action) {
|
|||
$welcomeMessage = str_replace('[[password]]', $d['password'], $welcomeMessage);
|
||||
$welcomeMessage = str_replace('[[url]]', APP_URL . '/?_route=login', $welcomeMessage);
|
||||
|
||||
$emailSubject = "Welcome to " . $config['CompanyName'];
|
||||
$subject = "Welcome to " . $config['CompanyName'];
|
||||
|
||||
$channels = [
|
||||
'sms' => [
|
||||
|
@ -565,8 +565,13 @@ switch ($action) {
|
|||
'email' => [
|
||||
'enabled' => isset($_POST['mail']),
|
||||
'method' => 'Message::sendEmail',
|
||||
'args' => [$d['email'], $emailSubject, $welcomeMessage, $d['email']]
|
||||
]
|
||||
'args' => [$d['email'], $subject, $welcomeMessage, $d['email']]
|
||||
],
|
||||
'inbox' => [
|
||||
'enabled' => isset($_POST['inbox']),
|
||||
'method' => 'Message::addToInbox',
|
||||
'args' => $d['id'], $subject, $welcomeMessage, $from = 'Admin'
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($channels as $channel => $message) {
|
||||
|
|
|
@ -48,7 +48,7 @@ switch ($action) {
|
|||
$c = ORM::for_table('tbl_customers')->findOne($tur['customer_id']);
|
||||
if ($c) {
|
||||
$dvc = Package::getDevice($p);
|
||||
if ($_app_stage != 'demo') {
|
||||
if ($_app_stage != 'Demo') {
|
||||
if (file_exists($dvc)) {
|
||||
require_once $dvc;
|
||||
if (method_exists($dvc, 'sync_customer')) {
|
||||
|
@ -349,7 +349,7 @@ switch ($action) {
|
|||
$p = ORM::for_table('tbl_plans')->find_one($d['plan_id']);
|
||||
$c = User::_info($d['customer_id']);
|
||||
$dvc = Package::getDevice($p);
|
||||
if ($_app_stage != 'demo') {
|
||||
if ($_app_stage != 'Demo') {
|
||||
if (file_exists($dvc)) {
|
||||
require_once $dvc;
|
||||
(new $p['device'])->remove_customer($c, $p);
|
||||
|
@ -367,64 +367,146 @@ switch ($action) {
|
|||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
|
||||
$msg = '';
|
||||
$id_plan = _post('id_plan');
|
||||
$recharged_on = _post('recharged_on');
|
||||
$expiration = _post('expiration');
|
||||
$time = _post('time');
|
||||
|
||||
$id = _post('id');
|
||||
|
||||
$d = ORM::for_table('tbl_user_recharges')->find_one($id);
|
||||
if ($d) {
|
||||
} else {
|
||||
if (!$d) {
|
||||
$msg .= Lang::T('Data Not Found') . '<br>';
|
||||
}
|
||||
|
||||
$customer = User::_info($d['customer_id']);
|
||||
$oldPlanID = $d['plan_id'];
|
||||
$newPlan = ORM::for_table('tbl_plans')->where('id', $id_plan)->find_one();
|
||||
if ($newPlan) {
|
||||
} else {
|
||||
|
||||
if (!$newPlan) {
|
||||
$msg .= ' Plan Not Found<br>';
|
||||
}
|
||||
|
||||
if ($msg == '') {
|
||||
run_hook('edit_customer_plan'); #HOOK
|
||||
run_hook('edit_customer_plan'); // Hook
|
||||
|
||||
$d->expiration = $expiration;
|
||||
$d->time = $time;
|
||||
if ($d['status'] == 'off') {
|
||||
if (strtotime($expiration . ' ' . $time) > time()) {
|
||||
$d->status = 'on';
|
||||
}
|
||||
|
||||
if ($d['status'] == 'off' && strtotime($expiration . ' ' . $time) > time()) {
|
||||
$d->status = 'on';
|
||||
}
|
||||
// plan different then do something
|
||||
|
||||
$p = null;
|
||||
if ($oldPlanID != $id_plan) {
|
||||
$d->plan_id = $newPlan['id'];
|
||||
$d->namebp = $newPlan['name_plan'];
|
||||
$customer = User::_info($d['customer_id']);
|
||||
//remove from old plan
|
||||
|
||||
if ($d['status'] == 'on') {
|
||||
$p = ORM::for_table('tbl_plans')->find_one($oldPlanID);
|
||||
$dvc = Package::getDevice($p);
|
||||
if ($_app_stage != 'demo') {
|
||||
if ($_app_stage != 'Demo') {
|
||||
if (file_exists($dvc)) {
|
||||
require_once $dvc;
|
||||
$p['plan_expired'] = 0;
|
||||
(new $p['device'])->remove_customer($customer, $p);
|
||||
} else {
|
||||
new Exception(Lang::T("Devices Not Found"));
|
||||
throw new Exception(Lang::T("Devices Not Found"));
|
||||
}
|
||||
}
|
||||
//add new plan
|
||||
|
||||
$dvc = Package::getDevice($newPlan);
|
||||
if ($_app_stage != 'demo') {
|
||||
if ($_app_stage != 'Demo') {
|
||||
if (file_exists($dvc)) {
|
||||
require_once $dvc;
|
||||
(new $newPlan['device'])->add_customer($customer, $newPlan);
|
||||
} else {
|
||||
new Exception(Lang::T("Devices Not Found"));
|
||||
throw new Exception(Lang::T("Devices Not Found"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$planName = $d['namebp'];
|
||||
$d->save();
|
||||
_log('[' . $admin['username'] . ']: ' . 'Edit Plan for Customer ' . $d['username'] . ' to [' . $d['namebp'] . '][' . Lang::moneyFormat($p['price']) . ']', $admin['user_type'], $admin['id']);
|
||||
|
||||
// Send Notifications
|
||||
if (isset($_POST['notify']) && $_POST['notify'] == true) {
|
||||
if ($oldPlanID != $id_plan) {
|
||||
$oldPlan = ORM::for_table('tbl_plans')->find_one($oldPlanID);
|
||||
$oldPlanName = $oldPlan ? $oldPlan['name_plan'] : 'Old Plan';
|
||||
$notifyMessage = Lang::getNotifText('plan_change_message');
|
||||
if (empty($notifyMessage)) {
|
||||
$notifyMessage = Lang::T('Great news') . ', [[name]]! ' .
|
||||
Lang::T('Your plan has been successfully upgraded from ') . ' [[old_plan]] ' .
|
||||
Lang::T('to') . ' [[new_plan]]. ' .
|
||||
Lang::T('You can now enjoy seamless internet access until') . ' [[expiry]]. ' .
|
||||
Lang::T('Thank you for choosing') . ' [[company]] ' .
|
||||
Lang::T('for your internet needs') . ', ' .
|
||||
Lang::T('Enjoy enhanced features and benefits starting today') . '!';
|
||||
} else {
|
||||
$notifyMessage = Lang::getNotifText('plan_change_message');
|
||||
}
|
||||
$notifyMessage = str_replace('[[old_plan]]', $oldPlanName, $notifyMessage);
|
||||
$notifyMessage = str_replace('[[new_plan]]', $planName, $notifyMessage);
|
||||
} else {
|
||||
if (empty($notifyMessage)) {
|
||||
$notifyMessage = Lang::T('Dear') . ' [[name]], ' .
|
||||
Lang::T('your') . ' [[plan]] ' .
|
||||
Lang::T('has been extended! You can now enjoy seamless internet access until') . ' [[expiry]]. ' .
|
||||
Lang::T('Thank you for choosing') . ' [[company]] ' .
|
||||
Lang::T('for your internet needs') . '!';
|
||||
} else {
|
||||
$notifyMessage = Lang::getNotifText('plan_change_message');
|
||||
}
|
||||
$notifyMessage = str_replace('[[plan]]', $planName, $notifyMessage);
|
||||
}
|
||||
|
||||
$notifyMessage = str_replace('[[company]]', $config['CompanyName'], $notifyMessage);
|
||||
$notifyMessage = str_replace('[[name]]', $customer['fullname'], $notifyMessage);
|
||||
$notifyMessage = str_replace('[[username]]', $customer['username'], $notifyMessage);
|
||||
$notifyMessage = str_replace('[[expiry]]', date('M d, Y h:i A', strtotime($expiration . ' ' . $time)), $notifyMessage);
|
||||
|
||||
$subject = $planName . ' ' . Lang::T('Expiry Extension Notification');
|
||||
|
||||
$channels = [
|
||||
'sms' => [
|
||||
'enabled' => isset($_POST['sms']),
|
||||
'method' => 'sendSMS',
|
||||
'args' => [$customer['phonenumber'], $notifyMessage]
|
||||
],
|
||||
'whatsapp' => [
|
||||
'enabled' => isset($_POST['wa']),
|
||||
'method' => 'sendWhatsapp',
|
||||
'args' => [$customer['phonenumber'], $notifyMessage]
|
||||
],
|
||||
'email' => [
|
||||
'enabled' => isset($_POST['mail']),
|
||||
'method' => 'Message::sendEmail',
|
||||
'args' => [$customer['email'], $subject, $notifyMessage, $d['email']]
|
||||
],
|
||||
'inbox' => [
|
||||
'enabled' => isset($_POST['inbox']),
|
||||
'method' => 'Message::addToInbox',
|
||||
'args' => [$customer['id'], $subject, $notifyMessage, 'Admin']
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($channels as $channel => $message) {
|
||||
if ($message['enabled']) {
|
||||
try {
|
||||
call_user_func_array($message['method'], $message['args']);
|
||||
_log("Notification sent to {$customer['username']} via: " . implode(', ', array_keys(array_filter($channels, fn($c) => $c['enabled']))));
|
||||
} catch (Exception $e) {
|
||||
_log("Failed to send notify message via $channel: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$price = isset($p['price']) ? Lang::moneyFormat($p['price']) : '';
|
||||
_log('[' . $admin['username'] . ']: Edit Plan for Customer ' . $d['username'] . ' to [' . $d['namebp'] . "][$price]", $admin['user_type'], $admin['id']);
|
||||
r2(getUrl('plan/list'), 's', Lang::T('Data Updated Successfully'));
|
||||
} else {
|
||||
r2(getUrl('plan/edit/') . $id, 'e', $msg);
|
||||
|
@ -737,7 +819,7 @@ switch ($action) {
|
|||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
if ($_app_stage == 'Demo') {
|
||||
r2(getUrl('plan/add-voucher/'), 'e', 'You cannot perform this action in Demo mode');
|
||||
r2(getUrl('plan/add-voucher/'), 'e', 'You cannot perform this action in demo mode');
|
||||
}
|
||||
|
||||
$type = _post('type');
|
||||
|
@ -1082,7 +1164,7 @@ switch ($action) {
|
|||
$p = ORM::for_table('tbl_plans')->find_one($tur['plan_id']);
|
||||
if ($p) {
|
||||
$dvc = Package::getDevice($p);
|
||||
if ($_app_stage != 'demo') {
|
||||
if ($_app_stage != 'Demo') {
|
||||
if (file_exists($dvc)) {
|
||||
require_once $dvc;
|
||||
global $isChangePlan;
|
||||
|
|
|
@ -126,7 +126,6 @@
|
|||
{Lang::T('User Cannot change this, only admin. if it Empty it will use Customer Credentials')}
|
||||
</span>
|
||||
</div>
|
||||
<div class="panel-heading"></div>
|
||||
<div class="panel-body">
|
||||
<div class="form-group">
|
||||
<label class="col-md-3 control-label">{Lang::T('Send welcome message')}</label>
|
||||
|
@ -139,12 +138,14 @@
|
|||
</div>
|
||||
<div class="form-group" id="method" style="display: none;">
|
||||
<label class="col-md-3 control-label">{Lang::T('Notification via')}</label>
|
||||
<label class="col-md-3 control-label"><input type="checkbox" name="sms" value="1">
|
||||
<label class="col-md-1 control-label"><input type="checkbox" name="sms" value="1">
|
||||
{Lang::T('SMS')}</label>
|
||||
<label class="col-md-2 control-label"><input type="checkbox" name="wa" value="1">
|
||||
<label class="col-md-1 control-label"><input type="checkbox" name="wa" value="1">
|
||||
{Lang::T('WA')}</label>
|
||||
<label class="col-md-2 control-label"><input type="checkbox" name="mail" value="1">
|
||||
<label class="col-md-1 control-label"><input type="checkbox" name="mail" value="1">
|
||||
{Lang::T('Email')}</label>
|
||||
<label class="col-md-1 control-label"><input type="checkbox" name="inbox" value="1">
|
||||
{Lang::T('Inbox')}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -23,12 +23,12 @@
|
|||
|
||||
<select id="id_plan" name="id_plan" class="form-control select2">
|
||||
{foreach $p as $ps}
|
||||
<option value="{$ps['id']}" {if $d['plan_id'] eq $ps['id']} selected {/if}>
|
||||
{if $ps['enabled'] neq 1}DISABLED PLAN • {/if}
|
||||
{$ps['name_plan']} •
|
||||
{Lang::moneyFormat($ps['price'])}
|
||||
{if $ps['prepaid'] neq 'yes'} • POSTPAID {/if}
|
||||
</option>
|
||||
<option value="{$ps['id']}" {if $d['plan_id'] eq $ps['id']} selected {/if}>
|
||||
{if $ps['enabled'] neq 1}DISABLED PLAN • {/if}
|
||||
{$ps['name_plan']} •
|
||||
{Lang::moneyFormat($ps['price'])}
|
||||
{if $ps['prepaid'] neq 'yes'} • POSTPAID {/if}
|
||||
</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
|
@ -36,8 +36,7 @@
|
|||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Created On')}</label>
|
||||
<div class="col-md-4">
|
||||
<input type="date" class="form-control" readonly
|
||||
value="{$d['recharged_on']}">
|
||||
<input type="date" class="form-control" readonly value="{$d['recharged_on']}">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<input type="text" class="form-control" placeholder="00:00:00" readonly
|
||||
|
@ -55,10 +54,31 @@
|
|||
value="{$d['time']}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Send Notification')}</label>
|
||||
<div class="col-md-4">
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="notify" value="1" name="notify">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="method" style="display: none;">
|
||||
<label class="col-md-2 control-label">{Lang::T('Notification via')}</label>
|
||||
<label class="col-md-1 control-label"><input type="checkbox" name="sms" value="1">
|
||||
{Lang::T('SMS')}</label>
|
||||
<label class="col-md-1 control-label"><input type="checkbox" name="wa" value="1">
|
||||
{Lang::T('WA')}</label>
|
||||
<label class="col-md-1 control-label"><input type="checkbox" name="mail" value="1">
|
||||
{Lang::T('Email')}</label>
|
||||
<label class="col-md-1 control-label"><input type="checkbox" name="inbox" value="1">
|
||||
{Lang::T('Inbox')}</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-lg-offset-2 col-lg-10">
|
||||
<button class="btn btn-success" onclick="return ask(this, '{Lang::T('Continue the package change process')}?')" type="submit">{Lang::T('Edit')}</button>
|
||||
<button class="btn btn-success"
|
||||
onclick="return ask(this, '{Lang::T('Continue the package change process')}?')"
|
||||
type="submit">{Lang::T('Edit')}</button>
|
||||
Or <a href="{Text::url('')}plan/list">{Lang::T('Cancel')}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -68,4 +88,37 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{include file="sections/footer.tpl"}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var sendWelcomeCheckbox = document.getElementById('notify');
|
||||
var methodSection = document.getElementById('method');
|
||||
|
||||
function toggleMethodSection() {
|
||||
if (sendWelcomeCheckbox.checked) {
|
||||
methodSection.style.display = 'block';
|
||||
} else {
|
||||
methodSection.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
toggleMethodSection();
|
||||
|
||||
sendWelcomeCheckbox.addEventListener('change', toggleMethodSection);
|
||||
document.querySelector('form').addEventListener('submit', function (event) {
|
||||
if (sendWelcomeCheckbox.checked) {
|
||||
var methodCheckboxes = methodSection.querySelectorAll('input[type="checkbox"]');
|
||||
var oneChecked = Array.from(methodCheckboxes).some(function (checkbox) {
|
||||
return checkbox.checked;
|
||||
});
|
||||
|
||||
if (!oneChecked) {
|
||||
event.preventDefault();
|
||||
alert('Please choose at least one method notification.');
|
||||
methodSection.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{include file="sections/footer.tpl"}
|
|
@ -114,7 +114,7 @@
|
|||
<b>[[footer]]</b> - {Lang::T('Invoice Footer')}.<br>
|
||||
<b>[[note]]</b> - {Lang::T('For Notes by admin')}.<br>
|
||||
<b>[[invoice_link]]</b> - <a href="{$app_url}/docs/#Reminder%20with%20payment%20link"
|
||||
target="_blank">{Lang::T("read documentation")}</a>.
|
||||
target="_blank">{Lang::T("read documentation")}</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -163,6 +163,46 @@
|
|||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Plan Change Notification')}</label>
|
||||
<div class="col-md-6">
|
||||
<textarea class="form-control" id="plan_change_message" name="plan_change_message"
|
||||
placeholder="{Lang::T('Great news')}, [[name]]! {Lang::T('Your plan has been successfully upgraded from ')} [[old_plan]] {Lang::T('to')} [[new_plan]]. {Lang::T('You can now enjoy seamless internet access until')} [[expiry]]. {Lang::T('Thank you for choosing')} [[company]] {Lang::T('for your internet needs')}, {Lang::T('Enjoy enhanced features and benefits starting today')}!"
|
||||
rows="4">{if $_json['plan_change_message']!=''}{Lang::htmlspecialchars($_json['plan_change_message'])}{else}{Lang::T('Great news')}, [[name]]! {Lang::T('Your plan has been successfully upgraded from ')} [[old_plan]] {Lang::T('to')} [[new_plan]]. {Lang::T('You can now enjoy seamless internet access until')} [[expiry]]. {Lang::T('Thank
|
||||
you for choosing')} [[company]] {Lang::T('for your internet needs')}, {Lang::T('Enjoy enhanced features and benefits starting today')}!{/if}</textarea>
|
||||
</div>
|
||||
<p class="help-block col-md-4">
|
||||
<b>[[name]]</b> - {Lang::T('will be replaced with Customer Name')}.<br>
|
||||
<b>[[username]]</b> - {Lang::T('will be replaced with Customer username')}.<br>
|
||||
<b>[[old_plan]]</b> - {Lang::T('will be replaced with old plan name')}.<br>
|
||||
<b>[[new_plan]]</b> - {Lang::T('will be replaced with new plan name')}.<br>
|
||||
<b>[[expiry]]</b> - {Lang::T('will be replaced with the expiry date of the plan')}.<br>
|
||||
<b>[[company]]</b> - {Lang::T('will be replaced with Company Name')}.<br>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Expiry Edit Notification')}</label>
|
||||
<div class="col-md-6">
|
||||
<textarea class="form-control" id="edit_expiry_message" name="edit_expiry_message"
|
||||
placeholder="{Lang::T('Dear')} [[name]], {Lang::T('your')} [[plan]] {Lang::T('expiry date has been extended! You can now enjoy seamless internet access until')} [[expiry]]. {Lang::T('Thank you for choosing')} [[company]] {Lang::T('for your internet needs')}!"
|
||||
rows="4"> {if $_json['edit_expiry_message']!=''}{Lang::htmlspecialchars($_json['edit_expiry_message'])}{else}{Lang::T('Dear')} [[name]], {Lang::T('your')} [[plan]] {Lang::T('expiry date has been extended! You can now enjoy
|
||||
seamless internet access until')} [[expiry]]. {Lang::T('Thank you for choosing')} [[company]] {Lang::T('for your
|
||||
internet needs')}! {/if}</textarea>
|
||||
</div>
|
||||
<p class="help-block col-md-4">
|
||||
<b>[[name]]</b> - {Lang::T('will be replaced with Customer Name')}.<br>
|
||||
<b>[[username]]</b> - {Lang::T('will be replaced with Customer username')}.<br>
|
||||
<b>[[plan]]</b> - {Lang::T('will be replaced with plan name')}.<br>
|
||||
<b>[[expiry]]</b> - {Lang::T('will be replaced with the expiry date of the plan')}.<br>
|
||||
<b>[[company]]</b> - {Lang::T('will be replaced with Company Name')}.<br>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{if $_c['enable_balance'] == 'yes'}
|
||||
<div class="panel-body">
|
||||
<div class="form-group">
|
||||
|
@ -193,7 +233,7 @@
|
|||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{* <div class="panel-body">
|
||||
{* <div class="panel-body">
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('PDF Invoice Template')}</label>
|
||||
<div class="col-md-6">
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue