diff --git a/.gitignore b/.gitignore index 5a2ce6e7..85d079af 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,8 @@ system/plugin/ui/* !system/plugin/ui/index.html ui/ui_custom/** !ui/ui_custom/index.html -!ui/ui_custom/README.md \ No newline at end of file +!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 diff --git a/CHANGELOG.md b/CHANGELOG.md index e65825bc..56210401 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,28 @@ # CHANGELOG +## 2023.8.15 + +- Fix PPPOE Delete Customer +- Fix Header Admin and Customer +- Fix PDF Export by Period +- Add pppoe_password for Customer, this pppoe_password only admin can change +- Country Code Number Settings +- Customer Meta Table for Custom Fields +- Fix Add and Edit Customer Form for admin +- add Notification Message Editor +- cron reminder +- Balance System, Customer can deposit money +- Auto renewal when package expired using Customer Balance + + ## 2023.8.1 - Add Update file script, one click updating PHPNuxBill - Add Custom UI folder, to custome your own template - Delete debug text - Fix Vendor JS + ## 2023.7.28 - Fix link buy Voucher @@ -22,13 +38,13 @@ Because the first time phpmixbill created, plan validity only for days and Months, many request ask for minutes and hours, i change it, but not the database. ## 2023.6.15 -- User can connect to internet from User Dashboard +- Customer can connect to internet from Customer Dashboard - Fix Confirm when delete - Change Logo PHPNuxBill - Using Composer -- Fix Search User -- Fix user check, if not found will logout -- User password show but hidden +- Fix Search Customer +- Fix Customer check, if not found will logout +- Customer password show but hidden - Voucher code hidden ## 2023.6.8 diff --git a/README.md b/README.md index d19af204..128d6cb4 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,10 @@ Minimum Requirements - Linux or Windows OS - PHP Version 7.4 - Both PDO & MySQLi Support -- GD2 Image Library -- CURL support +- PHP-GD2 Image Library +- PHP-CURL +- PHP-ZIP +- PHP-Mbstring - MySQL Version 4.1.x and above can be Installed in Raspberry Pi Device. @@ -48,6 +50,10 @@ The problem with windows is hard to set cronjob, better Linux [Installation instructions](https://github.com/hotspotbilling/phpnuxbill/wiki) +## Docker Version + +[Docker Repository](https://github.com/animegasan/phpnuxbill) + ## RADIUS system Still on development diff --git a/install/phpnuxbill.sql b/install/phpnuxbill.sql index 38169450..602f8364 100644 --- a/install/phpnuxbill.sql +++ b/install/phpnuxbill.sql @@ -50,10 +50,13 @@ CREATE TABLE `id` int(10) NOT NULL, `username` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `password` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `pppoe_password` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '1', `fullname` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `address` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci, `phonenumber` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0', `email` varchar(128) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '1', + `balance` decimal(15,2) NOT NULL COMMENT 'For Money Deposit', + `auto_renewal` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Auto renewal from balance', `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `last_login` datetime DEFAULT NULL ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci; @@ -295,6 +298,19 @@ CREATE TABLE `status` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci; + +-- +-- Struktur dari tabel `tbl_customers_meta` +-- + +CREATE TABLE `tbl_customers_meta` ( + `id` int(11) NOT NULL, + `customer_id` int(11) NOT NULL, + `meta_key` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', + `meta_value` longtext COLLATE utf8mb4_general_ci +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + + -- -- Indexes for dumped tables @@ -543,6 +559,17 @@ ALTER TABLE ALTER TABLE `tbl_voucher` MODIFY `id` int(10) NOT NULL AUTO_INCREMENT; +-- +-- Indeks untuk tabel `tbl_customers_meta` +-- +ALTER TABLE `tbl_customers_meta` + ADD PRIMARY KEY (`id`); + +-- +-- AUTO_INCREMENT untuk tabel `tbl_customers_meta` +-- +ALTER TABLE `tbl_customers_meta` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; COMMIT; -- diff --git a/install/step2.php b/install/step2.php index f65f6de4..df1989e3 100644 --- a/install/step2.php +++ b/install/step2.php @@ -57,7 +57,7 @@ Continue

Update System"); } else { echo ("
$ltext
Sorry. The requirements of PHPNuxBill is not available on your server. - Please contact with us- iesien22@yahoo.com with this code- $passed Or contact with your server administrator + Contact with us at Telegram @phpnuxbill with this code- $passed Or contact with your server administrator

Correct The Problem To Continue"); } diff --git a/system/autoload/Balance.php b/system/autoload/Balance.php new file mode 100644 index 00000000..2b3713d2 --- /dev/null +++ b/system/autoload/Balance.php @@ -0,0 +1,71 @@ +where('id', $id_customer)->find_one(); + $c->balance = $amount + $c['balance']; + $c->save(); + } + + public static function transfer($id_customer, $phoneTarget, $amount) + { + global $config; + if ($config['allow_balance_transfer'] == 'yes') { + if(Balance::min($id_customer, $amount)){ + if(Balance::plusByPhone($phoneTarget, $amount)){ + return true; + }else{ + Balance::plus($id_customer, $amount); + return false; + } + }else{ + return false; + } + }else{ + return false; + } + } + + public static function min($id_customer, $amount) + { + $c = ORM::for_table('tbl_customers')->where('id', $id_customer)->find_one(); + if ($c && $c['balance'] >= $amount) { + $c->balance = $amount - $c['balance']; + $c->save(); + return true; + } else { + return false; + } + } + + public static function plusByPhone($phone_customer, $amount) + { + $c = ORM::for_table('tbl_customers')->where('username', $phone_customer)->find_one(); + if($c){ + $c->balance = $amount + $c['balance']; + $c->save(); + return true; + } + return false; + } + + public static function minByPhone($phone_customer, $amount) + { + $c = ORM::for_table('tbl_customers')->where('username', $phone_customer)->find_one(); + if ($c && $c['balance'] >= $amount) { + $c->balance = $amount - $c['balance']; + $c->save(); + return true; + } else { + return false; + } + } +} diff --git a/system/autoload/Lang.php b/system/autoload/Lang.php index dc9292f6..6c790bd4 100644 --- a/system/autoload/Lang.php +++ b/system/autoload/Lang.php @@ -4,12 +4,31 @@ * PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/) **/ -class Lang { - public static function T($var) { +class Lang +{ + public static function T($var) + { return Lang($var); } - public static function htmlspecialchars($var) { + public static function htmlspecialchars($var) + { return htmlspecialchars($var); } + + public static function moneyFormat($var) + { + global $config; + return $config['currency_code'] . ' ' .number_format($var, 0, $config['dec_point'], $config['thousands_sep']); + } + + public static function phoneFormat($phone) + { + global $config; + if(Validator::UnsignedNumber($phone) && !empty($config['country_code_phone'])){ + return preg_replace('/^0/', $config['country_code_phone'], $phone); + }else{ + return $phone; + } + } } diff --git a/system/autoload/Message.php b/system/autoload/Message.php index 0606f42c..0373d682 100644 --- a/system/autoload/Message.php +++ b/system/autoload/Message.php @@ -39,20 +39,21 @@ class Message } } - public static function sendExpiredNotification($phone, $name, $package, $textExpired, $via) + public static function sendPackageNotification($phone, $name, $package, $message, $via) { + $msg = str_replace('[[name]]', "*$name*", $message); + $msg = str_replace('[[package]]', "*$package*", $msg); if ( !empty($phone) && strlen($phone) > 5 - && !empty($textExpired) && in_array($via, ['sms', 'wa']) + && !empty($message) && in_array($via, ['sms', 'wa']) ) { - $msg = str_replace('[[name]]', "*$name*", $textExpired); - $msg = str_replace('[[package]]', "*$package*", $msg); if ($via == 'sms') { Message::sendSMS($phone, $msg); } else if ($via == 'wa') { Message::sendWhatsapp($phone, $msg); } } + return "$via: $msg"; } } diff --git a/system/autoload/Mikrotik.php b/system/autoload/Mikrotik.php index 0b98ecd4..17b344e0 100644 --- a/system/autoload/Mikrotik.php +++ b/system/autoload/Mikrotik.php @@ -204,24 +204,29 @@ class Mikrotik '/ppp secret print .proplist=name', RouterOS\Query::where('name', $username) ); - $userName = $client->sendSync($printRequest)->getProperty('name'); + $id = $client->sendSync($printRequest)->getProperty('.id'); $removeRequest = new RouterOS\Request('/ppp/secret/remove'); $client( $removeRequest - ->setArgument('numbers', $userName) + ->setArgument('numbers', $id) ); } public static function addPpoeUser($client, $plan, $customer) { $addRequest = new RouterOS\Request('/ppp/secret/add'); + if(!empty($customer['pppoe_password'])){ + $pass = $customer['pppoe_password']; + }else{ + $pass = $customer['password']; + } $client->sendSync( $addRequest ->setArgument('name', $customer['username']) ->setArgument('service', 'pppoe') ->setArgument('profile', $plan['name_plan']) - ->setArgument('password', $customer['password']) + ->setArgument('password', $pass) ); } diff --git a/system/autoload/Package.php b/system/autoload/Package.php index 384140dd..26e1a5cc 100644 --- a/system/autoload/Package.php +++ b/system/autoload/Package.php @@ -19,7 +19,7 @@ class Package */ public static function rechargeUser($id_customer, $router_name, $plan_id, $gateway, $channel) { - global $_c, $_L; + global $_c, $_L, $_notifmsg; $date_now = date("Y-m-d H:i:s"); $date_only = date("Y-m-d"); $time = date("H:i:s"); @@ -30,6 +30,49 @@ class Package $c = ORM::for_table('tbl_customers')->where('id', $id_customer)->find_one(); $p = ORM::for_table('tbl_plans')->where('id', $plan_id)->where('enabled', '1')->find_one(); + + if ($router_name == 'balance') { + // insert table transactions + $inv = "INV-" . _raid(5); + $t = ORM::for_table('tbl_transactions')->create(); + $t->invoice = $inv; + $t->username = $c['username']; + $t->plan_name = $p['name_plan']; + $t->price = $p['price']; + $t->recharged_on = $date_only; + $t->expiration = $date_only; + $t->time = $time; + $t->method = "$gateway - $channel"; + $t->routers = $router_name; + $t->type = "Balance"; + $t->save(); + + Balance::plus($id_customer, $p['price']); + + $textInvoice = $_notifmsg['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('[[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('[[user_name]]', $c['username'], $textInvoice); + $textInvoice = str_replace('[[user_password]]', $c['password'], $textInvoice); + + if ($_c['user_notification_payment'] == 'sms') { + Message::sendSMS($c['phonenumber'], $textInvoice); + } else if ($_c['user_notification_payment'] == 'wa') { + Message::sendWhatsapp($c['phonenumber'], $textInvoice); + } + + return true; + } + + $b = ORM::for_table('tbl_user_recharges')->where('customer_id', $id_customer)->find_one(); $mikrotik = Mikrotik::info($router_name); @@ -198,28 +241,25 @@ class Package $in = ORM::for_table('tbl_transactions')->where('username', $c['username'])->order_by_desc('id')->find_one(); - $msg = "*$_c[CompanyName]*\n" . - "$_c[address]\n" . - "$_c[phone]\n" . - "\n\n" . - "INVOICE: *$in[invoice]*\n" . - "$_L[Date] : $date_now\n" . - "$gateway $channel\n" . - "\n\n" . - "$_L[Type] : *$in[type]*\n" . - "$_L[Plan_Name] : *$in[plan_name]*\n" . - "$_L[Plan_Price] : *$_c[currency_code] " . number_format($in['price'], 2, $_c['dec_point'], $_c['thousands_sep']) . "*\n\n" . - "$_L[Username] : *$in[username]*\n" . - "$_L[Password] : **********\n\n" . - "$_L[Created_On] :\n*" . date($_c['date_format'], strtotime($in['recharged_on'])) . "*\n" . - "$_L[Expires_On] :\n*" . date($_c['date_format'], strtotime($in['expiration'])) . " $in[time]*\n" . - "\n\n" . - "$_c[note]"; + $textInvoice = $_notifmsg['invoice_paid']; + $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]]', $in['invoice'], $textInvoice); + $textInvoice = str_replace('[[date]]', date($_c['date_format'], strtotime($date_now)) . " " . $time, $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('[[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); if ($_c['user_notification_payment'] == 'sms') { - Message::sendSMS($c['phonenumber'], $msg); + Message::sendSMS($c['phonenumber'], $textInvoice); } else if ($_c['user_notification_payment'] == 'wa') { - Message::sendWhatsapp($c['phonenumber'], $msg); + Message::sendWhatsapp($c['phonenumber'], $textInvoice); } return true; } diff --git a/system/boot.php b/system/boot.php index c2e0c637..9e458289 100644 --- a/system/boot.php +++ b/system/boot.php @@ -128,6 +128,12 @@ 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); +}else{ + $_notifmsg = json_decode(file_get_contents('system/uploads/notifications.default.json'), true); +} //register all plugin foreach (glob("system/plugin/*.php") as $filename) { diff --git a/system/controllers/accounts.php b/system/controllers/accounts.php index b586fdb2..559d7bd2 100644 --- a/system/controllers/accounts.php +++ b/system/controllers/accounts.php @@ -59,7 +59,11 @@ switch ($action) { } else { if (!$config['radius_mode']) { $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - Mikrotik::setPpoeUser($client, $c['username'], $npass); + if(!empty($d['pppoe_password'])){ + Mikrotik::setPpoeUser($client, $c['username'], $d['pppoe_password']); + }else{ + Mikrotik::setPpoeUser($client, $c['username'], $npass); + } Mikrotik::removePpoeActive($client, $user['username']); } $d->password = $npass; diff --git a/system/controllers/customers.php b/system/controllers/customers.php index 3aabc72b..cd12ed48 100644 --- a/system/controllers/customers.php +++ b/system/controllers/customers.php @@ -116,7 +116,8 @@ switch ($action) { $username = _post('username'); $fullname = _post('fullname'); $password = _post('password'); - $cpassword = _post('cpassword'); + $pppoe_password = _post('pppoe_password'); + $email = _post('email'); $address = _post('address'); $phonenumber = _post('phonenumber'); run_hook('add_customer'); #HOOK @@ -130,9 +131,6 @@ switch ($action) { if (!Validator::Length($password, 35, 2)) { $msg .= 'Password should be between 3 to 35 characters' . '
'; } - if ($password != $cpassword) { - $msg .= 'Passwords does not match' . '
'; - } $d = ORM::for_table('tbl_customers')->where('username', $username)->find_one(); if ($d) { @@ -141,11 +139,13 @@ switch ($action) { if ($msg == '') { $d = ORM::for_table('tbl_customers')->create(); - $d->username = $username; + $d->username = Lang::phoneFormat($username); $d->password = $password; + $d->pppoe_password = $pppoe_password; + $d->email = $email; $d->fullname = $fullname; $d->address = $address; - $d->phonenumber = $username; + $d->phonenumber = Lang::phoneFormat($phonenumber); $d->save(); r2(U . 'customers/list', 's', $_L['account_created_successfully']); } else { @@ -154,27 +154,25 @@ switch ($action) { break; case 'edit-post': - $username = _post('username'); + $username = Lang::phoneFormat(_post('username')); $fullname = _post('fullname'); $password = _post('password'); - $cpassword = _post('cpassword'); + $pppoe_password = _post('pppoe_password'); + $email = _post('email'); $address = _post('address'); - $phonenumber = _post('phonenumber'); + $phonenumber = Lang::phoneFormat(_post('phonenumber')); run_hook('edit_customer'); #HOOK $msg = ''; if (Validator::Length($username, 16, 2) == false) { $msg .= 'Username should be between 3 to 15 characters' . '
'; } - if (Validator::Length($fullname, 26, 2) == false) { - $msg .= 'Full Name should be between 3 to 25 characters' . '
'; + if (Validator::Length($fullname, 26, 1) == false) { + $msg .= 'Full Name should be between 2 to 25 characters' . '
'; } if ($password != '') { if (!Validator::Length($password, 15, 2)) { $msg .= 'Password should be between 3 to 15 characters' . '
'; } - if ($password != $cpassword) { - $msg .= 'Passwords does not match' . '
'; - } } $id = _post('id'); @@ -206,7 +204,11 @@ switch ($action) { } else { if(!$config['radius_mode']){ $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - Mikrotik::setPpoeUser($client,$c['username'],$password); + if(!empty($d['pppoe_password'])){ + Mikrotik::setPpoeUser($client, $c['username'], $d['pppoe_password']); + }else{ + Mikrotik::setPpoeUser($client, $c['username'], $password); + } Mikrotik::removePpoeActive($client,$user['username']); } @@ -217,7 +219,9 @@ switch ($action) { if ($password != '') { $d->password = $password; } + $d->pppoe_password = $pppoe_password; $d->fullname = $fullname; + $d->email = $email; $d->address = $address; $d->phonenumber = $phonenumber; $d->save(); @@ -227,6 +231,8 @@ switch ($action) { $d->password = $password; } $d->fullname = $fullname; + $d->pppoe_password = $pppoe_password; + $d->email = $email; $d->address = $address; $d->phonenumber = $phonenumber; $d->save(); diff --git a/system/controllers/export.php b/system/controllers/export.php index 0cd60ac7..0d2ba727 100644 --- a/system/controllers/export.php +++ b/system/controllers/export.php @@ -61,6 +61,12 @@ switch ($action) { $title = ' Reports [' . $mdate . ']'; $title = str_replace('-', ' ', $title); + if(file_exists('system/uploads/logo.png')){ + $logo = 'system/uploads/logo.png'; + }else{ + $logo = 'system/uploads/logo.default.png'; + } + if ($x) { $html = '
@@ -69,7 +75,7 @@ switch ($action) { ' . $config['address'] . '
' . $_L['Phone_Number'] . ': ' . $config['phone'] . '
- + @@ -178,7 +184,6 @@ EOF; if ($stype != '') { $d->where('type', $stype); } - $d->where_gte('recharged_on', $fdate); $d->where_lte('recharged_on', $tdate); $d->order_by_desc('id'); @@ -207,7 +212,6 @@ EOF; $fdate = _post('fdate'); $tdate = _post('tdate'); $stype = _post('stype'); - $d = ORM::for_table('tbl_transactions'); if ($stype != '') { $d->where('type', $stype); @@ -229,6 +233,11 @@ EOF; $title = ' Reports [' . $mdate . ']'; $title = str_replace('-', ' ', $title); + if(file_exists('system/uploads/logo.png')){ + $logo = 'system/uploads/logo.png'; + }else{ + $logo = 'system/uploads/logo.default.png'; + } if ($x) { $html = ' @@ -238,7 +247,7 @@ EOF; ' . $config['address'] . '
' . $_L['Phone_Number'] . ': ' . $config['phone'] . '
- +
@@ -281,11 +290,7 @@ EOF;

' . $config['currency_code'] . ' ' . number_format($xy, 2, $config['dec_point'], $config['thousands_sep']) . '

'; run_hook('pdf_by_period'); #HOOK - define('_MPDF_PATH', 'system/vendors/mpdf/'); - - require('system/vendors/mpdf/mpdf.php'); - - $mpdf = new mPDF('c', 'A4', '', '', 20, 15, 25, 25, 10, 10); + $mpdf = new \Mpdf\Mpdf(); $mpdf->SetProtection(array('print')); $mpdf->SetTitle($config['CompanyName'] . ' Reports'); $mpdf->SetAuthor($config['CompanyName']); diff --git a/system/controllers/home.php b/system/controllers/home.php index a4372225..6108d816 100644 --- a/system/controllers/home.php +++ b/system/controllers/home.php @@ -9,6 +9,11 @@ $ui->assign('_title', $_L['Dashboard']); $user = User::_info(); $ui->assign('_user', $user); +if(isset($_GET['renewal'])){ + $user->auto_renewal = $_GET['renewal']; + $user->save(); +} + //Client Page $bill = User::_billing(); diff --git a/system/controllers/order.php b/system/controllers/order.php index 016c2c4c..d1098e27 100644 --- a/system/controllers/order.php +++ b/system/controllers/order.php @@ -35,9 +35,13 @@ switch ($action) { $ui->assign('_title', 'Order Plan'); $ui->assign('_system_menu', 'package'); $routers = ORM::for_table('tbl_routers')->find_many(); - $plans = ORM::for_table('tbl_plans')->where('enabled', '1')->find_many(); + $plans_pppoe = ORM::for_table('tbl_plans')->where('enabled', '1')->where('type', 'PPPOE')->find_many(); + $plans_hotspot = ORM::for_table('tbl_plans')->where('enabled', '1')->where('type', 'Hotspot')->find_many(); + $plans_balance = ORM::for_table('tbl_plans')->where('enabled', '1')->where('type', 'Balance')->find_many(); $ui->assign('routers', $routers); - $ui->assign('plans', $plans); + $ui->assign('plans_pppoe', $plans_pppoe); + $ui->assign('plans_hotspot', $plans_hotspot); + $ui->assign('plans_balance', $plans_balance); run_hook('customer_view_order_plan'); #HOOK $ui->display('user-orderPlan.tpl'); break; @@ -118,12 +122,16 @@ switch ($action) { run_hook('customer_buy_plan'); #HOOK include 'system/paymentgateway/' . $config['payment_gateway'] . '.php'; call_user_func($config['payment_gateway'] . '_validate_config'); - - $router = ORM::for_table('tbl_routers')->where('enabled', '1')->find_one($routes['2'] * 1); - $plan = ORM::for_table('tbl_plans')->where('enabled', '1')->find_one($routes['3'] * 1); - if (empty($router) || empty($plan)) { - r2(U . $back, 'e', Lang::T("Plan Not found")); + if ($routes['2'] != '0') { + $router = ORM::for_table('tbl_routers')->where('enabled', '1')->find_one($routes['2']); + if (empty($router) || empty($plan)) { + r2(U . $back, 'e', Lang::T("Plan Not found")); + } + }else{ + $router['id'] = 0; + $router['name'] = 'balance'; } + $plan = ORM::for_table('tbl_plans')->where('enabled', '1')->find_one($routes['3']); $d = ORM::for_table('tbl_payment_gateway') ->where('username', $user['username']) ->where('status', 1) @@ -172,5 +180,5 @@ switch ($action) { } break; default: - $ui->display('404.tpl'); + r2(U . "order/package/", 's',''); } diff --git a/system/controllers/register.php b/system/controllers/register.php index 5f41f97f..8ebd8226 100644 --- a/system/controllers/register.php +++ b/system/controllers/register.php @@ -26,7 +26,8 @@ switch ($do) { $cpassword = _post('cpassword'); $address = _post('address'); if(!empty($config['sms_url'])){ - $phonenumber = $username; + $phonenumber = Lang::phoneFormat($username); + $username = $phonenumber; }else if(strlen($username)<21){ $phonenumber = $username; } diff --git a/system/controllers/services.php b/system/controllers/services.php index 7621a535..d36277d7 100644 --- a/system/controllers/services.php +++ b/system/controllers/services.php @@ -70,10 +70,10 @@ switch ($action) { $d = ORM::for_table('tbl_plans')->find_one($id); if ($d) { run_hook('delete_plan'); #HOOK - if(!$config['radius_mode']){ + if (!$config['radius_mode']) { $mikrotik = Mikrotik::info($d['routers']); $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - Mikrotik::removeHotspotPlan($client,$d['name_plan']); + Mikrotik::removeHotspotPlan($client, $d['name_plan']); } $d->delete(); @@ -96,7 +96,7 @@ switch ($action) { $validity = _post('validity'); $validity_unit = _post('validity_unit'); $routers = _post('routers'); - $enabled = _post('enabled')*1; + $enabled = _post('enabled'); $msg = ''; if (Validator::UnsignedNumber($validity) == false) { @@ -130,7 +130,7 @@ switch ($action) { } $rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown; - if(!$config['radius_mode']){ + if (!$config['radius_mode']) { $mikrotik = Mikrotik::info($routers); $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); Mikrotik::addHotspotPlan($client, $name, $sharedusers, $rate); @@ -176,7 +176,7 @@ switch ($action) { $validity = _post('validity'); $validity_unit = _post('validity_unit'); $routers = _post('routers'); - $enabled = _post('enabled')*1; + $enabled = _post('enabled'); $msg = ''; if (Validator::UnsignedNumber($validity) == false) { @@ -209,7 +209,7 @@ switch ($action) { } $rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown; - if(!$config['radius_mode']){ + if (!$config['radius_mode']) { $mikrotik = Mikrotik::info($routers); $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); Mikrotik::setHotspotPlan($client, $name, $sharedusers, $rate); @@ -293,7 +293,7 @@ switch ($action) { $d = ORM::for_table('tbl_plans')->find_one($id); if ($d) { run_hook('delete_ppoe'); #HOOK - if(!$config['radius_mode']){ + if (!$config['radius_mode']) { $mikrotik = Mikrotik::info($d['routers']); $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); Mikrotik::removePpoePlan($client, $d['name_plan']); @@ -312,7 +312,7 @@ switch ($action) { $validity_unit = _post('validity_unit'); $routers = _post('routers'); $pool = _post('pool_name'); - $enabled = _post('enabled')*1; + $enabled = _post('enabled'); $msg = ''; if (Validator::UnsignedNumber($validity) == false) { @@ -344,7 +344,7 @@ switch ($action) { } $rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown; - if(!$config['radius_mode']){ + if (!$config['radius_mode']) { $mikrotik = Mikrotik::info($routers); $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); Mikrotik::addPpoePlan($client, $name, $pool, $rate); @@ -377,7 +377,7 @@ switch ($action) { $validity_unit = _post('validity_unit'); $routers = _post('routers'); $pool = _post('pool_name'); - $enabled = _post('enabled')*1; + $enabled = _post('enabled'); $msg = ''; if (Validator::UnsignedNumber($validity) == false) { @@ -410,7 +410,7 @@ switch ($action) { } $rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown; - if(!$config['radius_mode']){ + if (!$config['radius_mode']) { $mikrotik = Mikrotik::info($routers); $client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); Mikrotik::setPpoePlan($client, $name, $pool, $rate); @@ -431,7 +431,112 @@ switch ($action) { r2(U . 'services/pppoe-edit/' . $id, 'e', $msg); } break; + case 'balance': + $ui->assign('_title', Lang::T('Balance Plans')); + $name = _post('name'); + if ($name != '') { + $paginator = Paginator::bootstrap('tbl_plans', 'name_plan', '%' . $name . '%', 'type', 'Balance'); + $d = ORM::for_table('tbl_plans')->where('tbl_plans.type', 'Balance')->where_like('tbl_plans.name_plan', '%' . $name . '%')->offset($paginator['startpoint'])->limit($paginator['limit'])->find_many(); + } else { + $paginator = Paginator::bootstrap('tbl_plans', 'type', 'Hotspot'); + $d = ORM::for_table('tbl_plans')->where('tbl_plans.type', 'Balance')->offset($paginator['startpoint'])->limit($paginator['limit'])->find_many(); + } + $ui->assign('d', $d); + $ui->assign('paginator', $paginator); + run_hook('view_list_balance'); #HOOK + $ui->display('balance.tpl'); + break; + case 'balance-add': + $ui->assign('_title', Lang::T('Balance Plans')); + run_hook('view_add_balance'); #HOOK + $ui->display('balance-add.tpl'); + break; + case 'balance-edit': + $ui->assign('_title', Lang::T('Balance Plans')); + $id = $routes['2']; + $d = ORM::for_table('tbl_plans')->find_one($id); + $ui->assign('d', $d); + run_hook('view_edit_balance'); #HOOK + $ui->display('balance-edit.tpl'); + break; + case 'balance-delete': + $id = $routes['2']; + + $d = ORM::for_table('tbl_plans')->find_one($id); + if ($d) { + run_hook('delete_balance'); #HOOK + $d->delete(); + r2(U . 'services/balance', 's', $_L['Delete_Successfully']); + } + break; + case 'balance-edit-post': + $id = _post('id'); + $name = _post('name'); + $price = _post('price'); + $enabled = _post('enabled'); + + $msg = ''; + if (Validator::UnsignedNumber($price) == false) { + $msg .= 'The price must be a number' . '
'; + } + if ($name == '') { + $msg .= $_L['All_field_is_required'] . '
'; + } + + $d = ORM::for_table('tbl_plans')->where('id', $id)->find_one(); + if ($d) { + } else { + $msg .= $_L['Data_Not_Found'] . '
'; + } + run_hook('edit_ppoe'); #HOOK + if ($msg == '') { + $d->name_plan = $name; + $d->price = $price; + $d->enabled = $enabled; + $d->save(); + + r2(U . 'services/balance', 's', $_L['Updated_Successfully']); + } else { + r2(U . 'services/balance-edit/' . $id, 'e', $msg); + } + break; + case 'balance-add-post': + $name = _post('name'); + $price = _post('price'); + $enabled = _post('enabled'); + + $msg = ''; + if (Validator::UnsignedNumber($price) == false) { + $msg .= 'The price must be a number' . '
'; + } + if ($name == '') { + $msg .= $_L['All_field_is_required'] . '
'; + } + + $d = ORM::for_table('tbl_plans')->where('name_plan', $name)->find_one(); + if ($d) { + $msg .= $_L['Plan_already_exist'] . '
'; + } + run_hook('add_ppoe'); #HOOK + if ($msg == '') { + $d = ORM::for_table('tbl_plans')->create(); + $d->type = 'Balance'; + $d->name_plan = $name; + $d->id_bw = 0; + $d->price = $price; + $d->validity = 0; + $d->validity_unit = 'Months'; + $d->routers = ''; + $d->pool = ''; + $d->enabled = $enabled; + $d->save(); + + r2(U . 'services/balance', 's', $_L['Created_Successfully']); + } else { + r2(U . 'services/balance-add', 'e', $msg); + } + break; default: echo 'action not defined'; } diff --git a/system/controllers/settings.php b/system/controllers/settings.php index 6a5625c6..0de22c16 100644 --- a/system/controllers/settings.php +++ b/system/controllers/settings.php @@ -206,13 +206,15 @@ switch ($action) { case 'app-post': $company = _post('company'); $footer = _post('footer'); + $enable_balance = _post('enable_balance'); + $allow_balance_transfer = _post('allow_balance_transfer'); $disable_voucher = _post('disable_voucher'); $telegram_bot = _post('telegram_bot'); $telegram_target_id = _post('telegram_target_id'); $sms_url = _post('sms_url'); $wa_url = _post('wa_url'); $user_notification_expired = _post('user_notification_expired'); - $user_notification_expired_text = _post('user_notification_expired_text'); + $user_notification_reminder = _post('user_notification_reminder'); $user_notification_payment = _post('user_notification_payment'); $address = _post('address'); $tawkto = _post('tawkto'); @@ -257,6 +259,28 @@ switch ($action) { $d->save(); } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'enable_balance')->find_one(); + if($d){ + $d->value = $enable_balance; + $d->save(); + }else{ + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'enable_balance'; + $d->value = $enable_balance; + $d->save(); + } + + $d = ORM::for_table('tbl_appconfig')->where('setting', 'allow_balance_transfer')->find_one(); + if($d){ + $d->value = $allow_balance_transfer; + $d->save(); + }else{ + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'allow_balance_transfer'; + $d->value = $allow_balance_transfer; + $d->save(); + } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'telegram_bot')->find_one(); if($d){ $d->value = $telegram_bot; @@ -312,14 +336,14 @@ switch ($action) { $d->save(); } - $d = ORM::for_table('tbl_appconfig')->where('setting', 'user_notification_expired_text')->find_one(); + $d = ORM::for_table('tbl_appconfig')->where('setting', 'user_notification_reminder')->find_one(); if($d){ - $d->value = $user_notification_expired_text; + $d->value = $user_notification_reminder; $d->save(); }else{ $d = ORM::for_table('tbl_appconfig')->create(); - $d->setting = 'user_notification_expired_text'; - $d->value = $user_notification_expired_text; + $d->setting = 'user_notification_reminder'; + $d->value = $user_notification_reminder; $d->save(); } @@ -370,6 +394,7 @@ switch ($action) { case 'localisation-post': $tzone = _post('tzone'); $date_format = _post('date_format'); + $country_code_phone = _post('country_code_phone'); $lan = _post('lan'); run_hook('save_localisation'); #HOOK if ($tzone == '' or $date_format == '' or $lan == '') { @@ -397,6 +422,18 @@ switch ($action) { $d->save(); } + + $d = ORM::for_table('tbl_appconfig')->where('setting', 'country_code_phone')->find_one(); + if($d){ + $d->value = $country_code_phone; + $d->save(); + }else{ + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'country_code_phone'; + $d->value = $country_code_phone; + $d->save(); + } + $currency_code = $_POST['currency_code']; $d = ORM::for_table('tbl_appconfig')->where('setting', 'currency_code')->find_one(); $d->value = $currency_code; @@ -455,7 +492,22 @@ switch ($action) { } break; - + case 'notifications': + if ($admin['user_type'] != 'Admin' and $admin['user_type'] != 'Sales') { + r2(U . "dashboard", 'e', $_L['Do_Not_Access']); + } + run_hook('view_notifications'); #HOOK + if(file_exists("system/uploads/notifications.json")){ + $ui->assign('_json', json_decode(file_get_contents('system/uploads/notifications.json'), true)); + }else{ + $ui->assign('_json', json_decode(file_get_contents('system/uploads/notifications.default.json'), true)); + } + $ui->display('app-notifications.tpl'); + break; + case 'notifications-post': + file_put_contents("system/uploads/notifications.json", json_encode($_POST)); + r2(U . 'settings/notifications', 's', $_L['Settings_Saved_Successfully']); + break; case 'dbstatus': if ($admin['user_type'] != 'Admin') { r2(U . "dashboard", 'e', $_L['Do_Not_Access']); diff --git a/system/cron.php b/system/cron.php index 13a4837f..e7774867 100644 --- a/system/cron.php +++ b/system/cron.php @@ -18,9 +18,15 @@ ORM::configure('logging', true); include "autoload/Hookers.php"; +// notification message +if (file_exists("uploads/notifications.json")) { + $_notifmsg = json_decode(file_get_contents('uploads/notifications.json'), true); +} else { + $_notifmsg = json_decode(file_get_contents('uploads/notifications.default.json'), true); +} //register all plugin -foreach (glob("system/plugin/*.php") as $filename) { +foreach (glob("plugin/*.php") as $filename) { include $filename; } @@ -55,7 +61,7 @@ foreach ($result as $value) { } date_default_timezone_set($config['timezone']); -$textExpired = $config['user_notification_expired_text']; +$textExpired = $_notifmsg['expired']; $d = ORM::for_table('tbl_user_recharges')->where('status', 'on')->find_many(); @@ -76,11 +82,26 @@ foreach ($d as $ds) { $client = Mikrotik::getClient($m['ip_address'], $m['username'], $m['password']); Mikrotik::setHotspotLimitUptime($client, $c['username']); Mikrotik::removeHotspotActiveUser($client, $c['username']); - Message::sendExpiredNotification($c['phonenumber'], $c['fullname'], $u['namebp'], $textExpired, $config['user_notification_expired']); + Message::sendPackageNotification($c['phonenumber'], $c['fullname'], $u['namebp'], $textExpired, $config['user_notification_expired']); } //update database user dengan status off $u->status = 'off'; $u->save(); + + // 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']); + } else { + Message::sendTelegram("FAILED RENEWAL #cron\n\n#u$c[username] #buy #Hotspot \n" . $p['name_plan'] . + "\nRouter: " . $router_name . + "\nPrice: " . $p['price']); + } + } + } } else echo " : ACTIVE \r\n"; } else { $date_now = strtotime(date("Y-m-d H:i:s")); @@ -96,11 +117,26 @@ foreach ($d as $ds) { $client = Mikrotik::getClient($m['ip_address'], $m['username'], $m['password']); Mikrotik::disablePpoeUser($client, $c['username']); Mikrotik::removePpoeActive($client, $c['username']); - Message::sendExpiredNotification($c['phonenumber'], $c['fullname'], $u['namebp'], $textExpired, $config['user_notification_expired']); + Message::sendPackageNotification($c['phonenumber'], $c['fullname'], $u['namebp'], $textExpired, $config['user_notification_expired']); } $u->status = 'off'; $u->save(); + + // 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']); + } else { + Message::sendTelegram("FAILED RENEWAL #cron\n\n#u$c[username] #buy #Hotspot \n" . $p['name_plan'] . + "\nRouter: " . $router_name . + "\nPrice: " . $p['price']); + } + } + } } else echo " : ACTIVE \r\n"; } } diff --git a/system/cron_reminder.php b/system/cron_reminder.php new file mode 100644 index 00000000..8fd04c12 --- /dev/null +++ b/system/cron_reminder.php @@ -0,0 +1,90 @@ +find_many(); +foreach ($result as $value) { + $config[$value['setting']] = $value['value']; +} +date_default_timezone_set($config['timezone']); + + +$d = ORM::for_table('tbl_user_recharges')->where('status', 'on')->find_many(); + +run_hook('cronjob_reminder'); #HOOK + + + +$day7 = date('Y-m-d', strtotime("+7 day")); +$day3 = date('Y-m-d', strtotime("+3 day")); +$day1 = date('Y-m-d', strtotime("+1 day")); +print_r([$day1,$day3,$day7]); +foreach ($d as $ds) { + if(in_array($ds['expiration'],[$day1,$day3,$day7])){ + $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(); + if($ds['expiration']==$day7){ + echo Message::sendPackageNotification($c['phonenumber'], $c['fullname'], $u['namebp'], $_notifmsg['reminder_7_day'], $config['user_notification_reminder'])."\n"; + }else if($ds['expiration']==$day3){ + echo Message::sendPackageNotification($c['phonenumber'], $c['fullname'], $u['namebp'], $_notifmsg['reminder_3_day'], $config['user_notification_reminder'])."\n"; + }else if($ds['expiration']==$day1){ + echo Message::sendPackageNotification($c['phonenumber'], $c['fullname'], $u['namebp'], $_notifmsg['reminder_1_day'], $config['user_notification_reminder'])."\n"; + } + } +} diff --git a/system/lan/english/common.lan.php b/system/lan/english/common.lan.php index a72756a0..0516eea8 100644 --- a/system/lan/english/common.lan.php +++ b/system/lan/english/common.lan.php @@ -332,3 +332,34 @@ $_L['Your_account_not_connected_to_internet'] = 'Your account not connected to i $_L['Failed_to_create_transaction_'] = 'Failed to create transaction. '; $_L['Failed_to_check_status_transaction_'] = 'Failed to check status transaction. '; $_L['Disable_Voucher'] = 'Disable Voucher'; +$_L['Balance'] = 'Balance'; +$_L['Balance_System'] = 'Balance System'; +$_L['Enable_System'] = 'Enable System'; +$_L['Allow_Transfer'] = 'Allow Transfer'; +$_L['Telegram_Notification'] = 'Telegram Notification'; +$_L['SMS_OTP_Registration'] = 'SMS OTP Registration'; +$_L['Whatsapp_Notification'] = 'Whatsapp Notification'; +$_L['Tawkto_Chat_Widget'] = 'Tawk.to Chat Widget'; +$_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'; +$_L['Reminder_Notification'] = 'Reminder Notification'; +$_L['Reminder_Notification_Message'] = 'Reminder Notification Message'; +$_L['Reminder_7_days'] = 'Reminder 7 days'; +$_L['Reminder_3_days'] = 'Reminder 3 days'; +$_L['Reminder_1_day'] = 'Reminder 1 day'; +$_L['PPPOE_Password'] = 'PPPOE Password'; +$_L['User_Cannot_change_this_only_admin_if_it_Empty_it_will_use_user_password'] = 'User Cannot change this, only admin. if it Empty it will use user password'; +$_L['Invoice_Balance_Message'] = 'Invoice Balance Message'; +$_L['Invoice_Notification_Payment'] = 'Invoice Notification Payment'; +$_L['Balance_Notification_Payment'] = 'Balance Notification Payment'; +$_L['Balance_Plans'] = 'Balance Plans'; +$_L['Buy_Balance'] = 'Buy Balance?'; +$_L['Price'] = 'Price'; +$_L['Validity'] = 'Validity'; +$_L['Disable_auto_renewal'] = 'Disable auto renewal?'; +$_L['Auto_Renewal_On'] = 'Auto Renewal On'; +$_L['Enable_auto_renewal'] = 'Enable auto renewal?'; +$_L['Auto_Renewal_Off'] = 'Auto Renewal Off'; diff --git a/system/lan/indonesia/common.lan.php b/system/lan/indonesia/common.lan.php index aeaafba2..8a197d45 100644 --- a/system/lan/indonesia/common.lan.php +++ b/system/lan/indonesia/common.lan.php @@ -325,3 +325,16 @@ $_L['Not_Online_Login_now'] = 'Internet mati, Nyalakan?'; $_L['You_are_Online_Logout'] = 'Internet hidup, Putuskan?'; $_L['Connect_to_Internet'] = 'Koneksikan internet?'; $_L['Your_account_not_connected_to_internet'] = 'Akun tidak terkoneksi dengan internet'; +$_L['Balance'] = 'Saldo'; +$_L['Balance_System'] = 'Sistem Saldo'; +$_L['Enable_System'] = 'Aktifkan Saldo'; +$_L['Allow_Transfer'] = 'Bolehkan Transfer'; +$_L['Telegram_Notification'] = 'Telegram Notification'; +$_L['SMS_OTP_Registration'] = 'SMS OTP Registration'; +$_L['Whatsapp_Notification'] = 'Whatsapp Notification'; +$_L['Tawkto_Chat_Widget'] = 'Tawk.to Chat Widget'; +$_L['Invoice'] = 'Invoice'; +$_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'; diff --git a/system/lan/spanish/common.lan.php b/system/lan/spanish/common.lan.php index 661fb5dc..ec13dfd0 100644 --- a/system/lan/spanish/common.lan.php +++ b/system/lan/spanish/common.lan.php @@ -328,6 +328,16 @@ $_L['Not_Online_Login_now'] = 'Not Online, Login now?'; $_L['You_are_Online_Logout'] = 'You are Online, Logout?'; $_L['Connect_to_Internet'] = 'Connect to Internet?'; $_L['Your_account_not_connected_to_internet'] = 'Your account not connected to internet'; - - - +$_L['Balance'] = 'Balance'; +$_L['Balance_System'] = 'Balance System'; +$_L['Enable_System'] = 'Enable System'; +$_L['Allow_Transfer'] = 'Allow Transfer'; +$_L['Telegram_Notification'] = 'Telegram Notification'; +$_L['SMS_OTP_Registration'] = 'SMS OTP Registration'; +$_L['Whatsapp_Notification'] = 'Whatsapp Notification'; +$_L['Tawkto_Chat_Widget'] = 'Tawk.to Chat Widget'; +$_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 diff --git a/system/lan/turkish/common.lan.php b/system/lan/turkish/common.lan.php index ef852b7c..c21d9b8b 100755 --- a/system/lan/turkish/common.lan.php +++ b/system/lan/turkish/common.lan.php @@ -304,3 +304,16 @@ $_L['Not_Online_Login_now'] = 'Not Online, Login now?'; $_L['You_are_Online_Logout'] = 'You are Online, Logout?'; $_L['Connect_to_Internet'] = 'Connect to Internet?'; $_L['Your_account_not_connected_to_internet'] = 'Your account not connected to internet'; +$_L['Balance'] = 'Balance'; +$_L['Balance_System'] = 'Balance System'; +$_L['Enable_System'] = 'Enable System'; +$_L['Allow_Transfer'] = 'Allow Transfer'; +$_L['Telegram_Notification'] = 'Telegram Notification'; +$_L['SMS_OTP_Registration'] = 'SMS OTP Registration'; +$_L['Whatsapp_Notification'] = 'Whatsapp Notification'; +$_L['Tawkto_Chat_Widget'] = 'Tawk.to Chat Widget'; +$_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 diff --git a/system/updates.json b/system/updates.json new file mode 100644 index 00000000..7dce27f7 --- /dev/null +++ b/system/updates.json @@ -0,0 +1,14 @@ +{ + "2023.8.9": [ + "ALTER TABLE `tbl_customers` ADD `balance` decimal(15,2) NOT NULL DEFAULT 0.00 COMMENT 'For Money Deposit' AFTER `email`;", + "CREATE TABLE `tbl_customers_meta` (`id` int(11) NOT NULL, `customer_id` int(11) NOT NULL,`meta_key` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', `meta_value` longtext COLLATE utf8mb4_general_ci) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;", + "ALTER TABLE `tbl_customers_meta` ADD PRIMARY KEY (`id`);", + "ALTER TABLE `tbl_customers_meta` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;" + ], + "2023.8.14": [ + "ALTER TABLE `tbl_customers` ADD `pppoe_password` varchar(45) NOT NULL DEFAULT '1' COMMENT 'For PPPOE Login' AFTER `password`;", + "ALTER TABLE `tbl_plans` CHANGE `type` `type` ENUM('Hotspot','PPPOE','Balance') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;", + "ALTER TABLE `tbl_transactions` CHANGE `type` `type` ENUM('Hotspot','PPPOE','Balance') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;", + "ALTER TABLE `tbl_customers` ADD `auto_renewal` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Auto renewall using balance' AFTER `balance`;" + ] +} \ No newline at end of file diff --git a/system/uploads/admin.png b/system/uploads/admin.default.png similarity index 100% rename from system/uploads/admin.png rename to system/uploads/admin.default.png diff --git a/system/uploads/logo.png b/system/uploads/logo.default.png similarity index 100% rename from system/uploads/logo.png rename to system/uploads/logo.default.png diff --git a/system/uploads/notifications.default.json b/system/uploads/notifications.default.json new file mode 100644 index 00000000..aff56897 --- /dev/null +++ b/system/uploads/notifications.default.json @@ -0,0 +1,8 @@ +{ + "expired": "Hello [[name]], your internet package [[package]] has been expired.", + "reminder_7_day": "Hello *[[name]]*, \r\nyour internet package *[[package]]* will be expired in 7 days.", + "reminder_3_day": "Hello *[[name]]*, \r\nyour internet package *[[package]]* will be expired in 3 days.", + "reminder_1_day": "Hello *[[name]]*,\r\n your internet package *[[package]]* will be expired tomorrow.", + "invoice_paid": "*[[company_name]]*\r\n[[address]]\r\n[[phone]]\r\n\r\n\r\nINVOICE: *[[invoice]]*\r\nDate : [[date]]\r\n[[payment_gateway]] [[payment_channel]]\r\n\r\n\r\nType : *[[type]]*\r\nPackage : *[[plan_name]]*\r\nPrice : *[[plan_price]]*\r\n\r\nUsername : *[[user_name]]*\r\nPassword : ***********\r\n\r\nExpired : *[[expired_date]]*\r\n\r\n\r\nThank you...", + "invoice_balance": "*[[company_name]]*\r\n[[address]]\r\n[[phone]]\r\n\r\n\r\nINVOICE: *[[invoice]]*\r\nDate : [[date]]\r\n[[payment_gateway]] [[payment_channel]]\r\n\r\n\r\nType : *[[type]]*\r\nPackage : *[[plan_name]]*\r\nPrice : *[[plan_price]]*\r\n\r\nThank you..." +} diff --git a/system/uploads/user.jpg b/system/uploads/user.default.jpg similarity index 100% rename from system/uploads/user.jpg rename to system/uploads/user.default.jpg diff --git a/ui/ui/app-localisation.tpl b/ui/ui/app-localisation.tpl index ebbc960a..a5ca2ba5 100644 --- a/ui/ui/app-localisation.tpl +++ b/ui/ui/app-localisation.tpl @@ -1,80 +1,107 @@ {include file="sections/header.tpl"} -
-
-
-
{$_L['Localisation']}
-
+
+
+
+
{$_L['Localisation']}
+
-
+
- -
- -
-
-
- -
- -
-
-
- -
- + {foreach $tlist as $value => $label} + {/foreach} - -
- + +
- -
- -
+ +
+ +
- -
- -
+ +
+ +
+
- -
- - {$_L['currency_help']} -
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + {$_L['currency_help']} +
+
+
+ +
+
+ + + +
+
+
+
+
+ +
-
-
- -
-
- -
-
-
-
-{include file="sections/footer.tpl"} +
+
+
+ + +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/app-notifications.tpl b/ui/ui/app-notifications.tpl new file mode 100644 index 00000000..ab5a40e1 --- /dev/null +++ b/ui/ui/app-notifications.tpl @@ -0,0 +1,125 @@ +{include file="sections/header.tpl"} + + +
+
+
+
+
+ +
+ {Lang::T('User Notification')} +
+
+
+ +
+ +
+

+ {Lang::T('[[name]] will be replaced with Customer Name. [[package]] will be replaced with Package name.')} +

+
+
+
+
+ +
+ +
+

+ {Lang::T('[[name]] will be replaced with Customer Name. [[package]] will be replaced with Package name.')} +

+
+
+
+
+ +
+ +
+

+ {Lang::T('[[name]] will be replaced with Customer Name. [[package]] will be replaced with Package name.')} +

+
+
+
+
+ +
+ +
+

+ {Lang::T('[[name]] will be replaced with Customer Name. [[package]] will be replaced with Package name.')} +

+
+
+
+
+ +
+ +
+

+ [[company_name]] Your Company Name at Settings.
+ [[address]] Your Company Address at Settings.
+ [[phone]] Your Company Phone at Settings.
+ [[invoice]] invoice number.
+ [[date]] Date invoice created.
+ [[payment_gateway]] Payment gateway user paid from.
+ [[payment_channel]] Payment channel user paid from.
+ [[type]] is Hotspot/PPPOE.
+ [[plan_name]] Internet Package.
+ [[plan_price]] Internet Package Prices.
+ [[user_name]] Username internet.
+ [[user_password]] User password.
+ [[expired_date]] Expired datetime. +

+
+
+
+
+ +
+ +
+

+ [[company_name]] Your Company Name at Settings.
+ [[address]] Your Company Address at Settings.
+ [[phone]] Your Company Phone at Settings.
+ [[invoice]] invoice number.
+ [[date]] Date invoice created.
+ [[payment_gateway]] Payment gateway user paid from.
+ [[payment_channel]] Payment channel user paid from.
+ [[type]] is Hotspot/PPPOE.
+ [[plan_name]] Internet Package.
+ [[plan_price]] Internet Package Prices.
+ [[user_name]] Username internet.
+ [[user_password]] User password.
+ [[trx_date]] Transaction datetime. +

+
+
+
+ +
+
+ +
+
+
+
+ +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/app-settings.tpl b/ui/ui/app-settings.tpl index f8ffb419..83ee92ae 100644 --- a/ui/ui/app-settings.tpl +++ b/ui/ui/app-settings.tpl @@ -4,31 +4,38 @@
-
{$_L['General_Settings']}
+
+
+ +
+ {$_L['General_Settings']} +
- {$_L['App_Name_Help_Text']} +
+ {$_L['App_Name_Help_Text']}
- {Lang::T('Will show below user pages')}
+ {Lang::T('Will show below user pages')}
- {$_L['You_can_use_html_tag']}
+ {$_L['You_can_use_html_tag']}
@@ -43,31 +50,71 @@ -

Still on Testing.

-

Changing from Radius will not add existing user to Mikrotik Hotspot. -

-

With Radius user can use Hotspot or PPOE.

+

Still on Testing.
+ Changing from Radius will not add existing user to Mikrotik Hotspot.
+ With Radius user can use Hotspot or PPOE.

-

edit at config.php

+

edit at config.php

-

Voucher activation menu will be hidden

+

{Lang::T('Voucher activation menu will be hidden')}

-
Telegram Notification
+
+
+ +
+ {Lang::T('Balance System')} +
+
+
+ +
+ +
+

{Lang::T('Customer can deposit money to buy voucher')}

+
+
+ +
+ +
+

{Lang::T('Allow balance transfer between customers')}

+
+
+
+
+ +
+ {Lang::T('Telegram Notification')} +
@@ -83,88 +130,122 @@ value="{$_c['telegram_target_id']}" placeholder="12345678">
- You will get Payment and Error notification + You will get Payment and Error + notification +
+
+
+ +
+ {Lang::T('SMS OTP Registration')}
-
SMS OTP Registration
-

Must include [text] & [number], it will be replaced. -

+

Must include [text] & [number], it will be + replaced. +

- You can use WhatsApp in here too. Free Server + You can use WhatsApp in here too. Free Server +
+
+
+ +
+ {Lang::T('Whatsapp Notification')}
-
Whatsapp Notification
-

Must include [text] & [number], it will be replaced. -

+

Must include [text] & [number], it will be + replaced. +

+ You can use WhatsApp in here too. Free Server +
+
+
+ +
+ {Lang::T('User Notification')}
-
{Lang::T('User Notification')}
- - - + + -

{Lang::T('User will get notification when package expired')}

-
-
-
- -
- -

{Lang::T('[[name]] will be replaced with Customer Name. [[package]] will be replaced with Package name.')}

+

{Lang::T('User will get notification when package expired')}

- - - + + + +
+

+ {Lang::T('User will get invoice notification when buy package or package refilled')}

+
+
+ +
+ -

{Lang::T('User will get invoice notification when buy package or package refilled')}

-
Tawk.to Chat Widget
+
+
+ +
+ {Lang::T('Tawk.to Chat Widget')} +
-

From Direct Chat Link.

-
/ip hotspot walled-garden
-add dst-host=tawk.to
-add dst-host=*.tawk.to
-
-
-
-
Invoice
-
-
- -
- - {$_L['You_can_use_html_tag']}
+

From Direct Chat Link.

+ +

/ip hotspot walled-garden
+ add dst-host=tawk.to
+ add dst-host=*.tawk.to

@@ -173,11 +254,11 @@ add dst-host=*.tawk.to - +
/ip hotspot walled-garden
-            add dst-host={$_domain}
-            add dst-host=*.{$_domain}
+add dst-host={$_domain} +add dst-host=*.{$_domain} diff --git a/ui/ui/balance-add.tpl b/ui/ui/balance-add.tpl new file mode 100644 index 00000000..8fa3c734 --- /dev/null +++ b/ui/ui/balance-add.tpl @@ -0,0 +1,48 @@ +{include file="sections/header.tpl"} + +
+
+
+
{$_L['Add_Plan']}
+
+
+
+ +
+ + +
+
+
+ +
+ +
+
+
+ +
+
+ {$_c['currency_code']} + +
+
+
+ +
+
+ + Or {$_L['Cancel']} +
+
+ +
+
+
+
+ +{include file="sections/footer.tpl"} diff --git a/ui/ui/balance-edit.tpl b/ui/ui/balance-edit.tpl new file mode 100644 index 00000000..16922bfb --- /dev/null +++ b/ui/ui/balance-edit.tpl @@ -0,0 +1,49 @@ +{include file="sections/header.tpl"} + +
+
+
+
{$_L['Edit_Plan']}
+
+
+ +
+ +
+ + +
+
+
+ +
+ +
+
+
+ +
+
+ {$_c['currency_code']} + +
+
+
+ +
+
+ + Or {$_L['Cancel']} +
+
+ +
+
+
+
+ +{include file="sections/footer.tpl"} diff --git a/ui/ui/balance.tpl b/ui/ui/balance.tpl new file mode 100644 index 00000000..17ace703 --- /dev/null +++ b/ui/ui/balance.tpl @@ -0,0 +1,56 @@ +{include file="sections/header.tpl"} + +
+
+
+
{Lang::T('Balance Plans')}
+
+
+
+ +
+
+ +
+ +
+ +
+
+ +
+   +
+
+
+ + + + + + + + + {foreach $d as $ds} + + + + + + {/foreach} + +
{$_L['Plan_Name']}{$_L['Plan_Price']}{$_L['Manage']}
{$ds['name_plan']}{Lang::moneyFormat($ds['price'])} + {$_L['Edit']} + {$_L['Delete']} +
+ + {$paginator['contents']} + + + + + + +{include file="sections/footer.tpl"} diff --git a/ui/ui/customers-add.tpl b/ui/ui/customers-add.tpl index 0d4ecb9d..c367095e 100644 --- a/ui/ui/customers-add.tpl +++ b/ui/ui/customers-add.tpl @@ -9,9 +9,13 @@
-
- -
+
+
+ + + +
+
@@ -20,17 +24,34 @@
- +
- +
+
+ +
+
+ + + +
+
+
- +
- +
+
+ +
+ + {Lang::T('User Cannot change this, only admin. if it Empty it will use user password')} +
+
diff --git a/ui/ui/customers-edit.tpl b/ui/ui/customers-edit.tpl index 8677665b..4886620e 100644 --- a/ui/ui/customers-edit.tpl +++ b/ui/ui/customers-edit.tpl @@ -11,7 +11,11 @@
- +
+ + + +
@@ -20,17 +24,34 @@
+
+ +
+ +
+
+
+ +
+
+ + + +
+
+
- + {$_L['password_change_help']}
- +
- + + {Lang::T('User Cannot change this, only admin. if it Empty it will use user password')}
@@ -39,12 +60,6 @@
-
- -
- -
-
diff --git a/ui/ui/hotspot-add.tpl b/ui/ui/hotspot-add.tpl index 4477bcfc..67a4a972 100644 --- a/ui/ui/hotspot-add.tpl +++ b/ui/ui/hotspot-add.tpl @@ -21,7 +21,6 @@
-

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

@@ -83,7 +82,10 @@
- +
+ {$_c['currency_code']} + +
diff --git a/ui/ui/hotspot-edit.tpl b/ui/ui/hotspot-edit.tpl index b6387279..3f3edc3d 100644 --- a/ui/ui/hotspot-edit.tpl +++ b/ui/ui/hotspot-edit.tpl @@ -21,7 +21,7 @@
- +
@@ -82,7 +82,10 @@
- +
+ {$_c['currency_code']} + +
diff --git a/ui/ui/hotspot.tpl b/ui/ui/hotspot.tpl index 371f0dcb..be5809d8 100644 --- a/ui/ui/hotspot.tpl +++ b/ui/ui/hotspot.tpl @@ -51,7 +51,7 @@ {$ds['routers']} {$_L['Edit']} - {$_L['Delete']} + {$_L['Delete']} {/foreach} diff --git a/ui/ui/pool.tpl b/ui/ui/pool.tpl index 6bf39add..d49a78f1 100644 --- a/ui/ui/pool.tpl +++ b/ui/ui/pool.tpl @@ -47,7 +47,7 @@ {$_L['Edit']} - {$_L['Delete']} diff --git a/ui/ui/pppoe-add.tpl b/ui/ui/pppoe-add.tpl index fbe86a6c..119f38f0 100644 --- a/ui/ui/pppoe-add.tpl +++ b/ui/ui/pppoe-add.tpl @@ -21,7 +21,6 @@
-

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

@@ -38,7 +37,10 @@
- +
+ {$_c['currency_code']} + +
diff --git a/ui/ui/pppoe-edit.tpl b/ui/ui/pppoe-edit.tpl index b710db45..d079f58a 100644 --- a/ui/ui/pppoe-edit.tpl +++ b/ui/ui/pppoe-edit.tpl @@ -21,7 +21,7 @@
- +
@@ -37,7 +37,10 @@
- +
+ {$_c['currency_code']} + +
diff --git a/ui/ui/pppoe.tpl b/ui/ui/pppoe.tpl index 090c9a76..36aa1fe4 100644 --- a/ui/ui/pppoe.tpl +++ b/ui/ui/pppoe.tpl @@ -47,7 +47,7 @@ {$ds['routers']} {$_L['Edit']} - {$_L['Delete']} + {$_L['Delete']} {/foreach} diff --git a/ui/ui/register-otp.tpl b/ui/ui/register-otp.tpl index bd48de86..cd571d4a 100644 --- a/ui/ui/register-otp.tpl +++ b/ui/ui/register-otp.tpl @@ -45,8 +45,11 @@
- +
+ + + +
diff --git a/ui/ui/register-rotp.tpl b/ui/ui/register-rotp.tpl index 87b80247..8cfe5b7a 100644 --- a/ui/ui/register-rotp.tpl +++ b/ui/ui/register-rotp.tpl @@ -58,8 +58,11 @@
- +
+ + + +
diff --git a/ui/ui/register.tpl b/ui/ui/register.tpl index 9b071830..c0777380 100644 --- a/ui/ui/register.tpl +++ b/ui/ui/register.tpl @@ -45,8 +45,11 @@
- +
+ + + +
diff --git a/ui/ui/routers.tpl b/ui/ui/routers.tpl index 5d9fa3d5..e4857e62 100644 --- a/ui/ui/routers.tpl +++ b/ui/ui/routers.tpl @@ -50,7 +50,7 @@ {$_L['Edit']} - {$_L['Delete']} + {$_L['Delete']} {/foreach} diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 187b5dad..be43feb2 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -53,12 +53,14 @@ @@ -224,7 +228,9 @@
  • {$_L['General_Settings']}
  • {$_L['Localisation']}
  • + href="{$_url}settings/localisation">{$_L['Localisation']} +
  • {Lang::T('User Notification')}
  • {$_L['Administrator_Users']}
  • User Image