diff --git a/system/controllers/home.php b/system/controllers/home.php
index a71d340e..20e1d1b6 100644
--- a/system/controllers/home.php
+++ b/system/controllers/home.php
@@ -317,7 +317,15 @@ if (!empty($_SESSION['nux-mac']) && !empty($_SESSION['nux-ip'] && !empty($_SESSI
}
}
}
-
+
+$tcf = ORM::for_table('tbl_customers_fields')
+ ->where('customer_id', $user['id'])
+ ->find_many();
+$vpn = ORM::for_table('tbl_port_pool')
+ ->find_one();
+$ui->assign('cf', $tcf);
+$ui->assign('vpn', $vpn);
+
$ui->assign('unpaid', ORM::for_table('tbl_payment_gateway')
->where('username', $user['username'])
->where('status', 1)
diff --git a/system/controllers/order.php b/system/controllers/order.php
index 0d4b2a3c..988db104 100644
--- a/system/controllers/order.php
+++ b/system/controllers/order.php
@@ -113,12 +113,19 @@ switch ($action) {
->where('type', 'Hotspot')
->where('prepaid', 'yes')
->find_many();
+ $plans_vpn = ORM::for_table('tbl_plans')
+ ->where('plan_type', $account_type)
+ ->where('enabled', '1')->where('is_radius', 0)
+ ->where('type', 'VPN')
+ ->where('prepaid', 'yes')
+ ->find_many();
}
$ui->assign('routers', $routers);
$ui->assign('radius_pppoe', $radius_pppoe);
$ui->assign('radius_hotspot', $radius_hotspot);
$ui->assign('plans_pppoe', $plans_pppoe);
$ui->assign('plans_hotspot', $plans_hotspot);
+ $ui->assign('plans_vpn', $plans_vpn);
run_hook('customer_view_order_plan'); #HOOK
$ui->display('user-ui/orderPlan.tpl');
break;
diff --git a/system/controllers/pool.php b/system/controllers/pool.php
index 5528e751..ba599f22 100644
--- a/system/controllers/pool.php
+++ b/system/controllers/pool.php
@@ -147,6 +147,132 @@ switch ($action) {
} else {
r2(U . 'pool/edit/' . $id, 'e', $msg);
}
+
+ case 'port':
+ $ui->assign('xfooter', '');
+
+ $name = _post('name');
+ if ($name != '') {
+ $query = ORM::for_table('tbl_port_pool')->where_like('pool_name', '%' . $name . '%')->order_by_desc('id');
+ $d = Paginator::findMany($query, ['name' => $name]);
+ } else {
+ $query = ORM::for_table('tbl_port_pool')->order_by_desc('id');
+ $d = Paginator::findMany($query);
+ }
+
+ $ui->assign('d', $d);
+ run_hook('view_port'); #HOOK
+ $ui->display('port.tpl');
+ break;
+
+ case 'add-port':
+ $r = ORM::for_table('tbl_routers')->find_many();
+ $ui->assign('r', $r);
+ run_hook('view_add_port'); #HOOK
+ $ui->display('port-add.tpl');
+ break;
+
+ case 'edit-port':
+ $id = $routes['2'];
+ $d = ORM::for_table('tbl_port_pool')->find_one($id);
+ if ($d) {
+ $ui->assign('d', $d);
+ run_hook('view_edit_port'); #HOOK
+ $ui->display('port-edit.tpl');
+ } else {
+ r2(U . 'pool/port', 'e', Lang::T('Account Not Found'));
+ }
+ break;
+
+ case 'delete-port':
+ $id = $routes['2'];
+ run_hook('delete_port'); #HOOK
+ $d = ORM::for_table('tbl_port_pool')->find_one($id);
+ if ($d) {
+ $d->delete();
+
+ r2(U . 'pool/port', 's', Lang::T('Data Deleted Successfully'));
+ }
+ break;
+
+ case 'sync':
+ $pools = ORM::for_table('tbl_port_pool')->find_many();
+ $log = '';
+ foreach ($pools as $pool) {
+ if ($pool['routers'] != 'radius') {
+ (new MikrotikPppoe())->update_pool($pool, $pool);
+ $log .= 'DONE: ' . $pool['port_name'] . ': ' . $pool['range_port'] . '
';
+ }
+ }
+ r2(U . 'pool/list', 's', $log);
+ break;
+ case 'add-port-post':
+ $name = _post('name');
+ $port_range = _post('port_range');
+ $public_ip = _post('public_ip');
+ $routers = _post('routers');
+ run_hook('add_pool'); #HOOK
+ $msg = '';
+ if (Validator::Length($name, 30, 2) == false) {
+ $msg .= 'Name should be between 3 to 30 characters' . '
';
+ }
+ if ($port_range == '' or $routers == '') {
+ $msg .= Lang::T('All field is required') . '
';
+ }
+
+ $d = ORM::for_table('tbl_port_pool')->where('routers', $routers)->find_one();
+ if ($d) {
+ $msg .= Lang::T('Routers already have ports, each router can only have 1 port range!') . '
';
+ }
+ if ($msg == '') {
+ $b = ORM::for_table('tbl_port_pool')->create();
+ $b->public_ip = $public_ip;
+ $b->port_name = $name;
+ $b->range_port = $port_range;
+ $b->routers = $routers;
+ $b->save();
+ r2(U . 'pool/port', 's', Lang::T('Data Created Successfully'));
+ } else {
+ r2(U . 'pool/add-port', 'e', $msg);
+ }
+ break;
+
+
+ case 'edit-port-post':
+ $name = _post('name');
+ $public_ip = _post('public_ip');
+ $range_port = _post('range_port');
+ $routers = _post('routers');
+ run_hook('edit_port'); #HOOK
+ $msg = '';
+ $msg = '';
+ if (Validator::Length($name, 30, 2) == false) {
+ $msg .= 'Name should be between 3 to 30 characters' . '
';
+ }
+ if ($range_port == '' or $routers == '') {
+ $msg .= Lang::T('All field is required') . '
';
+ }
+
+ $id = _post('id');
+ $d = ORM::for_table('tbl_port_pool')->find_one($id);
+ $old = ORM::for_table('tbl_port_pool')->find_one($id);
+ if (!$d) {
+ $msg .= Lang::T('Data Not Found') . '
';
+ }
+
+ if ($msg == '') {
+ $d->port_name = $name;
+ $d->public_ip = $public_ip;
+ $d->range_port = $range_port;
+ $d->routers = $routers;
+ $d->save();
+
+
+
+ r2(U . 'pool/port', 's', Lang::T('Data Updated Successfully'));
+ } else {
+ r2(U . 'pool/edit-port/' . $id, 'e', $msg);
+ }
break;
default:
diff --git a/system/controllers/services.php b/system/controllers/services.php
index aaa69635..9bc32e5e 100644
--- a/system/controllers/services.php
+++ b/system/controllers/services.php
@@ -901,6 +901,380 @@ switch ($action) {
r2(U . 'services/balance-add', 'e', $msg);
}
break;
+ case 'vpn':
+ $ui->assign('_title', Lang::T('VPN Plans'));
+ $ui->assign('xfooter', '');
+
+ $name = _post('name');
+ $name = _req('name');
+ $type1 = _req('type1');
+ $type2 = _req('type2');
+ $type3 = _req('type3');
+ $bandwidth = _req('bandwidth');
+ $valid = _req('valid');
+ $device = _req('device');
+ $status = _req('status');
+ $router = _req('router');
+ $ui->assign('type1', $type1);
+ $ui->assign('type2', $type2);
+ $ui->assign('type3', $type3);
+ $ui->assign('bandwidth', $bandwidth);
+ $ui->assign('valid', $valid);
+ $ui->assign('device', $device);
+ $ui->assign('status', $status);
+ $ui->assign('router', $router);
+
+ $append_url = "&type1=" . urlencode($type1)
+ . "&type2=" . urlencode($type2)
+ . "&type3=" . urlencode($type3)
+ . "&bandwidth=" . urlencode($bandwidth)
+ . "&valid=" . urlencode($valid)
+ . "&device=" . urlencode($device)
+ . "&status=" . urlencode($status)
+ . "&router=" . urlencode($router);
+
+ $bws = ORM::for_table('tbl_plans')->distinct()->select("id_bw")->where('tbl_plans.type', 'VPN')->findArray();
+ $ids = array_column($bws, 'id_bw');
+ if(count($ids)){
+ $ui->assign('bws', ORM::for_table('tbl_bandwidth')->select("id")->select('name_bw')->where_id_in($ids)->findArray());
+ }else{
+ $ui->assign('bws', []);
+ }
+ $ui->assign('type2s', ORM::for_table('tbl_plans')->getEnum("plan_type"));
+ $ui->assign('type3s', ORM::for_table('tbl_plans')->getEnum("typebp"));
+ $ui->assign('valids', ORM::for_table('tbl_plans')->getEnum("validity_unit"));
+ $ui->assign('routers', array_column(ORM::for_table('tbl_plans')->distinct()->select("routers")->whereNotEqual('routers', '')->findArray(), 'routers'));
+ $devices = [];
+ $files = scandir($DEVICE_PATH);
+ foreach ($files as $file) {
+ $ext = pathinfo($file, PATHINFO_EXTENSION);
+ if ($ext == 'php') {
+ $devices[] = pathinfo($file, PATHINFO_FILENAME);
+ }
+ }
+ $ui->assign('devices', $devices);
+ $query = ORM::for_table('tbl_bandwidth')
+ ->left_outer_join('tbl_plans', array('tbl_bandwidth.id', '=', 'tbl_plans.id_bw'))
+ ->where('tbl_plans.type', 'VPN');
+ if (!empty($type1)) {
+ $query->where('tbl_plans.prepaid', $type1);
+ }
+ if (!empty($type2)) {
+ $query->where('tbl_plans.plan_type', $type2);
+ }
+ if (!empty($type3)) {
+ $query->where('tbl_plans.typebp', $type3);
+ }
+ if (!empty($bandwidth)) {
+ $query->where('tbl_plans.id_bw', $bandwidth);
+ }
+ if (!empty($valid)) {
+ $query->where('tbl_plans.validity_unit', $valid);
+ }
+ if (!empty($router)) {
+ if ($router == 'radius') {
+ $query->where('tbl_plans.is_radius', '1');
+ } else {
+ $query->where('tbl_plans.routers', $router);
+ }
+ }
+ if (!empty($device)) {
+ $query->where('tbl_plans.device', $device);
+ }
+ if (in_array($status, ['0', '1'])) {
+ $query->where('tbl_plans.enabled', $status);
+ }
+ if ($name != '') {
+ $query->where_like('tbl_plans.name_plan', '%' . $name . '%');
+ }
+ $d = Paginator::findMany($query, ['name' => $name], 20, $append_url);
+
+ $ui->assign('d', $d);
+ run_hook('view_list_vpn'); #HOOK
+ $ui->display('vpn.tpl');
+ break;
+
+ case 'vpn-add':
+ $ui->assign('_title', Lang::T('VPN Plans'));
+ $d = ORM::for_table('tbl_bandwidth')->find_many();
+ $ui->assign('d', $d);
+ $r = ORM::for_table('tbl_routers')->find_many();
+ $ui->assign('r', $r);
+ $devices = [];
+ $files = scandir($DEVICE_PATH);
+ foreach ($files as $file) {
+ $ext = pathinfo($file, PATHINFO_EXTENSION);
+ if ($ext == 'php') {
+ $devices[] = pathinfo($file, PATHINFO_FILENAME);
+ }
+ }
+ $ui->assign('devices', $devices);
+ run_hook('view_add_vpn'); #HOOK
+ $ui->display('vpn-add.tpl');
+ break;
+
+ case 'vpn-edit':
+ $ui->assign('_title', Lang::T('VPN Plans'));
+ $id = $routes['2'];
+ $d = ORM::for_table('tbl_plans')->find_one($id);
+ if ($d) {
+ if (empty($d['device'])) {
+ if ($d['is_radius']) {
+ $d->device = 'Radius';
+ } else {
+ $d->device = 'MikrotikVpn';
+ }
+ $d->save();
+ }
+ $ui->assign('d', $d);
+ $p = ORM::for_table('tbl_pool')->where('routers', ($d['is_radius']) ? 'radius' : $d['routers'])->find_many();
+ $ui->assign('p', $p);
+ $b = ORM::for_table('tbl_bandwidth')->find_many();
+ $ui->assign('b', $b);
+ $r = [];
+ if ($d['is_radius']) {
+ $r = ORM::for_table('tbl_routers')->find_many();
+ }
+ $ui->assign('r', $r);
+ $devices = [];
+ $files = scandir($DEVICE_PATH);
+ foreach ($files as $file) {
+ $ext = pathinfo($file, PATHINFO_EXTENSION);
+ if ($ext == 'php') {
+ $devices[] = pathinfo($file, PATHINFO_FILENAME);
+ }
+ }
+ $ui->assign('devices', $devices);
+ //select expired plan
+ if ($d['is_radius']) {
+ $exps = ORM::for_table('tbl_plans')->selects('id', 'name_plan')->where('type', 'VPN')->where("is_radius", 1)->findArray();
+ } else {
+ $exps = ORM::for_table('tbl_plans')->selects('id', 'name_plan')->where('type', 'VPN')->where("routers", $d['routers'])->findArray();
+ }
+ $ui->assign('exps', $exps);
+ run_hook('view_edit_vpn'); #HOOK
+ $ui->display('vpn-edit.tpl');
+ } else {
+ r2(U . 'services/vpn', 'e', Lang::T('Account Not Found'));
+ }
+ break;
+
+ case 'vpn-delete':
+ $id = $routes['2'];
+
+ $d = ORM::for_table('tbl_plans')->find_one($id);
+ if ($d) {
+ run_hook('delete_vpn'); #HOOK
+
+ $dvc = Package::getDevice($d);
+ if ($_app_stage != 'demo') {
+ if (file_exists($dvc)) {
+ require_once $dvc;
+ (new $d['device'])->remove_plan($d);
+ } else {
+ new Exception(Lang::T("Devices Not Found"));
+ }
+ }
+ $d->delete();
+
+ r2(U . 'services/vpn', 's', Lang::T('Data Deleted Successfully'));
+ }
+ break;
+
+ case 'vpn-add-post':
+ $name = _post('name_plan');
+ $plan_type = _post('plan_type');
+ $radius = _post('radius');
+ $id_bw = _post('id_bw');
+ $price = _post('price');
+ $validity = _post('validity');
+ $validity_unit = _post('validity_unit');
+ $routers = _post('routers');
+ $device = _post('device');
+ $pool = _post('pool_name');
+ $enabled = _post('enabled');
+ $prepaid = _post('prepaid');
+ $expired_date = _post('expired_date');
+
+
+ $msg = '';
+ if (Validator::UnsignedNumber($validity) == false) {
+ $msg .= 'The validity must be a number' . '
';
+ }
+ if (Validator::UnsignedNumber($price) == false) {
+ $msg .= 'The price must be a number' . '
';
+ }
+ if ($name == '' or $id_bw == '' or $price == '' or $validity == '' or $pool == '') {
+ $msg .= Lang::T('All field is required') . '
';
+ }
+ if (empty($radius)) {
+ if ($routers == '') {
+ $msg .= Lang::T('All field is required') . '
';
+ }
+ }
+
+ $d = ORM::for_table('tbl_plans')->where('name_plan', $name)->find_one();
+ if ($d) {
+ $msg .= Lang::T('Name Plan Already Exist') . '
';
+ }
+ run_hook('add_vpn'); #HOOK
+ if ($msg == '') {
+ $b = ORM::for_table('tbl_bandwidth')->where('id', $id_bw)->find_one();
+ if ($b['rate_down_unit'] == 'Kbps') {
+ $unitdown = 'K';
+ $raddown = '000';
+ } else {
+ $unitdown = 'M';
+ $raddown = '000000';
+ }
+ if ($b['rate_up_unit'] == 'Kbps') {
+ $unitup = 'K';
+ $radup = '000';
+ } else {
+ $unitup = 'M';
+ $radup = '000000';
+ }
+ $rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown;
+ $radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown . '/' . $b['burst'];
+ $rate = trim($rate . " " . $b['burst']);
+ $d = ORM::for_table('tbl_plans')->create();
+ $d->type = 'VPN';
+ $d->name_plan = $name;
+ $d->id_bw = $id_bw;
+ $d->price = $price;
+ $d->plan_type = $plan_type;
+ $d->validity = $validity;
+ $d->validity_unit = $validity_unit;
+ $d->pool = $pool;
+ if (!empty($radius)) {
+ $d->is_radius = 1;
+ $d->routers = '';
+ } else {
+ $d->is_radius = 0;
+ $d->routers = $routers;
+ }
+ if ($prepaid == 'no') {
+ if ($expired_date > 28 && $expired_date < 1) {
+ $expired_date = 20;
+ }
+ $d->expired_date = $expired_date;
+ } else {
+ $d->expired_date = 0;
+ }
+ $d->enabled = $enabled;
+ $d->prepaid = $prepaid;
+ $d->device = $device;
+ $d->save();
+
+ $dvc = Package::getDevice($d);
+ if ($_app_stage != 'demo') {
+ if (file_exists($dvc)) {
+ require_once $dvc;
+ (new $d['device'])->add_plan($d);
+ } else {
+ new Exception(Lang::T("Devices Not Found"));
+ }
+ }
+ r2(U . 'services/vpn', 's', Lang::T('Data Created Successfully'));
+ } else {
+ r2(U . 'services/vpn-add', 'e', $msg);
+ }
+ break;
+
+ case 'edit-vpn-post':
+ $id = _post('id');
+ $plan_type = _post('plan_type');
+ $name = _post('name_plan');
+ $id_bw = _post('id_bw');
+ $price = _post('price');
+ $validity = _post('validity');
+ $validity_unit = _post('validity_unit');
+ $routers = _post('routers');
+ $device = _post('device');
+ $pool = _post('pool_name');
+ $plan_expired = _post('plan_expired');
+ $enabled = _post('enabled');
+ $prepaid = _post('prepaid');
+ $expired_date = _post('expired_date');
+ $on_login = _post('on_login');
+ $on_logout = _post('on_logout');
+
+ $msg = '';
+ if (Validator::UnsignedNumber($validity) == false) {
+ $msg .= 'The validity must be a number' . '
';
+ }
+ if (Validator::UnsignedNumber($price) == false) {
+ $msg .= 'The price must be a number' . '
';
+ }
+ if ($name == '' or $id_bw == '' or $price == '' or $validity == '' or $pool == '') {
+ $msg .= Lang::T('All field is required') . '
';
+ }
+
+ $d = ORM::for_table('tbl_plans')->where('id', $id)->find_one();
+ $old = ORM::for_table('tbl_plans')->where('id', $id)->find_one();
+ if ($d) {
+ } else {
+ $msg .= Lang::T('Data Not Found') . '
';
+ }
+ run_hook('edit_vpn'); #HOOK
+ if ($msg == '') {
+ $b = ORM::for_table('tbl_bandwidth')->where('id', $id_bw)->find_one();
+ if ($b['rate_down_unit'] == 'Kbps') {
+ $unitdown = 'K';
+ $raddown = '000';
+ } else {
+ $unitdown = 'M';
+ $raddown = '000000';
+ }
+ if ($b['rate_up_unit'] == 'Kbps') {
+ $unitup = 'K';
+ $radup = '000';
+ } else {
+ $unitup = 'M';
+ $radup = '000000';
+ }
+ $rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown;
+ $radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown . '/' . $b['burst'];
+ $rate = trim($rate . " " . $b['burst']);
+
+ $d->name_plan = $name;
+ $d->id_bw = $id_bw;
+ $d->price = $price;
+ $d->plan_type = $plan_type;
+ $d->validity = $validity;
+ $d->validity_unit = $validity_unit;
+ $d->routers = $routers;
+ $d->pool = $pool;
+ $d->plan_expired = $plan_expired;
+ $d->enabled = $enabled;
+ $d->prepaid = $prepaid;
+ $d->device = $device;
+ $d->on_login = $on_login;
+ $d->on_logout = $on_logout;
+ if ($prepaid == 'no') {
+ if ($expired_date > 28 && $expired_date < 1) {
+ $expired_date = 20;
+ }
+ $d->expired_date = $expired_date;
+ } else {
+ $d->expired_date = 0;
+ }
+ $d->save();
+
+ $dvc = Package::getDevice($d);
+ if ($_app_stage != 'demo') {
+ if (file_exists($dvc)) {
+ require_once $dvc;
+ (new $d['device'])->update_plan($old, $d);
+ } else {
+ new Exception(Lang::T("Devices Not Found"));
+ }
+ }
+ r2(U . 'services/vpn', 's', Lang::T('Data Updated Successfully'));
+ } else {
+ r2(U . 'services/vpn-edit/' . $id, 'e', $msg);
+ }
+ break;
default:
$ui->display('a404.tpl');
}
diff --git a/system/controllers/settings.php b/system/controllers/settings.php
index 33e4abe9..96cb497b 100644
--- a/system/controllers/settings.php
+++ b/system/controllers/settings.php
@@ -295,6 +295,16 @@ switch ($action) {
$d->value = _post('pppoe_plan');
$d->save();
}
+ $d = ORM::for_table('tbl_appconfig')->where('setting', 'vpn_plan')->find_one();
+ if ($d) {
+ $d->value = _post('vpn_plan');
+ $d->save();
+ } else {
+ $d = ORM::for_table('tbl_appconfig')->create();
+ $d->setting = 'vpn_plan';
+ $d->value = _post('vpn_plan');
+ $d->save();
+ }
$currency_code = $_POST['currency_code'];
$d = ORM::for_table('tbl_appconfig')->where('setting', 'currency_code')->find_one();
diff --git a/system/updates.json b/system/updates.json
index bce2f4ef..8d66fc0c 100644
--- a/system/updates.json
+++ b/system/updates.json
@@ -155,5 +155,11 @@
"2024.8.28" : [
"ALTER TABLE `tbl_routers` ADD `status` ENUM('Online', 'Offline') DEFAULT 'Online' AFTER `coordinates`;",
"ALTER TABLE `tbl_routers` ADD `last_seen` DATETIME AFTER `status`;"
+ ],
+ "2024.9.13" : [
+ "ALTER TABLE `tbl_plans` CHANGE `type` `type` ENUM('Hotspot','PPPOE','VPN','Balance') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;",
+ "ALTER TABLE `tbl_customers` CHANGE `service_type` `service_type` ENUM('Hotspot','PPPoE','VPN','Others') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'Others' COMMENT 'For selecting user type';",
+ "ALTER TABLE `tbl_transactions` CHANGE `type` `type` ENUM('Hotspot','PPPOE','VPN','Balance') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;",
+ "CREATE TABLE IF NOT EXISTS `tbl_port_pool` ( `id` int(10) NOT NULL AUTO_INCREMENT , `public_ip` varchar(40) NOT NULL, `port_name` varchar(40) NOT NULL, `range_port` varchar(40) NOT NULL, `routers` varchar(40) NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;"
]
}
\ No newline at end of file
diff --git a/ui/ui/app-localisation.tpl b/ui/ui/app-localisation.tpl
index 936c3abb..571d5588 100644
--- a/ui/ui/app-localisation.tpl
+++ b/ui/ui/app-localisation.tpl
@@ -128,6 +128,14 @@
{Lang::T('Change title in user Plan order')}
+
diff --git a/ui/ui/plan.tpl b/ui/ui/plan.tpl
index 3cca5861..32111f4a 100644
--- a/ui/ui/plan.tpl
+++ b/ui/ui/plan.tpl
@@ -95,9 +95,13 @@
{/if}
{if $ds['type'] == 'Hotspot'}
- {$ds['namebp']} |
- {else}
- {$ds['namebp']} |
+ {$ds['namebp']} |
+ {/if}
+ {if $ds['type'] == 'PPPOE'}
+ {$ds['namebp']} |
+ {/if}
+ {if $ds['type'] == 'VPN'}
+ {$ds['namebp']} |
{/if}
{$ds['type']} |
{Lang::dateAndTimeFormat($ds['recharged_on'],$ds['recharged_time'])} |
diff --git a/ui/ui/port-add.tpl b/ui/ui/port-add.tpl
new file mode 100644
index 00000000..b689a896
--- /dev/null
+++ b/ui/ui/port-add.tpl
@@ -0,0 +1,51 @@
+{include file="sections/header.tpl"}
+
+
+
+
+
{Lang::T('Add Port Pool')}
+
+
+
+
+
+{include file="sections/footer.tpl"}
diff --git a/ui/ui/port-edit.tpl b/ui/ui/port-edit.tpl
new file mode 100644
index 00000000..46413314
--- /dev/null
+++ b/ui/ui/port-edit.tpl
@@ -0,0 +1,49 @@
+{include file="sections/header.tpl"}
+
+
+
+
+
{Lang::T('Edit Port')}
+
+
+
+
+
+{include file="sections/footer.tpl"}
diff --git a/ui/ui/port.tpl b/ui/ui/port.tpl
new file mode 100644
index 00000000..77fd2661
--- /dev/null
+++ b/ui/ui/port.tpl
@@ -0,0 +1,76 @@
+{include file="sections/header.tpl"}
+
+
+
+
+
+
+ {Lang::T('Port Pool')} - VPN Tunnels
+
+
+
+
+
+
+
+ {Lang::T('Port Name')} |
+ {Lang::T('Public IP')} |
+ {Lang::T('Range Port')} |
+ {Lang::T('Routers')} |
+ {Lang::T('Manage')} |
+ ID |
+
+
+
+ {foreach $d as $ds}
+
+ {$ds['port_name']} |
+ {$ds['public_ip']} |
+ {$ds['range_port']} |
+ {$ds['routers']} |
+
+ {Lang::T('Edit')}
+
+ |
+ {$ds['id']} |
+
+ {/foreach}
+
+
+
+ {include file="pagination.tpl"}
+
+
{Lang::T('Create expired Internet Plan')}
+
{Lang::T('When customer expired, you can move it to Expired Internet Plan')}
+
+
+
+
+
+
+{include file="sections/footer.tpl"}
diff --git a/ui/ui/recharge.tpl b/ui/ui/recharge.tpl
index b896ab50..96370d58 100644
--- a/ui/ui/recharge.tpl
+++ b/ui/ui/recharge.tpl
@@ -22,6 +22,7 @@
+
@@ -215,6 +219,25 @@
{$_bill['plan_type']}
+ {if $_bill['type'] == 'VPN' && $_bill['routers'] == $vpn['routers']}
+
+ {Lang::T('Public IP')} |
+ {$vpn['public_ip']} / {$vpn['port_name']} |
+
+
+ {Lang::T('Private IP')} |
+ {$_user['pppoe_ip']} |
+
+ {foreach $cf as $tcf}
+
+ {if $tcf['field_name'] == 'Winbox' or $tcf['field_name'] == 'Api' or $tcf['field_name'] == 'Web'}
+ {$tcf['field_name']} - Port |
+ {$tcf['field_value']} |
+
+ {/if}
+ {/foreach}
+ {/if}
+
{if $nux_ip neq ''}
{Lang::T('Current IP')} |
diff --git a/ui/ui/user-ui/orderPlan.tpl b/ui/ui/user-ui/orderPlan.tpl
index f79ed4dd..9db514ff 100644
--- a/ui/ui/user-ui/orderPlan.tpl
+++ b/ui/ui/user-ui/orderPlan.tpl
@@ -226,6 +226,7 @@
{/if}
{foreach $routers as $router}
{if Validator::isRouterHasPlan($plans_hotspot, $router['name']) || Validator::isRouterHasPlan($plans_pppoe,
+ $router['name']) || Validator::isRouterHasPlan($plans_vpn,
$router['name'])}
@@ -338,9 +339,62 @@
{/if}
{/foreach}
+ {/if}
+ {if $_user['service_type'] == 'VPN' && Validator::countRouterPlan($plans_vpn,$router['name'])>0}
+
+
+ {foreach $plans_vpn as $plan}
+ {if $router['name'] eq $plan['routers']}
+
+
+
+
+
+
+
+
+ {Lang::T('Type')} |
+ {$plan['type']} |
+
+
+ {Lang::T('Price')} |
+ {Lang::moneyFormat($plan['price'])} |
+
+
+ {Lang::T('Validity')} |
+ {$plan['validity']} {$plan['validity_unit']} |
+
+
+
+
+
+
+
+ {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' &&
+ $_user['balance']>=$plan['price']}
+
{Lang::T('Buy for friend')}
+ {/if}
+
+
+
+ {/if}
+ {/foreach}
+
{/if}
{if $_user['service_type'] == 'Others' || $_user['service_type'] == '' &&
(Validator::countRouterPlan($plans_hotspot, $router['name'])>0 || Validator::countRouterPlan($plans_pppoe,
+ $router['name'])>0 || Validator::countRouterPlan($plans_vpn,
$router['name'])>0)}
@@ -443,6 +497,56 @@
{/if}
{/foreach}
+
+
+ {foreach $plans_vpn as $plan}
+ {if $router['name'] eq $plan['routers']}
+
+
+
+
+
+
+
+
+ {Lang::T('Type')} |
+ {$plan['type']} |
+
+
+ {Lang::T('Price')} |
+ {Lang::moneyFormat($plan['price'])} |
+
+
+ {Lang::T('Validity')} |
+ {$plan['validity']} {$plan['validity_unit']} |
+
+
+
+
+
+
+
+ {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' &&
+ $_user['balance']>=$plan['price']}
+
{Lang::T('Buy for friend')}
+ {/if}
+
+
+
+ {/if}
+ {/foreach}
+
{/if}
{/if}
diff --git a/ui/ui/vpn-add.tpl b/ui/ui/vpn-add.tpl
new file mode 100644
index 00000000..ae26a8ac
--- /dev/null
+++ b/ui/ui/vpn-add.tpl
@@ -0,0 +1,188 @@
+{include file="sections/header.tpl"}
+
+
+
+
+
{Lang::T('Add Service Plan')}
+
+
+
+
+
+{if $_c['radius_enable']}
+ {literal}
+
+ {/literal}
+{/if}
+{include file="sections/footer.tpl"}
diff --git a/ui/ui/vpn-edit.tpl b/ui/ui/vpn-edit.tpl
new file mode 100644
index 00000000..53428605
--- /dev/null
+++ b/ui/ui/vpn-edit.tpl
@@ -0,0 +1,255 @@
+{include file="sections/header.tpl"}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{include file="sections/footer.tpl"}
diff --git a/ui/ui/vpn.tpl b/ui/ui/vpn.tpl
new file mode 100644
index 00000000..6047e446
--- /dev/null
+++ b/ui/ui/vpn.tpl
@@ -0,0 +1,179 @@
+{include file="sections/header.tpl"}
+
+
+
+
+
+
{Lang::T('VPN Package')}
+
+
+
+
+
+
+ |
+ {Lang::T('Internet Plan')} |
+ |
+
+ {Lang::T('Expired')} |
+ |
+
+
+ {Lang::T('Name')} |
+ {Lang::T('Type')} |
+ {Lang::T('Bandwidth')} |
+ {Lang::T('Price')} |
+ {Lang::T('Validity')} |
+ {Lang::T('IP Pool')} |
+ {Lang::T('Internet Plan')} |
+ {Lang::T('Date')} |
+ {Lang::T('Location')} |
+ {Lang::T('Device')} |
+ {Lang::T('Manage')} |
+ ID |
+
+
+
+ {foreach $d as $ds}
+
+ {$ds['name_plan']} |
+ {$ds['plan_type']} {if $ds['prepaid'] != 'yes'}{Lang::T('Postpaid')}{else}{Lang::T('Prepaid')}{/if} |
+ {$ds['name_bw']} |
+ {Lang::moneyFormat($ds['price'])} |
+ {$ds['validity']} {$ds['validity_unit']} |
+ {$ds['pool']} |
+ {if $ds['plan_expired']}{Lang::T('Yes')}{else}{Lang::T('No')}
+ {/if} |
+ {if $ds['prepaid'] == no}{$ds['expired_date']}{/if} |
+
+ {if $ds['is_radius']}
+ RADIUS
+ {else}
+ {if $ds['routers']!=''}
+ {$ds['routers']}
+ {/if}
+ {/if}
+ |
+ {$ds['device']} |
+
+ {Lang::T('Edit')}
+
+ |
+ {$ds['id']} |
+
+ {/foreach}
+
+
+
+
+
+
+
+
+{include file="sections/footer.tpl"}