Compare commits

...

169 Commits

Author SHA1 Message Date
177cdef1cd Add Location Picker 2024-03-22 21:21:23 +07:00
ffe913cb8f .htaccess allow update.php 2024-03-22 20:29:05 +07:00
75955de6c5 Fix Broadcast Message by @Focuslinkstech 2024-03-22 10:40:51 +07:00
11d97c153f Merge pull request #142 from Focuslinkstech/Development
bulk SMS/WA message improvement
2024-03-22 10:30:56 +07:00
44cded581a Enhancement in bulk SMS/WA message
Enhancement in  SMS/WA message sending
2024-03-21 16:52:52 +01:00
b8ae562367 2024.3.20 2024-03-20 16:06:42 +07:00
d6bcb4edfc Merge branch 'master' into Development 2024-03-20 09:55:27 +07:00
5d16ff9484 show prepaid or postpaid in list 2024-03-20 09:54:48 +07:00
c1f815535d compiled folder missing in installation 2024-03-20 09:29:40 +07:00
37a8187f5a delete unused file 2024-03-20 09:28:10 +07:00
ec5aeedd1b Merge pull request #140 from gerandonk/Development
fix validity period is more than one month
2024-03-20 09:28:00 +07:00
7dd27e3080 Merge pull request #139 from Focuslinkstech/Development
Update message.php
2024-03-20 09:27:47 +07:00
93ca9fa586 Update customers-view.tpl
add account type
2024-03-19 19:23:34 +01:00
de302d2656 Update customers-add.tpl
fix customer add
2024-03-19 18:59:05 +01:00
4d8cec1a88 Merge branch 'hotspotbilling:Development' into Development 2024-03-19 18:46:54 +01:00
477dd11caa fix validity period is more than one month 2024-03-19 23:54:49 +07:00
36eb5ebd3b fix 1 payment gateway 2024-03-19 20:47:31 +07:00
6e2e907d85 move account_type 2024-03-19 19:05:35 +07:00
c460cdd2d6 Merge branch 'master' into Development 2024-03-19 19:00:21 +07:00
5b7683ae30 Update message.php
fix placeholder bugs
2024-03-19 12:27:38 +01:00
ea743b6db6 update plan type 2024-03-19 18:21:38 +07:00
1a165662ca Merge pull request #136 from Focuslinkstech/Development
Update map-customer.tpl
2024-03-19 18:10:54 +07:00
21058d5c4e Update map-customer.tpl
fix Map
2024-03-19 09:08:30 +01:00
af3995b421 plan price to Note 2024-03-19 11:38:32 +07:00
e9240f462d Merge branch 'development' 2024-03-19 11:05:42 +07:00
5b3be79420 2024.3.19 2024-03-19 11:05:08 +07:00
8f595af9a1 Fix map url 2024-03-19 10:22:54 +07:00
393a1195a5 Merge pull request #135 from pro-cms/master
Added Business/Personal System
2024-03-19 09:46:16 +07:00
0dd12b717d Merge branch 'Development' into master 2024-03-19 09:46:08 +07:00
d7d6709944 Merge pull request #134 from ahmadhusein17/patch-3
Update message-bulk.tpl
2024-03-19 09:41:25 +07:00
ef187817cf Merge pull request #131 from Focuslinkstech/Development
add send message button
2024-03-19 09:36:40 +07:00
24e45db017 break; the line 2024-03-19 09:34:28 +07:00
0a67ea25b5 Update phpnuxbill.sql
add coordinates
2024-03-19 01:10:19 +01:00
f27964dde6 map and customer geo location added
added map and customer geo location, we advice you to change/edit the customer coordinates according to their location, so that you can see where the customer is located on the Map
2024-03-19 00:59:34 +01:00
5b0e782efd fix syntax phpnuxbill.sql 2024-03-19 00:12:38 +03:00
865df09116 fixed account type ui 2024-03-18 23:28:16 +03:00
f44d800400 edit ,add customer type 2024-03-18 23:25:39 +03:00
aae5b58d57 added edit customer account type 2024-03-18 23:23:52 +03:00
19d60da919 added plan type to order user account 2024-03-18 23:12:23 +03:00
7be8552784 added plan type to service class 2024-03-18 22:55:08 +03:00
b92efe3d30 added plan type to front ui 2024-03-18 22:50:46 +03:00
f769e7b798 added plan type to listing 2024-03-18 22:40:27 +03:00
15ae5c844f added plan_type and account_type 2024-03-18 22:33:10 +03:00
0aff5f437a Update message-bulk.tpl
Removed translation in placeholder contents
2024-03-18 19:57:55 +07:00
605fbb73a6 fix translation error
fix translation error
2024-03-18 13:52:33 +01:00
3d2af75e5b add send message button
add send message button in customer
 view details
2024-03-18 12:28:54 +01:00
130451e1ae Fix notification 2024-03-18 11:48:22 +07:00
d36f39af8f Merge pull request #130 from Focuslinkstech/Development
send single and Bulk SMS, WhatsApp or Both WA/SMS message to customers
2024-03-18 11:05:03 +07:00
518917aac6 Add Message Feature
you can now send single and Bulk SMS, WhatsApp or Both WA/SMS message to customers based on their groups, more groups will be added later
2024-03-18 01:35:48 +01:00
dbc3a2623c Update customers.tpl
Functionality to filter table rows based on admin input
2024-03-17 15:56:42 +01:00
d31edde9d6 prepaid to plan file 2024-03-16 20:41:24 +07:00
32943b40be Fix Bills Zero 2024-03-16 20:41:24 +07:00
23790d3258 Merge pull request #129 from gerandonk/Development
Fix loop disconnect to all Nas
2024-03-16 20:24:25 +07:00
ffa55cdee5 Fix loop disconnect to all Nas
Fix loop disconnect to all Nas but still detecting Hotspot Multylogin from other Nas
2024-03-16 19:50:45 +07:00
6f5d49cd2f Show Paid 2024-03-15 10:56:08 +07:00
850581d328 Fix instalment finished 2024-03-15 10:48:17 +07:00
1d0d3f13ab 2024.3.14 2024-03-15 10:43:49 +07:00
c82b6b6acf Change Attribute to Bill Only 2024-03-15 10:38:05 +07:00
532fbf7337 Active plan on user page 2024-03-15 09:46:01 +07:00
c4afd6da7f Additional Cost at Cron 2024-03-15 09:29:15 +07:00
a812e3a3e0 Merge pull request #128 from gerandonk/Development
postpaid always zero for first time recharge and invoice atribute for…
2024-03-15 09:24:02 +07:00
a15510e62a postpaid always zero for first time recharge and invoice atribute for next month
for postpaid customer invoice reminder and order get from invoice attribute
2024-03-15 04:07:30 +07:00
78d1634470 Send plan to friend will pay for Additional Cost 2024-03-14 14:55:49 +07:00
cc8d810d45 Additional Cost Customer side 2024-03-14 14:42:20 +07:00
68d3c9181c View Invoice from Customer side 2024-03-14 13:40:44 +07:00
e206a583fd Additional Cost, and Confirm Recharge 2024-03-14 12:14:11 +07:00
ca27c47b75 fix get attributes 2024-03-14 11:38:32 +07:00
2c67108cf1 add Additional Cycle and check if price is zero 2024-03-14 10:28:36 +07:00
dee4c78e93 Change Menu Names 2024-03-13 16:59:12 +07:00
a6c004e1cb $day_exp 2024-03-13 16:33:06 +07:00
8318bb4e6b Merge branch 'Development' 2024-03-13 16:29:44 +07:00
b27e0adca9 Fix onclick prepaid 2024-03-13 16:29:22 +07:00
2925d3a1e3 Merge branch 'Development' 2024-03-13 15:51:23 +07:00
add28c2fca Merge pull request #124 from Focuslinkstech/Development
Update dashboard.php
2024-03-13 15:41:57 +07:00
afbab3dd42 Update dashboard.php
fix reporting
2024-03-13 09:34:57 +01:00
b68e4d2e68 2024.3.13 2024-03-13 14:54:36 +07:00
c8f4574984 Recharge with additional Cost 2024-03-13 14:53:33 +07:00
60c573821b Additional Cost from Customer Attributes 2024-03-13 14:48:01 +07:00
e6e993cf21 Expired day postpaid 2024-03-13 14:40:47 +07:00
ca0edb4e17 Postpaid 2024-03-13 14:32:10 +07:00
ed9a411095 Fix install Plugin 2024-03-13 09:37:45 +07:00
c69fb1cae2 Merge branch 'Development' 2024-03-12 16:40:58 +07:00
d30aadc5e4 Expired Date by created date 2024-03-12 16:39:01 +07:00
b732cfd90e Recharge with balance or zero cost 2024-03-12 16:39:01 +07:00
46a56c12e3 admin can recharge disabled plan 2024-03-12 16:39:01 +07:00
9b2d42610a delete allow_purchase in cron 2024-03-12 16:39:01 +07:00
ef85bdb02f Invoice number not Random 2024-03-12 16:39:01 +07:00
23763ed308 Period in hotspot 2024-03-12 16:39:00 +07:00
9fcdf04005 Show From Customer 2024-03-12 16:39:00 +07:00
60babfa7b5 Change button 2024-03-12 16:39:00 +07:00
4cdde32cb1 Multiple Payment gateway Fix 2024-03-12 16:39:00 +07:00
538850b323 delete button 2024-03-12 16:39:00 +07:00
47393b4da9 Delete Plugin 2024-03-12 16:39:00 +07:00
87167b7770 change path 2024-03-12 16:39:00 +07:00
81572a61a4 delete payment gateway 2024-03-12 16:39:00 +07:00
3412ecc7de Fix Logic Multiple Payment gateway 2024-03-12 16:39:00 +07:00
3ab38897f9 change path to /gateway/ 2024-03-12 16:39:00 +07:00
8c2471d1d2 delete none 2024-03-12 16:39:00 +07:00
b0937a424a .htaccess Firewall 2024-03-12 16:39:00 +07:00
171b938d3a Check if Period Validity 2024-03-12 16:39:00 +07:00
61c1d25096 We are excited to introduce a new feature
I am delighted to announce that a highly requested feature has been added to Nuxbill! We now support Multiple Payment Gateways, allowing customers to choose their preferred payment method. This update brings greater flexibility and convenience to our users.
2024-03-12 16:39:00 +07:00
f885b8e8a3 Update dashboard.php
Fix when user purchase services with his/her balance it wont be added as income because the balance has been added earlier
2024-03-12 16:39:00 +07:00
2bb664e241 Expired Date by created date 2024-03-12 15:28:32 +07:00
c9058769ce Recharge with balance or zero cost 2024-03-12 15:09:00 +07:00
6d15437333 admin can recharge disabled plan 2024-03-12 13:58:42 +07:00
7c5958c8c1 delete allow_purchase in cron 2024-03-12 13:46:40 +07:00
1a4a0f2c10 Invoice number not Random 2024-03-12 12:12:36 +07:00
629d9e8ed4 Period in hotspot 2024-03-12 12:01:49 +07:00
b9e987570c Show From Customer 2024-03-12 11:54:20 +07:00
b95788262d Change button 2024-03-12 11:48:17 +07:00
3bb55320e3 Multiple Payment gateway Fix 2024-03-12 11:17:05 +07:00
7a9f937a9e delete button 2024-03-12 10:43:34 +07:00
c00e51adda Delete Plugin 2024-03-12 10:42:42 +07:00
0cc526e29a change path 2024-03-12 10:00:40 +07:00
16f0642007 delete payment gateway 2024-03-12 10:00:28 +07:00
e1f7b324cb Fix Logic Multiple Payment gateway 2024-03-12 09:33:45 +07:00
8f0ff3e786 change path to /gateway/ 2024-03-12 09:24:16 +07:00
9023f89456 delete none 2024-03-12 09:23:59 +07:00
140b756994 .htaccess Firewall 2024-03-12 09:07:12 +07:00
ca59c89e1d Check if Period Validity 2024-03-12 09:07:12 +07:00
4e23918999 Merge pull request #122 from Focuslinkstech/Development
We are excited to introduce a new feature
2024-03-12 09:06:43 +07:00
758a0a99a9 We are excited to introduce a new feature
I am delighted to announce that a highly requested feature has been added to Nuxbill! We now support Multiple Payment Gateways, allowing customers to choose their preferred payment method. This update brings greater flexibility and convenience to our users.
2024-03-11 09:34:25 +01:00
b6cf9bec0b Merge pull request #121 from Focuslinkstech/Development
Update dashboard.php
2024-03-11 14:43:13 +07:00
6e07c3ae85 Update dashboard.php
Fix when user purchase services with his/her balance it wont be added as income because the balance has been added earlier
2024-03-10 22:41:48 +01:00
ef76aadc16 Merge pull request #120 from hotspotbilling/Development
fix delete customer attribute
2024-03-08 17:50:06 +07:00
8e960107fc Merge pull request #119 from Focuslinkstech/Development
Bug Fix
2024-03-08 17:47:44 +07:00
c4e702ee2f Update customers.php
Fix Delete the Customers Attributes with the given field name, it delete all from the table which belong to other customers
2024-03-08 10:43:07 +01:00
08790e7295 Merge branch 'Development' of https://github.com/Focuslinkstech/phpnuxbill into Development 2024-03-08 09:37:56 +01:00
cfefd38a31 if ($p['validity_unit'] == 'Period') then add Expired Date 2024-03-06 12:03:24 +07:00
37a5ee8566 Change the view of Attributes Customer 2024-03-06 11:15:45 +07:00
e5c8aae758 2024.3.5 2024-03-05 16:20:18 +07:00
99d393d0c0 Merge pull request #118 from gerandonk/Development
change due date for period plan to customer field attribute
2024-03-05 16:18:32 +07:00
e6280d597b change due date for period plan to customer field attribute
admin can change expired date for period plan as wish before recharger customer
2024-03-05 16:08:33 +07:00
18db9cd280 hide if balance off 2024-03-05 11:15:38 +07:00
6aab647f48 Company name in login 2024-03-05 11:15:26 +07:00
b8b4623078 notification variable fix 2024-03-04 14:26:36 +07:00
6a79cff233 checkUserType when edit is neq 2024-03-04 11:30:09 +07:00
4c02283fd0 add full name in telegram notification 2024-03-04 10:06:19 +07:00
403de91fba sendPackageNotification with customer variable 2024-03-04 10:02:23 +07:00
4ee3743cf3 Fix Password send to admin 2024-03-04 09:57:12 +07:00
77e48dae8b add is file exists 2024-03-03 19:54:04 +07:00
0745532951 2024.3.3 2024-03-03 17:29:53 +07:00
b53116d22a Customer Announcement 2024-03-03 17:24:01 +07:00
f7df824145 Merge pull request #116 from gerandonk/Development
Development
2024-03-03 17:11:38 +07:00
f154322f99 Merge pull request #115 from Focuslinkstech/master
improvement
2024-03-03 17:10:06 +07:00
a76ba6ee8b update db for validity period 2024-03-03 11:30:34 +07:00
61b3f5b5f5 Add planwith validity period 2024-03-03 11:03:25 +07:00
b153e5b595 distinguish between announcements on the user dashboard and the login page 2024-03-03 11:00:42 +07:00
9ab0b6a0fa improvement
just replace the save loading with css for better loading feature
2024-03-02 12:40:04 +01:00
a7f191f058 damn, that curly bracket make error :)) 2024-03-01 19:42:59 +07:00
012a1ecfab allow purchase = no, but can recharge 2024-03-01 16:10:01 +07:00
dc70a49f52 upload path 2024-03-01 13:44:46 +07:00
bc7380eab7 add variable to global 2024-03-01 10:36:24 +07:00
f4da09a26e move hook before sending notification 2024-03-01 10:11:18 +07:00
de3312055a add hook when recharge 2024-03-01 09:57:59 +07:00
699289662b Fix Upload URL 2024-03-01 09:37:13 +07:00
bae079f71c Fix Hook Functionality 2024-02-29 13:32:46 +07:00
28f4624e8d change Customer menu 2024-02-29 11:37:54 +07:00
fbd215e741 Merge branch 'master' into Development 2024-02-29 09:26:19 +07:00
2437096473 $_c to $config in php file 2024-02-29 09:25:26 +07:00
dfeee540cf Fix variable $_c 2024-02-28 18:19:17 +07:00
a0b9e85f38 Add Expired date for reminder 2024-02-28 11:31:36 +07:00
08153e6ec1 Fix Buy Plan with Balance 2024-02-28 11:31:31 +07:00
2660f5d2d0 Dashboard 2 Column 2024-02-27 14:22:17 +07:00
82e67f0b83 fix Recharge 2024-02-27 13:12:53 +07:00
41dd0d86e7 Fix Recharge 2024-02-27 13:12:25 +07:00
c8004f1a27 fix update file 2024-02-27 13:10:06 +07:00
61edfb932a fix wrong logic != to == 2024-02-27 12:00:49 +07:00
afe6b34fd6 Update Package.php
fix package recharge bug
2024-02-26 18:03:48 +01:00
90 changed files with 3707 additions and 1695 deletions

3
.gitignore vendored
View File

