diff --git a/install/phpnuxbill.sql b/install/phpnuxbill.sql index 27f75df1..a76642a9 100644 --- a/install/phpnuxbill.sql +++ b/install/phpnuxbill.sql @@ -72,7 +72,7 @@ DROP TABLE IF EXISTS `tbl_payment_gateway`; CREATE TABLE `tbl_payment_gateway` ( `id` int NOT NULL, `username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `user_id` int(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, + `user_id` int(11) NOT NULL, `gateway` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'xendit | midtrans', `gateway_trx_id` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', `plan_id` int NOT NULL, @@ -151,7 +151,7 @@ CREATE TABLE `tbl_transactions` ( `id` int NOT NULL, `invoice` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, - `user_id` int(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, + `user_id` int(11) NOT NULL, `plan_name` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `price` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `recharged_on` date NOT NULL, @@ -258,6 +258,23 @@ CREATE TABLE IF NOT EXISTS `tbl_meta` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='This Table to add additional data for any table'; +CREATE TABLE `tbl_coupons` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `code` VARCHAR(50) NOT NULL UNIQUE, + `type` ENUM('fixed', 'percent') NOT NULL, + `value` DECIMAL(10,2) NOT NULL, + `description` TEXT NOT NULL, + `max_usage` INT NOT NULL DEFAULT 1, + `usage_count` INT NOT NULL DEFAULT 0, + `status` ENUM('active', 'inactive') NOT NULL, + `min_order_amount` DECIMAL(10,2) NOT NULL, + `max_discount_amount` DECIMAL(10,2) NOT NULL, + `start_date` DATE NOT NULL, + `end_date` DATE NOT NULL, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + ALTER TABLE `rad_acct` ADD PRIMARY KEY (`id`), ADD KEY `username` (`username`), diff --git a/system/autoload/Message.php b/system/autoload/Message.php index a5bc9449..e4610b4d 100644 --- a/system/autoload/Message.php +++ b/system/autoload/Message.php @@ -17,12 +17,15 @@ require $root_path . 'system/autoload/mail/SMTP.php'; class Message { - public static function sendTelegram($txt) + public static function sendTelegram($txt, $chat_id = null) { global $config; - run_hook('send_telegram', [$txt]); #HOOK - if (!empty($config['telegram_bot']) && !empty($config['telegram_target_id'])) { - return Http::getData('https://api.telegram.org/bot' . $config['telegram_bot'] . '/sendMessage?chat_id=' . $config['telegram_target_id'] . '&text=' . urlencode($txt)); + run_hook('send_telegram', [$txt, $chat_id = null]); #HOOK + if (!empty($config['telegram_bot'])) { + if (empty($chat_id)) { + $chat_id = $config['telegram_target_id']; + } + return Http::getData('https://api.telegram.org/bot' . $config['telegram_bot'] . '/sendMessage?chat_id=' . $chat_id . '&text=' . urlencode($txt)); } } @@ -73,7 +76,7 @@ class Message $iport = explode(":", $mikrotik['ip_address']); $client_m = new RouterOS\Client($iport[0], $mikrotik['username'], $mikrotik['password'], ($iport[1]) ? $iport[1] : null); } - if(empty($config['mikrotik_sms_command'])){ + if (empty($config['mikrotik_sms_command'])) { $config['mikrotik_sms_command'] = "/tool sms send"; } $smsRequest = new RouterOS\Request($config['mikrotik_sms_command']); @@ -185,7 +188,7 @@ class Message // Add bills to the note if there are any additional costs if ($add_cost != 0) { foreach ($bills as $k => $v) { - $note .= $k . " : " . Lang::moneyFormat($v) . "\n"; + $note .= $k . " : " . Lang::moneyFormat($v) . "\n"; } $total += $add_cost; } @@ -221,7 +224,7 @@ class Message if (strpos($msg, '[[payment_link]]') !== false) { // token only valid for 1 day, for security reason $token = User::generateToken($customer['id'], 1); - if(!empty($token['token'])){ + if (!empty($token['token'])) { $tur = ORM::for_table('tbl_user_recharges') ->where('customer_id', $customer['id']) ->where('namebp', $package) @@ -230,7 +233,7 @@ class Message $url = '?_route=home&recharge=' . $tur['id'] . '&uid=' . urlencode($token['token']); $msg = str_replace('[[payment_link]]', $url, $msg); } - }else{ + } else { $msg = str_replace('[[payment_link]]', '', $msg); } } diff --git a/system/controllers/coupons.php b/system/controllers/coupons.php new file mode 100644 index 00000000..b76b0f59 --- /dev/null +++ b/system/controllers/coupons.php @@ -0,0 +1,315 @@ +assign('_title', Lang::T('Coupons')); +$ui->assign('_system_menu', 'crm'); + +$action = $routes['1']; +$ui->assign('_admin', $admin); + +switch ($action) { + + case 'add': + if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Sales'])) { + echo json_encode(['status' => 'error', 'message' => Lang::T('You do not have permission to access this page')]); + exit; + } + $ui->assign('_title', Lang::T('Add Coupon')); + $ui->assign('csrf_token', Csrf::generateAndStoreToken()); + $ui->display('coupons-add.tpl'); + break; + + case 'add-post': + + if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Sales'])) { + echo json_encode(['status' => 'error', 'message' => Lang::T('You do not have permission to access this page')]); + exit; + } + $csrf_token = _post('csrf_token'); + if (!Csrf::check($csrf_token)) { + r2($_SERVER['HTTP_REFERER'], 'e', Lang::T('Invalid or Expired CSRF Token') . "."); + } + $code = Text::alphanumeric(_post('code', '')); + $type = _post('type', ''); + $value = floatval(_post('value', '')); + $description = _post('description', ''); + $max_usage = _post('max_usage', ''); + $min_order_amount = _post('min_order_amount', ''); + $max_discount_amount = intval(_post('max_discount_amount', '')); + $status = _post('status', 'active'); + $start_date = strtotime(_post('start_date', '0000-00-00')); + $end_date = strtotime(_post('end_date', '0000-00-00')); + + $error = []; + if (empty($code)) { + $error[] = Lang::T('Coupon Code is required'); + } + if (empty($type)) { + $error[] = Lang::T('Coupon Type is required'); + } + if (empty($value)) { + $error[] = Lang::T('Coupon Value is required'); + } + if (empty($description)) { + $error[] = Lang::T('Coupon Description is required'); + } + if (empty($max_usage)) { + $error[] = Lang::T('Coupon Maximum Usage is required'); + } + if (empty($min_order_amount)) { + $error[] = Lang::T('Coupon Minimum Order Amount is required'); + } + if (empty($max_discount_amount)) { + $error[] = Lang::T('Coupon Maximum Discount Amount is required'); + } + if (empty($status)) { + $error[] = Lang::T('Coupon Status is required'); + } + if (empty($start_date)) { + $error[] = Lang::T('Coupon Start Date is required'); + } + if (empty($end_date)) { + $error[] = Lang::T('Coupon End Date is required'); + } + + if (!empty($error)) { + r2(U . 'coupons/add', 'e', implode('
', $error)); + exit; + } + + //check if coupon code already exists + $coupon = ORM::for_table('tbl_coupons')->where('code', $code)->find_one(); + if ($coupon) { + r2(U . 'coupons/add', 'e', Lang::T('Coupon Code already exists')); + exit; + } + + $coupon = ORM::for_table('tbl_coupons')->create(); + $coupon->code = $code; + $coupon->type = $type; + $coupon->value = $value; + $coupon->description = $description; + $coupon->max_usage = $max_usage; + $coupon->min_order_amount = $min_order_amount; + $coupon->max_discount_amount = $max_discount_amount; + $coupon->status = $status; + $coupon->start_date = date('Y-m-d', $start_date); + $coupon->end_date = date('Y-m-d', $end_date); + $coupon->created_at = date('Y-m-d H:i:s'); + try { + $coupon->save(); + r2(U . 'coupons', 's', Lang::T('Coupon has been added successfully')); + } catch (Exception $e) { + _log(Lang::T('Error adding coupon: ' . $e->getMessage())); + r2(U . 'coupons/add', 'e', Lang::T('Error adding coupon: ' . $e->getMessage())); + } + break; + + case 'edit': + + if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Sales'])) { + echo json_encode(['status' => 'error', 'message' => Lang::T('You do not have permission to access this page')]); + exit; + } + + $coupon_id = intval($routes['2']); + if (empty($coupon_id)) { + r2(U . 'coupons', 'e', Lang::T('Invalid Coupon ID')); + exit; + } + $coupon = ORM::for_table('tbl_coupons')->find_one($coupon_id); + if (!$coupon) { + r2(U . 'coupons', 'e', Lang::T('Coupon Not Found')); + exit; + } + $ui->assign('coupon', $coupon); + $ui->assign('_title', Lang::T('Edit Coupon: ' . $coupon['code'])); + $ui->assign('csrf_token', Csrf::generateAndStoreToken()); + $ui->display('coupons-edit.tpl'); + break; + + case 'edit-post': + + if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Sales'])) { + echo json_encode(['status' => 'error', 'message' => Lang::T('You do not have permission to access this page')]); + exit; + } + + $csrf_token = _post('csrf_token'); + if (!Csrf::check($csrf_token)) { + r2($_SERVER['HTTP_REFERER'], 'e', Lang::T('Invalid or Expired CSRF Token') . "."); + } + + $code = Text::alphanumeric(_post('code', '')); + $type = _post('type', ''); + $value = floatval(_post('value', '')); + $description = _post('description', ''); + $max_usage = _post('max_usage', ''); + $min_order_amount = _post('min_order_amount', ''); + $max_discount_amount = intval(_post('max_discount_amount', '')); + $status = _post('status', 'active'); + $start_date = strtotime(_post('start_date', '0000-00-00')); + $end_date = strtotime(_post('end_date', '0000-00-00')); + + $error = []; + if (empty($code)) { + $error[] = Lang::T('Coupon code is required'); + } + if (empty($type)) { + $error[] = Lang::T('Coupon type is required'); + } + if (empty($value)) { + $error[] = Lang::T('Coupon value is required'); + } + if (empty($description)) { + $error[] = Lang::T('Coupon description is required'); + } + if (empty($max_usage)) { + $error[] = Lang::T('Coupon maximum usage is required'); + } + if (empty($min_order_amount)) { + $error[] = Lang::T('Coupon minimum order amount is required'); + } + if (empty($max_discount_amount)) { + $error[] = Lang::T('Coupon maximum discount amount is required'); + } + if (empty($status)) { + $error[] = Lang::T('Coupon status is required'); + } + if (empty($start_date)) { + $error[] = Lang::T('Coupon start date is required'); + } + if (empty($end_date)) { + $error[] = Lang::T('Coupon end date is required'); + } + if (!empty($error)) { + r2(U . 'coupons/edit/' . $coupon_id, 'e', implode('
', $error)); + exit; + } + $coupon = ORM::for_table('tbl_coupons')->find_one($coupon_id); + $coupon->code = $code; + $coupon->type = $type; + $coupon->value = $value; + $coupon->description = $description; + $coupon->max_usage = $max_usage; + $coupon->min_order_amount = $min_order_amount; + $coupon->max_discount_amount = $max_discount_amount; + $coupon->status = $status; + $coupon->start_date = date('Y-m-d', $start_date); + $coupon->end_date = date('Y-m-d', $end_date); + $coupon->updated_at = date('Y-m-d H:i:s'); + try { + $coupon->save(); + r2(U . 'coupons', 's', Lang::T('Coupon has been updated successfully')); + } catch (Exception $e) { + _log(Lang::T('Error updating coupon: ') . $e->getMessage()); + r2(U . 'coupons/edit/' . $coupon_id, 'e', Lang::T('Error updating coupon: ') . $e->getMessage()); + } + break; + + case 'delete': + + if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Sales'])) { + echo json_encode(['status' => 'error', 'message' => Lang::T('You do not have permission to access this page')]); + exit; + } + + if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $couponIds = json_decode($_POST['couponIds'], true); + + if (is_array($couponIds) && !empty($couponIds)) { + // Delete coupons from the database + ORM::for_table('tbl_coupons') + ->where_in('id', $couponIds) + ->delete_many(); + + // Return success response + echo json_encode(['status' => 'success', 'message' => Lang::T("Coupons Deleted Successfully.")]); + exit; + } else { + echo json_encode(['status' => 'error', 'message' => Lang::T("Invalid or missing coupon IDs.")]); + exit; + } + } else { + echo json_encode(['status' => 'error', 'message' => Lang::T("Invalid request method.")]); + } + break; + + case 'status': + if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Sales'])) { + _alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard"); + exit; + } + + if ($_SERVER['REQUEST_METHOD'] === 'GET') { + $couponId = $_GET['coupon_id'] ?? ''; + $csrf_token = $_GET['csrf_token'] ?? ''; + $status = $_GET['status'] ?? ''; + if (empty($couponId) || empty($csrf_token) || !hotspot_validateCsrfToken($csrf_token) || empty($status)) { + r2($_SERVER['HTTP_REFERER'], 'e', Lang::T("Invalid request")); + exit; + } + $coupon = ORM::for_table('tbl_coupons')->where('id', $couponId)->find_one(); + if (!$coupon) { + r2($_SERVER['HTTP_REFERER'], 'e', Lang::T("Coupon not found.")); + exit; + } + $coupon->status = $status; + $coupon->save(); + r2($_SERVER['HTTP_REFERER'], 's', Lang::T("Coupon status updated successfully.")); + } else { + r2($_SERVER['HTTP_REFERER'], 'e', Lang::T("Invalid request method")); + } + break; + + default: + if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Sales'])) { + echo json_encode(['status' => 'error', 'message' => Lang::T('You do not have permission to access this page')]); + exit; + } + $ui->assign('_title', Lang::T('Coupons')); + $ui->assign('_system_menu', 'crm'); + + $search = _post('search'); + $filter = _post('filter', 'none'); + + $couponsData = ORM::for_table('tbl_coupons') + ->table_alias('c') + ->select_many( + 'c.id', + 'c.code', + 'c.type', + 'c.value', + 'c.description', + 'c.max_usage', + 'c.usage_count', + 'c.status', + 'c.min_order_amount', + 'c.max_discount_amount', + 'c.start_date', + 'c.end_date', + 'c.created_at', + 'c.updated_at' + ); + + // Apply filters + if ($search != '') { + $searchLike = "%$search%"; + $couponsData->whereRaw( + "code LIKE ? OR type LIKE ? OR value LIKE ? OR max_usage LIKE ? OR usage_count LIKE ? OR status LIKE ? OR min_order_amount LIKE ? OR max_discount_amount LIKE ?", + [$searchLike, $searchLike, $searchLike, $searchLike, $searchLike, $searchLike, $searchLike, $searchLike] + ); + } + $couponsData->order_by_asc('c.id'); + $coupons = Paginator::findMany($couponsData, ['search' => $search], 5, ''); + $ui->assign('csrf_token', Csrf::generateAndStoreToken()); + $ui->assign('coupons', $coupons); + $ui->display('coupons.tpl'); + break; +} diff --git a/system/controllers/order.php b/system/controllers/order.php index ca2fd298..d1be3771 100644 --- a/system/controllers/order.php +++ b/system/controllers/order.php @@ -26,7 +26,7 @@ switch ($action) { $query = ORM::for_table('tbl_payment_gateway')->where('username', $user['username'])->order_by_desc('id'); $d = Paginator::findMany($query); } - + $ui->assign('d', $d); $ui->assign('_title', Lang::T('Order History')); run_hook('customer_view_order_history'); #HOOK @@ -410,6 +410,78 @@ switch ($action) { if ($router['name'] != 'balance') { list($bills, $add_cost) = User::getBills($id_customer); } + + if (!isset($_SESSION['coupon_attempts'])) { + $_SESSION['coupon_attempts'] = 0; + } + + if ($_SESSION['coupon_attempts'] >= 5) { + r2($_SERVER['HTTP_REFERER'], 'e', Lang::T("Too many invalid attempts. Please try again later.")); + } + + if (_post('coupon')) { + + if ($plan['routers'] === 'balance') { + r2($_SERVER['HTTP_REFERER'], 'e', Lang::T("Coupon not available for Balance")); + } + + $coupon = ORM::for_table('tbl_coupons')->where('code', _post('coupon'))->find_one(); + + if (!$coupon) { + $_SESSION['coupon_attempts']++; + r2($_SERVER['HTTP_REFERER'], 'e', Lang::T("Coupon not found")); + } + + if ($coupon['status'] != 'active') { + $_SESSION['coupon_attempts']++; + r2($_SERVER['HTTP_REFERER'], 'e', Lang::T("Coupon is not active")); + } + + $today = date('Y-m-d'); + if ($today < $coupon['start_date'] || $today > $coupon['end_date']) { + $_SESSION['coupon_attempts']++; + r2($_SERVER['HTTP_REFERER'], 'e', Lang::T("Coupon is not valid for today")); + } + + if ($coupon['usage_count'] >= $coupon['max_usage']) { + $_SESSION['coupon_attempts']++; + r2($_SERVER['HTTP_REFERER'], 'e', Lang::T("Coupon usage limit reached")); + } + + if ($plan['price'] < $coupon['min_order_amount']) { + $_SESSION['coupon_attempts']++; + r2($_SERVER['HTTP_REFERER'], 'e', Lang::T("The order amount does not meet the minimum requirement for this coupon")); + } + + $_SESSION['coupon_attempts'] = 0; + + // Calculate discount value + $discount = 0; + switch ($coupon['type']) { + case 'percent': + $discount = ($coupon['value'] / 100) * $plan['price']; + if ($discount > $coupon['max_discount_amount']) { + $discount = $coupon['max_discount_amount']; + } + break; + case 'fixed': + $discount = $coupon['value']; + break; + } + + // Ensure discount does not exceed the plan price + if ($discount >= $plan['price']) { + r2($_SERVER['HTTP_REFERER'], 'e', Lang::T("Discount value exceeds the plan price")); + } + + $plan['price'] -= $discount; + $coupon->usage_count = $coupon['usage_count'] + 1; + $coupon->save(); + $ui->assign('discount', $discount); + $ui->assign('notify', Lang::T("Coupon applied successfully. You saved " . Lang::moneyFormat($discount))); + $ui->assign('notify_t', 's'); + } + $tax = Package::tax($plan['price'] + $add_cost, $tax_rate); $pgs = array_values(explode(',', $config['payment_gateway'])); if (count($pgs) == 0) { @@ -446,6 +518,7 @@ switch ($action) { } case 'buy': $gateway = _post('gateway'); + $discount = _post('discount') ?: 0; if ($gateway == 'balance') { unset($_SESSION['gateway']); r2(U . 'order/pay/' . $routes[2] . '/' . $routes[3]); @@ -566,12 +639,12 @@ switch ($action) { // Postpaid price from field $add_inv = User::getAttribute("Invoice", $id_customer); if (empty($add_inv) or $add_inv == 0) { - $d->price = ($plan['price'] + $add_cost + $tax); + $d->price = $plan['price'] + $add_cost + $tax - $discount; } else { - $d->price = ($add_inv + $add_cost + $tax); + $d->price = $add_inv + $add_cost + $tax - $discount; } } else { - $d->price = ($plan['price'] + $add_cost + $tax); + $d->price = $plan['price'] + $add_cost + $tax - $discount; } $d->created_date = date('Y-m-d H:i:s'); $d->status = 1; @@ -589,12 +662,12 @@ switch ($action) { // Postpaid price from field $add_inv = User::getAttribute("Invoice", $id_customer); if (empty($add_inv) or $add_inv == 0) { - $d->price = ($plan['price'] + $add_cost + $tax); + $d->price = ($plan['price'] + $add_cost + $tax - $discount); } else { - $d->price = ($add_inv + $add_cost + $tax); + $d->price = ($add_inv + $add_cost + $tax - $discount); } } else { - $d->price = ($plan['price'] + $add_cost + $tax); + $d->price = ($plan['price'] + $add_cost + $tax - $discount); } //$d->price = ($plan['price'] + $add_cost); $d->created_date = date('Y-m-d H:i:s'); diff --git a/system/controllers/plan.php b/system/controllers/plan.php index c19e37e5..91a84631 100644 --- a/system/controllers/plan.php +++ b/system/controllers/plan.php @@ -412,7 +412,7 @@ switch ($action) { break; case 'voucher': - $ui->assign('_title', Lang::T('Vouchers')); + $ui->assign('_title', Lang::T('Voucher Cards')); $search = _req('search'); $router = _req('router'); $customer = _req('customer'); @@ -422,6 +422,7 @@ switch ($action) { $ui->assign('customer', $customer); $ui->assign('status', $status); $ui->assign('plan', $plan); + $ui->assign('_system_menu', 'cards'); $query = ORM::for_table('tbl_plans') ->left_outer_join('tbl_voucher', array('tbl_plans.id', '=', 'tbl_voucher.id_plan')); diff --git a/system/updates.json b/system/updates.json index dd97c432..eb2526bb 100644 --- a/system/updates.json +++ b/system/updates.json @@ -59,108 +59,108 @@ "2024.2.19": [ "CREATE TABLE `tbl_customers_fields` (`id` INT PRIMARY KEY AUTO_INCREMENT, `customer_id` INT NOT NULL, `field_name` VARCHAR(255) NOT NULL, `field_value` VARCHAR(255) NOT NULL, FOREIGN KEY (customer_id) REFERENCES tbl_customers(id));" ], - "2024.2.20" : [ + "2024.2.20": [ "ALTER TABLE `tbl_plans` ADD `list_expired` VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'address list' AFTER `pool_expired`;", "ALTER TABLE `tbl_bandwidth` ADD `burst` VARCHAR(128) NOT NULL DEFAULT '' AFTER `rate_up_unit`;" ], - "2024.2.20.1" : [ + "2024.2.20.1": [ "DROP TABLE IF EXISTS `tbl_customers_meta`;" ], - "2024.2.23" : [ + "2024.2.23": [ "ALTER TABLE `tbl_transactions` ADD `admin_id` INT NOT NULL DEFAULT '1' AFTER `type`;", "ALTER TABLE `tbl_user_recharges` ADD `admin_id` INT NOT NULL DEFAULT '1' AFTER `type`;" ], - "2024.3.3" : [ - "ALTER TABLE `tbl_plans` CHANGE `validity_unit` `validity_unit` ENUM('Mins','Hrs','Days','Months','Period') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;" + "2024.3.3": [ + "ALTER TABLE `tbl_plans` CHANGE `validity_unit` `validity_unit` ENUM('Mins','Hrs','Days','Months','Period') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;" ], - "2024.3.12" : [ + "2024.3.12": [ "ALTER TABLE `tbl_plans` CHANGE `allow_purchase` `prepaid` ENUM('yes','no') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'yes' COMMENT 'is prepaid';" ], - "2024.3.14" : [ + "2024.3.14": [ "ALTER TABLE `tbl_transactions` ADD `note` VARCHAR(256) NOT NULL DEFAULT '' COMMENT 'for note' AFTER `type`;" ], - "2024.3.19" : [ + "2024.3.19": [ "ALTER TABLE `tbl_customers` ADD `coordinates` VARCHAR(50) NOT NULL DEFAULT '' COMMENT 'Latitude and Longitude coordinates' AFTER `email`;" ], - "2024.3.19.1" : [ + "2024.3.19.1": [ "ALTER TABLE `tbl_customers` ADD `account_type` ENUM('Business', 'Personal') DEFAULT 'Personal' COMMENT 'For selecting account type' AFTER `coordinates`;" ], - "2024.3.19.2" : [ + "2024.3.19.2": [ "ALTER TABLE `tbl_plans` ADD `plan_type` ENUM('Business', 'Personal') DEFAULT 'Personal' COMMENT 'For selecting account type' ;" ], "2023.3.20": [ "ALTER TABLE `tbl_customers` CHANGE `pppoe_password` `pppoe_password` VARCHAR(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'For PPPOE Login';" ], - "2024.4.5" : [ + "2024.4.5": [ "ALTER TABLE `tbl_payment_gateway` ADD `trx_invoice` VARCHAR(25) NOT NULL DEFAULT '' COMMENT 'from tbl_transactions' AFTER `paid_date`;" ], - "2024.5.17" : [ + "2024.5.17": [ "ALTER TABLE `tbl_customers` ADD `status` ENUM('Active','Banned','Disabled') NOT NULL DEFAULT 'Active' AFTER `auto_renewal`;" ], - "2024.5.18" : [ + "2024.5.18": [ "ALTER TABLE `tbl_customers` CHANGE `status` `status` ENUM('Active','Banned','Disabled','Inactive','Limited','Suspended') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'Active';" ], - "2024.5.20" : [ + "2024.5.20": [ "ALTER TABLE `tbl_customers` ADD `city` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci AFTER `address`, ADD `district` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci AFTER `city`, ADD `state` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci AFTER `district`, ADD `zip` VARCHAR(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci AFTER `state`;" ], - "2024.6.5" : [ + "2024.6.5": [ "ALTER TABLE `tbl_plans` ADD `price_old` VARCHAR(40) NOT NULL DEFAULT '' AFTER `price`;", "ALTER TABLE `tbl_plans` ADD `device` VARCHAR(32) NOT NULL DEFAULT '' AFTER `plan_type`;" ], - "2024.6.10" : [ + "2024.6.10": [ "ALTER TABLE `tbl_pool` ADD `local_ip` VARCHAR(40) NOT NULL DEFAULT '' AFTER `pool_name`;" ], - "2024.6.11" : [ + "2024.6.11": [ "ALTER TABLE `tbl_plans` ADD `plan_expired` INT NOT NULL DEFAULT '0' AFTER `pool`;", "ALTER TABLE `tbl_plans` DROP `pool_expired`, DROP `list_expired`;" ], - "2024.6.19" : [ + "2024.6.19": [ "ALTER TABLE `tbl_plans` ADD `expired_date` TINYINT(1) NOT NULL DEFAULT '20' AFTER `plan_expired`;" ], - "2024.6.21" : [ + "2024.6.21": [ "ALTER TABLE `tbl_plans` ADD `on_login` TEXT NULL DEFAULT NULL AFTER `device`;", "ALTER TABLE `tbl_plans` ADD `on_logout` TEXT NULL DEFAULT NULL AFTER `on_login`;" ], - "2024.7.6" : [ + "2024.7.6": [ "CREATE TABLE IF NOT EXISTS `rad_acct` ( `id` bigint NOT NULL, `acctsessionid` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', `username` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', `realm` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', `nasid` varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', `nasipaddress` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', `nasportid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `nasporttype` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `framedipaddress` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',`acctstatustype` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `macaddr` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `dateAdded` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;", "ALTER TABLE `rad_acct` ADD PRIMARY KEY (`id`), ADD KEY `username` (`username`), ADD KEY `framedipaddress` (`framedipaddress`), ADD KEY `acctsessionid` (`acctsessionid`), ADD KEY `nasipaddress` (`nasipaddress`);", "ALTER TABLE `rad_acct` MODIFY `id` bigint NOT NULL AUTO_INCREMENT;" ], - "2024.7.24" : [ + "2024.7.24": [ "ALTER TABLE `tbl_voucher` ADD `used_date` DATETIME NULL DEFAULT NULL AFTER `status`;", "UPDATE `tbl_voucher` SET `used_date`=now() WHERE `status`=1;" ], - "2024.8.1" : [ + "2024.8.1": [ "ALTER TABLE `tbl_payment_gateway` CHANGE `gateway_trx_id` `gateway_trx_id` VARCHAR(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '';", "ALTER TABLE `tbl_payment_gateway` CHANGE `pg_url_payment` `pg_url_payment` VARCHAR(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '';" ], - "2024.8.2" : [ + "2024.8.2": [ "CREATE TABLE IF NOT EXISTS `tbl_customers_inbox` (`id` int UNSIGNED NOT NULL AUTO_INCREMENT, `customer_id` int NOT NULL, `date_created` datetime NOT NULL, `date_read` datetime DEFAULT NULL, `subject` varchar(64) COLLATE utf8mb4_general_ci NOT NULL, `body` TEXT NULL DEFAULT NULL, `from` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'System' COMMENT 'System or Admin or Else',`admin_id` int NOT NULL DEFAULT '0' COMMENT 'other than admin is 0', PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;" ], - "2024.8.5" : [ + "2024.8.5": [ "ALTER TABLE `tbl_customers` ADD `pppoe_username` VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'For PPPOE Login' AFTER `password`;", "ALTER TABLE `tbl_customers` ADD `pppoe_ip` VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'For PPPOE Login' AFTER `pppoe_password`;" ], - "2024.8.5.1" : [ + "2024.8.5.1": [ "ALTER TABLE `tbl_routers` ADD `coordinates` VARCHAR(50) NOT NULL DEFAULT '' AFTER `description`;", "ALTER TABLE `tbl_routers` ADD `coverage` VARCHAR(8) NOT NULL DEFAULT '0' AFTER `coordinates`;" ], - "2024.8.6" : [ + "2024.8.6": [ "ALTER TABLE `rad_acct` ADD `acctinputoctets` BIGINT NOT NULL DEFAULT '0' AFTER `framedipaddress`;", "ALTER TABLE `rad_acct` ADD `acctoutputoctets` BIGINT NOT NULL DEFAULT '0' AFTER `acctinputoctets`;" ], - "2024.8.7" : [ + "2024.8.7": [ "ALTER TABLE `tbl_customers` CHANGE `coordinates` `coordinates` VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Latitude and Longitude coordinates';" ], - "2024.8.28" : [ + "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" : [ + "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;" + "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;" ], "2024.10.10": [ "ALTER TABLE `tbl_users` ADD `login_token` VARCHAR(40) AFTER `last_login`;" @@ -168,15 +168,18 @@ "2024.10.17": [ "CREATE TABLE IF NOT EXISTS `tbl_meta` ( `id` int UNSIGNED NOT NULL AUTO_INCREMENT, `tbl` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Table name', `tbl_id` int NOT NULL COMMENT 'table value id', `name` varchar(32) COLLATE utf8mb4_general_ci NOT NULL, `value` mediumtext COLLATE utf8mb4_general_ci, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='This Table to add additional data for any table';" ], - "2024.10.30" : [ + "2024.10.30": [ "ALTER TABLE `tbl_users` ADD `photo` VARCHAR(128) NOT NULL DEFAULT '/admin.default.png' AFTER `root`;", "ALTER TABLE `tbl_users` ADD `data` TEXT NULL DEFAULT NULL COMMENT 'to put additional data' AFTER `status`;" ], - "2024.10.31" : [ + "2024.10.31": [ "ALTER TABLE `tbl_customers` ADD `photo` VARCHAR(128) NOT NULL DEFAULT '/user.default.jpg' AFTER `password`;" ], - "2024.12.5" : [ + "2024.12.5": [ "ALTER TABLE `tbl_transactions` ADD `user_id` INT(11) NULL AFTER `username`;", "ALTER TABLE `tbl_payment_gateway` ADD `user_id` INT(11) NULL AFTER `username`;" + ], + "2024.12.16": [ + "CREATE TABLE `tbl_coupons` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `code` VARCHAR(50) NOT NULL UNIQUE, `type` ENUM('fixed', 'percent') NOT NULL, `value` DECIMAL(10,2) NOT NULL, `description` TEXT NOT NULL, `max_usage` INT NOT NULL DEFAULT 1,`usage_count` INT NOT NULL DEFAULT 0,`status` ENUM('active', 'inactive') NOT NULL, `min_order_amount` DECIMAL(10,2) NOT NULL, `max_discount_amount` DECIMAL(10,2) NOT NULL, `start_date` DATE NOT NULL,`end_date` DATE NOT NULL, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);" ] } \ No newline at end of file diff --git a/ui/ui/coupons-add.tpl b/ui/ui/coupons-add.tpl new file mode 100644 index 00000000..551a3f93 --- /dev/null +++ b/ui/ui/coupons-add.tpl @@ -0,0 +1,153 @@ +{include file="sections/header.tpl"} + + +
+
+
+
{Lang::T('Add Coupon')}
+
+
+ + + +
+ +
+
+ + + + +
+

{Lang::T('Unique code for the coupon')}

+
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +

{Lang::T('Value of the discount (amount or percentage)')}

+
+
+ + +
+ +
+ +

{Lang::T('Brief explanation of the coupon')}

+
+
+ + +
+ +
+ +

{Lang::T('Maximum number of times this coupon can be used')}

+
+
+ + +
+ +
+ +

{Lang::T('Minimum cart total required to use this coupon')}

+
+
+ + +
+ +
+ +

{Lang::T('Maximum discount amount applicable (for percent type)')}

+
+
+ + +
+ +
+ + +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+
+ + Or {Lang::T('Cancel')} +
+
+
+ +
+
+
+
+ + + + + +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/coupons-edit.tpl b/ui/ui/coupons-edit.tpl new file mode 100644 index 00000000..f6396efb --- /dev/null +++ b/ui/ui/coupons-edit.tpl @@ -0,0 +1,150 @@ +{include file="sections/header.tpl"} + + + + +
+
+
+
{Lang::T('Edit Coupon')}
+
+
+ + + +
+ +
+ +

{Lang::T('Unique code for the coupon')}

+
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +

{Lang::T('Value of the discount (amount or + percentage)')}

+
+
+ + +
+ +
+ +

{Lang::T('Brief explanation of the coupon')}

+
+
+ + +
+ +
+ +

{Lang::T('Maximum number of times this coupon can be + used')}

+
+
+ + +
+ +
+ +

{Lang::T('Minimum cart total required to use this + coupon')}

+
+
+ + +
+ +
+ +

{Lang::T('Maximum discount amount applicable (for percent + type)')}

+
+
+ + +
+ +
+ + +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+
+ + Or {Lang::T('Cancel')} +
+
+
+ +
+
+
+
+ + + + + +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/coupons.tpl b/ui/ui/coupons.tpl new file mode 100644 index 00000000..11d5d20f --- /dev/null +++ b/ui/ui/coupons.tpl @@ -0,0 +1,363 @@ +{include file="sections/header.tpl"} + + + +
+
+
+ +
+ +
+ +
+
+
+
+ +
+
+ +
+
+
+
+   +
+
+ + + + + + + + + + + + + + + + + + + + + + {if $coupons} + {foreach $coupons as $coupon} + + + + + + + + + + + + + + + + + + + {/foreach} + {else} + + + + {/if} + +
{Lang::T('Code')}{Lang::T('Type')}{Lang::T('Value')}{Lang::T('Description')}{Lang::T('Max Usage')}{Lang::T('Usage Count')}{Lang::T('Status')}{Lang::T('Min Order')}{Lang::T('Max Discount')}{Lang::T('Start Date')}{Lang::T('End Date')}{Lang::T('Created Date')}{Lang::T('Updated Date')}{Lang::T('Action')}
+ {$coupon['code']} + {$coupon['type']}{$coupon['value']}{$coupon['description']}{$coupon['max_usage']}{$coupon['usage_count']} + {if $coupon['status'] == 'inactive'} + {Lang::T('Inactive')} + {elseif $coupon['status'] == 'active'} + {Lang::T('Active')} + {else} + {Lang::T('Unknown')} + {/if} + {$coupon['min_order_amount']}{$coupon['max_discount_amount']}{$coupon['start_date']}{$coupon['end_date']}{$coupon['created_at']}{$coupon['updated_at']} +
+ {Lang::T('Edit')} + {if $coupon['status'] neq 'inactive'} + + {Lang::T('Block')} + + {else} + + {Lang::T('Unblock')} + + {/if} +
+
+ {Lang::T('No coupons found.')} +
+ {include file="pagination.tpl"} +
+
+
+
+ {if in_array($_admin['user_type'],['SuperAdmin','Admin'])} + + {/if} +
+
+
+
+
+   +
+ + + +{literal} + +{/literal} + +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/customer/selectGateway.tpl b/ui/ui/customer/selectGateway.tpl index 510bceae..c6ff6236 100644 --- a/ui/ui/customer/selectGateway.tpl +++ b/ui/ui/customer/selectGateway.tpl @@ -2,166 +2,178 @@
{if file_exists("$PAGES_PATH/Payment_Info.html")} -
-
-
{Lang::T('Payment Info')}
-
{include file="$PAGES_PATH/Payment_Info.html"}
-
+
+
+
{Lang::T('Payment Info')}
+
{include file="$PAGES_PATH/Payment_Info.html"}
+
{/if}
-
{Lang::T('Available Payment Gateway')}
- -
-
{Lang::T('Package Details')}
+
{Lang::T('Make Payment')}
-
    -
  • - {Lang::T('Plan Name')} {$plan['name_plan']} -
  • - {if $plan['is_radius'] or $plan['routers']} -
  • - {Lang::T('Location')} {if - $plan['is_radius']}Radius{else}{$plan['routers']} - {/if} -
  • - {/if} +
    +
    {Lang::T('Package Details')}
    + {if !$custom} +
    • - {Lang::T('Type')} {if $plan['prepaid'] eq - 'yes'}{Lang::T('Prepaid')}{else}{Lang::T('Postpaid')} - {/if} - {$plan['type']} + {Lang::T('Plan Name')} + {$plan['name_plan']}
    • + + {if $plan['is_radius'] or $plan['routers']}
    • - {Lang::T('Package Price')} + {Lang::T('Location')} + {if $plan['is_radius']}Radius{else}{$plan['routers']}{/if} +
    • + {/if} + +
    • + {Lang::T('Type')} + + {if $plan['prepaid'] eq 'yes'}{Lang::T('Prepaid')}{else}{Lang::T('Postpaid')}{/if} + {$plan['type']} + +
    • + +
    • + {Lang::T('Package Price')} + {if !empty($plan['price_old'])} - {Lang::moneyFormat($plan['price_old'])} + + {Lang::moneyFormat($plan['price_old'])} + {/if} {Lang::moneyFormat($plan['price'])}
    • + {if $plan['validity']} -
    • - {Lang::T('Validity Periode')} {$plan['validity']} - {$plan['validity_unit']} -
    • +
    • + {Lang::T('Validity Period')} + {$plan['validity']} {$plan['validity_unit']} +
    • {/if}
    + {else} +
      +
    • + {Lang::T('Plan Name')} + {Lang::T('Custom Balance')} +
    • + +
    • + {Lang::T('Amount')} + + {Lang::moneyFormat($amount)} + +
    • +
    + {/if} + {if $discount == '' && $plan['type'] neq 'Balance' && $custom == ''} + + +
    + +
    +
    + + + + +
    +
    +
    + + {/if} +
    {Lang::T('Summary')}
      - {if $tax} -
    • - {Lang::T('Tax')} {Lang::moneyFormat($tax)} -
    • - {if $add_cost!=0} - {foreach $bills as $k => $v} -
    • - {$k} {Lang::moneyFormat($v)} -
    • - {/foreach} -
    • - {Lang::T('Additional Cost')} {Lang::moneyFormat($add_cost)} -
    • -
    • - {Lang::T('Total')} ({Lang::T('Package Price')} - +{Lang::T('Additional Cost')}){Lang::moneyFormat($plan['price']+$add_cost+$tax)} -
    • - {else} -
    • - {Lang::T('Total')} ({Lang::T('Plan Price')} + {Lang::T('Tax')}){Lang::moneyFormat($plan['price']+$tax)} -
    • - {/if} + + {if $add_cost != 0} + {foreach $bills as $k => $v} +
    • + {$k} + {Lang::moneyFormat($v)} +
    • + {/foreach} +
    • + {Lang::T('Additional Cost')} + {Lang::moneyFormat($add_cost)} +
    • + {/if} + {if $discount} +
    • + {Lang::T('Discount Applied')} + {Lang::moneyFormat($discount)} +
    • + {/if} + + {if $amount neq '' && $custom == '1'} +
    • + {Lang::T('Total')} + + {Lang::moneyFormat($amount)} + +
    • + {elseif $plan['type'] eq 'Balance'} +
    • + {Lang::T('Total')} + + {Lang::moneyFormat($plan['price'] + $add_cost)} + +
    • {else} - {if $add_cost!=0} - {foreach $bills as $k => $v} -
    • - {$k} {Lang::moneyFormat($v)} -
    • - {/foreach} -
    • - {Lang::T('Additional Cost')} {Lang::moneyFormat($add_cost)} -
    • -
    • - {Lang::T('Total')} ({Lang::T('Package Price')} - +{Lang::T('Additional Cost')}){Lang::moneyFormat($plan['price']+$add_cost)} -
    • - {else} -
    • - {Lang::T('Total')} {Lang::moneyFormat($plan['price'])} -
    • - {/if} + {if $tax} +
    • + {Lang::T('Tax')} + {Lang::moneyFormat($tax)} +
    • + {/if} +
    • + {Lang::T('Total')} + + {Lang::moneyFormat($plan['price'] + $add_cost + $tax)} + +
    • {/if}
    -
    -
    - {Lang::T('Cancel')} -
    - - {else} -
    + +
    + + {if $custom == '1' && $amount neq ''} + + + {/if}
    -
      - - -
    • - {Lang::T('Custom Balance')} {Lang::moneyFormat($amount)} -
    • -


      -
    • - {Lang::T('Total')} {Lang::moneyFormat($amount)} -
    • -
    -
    - {Lang::T('Cancel')} + + {Lang::T('Cancel')}
    - {/if} -
+
-{include file="customer/footer.tpl"} +{include file="customer/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 1d8ad302..f4993f15 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -1240,7 +1240,7 @@ {if !in_array($_admin['user_type'],['Report'])}
  • - {Lang::T('Customer')} + {Lang::T('Customer')} @@ -1265,8 +1265,6 @@
  • {Lang::T('Active Users')}
  • {if $_c['disable_voucher'] != 'yes'} -
  • {Lang::T('Vouchers')}
  • {Lang::T('Refill Customer')}
  • {/if} @@ -1307,6 +1305,38 @@ {/if} {$_MENU_AFTER_PLANS} +
  • + + {Lang::T('Cards')} + + + + + +
  • + {$_MENU_AFTER_CRM} +
  • + + {Lang::T('CRM')} + + + + + +
  • + {$_MENU_AFTER_CARDS}
  • {if in_array($_admin['user_type'],['SuperAdmin','Admin', 'Report'])}