Compare commits

...

18 Commits

Author SHA1 Message Date
375403135e 2024.2.23.1 2024-02-23 15:04:53 +07:00
db49d0f4b5 Fix variable customer 2024-02-23 14:57:00 +07:00
c4fb99479b fix resend 2024-02-23 14:54:28 +07:00
091f4fb638 Fix Cookies Admin 2024-02-23 14:52:10 +07:00
8db3d6c679 update changelog 2024-02-23 14:44:37 +07:00
ddd7fb49fe Fix invoice 2024-02-23 14:40:47 +07:00
c6a203b1f0 Add Alert Page 2024-02-23 14:20:12 +07:00
6de63bed63 Integrate with PhpNuxBill Printer 2024-02-23 11:39:25 +07:00
9552a14de5 add button print 2024-02-22 18:37:28 +07:00
9d379b3fbd Phpnuxbill android printer support 2024-02-22 18:27:18 +07:00
4f3e5972b0 Merge pull request #112 from Focuslinkstech/Development
Update accounts.php
2024-02-22 11:45:29 +07:00
be65976310 link to settings when hide widget 2024-02-22 11:42:17 +07:00
8728af4332 Add Loading when click submit 2024-02-22 11:41:55 +07:00
07870d05ad Update accounts.php
Fix OTP not sending bug
2024-02-21 11:58:13 +01:00
cee6f8949c Merge branch 'Development' 2024-02-21 16:15:21 +07:00
3bdf44ddbe Merge pull request #111 from Focuslinkstech/Development
Bug Fix: OTP bugs
2024-02-21 16:13:26 +07:00
17c1675b4a Update accounts.php
fix lang function
2024-02-21 10:13:05 +01:00
54d1c4439d Bug Fix: OTP bugs
add phone number validation to prevent invalid phone number, phone number must be 10 digits up

fix issue with updating phone number without OTP
2024-02-21 10:02:31 +01:00
27 changed files with 475 additions and 160 deletions

View File

@ -2,6 +2,17 @@
# CHANGELOG
## 2024.2.23
- Integrate with PhpNuxBill Printer
- Fix Invoice
- add admin ID in transaction
## 2024.2.22
- Add Loading when click submit
- link to settings when hide widget
## 2024.2.21
- Fix SQL Installer

View File

