From 941c723193d9ecfbfef228b214e0e56568d66729 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Sat, 17 Feb 2024 19:30:35 +0100 Subject: [PATCH 1/2] New Feature Added "Custom Fields" admin can now add unlimited Custom Fields, and also edit or delete the Custom Fields --- install/phpnuxbill.sql | 9 ++ system/controllers/customers.php | 68 +++++++++- system/updates.json | 3 + ui/ui/customers-add.tpl | 79 ++++++++--- ui/ui/customers-edit.tpl | 51 ++++--- ui/ui/customers-view.tpl | 226 ++++++++++++++++--------------- 6 files changed, 292 insertions(+), 144 deletions(-) diff --git a/install/phpnuxbill.sql b/install/phpnuxbill.sql index 98ae076e..e31312c6 100644 --- a/install/phpnuxbill.sql +++ b/install/phpnuxbill.sql @@ -188,6 +188,15 @@ CREATE TABLE `tb_languages` ( `id` int(11) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +DROP TABLE IF EXISTS `tbl_customers_custom_fields`; +CREATE TABLE tbl_customers_custom_fields ( + id INT PRIMARY KEY AUTO_INCREMENT, + customer_id INT NOT NULL, + field_name VARCHAR(255) NOT NULL, + field_value VARCHAR(255) NOT NULL, + FOREIGN KEY (customer_id) REFERENCES tbl_customers(id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + ALTER TABLE `tbl_voucher` ADD `generated_by` INT NOT NULL DEFAULT '0' COMMENT 'id admin' AFTER `status`; ALTER TABLE `tbl_users` ADD `root` INT NOT NULL DEFAULT '0' COMMENT 'for sub account' AFTER `id`; ALTER TABLE `tbl_users` CHANGE `user_type` `user_type` ENUM('SuperAdmin','Admin','Report','Agent','Sales') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL; diff --git a/system/controllers/customers.php b/system/controllers/customers.php index 9cf7daad..6b5aab7c 100644 --- a/system/controllers/customers.php +++ b/system/controllers/customers.php @@ -166,6 +166,13 @@ switch ($action) { $customer = ORM::for_table('tbl_customers')->find_one($id); } if ($customer) { + + + // Fetch the custom field values from the tbl_customer_custom_fields table + $customFields = ORM::for_table('tbl_customers_custom_fields') + ->where('customer_id', $customer['id']) + ->find_many(); + $v = $routes['3']; if (empty($v) || $v == 'order') { $v = 'order'; @@ -193,6 +200,7 @@ switch ($action) { $ui->assign('package', $package); $ui->assign('v', $v); $ui->assign('d', $customer); + $ui->assign('customFields', $customFields); $ui->display('customers-view.tpl'); } else { r2(U . 'customers/list', 'e', $_L['Account_Not_Found']); @@ -202,8 +210,13 @@ switch ($action) { $id = $routes['2']; run_hook('edit_customer'); #HOOK $d = ORM::for_table('tbl_customers')->find_one($id); + // Fetch the custom field values from the tbl_customers_custom_fields table + $customFields = ORM::for_table('tbl_customers_custom_fields') + ->where('customer_id', $id) + ->find_many(); if ($d) { $ui->assign('d', $d); + $ui->assign('customFields', $customFields); $ui->display('customers-edit.tpl'); } else { r2(U . 'customers/list', 'e', $_L['Account_Not_Found']); @@ -218,6 +231,8 @@ switch ($action) { run_hook('delete_customer'); #HOOK $d = ORM::for_table('tbl_customers')->find_one($id); if ($d) { + // Delete the associated custom field records from tbl_customer_custom_fields table + ORM::for_table('tbl_customers_custom_fields')->where('customer_id', $id)->delete_many(); $c = ORM::for_table('tbl_user_recharges')->where('username', $d['username'])->find_one(); if ($c) { $p = ORM::for_table('tbl_plans')->find_one($c['plan_id']); @@ -270,6 +285,10 @@ switch ($action) { $address = _post('address'); $phonenumber = _post('phonenumber'); $service_type = _post('service_type'); + //post custom field + $custom_field_names = (array) $_POST['custom_field_name']; + $custom_field_values = (array) $_POST['custom_field_value']; + run_hook('add_customer'); #HOOK $msg = ''; if (Validator::Length($username, 35, 2) == false) { @@ -299,6 +318,25 @@ switch ($action) { $d->phonenumber = Lang::phoneFormat($phonenumber); $d->service_type = $service_type; $d->save(); + + // Retrieve the customer ID of the newly created customer + $customerId = $d->id(); + // Save custom field details + 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)) { + $customField = ORM::for_table('tbl_customers_custom_fields')->create(); + $customField->customer_id = $customerId; + $customField->field_name = $name; + $customField->field_value = $value; + $customField->save(); + } + } + } r2(U . 'customers/list', 's', Lang::T('Account Created Successfully')); } else { r2(U . 'customers/add', 'e', $msg); @@ -330,6 +368,12 @@ switch ($action) { $id = _post('id'); $d = ORM::for_table('tbl_customers')->find_one($id); + + //lets find user custom field using id + $customFields = ORM::for_table('tbl_customers_custom_fields') + ->where('customer_id', $id) + ->find_many(); + if (!$d) { $msg .= Lang::T('Data Not Found') . '
'; } @@ -343,7 +387,7 @@ switch ($action) { if ($oldusername != $username) { $c = ORM::for_table('tbl_customers')->where('username', $username)->find_one(); if ($c) { - $msg .= Lang::T('Account already axist') . '
'; + $msg .= Lang::T('Account already exist') . '
'; } $userDiff = true; } @@ -368,6 +412,28 @@ switch ($action) { $d->phonenumber = $phonenumber; $d->service_type = $service_type; $d->save(); + + + // Update custom field values in tbl_customers_custom_fields table + foreach ($customFields as $customField) { + $fieldName = $customField['field_name']; + if (isset($_POST['custom_fields'][$fieldName])) { + $customFieldValue = $_POST['custom_fields'][$fieldName]; + $customField->set('field_value', $customFieldValue); + $customField->save(); + } + + if (isset($_POST['delete_custom_fields'])) { + $fieldsToDelete = $_POST['delete_custom_fields']; + foreach ($fieldsToDelete as $fieldName) { + // Delete the custom field with the given field name + ORM::for_table('tbl_customers_custom_fields') + ->where('field_name', $fieldName) + ->delete_many(); + } + } + } + if ($userDiff || $pppoeDiff || $passDiff) { $c = ORM::for_table('tbl_user_recharges')->where('username', ($userDiff) ? $oldusername : $username)->find_one(); if ($c) { diff --git a/system/updates.json b/system/updates.json index bdf00988..2ae9a9e3 100644 --- a/system/updates.json +++ b/system/updates.json @@ -55,5 +55,8 @@ ], "2024.2.16": [ "ALTER TABLE `tbl_customers` ADD `created_by` INT NOT NULL DEFAULT '0' AFTER `auto_renewal`;" + ], + "2024.2.17": [ + "CREATE TABLE `tbl_customers_custom_fields` (`id` INT PRIMARY KEY AUTO_INCREMENT, `customer_id` INT NOT NULL, `field_name` VARCHAR(255) NOT NULL, `field_value` VARCHAR(255) NOT NULL, FOREIGN KEY (customer_id) REFERENCES tbl_customers(id));" ] } \ No newline at end of file diff --git a/ui/ui/customers-add.tpl b/ui/ui/customers-add.tpl index 9fe84121..03963c70 100644 --- a/ui/ui/customers-add.tpl +++ b/ui/ui/customers-add.tpl @@ -12,10 +12,10 @@
{if $_c['country_code_phone']!= ''} - + + + {else} - + {/if} @@ -39,10 +39,10 @@
{if $_c['country_code_phone']!= ''} - + + + {else} - + {/if} @@ -62,8 +62,8 @@ - {Lang::T('User Cannot change this, only admin. if it Empty it will use user password')} + {Lang::T('User Cannot change this, only admin. if it Empty it will + use user password')}
@@ -72,21 +72,31 @@
-
+
- -
+ +
+ +
+ +
+ +
+
+
- + Or {Lang::T('Cancel')}
@@ -96,6 +106,41 @@
+{literal} + +{/literal} {include file="sections/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/customers-edit.tpl b/ui/ui/customers-edit.tpl index f35b88b6..f50aad01 100644 --- a/ui/ui/customers-edit.tpl +++ b/ui/ui/customers-edit.tpl @@ -13,10 +13,10 @@
{if $_c['country_code_phone']!= ''} - + + + {else} - + {/if}
{if $_c['country_code_phone']!= ''} - + + + {else} - + {/if} @@ -67,8 +67,8 @@ - {Lang::T('User Cannot change this, only admin. if it Empty it will use user password')} + {Lang::T('User Cannot change this, only admin. if it Empty it will + use user password')}
@@ -77,21 +77,36 @@
-
+
- -
+ +
- + + {if $customFields} + {foreach $customFields as $customField} +
+ +
+ +
+ Delete +
+ {/foreach} + {/if} +
- + Or {Lang::T('Cancel')}
diff --git a/ui/ui/customers-view.tpl b/ui/ui/customers-view.tpl index 5455f15b..408ceb33 100644 --- a/ui/ui/customers-view.tpl +++ b/ui/ui/customers-view.tpl @@ -30,22 +30,31 @@ onclick="this.select()"> {if $d['pppoe_password'] != ''} -
  • - PPPOE {Lang::T('Password')} + PPPOE {Lang::T('Password')} -
  • + {/if} -
  • + + {if $customFields} + {foreach $customFields as $customField} +
  • + {$customField.field_name} {$customField.field_value} +
  • + {/foreach} + {/if} + +
  • {Lang::T('Service Type')} {Lang::T($d['service_type'])}
  • {Lang::T('Balance')} {Lang::moneyFormat($d['balance'])}
  • - {Lang::T('Auto Renewal')} {if $d['auto_renewal']}yes{else}no{/if} + {Lang::T('Auto Renewal')} {if + $d['auto_renewal']}yes{else}no{/if}
  • {Lang::T('Created On')}
    + class="btn btn-danger btn-block btn-sm" + onclick="return confirm('{Lang::T('Delete')}?')">
    {if $package} -
    -
    -

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

    -
      -
    • - {Lang::T('Active')} {if $package['status']=='on'}yes{else}no{/if} -
    • -
    • - {Lang::T('Created On')} {Lang::dateAndTimeFormat($package['recharged_on'],$package['recharged_time'])} -
    • -
    • - {Lang::T('Expires On')} {Lang::dateAndTimeFormat($package['expiration'], $package['time'])} -
    • -
    • - {$package['routers']} {$package['method']} -
    • -
    -
    - - - +
    +
    +

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

    +
      +
    • + {Lang::T('Active')} {if + $package['status']=='on'}yes{else}no{/if} +
    • +
    • + {Lang::T('Created On')} {Lang::dateAndTimeFormat($package['recharged_on'],$package['recharged_time'])} +
    • +
    • + {Lang::T('Expires On')} {Lang::dateAndTimeFormat($package['expiration'], + $package['time'])} +
    • +
    • + {$package['routers']} {$package['method']} +
    • +
    +
    +
    {else} - {Lang::T('Recharge')}
    + {Lang::T('Recharge')}
    {/if} {Lang::T('Back')}
    {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}
    From aa8fa3f4366a406874289d16512b4b4bb329dc86 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Sun, 18 Feb 2024 04:56:30 +0100 Subject: [PATCH 2/2] update admin can add more fields when editing customers --- system/controllers/customers.php | 38 +++++++++++++++++++++----- ui/ui/customers-edit.tpl | 47 +++++++++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 8 deletions(-) diff --git a/system/controllers/customers.php b/system/controllers/customers.php index 6b5aab7c..e6663be7 100644 --- a/system/controllers/customers.php +++ b/system/controllers/customers.php @@ -422,18 +422,42 @@ switch ($action) { $customField->set('field_value', $customFieldValue); $customField->save(); } + } - if (isset($_POST['delete_custom_fields'])) { - $fieldsToDelete = $_POST['delete_custom_fields']; - foreach ($fieldsToDelete as $fieldName) { - // Delete the custom field with the given field name - ORM::for_table('tbl_customers_custom_fields') - ->where('field_name', $fieldName) - ->delete_many(); + // Add new custom fields + if (isset($_POST['custom_field_name']) && isset($_POST['custom_field_value'])) { + $newCustomFieldNames = $_POST['custom_field_name']; + $newCustomFieldValues = $_POST['custom_field_value']; + + // Check if the number of field names and values match + if (count($newCustomFieldNames) == count($newCustomFieldValues)) { + $numNewFields = count($newCustomFieldNames); + + for ($i = 0; $i < $numNewFields; $i++) { + $fieldName = $newCustomFieldNames[$i]; + $fieldValue = $newCustomFieldValues[$i]; + + // Insert the new custom field + $newCustomField = ORM::for_table('tbl_customers_custom_fields')->create(); + $newCustomField->set('customer_id', $id); + $newCustomField->set('field_name', $fieldName); + $newCustomField->set('field_value', $fieldValue); + $newCustomField->save(); } } } + // Delete custom fields + if (isset($_POST['delete_custom_fields'])) { + $fieldsToDelete = $_POST['delete_custom_fields']; + foreach ($fieldsToDelete as $fieldName) { + // Delete the custom field with the given field name + ORM::for_table('tbl_customers_custom_fields') + ->where('field_name', $fieldName) + ->delete_many(); + } + } + if ($userDiff || $pppoeDiff || $passDiff) { $c = ORM::for_table('tbl_user_recharges')->where('username', ($userDiff) ? $oldusername : $username)->find_one(); if ($c) { diff --git a/ui/ui/customers-edit.tpl b/ui/ui/customers-edit.tpl index f50aad01..91231e96 100644 --- a/ui/ui/customers-edit.tpl +++ b/ui/ui/customers-edit.tpl @@ -102,7 +102,16 @@
    {/foreach} {/if} - + + +
    + +
    + +
    +
    +
    +{literal} + +{/literal} + {include file="sections/footer.tpl"} \ No newline at end of file