forked from kevinowino869/mitrobill
Compare commits
35 Commits
Author | SHA1 | Date | |
---|---|---|---|
ae3db05649 | |||
fa45d5f4b5 | |||
895bb26b02 | |||
a5affdb674 | |||
238fc03d03 | |||
cf8e23ae88 | |||
b9132082e5 | |||
ee63abb618 | |||
060718dfda | |||
651969924c | |||
a40b2cbea3 | |||
fc73a83732 | |||
6763fe09d8 | |||
0ea9de70fc | |||
c7ec8e2d27 | |||
822acef6d8 | |||
892c6bf7f5 | |||
c0c857e735 | |||
49794b99de | |||
126212f4c2 | |||
e3de07d435 | |||
2f551b1755 | |||
f766393e52 | |||
0bd587522a | |||
47c6e90624 | |||
fc0ef5b41a | |||
dff3970ff4 | |||
4c4fe4e99f | |||
2ed3dc991a | |||
be43a5b385 | |||
61bd042b15 | |||
b6fde35eb6 | |||
980af58eb1 | |||
f7deb828ac | |||
4c1e5da601 |
28
CHANGELOG.md
28
CHANGELOG.md
@ -2,6 +2,34 @@
|
||||
|
||||
# CHANGELOG
|
||||
|
||||
## 2024.5.14
|
||||
|
||||
- Show Plan and Location on expired list
|
||||
- Customizeable payment for recharge
|
||||
|
||||
## 2024.5.8
|
||||
|
||||
- Fix bugs burst by @Gerandonk
|
||||
- Fix sync for burst by @Gerandonk
|
||||
|
||||
## 2024.5.7
|
||||
|
||||
- Fix time for period Days
|
||||
- Fix Free radius attributes by @agstrxyz
|
||||
- Add Numeric Voucher Code by @pro-cms
|
||||
|
||||
## 2024.4.30
|
||||
|
||||
- CRITICAL UPDATE: last update Logic recharge not check is status on or off, it make expired customer stay in expired pool
|
||||
- Prevent double submit for recharge balance
|
||||
|
||||
## 2024.4.29
|
||||
|
||||
- Maps Pagination
|
||||
- Maps Search
|
||||
- Fix extend logic
|
||||
- Fix logic customer recharge to not delete when customer not change the plan
|
||||
|
||||
## 2024.4.23
|
||||
|
||||
- Fix Pagination Voucher
|
||||
|
34
init.php
34
init.php
@ -11,7 +11,7 @@ if (realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME'])) {
|
||||
die();
|
||||
}
|
||||
$root_path = realpath(dirname(__FILE__)) . DIRECTORY_SEPARATOR;
|
||||
if(!isset($isApi)){
|
||||
if (!isset($isApi)) {
|
||||
$isApi = false;
|
||||
}
|
||||
// on some server, it getting error because of slash is backwards
|
||||
@ -73,9 +73,9 @@ ORM::configure('return_result_sets', true);
|
||||
if ($_app_stage != 'Live') {
|
||||
ORM::configure('logging', true);
|
||||
}
|
||||
if($isApi){
|
||||
if ($isApi) {
|
||||
define('U', APP_URL . '/system/api.php?r=');
|
||||
}else{
|
||||
} else {
|
||||
define('U', APP_URL . '/index.php?_route=');
|
||||
}
|
||||
|
||||
@ -233,6 +233,32 @@ function showResult($success, $message = '', $result = [], $meta = [])
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
function generateUniqueNumericVouchers($totalVouchers, $length = 8)
|
||||
{
|
||||
// Define characters allowed in the voucher code
|
||||
$characters = '0123456789';
|
||||
$charactersLength = strlen($characters);
|
||||
$vouchers = array();
|
||||
|
||||
// Attempt to generate unique voucher codes
|
||||
for ($j = 0; $j < $totalVouchers; $j++) {
|
||||
do {
|
||||
$voucherCode = '';
|
||||
// Generate the voucher code
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$voucherCode .= $characters[rand(0, $charactersLength - 1)];
|
||||
}
|
||||
// Check if the generated voucher code already exists in the array
|
||||
$isUnique = !in_array($voucherCode, $vouchers);
|
||||
} while (!$isUnique);
|
||||
|
||||
$vouchers[] = $voucherCode;
|
||||
}
|
||||
|
||||
return $vouchers;
|
||||
}
|
||||
|
||||
function sendTelegram($txt)
|
||||
{
|
||||
Message::sendTelegram($txt);
|
||||
@ -253,7 +279,7 @@ function r2($to, $ntype = 'e', $msg = '')
|
||||
global $isApi;
|
||||
if ($isApi) {
|
||||
showResult(
|
||||
($ntype=='s')? true : false,
|
||||
($ntype == 's') ? true : false,
|
||||
$msg
|
||||
);
|
||||
}
|
||||
|
@ -115,13 +115,12 @@ class Message
|
||||
$mail->Subject = $subject;
|
||||
$mail->Body = $body;
|
||||
$mail->send();
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
public static function sendPackageNotification($customer, $package, $price, $message, $via)
|
||||
{
|
||||
global $user_recharge;
|
||||
global $ds;
|
||||
if(empty($message)){
|
||||
return "";
|
||||
}
|
||||
@ -141,8 +140,8 @@ class Message
|
||||
}else{
|
||||
$msg = str_replace('[[bills]]', '', $msg);
|
||||
}
|
||||
if ($user_recharge) {
|
||||
$msg = str_replace('[[expired_date]]', Lang::dateAndTimeFormat($user_recharge['expiration'], $user_recharge['time']), $msg);
|
||||
if ($ds) {
|
||||
$msg = str_replace('[[expired_date]]', Lang::dateAndTimeFormat($ds['expiration'], $ds['time']), $msg);
|
||||
}else{
|
||||
$msg = str_replace('[[expired_date]]', "", $msg);
|
||||
}
|
||||
|
@ -175,7 +175,9 @@ class Package
|
||||
};
|
||||
$time = date("23:59:00");
|
||||
} else if ($p['validity_unit'] == 'Days') {
|
||||
$date_exp = date("Y-m-d", strtotime('+' . $p['validity'] . ' day'));
|
||||
$datetime = explode(' ', date("Y-m-d H:i:s", strtotime('+' . $p['validity'] . ' day')));
|
||||
$date_exp = $datetime[0];
|
||||
$time = $datetime[1];
|
||||
} else if ($p['validity_unit'] == 'Hrs') {
|
||||
$datetime = explode(' ', date("Y-m-d H:i:s", strtotime('+' . $p['validity'] . ' hour')));
|
||||
$date_exp = $datetime[0];
|
||||
@ -185,9 +187,12 @@ class Package
|
||||
$date_exp = $datetime[0];
|
||||
$time = $datetime[1];
|
||||
}
|
||||
|
||||
$isChangePlan = false;
|
||||
if ($p['type'] == 'Hotspot') {
|
||||
if ($b) {
|
||||
if ($plan_id != $b['plan_id']) {
|
||||
$isChangePlan = true;
|
||||
}
|
||||
if ($b['namebp'] == $p['name_plan'] && $b['status'] == 'on') {
|
||||
// if it same internet plan, expired will extend
|
||||
if ($p['validity_unit'] == 'Months') {
|
||||
@ -210,13 +215,15 @@ class Package
|
||||
}
|
||||
}
|
||||
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, "$date_exp $time");
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removeHotspotUser($client, $c['username']);
|
||||
Mikrotik::removeHotspotActiveUser($client, $c['username']);
|
||||
Mikrotik::addHotspotUser($client, $p, $c);
|
||||
if ($isChangePlan || $b['status'] == 'off') {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, "$date_exp $time");
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removeHotspotUser($client, $c['username']);
|
||||
Mikrotik::removeHotspotActiveUser($client, $c['username']);
|
||||
Mikrotik::addHotspotUser($client, $p, $c);
|
||||
}
|
||||
}
|
||||
|
||||
$b->customer_id = $id_customer;
|
||||
@ -384,6 +391,9 @@ class Package
|
||||
} else {
|
||||
|
||||
if ($b) {
|
||||
if ($plan_id != $b['plan_id']) {
|
||||
$isChangePlan = true;
|
||||
}
|
||||
if ($b['namebp'] == $p['name_plan'] && $b['status'] == 'on') {
|
||||
// if it same internet plan, expired will extend
|
||||
if ($p['validity_unit'] == 'Months') {
|
||||
@ -406,13 +416,15 @@ class Package
|
||||
}
|
||||
}
|
||||
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, "$date_exp $time");
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removePpoeUser($client, $c['username']);
|
||||
Mikrotik::removePpoeActive($client, $c['username']);
|
||||
Mikrotik::addPpoeUser($client, $p, $c);
|
||||
if ($isChangePlan || $b['status'] == 'off') {
|
||||
if ($p['is_radius']) {
|
||||
Radius::customerAddPlan($c, $p, "$date_exp $time");
|
||||
} else {
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
Mikrotik::removePpoeUser($client, $c['username']);
|
||||
Mikrotik::removePpoeActive($client, $c['username']);
|
||||
Mikrotik::addPpoeUser($client, $p, $c);
|
||||
}
|
||||
}
|
||||
|
||||
$b->customer_id = $id_customer;
|
||||
@ -584,7 +596,7 @@ class Package
|
||||
}
|
||||
run_hook("recharge_user_finish");
|
||||
Message::sendInvoice($c, $t);
|
||||
if($trx){
|
||||
if ($trx) {
|
||||
$trx->trx_invoice = $inv;
|
||||
}
|
||||
return $inv;
|
||||
@ -730,7 +742,7 @@ class Package
|
||||
$invoice .= Lang::pad($note, ' ', 2) . "\n";
|
||||
}
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
if($cust){
|
||||
if ($cust) {
|
||||
$invoice .= Lang::pads(Lang::T('Full Name'), $cust['fullname'], ' ') . "\n";
|
||||
}
|
||||
$invoice .= Lang::pads(Lang::T('Username'), $in['username'], ' ') . "\n";
|
||||
@ -774,7 +786,7 @@ class Package
|
||||
$invoice .= Lang::pad($note, ' ', 2) . "\n";
|
||||
}
|
||||
$invoice .= Lang::pad("", '=') . "\n";
|
||||
if($cust){
|
||||
if ($cust) {
|
||||
$invoice .= Lang::pads(Lang::T('Full Name'), $cust['fullname'], ' ') . "\n";
|
||||
}
|
||||
$invoice .= Lang::pads(Lang::T('Username'), $in['username'], ' ') . "\n";
|
||||
|
@ -20,7 +20,6 @@ class Paginator
|
||||
}
|
||||
$url .= '&p=';
|
||||
$totalReq = $query->count();
|
||||
$next = $page + 1;
|
||||
$lastpage = ceil($totalReq / $per_page);
|
||||
$lpm1 = $lastpage - 1;
|
||||
$limit = $per_page;
|
||||
|
@ -30,7 +30,10 @@ class Radius
|
||||
{
|
||||
return ORM::for_table('nas', 'radius');
|
||||
}
|
||||
|
||||
public static function getTableAcct()
|
||||
{
|
||||
return ORM::for_table('radacct', 'radius');
|
||||
}
|
||||
public static function getTableCustomer()
|
||||
{
|
||||
return ORM::for_table('radcheck', 'radius');
|
||||
@ -88,9 +91,16 @@ class Radius
|
||||
public static function planUpSert($plan_id, $rate, $pool = null)
|
||||
{
|
||||
$rates = explode('/', $rate);
|
||||
##burst fixed
|
||||
if (strpos($rate, ' ')) {
|
||||
$ratos = $rates[0].'/'.$rates[1].' '.$rates[2].'/'.$rates[3].'/'.$rates[4].'/'.$rates[5].'/'.$rates[6];
|
||||
} else {
|
||||
$ratos = $rates[0].'/'.$rates[1];
|
||||
}
|
||||
|
||||
Radius::upsertPackage($plan_id, 'Ascend-Data-Rate', $rates[1], ':=');
|
||||
Radius::upsertPackage($plan_id, 'Ascend-Xmit-Rate', $rates[0], ':=');
|
||||
Radius::upsertPackage($plan_id, 'Mikrotik-Rate-Limit', $rate, ':=');
|
||||
Radius::upsertPackage($plan_id, 'Mikrotik-Rate-Limit', $ratos, ':=');
|
||||
// if ($pool != null) {
|
||||
// Radius::upsertPackage($plan_id, 'Framed-Pool', $pool, ':=');
|
||||
// }
|
||||
@ -161,6 +171,8 @@ class Radius
|
||||
$p = Radius::getTableUserPackage()->where_equal('username', $customer['username'])->findOne();
|
||||
if ($p) {
|
||||
// if exists
|
||||
Radius::delAtribute(Radius::getTableCustomer(), 'Max-All-Session', 'username', $customer['username']);
|
||||
Radius::delAtribute(Radius::getTableCustomer(), 'Max-Data', 'username', $customer['username']);
|
||||
$p->groupname = "plan_" . $plan['id'];
|
||||
$p->save();
|
||||
} else {
|
||||
@ -176,7 +188,7 @@ class Radius
|
||||
$timelimit = $plan['time_limit'] * 60 * 60;
|
||||
else
|
||||
$timelimit = $plan['time_limit'] * 60;
|
||||
Radius::upsertCustomer($customer['username'], 'Expire-After', $timelimit);
|
||||
Radius::upsertCustomer($customer['username'], 'Max-All-Session', $timelimit);
|
||||
} else if ($plan['limit_type'] == "Data_Limit") {
|
||||
if ($plan['data_unit'] == 'GB')
|
||||
$datalimit = $plan['data_limit'] . "000000000";
|
||||
@ -184,29 +196,40 @@ class Radius
|
||||
$datalimit = $plan['data_limit'] . "000000";
|
||||
//Radius::upsertCustomer($customer['username'], 'Max-Volume', $datalimit);
|
||||
// Mikrotik Spesific
|
||||
Radius::upsertCustomer($customer['username'], 'Mikrotik-Total-Limit', $datalimit);
|
||||
Radius::upsertCustomer($customer['username'], 'Max-Data', $datalimit);
|
||||
} else if ($plan['limit_type'] == "Both_Limit") {
|
||||
if ($plan['time_unit'] == 'Hrs')
|
||||
$timelimit = $plan['time_limit'] * 60 * 60;
|
||||
else
|
||||
$timelimit = $plan['time_limit'] . ":00";
|
||||
$timelimit = $plan['time_limit'] * 60;
|
||||
if ($plan['data_unit'] == 'GB')
|
||||
$datalimit = $plan['data_limit'] . "000000000";
|
||||
else
|
||||
$datalimit = $plan['data_limit'] . "000000";
|
||||
//Radius::upsertCustomer($customer['username'], 'Max-Volume', $datalimit);
|
||||
Radius::upsertCustomer($customer['username'], 'Expire-After', $timelimit);
|
||||
Radius::upsertCustomer($customer['username'], 'Max-All-Session', $timelimit);
|
||||
// Mikrotik Spesific
|
||||
Radius::upsertCustomer($customer['username'], 'Mikrotik-Total-Limit', $datalimit);
|
||||
Radius::upsertCustomer($customer['username'], 'Max-Data', $datalimit);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
//Radius::delAtribute(Radius::getTableCustomer(), 'Max-Volume', 'username', $customer['username']);
|
||||
Radius::delAtribute(Radius::getTableCustomer(), 'Expire-After', 'username', $customer['username']);
|
||||
Radius::delAtribute(Radius::getTableCustomer(), 'Mikrotik-Total-Limit', 'username', $customer['username']);
|
||||
Radius::delAtribute(Radius::getTableCustomer(), 'Max-All-Session', 'username', $customer['username']);
|
||||
Radius::delAtribute(Radius::getTableCustomer(), 'Max-Data', 'username', $customer['username']);
|
||||
}
|
||||
|
||||
Radius::disconnectCustomer($customer['username']);
|
||||
Radius::getTableAcct()->where_equal('username', $customer['username'])->delete_many();
|
||||
|
||||
|
||||
// expired user
|
||||
if ($expired != null) {
|
||||
//Radius::upsertCustomer($customer['username'], 'access-period', strtotime($expired) - time());
|
||||
//Radius::upsertCustomer($customer['username'], 'Max-All-Session', strtotime($expired) - time());
|
||||
Radius::upsertCustomer($customer['username'], 'expiration', date('d M Y H:i:s', strtotime($expired)));
|
||||
// Mikrotik Spesific
|
||||
Radius::upsertCustomer(
|
||||
@ -215,13 +238,15 @@ class Radius
|
||||
date('Y-m-d', strtotime($expired)) . 'T' . date('H:i:s', strtotime($expired)) . Timezone::getTimeOffset($config['timezone'])
|
||||
);
|
||||
} else {
|
||||
//Radius::delAtribute(Radius::getTableCustomer(), 'access-period', 'username', $customer['username']);
|
||||
//Radius::delAtribute(Radius::getTableCustomer(), 'Max-All-Session', 'username', $customer['username']);
|
||||
Radius::delAtribute(Radius::getTableCustomer(), 'expiration', 'username', $customer['username']);
|
||||
}
|
||||
|
||||
if ($plan['type'] == 'PPPOE') {
|
||||
Radius::upsertCustomerAttr($customer['username'], 'Framed-Pool', $plan['pool'], ':=');
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -267,7 +292,7 @@ class Radius
|
||||
/**
|
||||
* To insert or update existing customer
|
||||
*/
|
||||
private static function upsertCustomer($username, $attr, $value, $op = ':=')
|
||||
public static function upsertCustomer($username, $attr, $value, $op = ':=')
|
||||
{
|
||||
$r = Radius::getTableCustomer()->where_equal('username', $username)->whereEqual('attribute', $attr)->find_one();
|
||||
if (!$r) {
|
||||
|
@ -74,7 +74,7 @@ class User
|
||||
list($cost, $rem) = explode(":", $v);
|
||||
// :0 installment is done
|
||||
if ($rem != 0) {
|
||||
User::setAttribute($k, "$cost:".($rem - 1), $id);
|
||||
User::setAttribute($k, "$cost:" . ($rem - 1), $id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -177,21 +177,13 @@ class User
|
||||
}
|
||||
$d = ORM::for_table('tbl_user_recharges')
|
||||
->select('tbl_user_recharges.id', 'id')
|
||||
->select('customer_id')
|
||||
->select('username')
|
||||
->select('plan_id')
|
||||
->select('namebp')
|
||||
->select('recharged_on')
|
||||
->select('recharged_time')
|
||||
->select('expiration')
|
||||
->select('time')
|
||||
->select('status')
|
||||
->select('method')
|
||||
->select('plan_type')
|
||||
->select('tbl_user_recharges.routers', 'routers')
|
||||
->select('tbl_user_recharges.type', 'type')
|
||||
->select('admin_id')
|
||||
->select('prepaid')
|
||||
->selects([
|
||||
'customer_id', 'username', 'plan_id', 'namebp', 'recharged_on', 'recharged_time', 'expiration', 'time',
|
||||
'status', 'method', 'plan_type',
|
||||
['tbl_user_recharges.routers', 'routers'],
|
||||
['tbl_user_recharges.type', 'type'],
|
||||
'admin_id', 'prepaid'
|
||||
])
|
||||
->where('customer_id', $id)
|
||||
->join('tbl_plans', array('tbl_plans.id', '=', 'tbl_user_recharges.plan_id'))
|
||||
->find_many();
|
||||
|
@ -84,7 +84,6 @@ switch ($action) {
|
||||
}
|
||||
echo json_encode(['results' => $json]);
|
||||
die();
|
||||
break;
|
||||
default:
|
||||
$ui->display('a404.tpl');
|
||||
}
|
||||
|
@ -600,11 +600,20 @@ switch ($action) {
|
||||
|
||||
default:
|
||||
run_hook('list_customers'); #HOOK
|
||||
|
||||
$query = ORM::for_table('tbl_customers')->order_by_asc('username');
|
||||
$search = _post('search');
|
||||
if ($search != '') {
|
||||
$query = ORM::for_table('tbl_customers')
|
||||
->whereRaw("username LIKE '%$search%' OR fullname LIKE '%$search%' OR address LIKE '%$search%' ".
|
||||
"OR phonenumber LIKE '%$search%' OR email LIKE '%$search%' ")
|
||||
->order_by_asc('username');
|
||||
$d = $query->findMany();
|
||||
} else {
|
||||
$query = ORM::for_table('tbl_customers')->order_by_asc('username');
|
||||
}
|
||||
$d = $query->findMany();
|
||||
$ui->assign('xheader', '<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.11.3/css/jquery.dataTables.min.css">');
|
||||
$ui->assign('d', $d);
|
||||
$ui->assign('search', $search);
|
||||
$ui->display('customers.tpl');
|
||||
break;
|
||||
}
|
||||
|
@ -9,6 +9,17 @@ _admin();
|
||||
$ui->assign('_title', Lang::T('Dashboard'));
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
if(isset($_GET['refresh'])){
|
||||
$files = scandir($CACHE_PATH);
|
||||
foreach ($files as $file) {
|
||||
$ext = pathinfo($file, PATHINFO_EXTENSION);
|
||||
if (is_file($CACHE_PATH . DIRECTORY_SEPARATOR . $file) && $ext == 'temp') {
|
||||
unlink($CACHE_PATH . DIRECTORY_SEPARATOR . $file);
|
||||
}
|
||||
}
|
||||
r2(U . 'dashboard', 's', 'Data Refreshed');
|
||||
}
|
||||
|
||||
$fdate = date('Y-m-01');
|
||||
$tdate = date('Y-m-t');
|
||||
//first day of month
|
||||
|
@ -17,8 +17,14 @@ if (empty($action)) {
|
||||
|
||||
switch ($action) {
|
||||
case 'customer':
|
||||
|
||||
$c = ORM::for_table('tbl_customers')->find_many();
|
||||
if(!empty(_req('search'))){
|
||||
$search = _req('search');
|
||||
$query = ORM::for_table('tbl_customers')->whereRaw("coordinates != '' AND fullname LIKE '%$search%' OR username LIKE '%$search%' OR email LIKE '%$search%' OR phonenumber LIKE '%$search%'")->order_by_desc('fullname');
|
||||
$c = Paginator::findMany($query, ['search' => $search], 50);
|
||||
}else{
|
||||
$query = ORM::for_table('tbl_customers')->where_not_equal('coordinates','');
|
||||
$c = Paginator::findMany($query, ['search'=>''], 50);
|
||||
}
|
||||
$customerData = [];
|
||||
|
||||
foreach ($c as $customer) {
|
||||
@ -34,7 +40,7 @@ switch ($action) {
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$ui->assign('search', $search);
|
||||
$ui->assign('customers', $customerData);
|
||||
$ui->assign('xheader', '<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css">');
|
||||
$ui->assign('_title', Lang::T('Customer Geo Location Information'));
|
||||
|
@ -68,6 +68,12 @@ switch ($action) {
|
||||
if (isset($routes['2']) && !empty($routes['2'])) {
|
||||
$ui->assign('cust', ORM::for_table('tbl_customers')->find_one($routes['2']));
|
||||
}
|
||||
$usings = explode(',', $config['payment_usings']);
|
||||
$usings = array_filter(array_unique($usings));
|
||||
if(count($usings)==0){
|
||||
$usings[] = Lang::T('Cash');
|
||||
}
|
||||
$ui->assign('usings', $usings);
|
||||
run_hook('view_recharge'); #HOOK
|
||||
$ui->display('recharge.tpl');
|
||||
break;
|
||||
@ -146,7 +152,7 @@ switch ($action) {
|
||||
}
|
||||
|
||||
if ($msg == '') {
|
||||
$gateway = 'Recharge';
|
||||
$gateway = ucwords($using);
|
||||
$channel = $admin['fullname'];
|
||||
$cust = User::_info($id_customer);
|
||||
list($bills, $add_cost) = User::getBills($id_customer);
|
||||
@ -563,14 +569,27 @@ switch ($action) {
|
||||
}
|
||||
}
|
||||
run_hook('create_voucher'); #HOOK
|
||||
for ($i = 0; $i < $numbervoucher; $i++) {
|
||||
$code = strtoupper(substr(md5(time() . rand(10000, 99999)), 0, $lengthcode));
|
||||
if ($voucher_format == 'low') {
|
||||
$code = strtolower($code);
|
||||
} else if ($voucher_format == 'rand') {
|
||||
$code = Lang::randomUpLowCase($code);
|
||||
$vouchers = [];
|
||||
if($voucher_format == 'numbers'){
|
||||
if (strlen($lengthcode)<6) {
|
||||
$msg .= 'The Length Code must be a more than 6 for numbers' . '<br>';
|
||||
}
|
||||
die($code);
|
||||
$vouchers = generateUniqueNumericVouchers($numbervoucher, $lengthcode);
|
||||
}
|
||||
else {
|
||||
for ($i = 0; $i < $numbervoucher; $i++) {
|
||||
$code = strtoupper(substr(md5(time() . rand(10000, 99999)), 0, $lengthcode));
|
||||
if ($voucher_format == 'low') {
|
||||
$code = strtolower($code);
|
||||
} else if ($voucher_format == 'rand') {
|
||||
$code = Lang::randomUpLowCase($code);
|
||||
}
|
||||
$vouchers[] = $code;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
foreach($vouchers as $code){
|
||||
$d = ORM::for_table('tbl_voucher')->create();
|
||||
$d->type = $type;
|
||||
$d->routers = $server;
|
||||
@ -714,6 +733,14 @@ switch ($action) {
|
||||
}
|
||||
$user = _post('id_customer');
|
||||
$plan = _post('id_plan');
|
||||
$stoken = _req('stoken');
|
||||
if (App::getTokenValue($stoken)) {
|
||||
$c = ORM::for_table('tbl_customers')->where('id', $user)->find_one();
|
||||
$in = ORM::for_table('tbl_transactions')->where('username', $c['username'])->order_by_desc('id')->find_one();
|
||||
Package::createInvoice($in);
|
||||
$ui->display('invoice.tpl');
|
||||
die();
|
||||
}
|
||||
|
||||
run_hook('deposit_customer'); #HOOK
|
||||
if (!empty($user) && !empty($plan)) {
|
||||
@ -721,6 +748,9 @@ switch ($action) {
|
||||
$c = ORM::for_table('tbl_customers')->where('id', $user)->find_one();
|
||||
$in = ORM::for_table('tbl_transactions')->where('username', $c['username'])->order_by_desc('id')->find_one();
|
||||
Package::createInvoice($in);
|
||||
if(!empty($stoken)){
|
||||
App::setToken($stoken, $in['id']);
|
||||
}
|
||||
$ui->display('invoice.tpl');
|
||||
} else {
|
||||
r2(U . 'plan/refill', 'e', "Failed to refill account");
|
||||
@ -738,18 +768,18 @@ switch ($action) {
|
||||
}
|
||||
$tur = ORM::for_table('tbl_user_recharges')->find_one($id);
|
||||
$status = $tur['status'];
|
||||
if (strtotime($tur['expiration'] . ' ' . $tur['time']) > time()) {
|
||||
// not expired
|
||||
$expiration = date('Y-m-d', strtotime($tur['expiration'] . " +$days day"));
|
||||
} else {
|
||||
//expired
|
||||
$expiration = date('Y-m-d', strtotime(" +$days day"));
|
||||
}
|
||||
$tur->expiration = $expiration;
|
||||
$tur->status = "on";
|
||||
$tur->save();
|
||||
App::setToken($stoken, $id);
|
||||
if ($status == 'off') {
|
||||
if (strtotime($tur['expiration'] . ' ' . $tur['time']) > time()) {
|
||||
// not expired
|
||||
$expiration = date('Y-m-d', strtotime($tur['expiration'] . " +$days day"));
|
||||
} else {
|
||||
//expired
|
||||
$expiration = date('Y-m-d', strtotime(" +$days day"));
|
||||
}
|
||||
$tur->expiration = $expiration;
|
||||
$tur->status = "on";
|
||||
$tur->save();
|
||||
App::setToken($stoken, $id);
|
||||
if ($tur['routers'] != 'radius') {
|
||||
$mikrotik = Mikrotik::info($tur['routers']);
|
||||
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||
@ -761,21 +791,29 @@ switch ($action) {
|
||||
Radius::customerAddPlan($c, $p, $tur['expiration'] . ' ' . $tur['time']);
|
||||
} else {
|
||||
if ($tur['type'] == 'Hotspot') {
|
||||
Mikrotik::removeHotspotUser($client, $c['username']);
|
||||
Mikrotik::removeHotspotActiveUser($client, $c['username']);
|
||||
Mikrotik::addHotspotUser($client, $p, $c);
|
||||
} else if ($tur['type'] == 'PPPOE') {
|
||||
Mikrotik::removePpoeUser($client, $c['username']);
|
||||
Mikrotik::removePpoeActive($client, $c['username']);
|
||||
Mikrotik::addPpoeUser($client, $p, $c);
|
||||
}
|
||||
}
|
||||
_log("$admin[fullname] extend Customer $tur[customer_id] $tur[username] for $days days", $admin['user_type'], $admin['id']);
|
||||
r2(U . 'plan', 's', "Extend until $expiration");
|
||||
}else{
|
||||
r2(U . 'plan', 's', "Customer is not expired yet");
|
||||
}
|
||||
_log("$admin[fullname] extend Customer $tur[customer_id] $tur[username] for $days days", $admin['user_type'], $admin['id']);
|
||||
r2(U . 'plan', 's', "Extend until $expiration");
|
||||
break;
|
||||
default:
|
||||
$ui->assign('xfooter', '<script type="text/javascript" src="ui/lib/c/plan.js"></script>');
|
||||
$ui->assign('_title', Lang::T('Customer'));
|
||||
$search = _post('search');
|
||||
if ($search != '') {
|
||||
$query = ORM::for_table('tbl_user_recharges')->where_like('username', '%' . $search . '%')->order_by_desc('id');
|
||||
$query = ORM::for_table('tbl_user_recharges')
|
||||
->whereRaw("username LIKE '%$search%' OR namebp LIKE '%$search%' OR method LIKE '%$search%' OR routers LIKE '%$search%' OR type LIKE '%$search%'")
|
||||
->order_by_desc('id');
|
||||
$d = Paginator::findMany($query, ['search' => $search]);
|
||||
} else {
|
||||
$query = ORM::for_table('tbl_user_recharges')->order_by_desc('id');
|
||||
|
@ -38,7 +38,7 @@ switch ($action) {
|
||||
} else {
|
||||
$radup = '000000';
|
||||
}
|
||||
$radiusRate = $plan['rate_up'] . $radup . '/' . $plan['rate_down'] . $raddown;
|
||||
$radiusRate = $plan['rate_up'] . $radup . '/' . $plan['rate_down'] . $raddown . '/' . $plan['burst'];
|
||||
Radius::planUpSert($plan['id'], $radiusRate);
|
||||
$log .= "DONE : Radius $plan[name_plan], $plan[shared_users], $radiusRate<br>";
|
||||
} else {
|
||||
@ -83,7 +83,7 @@ switch ($action) {
|
||||
} else {
|
||||
$radup = '000000';
|
||||
}
|
||||
$radiusRate = $plan['rate_up'] . $radup . '/' . $plan['rate_down'] . $raddown;
|
||||
$radiusRate = $plan['rate_up'] . $radup . '/' . $plan['rate_down'] . $raddown . '/' . $plan['burst'];
|
||||
Radius::planUpSert($plan['id'], $radiusRate, $plan['pool']);
|
||||
$log .= "DONE : RADIUS $plan[name_plan], $plan[pool], $rate<br>";
|
||||
} else {
|
||||
@ -242,7 +242,7 @@ switch ($action) {
|
||||
$radup = '000000';
|
||||
}
|
||||
$rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown;
|
||||
$radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown;
|
||||
$radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown . '/' . $b['burst'];
|
||||
$rate = trim($rate . " " . $b['burst']);
|
||||
|
||||
// Check if tax is enabled in config
|
||||
@ -377,7 +377,7 @@ switch ($action) {
|
||||
$radup = '000000';
|
||||
}
|
||||
$rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown;
|
||||
$radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown;
|
||||
$radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown . '/' . $b['burst'];
|
||||
|
||||
$rate = trim($rate . " " . $b['burst']);
|
||||
|
||||
@ -576,7 +576,7 @@ switch ($action) {
|
||||
$radup = '000000';
|
||||
}
|
||||
$rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown;
|
||||
$radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown;
|
||||
$radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown . '/' . $b['burst'];
|
||||
$rate = trim($rate . " " . $b['burst']);
|
||||
|
||||
// Check if tax is enabled in config
|
||||
@ -699,7 +699,7 @@ switch ($action) {
|
||||
$radup = '000000';
|
||||
}
|
||||
$rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown;
|
||||
$radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown;
|
||||
$radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown . '/' . $b['burst'];
|
||||
$rate = trim($rate . " " . $b['burst']);
|
||||
|
||||
if ($d['is_radius']) {
|
||||
|
@ -67,7 +67,7 @@ foreach ($d as $ds) {
|
||||
}
|
||||
}
|
||||
if ($p && $p['enabled'] && $c['balance'] >= $p['price']) {
|
||||
if (Package::rechargeUser($ds['customer_id'], $p['routers'], $p['id'], 'Customer', 'Balance')) {
|
||||
if (Package::rechargeUser($ds['customer_id'], $ds['routers'], $p['id'], 'Customer', 'Balance')) {
|
||||
// if success, then get the balance
|
||||
Balance::min($ds['customer_id'], $p['price']);
|
||||
echo "plan enabled: $p[enabled] | User balance: $c[balance] | price $p[price]\n";
|
||||
@ -127,7 +127,7 @@ foreach ($d as $ds) {
|
||||
}
|
||||
}
|
||||
if ($p && $p['enabled'] && $c['balance'] >= $p['price']) {
|
||||
if (Package::rechargeUser($ds['customer_id'], $p['routers'], $p['id'], 'Customer', 'Balance')) {
|
||||
if (Package::rechargeUser($ds['customer_id'], $ds['routers'], $p['id'], 'Customer', 'Balance')) {
|
||||
// if success, then get the balance
|
||||
Balance::min($ds['customer_id'], $p['price']);
|
||||
echo "plan enabled: $p[enabled] | User balance: $c[balance] | price $p[price]\n";
|
||||
@ -144,4 +144,4 @@ foreach ($d as $ds) {
|
||||
} else
|
||||
echo " : ACTIVE \r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -577,5 +577,8 @@
|
||||
"Extend_Days": "Extend Days",
|
||||
"Confirmation_Message": "Confirmation Message",
|
||||
"You_are_already_logged_in": "You are already logged in",
|
||||
"Extend": "Extend"
|
||||
"Extend": "Extend",
|
||||
"Created___Expired": "Created \/ Expired",
|
||||
"Bank_Transfer": "Bank Transfer",
|
||||
"Recharge_Using": "Recharge Using"
|
||||
}
|
5204
system/orm.php
5204
system/orm.php
File diff suppressed because it is too large
Load Diff
@ -86,6 +86,13 @@
|
||||
href="https://github.com/hotspotbilling/phpnuxbill/wiki/Themes" target="_blank">Theme
|
||||
info</a></p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Recharge Using')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="text" name="payment_usings" class="form-control" value="{$_c['payment_usings']}" placeholder="{Lang::T('Cash')}, {Lang::T('Bank Transfer')}">
|
||||
</div>
|
||||
<p class="help-block col-md-4">This used for admin to select payment in recharge, using comma for every new options</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">APP URL</label>
|
||||
<div class="col-md-6">
|
||||
@ -152,6 +159,10 @@
|
||||
<option value="rand" {if $_c['voucher_format']=='rand' }selected="selected" {/if}>
|
||||
RaNdoM
|
||||
</option>
|
||||
<option value="numbers" {if $_c['voucher_format'] == 'numbers'}selected="selected"
|
||||
{/if}>
|
||||
Numbers
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<p class="help-block col-md-4">UPPERCASE lowercase RaNdoM</p>
|
||||
@ -234,13 +245,15 @@
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Extend Days')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="text" class="form-control" name="extend_days" placeholder="3" value="{$_c['extend_days']}">
|
||||
<input type="text" class="form-control" name="extend_days" placeholder="3"
|
||||
value="{$_c['extend_days']}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Confirmation Message')}</label>
|
||||
<div class="col-md-6">
|
||||
<textarea type="text" rows="4" class="form-control" name="extend_confirmation" placeholder="i agree to extends and will paid full after this">{$_c['extend_confirmation']}</textarea>
|
||||
<textarea type="text" rows="4" class="form-control" name="extend_confirmation"
|
||||
placeholder="i agree to extends and will paid full after this">{$_c['extend_confirmation']}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,58 +1,65 @@
|
||||
{include file="sections/header.tpl"}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="panel panel-hovered mb20 panel-primary">
|
||||
<div class="panel-heading">{Lang::T('Bandwidth Plans')}</div>
|
||||
<div class="panel-body">
|
||||
<div class="md-whiteframe-z1 mb20 text-center" style="padding: 15px">
|
||||
<div class="col-md-8">
|
||||
<form id="site-search" method="post" action="{$_url}bandwidth/list/">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">
|
||||
<span class="fa fa-search"></span>
|
||||
</div>
|
||||
<input type="text" name="name" class="form-control" placeholder="{Lang::T('Search by Name')}...">
|
||||
<div class="input-group-btn">
|
||||
<button class="btn btn-success" type="submit">{Lang::T('Search')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<a href="{$_url}bandwidth/add" class="btn btn-primary btn-block"><i class="ion ion-android-add"> </i> {Lang::T('New Bandwidth')}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-condensed table-striped table_mobile">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{Lang::T('Bandwidth Name')}</th>
|
||||
<th>{Lang::T('Rate')}</th>
|
||||
<th>{Lang::T('Burst')}</th>
|
||||
<th>{Lang::T('Manage')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{foreach $d as $ds}
|
||||
<tr>
|
||||
<td>{$ds['name_bw']}</td>
|
||||
<td>{$ds['rate_down']} {$ds['rate_down_unit']} / {$ds['rate_up']} {$ds['rate_up_unit']}</td>
|
||||
<td>{$ds['burst']}</td>
|
||||
<td>
|
||||
<a href="{$_url}bandwidth/edit/{$ds['id']}" class="btn btn-sm btn-warning">{Lang::T('Edit')}</a>
|
||||
<a href="{$_url}bandwidth/delete/{$ds['id']}" id="{$ds['id']}" class="btn btn-danger btn-sm" onclick="return confirm('{Lang::T('Delete')}?')" ><i class="glyphicon glyphicon-trash"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{include file="pagination.tpl"}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="panel panel-hovered mb20 panel-primary">
|
||||
<div class="panel-heading">{Lang::T('Bandwidth Plans')}</div>
|
||||
<div class="panel-body">
|
||||
<div class="md-whiteframe-z1 mb20 text-center" style="padding: 15px">
|
||||
<div class="col-md-8">
|
||||
<form id="site-search" method="post" action="{$_url}bandwidth/list/">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">
|
||||
<span class="fa fa-search"></span>
|
||||
</div>
|
||||
<input type="text" name="name" class="form-control"
|
||||
placeholder="{Lang::T('Search by Name')}...">
|
||||
<div class="input-group-btn">
|
||||
<button class="btn btn-success" type="submit">{Lang::T('Search')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<a href="{$_url}bandwidth/add" class="btn btn-primary btn-block"><i class="ion ion-android-add">
|
||||
</i> {Lang::T('New Bandwidth')}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-condensed table-striped table_mobile">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{Lang::T('Bandwidth Name')}</th>
|
||||
<th>{Lang::T('Rate')}</th>
|
||||
<th>{Lang::T('Burst')}</th>
|
||||
<th>{Lang::T('Manage')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{foreach $d as $ds}
|
||||
<tr>
|
||||
<td>{$ds['name_bw']}</td>
|
||||
<td>{$ds['rate_down']} {$ds['rate_down_unit']} / {$ds['rate_up']} {$ds['rate_up_unit']}
|
||||
</td>
|
||||
<td>{$ds['burst']}</td>
|
||||
<td>
|
||||
<a href="{$_url}bandwidth/edit/{$ds['id']}"
|
||||
class="btn btn-sm btn-warning">{Lang::T('Edit')}</a>
|
||||
<a href="{$_url}bandwidth/delete/{$ds['id']}" id="{$ds['id']}"
|
||||
class="btn btn-danger btn-sm"
|
||||
onclick="return confirm('{Lang::T('Delete')}?')"><i
|
||||
class="glyphicon glyphicon-trash"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{include file="pagination.tpl"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{include file="sections/footer.tpl"}
|
@ -1,8 +1,24 @@
|
||||
{include file="sections/header.tpl"}
|
||||
|
||||
<!-- Map container div -->
|
||||
|
||||
<div id="map" class="well" style="width: '100%'; height: 78vh; margin: 20px auto"></div>
|
||||
<form id="site-search" method="post" action="{$_url}map/customer/">
|
||||
<input type="hidden" name="_route" value="map/customer">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">
|
||||
<span class="fa fa-search"></span>
|
||||
</div>
|
||||
<input type="text" name="search" class="form-control" value="{$search}"
|
||||
placeholder="{Lang::T('Search')}...">
|
||||
<div class="input-group-btn">
|
||||
<button class="btn btn-success" type="submit">{Lang::T('Search')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Map container div -->
|
||||
<div id="map" class="well" style="width: '100%'; height: 70vh; margin: 20px auto"></div>
|
||||
|
||||
{include file="pagination.tpl"}
|
||||
|
||||
{literal}
|
||||
<script>
|
||||
@ -29,31 +45,31 @@
|
||||
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>',
|
||||
subdomains: 'abcd',
|
||||
maxZoom: 20
|
||||
}).addTo(map);
|
||||
}).addTo(map);
|
||||
|
||||
customers.forEach(function(customer) {
|
||||
var name = customer.id;
|
||||
var name = customer.name;
|
||||
var info = customer.info;
|
||||
var direction = customer.direction;
|
||||
var coordinates = customer.coordinates;
|
||||
var balance = customer.balance;
|
||||
var address = customer.address;
|
||||
customers.forEach(function(customer) {
|
||||
var name = customer.id;
|
||||
var name = customer.name;
|
||||
var info = customer.info;
|
||||
var direction = customer.direction;
|
||||
var coordinates = customer.coordinates;
|
||||
var balance = customer.balance;
|
||||
var address = customer.address;
|
||||
|
||||
// Create a popup for the marker
|
||||
var popupContent = "<strong>Name</strong>: " + name + "<br>" +
|
||||
"<strong>Info</strong>: " + info + "<br>" +
|
||||
"<strong>Balance</strong>: " + balance + "<br>" +
|
||||
"<strong>Address</strong>: " + address + "<br>" +
|
||||
"<a href='{/literal}{$_url}{literal}customers/view/"+ customer.id +"'>More Info</a> • " +
|
||||
"<a href='https://www.google.com/maps/dir//" + direction + "' target='maps'>Get Direction</a><br>";
|
||||
// Create a popup for the marker
|
||||
var popupContent = "<strong>Name</strong>: " + name + "<br>" +
|
||||
"<strong>Info</strong>: " + info + "<br>" +
|
||||
"<strong>Balance</strong>: " + balance + "<br>" +
|
||||
"<strong>Address</strong>: " + address + "<br>" +
|
||||
"<a href='{/literal}{$_url}{literal}customers/view/"+ customer.id +"'>More Info</a> • " +
|
||||
"<a href='https://www.google.com/maps/dir//" + direction + "' target='maps'>Get Direction</a><br>";
|
||||
|
||||
// Add marker to map
|
||||
var marker = L.marker(JSON.parse(coordinates)).addTo(group);
|
||||
marker.bindTooltip(name, { permanent: true }).bindPopup(popupContent);
|
||||
});
|
||||
// Add marker to map
|
||||
var marker = L.marker(JSON.parse(coordinates)).addTo(group);
|
||||
marker.bindTooltip(name, { permanent: true }).bindPopup(popupContent);
|
||||
});
|
||||
|
||||
map.fitBounds(group.getBounds());
|
||||
map.fitBounds(group.getBounds());
|
||||
}
|
||||
window.onload = function() {
|
||||
getLocation();
|
||||
|
@ -27,7 +27,18 @@
|
||||
<div class="panel-body">
|
||||
<div class="md-whiteframe-z1 mb20 text-center" style="padding: 15px">
|
||||
<div class="col-md-8">
|
||||
|
||||
<form id="site-search" method="post" action="{$_url}customers">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">
|
||||
<span class="fa fa-search"></span>
|
||||
</div>
|
||||
<input type="text" name="search" class="form-control"
|
||||
placeholder="{Lang::T('Search')}..." value="{$search}">
|
||||
<div class="input-group-btn">
|
||||
<button class="btn btn-success" type="submit">{Lang::T('Search')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<a href="{$_url}customers/add" class="btn btn-primary btn-block"><i class="ion ion-android-add">
|
||||
|
@ -74,8 +74,7 @@
|
||||
<div class="box-tools pull-right">
|
||||
<button type="button" class="btn bg-teal btn-sm" data-widget="collapse"><i class="fa fa-minus"></i>
|
||||
</button>
|
||||
<a href="{$_url}settings/app#hide_dashboard_content" class="btn bg-teal btn-sm"><i
|
||||
class="fa fa-times"></i>
|
||||
<a href="{$_url}dashboard&refresh" class="btn bg-teal btn-sm"><i class="fa fa-refresh"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@ -96,8 +95,7 @@
|
||||
<div class="box-tools pull-right">
|
||||
<button type="button" class="btn bg-teal btn-sm" data-widget="collapse"><i class="fa fa-minus"></i>
|
||||
</button>
|
||||
<a href="{$_url}settings/app#hide_dashboard_content" class="btn bg-teal btn-sm"><i
|
||||
class="fa fa-times"></i>
|
||||
<a href="{$_url}dashboard&refresh" class="btn bg-teal btn-sm"><i class="fa fa-refresh"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@ -146,18 +144,24 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{Lang::T('Username')}</th>
|
||||
<th>{Lang::T('Created On')}</th>
|
||||
<th>{Lang::T('Expires On')}</th>
|
||||
<th>{Lang::T('Created / Expired')}</th>
|
||||
<th>{Lang::T('Internet Plan')}</th>
|
||||
<th>{Lang::T('Location')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{foreach $expire as $expired}
|
||||
{assign var="rem_exp" value="{$expired['expiration']} {$expired['time']}"}
|
||||
{assign var="rem_started" value="{$expired['recharged_on']} {$expired['recharged_time']}"}
|
||||
<tr>
|
||||
<td><a href="{$_url}customers/viewu/{$expired['username']}">{$expired['username']}</a></td>
|
||||
<td>{Lang::dateAndTimeFormat($expired['recharged_on'],$expired['recharged_time'])}
|
||||
</td>
|
||||
<td>{Lang::dateAndTimeFormat($expired['expiration'],$expired['time'])}
|
||||
<td><small data-toggle="tooltip" data-placement="top"
|
||||
title="{Lang::dateAndTimeFormat($expired['recharged_on'],$expired['recharged_time'])}">{Lang::timeElapsed($rem_started)}</small> /
|
||||
<span data-toggle="tooltip" data-placement="top"
|
||||
title="{Lang::dateAndTimeFormat($expired['expiration'],$expired['time'])}">{Lang::timeElapsed($rem_exp)}</span>
|
||||
</td>
|
||||
<td>{$expired['namebp']}</td>
|
||||
<td>{$expired['routers']}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
{/foreach}
|
||||
@ -381,6 +385,21 @@
|
||||
var latestVersion = data.version;
|
||||
if (localVersion !== latestVersion) {
|
||||
$('#version').html('Latest Version: ' + latestVersion);
|
||||
Swal.fire({
|
||||
icon: 'info',
|
||||
title: "New Version Available\nVersion: "+latestVersion,
|
||||
toast: true,
|
||||
position: 'bottom-right',
|
||||
showConfirmButton: true,
|
||||
showCloseButton: true,
|
||||
timer: 30000,
|
||||
confirmButtonText: '<a href="{$_url}community#latestVersion" style="color: white;">Update Now</a>',
|
||||
timerProgressBar: true,
|
||||
didOpen: (toast) => {
|
||||
toast.addEventListener('mouseenter', Swal.stopTimer)
|
||||
toast.addEventListener('mouseleave', Swal.resumeTimer)
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -6,6 +6,7 @@
|
||||
<div class="panel-heading">{Lang::T('Refill Balance')}</div>
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" method="post" role="form" action="{$_url}plan/deposit-post">
|
||||
<input type="hidden" name="stoken" value="{App::getToken()}">
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Select Account')}</label>
|
||||
<div class="col-md-6">
|
||||
|
@ -59,7 +59,7 @@
|
||||
<div class="col-md-10">
|
||||
<input type="radio" id="Unlimited" name="typebp" value="Unlimited"
|
||||
{if $d['typebp'] eq 'Unlimited'} checked {/if}> {Lang::T('Unlimited')}
|
||||
<input type="radio" id="Limited" {if $_c['radius_enable'] and $d['is_radius']}disabled{/if}
|
||||
<input type="radio" id="Limited"
|
||||
name="typebp" value="Limited" {if $d['typebp'] eq 'Limited'} checked {/if}>
|
||||
{Lang::T('Limited')}
|
||||
</div>
|
||||
|
@ -45,7 +45,6 @@
|
||||
<tr>
|
||||
<th>{Lang::T('Username')}</th>
|
||||
<th>{Lang::T('Plan Name')}</th>
|
||||
<th>{Lang::T('Plan Type')}</th>
|
||||
<th>{Lang::T('Type')}</th>
|
||||
<th>{Lang::T('Created On')}</th>
|
||||
<th>{Lang::T('Expires On')}</th>
|
||||
@ -60,7 +59,6 @@
|
||||
<td><a href="{$_url}customers/viewu/{$ds['username']}">{$ds['username']}</a></td>
|
||||
<td>{$ds['namebp']}</td>
|
||||
<td>{$ds['type']}</td>
|
||||
<td>{$ds['plan_type']}</td>
|
||||
<td>{Lang::dateAndTimeFormat($ds['recharged_on'],$ds['recharged_time'])}</td>
|
||||
<td>{Lang::dateAndTimeFormat($ds['expiration'],$ds['time'])}</td>
|
||||
<td>{$ds['method']}</td>
|
||||
|
@ -45,7 +45,9 @@
|
||||
<label class="col-md-2 control-label">{Lang::T('Using')}</label>
|
||||
<div class="col-md-6">
|
||||
<select name="using" class="form-control">
|
||||
<option value="cash">{Lang::T('Cash')}</option>
|
||||
{foreach $usings as $using}
|
||||
<option value="{trim(ucWords($using))}">{trim(ucWords($using))}</option>
|
||||
{/foreach}
|
||||
{if $_c['enable_balance'] eq 'yes'}
|
||||
<option value="balance">{Lang::T('Customer Balance')}</option>
|
||||
{/if}
|
||||
|
@ -86,6 +86,10 @@
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
$(function() {
|
||||
$('[data-toggle="tooltip"]').tooltip()
|
||||
})
|
||||
</script>
|
||||
{/literal}
|
||||
|
||||
|
@ -419,4 +419,4 @@
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{/if}
|
||||
{/if}
|
@ -41,6 +41,10 @@
|
||||
<label class="col-md-2 control-label">{Lang::T('Voucher Format')}</label>
|
||||
<div class="col-md-6">
|
||||
<select name="voucher_format" id="voucher_format" class="form-control">
|
||||
<option value="numbers" {if $_c['voucher_format'] == 'numbers'}selected="selected"
|
||||
{/if}>
|
||||
Numbers
|
||||
</option>
|
||||
<option value="up" {if $_c['voucher_format'] == 'up'}selected="selected" {/if}>UPPERCASE
|
||||
</option>
|
||||
<option value="low" {if $_c['voucher_format'] == 'low'}selected="selected" {/if}>
|
||||
@ -56,7 +60,8 @@
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Voucher Prefix')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="text" class="form-control" name="prefix" placeholder="NUX-" value="{$_c['voucher_prefix']}">
|
||||
<input type="text" class="form-control" name="prefix" placeholder="NUX-"
|
||||
value="{$_c['voucher_prefix']}">
|
||||
</div>
|
||||
<p class="help-block col-md-4">NUX-VoUCHeRCOdE</p>
|
||||
</div>
|
||||
@ -68,8 +73,7 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-lg-offset-2 col-lg-10">
|
||||
<button class="btn btn-success"
|
||||
type="submit">{Lang::T('Generate')}</button>
|
||||
<button class="btn btn-success" type="submit">{Lang::T('Generate')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -79,4 +83,4 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{include file="sections/footer.tpl"}
|
||||
{include file="sections/footer.tpl"}
|
||||
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"version": "2024.4.23"
|
||||
"version": "2024.5.14"
|
||||
}
|
Reference in New Issue
Block a user