commit
4fe0e8d58c
@ -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),
|
||||
`user_id` int(11) INT NOT NULL DEFAULT 0,
|
||||
`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),
|
||||
`user_id` int(11) INT NOT NULL DEFAULT 0,
|
||||
`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,
|
||||
@ -213,6 +213,7 @@ CREATE TABLE `tbl_voucher` (
|
||||
`code` varchar(55) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`user` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`status` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`used_date` DATETIME NULL DEFAULT NULL,
|
||||
`generated_by` int NOT NULL DEFAULT '0' COMMENT 'id admin'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
@ -258,6 +259,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`),
|
||||
|
75
radius.php
75
radius.php
@ -42,7 +42,7 @@ try {
|
||||
$CHAPchallenge = _req('CHAPchallenge');
|
||||
$isCHAP = false;
|
||||
if (!empty($CHAPassword)) {
|
||||
$c = ORM::for_table('tbl_customers')->select('password')->select('pppoe_password')->whereRaw("BINARY username = '$username'")->find_one();
|
||||
$c = ORM::for_table('tbl_customers')->select('password')->select('pppoe_password')->whereRaw("BINARY username = '$username' AND status = 'Active'")->find_one();
|
||||
if ($c) {
|
||||
if (Password::chap_verify($c['password'], $CHAPassword, $CHAPchallenge)) {
|
||||
$password = $c['password'];
|
||||
@ -68,7 +68,7 @@ try {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$c = ORM::for_table('tbl_customers')->select('password')->select('pppoe_password')->whereRaw("BINARY `pppoe_username` = '$username'")->find_one();
|
||||
$c = ORM::for_table('tbl_customers')->select('password')->select('pppoe_password')->whereRaw("BINARY pppoe_username = '$username' AND status = 'Active'")->find_one();
|
||||
if ($c) {
|
||||
if (Password::chap_verify($c['password'], $CHAPassword, $CHAPchallenge)) {
|
||||
$password = $c['password'];
|
||||
@ -111,7 +111,7 @@ try {
|
||||
$username = Text::alphanumeric($username, "-_.,");
|
||||
$d = ORM::for_table('tbl_voucher')->whereRaw("BINARY code = '$username'")->find_one();
|
||||
} else {
|
||||
$d = ORM::for_table('tbl_customers')->whereRaw("BINARY username = '$username'")->find_one();
|
||||
$d = ORM::for_table('tbl_customers')->whereRaw("BINARY username = '$username' AND status = 'Active'")->find_one();
|
||||
if ($d['password'] != $password) {
|
||||
if ($d['pppoe_password'] != $password) {
|
||||
unset($d);
|
||||
@ -136,7 +136,7 @@ try {
|
||||
$CHAPchallenge = _req('CHAPchallenge');
|
||||
$isCHAP = false;
|
||||
if (!empty($CHAPassword)) {
|
||||
$c = ORM::for_table('tbl_customers')->select('password')->select('pppoe_password')->whereRaw("BINARY username = '$username'")->find_one();
|
||||
$c = ORM::for_table('tbl_customers')->select('password')->select('pppoe_password')->whereRaw("BINARY username = '$username' AND status = 'Active'")->find_one();
|
||||
if ($c) {
|
||||
if (Password::chap_verify($c['password'], $CHAPassword, $CHAPchallenge)) {
|
||||
$password = $c['password'];
|
||||
@ -162,14 +162,16 @@ try {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$c = ORM::for_table('tbl_customers')->select('password')->select('pppoe_password')->whereRaw("BINARY `pppoe_username` = '$username'")->find_one();
|
||||
$c = ORM::for_table('tbl_customers')->select('password')->select('username')->select('pppoe_password')->whereRaw("BINARY pppoe_username = '$username' AND status = 'Active'")->find_one();
|
||||
if ($c) {
|
||||
if (Password::chap_verify($c['password'], $CHAPassword, $CHAPchallenge)) {
|
||||
$password = $c['password'];
|
||||
$username = $c['username'];
|
||||
$isVoucher = false;
|
||||
$isCHAP = true;
|
||||
} else if (!empty($c['pppoe_password']) && Password::chap_verify($c['pppoe_password'], $CHAPassword, $CHAPchallenge)) {
|
||||
$password = $c['pppoe_password'];
|
||||
$username = $c['username'];
|
||||
$isVoucher = false;
|
||||
$isCHAP = true;
|
||||
} else {
|
||||
@ -202,9 +204,17 @@ try {
|
||||
}
|
||||
}
|
||||
$tur = ORM::for_table('tbl_user_recharges')->whereRaw("BINARY username = '$username'")->find_one();
|
||||
if (!$tur) {
|
||||
// if check if pppoe_username
|
||||
$c = ORM::for_table('tbl_customers')->select('username')->select('pppoe_password')->whereRaw("BINARY pppoe_username = '$username'")->find_one();
|
||||
if($c){
|
||||
$username = $c['username'];
|
||||
$tur = ORM::for_table('tbl_user_recharges')->whereRaw("BINARY username = '$username'")->find_one();
|
||||
}
|
||||
}
|
||||
if ($tur) {
|
||||
if (!$isVoucher && !$isCHAP) {
|
||||
$d = ORM::for_table('tbl_customers')->select('password')->select('pppoe_password')->whereRaw("BINARY username = '$username'")->find_one();
|
||||
$d = ORM::for_table('tbl_customers')->select('password')->select('pppoe_password')->whereRaw("BINARY username = '$username' AND status = 'Active'")->find_one();
|
||||
if ($d) {
|
||||
if ($d['password'] != $password) {
|
||||
if ($d['pppoe_password'] != $password) {
|
||||
@ -212,7 +222,7 @@ try {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$d = ORM::for_table('tbl_customers')->select('password')->select('pppoe_password')->whereRaw("BINARY `pppoe_username` = '$username'")->find_one();
|
||||
$d = ORM::for_table('tbl_customers')->select('password')->select('pppoe_password')->whereRaw("BINARY pppoe_username = '$username' AND status = 'Active'")->find_one();
|
||||
if ($d) {
|
||||
if ($d['password'] != $password) {
|
||||
if ($d['pppoe_password'] != $password) {
|
||||
@ -226,7 +236,7 @@ try {
|
||||
} else {
|
||||
if ($isVoucher) {
|
||||
$username = Text::alphanumeric($username, "-_.,");
|
||||
$v = ORM::for_table('tbl_voucher')->whereRaw("BINARY code = '$username'")->where('routers', 'radius')->find_one();
|
||||
$v = ORM::for_table('tbl_voucher')->whereRaw("BINARY code = '$username' AND routers = 'radius'")->find_one();
|
||||
if ($v) {
|
||||
if ($v['status'] == 0) {
|
||||
if (Package::rechargeUser(0, $v['routers'], $v['id_plan'], "Voucher", $username)) {
|
||||
@ -246,7 +256,7 @@ try {
|
||||
show_radius_result(['Reply-Message' => 'Voucher Expired...'], 401);
|
||||
}
|
||||
} else {
|
||||
show_radius_result(['Reply-Message' => 'Voucher Expired..'], 401);
|
||||
show_radius_result(['Reply-Message' => 'Invalid Voucher..'], 401);
|
||||
}
|
||||
} else {
|
||||
show_radius_result(['Reply-Message' => 'Internet Plan Expired..'], 401);
|
||||
@ -264,8 +274,7 @@ try {
|
||||
}
|
||||
header("HTTP/1.1 200 ok");
|
||||
$d = ORM::for_table('rad_acct')
|
||||
->whereRaw("BINARY username = '$username'")
|
||||
->where('acctsessionid', _post('acctsessionid'))
|
||||
->whereRaw("BINARY username = '$username' AND macaddr = '"._post('macAddr')."' AND nasid = '"._post('nasid')."'")
|
||||
->findOne();
|
||||
if (!$d) {
|
||||
$d = ORM::for_table('rad_acct')->create();
|
||||
@ -279,7 +288,7 @@ try {
|
||||
$d->acctOutputOctets = 0;
|
||||
$d->acctInputOctets = 0;
|
||||
}
|
||||
$d->acctSessionId = _post('acctSessionId');
|
||||
$d->acctsessionid = _post('acctSessionId');
|
||||
$d->username = $username;
|
||||
$d->realm = _post('realm');
|
||||
$d->nasipaddress = _post('nasip');
|
||||
@ -287,19 +296,24 @@ try {
|
||||
$d->nasportid = _post('nasPortId');
|
||||
$d->nasporttype = _post('nasPortType');
|
||||
$d->framedipaddress = _post('framedIPAddress');
|
||||
$d->acctstatustype = _post('acctStatusType');
|
||||
if(in_array(_post('acctStatusType'), ['Start', 'Stop'])){
|
||||
$d->acctstatustype = _post('acctStatusType');
|
||||
}
|
||||
$d->macaddr = _post('macAddr');
|
||||
$d->dateAdded = date('Y-m-d H:i:s');
|
||||
$d->save();
|
||||
if (_post('acctStatusType') == 'Start') {
|
||||
$tur = ORM::for_table('tbl_user_recharges')->whereRaw("BINARY username = '$username'")->where('status', 'on')->where('routers', 'radius')->find_one();
|
||||
$plan = ORM::for_table('tbl_plans')->where('id', $tur['plan_id'])->find_one();
|
||||
if ($plan['limit_type'] == "Data_Limit" || $plan['limit_type'] == "Both_Limit") {
|
||||
$totalUsage = $d['acctOutputOctets'] + $d['acctInputOctets'];
|
||||
$attrs['reply:Mikrotik-Total-Limit'] = Text::convertDataUnit($plan['data_limit'], $plan['data_unit']) - $totalUsage;
|
||||
if ($attrs['reply:Mikrotik-Total-Limit'] < 0) {
|
||||
$attrs['reply:Mikrotik-Total-Limit'] = 0;
|
||||
show_radius_result(["control:Auth-Type" => "Accept", 'Reply-Message' => 'You have exceeded your data limit.'], 401);
|
||||
// pastikan data akunting yang disimpan memang customer aktif phpnuxbill
|
||||
$tur = ORM::for_table('tbl_user_recharges')->whereRaw("BINARY username = '$username' AND `status` = 'on' AND `routers` = 'radius'")->find_one();
|
||||
if($tur){
|
||||
$d->save();
|
||||
if (_post('acctStatusType') == 'Start') {
|
||||
$plan = ORM::for_table('tbl_plans')->where('id', $tur['plan_id'])->find_one();
|
||||
if ($plan['limit_type'] == "Data_Limit" || $plan['limit_type'] == "Both_Limit") {
|
||||
$totalUsage = $d['acctOutputOctets'] + $d['acctInputOctets'];
|
||||
$attrs['reply:Mikrotik-Total-Limit'] = Text::convertDataUnit($plan['data_limit'], $plan['data_unit']) - $totalUsage;
|
||||
if ($attrs['reply:Mikrotik-Total-Limit'] < 0) {
|
||||
$attrs['reply:Mikrotik-Total-Limit'] = 0;
|
||||
show_radius_result(["control:Auth-Type" => "Accept", 'Reply-Message' => 'You have exceeded your data limit.'], 401);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -334,10 +348,12 @@ function process_radiust_rest($tur, $code)
|
||||
$bw = ORM::for_table("tbl_bandwidth")->find_one($plan['id_bw']);
|
||||
// Count User Onlines
|
||||
$USRon = ORM::for_table('rad_acct')
|
||||
->where('username', $tur['username'])
|
||||
->where("acctStatusType", 'Start')
|
||||
->count();
|
||||
if ($USRon >= $plan['shared_users'] && $plan['type'] == 'Hotspot') {
|
||||
->whereRaw("BINARY username = '".$tur['username']."' AND acctStatusType = 'Start'")
|
||||
->find_array();
|
||||
// get all the IP
|
||||
$ips = array_column($USRon, 'framedipaddress');
|
||||
// check if user reach shared_users limit but IP is not in the list active
|
||||
if (count($USRon) >= $plan['shared_users'] && $plan['type'] == 'Hotspot' && !in_array(_post('framedIPAddress'), $ips)) {
|
||||
show_radius_result(["control:Auth-Type" => "Accept", 'Reply-Message' => 'You are already logged in - access denied ('.$USRon.')'], 401);
|
||||
}
|
||||
if ($bw['rate_down_unit'] == 'Kbps') {
|
||||
@ -434,6 +450,5 @@ function show_radius_result($array, $code = 200)
|
||||
header("HTTP/1.1 204 No Content");
|
||||
die();
|
||||
}
|
||||
echo json_encode($array);
|
||||
die();
|
||||
}
|
||||
die(json_encode($array));
|
||||
}
|
@ -29,4 +29,23 @@ class App{
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public static function getVoucher(){
|
||||
return md5(microtime());
|
||||
}
|
||||
|
||||
public static function setVoucher($token, $value){
|
||||
$_SESSION[$token] = $value;
|
||||
}
|
||||
|
||||
public static function getVoucherValue($key){
|
||||
if(empty($key)){
|
||||
return "";
|
||||
}
|
||||
if(isset($_SESSION[$key])){
|
||||
return $_SESSION[$key];
|
||||
}else{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -34,9 +34,9 @@ switch ($action) {
|
||||
die();
|
||||
case 'balance':
|
||||
$balance = ORM::for_table('tbl_customers')->select("balance")->find_one($routes['2'])['balance'];
|
||||
if($routes['3']=='1'){
|
||||
if ($routes['3'] == '1') {
|
||||
echo Lang::moneyFormat($balance);
|
||||
}else{
|
||||
} else {
|
||||
echo $balance;
|
||||
}
|
||||
die();
|
||||
@ -76,16 +76,26 @@ switch ($action) {
|
||||
$server = _post('server');
|
||||
$jenis = _post('jenis');
|
||||
if (in_array($admin['user_type'], array('SuperAdmin', 'Admin'))) {
|
||||
if ($server == 'radius') {
|
||||
$d = ORM::for_table('tbl_plans')->where('is_radius', 1)->where('type', $jenis)->find_many();
|
||||
} else {
|
||||
$d = ORM::for_table('tbl_plans')->where('routers', $server)->where('type', $jenis)->find_many();
|
||||
switch ($server) {
|
||||
case 'radius':
|
||||
$d = ORM::for_table('tbl_plans')->where('is_radius', 1)->where('type', $jenis)->find_many();
|
||||
break;
|
||||
case '':
|
||||
break;
|
||||
default:
|
||||
$d = ORM::for_table('tbl_plans')->where('routers', $server)->where('type', $jenis)->find_many();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if ($server == 'radius') {
|
||||
$d = ORM::for_table('tbl_plans')->where('is_radius', 1)->where('type', $jenis)->where('enabled', '1')->find_many();
|
||||
} else {
|
||||
$d = ORM::for_table('tbl_plans')->where('routers', $server)->where('type', $jenis)->where('enabled', '1')->find_many();
|
||||
switch ($server) {
|
||||
case 'radius':
|
||||
$d = ORM::for_table('tbl_plans')->where('is_radius', 1)->where('type', $jenis)->find_many();
|
||||
break;
|
||||
case '':
|
||||
break;
|
||||
default:
|
||||
$d = ORM::for_table('tbl_plans')->where('routers', $server)->where('type', $jenis)->find_many();
|
||||
break;
|
||||
}
|
||||
}
|
||||
$ui->assign('d', $d);
|
||||
@ -97,7 +107,7 @@ switch ($action) {
|
||||
$c = ORM::for_table('tbl_customers')->where('username', $routes['2'])->find_one();
|
||||
$p = ORM::for_table('tbl_plans')->find_one($routes['3']);
|
||||
$dvc = Package::getDevice($p);
|
||||
if ($_app_stage != 'demo') {
|
||||
if ($_app_stage != 'Demo') {
|
||||
if (file_exists($dvc)) {
|
||||
require_once $dvc;
|
||||
try {
|
||||
@ -124,7 +134,7 @@ switch ($action) {
|
||||
$p = ORM::for_table('tbl_plans')->find_one($d['plan_id']);
|
||||
$dvc = Package::getDevice($p);
|
||||
$status = "";
|
||||
if ($_app_stage != 'demo') {
|
||||
if ($_app_stage != 'Demo') {
|
||||
if (file_exists($dvc)) {
|
||||
require_once $dvc;
|
||||
try {
|
||||
|
315
system/controllers/coupons.php
Normal file
315
system/controllers/coupons.php
Normal file
@ -0,0 +1,315 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
* Coupons Controller by https://t.me/focuslinkstech
|
||||
**/
|
||||
|
||||
_admin();
|
||||
$ui->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', '0');
|
||||
$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 ($max_usage < 0) {
|
||||
$error[] = Lang::T('Coupon Maximum Usage must be greater than or equal to 0');
|
||||
}
|
||||
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('<br>', $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 ($max_usage < 0) {
|
||||
$error[] = Lang::T('Coupon Maximum Usage must be greater than or equal to 0');
|
||||
}
|
||||
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('<br>', $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) || !Csrf::check($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;
|
||||
}
|
@ -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,92 @@ switch ($action) {
|
||||
if ($router['name'] != 'balance') {
|
||||
list($bills, $add_cost) = User::getBills($id_customer);
|
||||
}
|
||||
|
||||
if (!isset($_SESSION['coupon_attempts'])) {
|
||||
$_SESSION['coupon_attempts'] = 0;
|
||||
$_SESSION['last_attempt_time'] = time();
|
||||
}
|
||||
|
||||
if ($_SESSION['coupon_attempts'] >= 5) {
|
||||
$timeout = 10 * 60; // 10 minutes in seconds
|
||||
$time_diff = time() - $_SESSION['last_attempt_time'];
|
||||
|
||||
if ($time_diff >= $timeout) {
|
||||
$_SESSION['coupon_attempts'] = 0;
|
||||
$_SESSION['last_attempt_time'] = time();
|
||||
} else {
|
||||
$remaining_time = ceil(($timeout - $time_diff) / 60);
|
||||
r2($_SERVER['HTTP_REFERER'], 'e', Lang::T("Too many invalid attempts. Please try again after $remaining_time minutes."));
|
||||
}
|
||||
}
|
||||
|
||||
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']++;
|
||||
$_SESSION['last_attempt_time'] = time();
|
||||
r2($_SERVER['HTTP_REFERER'], 'e', Lang::T("Coupon not found"));
|
||||
}
|
||||
|
||||
if ($coupon['status'] != 'active') {
|
||||
$_SESSION['coupon_attempts']++;
|
||||
$_SESSION['last_attempt_time'] = time();
|
||||
r2($_SERVER['HTTP_REFERER'], 'e', Lang::T("Coupon is not active"));
|
||||
}
|
||||
|
||||
// Reset attempts after a successful coupon validation
|
||||
$_SESSION['coupon_attempts'] = 0;
|
||||
$_SESSION['last_attempt_time'] = time();
|
||||
|
||||
$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['max_usage'] > 0 && $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"));
|
||||
}
|
||||
|
||||
// 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 +532,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 +653,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 +676,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');
|
||||
|
@ -51,7 +51,7 @@ switch ($action) {
|
||||
require_once $dvc;
|
||||
if (method_exists($dvc, 'sync_customer')) {
|
||||
(new $p['device'])->sync_customer($c, $p);
|
||||
}else{
|
||||
} else {
|
||||
(new $p['device'])->add_customer($c, $p);
|
||||
}
|
||||
} else {
|
||||
@ -106,24 +106,24 @@ switch ($action) {
|
||||
$plan = ORM::for_table('tbl_plans')->find_one($planId);
|
||||
list($bills, $add_cost) = User::getBills($id_customer);
|
||||
|
||||
// Tax calculation start
|
||||
$tax_enable = isset($config['enable_tax']) ? $config['enable_tax'] : 'no';
|
||||
$tax_rate_setting = isset($config['tax_rate']) ? $config['tax_rate'] : null;
|
||||
$custom_tax_rate = isset($config['custom_tax_rate']) ? (float)$config['custom_tax_rate'] : null;
|
||||
// Tax calculation start
|
||||
$tax_enable = isset($config['enable_tax']) ? $config['enable_tax'] : 'no';
|
||||
$tax_rate_setting = isset($config['tax_rate']) ? $config['tax_rate'] : null;
|
||||
$custom_tax_rate = isset($config['custom_tax_rate']) ? (float)$config['custom_tax_rate'] : null;
|
||||
|
||||
if ($tax_rate_setting === 'custom') {
|
||||
$tax_rate = $custom_tax_rate;
|
||||
} else {
|
||||
$tax_rate = $tax_rate_setting;
|
||||
}
|
||||
if ($tax_rate_setting === 'custom') {
|
||||
$tax_rate = $custom_tax_rate;
|
||||
} else {
|
||||
$tax_rate = $tax_rate_setting;
|
||||
}
|
||||
|
||||
if ($tax_enable === 'yes') {
|
||||
$tax = Package::tax($plan['price'], $tax_rate);
|
||||
} else {
|
||||
$tax = 0;
|
||||
}
|
||||
// Tax calculation stop
|
||||
$total_cost = $plan['price'] + $add_cost + $tax;
|
||||
if ($tax_enable === 'yes') {
|
||||
$tax = Package::tax($plan['price'], $tax_rate);
|
||||
} else {
|
||||
$tax = 0;
|
||||
}
|
||||
// Tax calculation stop
|
||||
$total_cost = $plan['price'] + $add_cost + $tax;
|
||||
|
||||
if ($using == 'balance' && $config['enable_balance'] == 'yes') {
|
||||
if (!$cust) {
|
||||
@ -146,7 +146,7 @@ switch ($action) {
|
||||
if (count($usings) == 0) {
|
||||
$usings[] = Lang::T('Cash');
|
||||
}
|
||||
if ($tax_enable === 'yes') {
|
||||
if ($tax_enable === 'yes') {
|
||||
$ui->assign('tax', $tax);
|
||||
}
|
||||
$ui->assign('usings', $usings);
|
||||
@ -172,12 +172,12 @@ switch ($action) {
|
||||
$server = _post('server');
|
||||
$planId = _post('plan');
|
||||
$using = _post('using');
|
||||
$stoken = _post('stoken');
|
||||
$svoucher = _post('svoucher');
|
||||
|
||||
$plan = ORM::for_table('tbl_plans')->find_one($planId);
|
||||
$plan = ORM::for_table('tbl_plans')->find_one($planId);
|
||||
|
||||
if (!empty(App::getTokenValue($stoken))) {
|
||||
$username = App::getTokenValue($stoken);
|
||||
if (!empty(App::getVoucherValue($svoucher))) {
|
||||
$username = App::getVoucherValue($svoucher);
|
||||
$in = ORM::for_table('tbl_transactions')->where('username', $username)->order_by_desc('id')->find_one();
|
||||
Package::createInvoice($in);
|
||||
$ui->display('invoice.tpl');
|
||||
@ -195,24 +195,24 @@ switch ($action) {
|
||||
$cust = User::_info($id_customer);
|
||||
list($bills, $add_cost) = User::getBills($id_customer);
|
||||
|
||||
// Tax calculation start
|
||||
$tax_enable = isset($config['enable_tax']) ? $config['enable_tax'] : 'no';
|
||||
$tax_rate_setting = isset($config['tax_rate']) ? $config['tax_rate'] : null;
|
||||
$custom_tax_rate = isset($config['custom_tax_rate']) ? (float)$config['custom_tax_rate'] : null;
|
||||
// Tax calculation start
|
||||
$tax_enable = isset($config['enable_tax']) ? $config['enable_tax'] : 'no';
|
||||
$tax_rate_setting = isset($config['tax_rate']) ? $config['tax_rate'] : null;
|
||||
$custom_tax_rate = isset($config['custom_tax_rate']) ? (float)$config['custom_tax_rate'] : null;
|
||||
|
||||
if ($tax_rate_setting === 'custom') {
|
||||
$tax_rate = $custom_tax_rate;
|
||||
} else {
|
||||
$tax_rate = $tax_rate_setting;
|
||||
}
|
||||
if ($tax_rate_setting === 'custom') {
|
||||
$tax_rate = $custom_tax_rate;
|
||||
} else {
|
||||
$tax_rate = $tax_rate_setting;
|
||||
}
|
||||
|
||||
if ($tax_enable === 'yes') {
|
||||
$tax = Package::tax($plan['price'], $tax_rate);
|
||||
} else {
|
||||
$tax = 0;
|
||||
}
|
||||
// Tax calculation stop
|
||||
$total_cost = $plan['price'] + $add_cost + $tax;
|
||||
if ($tax_enable === 'yes') {
|
||||
$tax = Package::tax($plan['price'], $tax_rate);
|
||||
} else {
|
||||
$tax = 0;
|
||||
}
|
||||
// Tax calculation stop
|
||||
$total_cost = $plan['price'] + $add_cost + $tax;
|
||||
|
||||
if ($using == 'balance' && $config['enable_balance'] == 'yes') {
|
||||
//$plan = ORM::for_table('tbl_plans')->find_one($planId);
|
||||
@ -238,7 +238,7 @@ switch ($action) {
|
||||
}
|
||||
$in = ORM::for_table('tbl_transactions')->where('username', $cust['username'])->order_by_desc('id')->find_one();
|
||||
Package::createInvoice($in);
|
||||
App::setToken($stoken, $cust['username']);
|
||||
App::setVoucher($svoucher, $cust['username']);
|
||||
$ui->display('invoice.tpl');
|
||||
_log('[' . $admin['username'] . ']: ' . 'Recharge ' . $cust['username'] . ' [' . $in['plan_name'] . '][' . Lang::moneyFormat($in['price']) . ']', $admin['user_type'], $admin['id']);
|
||||
} else {
|
||||
@ -277,7 +277,7 @@ switch ($action) {
|
||||
$ui->assign('content', $content);
|
||||
} else {
|
||||
$id = _post('id');
|
||||
if(empty($id)) {
|
||||
if (empty($id)) {
|
||||
$id = $routes['2'];
|
||||
}
|
||||
$d = ORM::for_table('tbl_transactions')->where('id', $id)->find_one();
|
||||
@ -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,9 +422,10 @@ 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'));
|
||||
->inner_join('tbl_voucher', ['tbl_plans.id', '=', 'tbl_voucher.id_plan']);
|
||||
|
||||
if (!empty($router)) {
|
||||
$query->where('tbl_voucher.routers', $router);
|
||||
@ -551,6 +552,7 @@ switch ($action) {
|
||||
$pagebreak = _post('pagebreak');
|
||||
$limit = _post('limit');
|
||||
$vpl = _post('vpl');
|
||||
$selected_datetime = _post('selected_datetime');
|
||||
if (empty($vpl)) {
|
||||
$vpl = 3;
|
||||
}
|
||||
@ -593,6 +595,17 @@ switch ($action) {
|
||||
->left_outer_join('tbl_voucher', array('tbl_plans.id', '=', 'tbl_voucher.id_plan'))
|
||||
->where('tbl_voucher.status', '0')
|
||||
->where_gt('tbl_voucher.id', $from_id);
|
||||
} else if ($from_id > 0 && $planid == 0 && $selected_datetime != '') {
|
||||
$v = ORM::for_table('tbl_plans')
|
||||
->left_outer_join('tbl_voucher', array('tbl_plans.id', '=', 'tbl_voucher.id_plan'))
|
||||
->where('tbl_voucher.status', '0')
|
||||
->where_raw("DATE(created_at) = ?", [$selected_datetime])
|
||||
->where_gt('tbl_voucher.id', $from_id)
|
||||
->limit($limit);
|
||||
$vc = ORM::for_table('tbl_plans')
|
||||
->left_outer_join('tbl_voucher', array('tbl_plans.id', '=', 'tbl_voucher.id_plan'))
|
||||
->where('tbl_voucher.status', '0')
|
||||
->where_gt('tbl_voucher.id', $from_id);
|
||||
} else {
|
||||
$v = ORM::for_table('tbl_plans')
|
||||
->left_outer_join('tbl_voucher', array('tbl_plans.id', '=', 'tbl_voucher.id_plan'))
|
||||
@ -615,6 +628,7 @@ switch ($action) {
|
||||
$v = $v->where_in('generated_by', $sales)->find_many();
|
||||
$vc = $vc->where_in('generated_by', $sales)->count();
|
||||
}
|
||||
|
||||
$template = file_get_contents("pages/Voucher.html");
|
||||
$template = str_replace('[[company_name]]', $config['CompanyName'], $template);
|
||||
|
||||
@ -628,6 +642,19 @@ switch ($action) {
|
||||
$ui->assign('limit', $limit);
|
||||
$ui->assign('planid', $planid);
|
||||
|
||||
$createdate = ORM::for_table('tbl_voucher')
|
||||
->select_expr(
|
||||
"CASE WHEN DATE(created_at) = CURDATE() THEN 'Today' ELSE DATE(created_at) END",
|
||||
'created_datetime'
|
||||
)
|
||||
->where_not_equal('created_at', '0')
|
||||
->select_expr('COUNT(*)', 'voucher_count')
|
||||
->group_by('created_datetime')
|
||||
->order_by_desc('created_datetime')
|
||||
->find_array();
|
||||
|
||||
$ui->assign('createdate', $createdate);
|
||||
|
||||
$voucher = [];
|
||||
$n = 1;
|
||||
foreach ($v as $vs) {
|
||||
@ -643,6 +670,7 @@ switch ($action) {
|
||||
|
||||
$ui->assign('voucher', $voucher);
|
||||
$ui->assign('vc', $vc);
|
||||
$ui->assign('selected_datetime', $selected_datetime);
|
||||
|
||||
//for counting pagebreak
|
||||
$ui->assign('jml', 0);
|
||||
@ -653,6 +681,7 @@ switch ($action) {
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent', 'Sales'])) {
|
||||
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
|
||||
}
|
||||
|
||||
$type = _post('type');
|
||||
$plan = _post('plan');
|
||||
$voucher_format = _post('voucher_format');
|
||||
@ -660,18 +689,22 @@ switch ($action) {
|
||||
$server = _post('server');
|
||||
$numbervoucher = _post('numbervoucher');
|
||||
$lengthcode = _post('lengthcode');
|
||||
$printNow = _post('print_now', 'no');
|
||||
$voucherPerPage = _post('voucher_per_page', '36');
|
||||
|
||||
$msg = '';
|
||||
if ($type == '' or $plan == '' or $server == '' or $numbervoucher == '' or $lengthcode == '') {
|
||||
$msg .= Lang::T('All field is required') . '<br>';
|
||||
if (empty($type) || empty($plan) || empty($server) || empty($numbervoucher) || empty($lengthcode)) {
|
||||
$msg .= Lang::T('All fields are required') . '<br>';
|
||||
}
|
||||
if (Validator::UnsignedNumber($numbervoucher) == false) {
|
||||
if (!Validator::UnsignedNumber($numbervoucher)) {
|
||||
$msg .= 'The Number of Vouchers must be a number' . '<br>';
|
||||
}
|
||||
if (Validator::UnsignedNumber($lengthcode) == false) {
|
||||
if (!Validator::UnsignedNumber($lengthcode)) {
|
||||
$msg .= 'The Length Code must be a number' . '<br>';
|
||||
}
|
||||
|
||||
if ($msg == '') {
|
||||
// Update or create voucher prefix
|
||||
if (!empty($prefix)) {
|
||||
$d = ORM::for_table('tbl_appconfig')->where('setting', 'voucher_prefix')->find_one();
|
||||
if ($d) {
|
||||
@ -684,11 +717,14 @@ switch ($action) {
|
||||
$d->save();
|
||||
}
|
||||
}
|
||||
run_hook('create_voucher'); #HOOK
|
||||
|
||||
run_hook('create_voucher'); // HOOK
|
||||
$vouchers = [];
|
||||
$newVoucherIds = [];
|
||||
|
||||
if ($voucher_format == 'numbers') {
|
||||
if (strlen($lengthcode) < 6) {
|
||||
$msg .= 'The Length Code must be a more than 6 for numbers' . '<br>';
|
||||
if ($lengthcode < 6) {
|
||||
$msg .= 'The Length Code must be more than 6 for numbers' . '<br>';
|
||||
}
|
||||
$vouchers = generateUniqueNumericVouchers($numbervoucher, $lengthcode);
|
||||
} else {
|
||||
@ -708,12 +744,47 @@ switch ($action) {
|
||||
$d->type = $type;
|
||||
$d->routers = $server;
|
||||
$d->id_plan = $plan;
|
||||
$d->code = $prefix . $code;
|
||||
$d->code = "$prefix$code";
|
||||
$d->user = '0';
|
||||
$d->status = '0';
|
||||
$d->generated_by = $admin['id'];
|
||||
$d->save();
|
||||
$newVoucherIds[] = $d->id();
|
||||
}
|
||||
|
||||
if ($printNow == 'yes' && count($newVoucherIds) > 0) {
|
||||
$template = file_get_contents("pages/Voucher.html");
|
||||
$template = str_replace('[[company_name]]', $config['CompanyName'], $template);
|
||||
|
||||
$vouchersToPrint = ORM::for_table('tbl_voucher')
|
||||
->left_outer_join('tbl_plans', ['tbl_plans.id', '=', 'tbl_voucher.id_plan'])
|
||||
->where_in('tbl_voucher.id', $newVoucherIds)
|
||||
->find_many();
|
||||
|
||||
$voucherHtmls = [];
|
||||
$n = 1;
|
||||
|
||||
foreach ($vouchersToPrint as $vs) {
|
||||
$temp = $template;
|
||||
$temp = str_replace('[[qrcode]]', '<img src="qrcode/?data=' . $vs['code'] . '">', $temp);
|
||||
$temp = str_replace('[[price]]', Lang::moneyFormat($vs['price']), $temp);
|
||||
$temp = str_replace('[[voucher_code]]', $vs['code'], $temp);
|
||||
$temp = str_replace('[[plan]]', $vs['name_plan'], $temp);
|
||||
$temp = str_replace('[[counter]]', $n, $temp);
|
||||
$voucherHtmls[] = $temp;
|
||||
$n++;
|
||||
}
|
||||
|
||||
$vc = count($voucherHtmls);
|
||||
$ui->assign('voucher', $voucherHtmls);
|
||||
$ui->assign('vc', $vc);
|
||||
$ui->assign('jml', 0);
|
||||
$ui->assign('from_id', 0);
|
||||
$ui->assign('vpl', '3');
|
||||
$ui->assign('pagebreak', $voucherPerPage);
|
||||
$ui->display('print-voucher.tpl');
|
||||
}
|
||||
|
||||
if ($numbervoucher == 1) {
|
||||
r2(U . 'plan/voucher-view/' . $d->id(), 's', Lang::T('Create Vouchers Successfully'));
|
||||
}
|
||||
@ -724,6 +795,43 @@ switch ($action) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'voucher-delete-many':
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$admin = Admin::_info();
|
||||
|
||||
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
echo json_encode(['status' => 'error', 'message' => Lang::T('You do not have permission to access this page')]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$voucherIds = json_decode($_POST['voucherIds'], true);
|
||||
|
||||
if (is_array($voucherIds) && !empty($voucherIds)) {
|
||||
$voucherIds = array_map('intval', $voucherIds);
|
||||
|
||||
try {
|
||||
ORM::for_table('tbl_voucher')
|
||||
->where_in('id', $voucherIds)
|
||||
->delete_many();
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(['status' => 'error', 'message' => Lang::T('Failed to delete vouchers.')]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Return success response
|
||||
echo json_encode(['status' => 'success', 'message' => Lang::T("Vouchers Deleted Successfully.")]);
|
||||
exit;
|
||||
} else {
|
||||
echo json_encode(['status' => 'error', 'message' => Lang::T("Invalid or missing voucher IDs.")]);
|
||||
exit;
|
||||
}
|
||||
} else {
|
||||
echo json_encode(['status' => 'error', 'message' => Lang::T("Invalid request method.")]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'voucher-view':
|
||||
$id = $routes[2];
|
||||
if (in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
|
||||
@ -849,17 +957,17 @@ switch ($action) {
|
||||
$amount = _post('amount');
|
||||
$plan = _post('id_plan');
|
||||
$note = _post('note');
|
||||
$stoken = _req('stoken');
|
||||
$svoucher = _req('svoucher');
|
||||
$c = ORM::for_table('tbl_customers')->find_one($user);
|
||||
if (App::getTokenValue($stoken)) {
|
||||
$in = ORM::for_table('tbl_transactions')->find_one(App::getTokenValue($stoken));
|
||||
if (App::getVoucherValue($svoucher)) {
|
||||
$in = ORM::for_table('tbl_transactions')->find_one(App::getVoucherValue($svoucher));
|
||||
Package::createInvoice($in);
|
||||
$ui->display('invoice.tpl');
|
||||
die();
|
||||
}
|
||||
|
||||
run_hook('deposit_customer'); #HOOK
|
||||
if (!empty($user) && strlen($amount)>0 && $amount != 0) {
|
||||
if (!empty($user) && strlen($amount) > 0 && $amount != 0) {
|
||||
$plan = [];
|
||||
$plan['name_plan'] = Lang::T('Balance');
|
||||
$plan['price'] = $amount;
|
||||
@ -867,21 +975,21 @@ switch ($action) {
|
||||
if ($trxId > 0) {
|
||||
$in = ORM::for_table('tbl_transactions')->find_one($trxId);
|
||||
Package::createInvoice($in);
|
||||
if (!empty($stoken)) {
|
||||
App::setToken($stoken, $trxId);
|
||||
if (!empty($svoucher)) {
|
||||
App::setVoucher($svoucher, $trxId);
|
||||
}
|
||||
$ui->display('invoice.tpl');
|
||||
} else {
|
||||
r2(U . 'plan/refill', 'e', "Failed to refill account");
|
||||
}
|
||||
}else if (!empty($user) && !empty($plan)) {
|
||||
} else if (!empty($user) && !empty($plan)) {
|
||||
$p = ORM::for_table('tbl_plans')->find_one($plan);
|
||||
$trxId = Package::rechargeBalance($c, $p, "Deposit", $admin['fullname'], $note);
|
||||
if ($trxId > 0) {
|
||||
$in = ORM::for_table('tbl_transactions')->find_one($trxId);
|
||||
Package::createInvoice($in);
|
||||
if (!empty($stoken)) {
|
||||
App::setToken($stoken, $trxId);
|
||||
if (!empty($svoucher)) {
|
||||
App::setVoucher($svoucher, $trxId);
|
||||
}
|
||||
$ui->display('invoice.tpl');
|
||||
} else {
|
||||
@ -894,8 +1002,8 @@ switch ($action) {
|
||||
case 'extend':
|
||||
$id = $routes[2];
|
||||
$days = $routes[3];
|
||||
$stoken = $_GET['stoken'];
|
||||
if (App::getTokenValue($stoken)) {
|
||||
$svoucher = $_GET['svoucher'];
|
||||
if (App::getVoucherValue($svoucher)) {
|
||||
r2(U . 'plan', 's', "Extend already done");
|
||||
}
|
||||
$tur = ORM::for_table('tbl_user_recharges')->find_one($id);
|
||||
@ -908,7 +1016,7 @@ switch ($action) {
|
||||
//expired
|
||||
$expiration = date('Y-m-d', strtotime(" +$days day"));
|
||||
}
|
||||
App::setToken($stoken, $id);
|
||||
App::setVoucher($svoucher, $id);
|
||||
$c = ORM::for_table('tbl_customers')->findOne($tur['customer_id']);
|
||||
if ($c) {
|
||||
$p = ORM::for_table('tbl_plans')->find_one($tur['plan_id']);
|
||||
|
@ -103,6 +103,23 @@ foreach ($d as $ds) {
|
||||
}
|
||||
}
|
||||
|
||||
//Cek interim-update radiusrest
|
||||
if ($config['frrest_interim_update'] != 0) {
|
||||
|
||||
$r_a = ORM::for_table('rad_acct')
|
||||
->whereRaw("BINARY acctstatustype = 'Start' OR acctstatustype = 'Interim-Update'")
|
||||
->where_lte('dateAdded', date("Y-m-d H:i:s"))->find_many();
|
||||
|
||||
foreach ($r_a as $ra) {
|
||||
$interval = $_c['frrest_interim_update']*60;
|
||||
$timeUpdate = strtotime($ra['dateAdded'])+$interval;
|
||||
$timeNow = strtotime(date("Y-m-d H:i:s"));
|
||||
if ($timeNow >= $timeUpdate) {
|
||||
$ra->acctstatustype = 'Stop';
|
||||
$ra->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($config['router_check']) {
|
||||
echo "Checking router status...\n";
|
||||
@ -208,4 +225,4 @@ $timestampFile = "$UPLOAD_PATH/cron_last_run.txt";
|
||||
file_put_contents($timestampFile, time());
|
||||
|
||||
|
||||
run_hook('cronjob_end'); #HOOK
|
||||
run_hook('cronjob_end'); #HOOK
|
||||
|
@ -923,5 +923,22 @@
|
||||
"Notify_Admin_upon_self_registration": "Notify Admin upon self registration",
|
||||
"Registration_Mandatory_Fields": "Registration Mandatory Fields",
|
||||
"Mikrotik_SMS_Command": "Mikrotik SMS Command",
|
||||
"Mandatory_Fields": "Mandatory Fields"
|
||||
"Mandatory_Fields": "Mandatory Fields",
|
||||
"Usernames": "Usernames",
|
||||
"Yours_Balance": "Yours Balance",
|
||||
"Friend_Usernames": "Friend Usernames",
|
||||
"Send_yours_balance___": "Send yours balance ? ",
|
||||
"Cards": "Cards",
|
||||
"CRM": "CRM",
|
||||
"Coupons": "Coupons",
|
||||
"Voucher_Cards": "Voucher Cards",
|
||||
"Create_Date": "Create Date",
|
||||
"Delete_Selected": "Delete Selected",
|
||||
"Print_Now": "Print Now",
|
||||
"Vouchers_Per_Page": "Vouchers Per Page",
|
||||
"Save_as_template": "Save as template",
|
||||
"Template_Name": "Template Name",
|
||||
"Voucher_Code": "Voucher Code",
|
||||
"Voucher_Package": "Voucher Package",
|
||||
"Counter": "Counter"
|
||||
}
|
@ -381,8 +381,8 @@
|
||||
"SuperAdmin": "Super Admin",
|
||||
"Lists": "Daftar",
|
||||
"Vouchers": "Voucher",
|
||||
"Refill_Customer": "Isi Ulang Pelanggan",
|
||||
"Recharge_Customer": "Isi Ulang Pelanggan",
|
||||
"Refill_Customer": "Isi Ulang Voucher",
|
||||
"Recharge_Customer": "Isi Ulang Paket",
|
||||
"Plans": "Paket",
|
||||
"PPPOE": "PPPOE",
|
||||
"Bandwidth": "Bandwidth",
|
||||
@ -822,7 +822,6 @@
|
||||
"Methods": "Metode",
|
||||
"Hap_Lite": "Hap Lite",
|
||||
"balance": "saldo",
|
||||
"Balance": "Saldo",
|
||||
"radius": "radius",
|
||||
"Max_30_days": "Maksimal 30 hari",
|
||||
"Information": "Informasi",
|
||||
@ -848,9 +847,67 @@
|
||||
"Forgot_Password": "Lupa Kata Sandi",
|
||||
"Validity_Periode": "Periode Validitas",
|
||||
"Transaction_History_List": "Daftar Riwayat Transaksi",
|
||||
"Plan": "Paket",
|
||||
"plan": "paket",
|
||||
"Plans" "Paket",
|
||||
"Package": "Paket",
|
||||
"package": "paket"
|
||||
}
|
||||
"package": "paket",
|
||||
"Cards": "Kartu",
|
||||
"CRM": "CRM",
|
||||
"Coupons": "Kupon",
|
||||
"Custom_Fields": "Bidang Kustom",
|
||||
"Search_Coupons": "Cari Kupon",
|
||||
"Add_Coupon": "Tambahkan Kupon",
|
||||
"Value": "Nilai",
|
||||
"Max_Usage": "Penggunaan Maksimal",
|
||||
"Usage_Count": "Jumlah Pemakaian",
|
||||
"Min_Order": "Pesanan Min",
|
||||
"Max_Discount": "Diskon Maksimal",
|
||||
"Updated_Date": "Tanggal Diperbarui",
|
||||
"Action": "Tindakan",
|
||||
"No_coupons_found_": "Tidak ada kupon yang ditemukan.",
|
||||
"Delete_Selected": "Hapus yang Dipilih",
|
||||
"Coupon_Code": "Kode Kupon",
|
||||
"Random": "Acak",
|
||||
"Unique_code_for_the_coupon": "Kode unik untuk kupon",
|
||||
"Fixed_Discount": "Diskon Tetap",
|
||||
"Percent_Discount": "Diskon Persen",
|
||||
"Discount_Value": "Nilai Diskon",
|
||||
"Value_of_the_discount__amount_or_percentage_": "Nilai diskon (jumlah atau persentase)",
|
||||
"Brief_explanation_of_the_coupon": "Penjelasan singkat tentang kupon",
|
||||
"Maximum_number_of_times_this_coupon_can_be_used_0_is_Unlimited": "Jumlah maksimum penggunaan kupon ini 0 adalah Tidak Terbatas",
|
||||
"Minimum_Order_Amount": "Jumlah Pesanan Minimum",
|
||||
"Minimum_cart_total_required_to_use_this_coupon": "Total keranjang minimum yang diperlukan untuk menggunakan kupon ini",
|
||||
"Max_Discount_Amount": "Jumlah Diskon Maksimum",
|
||||
"Maximum_discount_amount_applicable__for_percent_type_": "Jumlah diskon maksimum yang berlaku (untuk jenis persen)",
|
||||
"Value_of_the_discount__percentage__max_100_": "Nilai diskon (persentase, maks 100)",
|
||||
"Value_of_the_discount__amount_": "Nilai diskon (jumlah)",
|
||||
"Voucher_Cards": "Kartu Voucher",
|
||||
"Create_Date": "Tanggal Pembuatan",
|
||||
"Postpaid_Recharge_for_the_first_time_use": "Isi Ulang Pascabayar untuk penggunaan pertama kali",
|
||||
"Select_Balance_Package_or_Custom_Amount": "Pilih Paket Saldo atau Jumlah Kustom",
|
||||
"Or_custom_balance_amount_below": "Atau jumlah saldo khusus di bawah ini",
|
||||
"Balance_Amount": "Jumlah Saldo",
|
||||
"Input_custom_balance__will_ignore_plan_above": "Masukkan saldo khusus, akan mengabaikan rencana di atas",
|
||||
"Note": "Catatan",
|
||||
"Customer_Login_Page_Settings": "Pengaturan Halaman Login Pelanggan",
|
||||
"Choose_Template": "Pilih Template",
|
||||
"Select_your_login_template_type": "Pilih jenis template login Anda",
|
||||
"Select_Login_Page": "Pilih Halaman Login",
|
||||
"Select_your_preferred_login_template": "Pilih template login pilihan Anda",
|
||||
"Page_Heading___Company_Name": "Judul Halaman \/ Nama Perusahaan",
|
||||
"This_Name_will_be_shown_on_the_login_wallpaper": "Nama ini akan ditampilkan pada wallpaper login",
|
||||
"Page_Description": "Deskripsi Halaman",
|
||||
"This_will_also_display_on_wallpaper__You_can_use_html_tag": "Ini juga akan ditampilkan di wallpaper, Anda dapat menggunakan tag html",
|
||||
"Favicon": "Ikon favicon",
|
||||
"Best_size_30_x_30___uploaded_image_will_be_autosize": "Ukuran terbaik 30 x 30 | gambar yang diunggah akan berukuran otomatis",
|
||||
"Login_Page_Logo": "Logo Halaman Login",
|
||||
"Best_size_300_x_60___uploaded_image_will_be_autosize": "Ukuran terbaik 300 x 60 | gambar yang diunggah akan berukuran otomatis",
|
||||
"Login_Page_Wallpaper": "Wallpaper Halaman Login",
|
||||
"Best_size_1920_x_1080___uploaded_image_will_be_autosize": "Ukuran terbaik 1920 x 1080 | gambar yang diunggah akan berukuran otomatis",
|
||||
"Photo_Required": "Foto Diperlukan",
|
||||
"Customer_Registration_need_to_upload_their_photo": "Registrasi Pelanggan perlu mengunggah foto mereka",
|
||||
"Notify_Admin": "Beritahu Admin",
|
||||
"Notify_Admin_upon_self_registration": "Beritahu Admin saat registrasi mandiri",
|
||||
"Mandatory_Fields": "Bidang yang wajib diisi",
|
||||
"Single_Admin_Session": "Sesi Admin Tunggal",
|
||||
"Mikrotik_SMS_Command": "Perintah SMS Mikrotik",
|
||||
"Expired_Cronjob_Every_5_Minutes__Recommended_": "Cronjob Kedaluwarsa Setiap 5 Menit [Direkomendasikan]"
|
||||
}
|
@ -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,21 @@
|
||||
"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" : [
|
||||
"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.5": [
|
||||
"ALTER TABLE `tbl_transactions` ADD `user_id` INT(11) INT NOT NULL DEFAULT 0, AFTER `username`;",
|
||||
"ALTER TABLE `tbl_payment_gateway` ADD `user_id` INT(11) INT NOT NULL DEFAULT 0, 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);"
|
||||
],
|
||||
"2024.12.20": [
|
||||
"ALTER TABLE `tbl_voucher` ADD `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `status`;"
|
||||
]
|
||||
}
|
@ -134,6 +134,16 @@
|
||||
phpnuxbill-login-hotspot</a></small>
|
||||
</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-3 control-label">{Lang::T('Radius Rest Interim-Update')}</label>
|
||||
<div class="col-md-5">
|
||||
<input type="number" class="form-control" id="frrest_interim_update" name="frrest_interim_update"
|
||||
value="{if $_c['frrest_interim_update']}{$_c['frrest_interim_update']}{else}0{/if}">
|
||||
</div>
|
||||
<p class="help-block col-md-4"><small>
|
||||
{Lang::T('in minutes, leave 0 to disable this feature.')}</small>
|
||||
</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-3 control-label">{Lang::T('Check if Customer Online')}</label>
|
||||
<div class="col-md-5">
|
||||
@ -197,4 +207,4 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{include file="sections/footer.tpl"}
|
||||
{include file="sections/footer.tpl"}
|
||||
|
153
ui/ui/coupons-add.tpl
Normal file
153
ui/ui/coupons-add.tpl
Normal file
@ -0,0 +1,153 @@
|
||||
{include file="sections/header.tpl"}
|
||||
<!-- coupon-add -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-12">
|
||||
<div class="panel panel-primary panel-hovered panel-stacked mb30">
|
||||
<div class="panel-heading">{Lang::T('Add Coupon')}</div>
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" method="post" role="form" action="{$_url}coupons/add-post">
|
||||
<input type="hidden" name="csrf_token" value="{$csrf_token}">
|
||||
|
||||
<!-- Coupon Code -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Coupon Code')}</label>
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" name="code" id="code" maxlength="50" required>
|
||||
<span class="input-group-btn">
|
||||
<button type="button" class="btn btn-info btn-flat" onclick="generateRandomCode()">{Lang::T('Random')}</button>
|
||||
</span>
|
||||
</div>
|
||||
<p class="help-block"><small>{Lang::T('Unique code for the coupon')}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Type -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Type')}</label>
|
||||
<div class="col-md-6">
|
||||
<select class="form-control" name="type" id="type" required onchange="updateValueInput()">
|
||||
<option value="fixed">{Lang::T('Fixed Discount')}</option>
|
||||
<option value="percent">{Lang::T('Percent Discount')}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Value -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Discount Value')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="number" class="form-control" name="value" id="value" step="0.01" placeholder="Enter amount" required>
|
||||
<p class="help-block"><small id="value-help">{Lang::T('Value of the discount (amount or percentage)')}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Description -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Description')}</label>
|
||||
<div class="col-md-6">
|
||||
<textarea class="form-control" name="description" required></textarea>
|
||||
<p class="help-block"><small>{Lang::T('Brief explanation of the coupon')}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Max Usage -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Max Usage')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="number" class="form-control" name="max_usage" value="0" required placeholder="0 is Unlimited">
|
||||
<p class="help-block"><small>{Lang::T('Maximum number of times this coupon can be used 0 is Unlimited')}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Minimum Order Amount -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Minimum Order Amount')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="number" class="form-control" name="min_order_amount" step="0.01" required>
|
||||
<p class="help-block"><small>{Lang::T('Minimum cart total required to use this coupon')}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Max Discount Amount -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Max Discount Amount')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="number" class="form-control" name="max_discount_amount" step="0.01">
|
||||
<p class="help-block"><small>{Lang::T('Maximum discount amount applicable (for percent type)')}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Status -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Status')}</label>
|
||||
<div class="col-md-6">
|
||||
<label class="radio-inline">
|
||||
<input type="radio" name="status" value="active" checked> {Lang::T('Active')}
|
||||
</label>
|
||||
<label class="radio-inline">
|
||||
<input type="radio" name="status" value="inactive"> {Lang::T('Inactive')}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Start Date -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Start Date')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="date" class="form-control" name="start_date" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Expiry Date -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('End Date')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="date" class="form-control" name="end_date" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<div class="form-group">
|
||||
<div class="col-lg-offset-2 col-lg-10">
|
||||
<button class="btn btn-primary" type="submit">
|
||||
{Lang::T('Save')}
|
||||
</button>
|
||||
Or <a href="{$_url}coupons/list">{Lang::T('Cancel')}</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function updateValueInput() {
|
||||
const type = document.getElementById('type').value;
|
||||
const valueInput = document.getElementById('value');
|
||||
const helpText = document.getElementById('value-help');
|
||||
|
||||
if (type === 'percent') {
|
||||
valueInput.setAttribute('max', '100');
|
||||
valueInput.setAttribute('placeholder', 'Enter percentage');
|
||||
helpText.textContent = '{Lang::T('Value of the discount (percentage, max 100)')}';
|
||||
} else {
|
||||
valueInput.removeAttribute('max');
|
||||
valueInput.setAttribute('placeholder', 'Enter amount');
|
||||
helpText.textContent = '{Lang::T('Value of the discount (amount)')}';
|
||||
}
|
||||
}
|
||||
|
||||
function generateRandomCode() {
|
||||
const codeInput = document.getElementById('code');
|
||||
const randomCode = Math.random().toString(36).substring(2, 10).toUpperCase();
|
||||
codeInput.value = randomCode;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
{include file="sections/footer.tpl"}
|
149
ui/ui/coupons-edit.tpl
Normal file
149
ui/ui/coupons-edit.tpl
Normal file
@ -0,0 +1,149 @@
|
||||
{include file="sections/header.tpl"}
|
||||
<!-- Coupon-edit -->
|
||||
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-12">
|
||||
<div class="panel panel-primary panel-hovered panel-stacked mb30">
|
||||
<div class="panel-heading">{Lang::T('Edit Coupon')}</div>
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" method="post" role="form" action="{$_url}coupons/edit-post">
|
||||
<input type="hidden" name="csrf_token" value="{$csrf_token}">
|
||||
|
||||
<!-- Coupon Code -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Coupon Code')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="text" class="form-control" name="code" id="code" maxlength="50" readonly
|
||||
value="{$coupon['code']}">
|
||||
<p class="help-block"><small>{Lang::T('Unique code for the coupon')}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Type -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Type')}</label>
|
||||
<div class="col-md-6">
|
||||
<select class="form-control" name="type" id="type" required onchange="updateValueInput()">
|
||||
<option value="fixed" {if $coupon['type']== 'fixed'} selected {/if}>{Lang::T('Fixed Discount')}</option>
|
||||
<option value="percent" {if $coupon['type']== 'percent'} selected {/if}>{Lang::T('Percent Discount')}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Value -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Discount Value')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="number" class="form-control" name="value" id="value" step="0.01"
|
||||
placeholder="Enter amount" required value="{$coupon['value']}">
|
||||
<p class="help-block"><small id="value-help">{Lang::T('Value of the discount (amount or
|
||||
percentage)')}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Description -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Description')}</label>
|
||||
<div class="col-md-6">
|
||||
<textarea class="form-control" name="description" required>{$coupon['description']}</textarea>
|
||||
<p class="help-block"><small>{Lang::T('Brief explanation of the coupon')}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Max Usage -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Max Usage')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="number" class="form-control" name="max_usage" required value="{$coupon['max_usage']}">
|
||||
<p class="help-block"><small>{Lang::T('Maximum number of times this coupon can be used 0 is Unlimited')}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Minimum Order Amount -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Minimum Order Amount')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="number" class="form-control" name="min_order_amount" step="0.01" required value="{$coupon['min_order_amount']}">
|
||||
<p class="help-block"><small>{Lang::T('Minimum cart total required to use this
|
||||
coupon')}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Max Discount Amount -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Max Discount Amount')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="number" class="form-control" name="max_discount_amount" step="0.01" value="{$coupon['max_discount_amount']}">
|
||||
<p class="help-block"><small>{Lang::T('Maximum discount amount applicable (for percent
|
||||
type)')}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Status -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Status')}</label>
|
||||
<div class="col-md-6">
|
||||
<label class="radio-inline">
|
||||
<input type="radio" name="status" value="active" {if $coupon['status']== 'active'} checked {/if}> {Lang::T('Active')}
|
||||
</label>
|
||||
<label class="radio-inline">
|
||||
<input type="radio" name="status" value="inactive" {if $coupon['status']== 'inactive'} checked {/if}> {Lang::T('Inactive')}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Start Date -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Start Date')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="date" class="form-control" name="start_date" required value="{$coupon['start_date']}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Expiry Date -->
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('End Date')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="date" class="form-control" name="end_date" required value="{$coupon['end_date']}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<div class="form-group">
|
||||
<div class="col-lg-offset-2 col-lg-10">
|
||||
<button class="btn btn-primary" type="submit">
|
||||
{Lang::T('Save')}
|
||||
</button>
|
||||
Or <a href="{$_url}coupons/list">{Lang::T('Cancel')}</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function updateValueInput() {
|
||||
const type = document.getElementById('type').value;
|
||||
const valueInput = document.getElementById('value');
|
||||
const helpText = document.getElementById('value-help');
|
||||
|
||||
if (type === 'percent') {
|
||||
valueInput.setAttribute('max', '100');
|
||||
valueInput.setAttribute('placeholder', 'Enter percentage');
|
||||
helpText.textContent = '{Lang::T('Value of the discount(percentage, max 100)')}';
|
||||
} else {
|
||||
valueInput.removeAttribute('max');
|
||||
valueInput.setAttribute('placeholder', 'Enter amount');
|
||||
helpText.textContent = '{Lang::T('Value of the discount(amount)')}';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
{include file="sections/footer.tpl"}
|
363
ui/ui/coupons.tpl
Normal file
363
ui/ui/coupons.tpl
Normal file
@ -0,0 +1,363 @@
|
||||
{include file="sections/header.tpl"}
|
||||
<style>
|
||||
/* Styles for overall layout and responsiveness */
|
||||
body {
|
||||
background-color: #f8f9fa;
|
||||
font-family: 'Arial', sans-serif;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin-top: 20px;
|
||||
background-color: #d8dfe5;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
padding: 20px;
|
||||
max-width: 98%;
|
||||
overflow-x: auto;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Styles for table and pagination */
|
||||
.table {
|
||||
width: 100%;
|
||||
margin-bottom: 1rem;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.table th {
|
||||
vertical-align: middle;
|
||||
border-color: #dee2e6;
|
||||
background-color: #343a40;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.table td {
|
||||
vertical-align: middle;
|
||||
border-color: #dee2e6;
|
||||
}
|
||||
|
||||
.table-striped tbody tr:nth-of-type(odd) {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.table-hover tbody tr:hover {
|
||||
background-color: rgba(0, 0, 0, 0.075);
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
transition: background-color 0.3s, color 0.3s;
|
||||
}
|
||||
|
||||
.pagination .page-item .page-link {
|
||||
color: #007bff;
|
||||
background-color: #fff;
|
||||
border: 1px solid #dee2e6;
|
||||
margin: 0 2px;
|
||||
padding: 6px 12px;
|
||||
transition: background-color 0.3s, color 0.3s;
|
||||
}
|
||||
|
||||
.pagination .page-item .page-link:hover {
|
||||
background-color: #e9ecef;
|
||||
color: #0056b3;
|
||||
}
|
||||
|
||||
.pagination .page-item.active .page-link {
|
||||
z-index: 1;
|
||||
color: #fff;
|
||||
background-color: #007bff;
|
||||
border-color: #007bff;
|
||||
}
|
||||
|
||||
.dataTables_wrapper .dataTables_paginate .paginate_button {
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
margin-right: 5px;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #fff;
|
||||
color: #333;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.hidden-field {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.btn-group-flex {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.btn-group-flex .btn {
|
||||
flex: 1 1 auto;
|
||||
/* Allow buttons to shrink/grow as needed */
|
||||
max-width: 150px;
|
||||
/* Optional: Limit button width */
|
||||
}
|
||||
</style>
|
||||
|
||||
<form id="" method="post" action="">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">
|
||||
<a href=""><span class="fa fa-refresh"></span></a>
|
||||
</div>
|
||||
<input type="text" name="search" class="form-control" value="{$search}" placeholder="{Lang::T('Search')}...">
|
||||
<div class="input-group-btn">
|
||||
<button class="btn btn-success" type="submit">{Lang::T('Search Coupons')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<br>
|
||||
<!-- coupon -->
|
||||
<div class="row" style="padding: 5px">
|
||||
<div class="col-lg-3 col-lg-offset-9">
|
||||
<div class="btn-group btn-group-justified" role="group">
|
||||
<div class="btn-group" role="group">
|
||||
<a href="{$_url}coupons/add" class="btn btn-primary">
|
||||
{Lang::T('Add Coupon')}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-hovered mb20 panel-primary">
|
||||
<div class="panel-heading">
|
||||
|
||||
</div>
|
||||
<div class="container">
|
||||
<table id="datatable" class="table table-bordered table-striped table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><input type="checkbox" id="select-all"></th>
|
||||
<th>{Lang::T('Code')}</th>
|
||||
<th>{Lang::T('Type')}</th>
|
||||
<th>{Lang::T('Value')}</th>
|
||||
<th>{Lang::T('Description')}</th>
|
||||
<th>{Lang::T('Max Usage')}</th>
|
||||
<th>{Lang::T('Usage Count')}</th>
|
||||
<th>{Lang::T('Status')}</th>
|
||||
<th>{Lang::T('Min Order')}</th>
|
||||
<th>{Lang::T('Max Discount')}</th>
|
||||
<th>{Lang::T('Start Date')}</th>
|
||||
<th>{Lang::T('End Date')}</th>
|
||||
<th>{Lang::T('Created Date')}</th>
|
||||
<th>{Lang::T('Updated Date')}</th>
|
||||
<th>{Lang::T('Action')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{if $coupons}
|
||||
{foreach $coupons as $coupon}
|
||||
<tr>
|
||||
<td><input type="checkbox" name="coupon_ids[]" value="{$coupon['id']}"></td>
|
||||
<td style="background-color: black; color: black;"
|
||||
onmouseleave="this.style.backgroundColor = 'black';"
|
||||
onmouseenter="this.style.backgroundColor = 'white';">
|
||||
{$coupon['code']}
|
||||
</td>
|
||||
<td>{$coupon['type']}</td>
|
||||
<td>{$coupon['value']}</td>
|
||||
<td>{$coupon['description']}</td>
|
||||
<td>{$coupon['max_usage']}</td>
|
||||
<td>{$coupon['usage_count']}</td>
|
||||
<td>
|
||||
{if $coupon['status'] == 'inactive'}
|
||||
<span class="label label-danger">{Lang::T('Inactive')}</span>
|
||||
{elseif $coupon['status'] == 'active'}
|
||||
<span class="label label-success">{Lang::T('Active')}</span>
|
||||
{else}
|
||||
<span class="label label-primary">{Lang::T('Unknown')}</span>
|
||||
{/if}
|
||||
</td>
|
||||
<td>{$coupon['min_order_amount']}</td>
|
||||
<td>{$coupon['max_discount_amount']}</td>
|
||||
<td>{$coupon['start_date']}</td>
|
||||
<td>{$coupon['end_date']}</td>
|
||||
<td>{$coupon['created_at']}</td>
|
||||
<td>{$coupon['updated_at']}</td>
|
||||
<!-- <td>{if $coupon['admin_name']}
|
||||
<a href="{$_url}settings/users-view/{$coupon['generated_by']}">{$coupon['admin_name']}</a>
|
||||
{else} -
|
||||
{/if}
|
||||
</td> -->
|
||||
<td colspan="10" style="text-align: center;">
|
||||
<div style="display: flex; justify-content: center; gap: 10px; flex-wrap: wrap;">
|
||||
<a href="{$_url}coupons/edit/{$coupon['id']}&token={$csrf_token}" id="{$coupon['id']}"
|
||||
class="btn btn-success btn-xs">{Lang::T('Edit')}</a>
|
||||
{if $coupon['status'] neq 'inactive'}
|
||||
<a href="javascript:void(0);"
|
||||
onclick="confirmAction('{$_url}coupons/status/&coupon_id={$coupon['id']}&status=inactive&csrf_token={$csrf_token}', '{Lang::T('Block')}')"
|
||||
id="{$coupon['id']}" class="btn btn-danger btn-xs">
|
||||
{Lang::T('Block')}
|
||||
</a>
|
||||
{else}
|
||||
<a href="javascript:void(0);"
|
||||
onclick="confirmAction('{$_url}coupons/status/&coupon_id={$coupon['id']}&status=active&csrf_token={$csrf_token}', '{Lang::T('Unblock')}')"
|
||||
id="{$coupon['id']}" class="btn btn-warning btn-xs">
|
||||
{Lang::T('Unblock')}
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
{else}
|
||||
<tr>
|
||||
<td colspan="11" style="text-align: center;">
|
||||
{Lang::T('No coupons found.')}
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
</tbody>
|
||||
</table>
|
||||
{include file="pagination.tpl"}
|
||||
<div class="row" style="padding: 5px">
|
||||
<div class="col-lg-3 col-lg-offset-9">
|
||||
<div class="btn-group btn-group-justified" role="group">
|
||||
<div class="btn-group" role="group">
|
||||
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
|
||||
<button id="deleteSelectedCoupons" class="btn btn-danger">{Lang::T('Delete
|
||||
Selected')}</button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<script>
|
||||
function deleteCoupons(couponIds) {
|
||||
if (couponIds.length > 0) {
|
||||
Swal.fire({
|
||||
title: 'Are you sure?',
|
||||
text: 'You won\'t be able to revert this!',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Yes, delete it!',
|
||||
cancelButtonText: 'Cancel'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', '{$_url}coupons/delete', true);
|
||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
||||
xhr.onload = function () {
|
||||
if (xhr.status === 200) {
|
||||
var response = JSON.parse(xhr.responseText);
|
||||
|
||||
if (response.status === 'success') {
|
||||
Swal.fire({
|
||||
title: 'Deleted!',
|
||||
text: response.message,
|
||||
icon: 'success',
|
||||
confirmButtonText: 'OK'
|
||||
}).then(() => {
|
||||
location.reload(); // Reload the page after confirmation
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: 'Error!',
|
||||
text: response.message,
|
||||
icon: 'error',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: 'Error!',
|
||||
text: 'Failed to delete coupons. Please try again.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
}
|
||||
};
|
||||
xhr.send('couponIds=' + JSON.stringify(couponIds));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: 'Error!',
|
||||
text: 'No coupons selected to delete.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Example usage for selected coupons
|
||||
document.getElementById('deleteSelectedCoupons').addEventListener('click', function () {
|
||||
var selectedCoupons = [];
|
||||
document.querySelectorAll('input[name="coupon_ids[]"]:checked').forEach(function (checkbox) {
|
||||
selectedCoupons.push(checkbox.value);
|
||||
});
|
||||
|
||||
if (selectedCoupons.length > 0) {
|
||||
deleteCoupons(selectedCoupons);
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: 'Error!',
|
||||
text: 'Please select at least one coupon to delete.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Example usage for single coupon deletion
|
||||
document.querySelectorAll('.delete-coupon').forEach(function (button) {
|
||||
button.addEventListener('click', function () {
|
||||
var couponId = this.getAttribute('data-id');
|
||||
deleteCoupons([couponId]);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Select or deselect all checkboxes
|
||||
document.getElementById('select-all').addEventListener('change', function () {
|
||||
var checkboxes = document.querySelectorAll('input[name="coupon_ids[]"]');
|
||||
for (var checkbox of checkboxes) {
|
||||
checkbox.checked = this.checked;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{literal}
|
||||
<script>
|
||||
function confirmAction(url, action) {
|
||||
Swal.fire({
|
||||
title: 'Are you sure?',
|
||||
text: `Do you really want to ${action.toLowerCase()} this coupon?`,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: 'Yes, proceed!',
|
||||
cancelButtonText: 'No, cancel!'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
window.location.href = url;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{/literal}
|
||||
<script>
|
||||
const $j = jQuery.noConflict();
|
||||
|
||||
$j(document).ready(function () {
|
||||
$j('#datatable').DataTable({
|
||||
"pagingType": "full_numbers",
|
||||
"order": [
|
||||
[1, 'desc']
|
||||
]
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{include file="sections/footer.tpl"}
|
@ -2,166 +2,178 @@
|
||||
|
||||
<div class="row">
|
||||
{if file_exists("$PAGES_PATH/Payment_Info.html")}
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-warning panel-hovered">
|
||||
<div class="panel-heading">{Lang::T('Payment Info')}</div>
|
||||
<div class="panel-body">{include file="$PAGES_PATH/Payment_Info.html"}</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-warning panel-hovered">
|
||||
<div class="panel-heading">{Lang::T('Payment Info')}</div>
|
||||
<div class="panel-body">{include file="$PAGES_PATH/Payment_Info.html"}</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="{if file_exists("$PAGES_PATH/Payment_Info.html")}col-md-6{else}col-md-6 col-md-offset-3{/if}">
|
||||
<div class="panel panel-success panel-hovered">
|
||||
<div class="panel-heading">{Lang::T('Available Payment Gateway')}</div>
|
||||
<div class="panel-footer">
|
||||
{if !$custom}
|
||||
<form method="post" action="{$_url}order/buy/{$route2}/{$route3}">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-4">{Lang::T('Payment Gateway')}</label>
|
||||
<div class="col-md-8">
|
||||
<select name="gateway" id="gateway" class="form-control">
|
||||
{if $_c['enable_balance'] == 'yes'}
|
||||
<option value="balance">{Lang::T('Balance')} {Lang::moneyFormat($_user['balance'])}
|
||||
</option>
|
||||
{/if}
|
||||
{foreach $pgs as $pg}
|
||||
<option value="{$pg}">{ucwords($pg)}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<center><b>{Lang::T('Package Details')}</b></center>
|
||||
<div class="panel-heading">{Lang::T('Make Payment')}</div>
|
||||
|
||||
<ul class="list-group list-group-unbordered">
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Plan Name')}</b> <span class="pull-right">{$plan['name_plan']}</span>
|
||||
</li>
|
||||
{if $plan['is_radius'] or $plan['routers']}
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Location')}</b> <span class="pull-right">{if
|
||||
$plan['is_radius']}Radius{else}{$plan['routers']}
|
||||
{/if}</span>
|
||||
</li>
|
||||
{/if}
|
||||
<div class="panel-body">
|
||||
<center><b>{Lang::T('Package Details')}</b></center>
|
||||
{if !$custom}
|
||||
<ul class="list-group list-group-unbordered">
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Type')}</b> <span class="pull-right">{if $plan['prepaid'] eq
|
||||
'yes'}{Lang::T('Prepaid')}{else}{Lang::T('Postpaid')}
|
||||
{/if}
|
||||
{$plan['type']}</span>
|
||||
<b>{Lang::T('Package Name')}</b>
|
||||
<span class="pull-right">{$plan['name_plan']}</span>
|
||||
</li>
|
||||
|
||||
{if $plan['is_radius'] or $plan['routers']}
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Package Price')}</b> <span class="pull-right">
|
||||
<b>{Lang::T('Location')}</b>
|
||||
<span class="pull-right">{if $plan['is_radius']}Radius{else}{$plan['routers']}{/if}</span>
|
||||
</li>
|
||||
{/if}
|
||||
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Type')}</b>
|
||||
<span class="pull-right">
|
||||
{if $plan['prepaid'] eq 'yes'}{Lang::T('Prepaid')}{else}{Lang::T('Postpaid')}{/if}
|
||||
{$plan['type']}
|
||||
</span>
|
||||
</li>
|
||||
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Package Price')}</b>
|
||||
<span class="pull-right">
|
||||
{if !empty($plan['price_old'])}
|
||||
<sup
|
||||
style="text-decoration: line-through; color: red">{Lang::moneyFormat($plan['price_old'])}</sup>
|
||||
<sup style="text-decoration: line-through; color: red">
|
||||
{Lang::moneyFormat($plan['price_old'])}
|
||||
</sup>
|
||||
{/if}
|
||||
{Lang::moneyFormat($plan['price'])}
|
||||
</span>
|
||||
</li>
|
||||
|
||||
{if $plan['validity']}
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Validity Periode')}</b> <span class="pull-right">{$plan['validity']}
|
||||
{$plan['validity_unit']}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Validity Period')}</b>
|
||||
<span class="pull-right">{$plan['validity']} {$plan['validity_unit']}</span>
|
||||
</li>
|
||||
{/if}
|
||||
</ul>
|
||||
{else}
|
||||
<ul class="list-group list-group-unbordered">
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Package Name')}</b>
|
||||
<span class="pull-right">{Lang::T('Custom Balance')}</span>
|
||||
</li>
|
||||
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Amount')}</b>
|
||||
<span class="pull-right">
|
||||
{Lang::moneyFormat($amount)}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
{/if}
|
||||
{if $discount == '' && $plan['type'] neq 'Balance' && $custom == ''}
|
||||
<!-- Coupon Code Form -->
|
||||
<form action="{$_url}order/gateway/{$route2}/{$route3}" method="post">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-4 control-label">{Lang::T('Coupon Code')}</label>
|
||||
<div class="col-md-8">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" name="coupon" id="coupon" maxlength="50"
|
||||
required placeholder="{Lang::T('Enter your coupon code')}">
|
||||
<span class="input-group-btn">
|
||||
<button type="submit" name="add_coupon"
|
||||
class="btn btn-info btn-flat">{Lang::T('Apply Coupon')}</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{/if}
|
||||
<br>
|
||||
<center><b>{Lang::T('Summary')}</b></center>
|
||||
<ul class="list-group list-group-unbordered">
|
||||
{if $tax}
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Tax')}</b> <span class="pull-right">{Lang::moneyFormat($tax)}</span>
|
||||
</li>
|
||||
{if $add_cost!=0}
|
||||
{foreach $bills as $k => $v}
|
||||
<li class="list-group-item">
|
||||
<b>{$k}</b> <span class="pull-right">{Lang::moneyFormat($v)}</span>
|
||||
</li>
|
||||
{/foreach}
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Additional Cost')}</b> <span
|
||||
class="pull-right">{Lang::moneyFormat($add_cost)}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Total')}</b> <small>({Lang::T('Package Price')}
|
||||
+{Lang::T('Additional Cost')})</small><span class="pull-right"
|
||||
style="font-size: large; font-weight:bolder; font-family: 'Courier New', Courier, monospace; ">{Lang::moneyFormat($plan['price']+$add_cost+$tax)}</span>
|
||||
</li>
|
||||
{else}
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Total')}</b> <small>({Lang::T('Plan Price')} + {Lang::T('Tax')})</small><span
|
||||
class="pull-right"
|
||||
style="font-size: large; font-weight:bolder; font-family: 'Courier New', Courier, monospace; ">{Lang::moneyFormat($plan['price']+$tax)}</span>
|
||||
</li>
|
||||
{/if}
|
||||
|
||||
{if $add_cost != 0}
|
||||
{foreach $bills as $k => $v}
|
||||
<li class="list-group-item">
|
||||
<b>{$k}</b>
|
||||
<span class="pull-right">{Lang::moneyFormat($v)}</span>
|
||||
</li>
|
||||
{/foreach}
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Additional Cost')}</b>
|
||||
<span class="pull-right">{Lang::moneyFormat($add_cost)}</span>
|
||||
</li>
|
||||
{/if}
|
||||
{if $discount}
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Discount Applied')}</b>
|
||||
<span class="pull-right">{Lang::moneyFormat($discount)}</span>
|
||||
</li>
|
||||
{/if}
|
||||
|
||||
{if $amount neq '' && $custom == '1'}
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Total')}</b>
|
||||
<span class="pull-right" style="font-size: large; font-weight: bolder;">
|
||||
{Lang::moneyFormat($amount)}
|
||||
</span>
|
||||
</li>
|
||||
{elseif $plan['type'] eq 'Balance'}
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Total')}</b>
|
||||
<span class="pull-right" style="font-size: large; font-weight: bolder;">
|
||||
{Lang::moneyFormat($plan['price'] + $add_cost)}
|
||||
</span>
|
||||
</li>
|
||||
{else}
|
||||
{if $add_cost!=0}
|
||||
{foreach $bills as $k => $v}
|
||||
<li class="list-group-item">
|
||||
<b>{$k}</b> <span class="pull-right">{Lang::moneyFormat($v)}</span>
|
||||
</li>
|
||||
{/foreach}
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Additional Cost')}</b> <span
|
||||
class="pull-right">{Lang::moneyFormat($add_cost)}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Total')}</b> <small>({Lang::T('Package Price')}
|
||||
+{Lang::T('Additional Cost')})</small><span class="pull-right"
|
||||
style="font-size: large; font-weight:bolder; font-family: 'Courier New', Courier, monospace; ">{Lang::moneyFormat($plan['price']+$add_cost)}</span>
|
||||
</li>
|
||||
{else}
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Total')}</b> <span class="pull-right"
|
||||
style="font-size: large; font-weight:bolder; font-family: 'Courier New', Courier, monospace; ">{Lang::moneyFormat($plan['price'])}</span>
|
||||
</li>
|
||||
{/if}
|
||||
{if $tax}
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Tax')}</b>
|
||||
<span class="pull-right">{Lang::moneyFormat($tax)}</span>
|
||||
</li>
|
||||
{/if}
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Total')}</b>
|
||||
<span class="pull-right" style="font-size: large; font-weight: bolder;">
|
||||
{Lang::moneyFormat($plan['price'] + $add_cost + $tax)}
|
||||
</span>
|
||||
</li>
|
||||
{/if}
|
||||
</ul>
|
||||
<center>
|
||||
<button type="submit" class="btn btn-primary"
|
||||
onclick="return ask(this, '{Lang::T("Are You Sure?")}')">{Lang::T('Pay Now')}</button><br>
|
||||
<a class="btn btn-link" href="{$_url}home">{Lang::T('Cancel')}</a>
|
||||
</center>
|
||||
</form>
|
||||
{else}
|
||||
<br>
|
||||
|
||||
<!-- Payment Gateway Form -->
|
||||
<form method="post" action="{$_url}order/buy/{$route2}/{$route3}">
|
||||
<input type="hidden" name="coupon" value="{$discount}">
|
||||
{if $custom == '1' && $amount neq ''}
|
||||
<input type="hidden" name="custom" value="1">
|
||||
<input type="hidden" name="amount" value="{$amount}">
|
||||
{/if}
|
||||
<div class="form-group row">
|
||||
<label class="col-md-4">{Lang::T('Payment Gateway')}</label>
|
||||
<div class="col-md-8">
|
||||
<select name="gateway" id="gateway" class="form-control">
|
||||
{if $_c['enable_balance'] neq 'no' && $plan['type'] neq 'Balance' && $custom == '' &&
|
||||
$_user['balance'] >= $plan['price'] + $add_cost + $tax}
|
||||
<option value="balance">{Lang::T('Balance')} {Lang::moneyFormat($_user['balance'])}
|
||||
</option>
|
||||
{/if}
|
||||
{foreach $pgs as $pg}
|
||||
<option value="{$pg}">
|
||||
{ucwords($pg)}</option>
|
||||
<option value="{$pg}">{ucwords($pg)}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="list-group list-group-unbordered">
|
||||
<input type="hidden" name="custom" value="1">
|
||||
<input type="hidden" name="amount" value="{$amount}">
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Custom Balance')}</b> <span
|
||||
class="pull-right">{Lang::moneyFormat($amount)}</span>
|
||||
</li>
|
||||
<br> <br> <br>
|
||||
<li class="list-group-item">
|
||||
<b>{Lang::T('Total')}</b> <span class="pull-right"
|
||||
style="font-size: large; font-weight:bolder; font-family: 'Courier New', Courier, monospace; ">{Lang::moneyFormat($amount)}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<center>
|
||||
<button type="submit" class="btn btn-primary"
|
||||
onclick="return ask(this, '{Lang::T("Are You Sure?")}')">{Lang::T('Pay Now')}</button><br>
|
||||
<a class="btn btn-link" href="{$_url}home">{Lang::T('Cancel')}</a>
|
||||
<button type="submit" name="pay" class="btn btn-primary" onclick="return ask(this, '{Lang::T("
|
||||
Are You Sure?")}')">{Lang::T('Pay Now')}</button>
|
||||
<a href="{$_url}home" class="btn btn-secondary">{Lang::T('Cancel')}</a>
|
||||
</center>
|
||||
</form>
|
||||
{/if}
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{include file="customer/footer.tpl"}
|
||||
|
@ -9,14 +9,14 @@
|
||||
.ukuran {
|
||||
size: A4;
|
||||
}
|
||||
|
||||
|
||||
body,
|
||||
td,
|
||||
th {
|
||||
font-size: 12px;
|
||||
font-family: Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif;
|
||||
}
|
||||
|
||||
|
||||
page[size="A4"] {
|
||||
background: white;
|
||||
width: 21cm;
|
||||
@ -24,32 +24,28 @@
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 0.5cm;
|
||||
|
||||
html,
|
||||
body {
|
||||
width: 210mm;
|
||||
height: 297mm;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media print {
|
||||
body {
|
||||
size: auto;
|
||||
margin: 0;
|
||||
box-shadow: 0;
|
||||
}
|
||||
|
||||
page[size="A4"] {
|
||||
margin: 0;
|
||||
size: auto;
|
||||
box-shadow: 0;
|
||||
}
|
||||
|
||||
.page-break {
|
||||
display: block;
|
||||
page-break-before: always;
|
||||
}
|
||||
|
||||
.no-print,
|
||||
.no-print * {
|
||||
display: none !important;
|
||||
@ -65,10 +61,10 @@
|
||||
<tr>
|
||||
<td>From ID > <input type="text" name="from_id" style="width:40px" value="{$from_id}"> limit
|
||||
<input type="text" name="limit" style="width:40px" value="{$limit}"></td>
|
||||
<td>Voucher PerLine <input type="text" style="width:40px" name="vpl" value="{$vpl}">
|
||||
vouchers</td>
|
||||
<td>PageBreak after <input type="text" style="width:40px" name="pagebreak" value="{$pagebreak}">
|
||||
vouchers</td>
|
||||
<td>Voucher PerLine <input type="text" style="width:40px" name="vpl" value="{$vpl}"> vouchers
|
||||
</td>
|
||||
<td>PageBreak after <input type="text" style="width:40px" name="pagebreak" value="{$pagebreak}"> vouchers
|
||||
</td>
|
||||
<td>Plans <select id="plan_id" name="planid" style="width:50px">
|
||||
<option value="0">--all--</option>
|
||||
{foreach $plans as $plan}
|
||||
@ -76,51 +72,41 @@
|
||||
</option>
|
||||
{/foreach}
|
||||
</select></td>
|
||||
<td>Date <select id="selected_datetime" name="selected_datetime" style="width:50px">
|
||||
<option value="">--all--</option>
|
||||
{foreach $createdate as $date}
|
||||
<option value="{$date.created_datetime}" {if $date.created_datetime eq $selected_datetime}selected{/if}>
|
||||
{$date.created_datetime} ({$date.voucher_count})
|
||||
</option>
|
||||
{/foreach}
|
||||
</select></td>
|
||||
<td><button type="submit">submit</button></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<center><button type="button" onclick="window.print()"
|
||||
class="btn btn-default btn-sm no-print">{Lang::T('Click Here to Print')}</button><br>
|
||||
{Lang::T('Print side by side, it will easy to cut')}<br>
|
||||
show {$v|@count} vouchers from {$vc} vouchers<br>
|
||||
from ID {$v[0]['id']} limit {$limit} vouchers
|
||||
<center><button type="button" onclick="window.print()" class="btn btn-default btn-sm no-print">{Lang::T('Click Here to Print')}</button><br> {Lang::T('Print side by side, it will easy to cut')}<br> show {$v|@count} vouchers from {$vc} vouchers<br> from ID {$v[0]['id']} limit {$limit} vouchers
|
||||
</center>
|
||||
</form>
|
||||
<div id="printable" align="center">
|
||||
<hr>
|
||||
{$n = 1}
|
||||
{foreach $voucher as $vs}
|
||||
{$jml = $jml + 1}
|
||||
{if $n == 1}
|
||||
<table>
|
||||
<tr>
|
||||
{/if}
|
||||
<td>{$vs}</td>
|
||||
{if $n == $vpl}
|
||||
</table>
|
||||
{$n = 1}
|
||||
{else}
|
||||
{$n = $n + 1}
|
||||
{/if}
|
||||
|
||||
|
||||
{if $jml == $pagebreak}
|
||||
{$jml = 0}
|
||||
<!-- pageBreak -->
|
||||
<div class="page-break">
|
||||
<div class="no-print" style="background-color: #E91E63; color:#FFF;" align="center">-- pageBreak --
|
||||
<hr>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/foreach}
|
||||
<hr> {$n = 1} {foreach $voucher as $vs} {$jml = $jml + 1} {if $n == 1}
|
||||
<table>
|
||||
<tr>
|
||||
{/if}
|
||||
<td>{$vs}</td>
|
||||
{if $n == $vpl}
|
||||
</table>
|
||||
{$n = 1} {else} {$n = $n + 1} {/if} {if $jml == $pagebreak} {$jml = 0}
|
||||
<!-- pageBreak -->
|
||||
<div class="page-break">
|
||||
<div class="no-print" style="background-color: #E91E63; color:#FFF;" align="center">-- pageBreak --
|
||||
<hr>
|
||||
</div>
|
||||
</div>
|
||||
{/if} {/foreach}
|
||||
</div>
|
||||
</page>
|
||||
<script src="ui/ui/scripts/jquery.min.js"></script>
|
||||
{if isset($xfooter)}
|
||||
{$xfooter}
|
||||
{/if}
|
||||
{if isset($xfooter)} {$xfooter} {/if}
|
||||
<script>
|
||||
jQuery(document).ready(function() {
|
||||
// initiate layout and plugins
|
||||
|
@ -1240,7 +1240,7 @@
|
||||
{if !in_array($_admin['user_type'],['Report'])}
|
||||
<li class="{if in_array($_system_menu, ['customers', 'map'])}active{/if} treeview">
|
||||
<a href="#">
|
||||
<i class="fa fa-users"></i> <span>{Lang::T('Customer')}</span>
|
||||
<i class="fa fa-user"></i> <span>{Lang::T('Customer')}</span>
|
||||
<span class="pull-right-container">
|
||||
<i class="fa fa-angle-left pull-right"></i>
|
||||
</span>
|
||||
@ -1265,8 +1265,6 @@
|
||||
<li {if $_routes[1] eq 'list' }class="active" {/if}><a
|
||||
href="{$_url}plan/list">{Lang::T('Active Users')}</a></li>
|
||||
{if $_c['disable_voucher'] != 'yes'}
|
||||
<li {if $_routes[1] eq 'voucher' }class="active" {/if}><a
|
||||
href="{$_url}plan/voucher">{Lang::T('Vouchers')}</a></li>
|
||||
<li {if $_routes[1] eq 'refill' }class="active" {/if}><a
|
||||
href="{$_url}plan/refill">{Lang::T('Refill Customer')}</a></li>
|
||||
{/if}
|
||||
@ -1307,6 +1305,38 @@
|
||||
</li>
|
||||
{/if}
|
||||
{$_MENU_AFTER_PLANS}
|
||||
<li class="{if $_system_menu eq 'cards'}active{/if} treeview">
|
||||
<a href="#">
|
||||
<i class="glyphicon glyphicon-credit-card"></i> <span>{Lang::T('Cards')}</span>
|
||||
<span class="pull-right-container">
|
||||
<i class="fa fa-angle-left pull-right"></i>
|
||||
</span>
|
||||
</a>
|
||||
<ul class="treeview-menu">
|
||||
{if $_c['disable_voucher'] != 'yes'}
|
||||
<li {if $_routes[1] eq 'voucher' }class="active" {/if}><a
|
||||
href="{$_url}plan/voucher">{Lang::T('Vouchers')}</a></li>
|
||||
{/if}
|
||||
{$_MENU_CARDS}
|
||||
</ul>
|
||||
</li>
|
||||
{$_MENU_AFTER_CRM}
|
||||
<li class="{if $_system_menu eq 'crm'}active{/if} treeview">
|
||||
<a href="#">
|
||||
<i class="fa fa-users"></i> <span>{Lang::T('CRM')}</span>
|
||||
<span class="pull-right-container">
|
||||
<i class="fa fa-angle-left pull-right"></i>
|
||||
</span>
|
||||
</a>
|
||||
<ul class="treeview-menu">
|
||||
{if $_c['disable_coupons'] != 'yes'}
|
||||
<li {if $_routes[0] eq 'coupons' }class="active" {/if}><a
|
||||
href="{$_url}coupons">{Lang::T('Coupons')}</a></li>
|
||||
{/if}
|
||||
{$_MENU_CRM}
|
||||
</ul>
|
||||
</li>
|
||||
{$_MENU_AFTER_CARDS}
|
||||
<li class="{if $_system_menu eq 'reports'}active{/if} treeview">
|
||||
{if in_array($_admin['user_type'],['SuperAdmin','Admin', 'Report'])}
|
||||
<a href="#">
|
||||
|
@ -41,16 +41,15 @@
|
||||
<label class="col-md-2 control-label">{Lang::T('Voucher Format')}</label>
|
||||
<div class="col-md-6">
|
||||
<select name="voucher_format" id="voucher_format" class="form-control">
|
||||
<option value="numbers" {if $_c['voucher_format'] == 'numbers'}selected="selected"
|
||||
{/if}>
|
||||
<option value="numbers" {if $_c['voucher_format']=='numbers' }selected="selected" {/if}>
|
||||
Numbers
|
||||
</option>
|
||||
<option value="up" {if $_c['voucher_format'] == 'up'}selected="selected" {/if}>UPPERCASE
|
||||
<option value="up" {if $_c['voucher_format']=='up' }selected="selected" {/if}>UPPERCASE
|
||||
</option>
|
||||
<option value="low" {if $_c['voucher_format'] == 'low'}selected="selected" {/if}>
|
||||
<option value="low" {if $_c['voucher_format']=='low' }selected="selected" {/if}>
|
||||
lowercase
|
||||
</option>
|
||||
<option value="rand" {if $_c['voucher_format'] == 'rand'}selected="selected" {/if}>
|
||||
<option value="rand" {if $_c['voucher_format']=='rand' }selected="selected" {/if}>
|
||||
RaNdoM
|
||||
</option>
|
||||
</select>
|
||||
@ -60,8 +59,7 @@
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">{Lang::T('Voucher Prefix')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="text" class="form-control" name="prefix" placeholder="NUX-"
|
||||
value="{$_c['voucher_prefix']}">
|
||||
<input type="text" class="form-control" name="prefix" placeholder="NUX-" value="{$_c['voucher_prefix']}">
|
||||
</div>
|
||||
<p class="help-block col-md-4">NUX-VoUCHeRCOdE</p>
|
||||
</div>
|
||||
@ -71,6 +69,24 @@
|
||||
<input type="text" class="form-control" name="lengthcode" value="12">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="inputSkills" class="col-sm-2 control-label">{Lang::T('Print Now')}</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<input type="checkbox" id="print_now" name="print_now" class="iCheck" value="yes" onclick="showVouchersPerPage()">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="printers" style="display:none;">
|
||||
<label class="col-md-2 control-label">{Lang::T('Vouchers Per Page')}</label>
|
||||
<div class="col-md-6">
|
||||
<input type="text" id="voucher-print" class="form-control" name="voucher_per_page" value="36" placeholder="Vouchers Per Page (default 36)">
|
||||
</div>
|
||||
<p class="help-block col-md-4">
|
||||
{Lang::T('Vouchers Per Page')} (default 36)
|
||||
</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-lg-offset-2 col-lg-10">
|
||||
<button class="btn btn-success" onclick="return ask(this, 'Continue the Voucher creation process?')" type="submit">{Lang::T('Generate')}</button>
|
||||
@ -83,4 +99,22 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{include file="sections/footer.tpl"}
|
||||
<!-- /voucher-add -->
|
||||
|
||||
<script>
|
||||
function showVouchersPerPage() {
|
||||
var printNow = document.getElementById('print_now');
|
||||
var printers = document.getElementById('printers');
|
||||
var voucherPrint = document.getElementById('voucher-print');
|
||||
|
||||
voucherPrint.required = false;
|
||||
if (printNow.checked) {
|
||||
printers.style.display = 'block';
|
||||
voucherPrint.required = true;
|
||||
} else {
|
||||
printers.style.display = 'none';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{include file="sections/footer.tpl"}
|
@ -90,6 +90,7 @@
|
||||
<table id="datatable" class="table table-bordered table-striped table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><input type="checkbox" id="select-all"></th>
|
||||
<th>ID</th>
|
||||
<th>{Lang::T('Type')}</th>
|
||||
<th>{Lang::T('Routers')}</th>
|
||||
@ -97,6 +98,7 @@
|
||||
<th>{Lang::T('Code Voucher')}</th>
|
||||
<th>{Lang::T('Status Voucher')}</th>
|
||||
<th>{Lang::T('Customer')}</th>
|
||||
<th>{Lang::T('Create Date')}</th>
|
||||
<th>{Lang::T('Used Date')}</th>
|
||||
<th>{Lang::T('Generated By')}</th>
|
||||
<th>{Lang::T('Manage')}</th>
|
||||
@ -105,6 +107,7 @@
|
||||
<tbody>
|
||||
{foreach $d as $ds}
|
||||
<tr {if $ds['status'] eq '1' }class="danger" {/if}>
|
||||
<td><input type="checkbox" name="voucher_ids[]" value="{$ds['id']}"></td>
|
||||
<td>{$ds['id']}</td>
|
||||
<td>{$ds['type']}</td>
|
||||
<td>{$ds['routers']}</td>
|
||||
@ -119,6 +122,7 @@
|
||||
<td>{if $ds['user'] eq '0'} -
|
||||
{else}<a href="{$_url}customers/viewu/{$ds['user']}">{$ds['user']}</a>
|
||||
{/if}</td>
|
||||
<td>{if $ds['created_at']}{Lang::dateTimeFormat($ds['created_at'])}{/if}</td>
|
||||
<td>{if $ds['used_date']}{Lang::dateTimeFormat($ds['used_date'])}{/if}</td>
|
||||
<td>{if $ds['generated_by']}
|
||||
<a
|
||||
@ -143,6 +147,112 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{include file="pagination.tpl"}
|
||||
</div>
|
||||
<div class="row" style="padding: 5px">
|
||||
<div class="col-lg-3 col-lg-offset-9">
|
||||
<div class="btn-group btn-group-justified" role="group">
|
||||
<div class="btn-group" role="group">
|
||||
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
|
||||
<button id="deleteSelectedVouchers" class="btn btn-danger">{Lang::T('Delete
|
||||
Selected')}</button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{include file="pagination.tpl"}
|
||||
|
||||
<script>
|
||||
function deleteVouchers(voucherIds) {
|
||||
if (voucherIds.length > 0) {
|
||||
Swal.fire({
|
||||
title: 'Are you sure?',
|
||||
text: 'You won\'t be able to revert this!',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Yes, delete it!',
|
||||
cancelButtonText: 'Cancel'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', '{$_url}plan/voucher-delete-many', true);
|
||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
||||
xhr.onload = function () {
|
||||
if (xhr.status === 200) {
|
||||
var response = JSON.parse(xhr.responseText);
|
||||
|
||||
if (response.status === 'success') {
|
||||
Swal.fire({
|
||||
title: 'Deleted!',
|
||||
text: response.message,
|
||||
icon: 'success',
|
||||
confirmButtonText: 'OK'
|
||||
}).then(() => {
|
||||
location.reload(); // Reload the page after confirmation
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: 'Error!',
|
||||
text: response.message,
|
||||
icon: 'error',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: 'Error!',
|
||||
text: 'Failed to delete vouchers. Please try again.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
}
|
||||
};
|
||||
xhr.send('voucherIds=' + JSON.stringify(voucherIds));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: 'Error!',
|
||||
text: 'No vouchers selected to delete.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Example usage for selected vouchers
|
||||
document.getElementById('deleteSelectedVouchers').addEventListener('click', function () {
|
||||
var selectedVouchers = [];
|
||||
document.querySelectorAll('input[name="voucher_ids[]"]:checked').forEach(function (checkbox) {
|
||||
selectedVouchers.push(checkbox.value);
|
||||
});
|
||||
|
||||
if (selectedVouchers.length > 0) {
|
||||
deleteVouchers(selectedVouchers);
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: 'Error!',
|
||||
text: 'Please select at least one voucher to delete.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
document.querySelectorAll('.delete-voucher').forEach(function (button) {
|
||||
button.addEventListener('click', function () {
|
||||
var voucherId = this.getAttribute('data-id');
|
||||
deleteVouchers([voucherId]);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Select or deselect all checkboxes
|
||||
document.getElementById('select-all').addEventListener('change', function () {
|
||||
var checkboxes = document.querySelectorAll('input[name="voucher_ids[]"]');
|
||||
for (var checkbox of checkboxes) {
|
||||
checkbox.checked = this.checked;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{include file="sections/footer.tpl"}
|
Loading…
x
Reference in New Issue
Block a user