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..e6663be7 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,52 @@ 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();
+ }
+ }
+
+ // 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/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 @@
{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} | +