diff --git a/install/phpnuxbill.sql b/install/phpnuxbill.sql index 097896d9..6b811b39 100644 --- a/install/phpnuxbill.sql +++ b/install/phpnuxbill.sql @@ -26,6 +26,7 @@ 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 '6.465422, 3.406448' 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', `auto_renewal` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Auto renewall using balance', diff --git a/system/controllers/customers.php b/system/controllers/customers.php index 2300af01..151ace8a 100644 --- a/system/controllers/customers.php +++ b/system/controllers/customers.php @@ -130,7 +130,7 @@ switch ($action) { $ui->assign('using', 'cash'); $ui->assign('plan', $plan); $ui->display('recharge-confirm.tpl'); - }else{ + } else { r2(U . 'customers/view/' . $id_customer, 'e', 'Cannot find active plan'); } break; @@ -191,7 +191,7 @@ switch ($action) { } } } - r2(U . 'customers/view/' . $id_customer, 's', 'Sync success to '.implode(", ",$routers)); + r2(U . 'customers/view/' . $id_customer, 's', 'Sync success to ' . implode(", ", $routers)); } r2(U . 'customers/view/' . $id_customer, 'e', 'Cannot find active plan'); break; @@ -212,7 +212,7 @@ switch ($action) { ->find_many(); $v = $routes['3']; - if(empty($v)){ + if (empty($v)) { $v = 'activation'; } if ($v == 'order') { @@ -328,6 +328,7 @@ switch ($action) { $address = _post('address'); $phonenumber = _post('phonenumber'); $service_type = _post('service_type'); + $coordinates = _post('coordinates'); //post Customers Attributes $custom_field_names = (array) $_POST['custom_field_name']; $custom_field_values = (array) $_POST['custom_field_value']; @@ -360,6 +361,7 @@ switch ($action) { $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 @@ -395,6 +397,7 @@ switch ($action) { $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) { @@ -454,6 +457,7 @@ switch ($action) { $d->address = $address; $d->phonenumber = $phonenumber; $d->service_type = $service_type; + $d->coordinates = $coordinates; $d->save(); diff --git a/system/controllers/map.php b/system/controllers/map.php new file mode 100644 index 00000000..053019f4 --- /dev/null +++ b/system/controllers/map.php @@ -0,0 +1,45 @@ +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) { + $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', ''); + $ui->assign('_title', Lang::T('Customer Geo Location Information')); + $ui->assign('xfooter', ''); + $ui->display('map-customer.tpl'); + break; + + default: + r2(U . 'map/customer', 'e', 'action not defined'); + break; +} diff --git a/system/controllers/message.php b/system/controllers/message.php index 46cf0902..e12eadff 100644 --- a/system/controllers/message.php +++ b/system/controllers/message.php @@ -40,8 +40,11 @@ document.addEventListener("DOMContentLoaded", function(event) { }); EOT; - $c = ORM::for_table('tbl_customers')->find_many(); - $ui->assign('c', $c); + 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; diff --git a/system/updates.json b/system/updates.json index 29f3282a..9a25dbb5 100644 --- a/system/updates.json +++ b/system/updates.json @@ -78,5 +78,10 @@ ], "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 '6.465422, 3.406448' COMMENT 'Latitude and Longitude coordinates' AFTER `email`;" ] + + } \ No newline at end of file diff --git a/ui/ui/customers-add.tpl b/ui/ui/customers-add.tpl index acef5cfe..0ff75696 100644 --- a/ui/ui/customers-add.tpl +++ b/ui/ui/customers-add.tpl @@ -11,10 +11,10 @@
{if $_c['country_code_phone']!= ''} - + + + {else} - + {/if} @@ -38,10 +38,10 @@
{if $_c['country_code_phone']!= ''} - + + + {else} - + {/if} @@ -51,8 +51,9 @@
- +
@@ -72,6 +73,17 @@
+
+ +
+ + + {Lang::T('Latitude and Longitude coordinates for map must be separate with comma + ","')} + +
+
@@ -110,16 +122,16 @@ {literal} - + + customFieldsContainer.addEventListener('click', function (event) { + if (event.target.classList.contains('remove-custom-field')) { + var fieldContainer = event.target.parentNode.parentNode; + fieldContainer.parentNode.removeChild(fieldContainer); + } + }); + }); + {/literal} diff --git a/ui/ui/customers-edit.tpl b/ui/ui/customers-edit.tpl index 219fdf42..b6eb03a6 100644 --- a/ui/ui/customers-edit.tpl +++ b/ui/ui/customers-edit.tpl @@ -12,10 +12,10 @@
{if $_c['country_code_phone']!= ''} - + + + {else} - + {/if}
{if $_c['country_code_phone']!= ''} - + + + {else} - + {/if} @@ -77,6 +77,16 @@
+
+ +
+ + + {Lang::T('Latitude and Longitude coordinates for map must be separate with comma + ","')} + +
+
@@ -97,19 +107,20 @@
{if $customFields} - {foreach $customFields as $customField} -
- -
- -
- -
- {/foreach} + {foreach $customFields as $customField} +
+ +
+ +
+ +
+ {/foreach} {/if} @@ -133,16 +144,16 @@ {literal} - + + customFieldsContainer.addEventListener('click', function (event) { + if (event.target.classList.contains('remove-custom-field')) { + var fieldContainer = event.target.parentNode.parentNode; + fieldContainer.parentNode.removeChild(fieldContainer); + } + }); + }); + {/literal} {include file="sections/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/customers-view.tpl b/ui/ui/customers-view.tpl index d39792ca..67d1af85 100644 --- a/ui/ui/customers-view.tpl +++ b/ui/ui/customers-view.tpl @@ -30,26 +30,29 @@ onclick="this.select()"> {if $d['pppoe_password'] != ''} -
  • - PPPOE {Lang::T('Password')} -
  • +
  • + PPPOE {Lang::T('Password')} +
  • {/if} +
  • + {Lang::T('Coordinates')} {Lang::T($d['coordinates'])} +
  • {if $customFields} - {foreach $customFields as $customField} -
  • - {$customField.field_name} - {if strpos($customField.field_value, ':0') === false} - {$customField.field_value} - {else} - {Lang::T('Paid')} - {/if} - -
  • - {/foreach} + {foreach $customFields as $customField} +
  • + {$customField.field_name} + {if strpos($customField.field_value, ':0') === false} + {$customField.field_value} + {else} + {Lang::T('Paid')} + {/if} + +
  • + {/foreach} {/if}
  • @@ -86,12 +89,12 @@
  • {foreach $packages as $package} -
    -
    -

    {$package['type']} - {$package['namebp']}

    -
      -
    • - {Lang::T('Active')} {if +
      +
      +

      {$package['type']} - {$package['namebp']}

      +
        +
      • + {Lang::T('Active')} {if $package['status']=='on'}yes{else}no {/if}
      • @@ -104,7 +107,8 @@ class="pull-right">{Lang::dateAndTimeFormat($package['recharged_on'],$package['recharged_time'])}
      • - {Lang::T('Expires On')} {Lang::dateAndTimeFormat($package['expiration'], + {Lang::T('Expires On')} {Lang::dateAndTimeFormat($package['expiration'], $package['time'])}
      • @@ -129,11 +133,15 @@ -
      @@ -146,68 +154,68 @@
      {if Lang::arrayCount($activation)} - - - - - - - - - - - - - - {foreach $activation as $ds} - - - - - - - - - - - {/foreach} - + + + + + + + + + + + + + + {foreach $activation as $ds} + + + + + + + + + + + {/foreach} + {/if} {if Lang::arrayCount($order)} - - - - - - - - - - - - - - - {foreach $order as $ds} - - - - - - - - - - - - {/foreach} - + + + + + + + + + + + + + + + {foreach $order as $ds} + + + + + + + + + + + + {/foreach} + {/if}
      {Lang::T('Invoice')}{Lang::T('Username')}{Lang::T('Plan Name')}{Lang::T('Plan Price')}{Lang::T('Type')}{Lang::T('Created On')}{Lang::T('Expires On')}{Lang::T('Method')}
      {$ds['invoice']}{$ds['username']}{$ds['plan_name']}{Lang::moneyFormat($ds['price'])}{$ds['type']}{Lang::dateAndTimeFormat($ds['recharged_on'],$ds['recharged_time'])} - {Lang::dateAndTimeFormat($ds['expiration'],$ds['time'])}{$ds['method']}
      {Lang::T('Invoice')}{Lang::T('Username')}{Lang::T('Plan Name')}{Lang::T('Plan Price')}{Lang::T('Type')}{Lang::T('Created On')}{Lang::T('Expires On')}{Lang::T('Method')}
      {$ds['invoice']}{$ds['username']}{$ds['plan_name']}{Lang::moneyFormat($ds['price'])}{$ds['type']}{Lang::dateAndTimeFormat($ds['recharged_on'],$ds['recharged_time'])} + {Lang::dateAndTimeFormat($ds['expiration'],$ds['time'])}{$ds['method']}
      {Lang::T('Plan Name')}{Lang::T('Gateway')}{Lang::T('Routers')}{Lang::T('Type')}{Lang::T('Plan Price')}{Lang::T('Created On')}{Lang::T('Expires On')}{Lang::T('Date Done')}{Lang::T('Method')}
      {$ds['plan_name']}{$ds['gateway']}{$ds['routers']}{$ds['payment_channel']}{Lang::moneyFormat($ds['price'])}{Lang::dateTimeFormat($ds['created_date'])}{Lang::dateTimeFormat($ds['expired_date'])}{if $ds['status']!=1}{Lang::dateTimeFormat($ds['paid_date'])}{/if}{if $ds['status']==1}{Lang::T('UNPAID')} - {elseif $ds['status']==2}{Lang::T('PAID')} - {elseif $ds['status']==3}{$_L['FAILED']} - {elseif $ds['status']==4}{Lang::T('CANCELED')} - {elseif $ds['status']==5}{Lang::T('UNKNOWN')} - {/if}
      {Lang::T('Plan Name')}{Lang::T('Gateway')}{Lang::T('Routers')}{Lang::T('Type')}{Lang::T('Plan Price')}{Lang::T('Created On')}{Lang::T('Expires On')}{Lang::T('Date Done')}{Lang::T('Method')}
      {$ds['plan_name']}{$ds['gateway']}{$ds['routers']}{$ds['payment_channel']}{Lang::moneyFormat($ds['price'])}{Lang::dateTimeFormat($ds['created_date'])}{Lang::dateTimeFormat($ds['expired_date'])}{if $ds['status']!=1}{Lang::dateTimeFormat($ds['paid_date'])}{/if}{if $ds['status']==1}{Lang::T('UNPAID')} + {elseif $ds['status']==2}{Lang::T('PAID')} + {elseif $ds['status']==3}{$_L['FAILED']} + {elseif $ds['status']==4}{Lang::T('CANCELED')} + {elseif $ds['status']==5}{Lang::T('UNKNOWN')} + {/if}
      diff --git a/ui/ui/map-customer.tpl b/ui/ui/map-customer.tpl new file mode 100644 index 00000000..9192c869 --- /dev/null +++ b/ui/ui/map-customer.tpl @@ -0,0 +1,46 @@ +{include file="sections/header.tpl"} + + +
      + +{literal} + +{/literal} + +{include file="sections/footer.tpl"} diff --git a/ui/ui/message-bulk.tpl b/ui/ui/message-bulk.tpl index fc03fc1c..946ed18a 100644 --- a/ui/ui/message-bulk.tpl +++ b/ui/ui/message-bulk.tpl @@ -35,13 +35,13 @@

      {Lang::T('Use placeholders:')}
      - {Lang::T('[[name]]')} - {Lang::T('Customer Name')} + [[name]] - {Lang::T('Customer Name')}
      - {Lang::T('[[user_name]]')} - {Lang::T('Customer Username')} + [[user_name]] - {Lang::T('Customer Username')}
      - {Lang::T('[[phone]]')} - {Lang::T('Customer Phone')} + [[phone]] - {Lang::T('Customer Phone')}
      - {Lang::T('[[company_name]]')} - {Lang::T('Your Company Name')} + [[company_name]] - {Lang::T('Your Company Name')}

      diff --git a/ui/ui/message.tpl b/ui/ui/message.tpl index 04ce1ec3..eef83681 100644 --- a/ui/ui/message.tpl +++ b/ui/ui/message.tpl @@ -1,65 +1,64 @@ {include file="sections/header.tpl"} -
      -
      -
      -
      {Lang::T('Send Personal Message')}
      -
      -
      -
      - -
      - -
      -
      -
      - -
      - -
      -
      -
      - -
      - -
      -

      - {Lang::T('Use placeholders:')} -
      - {Lang::T('[[name]]')} - {Lang::T('Customer Name')} -
      - {Lang::T('[[user_name]]')} - {Lang::T('Customer Username')} -
      - {Lang::T('[[phone]]')} - {Lang::T('Customer Phone')} -
      - {Lang::T('[[company_name]]')} - {Lang::T('Your Company Name')} -

      -
      - -
      -
      - - {Lang::T('Cancel')} -
      -
      -
      +
      +
      +
      +
      {Lang::T('Send Personal Message')}
      +
      +
      +
      + +
      + +
      -
      +
      + +
      + +
      +
      +
      + +
      + +
      +

      + {Lang::T('Use placeholders:')} +
      + [[name]] - {Lang::T('Customer Name')} +
      + [[user_name]] - {Lang::T('Customer Username')} +
      + [[phone]] - {Lang::T('Customer Phone')} +
      + [[company_name]] - {Lang::T('Your Company Name')} +

      +
      + +
      +
      + + {Lang::T('Cancel')} +
      +
      +
      +
      +
      -{include file="sections/footer.tpl"} +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 069848ed..6eee53e2 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -234,6 +234,20 @@
    {$_MENU_AFTER_REPORTS} +
  • + + {Lang::T('Map')} + + + + + +
  • + {$_MENU_AFTER_MAP}
  • {Lang::T('Send Message')}