diff --git a/.gitignore b/.gitignore index 85d079af..8d917f5a 100644 --- a/.gitignore +++ b/.gitignore @@ -20,7 +20,9 @@ system/plugin/ui/* ui/ui_custom/** !ui/ui_custom/index.html !ui/ui_custom/README.md -system/uploads/admin.png -system/uploads/logo.png -system/uploads/user.jpg -system/uploads/notifications.json \ No newline at end of file +system/uploads/** +!system/uploads/*.default.png +system/uploads/sms/** +!system/uploads/sms/index.html +system/uploads/system/** +!system/uploads/system/index.html \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 487e4c9c..586403e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,49 @@ # CHANGELOG +## 2023.9.15 + +- Fix Customer balance header +- Deactivate Customer active plan +- Sync Customer Plan to Mikrotik +- Recharge Customer from Customer Details + +## 2023.9.13 + +- add Current balance in notification +- Buy Plan for Friend +- Recharge Friend plan +- Fix recharge Plan +- Show Customer active plan in Customer list +- Fix Customer counter in dashboard +- Show Customer Balance in header +- Fix Plugin Manager using Http::Get +- Show Some error page when crash +## 2023.9.7 + +- Fix PPPOE Delete Customer +- Remove active Customer before deleting +- Show IP and Mac even if it not Hotspot + +## 2023.9.6 + +- Expired Pool +Customer can be move to expired pool after plan expired by cron +- Fix Delete customer +- tbl_language removed + +## 2023.9.1.1 + +- Fix cronjob Delete customer +- Fix reminder text + +## 2023.9.1 + +- Critical bug fixes, bug happen when user buy package, expired time will be calculated from last expired, not from when they buy the package +- Time not change after user buy package for extending +- Add Cancel Button to user dashboard when it show unpaid package +- Fix username in user dashboard + ## 2023.8.30 - Upload Logo from settings diff --git a/Sample/Voucher_after_print.jpg b/Sample/Voucher_after_print.jpg deleted file mode 100644 index 553b2ba8..00000000 Binary files a/Sample/Voucher_after_print.jpg and /dev/null differ diff --git a/Sample/Voucher_before_Printed.png b/Sample/Voucher_before_Printed.png deleted file mode 100644 index 8d4a9985..00000000 Binary files a/Sample/Voucher_before_Printed.png and /dev/null differ diff --git a/Sample/dont_upload_to_server b/Sample/dont_upload_to_server deleted file mode 100644 index e69de29b..00000000 diff --git a/install/phpnuxbill.sql b/install/phpnuxbill.sql index c2c2127b..941ea5a3 100644 --- a/install/phpnuxbill.sql +++ b/install/phpnuxbill.sql @@ -65,22 +65,6 @@ CREATE TABLE -- --- Struktur dari tabel `tbl_language` - --- - -CREATE TABLE - `tbl_language` ( - `id` int(10) NOT NULL, - `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `folder` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `author` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL - ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci; - --- -------------------------------------------------------- - --- - -- Struktur dari tabel `tbl_logs` -- @@ -174,6 +158,7 @@ CREATE TABLE `shared_users` int(10) DEFAULT NULL, `routers` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `pool` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `pool_expired` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '', `enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0 disabled\r\n' ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci; @@ -345,14 +330,6 @@ ALTER TABLE `tbl_customers` ADD PRIMARY KEY (`id`); -- --- Indeks untuk tabel `tbl_language` - --- - -ALTER TABLE `tbl_language` ADD PRIMARY KEY (`id`); - --- - -- Indeks untuk tabel `tbl_logs` -- @@ -466,15 +443,6 @@ ALTER TABLE -- --- AUTO_INCREMENT untuk tabel `tbl_language` - --- - -ALTER TABLE - `tbl_language` MODIFY `id` int(10) NOT NULL AUTO_INCREMENT; - --- - -- AUTO_INCREMENT untuk tabel `tbl_logs` -- @@ -610,39 +578,4 @@ VALUES ( 'Active', '2022-09-06 16:09:50', '2014-06-23 01:43:07' - ); - --- - --- Dumping data untuk tabel `tbl_language` - --- - -INSERT INTO - `tbl_language` ( - `id`, - `name`, - `folder`, - `author` - ) -VALUES ( - 1, - 'Indonesia', - 'indonesia', - 'Ismail Marzuqi' - ), ( - 2, - 'English', - 'english', - 'Ismail Marzuqi' - ), ( - 3, - 'Spanish', - 'spanish', - 'Luis Hernandez' - ), ( - 4, - 'Türkçe', - 'turkish', - 'Goktug Bogac Ogel' ); \ No newline at end of file diff --git a/system/autoload/Balance.php b/system/autoload/Balance.php index f6557a3f..208551c1 100644 --- a/system/autoload/Balance.php +++ b/system/autoload/Balance.php @@ -19,12 +19,7 @@ class Balance { global $config; if (Balance::min($id_customer, $amount)) { - if (Balance::plusByPhone($phoneTarget, $amount)) { - return true; - } else { - Balance::plus($id_customer, $amount); - return false; - } + return Balance::plusByPhone($phoneTarget, $amount); } else { return false; } diff --git a/system/autoload/Http.php b/system/autoload/Http.php index e4b1982e..2dd21acd 100644 --- a/system/autoload/Http.php +++ b/system/autoload/Http.php @@ -2,12 +2,17 @@ /** * PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/) + * using proxy, add this variable in config.php + * $http_proxy = '127.0.0.1:3128'; + * if proxy using authentication, use this parameter + * $http_proxyauth = 'user:password'; **/ class Http { - public static function getData($url, $headers) + public static function getData($url, $headers = []) { + global $http_proxy, $http_proxyauth, $admin; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, 0); @@ -15,13 +20,26 @@ class Http curl_setopt($ch, CURLOPT_TIMEOUT, 15); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + if (!empty($http_proxy)) { + curl_setopt($ch, CURLOPT_PROXY, $http_proxy); + if (!empty($http_proxyauth)) { + curl_setopt($ch, CURLOPT_PROXYUSERPWD, $http_proxyauth); + } + } $server_output = curl_exec($ch); + if (curl_errno($ch)) { + $error_msg = curl_error($ch); + } curl_close($ch); - return $server_output; + if($admin && $error_msg){ + r2(U . 'dashboard', 'd', $error_msg); + } + return ($server_output) ? $server_output : $error_msg; } public static function postJsonData($url, $array_post, $headers = [], $basic = null) { + global $http_proxy, $http_proxyauth, $admin; $headers[] = 'Content-Type: application/json'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); @@ -30,6 +48,12 @@ class Http curl_setopt($ch, CURLOPT_TIMEOUT, 15); curl_setopt($ch, CURLOPT_VERBOSE, false); curl_setopt($ch, CURLINFO_HEADER_OUT, false); + if (!empty($http_proxy)) { + curl_setopt($ch, CURLOPT_PROXY, $http_proxy); + if (!empty($http_proxyauth)) { + curl_setopt($ch, CURLOPT_PROXYUSERPWD, $http_proxyauth); + } + } curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($array_post)); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); if (!empty($basic)) { @@ -37,13 +61,20 @@ class Http } curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $server_output = curl_exec($ch); + if (curl_errno($ch)) { + $error_msg = curl_error($ch); + } curl_close($ch); - return $server_output; + if($admin && $error_msg){ + r2(U . 'dashboard', 'd', $error_msg); + } + return ($server_output) ? $server_output : $error_msg; } public static function postData($url, $array_post, $headers = [], $basic = null) { + global $http_proxy, $http_proxyauth, $admin; $headers[] = 'Content-Type: application/x-www-form-urlencoded'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); @@ -52,6 +83,12 @@ class Http curl_setopt($ch, CURLOPT_TIMEOUT, 15); curl_setopt($ch, CURLOPT_VERBOSE, false); curl_setopt($ch, CURLINFO_HEADER_OUT, false); + if (!empty($http_proxy)) { + curl_setopt($ch, CURLOPT_PROXY, $http_proxy); + if (!empty($http_proxyauth)) { + curl_setopt($ch, CURLOPT_PROXYUSERPWD, $http_proxyauth); + } + } curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($array_post)); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); if (!empty($basic)) { @@ -59,7 +96,13 @@ class Http } curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $server_output = curl_exec($ch); + if (curl_errno($ch)) { + $error_msg = curl_error($ch); + } curl_close($ch); - return $server_output; + if($admin && $error_msg){ + r2(U . 'dashboard', 'd', $error_msg); + } + return ($server_output) ? $server_output : $error_msg; } } diff --git a/system/autoload/Lang.php b/system/autoload/Lang.php index 5d9b707a..de8dca4c 100644 --- a/system/autoload/Lang.php +++ b/system/autoload/Lang.php @@ -39,7 +39,11 @@ class Lang public static function dateTimeFormat($date){ global $config; - return date($config['date_format']. ' H:i', strtotime($date)); + if(strtotime($date) < strtotime("2000-01-01 00:00:00")){ + return ""; + }else{ + return date($config['date_format']. ' H:i', strtotime($date)); + } } public static function dateAndTimeFormat($date, $time){ diff --git a/system/autoload/Message.php b/system/autoload/Message.php index 15981d06..71fb36f4 100644 --- a/system/autoload/Message.php +++ b/system/autoload/Message.php @@ -12,7 +12,7 @@ class Message global $config; run_hook('send_telegram'); #HOOK if (!empty($config['telegram_bot']) && !empty($config['telegram_target_id'])) { - file_get_contents('https://api.telegram.org/bot' . $config['telegram_bot'] . '/sendMessage?chat_id=' . $config['telegram_target_id'] . '&text=' . urlencode($txt)); + Http::getData('https://api.telegram.org/bot' . $config['telegram_bot'] . '/sendMessage?chat_id=' . $config['telegram_target_id'] . '&text=' . urlencode($txt)); } } @@ -24,7 +24,7 @@ class Message if (!empty($config['sms_url'])) { $smsurl = str_replace('[number]', urlencode($phone), $config['sms_url']); $smsurl = str_replace('[text]', urlencode($txt), $smsurl); - file_get_contents($smsurl); + Http::getData($smsurl); } } @@ -35,7 +35,7 @@ class Message if (!empty($config['wa_url'])) { $waurl = str_replace('[number]', urlencode($phone), $config['wa_url']); $waurl = str_replace('[text]', urlencode($txt), $waurl); - file_get_contents($waurl); + Http::getData($waurl); } } @@ -56,9 +56,10 @@ class Message return "$via: $msg"; } - public static function sendBalanceNotification($phone, $name, $balance, $message, $via) + public static function sendBalanceNotification($phone, $name, $balance, $balance_now, $message, $via) { $msg = str_replace('[[name]]', "*$name*", $message); + $msg = str_replace('[[current_balance]]', Lang::moneyFormat($balance_now), $msg); $msg = str_replace('[[balance]]', "*" . Lang::moneyFormat($balance) . "*", $msg); if ( !empty($phone) && strlen($phone) > 5 diff --git a/system/autoload/Mikrotik.php b/system/autoload/Mikrotik.php index a965e785..b6707dc2 100644 --- a/system/autoload/Mikrotik.php +++ b/system/autoload/Mikrotik.php @@ -17,7 +17,8 @@ class Mikrotik $iport = explode(":", $ip); return new RouterOS\Client($iport[0], $user, $pass, ($iport[1]) ? $iport[1] : null); } catch (Exception $e) { - $ui->assign("error_meesage","Unable to connect to the router.
" . $e->getMessage()); + $ui->assign("error_title", "Mikrotik Connection Error"); + $ui->assign("error_message", "Unable to connect to the router.
" . $e->getMessage()); $ui->display('router-error.tpl'); die(); } @@ -72,46 +73,77 @@ class Mikrotik public static function setHotspotPlan($client, $name, $sharedusers, $rate) { $printRequest = new RouterOS\Request( - '/ip hotspot user profile print .proplist=name', + '/ip hotspot user profile print .proplist=.id', RouterOS\Query::where('name', $name) ); - $profileName = $client->sendSync($printRequest)->getProperty('name'); + $profileID = $client->sendSync($printRequest)->getProperty('.id'); + if (empty($profileID)) { + Mikrotik::addHotspotPlan($client, $name, $sharedusers, $rate); + }else{ + $setRequest = new RouterOS\Request('/ip/hotspot/user/profile/set'); + $client( + $setRequest + ->setArgument('numbers', $profileID) + ->setArgument('shared-users', $sharedusers) + ->setArgument('rate-limit', $rate) + ); + } + } - $setRequest = new RouterOS\Request('/ip/hotspot/user/profile/set'); - $client( - $setRequest - ->setArgument('numbers', $profileName) - ->setArgument('shared-users', $sharedusers) - ->setArgument('rate-limit', $rate) + public static function setHotspotExpiredPlan($client, $name, $pool) + { + $printRequest = new RouterOS\Request( + '/ip hotspot user profile print .proplist=.id', + RouterOS\Query::where('name', $name) ); + $profileID = $client->sendSync($printRequest)->getProperty('.id'); + if (empty($profileID)) { + $addRequest = new RouterOS\Request('/ip/hotspot/user/profile/add'); + $client->sendSync( + $addRequest + ->setArgument('name', $name) + ->setArgument('shared-users', 3) + ->setArgument('address-pool', $pool) + ->setArgument('rate-limit', '512K/512K') + ); + }else{ + $setRequest = new RouterOS\Request('/ip/hotspot/user/profile/set'); + $client( + $setRequest + ->setArgument('numbers', $profileID) + ->setArgument('shared-users', 3) + ->setArgument('address-pool', $pool) + ->setArgument('rate-limit', '512K/512K') + ); + } } public static function removeHotspotPlan($client, $name) { $printRequest = new RouterOS\Request( - '/ip hotspot user profile print .proplist=name', + '/ip hotspot user profile print .proplist=.id', RouterOS\Query::where('name', $name) ); - $profileName = $client->sendSync($printRequest)->getProperty('name'); + $profileID = $client->sendSync($printRequest)->getProperty('.id'); $removeRequest = new RouterOS\Request('/ip/hotspot/user/profile/remove'); $client( $removeRequest - ->setArgument('numbers', $profileName) + ->setArgument('numbers', $profileID) ); } public static function removeHotspotUser($client, $username) { $printRequest = new RouterOS\Request( - '/ip hotspot user print .proplist=name', + '/ip hotspot user print .proplist=.id', RouterOS\Query::where('name', $username) ); - $userName = $client->sendSync($printRequest)->getProperty('name'); + $userID = $client->sendSync($printRequest)->getProperty('.id'); $removeRequest = new RouterOS\Request('/ip/hotspot/user/remove'); $client( $removeRequest - ->setArgument('numbers', $userName) + ->setArgument('numbers', $userID) ); } @@ -179,7 +211,7 @@ class Mikrotik } } - public static function setHotspotUser($client, $user, $pass, $nuser = null) + public static function setHotspotUser($client, $user, $pass) { $printRequest = new RouterOS\Request('/ip/hotspot/user/print'); $printRequest->setArgument('.proplist', '.id'); @@ -192,6 +224,19 @@ class Mikrotik $client->sendSync($setRequest); } + public static function setHotspotUserPackage($client, $user, $plan) + { + $printRequest = new RouterOS\Request('/ip/hotspot/user/print'); + $printRequest->setArgument('.proplist', '.id'); + $printRequest->setQuery(RouterOS\Query::where('name', $user)); + $id = $client->sendSync($printRequest)->getProperty('.id'); + + $setRequest = new RouterOS\Request('/ip/hotspot/user/set'); + $setRequest->setArgument('numbers', $id); + $setRequest->setArgument('profile', $plan); + $client->sendSync($setRequest); + } + public static function removeHotspotActiveUser($client, $username) { $onlineRequest = new RouterOS\Request('/ip/hotspot/active/print'); @@ -204,32 +249,16 @@ class Mikrotik $client->sendSync($removeRequest); } - public static function setHotspotLimitUptime($client, $username) - { - $printRequest = new RouterOS\Request('/ip/hotspot/user/print'); - $printRequest->setArgument('.proplist', '.id'); - $printRequest->setQuery(RouterOS\Query::where('name', $username)); - $id = $client->sendSync($printRequest)->getProperty('.id'); - - $setRequest = new RouterOS\Request('/ip/hotspot/user/set'); - $setRequest->setArgument('numbers', $id); - $setRequest->setArgument('limit-uptime', '00:00:05'); - $client->sendSync($setRequest); - } - public static function removePpoeUser($client, $username) { - $printRequest = new RouterOS\Request('/ppp/secret/print'); - $printRequest->setArgument('.proplist', '.id'); - $printRequest->setQuery(RouterOS\Query::where('name', $username)); - $id = $client->sendSync($printRequest)->getProperty('.id'); - - $removeRequest = new RouterOS\Request('/ppp/secret/remove'); - $client( - $removeRequest - ->setArgument('numbers', $id) - ); + $printRequest = new RouterOS\Request('/ppp/secret/print'); + //$printRequest->setArgument('.proplist', '.id'); + $printRequest->setQuery(RouterOS\Query::where('name', $username)); + $id = $client->sendSync($printRequest)->getProperty('.id'); + $removeRequest = new RouterOS\Request('/ppp/secret/remove'); + $removeRequest->setArgument('numbers', $id); + $client->sendSync($removeRequest); } public static function addPpoeUser($client, $plan, $customer) @@ -250,7 +279,7 @@ class Mikrotik ); } - public static function setPpoeUser($client, $user, $pass, $nuser = null) + public static function setPpoeUser($client, $user, $pass) { $printRequest = new RouterOS\Request('/ppp/secret/print'); $printRequest->setArgument('.proplist', '.id'); @@ -263,15 +292,16 @@ class Mikrotik $client->sendSync($setRequest); } - public static function disablePpoeUser($client, $username) + public static function setPpoeUserPlan($client, $user, $plan) { $printRequest = new RouterOS\Request('/ppp/secret/print'); $printRequest->setArgument('.proplist', '.id'); - $printRequest->setQuery(RouterOS\Query::where('name', $username)); + $printRequest->setQuery(RouterOS\Query::where('name', $user)); $id = $client->sendSync($printRequest)->getProperty('.id'); - $setRequest = new RouterOS\Request('/ppp/secret/disable'); + $setRequest = new RouterOS\Request('/ppp/secret/set'); $setRequest->setArgument('numbers', $id); + $setRequest->setArgument('profile', $plan); $client->sendSync($setRequest); } @@ -290,15 +320,15 @@ class Mikrotik public static function removePool($client, $name) { $printRequest = new RouterOS\Request( - '/ip pool print .proplist=name', + '/ip pool print .proplist=.id', RouterOS\Query::where('name', $name) ); - $poolName = $client->sendSync($printRequest)->getProperty('name'); + $poolID = $client->sendSync($printRequest)->getProperty('.id'); $removeRequest = new RouterOS\Request('/ip/pool/remove'); $client( $removeRequest - ->setArgument('numbers', $poolName) + ->setArgument('numbers', $poolID) ); } @@ -315,18 +345,18 @@ class Mikrotik public static function setPool($client, $name, $ip_address) { $printRequest = new RouterOS\Request( - '/ip pool print .proplist=name', + '/ip pool print .proplist=.id', RouterOS\Query::where('name', $name) ); - $poolName = $client->sendSync($printRequest)->getProperty('name'); + $poolID = $client->sendSync($printRequest)->getProperty('id'); - if (empty($poolName)) { + if (empty($poolID)) { self::addPool($client, $name, $ip_address); } else { $setRequest = new RouterOS\Request('/ip/pool/set'); $client( $setRequest - ->setArgument('numbers', $poolName) + ->setArgument('numbers', $poolID) ->setArgument('ranges', $ip_address) ); } @@ -348,17 +378,17 @@ class Mikrotik public static function setPpoePlan($client, $name, $pool, $rate) { $printRequest = new RouterOS\Request( - '/ppp profile print .proplist=name', + '/ppp profile print .proplist=.id', RouterOS\Query::where('name', $name) ); - $profileName = $client->sendSync($printRequest)->getProperty('name'); - if (empty($profileName)) { + $profileID = $client->sendSync($printRequest)->getProperty('.id'); + if (empty($profileID)) { self::addPpoePlan($client, $name, $pool, $rate); } else { $setRequest = new RouterOS\Request('/ppp/profile/set'); $client( $setRequest - ->setArgument('numbers', $profileName) + ->setArgument('numbers', $profileID) ->setArgument('local-address', $pool) ->setArgument('remote-address', $pool) ->setArgument('rate-limit', $rate) @@ -369,15 +399,15 @@ class Mikrotik public static function removePpoePlan($client, $name) { $printRequest = new RouterOS\Request( - '/ppp profile print .proplist=name', + '/ppp profile print .proplist=.id', RouterOS\Query::where('name', $name) ); - $profileName = $client->sendSync($printRequest)->getProperty('name'); + $profileID = $client->sendSync($printRequest)->getProperty('.id'); $removeRequest = new RouterOS\Request('/ppp/profile/remove'); $client( $removeRequest - ->setArgument('numbers', $profileName) + ->setArgument('numbers', $profileID) ); } } diff --git a/system/autoload/Package.php b/system/autoload/Package.php index 61c6dd1d..8e9a2317 100644 --- a/system/autoload/Package.php +++ b/system/autoload/Package.php @@ -5,8 +5,6 @@ **/ -use PEAR2\Net\RouterOS; - class Package { /** @@ -19,7 +17,7 @@ class Package */ public static function rechargeUser($id_customer, $router_name, $plan_id, $gateway, $channel) { - global $_c, $_L, $_notifmsg; + global $_c; $date_now = date("Y-m-d H:i:s"); $date_only = date("Y-m-d"); $time_only = date("H:i:s"); @@ -49,22 +47,27 @@ class Package $t->type = "Balance"; $t->save(); + $balance_before = $c['balance']; Balance::plus($id_customer, $p['price']); + $balance = $c['balance'] + $p['price']; $textInvoice = Lang::getNotifText('invoice_balance'); $textInvoice = str_replace('[[company_name]]', $_c['CompanyName'], $textInvoice); $textInvoice = str_replace('[[address]]', $_c['address'], $textInvoice); $textInvoice = str_replace('[[phone]]', $_c['phone'], $textInvoice); $textInvoice = str_replace('[[invoice]]', $inv, $textInvoice); - $textInvoice = str_replace('[[date]]', date($_c['date_format'], strtotime($date_only)) . " " . $time, $textInvoice); + $textInvoice = str_replace('[[date]]', Lang::dateTimeFormat($date_now), $textInvoice); $textInvoice = str_replace('[[payment_gateway]]', $_c['gateway'], $textInvoice); $textInvoice = str_replace('[[payment_channel]]', $_c['channel'], $textInvoice); $textInvoice = str_replace('[[type]]', 'Balance', $textInvoice); $textInvoice = str_replace('[[plan_name]]', $p['name_plan'], $textInvoice); - $textInvoice = str_replace('[[plan_price]]', $_c['currency_code'] . " " . number_format($p['price'], 2, $_c['dec_point'], $_c['thousands_sep']), $textInvoice); + $textInvoice = str_replace('[[plan_price]]', Lang::moneyFormat($p['price']), $textInvoice); + $textInvoice = str_replace('[[name]]', $c['fullname'], $textInvoice); $textInvoice = str_replace('[[user_name]]', $c['username'], $textInvoice); $textInvoice = str_replace('[[user_password]]', $c['password'], $textInvoice); $textInvoice = str_replace('[[footer]]', $_c['note'], $textInvoice); + $textInvoice = str_replace('[[balance_before]]', Lang::moneyFormat($balance_before), $textInvoice); + $textInvoice = str_replace('[[balance]]', Lang::moneyFormat($balance), $textInvoice); if ($_c['user_notification_payment'] == 'sms') { Message::sendSMS($c['phonenumber'], $textInvoice); @@ -99,15 +102,19 @@ class Package $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); Mikrotik::removeHotspotUser($client, $c['username']); Mikrotik::removePpoeUser($client, $c['username']); + Mikrotik::removeHotspotActiveUser($client, $c['username']); + Mikrotik::removePpoeActive($client, $c['username']); Mikrotik::addHotspotUser($client, $p, $c); } - if ($b['namebp'] == $p['name_plan']) { + if ($b['namebp'] == $p['name_plan'] && $b['status'] == 'on') { // if it same internet plan, expired will extend if ($p['validity_unit'] == 'Months') { $date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months')); + $time = $b['time']; } else if ($p['validity_unit'] == 'Days') { $date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' days')); + $time = $b['time']; } else if ($p['validity_unit'] == 'Hrs') { $datetime = explode(' ', date("Y-m-d H:i:s", strtotime($b['expiration'] . ' ' . $b['time'] . ' +' . $p['validity'] . ' hours'))); $date_exp = $datetime[0]; @@ -150,7 +157,10 @@ class Package } else { if (!$_c['radius_mode']) { $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + Mikrotik::removeHotspotUser($client, $c['username']); Mikrotik::removePpoeUser($client, $c['username']); + Mikrotik::removeHotspotActiveUser($client, $c['username']); + Mikrotik::removePpoeActive($client, $c['username']); Mikrotik::addHotspotUser($client, $p, $c); } @@ -196,16 +206,20 @@ class Package $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); Mikrotik::removeHotspotUser($client, $c['username']); Mikrotik::removePpoeUser($client, $c['username']); + Mikrotik::removeHotspotActiveUser($client, $c['username']); + Mikrotik::removePpoeActive($client, $c['username']); Mikrotik::addPpoeUser($client, $p, $c); } - if ($b['namebp'] == $p['name_plan']) { + if ($b['namebp'] == $p['name_plan'] && $b['status'] == 'on') { // if it same internet plan, expired will extend if ($p['validity_unit'] == 'Months') { $date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months')); + $time = $b['time']; } else if ($p['validity_unit'] == 'Days') { $date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' days')); + $time = $b['time']; } else if ($p['validity_unit'] == 'Hrs') { $datetime = explode(' ', date("Y-m-d H:i:s", strtotime($b['expiration'] . ' ' . $b['time'] . ' +' . $p['validity'] . ' hours'))); $date_exp = $datetime[0]; @@ -250,6 +264,8 @@ class Package $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); Mikrotik::removeHotspotUser($client, $c['username']); Mikrotik::removePpoeUser($client, $c['username']); + Mikrotik::removeHotspotActiveUser($client, $c['username']); + Mikrotik::removePpoeActive($client, $c['username']); Mikrotik::addPpoeUser($client, $p, $c); } @@ -297,15 +313,16 @@ class Package $textInvoice = str_replace('[[address]]', $_c['address'], $textInvoice); $textInvoice = str_replace('[[phone]]', $_c['phone'], $textInvoice); $textInvoice = str_replace('[[invoice]]', $in['invoice'], $textInvoice); - $textInvoice = str_replace('[[date]]', date($_c['date_format'], strtotime($date_now)) . " " . $time, $textInvoice); + $textInvoice = str_replace('[[date]]', Lang::dateTimeFormat($date_now), $textInvoice); $textInvoice = str_replace('[[payment_gateway]]', $_c['gateway'], $textInvoice); $textInvoice = str_replace('[[payment_channel]]', $_c['channel'], $textInvoice); $textInvoice = str_replace('[[type]]', $in['type'], $textInvoice); $textInvoice = str_replace('[[plan_name]]', $in['plan_name'], $textInvoice); - $textInvoice = str_replace('[[plan_price]]', $_c['currency_code'] . " " . number_format($in['price'], 2, $_c['dec_point'], $_c['thousands_sep']), $textInvoice); + $textInvoice = str_replace('[[plan_price]]', Lang::moneyFormat($in['price']), $textInvoice); + $textInvoice = str_replace('[[name]]', $c['fullname'], $textInvoice); $textInvoice = str_replace('[[user_name]]', $in['username'], $textInvoice); $textInvoice = str_replace('[[user_password]]', $c['password'], $textInvoice); - $textInvoice = str_replace('[[expired_date]]', date($_c['date_format'], strtotime($in['expiration'])) . " " . $in['time'], $textInvoice); + $textInvoice = str_replace('[[expired_date]]', Lang::dateAndTimeFormat($in['expiration'], $in['time']), $textInvoice); $textInvoice = str_replace('[[footer]]', $_c['note'], $textInvoice); if ($_c['user_notification_payment'] == 'sms') { @@ -329,6 +346,8 @@ class Package $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); Mikrotik::removeHotspotUser($client, $c['username']); Mikrotik::removePpoeUser($client, $c['username']); + Mikrotik::removeHotspotActiveUser($client, $c['username']); + Mikrotik::removePpoeActive($client, $c['username']); Mikrotik::addHotspotUser($client, $p, $c); } } else { @@ -336,6 +355,8 @@ class Package $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); Mikrotik::removeHotspotUser($client, $c['username']); Mikrotik::removePpoeUser($client, $c['username']); + Mikrotik::removeHotspotActiveUser($client, $c['username']); + Mikrotik::removePpoeActive($client, $c['username']); Mikrotik::addHotspotUser($client, $p, $c); } } @@ -345,6 +366,8 @@ class Package $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); Mikrotik::removeHotspotUser($client, $c['username']); Mikrotik::removePpoeUser($client, $c['username']); + Mikrotik::removeHotspotActiveUser($client, $c['username']); + Mikrotik::removePpoeActive($client, $c['username']); Mikrotik::addPpoeUser($client, $p, $c); } } else { @@ -352,6 +375,8 @@ class Package $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); Mikrotik::removeHotspotUser($client, $c['username']); Mikrotik::removePpoeUser($client, $c['username']); + Mikrotik::removeHotspotActiveUser($client, $c['username']); + Mikrotik::removePpoeActive($client, $c['username']); Mikrotik::addPpoeUser($client, $p, $c); } } diff --git a/system/boot.php b/system/boot.php index dcfe4f11..a3c055f5 100644 --- a/system/boot.php +++ b/system/boot.php @@ -4,6 +4,33 @@ * PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/) **/ + + +// on some server, it getting error because of slash is backwards +function _autoloader($class) +{ + if (strpos($class, '_') !== false) { + $class = str_replace('_', DIRECTORY_SEPARATOR, $class); + if (file_exists('autoload' . DIRECTORY_SEPARATOR . $class . '.php')) { + include 'autoload' . DIRECTORY_SEPARATOR . $class . '.php'; + } else { + $class = str_replace("\\", DIRECTORY_SEPARATOR, $class); + if (file_exists(__DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php')) + include __DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php'; + } + } else { + if (file_exists('autoload' . DIRECTORY_SEPARATOR . $class . '.php')) { + include 'autoload' . DIRECTORY_SEPARATOR . $class . '.php'; + } else { + $class = str_replace("\\", DIRECTORY_SEPARATOR, $class); + if (file_exists(__DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php')) + include __DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php'; + } + } +} + +spl_autoload_register('_autoloader'); + function r2($to, $ntype = 'e', $msg = '') { if ($msg == '') { @@ -46,33 +73,52 @@ function _get($param, $defvalue = '') return safedata($_GET[$param]); } } +try { + require_once File::pathFixer('system/orm.php'); -require('system/orm.php'); + ORM::configure("mysql:host=$db_host;dbname=$db_name"); + ORM::configure('username', $db_user); + ORM::configure('password', $db_password); + ORM::configure('driver_options', array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8')); + ORM::configure('return_result_sets', true); + if ($_app_stage != 'Live') { + ORM::configure('logging', true); + } -ORM::configure("mysql:host=$db_host;dbname=$db_name"); -ORM::configure('username', $db_user); -ORM::configure('password', $db_password); -ORM::configure('driver_options', array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8')); -ORM::configure('return_result_sets', true); -if ($_app_stage != 'Live') { - ORM::configure('logging', true); -} + $result = ORM::for_table('tbl_appconfig')->find_many(); + foreach ($result as $value) { + $config[$value['setting']] = $value['value']; + } -$result = ORM::for_table('tbl_appconfig')->find_many(); -foreach ($result as $value) { - $config[$value['setting']] = $value['value']; -} + date_default_timezone_set($config['timezone']); + $_c = $config; -date_default_timezone_set($config['timezone']); -$_c = $config; - -if ($config['radius_mode']) { - ORM::configure("mysql:host=$radius_host;dbname=$radius_name", null, 'radius'); - ORM::configure('username', $radius_user, 'radius'); - ORM::configure('password', $radius_password, 'radius'); - ORM::configure('driver_options', array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'), 'radius'); - ORM::configure('return_result_sets', true, 'radius'); + // check if proxy setup in database + if (empty($http_proxy) && !empty($config['http_proxy'])) { + $http_proxy = $config['http_proxy']; + if (empty($http_proxyauth) && !empty($config['http_proxyauth'])) { + $http_proxyauth = $config['http_proxyauth']; + } + } + if ($config['radius_mode']) { + ORM::configure("mysql:host=$radius_host;dbname=$radius_name", null, 'radius'); + ORM::configure('username', $radius_user, 'radius'); + ORM::configure('password', $radius_password, 'radius'); + ORM::configure('driver_options', array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'), 'radius'); + ORM::configure('return_result_sets', true, 'radius'); + } +} catch (Exception $e) { + $ui = new Smarty(); + $ui->setTemplateDir(['custom' => File::pathFixer('ui/ui_custom/'), 'default' => File::pathFixer('ui/ui/')]); + $ui->assign('_url', APP_URL . '/index.php?_route='); + $ui->setCompileDir(File::pathFixer('ui/compiled/')); + $ui->setConfigDir(File::pathFixer('ui/conf/')); + $ui->setCacheDir(File::pathFixer('ui/cache/')); + $ui->assign("error_title", "PHPNuxBill Crash"); + $ui->assign("error_message", $e->getMessage()); + $ui->display('router-error.tpl'); + die(); } function _notify($msg, $type = 'e') @@ -81,15 +127,15 @@ function _notify($msg, $type = 'e') $_SESSION['notify'] = $msg; } -$lan_file = 'system/lan/' . $config['language'] . '/common.lan.php'; +$lan_file = File::pathFixer('system/lan/' . $config['language'] . '/common.lan.php'); require($lan_file); $ui = new Smarty(); -$ui->setTemplateDir(['custom' => 'ui/ui_custom/', 'default' => 'ui/ui/']); -$ui->addTemplateDir('system/paymentgateway/ui/', 'pg'); -$ui->addTemplateDir('system/plugin/ui/', 'plugin'); -$ui->setCompileDir('ui/compiled/'); -$ui->setConfigDir('ui/conf/'); -$ui->setCacheDir('ui/cache/'); +$ui->setTemplateDir(['custom' => File::pathFixer('ui/ui_custom/'), 'default' => File::pathFixer('ui/ui/')]); +$ui->addTemplateDir(File::pathFixer('system/paymentgateway/ui/'), 'pg'); +$ui->addTemplateDir(File::pathFixer('system/plugin/ui/'), 'plugin'); +$ui->setCompileDir(File::pathFixer('ui/compiled/')); +$ui->setConfigDir(File::pathFixer('ui/conf/')); +$ui->setCacheDir(File::pathFixer('ui/cache/')); $ui->assign('app_url', APP_URL); $ui->assign('_domain', str_replace('www.', '', parse_url(APP_URL, PHP_URL_HOST))); define('U', APP_URL . '/index.php?_route='); @@ -129,40 +175,16 @@ if (isset($_SESSION['notify'])) { include "autoload/Hookers.php"; // notification message -if(file_exists("system/uploads/notifications.json")){ - $_notifmsg =json_decode(file_get_contents('system/uploads/notifications.json'), true); +if (file_exists(File::pathFixer("system/uploads/notifications.json"))) { + $_notifmsg = json_decode(file_get_contents(File::pathFixer('system/uploads/notifications.json')), true); } -$_notifmsg_default = json_decode(file_get_contents('system/uploads/notifications.default.json'), true); +$_notifmsg_default = json_decode(file_get_contents(File::pathFixer('system/uploads/notifications.default.json')), true); //register all plugin -foreach (glob("system/plugin/*.php") as $filename) { +foreach (glob(File::pathFixer("system/plugin/*.php")) as $filename) { include $filename; } -// on some server, it getting error because of slash is backwards -function _autoloader($class) -{ - if (strpos($class, '_') !== false) { - $class = str_replace('_', DIRECTORY_SEPARATOR, $class); - if (file_exists('autoload' . DIRECTORY_SEPARATOR . $class . '.php')) { - include 'autoload' . DIRECTORY_SEPARATOR . $class . '.php'; - } else { - $class = str_replace("\\", DIRECTORY_SEPARATOR, $class); - if (file_exists(__DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php')) - include __DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php'; - } - } else { - if (file_exists('autoload' . DIRECTORY_SEPARATOR . $class . '.php')) { - include 'autoload' . DIRECTORY_SEPARATOR . $class . '.php'; - } else { - $class = str_replace("\\", DIRECTORY_SEPARATOR, $class); - if (file_exists(__DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php')) - include __DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php'; - } - } -} - -spl_autoload_register('_autoloader'); function _auth($login = true) { @@ -281,34 +303,42 @@ $handler = $routes[0]; if ($handler == '') { $handler = 'default'; } -$sys_render = 'system/controllers/' . $handler . '.php'; -if (file_exists($sys_render)) { - $menus = array(); - // "name" => $name, - // "admin" => $admin, - // "position" => $position, - // "function" => $function - $ui->assign('_system_menu', $routes[0]); - foreach ($menu_registered as $menu) { - if ($menu['admin'] && _admin(false)) { - $menus[$menu['position']] .= ''; - if (!empty($menu['icon'])) { - $menus[$menu['position']] .= ''; +try { + + $sys_render = File::pathFixer('system/controllers/' . $handler . '.php'); + if (file_exists($sys_render)) { + $menus = array(); + // "name" => $name, + // "admin" => $admin, + // "position" => $position, + // "function" => $function + $ui->assign('_system_menu', $routes[0]); + foreach ($menu_registered as $menu) { + if ($menu['admin'] && _admin(false)) { + $menus[$menu['position']] .= ''; + if (!empty($menu['icon'])) { + $menus[$menu['position']] .= ''; + } + $menus[$menu['position']] .= '' . $menu['name'] . ''; + } else if (!$menu['admin'] && _auth(false)) { + $menus[$menu['position']] .= ''; + if (!empty($menu['icon'])) { + $menus[$menu['position']] .= ''; + } + $menus[$menu['position']] .= '' . $menu['name'] . ''; } - $menus[$menu['position']] .= '' . $menu['name'] . ''; - } else if (!$menu['admin'] && _auth(false)) { - $menus[$menu['position']] .= ''; - if (!empty($menu['icon'])) { - $menus[$menu['position']] .= ''; - } - $menus[$menu['position']] .= '' . $menu['name'] . ''; } + foreach ($menus as $k => $v) { + $ui->assign('_MENU_' . $k, $v); + } + unset($menus, $menu_registered); + include($sys_render); + } else { + r2(U . 'dashboard', 'e', 'not found'); } - foreach ($menus as $k => $v) { - $ui->assign('_MENU_' . $k, $v); - } - unset($menus, $menu_registered); - include($sys_render); -} else { - r2(U . 'dashboard', 'e', 'not found'); +} catch (Exception $e) { + $ui->assign("error_title", "PHPNuxBill Crash"); + $ui->assign("error_message", $e->getMessage()); + $ui->display('router-error.tpl'); + die(); } diff --git a/system/controllers/autoload.php b/system/controllers/autoload.php index e3b782eb..70a448ff 100644 --- a/system/controllers/autoload.php +++ b/system/controllers/autoload.php @@ -36,6 +36,18 @@ switch ($action) { $ui->display('autoload.tpl'); break; + case 'customer_is_active': + $d = ORM::for_table('tbl_user_recharges')->where('customer_id', $routes['2'])->findOne(); + if ($d) { + if ($d['status'] == 'on') { + die(''.$d['namebp'].''); + } else { + die(''.$d['namebp'].''); + } + } else { + die(''); + } + break; case 'customer_select2': $s = addslashes(_get('s')); diff --git a/system/controllers/customers.php b/system/controllers/customers.php index c4c54603..d454a3d7 100644 --- a/system/controllers/customers.php +++ b/system/controllers/customers.php @@ -12,9 +12,6 @@ $action = $routes['1']; $admin = Admin::_info(); $ui->assign('_admin', $admin); -use PEAR2\Net\RouterOS; - -require_once 'system/autoload/PEAR2/Autoload.php'; if ($admin['user_type'] != 'Admin' and $admin['user_type'] != 'Sales') { r2(U . "dashboard", 'e', $_L['Do_Not_Access']); @@ -34,7 +31,8 @@ switch ($action) { ->order_by_desc('id')->find_many(); } else { $paginator = Paginator::bootstrap('tbl_customers'); - $d = ORM::for_table('tbl_customers')->offset($paginator['startpoint'])->limit($paginator['limit'])->order_by_desc('id')->find_many(); + $d = ORM::for_table('tbl_customers') + ->offset($paginator['startpoint'])->limit($paginator['limit'])->order_by_desc('id')->find_many(); } $ui->assign('search', htmlspecialchars($search)); @@ -47,13 +45,67 @@ switch ($action) { run_hook('view_add_customer'); #HOOK $ui->display('customers-add.tpl'); break; - + case 'recharge': + $id_customer = $routes['2']; + $b = ORM::for_table('tbl_user_recharges')->where('customer_id', $id_customer)->find_one(); + if ($b) { + $mikrotik = Mikrotik::info($b['routers']); + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + if (Package::rechargeUser($id_customer, $b['routers'], $b['plan_id'], "Recharge", $admin['fullname'])) { + r2(U . 'customers/view/' . $id_customer, 's', 'Success Recharge Customer'); + } else { + r2(U . 'customers/view/' . $id_customer, 'e', 'Customer plan is inactive'); + } + } + r2(U . 'customers/view/' . $id_customer, 'e', 'Cannot find active plan'); + case 'deactivate': + $id_customer = $routes['2']; + $b = ORM::for_table('tbl_user_recharges')->where('customer_id', $id_customer)->find_one(); + if ($b) { + $mikrotik = Mikrotik::info($b['routers']); + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + if ($b['type'] == 'Hotspot') { + Mikrotik::removeHotspotUser($client, $b['username']); + Mikrotik::removeHotspotActiveUser($client, $b['username']); + } else if ($b['type'] == 'PPPOE') { + Mikrotik::removePpoeUser($client, $b['username']); + Mikrotik::removePpoeActive($client, $b['username']); + } + $b->status = 'off'; + $b->expiration = date('Y-m-d'); + $b->time = date('H:i:s'); + $b->save(); + r2(U . 'customers/view/' . $id_customer, 's', 'Success deactivate customer to Mikrotik'); + } + r2(U . 'customers/view/' . $id_customer, 'e', 'Cannot find active plan'); + break; + case 'sync': + $id_customer = $routes['2']; + $b = ORM::for_table('tbl_user_recharges')->where('customer_id', $id_customer)->where('status', 'on')->find_one(); + if ($b) { + $mikrotik = Mikrotik::info($b['routers']); + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $c = ORM::for_table('tbl_customers')->find_one($id_customer); + $p = ORM::for_table('tbl_plans')->where('id', $b['plan_id'])->where('enabled', '1')->find_one(); + if ($p) { + if ($b['type'] == 'Hotspot') { + Mikrotik::addHotspotUser($client, $p, $c); + } else if ($b['type'] == 'PPPOE') { + Mikrotik::addPpoeUser($client, $p, $c); + } + r2(U . 'customers/view/' . $id_customer, 's', 'Success sync customer to Mikrotik'); + } else { + r2(U . 'customers/view/' . $id_customer, 'e', 'Customer plan is inactive'); + } + } + r2(U . 'customers/view/' . $id_customer, 'e', 'Cannot find active plan'); + break; case 'viewu': $customer = ORM::for_table('tbl_customers')->where('username', $routes['2'])->find_one(); case 'view': $id = $routes['2']; run_hook('view_customer'); #HOOK - if(!$customer){ + if (!$customer) { $customer = ORM::for_table('tbl_customers')->find_one($id); } if ($customer) { @@ -81,7 +133,7 @@ switch ($action) { // $ui->assign('paginator', $paginator); $ui->assign('activation', $activation); } - $package = ORM::for_table('tbl_user_recharges')->where('username',$customer['username'])->find_one(); + $package = ORM::for_table('tbl_user_recharges')->where('username', $customer['username'])->find_one(); $ui->assign('package', $package); $ui->assign('v', $v); $ui->assign('d', $customer); @@ -113,14 +165,14 @@ switch ($action) { if ($c['type'] == 'Hotspot') { if (!$config['radius_mode']) { $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - Mikrotik::removeHotspotUser($client, $c['username']); - Mikrotik::removeHotspotActiveUser($client, $c['username']); + Mikrotik::removeHotspotUser($client, $d['username']); + Mikrotik::removeHotspotActiveUser($client, $d['username']); } } else { if (!$config['radius_mode']) { $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - Mikrotik::removePpoeUser($client, $c['username']); - Mikrotik::removePpoeActive($client, $c['username']); + Mikrotik::removePpoeUser($client, $d['username']); + Mikrotik::removePpoeActive($client, $d['username']); } } try { diff --git a/system/controllers/dashboard.php b/system/controllers/dashboard.php index 320ac76e..f609c719 100644 --- a/system/controllers/dashboard.php +++ b/system/controllers/dashboard.php @@ -1,13 +1,14 @@ assign('_title', $_L['Dashboard']); $admin = Admin::_info(); $ui->assign('_admin', $admin); -if(!in_array($admin['user_type'],['Admin','Sales'])){ - r2(U."home",'e',$_L['Do_Not_Access']); +if (!in_array($admin['user_type'], ['Admin', 'Sales'])) { + r2(U . "home", 'e', $_L['Do_Not_Access']); } $fdate = date('Y-m-01'); @@ -17,59 +18,67 @@ $first_day_month = date('Y-m-01'); $mdate = date('Y-m-d'); $month_n = date('n'); -$iday = ORM::for_table('tbl_transactions')->where('recharged_on',$mdate)->sum('price'); -if($iday == ''){ +$iday = ORM::for_table('tbl_transactions')->where('recharged_on', $mdate)->sum('price'); +if ($iday == '') { $iday = '0.00'; } -$ui->assign('iday',$iday); +$ui->assign('iday', $iday); -$imonth = ORM::for_table('tbl_transactions')->where_gte('recharged_on',$first_day_month)->where_lte('recharged_on',$mdate)->sum('price'); -if($imonth == ''){ +$imonth = ORM::for_table('tbl_transactions')->where_gte('recharged_on', $first_day_month)->where_lte('recharged_on', $mdate)->sum('price'); +if ($imonth == '') { $imonth = '0.00'; } -$ui->assign('imonth',$imonth); +$ui->assign('imonth', $imonth); -$u_act = ORM::for_table('tbl_user_recharges')->where('status','on')->count(); -if($u_act == ''){ +$u_act = ORM::for_table('tbl_user_recharges')->where('status', 'on')->count(); +if (empty($u_act)) { $u_act = '0'; } -$ui->assign('u_act',$u_act); +$ui->assign('u_act', $u_act); $u_all = ORM::for_table('tbl_user_recharges')->count(); -if($u_all == ''){ +if (empty($u_all)) { $u_all = '0'; } -$ui->assign('u_all',$u_all); +$ui->assign('u_all', $u_all); + + +$c_all = ORM::for_table('tbl_customers')->count(); +if (empty($c_all)) { + $c_all = '0'; +} +$ui->assign('c_all', $c_all); + //user expire -$expire = ORM::for_table('tbl_user_recharges')->where('expiration',$mdate)->order_by_desc('id')->find_many(); -$ui->assign('expire',$expire); +$expire = ORM::for_table('tbl_user_recharges')->where('expiration', $mdate)->order_by_desc('id')->find_many(); +$ui->assign('expire', $expire); //activity log $dlog = ORM::for_table('tbl_logs')->limit(5)->order_by_desc('id')->find_many(); -$ui->assign('dlog',$dlog); +$ui->assign('dlog', $dlog); $log = ORM::for_table('tbl_logs')->count(); -$ui->assign('log',$log); +$ui->assign('log', $log); // Count stock $tmp = $v = ORM::for_table('tbl_plans')->select('id')->select('name_plan')->find_many(); $plans = array(); -$stocks = array("used"=>0,"unused"=>0); +$stocks = array("used" => 0, "unused" => 0); $n = 0; -foreach($tmp as $plan){ +foreach ($tmp as $plan) { $plans[$n]['name_plan'] = $plan['name_plan']; $plans[$n]['unused'] = ORM::for_table('tbl_voucher') - ->where('id_plan',$plan['id']) - ->where('status',0)->count();; + ->where('id_plan', $plan['id']) + ->where('status', 0)->count();; $stocks["unused"] += $plans[$n]['unused']; $plans[$n]['used'] = ORM::for_table('tbl_voucher') - ->where('id_plan',$plan['id']) - ->where('status',1)->count();; + ->where('id_plan', $plan['id']) + ->where('status', 1)->count();; $stocks["used"] += $plans[$n]['used']; $n++; } -$ui->assign('stocks',$stocks); -$ui->assign('plans',$plans); +$ui->assign('stocks', $stocks); +$ui->assign('plans', $plans); run_hook('view_dashboard'); #HOOK -$ui->display('dashboard.tpl'); \ No newline at end of file +$ui->display('dashboard.tpl'); diff --git a/system/controllers/home.php b/system/controllers/home.php index 851a7a16..c2eef6ce 100644 --- a/system/controllers/home.php +++ b/system/controllers/home.php @@ -25,7 +25,7 @@ if (_post('send') == 'balance') { if ($user['balance'] < $balance) { r2(U . 'home', 'd', Lang::T('insufficient balance')); } - if (!empty($config['minimum_transfer']) && intval($balance) <= intval($config['minimum_transfer'])) { + if (!empty($config['minimum_transfer']) && intval($balance) < intval($config['minimum_transfer'])) { r2(U . 'home', 'd', Lang::T('Minimum Transfer') . ' ' . Lang::moneyFormat($config['minimum_transfer'])); } if ($user['username'] == $target['username']) { @@ -66,13 +66,23 @@ if (_post('send') == 'balance') { $d->pg_url_payment = 'balance'; $d->status = 2; $d->save(); - Message::sendBalanceNotification($user['phonenumber'], $target['fullname'] . ' (' . $target['username'] . ')', $balance, Lang::getNotifText('balance_send'), $config['user_notification_payment']); - Message::sendBalanceNotification($target['phonenumber'], $user['fullname'] . ' (' . $user['username'] . ')', $balance, Lang::getNotifText('balance_received'), $config['user_notification_payment']); + Message::sendBalanceNotification($user['phonenumber'], $target['fullname'] . ' (' . $target['username'] . ')', $balance, ($user['balance'] - $balance), Lang::getNotifText('balance_send'), $config['user_notification_payment']); + Message::sendBalanceNotification($target['phonenumber'], $user['fullname'] . ' (' . $user['username'] . ')', $balance, ($target['balance'] + $balance), Lang::getNotifText('balance_received'), $config['user_notification_payment']); Message::sendTelegram("#u$user[username] send balance to #u$target[username] \n" . Lang::moneyFormat($balance)); r2(U . 'home', 's', Lang::T('Sending balance success')); } } else { - r2(U . 'home', 'd', 'Failed, balance is not available'); + r2(U . 'home', 'd', Lang::T('Failed, balance is not available')); + } +} else if (_post('send') == 'plan') { + $active = ORM::for_table('tbl_user_recharges') + ->where('username', _post('username')) + ->find_one(); + $router = ORM::for_table('tbl_routers')->where('name', $active['routers'])->find_one(); + if ($router) { + r2(U . "order/send/$router[id]/$active[plan_id]&u=" . trim(_post('username')), 's', Lang::T('Review package before recharge')); + } else { + r2(U . 'package/order', 'w', Lang::T('Your friend do not have active package')); } } diff --git a/system/controllers/order.php b/system/controllers/order.php index d665889b..df5652ee 100644 --- a/system/controllers/order.php +++ b/system/controllers/order.php @@ -98,7 +98,7 @@ switch ($action) { } } if (empty($trx)) { - r2(U . "order", 'e', Lang::T("Transaction Not found")); + r2(U . "order/package", 'e', Lang::T("Transaction Not found")); } $router = ORM::for_table('tbl_routers')->find_one($trx['routers_id']); $plan = ORM::for_table('tbl_plans')->find_one($trx['plan_id']); @@ -111,8 +111,8 @@ switch ($action) { $ui->display('user-orderView.tpl'); break; case 'pay': - if ($_c['enable_balance'] != 'yes'){ - r2(U . "order", 'e', Lang::T("Balance not enabled")); + if ($_c['enable_balance'] != 'yes' && $config['allow_balance_transfer'] != 'yes') { + r2(U . "order/package", 'e', Lang::T("Balance not enabled")); } $plan = ORM::for_table('tbl_plans')->where('enabled', '1')->find_one($routes['3']); $router = ORM::for_table('tbl_routers')->where('enabled', '1')->find_one($routes['2']); @@ -130,10 +130,91 @@ switch ($action) { "\nRouter: " . $router_name . "\nPrice: " . $p['price']); } - }else{ + } else { echo "no renewall | plan enabled: $p[enabled] | User balance: $c[balance] | price $p[price]\n"; } break; + case 'send': + if ($_c['enable_balance'] != 'yes') { + r2(U . "order/package", 'e', Lang::T("Balance not enabled")); + } + $ui->assign('_title', Lang::T('Buy for friend')); + $ui->assign('_system_menu', 'package'); + $plan = ORM::for_table('tbl_plans')->find_one($routes['3']); + if (empty($plan)) { + r2(U . "order/package", 'e', Lang::T("Plan Not found")); + } + if (isset($_POST['send']) && $_POST['send'] == 'plan') { + $target = ORM::for_table('tbl_customers')->where('username', _post('username'))->find_one(); + if (!$target) { + r2(U . 'home', 'd', Lang::T('Username not found')); + } + if ($user['balance'] < $plan['price']) { + r2(U . 'home', 'd', Lang::T('insufficient balance')); + } + if ($user['username'] == $target['username']) { + r2(U . "order/pay/$routes[2]/$routes[3]", 's', '^_^ v'); + } + $active = ORM::for_table('tbl_user_recharges') + ->where('username', _post('username')) + ->where('status', 'on') + ->find_one(); + + if ($active && $active['plan_id'] != $plan['id']) { + r2(U . "order/package", 'e', Lang::T("Target has active plan, different with current plant.")." [ $active[namebp] ]"); + } + if (Package::rechargeUser($target['id'], $plan['routers'], $plan['id'], $user['fullname'], 'Balance')) { + // if success, then get the balance + Balance::min($user['id'], $plan['price']); + //sender + $d = ORM::for_table('tbl_payment_gateway')->create(); + $d->username = $user['username']; + $d->gateway = $target['username']; + $d->plan_id = $plan['id']; + $d->plan_name = $plan['name_plan']; + $d->routers_id = $routes['2']; + $d->routers = $plan['routers']; + $d->price = $plan['price']; + $d->payment_method = "Balance"; + $d->payment_channel = "Send Plan"; + $d->created_date = date('Y-m-d H:i:s'); + $d->paid_date = date('Y-m-d H:i:s'); + $d->expired_date = date('Y-m-d H:i:s'); + $d->pg_url_payment = 'balance'; + $d->status = 2; + $d->save(); + $trx_id = $d->id(); + //receiver + $d = ORM::for_table('tbl_payment_gateway')->create(); + $d->username = $target['username']; + $d->gateway = $user['username']; + $d->plan_id = $plan['id']; + $d->plan_name = $plan['name_plan']; + $d->routers_id = $routes['2']; + $d->routers = $plan['routers']; + $d->price = $plan['price']; + $d->payment_method = "Balance"; + $d->payment_channel = "Received Plan"; + $d->created_date = date('Y-m-d H:i:s'); + $d->paid_date = date('Y-m-d H:i:s'); + $d->expired_date = date('Y-m-d H:i:s'); + $d->pg_url_payment = 'balance'; + $d->status = 2; + $d->save(); + r2(U . "order/view/$trx_id", 's', Lang::T("Success to send package")); + } else { + r2(U . "order/package", 'e', Lang::T("Failed to Send package")); + Message::sendTelegram("Send Package with Balance Failed\n\n#u$user[username] #send \n" . $plan['name_plan'] . + "\nRouter: " . $plan['routers'] . + "\nPrice: " . $plan['price']); + } + } + + $ui->assign('username', $_GET['u']); + $ui->assign('router', $router); + $ui->assign('plan', $plan); + $ui->display('user-sendPlan.tpl'); + break; case 'buy': if (strpos($user['email'], '@') === false) { r2(U . 'accounts/profile', 'e', Lang::T("Please enter your email address")); @@ -147,9 +228,9 @@ switch ($action) { run_hook('customer_buy_plan'); #HOOK include 'system/paymentgateway/' . $config['payment_gateway'] . '.php'; call_user_func($config['payment_gateway'] . '_validate_config'); - if ($routes['2']>0) { + if ($routes['2'] > 0) { $router = ORM::for_table('tbl_routers')->where('enabled', '1')->find_one($routes['2']); - }else{ + } else { $router['id'] = 0; $router['name'] = 'balance'; } @@ -205,5 +286,5 @@ switch ($action) { } break; default: - r2(U . "order/package/", 's',''); + r2(U . "order/package/", 's', ''); } diff --git a/system/controllers/pluginmanager.php b/system/controllers/pluginmanager.php index c3f11a45..4eaa747f 100644 --- a/system/controllers/pluginmanager.php +++ b/system/controllers/pluginmanager.php @@ -21,9 +21,14 @@ if ($admin['user_type'] != 'Admin') { $cache = File::pathFixer('system/cache/plugin_repository.json'); if (file_exists($cache) && time() - filemtime($cache) < (24 * 60 * 60)) { - $json = json_decode(file_get_contents($cache), true); + $txt = file_get_contents($cache); + $json = json_decode($txt, true); + if(empty($json['plugins']) && empty($json['payment_gateway'])){ + unlink($cache); + r2(U . 'dashboard', 'd', $txt); + } } else { - $data = file_get_contents($plugin_repository); + $data = Http::getData($plugin_repository); file_put_contents($cache, $data); $json = json_decode($data, true); } diff --git a/system/controllers/pool.php b/system/controllers/pool.php index 69b06371..c633dc75 100644 --- a/system/controllers/pool.php +++ b/system/controllers/pool.php @@ -15,9 +15,6 @@ if ($admin['user_type'] != 'Admin') { r2(U . "dashboard", 'e', $_L['Do_Not_Access']); } -use PEAR2\Net\RouterOS; - -require_once 'system/autoload/PEAR2/Autoload.php'; switch ($action) { case 'list': @@ -73,6 +70,17 @@ switch ($action) { } break; + case 'sync': + $pools = ORM::for_table('tbl_pool')->find_many(); + $log = ''; + foreach($pools as $pool){ + $mikrotik = Mikrotik::info($pool['routers']); + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + Mikrotik::addPool($client, $pool['pool_name'], $pool['range_ip']); + $log .= 'DONE: '.$pool['pool_name'].': '.$pool['range_ip'].'
'; + } + r2(U . 'pool/list', 's', $log); + break; case 'add-post': $name = _post('name'); $ip_address = _post('ip_address'); diff --git a/system/controllers/prepaid.php b/system/controllers/prepaid.php index e3910e1b..6dd0709f 100644 --- a/system/controllers/prepaid.php +++ b/system/controllers/prepaid.php @@ -40,9 +40,31 @@ EOT; require_once 'system/autoload/PEAR2/Autoload.php'; switch ($action) { + case 'sync': + set_time_limit(-1); + $plans = ORM::for_table('tbl_user_recharges')->where('status', 'on')->find_many(); + echo count($plans); + $log = ''; + $router = ''; + foreach ($plans as $plan) { + if ($router != $plan['routers']) { + $mikrotik = Mikrotik::info($plan['routers']); + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $router = $plan['routers']; + } + $p = ORM::for_table('tbl_plans')->findOne($plan['plan_id']); + $c = ORM::for_table('tbl_customers')->findOne($plan['customer_id']); + if ($plan['type'] == 'Hotspot') { + Mikrotik::addHotspotUser($client, $p, $c); + } else if ($plan['type'] == 'PPPOE') { + Mikrotik::addPpoeUser($client, $p, $c); + } + $log .= "DONE : $plan[username], $plan[namebp], $plan[type], $plan[routers]
"; + } + r2(U . 'prepaid/list', 's', $log); case 'list': $ui->assign('xfooter', ''); - + $ui->assign('_title', $_L['Customers']); $username = _post('username'); if ($username != '') { $paginator = Paginator::bootstrap('tbl_user_recharges', 'username', '%' . $username . '%'); @@ -65,6 +87,9 @@ switch ($action) { $ui->assign('p', $p); $r = ORM::for_table('tbl_routers')->where('enabled', '1')->find_many(); $ui->assign('r', $r); + if (isset($routes['2']) && !empty($routes['2'])) { + $ui->assign('cust', ORM::for_table('tbl_customers')->find_one($routes['2'])); + } run_hook('view_recharge'); #HOOK $ui->display('recharge.tpl'); break; @@ -146,14 +171,16 @@ switch ($action) { if ($d['type'] == 'Hotspot') { if (!$config['radius_mode']) { $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - Mikrotik::removeHotspotUser($client, $c['username']); + Mikrotik::removeHotspotUser($client, $d['username']); + Mikrotik::removeHotspotActiveUser($client, $d['username']); } $d->delete(); } else { if (!$config['radius_mode']) { $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - Mikrotik::removePpoeUser($client, $c['username']); + Mikrotik::removePpoeUser($client, $d['username']); + Mikrotik::removePpoeActive($client, $d['username']); } $d->delete(); } diff --git a/system/controllers/services.php b/system/controllers/services.php index ed44feb3..cce9e4d8 100644 --- a/system/controllers/services.php +++ b/system/controllers/services.php @@ -21,6 +21,68 @@ use PEAR2\Net\RouterOS; require_once 'system/autoload/PEAR2/Autoload.php'; switch ($action) { + case 'sync': + set_time_limit(-1); + if ($routes['2'] == 'hotspot') { + $plans = ORM::for_table('tbl_bandwidth')->join('tbl_plans', array('tbl_bandwidth.id', '=', 'tbl_plans.id_bw'))->where('tbl_plans.type', 'Hotspot')->where('tbl_plans.enabled', '1')->find_many(); + $log = ''; + $router = ''; + foreach ($plans as $plan) { + if ($router != $plan['routers']) { + $mikrotik = Mikrotik::info($plan['routers']); + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $router = $plan['routers']; + } + if ($plan['rate_down_unit'] == 'Kbps') { + $unitdown = 'K'; + } else { + $unitdown = 'M'; + } + if ($plan['rate_up_unit'] == 'Kbps') { + $unitup = 'K'; + } else { + $unitup = 'M'; + } + $rate = $plan['rate_up'] . $unitup . "/" . $plan['rate_down'] . $unitdown; + Mikrotik::addHotspotPlan($client, $plan['name_plan'], $plan['shared_users'], $rate); + $log .= "DONE : $plan[name_plan], $plan[shared_users], $rate
"; + if (!empty($plan['pool_expired'])) { + Mikrotik::setHotspotExpiredPlan($client, 'EXPIRED NUXBILL ' . $plan['pool_expired'], $plan['pool_expired']); + $log .= "DONE Expired : EXPIRED NUXBILL $plan[pool_expired]
"; + } + } + r2(U . 'services/hotspot', 's', $log); + }else if ($routes['2'] == 'pppoe') { + $plans = ORM::for_table('tbl_bandwidth')->join('tbl_plans', array('tbl_bandwidth.id', '=', 'tbl_plans.id_bw'))->where('tbl_plans.type', 'PPPOE')->where('tbl_plans.enabled', '1')->find_many(); + $log = ''; + $router = ''; + foreach ($plans as $plan) { + if ($router != $plan['routers']) { + $mikrotik = Mikrotik::info($plan['routers']); + $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $router = $plan['routers']; + } + if ($plan['rate_down_unit'] == 'Kbps') { + $unitdown = 'K'; + } else { + $unitdown = 'M'; + } + if ($plan['rate_up_unit'] == 'Kbps') { + $unitup = 'K'; + } else { + $unitup = 'M'; + } + $rate = $plan['rate_up'] . $unitup . "/" . $plan['rate_down'] . $unitdown; + Mikrotik::addPpoePlan($client, $plan['name_plan'], $plan['pool'], $rate); + $log .= "DONE : $plan[name_plan], $plan[pool], $rate
"; + if (!empty($plan['pool_expired'])) { + Mikrotik::setPpoePlan($client, 'EXPIRED NUXBILL ' . $plan['pool_expired'], $plan['pool_expired'], '512K/512K'); + $log .= "DONE Expired : EXPIRED NUXBILL $plan[pool_expired]
"; + } + } + r2(U . 'services/pppoe', 's', $log); + } + r2(U . 'services/hotspot', 'w', 'Unknown command'); case 'hotspot': $ui->assign('xfooter', ''); @@ -53,10 +115,10 @@ switch ($action) { $d = ORM::for_table('tbl_plans')->find_one($id); if ($d) { $ui->assign('d', $d); + $p = ORM::for_table('tbl_pool')->where('routers', $d['routers'])->find_many(); + $ui->assign('p', $p); $b = ORM::for_table('tbl_bandwidth')->find_many(); $ui->assign('b', $b); - $r = ORM::for_table('tbl_routers')->find_many(); - $ui->assign('r', $r); run_hook('view_edit_plan'); #HOOK $ui->display('hotspot-edit.tpl'); } else { @@ -96,6 +158,7 @@ switch ($action) { $validity = _post('validity'); $validity_unit = _post('validity_unit'); $routers = _post('routers'); + $pool_expired = _post('pool_expired'); $enabled = _post('enabled'); $msg = ''; @@ -134,8 +197,12 @@ switch ($action) { $mikrotik = Mikrotik::info($routers); $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); Mikrotik::addHotspotPlan($client, $name, $sharedusers, $rate); + if (!empty($pool_expired)) { + Mikrotik::setHotspotExpiredPlan($client, 'EXPIRED NUXBILL ' . $pool_expired, $pool_expired); + } } + $d = ORM::for_table('tbl_plans')->create(); $d->name_plan = $name; $d->id_bw = $id_bw; @@ -151,6 +218,7 @@ switch ($action) { $d->validity_unit = $validity_unit; $d->shared_users = $sharedusers; $d->routers = $routers; + $d->pool_expired = $pool_expired; $d->enabled = $enabled; $d->save(); @@ -176,6 +244,7 @@ switch ($action) { $validity = _post('validity'); $validity_unit = _post('validity_unit'); $routers = _post('routers'); + $pool_expired = _post('pool_expired'); $enabled = _post('enabled'); $msg = ''; @@ -213,6 +282,9 @@ switch ($action) { $mikrotik = Mikrotik::info($routers); $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); Mikrotik::setHotspotPlan($client, $name, $sharedusers, $rate); + if (!empty($pool_expired)) { + Mikrotik::setHotspotExpiredPlan($client, 'EXPIRED NUXBILL ' . $pool_expired, $pool_expired); + } } $d->name_plan = $name; @@ -228,6 +300,7 @@ switch ($action) { $d->validity_unit = $validity_unit; $d->shared_users = $sharedusers; $d->routers = $routers; + $d->pool_expired = $pool_expired; $d->enabled = $enabled; $d->save(); @@ -260,8 +333,6 @@ switch ($action) { $ui->assign('_title', $_L['PPPOE_Plans']); $d = ORM::for_table('tbl_bandwidth')->find_many(); $ui->assign('d', $d); - $p = ORM::for_table('tbl_pool')->find_many(); - $ui->assign('p', $p); $r = ORM::for_table('tbl_routers')->find_many(); $ui->assign('r', $r); run_hook('view_add_ppoe'); #HOOK @@ -274,10 +345,10 @@ switch ($action) { $d = ORM::for_table('tbl_plans')->find_one($id); if ($d) { $ui->assign('d', $d); + $p = ORM::for_table('tbl_pool')->where('routers', $d['routers'])->find_many(); + $ui->assign('p', $p); $b = ORM::for_table('tbl_bandwidth')->find_many(); $ui->assign('b', $b); - $p = ORM::for_table('tbl_pool')->find_many(); - $ui->assign('p', $p); $r = ORM::for_table('tbl_routers')->find_many(); $ui->assign('r', $r); run_hook('view_edit_ppoe'); #HOOK @@ -312,6 +383,7 @@ switch ($action) { $validity_unit = _post('validity_unit'); $routers = _post('routers'); $pool = _post('pool_name'); + $pool_expired = _post('pool_expired'); $enabled = _post('enabled'); $msg = ''; @@ -348,6 +420,9 @@ switch ($action) { $mikrotik = Mikrotik::info($routers); $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); Mikrotik::addPpoePlan($client, $name, $pool, $rate); + if (!empty($pool_expired)) { + Mikrotik::setPpoePlan($client, 'EXPIRED NUXBILL ' . $pool_expired, $pool_expired, '512K/512K'); + } } $d = ORM::for_table('tbl_plans')->create(); @@ -359,6 +434,7 @@ switch ($action) { $d->validity_unit = $validity_unit; $d->routers = $routers; $d->pool = $pool; + $d->pool_expired = $pool_expired; $d->enabled = $enabled; $d->save(); @@ -377,6 +453,7 @@ switch ($action) { $validity_unit = _post('validity_unit'); $routers = _post('routers'); $pool = _post('pool_name'); + $pool_expired = _post('pool_expired'); $enabled = _post('enabled'); $msg = ''; @@ -414,6 +491,9 @@ switch ($action) { $mikrotik = Mikrotik::info($routers); $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); Mikrotik::setPpoePlan($client, $name, $pool, $rate); + if (!empty($pool_expired)) { + Mikrotik::setPpoePlan($client, 'EXPIRED NUXBILL ' . $pool_expired, $pool_expired, '512K/512K'); + } } $d->name_plan = $name; @@ -423,6 +503,7 @@ switch ($action) { $d->validity_unit = $validity_unit; $d->routers = $routers; $d->pool = $pool; + $d->pool_expired = $pool_expired; $d->enabled = $enabled; $d->save(); diff --git a/system/controllers/settings.php b/system/controllers/settings.php index b152eec8..bae3cf7f 100644 --- a/system/controllers/settings.php +++ b/system/controllers/settings.php @@ -31,8 +31,14 @@ switch ($action) { if ($admin['user_type'] != 'Admin') { r2(U . "dashboard", 'e', $_L['Do_Not_Access']); } - $lan = ORM::for_table('tbl_language')->find_many(); - $ui->assign('lan', $lan); + $folders = []; + $files = scandir('system/lan/'); + foreach ($files as $file) { + if(is_dir('system/lan/'.$file) && !in_array($file,['.','..'])){ + $folders[] = $file; + } + } + $ui->assign('lan', $folders); $timezonelist = Timezone::timezoneList(); $ui->assign('tlist', $timezonelist); @@ -225,6 +231,8 @@ switch ($action) { $user_notification_payment = _post('user_notification_payment'); $address = _post('address'); $tawkto = _post('tawkto'); + $http_proxy = _post('http_proxy'); + $http_proxyauth = _post('http_proxyauth'); $radius_mode = _post('radius_mode') * 1; run_hook('save_settings'); #HOOK @@ -251,6 +259,28 @@ switch ($action) { $d->save(); + $d = ORM::for_table('tbl_appconfig')->where('setting', 'http_proxy')->find_one(); + if ($d) { + $d->value = $http_proxy; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'http_proxy'; + $d->value = $http_proxy; + $d->save(); + } + + $d = ORM::for_table('tbl_appconfig')->where('setting', 'http_proxyauth')->find_one(); + if ($d) { + $d->value = $http_proxyauth; + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'http_proxyauth'; + $d->value = $http_proxyauth; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'CompanyFooter')->find_one(); if ($d) { $d->value = $footer; diff --git a/system/cron.php b/system/cron.php index 6c324b7f..739853de 100644 --- a/system/cron.php +++ b/system/cron.php @@ -4,10 +4,40 @@ * PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/) **/ -require('../config.php'); -require('orm.php'); +// on some server, it getting error because of slash is backwards +function _autoloader($class) +{ + if (strpos($class, '_') !== false) { + $class = str_replace('_', DIRECTORY_SEPARATOR, $class); + if (file_exists(__DIR__.DIRECTORY_SEPARATOR.'autoload' . DIRECTORY_SEPARATOR . $class . '.php')) { + include __DIR__.DIRECTORY_SEPARATOR.'autoload' . DIRECTORY_SEPARATOR . $class . '.php'; + } else { + $class = str_replace("\\", DIRECTORY_SEPARATOR, $class); + if (file_exists(__DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php')) + include __DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php'; + } + } else { + if (file_exists(__DIR__.DIRECTORY_SEPARATOR.'autoload' . DIRECTORY_SEPARATOR . $class . '.php')) { + include __DIR__.DIRECTORY_SEPARATOR.'autoload' . DIRECTORY_SEPARATOR . $class . '.php'; + } else { + $class = str_replace("\\", DIRECTORY_SEPARATOR, $class); + if (file_exists(__DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php')) + include __DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php'; + } + } +} +spl_autoload_register('_autoloader'); + +if(php_sapi_name() !== 'cli'){ + echo "
";
+}
+
+
+require_once '../config.php';
+require_once 'orm.php';
 require_once 'autoload/PEAR2/Autoload.php';