@ -219,6 +219,23 @@ function sendWhatsapp($phone, $txt)
Message::sendWhatsapp($phone, $txt);
}
function _alert($text, $type = 'success', $url = "home")
{
global $ui;
if(!isset($ui)) return;
if(strlen($url)>4){
if(substr($url,0,4)!="http"){
$url = U.$url;
}
}else{
$url = U.$url;
}
$ui->assign('text', $text);
$ui->assign('type', $type);
$ui->assign('url', $url);
$ui->display('alert.tpl');
}
if(!isset($api_secret)){
$api_secret = $db_password;

View File

@ -181,16 +181,6 @@ CREATE TABLE `tb_languages` (
`id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
ALTER TABLE `tbl_voucher` ADD `generated_by` INT NOT NULL DEFAULT '0' COMMENT 'id admin' AFTER `status`;
ALTER TABLE `tbl_users` ADD `root` INT NOT NULL DEFAULT '0' COMMENT 'for sub account' AFTER `id`;
ALTER TABLE `tbl_users` CHANGE `user_type` `user_type` ENUM('SuperAdmin','Admin','Report','Agent','Sales') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;
ALTER TABLE `tbl_users` CHANGE `password` `password` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;
ALTER TABLE `tbl_users` ADD `phone` VARCHAR(32) NOT NULL DEFAULT '' AFTER `password`, ADD `email` VARCHAR(128) NOT NULL DEFAULT '' AFTER `phone`, ADD `city` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'kota' AFTER `email`, ADD `subdistrict` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'kecamatan' AFTER `city`, ADD `ward` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'kelurahan' AFTER `subdistrict`;
ALTER TABLE `tbl_customers` ADD `created_by` INT NOT NULL DEFAULT '0' AFTER `auto_renewal`;
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`;
ALTER TABLE `tbl_appconfig`
ADD PRIMARY KEY (`id`);
@ -316,3 +306,14 @@ CREATE TABLE tbl_customers_fields (
field_value VARCHAR(255) NOT NULL,
FOREIGN KEY (customer_id) REFERENCES tbl_customers(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
ALTER TABLE `tbl_voucher` ADD `generated_by` INT NOT NULL DEFAULT '0' COMMENT 'id admin' AFTER `status`;
ALTER TABLE `tbl_users` ADD `root` INT NOT NULL DEFAULT '0' COMMENT 'for sub account' AFTER `id`;
ALTER TABLE `tbl_users` CHANGE `user_type` `user_type` ENUM('SuperAdmin','Admin','Report','Agent','Sales') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;
ALTER TABLE `tbl_users` CHANGE `password` `password` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;
ALTER TABLE `tbl_users` ADD `phone` VARCHAR(32) NOT NULL DEFAULT '' AFTER `password`, ADD `email` VARCHAR(128) NOT NULL DEFAULT '' AFTER `phone`, ADD `city` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'kota' AFTER `email`, ADD `subdistrict` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'kecamatan' AFTER `city`, ADD `ward` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'kelurahan' AFTER `subdistrict`;
ALTER TABLE `tbl_customers` ADD `created_by` INT NOT NULL DEFAULT '0' AFTER `auto_renewal`;
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`;
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`;

View File

@ -38,9 +38,10 @@ Class Admin{
}
}
public static function _info(){
$id = Admin::getID();
$d = ORM::for_table('tbl_users')->find_one($id);
return $d;
public static function _info($id = 0){
if(empty($id) && $id==0){
$id = Admin::getID();
}
return ORM::for_table('tbl_users')->find_one($id);
}
}

View File

@ -19,7 +19,7 @@ class Package
*/
public static function rechargeUser($id_customer, $router_name, $plan_id, $gateway, $channel)
{
global $_c;
global $config, $admin;
$date_now = date("Y-m-d H:i:s");
$date_only = date("Y-m-d");
$time_only = date("H:i:s");
@ -47,6 +47,11 @@ class Package
$t->method = "$gateway - $channel";
$t->routers = $router_name;
$t->type = "Balance";
if ($admin) {
$t->admin_id = $admin['id'];
}else{
$t->admin_id = '0';
}
$t->save();
$balance_before = $c['balance'];
@ -54,9 +59,9 @@ class Package
$balance = $c['balance'] + $p['price'];
$textInvoice = Lang::getNotifText('invoice_balance');
$textInvoice = str_replace('[[company_name]]', $_c['CompanyName'], $textInvoice);
$textInvoice = str_replace('[[address]]', $_c['address'], $textInvoice);
$textInvoice = str_replace('[[phone]]', $_c['phone'], $textInvoice);
$textInvoice = str_replace('[[company_name]]', $config['CompanyName'], $textInvoice);
$textInvoice = str_replace('[[address]]', $config['address'], $textInvoice);
$textInvoice = str_replace('[[phone]]', $config['phone'], $textInvoice);
$textInvoice = str_replace('[[invoice]]', $inv, $textInvoice);
$textInvoice = str_replace('[[date]]', Lang::dateTimeFormat($date_now), $textInvoice);
$textInvoice = str_replace('[[payment_gateway]]', $gateway, $textInvoice);
@ -67,13 +72,13 @@ class Package
$textInvoice = str_replace('[[name]]', $c['fullname'], $textInvoice);
$textInvoice = str_replace('[[user_name]]', $c['username'], $textInvoice);
$textInvoice = str_replace('[[user_password]]', $c['password'], $textInvoice);
$textInvoice = str_replace('[[footer]]', $_c['note'], $textInvoice);
$textInvoice = str_replace('[[footer]]', $config['note'], $textInvoice);
$textInvoice = str_replace('[[balance_before]]', Lang::moneyFormat($balance_before), $textInvoice);
$textInvoice = str_replace('[[balance]]', Lang::moneyFormat($balance), $textInvoice);
if ($_c['user_notification_payment'] == 'sms') {
if ($config['user_notification_payment'] == 'sms') {
Message::sendSMS($c['phonenumber'], $textInvoice);
} else if ($_c['user_notification_payment'] == 'wa') {
} else if ($config['user_notification_payment'] == 'wa') {
Message::sendWhatsapp($c['phonenumber'], $textInvoice);
}
@ -127,7 +132,7 @@ class Package
if ($p['is_radius']) {
Radius::customerAddPlan($c, $p, "$date_exp $time");
}else{
} else {
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
Mikrotik::removeHotspotUser($client, $c['username']);
Mikrotik::removeHotspotActiveUser($client, $c['username']);
@ -146,6 +151,11 @@ class Package
$b->method = "$gateway - $channel";
$b->routers = $router_name;
$b->type = "Hotspot";
if ($admin) {
$b->admin_id = $admin['id'];
}else{
$b->admin_id = '0';
}
$b->save();
// insert table transactions
@ -161,11 +171,16 @@ class Package
$t->method = "$gateway - $channel";
$t->routers = $router_name;
$t->type = "Hotspot";
if ($admin) {
$t->admin_id = $admin['id'];
}else{
$t->admin_id = '0';
}
$t->save();
} else {
if ($p['is_radius']) {
Radius::customerAddPlan($c, $p, "$date_exp $time");
}else{
} else {
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
Mikrotik::removeHotspotUser($client, $c['username']);
Mikrotik::removeHotspotActiveUser($client, $c['username']);
@ -185,6 +200,11 @@ class Package
$d->method = "$gateway - $channel";
$d->routers = $router_name;
$d->type = "Hotspot";
if ($admin) {
$b->admin_id = $admin['id'];
}else{
$b->admin_id = '0';
}
$d->save();
// insert table transactions
@ -200,6 +220,11 @@ class Package
$t->method = "$gateway - $channel";
$t->routers = $router_name;
$t->type = "Hotspot";
if ($admin) {
$t->admin_id = $admin['id'];
}else{
$t->admin_id = '0';
}
$t->save();
}
Message::sendTelegram("#u$c[username] #buy #Hotspot \n" . $p['name_plan'] .
@ -231,7 +256,7 @@ class Package
if ($p['is_radius']) {
Radius::customerAddPlan($c, $p, "$date_exp $time");
}else{
} else {
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
Mikrotik::removePpoeUser($client, $c['username']);
Mikrotik::removePpoeActive($client, $c['username']);
@ -250,6 +275,11 @@ class Package
$b->method = "$gateway - $channel";
$b->routers = $router_name;
$b->type = "PPPOE";
if ($admin) {
$b->admin_id = $admin['id'];
}else{
$b->admin_id = '0';
}
$b->save();
// insert table transactions
@ -265,11 +295,16 @@ class Package
$t->method = "$gateway - $channel";
$t->routers = $router_name;
$t->type = "PPPOE";
if ($admin) {
$t->admin_id = $admin['id'];
}else{
$t->admin_id = '0';
}
$t->save();
} else {
if ($p['is_radius']) {
Radius::customerAddPlan($c, $p, "$date_exp $time");
}else{
} else {
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
Mikrotik::removePpoeUser($client, $c['username']);
Mikrotik::removePpoeActive($client, $c['username']);
@ -289,6 +324,11 @@ class Package
$d->method = "$gateway - $channel";
$d->routers = $router_name;
$d->type = "PPPOE";
if ($admin) {
$d->admin_id = $admin['id'];
}else{
$d->admin_id = '0';
}
$d->save();
// insert table transactions
@ -303,6 +343,11 @@ class Package
$t->time = $time;
$t->method = "$gateway - $channel";
$t->routers = $router_name;
if ($admin) {
$t->admin_id = $admin['id'];
}else{
$t->admin_id = '0';
}
$t->type = "PPPOE";
$t->save();
}
@ -322,9 +367,9 @@ class Package
$c = ORM::for_table('tbl_customers')->where('username', $username)->find_one();
$p = ORM::for_table('tbl_plans')->where('id', $plan_id)->where('enabled', '1')->find_one();
$b = ORM::for_table('tbl_user_recharges')->find_one($from_id);
if($p['routers'] == $b['routers'] && $b['routers'] != 'radius'){
if ($p['routers'] == $b['routers'] && $b['routers'] != 'radius') {
$mikrotik = Mikrotik::info($p['routers']);
}else{
} else {
$mikrotik = Mikrotik::info($b['routers']);
}
// delete first
@ -358,21 +403,21 @@ class Package
}
}
// call the next mikrotik
if($p['routers'] != $b['routers'] && $p['routers'] != 'radius'){
if ($p['routers'] != $b['routers'] && $p['routers'] != 'radius') {
$mikrotik = Mikrotik::info($p['routers']);
}
if ($p['type'] == 'Hotspot') {
if ($b) {
if ($p['is_radius']) {
Radius::customerAddPlan($c, $p, $b['expiration'].''.$b['time']);
}else{
Radius::customerAddPlan($c, $p, $b['expiration'] . '' . $b['time']);
} else {
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
Mikrotik::addHotspotUser($client, $p, $c);
}
} else {
if ($p['is_radius']) {
Radius::customerAddPlan($c, $p, $b['expiration'].''.$b['time']);
}else{
Radius::customerAddPlan($c, $p, $b['expiration'] . '' . $b['time']);
} else {
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
Mikrotik::addHotspotUser($client, $p, $c);
}
@ -381,14 +426,14 @@ class Package
if ($b) {
if ($p['is_radius']) {
Radius::customerAddPlan($c, $p);
}else{
} else {
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
Mikrotik::addPpoeUser($client, $p, $c);
}
} else {
if ($p['is_radius']) {
Radius::customerAddPlan($c, $p);
}else{
} else {
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
Mikrotik::addPpoeUser($client, $p, $c);
}
@ -401,4 +446,71 @@ class Package
{
return substr(str_shuffle(str_repeat('0123456789', $l)), 0, $l);
}
/**
* @param in tbl_transactions
* @param string $router_name router name for this package
* @param int $plan_id plan id for this package
* @param string $gateway payment gateway name
* @param string $channel channel payment gateway
* @return boolean
*/
public static function createInvoice($in)
{
global $config, $admin, $ui;
$date = Lang::dateAndTimeFormat($in['recharged_on'], $in['recharged_time']);
if ($admin['id'] != $in['admin_id'] && $in['admin_id'] > 0) {
$_admin = Admin::_info($in['admin_id']);
// if admin not deleted
if ($_admin) $admin = $_admin;
}
//print
$invoice = Lang::pad($config['CompanyName'], ' ', 2) . "\n";
$invoice .= Lang::pad($config['address'], ' ', 2) . "\n";
$invoice .= Lang::pad($config['phone'], ' ', 2) . "\n";
$invoice .= Lang::pad("", '=') . "\n";
$invoice .= Lang::pads("Invoice", $in['invoice'], ' ') . "\n";
$invoice .= Lang::pads(Lang::T('Date'), $date, ' ') . "\n";
$invoice .= Lang::pads(Lang::T('Sales'), $admin['fullname'], ' ') . "\n";
$invoice .= Lang::pad("", '=') . "\n";
$invoice .= Lang::pads(Lang::T('Type'), $in['type'], ' ') . "\n";
$invoice .= Lang::pads(Lang::T('Plan Name'), $in['plan_name'], ' ') . "\n";
$invoice .= Lang::pads(Lang::T('Plan Price'), Lang::moneyFormat($in['price']), ' ') . "\n";
$invoice .= Lang::pad($in['method'], ' ', 2) . "\n";
$invoice .= Lang::pads(Lang::T('Username'), $in['username'], ' ') . "\n";
$invoice .= Lang::pads(Lang::T('Password'), '**********', ' ') . "\n";
if ($in['type'] != 'Balance') {
$invoice .= Lang::pads(Lang::T('Created On'), Lang::dateAndTimeFormat($in['recharged_on'], $in['recharged_time']), ' ') . "\n";
$invoice .= Lang::pads(Lang::T('Expires On'), Lang::dateAndTimeFormat($in['expiration'], $in['time']), ' ') . "\n";
}
$invoice .= Lang::pad("", '=') . "\n";
$invoice .= Lang::pad($config['note'], ' ', 2) . "\n";
$ui->assign('invoice', $invoice);
$config['printer_cols'] = 30;
//whatsapp
$invoice = Lang::pad($config['CompanyName'], ' ', 2) . "\n";
$invoice .= Lang::pad($config['address'], ' ', 2) . "\n";
$invoice .= Lang::pad($config['phone'], ' ', 2) . "\n";
$invoice .= Lang::pad("", '=') . "\n";
$invoice .= Lang::pads("Invoice", $in['invoice'], ' ') . "\n";
$invoice .= Lang::pads(Lang::T('Date'), $date, ' ') . "\n";
$invoice .= Lang::pads(Lang::T('Sales'), $admin['fullname'], ' ') . "\n";
$invoice .= Lang::pad("", '=') . "\n";
$invoice .= Lang::pads(Lang::T('Type'), $in['type'], ' ') . "\n";
$invoice .= Lang::pads(Lang::T('Plan Name'), $in['plan_name'], ' ') . "\n";
$invoice .= Lang::pads(Lang::T('Plan Price'), Lang::moneyFormat($in['price']), ' ') . "\n";
$invoice .= Lang::pad($in['method'], ' ', 2) . "\n";
$invoice .= Lang::pads(Lang::T('Username'), $in['username'], ' ') . "\n";
$invoice .= Lang::pads(Lang::T('Password'), '**********', ' ') . "\n";
if ($in['type'] != 'Balance') {
$invoice .= Lang::pads(Lang::T('Created On'), Lang::dateAndTimeFormat($in['recharged_on'], $in['recharged_time']), ' ') . "\n";
$invoice .= Lang::pads(Lang::T('Expires On'), Lang::dateAndTimeFormat($in['expiration'], $in['time']), ' ') . "\n";
}
$invoice .= Lang::pad("", '=') . "\n";
$invoice .= Lang::pad($config['note'], ' ', 2) . "\n";
$ui->assign('whatsapp', urlencode("```$invoice```"));
$ui->assign('in',$in);
}
}

View File

@ -101,7 +101,6 @@ if (isset($_SESSION['notify'])) {
unset($_SESSION['ntype']);
}
// Routing Engine
$req = _get('_route');
$routes = explode('/', $req);

View File

@ -84,7 +84,7 @@ switch ($action) {
$ui->assign('d', $d);
$ui->display('user-profile.tpl');
} else {
r2(U . 'home', 'e', $_L['Account_Not_Found']);
r2(U . 'home', 'e', Lang::T('Account Not Found'));
}
break;
@ -122,6 +122,7 @@ switch ($action) {
}
break;
case 'phone-update':
$d = ORM::for_table('tbl_customers')->find_one($user['id']);
@ -139,6 +140,11 @@ switch ($action) {
$username = $user['username'];
$otpPath = 'system/cache/sms/';
// Validate the phone number format
if (!preg_match('/^[0-9]{10,}$/', $phone)) {
r2(U . 'accounts/phone-update', 'e', Lang::T('Invalid phone number format'));
}
if (empty($config['sms_url'])) {
r2(U . 'accounts/phone-update', 'e', Lang::T('SMS server not Available, Please try again later'));
}
@ -163,7 +169,16 @@ switch ($action) {
$otp = rand(100000, 999999);
file_put_contents($otpFile, $otp);
file_put_contents($phoneFile, $phone);
Message::sendSMS($phone, $config['CompanyName'] . "\n Your Verification code is: $otp");
// send send OTP to user
if ($config['phone_otp_type'] === 'sms') {
Message::sendSMS($phone, $config['CompanyName'] . "\n Your Verification code is: $otp");
} elseif ($config['phone_otp_type'] === 'whatsapp') {
Message::sendWhatsapp($phone, $config['CompanyName'] . "\n Your Verification code is: $otp");
} elseif ($config['phone_otp_type'] === 'both') {
Message::sendSMS($phone, $config['CompanyName'] . "\n Your Verification code is: $otp");
Message::sendWhatsapp($phone, $config['CompanyName'] . "\n Your Verification code is: $otp");
}
//redirect after sending OTP
r2(U . 'accounts/phone-update', 'e', Lang::T('Verification code has been sent to your phone'));
}
}
@ -177,41 +192,61 @@ switch ($action) {
$username = $user['username'];
$otpPath = 'system/cache/sms/';
// Validate the phone number format
if (!preg_match('/^[0-9]{10,}$/', $phone)) {
r2(U . 'accounts/phone-update', 'e', Lang::T('Invalid phone number format'));
exit();
}
if (!empty($config['sms_url'])) {
$otpFile = $otpPath . sha1($username . $db_password) . ".txt";
$phoneFile = $otpPath . sha1($username . $db_password) . "_phone.txt";
// Check if OTP file exists
if (!file_exists($otpFile)) {
r2(U . 'accounts/phone-update', 'e', Lang::T('Please request OTP first'));
exit();
}
// expired 10 minutes
if (file_exists($otpFile) && time() - filemtime($otpFile) > 1200) {
if (time() - filemtime($otpFile) > 1200) {
unlink($otpFile);
unlink($phoneFile);
r2(U . 'accounts/phone-update', 'e', 'Verification code expired');
} else if (file_exists($otpFile)) {
r2(U . 'accounts/phone-update', 'e', Lang::T('Verification code expired'));
exit();
} else {
$code = file_get_contents($otpFile);
// Check if OTP code matches
if ($code != $otp_code) {
r2(U . 'accounts/phone-update', 'e', 'Wrong Verification code');
r2(U . 'accounts/phone-update', 'e', Lang::T('Wrong Verification code'));
exit();
} elseif (file_exists($phoneFile)) {
$savedPhone = file_get_contents($phoneFile);
if ($savedPhone !== $phone) {
r2(U . 'accounts/phone-update', 'e', 'The phone number does not match the one that requested the OTP');
exit();
} else {
unlink($otpFile);
unlink($phoneFile);
}
} else {
r2(U . 'accounts/phone-update', 'e', 'No Verification code');
}
// Check if the phone number matches the one that requested the OTP
$savedPhone = file_get_contents($phoneFile);
if ($savedPhone !== $phone) {
r2(U . 'accounts/phone-update', 'e', Lang::T('The phone number does not match the one that requested the OTP'));
exit();
}
// OTP verification successful, delete OTP and phone number files
unlink($otpFile);
unlink($phoneFile);
}
} else {
r2(U . 'accounts/phone-update', 'e', Lang::T('SMS server not available'));
exit();
}
// Update the phone number in the database
$d = ORM::for_table('tbl_customers')->where('username', $username)->find_one();
if ($d) {
$d->phonenumber = Lang::phoneFormat($phone);
$d->save();
}
r2(U . 'accounts/profile', 's', 'Phone number updated successfully');
r2(U . 'accounts/profile', 's', Lang::T('Phone number updated successfully'));
break;
default:

View File

@ -26,19 +26,16 @@ switch ($do) {
$d->last_login = date('Y-m-d H:i:s');
$d->save();
_log($username . ' ' . Lang::T('Login Successful'), $d['user_type'], $d['id']);
r2(U . 'dashboard');
_alert(Lang::T('Login Successful'),'success', "dashboard");
} else {
_msglog('e', Lang::T('Invalid Username or Password'));
_log($username . ' ' . Lang::T('Failed Login'), $d['user_type']);
r2(U . 'admin');
_alert(Lang::T('Invalid Username or Password'),'danger', "admin");
}
} else {
_msglog('e', Lang::T('Invalid Username or Password'));
r2(U . 'admin');
_alert(Lang::T('Invalid Username or Password'),'danger', "admin");
}
} else {
_msglog('e', Lang::T('Invalid Username or Password'));
r2(U . 'admin');
_alert(Lang::T('Invalid Username or Password'),'danger', "admin");
}
break;

View File

@ -26,7 +26,7 @@ switch ($do) {
$d->last_login = date('Y-m-d H:i:s');
$d->save();
_log($username . ' ' . Lang::T('Login Successful'), 'User', $d['id']);
r2(U . 'home');
_alert(Lang::T('Login Successful'),'success', "home");
} else {
_msglog('e', Lang::T('Invalid Username or Password'));
_log($username . ' ' . Lang::T('Failed Login'), 'User');
@ -64,6 +64,7 @@ switch ($do) {
r2(U . 'login', 'e', Lang::T('Voucher activation failed'));
}
} else {
_alert(Lang::T('Login Successful'),'success', "dashboard");
r2(U . 'login', 'e', Lang::T('Voucher activation failed') . '.');
}
}

View File

@ -9,4 +9,4 @@ if (session_status() == PHP_SESSION_NONE) session_start();
Admin::removeCookie();
User::removeCookie();
session_destroy();
header('location: index.php');
_alert(Lang::T('Logout Successful'),'warning', "login");

View File

@ -129,8 +129,7 @@ switch ($action) {
if (Package::rechargeUser($id_customer, $server, $plan, "Recharge", $admin['fullname'])) {
$c = ORM::for_table('tbl_customers')->where('id', $id_customer)->find_one();
$in = ORM::for_table('tbl_transactions')->where('username', $c['username'])->order_by_desc('id')->find_one();
$ui->assign('in', $in);
$ui->assign('date', date("Y-m-d H:i:s"));
Package::createInvoice($in);
$ui->display('invoice.tpl');
_log('[' . $admin['username'] . ']: ' . 'Recharge ' . $c['username'] . ' [' . $in['plan_name'] . '][' . Lang::moneyFormat($in['price']) . ']', $admin['user_type'], $admin['id']);
} else {
@ -143,19 +142,18 @@ switch ($action) {
case 'view':
$id = $routes['2'];
$d = ORM::for_table('tbl_transactions')->where('id', $id)->find_one();
$ui->assign('in', $d);
$in = ORM::for_table('tbl_transactions')->where('id', $id)->find_one();
$ui->assign('in', $in);
if (!empty($routes['3']) && $routes['3'] == 'send') {
$c = ORM::for_table('tbl_customers')->where('username', $d['username'])->find_one();
$c = ORM::for_table('tbl_customers')->where('username', $in['username'])->find_one();
if ($c) {
Message::sendInvoice($c, $d);
Message::sendInvoice($c, $in);
r2(U . 'prepaid/view/' . $id, 's', "Success send to customer");
}
r2(U . 'prepaid/view/' . $id, 'd', "Customer not found");
}
Package::createInvoice($in);
$ui->assign('_title', 'View Invoice');
$ui->assign('date', Lang::dateAndTimeFormat($d['recharged_on'], $d['recharged_time']));
$ui->display('invoice.tpl');
break;
@ -163,6 +161,10 @@ switch ($action) {
case 'print':
$content = $_POST['content'];
if (!empty($content)) {
if ($_POST['nux'] == 'print') {
//header("Location: nux://print?text=".urlencode($content));
$ui->assign('nuxprint', "nux://print?text=" . urlencode($content));
}
$ui->assign('content', $content);
} else {
$id = _post('id');
@ -593,7 +595,7 @@ switch ($action) {
$content .= Lang::pad("", '=') . "\n";
$content .= Lang::pad($config['note'], ' ', 2) . "\n";
$ui->assign('_title', Lang::T('View'));
$ui->assign('wa', urlencode("```$content```"));
$ui->assign('whatsapp', urlencode("```$content```"));
$ui->display('voucher-view.tpl');
} else {
r2(U . 'prepaid/voucher/', 'e', Lang::T('Voucher Not Found'));
@ -632,8 +634,7 @@ switch ($action) {
$v1->user = $user['username'];
$v1->save();
$in = ORM::for_table('tbl_transactions')->where('username', $user['username'])->order_by_desc('id')->find_one();
$ui->assign('in', $in);
$ui->assign('date', date("Y-m-d H:i:s"));
Package::createInvoice($in);
$ui->display('invoice.tpl');
} else {
r2(U . 'prepaid/refill', 'e', "Failed to refill account");
@ -658,8 +659,7 @@ switch ($action) {
if (Package::rechargeUser($user, 'balance', $plan, "Deposit", $admin['fullname'])) {
$c = ORM::for_table('tbl_customers')->where('id', $user)->find_one();
$in = ORM::for_table('tbl_transactions')->where('username', $c['username'])->order_by_desc('id')->find_one();
$ui->assign('in', $in);
$ui->assign('date', date("Y-m-d H:i:s"));
Package::createInvoice($in);
$ui->display('invoice.tpl');
} else {
r2(U . 'prepaid/refill', 'e', "Failed to refill account");

View File

@ -441,5 +441,18 @@
"OTP_is_required_when_user_want_to_change_phone_number": "OTP is required when user want to change phone number",
"Rate": "Rate",
"Burst": "Burst",
"Editing_Bandwidth_will_not_automatically_update_the_plan__you_need_to_edit_the_plan_then_save_again": "Editing Bandwidth will not automatically update the plan, you need to edit the plan then save again"
"Editing_Bandwidth_will_not_automatically_update_the_plan__you_need_to_edit_the_plan_then_save_again": "Editing Bandwidth will not automatically update the plan, you need to edit the plan then save again",
"OTP_Method": "OTP Method",
"SMS": "SMS",
"WhatsApp": "WhatsApp",
"SMS_and_WhatsApp": "SMS and WhatsApp",
"The_method_which_OTP_will_be_sent_to_user": "The method which OTP will be sent to user",
"Report_Viewer": "Report Viewer",
"Super_Administrator": "Super Administrator",
"Send_To": "Send To",
"Resend": "Resend",
"Alert": "Alert",
"success": "success",
"Click_Here": "Click Here",
"danger": "danger"
}

View File

@ -65,5 +65,9 @@
],
"2024.2.20.1" : [
"DROP TABLE IF EXISTS `tbl_customers_meta`;"
],
"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`;"
]
}

47
ui/ui/alert.tpl Normal file
View File

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>{ucwords(Lang::T($type))} - {$_c['CompanyName']}</title>
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<link rel="shortcut icon" href="ui/ui/images/logo.png" type="image/x-icon" />
<link rel="stylesheet" href="ui/ui/styles/bootstrap.min.css">
<link rel="stylesheet" href="ui/ui/styles/modern-AdminLTE.min.css">
<meta http-equiv="refresh" content="3; url={$url}">
</head>
<body class="hold-transition lockscreen">
<div class="lockscreen-wrapper">
<div class="panel panel-{$type}">
<div class="panel-heading">{ucwords(Lang::T($type))}</div>
<div class="panel-body">
{$text}
</div>
<div class="panel-footer">
<a href="{$url}" id="button" class="btn btn-{$type} btn-block btn-block">{Lang::T('Click Here')} (3)</a>
</div>
</div>
<div class="lockscreen-footer text-center">
{$_c['CompanyName']}
</div>
</div>
<script>
var time = 3;
timer();
function timer() {
setTimeout(() => {
time--;
if (time > -1) {
document.getElementById("button").innerHTML = "{Lang::T('Click Here')} (" + time + ")";
timer();
}
}, 1000);
}
</script>
</body>
</html>

View File

@ -94,7 +94,7 @@
<p class="help-block col-md-4">edit at config.php</p>
</div>
</div>
<div class="panel-heading">
<div class="panel-heading" id="hide_dashboard_content">
<div class="btn-group pull-right">
<button class="btn btn-primary btn-xs" title="save" type="submit"><span
class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span></button>
@ -475,6 +475,21 @@
<p class="help-block col-md-4">{Lang::T('OTP is required when user want to change phone
number')}</p>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('OTP Method')}</label>
<div class="col-md-6">
<select name="phone_otp_type" id="phone_otp_type" class="form-control">
<option value="sms" {if $_c['phone_otp_type']=='sms' }selected="selected" {/if}>
{Lang::T('SMS')}
<option value="whatsapp" {if $_c['phone_otp_type']=='whatsapp' }selected="selected"
{/if}> {Lang::T('WhatsApp')}
<option value="both" {if $_c['phone_otp_type']=='both' }selected="selected" {/if}>
{Lang::T('SMS and WhatsApp')}
</option>
</select>
</div>
<p class="help-block col-md-4">{Lang::T('The method which OTP will be sent to user')}</p>
</div>
</div>
{* <div class="panel-heading" id="envato">
<div class="btn-group pull-right">

View File

@ -71,8 +71,8 @@
<div class="box-tools pull-right">
<button type="button" class="btn bg-teal btn-sm" data-widget="collapse"><i class="fa fa-minus"></i>
</button>
<button type="button" class="btn bg-teal btn-sm" data-widget="remove"><i class="fa fa-times"></i>
</button>
<a href="{$_url}settings/app#hide_dashboard_content" class="btn bg-teal btn-sm" ><i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="box-body border-radius-none">
@ -92,8 +92,8 @@
<div class="box-tools pull-right">
<button type="button" class="btn bg-teal btn-sm" data-widget="collapse"><i class="fa fa-minus"></i>
</button>
<button type="button" class="btn bg-teal btn-sm" data-widget="remove"><i class="fa fa-times"></i>
</button>
<a href="{$_url}settings/app#hide_dashboard_content" class="btn bg-teal btn-sm" ><i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="box-body border-radius-none">

View File

@ -15,47 +15,58 @@
</script>
</head>
<body topmargin="0" leftmargin="0" onload="printpage()">
<body topmargin="0" leftmargin="0" {if !$nuxprint} onload="printpage()" {/if}>
<div class="row">
<div class="col-md-12">
<div class="col-md-6">
<table width="200">
<tr>
<td>
{if $content}<pre style="border-style: none; background-color: white;">{$content}</pre>{else}
<pre style="border-style: none; background-color: white;"><b>{Lang::pad($_c['CompanyName'],' ', 2)}</b>
{Lang::pad($_c['address'],' ', 2)}
{Lang::pad($_c['phone'],' ', 2)}
{Lang::pad("", '=')}
{Lang::pads("Invoice", $in['invoice'], ' ')}
{Lang::pads(Lang::T('Date'), $date, ' ')}
{Lang::pads(Lang::T('Sales'), $_admin['fullname'], ' ')}
{Lang::pad("", '=')}
{Lang::pads(Lang::T('Type'), $in['type'], ' ')}
{Lang::pads(Lang::T('Plan Name'), $in['plan_name'], ' ')}
{Lang::pads(Lang::T('Plan Price'), Lang::moneyFormat($in['price']), ' ')}
{Lang::pad($in['method'], ' ', 2)}
{if $content}
<pre style="border-style: none; background-color: white;">{$content}</pre>{else}
<pre style="border-style: none; background-color: white;"><b>{Lang::pad($_c['CompanyName'],' ', 2)}</b>
{Lang::pad($_c['address'],' ', 2)}
{Lang::pad($_c['phone'],' ', 2)}
{Lang::pad("", '=')}
{Lang::pads("Invoice", $in['invoice'], ' ')}
{Lang::pads(Lang::T('Date'), $date, ' ')}
{Lang::pads(Lang::T('Sales'), $_admin['fullname'], ' ')}
{Lang::pad("", '=')}
{Lang::pads(Lang::T('Type'), $in['type'], ' ')}
{Lang::pads(Lang::T('Plan Name'), $in['plan_name'], ' ')}
{Lang::pads(Lang::T('Plan Price'), Lang::moneyFormat($in['price']), ' ')}
{Lang::pad($in['method'], ' ', 2)}
{Lang::pads(Lang::T('Username'), $in['username'], ' ')}
{Lang::pads(Lang::T('Password'), '**********', ' ')}
{if $in['type'] != 'Balance'}
{Lang::pads(Lang::T('Created On'), Lang::dateAndTimeFormat($in['recharged_on'],$in['recharged_time']), ' ')}
{Lang::pads(Lang::T('Expires On'), Lang::dateAndTimeFormat($in['expiration'],$in['time']), ' ')}
{/if}
{Lang::pad("", '=')}
{Lang::pad($_c['note'],' ', 2)}</pre>
{/if}
{Lang::pads(Lang::T('Username'), $in['username'], ' ')}
{Lang::pads(Lang::T('Password'), '**********', ' ')}
{if $in['type'] != 'Balance'}
{Lang::pads(Lang::T('Created On'), Lang::dateAndTimeFormat($in['recharged_on'],$in['recharged_time']), ' ')}
{Lang::pads(Lang::T('Expires On'), Lang::dateAndTimeFormat($in['expiration'],$in['time']), ' ')}
{/if}
{Lang::pad("", '=')}
{Lang::pad($_c['note'],' ', 2)}</pre>
{/if}
</td>
</tr>
</table>
{if $nuxprint}
<a href="{$nuxprint}" class="btn btn-success text-black btn-sm" name="nux" value="print">
<i class="glyphicon glyphicon-print"></i>
Nux Print
<i class="glyphicon glyphicon-phone"></i>
</a>
<br>
<iframe src="{$nuxprint}" style="height: 2px;"><iframe>
{/if}
</div>
</div>
<script src="ui/ui/scripts/jquery-1.10.2.js"></script>
<script src="ui/ui/scripts/jquery.min.js"></script>
<script src="ui/ui/scripts/bootstrap.min.js"></script>
{if isset($xfooter)}
{$xfooter}
{/if}
</body>
</html>

View File

@ -5,37 +5,30 @@
<div class="panel panel-hovered panel-primary panel-stacked mb30">
<div class="panel-heading">{$in['invoice']}</div>
<div class="panel-body">
<form class="form-horizontal" method="post" action="{$_url}prepaid/print" target="_blank">
<pre id="content"></pre>
<textarea class="hidden" id="formcontent" name="content">{Lang::pad($_c['CompanyName'],' ', 2)}
{Lang::pad($_c['address'],' ', 2)}
{Lang::pad($_c['phone'],' ', 2)}
{Lang::pad("", '=')}
{Lang::pads("Invoice", $in['invoice'], ' ')}
{Lang::pads(Lang::T('Date'), $date, ' ')}
{Lang::pads(Lang::T('Sales'), $_admin['fullname'], ' ')}
{Lang::pad("", '=')}
{Lang::pads(Lang::T('Type'), $in['type'], ' ')}
{Lang::pads(Lang::T('Plan Name'), $in['plan_name'], ' ')}
{Lang::pads(Lang::T('Plan Price'), Lang::moneyFormat($in['price']), ' ')}
{Lang::pad($in['method'], ' ', 2)}
{Lang::pads(Lang::T('Username'), $in['username'], ' ')}
{Lang::pads(Lang::T('Password'), '**********', ' ')}
{if $in['type'] != 'Balance'}
{Lang::pads(Lang::T('Created On'), Lang::dateAndTimeFormat($in['recharged_on'],$in['recharged_time']), ' ')}
{Lang::pads(Lang::T('Expires On'), Lang::dateAndTimeFormat($in['expiration'],$in['time']), ' ')}
{/if}
{Lang::pad("", '=')}
{Lang::pad($_c['note'],' ', 2)}</textarea>
<input type="hidden" name="id" value="{$in['id']}">
<a href="{$_url}prepaid/list" class="btn btn-primary btn-sm"><i
class="ion-reply-all"></i>{Lang::T('Finish')}</a>
<a href="{$_url}prepaid/view/{$in['id']}/send" class="btn btn-info text-black btn-sm"><i
class="glyphicon glyphicon-envelope"></i> {Lang::T("Resend To Customer")}</a>
<button type="submit" class="btn btn-default btn-sm"><i class="fa fa-print"></i>
{Lang::T('Click Here to Print')}</button>
</form>
<form class="form-horizontal" method="post" action="{$_url}prepaid/print" target="_blank">
<pre id="content"></pre>
<textarea class="hidden" id="formcontent" name="content">{$invoice}</textarea>
<input type="hidden" name="id" value="{$in['id']}">
<a href="{$_url}prepaid/list" class="btn btn-default btn-sm"><i
class="ion-reply-all"></i>{Lang::T('Finish')}</a>
<a href="https://api.whatsapp.com/send/?text={$whatsapp}" target="_blank"
class="btn btn-primary btn-sm">
<i class="glyphicon glyphicon-share"></i> WhatsApp</a>
<a href="{$_url}prepaid/view/{$in['id']}/send" class="btn btn-info text-black btn-sm"><i
class="glyphicon glyphicon-envelope"></i> {Lang::T("Resend")}</a>
<button type="submit" class="btn btn-info text-black btn-sm"><i class="glyphicon glyphicon-print"></i>
Print</button>
<a href="nux://print?text={urlencode($invoice)}"
class="btn btn-success text-black btn-sm hidden-md hidden-lg">
<i class="glyphicon glyphicon-phone"></i>
NuxPrint
</a>
<a href="https://github.com/hotspotbilling/android-printer"
class="btn btn-success text-black btn-sm hidden-xs hidden-sm" target="_blank">
<i class="glyphicon glyphicon-phone"></i>
NuxPrint
</a>
</form>
</div>
</div>
</div>

View File

@ -4,15 +4,15 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>{$_title} - {Lang::T('Register')}</title>
<title>{Lang::T('Register')} - {$_c['CompanyName']}</title>
<link rel="shortcut icon" href="ui/ui/images/logo.png" type="image/x-icon" />
<link rel="stylesheet" href="ui/ui/styles/bootstrap.min.css">
<link rel="stylesheet" href="ui/ui/styles/modern-AdminLTE.min.css">
<link rel="stylesheet" href="ui/ui/styles/sweetalert2.min.css" />
<script src="ui/ui/scripts/sweetalert2.all.min.js"></script>
</head>

View File

@ -4,15 +4,15 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>{$_title} - {Lang::T('Register')}</title>
<title>{Lang::T('Register')} - {$_c['CompanyName']}</title>
<link rel="shortcut icon" href="ui/ui/images/logo.png" type="image/x-icon" />
<link rel="stylesheet" href="ui/ui/styles/bootstrap.min.css">
<link rel="stylesheet" href="ui/ui/styles/modern-AdminLTE.min.css">
<link rel="stylesheet" href="ui/ui/styles/sweetalert2.min.css" />
<script src="ui/ui/scripts/sweetalert2.all.min.js"></script>
</head>

View File

@ -4,15 +4,15 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>{$_title} - {Lang::T('Register')}</title>
<title>{Lang::T('Register')} - {$_c['CompanyName']}</title>
<link rel="shortcut icon" href="ui/ui/images/logo.png" type="image/x-icon" />
<link rel="stylesheet" href="ui/ui/styles/bootstrap.min.css">
<link rel="stylesheet" href="ui/ui/styles/modern-AdminLTE.min.css">
<link rel="stylesheet" href="ui/ui/styles/sweetalert2.min.css" />
<script src="ui/ui/scripts/sweetalert2.all.min.js"></script>
</head>

View File

@ -21,10 +21,32 @@
<script>
$(document).ready(function() {
$('.select2').select2({theme: "bootstrap"});
});
$(document).ready(function() {
$('.select2tag').select2({theme: "bootstrap", tags: true});
var listAtts = document.querySelectorAll(`button[type="submit"]`);
listAtts.forEach(function(el) {
if (el.addEventListener) { // all browsers except IE before version 9
el.addEventListener("click", function() {
$(this).html(
`<span class="glyphicon glyphicon-refresh" role="status" aria-hidden="true"></span>`
);
setTimeout(() => {
$(this).prop("disabled", true);
}, 100);
}, false);
} else {
if (el.attachEvent) { // IE before version 9
el.attachEvent("click", function() {
$(this).html(
`<span class="glyphicon glyphicon-refresh" role="status" aria-hidden="true"></span>`
);
setTimeout(() => {
$(this).prop("disabled", true);
}, 100);
});
}
}
});
});
var listAtts = document.querySelectorAll(`[api-get-text]`);

View File

@ -79,6 +79,33 @@
el.innerHTML = data;
});
});
$(document).ready(function() {
var listAtts = document.querySelectorAll(`button[type="submit"]`);
listAtts.forEach(function(el) {
if (el.addEventListener) { // all browsers except IE before version 9
el.addEventListener("click", function() {
$(this).html(
`<span class="glyphicon glyphicon-refresh" role="status" aria-hidden="true"></span>`
);
setTimeout(() => {
$(this).prop("disabled", true);
}, 100);
}, false);
} else {
if (el.attachEvent) { // IE before version 9
el.attachEvent("click", function() {
$(this).html(
`<span class="glyphicon glyphicon-refresh" role="status" aria-hidden="true"></span>`
);
setTimeout(() => {
$(this).prop("disabled", true);
}, 100);
});
}
}
});
});
</script>
{/literal}

View File

@ -4,12 +4,12 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>{$_title} - {Lang::T('Login')}</title>
<title>{Lang::T('Login')} - {$_c['CompanyName']}</title>
<link rel="shortcut icon" href="ui/ui/images/logo.png" type="image/x-icon" />
<link rel="stylesheet" href="ui/ui/styles/bootstrap.min.css">
<link rel="stylesheet" href="ui/ui/styles/modern-AdminLTE.min.css">
</head>

View File

@ -4,13 +4,11 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>{$_title} - {Lang::T('Login')}</title>
<title>{Lang::T('Login')} - {$_c['CompanyName']}</title>
<link rel="shortcut icon" href="ui/ui/images/logo.png" type="image/x-icon" />
<link rel="stylesheet" href="ui/ui/styles/bootstrap.min.css">
<link rel="stylesheet" href="ui/ui/styles/modern-AdminLTE.min.css">
</head>
<body>

View File

@ -8,12 +8,23 @@
<pre id="content"></pre>
<textarea class="hidden" id="formcontent" name="content">{$print}</textarea>
<input type="hidden" name="id" value="{$in['id']}">
<a href="{$_url}prepaid/voucher" class="btn btn-primary btn-sm"><i
<a href="{$_url}prepaid/voucher" class="btn btn-default btn-sm"><i
class="ion-reply-all"></i>{Lang::T('Finish')}</a>
<a href="https://api.whatsapp.com/send/?text={$wa}" target="_blank" class="btn btn-info text-black btn-sm"><i
class="glyphicon glyphicon-envelope"></i> {Lang::T("Send To Customer")}</a>
<button type="submit" class="btn btn-default btn-sm"><i class="fa fa-print"></i>
{Lang::T('Click Here to Print')}</button>
<a href="https://api.whatsapp.com/send/?text={$whatsapp}" target="_blank"
class="btn btn-primary btn-sm">
<i class="glyphicon glyphicon-share"></i> WhatsApp</a>
<button type="submit" class="btn btn-info text-black btn-sm"><i class="glyphicon glyphicon-print"></i>
Print</button>
<a href="nux://print?text={urlencode($print)}"
class="btn btn-success text-black btn-sm hidden-md hidden-lg">
<i class="glyphicon glyphicon-phone"></i>
NuxPrint
</a>
<a href="https://github.com/hotspotbilling/android-printer"
class="btn btn-success text-black btn-sm hidden-xs hidden-sm" target="_blank">
<i class="glyphicon glyphicon-phone"></i>
NuxPrint
</a>
</form>
<javascript type="text/javascript">
</javascript>

View File

@ -1,3 +1,3 @@
{
"version": "2024.2.21"
"version": "2024.2.23.1"
}