@ -38,4 +38,5 @@ system/lan/**
!system/lan/spanish.json
!system/lan/turkish.json
!system/lan/english.json
!system/lan/country.json
!system/lan/country.json
*.zip

14
.htaccess_firewall Normal file
View File

@ -0,0 +1,14 @@
<Files *.php>
Order Deny,Allow
Deny from all
</Files>
<Files index.php>
Order Allow,Deny
Allow from all
</Files>
<Files update.php>
Order Allow,Deny
Allow from all
</Files>

View File

@ -2,6 +2,85 @@
# CHANGELOG
## 2024.3.22
- Fix Broadcast Message by @Focuslinkstech
- Add Location Picker
## 2024.3.20
- Fixing some bugs
## 2024.3.19
- Add Customer Type Personal or Bussiness by @pro-cms
- Fix Broadcast Message by @Focuslinkstech
- Add Customer Geolocation by @Focuslinkstech
- Change Customer Menu
## 2024.3.18
- Add Broadcasting SMS by @Focuslinkstech
- Fix Notification with Bills
## 2024.3.16
- Fix Zero Charging
- Fix Disconnect Customer from Radius without loop by @Gerandonk
## 2024.3.15
- Fix Customer View to list active Plan
- Additional Bill using Customer Attributes
## 2024.3.14
- Add Note to Invoices
- Add Additional Bill
- View Invoice from Customer side
## 2024.3.13
- Postpaid System
- Additional Cost
## 2024.3.12
- Check if Validity Period, so calculate price will not affected other validity
- Add firewall using .htaccess for apache only
- Multiple Payment Gateway by @Focuslinkstech
- Fix Logic Multiple Payment gateway
- Fix delete Attribute
- Allow Delete Payment Gateway
- Allow Delete Plugin
## 2024.3.6
- change attributes view
## 2024.3.4
- add [[username]] for reminder
- fix agent show when editing
- fix password admin when sending notification
- add file exists for pages
## 2024.3.3
- Change loading button by @Focuslinkstech
- Add Customer Announcements by @Gerandonk
- Add PPPOE Period Validity by @Gerandonk
## 2024.2.29
- Fix Hook Functionality
- Change Customer Menu
## 2024.2.28
- Fix Buy Plan with Balance
- Add Expired date for reminder
## 2024.2.27
- fix path notification

View File

@ -37,7 +37,6 @@ function _autoloader($class)
}
spl_autoload_register('_autoloader');
if (!file_exists($root_path . 'config.php')) {
$root_path .= '..' . DIRECTORY_SEPARATOR;
if (!file_exists($root_path . 'config.php')) {
@ -96,6 +95,7 @@ $result = ORM::for_table('tbl_appconfig')->find_many();
foreach ($result as $value) {
$config[$value['setting']] = $value['value'];
}
$_c = $config;
if (empty($http_proxy) && !empty($config['http_proxy'])) {
$http_proxy = $config['http_proxy'];
if (empty($http_proxyauth) && !empty($config['http_proxyauth'])) {
@ -237,7 +237,7 @@ function r2($to, $ntype = 'e', $msg = '')
exit;
}
function _alert($text, $type = 'success', $url = "home")
function _alert($text, $type = 'success', $url = "home", $time = 3)
{
global $ui;
if (!isset($ui)) return;
@ -250,8 +250,10 @@ function _alert($text, $type = 'success', $url = "home")
}
$ui->assign('text', $text);
$ui->assign('type', $type);
$ui->assign('time', $time);
$ui->assign('url', $url);
$ui->display('alert.tpl');
die();
}

View File

@ -26,8 +26,10 @@ CREATE TABLE `tbl_customers` (
`address` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci,
`phonenumber` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0',
`email` varchar(128) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '1',
`coordinates` VARCHAR(50) NOT NULL DEFAULT '' COMMENT 'Latitude and Longitude coordinates',
`balance` decimal(15,2) NOT NULL DEFAULT '0.00' COMMENT 'For Money Deposit',
`service_type` ENUM('Hotspot','PPPoE','Others') DEFAULT 'Others' COMMENT 'For selecting user type',
`account_type` ENUM('Business', 'Personal') DEFAULT 'Personal' COMMENT 'For selecting account type',
`auto_renewal` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Auto renewall using balance',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_login` datetime DEFAULT NULL
@ -79,26 +81,27 @@ CREATE TABLE `tbl_payment_gateway` (
DROP TABLE IF EXISTS `tbl_plans`;
CREATE TABLE `tbl_plans` (
`id` int(10) NOT NULL,
`name_plan` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`id_bw` int(10) NOT NULL,
`price` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`type` enum('Hotspot','PPPOE','Balance') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`typebp` enum('Unlimited','Limited') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`limit_type` enum('Time_Limit','Data_Limit','Both_Limit') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`time_limit` int(10) UNSIGNED DEFAULT NULL,
`time_unit` enum('Mins','Hrs') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`data_limit` int(10) UNSIGNED DEFAULT NULL,
`data_unit` enum('MB','GB') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`validity` int(10) NOT NULL,
`validity_unit` enum('Mins','Hrs','Days','Months') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`shared_users` int(10) DEFAULT NULL,
`routers` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`is_radius` tinyint(1) NOT NULL DEFAULT '0' COMMENT '1 is radius',
`pool` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`pool_expired` varchar(40) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0 disabled\r\n',
`allow_purchase` enum('yes','no') DEFAULT 'yes' COMMENT 'allow to show package in buy package page'
`id` int(10) NOT NULL,
`name_plan` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`id_bw` int(10) NOT NULL,
`price` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`type` enum('Hotspot','PPPOE','Balance') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`typebp` enum('Unlimited','Limited') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`limit_type` enum('Time_Limit','Data_Limit','Both_Limit') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`time_limit` int(10) UNSIGNED DEFAULT NULL,
`time_unit` enum('Mins','Hrs') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`data_limit` int(10) UNSIGNED DEFAULT NULL,
`data_unit` enum('MB','GB') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`validity` int(10) NOT NULL,
`validity_unit` enum('Mins','Hrs','Days','Months','Period') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`shared_users` int(10) DEFAULT NULL,
`routers` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`is_radius` tinyint(1) NOT NULL DEFAULT '0' COMMENT '1 is radius',
`pool` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`pool_expired` varchar(40) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0 disabled',
`allow_purchase` enum('yes','no') DEFAULT 'yes' COMMENT 'allow to show package in buy package page',
`plan_type` ENUM('Business', 'Personal') DEFAULT 'Personal' COMMENT 'For switching plan according to user type'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `tbl_pool`;
@ -315,4 +318,6 @@ ALTER TABLE `tbl_customers` ADD `created_by` INT NOT NULL DEFAULT '0' AFTER `aut
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`;
ALTER TABLE `tbl_user_recharges` ADD `admin_id` INT NOT NULL DEFAULT '1' AFTER `type`;
ALTER TABLE `tbl_plans` CHANGE `allow_purchase` `prepaid` ENUM('yes','no') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'yes' COMMENT 'is prepaid';
ALTER TABLE `tbl_transactions` ADD `note` VARCHAR(256) NOT NULL DEFAULT '' COMMENT 'for note' AFTER `type`;

View File

@ -1 +1,3 @@
Pengumuman!!<br>Besok libur<br><br>Announcement!!<br>Tomorrow holiday<br>
Pengumuman!!<br>Besok libur<br><br>Announcement!!<br>Tomorrow holiday<br><br>
<br>
This Announcement is for Login Page.

View File

@ -0,0 +1,8 @@
Pengumuman Pelanggan!!<br>
Besok libur<br>
<br>
Customer Announcement!!<br>
Tomorrow holiday<br>
<br>
<br>
This Announcement is for Customer Dashboard

19
system/.htaccess Normal file
View File

@ -0,0 +1,19 @@
<Files *.php>
Order Deny,Allow
Deny from all
</Files>
<Files cron.php>
Order Allow,Deny
Allow from all
</Files>
<Files api.php>
Order Allow,Deny
Allow from all
</Files>
<Files cron_reminder.php>
Order Allow,Deny
Allow from all
</Files>

View File

@ -38,6 +38,7 @@ function register_menu($name, $admin, $function, $position, $icon = '', $label =
$hook_registered = array();
function register_hook($action, $function){
global $hook_registered;
$hook_registered[] = [
'action' => $action,
'function' => $function

View File

@ -60,25 +60,30 @@ class Message
global $config;
run_hook('send_whatsapp'); #HOOK
if (!empty($config['wa_url'])) {
$waurl = str_replace('[number]', urlencode($phone), $config['wa_url']);
$waurl = str_replace('[number]', urlencode(Lang::phoneFormat($phone)), $config['wa_url']);
$waurl = str_replace('[text]', urlencode($txt), $waurl);
return Http::getData($waurl);
}
}
public static function sendPackageNotification($phone, $name, $package, $price, $message, $via)
public static function sendPackageNotification($customer, $package, $price, $message, $via)
{
$msg = str_replace('[[name]]', $name, $message);
global $u;
$msg = str_replace('[[name]]', $customer['fullname'], $message);
$msg = str_replace('[[username]]', $customer['username'], $msg);
$msg = str_replace('[[package]]', $package, $msg);
$msg = str_replace('[[price]]', $price, $msg);
if($u){
$msg = str_replace('[[expired_date]]', Lang::dateAndTimeFormat($u['expiration'], $u['time']), $msg);
}
if (
!empty($phone) && strlen($phone) > 5
!empty($customer['phonenumber']) && strlen($customer['phonenumber']) > 5
&& !empty($message) && in_array($via, ['sms', 'wa'])
) {
if ($via == 'sms') {
Message::sendSMS($phone, $msg);
Message::sendSMS($customer['phonenumber'], $msg);
} else if ($via == 'wa') {
Message::sendWhatsapp($phone, $msg);
Message::sendWhatsapp($customer['phonenumber'], $msg);
}
}
return "$via: $msg";
@ -111,6 +116,9 @@ class Message
$textInvoice = str_replace('[[phone]]', $config['phone'], $textInvoice);
$textInvoice = str_replace('[[invoice]]', $trx['invoice'], $textInvoice);
$textInvoice = str_replace('[[date]]', Lang::dateAndTimeFormat($trx['recharged_on'], $trx['recharged_time']), $textInvoice);
if (!empty($trx['note'])) {
$textInvoice = str_replace('[[note]]', $trx['note'], $textInvoice);
}
$gc = explode("-", $trx['method']);
$textInvoice = str_replace('[[payment_gateway]]', trim($gc[0]), $textInvoice);
$textInvoice = str_replace('[[payment_channel]]', trim($gc[1]), $textInvoice);
@ -118,8 +126,11 @@ class Message
$textInvoice = str_replace('[[plan_name]]', $trx['plan_name'], $textInvoice);
$textInvoice = str_replace('[[plan_price]]', Lang::moneyFormat($trx['price']), $textInvoice);
$textInvoice = str_replace('[[name]]', $cust['fullname'], $textInvoice);
$textInvoice = str_replace('[[note]]', $cust['note'], $textInvoice);
$textInvoice = str_replace('[[user_name]]', $trx['username'], $textInvoice);
$textInvoice = str_replace('[[user_password]]', $cust['password'], $textInvoice);
$textInvoice = str_replace('[[username]]', $trx['username'], $textInvoice);
$textInvoice = str_replace('[[password]]', $cust['password'], $textInvoice);
$textInvoice = str_replace('[[expired_date]]', Lang::dateAndTimeFormat($trx['expiration'], $trx['time']), $textInvoice);
$textInvoice = str_replace('[[footer]]', $config['note'], $textInvoice);

View File

@ -17,9 +17,9 @@ class Package
* @param string $channel channel payment gateway
* @return boolean
*/
public static function rechargeUser($id_customer, $router_name, $plan_id, $gateway, $channel)
public static function rechargeUser($id_customer, $router_name, $plan_id, $gateway, $channel, $note = '')
{
global $config, $admin;
global $config, $admin, $c, $p, $b, $t, $d, $zero;
$date_now = date("Y-m-d H:i:s");
$date_only = date("Y-m-d");
$time_only = date("H:i:s");
@ -30,11 +30,52 @@ class Package
}
$c = ORM::for_table('tbl_customers')->where('id', $id_customer)->find_one();
$p = ORM::for_table('tbl_plans')->where('id', $plan_id)->where('enabled', '1')->find_one();
$p = ORM::for_table('tbl_plans')->where('id', $plan_id)->find_one();
$add_cost = 0;
$bills = [];
// Zero cost recharge
if (isset($zero) && $zero == 1) {
$p['price'] = 0;
} else {
// Additional cost
list($bills, $add_cost) = User::getBills($id_customer);
if ($add_cost > 0 && $router_name != 'balance') {
foreach ($bills as $k => $v) {
$note .= $k . " : " . Lang::moneyFormat($v) . "\n";
}
}
}
if (!$p['enabled']) {
if (!isset($admin) || !isset($admin['id']) || empty($admin['id'])) {
r2(U . 'home', 'e', Lang::T('Plan Not found'));
}
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
r2(U . 'dashboard', 'e', Lang::T('Plan Not found'));
}
}
if ($p['validity_unit'] == 'Period') {
$day_exp = User::getAttribute("Expired Date", $c['id']); //ORM::for_table('tbl_customers_fields')->where('field_name', 'Expired Date')->where('customer_id', $c['id'])->find_one();
if (!$day_exp) {
$day_exp = 20;
// $day_exp = date('d', strtotime($c['created_at']));
// if (empty($day_exp) || $day_exp > 28) {
// $day_exp = 1;
// }
$f = ORM::for_table('tbl_customers_fields')->create();
$f->customer_id = $c['id'];
$f->field_name = 'Expired Date';
$f->field_value = $day_exp;
$f->save();
}
}
if ($router_name == 'balance') {
// insert table transactions
$inv = "INV-" . Package::_raid(5);
$inv = "INV-" . Package::_raid();
$t = ORM::for_table('tbl_transactions')->create();
$t->invoice = $inv;
$t->username = $c['username'];
@ -48,8 +89,8 @@ class Package
$t->routers = $router_name;
$t->type = "Balance";
if ($admin) {
$t->admin_id = $admin['id'];
}else{
$t->admin_id = ($admin['id']) ? $admin['id'] : '0';
} else {
$t->admin_id = '0';
}
$t->save();
@ -86,17 +127,49 @@ class Package
}
/**
* 1 Customer only can have 1 PPPOE and 1 Hotspot Plan
* 1 Customer only can have 1 PPPOE and 1 Hotspot Plan, 1 prepaid and 1 postpaid
*/
$b = ORM::for_table('tbl_user_recharges')
->select('tbl_user_recharges.id', 'id')
->select('customer_id')
->select('username')
->select('plan_id')
->select('namebp')
->select('recharged_on')
->select('recharged_time')
->select('expiration')
->select('time')
->select('status')
->select('method')
->select('tbl_user_recharges.routers', 'routers')
->select('tbl_user_recharges.type', 'type')
->select('admin_id')
->select('prepaid')
->where('customer_id', $id_customer)
->where('routers', $router_name)
->where('Type', $p['type'])
->where('tbl_user_recharges.routers', $router_name)
->where('tbl_user_recharges.Type', $p['type'])
->where('prepaid', $p['prepaid'])
->join('tbl_plans', array('tbl_plans.id', '=', 'tbl_user_recharges.plan_id'))
->find_one();
run_hook("recharge_user");
$mikrotik = Mikrotik::info($router_name);
if ($p['validity_unit'] == 'Months') {
$date_exp = date("Y-m-d", strtotime('+' . $p['validity'] . ' month'));
} else if ($p['validity_unit'] == 'Period') {
$date_tmp = date("Y-m-$day_exp", strtotime('+' . $p['validity'] . ' month'));
$dt1 = new DateTime("$date_only");
$dt2 = new DateTime("$date_tmp");
$diff = $dt2->diff($dt1);
$sum = $diff->format("%a"); // => 453
if ($sum >= 35 * $p['validity']) {
$date_exp = date("Y-m-$day_exp", strtotime('+0 month'));
} else {
$date_exp = date("Y-m-$day_exp", strtotime('+' . $p['validity'] . ' month'));
};
$time = date("23:59:00");
} else if ($p['validity_unit'] == 'Days') {
$date_exp = date("Y-m-d", strtotime('+' . $p['validity'] . ' day'));
} else if ($p['validity_unit'] == 'Hrs') {
@ -116,6 +189,9 @@ class Package
if ($p['validity_unit'] == 'Months') {
$date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
$time = $b['time'];
} else if ($p['validity_unit'] == 'Period') {
$date_exp = date("Y-m-$day_exp", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
$time = date("23:59:00");
} else if ($p['validity_unit'] == 'Days') {
$date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' days'));
$time = $b['time'];
@ -152,31 +228,66 @@ class Package
$b->routers = $router_name;
$b->type = "Hotspot";
if ($admin) {
$b->admin_id = $admin['id'];
}else{
$b->admin_id = ($admin['id']) ? $admin['id'] : '0';
} else {
$b->admin_id = '0';
}
$b->save();
// insert table transactions
$t = ORM::for_table('tbl_transactions')->create();
$t->invoice = "INV-" . Package::_raid(5);
$t->invoice = "INV-" . Package::_raid();
$t->username = $c['username'];
$t->plan_name = $p['name_plan'];
$t->price = $p['price'];
if ($p['validity_unit'] == 'Period') {
// Postpaid price from field
$add_inv = User::getAttribute("Invoice", $id_customer);
if (empty($add_inv) or $add_inv == 0) {
$t->price = $p['price'] + $add_cost;
} else {
$t->price = $add_inv + $add_cost;
}
} else {
$t->price = $p['price'] + $add_cost;
}
$t->recharged_on = $date_only;
$t->recharged_time = $time_only;
$t->expiration = $date_exp;
$t->time = $time;
$t->method = "$gateway - $channel";
$t->routers = $router_name;
$t->note = $note;
$t->type = "Hotspot";
if ($admin) {
$t->admin_id = $admin['id'];
}else{
$t->admin_id = ($admin['id']) ? $admin['id'] : '0';
} else {
$t->admin_id = '0';
}
$t->save();
if ($p['validity_unit'] == 'Period') {
// insert price to fields for invoice next month
$fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
if (!$fl) {
$fl = ORM::for_table('tbl_customers_fields')->create();
$fl->customer_id = $c['id'];
$fl->field_name = 'Invoice';
$fl->field_value = $p['price'];
$fl->save();
} else {
$fl->customer_id = $c['id'];
$fl->field_value = $p['price'];
$fl->save();
}
}
Message::sendTelegram("#u$c[username] $c[fullname] #recharge #Hotspot \n" . $p['name_plan'] .
"\nRouter: " . $router_name .
"\nGateway: " . $gateway .
"\nChannel: " . $channel .
"\nPrice: " . Lang::moneyFormat($p['price']) .
"\nNote:\n" . $note);
} else {
if ($p['is_radius']) {
Radius::customerAddPlan($c, $p, "$date_exp $time");
@ -201,37 +312,71 @@ class Package
$d->routers = $router_name;
$d->type = "Hotspot";
if ($admin) {
$b->admin_id = $admin['id'];
}else{
$b->admin_id = '0';
$d->admin_id = ($admin['id']) ? $admin['id'] : '0';
} else {
$d->admin_id = '0';
}
$d->save();
// insert table transactions
$t = ORM::for_table('tbl_transactions')->create();
$t->invoice = "INV-" . Package::_raid(5);
$t->invoice = "INV-" . Package::_raid();
$t->username = $c['username'];
$t->plan_name = $p['name_plan'];
$t->price = $p['price'];
if ($p['validity_unit'] == 'Period') {
// Postpaid price always zero for first time
$t->price = 0 + $add_cost;
} else {
$t->price = $p['price'] + $add_cost;
}
$t->recharged_on = $date_only;
$t->recharged_time = $time_only;
$t->expiration = $date_exp;
$t->time = $time;
$t->method = "$gateway - $channel";
$t->routers = $router_name;
$t->note = $note;
$t->type = "Hotspot";
if ($admin) {
$t->admin_id = $admin['id'];
}else{
$t->admin_id = ($admin['id']) ? $admin['id'] : '0';
} else {
$t->admin_id = '0';
}
$t->save();
if ($p['validity_unit'] == 'Period' && $p['price'] != 0) {
// insert price to fields for invoice next month
$fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
if (!$fl) {
$fl = ORM::for_table('tbl_customers_fields')->create();
$fl->customer_id = $c['id'];
$fl->field_name = 'Invoice';
// Calculating Price
$sd = new DateTime("$date_only");
$ed = new DateTime("$date_exp");
$td = $ed->diff($sd);
$fd = $td->format("%a");
$gi = ($p['price'] / (30 * $p['validity'])) * $fd;
if ($gi > $p['price']) {
$fl->field_value = $p['price'];
} else {
$fl->field_value = $gi;
}
$fl->save();
} else {
$fl->customer_id = $c['id'];
$fl->field_value = $p['price'];
$fl->save();
}
}
Message::sendTelegram("#u$c[username] $c[fullname] #buy #Hotspot \n" . $p['name_plan'] .
"\nRouter: " . $router_name .
"\nGateway: " . $gateway .
"\nChannel: " . $channel .
"\nPrice: " . Lang::moneyFormat($p['price']) .
"\nNote:\n" . $note);
}
Message::sendTelegram("#u$c[username] #buy #Hotspot \n" . $p['name_plan'] .
"\nRouter: " . $router_name .
"\nGateway: " . $gateway .
"\nChannel: " . $channel .
"\nPrice: " . Lang::moneyFormat($p['price']));
} else {
if ($b) {
@ -240,6 +385,9 @@ class Package
if ($p['validity_unit'] == 'Months') {
$date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
$time = $b['time'];
} else if ($p['validity_unit'] == 'Period') {
$date_exp = date("Y-m-$day_exp", strtotime($b['expiration'] . ' +' . $p['validity'] . ' months'));
$time = date("23:59:00");
} else if ($p['validity_unit'] == 'Days') {
$date_exp = date("Y-m-d", strtotime($b['expiration'] . ' +' . $p['validity'] . ' days'));
$time = $b['time'];
@ -276,31 +424,65 @@ class Package
$b->routers = $router_name;
$b->type = "PPPOE";
if ($admin) {
$b->admin_id = $admin['id'];
}else{
$b->admin_id = ($admin['id']) ? $admin['id'] : '0';
} else {
$b->admin_id = '0';
}
$b->save();
// insert table transactions
$t = ORM::for_table('tbl_transactions')->create();
$t->invoice = "INV-" . Package::_raid(5);
$t->invoice = "INV-" . Package::_raid();
$t->username = $c['username'];
$t->plan_name = $p['name_plan'];
$t->price = $p['price'];
if ($p['validity_unit'] == 'Period') {
// Postpaid price from field
$add_inv = User::getAttribute("Invoice", $id_customer);
if (empty($add_inv) or $add_inv == 0) {
$t->price = $p['price'] + $add_cost;
} else {
$t->price = $add_inv + $add_cost;
}
} else {
$t->price = $p['price'] + $add_cost;
}
$t->recharged_on = $date_only;
$t->recharged_time = $time_only;
$t->expiration = $date_exp;
$t->time = $time;
$t->method = "$gateway - $channel";
$t->routers = $router_name;
$t->note = $note;
$t->type = "PPPOE";
if ($admin) {
$t->admin_id = $admin['id'];
}else{
$t->admin_id = ($admin['id']) ? $admin['id'] : '0';
} else {
$t->admin_id = '0';
}
$t->save();
if ($p['validity_unit'] == 'Period' && $p['price'] != 0) {
// insert price to fields for invoice next month
$fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
if (!$fl) {
$fl = ORM::for_table('tbl_customers_fields')->create();
$fl->customer_id = $c['id'];
$fl->field_name = 'Invoice';
$fl->field_value = $p['price'];
$fl->save();
} else {
$fl->customer_id = $c['id'];
$fl->field_value = $p['price'];
$fl->save();
}
}
Message::sendTelegram("#u$c[username] $c[fullname] #recharge #PPPOE \n" . $p['name_plan'] .
"\nRouter: " . $router_name .
"\nGateway: " . $gateway .
"\nChannel: " . $channel .
"\nPrice: " . Lang::moneyFormat($p['price']) .
"\nNote:\n" . $note);
} else {
if ($p['is_radius']) {
Radius::customerAddPlan($c, $p, "$date_exp $time");
@ -325,39 +507,76 @@ class Package
$d->routers = $router_name;
$d->type = "PPPOE";
if ($admin) {
$d->admin_id = $admin['id'];
}else{
$d->admin_id = ($admin['id']) ? $admin['id'] : '0';
} else {
$d->admin_id = '0';
}
$d->save();
// insert table transactions
$t = ORM::for_table('tbl_transactions')->create();
$t->invoice = "INV-" . Package::_raid(5);
$t->invoice = "INV-" . Package::_raid();
$t->username = $c['username'];
$t->plan_name = $p['name_plan'];
$t->price = $p['price'];
if ($p['validity_unit'] == 'Period') {
// Postpaid price always zero for first time
$t->price = 0 + $add_cost;
} else {
$t->price = $p['price'] + $add_cost;
}
$t->recharged_on = $date_only;
$t->recharged_time = $time_only;
$t->expiration = $date_exp;
$t->time = $time;
$t->method = "$gateway - $channel";
$t->note = $note;
$t->routers = $router_name;
if ($admin) {
$t->admin_id = $admin['id'];
}else{
$t->admin_id = ($admin['id']) ? $admin['id'] : '0';
} else {
$t->admin_id = '0';
}
$t->type = "PPPOE";
$t->save();
}
Message::sendTelegram("#u$c[username] #buy #PPPOE \n" . $p['name_plan'] .
"\nRouter: " . $router_name .
"\nGateway: " . $gateway .
"\nChannel: " . $channel .
"\nPrice: " . Lang::moneyFormat($p['price']));
}
if ($p['validity_unit'] == 'Period' && $p['price'] != 0) {
// insert price to fields for invoice next month
$fl = ORM::for_table('tbl_customers_fields')->where('field_name', 'Invoice')->where('customer_id', $c['id'])->find_one();
if (!$fl) {
$fl = ORM::for_table('tbl_customers_fields')->create();
$fl->customer_id = $c['id'];
$fl->field_name = 'Invoice';
// Calculating Price
$sd = new DateTime("$date_only");
$ed = new DateTime("$date_exp");
$td = $ed->diff($sd);
$fd = $td->format("%a");
$gi = ($p['price'] / (30 * $p['validity'])) * $fd;
if ($gi > $p['price']) {
$fl->field_value = $p['price'];
} else {
$fl->field_value = $gi;
}
$fl->save();
} else {
$fl->customer_id = $c['id'];
$fl->field_value = $p['price'];
$fl->save();
}
}
Message::sendTelegram("#u$c[username] $c[fullname] #buy #PPPOE \n" . $p['name_plan'] .
"\nRouter: " . $router_name .
"\nGateway: " . $gateway .
"\nChannel: " . $channel .
"\nPrice: " . Lang::moneyFormat($p['price']) .
"\nNote:\n" . $note);
}
}
if (is_array($bills) && count($bills) > 0) {
User::billsPaid($bills, $id_customer);
}
run_hook("recharge_user_finish");
Message::sendInvoice($c, $t);
return true;
}
@ -365,7 +584,7 @@ class Package
public static function changeTo($username, $plan_id, $from_id)
{
$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();
$p = ORM::for_table('tbl_plans')->where('id', $plan_id)->find_one();
$b = ORM::for_table('tbl_user_recharges')->find_one($from_id);
if ($p['routers'] == $b['routers'] && $b['routers'] != 'radius') {
$mikrotik = Mikrotik::info($p['routers']);
@ -442,9 +661,9 @@ class Package
}
public static function _raid($l)
public static function _raid()
{
return substr(str_shuffle(str_repeat('0123456789', $l)), 0, $l);
return ORM::for_table('tbl_transactions')->max('id') + 1;
}
/**
@ -463,7 +682,10 @@ class Package
$_admin = Admin::_info($in['admin_id']);
// if admin not deleted
if ($_admin) $admin = $_admin;
} else {
$admin['fullname'] = 'Customer';
}
$note = '';
//print
$invoice = Lang::pad($config['CompanyName'], ' ', 2) . "\n";
$invoice .= Lang::pad($config['address'], ' ', 2) . "\n";
@ -475,9 +697,28 @@ class Package
$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";
if (!empty($in['note'])) {
$in['note'] = str_replace("\r", "", $in['note']);
$tmp = explode("\n", $in['note']);
foreach ($tmp as $t) {
if (strpos($t, " : ") === false) {
if (!empty($t)) {
$note .= "$t\n";
}
} else {
$tmp2 = explode(" : ", $t);
$invoice .= Lang::pads($tmp2[0], $tmp2[1], ' ') . "\n";
}
}
}
$invoice .= Lang::pads(Lang::T('Total'), Lang::moneyFormat($in['price']), ' ') . "\n";
$method = explode("-", $in['method']);
$invoice .= Lang::pads($method[0], $method[1], ' ') . "\n";
if (!empty($note)) {
$invoice .= Lang::pad("", '=') . "\n";
$invoice .= Lang::pad($note, ' ', 2) . "\n";
}
$invoice .= Lang::pad("", '=') . "\n";
$invoice .= Lang::pads(Lang::T('Username'), $in['username'], ' ') . "\n";
$invoice .= Lang::pads(Lang::T('Password'), '**********', ' ') . "\n";
if ($in['type'] != 'Balance') {
@ -499,9 +740,26 @@ class Package
$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";
if (!empty($in['note'])) {
$invoice .= Lang::pad("", '=') . "\n";
foreach ($tmp as $t) {
if (strpos($t, " : ") === false) {
if (!empty($t)) {
$invoice .= Lang::pad($t, ' ', 2) . "\n";
}
} else {
$tmp2 = explode(" : ", $t);
$invoice .= Lang::pads($tmp2[0], $tmp2[1], ' ') . "\n";
}
}
}
$invoice .= Lang::pads(Lang::T('Total'), Lang::moneyFormat($in['price']), ' ') . "\n";
$invoice .= Lang::pads($method[0], $method[1], ' ') . "\n";
if (!empty($note)) {
$invoice .= Lang::pad("", '=') . "\n";
$invoice .= Lang::pad($note, ' ', 2) . "\n";
}
$invoice .= Lang::pad("", '=') . "\n";
$invoice .= Lang::pads(Lang::T('Username'), $in['username'], ' ') . "\n";
$invoice .= Lang::pads(Lang::T('Password'), '**********', ' ') . "\n";
if ($in['type'] != 'Balance') {
@ -511,6 +769,6 @@ class Package
$invoice .= Lang::pad("", '=') . "\n";
$invoice .= Lang::pad($config['note'], ' ', 2) . "\n";
$ui->assign('whatsapp', urlencode("```$invoice```"));
$ui->assign('in',$in);
$ui->assign('in', $in);
}
}

View File

@ -301,7 +301,11 @@ class Radius
if ($_app_stage == 'demo') {
return null;
}
$nas = Radius::getTableNas()->findMany();
/**
* Fix loop to all Nas but still detecting Hotspot Multylogin from other Nas
*/
$act = ORM::for_table('radacct')->where_raw("acctstoptime IS NULL")->where('username', $username)->find_one();
$nas = Radius::getTableNas()->where('nasname', $act['nasipaddress'])->find_many();
$count = count($nas) * 15;
set_time_limit($count);
$result = [];
@ -310,7 +314,7 @@ class Radius
if (!empty($n['ports'])) {
$port = $n['ports'];
}
$result[] = $n['nasname'] . ': ' . @shell_exec("echo 'User-Name = $username' | " . Radius::getClient() . " " . trim($n['nasname']) . ":$port disconnect '" . $n['secret'] . "'");
$result[] = $n['nasname'] . ': ' . @shell_exec("echo 'User-Name = $username,Framed-IP-Address = " . $act['framedipaddress'] . "' | radclient -x " . trim($n['nasname']) . ":$port disconnect '" . $n['secret'] . "'");
}
return $result;
}

View File