+include "autoload/Hookers.php";
 
 ORM::configure("mysql:host=$db_host;dbname=$db_name");
 ORM::configure('username', $db_user);
@@ -16,49 +46,30 @@ ORM::configure('return_result_sets', true);
 ORM::configure('logging', true);
 
 
-include "autoload/Hookers.php";
-
 // notification message
-if(file_exists("system/uploads/notifications.json")){
-    $_notifmsg =json_decode(file_get_contents('system/uploads/notifications.json'), true);
+if (file_exists("uploads/notifications.json")) {
+    $_notifmsg = json_decode(file_get_contents('uploads/notifications.json'), true);
 }
-$_notifmsg_default = json_decode(file_get_contents('system/uploads/notifications.default.json'), true);
+$_notifmsg_default = json_decode(file_get_contents('uploads/notifications.default.json'), true);
 
 //register all plugin
-foreach (glob("plugin/*.php") as $filename) {
+foreach (glob(File::pathFixer("plugin/*.php")) as $filename) {
     include $filename;
 }
 
-// on some server, it getting error because of slash is backwards
-function _autoloader($class)
-{
-    if (strpos($class, '_') !== false) {
-        $class = str_replace('_', DIRECTORY_SEPARATOR, $class);
-        if (file_exists('autoload' . DIRECTORY_SEPARATOR . $class . '.php')) {
-            include 'autoload' . DIRECTORY_SEPARATOR . $class . '.php';
-        } else {
-            $class = str_replace("\\", DIRECTORY_SEPARATOR, $class);
-            if (file_exists(__DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php'))
-                include __DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php';
-        }
-    } else {
-        if (file_exists('autoload' . DIRECTORY_SEPARATOR . $class . '.php')) {
-            include 'autoload' . DIRECTORY_SEPARATOR . $class . '.php';
-        } else {
-            $class = str_replace("\\", DIRECTORY_SEPARATOR, $class);
-            if (file_exists(__DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php'))
-                include __DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php';
-        }
-    }
-}
-
-spl_autoload_register('_autoloader');
-
 $result = ORM::for_table('tbl_appconfig')->find_many();
 foreach ($result as $value) {
     $config[$value['setting']] = $value['value'];
 }
 
+echo "PHP Time\t" . date('Y-m-d H:i:s') . "\n";
+$res = ORM::raw_execute('SELECT NOW() AS WAKTU;');
+$statement = ORM::get_last_statement();
+$rows = array();
+while ($row = $statement->fetch(PDO::FETCH_ASSOC)) {
+    echo "MYSQL Time\t" . $row['WAKTU'] . "\n";
+}
+
 $_c = $config;
 
 date_default_timezone_set($config['timezone']);
@@ -66,7 +77,7 @@ date_default_timezone_set($config['timezone']);
 $textExpired = Lang::getNotifText('expired');
 
 $d = ORM::for_table('tbl_user_recharges')->where('status', 'on')->where_lte('expiration', date("Y-m-d"))->find_many();
-echo "Found ".count($d)." user(s)\n";
+echo "Found " . count($d) . " user(s)\n";
 run_hook('cronjob'); #HOOK
 
 foreach ($d as $ds) {
@@ -79,10 +90,15 @@ foreach ($d as $ds) {
             $u = ORM::for_table('tbl_user_recharges')->where('id', $ds['id'])->find_one();
             $c = ORM::for_table('tbl_customers')->where('id', $ds['customer_id'])->find_one();
             $m = ORM::for_table('tbl_routers')->where('name', $ds['routers'])->find_one();
+            $p = ORM::for_table('tbl_plans')->where('id', $u['plan_id'])->find_one();
 
             if (!$_c['radius_mode']) {
                 $client = Mikrotik::getClient($m['ip_address'], $m['username'], $m['password']);
-                Mikrotik::setHotspotLimitUptime($client, $c['username']);
+                if(!empty($p['pool_expired'])){
+                    Mikrotik::setHotspotUserPackage($client, $c['username'], 'EXPIRED NUXBILL '.$p['pool_expired']);
+                }else{
+                    Mikrotik::removeHotspotUser($client, $c['username']);
+                }
                 Mikrotik::removeHotspotActiveUser($client, $c['username']);
                 Message::sendPackageNotification($c['phonenumber'], $c['fullname'], $u['namebp'], $textExpired, $config['user_notification_expired']);
             }
@@ -92,7 +108,6 @@ foreach ($d as $ds) {
 
             // autorenewal from deposit
             if ($config['enable_balance'] == 'yes' && $c['auto_renewal']) {
-                $p = ORM::for_table('tbl_plans')->where('id', $u['plan_id'])->find_one();
                 if ($p && $p['enabled'] && $c['balance'] >= $p['price']) {
                     if (Package::rechargeUser($ds['customer_id'], $p['routers'], $p['id'], 'Customer', 'Balance')) {
                         // if success, then get the balance
@@ -106,10 +121,10 @@ foreach ($d as $ds) {
                             "\nRouter: " . $router_name .
                             "\nPrice: " . $p['price']);
                     }
-                }else{
+                } else {
                     echo "no renewall | plan enabled: $p[enabled] | User balance: $c[balance] | price $p[price]\n";
                 }
-            }else{
+            } else {
                 echo "no renewall | balance $config[enable_balance] auto_renewal $c[auto_renewal]\n";
             }
         } else echo " : ACTIVE \r\n";
@@ -122,10 +137,15 @@ foreach ($d as $ds) {
             $u = ORM::for_table('tbl_user_recharges')->where('id', $ds['id'])->find_one();
             $c = ORM::for_table('tbl_customers')->where('id', $ds['customer_id'])->find_one();
             $m = ORM::for_table('tbl_routers')->where('name', $ds['routers'])->find_one();
+            $p = ORM::for_table('tbl_plans')->where('id', $u['plan_id'])->find_one();
 
             if (!$_c['radius_mode']) {
                 $client = Mikrotik::getClient($m['ip_address'], $m['username'], $m['password']);
-                Mikrotik::disablePpoeUser($client, $c['username']);
+                if(!empty($p['pool_expired'])){
+                    Mikrotik::setPpoeUserPlan($client, $c['username'], 'EXPIRED NUXBILL '.$p['pool_expired']);
+                }else{
+                    Mikrotik::removePpoeUser($client, $c['username']);
+                }
                 Mikrotik::removePpoeActive($client, $c['username']);
                 Message::sendPackageNotification($c['phonenumber'], $c['fullname'], $u['namebp'], $textExpired, $config['user_notification_expired']);
             }
@@ -135,12 +155,15 @@ foreach ($d as $ds) {
 
             // autorenewal from deposit
             if ($config['enable_balance'] == 'yes' && $c['auto_renewal']) {
-                $p = ORM::for_table('tbl_plans')->where('id', $u['plan_id'])->find_one();
                 if ($p && $p['enabled'] && $c['balance'] >= $p['price']) {
                     if (Package::rechargeUser($ds['customer_id'], $p['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";
+                        echo "auto renewall Success\n";
                     } else {
+                        echo "plan enabled: $p[enabled] | User balance: $c[balance] | price $p[price]\n";
+                        echo "auto renewall Failed\n";
                         Message::sendTelegram("FAILED RENEWAL #cron\n\n#u$c[username] #buy #PPPOE \n" . $p['name_plan'] .
                             "\nRouter: " . $router_name .
                             "\nPrice: " . $p['price']);
diff --git a/system/cron_reminder.php b/system/cron_reminder.php
index 2985a4af..5a55e180 100644
--- a/system/cron_reminder.php
+++ b/system/cron_reminder.php
@@ -7,46 +7,21 @@
  * 0 7 * * * /usr/bin/php /var/www/system/cron_reminder.php
  **/
 
-require('../config.php');
-require('orm.php');
-
-require_once 'autoload/PEAR2/Autoload.php';
-
-ORM::configure("mysql:host=$db_host;dbname=$db_name");
-ORM::configure('username', $db_user);
-ORM::configure('password', $db_password);
-ORM::configure('return_result_sets', true);
-ORM::configure('logging', true);
-
-
-include "autoload/Hookers.php";
-
-// notification message
-if(file_exists("system/uploads/notifications.json")){
-    $_notifmsg =json_decode(file_get_contents('system/uploads/notifications.json'), true);
-}
-$_notifmsg_default = json_decode(file_get_contents('system/uploads/notifications.default.json'), true);
-
-//register all plugin
-foreach (glob("plugin/*.php") as $filename) {
-    include $filename;
-}
-
 // on some server, it getting error because of slash is backwards
 function _autoloader($class)
 {
     if (strpos($class, '_') !== false) {
         $class = str_replace('_', DIRECTORY_SEPARATOR, $class);
-        if (file_exists('autoload' . DIRECTORY_SEPARATOR . $class . '.php')) {
-            include 'autoload' . DIRECTORY_SEPARATOR . $class . '.php';
+        if (file_exists(__DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php')) {
+            include __DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php';
         } else {
             $class = str_replace("\\", DIRECTORY_SEPARATOR, $class);
             if (file_exists(__DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php'))
                 include __DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php';
         }
     } else {
-        if (file_exists('autoload' . DIRECTORY_SEPARATOR . $class . '.php')) {
-            include 'autoload' . DIRECTORY_SEPARATOR . $class . '.php';
+        if (file_exists(__DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php')) {
+            include __DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php';
         } else {
             $class = str_replace("\\", DIRECTORY_SEPARATOR, $class);
             if (file_exists(__DIR__ . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php'))
@@ -54,9 +29,34 @@ function _autoloader($class)
         }
     }
 }
-
 spl_autoload_register('_autoloader');
 
+if(php_sapi_name() !== 'cli'){
+    echo "
";
+}
+
+require_once '../config.php';
+require_once 'orm.php';
+require_once 'autoload/PEAR2/Autoload.php';
+include "autoload/Hookers.php";
+
+ORM::configure("mysql:host=$db_host;dbname=$db_name");
+ORM::configure('username', $db_user);
+ORM::configure('password', $db_password);
+ORM::configure('return_result_sets', true);
+ORM::configure('logging', true);
+
+// notification message
+if (file_exists("uploads/notifications.json")) {
+    $_notifmsg = json_decode(file_get_contents('uploads/notifications.json'), true);
+}
+$_notifmsg_default = json_decode(file_get_contents('uploads/notifications.default.json'), true);
+
+//register all plugin
+foreach (glob(File::pathFixer("plugin/*.php")) as $filename) {
+    include $filename;
+}
+
 $result = ORM::for_table('tbl_appconfig')->find_many();
 foreach ($result as $value) {
     $config[$value['setting']] = $value['value'];
@@ -69,6 +69,14 @@ $d = ORM::for_table('tbl_user_recharges')->where('status', 'on')->find_many();
 run_hook('cronjob_reminder'); #HOOK
 
 
+echo "PHP Time\t" . date('Y-m-d H:i:s') . "\n";
+$res = ORM::raw_execute('SELECT NOW() AS WAKTU;');
+$statement = ORM::get_last_statement();
+$rows = array();
+while ($row = $statement->fetch(PDO::FETCH_ASSOC)) {
+    echo "MYSQL Time\t" . $row['WAKTU'] . "\n";
+}
+
 
 $day7 = date('Y-m-d', strtotime("+7 day"));
 $day3 = date('Y-m-d', strtotime("+3 day"));
diff --git a/system/lan/english/common.lan.php b/system/lan/english/common.lan.php
index 44d946ba..e5e49c8f 100644
--- a/system/lan/english/common.lan.php
+++ b/system/lan/english/common.lan.php
@@ -375,13 +375,30 @@ $_L['Active'] = 'Active';
 $_L['Transfer_Balance'] = 'Transfer Balance';
 $_L['Send_your_balance'] = 'Send your balance?';
 $_L['Send'] = 'Send';
-$_L['Cannot_send_to_yourself'] = 'Cannot send to yourself';
-$_L['Sending_balance_success'] = 'Sending balance success';
-$_L['From'] = 'From';
-$_L['To'] = 'To';
-$_L['insufficient_balance'] = 'insufficient balance';
-$_L['Send_Balance'] = 'Send Balance';
-$_L['Received_Balance'] = 'Received Balance';
-$_L['Minimum_Balance_Transfer'] = 'Minimum Balance Transfer';
-$_L['Minimum_Transfer'] = 'Minimum Transfer';
-$_L['Company_Logo'] = 'Company Logo';
+$_L['Cannot_send_to_yourself'] = 'Cannot send to yourself';
+$_L['Sending_balance_success'] = 'Sending balance success';
+$_L['From'] = 'From';
+$_L['To'] = 'To';
+$_L['insufficient_balance'] = 'insufficient balance';
+$_L['Send_Balance'] = 'Send Balance';
+$_L['Received_Balance'] = 'Received Balance';
+$_L['Minimum_Balance_Transfer'] = 'Minimum Balance Transfer';
+$_L['Minimum_Transfer'] = 'Minimum Transfer';
+$_L['Company_Logo'] = 'Company Logo';
+$_L['Expired_IP_Pool'] = 'Expired IP Pool';
+$_L['Expired_IP_Pool'] = 'Expired IP Pool';
+$_L['Proxy'] = 'Proxy';
+$_L['Proxy_Server'] = 'Proxy Server';
+$_L['Proxy_Server_Login'] = 'Proxy Server Login';
+$_L['Hotspot_Plan'] = 'Hotspot Plan';
+$_L['PPPOE_Plan'] = 'PPPOE Plan';
+$_L['UNKNOWN'] = 'UNKNOWN';
+$_L['Are_You_Sure'] = 'Are You Sure?';
+$_L['Success_to_send_package'] = 'Success to send package';
+$_L['Target_has_active_plan_different_with_current_plant'] = 'Target has active plan, different with current plant.';
+$_L['Recharge_a_friend'] = 'Recharge a friend';
+$_L['Buy_for_friend'] = 'Buy for friend';
+$_L['Buy_this_for_friend_account'] = 'Buy this for friend account?';
+$_L['Review_package_before_recharge'] = 'Review package before recharge';
+$_L['Deactivate'] = 'Deactivate';
+$_L['Sync'] = 'Sync';
diff --git a/system/lan/indonesia/common.lan.php b/system/lan/indonesia/common.lan.php
index 8a197d45..f789d5b7 100644
--- a/system/lan/indonesia/common.lan.php
+++ b/system/lan/indonesia/common.lan.php
@@ -338,3 +338,11 @@ $_L['Country_Code_Phone'] = 'Kode Negara Telepon';
 $_L['Voucher_activation_menu_will_be_hidden'] = 'Info Pembelian Voucher dan Redeem akan disembunyikan';
 $_L['Customer_can_deposit_money_to_buy_voucher'] = 'Pelanggan dapat topup saldo untuk langganan Internet';
 $_L['Allow_balance_transfer_between_customers'] = 'Bolehkan transfer saldo antar pelanggan';
+$_L['Refill_Balance'] = 'Refill Balance';
+$_L['Balance_Plans'] = 'Balance Plans';
+$_L['Expired_IP_Pool'] = 'Expired IP Pool';
+$_L['Company_Logo'] = 'Company Logo';
+$_L['Disable_Voucher'] = 'Disable Voucher';
+$_L['Minimum_Balance_Transfer'] = 'Minimum Balance Transfer';
+$_L['Reminder_Notification'] = 'Reminder Notification';
+$_L['Invoice_Footer'] = 'Invoice Footer';
diff --git a/system/lan/spanish/common.lan.php b/system/lan/spanish/common.lan.php
index ec13dfd0..c4ca672a 100644
--- a/system/lan/spanish/common.lan.php
+++ b/system/lan/spanish/common.lan.php
@@ -340,4 +340,5 @@ $_L['Invoice'] = 'Invoice';
 $_L['Country_Code_Phone'] = 'Country Code Phone';
 $_L['Voucher_activation_menu_will_be_hidden'] = 'Voucher activation menu will be hidden';
 $_L['Customer_can_deposit_money_to_buy_voucher'] = 'Customer can deposit money to buy voucher';
-$_L['Allow_balance_transfer_between_customers'] = 'Allow balance transfer between customers';
\ No newline at end of file
+$_L['Allow_balance_transfer_between_customers'] = 'Allow balance transfer between customers';$_L['Refill_Balance'] = 'Refill Balance';
+$_L['Balance_Plans'] = 'Balance Plans';
diff --git a/system/radius.php b/system/radius.php
index 174a862a..13073efc 100644
--- a/system/radius.php
+++ b/system/radius.php
@@ -7,11 +7,12 @@ if(php_sapi_name() !== 'cli'){
     die("RUN ON COMMAND LINE ONLY BY RADIUS ENGINE");
 }
 
-require(__DIR__.'/../config.php');
-require(__DIR__.'/orm.php');
+require_once __DIR__.File::pathFixer('/../config.php');
+require_once __DIR__.File::pathFixer('orm.php');
+require_once __DIR__.File::pathFixer('/autoload/PEAR2/Autoload.php');
+include __DIR__.File::pathFixer("/autoload/Hookers.php");
 
 use PEAR2\Net\RouterOS;
-require_once 'autoload/PEAR2/Autoload.php';
 
 ORM::configure("mysql:host=$db_host;dbname=$db_name");
 ORM::configure('username', $db_user);
diff --git a/system/updates.json b/system/updates.json
index 6269b896..77023a3d 100644
--- a/system/updates.json
+++ b/system/updates.json
@@ -17,5 +17,9 @@
     "2023.8.28" : [
         "ALTER TABLE `tbl_user_recharges` ADD `recharged_time` time NOT NULL DEFAULT '00:00:00' AFTER `recharged_on`;",
         "ALTER TABLE `tbl_transactions` ADD `recharged_time` time NOT NULL DEFAULT '00:00:00' AFTER `recharged_on`;"
+    ],
+    "2023.9.5" : [
+        "DROP TABLE `tbl_language`;",
+        "ALTER TABLE `tbl_plans` ADD `pool_expired`  varchar(40) NOT NULL DEFAULT '' AFTER `pool`;"
     ]
 }
\ No newline at end of file
diff --git a/ui/ui/app-localisation.tpl b/ui/ui/app-localisation.tpl
index a5ca2ba5..0adf9961 100644
--- a/ui/ui/app-localisation.tpl
+++ b/ui/ui/app-localisation.tpl
@@ -45,18 +45,16 @@
                     
                     
-
+
-
- {$_L['Add_Language']} +
+ To add new Language, just add the folder, it will automatically detected
@@ -78,8 +76,8 @@
- {$_L['currency_help']}
+ {$_L['currency_help']}
diff --git a/ui/ui/app-notifications.tpl b/ui/ui/app-notifications.tpl index a453f864..b3d14000 100644 --- a/ui/ui/app-notifications.tpl +++ b/ui/ui/app-notifications.tpl @@ -80,6 +80,7 @@ [[type]] is Hotspot/PPPOE.
[[plan_name]] Internet Package.
[[plan_price]] Internet Package Prices.
+ [[name]] Receiver name.
[[user_name]] Username internet.
[[user_password]] User password.
[[expired_date]] Expired datetime.
@@ -106,9 +107,12 @@ [[type]] is Hotspot/PPPOE.
[[plan_name]] Internet Package.
[[plan_price]] Internet Package Prices.
+ [[name]] Receiver name.
[[user_name]] Username internet.
[[user_password]] User password.
[[trx_date]] Transaction datetime.
+ [[balance_before]] Balance Before.
+ [[balance]] Balance After.
[[footer]] Invoice Footer.

@@ -122,7 +126,8 @@

[[name]] Receiver name.
- [[balance]] how much balance have been send. + [[balance]] how much balance have been send.
+ [[current_balance]] Current Balance.

@@ -135,7 +140,8 @@

[[name]] Sender name.
- [[balance]] how much balance have been received. + [[balance]] how much balance have been received.
+ [[current_balance]] Current Balance.

diff --git a/ui/ui/app-settings.tpl b/ui/ui/app-settings.tpl index bcf268b6..1b747a23 100644 --- a/ui/ui/app-settings.tpl +++ b/ui/ui/app-settings.tpl @@ -24,7 +24,8 @@
- For PDF Reports | Beset size 1078 x 200 | uploaded image will be autosize + For PDF Reports | Best size 1078 x 200 | uploaded image will be + autosize
logo for PDF @@ -135,7 +136,8 @@
-
@@ -270,7 +272,6 @@ {Lang::T('Invoice')} -
@@ -281,6 +282,30 @@
+
+
+ +
+ {Lang::T('Proxy')} +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
diff --git a/ui/ui/autoload-pool.tpl b/ui/ui/autoload-pool.tpl index bb1b6d75..c4f825de 100644 --- a/ui/ui/autoload-pool.tpl +++ b/ui/ui/autoload-pool.tpl @@ -1,4 +1,4 @@ - + {foreach $d as $ds} {/foreach} \ No newline at end of file diff --git a/ui/ui/autoload-server.tpl b/ui/ui/autoload-server.tpl index 9260b1b9..51e6616b 100644 --- a/ui/ui/autoload-server.tpl +++ b/ui/ui/autoload-server.tpl @@ -1,4 +1,4 @@ - + {foreach $d as $ds} {/foreach} \ No newline at end of file diff --git a/ui/ui/autoload.tpl b/ui/ui/autoload.tpl index d96e117b..86f0d744 100644 --- a/ui/ui/autoload.tpl +++ b/ui/ui/autoload.tpl @@ -1,4 +1,4 @@ {foreach $d as $ds} - + {/foreach} \ No newline at end of file diff --git a/ui/ui/community.tpl b/ui/ui/community.tpl index 9d673bf1..c23242c6 100644 --- a/ui/ui/community.tpl +++ b/ui/ui/community.tpl @@ -130,7 +130,7 @@
-
+

PHPNUXBILL

@@ -142,8 +142,7 @@
+ {else} + {Lang::T('Recharge')}
{/if} {Lang::T('Back')}
diff --git a/ui/ui/customers.tpl b/ui/ui/customers.tpl index 38cd5d4e..dd6d598c 100644 --- a/ui/ui/customers.tpl +++ b/ui/ui/customers.tpl @@ -24,34 +24,37 @@
 
- +
- + - + {foreach $d as $ds} - - - + + + - + {/foreach} diff --git a/ui/ui/dashboard.tpl b/ui/ui/dashboard.tpl index 873d4ee0..e89078a1 100644 --- a/ui/ui/dashboard.tpl +++ b/ui/ui/dashboard.tpl @@ -33,7 +33,7 @@
-

{$u_act}

+

{$u_act}/{$u_all}

{$_L['Users_Active']}

@@ -47,7 +47,7 @@
-

{$u_all}

+

{$c_all}

{$_L['Total_Users']}

diff --git a/ui/ui/hotspot-add.tpl b/ui/ui/hotspot-add.tpl index 448dc26b..de325104 100644 --- a/ui/ui/hotspot-add.tpl +++ b/ui/ui/hotspot-add.tpl @@ -112,7 +112,8 @@
- + {foreach $r as $rs} {/foreach} @@ -120,9 +121,16 @@

{Lang::T('Cannot be change after saved')}

- +
+ +
+ +
+
-
+
Or {$_L['Cancel']}
diff --git a/ui/ui/hotspot-edit.tpl b/ui/ui/hotspot-edit.tpl index 769c2ff4..e1868445 100644 --- a/ui/ui/hotspot-edit.tpl +++ b/ui/ui/hotspot-edit.tpl @@ -114,9 +114,20 @@
+
+ +
+ +
+
-
+
Or {$_L['Cancel']}
diff --git a/ui/ui/hotspot.tpl b/ui/ui/hotspot.tpl index 1d26c376..fdd7ab3b 100644 --- a/ui/ui/hotspot.tpl +++ b/ui/ui/hotspot.tpl @@ -1,68 +1,81 @@ {include file="sections/header.tpl"} -
-
-
-
{$_L['Hotspot_Plans']}
-
-
-
- -
-
- -
- -
- -
-
- -
-   -
-
-
{$_L['Manage']} {$_L['Username']} {$_L['Full_Name']} {Lang::T('Balance')} {$_L['Phone_Number']} {$_L['Email']}{$_L['Package']} {$_L['Created_On']}{$_L['Recharge']}{$_L['Manage']}
- {Lang::T('View')} - {$ds['username']}{$ds['fullname']}{$ds['username']}{$ds['fullname']} {Lang::moneyFormat($ds['balance'])} {$ds['phonenumber']} {$ds['email']} + + {Lang::dateTimeFormat($ds['created_at'])}{$_L['Recharge']} +   {Lang::T('View')}   + {$_L['Recharge']} +
- - - - - - - - - - - - - - - {foreach $d as $ds} - - - - - - - - - - - - {/foreach} - -
{$_L['Plan_Name']}{$_L['Plan_Type']}{$_L['Bandwidth_Plans']}{$_L['Plan_Price']}{$_L['Time_Limit']}{$_L['Data_Limit']}{$_L['Plan_Validity']}{$_L['Routers']}{$_L['Manage']}
{$ds['name_plan']}{$ds['typebp']}{$ds['name_bw']}{Lang::moneyFormat($ds['price'])}{$ds['time_limit']} {$ds['time_unit']}{$ds['data_limit']} {$ds['data_unit']}{$ds['validity']} {$ds['validity_unit']}{$ds['routers']} - {$_L['Edit']} - {$_L['Delete']} -
-
- {$paginator['contents']} +
+
+
+
+
+ sync +
{$_L['Hotspot_Plans']} +
+
+
+
+ +
+   +
+
+ + + + + + + + + + + + + + + + + {foreach $d as $ds} + + + + + + + + + + + + + {/foreach} + +
{$_L['Plan_Name']}{$_L['Plan_Type']}{$_L['Bandwidth_Plans']}{$_L['Plan_Price']}{$_L['Time_Limit']}{$_L['Data_Limit']}{$_L['Plan_Validity']}{$_L['Routers']}{Lang::T('Expired IP Pool')}{$_L['Manage']}
{$ds['name_plan']}{$ds['typebp']}{$ds['name_bw']}{Lang::moneyFormat($ds['price'])}{$ds['time_limit']} {$ds['time_unit']}{$ds['data_limit']} {$ds['data_unit']}{$ds['validity']} {$ds['validity_unit']}{$ds['routers']}{$ds['pool_expired']} + {$_L['Edit']} + {$_L['Delete']} +
+
+ {$paginator['contents']} -
-
-
-
+ + + + -{include file="sections/footer.tpl"} +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/images/error.png b/ui/ui/images/error.png new file mode 100644 index 00000000..a21c2c52 Binary files /dev/null and b/ui/ui/images/error.png differ diff --git a/ui/ui/pool.tpl b/ui/ui/pool.tpl index d49a78f1..a5e40ecd 100644 --- a/ui/ui/pool.tpl +++ b/ui/ui/pool.tpl @@ -3,7 +3,14 @@
-
{$_L['Pool']}
+
+
+ sync +
+ {$_L['Pool']} +
@@ -45,9 +52,9 @@ {$ds['range_ip']} {$ds['routers']} - {$_L['Edit']} - {$_L['Edit']} + {$_L['Delete']} diff --git a/ui/ui/pppoe-add.tpl b/ui/ui/pppoe-add.tpl index a79920d1..f3c0716b 100644 --- a/ui/ui/pppoe-add.tpl +++ b/ui/ui/pppoe-add.tpl @@ -60,7 +60,7 @@
- {foreach $r as $rs} @@ -72,14 +72,21 @@
-
-
-
+ +
+ +
+
+
+
Or {$_L['Cancel']}
diff --git a/ui/ui/pppoe-edit.tpl b/ui/ui/pppoe-edit.tpl index aa23412a..10958805 100644 --- a/ui/ui/pppoe-edit.tpl +++ b/ui/ui/pppoe-edit.tpl @@ -60,9 +60,20 @@
- {foreach $p as $ps} - + + {/foreach} + +
+
+
+ +
+
diff --git a/ui/ui/pppoe.tpl b/ui/ui/pppoe.tpl index 6d14b1c7..e6e34d79 100644 --- a/ui/ui/pppoe.tpl +++ b/ui/ui/pppoe.tpl @@ -1,63 +1,76 @@ {include file="sections/header.tpl"} -
-
-
-
{$_L['PPPOE_Plans']}
-
-
-
- -
-   -
-
- - - - - - - - - - - - - - {foreach $d as $ds} - - - - - - - - - - {/foreach} - -
{$_L['Plan_Name']}{$_L['Bandwidth_Plans']}{$_L['Plan_Price']}{$_L['Plan_Validity']}{$_L['Pool']}{$_L['Routers']}{$_L['Manage']}
{$ds['name_plan']}{$ds['name_bw']}{Lang::moneyFormat($ds['price'])}{$ds['validity']} {$ds['validity_unit']}{$ds['pool']}{$ds['routers']} - {$_L['Edit']} - {$_L['Delete']} -
-
- {$paginator['contents']} -
-
-
-
+
+
+
+
+
+ sync +
{$_L['PPPOE_Plans']} +
+
+
+
+ +
+   +
+
+ + + + + + + + + + + + + + + {foreach $d as $ds} + + + + + + + + + + + {/foreach} + +
{$_L['Plan_Name']}{$_L['Bandwidth_Plans']}{$_L['Plan_Price']}{$_L['Plan_Validity']}{$_L['Pool']}{Lang::T('Expired IP Pool')}{$_L['Routers']}{$_L['Manage']}
{$ds['name_plan']}{$ds['name_bw']}{Lang::moneyFormat($ds['price'])}{$ds['validity']} {$ds['validity_unit']}{$ds['pool']}{$ds['pool_expired']}{$ds['routers']} + {$_L['Edit']} + {$_L['Delete']} +
+
+ {$paginator['contents']} +
+
+
+
-{include file="sections/footer.tpl"} +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/prepaid-edit.tpl b/ui/ui/prepaid-edit.tpl index 8e46332e..f7d5d92a 100644 --- a/ui/ui/prepaid-edit.tpl +++ b/ui/ui/prepaid-edit.tpl @@ -28,12 +28,15 @@
-
-
- +
+ +
+
+
diff --git a/ui/ui/prepaid.tpl b/ui/ui/prepaid.tpl index 3a8ad2be..bd7c0298 100644 --- a/ui/ui/prepaid.tpl +++ b/ui/ui/prepaid.tpl @@ -3,7 +3,13 @@
-
{$_L['Prepaid_User']}
+
+
+ sync +
{$_L['Prepaid_User']} +
@@ -41,7 +47,7 @@ {foreach $d as $ds} - + {$ds['username']} {$ds['namebp']} {$ds['type']} @@ -53,6 +59,7 @@ {$_L['Edit']} {$_L['Delete']} diff --git a/ui/ui/recharge.tpl b/ui/ui/recharge.tpl index ddfd28fc..b16bbc4c 100644 --- a/ui/ui/recharge.tpl +++ b/ui/ui/recharge.tpl @@ -1,53 +1,58 @@ {include file="sections/header.tpl"} -
-
-
-
{$_L['Recharge_Account']}
-
-
-
- -
- -
-
-
- -
- {$_L['Hotspot_Plans']} - {$_L['PPPOE_Plans']} -
-
-
- -
- -
-
+
+
+
+
{$_L['Recharge_Account']}
+
+ +
+ +
+ +
+
+
+ +
+ {$_L['Hotspot_Plans']} + {$_L['PPPOE_Plans']} +
+
+
+ +
+ +
+
-
- -
- -
-
+
+ +
+ +
+
-
-
- - Or {$_L['Cancel']} -
-
- -
-
-
-
+
+
+ + Or {$_L['Cancel']} +
+
+ +
+
+
+
-{include file="sections/footer.tpl"} +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/router-error.tpl b/ui/ui/router-error.tpl index fad1e26d..59293434 100644 --- a/ui/ui/router-error.tpl +++ b/ui/ui/router-error.tpl @@ -4,7 +4,7 @@ - Router Error - PHPNuxBill + Error - PHPNuxBill @@ -32,27 +32,45 @@
-
-

- Router Error -

-
-
+
+ +
-
- {$error_meesage} +
+ +
+

+ {$error_title} +

+
+
+ +
+
+

+ {$error_message} +


+
+
- back +
+
+
-
- PHPNuxBill by iBNuX -
diff --git a/ui/ui/routers-add.tpl b/ui/ui/routers-add.tpl index d5e2ffca..35329d36 100644 --- a/ui/ui/routers-add.tpl +++ b/ui/ui/routers-add.tpl @@ -42,7 +42,8 @@
- +
diff --git a/ui/ui/scripts/custom.js b/ui/ui/scripts/custom.js index 54e7f8bd..b7f9b122 100644 --- a/ui/ui/scripts/custom.js +++ b/ui/ui/scripts/custom.js @@ -14,7 +14,7 @@ $(document).ready(function () { $('#TimeLimit').show(); $('#DataLimit').show(); } - + if ($('#Unlimited').is(':checked')) { $('#Type').hide(); $('#TimeLimit').hide(); @@ -26,12 +26,12 @@ $(document).ready(function () { if ($('#Hotspot').is(':checked')) { $('#p').hide(); $('#h').show(); - } + } if ($('#PPPOE').is(':checked')) { $('#p').show(); $('#h').hide(); } - + }); }); $("#Hotspot").prop("checked", true).change(); @@ -48,6 +48,7 @@ $(document).ready(function(){ cache: false, success: function(msg){ $("#pool_name").html(msg); + $("#pool_expired").html(msg); } }); }); @@ -62,10 +63,10 @@ $(function() { dataType: "html", url: "index.php?_route=autoload/server", success: function(msg){ - $("#server").html(msg); + $("#server").html(msg); } }); - + $("#server").change(getAjaxAlamat); function getAjaxAlamat(){ var server = $("#server").val(); diff --git a/ui/ui/sections/footer.tpl b/ui/ui/sections/footer.tpl index daca93fe..cefb25f0 100644 --- a/ui/ui/sections/footer.tpl +++ b/ui/ui/sections/footer.tpl @@ -22,6 +22,17 @@ $(document).ready(function() { $('.select2').select2({theme: "bootstrap"}); }); + +$(document).ready(function() { + $('.select2tag').select2({theme: "bootstrap", tags: true}); +}); + +var listAtts = document.querySelectorAll(`[api-get-text]`); +listAtts.forEach(function(el) { + $.get(el.getAttribute('api-get-text'), function(data) { + el.innerHTML = data; + }); +}); {/literal} diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index efb7d216..ad2fa9ca 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -241,8 +241,8 @@ href="{$_url}settings/notifications">{Lang::T('User Notification')}
  • {$_L['Administrator_Users']}
  • -
  • {$_L['Backup_Restore']}
  • + {*
  • {$_L['Backup_Restore']}
  • *}
  • {Lang::T('Plugin Manager')}
  • diff --git a/ui/ui/sections/user-footer.tpl b/ui/ui/sections/user-footer.tpl index 80701398..7c690beb 100644 --- a/ui/ui/sections/user-footer.tpl +++ b/ui/ui/sections/user-footer.tpl @@ -1,45 +1,58 @@ -
    - {if isset($_c['CompanyFooter'])} -
    - {$_c['CompanyFooter']} -
    - {else} - - {/if} -
    +
    + {if isset($_c['CompanyFooter'])} +
    + {$_c['CompanyFooter']} +
    + {else} + + {/if} +
    - - - + + + - - + + -{if isset($xfooter)} - {$xfooter} -{/if} + {if isset($xfooter)} + {$xfooter} + {/if} -{if $_c['tawkto'] != ''} - - - -{/if} + {if $_c['tawkto'] != ''} + + + + {/if} - + {literal} + + {/literal} + + \ No newline at end of file diff --git a/ui/ui/sections/user-header.tpl b/ui/ui/sections/user-header.tpl index cdbee5ad..7965899a 100644 --- a/ui/ui/sections/user-header.tpl +++ b/ui/ui/sections/user-header.tpl @@ -27,6 +27,16 @@ color: red; background: yellow; } + + .content-wrapper { + margin-top: 50px; + } + + @media (max-width: 767px) { + .content-wrapper { + margin-top: 100px; + } + } {if isset($xheader)} @@ -37,8 +47,7 @@
    - -
    +
    -
    {/if} @@ -54,7 +65,7 @@ - + @@ -93,19 +104,19 @@ {if $_bill['time'] ne ''}{Lang::dateAndTimeFormat($_bill['expiration'],$_bill['time'])}{/if}  + {if $nux_ip} + + + + + {/if} + {if $nux_mac} + + + + + {/if} {if $_bill['type'] == 'Hotspot' && $_bill['status'] == 'on'} - {if $nux_ip} - - - - - {/if} - {if $nux_mac} - - - - - {/if}
    {$_L['Username']}{$_bill['username']}{$_user['username']}
    {$_L['Password']}
    {Lang::T('Current IP')}{$nux_ip}
    {Lang::T('Current MAC')}{$nux_mac}
    {Lang::T('Current IP')}{$nux_ip}
    {Lang::T('Current MAC')}{$nux_mac}
    {Lang::T('Login Status')} @@ -156,7 +167,7 @@
    + onclick="return confirm('{Lang::T("Are You Sure?")}')" value="balance">
    @@ -172,6 +183,23 @@ } +
    +

    {Lang::T("Recharge a friend")}

    +
    +
    +
    +
    +
    + +
    +
    + +
    +
    +
    +
    {/if}
    diff --git a/ui/ui/user-login.tpl b/ui/ui/user-login.tpl index 3a5a4d29..5d5ea4de 100644 --- a/ui/ui/user-login.tpl +++ b/ui/ui/user-login.tpl @@ -70,10 +70,10 @@
    - + {$_L['Register']}
    - {$_L['Register']} +
    diff --git a/ui/ui/user-orderPlan.tpl b/ui/ui/user-orderPlan.tpl index d8a2c91b..96a5829d 100644 --- a/ui/ui/user-orderPlan.tpl +++ b/ui/ui/user-orderPlan.tpl @@ -33,10 +33,6 @@ {/foreach} - -
    -
    {Lang::T('Balance')} {Lang::moneyFormat($_user['balance'])}
    -
    {/if} {foreach $routers as $router}
    @@ -47,7 +43,7 @@
    {/if} {if count($plans_hotspot)>0} -
    Hotspot
    +
    {Lang::T('Hotspot Plan')}
    {foreach $plans_hotspot as $plan} {if $router['name'] eq $plan['routers']} @@ -83,6 +79,11 @@ class="btn btn-sm btn-block btn-success">{Lang::T('Pay With Balance')} {/if}
    + {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && $_user['balance']>=$plan['price']} + {Lang::T('Buy for friend')} + {/if} @@ -91,7 +92,7 @@ {/if} {if count($plans_pppoe)>0} -
    PPPOE
    +
    {Lang::T('PPPOE Plan')}
    {foreach $plans_pppoe as $plan} {if $router['name'] eq $plan['routers']} @@ -127,6 +128,11 @@ class="btn btn-sm btn-block btn-success">{Lang::T('Pay With Balance')} {/if}
    + {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && $_user['balance']>=$plan['price']} + {Lang::T('Buy for friend')} + {/if} diff --git a/ui/ui/user-sendPlan.tpl b/ui/ui/user-sendPlan.tpl new file mode 100644 index 00000000..1e959da2 --- /dev/null +++ b/ui/ui/user-sendPlan.tpl @@ -0,0 +1,43 @@ +{include file="sections/user-header.tpl"} + +
    +
    +
    +
    +
    {$plan['name_plan']}
    +
    + + + + + + + + + + + + + + + +
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    +
    + +
    +
    +
    +{include file="sections/user-footer.tpl"} \ No newline at end of file diff --git a/version.json b/version.json index ede51202..5e926093 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2023.8.30" + "version": "2023.9.15" } \ No newline at end of file