@ -8,15 +8,16 @@
class User
{
public static function getID(){
public static function getID()
{
global $db_password;
if(isset($_SESSION['uid']) && !empty($_SESSION['uid'])){
if (isset($_SESSION['uid']) && !empty($_SESSION['uid'])) {
return $_SESSION['uid'];
}else if(isset($_COOKIE['uid'])){
} else if (isset($_COOKIE['uid'])) {
// id.time.sha1
$tmp = explode('.',$_COOKIE['uid']);
if(sha1($tmp[0].'.'.$tmp[1].'.'.$db_password)==$tmp[2]){
if(time()-$tmp[1] < 86400*30){
$tmp = explode('.', $_COOKIE['uid']);
if (sha1($tmp[0] . '.' . $tmp[1] . '.' . $db_password) == $tmp[2]) {
if (time() - $tmp[1] < 86400 * 30) {
$_SESSION['uid'] = $tmp[0];
return $tmp[0];
}
@ -25,35 +26,174 @@ class User
return 0;
}
public static function setCookie($uid){
global $db_password;
if(isset($uid)){
$time = time();
setcookie('uid', $uid.'.'.$time.'.'.sha1($uid.'.'.$time.'.'.$db_password), time()+86400*30);
}
}
public static function removeCookie(){
if(isset($_COOKIE['uid'])){
setcookie('uid', '', time()-86400);
}
}
public static function _info()
public static function getBills($id = 0)
{
$id = User::getID();
if (!$id) {
$id = User::getID();
if (!$id) {
return [];
}
}
$addcost = 0;
$bills = [];
$attrs = User::getAttributes('Bill', $id);
foreach ($attrs as $k => $v) {
// if has : then its an installment
if (strpos($v, ":") === false) {
// Not installment
$bills[$k] = $v;
$addcost += $v;
} else {
// installment
list($cost, $rem) = explode(":", $v);
// :0 installment is done
if (!empty($rem)) {
$bills[$k] = $cost;
$addcost += $cost;
}
}
}
return [$bills, $addcost];
}
public static function billsPaid($bills, $id = 0)
{
if (!$id) {
$id = User::getID();
if (!$id) {
return [];
}
}
foreach ($bills as $k => $v) {
// if has : then its an installment
$v = User::getAttribute($k, $id);
if (strpos($v, ":") === false) {
// Not installment, no need decrement
} else {
// installment
list($cost, $rem) = explode(":", $v);
// :0 installment is done
if ($rem != 0) {
User::setAttribute($k, "$cost:".($rem - 1), $id);
}
}
}
}
public static function setAttribute($name, $value, $id = 0)
{
if (!$id) {
$id = User::getID();
if (!$id) {
return '';
}
}
$f = ORM::for_table('tbl_customers_fields')->where('field_name', $name)->where('customer_id', $id)->find_one();
if (!$f) {
$f = ORM::for_table('tbl_customers_fields')->create();
$f->customer_id = $id;
$f->field_name = $name;
$f->field_value = $value;
$f->save();
$result = $f->id();
if ($result) {
return $result;
}
} else {
$f->field_value = $value;
$f->save();
return $f['id'];
}
return 0;
}
public static function getAttribute($name, $id = 0)
{
if (!$id) {
$id = User::getID();
if (!$id) {
return [];
}
}
$f = ORM::for_table('tbl_customers_fields')->where('field_name', $name)->where('customer_id', $id)->find_one();
if ($f) {
return $f['field_value'];
}
return '';
}
public static function getAttributes($endWith, $id = 0)
{
if (!$id) {
$id = User::getID();
if (!$id) {
return [];
}
}
$attrs = [];
$f = ORM::for_table('tbl_customers_fields')->where_like('field_name', "%$endWith")->where('customer_id', $id)->find_many();
if ($f) {
foreach ($f as $k) {
$attrs[$k['field_name']] = $k['field_value'];
}
return $attrs;
}
return [];
}
public static function setCookie($uid)
{
global $db_password;
if (isset($uid)) {
$time = time();
setcookie('uid', $uid . '.' . $time . '.' . sha1($uid . '.' . $time . '.' . $db_password), time() + 86400 * 30);
}
}
public static function removeCookie()
{
if (isset($_COOKIE['uid'])) {
setcookie('uid', '', time() - 86400);
}
}
public static function _info($id = 0)
{
if (!$id) {
$id = User::getID();
}
$d = ORM::for_table('tbl_customers')->find_one($id);
if(empty($d['username'])){
if (empty($d['username'])) {
r2(U . 'logout', 'd', '');
}
return $d;
}
public static function _billing()
public static function _billing($id = 0)
{
$id = User::getID();
$d = ORM::for_table('tbl_user_recharges')->where('customer_id', $id)->find_many();
if (!$id) {
$id = User::getID();
}
$d = ORM::for_table('tbl_user_recharges')
->select('tbl_user_recharges.id', 'id')
->select('customer_id')
->select('username')
->select('plan_id')
->select('namebp')
->select('recharged_on')
->select('recharged_time')
->select('expiration')
->select('time')
->select('status')
->select('method')
->select('tbl_user_recharges.routers', 'routers')
->select('tbl_user_recharges.type', 'type')
->select('admin_id')
->select('prepaid')
->where('customer_id', $id)
->join('tbl_plans', array('tbl_plans.id', '=', 'tbl_user_recharges.plan_id'))
->find_many();
return $d;
}
}

View File

@ -78,9 +78,9 @@ $ui->assign('_domain', str_replace('www.', '', parse_url(APP_URL, PHP_URL_HOST))
$ui->assign('_url', APP_URL . '/index.php?_route=');
$ui->assign('_path', __DIR__);
$ui->assign('_c', $config);
$ui->assign('UPLOAD_PATH', $UPLOAD_PATH);
$ui->assign('CACHE_PATH', $CACHE_PATH);
$ui->assign('PAGES_PATH', $PAGES_PATH);
$ui->assign('UPLOAD_PATH', str_replace($root_path, '', $UPLOAD_PATH));
$ui->assign('CACHE_PATH', str_replace($root_path, '', $CACHE_PATH));
$ui->assign('PAGES_PATH', str_replace($root_path, '', $PAGES_PATH));
$ui->assign('_system_menu', 'dashboard');
function _msglog($type, $msg)

View File

@ -38,10 +38,18 @@ switch ($action) {
case 'plan':
$server = _post('server');
$jenis = _post('jenis');
if($server=='radius'){
$d = ORM::for_table('tbl_plans')->where('is_radius', 1)->where('type', $jenis)->where('enabled', '1')->find_many();
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();
}
}else{
$d = ORM::for_table('tbl_plans')->where('routers', $server)->where('type', $jenis)->where('enabled', '1')->find_many();
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();
}
}
$ui->assign('d', $d);

View File

@ -12,6 +12,13 @@ $ui->assign('_system_menu', 'customers');
$action = $routes['1'];
$ui->assign('_admin', $admin);
if (empty ($action)) {
$action = 'list';
}
$leafletpickerHeader = <<<EOT
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css">
EOT;
switch ($action) {
case 'list':
@ -45,7 +52,7 @@ switch ($action) {
case 'csv':
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
}
$cs = ORM::for_table('tbl_customers')
->select('tbl_customers.id', 'id')
@ -83,34 +90,64 @@ switch ($action) {
}
break;
case 'add':
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent', 'Sales'])) {
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent', 'Sales'])) {
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
}
$ui->assign('xheader', $leafletpickerHeader);
run_hook('view_add_customer'); #HOOK
$ui->display('customers-add.tpl');
break;
case 'recharge':
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent', 'Sales'])) {
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent', 'Sales'])) {
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
}
$id_customer = $routes['2'];
$b = ORM::for_table('tbl_user_recharges')->where('customer_id', $id_customer)->find_one();
$id_customer = $routes['2'];
$plan_id = $routes['3'];
$b = ORM::for_table('tbl_user_recharges')->where('customer_id', $id_customer)->where('plan_id', $plan_id)->find_one();
if ($b) {
if (Package::rechargeUser($id_customer, $b['routers'], $b['plan_id'], "Recharge", $admin['fullname'])) {
r2(U . 'customers/view/' . $id_customer, 's', 'Success Recharge Customer');
} else {
r2(U . 'customers/view/' . $id_customer, 'e', 'Customer plan is inactive');
$gateway = 'Recharge';
$channel = $admin['fullname'];
$cust = User::_info($id_customer);
$plan = ORM::for_table('tbl_plans')->find_one($b['plan_id']);
list($bills, $add_cost) = User::getBills($id_customer);
if ($using == 'balance' && $config['enable_balance'] == 'yes') {
if (!$cust) {
r2(U . 'plan/recharge', 'e', Lang::T('Customer not found'));
}
if (!$plan) {
r2(U . 'plan/recharge', 'e', Lang::T('Plan not found'));
}
if ($cust['balance'] < ($plan['price'] + $add_cost)) {
r2(U . 'plan/recharge', 'e', Lang::T('insufficient balance'));
}
$gateway = 'Recharge Balance';
}
if ($using == 'zero') {
$zero = 1;
$gateway = 'Recharge Zero';
}
$ui->assign('bills', $bills);
$ui->assign('add_cost', $add_cost);
$ui->assign('cust', $cust);
$ui->assign('gateway', $gateway);
$ui->assign('channel', $channel);
$ui->assign('server', $b['routers']);
$ui->assign('using', 'cash');
$ui->assign('plan', $plan);
$ui->display('recharge-confirm.tpl');
} else {
r2(U . 'customers/view/' . $id_customer, 'e', 'Cannot find active plan');
}
r2(U . 'customers/view/' . $id_customer, 'e', 'Cannot find active plan');
break;
case 'deactivate':
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
}
$id_customer = $routes['2'];
$b = ORM::for_table('tbl_user_recharges')->where('customer_id', $id_customer)->find_one();
$id_customer = $routes['2'];
$plan_id = $routes['3'];
$b = ORM::for_table('tbl_user_recharges')->where('customer_id', $id_customer)->where('plan_id', $plan_id)->find_one();
if ($b) {
$p = ORM::for_table('tbl_plans')->where('id', $b['plan_id'])->where('enabled', '1')->find_one();
$p = ORM::for_table('tbl_plans')->where('id', $b['plan_id'])->find_one();
if ($p) {
if ($p['is_radius']) {
Radius::customerDeactivate($b['username']);
@ -137,35 +174,36 @@ switch ($action) {
r2(U . 'customers/view/' . $id_customer, 'e', 'Cannot find active plan');
break;
case 'sync':
$id_customer = $routes['2'];
$b = ORM::for_table('tbl_user_recharges')->where('customer_id', $id_customer)->where('status', 'on')->find_one();
if ($b) {
$c = ORM::for_table('tbl_customers')->find_one($id_customer);
$p = ORM::for_table('tbl_plans')->where('id', $b['plan_id'])->where('enabled', '1')->find_one();
if ($p) {
if ($p['is_radius']) {
Radius::customerAddPlan($c, $p, $p['expiration'] . ' ' . $p['time']);
r2(U . 'customers/view/' . $id_customer, 's', 'Success sync customer to Radius');
} else {
$mikrotik = Mikrotik::info($b['routers']);
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
if ($b['type'] == 'Hotspot') {
Mikrotik::addHotspotUser($client, $p, $c);
} else if ($b['type'] == 'PPPOE') {
Mikrotik::addPpoeUser($client, $p, $c);
$id_customer = $routes['2'];
$bs = ORM::for_table('tbl_user_recharges')->where('customer_id', $id_customer)->where('status', 'on')->findMany();
if ($bs) {
$routers = [];
foreach ($bs as $b) {
$c = ORM::for_table('tbl_customers')->find_one($id_customer);
$p = ORM::for_table('tbl_plans')->where('id', $b['plan_id'])->where('enabled', '1')->find_one();
if ($p) {
$routers[] = $b['routers'];
if ($p['is_radius']) {
Radius::customerAddPlan($c, $p, $p['expiration'] . ' ' . $p['time']);
} else {
$mikrotik = Mikrotik::info($b['routers']);
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
if ($b['type'] == 'Hotspot') {
Mikrotik::addHotspotUser($client, $p, $c);
} else if ($b['type'] == 'PPPOE') {
Mikrotik::addPpoeUser($client, $p, $c);
}
}
r2(U . 'customers/view/' . $id_customer, 's', 'Success sync customer to Mikrotik');
}
} else {
r2(U . 'customers/view/' . $id_customer, 'e', 'Customer plan is inactive');
}
r2(U . 'customers/view/' . $id_customer, 's', 'Sync success to ' . implode(", ", $routers));
}
r2(U . 'customers/view/' . $id_customer, 'e', 'Cannot find active plan');
break;
case 'viewu':
$customer = ORM::for_table('tbl_customers')->where('username', $routes['2'])->find_one();
case 'view':
$id = $routes['2'];
$id = $routes['2'];
run_hook('view_customer'); #HOOK
if (!$customer) {
$customer = ORM::for_table('tbl_customers')->find_one($id);
@ -177,9 +215,11 @@ switch ($action) {
$customFields = ORM::for_table('tbl_customers_fields')
->where('customer_id', $customer['id'])
->find_many();
$v = $routes['3'];
if (empty($v) || $v == 'order') {
$v = $routes['3'];
if (empty ($v)) {
$v = 'activation';
}
if ($v == 'order') {
$v = 'order';
$paginator = Paginator::build(ORM::for_table('tbl_payment_gateway'), ['username' => $customer['username']]);
$order = ORM::for_table('tbl_payment_gateway')
@ -201,8 +241,7 @@ switch ($action) {
$ui->assign('paginator', $paginator);
$ui->assign('activation', $activation);
}
$package = ORM::for_table('tbl_user_recharges')->where('username', $customer['username'])->find_one();
$ui->assign('package', $package);
$ui->assign('packages', User::_billing($customer['id']));
$ui->assign('v', $v);
$ui->assign('d', $customer);
$ui->assign('customFields', $customFields);
@ -212,10 +251,10 @@ switch ($action) {
}
break;
case 'edit':
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent'])) {
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent'])) {
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
}
$id = $routes['2'];
$id = $routes['2'];
run_hook('edit_customer'); #HOOK
$d = ORM::for_table('tbl_customers')->find_one($id);
// Fetch the Customers Attributes values from the tbl_customers_fields table
@ -225,6 +264,7 @@ switch ($action) {
if ($d) {
$ui->assign('d', $d);
$ui->assign('customFields', $customFields);
$ui->assign('xheader', $leafletpickerHeader);
$ui->display('customers-edit.tpl');
} else {
r2(U . 'customers/list', 'e', $_L['Account_Not_Found']);
@ -233,9 +273,9 @@ switch ($action) {
case 'delete':
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
}
$id = $routes['2'];
$id = $routes['2'];
run_hook('delete_customer'); #HOOK
$d = ORM::for_table('tbl_customers')->find_one($id);
if ($d) {
@ -274,7 +314,8 @@ switch ($action) {
} catch (Throwable $e) {
}
try {
if($c) $c->delete();
if ($c)
$c->delete();
} catch (Exception $e) {
} catch (Throwable $e) {
}
@ -293,6 +334,8 @@ switch ($action) {
$address = _post('address');
$phonenumber = _post('phonenumber');
$service_type = _post('service_type');
$account_type = _post('account_type');
$coordinates = _post('coordinates');
//post Customers Attributes
$custom_field_names = (array) $_POST['custom_field_name'];
$custom_field_values = (array) $_POST['custom_field_value'];
@ -320,23 +363,25 @@ switch ($action) {
$d->password = $password;
$d->pppoe_password = $pppoe_password;
$d->email = $email;
$d->account_type = $account_type;
$d->fullname = $fullname;
$d->address = $address;
$d->created_by = $admin['id'];
$d->phonenumber = Lang::phoneFormat($phonenumber);
$d->service_type = $service_type;
$d->coordinates = $coordinates;
$d->save();
// Retrieve the customer ID of the newly created customer
$customerId = $d->id();
// Save Customers Attributes details
if (!empty($custom_field_names) && !empty($custom_field_values)) {
if (!empty ($custom_field_names) && !empty ($custom_field_values)) {
$totalFields = min(count($custom_field_names), count($custom_field_values));
for ($i = 0; $i < $totalFields; $i++) {
$name = $custom_field_names[$i];
$value = $custom_field_values[$i];
if (!empty($name)) {
if (!empty ($name)) {
$customField = ORM::for_table('tbl_customers_fields')->create();
$customField->customer_id = $customerId;
$customField->field_name = $name;
@ -354,12 +399,14 @@ switch ($action) {
case 'edit-post':
$username = Lang::phoneFormat(_post('username'));
$fullname = _post('fullname');
$account_type = _post('account_type');
$password = _post('password');
$pppoe_password = _post('pppoe_password');
$email = _post('email');
$address = _post('address');
$phonenumber = Lang::phoneFormat(_post('phonenumber'));
$service_type = _post('service_type');
$coordinates = _post('coordinates');
run_hook('edit_customer'); #HOOK
$msg = '';
if (Validator::Length($username, 35, 2) == false) {
@ -387,8 +434,8 @@ switch ($action) {
}
$oldusername = $d['username'];
$oldPppoePassword = $d['password'];
$oldPassPassword = $d['pppoe_password'];
$oldPppoePassword = $d['password'];
$oldPassPassword = $d['pppoe_password'];
$userDiff = false;
$pppoeDiff = false;
$passDiff = false;
@ -416,16 +463,18 @@ switch ($action) {
$d->pppoe_password = $pppoe_password;
$d->fullname = $fullname;
$d->email = $email;
$d->account_type = $account_type;
$d->address = $address;
$d->phonenumber = $phonenumber;
$d->service_type = $service_type;
$d->coordinates = $coordinates;
$d->save();
// Update Customers Attributes values in tbl_customers_fields table
foreach ($customFields as $customField) {
$fieldName = $customField['field_name'];
if (isset($_POST['custom_fields'][$fieldName])) {
if (isset ($_POST['custom_fields'][$fieldName])) {
$customFieldValue = $_POST['custom_fields'][$fieldName];
$customField->set('field_value', $customFieldValue);
$customField->save();
@ -433,7 +482,7 @@ switch ($action) {
}
// Add new Customers Attributess
if (isset($_POST['custom_field_name']) && isset($_POST['custom_field_value'])) {
if (isset ($_POST['custom_field_name']) && isset ($_POST['custom_field_value'])) {
$newCustomFieldNames = $_POST['custom_field_name'];
$newCustomFieldValues = $_POST['custom_field_value'];
@ -456,12 +505,13 @@ switch ($action) {
}
// Delete Customers Attributess
if (isset($_POST['delete_custom_fields'])) {
if (isset ($_POST['delete_custom_fields'])) {
$fieldsToDelete = $_POST['delete_custom_fields'];
foreach ($fieldsToDelete as $fieldName) {
// Delete the Customers Attributes with the given field name
ORM::for_table('tbl_customers_fields')
->where('field_name', $fieldName)
->where('customer_id', $id)
->delete_many();
}
}
@ -485,7 +535,7 @@ switch ($action) {
Mikrotik::removeHotspotActiveUser($client, $d['username']);
} else {
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
if (!empty($d['pppoe_password'])) {
if (!empty ($d['pppoe_password'])) {
Mikrotik::setPpoeUser($client, $c['username'], $d['pppoe_password']);
} else {
Mikrotik::setPpoeUser($client, $c['username'], $password);
@ -495,7 +545,7 @@ switch ($action) {
}
}
}
r2(U . 'customers/list', 's', 'User Updated Successfully');
r2(U . 'customers/view/' . $id, 's', 'User Updated Successfully');
} else {
r2(U . 'customers/edit/' . $id, 'e', $msg);
}

View File

@ -16,13 +16,18 @@ $first_day_month = date('Y-m-01');
$mdate = date('Y-m-d');
$month_n = date('n');
$iday = ORM::for_table('tbl_transactions')->where('recharged_on', $mdate)->sum('price');
$iday = ORM::for_table('tbl_transactions')
->where('recharged_on', $mdate)
->where_not_equal('method', 'Customer - Balance')
->where_not_equal('method', 'Recharge Balance - Administrator')
->sum('price');
if ($iday == '') {
$iday = '0.00';
}
$ui->assign('iday', $iday);
$imonth = ORM::for_table('tbl_transactions')->where_gte('recharged_on', $first_day_month)->where_lte('recharged_on', $mdate)->sum('price');
$imonth = ORM::for_table('tbl_transactions')->where_not_equal('method', 'Customer - Balance')->where_not_equal('method', 'Recharge Balance - Administrator')->where_gte('recharged_on', $first_day_month)->where_lte('recharged_on', $mdate)->sum('price');
if ($imonth == '') {
$imonth = '0.00';
}
@ -144,6 +149,8 @@ if (file_exists($cacheMSfile) && time() - filemtime($cacheMSfile) < 43200) {
->select_expr('MONTH(recharged_on)', 'month')
->select_expr('SUM(price)', 'total')
->where_raw("YEAR(recharged_on) = YEAR(CURRENT_DATE())") // Filter by the current year
->where_not_equal('method', 'Customer - Balance')
->where_not_equal('method', 'Recharge Balance - Administrator')
->group_by_expr('MONTH(recharged_on)')
->find_many();

View File

@ -62,10 +62,11 @@ switch ($action) {
$title = ' Reports [' . $mdate . ']';
$title = str_replace('-', ' ', $title);
$UPLOAD_URL_PATH = str_replace($root_path, '', $UPLOAD_PATH);
if (file_exists($UPLOAD_PATH . '/logo.png')) {
$logo = $UPLOAD_PATH . '/logo.png';
$logo = $UPLOAD_URL_PATH . '/logo.png';
} else {
$logo = $UPLOAD_PATH . '/logo.default.png';
$logo = $UPLOAD_URL_PATH . '/logo.default.png';
}
if ($x) {
@ -169,7 +170,7 @@ $style
$html
EOF;
$mpdf->WriteHTML($nhtml);
$mpdf->Output(date('Y-m-d') . Package::_raid(4) . '.pdf', 'D');
$mpdf->Output(date('Ymd_His') . '.pdf', 'D');
} else {
echo 'No Data';
}
@ -234,10 +235,12 @@ EOF;
$title = ' Reports [' . $mdate . ']';
$title = str_replace('-', ' ', $title);
$UPLOAD_URL_PATH = str_replace($root_path, '', $UPLOAD_PATH);
if (file_exists($UPLOAD_PATH . '/logo.png')) {
$logo = $UPLOAD_PATH . '/logo.png';
$logo = $UPLOAD_URL_PATH . '/logo.png';
} else {
$logo = $UPLOAD_PATH . '/logo.default.png';
$logo = $UPLOAD_URL_PATH . '/logo.default.png';
}
if ($x) {
@ -341,7 +344,7 @@ $style
$html
EOF;
$mpdf->WriteHTML($nhtml);
$mpdf->Output(date('Y-m-d') . Package::_raid(4) . '.pdf', 'D');
$mpdf->Output(date('Ymd_His') . '.pdf', 'D');
} else {
echo 'No Data';
}

View File

@ -99,9 +99,6 @@ if (isset($_GET['recharge']) && !empty($_GET['recharge'])) {
if(!$plan['enabled']){
r2(U . "home", 'e', 'Plan is not exists');
}
if($plan['allow_purchase'] != 'yes'){
r2(U . "home", 'e', 'Cannot recharge this plan');
}
if ($user['balance'] > $plan['price']) {
r2(U . "order/pay/$router[id]/$bill[plan_id]", 'e', 'Order Plan');
} else {

View File

@ -0,0 +1,47 @@
<?php
/**
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
**/
_admin();
$ui->assign('_system_menu', 'map');
$action = $routes['1'];
$ui->assign('_admin', $admin);
if (empty($action)) {
$action = 'customer';
}
switch ($action) {
case 'customer':
$c = ORM::for_table('tbl_customers')->find_many();
$customerData = [];
foreach ($c as $customer) {
if (!empty($customer->coordinates)) {
$customerData[] = [
'id' => $customer->id,
'name' => $customer->fullname,
'balance' => $customer->balance,
'address' => $customer->address,
'info' => Lang::T("Username") . ": " . $customer->username . " - " . Lang::T("Full Name") . ": " . $customer->fullname . " - " . Lang::T("Email") . ": " . $customer->email . " - " . Lang::T("Phone") . ": " . $customer->phonenumber . " - " . Lang::T("Service Type") . ": " . $customer->service_type,
'coordinates' => '[' . $customer->coordinates . ']',
];
}
}
$ui->assign('customers', $customerData);
$ui->assign('xheader', '<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css">');
$ui->assign('_title', Lang::T('Customer Geo Location Information'));
$ui->assign('xfooter', '<script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"></script>');
$ui->display('map-customer.tpl');
break;
default:
r2(U . 'map/customer', 'e', 'action not defined');
break;
}

View File

@ -0,0 +1,238 @@
<?php
/**
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
**/
_admin();
$ui->assign('_title', Lang::T('Send Message'));
$ui->assign('_system_menu', 'message');
$action = $routes['1'];
$ui->assign('_admin', $admin);
if (empty($action)) {
$action = 'send';
}
switch ($action) {
case 'send':
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent', 'Sales'])) {
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
}
$select2_customer = <<<EOT
<script>
document.addEventListener("DOMContentLoaded", function(event) {
$('#personSelect').select2({
theme: "bootstrap",
ajax: {
url: function(params) {
if(params.term != undefined){
return './index.php?_route=autoload/customer_select2&s='+params.term;
}else{
return './index.php?_route=autoload/customer_select2';
}
}
}
});
});
</script>
EOT;
if (isset($routes['2']) && !empty($routes['2'])) {
$ui->assign('cust', ORM::for_table('tbl_customers')->find_one($routes['2']));
}
$id = $routes['2'];
$ui->assign('id', $id);
$ui->assign('xfooter', $select2_customer);
$ui->display('message.tpl');
break;
case 'send-post':
// Check user permissions
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent', 'Sales'])) {
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
}
// Get form data
$id_customer = $_POST['id_customer'];
$message = $_POST['message'];
$via = $_POST['via'];
// Check if fields are empty
if ($id_customer == '' or $message == '' or $via == '') {
r2(U . 'message/send', 'e', Lang::T('All field is required'));
} else {
// Get customer details from the database
$c = ORM::for_table('tbl_customers')->find_one($id_customer);
// Replace placeholders in the message with actual values
$message = str_replace('[[name]]', $c['fullname'], $message);
$message = str_replace('[[user_name]]', $c['username'], $message);
$message = str_replace('[[phone]]', $c['phonenumber'], $message);
$message = str_replace('[[company_name]]', $config['CompanyName'], $message);
//Send the message
if ($via == 'sms' || $via == 'both') {
$smsSent = Message::sendSMS($c['phonenumber'], $message);
}
if ($via == 'wa' || $via == 'both') {
$waSent = Message::sendWhatsapp($c['phonenumber'], $message);
}
if (isset($smsSent) || isset($waSent)) {
r2(U . 'message/send', 's', Lang::T('Message Sent Successfully'));
} else {
r2(U . 'message/send', 'e', Lang::T('Failed to send message'));
}
}
break;
case 'send_bulk':
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin', 'Agent', 'Sales'])) {
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
}
// Get form data
$group = $_POST['group'];
$message = $_POST['message'];
$via = $_POST['via'];
$test = isset($_POST['test']) && $_POST['test'] === 'on' ? 'yes' : 'no';
$batch = $_POST['batch'];
$delay = $_POST['delay'];
// Initialize counters
$totalSMSSent = 0;
$totalSMSFailed = 0;
$totalWhatsappSent = 0;
$totalWhatsappFailed = 0;
$batchStatus = [];
if (_req('send') == 'now') {
// Check if fields are empty
if ($group == '' || $message == '' || $via == '') {
r2(U . 'message/send_bulk', 'e', Lang::T('All fields are required'));
} else {
// Get customer details from the database based on the selected group
if ($group == 'all') {
$customers = ORM::for_table('tbl_customers')->find_many()->as_array();
} elseif ($group == 'new') {
// Get customers created just a month ago
$customers = ORM::for_table('tbl_customers')->where_raw("DATE(created_at) >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)")->find_many()->as_array();
} elseif ($group == 'expired') {
// Get expired user recharges where status is 'off'
$expired = ORM::for_table('tbl_user_recharges')->where('status', 'off')->find_many();
$customer_ids = [];
foreach ($expired as $recharge) {
$customer_ids[] = $recharge->customer_id;
}
$customers = ORM::for_table('tbl_customers')->where_in('id', $customer_ids)->find_many()->as_array();
} elseif ($group == 'active') {
// Get active user recharges where status is 'on'
$active = ORM::for_table('tbl_user_recharges')->where('status', 'on')->find_many();
$customer_ids = [];
foreach ($active as $recharge) {
$customer_ids[] = $recharge->customer_id;
}
$customers = ORM::for_table('tbl_customers')->where_in('id', $customer_ids)->find_many()->as_array();
}
// Set the batch size
$batchSize = $batch;
// Calculate the number of batches
$totalCustomers = count($customers);
$totalBatches = ceil($totalCustomers / $batchSize);
// Loop through batches
for ($batchIndex = 0; $batchIndex < $totalBatches; $batchIndex++) {
// Get the starting and ending index for the current batch
$start = $batchIndex * $batchSize;
$end = min(($batchIndex + 1) * $batchSize, $totalCustomers);
$batchCustomers = array_slice($customers, $start, $end - $start);
// Loop through customers in the current batch and send messages
foreach ($batchCustomers as $customer) {
// Create a copy of the original message for each customer and save it as currentMessage
$currentMessage = $message;
$currentMessage = str_replace('[[name]]', $customer['fullname'], $currentMessage);
$currentMessage = str_replace('[[user_name]]', $customer['username'], $currentMessage);
$currentMessage = str_replace('[[phone]]', $customer['phonenumber'], $currentMessage);
$currentMessage = str_replace('[[company_name]]', $config['CompanyName'], $currentMessage);
// Send the message based on the selected method
if ($test === 'yes') {
// Only for testing, do not send messages to customers
$batchStatus[] = [
'name' => $customer['fullname'],
'phone' => $customer['phonenumber'],
'message' => $currentMessage,
'status' => 'Test Mode - Message not sent'
];
} else {
// Send the actual messages
if ($via == 'sms' || $via == 'both') {
$smsSent = Message::sendSMS($customer['phonenumber'], $currentMessage);
if ($smsSent) {
$totalSMSSent++;
$batchStatus[] = [
'name' => $customer['fullname'],
'phone' => $customer['phonenumber'],
'message' => $currentMessage,
'status' => 'SMS Message Sent'
];
} else {
$totalSMSFailed++;
$batchStatus[] = [
'name' => $customer['fullname'],
'phone' => $customer['phonenumber'],
'message' => $currentMessage,
'status' => 'SMS Message Failed'
];
}
}
if ($via == 'wa' || $via == 'both') {
$waSent = Message::sendWhatsapp($customer['phonenumber'], $currentMessage);
if ($waSent) {
$totalWhatsappSent++;
$batchStatus[] = [
'name' => $customer['fullname'],
'phone' => $customer['phonenumber'],
'message' => $currentMessage,
'status' => 'WhatsApp Message Sent'
];
} else {
$totalWhatsappFailed++;
$batchStatus[] = [
'name' => $customer['fullname'],
'phone' => $customer['phonenumber'],
'message' => $currentMessage,
'status' => 'WhatsApp Message Failed'
];
}
}
}
}
// Introduce a delay between each batch
if ($batchIndex < $totalBatches - 1) {
sleep($delay);
}
}
}
}
$ui->assign('batchStatus', $batchStatus);
$ui->assign('totalSMSSent', $totalSMSSent);
$ui->assign('totalSMSFailed', $totalSMSFailed);
$ui->assign('totalWhatsappSent', $totalWhatsappSent);
$ui->assign('totalWhatsappFailed', $totalWhatsappFailed);
$ui->display('message-bulk.tpl');
break;
default:
r2(U . 'message/send_sms', 'e', 'action not defined');
}

View File

@ -37,7 +37,7 @@ switch ($action) {
}
$ui->assign('_title', 'Top Up');
$ui->assign('_system_menu', 'balance');
$plans_balance = ORM::for_table('tbl_plans')->where('enabled', '1')->where('type', 'Balance')->where('allow_purchase', 'yes')->find_many();
$plans_balance = ORM::for_table('tbl_plans')->where('enabled', '1')->where('type', 'Balance')->where('prepaid', 'yes')->find_many();
$ui->assign('plans_balance', $plans_balance);
$ui->display('user-orderBalance.tpl');
break;
@ -47,26 +47,30 @@ switch ($action) {
}
$ui->assign('_title', 'Order Plan');
$ui->assign('_system_menu', 'package');
if (!empty($_SESSION['nux-router'])) {
$account_type = $user['account_type'];
if(empty($account_type)){
$account_type = 'Personal';
}
if (!empty ($_SESSION['nux-router'])) {
if ($_SESSION['nux-router'] == 'radius') {
$radius_pppoe = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 1)->where('type', 'PPPOE')->where('allow_purchase', 'yes')->find_many();
$radius_hotspot = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 1)->where('type', 'Hotspot')->where('allow_purchase', 'yes')->find_many();
$radius_pppoe = ORM::for_table('tbl_plans')->where('plan_type', $account_type)->where('enabled', '1')->where('is_radius', 1)->where('type', 'PPPOE')->where('prepaid', 'yes')->find_many();
$radius_hotspot = ORM::for_table('tbl_plans')->where('plan_type', $account_type)->where('enabled', '1')->where('is_radius', 1)->where('type', 'Hotspot')->where('prepaid', 'yes')->find_many();
} else {
$routers = ORM::for_table('tbl_routers')->where('id', $_SESSION['nux-router'])->find_many();
$rs = [];
foreach ($routers as $r) {
$rs[] = $r['name'];
}
$plans_pppoe = ORM::for_table('tbl_plans')->where('enabled', '1')->where_in('routers', $rs)->where('is_radius', 0)->where('type', 'PPPOE')->where('allow_purchase', 'yes')->find_many();
$plans_hotspot = ORM::for_table('tbl_plans')->where('enabled', '1')->where_in('routers', $rs)->where('is_radius', 0)->where('type', 'Hotspot')->where('allow_purchase', 'yes')->find_many();
$plans_pppoe = ORM::for_table('tbl_plans')->where('plan_type', $account_type)->where('enabled', '1')->where_in('routers', $rs)->where('is_radius', 0)->where('type', 'PPPOE')->where('prepaid', 'yes')->find_many();
$plans_hotspot = ORM::for_table('tbl_plans')->where('plan_type', $account_type)->where('enabled', '1')->where_in('routers', $rs)->where('is_radius', 0)->where('type', 'Hotspot')->where('prepaid', 'yes')->find_many();
}
} else {
$radius_pppoe = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 1)->where('type', 'PPPOE')->where('allow_purchase', 'yes')->find_many();
$radius_hotspot = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 1)->where('type', 'Hotspot')->where('allow_purchase', 'yes')->find_many();
$radius_pppoe = ORM::for_table('tbl_plans')->where('plan_type', $account_type)->where('enabled', '1')->where('is_radius', 1)->where('type', 'PPPOE')->where('prepaid', 'yes')->find_many();
$radius_hotspot = ORM::for_table('tbl_plans')->where('plan_type', $account_type)->where('enabled', '1')->where('is_radius', 1)->where('type', 'Hotspot')->where('prepaid', 'yes')->find_many();
$routers = ORM::for_table('tbl_routers')->find_many();
$plans_pppoe = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 0)->where('type', 'PPPOE')->where('allow_purchase', 'yes')->find_many();
$plans_hotspot = ORM::for_table('tbl_plans')->where('enabled', '1')->where('is_radius', 0)->where('type', 'Hotspot')->where('allow_purchase', 'yes')->find_many();
$plans_pppoe = ORM::for_table('tbl_plans')->where('plan_type', $account_type)->where('enabled', '1')->where('is_radius', 0)->where('type', 'PPPOE')->where('prepaid', 'yes')->find_many();
$plans_hotspot = ORM::for_table('tbl_plans')->where('plan_type', $account_type)->where('enabled', '1')->where('is_radius', 0)->where('type', 'Hotspot')->where('prepaid', 'yes')->find_many();
}
$ui->assign('routers', $routers);
$ui->assign('radius_pppoe', $radius_pppoe);
@ -84,7 +88,7 @@ switch ($action) {
run_hook('custome
r_find_unpaid'); #HOOK
if ($d) {
if (empty($d['pg_url_payment'])) {
if (empty ($d['pg_url_payment'])) {
r2(U . "order/buy/" . $trx['routers_id'] . '/' . $trx['plan_id'], 'w', Lang::T("Checking payment"));
} else {
r2(U . "order/view/" . $d['id'] . '/check/', 's', Lang::T("You have unpaid transaction"));
@ -100,11 +104,11 @@ switch ($action) {
->find_one($trxid);
run_hook('customer_view_payment'); #HOOK
// jika tidak ditemukan, berarti punya orang lain
if (empty($trx)) {
if (empty ($trx)) {
r2(U . "order/package", 'w', Lang::T("Payment not found"));
}
// jika url kosong, balikin ke buy
if (empty($trx['pg_url_payment'])) {
if (empty ($trx['pg_url_payment'])) {
r2(U . "order/buy/" . (($trx['routers_id'] == 0) ? $trx['routers'] : $trx['routers_id']) . '/' . $trx['plan_id'], 'w', Lang::T("Checking payment"));
}
if ($routes['3'] == 'check') {
@ -114,7 +118,7 @@ switch ($action) {
run_hook('customer_check_payment_status'); #HOOK
include $PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $trx['gateway'] . '.php';
call_user_func($trx['gateway'] . '_validate_config');
call_user_func($config['payment_gateway'] . '_get_status', $trx, $user);
call_user_func($trx['gateway'] . '_get_status', $trx, $user);
} else if ($routes['3'] == 'cancel') {
run_hook('customer_cancel_payment'); #HOOK
$trx->pg_paid_response = '{}';
@ -124,16 +128,16 @@ switch ($action) {
$trx = ORM::for_table('tbl_payment_gateway')
->where('username', $user['username'])
->find_one($trxid);
if ('midtrans' == $trx['gateway']) {
//Hapus invoice link
}
}
if (empty($trx)) {
if (empty ($trx)) {
r2(U . "order/package", 'e', Lang::T("Transaction Not found"));
}
$router = ORM::for_table('tbl_routers')->find_one($trx['routers_id']);
$router = Mikrotik::info($trx['routers']);
$plan = ORM::for_table('tbl_plans')->find_one($trx['plan_id']);
$bandw = ORM::for_table('tbl_bandwidth')->find_one($plan['id_bw']);
list($bills, $add_cost) = User::getBills($id_customer);
$ui->assign('bills', $bills);
$ui->assign('add_cost', $add_cost);
$ui->assign('trx', $trx);
$ui->assign('router', $router);
$ui->assign('plan', $plan);
@ -142,29 +146,27 @@ switch ($action) {
$ui->display('user-orderView.tpl');
break;
case 'pay':
if ($_c['enable_balance'] != 'yes' && $config['allow_balance_transfer'] != 'yes') {
if ($config['enable_balance'] != 'yes') {
r2(U . "order/package", 'e', Lang::T("Balance not enabled"));
}
$plan = ORM::for_table('tbl_plans')->where('enabled', '1')->find_one($routes['3']);
if (empty($plan)) {
if (empty ($plan)) {
r2(U . "order/package", 'e', Lang::T("Plan Not found"));
}
if (!$plan['enabled']) {
r2(U . "home", 'e', 'Plan is not exists');
}
if ($plan['allow_purchase'] != 'yes') {
r2(U . "home", 'e', 'Cannot recharge this plan');
}
if ($routes['2'] == 'radius') {
$router_name = 'radius';
} else {
$router_name = $plan['routers'];
}
list($bills, $add_cost) = User::getBills($id_customer);
if ($plan && $plan['enabled'] && $user['balance'] >= $plan['price']) {
if (Package::rechargeUser($user['id'], $router_name, $plan['id'], 'Customer', 'Balance')) {
// if success, then get the balance
Balance::min($user['id'], $plan['price']);
r2(U . "home", 's', Lang::T("Success to buy package"));
Balance::min($user['id'], $plan['price'] + $add_cost);
r2(U . "voucher/invoice/", 's', Lang::T("Success to buy package"));
} else {
r2(U . "order/package", 'e', Lang::T("Failed to buy package"));
Message::sendTelegram("Buy Package with Balance Failed\n\n#u$c[username] #buy \n" . $plan['name_plan'] .
@ -176,28 +178,31 @@ switch ($action) {
}
break;
case 'send':
if ($_c['enable_balance'] != 'yes') {
if ($config['enable_balance'] != 'yes') {
r2(U . "order/package", 'e', Lang::T("Balance not enabled"));
}
$ui->assign('_title', Lang::T('Buy for friend'));
$ui->assign('_system_menu', 'package');
$plan = ORM::for_table('tbl_plans')->find_one($routes['3']);
if (empty($plan)) {
if (empty ($plan)) {
r2(U . "order/package", 'e', Lang::T("Plan Not found"));
}
if (!$plan['enabled']) {
r2(U . "home", 'e', 'Plan is not exists');
}
if ($plan['allow_purchase'] != 'yes') {
r2(U . "home", 'e', 'Cannot recharge this plan');
}
if ($routes['2'] == 'radius') {
$router_name = 'radius';
} else {
$router_name = $plan['routers'];
}
if (isset($_POST['send']) && $_POST['send'] == 'plan') {
if (isset ($_POST['send']) && $_POST['send'] == 'plan') {
$target = ORM::for_table('tbl_customers')->where('username', _post('username'))->find_one();
list($bills, $add_cost) = User::getBills($target['id']);
if (!empty ($add_cost)) {
$ui->assign('bills', $bills);
$ui->assign('add_cost', $add_cost);
$plan['price'] += $add_cost;
}
if (!$target) {
r2(U . 'home', 'd', Lang::T('Username not found'));
}
@ -266,19 +271,49 @@ switch ($action) {
$ui->assign('plan', $plan);
$ui->display('user-sendPlan.tpl');
break;
case 'buy':
case 'gateway':
$ui->assign('_title', Lang::T('Select Payment Gateway'));
$ui->assign('_system_menu', 'package');
if (strpos($user['email'], '@') === false) {
r2(U . 'accounts/profile', 'e', Lang::T("Please enter your email address"));
}
if ($config['payment_gateway'] == 'none') {
r2(U . 'home', 'e', Lang::T("No Payment Gateway Available"));
$pgs = array_values(explode(',', $config['payment_gateway']));
if (count($pgs) == 0) {
sendTelegram("Payment Gateway not set, please set it in Settings");
_log(Lang::T("Payment Gateway not set, please set it in Settings"));
r2(U . "home", 'e', Lang::T("Failed to create Transaction.."));
}
if (!file_exists($PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $config['payment_gateway'] . '.php')) {
r2(U . 'home', 'e', Lang::T("No Payment Gateway Available"));
if (count($pgs) > 1) {
$ui->assign('pgs', $pgs);
//$ui->assign('pgs', $pgs);
$ui->assign('route2', $routes[2]);
$ui->assign('route3', $routes[3]);
//$ui->assign('plan', $plan);
$ui->display('user-selectGateway.tpl');
break;
} else {
if (empty ($pgs[0])) {
sendTelegram("Payment Gateway not set, please set it in Settings");
_log(Lang::T("Payment Gateway not set, please set it in Settings"));
r2(U . "home", 'e', Lang::T("Failed to create Transaction.."));
} else {
$_POST['gateway'] = $pgs[0];
}
}
case 'buy':
$gateway = _post('gateway');
if (empty ($gateway) && !empty ($_SESSION['gateway'])) {
$gateway = $_SESSION['gateway'];
} else if (!empty ($gateway)) {
$_SESSION['gateway'] = $gateway;
}
if (empty ($gateway)) {
r2(U . 'order/gateway/' . $routes[2] . '/' . $routes[3], 'w', Lang::T("Please select Payment Gateway"));
}
run_hook('customer_buy_plan'); #HOOK
include $PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $config['payment_gateway'] . '.php';
call_user_func($config['payment_gateway'] . '_validate_config');
include $PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $gateway . '.php';
call_user_func($gateway . '_validate_config');
if ($routes['2'] == 'radius') {
$router['id'] = 0;
@ -289,8 +324,8 @@ switch ($action) {
$router['id'] = 0;
$router['name'] = 'balance';
}
$plan = ORM::for_table('tbl_plans')->where('enabled', '1')->where('allow_purchase', 'yes')->find_one($routes['3']);
if (empty($router) || empty($plan)) {
$plan = ORM::for_table('tbl_plans')->where('enabled', '1')->find_one($routes['3']);
if (empty ($router) || empty ($plan)) {
r2(U . "order/package", 'e', Lang::T("Plan Not found"));
}
$d = ORM::for_table('tbl_payment_gateway')
@ -301,7 +336,7 @@ switch ($action) {
if ($d['pg_url_payment']) {
r2(U . "order/view/" . $d['id'], 'w', Lang::T("You already have unpaid transaction, cancel it or pay it."));
} else {
if ($config['payment_gateway'] == $d['gateway']) {
if ($gateway == $d['gateway']) {
$id = $d['id'];
} else {
$d->status = 4;
@ -309,27 +344,53 @@ switch ($action) {
}
}
}
if (empty($id)) {
$add_cost = 0;
if ($router['name'] != 'balance') {
list($bills, $add_cost) = User::getBills($id_customer);
}
if (empty ($id)) {
$d = ORM::for_table('tbl_payment_gateway')->create();
$d->username = $user['username'];
$d->gateway = $config['payment_gateway'];
$d->gateway = $gateway;
$d->plan_id = $plan['id'];
$d->plan_name = $plan['name_plan'];
$d->routers_id = $router['id'];
$d->routers = $router['name'];
$d->price = $plan['price'];
if ($plan['validity_unit'] == 'Period') {
// 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);
} else {
$d->price = ($add_inv + $add_cost);
}
} else {
$d->price = ($plan['price'] + $add_cost);
}
//$d->price = ($plan['price'] + $add_cost);
$d->created_date = date('Y-m-d H:i:s');
$d->status = 1;
$d->save();
$id = $d->id();
} else {
$d->username = $user['username'];
$d->gateway = $config['payment_gateway'];
$d->gateway = $gateway;
$d->plan_id = $plan['id'];
$d->plan_name = $plan['name_plan'];
$d->routers_id = $router['id'];
$d->routers = $router['name'];
$d->price = $plan['price'];
if ($plan['validity_unit'] == 'Period') {
// 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);
} else {
$d->price = ($add_inv + $add_cost);
}
} else {
$d->price = ($plan['price'] + $add_cost);
}
//$d->price = ($plan['price'] + $add_cost);
$d->created_date = date('Y-m-d H:i:s');
$d->status = 1;
$d->save();
@ -337,7 +398,7 @@ switch ($action) {
if (!$id) {
r2(U . "order/package/" . $d['id'], 'e', Lang::T("Failed to create Transaction.."));
} else {
call_user_func($config['payment_gateway'] . '_create_transaction', $d, $user);
call_user_func($gateway . '_create_transaction', $d, $user);
}
break;
default:

View File

@ -8,9 +8,35 @@
_admin();
$ui->assign('_system_menu', 'paymentgateway');
$action = alphanumeric($routes['1']);
$action = alphanumeric($routes[1]);
$ui->assign('_admin', $admin);
if ($action == 'delete') {
$pg = alphanumeric($routes[2]);
if (file_exists($PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $pg . '.php')) {
deleteFile($PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR, $pg);
}
r2(U . 'paymentgateway', 's', Lang::T('Payment Gateway Deleted'));
}
if (_post('save') == 'actives') {
$pgs = '';
if(is_array($_POST['pgs'])){
$pgs = implode(',', $_POST['pgs']);
}
$d = ORM::for_table('tbl_appconfig')->where('setting', 'payment_gateway')->find_one();
if ($d) {
$d->value = $pgs;
$d->save();
} else {
$d = ORM::for_table('tbl_appconfig')->create();
$d->setting = 'payment_gateway';
$d->value = $pgs;
$d->save();
}
r2(U . 'paymentgateway', 's', Lang::T('Payment Gateway saved successfully'));
}
if (file_exists($PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $action . '.php')) {
include $PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $action . '.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
@ -36,22 +62,22 @@ if (file_exists($PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $action . '.php'))
$pgs[] = str_replace('.php', '', $file);
}
}
if (isset($_POST['payment_gateway'])) {
$payment_gateway = _post('payment_gateway');
$d = ORM::for_table('tbl_appconfig')->where('setting', 'payment_gateway')->find_one();
if ($d) {
$d->value = $payment_gateway;
$d->save();
} else {
$d = ORM::for_table('tbl_appconfig')->create();
$d->setting = 'payment_gateway';
$d->value = $payment_gateway;
$d->save();
}
r2(U . 'paymentgateway', 's', Lang::T('Payment Gateway saved successfully'));
}
$ui->assign('_title', 'Payment Gateway Settings');
$ui->assign('pgs', $pgs);
$ui->assign('actives', explode(',', $config['payment_gateway']));
$ui->display('paymentgateway.tpl');
}
}
function deleteFile($path, $name)
{
$files = scandir($path);
foreach ($files as $file) {
if (is_file($path . $file) && strpos($file, $name) !== false) {
unlink($path . $file);
} else if (is_dir($path . $file) && !in_array($file, ['.', '..'])) {
deleteFile($path . $file . DIRECTORY_SEPARATOR, $name);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -32,9 +32,55 @@ if (file_exists($cache) && time() - filemtime($cache) < (24 * 60 * 60)) {
file_put_contents($cache, $data);
$json = json_decode($data, true);
}
switch ($action) {
case 'delete':
if (!is_writeable($CACHE_PATH)) {
r2(U . "pluginmanager", 'e', 'Folder cache/ is not writable');
}
if (!is_writeable($PLUGIN_PATH)) {
r2(U . "pluginmanager", 'e', 'Folder plugin/ is not writable');
}
set_time_limit(-1);
$tipe = $routes['2'];
$plugin = $routes['3'];
$file = $CACHE_PATH . DIRECTORY_SEPARATOR . $plugin . '.zip';
if (file_exists($file)) unlink($file);
if ($tipe == 'plugin') {
foreach ($json['plugins'] as $plg) {
if ($plg['id'] == $plugin) {
$fp = fopen($file, 'w+');
$ch = curl_init($plg['github'] . '/archive/refs/heads/master.zip');
curl_setopt($ch, CURLOPT_POST, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_exec($ch);
curl_close($ch);
fclose($fp);
$zip = new ZipArchive();
$zip->open($file);
$zip->extractTo($CACHE_PATH);
$zip->close();
$folder = $CACHE_PATH . File::pathFixer('/' . $plugin . '-main/');
if (!file_exists($folder)) {
$folder = $CACHE_PATH . File::pathFixer('/' . $plugin . '-master/');
}
if (!file_exists($folder)) {
r2(U . "pluginmanager", 'e', 'Extracted Folder is unknown');
}
scanAndRemovePath($folder, $PLUGIN_PATH . DIRECTORY_SEPARATOR);
File::deleteFolder($folder);
unlink($file);
r2(U . "pluginmanager", 's', 'Plugin ' . $plugin . ' has been deleted');
break;
}
}
break;
}
break;
case 'install':
if (!is_writeable($CACHE_PATH)) {
r2(U . "pluginmanager", 'e', 'Folder cache/ is not writable');
@ -45,7 +91,7 @@ switch ($action) {
set_time_limit(-1);
$tipe = $routes['2'];
$plugin = $routes['3'];
$file = $CACHE_PATH . File::pathFixer('/') . $plugin . '.zip';
$file = $CACHE_PATH . DIRECTORY_SEPARATOR . $plugin . '.zip';
if (file_exists($file)) unlink($file);
if ($tipe == 'plugin') {
foreach ($json['plugins'] as $plg) {
@ -127,3 +173,24 @@ switch ($action) {
$ui->assign('pgs', $json['payment_gateway']);
$ui->display('plugin-manager.tpl');
}
function scanAndRemovePath($source, $target)
{
$files = scandir($source);
foreach ($files as $file) {
if (is_file($source . $file)) {
if(file_exists($target.$file)){
unlink($target . $file);
}
} else if (is_dir($source . $file) && !in_array($file, ['.', '..'])) {
scanAndRemovePath($source. $file. DIRECTORY_SEPARATOR, $target. $file. DIRECTORY_SEPARATOR);
if(file_exists($target.$file)){
rmdir($target . $file);
}
}
}
if(file_exists($target)){
rmdir($target);
}
}

View File

@ -12,7 +12,7 @@ $action = $routes['1'];
$ui->assign('_admin', $admin);
if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) {
_alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard");
_alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard");
}
use PEAR2\Net\RouterOS;
@ -60,7 +60,7 @@ switch ($action) {
$rate = $plan['rate_up'] . $unitup . "/" . $plan['rate_down'] . $unitdown;
Mikrotik::addHotspotPlan($client, $plan['name_plan'], $plan['shared_users'], $rate);
$log .= "DONE : $plan[name_plan], $plan[shared_users], $rate<br>";
if (!empty($plan['pool_expired'])) {
if (!empty ($plan['pool_expired'])) {
Mikrotik::setHotspotExpiredPlan($client, 'EXPIRED NUXBILL ' . $plan['pool_expired'], $plan['pool_expired']);
$log .= "DONE Expired : EXPIRED NUXBILL $plan[pool_expired]<br>";
}
@ -105,7 +105,7 @@ switch ($action) {
$rate = $plan['rate_up'] . $unitup . "/" . $plan['rate_down'] . $unitdown;
Mikrotik::addPpoePlan($client, $plan['name_plan'], $plan['pool'], $rate);
$log .= "DONE : $plan[name_plan], $plan[pool], $rate<br>";
if (!empty($plan['pool_expired'])) {
if (!empty ($plan['pool_expired'])) {
Mikrotik::setPpoePlan($client, 'EXPIRED NUXBILL ' . $plan['pool_expired'], $plan['pool_expired'], '512K/512K');
$log .= "DONE Expired : EXPIRED NUXBILL $plan[pool_expired]<br>";
}
@ -142,7 +142,7 @@ switch ($action) {
break;
case 'edit':
$id = $routes['2'];
$id = $routes['2'];
$d = ORM::for_table('tbl_plans')->find_one($id);
if ($d) {
$ui->assign('d', $d);
@ -158,7 +158,7 @@ switch ($action) {
break;
case 'delete':
$id = $routes['2'];
$id = $routes['2'];
$d = ORM::for_table('tbl_plans')->find_one($id);
if ($d) {
@ -185,6 +185,7 @@ switch ($action) {
case 'add-post':
$name = _post('name');
$plan_type = _post('plan_type'); //Personal / Business
$radius = _post('radius');
$typebp = _post('typebp');
$limit_type = _post('limit_type');
@ -201,7 +202,7 @@ switch ($action) {
$pool_expired = _post('pool_expired');
$list_expired = _post('list_expired');
$enabled = _post('enabled');
$allow_purchase = _post('allow_purchase');
$prepaid = _post('prepaid');
$msg = '';
if (Validator::UnsignedNumber($validity) == false) {
@ -213,7 +214,7 @@ switch ($action) {
if ($name == '' or $id_bw == '' or $price == '' or $validity == '') {
$msg .= Lang::T('All field is required') . '<br>';
}
if (empty($radius)) {
if (empty ($radius)) {
if ($routers == '') {
$msg .= Lang::T('All field is required') . '<br>';
}
@ -251,6 +252,7 @@ switch ($action) {
$d->price = $price;
$d->type = 'Hotspot';
$d->typebp = $typebp;
$d->plan_type = $plan_type;
$d->limit_type = $limit_type;
$d->time_limit = $time_limit;
$d->time_unit = $time_unit;
@ -259,7 +261,7 @@ switch ($action) {
$d->validity = $validity;
$d->validity_unit = $validity_unit;
$d->shared_users = $sharedusers;
if (!empty($radius)) {
if (!empty ($radius)) {
$d->is_radius = 1;
$d->routers = '';
} else {
@ -269,7 +271,7 @@ switch ($action) {
$d->pool_expired = $pool_expired;
$d->list_expired = $list_expired;
$d->enabled = $enabled;
$d->allow_purchase = $allow_purchase;
$d->prepaid = $prepaid;
$d->save();
$plan_id = $d->id();
@ -279,7 +281,7 @@ switch ($action) {
$mikrotik = Mikrotik::info($routers);
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
Mikrotik::addHotspotPlan($client, $name, $sharedusers, $rate);
if (!empty($pool_expired)) {
if (!empty ($pool_expired)) {
Mikrotik::setHotspotExpiredPlan($client, 'EXPIRED NUXBILL ' . $pool_expired, $pool_expired);
}
}
@ -295,6 +297,7 @@ switch ($action) {
case 'edit-post':
$id = _post('id');
$name = _post('name');
$plan_type = _post('plan_type');
$id_bw = _post('id_bw');
$typebp = _post('typebp');
$price = _post('price');
@ -309,7 +312,7 @@ switch ($action) {
$pool_expired = _post('pool_expired');
$list_expired = _post('list_expired');
$enabled = _post('enabled');
$allow_purchase = _post('allow_purchase');
$prepaid = _post('prepaid');
$routers = _post('routers');
$msg = '';
if (Validator::UnsignedNumber($validity) == false) {
@ -354,7 +357,7 @@ switch ($action) {
$mikrotik = Mikrotik::info($routers);
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
Mikrotik::setHotspotPlan($client, $name, $sharedusers, $rate);
if (!empty($pool_expired)) {
if (!empty ($pool_expired)) {
Mikrotik::setHotspotExpiredPlan($client, 'EXPIRED NUXBILL ' . $pool_expired, $pool_expired);
}
}
@ -367,6 +370,7 @@ switch ($action) {
$d->time_limit = $time_limit;
$d->time_unit = $time_unit;
$d->data_limit = $data_limit;
$d->plan_type = $plan_type;
$d->data_unit = $data_unit;
$d->validity = $validity;
$d->validity_unit = $validity_unit;
@ -374,7 +378,7 @@ switch ($action) {
$d->pool_expired = $pool_expired;
$d->list_expired = $list_expired;
$d->enabled = $enabled;
$d->allow_purchase = $allow_purchase;
$d->prepaid = $prepaid;
$d->save();
r2(U . 'services/hotspot', 's', Lang::T('Data Updated Successfully'));
@ -414,7 +418,7 @@ switch ($action) {
case 'pppoe-edit':
$ui->assign('_title', Lang::T('PPPOE Plans'));
$id = $routes['2'];
$id = $routes['2'];
$d = ORM::for_table('tbl_plans')->find_one($id);
if ($d) {
$ui->assign('d', $d);
@ -435,7 +439,7 @@ switch ($action) {
break;
case 'pppoe-delete':
$id = $routes['2'];
$id = $routes['2'];
$d = ORM::for_table('tbl_plans')->find_one($id);
if ($d) {
@ -461,6 +465,7 @@ switch ($action) {
case 'pppoe-add-post':
$name = _post('name_plan');
$plan_type = _post('plan_type');
$radius = _post('radius');
$id_bw = _post('id_bw');
$price = _post('price');
@ -471,7 +476,7 @@ switch ($action) {
$pool_expired = _post('pool_expired');
$list_expired = _post('list_expired');
$enabled = _post('enabled');
$allow_purchase = _post('allow_purchase');
$prepaid = _post('prepaid');
$msg = '';
@ -484,7 +489,7 @@ switch ($action) {
if ($name == '' or $id_bw == '' or $price == '' or $validity == '' or $pool == '') {
$msg .= Lang::T('All field is required') . '<br>';
}
if (empty($radius)) {
if (empty ($radius)) {
if ($routers == '') {
$msg .= Lang::T('All field is required') . '<br>';
}
@ -520,10 +525,11 @@ switch ($action) {
$d->name_plan = $name;
$d->id_bw = $id_bw;
$d->price = $price;
$d->plan_type = $plan_type;
$d->validity = $validity;
$d->validity_unit = $validity_unit;
$d->pool = $pool;
if (!empty($radius)) {
if (!empty ($radius)) {
$d->is_radius = 1;
$d->routers = '';
} else {
@ -533,7 +539,7 @@ switch ($action) {
$d->pool_expired = $pool_expired;
$d->list_expired = $list_expired;
$d->enabled = $enabled;
$d->allow_purchase = $allow_purchase;
$d->prepaid = $prepaid;
$d->save();
$plan_id = $d->id();
@ -543,7 +549,7 @@ switch ($action) {
$mikrotik = Mikrotik::info($routers);
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
Mikrotik::addPpoePlan($client, $name, $pool, $rate);
if (!empty($pool_expired)) {
if (!empty ($pool_expired)) {
Mikrotik::setPpoePlan($client, 'EXPIRED NUXBILL ' . $pool_expired, $pool_expired, '512K/512K');
}
}
@ -556,6 +562,7 @@ switch ($action) {
case 'edit-pppoe-post':
$id = _post('id');
$plan_type = _post('plan_type');
$name = _post('name_plan');
$id_bw = _post('id_bw');
$price = _post('price');
@ -566,7 +573,7 @@ switch ($action) {
$pool_expired = _post('pool_expired');
$list_expired = _post('list_expired');
$enabled = _post('enabled');
$allow_purchase = _post('allow_purchase');
$prepaid = _post('prepaid');
$msg = '';
if (Validator::UnsignedNumber($validity) == false) {
@ -611,7 +618,7 @@ switch ($action) {
$mikrotik = Mikrotik::info($routers);
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
Mikrotik::setPpoePlan($client, $name, $pool, $rate);
if (!empty($pool_expired)) {
if (!empty ($pool_expired)) {
Mikrotik::setPpoePlan($client, 'EXPIRED NUXBILL ' . $pool_expired, $pool_expired, '512K/512K');
}
}
@ -619,6 +626,7 @@ switch ($action) {
$d->name_plan = $name;
$d->id_bw = $id_bw;
$d->price = $price;
$d->plan_type = $plan_type;
$d->validity = $validity;
$d->validity_unit = $validity_unit;
$d->routers = $routers;
@ -626,7 +634,7 @@ switch ($action) {
$d->pool_expired = $pool_expired;
$d->list_expired = $list_expired;
$d->enabled = $enabled;
$d->allow_purchase = $allow_purchase;
$d->prepaid = $prepaid;
$d->save();
r2(U . 'services/pppoe', 's', Lang::T('Data Updated Successfully'));
@ -657,14 +665,14 @@ switch ($action) {
break;
case 'balance-edit':
$ui->assign('_title', Lang::T('Balance Plans'));
$id = $routes['2'];
$id = $routes['2'];
$d = ORM::for_table('tbl_plans')->find_one($id);
$ui->assign('d', $d);
run_hook('view_edit_balance'); #HOOK
$ui->display('balance-edit.tpl');
break;
case 'balance-delete':
$id = $routes['2'];
$id = $routes['2'];
$d = ORM::for_table('tbl_plans')->find_one($id);
if ($d) {
@ -678,7 +686,7 @@ switch ($action) {
$name = _post('name');
$price = _post('price');
$enabled = _post('enabled');
$allow_purchase = _post('allow_purchase');
$prepaid = _post('prepaid');
$msg = '';
if (Validator::UnsignedNumber($price) == false) {
@ -698,7 +706,7 @@ switch ($action) {
$d->name_plan = $name;
$d->price = $price;
$d->enabled = $enabled;
$d->allow_purchase = $allow_purchase;
$d->prepaid = 'yes';
$d->save();
r2(U . 'services/balance', 's', Lang::T('Data Updated Successfully'));
@ -710,7 +718,6 @@ switch ($action) {
$name = _post('name');
$price = _post('price');
$enabled = _post('enabled');
$allow_purchase = _post('allow_purchase');
$msg = '';
if (Validator::UnsignedNumber($price) == false) {
@ -736,7 +743,7 @@ switch ($action) {
$d->routers = '';
$d->pool = '';
$d->enabled = $enabled;
$d->allow_purchase = $allow_purchase;
$d->prepaid = 'yes';
$d->save();
r2(U . 'services/balance', 's', Lang::T('Data Created Successfully'));

View File

@ -30,15 +30,16 @@ switch ($action) {
r2(U . "settings/app", 's', 'Test Telegram has been send<br>Result: ' . $result);
}
$UPLOAD_URL_PATH = str_replace($root_path,'', $UPLOAD_PATH);
if (file_exists($UPLOAD_PATH . DIRECTORY_SEPARATOR . 'logo.png')) {
$logo = $UPLOAD_PATH . DIRECTORY_SEPARATOR . 'logo.png?' . time();
$logo = $UPLOAD_URL_PATH . DIRECTORY_SEPARATOR . 'logo.png?' . time();
} else {
$logo = $UPLOAD_PATH . DIRECTORY_SEPARATOR . 'logo.default.png';
$logo = $UPLOAD_URL_PATH . DIRECTORY_SEPARATOR . 'logo.default.png';
}
$ui->assign('logo', $logo);
if ($_c['radius_enable'] && empty($_c['radius_client'])) {
if ($config['radius_enable'] && empty($config['radius_client'])) {
try {
$_c['radius_client'] = Radius::getClient();
$config['radius_client'] = Radius::getClient();
$ui->assign('_c', $_c);
} catch (Exception $e) {
//ignore
@ -495,11 +496,11 @@ switch ($action) {
$date_now = date("Y-m-d H:i:s");
run_hook('add_admin'); #HOOK
if ($msg == '') {
$password = Password::_crypt($password);
$passwordC = Password::_crypt($password);
$d = ORM::for_table('tbl_users')->create();
$d->username = $username;
$d->fullname = $fullname;
$d->password = $password;
$d->password = $passwordC;
$d->user_type = $user_type;
$d->phone = $phone;
$d->email = $email;

View File

@ -49,7 +49,20 @@ switch ($action) {
$ui->display('user-activation-list.tpl');
break;
case 'invoice':
$id = $routes[2];
if(empty($id)){
$in = ORM::for_table('tbl_transactions')->where('username', $user['username'])->order_by_desc('id')->find_one();
}else{
$in = ORM::for_table('tbl_transactions')->where('username', $user['username'])->where('id', $id)->find_one();
}
if($in){
Package::createInvoice($in);
$ui->display('invoice-customer.tpl');
}else{
r2(U . 'voucher/list-activated', 'e', Lang::T('Not Found'));
}
break;
default:
$ui->display('a404.tpl');
}

View File

@ -24,7 +24,7 @@ echo "Found " . count($d) . " user(s)\n";
run_hook('cronjob'); #HOOK
foreach ($d as $ds) {
if ($ds['type'] == 'Hotspot') {
if ($ds['type'] == 'Hotspot') { # HOTSPOT
$date_now = strtotime(date("Y-m-d H:i:s"));
$expiration = strtotime($ds['expiration'] . ' ' . $ds['time']);
echo $ds['expiration'] . " : " . (($isCli) ? $ds['username'] : Lang::maskText($ds['username']));
@ -46,22 +46,28 @@ foreach ($d as $ds) {
$client = Mikrotik::getClient($m['ip_address'], $m['username'], $m['password']);
if (!empty($p['pool_expired'])) {
Mikrotik::setHotspotUserPackage($client, $c['username'], 'EXPIRED NUXBILL ' . $p['pool_expired']);
// }if (!empty($p['list_expired'])) {
// $ip = Mikrotik::getIpHotspotUser($client, $ds['username']);
// Mikrotik::addIpToAddressList($client, $ip, $p['list_expired'], $c['username']);
// }if (!empty($p['list_expired'])) {
// $ip = Mikrotik::getIpHotspotUser($client, $ds['username']);
// Mikrotik::addIpToAddressList($client, $ip, $p['list_expired'], $c['username']);
} else {
Mikrotik::removeHotspotUser($client, $c['username']);
}
Mikrotik::removeHotspotActiveUser($client, $c['username']);
}
echo Message::sendPackageNotification($c['phonenumber'], $c['fullname'], $u['namebp'], $price, $textExpired, $config['user_notification_expired'])."\n";
echo Message::sendPackageNotification($c, $u['namebp'], $price, $textExpired, $config['user_notification_expired']) . "\n";
//update database user dengan status off
$u->status = 'off';
$u->save();
// autorenewal from deposit
if ($config['enable_balance'] == 'yes' && $c['auto_renewal']) {
if ($p && $p['enabled'] && $c['balance'] >= $p['price'] && $p['allow_purchase'] == 'yes') {
list($bills, $add_cost) = User::getBills($ds['customer_id']);
if ($add_cost > 0) {
if (!empty($add_cost)) {
$p['price'] += $add_cost;
}
}
if ($p && $p['enabled'] && $c['balance'] >= $p['price']) {
if (Package::rechargeUser($ds['customer_id'], $p['routers'], $p['id'], 'Customer', 'Balance')) {
// if success, then get the balance
Balance::min($ds['customer_id'], $p['price']);
@ -82,7 +88,7 @@ foreach ($d as $ds) {
}
} else
echo " : ACTIVE \r\n";
} else {
} else { # PPPOE
$date_now = strtotime(date("Y-m-d H:i:s"));
$expiration = strtotime($ds['expiration'] . ' ' . $ds['time']);
echo $ds['expiration'] . " : " . (($isCli) ? $ds['username'] : Lang::maskText($ds['username']));
@ -109,14 +115,20 @@ foreach ($d as $ds) {
}
Mikrotik::removePpoeActive($client, $c['username']);
}
echo Message::sendPackageNotification($c['phonenumber'], $c['fullname'], $u['namebp'], $price, $textExpired, $config['user_notification_expired'])."\n";
echo Message::sendPackageNotification($c, $u['namebp'], $price, $textExpired, $config['user_notification_expired']) . "\n";
$u->status = 'off';
$u->save();
// autorenewal from deposit
if ($config['enable_balance'] == 'yes' && $c['auto_renewal']) {
if ($p && $p['enabled'] && $c['balance'] >= $p['price'] && $p['allow_purchase'] == 'yes') {
list($bills, $add_cost) = User::getBills($ds['customer_id']);
if ($add_cost > 0) {
if (!empty($add_cost)) {
$p['price'] += $add_cost;
}
}
if ($p && $p['enabled'] && $c['balance'] >= $p['price']) {
if (Package::rechargeUser($ds['customer_id'], $p['routers'], $p['id'], 'Customer', 'Balance')) {
// if success, then get the balance
Balance::min($ds['customer_id'], $p['price']);

View File

@ -38,13 +38,29 @@ foreach ($d as $ds) {
$u = ORM::for_table('tbl_user_recharges')->where('id', $ds['id'])->find_one();
$p = ORM::for_table('tbl_plans')->where('id', $u['plan_id'])->find_one();
$c = ORM::for_table('tbl_customers')->where('id', $ds['customer_id'])->find_one();
$price = Lang::moneyFormat($p['price']);
list($bills, $add_cost) = User::getBills($ds['customer_id']);
if ($add_cost > 0) {
if (!empty($add_cost)) {
$p['price'] += $add_cost;
}
}
if ($p['validity_unit'] == 'Period') {
// Postpaid price from field
$add_inv = User::getAttribute("Invoice", $ds['customer_id']);
if (empty ($add_inv) or $add_inv == 0) {
$price = Lang::moneyFormat($p['price']);
} else {
$price = Lang::moneyFormat($add_inv);
}
} else {
$price = Lang::moneyFormat($p['price']);
}
if ($ds['expiration'] == $day7) {
echo Message::sendPackageNotification($c['phonenumber'], $c['fullname'], $p['name_plan'], $price, Lang::getNotifText('reminder_7_day'), $config['user_notification_reminder']) . "\n";
echo Message::sendPackageNotification($c, $p['name_plan'], $price, Lang::getNotifText('reminder_7_day'), $config['user_notification_reminder']) . "\n";
} else if ($ds['expiration'] == $day3) {
echo Message::sendPackageNotification($c['phonenumber'], $c['fullname'], $p['name_plan'], $price, Lang::getNotifText('reminder_3_day'), $config['user_notification_reminder']) . "\n";
echo Message::sendPackageNotification($c, $p['name_plan'], $price, Lang::getNotifText('reminder_3_day'), $config['user_notification_reminder']) . "\n";
} else if ($ds['expiration'] == $day1) {
echo Message::sendPackageNotification($c['phonenumber'], $c['fullname'], $p['name_plan'], $price, Lang::getNotifText('reminder_1_day'), $config['user_notification_reminder']) . "\n";
echo Message::sendPackageNotification($c, $p['name_plan'], $price, Lang::getNotifText('reminder_1_day'), $config['user_notification_reminder']) . "\n";
}
}
}

View File

@ -100,9 +100,6 @@
"Add_Pool": "Add Pool",
"Edit_Pool": "Edit Pool",
"Pool_Name_Already_Exist": "Pool Name Already Exist",
"Prepaid": "Prepaid",
"Prepaid_Users": "Prepaid Users",
"Prepaid_Vouchers": "Prepaid Vouchers",
"Refill_Account": "Refill Account",
"Recharge_Account": "Recharge Account",
"Select_Account": "Select Account",
@ -384,7 +381,6 @@
"After_Customer_activate_voucher_or_login__customer_will_be_redirected_to_this_url": "After Customer activate voucher or login, customer will be redirected to this url",
"Voucher_Prefix": "Voucher Prefix",
"Voucher_activation_success__now_you_can_login": "Voucher activation success, now you can login",
"Client_Can_Purchase": "Client Can Purchase",
"Buy_this__your_active_package_will_be_overwritten": "Buy this? your active package will be overwritten",
"Pay_this_with_Balance__your_active_package_will_be_overwritten": "Pay this with Balance? your active package will be overwritten",
"Buy_this__your_active_package_will_be_overwrite": "Buy this? your active package will be overwrite",
@ -456,5 +452,88 @@
"Click_Here": "Click Here",
"danger": "danger",
"Logout_Successful": "Logout Successful",
"warning": "warning"
"warning": "warning",
"Users_Announcement": "Users Announcement",
"Customer_Announcement": "Customer Announcement",
"1_Period___1_Month__Expires_the_20th_of_each_month": "1 Period = 1 Month, Expires the 20th of each month",
"Period": "Period",
"Add": "Add",
"Select_Payment_Gateway": "Select Payment Gateway",
"Available_Payment_Gateway": "Available Payment Gateway",
"Pay_Now": "Pay Now",
"Please_select_Payment_Gateway": "Please select Payment Gateway",
"Payment_Gateway_Deleted": "Payment Gateway Deleted",
"Payment_Gateway_not_set__please_set_it_in_Settings": "Payment Gateway not set, please set it in Settings",
"Failed_to_create_Transaction__": "Failed to create Transaction..",
"Show_To_Customer": "Type",
"Using": "Using",
"Default": "Default",
"Customer_Balance": "Customer Balance",
"Vouchers": "Vouchers",
"Refill_Customer": "Refill Customer",
"Recharge_Customer": "Recharge Customer",
"Plans": "Plans",
"PPPOE": "PPPOE",
"Bandwidth": "Bandwidth",
"Customers": "Customers",
"Actives": "Actives",
"Name": "Name",
"Confirm": "Confirm",
"Plan": "Plan",
"Total": "Total",
"Current_Cycle": "Current Cycle",
"Additional_Cost": "Additional Cost",
"Remaining": "Remaining",
"Not_Found": "Not Found",
"Cash": "Cash",
"Payment_not_found": "Payment not found",
"If_your_friend_have_Additional_Cost__you_will_pay_for_that_too": "If your friend have Additional Cost, you will pay for that too",
"Cache_cleared_successfully_": "Cache cleared successfully!",
"Paid": "Paid",
"Send_Message": "Send Message",
"Send_Personal_Message": "Send Personal Message",
"Send_Via": "Send Via",
"Compose_your_message___": "Compose your message...",
"Use_placeholders_": "Use placeholders:",
"Customer_Name": "Customer Name",
"Customer_Username": "Customer Username",
"Customer_Phone": "Customer Phone",
"Your_Company_Name": "Your Company Name",
"Message_Sent_Successfully": "Message Sent Successfully",
"Send_Bulk_Message": "Send Bulk Message",
"Group": "Group",
"All_Customers": "All Customers",
"New_Customers": "New Customers",
"Expired_Customers": "Expired Customers",
"Active_Customers": "Active Customers",
"Map": "Map",
"Customer_Location": "Customer Location",
"Account_Type": "Account Type",
"Coordinates": "Coordinates",
"Latitude_and_Longitude_coordinates_for_map_must_be_separate_with_comma____": "Latitude and Longitude coordinates for map must be separate with comma &quot;,&quot;",
"Customer_Geo_Location_Information": "Customer Geo Location Information",
"List": "List",
"Lists": "Lists",
"Single_Customer": "Single Customer",
"Bulk_Customers": "Bulk Customers",
"Message_per_time": "Message per time",
"5_Messages": "5 Messages",
"10_Messages": "10 Messages",
"15_Messages": "15 Messages",
"20_Messages": "20 Messages",
"30_Messages": "30 Messages",
"40_Messages": "40 Messages",
"50_Messages": "50 Messages",
"60_Messages": "60 Messages",
"Use_20_and_above_if_you_are_sending_to_all_customers_to_avoid_server_time_out": "Use 20 and above if you are sending to all customers to avoid server time out",
"Delay": "Delay",
"No_Delay": "No Delay",
"5_Seconds": "5 Seconds",
"10_Seconds": "10 Seconds",
"15_Seconds": "15 Seconds",
"20_Seconds": "20 Seconds",
"Use_at_least_5_secs_if_you_are_sending_to_all_customers_to_avoid_being_banned_by_your_message_provider": "Use at least 5 secs if you are sending to all customers to avoid being banned by your message provider",
"Testing__if_checked_no_real_message_is_sent_": "Testing [if checked no real message is sent]",
"All_fields_are_required": "All fields are required",
"Personal": "Personal"
}

View File

@ -100,9 +100,6 @@
"Add_Pool": "Tambahkan Pool",
"Edit_Pool": "Sunting Pool",
"Pool_Name_Already_Exist": "Nama Pool Sudah Ada",
"Prepaid": "Prabayar",
"Prepaid_Users": "Pengguna Prabayar",
"Prepaid_Vouchers": "Voucher Prabayar",
"Refill_Account": "Isi Ulang Akun",
"Recharge_Account": "Isi Ulang Akun",
"Select_Account": "Pilih Akun",

View File

@ -100,9 +100,6 @@
"Add_Pool": "Agregar Pool",
"Edit_Pool": "Editar Pool",
"Pool_Name_Already_Exist": "Nombre del Pool ya existe",
"Prepaid": "Prepago",
"Prepaid_Users": "Usuarios prepago",
"Prepaid_Vouchers": "Fichas prepago",
"Refill_Account": "Recargar Ficha",
"Recharge_Account": "Recargar Cuenta",
"Select_Account": "Seleccionar cuenta",

View File

@ -96,9 +96,6 @@
"Add_Pool": "Havuz ekle",
"Edit_Pool": "Havuzu D\u00fczenle",
"Pool_Name_Already_Exist": "Havuz Ad\u0131 \u200b\u200bZaten Var",
"Prepaid": "\u00d6n \u00d6demeli",
"Prepaid_Users": "\u00d6n \u00d6demeli Kullan\u0131c\u0131lar",
"Prepaid_Vouchers": "\u00d6n \u00d6demeli Kuponlar",
"Refill_Account": "Hesab\u0131 Yenile",
"Recharge_Account": "Hesab\u0131 Yeniden \u015earj Et",
"Select_Account": "Hesap Se\u00e7",

View File

@ -69,5 +69,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.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" : [
"ALTER TABLE `tbl_transactions` ADD `note` VARCHAR(256) NOT NULL DEFAULT '' COMMENT 'for note' AFTER `type`;"
],
"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" : [
"ALTER TABLE `tbl_customers` ADD `account_type` ENUM('Business', 'Personal') DEFAULT 'Personal' COMMENT 'For selecting account type' AFTER `coordinates`;"
],
"2024.3.19.2" : [
"ALTER TABLE `tbl_plans` ADD `plan_type` ENUM('Business', 'Personal') DEFAULT 'Personal' COMMENT 'For selecting account type' ;"
]
}

View File

@ -1,8 +0,0 @@
<html>
<head>
<title>403 Forbidden</title>
</head>
<body>
<p>Directory access is forbidden.</p>
</body>
</html>

View File

@ -1,9 +1,9 @@
$(document).on("click", ".cdelete", function(e) {
e.preventDefault();
var id = this.id;
bootbox.confirm("Are you sure?", function(result) {
if(result){
window.location.href = "index.php?_route=prepaid/delete/" + id;
}
});
$(document).on("click", ".cdelete", function(e) {
e.preventDefault();
var id = this.id;
bootbox.confirm("Are you sure?", function(result) {
if(result){
window.location.href = "index.php?_route=plan/delete/" + id;
}
});
});

View File

@ -3,7 +3,7 @@
var id = this.id;
bootbox.confirm("Are you sure?", function(result) {
if(result){
window.location.href = "index.php?_route=prepaid/voucher-delete/" + id;
window.location.href = "index.php?_route=plan/voucher-delete/" + id;
}
});
});

View File

@ -4,19 +4,19 @@
<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 class="hold-transition login-page">
<div class="login-box">
<div class="login-logo">
<b>Nux</b>Billing
{$_c['CompanyName']}
</div>
<div class="login-box-body">
<p class="login-box-msg">{Lang::T('Enter Admin Area')}</p>

View File

@ -9,7 +9,7 @@
<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}">
<meta http-equiv="refresh" content="{$time}; url={$url}">
</head>
<body class="hold-transition lockscreen">
@ -20,7 +20,7 @@
{$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>
<a href="{$url}" id="button" class="btn btn-{$type} btn-block btn-block">{Lang::T('Click Here')} ({$time})</a>
</div>
</div>
<div class="lockscreen-footer text-center">
@ -29,7 +29,7 @@
</div>
<script>
var time = 3;
var time = {$time};
timer();
function timer() {

View File

@ -15,13 +15,14 @@
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Expired Notification Message')}</label>
<div class="col-md-6">
<textarea class="form-control" id="expired"
name="expired"
<textarea class="form-control" id="expired" name="expired"
placeholder="Hello [[name]], your internet package [[package]] has been expired"
rows="3">{if $_json['expired']!=''}{Lang::htmlspecialchars($_json['expired'])}{else}Hello [[name]], your internet package [[package]] has been expired.{/if}</textarea>
</div>
<p class="help-block col-md-4">
<b>[[name]]</b> will be replaced with Customer Name. <b>[[package]]</b> will be replaced with Package name. <b>[[price]]</b> will be replaced with Package price.
<b>[[name]]</b> will be replaced with Customer Name.
<b>[[package]]</b> will be replaced with Package name.
<b>[[price]]</b> will be replaced with Package price.
</p>
</div>
</div>
@ -33,7 +34,10 @@
rows="3">{Lang::htmlspecialchars($_json['reminder_7_day'])}</textarea>
</div>
<p class="help-block col-md-4">
<b>[[name]]</b> will be replaced with Customer Name. <b>[[package]]</b> will be replaced with Package name. <b>[[price]]</b> will be replaced with Package price.
<b>[[name]]</b> will be replaced with Customer Name.
<b>[[package]]</b> will be replaced with Package name.
<b>[[price]]</b> will be replaced with Package price.
<b>[[expired_date]]</b> will be replaced with Expiration date.
</p>
</div>
</div>
@ -45,7 +49,10 @@
rows="3">{Lang::htmlspecialchars($_json['reminder_3_day'])}</textarea>
</div>
<p class="help-block col-md-4">
<b>[[name]]</b> will be replaced with Customer Name. <b>[[package]]</b> will be replaced with Package name. <b>[[price]]</b> will be replaced with Package price.
<b>[[name]]</b> will be replaced with Customer Name.
<b>[[package]]</b> will be replaced with Package name.
<b>[[price]]</b> will be replaced with Package price.
<b>[[expired_date]]</b> will be replaced with Expiration date.
</p>
</div>
</div>
@ -57,7 +64,10 @@
rows="3">{Lang::htmlspecialchars($_json['reminder_1_day'])}</textarea>
</div>
<p class="help-block col-md-4">
<b>[[name]]</b> will be replaced with Customer Name. <b>[[package]]</b> will be replaced with Package name. <b>[[price]]</b> will be replaced with Package price.
<b>[[name]]</b> will be replaced with Customer Name.
<b>[[package]]</b> will be replaced with Package name.
<b>[[price]]</b> will be replaced with Package price.
<b>[[expired_date]]</b> will be replaced with Expiration date.
</p>
</div>
</div>
@ -117,40 +127,41 @@
</p>
</div>
</div>
<div class="panel-body">
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Send Balance')}</label>
<div class="col-md-6">
<textarea class="form-control" id="balance_send" name="balance_send"
rows="3">{if $_json['balance_send']}{Lang::htmlspecialchars($_json['balance_send'])}{else}{Lang::htmlspecialchars($_default['balance_send'])}{/if}</textarea>
{if $_c['enable_balance'] == 'yes'}
<div class="panel-body">
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Send Balance')}</label>
<div class="col-md-6">
<textarea class="form-control" id="balance_send" name="balance_send"
rows="3">{if $_json['balance_send']}{Lang::htmlspecialchars($_json['balance_send'])}{else}{Lang::htmlspecialchars($_default['balance_send'])}{/if}</textarea>
</div>
<p class="col-md-4 help-block">
<b>[[name]]</b> Receiver name.<br>
<b>[[balance]]</b> how much balance have been send.<br>
<b>[[current_balance]]</b> Current Balance.
</p>
</div>
<p class="col-md-4 help-block">
<b>[[name]]</b> Receiver name.<br>
<b>[[balance]]</b> how much balance have been send.<br>
<b>[[current_balance]]</b> Current Balance.
</p>
</div>
</div>
<div class="panel-body">
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Received Balance')}</label>
<div class="col-md-6">
<textarea class="form-control" id="balance_received" name="balance_received"
rows="3">{if $_json['balance_received']}{Lang::htmlspecialchars($_json['balance_received'])}{else}{Lang::htmlspecialchars($_default['balance_received'])}{/if}</textarea>
<div class="panel-body">
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Received Balance')}</label>
<div class="col-md-6">
<textarea class="form-control" id="balance_received" name="balance_received"
rows="3">{if $_json['balance_received']}{Lang::htmlspecialchars($_json['balance_received'])}{else}{Lang::htmlspecialchars($_default['balance_received'])}{/if}</textarea>
</div>
<p class="col-md-4 help-block">
<b>[[name]]</b> Sender name.<br>
<b>[[balance]]</b> how much balance have been received.<br>
<b>[[current_balance]]</b> Current Balance.
</p>
</div>
<p class="col-md-4 help-block">
<b>[[name]]</b> Sender name.<br>
<b>[[balance]]</b> how much balance have been received.<br>
<b>[[current_balance]]</b> Current Balance.
</p>
</div>
</div>
{/if}
</div>
<div class="panel-body">
<div class="form-group">
<button class="btn btn-success btn-block"
type="submit">{Lang::T('Save Changes')}</button>
<button class="btn btn-success btn-block" type="submit">{Lang::T('Save Changes')}</button>
</div>
</div>
</div>

View File

@ -1,4 +1,9 @@
<option value="">Select Plans</option>
{foreach $d as $ds}
<option value="{$ds['id']}">{$ds['name_plan']} &bull; {Lang::moneyFormat($ds['price'])}</option>
<option value="{$ds['id']}">
{if $ds['enabled'] neq 1}DISABLED PLAN &bull; {/if}
{$ds['name_plan']} &bull;
{Lang::moneyFormat($ds['price'])}
{if $ds['prepaid'] neq 'yes'} &bull; POSTPAID {/if}
</option>
{/foreach}

View File

@ -1,59 +1,49 @@
{include file="sections/header.tpl"}
<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 Service Plan')}</div>
<div class="panel-body">
<form class="form-horizontal" method="post" role="form" action="{$_url}services/balance-add-post" >
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Status')}</label>
<div class="col-md-10">
<label class="radio-inline warning">
<input type="radio" checked name="enabled" value="1"> Enable
</label>
<label class="radio-inline">
<input type="radio" name="enabled" value="0"> Disable
</label>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Client Can Purchase')}</label>
<div class="col-md-10">
<label class="radio-inline warning">
<input type="radio" checked name="allow_purchase" value="yes"> Yes
</label>
<label class="radio-inline">
<input type="radio" name="allow_purchase" value="no"> No
</label>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Plan Name')}</label>
<div class="col-md-6">
<input type="text" required class="form-control" id="name" name="name" maxlength="40" placeholder="Topup 100">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Plan Price')}</label>
<div class="col-md-6">
<div class="input-group">
<span class="input-group-addon">{$_c['currency_code']}</span>
<input type="number" class="form-control" name="price" required>
</div>
</div>
<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 Service Plan')}</div>
<div class="panel-body">
<form class="form-horizontal" method="post" role="form" action="{$_url}services/balance-add-post">
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Status')}</label>
<div class="col-md-10">
<label class="radio-inline warning">
<input type="radio" checked name="enabled" value="1"> Enable
</label>
<label class="radio-inline">
<input type="radio" name="enabled" value="0"> Disable
</label>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Plan Name')}</label>
<div class="col-md-6">
<input type="text" required class="form-control" id="name" name="name" maxlength="40"
placeholder="Topup 100">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Plan Price')}</label>
<div class="col-md-6">
<div class="input-group">
<span class="input-group-addon">{$_c['currency_code']}</span>
<input type="number" class="form-control" name="price" required>
</div>
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<button class="btn btn-success" type="submit">{Lang::T('Save Changes')}</button>
Or <a href="{$_url}services/balance">{Lang::T('Cancel')}</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<button class="btn btn-success" type="submit">{Lang::T('Save Changes')}</button>
Or <a href="{$_url}services/balance">{Lang::T('Cancel')}</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{include file="sections/footer.tpl"}
{include file="sections/footer.tpl"}

View File

@ -18,18 +18,6 @@
</label>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Client Can Purchase')}</label>
<div class="col-md-10">
<label class="radio-inline warning">
<input type="radio" {if $d['allow_purchase'] == yes}checked{/if} name="allow_purchase" value="yes"> Yes
</label>
<label class="radio-inline">
<input type="radio" {if $d['allow_purchase'] == no}checked{/if} name="allow_purchase" value="no">
No
</label>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Plan Name')}</label>
<div class="col-md-6">

View File

@ -1,21 +1,20 @@
{include file="sections/header.tpl"}
<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 New Contact')}</div>
<div class="panel-body">
<form class="form-horizontal" method="post" role="form" action="{$_url}customers/add-post">
<form class="form-horizontal" method="post" role="form" action="{$_url}customers/add-post">
<div class="row">
<div class="col-md-6">
<div class="panel panel-primary panel-hovered panel-stacked mb30">
<div class="panel-heading">{Lang::T('Add New Contact')}</div>
<div class="panel-body">
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Username')}</label>
<div class="col-md-6">
<label class="col-md-3 control-label">{Lang::T('Username')}</label>
<div class="col-md-9">
<div class="input-group">
{if $_c['country_code_phone']!= ''}
<span class="input-group-addon" id="basic-addon1">+</span>
<span class="input-group-addon" id="basic-addon1">+</span>
{else}
<span class="input-group-addon" id="basic-addon1"><i
class="glyphicon glyphicon-phone-alt"></i></span>
<span class="input-group-addon" id="basic-addon1"><i
class="glyphicon glyphicon-phone-alt"></i></span>
{/if}
<input type="text" class="form-control" name="username" required
placeholder="{if $_c['country_code_phone']!= ''}{$_c['country_code_phone']}{/if} {Lang::T('Phone Number')}">
@ -23,26 +22,26 @@
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Full Name')}</label>
<div class="col-md-6">
<label class="col-md-3 control-label">{Lang::T('Full Name')}</label>
<div class="col-md-9">
<input type="text" required class="form-control" id="fullname" name="fullname">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Email')}</label>
<div class="col-md-6">
<label class="col-md-3 control-label">{Lang::T('Email')}</label>
<div class="col-md-9">
<input type="email" class="form-control" id="email" name="email">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Phone Number')}</label>
<div class="col-md-6">
<label class="col-md-3 control-label">{Lang::T('Phone Number')}</label>
<div class="col-md-9">
<div class="input-group">
{if $_c['country_code_phone']!= ''}
<span class="input-group-addon" id="basic-addon1">+</span>
<span class="input-group-addon" id="basic-addon1">+</span>
{else}
<span class="input-group-addon" id="basic-addon1"><i
class="glyphicon glyphicon-phone-alt"></i></span>
<span class="input-group-addon" id="basic-addon1"><i
class="glyphicon glyphicon-phone-alt"></i></span>
{/if}
<input type="text" class="form-control" name="phonenumber"
placeholder="{if $_c['country_code_phone']!= ''}{$_c['country_code_phone']}{/if} {Lang::T('Phone Number')}">
@ -50,15 +49,16 @@
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Password')}</label>
<div class="col-md-6">
<label class="col-md-3 control-label">{Lang::T('Password')}</label>
<div class="col-md-9">
<input type="password" class="form-control" autocomplete="off" required id="password"
name="password" onmouseleave="this.type = 'password'" onmouseenter="this.type = 'text'">
value="{rand(000000,999999)}" name="password" onmouseleave="this.type = 'password'"
onmouseenter="this.type = 'text'">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('PPPOE Password')}</label>
<div class="col-md-6">
<label class="col-md-3 control-label">{Lang::T('PPPOE Password')}</label>
<div class="col-md-9">
<input type="password" class="form-control" id="pppoe_password" name="pppoe_password"
value="{$d['pppoe_password']}" onmouseleave="this.type = 'password'"
onmouseenter="this.type = 'text'">
@ -68,80 +68,134 @@
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Address')}</label>
<div class="col-md-6">
<label class="col-md-3 control-label">{Lang::T('Address')}</label>
<div class="col-md-9">
<textarea name="address" id="address" class="form-control"></textarea>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Service Type')}</label>
<div class="col-md-6">
<label class="col-md-3 control-label">{Lang::T('Service Type')}</label>
<div class="col-md-9">
<select class="form-control" id="service_type" name="service_type">
<option value="Hotspot" {if $d['service_type'] eq 'Hotspot' }selected{/if}>Hotspot
<option value="Hotspot">Hotspot
</option>
<option value="PPPoE" {if $d['service_type'] eq 'PPPoE' }selected{/if}>PPPoE</option>
<option value="Others" {if $d['service_type'] eq 'Others' }selected{/if}>Others</option>
<option value="PPPoE">PPPoE</option>
<option value="Others">Others</option>
</select>
</div>
</div>
<!-- Customers Attributes add start -->
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Attributes')}</label>
<div id="custom-fields-container" class="col-md-6">
<button class="btn btn-success btn-sm" type="button"
id="add-custom-field">+</button>
<label class="col-md-3 control-label">{Lang::T('Account Type')}</label>
<div class="col-md-9">
<select class="form-control" id="account_type" name="account_type">
<option value="Personal">Personal
</option>
<option value="Business">Business</option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label">{Lang::T('Coordinates')}</label>
<div class="col-md-9">
<input name="coordinates" id="coordinates" class="form-control" value=""
placeholder="6.465422, 3.406448">
<div id="map" style="width: '100%'; height: 200px; min-height: 150px;"></div>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="panel panel-primary panel-hovered panel-stacked mb30">
<div class="panel-heading">{Lang::T('Attributes')}</div>
<div class="panel-body">
<!-- Customers Attributes add start -->
<div id="custom-fields-container">
</div>
<!-- Customers Attributes add end -->
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<button class="btn btn-primary" type="submit">
{Lang::T('Save Changes')}
</button>
Or <a href="{$_url}customers/list">{Lang::T('Cancel')}</a>
</div>
</div>
</form>
</div>
<div class="panel-footer">
<button class="btn btn-success btn-block" type="button"
id="add-custom-field">{Lang::T('Add')}</button>
</div>
</div>
</div>
</div>
</div>
</div>
<center>
<button class="btn btn-primary" type="submit">
{Lang::T('Save Changes')}
</button>
<br><a href="{$_url}customers/list" class="btn btn-link">{Lang::T('Cancel')}</a>
</center>
</form>
{literal}
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
var customFieldsContainer = document.getElementById('custom-fields-container');
var addCustomFieldButton = document.getElementById('add-custom-field');
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
var customFieldsContainer = document.getElementById('custom-fields-container');
var addCustomFieldButton = document.getElementById('add-custom-field');
addCustomFieldButton.addEventListener('click', function() {
var fieldIndex = customFieldsContainer.children.length;
var newField = document.createElement('div');
newField.className = 'form-group';
newField.innerHTML = `
<label class="col-md-2 control-label">Name:</label>
<div class="col-md-3">
addCustomFieldButton.addEventListener('click', function() {
var fieldIndex = customFieldsContainer.children.length;
var newField = document.createElement('div');
newField.className = 'form-group';
newField.innerHTML = `
<div class="col-md-4">
<input type="text" class="form-control" name="custom_field_name[]" placeholder="Name">
</div>
<label class="col-md-2 control-label">Value:</label>
<div class="col-md-3">
<div class="col-md-6">
<input type="text" class="form-control" name="custom_field_value[]" placeholder="Value">
</div>
<div class="col-md-2">
<button type="button" class="remove-custom-field btn btn-danger btn-sm">-</button>
</div>
`;
customFieldsContainer.appendChild(newField);
});
customFieldsContainer.appendChild(newField);
});
customFieldsContainer.addEventListener('click', function(event) {
if (event.target.classList.contains('remove-custom-field')) {
var fieldContainer = event.target.parentNode.parentNode;
fieldContainer.parentNode.removeChild(fieldContainer);
}
customFieldsContainer.addEventListener('click', function(event) {
if (event.target.classList.contains('remove-custom-field')) {
var fieldContainer = event.target.parentNode.parentNode;
fieldContainer.parentNode.removeChild(fieldContainer);
}
});
});
});
</script>
</script>
<script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"></script>
<script>
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
} else {
setupMap(51.505, -0.09);
}
}
function showPosition(position) {
setupMap(position.coords.latitude, position.coords.longitude);
}
function setupMap(lat, lon) {
var map = L.map('map').setView([lat, lon], 13);
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/light_all/{z}/{x}/{y}.png', {
attribution:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>',
subdomains: 'abcd',
maxZoom: 20
}).addTo(map);
var marker = L.marker([lat, lon]).addTo(map);
map.on('click', function(e){
var coord = e.latlng;
var lat = coord.lat;
var lng = coord.lng;
var newLatLng = new L.LatLng(lat, lng);
marker.setLatLng(newLatLng);
$('#coordinates').val(lat + ',' + lng);
});
}
window.onload = function() {
getLocation();
}
</script>
{/literal}

View File

@ -1,22 +1,21 @@
{include file="sections/header.tpl"}
<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 Contact')}</div>
<div class="panel-body">
<form class="form-horizontal" method="post" role="form" action="{$_url}customers/edit-post">
<form class="form-horizontal" method="post" role="form" action="{$_url}customers/edit-post">
<div class="row">
<div class="col-md-6">
<div class="panel panel-primary panel-hovered panel-stacked mb30">
<div class="panel-heading">{Lang::T('Edit Contact')}</div>
<div class="panel-body">
<input type="hidden" name="id" value="{$d['id']}">
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Username')}</label>
<div class="col-md-6">
<label class="col-md-3 control-label">{Lang::T('Username')}</label>
<div class="col-md-9">
<div class="input-group">
{if $_c['country_code_phone']!= ''}
<span class="input-group-addon" id="basic-addon1">+</span>
<span class="input-group-addon" id="basic-addon1">+</span>
{else}
<span class="input-group-addon" id="basic-addon1"><i
class="glyphicon glyphicon-phone-alt"></i></span>
<span class="input-group-addon" id="basic-addon1"><i
class="glyphicon glyphicon-phone-alt"></i></span>
{/if}
<input type="text" class="form-control" name="username" value="{$d['username']}"
required
@ -25,27 +24,27 @@
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Full Name')}</label>
<div class="col-md-6">
<label class="col-md-3 control-label">{Lang::T('Full Name')}</label>
<div class="col-md-9">
<input type="text" class="form-control" id="fullname" name="fullname"
value="{$d['fullname']}">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Email')}</label>
<div class="col-md-6">
<label class="col-md-3 control-label">{Lang::T('Email')}</label>
<div class="col-md-9">
<input type="email" class="form-control" id="email" name="email" value="{$d['email']}">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Phone Number')}</label>
<div class="col-md-6">
<label class="col-md-3 control-label">{Lang::T('Phone Number')}</label>
<div class="col-md-9">
<div class="input-group">
{if $_c['country_code_phone']!= ''}
<span class="input-group-addon" id="basic-addon1">+</span>
<span class="input-group-addon" id="basic-addon1">+</span>
{else}
<span class="input-group-addon" id="basic-addon1"><i
class="glyphicon glyphicon-phone-alt"></i></span>
<span class="input-group-addon" id="basic-addon1"><i
class="glyphicon glyphicon-phone-alt"></i></span>
{/if}
<input type="text" class="form-control" name="phonenumber" value="{$d['phonenumber']}"
placeholder="{if $_c['country_code_phone']!= ''}{$_c['country_code_phone']}{/if} {Lang::T('Phone Number')}">
@ -53,8 +52,8 @@
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Password')}</label>
<div class="col-md-6">
<label class="col-md-3 control-label">{Lang::T('Password')}</label>
<div class="col-md-9">
<input type="password" autocomplete="off" class="form-control" id="password" name="password"
onmouseleave="this.type = 'password'" onmouseenter="this.type = 'text'"
value="{$d['password']}">
@ -62,8 +61,8 @@
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('PPPOE Password')}</label>
<div class="col-md-6">
<label class="col-md-3 control-label">{Lang::T('PPPOE Password')}</label>
<div class="col-md-9">
<input type="password" autocomplete="off" class="form-control" id="pppoe_password"
name="pppoe_password" value="{$d['pppoe_password']}"
onmouseleave="this.type = 'password'" onmouseenter="this.type = 'text'">
@ -73,14 +72,14 @@
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Address')}</label>
<div class="col-md-6">
<label class="col-md-3 control-label">{Lang::T('Address')}</label>
<div class="col-md-9">
<textarea name="address" id="address" class="form-control">{$d['address']}</textarea>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Service Type')}</label>
<div class="col-md-6">
<label class="col-md-3 control-label">{Lang::T('Service Type')}</label>
<div class="col-md-9">
<select class="form-control" id="service_type" name="service_type">
<option value="Hotspot" {if $d['service_type'] eq 'Hotspot' }selected{/if}>Hotspot
</option>
@ -89,79 +88,143 @@
</select>
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label">{Lang::T('Account Type')}</label>
<div class="col-md-9">
<select class="form-control" id="account_type" name="account_type">
<option value="Personal" {if $d['account_type'] eq 'Personal' }selected{/if}>Personal
</option>
<option value="Business" {if $d['account_type'] eq 'Business' }selected{/if}>Business
</option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label">{Lang::T('Coordinates')}</label>
<div class="col-md-9">
<input name="coordinates" id="coordinates" class="form-control" value="{$d['coordinates']}"
placeholder="6.465422, 3.406448">
<div id="map" style="width: '100%'; height: 200px; min-height: 150px;"></div>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="panel panel-primary panel-hovered panel-stacked mb30">
<div class="panel-heading">{Lang::T('Attributes')}</div>
<div class="panel-body">
<!--Customers Attributes edit start -->
{if $customFields}
{foreach $customFields as $customField}
<div class="form-group">
<label class="col-md-2 control-label"
for="{$customField.field_name}">{$customField.field_name}</label>
<div class="col-md-6">
<input class="form-control" type="text" name="custom_fields[{$customField.field_name}]"
id="{$customField.field_name}" value="{$customField.field_value}">
</div>
<input type="checkbox" name="delete_custom_fields[]" value="{$customField.field_name}"> Delete
</div>
{/foreach}
{foreach $customFields as $customField}
<div class="form-group">
<label class="col-md-4 control-label"
for="{$customField.field_name}">{$customField.field_name}</label>
<div class="col-md-6">
<input class="form-control" type="text" name="custom_fields[{$customField.field_name}]"
id="{$customField.field_name}" value="{$customField.field_value}">
</div>
<label class="col-md-2">
<input type="checkbox" name="delete_custom_fields[]" value="{$customField.field_name}">
Delete
</label>
</div>
{/foreach}
{/if}
<!--Customers Attributes edit end -->
<!--Customers Attributes add start -->
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Attributes')}</label>
<div id="custom-fields-container" class="col-md-6">
<button class="btn btn-success btn-sm" type="button"
id="add-custom-field">+</button>
</div>
<!-- Customers Attributes add start -->
<div id="custom-fields-container">
</div>
<!--Customers Attributes add end -->
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<button class="btn btn-primary" type="submit">
{Lang::T('Save Changes')}
</button>
Or <a href="{$_url}customers/list">{Lang::T('Cancel')}</a>
</div>
</div>
</form>
<!-- Customers Attributes add end -->
</div>
<div class="panel-footer">
<button class="btn btn-success btn-block" type="button"
id="add-custom-field">{Lang::T('Add')}</button>
</div>
</div>
</div>
</div>
</div>
</div>
<center>
<button class="btn btn-primary" type="submit">
{Lang::T('Save Changes')}
</button>
<br><a href="{$_url}customers/list" class="btn btn-link">{Lang::T('Cancel')}</a>
</center>
</form>
{literal}
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function () {
var customFieldsContainer = document.getElementById('custom-fields-container');
var addCustomFieldButton = document.getElementById('add-custom-field');
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
var customFieldsContainer = document.getElementById('custom-fields-container');
var addCustomFieldButton = document.getElementById('add-custom-field');
addCustomFieldButton.addEventListener('click', function () {
var fieldIndex = customFieldsContainer.children.length;
var newField = document.createElement('div');
newField.className = 'form-group';
newField.innerHTML = `
<label class="col-md-2 control-label">Name:</label>
<div class="col-md-3">
addCustomFieldButton.addEventListener('click', function() {
var fieldIndex = customFieldsContainer.children.length;
var newField = document.createElement('div');
newField.className = 'form-group';
newField.innerHTML = `
<div class="col-md-4">
<input type="text" class="form-control" name="custom_field_name[]" placeholder="Name">
</div>
<label class="col-md-2 control-label">Value:</label>
<div class="col-md-3">
<div class="col-md-6">
<input type="text" class="form-control" name="custom_field_value[]" placeholder="Value">
</div>
<div class="col-md-2">
<button type="button" class="remove-custom-field btn btn-danger btn-sm">-</button>
</div>
`;
customFieldsContainer.appendChild(newField);
});
customFieldsContainer.appendChild(newField);
});
customFieldsContainer.addEventListener('click', function (event) {
if (event.target.classList.contains('remove-custom-field')) {
var fieldContainer = event.target.parentNode.parentNode;
fieldContainer.parentNode.removeChild(fieldContainer);
}
customFieldsContainer.addEventListener('click', function(event) {
if (event.target.classList.contains('remove-custom-field')) {
var fieldContainer = event.target.parentNode.parentNode;
fieldContainer.parentNode.removeChild(fieldContainer);
}
});
});
});
</script>
</script>
<script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"></script>
<script>
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
} else {
setupMap(51.505, -0.09);
}
}
function showPosition(position) {
setupMap(position.coords.latitude, position.coords.longitude);
}
function setupMap(lat, lon) {
var map = L.map('map').setView([lat, lon], 13);
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/light_all/{z}/{x}/{y}.png', {
attribution:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>',
subdomains: 'abcd',
maxZoom: 20
}).addTo(map);
var marker = L.marker([lat, lon]).addTo(map);
map.on('click', function(e) {
var coord = e.latlng;
var lat = coord.lat;
var lng = coord.lng;
var newLatLng = new L.LatLng(lat, lng);
marker.setLatLng(newLatLng);
$('#coordinates').val(lat + ',' + lng);
});
}
window.onload = function() {
{/literal}{if $d['coordinates']}
setupMap({$d['coordinates']});
{else}
getLocation();
{/if}{literal}
}
</script>
{/literal}
{include file="sections/footer.tpl"}

View File

@ -37,11 +37,20 @@
onclick="this.select()">
</li>
{/if}
<li class="list-group-item">
<b>{Lang::T('Coordinates')}</b> <span class="pull-right">{$d['coordinates']}</span>
</li>
<!--Customers Attributes view start -->
{if $customFields}
{foreach $customFields as $customField}
<li class="list-group-item">
<b>{$customField.field_name}</b> <span class="pull-right">{$customField.field_value}</span>
<b>{$customField.field_name}</b> <span class="pull-right">
{if strpos($customField.field_value, ':0') === false}
{$customField.field_value}
{else}
<b>{Lang::T('Paid')}</b>
{/if}
</span>
</li>
{/foreach}
{/if}
@ -49,12 +58,16 @@
<li class="list-group-item">
<b>{Lang::T('Service Type')}</b> <span class="pull-right">{Lang::T($d['service_type'])}</span>
</li>
<li class="list-group-item">
<b>{Lang::T('Account Type')}</b> <span class="pull-right">{Lang::T($d['account_type'])}</span>
</li>
<li class="list-group-item">
<b>{Lang::T('Balance')}</b> <span class="pull-right">{Lang::moneyFormat($d['balance'])}</span>
</li>
<li class="list-group-item">
<b>{Lang::T('Auto Renewal')}</b> <span class="pull-right">{if
$d['auto_renewal']}yes{else}no{/if}</span>
$d['auto_renewal']}yes{else}no
{/if}</span>
</li>
<li class="list-group-item">
<b>{Lang::T('Created On')}</b> <span
@ -78,14 +91,19 @@
</div>
</div>
</div>
{if $package}
{foreach $packages as $package}
<div class="box box-{if $package['status']=='on'}success{else}danger{/if}">
<div class="box-body box-profile">
<h4 class="text-center">{$package['type']} - {$package['namebp']}</h4>
<ul class="list-group list-group-unbordered">
<li class="list-group-item">
{Lang::T('Active')} <span class="pull-right">{if
$package['status']=='on'}yes{else}no{/if}</span>
$package['status']=='on'}yes{else}no
{/if}</span>
</li>
<li class="list-group-item">
{Lang::T('Type')} <span class="pull-right">
{if $package['prepaid'] eq yes}Prepaid{else}<b>Postpaid</b>{/if}</span>
</li>
<li class="list-group-item">
{Lang::T('Created On')} <span
@ -102,28 +120,32 @@
</ul>
<div class="row">
<div class="col-xs-4">
<a href="{$_url}customers/deactivate/{$d['id']}" id="{$d['id']}"
<a href="{$_url}customers/deactivate/{$d['id']}/{$package['plan_id']}" id="{$d['id']}"
class="btn btn-danger btn-block btn-sm"
onclick="return confirm('This will deactivate Customer Plan, and make it expired')">{Lang::T('Deactivate')}</a>
</div>
<div class="col-xs-4">
<a href="{$_url}customers/recharge/{$d['id']}"
onclick="return confirm('This will extend Customer plan, same as recharge')"
<div class="col-xs-8">
<a href="{$_url}customers/recharge/{$d['id']}/{$package['plan_id']}"
class="btn btn-success btn-sm btn-block">{Lang::T('Recharge')}</a>
</div>
<div class="col-xs-4">
<a href="{$_url}customers/sync/{$d['id']}"
onclick="return confirm('This will sync Customer to Mikrotik?')"
class="btn btn-primary btn-sm btn-block">{Lang::T('Sync')}</a>
</div>
</div>
</div>
</div>
{else}
<a href="{$_url}prepaid/recharge/{$d['id']}"
class="btn btn-success btn-sm btn-block mt-1">{Lang::T('Recharge')}</a><br>
{/if}
<a href="{$_url}customers/list" class="btn btn-primary btn-sm btn-block mt-1">{Lang::T('Back')}</a><br>
{/foreach}
<div class="row">
<div class="col-xs-4">
<a href="{$_url}customers/list" class="btn btn-primary btn-sm btn-block">{Lang::T('Back')}</a>
</div>
<div class="col-xs-4">
<a href="{$_url}customers/sync/{$d['id']}"
onclick="return confirm('This will sync Customer to Mikrotik?')"
class="btn btn-info btn-sm btn-block">{Lang::T('Sync')}</a>
</div>
<div class="col-xs-4">
<a href="{$_url}message/send/{$d['id']}" class="btn btn-success btn-sm btn-block">{Lang::T('Send
Message')}</a>
</div>
</div>
</div>
<div class="col-sm-8 col-md-8">
<ul class="nav nav-tabs">
@ -149,7 +171,7 @@
</thead>
<tbody>
{foreach $activation as $ds}
<tr onclick="window.location.href = '{$_url}prepaid/view/{$ds['id']}'" style="cursor:pointer;">
<tr onclick="window.location.href = '{$_url}plan/view/{$ds['id']}'" style="cursor:pointer;">
<td>{$ds['invoice']}</td>
<td>{$ds['username']}</td>
<td>{$ds['plan_name']}</td>

View File

@ -18,7 +18,7 @@
<div class="col-md-8">
<form id="site-search" method="post" action="{$_url}customers/list/">
<div class="input-group">
<input type="text" name="search" value="{$search}" class="form-control"
<input type="text" id="search-input" name="search" value="{$search}" class="form-control"
placeholder="{Lang::T('Search')}...">
<div class="input-group-btn">
<button class="btn btn-success" type="submit"><span
@ -37,6 +37,7 @@
<thead>
<tr>
<th>{Lang::T('Username')}</th>
<th>{Lang::T('Account Type')}</th>
<th>{Lang::T('Full Name')}</th>
<th>{Lang::T('Balance')}</th>
<th>{Lang::T('Phone Number')}</th>
@ -52,6 +53,7 @@
<tr>
<td onclick="window.location.href = '{$_url}customers/view/{$ds['id']}'"
style="cursor:pointer;">{$ds['username']}</td>
<td>{$ds['account_type']}</td>
<td onclick="window.location.href = '{$_url}customers/view/{$ds['id']}'"
style="cursor: pointer;">{$ds['fullname']}</td>
<td>{Lang::moneyFormat($ds['balance'])}</td>
@ -65,7 +67,7 @@
<td align="center">
<a href="{$_url}customers/view/{$ds['id']}" id="{$ds['id']}" style="margin: 0px;"
class="btn btn-success btn-xs">&nbsp;&nbsp;{Lang::T('View')}&nbsp;&nbsp;</a>
<a href="{$_url}prepaid/recharge/{$ds['id']}" id="{$ds['id']}" style="margin: 0px;"
<a href="{$_url}plan/recharge/{$ds['id']}" id="{$ds['id']}" style="margin: 0px;"
class="btn btn-primary btn-xs">{Lang::T('Recharge')}</a>
</td>
</tr>
@ -79,4 +81,25 @@
</div>
</div>
<script>
// Functionality to filter table rows based on admin input
document.addEventListener('DOMContentLoaded', function () {
var searchInput = document.getElementById('search-input');
var tableRows = document.querySelectorAll('tbody tr');
searchInput.addEventListener('input', function () {
var searchText = this.value.toLowerCase();
tableRows.forEach(function (row) {
var rowData = row.textContent.toLowerCase();
if (rowData.includes(searchText)) {
row.style.display = '';
} else {
row.style.display = 'none';
}
});
});
});
</script>
{include file="sections/footer.tpl"}

View File

@ -41,7 +41,7 @@
<div class="icon">
<i class="ion ion-person"></i>
</div>
<a href="{$_url}prepaid/list" class="small-box-footer">{Lang::T('View All')} <i
<a href="{$_url}plan/list" class="small-box-footer">{Lang::T('View All')} <i
class="fa fa-arrow-circle-right"></i></a>
</div>
</div>
@ -60,49 +60,52 @@
</div>
</div>
</div>
<!-- solid sales graph -->
{if $_c['hide_mrc'] != 'yes'}
<div class="box box-solid ">
<div class="box-header">
<i class="fa fa-th"></i>
<h3 class="box-title">{Lang::T('Monthly Registered Customers')}</h3>
<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>
<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">
<canvas class="chart" id="chart" style="height: 250px;"></canvas>
</div>
</div>
{/if}
<!-- solid sales graph -->
{if $_c['hide_tms'] != 'yes'}
<div class="box box-solid ">
<div class="box-header">
<i class="fa fa-inbox"></i>
<h3 class="box-title">{Lang::T('Total Monthly Sales')}</h3>
<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>
<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">
<canvas class="chart" id="salesChart" style="height: 250px;"></canvas>
</div>
</div>
{/if}
<div class="row">
<div class="col-md-7">
<!-- solid sales graph -->
{if $_c['hide_mrc'] != 'yes'}
<div class="box box-solid ">
<div class="box-header">
<i class="fa fa-th"></i>
<h3 class="box-title">{Lang::T('Monthly Registered Customers')}</h3>
<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>
<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">
<canvas class="chart" id="chart" style="height: 250px;"></canvas>
</div>
</div>
{/if}
<!-- solid sales graph -->
{if $_c['hide_tms'] != 'yes'}
<div class="box box-solid ">
<div class="box-header">
<i class="fa fa-inbox"></i>
<h3 class="box-title">{Lang::T('Total Monthly Sales')}</h3>
<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>
<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">
<canvas class="chart" id="salesChart" style="height: 250px;"></canvas>
</div>
</div>
{/if}
{if $_c['disable_voucher'] != 'yes' && $stocks['unused']>0 || $stocks['used']>0}
{if $_c['hide_vs'] != 'yes'}
<div class="panel panel-primary mb20 panel-hovered project-stats table-responsive">

View File

@ -5,7 +5,7 @@
<div class="panel panel-primary panel-hovered panel-stacked mb30">
<div class="panel-heading">{Lang::T('Refill Balance')}</div>
<div class="panel-body">
<form class="form-horizontal" method="post" role="form" action="{$_url}prepaid/deposit-post">
<form class="form-horizontal" method="post" role="form" action="{$_url}plan/deposit-post">
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Select Account')}</label>
<div class="col-md-6">
@ -21,7 +21,7 @@
data-placeholder="{Lang::T('Select Plans')}...">
<option></option>
{foreach $p as $pl}
<option value="{$pl['id']}">{$pl['name_plan']} - {Lang::moneyFormat($pl['price'])}</option>
<option value="{$pl['id']}">{if $pl['enabled'] neq 1}DISABLED PLAN &bull; {/if}{$pl['name_plan']} - {Lang::moneyFormat($pl['price'])}</option>
{/foreach}
</select>
</div>

View File

@ -14,10 +14,18 @@
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Client Can Purchase')}</label>
<label class="col-md-2 control-label">{Lang::T('Type')}</label>
<div class="col-md-10">
<input type="radio" name="allow_purchase" value="yes" checked> Yes
<input type="radio" name="allow_purchase" value="no"> No
<input type="radio" name="prepaid" onclick="prePaid()" value="yes" checked> Prepaid
<input type="radio" name="prepaid" onclick="postPaid()" value="no"> Postpaid
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Plan Type')}</label>
<div class="col-md-10">
<input type="radio" name="plan_type" value="Personal" checked> Personal
<input type="radio" name="plan_type" value="Business"> Business
</div>
</div>
{if $_c['radius_enable']}
@ -121,16 +129,9 @@
</div>
<div class="col-md-2">
<select class="form-control" id="validity_unit" name="validity_unit">
<option value="Mins" {if $d['validity_unit'] eq 'Mins'} selected {/if}>{Lang::T('Mins')}
</option>
<option value="Hrs" {if $d['validity_unit'] eq 'Hrs'} selected {/if}>{Lang::T('Hrs')}
</option>
<option value="Days" {if $d['validity_unit'] eq 'Days'} selected {/if}>{Lang::T('Days')}
</option>
<option value="Months" {if $d['validity_unit'] eq 'Months'} selected {/if}>
{Lang::T('Months')}</option>
</select>
</div>
<p class="help-block col-md-4">{Lang::T('1 Period = 1 Month, Expires the 20th of each month')}</p>
</div>
<span id="routerChoose" class="">
<div class="form-group">
@ -165,8 +166,7 @@
</div> *}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button class="btn btn-success"
type="submit">{Lang::T('Save Changes')}</button>
<button class="btn btn-success" type="submit">{Lang::T('Save Changes')}</button>
Or <a href="{$_url}services/hotspot">{Lang::T('Cancel')}</a>
</div>
</div>
@ -175,6 +175,23 @@
</div>
</div>
</div>
<script>
var preOpt = `<option value="Mins">{Lang::T('Mins')}</option>
<option value="Hrs">{Lang::T('Hrs')}</option>
<option value="Days">{Lang::T('Days')}</option>
<option value="Months">{Lang::T('Months')}</option>`;
var postOpt = `<option value="Period">{Lang::T('Period')}</option>`;
function prePaid() {
$("#validity_unit").html(preOpt);
}
function postPaid() {
$("#validity_unit").html(postOpt);
}
document.addEventListener("DOMContentLoaded", function(event) {
prePaid()
})
</script>
{if $_c['radius_enable']}
{literal}
<script>

View File

@ -10,17 +10,35 @@
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Status')}</label>
<div class="col-md-10">
<input type="radio" name="enabled" value="1" {if $d['enabled'] == 1}checked{/if}> Enable
<input type="radio" name="enabled" value="0" {if $d['enabled'] == 0}checked{/if}> Disable
<input type="radio" name="enabled" value="1" {if $d['enabled'] == 1}checked{/if}> Enable
<input type="radio" name="enabled" value="0" {if $d['enabled'] == 0}checked{/if}> Disable
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Client Can Purchase')}</label>
<label class="col-md-2 control-label">{Lang::T('Type')}</label>
<div class="col-md-10">
<input type="radio" name="allow_purchase" value="yes" {if $d['allow_purchase'] == yes}checked{/if}> Yes
<input type="radio" name="allow_purchase" value="no" {if $d['allow_purchase'] == no}checked{/if}> No
<input type="radio" name="prepaid" onclick="prePaid()" value="yes"
{if $d['prepaid'] == yes}checked{/if}>
Prepaid
<input type="radio" name="prepaid" onclick="postPaid()" value="no"
{if $d['prepaid'] == no}checked{/if}> Postpaid
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Plan Type')}</label>
<div class="col-md-10">
<input type="radio" name="plan_type" value="Personal"
{if $d['plan_type'] == 'Personal'}checked{/if}>
Personal
<input type="radio" name="plan_type" value="Business"
{if $d['plan_type'] == 'Business'}checked{/if}> Business
</div>
</div>
{if $_c['radius_enable'] and $d['is_radius']}
<div class="form-group">
<label class="col-md-2 control-label">Radius</label>
@ -131,16 +149,23 @@
</div>
<div class="col-md-2">
<select class="form-control" id="validity_unit" name="validity_unit">
<option value="Mins" {if $d['validity_unit'] eq 'Mins'} selected {/if}>{Lang::T('Mins')}
</option>
<option value="Hrs" {if $d['validity_unit'] eq 'Hrs'} selected {/if}>{Lang::T('Hrs')}
</option>
<option value="Days" {if $d['validity_unit'] eq 'Days'} selected {/if}>{Lang::T('Days')}
</option>
<option value="Months" {if $d['validity_unit'] eq 'Months'} selected {/if}>
{Lang::T('Months')}</option>
{if $d['prepaid'] == yes}
<option value="Mins" {if $d['validity_unit'] eq 'Mins'} selected {/if}>{Lang::T('Mins')}
</option>
<option value="Hrs" {if $d['validity_unit'] eq 'Hrs'} selected {/if}>{Lang::T('Hrs')}
</option>
<option value="Days" {if $d['validity_unit'] eq 'Days'} selected {/if}>{Lang::T('Days')}
</option>
<option value="Months" {if $d['validity_unit'] eq 'Months'} selected {/if}>
{Lang::T('Months')}</option>
{else}
<option value="Period" {if $d['validity_unit'] eq 'Period'} selected {/if}>
{Lang::T('Period')}</option>
{/if}
</select>
</div>
<p class="help-block col-md-4">{Lang::T('1 Period = 1 Month, Expires the 20th of each month')}
</p>
</div>
<span id="routerChoose" class="{if $d['is_radius']}hidden{/if}">
<div class="form-group">
@ -174,8 +199,7 @@
</div> *}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button class="btn btn-success"
type="submit">{Lang::T('Save Changes')}</button>
<button class="btn btn-success" type="submit">{Lang::T('Save Changes')}</button>
Or <a href="{$_url}services/hotspot">{Lang::T('Cancel')}</a>
</div>
</div>
@ -186,6 +210,21 @@
</div>
</div>
<script>
var preOpt = `<option value="Mins">{Lang::T('Mins')}</option>
<option value="Hrs">{Lang::T('Hrs')}</option>
<option value="Days">{Lang::T('Days')}</option>
<option value="Months">{Lang::T('Months')}</option>`;
var postOpt = `<option value="Period">{Lang::T('Period')}</option>`;
function prePaid() {
$("#validity_unit").html(preOpt);
}
function postPaid() {
$("#validity_unit").html(postOpt);
}
</script>
{if $_c['radius_enable'] && $d['is_radius']}
{literal}
<script>
@ -213,4 +252,4 @@
</script>
{/literal}
{/if}
{include file="sections/footer.tpl"}
{include file="sections/footer.tpl"}

View File

@ -27,8 +27,8 @@
</form>
</div>
<div class="col-md-4">
<a href="{$_url}services/add" class="btn btn-primary btn-block"><i
class="ion ion-android-add"> </i> {Lang::T('New Service Plan')}</a>
<a href="{$_url}services/add" class="btn btn-primary btn-block"><i class="ion ion-android-add">
</i> {Lang::T('New Service Plan')}</a>
</div>&nbsp;
</div>
<div class="table-responsive">
@ -50,9 +50,9 @@
</thead>
<tbody>
{foreach $d as $ds}
<tr {if $ds['enabled'] != 1}class="danger" title="disabled"
{elseif $ds['allow_purchase'] != 'yes'}class="warning" title="Customer can't purchase" {/if}>
<tr {if $ds['enabled'] != 1}class="danger" title="disabled"{/if}>
<td class="headcol">{$ds['name_plan']}</td>
<td>{$ds['plan_type']} {if $ds['prepaid'] != 'yes'}<b>Postpaid</b>{else}Prepaid{/if}</td>
<td>{$ds['typebp']}</td>
<td>{$ds['name_bw']}</td>
<td>{Lang::moneyFormat($ds['price'])}</td>
@ -68,7 +68,10 @@
{/if}
{/if}
</td>
<td>{$ds['pool_expired']}{if $ds['list_expired']}{if $ds['pool_expired']} | {/if}{$ds['list_expired']}{/if}</td>
<td>{$ds['pool_expired']}{if $ds['list_expired']}
{if $ds['pool_expired']} |
{/if}{$ds['list_expired']}
{/if}</td>
<td>
<a href="{$_url}services/edit/{$ds['id']}"
class="btn btn-info btn-xs">{Lang::T('Edit')}</a>

View File

@ -0,0 +1,21 @@
{include file="sections/user-header.tpl"}
<div class="row">
<div class="col-md-4 col-md-offset-2">
<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}plan/print" target="_blank">
<pre id="content">{$invoice}</pre>
<input type="hidden" name="id" value="{$in['id']}">
<a href="{$_url}voucher/list-activated" 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>
</form>
</div>
</div>
</div>
</div>
{include file="sections/user-footer.tpl"}

View File

@ -5,16 +5,16 @@
<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">
<form class="form-horizontal" method="post" action="{$_url}plan/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
<a href="{$_url}plan/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
<a href="{$_url}plan/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>

61
ui/ui/map-customer.tpl Normal file
View File

@ -0,0 +1,61 @@
{include file="sections/header.tpl"}
<!-- Map container div -->
<div id="map" style="width: '100%'; height: 600px; margin: 20px auto"></div>
{literal}
<script>
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
} else {
setupMap(51.505, -0.09);
}
}
function showPosition(position) {
setupMap(position.coords.latitude, position.coords.longitude);
}
function setupMap(lat, lon) {
var map = L.map('map').setView([lat, lon], 13);
var group = L.featureGroup().addTo(map);
var customers = {/literal}{$customers|json_encode}{literal};
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/light_all/{z}/{x}/{y}.png', {
attribution:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>',
subdomains: 'abcd',
maxZoom: 20
}).addTo(map);
customers.forEach(function(customer) {
var name = customer.id;
var name = customer.name;
var info = customer.info;
var coordinates = customer.coordinates;
var balance = customer.balance;
var address = customer.address;
// Create a popup for the marker
var popupContent = "<strong>Customer Name</strong>: " + name + "<br>" +
"<strong>Customer Info</strong>: " + info + "<br>" +
"<strong>Customer Balance</strong>: " + balance + "<br>" +
"<strong>Address</strong>: " + address + "<br>" +
"<strong>Coordinates</strong>: " + coordinates + "<br>" +
"<a href='{/literal}{$_url}{literal}customers/view/"+ customer.id +"'>More Info</a><br>";
// Add marker to map
var marker = L.marker(JSON.parse(coordinates)).addTo(group);
marker.bindTooltip(name).bindPopup(popupContent);
});
map.fitBounds(group.getBounds());
}
window.onload = function() {
getLocation();
}
</script>
{/literal}
{include file="sections/footer.tpl"}

142
ui/ui/message-bulk.tpl Normal file
View File

@ -0,0 +1,142 @@
{include file="sections/header.tpl"}
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.11.3/css/jquery.dataTables.min.css">
<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('Send Bulk Message')}</div>
<div class="panel-body">
<form class="form-horizontal" method="post" role="form" id="bulkMessageForm" action="">
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Group')}</label>
<div class="col-md-6">
<select class="form-control" name="group" id="group">
<option value="all" selected>{Lang::T('All Customers')}</option>
<option value="new">{Lang::T('New Customers')}</option>
<option value="expired">{Lang::T('Expired Customers')}</option>
<option value="active">{Lang::T('Active Customers')}</option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Send Via')}</label>
<div class="col-md-6">
<select class="form-control" name="via" id="via">
<option value="sms" selected>{Lang::T('SMS')}</option>
<option value="wa">{Lang::T('WhatsApp')}</option>
<option value="both">{Lang::T('SMS and WhatsApp')}</option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Message per time')}</label>
<div class="col-md-6">
<select class="form-control" name="batch" id="batch">
<option value="5">{Lang::T('5 Messages')}</option>
<option value="10" selected>{Lang::T('10 Messages')}</option>
<option value="15">{Lang::T('15 Messages')}</option>
<option value="20">{Lang::T('20 Messages')}</option>
<option value="20">{Lang::T('30 Messages')}</option>
<option value="20">{Lang::T('40 Messages')}</option>
<option value="20">{Lang::T('50 Messages')}</option>
<option value="20">{Lang::T('60 Messages')}</option>
</select>{Lang::T('Use 20 and above if you are sending to all customers to avoid server time out')}
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Delay')}</label>
<div class="col-md-6">
<select class="form-control" name="delay" id="delay">
<option value="0" selected>{Lang::T('No Delay')}</option>
<option value="5">{Lang::T('5 Seconds')}</option>
<option value="10">{Lang::T('10 Seconds')}</option>
<option value="15">{Lang::T('15 Seconds')}</option>
<option value="20">{Lang::T('20 Seconds')}</option>
</select>{Lang::T('Use at least 5 secs if you are sending to all customers to avoid being banned by your message provider')}
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Message')}</label>
<div class="col-md-6">
<textarea class="form-control" id="message" name="message"
placeholder="{Lang::T('Compose your message...')}" rows="5"></textarea>
<input name="test" type="checkbox"> {Lang::T('Testing [if checked no real message is sent]')}
</div>
<p class="help-block col-md-4">
{Lang::T('Use placeholders:')}
<br>
<b>[[name]]</b> - {Lang::T('Customer Name')}
<br>
<b>[[user_name]]</b> - {Lang::T('Customer Username')}
<br>
<b>[[phone]]</b> - {Lang::T('Customer Phone')}
<br>
<b>[[company_name]]</b> - {Lang::T('Your Company Name')}
</p>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<button class="btn btn-success" type="submit" name=send value=now>
{Lang::T('Send Message')}</button>
<a href="{$_url}dashboard" class="btn btn-default">{Lang::T('Cancel')}</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{if $batchStatus}
<p><span class="label label-success">Total SMS Sent: {$totalSMSSent}</span> <span class="label label-danger">Total SMS
Failed: {$totalSMSFailed}</span> <span class="label label-success">Total WhatsApp Sent:
{$totalWhatsappSent}</span> <span class="label label-danger">Total WhatsApp Failed:
{$totalWhatsappFailed}</span></p>
{/if}
<div class="box">
<div class="box-header">
<h3 class="box-title">Message Results</h3>
</div>
<!-- /.box-header -->
<div class="box-body">
<table id="messageResultsTable" class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Phone</th>
<th>Message</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{foreach $batchStatus as $customer}
<tr>
<td>{$customer.name}</td>
<td>{$customer.phone}</td>
<td>{$customer.message}</td>
<td>{$customer.status}</td>
</tr>
{/foreach}
</tbody>
</table>
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js"></script>
<script>
var $j = jQuery.noConflict();
$j(document).ready(function () {
$j('#messageResultsTable').DataTable();
});
</script>
{include file="sections/footer.tpl"}

64
ui/ui/message.tpl Normal file
View File

@ -0,0 +1,64 @@
{include file="sections/header.tpl"}
<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('Send Personal Message')}</div>
<div class="panel-body">
<form class="form-horizontal" method="post" role="form" action="{$_url}message/send-post">
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Customer')}</label>
<div class="col-md-6">
<select {if $cust}{else}id="personSelect" {/if} class="form-control select2"
name="id_customer" style="width: 100%"
data-placeholder="{Lang::T('Select a customer')}...">
{if $cust}
<option value="{$cust['id']}">{$cust['username']} &bull; {$cust['fullname']} &bull;
{$cust['email']}</option>
{/if}
</select>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Send Via')}</label>
<div class="col-md-6">
<select class="form-control" name="via" id="via">
<option value="sms" selected> {Lang::T('SMS')}</option>
<option value="wa"> {Lang::T('WhatsApp')}</option>
<option value="both"> {Lang::T('SMS and WhatsApp')}</option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Message')}</label>
<div class="col-md-6">
<textarea class="form-control" id="message" name="message"
placeholder="{Lang::T('Compose your message...')}" rows="5"></textarea>
</div>
<p class="help-block col-md-4">
{Lang::T('Use placeholders:')}
<br>
<b>[[name]]</b> - {Lang::T('Customer Name')}
<br>
<b>[[user_name]]</b> - {Lang::T('Customer Username')}
<br>
<b>[[phone]]</b> - {Lang::T('Customer Phone')}
<br>
<b>[[company_name]]</b> - {Lang::T('Your Company Name')}
</p>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<button class="btn btn-success" type="submit">{Lang::T('Send Message')}</button>
<a href="{$_url}dashboard" class="btn btn-default">{Lang::T('Cancel')}</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{include file="sections/footer.tpl"}

View File

@ -1,34 +1,31 @@
{include file="sections/header.tpl"}
<div class="row">
<div class="col-sm-12">
<form method="post">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="panel panel-info panel-hovered">
<div class="panel-heading">{Lang::T('Payment Gateway')}</div>
<div class="panel-body row">
{foreach $pgs as $pg}
<div class="col-sm-4 mb20">
<a href="{$_url}paymentgateway/{$pg}"
class="btn btn-block btn-{if $pg==$_c['payment_gateway']}success{else}default{/if}">{ucwords($pg)}</a>
</div>
{/foreach}
</div>
<div class="panel-footer">
<form method="post">
<div class="form-group row">
<label class="col-md-2 control-label">Payment Gateway</label>
<div class="col-md-8">
<select name="payment_gateway" id="payment_gateway" class="form-control">
<option value="none">None</option>
<div class="panel-heading">{Lang::T('Payment Gateway')}</div>
<div class="table-responsive">
<table class="table table-striped table-condensed">
<tbody>
{foreach $pgs as $pg}
<option value="{$pg}" {if $_c['payment_gateway'] eq {$pg}}selected="selected" {/if}>{ucwords($pg)}</option>
<tr>
<td width="10" align="center" valign="center"><input type="checkbox" name="pgs[]"
{if in_array($pg, $actives)}checked{/if} value="{$pg}"></td>
<td><a href="{$_url}paymentgateway/{$pg}"
class="btn btn-block btn-{if in_array($pg, $actives)}info{else}default{/if} text-left">{ucwords($pg)}</a>
</td>
<td width="10"><a href="{$_url}paymentgateway/delete/{$pg}"
onclick="return confirm('{Lang::T('Delete')} {$pg}?')" class="btn btn-danger"><i
class="glyphicon glyphicon-trash"></i></a></td>
</tr>
{/foreach}
</select>
</div>
<div class="col-md-2">
<button class="btn btn-block btn-primary" type="submit">{Lang::T('Save Changes')}</button>
</div>
</div>
</tbody>
</table>
</div>
<div class="panel-footer"><button type="submit" class="btn btn-primary btn-block" name="save"
value="actives">{Lang::T('Save Changes')}</button></div>
</div>
</div>
</div>
</div>
{include file="sections/footer.tpl"}
</form>
{include file="sections/footer.tpl"}

View File

@ -7,7 +7,7 @@
<h3 class="panel-title">Edit Plan</h3>
</div>
<div class="panel-body">
<form class="form-horizontal" method="post" role="form" action="{$_url}prepaid/edit-post">
<form class="form-horizontal" method="post" role="form" action="{$_url}plan/edit-post">
<input type="hidden" name="id" value="{$d['id']}">
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Select Account')}</label>
@ -23,7 +23,8 @@
<select id="id_plan" name="id_plan" class="form-control select2">
{foreach $p as $ps}
<option value="{$ps['id']}" {if $d['plan_id'] eq $ps['id']} selected {/if}>
{if $ps['is_radius']=='1'}Radius{else}{$ps['routers']}{/if} - {$ps['name_plan']}</option>
{if $ps['enabled'] neq 1}DISABLED PLAN &bull; {/if}
{if $ps['is_radius']=='1'}Radius{else}{$ps['routers']}{/if} &bull; {$ps['name_plan']}</option>
{/foreach}
</select>
</div>
@ -55,7 +56,7 @@
<div class="col-lg-offset-2 col-lg-10">
<button class="btn btn-success"
type="submit">{Lang::T('Edit')}</button>
Or <a href="{$_url}prepaid/list">{Lang::T('Cancel')}</a>
Or <a href="{$_url}plan/list">{Lang::T('Cancel')}</a>
</div>
</div>
</form>

View File

@ -6,7 +6,7 @@
<div class="panel-heading">
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
<div class="btn-group pull-right">
<a class="btn btn-primary btn-xs" title="save" href="{$_url}prepaid/sync"
<a class="btn btn-primary btn-xs" title="save" href="{$_url}plan/sync"
onclick="return confirm('This will sync/send Caustomer active plan to Mikrotik?')"><span
class="glyphicon glyphicon-refresh" aria-hidden="true"></span> sync</a>
</div>
@ -16,12 +16,12 @@
aria-hidden="true"></span> CSV</a>
</div>
{/if}
{Lang::T('Prepaid Users')}
&nbsp;
</div>
<div class="panel-body">
<div class="md-whiteframe-z1 mb20 text-center" style="padding: 15px">
<div class="col-md-8">
<form id="site-search" method="post" action="{$_url}prepaid/list/">
<form id="site-search" method="post" action="{$_url}plan/list/">
<div class="input-group">
<div class="input-group-addon">
<span class="fa fa-search"></span>
@ -35,7 +35,7 @@
</form>
</div>
<div class="col-md-4">
<a href="{$_url}prepaid/recharge" class="btn btn-primary btn-block"><i
<a href="{$_url}plan/recharge" class="btn btn-primary btn-block"><i
class="ion ion-android-add"> </i> {Lang::T('Recharge Account')}</a>
</div>&nbsp;
</div>
@ -45,6 +45,7 @@
<tr>
<th>{Lang::T('Username')}</th>
<th>{Lang::T('Plan Name')}</th>
<th>{Lang::T('Plan Type')}</th>
<th>{Lang::T('Type')}</th>
<th>{Lang::T('Created On')}</th>
<th>{Lang::T('Expires On')}</th>
@ -59,15 +60,16 @@
<td><a href="{$_url}customers/viewu/{$ds['username']}">{$ds['username']}</a></td>
<td>{$ds['namebp']}</td>
<td>{$ds['type']}</td>
<td>{$ds['plan_type']}</td>
<td>{Lang::dateAndTimeFormat($ds['recharged_on'],$ds['recharged_time'])}</td>
<td>{Lang::dateAndTimeFormat($ds['expiration'],$ds['time'])}</td>
<td>{$ds['method']}</td>
<td>{$ds['routers']}</td>
<td>
<a href="{$_url}prepaid/edit/{$ds['id']}"
<a href="{$_url}plan/edit/{$ds['id']}"
class="btn btn-warning btn-xs">{Lang::T('Edit')}</a>
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
<a href="{$_url}prepaid/delete/{$ds['id']}" id="{$ds['id']}"
<a href="{$_url}plan/delete/{$ds['id']}" id="{$ds['id']}"
onclick="return confirm('{Lang::T('Delete')}?')"
class="btn btn-danger btn-xs"><i class="glyphicon glyphicon-trash"></i></a>
{/if}

View File

@ -14,17 +14,22 @@
<div style="max-height: 50px; min-height: 50px;">{$plugin['description']}</div>
</div>
<div class="box-footer ">
<center><small><i>@{$plugin['author']} Last update: {$plugin['last_update']}</i></small></center>
<center><small><i>@{$plugin['author']} Last update: {$plugin['last_update']}</i></small>
</center>
<div class="btn-group btn-group-justified" role="group" aria-label="...">
<a href="{$plugin['url']}" target="_blank" class="btn btn-primary"><i
class="ion ion-chatboxes"></i> Website</a>
<a href="{$plugin['github']}" target="_blank" class="btn btn-success"><i
class="ion ion-chatboxes"></i> Github</a>
<a href="{$plugin['url']}" target="_blank" style="color: black;" class="btn btn-primary"><i
class="glyphicon glyphicon-globe"></i> Web</a>
<a href="{$plugin['github']}" target="_blank" style="color: black;" class="btn btn-info"><i
class="glyphicon glyphicon-align-left"></i> Source</a>
</div>
<div class="btn-group btn-group-justified" role="group" aria-label="...">
<a href="{$_url}pluginmanager/delete/plugin/{$plugin['id']}" onclick="return confirm('{Lang::T('Delete')}?')" class="btn btn-danger"><i
class="glyphicon glyphicon-trash"></i> Delete</a>
<a {if $zipExt } href="{$_url}pluginmanager/install/plugin/{$plugin['id']}"
onclick="return confirm('Installing plugin will take some time to complete, do not close the page while it loading to install the plugin')"
{else} href="#" onclick="alert('PHP ZIP extension is not installed')"
{/if}
class="btn btn-warning"><i class="ion ion-chatboxes"></i> Install</a>
{else} href="#" onclick="alert('PHP ZIP extension is not installed')"
{/if} style="color: black;"
class="btn btn-success"><i class="glyphicon glyphicon-circle-arrow-down"></i> Install</a>
</div>
</div>
</div>
@ -47,15 +52,15 @@
<div class="box-footer ">
<center><small><i>@{$pg['author']} Last update: {$pg['last_update']}</i></small></center>
<div class="btn-group btn-group-justified" role="group" aria-label="...">
<a href="{$pg['url']}" target="_blank" class="btn btn-primary"><i
class="ion ion-chatboxes"></i> Website</a>
<a href="{$pg['github']}" target="_blank" class="btn btn-success"><i
class="ion ion-chatboxes"></i> Github</a>
<a href="{$pg['url']}" target="_blank" style="color: black;" class="btn btn-primary"><i
class="glyphicon glyphicon-globe"></i> Web</a>
<a href="{$pg['github']}" target="_blank" style="color: black;" class="btn btn-info"><i
class="glyphicon glyphicon-align-left"></i> Source</a>
<a {if $zipExt } href="{$_url}pluginmanager/install/payment/{$pg['id']}"
onclick="return confirm('Installing plugin will take some time to complete, do not close the page while it loading to install the plugin')"
{else} href="#" onclick="alert('PHP ZIP extension is not available')"
{/if}
class="btn btn-warning"><i class="ion ion-chatboxes"></i> Install</a>
{else} href="#" onclick="alert('PHP ZIP extension is not available')"
{/if} style="color: black;"
class="btn btn-success"><i class="glyphicon glyphicon-circle-arrow-down"></i> Install</a>
</div>
</div>
</div>

View File

@ -14,12 +14,21 @@
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Client Can Purchase')}</label>
<label class="col-md-2 control-label">{Lang::T('Type')}</label>
<div class="col-md-10">
<input type="radio" checked name="allow_purchase" value="yes"> Yes
<input type="radio" name="allow_purchase" value="no"> No
<input type="radio" name="prepaid" onclick="prePaid()" value="yes" checked> Prepaid
<input type="radio" name="prepaid" onclick="postPaid()" value="no"> Postpaid
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Plan Type')}</label>
<div class="col-md-10">
<input type="radio" name="plan_type" value="Personal" checked> Personal
<input type="radio" name="plan_type" value="Business"> Business
</div>
</div>
{if $_c['radius_enable']}
<div class="form-group">
<label class="col-md-2 control-label">Radius</label>
@ -63,12 +72,9 @@
</div>
<div class="col-md-2">
<select class="form-control" id="validity_unit" name="validity_unit">
<option value="Mins">{Lang::T('Mins')}</option>
<option value="Hrs">{Lang::T('Hrs')}</option>
<option value="Days">{Lang::T('Days')}</option>
<option value="Months">{Lang::T('Months')}</option>
</select>
</div>
<p class="help-block col-md-4">{Lang::T('1 Period = 1 Month, Expires the 20th of each month')}</p>
</div>
<div class="form-group">
<label class="col-md-2 control-label"><a
@ -119,6 +125,23 @@
</div>
</div>
</div>
<script>
var preOpt = `<option value="Mins">{Lang::T('Mins')}</option>
<option value="Hrs">{Lang::T('Hrs')}</option>
<option value="Days">{Lang::T('Days')}</option>
<option value="Months">{Lang::T('Months')}</option>`;
var postOpt = `<option value="Period">{Lang::T('Period')}</option>`;
function prePaid() {
$("#validity_unit").html(preOpt);
}
function postPaid() {
$("#validity_unit").html(postOpt);
}
document.addEventListener("DOMContentLoaded", function(event) {
prePaid()
})
</script>
{if $_c['radius_enable']}
{literal}
<script>

View File

@ -15,12 +15,24 @@
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Client Can Purchase')}</label>
<label class="col-md-2 control-label">{Lang::T('Type')}</label>
<div class="col-md-10">
<input type="radio" name="allow_purchase" value="yes" {if $d['allow_purchase'] == yes}checked{/if}> Yes
<input type="radio" name="allow_purchase" value="no" {if $d['allow_purchase'] == no}checked{/if}> No
<input type="radio" name="prepaid" onclick="prePaid()" value="yes" {if $d['prepaid'] == yes}checked{/if}>
Prepaid
<input type="radio" name="prepaid" onclick="postPaid()" value="no" {if $d['prepaid'] == no}checked{/if}> Postpaid
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Plan Type')}</label>
<div class="col-md-10">
<input type="radio" name="plan_type" value="Personal"
{if $d['plan_type'] == 'Personal'}checked{/if}>
Personal
<input type="radio" name="plan_type" value="Business"
{if $d['plan_type'] == 'Business'}checked{/if}> Business
</div>
</div>
{if $_c['radius_enable'] and $d['is_radius']}
<div class="form-group">
<label class="col-md-2 control-label">Radius</label>
@ -65,16 +77,23 @@
</div>
<div class="col-md-2">
<select class="form-control" id="validity_unit" name="validity_unit">
<option value="Mins" {if $d['validity_unit'] eq 'Mins'} selected {/if}>{Lang::T('Mins')}
</option>
<option value="Hrs" {if $d['validity_unit'] eq 'Hrs'} selected {/if}>{Lang::T('Hrs')}
</option>
<option value="Days" {if $d['validity_unit'] eq 'Days'} selected {/if}>{Lang::T('Days')}
</option>
<option value="Months" {if $d['validity_unit'] eq 'Months'} selected {/if}>
{Lang::T('Months')}</option>
{if $d['prepaid'] == yes}
<option value="Mins" {if $d['validity_unit'] eq 'Mins'} selected {/if}>{Lang::T('Mins')}
</option>
<option value="Hrs" {if $d['validity_unit'] eq 'Hrs'} selected {/if}>{Lang::T('Hrs')}
</option>
<option value="Days" {if $d['validity_unit'] eq 'Days'} selected {/if}>{Lang::T('Days')}
</option>
<option value="Months" {if $d['validity_unit'] eq 'Months'} selected {/if}>
{Lang::T('Months')}</option>
{else}
<option value="Period" {if $d['validity_unit'] eq 'Period'} selected {/if}>
{Lang::T('Period')}</option>
{/if}
</select>
</div>
<p class="help-block col-md-4">
{Lang::T('1 Period = 1 Month, Expires the 20th of each month')}</p>
</div>
<div class="form-group">
<label class="col-md-2 control-label"><a href="{$_url}pool/add">{Lang::T('IP Pool')}</a></label>
@ -116,8 +135,7 @@
</div> *}
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<button class="btn btn-success"
type="submit">{Lang::T('Save Changes')}</button>
<button class="btn btn-success" type="submit">{Lang::T('Save Changes')}</button>
Or <a href="{$_url}services/pppoe">{Lang::T('Cancel')}</a>
</div>
</div>
@ -127,6 +145,21 @@
</div>
</div>
<script>
var preOpt = `<option value="Mins">{Lang::T('Mins')}</option>
<option value="Hrs">{Lang::T('Hrs')}</option>
<option value="Days">{Lang::T('Days')}</option>
<option value="Months">{Lang::T('Months')}</option>`;
var postOpt = `<option value="Period">{Lang::T('Period')}</option>`;
function prePaid() {
$("#validity_unit").html(preOpt);
}
function postPaid() {
$("#validity_unit").html(postOpt);
}
</script>
{if $_c['radius_enable'] && $d['is_radius']}
{literal}
<script>
@ -145,4 +178,4 @@
</script>
{/literal}
{/if}
{include file="sections/footer.tpl"}
{include file="sections/footer.tpl"}

View File

@ -36,6 +36,7 @@
<thead>
<tr>
<th>{Lang::T('Plan Name')}</th>
<th>{Lang::T('Plan Type')}</th>
<th>{Lang::T('Bandwidth Plans')}</th>
<th>{Lang::T('Plan Price')}</th>
<th>{Lang::T('Plan Validity')}</th>
@ -48,22 +49,26 @@
</thead>
<tbody>
{foreach $d as $ds}
<tr {if $ds['enabled'] != 1}class="danger" title="disabled"
{elseif $ds['allow_purchase'] != 'yes'}class="warning" title="Customer can't purchase" {/if}>
<tr {if $ds['enabled'] != 1}class="danger" title="disabled"{/if}>
<td>{$ds['name_plan']}</td>
<td>{$ds['plan_type']} {if $ds['prepaid'] != 'yes'}<b>Postpaid</b>{else}Prepaid{/if}</td>
<td>{$ds['name_bw']}</td>
<td>{Lang::moneyFormat($ds['price'])}</td>
<td>{$ds['validity']} {$ds['validity_unit']}</td>
<td>{$ds['pool']}</td>
<td>{$ds['pool_expired']}{if $ds['list_expired']}{if $ds['pool_expired']} | {/if}{$ds['list_expired']}{/if}</td>
<td>{$ds['pool_expired']}{if $ds['list_expired']}
{if $ds['pool_expired']} |
{/if}{$ds['list_expired']}
{/if}</td>
<td>
{if $ds['is_radius']}
<span class="label label-primary">RADIUS</span>
{else}
{if $ds['routers']!=''}
<a href="{$_url}routers/edit/0&name={$ds['routers']}">{$ds['routers']}</a>
{if $ds['is_radius']}
<span class="label label-primary">RADIUS</span>
{else}
{if $ds['routers']!=''}
<a href="{$_url}routers/edit/0&name={$ds['routers']}">{$ds['routers']}</a>
{/if}
{/if}
{/if}</td>
</td>
<td>
<a href="{$_url}services/pppoe-edit/{$ds['id']}"
class="btn btn-info btn-xs">{Lang::T('Edit')}</a>

View File

@ -60,7 +60,7 @@
<body>
<page size="A4">
<form method="post" action="{$_url}prepaid/print-voucher/" class="no-print">
<form method="post" action="{$_url}plan/print-voucher/" class="no-print">
<table width="100%" border="0" cellspacing="0" cellpadding="1" class="btn btn-default btn-sm">
<tr>
<td>From ID &gt; <input type="text" name="from_id" style="width:40px" value="{$from_id}"> limit

View File

@ -0,0 +1,94 @@
{include file="sections/header.tpl"}
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="panel panel-primary panel-hovered panel-stacked mb30">
<div class="panel-heading">{Lang::T('Confirm')}</div>
<div class="panel-body">
<center><b>{Lang::T('Customer')}</b></center>
<ul class="list-group list-group-unbordered">
<li class="list-group-item">
<b>{Lang::T('Username')}</b> <span class="pull-right">{$cust['username']}</span>
</li>
<li class="list-group-item">
<b>{Lang::T('Name')}</b> <span class="pull-right">{$cust['fullname']}</span>
</li>
<li class="list-group-item">
<b>{Lang::T('Phone Number')}</b> <span class="pull-right">{$cust['phonenumber']}</span>
</li>
<li class="list-group-item">
<b>{Lang::T('Email')}</b> <span class="pull-right">{$cust['email']}</span>
</li>
<li class="list-group-item">
<b>{Lang::T('Address')}</b> <span class="pull-right">{$cust['address']}</span>
</li>
<li class="list-group-item">
<b>{Lang::T('Balance')}</b> <span
class="pull-right">{Lang::moneyFormat($cust['balance'])}</span>
</li>
</ul>
<center><b>{Lang::T('Plan')}</b></center>
<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>
<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>
<li class="list-group-item">
<b>{Lang::T('Type')}</b> <span
class="pull-right">{if $plan['prepaid'] eq 'yes'}Prepaid{else}Postpaid{/if}
{$plan['type']}</span>
</li>
<li class="list-group-item">
<b>{Lang::T('Plan Price')}</b> <span
class="pull-right">{if $using eq 'zero'}{Lang::moneyFormat(0)}{else}{Lang::moneyFormat($plan['price'])}{/if}</span>
</li>
<li class="list-group-item">
<b>{Lang::T('Plan Validity')}</b> <span class="pull-right">{$plan['validity']}
{$plan['validity_unit']}</span>
</li>
<li class="list-group-item">
<b>{Lang::T('Using')}</b> <span class="pull-right">{ucwords($using)}</span>
</li>
</ul>
<center><b>{Lang::T('Total')}</b></center>
<ul class="list-group list-group-unbordered">
{if $using neq 'zero' and $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('Plan 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; ">{if $using eq 'zero'}{Lang::moneyFormat(0)}{else}{Lang::moneyFormat($plan['price'])}{/if}</span>
</li>
{/if}
</ul>
<form class="form-horizontal" method="post" role="form" action="{$_url}plan/recharge-post">
<input type="hidden" name="id_customer" value="{$cust['id']}">
<input type="hidden" name="plan" value="{$plan['id']}">
<input type="hidden" name="server" value="{$server}">
<input type="hidden" name="using" value="{$using}">
<center>
<button class="btn btn-success" type="submit">{Lang::T('Recharge')}</button><br>
<a class="btn btn-link" href="{$_url}plan/recharge">{Lang::T('Cancel')}</a>
</center>
</form>
</div>
</div>
</div>
</div>
{include file="sections/footer.tpl"}

View File

@ -1,62 +0,0 @@
{include file="sections/header.tpl"}
<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('Recharge Account')}</div>
<div class="panel-body">
<form class="form-horizontal" method="post" role="form" action="{$_url}prepaid/recharge-post" >
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Select Account')}</label>
<div class="col-md-6">
<select id="personSelect" class="form-control select2" name="id_customer" style="width: 100%" data-placeholder="Select a customer...">
<option></option>
{foreach $c as $cs}
{if $id eq $cs['id']}
<option value="{$cs['id']}" selected>{$cs['username']}</option>
{else}
<option value="{$cs['id']}">{$cs['username']}</option>
{/if}
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Type')}</label>
<div class="col-md-6">
<label><input type="radio" id="Hot" name="type" value="Hotspot"> {Lang::T('Hotspot Plans')}</label>
<label><input type="radio" id="POE" name="type" value="PPPOE"> {Lang::T('PPPOE Plans')}</label>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Routers')}</label>
<div class="col-md-6">
<select id="server" name="server" class="form-control select2">
<option value=''>Select Routers</option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Service Plan')}</label>
<div class="col-md-6">
<select id="plan" name="plan" class="form-control select2">
<option value=''>Select Plans</option>
</select>
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<button class="btn btn-success" type="submit">{Lang::T('Recharge')}</button>
Or <a href="{$_url}customers/list">{Lang::T('Cancel')}</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{include file="sections/footer.tpl"}

View File

@ -5,7 +5,7 @@
<div class="panel panel-primary panel-hovered panel-stacked mb30">
<div class="panel-heading">{Lang::T('Recharge Account')}</div>
<div class="panel-body">
<form class="form-horizontal" method="post" role="form" action="{$_url}prepaid/recharge-post">
<form class="form-horizontal" method="post" role="form" action="{$_url}plan/recharge-confirm">
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Select Account')}</label>
<div class="col-md-6">
@ -27,7 +27,7 @@
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Routers')}</label>
<div class="col-md-6">
<select id="server" name="server" class="form-control select2">
<select id="server" data-type="server" name="server" class="form-control select2">
<option value=''>{Lang::T('Select Routers')}</option>
</select>
</div>
@ -41,7 +41,19 @@
</select>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Using')}</label>
<div class="col-md-6">
<select name="using" class="form-control">
<option value="cash">{Lang::T('Cash')}</option>
{if $_c['enable_balance'] eq 'yes'}
<option value="balance">{Lang::T('Customer Balance')}</option>
{/if}
<option value="zero">{$_c['currency_code']} 0</option>
</select>
</div>
<p class="help-block col-md-4">Postpaid Recharge for the first time use {$_c['currency_code']} 0</p>
</div>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<button class="btn btn-success"

View File

@ -5,7 +5,7 @@
<div class="panel panel-primary panel-hovered panel-stacked mb30">
<div class="panel-heading">{Lang::T('Refill Account')}</div>
<div class="panel-body">
<form class="form-horizontal" method="post" role="form" action="{$_url}prepaid/refill-post">
<form class="form-horizontal" method="post" role="form" action="{$_url}plan/refill-post">
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Select Account')}</label>
<div class="col-md-6">

View File

@ -44,7 +44,7 @@
<tbody>
{foreach $activation as $ds}
<tr>
<td onclick="window.location.href = '{$_url}prepaid/view/{$ds['id']}'"
<td onclick="window.location.href = '{$_url}plan/view/{$ds['id']}'"
style="cursor:pointer;">{$ds['invoice']}</td>
<td onclick="window.location.href = '{$_url}customers/viewu/{$ds['username']}'"
style="cursor:pointer;">{$ds['username']}</td>

View File

@ -54,17 +54,18 @@
<li>Make sure your hosting not blocking port to external</li>
<li>Make sure your Mikrotik accessible from PHPNuxBill</li>
</ul>
If you just update PHPNuxBill from upload files, try click Update Database
</div>
<div class="box-footer">
<div class="btn-group btn-group-justified" role="group" aria-label="...">
<a href="./update.php?step=4" class="btn btn-info btn-sm btn-block">Update Database</a>
<a href="{$_url}community#update" class="btn btn-success btn-sm btn-block">Update
<a href="./update.php?step=4" style="color: black;" class="btn btn-info btn-sm btn-block">Update Database</a>
<a href="{$_url}community#update" style="color: black;" class="btn btn-success btn-sm btn-block">Update
PHPNuxBill</a>
</div>
<br>
<div class="btn-group btn-group-justified" role="group" aria-label="...">
<a href="https://github.com/hotspotbilling/phpnuxbill/discussions" target="_blank"
class="btn btn-success btn-sm btn-block">Ask Github Community</a>
class="btn btn-success btn-sm btn-block" style="color: black;">Ask Github Community</a>
<a href="https://t.me/phpnuxbill" target="_blank"
class="btn btn-primary btn-sm btn-block">Ask Telegram Community</a>
</div>

View File

@ -27,21 +27,21 @@
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>`
`<span class="loading"></span>`
);
setTimeout(() => {
$(this).prop("disabled", true);
}, 100);
// 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>`
`<span class="loading"></span>`
);
setTimeout(() => {
$(this).prop("disabled", true);
}, 100);
// setTimeout(() => {
// $(this).prop("disabled", true);
// }, 100);
});
}
}

View File

@ -57,8 +57,36 @@
max-height: 1em;
line-height: 1em;
}
</style>
.loading {
pointer-events: none;
opacity: 0.7;
}
.loading::after {
content: "";
display: inline-block;
width: 16px;
height: 16px;
vertical-align: middle;
margin-left: 10px;
border: 2px solid #fff;
border-top-color: transparent;
border-radius: 50%;
animation: spin 0.8s infinite linear;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
{if isset($xheader)}
{$xheader}
{/if}
@ -122,7 +150,7 @@
<aside class="main-sidebar">
<section class="sidebar">
<ul class="sidebar-menu" data-widget="tree">
<li {if $_system_menu eq 'dashboard'}class="active" {/if}>
<li {if $_system_menu eq 'dashboard' }class="active" {/if}>
<a href="{$_url}dashboard">
<i class="ion ion-monitor"></i>
<span>{Lang::T('Dashboard')}</span>
@ -130,69 +158,73 @@
</li>
{$_MENU_AFTER_DASHBOARD}
{if !in_array($_admin['user_type'],['Report'])}
<li class="{if $_system_menu eq 'customers'}active{/if} treeview">
<li class="{if in_array($_system_menu, ['customers', 'map'])}active{/if} treeview">
<a href="#">
<i class="ion ion-android-contacts"></i> <span>{Lang::T('Customer')}</span>
<i class="fa fa-users"></i> <span>{Lang::T('Customer')}</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li {if $_routes[1] eq 'add'}class="active" {/if}><a href="{$_url}customers/add"><i
class="fa fa-user-plus"></i> {Lang::T('Add New Contact')}</a></li>
<li {if $_routes[1] eq 'list'}class="active" {/if}><a href="{$_url}customers/list"><i
class="fa fa-users"></i> {Lang::T('List Contact')}</a></li>
<li {if $_system_menu eq 'customers' }class="active" {/if}><a
href="{$_url}customers">{Lang::T('Lists')}</a></li>
<li {if $_system_menu eq 'map' }class="active" {/if}><a
href="{$_url}map/customer">{Lang::T('Location')}</a></li>
{$_MENU_CUSTOMERS}
</ul>
</li>
{$_MENU_AFTER_CUSTOMERS}
<li class="{if $_system_menu eq 'prepaid'}active{/if} treeview">
<li class="{if $_system_menu eq 'plan'}active{/if} treeview">
<a href="#">
<i class="fa fa-ticket"></i> <span>{Lang::T('Prepaid')}</span>
<i class="fa fa-ticket"></i> <span>{Lang::T('Services')}</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li {if $_routes[1] eq 'list'}class="active" {/if}><a
href="{$_url}prepaid/list">{Lang::T('Prepaid Users')}</a></li>
<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}prepaid/voucher">{Lang::T('Prepaid Vouchers')}</a></li>
<li {if $_routes[1] eq 'refill'}class="active" {/if}><a
href="{$_url}prepaid/refill">{Lang::T('Refill Account')}</a></li>
<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}
<li {if $_routes[1] eq 'recharge' }class="active" {/if}><a
href="{$_url}plan/recharge">{Lang::T('Recharge Customer')}</a></li>
{if $_c['enable_balance'] == 'yes'}
<li {if $_routes[1] eq 'deposit' }class="active" {/if}><a
href="{$_url}plan/deposit">{Lang::T('Refill Balance')}</a></li>
{/if}
<li {if $_routes[1] eq 'recharge'}class="active" {/if}><a
href="{$_url}prepaid/recharge">{Lang::T('Recharge Account')}</a></li>
<li {if $_routes[1] eq 'deposit'}class="active" {/if}><a
href="{$_url}prepaid/deposit">{Lang::T('Refill Balance')}</a></li>
{$_MENU_PREPAID}
</ul>
</li>
{/if}
{$_MENU_AFTER_PREPAID}
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
<li class="{if $_system_menu eq 'services'}active{/if} treeview">
<a href="#">
<i class="ion ion-cube"></i> <span>{Lang::T('Services')}</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li {if $_routes[1] eq 'hotspot'}class="active" {/if}><a
href="{$_url}services/hotspot">{Lang::T('Hotspot Plans')}</a></li>
<li {if $_routes[1] eq 'pppoe'}class="active" {/if}><a
href="{$_url}services/pppoe">{Lang::T('PPPOE Plans')}</a></li>
<li {if $_routes[1] eq 'list'}class="active" {/if}><a
href="{$_url}bandwidth/list">{Lang::T('Bandwidth Plans')}</a></li>
<li {if $_routes[1] eq 'balance'}class="active" {/if}><a
href="{$_url}services/balance">{Lang::T('Balance Plans')}</a></li>
{$_MENU_SERVICES}
</ul>
</li>
{/if}
{$_MENU_AFTER_SERVICES}
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
<li class="{if $_system_menu eq 'services'}active{/if} treeview">
<a href="#">
<i class="ion ion-cube"></i> <span>{Lang::T('Plans')}</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li {if $_routes[1] eq 'hotspot' }class="active" {/if}><a
href="{$_url}services/hotspot">{Lang::T('Hotspot')}</a></li>
<li {if $_routes[1] eq 'pppoe' }class="active" {/if}><a
href="{$_url}services/pppoe">{Lang::T('PPPOE')}</a></li>
<li {if $_routes[1] eq 'list' }class="active" {/if}><a
href="{$_url}bandwidth/list">{Lang::T('Bandwidth')}</a></li>
{if $_c['enable_balance'] == 'yes'}
<li {if $_routes[1] eq 'balance' }class="active" {/if}><a
href="{$_url}services/balance">{Lang::T('Balance')}</a></li>
{/if}
{$_MENU_PLANS}
</ul>
</li>
{/if}
{$_MENU_AFTER_PLANS}
<li class="{if $_system_menu eq 'reports'}active{/if} treeview">
<a href="#">
<i class="ion ion-clipboard"></i> <span>{Lang::T('Reports')}</span>
@ -201,16 +233,32 @@
</span>
</a>
<ul class="treeview-menu">
<li {if $_routes[1] eq 'daily-report'}class="active" {/if}><a
<li {if $_routes[1] eq 'daily-report' }class="active" {/if}><a
href="{$_url}reports/daily-report">{Lang::T('Daily Reports')}</a></li>
<li {if $_routes[1] eq 'by-period'}class="active" {/if}><a
<li {if $_routes[1] eq 'by-period' }class="active" {/if}><a
href="{$_url}reports/by-period">{Lang::T('Period Reports')}</a></li>
<li {if $_routes[1] eq 'activation'}class="active" {/if}><a
<li {if $_routes[1] eq 'activation' }class="active" {/if}><a
href="{$_url}reports/activation">{Lang::T('Activation History')}</a></li>
{$_MENU_REPORTS}
</ul>
</li>
{$_MENU_AFTER_REPORTS}
<li class="{if $_system_menu eq 'message'}active{/if} treeview">
<a href="#">
<i class="ion ion-android-chat"></i> <span>{Lang::T('Send Message')}</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li {if $_routes[1] eq 'send' }class="active" {/if}><a
href="{$_url}message/send">{Lang::T('Single Customer')}</a></li>
<li {if $_routes[1] eq 'send_bulk' }class="active" {/if}><a
href="{$_url}message/send_bulk">{Lang::T('Bulk Customers')}</a></li>
{$_MENU_MESSAGE}
</ul>
</li>
{$_MENU_AFTER_MESSAGE}
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
<li class="{if $_system_menu eq 'network'}active{/if} treeview">
<a href="#">
@ -220,9 +268,9 @@
</span>
</a>
<ul class="treeview-menu">
<li {if $_routes[0] eq 'routers' and $_routes[1] eq 'list'}class="active" {/if}><a
<li {if $_routes[0] eq 'routers' and $_routes[1] eq 'list' }class="active" {/if}><a
href="{$_url}routers/list">{Lang::T('Routers')}</a></li>
<li {if $_routes[0] eq 'pool' and $_routes[1] eq 'list'}class="active" {/if}><a
<li {if $_routes[0] eq 'pool' and $_routes[1] eq 'list' }class="active" {/if}><a
href="{$_url}pool/list">{Lang::T('IP Pool')}</a></li>
{$_MENU_NETWORK}
</ul>
@ -237,7 +285,7 @@
</span>
</a>
<ul class="treeview-menu">
<li {if $_routes[0] eq 'radius' and $_routes[1] eq 'nas-list'}class="active" {/if}><a
<li {if $_routes[0] eq 'radius' and $_routes[1] eq 'nas-list' }class="active" {/if}><a
href="{$_url}radius/nas-list">{Lang::T('Radius NAS')}</a></li>
{$_MENU_RADIUS}
</ul>
@ -252,17 +300,20 @@
</span>
</a>
<ul class="treeview-menu">
<li {if $_routes[1] eq 'Order_Voucher'}class="active" {/if}><a
<li {if $_routes[1] eq 'Order_Voucher' }class="active" {/if}><a
href="{$_url}pages/Order_Voucher">{Lang::T('Order Voucher')}</a></li>
<li {if $_routes[1] eq 'Voucher'}class="active" {/if}><a
<li {if $_routes[1] eq 'Voucher' }class="active" {/if}><a
href="{$_url}pages/Voucher">{Lang::T('Voucher')} Template</a></li>
<li {if $_routes[1] eq 'Announcement'}class="active" {/if}><a
<li {if $_routes[1] eq 'Announcement' }class="active" {/if}><a
href="{$_url}pages/Announcement">{Lang::T('Announcement')}</a></li>
<li {if $_routes[1] eq 'Registration_Info'}class="active" {/if}><a
<li {if $_routes[1] eq 'Announcement_Customer' }class="active" {/if}><a
href="{$_url}pages/Announcement_Customer">{Lang::T('Customer Announcement')}</a>
</li>
<li {if $_routes[1] eq 'Registration_Info' }class="active" {/if}><a
href="{$_url}pages/Registration_Info">{Lang::T('Registration Info')}</a></li>
<li {if $_routes[1] eq 'Privacy_Policy'}class="active" {/if}><a
<li {if $_routes[1] eq 'Privacy_Policy' }class="active" {/if}><a
href="{$_url}pages/Privacy_Policy">Privacy Policy</a></li>
<li {if $_routes[1] eq 'Terms_and_Conditions'}class="active" {/if}><a
<li {if $_routes[1] eq 'Terms_and_Conditions' }class="active" {/if}><a
href="{$_url}pages/Terms_and_Conditions">Terms and Conditions</a></li>
{$_MENU_PAGES}
</ul>
@ -279,31 +330,31 @@
</a>
<ul class="treeview-menu">
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
<li {if $_routes[1] eq 'app'}class="active" {/if}><a
<li {if $_routes[1] eq 'app' }class="active" {/if}><a
href="{$_url}settings/app">{Lang::T('General Settings')}</a></li>
<li {if $_routes[1] eq 'localisation'}class="active" {/if}><a
<li {if $_routes[1] eq 'localisation' }class="active" {/if}><a
href="{$_url}settings/localisation">{Lang::T('Localisation')}</a></li>
<li {if $_routes[1] eq 'notifications'}class="active" {/if}><a
<li {if $_routes[1] eq 'notifications' }class="active" {/if}><a
href="{$_url}settings/notifications">{Lang::T('User Notification')}</a></li>
{/if}
{if in_array($_admin['user_type'],['SuperAdmin','Admin','Agent'])}
<li {if $_routes[1] eq 'users'}class="active" {/if}><a
<li {if $_routes[1] eq 'users' }class="active" {/if}><a
href="{$_url}settings/users">{Lang::T('Administrator Users')}</a></li>
{/if}
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
<li {if $_routes[1] eq 'dbstatus'}class="active" {/if}><a
<li {if $_routes[1] eq 'dbstatus' }class="active" {/if}><a
href="{$_url}settings/dbstatus">{Lang::T('Backup/Restore')}</a></li>
<li {if $_system_menu eq 'paymentgateway'}class="active" {/if}>
<li {if $_system_menu eq 'paymentgateway' }class="active" {/if}>
<a href="{$_url}paymentgateway">
<span class="text">{Lang::T('Payment Gateway')}</span>
</a>
</li>
{$_MENU_SETTINGS}
<li {if $_routes[0] eq 'pluginmanager'}class="active" {/if}>
<li {if $_routes[0] eq 'pluginmanager' }class="active" {/if}>
<a href="{$_url}pluginmanager"><i class="glyphicon glyphicon-tasks"></i>
{Lang::T('Plugin Manager')} <small class="label pull-right">Free</small></a>
</li>
{* <li {if $_routes[0] eq 'codecanyon'}class="active" {/if}>
{* <li {if $_routes[0] eq 'codecanyon' }class="active" {/if}>
<a href="{$_url}codecanyon"><i class="glyphicon glyphicon-shopping-cart"></i>
Codecanyon.net <small class="label pull-right">Paid</small></a>
</li> *}
@ -320,10 +371,11 @@
</span>
</a>
<ul class="treeview-menu">
<li {if $_routes[1] eq 'list'}class="active" {/if}><a
<li {if $_routes[1] eq 'list' }class="active" {/if}><a
href="{$_url}logs/phpnuxbill">PhpNuxBill</a></li>
{if $_c['radius_enable']}
<li {if $_routes[1] eq 'radius'}class="active" {/if}><a href="{$_url}logs/radius">Radius</a>
<li {if $_routes[1] eq 'radius' }class="active" {/if}><a
href="{$_url}logs/radius">Radius</a>
</li>
{/if}
</ul>
@ -331,7 +383,7 @@
</li>
{/if}
{$_MENU_AFTER_LOGS}
<li {if $_system_menu eq 'community'}class="active" {/if}>
<li {if $_system_menu eq 'community' }class="active" {/if}>
<a href="{$_url}community">
<i class="ion ion-chatboxes"></i>
<span class="text">{Lang::T('Community')}</span>

View File

@ -85,7 +85,7 @@
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>`
`<span class="loading"></span>`
);
setTimeout(() => {
$(this).prop("disabled", true);
@ -95,7 +95,7 @@
if (el.attachEvent) { // IE before version 9
el.attachEvent("click", function() {
$(this).html(
`<span class="glyphicon glyphicon-refresh" role="status" aria-hidden="true"></span>`
`<span class="loading"></span>`
);
setTimeout(() => {
$(this).prop("disabled", true);

View File

@ -37,6 +37,35 @@
margin-top: 100px;
}
}
.loading {
pointer-events: none;
opacity: 0.7;
}
.loading::after {
content: "";
display: inline-block;
width: 16px;
height: 16px;
vertical-align: middle;
margin-left: 10px;
border: 2px solid #fff;
border-top-color: transparent;
border-radius: 50%;
animation: spin 0.8s infinite linear;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
{if isset($xheader)}
@ -61,7 +90,8 @@
<li class="dropdown user user-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
{if $_c['enable_balance'] == 'yes'}
<span style="color: whitesmoke;">&nbsp;{Lang::moneyFormat($_user['balance'])}&nbsp;</span>
<span
style="color: whitesmoke;">&nbsp;{Lang::moneyFormat($_user['balance'])}&nbsp;</span>
{else}
<span>{$_user['fullname']}</span>
{/if}
@ -78,7 +108,7 @@
<p>
{$_user['fullname']}
<small>{$_user['phonenumber']}<br>
{$_user['email']}</small>
{$_user['email']}</small>
</p>
</li>
<li class="user-body">
@ -168,20 +198,20 @@
{if isset($notify)}
<script>
// Display SweetAlert toast notification
Swal.fire({
icon: '{if $notify_t == "s"}success{else}warning{/if}',
title: '{$notify}',
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 5000,
timerProgressBar: true,
didOpen: (toast) => {
toast.addEventListener('mouseenter', Swal.stopTimer)
toast.addEventListener('mouseleave', Swal.resumeTimer)
}
});
</script>
{/if}
<script>
// Display SweetAlert toast notification
Swal.fire({
icon: '{if $notify_t == "s"}success{else}warning{/if}',
title: '{$notify}',
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 5000,
timerProgressBar: true,
didOpen: (toast) => {
toast.addEventListener('mouseenter', Swal.stopTimer)
toast.addEventListener('mouseleave', Swal.resumeTimer)
}
});
</script>
{/if}

View File

@ -10,7 +10,7 @@
<table id="datatable" class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>{Lang::T('Username')}</th>
<th>{Lang::T('Invoice')}</th>
<th>{Lang::T('Plan Name')}</th>
<th>{Lang::T('Plan Price')}</th>
<th>{Lang::T('Type')}</th>
@ -21,8 +21,8 @@
</thead>
<tbody>
{foreach $d as $ds}
<tr>
<td>{$ds['username']}</td>
<tr onclick="window.location.href = '{$_url}voucher/invoice/{$ds['id']}'" style="cursor: pointer;">
<td>{$ds['invoice']}</td>
<td>{$ds['plan_name']}</td>
<td>{Lang::moneyFormat($ds['price'])}</td>
<td>{$ds['type']}</td>

View File

@ -53,7 +53,10 @@
<h3 class="box-title">{Lang::T('Announcement')}</h3>
</div>
<div class="box-body">
{include file="$_path/../pages/Announcement.html"}
{$Announcement_Customer = "{$PAGES_PATH}/Announcement_Customer.html"}
{if file_exists($Announcement_Customer)}
{include file=$Announcement_Customer}
{/if}
</div>
</div>
</div>
@ -111,7 +114,7 @@
<div class="box-header">
<h3 class="box-title">{$_bill['routers']}</h3>
<div class="btn-group pull-right">
{if $_bill['type'] != 'Hotspot'}
{if $_bill['type'] == 'Hotspot'}
{if $_c['hotspot_plan']==''}Hotspot Plan{else}{$_c['hotspot_plan']}{/if}
{else}
{if $_c['pppoe_plan']==''}PPPOE Plan{else}{$_c['pppoe_plan']}{/if}
@ -128,11 +131,8 @@
<td class="small text-primary text-uppercase text-normal">{Lang::T('Plan Name')}</td>
<td class="small mb15">
{$_bill['namebp']}
{if $_bill['status'] == 'on'}
<a class="label label-danger pull-right" href="{$_url}home&deactivate={$_bill['id']}"
onclick="return confirm('{Lang::T('Deactivate')}?')">{Lang::T('Deactivate')}</a>
{else}
<a class="label label-warning pull-right" href="{$_url}order/package">{Lang::T('expired')}</a>
{if $_bill['status'] != 'on'}
<a class="label label-danger pull-right" href="{$_url}order/package">{Lang::T('expired')}</a>
{/if}
</td>
</tr>
@ -146,17 +146,21 @@
<td class="small text-danger text-uppercase text-normal">{Lang::T('Expires On')}</td>
<td class="small mb15 text-danger">
{if $_bill['time'] ne ''}{Lang::dateAndTimeFormat($_bill['expiration'],$_bill['time'])}{/if}&nbsp;
<a class="label label-primary pull-right" href="{$_url}home&recharge={$_bill['id']}"
onclick="return confirm('{Lang::T('Recharge')}?')">{Lang::T('Recharge')}</a>
</td>
</tr>
{if $nux_ip}
<tr>
<td class="small text-success text-uppercase text-normal">{Lang::T('Type')}</td>
<td class="small mb15 text-success">
<b>{if $_bill['prepaid'] eq yes}Prepaid{else}Postpaid{/if}</b>
</td>
</tr>
{if $nux_ip neq ''}
<tr>
<td class="small text-primary text-uppercase text-normal">{Lang::T('Current IP')}</td>
<td class="small mb15">{$nux_ip}</td>
</tr>
{/if}
{if $nux_mac}
{if $nux_mac neq ''}
<tr>
<td class="small text-primary text-uppercase text-normal">{Lang::T('Current MAC')}</td>
<td class="small mb15">{$nux_mac}</td>
@ -170,6 +174,18 @@
</td>
</tr>
{/if}
<tr>
<td class="small text-primary text-uppercase text-normal">
{if $_bill['status'] == 'on'}
<a href="{$_url}home&deactivate={$_bill['id']}" onclick="return confirm('{Lang::T('Deactivate')}?')"
class="btn btn-danger btn-xs"><i class="glyphicon glyphicon-trash"></i></a>
{/if}
</td>
<td class="small row">
<a class="btn btn-primary pull-right btn-sm" href="{$_url}home&recharge={$_bill['id']}"
onclick="return confirm('{Lang::T('Recharge')}?')">{Lang::T('Recharge')}</a>
</td>
</tr>
</table>
{/foreach}
</div>

View File

@ -32,7 +32,10 @@
<div class="panel panel-info">
<div class="panel-heading">{Lang::T('Announcement')}</div>
<div class="panel-body">
{include file="$_path/../pages/Announcement.html"}
{$Announcement = "{$PAGES_PATH}/Announcement.html"}
{if file_exists($Announcement)}
{include file=$Announcement}
{/if}
</div>
</div>
</div>

View File

@ -21,7 +21,7 @@
</table>
</div>
<div class="box-body">
<a href="{$_url}order/buy/0/{$plan['id']}"
<a href="{$_url}order/gateway/0/{$plan['id']}"
onclick="return confirm('{Lang::T('Buy Balance')}?')"
class="btn btn-sm btn-block btn-primary">Buy</a>
</div>

View File

@ -37,7 +37,7 @@
</div>
<div class="box-body">
<div class="btn-group btn-group-justified" role="group" aria-label="...">
<a href="{$_url}order/buy/radius/{$plan['id']}"
<a href="{$_url}order/gateway/radius/{$plan['id']}"
onclick="return confirm('{Lang::T('Buy this? your active package will be overwrite')}')"
class="btn btn-sm btn-block btn-warning text-black">Buy</a>
{if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']}
@ -88,7 +88,7 @@
</div>
<div class="box-body">
<div class="btn-group btn-group-justified" role="group" aria-label="...">
<a href="{$_url}order/buy/radius/{$plan['id']}"
<a href="{$_url}order/gateway/radius/{$plan['id']}"
onclick="return confirm('{Lang::T('Buy this? your active package will be overwrite')}')"
class="btn btn-sm btn-block btn-warning text-black">Buy</a>
{if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']}
@ -113,8 +113,8 @@
<li>{if $_c['radius_plan']==''}Radius Plan{else}{$_c['radius_plan']}{/if}</li>
<li>{if $_c['pppoe_plan']==''}PPPOE Plan{else}{$_c['pppoe_plan']}{/if}</li>
</ol>
<div class="row">
{if Lang::arrayCount($radius_pppoe)>0}
{if Lang::arrayCount($radius_pppoe)>0}
<div class="row">
{foreach $radius_pppoe as $plan}
<div class="col col-md-4">
<div class="box box-primary">
@ -139,7 +139,7 @@
</div>
<div class="box-body">
<div class="btn-group btn-group-justified" role="group" aria-label="...">
<a href="{$_url}order/buy/pppoe/{$plan['id']}"
<a href="{$_url}order/gateway/pppoe/{$plan['id']}"
onclick="return confirm('{Lang::T('Buy this? your active package will be overwritten')}')"
class="btn btn-sm btn-block btn-warning text-black">Buy</a>
{if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']}
@ -157,13 +157,14 @@
</div>
</div>
{/foreach}
{/if}
{if Lang::arrayCount($radius_hotspot)>0}
<ol class="breadcrumb">
<li>{if $_c['radius_plan']==''}Radius Plan{else}{$_c['radius_plan']}{/if}</li>
<li>{if $_c['hotspot_plan']==''}Hotspot Plan{else}{$_c['hotspot_plan']}{/if}</li>
</ol>
</div>
{/if}
{if Lang::arrayCount($radius_hotspot)>0}
<ol class="breadcrumb">
<li>{if $_c['radius_plan']==''}Radius Plan{else}{$_c['radius_plan']}{/if}</li>
<li>{if $_c['hotspot_plan']==''}Hotspot Plan{else}{$_c['hotspot_plan']}{/if}</li>
</ol>
<div class="row">
{foreach $radius_hotspot as $plan}
<div class="col col-md-4">
<div class="box box-primary">
@ -188,7 +189,7 @@
</div>
<div class="box-body">
<div class="btn-group btn-group-justified" role="group" aria-label="...">
<a href="{$_url}order/buy/hotspot/{$plan['id']}"
<a href="{$_url}order/gateway/hotspot/{$plan['id']}"
onclick="return confirm('{Lang::T('Buy this? your active package will be overwritten')}')"
class="btn btn-sm btn-block btn-warning text-black">Buy</a>
{if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']}
@ -206,8 +207,8 @@
</div>
</div>
{/foreach}
{/if}
</div>
</div>
{/if}
{/if}
{/if}
{foreach $routers as $router}
@ -248,7 +249,7 @@
</div>
<div class="box-body">
<div class="btn-group btn-group-justified" role="group" aria-label="...">
<a href="{$_url}order/buy/{$router['id']}/{$plan['id']}"
<a href="{$_url}order/gateway/{$router['id']}/{$plan['id']}"
onclick="return confirm('{Lang::T('Buy this? your active package will be overwrite')}')"
class="btn btn-sm btn-block btn-warning text-black">Buy</a>
{if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']}
@ -297,7 +298,7 @@
</div>
<div class="box-body">
<div class="btn-group btn-group-justified" role="group" aria-label="...">
<a href="{$_url}order/buy/{$router['id']}/{$plan['id']}"
<a href="{$_url}order/gateway/{$router['id']}/{$plan['id']}"
onclick="return confirm('{Lang::T('Buy this? your active package will be overwrite')}')"
class="btn btn-sm btn-block btn-warning text-black">Buy</a>
{if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']}
@ -347,7 +348,7 @@
</div>
<div class="box-body">
<div class="btn-group btn-group-justified" role="group" aria-label="...">
<a href="{$_url}order/buy/{$router['id']}/{$plan['id']}"
<a href="{$_url}order/gateway/{$router['id']}/{$plan['id']}"
onclick="return confirm('{Lang::T('Buy this? your active package will be overwrite')}')"
class="btn btn-sm btn-block btn-warning text-black">Buy</a>
{if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']}
@ -394,7 +395,7 @@
</div>
<div class="box-body">
<div class="btn-group btn-group-justified" role="group" aria-label="...">
<a href="{$_url}order/buy/{$router['id']}/{$plan['id']}"
<a href="{$_url}order/gateway/{$router['id']}/{$plan['id']}"
onclick="return confirm('{Lang::T('Buy this? your active package will be overwrite')}')"
class="btn btn-sm btn-block btn-warning text-black">Buy</a>
{if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']}

View File

@ -6,7 +6,7 @@
<div
class="panel mb20 {if $trx['status']==1}panel-warning{elseif $trx['status']==2}panel-success{elseif $trx['status']==3}panel-danger{elseif $trx['status']==4}panel-danger{else}panel-primary{/if} panel-hovered">
<div class="panel-footer">Transaction #{$trx['id']}</div>
{if $trx['routers']!='balance'}
{if !in_array($trx['routers'],['balance','radius'])}
<div class="panel-body">
<div class="panel panel-primary panel-hovered">
<div class="panel-heading">{$router['name']}</div>
@ -30,8 +30,8 @@
{date('H:i', strtotime($trx['paid_date']))} </td>
</tr>
<tr>
{if $trx['plan_name'] == 'Receive Balance'}
<td>{Lang::T('From')}</td>
{if $trx['plan_name'] == 'Receive Balance'}
<td>{Lang::T('From')}</td>
{else}
<td>{Lang::T('To')}</td>
{/if}
@ -67,9 +67,21 @@
<td>{Lang::T('Plan Name')}</td>
<td>{$plan['name_plan']}</td>
</tr>
{if $add_cost>0}
{foreach $bills as $k => $v}
<tr>
<td>{$k}</td>
<td>{Lang::moneyFormat($v)}</td>
</tr>
{/foreach}
<tr>
<td>{Lang::T('Additional Cost')}</td>
<td>{Lang::moneyFormat($add_cost)}</td>
</tr>
{/if}
<tr>
<td>{Lang::T('Plan Price')}</td>
<td>{Lang::moneyFormat($plan['price'])}</td>
<td>{Lang::T('Plan Price')}{if $add_cost>0}<small> + {Lang::T('Additional Cost')}{/if}</small></td>
<td style="font-size: large; font-weight:bolder; font-family: 'Courier New', Courier, monospace; ">{Lang::moneyFormat($trx['price'])}</td>
</tr>
<tr>
<td>{Lang::T('Type')}</td>

View File

@ -0,0 +1,29 @@
{include file="sections/user-header.tpl"}
<div class="row">
<div class="col-sm-12">
<div class="panel panel-info panel-hovered">
<div class="panel-heading">{Lang::T('Available Payment Gateway')}</div>
<div class="panel-footer">
<form method="post" action="{$_url}order/buy/{$route2}/{$route3}">
<div class="form-group row">
<label class="col-md-2 control-label">Payment Gateway</label>
<div class="col-md-8">
<select name="gateway" id="gateway" class="form-control">
{foreach $pgs as $pg}
<option value="{$pg}">
{ucwords($pg)}</option>
{/foreach}
</select>
</div>
<div class="col-md-2">
<button type="submit" class="btn btn-block btn-primary">{Lang::T('Pay Now')}</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{include file="sections/user-footer.tpl"}

View File

@ -12,9 +12,21 @@
<td>{Lang::T('Type')}</td>
<td>{$plan['type']}</td>
</tr>
{if $add_cost>0}
{foreach $bills as $k => $v}
<tr>
<td>{$k}</td>
<td>{Lang::moneyFormat($v)}</td>
</tr>
{/foreach}
<tr>
<td>{Lang::T('Additional Cost')}</td>
<td>{Lang::moneyFormat($add_cost)}</td>
</tr>
{/if}
<tr>
<td>{Lang::T('Price')}</td>
<td>{Lang::moneyFormat($plan['price'])}</td>
<td>{Lang::T('Price')}{if $add_cost>0}<small> + {Lang::T('Additional Cost')}{/if}</td>
<td style="font-size: large; font-weight:bolder; font-family: 'Courier New', Courier, monospace; ">{Lang::moneyFormat($plan['price'])}</td>
</tr>
<tr>
<td>{Lang::T('Validity')}</td>
@ -35,6 +47,7 @@
value="plan"><i class="glyphicon glyphicon-send"></i></button>
</div>
</div>
<p class="help-block text-center">{Lang::T('If your friend have Additional Cost, you will pay for that too')}</p>
</form>
</div>
</div>

View File

@ -65,7 +65,7 @@
<div class="form-group">
<label class="col-md-3 control-label">{Lang::T('User Type')}</label>
<div class="col-md-9">
<select name="user_type" id="user_type" class="form-control">
<select name="user_type" id="user_type" class="form-control" onchange="checkUserType(this)">
{if $_admin['user_type'] eq 'Agent'}
<option value="Sales" {if $d['user_type'] eq 'Sales'}selected="selected" {/if}>Sales
</option>
@ -87,7 +87,7 @@
</select>
</div>
</div>
<div class="form-group {if $d['user_type'] eq 'Sales'}hidden{/if}" id="agentChooser">
<div class="form-group {if $d['user_type'] neq 'Sales'}hidden{/if}" id="agentChooser">
<label class="col-md-3 control-label">{Lang::T('Agent')}</label>
<div class="col-md-9">
<select name="root" id="root" class="form-control">

View File

@ -7,7 +7,7 @@
<div class="panel-heading">{Lang::T('Add Vouchers')}</div>
<div class="panel-body">
<form class="form-horizontal" method="post" role="form" action="{$_url}prepaid/voucher-post">
<form class="form-horizontal" method="post" role="form" action="{$_url}plan/voucher-post">
<div class="form-group">
<label class="col-md-2 control-label">{Lang::T('Type')}</label>
<div class="col-md-6">

View File

@ -4,11 +4,11 @@
<div class="col-md-6 col-sm-12 col-md-offset-3">
<div class="panel panel-hovered panel-primary panel-stacked mb30">
<div class="panel-body">
<form class="form-horizontal" method="post" action="{$_url}prepaid/print" target="_blank">
<form class="form-horizontal" method="post" action="{$_url}plan/print" target="_blank">
<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-default btn-sm"><i
<a href="{$_url}plan/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={$whatsapp}" target="_blank"
class="btn btn-primary btn-sm">

View File

@ -6,17 +6,17 @@
<div class="panel-heading">
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
<div class="btn-group pull-right">
<a class="btn btn-danger btn-xs" title="Remove used Voucher" href="{$_url}prepaid/remove-voucher"
<a class="btn btn-danger btn-xs" title="Remove used Voucher" href="{$_url}plan/remove-voucher"
onclick="return confirm('Delete all used voucher code?')"><span
class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete All</a>
</div>
{/if}
{Lang::T('Prepaid Vouchers')}
&nbsp;
</div>
<div class="panel-body">
<div class="md-whiteframe-z1 mb20 text-center" style="padding: 15px">
<div class="col-md-8">
<form id="site-search" method="post" action="{$_url}prepaid/voucher/">
<form id="site-search" method="post" action="{$_url}plan/voucher/">
<div class="input-group">
<div class="input-group-addon">
<span class="fa fa-search"></span>
@ -32,11 +32,11 @@
<div class="col-md-4">
<div class="btn-group btn-group-justified" role="group">
<div class="btn-group" role="group">
<a href="{$_url}prepaid/add-voucher" class="btn btn-primary btn-block"><i
<a href="{$_url}plan/add-voucher" class="btn btn-primary btn-block"><i
class="ion ion-android-add"> </i> {Lang::T('Add Vouchers')}</a>
</div>
<div class="btn-group" role="group">
<a href="{$_url}prepaid/print-voucher" target="print_voucher" class="btn btn-info"><i
<a href="{$_url}plan/print-voucher" target="print_voucher" class="btn btn-info"><i
class="ion ion-android-print"> </i> Print</a>
</div>
</div>
@ -82,12 +82,12 @@
</td>
<td>
{if $ds['status'] neq '1'}
<a href="{$_url}prepaid/voucher-view/{$ds['id']}" id="{$ds['id']}"
<a href="{$_url}plan/voucher-view/{$ds['id']}" id="{$ds['id']}"
style="margin: 0px;"
class="btn btn-success btn-xs">&nbsp;&nbsp;{Lang::T('View')}&nbsp;&nbsp;</a>
{/if}
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
<a href="{$_url}prepaid/voucher-delete/{$ds['id']}" id="{$ds['id']}"
<a href="{$_url}plan/voucher-delete/{$ds['id']}" id="{$ds['id']}"
class="btn btn-danger btn-xs"
onclick="return confirm('{Lang::T('Delete')}?')"><i
class="glyphicon glyphicon-trash"></i></a>
@ -101,10 +101,10 @@
<ul class="pagination pagination-sm">
{if $page>0}
<li><a href="{$_url}prepaid/voucher&p={$page-1}&code={$_code}">{Lang::T('Prev')}</a></li>
<li><a href="{$_url}plan/voucher&p={$page-1}&code={$_code}">{Lang::T('Prev')}</a></li>
{/if}
{if $d}
<li><a href="{$_url}prepaid/voucher&p={$page+1}&code={$_code}">{Lang::T('Next')}</a></li>
<li><a href="{$_url}plan/voucher&p={$page+1}&code={$_code}">{Lang::T('Next')}</a></li>
{/if}
</ul>
</div>

View File

@ -77,6 +77,9 @@ if (empty($step)) {
// remove downloaded zip
if (file_exists($file)) unlink($file);
} else if ($step == 3) {
deleteFolder('system/autoload/');
deleteFolder('system/vendor/');
deleteFolder('ui/ui/');
copyFolder($folder, pathFixer('./'));
deleteFolder('install/');
deleteFolder($folder);

View File

@ -1,3 +1,3 @@
{
"version": "2024.2.27"
"version": "2024.3.22.1"
}