From a8660f5097424cfc979a6cd2e4347c3f8f50285c Mon Sep 17 00:00:00 2001 From: "venkatesh.r" Date: Thu, 9 Oct 2025 12:49:56 +0530 Subject: [PATCH 01/17] CHANGE_EB_CHANGES : RV --- app/Config/Routes.php | 6 + app/Controllers/JobWorker.php | 4 + app/Controllers/LeadsController.php | 898 +++++++++++++++++++++++++- app/Controllers/TestingController.php | 187 ++++++ app/Helpers/excel_util_helper.php | 331 +++++++++- app/Models/LeadFilesModel.php | 5 +- app/Models/LeadsModel.php | 2 + app/Views/excel_errors.php | 13 +- app/Views/leads_list.php | 13 +- app/Views/view_rfq.php | 686 ++++++++++++++++++-- 10 files changed, 2067 insertions(+), 78 deletions(-) diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 9996931c..cf545319 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -388,6 +388,10 @@ $routes->group("/util", ["filter" => "authMVC"], function ($routes) { $routes->get("download_claim_dump_file/(:any)", "TicketController::downloadClaimDumpFile/$1"); $routes->post('uploadMultiFileFromRfq', 'LeadsController::uploadMultiFileFromRfq'); $routes->get('downloadMemberFile/(:any)', 'LeadsController::downloadMemberFile/$1'); + $routes->get('downloadFullMemberDataExcelErrorFile/(:any)', 'LeadsController::downloadFullMemberDataExcelErrorFile/$1'); + $routes->get('getMemberDataExcelFileErrors', 'LeadsController::getMemberDataExcelFileErrors'); + $routes->post('savePlacementDataAndValidateMemberDataFile', 'LeadsController::savePlacementDataAndValidateMemberDataFile'); + $routes->get('checkMemberDataFileValidationStatus', 'LeadsController::checkMemberDataFileValidationStatus'); }); $routes->post("policy_tranction/sendInstallmentRemainderMail","PolicyTransactionController::sendInstallmentRemainderMail"); @@ -700,6 +704,8 @@ $routes->group('test', function($routes) { $routes->get('viewrfq', 'TestingController::viewRFQNonEb'); $routes->get('exportexcel', 'TestingController::exportExcel'); $routes->post('saverfq', 'TestingController::saverfq'); + $routes->get('membervalidation', 'TestingController::membervalidation'); + $routes->get('generateExcel', 'TestingController::generateExcel'); }); $routes->cli('cli/testcli', 'TestingController::testcli'); diff --git a/app/Controllers/JobWorker.php b/app/Controllers/JobWorker.php index 1f322c84..50c9820b 100755 --- a/app/Controllers/JobWorker.php +++ b/app/Controllers/JobWorker.php @@ -167,6 +167,10 @@ class JobWorker extends AdminController 'type' => 'CC', // Handler Category 'handler' => 'App\Controllers\EmployeeMultiEventServiceController', ], + 'memberDataListExcelFileFormatValidation' => [ + 'type' => 'CC', // Handler Category + 'handler' => 'App\Controllers\LeadsController', + ], ]; diff --git a/app/Controllers/LeadsController.php b/app/Controllers/LeadsController.php index 308e7184..40afde50 100644 --- a/app/Controllers/LeadsController.php +++ b/app/Controllers/LeadsController.php @@ -81,11 +81,13 @@ class LeadsController extends BaseController protected $claim_type_for_gpa; protected $cause_of_death; protected $buisnessType; + protected $member_data_excel_columns; + protected $general_relationships; public function __construct() { - set_session_context('Leads'); + set_session_context('LEAD CONTROLLER'); $this->myLogger = \Config\Services::mylogger(); $this->clientModel = new ClientModel(); @@ -138,6 +140,161 @@ class LeadsController extends BaseController 'suicide' => 'Suicide', 'accident' => 'Accident' ]; + + $this->member_data_excel_columns = [ + 'sno' => [ + 'col_idx' => 0, + 'col_cell_name' => 'A', + 'col_name' => 'Sl no', + 'is_mandatory' => false, + 'data_type' => 'str', + 'format' => null, + 'allowed_values' => null + ], + 'emp_code' => [ + 'col_idx' => 1, + 'col_cell_name' => 'B', + 'col_name' => 'Emp Code', + 'is_mandatory' => true, + 'data_type' => 'str', + 'format' => null, + 'allowed_values' => null + ], + 'name' => [ + 'col_idx' => 2, + 'col_cell_name' => 'C', + 'col_name' => 'Name', + 'is_mandatory' => true, + 'data_type' => 'str', + 'format' => null, + 'allowed_values' => null + ], + 'relationship' => [ + 'col_idx' => 3, + 'col_cell_name' => 'D', + 'col_name' => 'Relationship', + 'is_mandatory' => true, + 'data_type' => 'str', + 'format' => null, + 'allowed_values' => [ + 'Self', 'Spouse', 'Son', 'Daughter', 'Father', 'Mother', + 'Father-in-law', 'Mother-in-law', + 'self', 'spouse', 'son', 'daughter', 'father', 'mother', + 'father-in-law', 'mother-in-law' + ], + 'custom' => 'check_relationship_for_member_data', + 'params' => ['row', 'relationship', 'columns_to_check'] + ], + 'gender' => [ + 'col_idx' => 4, + 'col_cell_name' => 'E', + 'col_name' => 'Gender', + 'is_mandatory' => true, + 'data_type' => 'str', + 'format' => null, + 'allowed_values' => ['M', 'F'] + ], + 'dob' => [ + 'col_idx' => 5, + 'col_cell_name' => 'F', + 'col_name' => 'DOB', + 'is_mandatory' => true, + 'data_type' => 'str', + 'format' => 'd-M-Y', + 'allowed_values' => null, + 'age_validation' => true, + // 'custom' => 'check_dob_diff', + // 'params' => ['row', 'relationship', 'default_age_ratio', 'policy_details'] + ], + 'age' => [ + 'col_idx' => 6, + 'col_cell_name' => 'G', + 'col_name' => 'Age', + 'is_mandatory' => true, + 'data_type' => 'int', + 'format' => null, + 'allowed_values' => null + ], + 'email' => [ + 'col_idx' => 7, + 'col_cell_name' => 'H', + 'col_name' => 'Email', + 'is_mandatory' => false, + 'data_type' => 'str', + 'format' => null, + 'allowed_values' => null + ], + 'mobile' => [ + 'col_idx' => 8, + 'col_cell_name' => 'I', + 'col_name' => 'Mobile', + 'is_mandatory' => false, + 'data_type' => 'str', + 'format' => null, + 'allowed_values' => null + ], + 'si' => [ + 'col_idx' => 9, + 'col_cell_name' => 'J', + 'col_name' => 'SI', + 'is_mandatory' => false, + 'data_type' => 'int', + 'format' => null, + 'allowed_values' => null, + ] + ]; + + $this->general_relationships = [ + 'self' => [ + 'name' => 'Self', + 'gender' => 'M', + 'age_min' => 18, + 'age_max' => null + ], + 'spouse' => [ + 'name' => 'Spouse', + 'gender' => 'F', + 'age_min' => 18, + 'age_max' => null + ], + 'son' => [ + 'name' => 'Son', + 'gender' => 'M', + 'age_min' => null, + 'age_max' => 25 + ], + 'daughter' => [ + 'name' => 'Daughter', + 'gender' => 'F', + 'age_min' => null, + 'age_max' => 25 + ], + 'father' => [ + 'name' => 'Father', + 'gender' => 'M', + 'age_min' => 18, + 'age_max' => null + ], + 'mother' => [ + 'name' => 'Mother', + 'gender' => 'F', + 'age_min' => 18, + 'age_max' => null + ], + 'father-in-law' => [ + 'name' => 'Father in Law', + 'gender' => 'M', + 'age_min' => 18, + 'age_max' => null + ], + 'mother-in-law' => [ + 'name' => 'Mother in Law', + 'gender' => 'F', + 'age_min' => 18, + 'age_max' => null + ] + ]; + } public function viewLeadsList() @@ -505,7 +662,7 @@ class LeadsController extends BaseController if ($value['lead_form_type'] == 1) { //for this push the job to the calculateMembersDemography() function $job_details = new Jobs(); - $r = Jobs::addJob(['job_name' => 'calculateMembersDemography', 'payload' => [ + $r = Jobs::addJob(['job_name' => 'memberDataListExcelFileFormatValidation', 'payload' => [ 'lead_id' => $insert, ]]); } @@ -568,7 +725,11 @@ class LeadsController extends BaseController // $data['premium_date'] = null; // } - $data['multi_file_data'] = $this->leadFilesModel->where('lead_id', $id)->first() ?? null; + $data['multi_file_data'] = $this->leadFilesModel + ->where('lead_id', $id) + ->where('type !=', 2) + ->where('is_active', 1) + ->first() ?? null; $data['lastFiveYears'] = $this->getLastFiveFinancialYears(); $data['gpaClaimType'] = $this->claim_type_for_gpa; @@ -645,7 +806,7 @@ class LeadsController extends BaseController if (!empty($lead_form_type) && $lead_form_type == 1 && $key == 0) { //for this push the job to the calculateMembersDemography() function $job_details = new Jobs(); - $r = Jobs::addJob(['job_name' => 'calculateMembersDemography', 'payload' => [ + $r = Jobs::addJob(['job_name' => 'memberDataListExcelFileFormatValidation', 'payload' => [ 'lead_id' => $lead_id, ]]); log_message('info', "calculateMembersDemography JOB PUSHED"); @@ -860,13 +1021,23 @@ class LeadsController extends BaseController // 3. Optimize lead data query with specific field selection $lead_data = $this->leadsModel ->select(' - leads.id, leads.policy_type_id, leads.lead_type, leads.source_policy_id, - leads.policy_end_date, leads.lead_form_type, leads.created_by, leads.client_name, - policy_type.question_json, policy_type.policy_type, policy_type.long_name, - user_profiles.email as created_person_email - ') + leads.id, + leads.policy_type_id, + leads.lead_type, + leads.source_policy_id, + leads.policy_end_date, + leads.lead_form_type, + leads.created_by, + leads.client_name, + lead_files.status as demography_file_status, + policy_type.question_json, + policy_type.policy_type, + policy_type.long_name, + user_profiles.email as created_person_email + ') ->join('policy_type', 'leads.policy_type_id = policy_type.id') ->join('user_profiles', 'leads.created_by = user_profiles.id', 'left') + ->join('lead_files', 'leads.id = lead_files.lead_id AND lead_files.type = 2 AND lead_files.is_active = 1', 'left') ->where('leads.id', $id) ->where('leads.is_active', 1) ->first(); @@ -930,6 +1101,7 @@ class LeadsController extends BaseController // 10. Combine related queries $data['multi_file_data'] = $this->leadFilesModel ->where('lead_id', $id) + ->where('type !=', 2) ->where('is_active', 1) ->findAll(); @@ -3047,7 +3219,6 @@ class LeadsController extends BaseController 'cd_amount' => $params['cd_amount'] ?? null, 'no_of_installment' => $params['no_of_installment'] ?? null, 'is_installment' => $params['is_installment'] ?? null, - 'is_installment' => $params['is_installment'] ?? null, 'acm_id' => $params['acm_pk'] ?? null, ]; @@ -3609,6 +3780,13 @@ class LeadsController extends BaseController $input_value = $cellData['input_value'] != "" ? $cellData['input_value'] : ($cellData['value'] ?? ''); $value = $cellData['value'] ?? ''; + if( $item == "family_composition" && $subth == $insurer_name && $policy_type == 2){ + $age_ratio_array = json_decode($input_value, true)['age_ratio'] ?? null; + if(!empty($age_ratio_array)){ + $age_ratio = $age_ratio_array; + } + } + // Skip unwanted keys if (in_array($parentth, ['Sno', 'Item Key', 'Particulars', 'Action']) || in_array($subth, ['Quote Asked'])) { continue; @@ -3770,7 +3948,6 @@ class LeadsController extends BaseController return json_encode($placement_json_data); } - //------------------------------------------------------------------------------------------------ @@ -3814,7 +3991,6 @@ class LeadsController extends BaseController } } - public function getLastFiveFinancialYears() { $currentYear = date('Y'); @@ -3878,7 +4054,11 @@ class LeadsController extends BaseController $data['lead_edit_data'] = $this->leadsModel->where('id', $id)->first() ?? []; - $data['lead_edit_data']['multi_file_data'] = $this->leadFilesModel->where('lead_id', $id)->where('is_active', 1)->findAll() ?? null; + $data['lead_edit_data']['multi_file_data'] = $this->leadFilesModel + ->where('lead_id', $id) + ->where('type !=', 2) + ->where('is_active', 1) + ->findAll() ?? null; $data['lead_edit_data']['lead_file_count'] = count($data['lead_edit_data']['multi_file_data']); // Decode and merge custom fields if present @@ -5024,6 +5204,7 @@ class LeadsController extends BaseController $lead_file = $this->leadFilesModel ->where('lead_id', $lead_id) ->where('id', $id) + ->where('type !=', 2) ->where('is_active', 1) ->first(); @@ -5061,7 +5242,6 @@ class LeadsController extends BaseController return $attachments; } - public function handleMemberDataGPATotalSumInsurerFromExcel($params) { $lead_id = $params['lead_id']; @@ -5129,7 +5309,6 @@ class LeadsController extends BaseController return []; } - public function generateDemographyDataTable($param) { $returnData = $this->calculateMembersDemography($param, "internal"); @@ -5415,6 +5594,7 @@ class LeadsController extends BaseController // Get the updated lead file data $lead_file_data = $this->leadFilesModel ->where('is_active', 1) + ->where('type !=', 2) ->where('lead_id', $lead_id) ->findAll(); @@ -5455,8 +5635,7 @@ class LeadsController extends BaseController } } - - function renderFileFields($multi_file_data = []) + public function renderFileFields($multi_file_data = []) { $uploadFilePath = WRITEPATH . 'uploads/lead_files/'; $html = ''; @@ -5548,5 +5727,690 @@ class LeadsController extends BaseController return $this->response->download($filePath, null); } + // ----------- MEMBER DATA VALIDAATION ------------------------------------------------------------------------------------------------------ + + public function memberDataListValidation() + { + $lead_id = $this->request->getPost('lead_id'); + $this->memberDataListExcelFileFormatValidation(['lead_id' => $lead_id]); + } + + public function memberDataListExcelFileFormatValidation($params) + { + helper('excel_util_helper'); + + $this->myLogger->logme('error', 'Start memberDataListExcelFileFormatValidation'); + $this->myLogger->logme('error', "Received params: " . json_encode($params)); + + $lead_id = $params['lead_id']; + $age_validation_check = $params['age_validation'] ?? null; + $lead_data = $this->leadsModel->where('id', $lead_id)->first(); + // dd($lead_data); + + $return = []; + if (!isset($lead_data)) { + $this->myLogger->logme('error', "Lead not found for lead_id: {$lead_id}"); + $this->leadFilesModel->where('lead_id', $lead_id)->where('type', 2)->set(['status' => 'failed', 'error_data' => json_encode(['error_summary' => array_count_values([12]),'error_data' => 'file not found in DB'])])->update(); + return array('status' => false, 'msg' => 'file not found in DB'); + } + + //get the lead files data + $lead_file_data = $this->leadFilesModel->where('is_active', 1)->where('type', 2)->first(); + + //check the lead file table has the error data entry if not than create new entry + if(empty($lead_file_data)){ + $data['type'] = 2; + $data['file_name'] = $lead_data['file_name']; + $data['docs_name'] = "Member List"; + $data['lead_id'] = $lead_id; + $lead_file_last_insert_id = $this->leadFilesModel->insert($data); + $this->myLogger->logme('error', "New lead file entry created for store the error data, insert_id : '{$lead_file_last_insert_id}'"); + } + + $family_composition = []; + if($age_validation_check && !empty($lead_data['proposel_data'])){ + $family_composition = $this->getAgeRatioFromRfqJson($lead_id, $lead_data['proposel_data']); + $this->myLogger->logme('info', 'Family composition :',json_encode($family_composition)); + } + // dd($family_composition); + + // get the file path + $file_name_with_path = WRITEPATH . "/uploads/lead_files/" . $lead_data['file_name']; + $this->myLogger->logme('error', "File path: {$file_name_with_path}"); + + //check physical file + if (!file_exists($file_name_with_path)) { + //file not found update status and reason + $message = "Physcial file not found"; + $this->myLogger->logme('error', ($message . ' for lead id ' . $lead_id)); + $this->leadFilesModel + ->where('lead_id', $lead_id) + ->where('type', 2) + ->set(['status' => 'failed','error_data' => json_encode(['error_summary' => array_count_values([5]),'error_data' => $message])]) + ->update(); + return array('error_summary' => [5], 'error_data' => $message); + } + + $this->myLogger->logme('info', 'File exists, starting validation process'); + + //start validation process + $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path); + $sheet = $spreadsheet->getActiveSheet(); + + $highestRowAndColumn = $sheet->getHighestRowAndColumn(); + // dd($highestRowAndColumn); + + $columns_to_check = $this->member_data_excel_columns; + + $result = ['error_type' => 1, 'error_summary' => [], 'error_data' => []]; + $keys = array_keys($columns_to_check); + $allowedHighestColumn = end($columns_to_check); + $excel_data = $sheet->rangeToArray('A1:' . $allowedHighestColumn['col_cell_name'] . $highestRowAndColumn['row']); + $excel_data = ExcelSanitizeHelper::sanitizeArrayData($excel_data); + $this->myLogger->logme('error', 'Excel data sanitized count : {row_count}', ['row_count' => count($excel_data)]); + // dd($excel_data); + + //check number of columns in excel + $excel_columns = ($excel_data[0]); + + //check columns order in excel + $column_count_res = check_columns_name_exist($columns_to_check, $excel_columns); + // dd($column_count_res); + + if (isset($column_count_res) && count($column_count_res)) { + //columns count mismatch + $message = implode("\n", $column_count_res); + // echo $message; + $this->myLogger->logme('error', ($message . ' for lead id ' . $lead_id)); + $this->leadFilesModel + ->where('lead_id', $lead_id) + ->where('type', 2) + ->set(['status' => 'failed','error_data' => json_encode(['error_summary' => array_count_values([6]),'error_data' => $message])]) + ->update(); + return array('error_summary' => [6], 'error_data' => $message); + } + + $relationship = $this->general_relationships; + + $column_count_res = update_excel_column_indexes($columns_to_check, $excel_columns); + // dd($column_count_res); + + //remove header + unset($excel_data[0]); + $member_family_data = []; + foreach ($excel_data as $row_key => $row) { + + //1. avoid empty rows + if (check_row_is_empty_or_null($row)) { + $this->myLogger->logme('error', "Empty row found at index {$row_key}, stopping row iteration"); + break; + } + + //iterate each row for columns validations + foreach ($row as $col_key => $col) { + + $is_mandatory = $columns_to_check[$keys[$col_key]]['is_mandatory']; + $format = $columns_to_check[$keys[$col_key]]['format']; + $allowed_values = $columns_to_check[$keys[$col_key]]['allowed_values']; + $custom_function = isset($columns_to_check[$keys[$col_key]]['custom']) ? $columns_to_check[$keys[$col_key]]['custom'] : null; + $binding_params = isset($columns_to_check[$keys[$col_key]]['params']) ? $columns_to_check[$keys[$col_key]]['params'] : null; + + $column_dispaly_name = $columns_to_check[$keys[$col_key]]['col_name']; + $column_index = $columns_to_check[$keys[$col_key]]['col_idx']; + $column_cell = $columns_to_check[$keys[$col_key]]['col_cell_name']; + + + //mandatory check + if (is_bool($is_mandatory) && $is_mandatory === true) { + if ($col == "" || $col == NULL) { + array_push($result['error_summary'], 1); //push error code for summary + $result['error_data'][$row_key][$keys[$col_key]]['col_name'] = $column_dispaly_name; //push column name + $result['error_data'][$row_key][$keys[$col_key]]['col_idx'] = $column_index; //push column index + $result['error_data'][$row_key][$keys[$col_key]]['error'][] = 'Value is mandatory'; //push exact error desc + } + } + + //if is_mandatory is array (action based mandatory check) + if (is_array($is_mandatory)) { + $allowed_actions = $columns_to_check[$keys[$col_key]]['is_mandatory']; + if ($col == "" || $col == NULL) { + array_push($result['error_summary'], 1); + $result['error_data'][$row_key][$keys[$col_key]]['col_name'] = $column_dispaly_name; //push column name + $result['error_data'][$row_key][$keys[$col_key]]['col_idx'] = $column_index; //push column index + $result['error_data'][$row_key][$keys[$col_key]]['error'][] = 'Value is mandatory for this action/event'; + } + } + + //format check + if (isset($format)) { + $format_error = check_excel_date_format($col, $format); + if (!$format_error['status']) { + array_push($result['error_summary'], 2); + $result['error_data'][$row_key][$keys[$col_key]]['col_name'] = $column_dispaly_name; //push column name + $result['error_data'][$row_key][$keys[$col_key]]['col_idx'] = $column_index; //push column index + $result['error_data'][$row_key][$keys[$col_key]]['error'][] = $format_error['error']; + } + } + + //allowed values check + if (($is_mandatory === true && isset($allowed_values) && is_array($allowed_values)) || (is_array($is_mandatory) && (isset($allowed_values) && is_array($allowed_values)))) { + if (!in_array((trim($col)), $allowed_values)) { + array_push($result['error_summary'], 3); + $result['error_data'][$row_key][$keys[$col_key]]['col_name'] = $column_dispaly_name; //push column name + $result['error_data'][$row_key][$keys[$col_key]]['col_idx'] = $column_index; //push column index + $result['error_data'][$row_key][$keys[$col_key]]['error'][] = "Value not allowed: Expected " . implode(",", $allowed_values) . " and received $col"; + } + } + + //custom function check + if (isset($custom_function)) { + //convert string params into PHP variables + // Create an array of variables to pass custom helper funcitons + $param_values = []; + foreach ($binding_params as $bkey => $bparam) { + $param_values[] = ($$bparam); + } + // dd(($param_values));//die(); + $res = call_user_func_array($custom_function, $param_values); + if ($res['status'] === false) { + array_push($result['error_summary'], 4); + $result['error_data'][$row_key][$keys[$col_key]]['col_name'] = $column_dispaly_name; //push column name + $result['error_data'][$row_key][$keys[$col_key]]['col_idx'] = $column_index; //push column index + $result['error_data'][$row_key][$keys[$col_key]]['error'][] = $res['error']; + } + } + } + + //age validation + $age_validation = isset($columns_to_check['dob']['age_validation']) ?? null; + if (isset($age_validation) && $age_validation && $age_validation_check && !empty($family_composition)) { + $format_error = check_age_validation($row, $family_composition); + if (!$format_error['status']) { + array_push($result['error_summary'], 2); + $result['error_data'][$row_key][$keys[$columns_to_check['dob']['col_idx']]]['col_name'] = $columns_to_check['dob']['col_name']; //push column name + $result['error_data'][$row_key][$keys[$columns_to_check['dob']['col_idx']]]['col_idx'] = $columns_to_check['dob']['col_idx']; //push column index + $result['error_data'][$row_key][$keys[$columns_to_check['dob']['col_idx']]]['error'][] = $format_error['error']; + } + } + + $row['row_index'] = $row_key; + $relation_idx = $columns_to_check['relationship']['col_idx']; + $emp_code_idx = $columns_to_check['emp_code']['col_idx']; + + if (isset($row[$relation_idx]) && strtolower($row[$relation_idx]) == 'self' && isset($member_family_data[$row[$emp_code_idx]])) { + array_unshift($member_family_data[$row[$emp_code_idx]], $row); + } else { + $member_family_data[$row[$emp_code_idx]][] = $row; + } + } + // dd($member_family_data); + + $this->myLogger->logme('info', 'Row validation completed, starting duplicate check'); + $check_row_dublicate = check_duplicate_rows_and_contacts($excel_data, $columns_to_check, $result); + // dd($check_row_dublicate); + + if(count($check_row_dublicate)){ + $result = $check_row_dublicate; + } + + $this->myLogger->logme('info', 'Starting family validation'); + $result = validateFamily($member_family_data, $columns_to_check, $result); + // dd($family_validation); + + if (isset($result['error_summary']) && count($result['error_summary'])) { + $result['error_summary'] = array_count_values($result['error_summary']); + $status = 'failed'; + $failure_reason = ((json_encode($result))); + $this->leadFilesModel->where('lead_id', $lead_id)->where('type', 2)->set(['status' => $status,'error_data' => $failure_reason])->update(); + $this->myLogger->logme("error", '{lead_id} uploaded failed for this lead id', ['lead_id' => $lead_id]); + } else { + $this->leadFilesModel->where('lead_id', $lead_id)->where('type', 2)->set(['status' => 'success','error_data' => ''])->update(); + $r = Jobs::addJob(['job_name' => 'calculateMembersDemography', 'payload' => ['lead_id' => $lead_id]]); + } + + return $result; + } + + public function getAgeRatioFromRfqJson($lead_id, $porposel_data) + { + $age_ratio = []; + $rfq_data = $this->RFQModel->where('is_active', 1)->where('lead_id', $lead_id)->orderBy('id', 'desc')->first(); + if(empty($rfq_data) || empty($rfq_data['json'])){ + return $age_ratio; + } + + $data = json_decode($rfq_data['json'], true); + $proposal_and_insurer = json_decode($porposel_data, true); + $insurer_key = $proposal_and_insurer['insurer_name'] ?? null; + + if(isset($data['table_data']['data'])){ + foreach ($data['table_data']['data'] as $key => $value) { + if($value['items'] == 'family_composition'){ + foreach ($value['data'] as $family_composition) { + if($family_composition['subth'] == $insurer_key){ + $age_ratio = json_decode($family_composition['input_value'] ?? "", true) ?? []; + } + } + } + } + } + + return $age_ratio; + } + + public function getMemberDataExcelFileErrors() + { + $lead_id = $this->request->getGet('lead_id'); + // $lead_id = 329; + + // Render views and capture output + $result = $this->getMemberDataListExcelErrorData($lead_id); + + if ($result != 0) { + + $result['lead_id'] = $lead_id; + echo view('excel_errors', $result); + } else if ($result == 0) { + + $data['message'] = 'File Not Found Physically'; + return view('errors/404', $data); + } else { + + echo view('errors/html/production'); + } + } + + public function getMemberDataListExcelErrorData($lead_id) + { + try { + $file = $this->leadFilesModel->where('lead_id', $lead_id)->where('type', 2)->where('is_active', 1)->first(); + $error_data = json_decode($file['error_data']); + // dd($error_data); + // return $error_data; + + $file_name_with_path = WRITEPATH . "/uploads/lead_files/" . $file['file_name']; + + //check the file exist or not + if (!file_exists($file_name_with_path)) { + $error_message = "File not found"; + $this->myLogger->logme('error', ($error_message . ' for file id ' . $lead_id)); + return 0; + } + + $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path); + $sheet = $spreadsheet->getActiveSheet(); + + $highestRowAndColumn = $sheet->getHighestRowAndColumn(); + $excel_data = $sheet->rangeToArray('A1:' . $highestRowAndColumn['column'] . $highestRowAndColumn['row']); + $excelErrorData['excel_header'] = $excel_data[0]; + unset($excel_data[0]); + // Kint::dump($excel_data); + + if ($error_data->error_type == 1) { + + $finalArray = []; + foreach ($error_data->error_data as $key => $value) { + + foreach ($value as $key2 => $value2) { + $error_data = $value2->error; + $data = ['value' => $excel_data[$key][$value2->col_idx], 'error' => $error_data,]; + $excel_data[$key][$value2->col_idx] = $data; + } + array_push($finalArray, $excel_data[$key]); + } + + foreach ($finalArray as $fkey => $value) { + foreach ($value as $vkey => $arrayData) { + if (!is_array($arrayData)) { + $data = ['value' => $arrayData]; + $finalArray[$fkey][$vkey] = $data; + } + } + } + + $excelErrorData['excel_data'] = $finalArray; + return $excelErrorData; + } else if ($error_data->error_type == 2) { + + + $allErrors = []; + $typeTowArray = []; + + foreach ($error_data->error_data as $index => $item) { + + foreach ($item as $field) { + if (!isset($allErrors[$index])) { + $allErrors[$index] = []; + } + $allErrors[$index] = array_merge($allErrors[$index], $field->error); + } + } + + // dd(array_keys($allErrors)); + foreach ($allErrors as $key => $value) { + // echo $key; + // print_r($value); + foreach ($excel_data as $excel_data_index => $excel_data_value) { + if ($excel_data_value[0] == $key) { + $data = ['value' => $excel_data[$excel_data_index][1], 'error' => $value,]; + $excel_data[$excel_data_index][1] = $data; + array_push($typeTowArray, $excel_data[$excel_data_index]); + break; + } + } + } + // dd($data); + foreach ($typeTowArray as $fkey => $value) { + foreach ($value as $vkey => $arrayData) { + if (!is_array($arrayData)) { + $data = ['value' => $arrayData]; + $typeTowArray[$fkey][$vkey] = $data; + } + } + } + + $excelErrorData['excel_data'] = $typeTowArray; + return $excelErrorData; + } + } catch (\Exception $e) { + // Handle any exceptions + $errorMessage = $e->getMessage(); //die(); + $this->myLogger->logme('error', $errorMessage); + return false; // You can return an error response here + } + } + + public function downloadFullMemberDataExcelErrorFile($lead_id, $rowIndex = 1, $colIndex = 1) + { + // Get file data from the database + $file_data = $this->leadFilesModel->where('lead_id', $lead_id)->where('type', 2)->where('is_active', 1)->first(); + + $error = json_decode($file_data['error_data']); + + // Check if the file exists + if (!$file_data) { + $error_message = "File not found"; + $this->myLogger->logme('error', $error_message . ' for file id ' . $lead_id); + return $error_message; + } + + $fileName = $file_data['file_name']; + $filePath = WRITEPATH . '/uploads/lead_files/' . $fileName; + + // Check if the file exists + if (!file_exists($filePath)) { + $error_message = "File not found"; + $this->myLogger->logme('error', $error_message . ' for file id ' . $lead_id); + $data['message'] = 'Physical File Not Found'; + return view('errors/404', $data); + } + + // Load the Excel file + $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($filePath); + $sheet = $spreadsheet->getActiveSheet(); + + foreach ($error->error_data as $index => $error_data) { + + $rowIndex = $index + 1; + + if ($error->error_type == 1) { + + foreach ($error_data as $key => $value) { + + $colIndex = $value->col_idx + 1; + + $originalValue = $sheet->getCell([$colIndex, $rowIndex])->getValue(); + + $newValue = implode(', ', $value->error); + $val = $originalValue . ' ( ' . $newValue . ' )'; + $sheet->setCellValue([$colIndex, $rowIndex], $val); + + $style = [ + 'fill' => [ + 'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, + 'startColor' => ['rgb' => 'ffad99'] // Red color + ] + ]; + + $sheet->getStyle([$colIndex, $rowIndex])->applyFromArray($style); + } + } else if ($error->error_type == 2) { + + + foreach ($error_data as $key => $value) { + + + $originalValue = $sheet->getCell([1, $rowIndex])->getValue(); + + $newValue = implode(', ', $value->error); + $val = $originalValue . ' ( ' . $newValue . ' )'; + $sheet->setCellValue([$colIndex, $rowIndex], $val); + + $style = [ + 'fill' => [ + 'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, + 'startColor' => ['rgb' => 'ffad99'] // Red color + ] + ]; + $sheet->getStyle([$colIndex, $rowIndex])->applyFromArray($style); + } + } + } + + // Create a new filename for the modified Excel file + $newFileName = 'error_with_highlight_' . $fileName; + + // Save the modified Excel file to a new location + $newFilePath = WRITEPATH . '/uploads/lead_files/' . $newFileName; + $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet); + $writer->save($newFilePath); + + // Set headers to force download + $response = service('response'); + $response->setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); + $response->setHeader('Content-Disposition', 'attachment;filename="' . $newFileName . '"'); + $response->setHeader('Cache-Control', 'max-age=0'); + $response->setHeader('Content-Length', filesize($newFilePath)); + $response->setBody(file_get_contents($newFilePath)); + + // Delete the temporary file + unlink($newFilePath); + + // Return the response + return $response; + } + + public function savePlacementDataAndValidateMemberDataFile() + { + try { + + $this->myLogger->logme('error', '--- savePlacementDataAndValidateMemberDataFile START ---'); + + $params = $this->request->getPost(); + $this->myLogger->logme('error', 'Received params: ' . json_encode($params)); + + if (empty($params['lead_id'])) { + $this->myLogger->logme('error', 'Lead ID missing'); + return $this->respond([ + 'status' => false, + 'code' => 400, + 'message' => 'Lead ID is required' + ], 400); + } + + $lead_id = $params['lead_id']; + $proposal_insurer = $params['proposal_insurer'] ?? ''; + + // Handle proposal and insurer details + if (!empty($proposal_insurer) && strpos($proposal_insurer, '-') !== false) { + list($proposal_key, $insurer_key) = explode('-', $proposal_insurer, 2); + $lead_update_data = json_encode([ + 'proposel_name' => $proposal_key, + 'insurer_name' => $insurer_key, + 'insurer' => $params['insurer_and_branch'] ?? null, + ]); + $this->myLogger->logme('error', "Proposal/Insurer parsed successfully: $proposal_key - $insurer_key"); + } else { + $lead_update_data = null; + $this->myLogger->logme('error', 'Proposal/Insurer not provided or invalid format'); + } + + $data = [ + 'proposel_data' => $lead_update_data, + 'placement_date' => !empty($params['placement_date']) ? change_date_format($params['placement_date']) : null, + 'payment_date' => !empty($params['payment_date']) ? change_date_format($params['payment_date']) : null, + 'utr_no' => $params['utr_no'] ?? null, + 'is_cd' => $params['is_cd'] ?? null, + 'premium_amount' => $params['premium_amount'] ?? null, + 'total_amount' => $params['total_amount'] ?? null, + 'cd_amount' => $params['cd_amount'] ?? null, + 'no_of_installment' => $params['no_of_installment'] ?? null, + 'is_installment' => $params['is_installment'] ?? null, + 'acm_id' => $params['acm_pk'] ?? null, + ]; + + // get lead data + $lead_data = $this->leadsModel->where('id', $lead_id)->first(); + + // Compare and update only if changed the start and end date + if (!empty($params['policy_start_date'])) { + $converted_start = change_date_format($params['policy_start_date']); + if ($converted_start !== $lead_data['policy_start_date']) { + $data['policy_start_date'] = $converted_start; + $this->myLogger->logme('error', "Policy start date updated: $converted_start"); + } + } + + if (!empty($params['policy_end_date'])) { + $converted_end = change_date_format($params['policy_end_date']); + if ($converted_end !== $lead_data['policy_end_date']) { + $data['policy_end_date'] = $converted_end; + $this->myLogger->logme('error', "Policy end date updated: $converted_end"); + } + } + + // Handle TPA details + if (!empty($params['tpa_id']) && strpos($params['tpa_id'], '-') !== false) { + list($tpaBranchId, $tpaId) = explode('-', $params['tpa_id']); + $data['tpa_branch_id'] = $tpaBranchId; + $data['tpa_id'] = $tpaId; + $this->myLogger->logme('error', "TPA details added: branch=$tpaBranchId, id=$tpaId"); + } + + $this->myLogger->logme('error', 'Prepared lead update data: ' . json_encode($data)); + + // Update main lead record + $this->leadsModel->update($lead_id, $data); + $this->myLogger->logme('error', "Lead updated successfully for ID: $lead_id"); + + // Save installment details + if (!empty($params['installments'])) { + $installments = json_decode($params['installments'], true); + $this->myLogger->logme('error', "Installments data received: " . json_encode($installments)); + + if (is_array($installments) && !empty($installments)) { + foreach ($installments as $installment) { + $installment['payment_date'] = !empty($installment['payment_date']) && strtotime($installment['payment_date']) + ? date('Y-m-d', strtotime($installment['payment_date'])) + : null; + + $installment['lead_id'] = $lead_id; + + if (!empty($installment['id'])) { + $this->leadInstallmentPaymentDetails->update($installment['id'], $installment); + $this->myLogger->logme('error', "Installment updated: " . json_encode($installment)); + } else { + $this->leadInstallmentPaymentDetails->insert($installment); + $this->myLogger->logme('error', "Installment inserted: " . json_encode($installment)); + } + } + } + } else { + $this->myLogger->logme('error', "No installments provided"); + } + + // Update lead file status to pending + $this->leadFilesModel->where('lead_id', $lead_id)->where('type', 2)->set(['status' => 'pending'])->update(); + + // Queue job after save + $r = Jobs::addJob(['job_name' => 'memberDataListExcelFileFormatValidation', 'payload' => ['lead_id' => $lead_id, 'age_validation' => true]]); + $this->myLogger->logme('error', "Job queued successfully: " . json_encode($r)); + + $this->myLogger->logme('error', "--- savePlacementDataAndValidateMemberDataFile END (SUCCESS) ---"); + + return $this->respond([ + 'status' => true, + 'code' => 200, + 'message' => 'Placement data saved successfully. File being validated', + 'lead_id' => $lead_id, + 'data' => $data, + 'params' => $params + ], 200); + + } catch (\Exception $e) { + $errorDetails = [ + 'error_message' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack_trace' => $e->getTraceAsString(), + ]; + $this->myLogger->logme('error', "--- savePlacementDataAndValidateMemberDataFile ERROR --- " . json_encode($errorDetails)); + return $this->respond([ + 'status' => false, + 'code' => 500, + 'message' => 'Error while validating the member data', + 'error' => $errorDetails + ], 500); + } + } + + public function checkMemberDataFileValidationStatus() + { + $lead_id = $this->request->getVar('lead_id'); + if (empty($lead_id)) { + return $this->respond([ + 'status' => false, + 'code' => 400, + 'message' => 'lead_id is required' + ], 400); + } + + // Fetch file validation status + $lead_file = $this->leadFilesModel + ->select('id, lead_id, status') + ->where('lead_id', $lead_id) + ->where('type', 2) + ->first(); + + if (!$lead_file) { + return $this->respond([ + 'status' => false, + 'code' => 404, + 'message' => 'No file found for this lead_id' + ], 404); + } + + // If validation is still running + if ($lead_file['status'] === 'pending' || $lead_file['status'] === null) { + return $this->respond([ + 'status' => true, + 'code' => 202, // Accepted - still processing + 'message' => 'Validation in progress', + 'data' => ['status' => $lead_file['status']] + ], 200); + } + + // If validation finished (success or failed) + return $this->respond([ + 'status' => true, + 'code' => 200, + 'message' => 'Validation completed', + 'data' => $lead_file + ], 200); + } + + + // ----------- END OF MEMBER DATA VALIDAATION ------------------------------------------------------------------------------------------------------ + } diff --git a/app/Controllers/TestingController.php b/app/Controllers/TestingController.php index 87310adc..d9756a7b 100644 --- a/app/Controllers/TestingController.php +++ b/app/Controllers/TestingController.php @@ -11,6 +11,12 @@ use CodeIgniter\API\ResponseTrait; use Dompdf\Dompdf; use Dompdf\Options; +use PhpOffice\PhpSpreadsheet\Spreadsheet; +use PhpOffice\PhpSpreadsheet\Writer\Xlsx; +use PhpOffice\PhpSpreadsheet\Style\Alignment; +use PhpOffice\PhpSpreadsheet\Style\Fill; +use PhpOffice\PhpSpreadsheet\Style\Border; + class TestingController extends BaseController { use ResponseTrait; @@ -346,4 +352,185 @@ class TestingController extends BaseController dd($policy_data); } + public function membervalidation($lead_id = 329) + { + $lead_controll = new LeadsController(); + // $lead_controll->getMemberDataExcelFileErrors(); + $res = $lead_controll->memberDataListExcelFileFormatValidation(['lead_id' => $lead_id]); + dd($res); + } + + private $firstNames = [ + 'Rajesh', 'Priya', 'Amit', 'Sneha', 'Vikram', 'Anjali', 'Rahul', 'Deepika', + 'Sanjay', 'Kavita', 'Arun', 'Pooja', 'Manoj', 'Nisha', 'Suresh', 'Meera', + 'Karthik', 'Divya', 'Ravi', 'Lakshmi', 'Anand', 'Swathi', 'Vijay', 'Rekha', + 'Ashok', 'Sangeetha', 'Prakash', 'Uma', 'Ramesh', 'Vani', 'Kumar', 'Radha', + 'Dinesh', 'Shanti', 'Ganesh', 'Parvati', 'Mohan', 'Sita', 'Arjun', 'Geetha' + ]; + + private $lastNames = [ + 'Kumar', 'Sharma', 'Singh', 'Patel', 'Reddy', 'Nair', 'Iyer', 'Krishnan', + 'Rao', 'Gupta', 'Verma', 'Agarwal', 'Joshi', 'Mehta', 'Desai', 'Pillai', + 'Menon', 'Bhat', 'Naidu', 'Varma', 'Malhotra', 'Kapoor', 'Chopra', 'Saxena', + 'Pandey', 'Mishra', 'Tiwari', 'Dubey', 'Sinha', 'Jain', 'Shah', 'Thakur' + ]; + + private $relationships = ['Self', 'Spouse', 'Son', 'Daughter', 'Father', 'Mother']; + private $genders = ['M', 'F']; + private $domains = ['gmail.com', 'yahoo.com', 'outlook.com', 'company.com', 'example.com']; + + public function generateExcel() + { + // Increase execution time and memory for large files + ini_set('max_execution_time', 600); + ini_set('memory_limit', '1024M'); + + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + + // Define headers + $headers = [ + 'Sl no', + 'Emp Code', + 'Name', + 'Relationship', + 'Gender', + 'DOB', + 'Age', + 'Email', + 'Mobile', + 'SI', + 'SI Enhancement', + 'Proposed Sum Insured 1', + 'Proposed Sum Insured 2', + 'Proposed Sum Insured 3', + 'Proposed Sum Insured 4' + ]; + + // Set headers in row 1 + $col = 'A'; + foreach ($headers as $header) { + $sheet->setCellValue($col . '1', $header); + $col++; + } + + // Style the header row + $headerStyle = [ + 'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']], + 'fill' => ['fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => '4472C4']], + 'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER, 'vertical' => Alignment::VERTICAL_CENTER], + 'borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN]] + ]; + $sheet->getStyle('A1:O1')->applyFromArray($headerStyle); + + // Generate 70,000 sample records + $totalRecords = 1000; + $batchSize = 1000; + + for ($i = 1; $i <= $totalRecords; $i++) { + $row = $i + 1; // Start from row 2 (row 1 is header) + + $record = $this->generateSampleRecord($i); + + $sheet->setCellValue('A' . $row, $record['sl_no']); + $sheet->setCellValue('B' . $row, $record['emp_code']); + $sheet->setCellValue('C' . $row, $record['name']); + $sheet->setCellValue('D' . $row, $record['relationship']); + $sheet->setCellValue('E' . $row, $record['gender']); + $sheet->setCellValue('F' . $row, $record['dob']); + $sheet->setCellValue('G' . $row, $record['age']); + $sheet->setCellValue('H' . $row, $record['email']); + $sheet->setCellValue('I' . $row, $record['mobile']); + $sheet->setCellValue('J' . $row, $record['si']); + $sheet->setCellValue('K' . $row, $record['si_enhancement']); + $sheet->setCellValue('L' . $row, $record['proposed_si_1']); + $sheet->setCellValue('M' . $row, $record['proposed_si_2']); + $sheet->setCellValue('N' . $row, $record['proposed_si_3']); + $sheet->setCellValue('O' . $row, $record['proposed_si_4']); + + // Clear memory every batch + if ($i % $batchSize == 0) { + $sheet->garbageCollect(); + } + } + + // Auto-size columns + foreach (range('A', 'O') as $col) { + $sheet->getColumnDimension($col)->setAutoSize(true); + } + + // Generate filename + $filename = 'employee_data_70k_' . date('Y-m-d_His') . '.xlsx'; + + // Set headers for download + header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); + header('Content-Disposition: attachment;filename="' . $filename . '"'); + header('Cache-Control: max-age=0'); + + // Write file to output + $writer = new Xlsx($spreadsheet); + $writer->save('php://output'); + + // Clean up + $spreadsheet->disconnectWorksheets(); + unset($spreadsheet); + exit; + } + + private function generateSampleRecord($index) + { + $firstName = $this->firstNames[array_rand($this->firstNames)]; + $lastName = $this->lastNames[array_rand($this->lastNames)]; + $name = $firstName . ' ' . $lastName; + + $relationship = $this->relationships[array_rand($this->relationships)]; + $gender = $this->genders[array_rand($this->genders)]; + + // Generate random age between 18 and 65 + $age = rand(18, 65); + + // Calculate DOB based on age + $year = date('Y') - $age; + $month = str_pad(rand(1, 12), 2, '0', STR_PAD_LEFT); + $day = str_pad(rand(1, 28), 2, '0', STR_PAD_LEFT); + $dob = "{$day}-{$month}-{$year}"; + + // Generate employee code + $empCode = 'EMP' . str_pad($index, 6, '0', STR_PAD_LEFT); + + // Generate email + $email = strtolower($firstName . '.' . $lastName . $index) . '@' . $this->domains[array_rand($this->domains)]; + + // Generate mobile number (Indian format) + $mobile = '+91' . rand(7000000000, 9999999999); + + // Generate insurance amounts + $siOptions = [100000, 200000, 300000, 500000, 1000000]; + $si = $siOptions[array_rand($siOptions)]; + $si_enhancement = rand(0, 1) ? rand(50000, 200000) : 0; + + $proposed_si_1 = $si + rand(100000, 500000); + $proposed_si_2 = $proposed_si_1 + rand(100000, 500000); + $proposed_si_3 = $proposed_si_2 + rand(100000, 500000); + $proposed_si_4 = $proposed_si_3 + rand(100000, 500000); + + return [ + 'sl_no' => $index, + 'emp_code' => $empCode, + 'name' => $name, + 'relationship' => $relationship, + 'gender' => $gender, + 'dob' => $dob, + 'age' => $age, + 'email' => $email, + 'mobile' => $mobile, + 'si' => $si, + 'si_enhancement' => $si_enhancement, + 'proposed_si_1' => $proposed_si_1, + 'proposed_si_2' => $proposed_si_2, + 'proposed_si_3' => $proposed_si_3, + 'proposed_si_4' => $proposed_si_4 + ]; + } + } diff --git a/app/Helpers/excel_util_helper.php b/app/Helpers/excel_util_helper.php index 932e53c8..e608b013 100755 --- a/app/Helpers/excel_util_helper.php +++ b/app/Helpers/excel_util_helper.php @@ -1993,7 +1993,6 @@ if (!function_exists('group_slab_rates_basedon_name')) { } } - //this key generating mandantory for display employee info in enrolment app w/o error if (!function_exists('generate_family_floater_key')) { function generate_family_floater_key($relationship) @@ -2002,7 +2001,7 @@ if (!function_exists('generate_family_floater_key')) { $relation = 'parent'; } else if (strtolower(trim($relationship)) === 'son' || strtolower(trim($relationship)) === 'daughter') { $relation = 'child'; - } else if ((strtolower(trim($relationship)) === 'father in Law' || strtolower(trim($relationship)) === 'mother in Law') || (strtolower(trim($relationship)) === 'father-in-Law' || strtolower(trim($relationship)) === 'mother-in-Law')) { + } else if ((strtolower(trim($relationship)) === 'father in law' || strtolower(trim($relationship)) === 'mother in law') || (strtolower(trim($relationship)) === 'father-in-law' || strtolower(trim($relationship)) === 'mother-in-law')) { $relation = 'parent_in_law'; } else if (strtolower(trim($relationship)) === 'spouse') { $relation = 'spouse'; @@ -2041,3 +2040,331 @@ if (!function_exists('formatIndianCurrency')) { return $formatted . $decimal; } } + +// ------------- FUNCTION FOR LEAD MEMBER DATA LIST VALIDATIONS -------------------------------------- + +if (!function_exists('check_columns_name_exist')) { + function check_columns_name_exist($definedColumns, $excelColumns) + { + $mismatchedColumns = []; + + foreach ($definedColumns as $colKey => $definedCol) { + $definedColName = strtolower(trim($definedCol['col_name'])); + + // Normalize excel columns to lowercase for comparison + $excelColsLower = array_map('strtolower', array_map('trim', $excelColumns)); + + if (!in_array($definedColName, $excelColsLower)) { + $mismatchedColumns[] = "Missing column: " . $definedCol['col_name'] . " in Excel file.
"; + } + } + + return $mismatchedColumns; + } +} + +if (!function_exists('update_excel_column_indexes')) { + function update_excel_column_indexes($definedColumns, $excelColumns) + { + // $excelColumns is the first row of the Excel file (header row) + // Example: ['Emp Code', 'Name', 'Gender', 'DOB', 'SI'] + + foreach ($definedColumns as $key => &$definedCol) { + $definedColName = strtolower(trim($definedCol['col_name'])); + $excelColsLower = array_map('strtolower', array_map('trim', $excelColumns)); + + // Find column index in Excel + $colIndex = array_search($definedColName, $excelColsLower); + + if ($colIndex !== false) { + $definedCol['col_idx'] = $colIndex; + $definedCol['col_cell_name'] = chr(65 + $colIndex); // A=65, B=66... + } else { + // If column missing in Excel + $definedCol['col_idx'] = null; + $definedCol['col_cell_name'] = null; + } + } + + return $definedColumns; + } +} + +if (!function_exists('check_duplicate_rows_and_contacts')) { + function check_duplicate_rows_and_contacts($excel_data, $columns_to_check, $err_data) + { + $exl_col = $columns_to_check; + $keys = array_keys($columns_to_check); + unset($columns_to_check['sno'], $columns_to_check['si'], $columns_to_check['email'], $columns_to_check['mobile'], $columns_to_check['age']); + + $seenRows = []; + $emailSeen = []; + $mobileSeen = []; + $duplicateRows = []; + + foreach ($excel_data as $rowIndex => $row) { + + // Build unique key from selected columns + $values = []; + foreach ($columns_to_check as $colIdx) { + $values[] = isset($row[$colIdx['col_idx']]) ? trim($row[$colIdx['col_idx']]) : ''; + } + $rowKey = json_encode($values); + + // =============== STEP 1: Main duplicate check =============== + if (!isset($seenRows[$rowKey])) { + $seenRows[$rowKey] = [$rowIndex]; + } else { + // First duplicate occurrence — mark all related rows + $seenRows[$rowKey][] = $rowIndex; + $indexes = $seenRows[$rowKey]; + + $rows_str = implode(', ', array_map(fn($i) => $i + 1, $indexes)); + $error_message = "Duplicate found in selected columns: Rows {$rows_str} are identical"; + + foreach ($indexes as $i) { + // Avoid re-adding duplicate errors + if (!in_array($i, $duplicateRows)) { + array_push($err_data['error_summary'], 1); + $err_data['error_data'][$i][$keys[0]]['col_name'] = 'Sl no'; + $err_data['error_data'][$i][$keys[0]]['col_idx'] = 0; + $err_data['error_data'][$i][$keys[0]]['error'][] = $error_message; + $duplicateRows[] = $i; + } + } + + // Skip email/mobile check for this duplicate row + continue; + } + + // =============== STEP 2: Email & Mobile check (only if not duplicate) =============== + $email = isset($row[$exl_col['email']['col_idx']]) ? trim($row[$exl_col['email']['col_idx']]) : ''; + $mobile = isset($row[$exl_col['mobile']['col_idx']]) ? trim($row[$exl_col['mobile']['col_idx']]) : ''; + + // Check email duplicates + if ($email !== '') { + if (isset($emailSeen[$email])) { + $firstIndex = $emailSeen[$email] + 1; + $currentRow = $rowIndex + 1; + $error_message = "Duplicate email found: Row {$currentRow} and Row {$firstIndex} have the same email '$email'"; + array_push($err_data['error_summary'], 1); + $err_data['error_data'][$rowIndex][$keys[$exl_col['email']['col_idx']]]['col_name'] = $exl_col['email']['col_name']; + $err_data['error_data'][$rowIndex][$keys[$exl_col['email']['col_idx']]]['col_idx'] = $exl_col['email']['col_idx']; + $err_data['error_data'][$rowIndex][$keys[$exl_col['email']['col_idx']]]['error'][] = $error_message; + } else { + $emailSeen[$email] = $rowIndex; + } + } + + // Check mobile duplicates + if ($mobile !== '') { + if (isset($mobileSeen[$mobile])) { + $firstIndex = $mobileSeen[$mobile] + 1; + $currentRow = $rowIndex + 1; + $error_message = "Duplicate mobile number found: Row {$currentRow} and Row {$firstIndex} have the same mobile '$mobile'"; + array_push($err_data['error_summary'], 1); + $err_data['error_data'][$rowIndex][$keys[$exl_col['mobile']['col_idx']]]['col_name'] = $exl_col['mobile']['col_name']; + $err_data['error_data'][$rowIndex][$keys[$exl_col['mobile']['col_idx']]]['col_idx'] = $exl_col['mobile']['col_idx']; + $err_data['error_data'][$rowIndex][$keys[$exl_col['mobile']['col_idx']]]['error'][] = $error_message; + } else { + $mobileSeen[$mobile] = $rowIndex; + } + } + } + + return $err_data; + } +} + +if (!function_exists('check_relationship_for_member_data')) { + function check_relationship_for_member_data($row, $relationship, $columns_to_check) + { + $relation_col_idx = $columns_to_check['relationship']['col_idx'] ?? null; + $gender_col_idx = $columns_to_check['gender']['col_idx'] ?? null; + + if ($relation_col_idx !== null && $gender_col_idx !== null && !empty($row[$relation_col_idx]) && !empty($row[$gender_col_idx])) { //$row[5] = relationship $row[4] = Gender + + $slug = \Config\Services::slug(); + $col = $slug->slugify($row[$relation_col_idx]); + + if ($col != 'self' && $col != 'spouse') { + if (!isset($relationship[$col])) { + return array('status' => false, 'error' => 'Rule Conflict: Unknown Relationship'); + } + + if (isset($relationship[$col]) && $relationship[$col]['gender'] != $row[$gender_col_idx]) { + $error = "Gender relationship conflict: Expected " . $relationship[$col]['gender'] . ", received $row[$gender_col_idx]"; + return array('status' => false, 'error' => $error); + } + } + + return array('status' => true); + } else { + return array('status' => false, 'error' => 'Rule Conflict: Both Relationship and Gender required for check relationship conflict'); + } + } +} + +if (!function_exists('member_data_group_by_family')) { + function member_data_group_by_family($member_data, $columns_to_check) + { + $result = []; + // Kint::dump($member_data); + foreach ($member_data as $rowIndex => $row) { + if (!check_row_is_empty_or_null($row)) { + + $row['row_index'] = $rowIndex; + + $relation_idx = $columns_to_check['relationship']['col_idx']; + $emp_code_idx = $columns_to_check['emp_code']['col_idx']; + + if (isset($row[$relation_idx]) && strtolower($row[$relation_idx]) == 'self' && isset($result[$row[$emp_code_idx]])) { + array_unshift($result[$row[$emp_code_idx]], $row); + } else { + $result[$row[$emp_code_idx]][] = $row; + } + } + } + return $result; + } +} + +if (!function_exists('validateFamily')) { + function validateFamily($familyData, $columns_to_check, $errors) { + + $keys = array_keys($columns_to_check); + foreach ($familyData as $familyId => $members) { + + $selfMember = null; + $spouseMember = null; + $selfCount = 0; + $row_index = null; + + // Find Self and Spouse members + foreach ($members as $member) { + $relation = trim($member[3]); // Relationship field + + if (strtolower($relation) == 'self') { + $selfCount++; + $selfMember = $member; + } + + if (strtolower($relation) == 'spouse') { + $spouseMember = $member; + } + + if($row_index == null){ + if(strtolower($relation) == 'self'){ + $row_index = $member['row_index']; + }else if(strtolower($relation) == 'spouse'){ + $row_index = $member['row_index']; + }else{ + $row_index = $member['row_index']; + } + } + + } + + // Validation 1: Check if Self exists + if ($selfCount === 0) { + + $message = "Emp ID - {$familyId}: Missing 'Self' member"; + array_push($errors['error_summary'], 4); + $errors['error_data'][$row_index][$keys[$columns_to_check['emp_code']['col_idx']]]['col_name'] = $columns_to_check['emp_code']['col_name']; + $errors['error_data'][$row_index][$keys[$columns_to_check['emp_code']['col_idx']]]['col_idx'] = $columns_to_check['emp_code']['col_idx']; + $errors['error_data'][$row_index][$keys[$columns_to_check['emp_code']['col_idx']]]['error'][] = $message; + + continue; + } + + // Validation 2: Check if there's exactly one Self + if ($selfCount > 1) { + $message = "Emp ID - {$familyId}: Multiple 'Self' members found. Only one 'Self' is allowed per family"; + array_push($errors['error_summary'], 5); + $errors['error_data'][$row_index][$keys[$columns_to_check['emp_code']['col_idx']]]['col_name'] = $columns_to_check['emp_code']['col_name']; + $errors['error_data'][$row_index][$keys[$columns_to_check['emp_code']['col_idx']]]['col_idx'] = $columns_to_check['emp_code']['col_idx']; + $errors['error_data'][$row_index][$keys[$columns_to_check['emp_code']['col_idx']]]['error'][] = $message; + + continue; + } + + // Validation 3: Validate spouse gender if spouse exists + if ($spouseMember !== null) { + + $selfGender = strtoupper(trim($selfMember[4])); // Gender field + $spouseGender = strtoupper(trim($spouseMember[4])); + $selfName = $selfMember[2]; // Name field + $spouseName = $spouseMember[2]; + + // Check gender compatibility + $message = ''; + if ($selfGender === 'M' && $spouseGender !== 'F') { + $message = "Emp ID - {$familyId}: Self ('{$selfName}') is Male (M); spouse must be Female (F). Found spouse ('{$spouseName}') with gender '({$spouseGender})'."; + } elseif ($selfGender === 'F' && $spouseGender !== 'M') { + $message = "Emp ID - {$familyId}: Self ('{$selfName}') is Female (F); spouse must be Male (M). Found spouse ('{$spouseName}') with gender '({$spouseGender})'."; + } elseif (!in_array($selfGender, ['M', 'F'])) { + $message = "Emp ID - {$familyId}: Invalid gender for Self member ('{$selfName}'). Expected 'M' or 'F', found '({$selfGender})'."; + } + + if(isset($message) && !empty($message)){ + array_push($errors['error_summary'], 6); + $errors['error_data'][$row_index][$keys[$columns_to_check['emp_code']['col_idx']]]['col_name'] = $columns_to_check['emp_code']['col_name']; + $errors['error_data'][$row_index][$keys[$columns_to_check['emp_code']['col_idx']]]['col_idx'] = $columns_to_check['emp_code']['col_idx']; + $errors['error_data'][$row_index][$keys[$columns_to_check['emp_code']['col_idx']]]['error'][] = $message; + } + } + } + + return $errors; + } +} + +if (!function_exists('check_age_validation')) { + function check_age_validation($row, $family_composition) + { + if ($row[5] != null) { + + $dateString = convert_string_to_date($row[5]); + if ($dateString === false) { + return array('status' => false, 'error' => 'Not a valid Date'); + } + + $relationships = $family_composition['age_ratio']; + + $dob = $dateString; + $currentDateTime = new DateTime(); + + $passedDateTime = new DateTime($dob); + $interval = $currentDateTime->diff($passedDateTime); + + $slug = \Config\Services::slug(); + $relationship = $slug->slugify($row[3]); + if($relationship == 'son' || $relationship == 'daughter'){ + $relationship = 'child'; + } + if($relationship == 'father' || $relationship == 'mother' || $relationship == 'mother-in-law'|| $relationship == 'father-in-law' ){ + $relationship = 'elders'; + } + + $age_min = isset($relationships[$relationship]['min']) ? $relationships[$relationship]['min'] : NULL; + $age_max = isset($relationships[$relationship]['max']) ? $relationships[$relationship]['max'] : NULL; + + // Kint::dump($dob,$currentDateTime,$passedDateTime, $interval->y, $age_min, $age_max, $relationship, $relationships); + + if ($age_min !== null && $age_min > $interval->y) { + return array('status' => false, 'error' => "Age conflict : minimum $age_min yrs allowed, received $interval->y"); + } + if ($age_max !== null && $age_max < $interval->y) { + return array('status' => false, 'error' => "Age conflict : maximum $age_max yrs allowed, received $interval->y"); + } + return array('status' => true); + + } else { + return array('status' => false, 'error' => 'Rule Conflict: Both DOB and Relationship required for age check'); + } + } +} + +// ------------- END OF LEAD MEMBER DATA LIST VALIDATIONS -------------------------------------- + + diff --git a/app/Models/LeadFilesModel.php b/app/Models/LeadFilesModel.php index 37db8e16..f3532d1f 100644 --- a/app/Models/LeadFilesModel.php +++ b/app/Models/LeadFilesModel.php @@ -17,7 +17,10 @@ class LeadFilesModel extends Model 'updated_by', 'created_at', 'updated_at', - 'is_active' + 'is_active', + 'error_data', + 'status', + 'type', ]; // Callbacks diff --git a/app/Models/LeadsModel.php b/app/Models/LeadsModel.php index 005eacd2..7cc56602 100644 --- a/app/Models/LeadsModel.php +++ b/app/Models/LeadsModel.php @@ -147,6 +147,7 @@ class LeadsModel extends Model $data = $this->select(' leads.*, + lead_files.status as demography_file_status, kyc_entity_type.name as entity_type, policy_type.policy_type, user_profiles.first_name as salse_person_name, @@ -169,6 +170,7 @@ class LeadsModel extends Model ->join('kyc_entity_type', 'leads.entity_type_id = kyc_entity_type.id', 'left') ->join('user_profiles', 'leads.salse_person_id = user_profiles.id', 'left') ->join('policy_type', 'leads.policy_type_id = policy_type.id', 'left') + ->join('lead_files', 'leads.id = lead_files.lead_id AND lead_files.type = 2 AND lead_files.is_active = 1', 'left') ->where('leads.is_active', 1); if (!empty($where)) { diff --git a/app/Views/excel_errors.php b/app/Views/excel_errors.php index 04db844d..7e9141e4 100755 --- a/app/Views/excel_errors.php +++ b/app/Views/excel_errors.php @@ -110,7 +110,18 @@ table.dataTable tbody td { + + \ No newline at end of file From 69d343a744d2351f3cafcee18986ad271363a90a Mon Sep 17 00:00:00 2001 From: velz Date: Thu, 9 Oct 2025 15:00:03 +0530 Subject: [PATCH 02/17] FIX_CHATBOT_ECARD_MENU --- .../Chatbot/EcardDownloadConversation.php | 70 ++++++++++++++++--- .../Chatbot/MainMenuConversation.php | 2 +- .../Chatbot/NetworkHospitalConversation.php | 54 +++++++++++++- app/Helpers/ChatbotHelper.php | 2 +- app/Models/EmployeeModel.php | 7 +- 5 files changed, 119 insertions(+), 16 deletions(-) diff --git a/app/Controllers/Chatbot/EcardDownloadConversation.php b/app/Controllers/Chatbot/EcardDownloadConversation.php index a0a644a0..d0b0f08d 100644 --- a/app/Controllers/Chatbot/EcardDownloadConversation.php +++ b/app/Controllers/Chatbot/EcardDownloadConversation.php @@ -18,7 +18,59 @@ class EcardDownloadConversation extends Conversation $this->showEcardMenu(); } - protected function showEcardMenu() + protected function showEcardMenu() +{ +// Log entry for debugging +log_message('error', 'showEcardMenu function called'); + + +// Get chat session and policies +$chat_session_info = get_chatbot_session_info(); +$policy_list = ChatbotHelper::getListOfPolicies($chat_session_info); + +// If policies found, build an HTML list of links (and raw URLs as fallback) +if (is_array($policy_list) && count($policy_list)) { + $parts = []; + foreach ($policy_list as $policy) { + // Resolve rand string (defensive) + $randString = ''; + if (isset($policy['rand_string']) && $policy['rand_string'] !== '') { + $randString = $policy['rand_string']; + } elseif (isset($policy['rand']) && $policy['rand'] !== '') { + $randString = $policy['rand']; + } elseif (isset($policy['emp_policy_id'])) { + // As a last resort, use emp_policy_id (not ideal but prevents broken links) + $randString = $policy['emp_policy_id']; + } + + // Build link; make sure base_url produces correct path + $link = base_url('/download-e-card/' . $randString . '/1'); + + // Escape policy name to avoid HTML injection + $safeName = isset($policy['policy_name']) ? htmlspecialchars($policy['policy_name'], ENT_QUOTES, 'UTF-8') : 'Policy'; + + // Add to parts; include anchor and raw URL fallback + $parts[] = "🔹 {$safeName}
"; + } + + $message = "Choose a policy to download (click the policy name below):

" . implode('

', $parts); + log_message('error', 'Ecard links displayed: ' . json_encode(array_column($policy_list, 'policy_name'))); + $this->say($message); +} else { + log_message('error', 'No policies found for ecard download'); + $this->say('No policy found.'); +} + +// After showing links, move to confirmation conversation (Do you want to continue?) +// This keeps the UX identical to previous flow where we asked the user if they want to continue. +$this->bot->startConversation(new doYouWantToContinueConversation()); + + +} + + + + protected function showEcardMenuOLD() { log_message('error', ('showEcardMenu function called')); @@ -27,17 +79,13 @@ class EcardDownloadConversation extends Conversation $buttons = []; $question = 'Choose Policy to Download Ecard:'; - // log_message('error', ('policy_list : ' . json_encode($policy_list))); + log_message('error', ('policy_list : ' . json_encode($policy_list))); if(is_array($policy_list) && count($policy_list)) { foreach($policy_list as $policy) { - // $question = Question::create("Choose Policy to Download Ecard:") - // ->addButtons([ - // Button::create("🔹 $policy['policy_name']")->value("$policy['emp_policy_id']"), - // Button::create("◀️ Go Back")->value("go_back"), - // ]); + $this->buttonsData[$policy['emp_policy_id'].'#'.$policy['rand_string']] = ['response_text' => "🔹 {$policy['policy_name']}"] ; $buttons[] = Button::create("{$policy['policy_name']}")->value($policy['emp_policy_id'].'#'.$policy['rand_string']); } @@ -63,10 +111,9 @@ class EcardDownloadConversation extends Conversation case is_string($answer->getValue()) && is_array(explode('#',$answer->getValue())) && count((explode('#',$answer->getValue()))) == 2: $link = base_url().'/download-e-card/' . explode('#',$answer->getValue())[1].'/1'; - $this->say('Click here to downlad: Ecard'); - + log_message('error', $link); + $this->say('Click here to downlad: GMC
Click here to downlad: GMC Parent'); $this->bot->startConversation(new doYouWantToContinueConversation()); // ✅ Restart the - break; default: @@ -76,4 +123,7 @@ class EcardDownloadConversation extends Conversation } }); } + + + } diff --git a/app/Controllers/Chatbot/MainMenuConversation.php b/app/Controllers/Chatbot/MainMenuConversation.php index f06fd078..e5bf7a3d 100644 --- a/app/Controllers/Chatbot/MainMenuConversation.php +++ b/app/Controllers/Chatbot/MainMenuConversation.php @@ -23,7 +23,7 @@ class MainMenuConversation extends Conversation { $this->bot->userStorage()->delete(); $this->bot->types(); // Typing indicator for the first message - sleep(0.5); // Delay + // sleep(0.5); // Delay $this->showMainMenu(); } diff --git a/app/Controllers/Chatbot/NetworkHospitalConversation.php b/app/Controllers/Chatbot/NetworkHospitalConversation.php index 34e44f2b..57bb13de 100644 --- a/app/Controllers/Chatbot/NetworkHospitalConversation.php +++ b/app/Controllers/Chatbot/NetworkHospitalConversation.php @@ -16,11 +16,11 @@ class NetworkHospitalConversation extends Conversation public function run() { $this->bot->types(); // Typing indicator for the first message - sleep(0.5); // Delay + // sleep(0.5); // Delay $this->showHospitalMenu(); } - protected function showHospitalMenu() + protected function showHospitalMenuOLD() { $chat_session_info = get_chatbot_session_info(); $policy_list = ChatbotHelper::getListOfPolicies($chat_session_info); @@ -92,4 +92,54 @@ class NetworkHospitalConversation extends Conversation }); } + protected function showHospitalMenu() +{ +log_message('error', 'showHospitalMenu function called'); + + +// Get chat session and policies +$chat_session_info = get_chatbot_session_info(); +$policy_list = ChatbotHelper::getListOfPolicies($chat_session_info); + +if (is_array($policy_list) && count($policy_list)) { + $parts = []; + foreach ($policy_list as $policy) { + // Resolve rand string (defensive) + $randString = ''; + if (isset($policy['rand_string']) && $policy['rand_string'] !== '') { + $randString = $policy['rand_string']; + } elseif (isset($policy['rand']) && $policy['rand'] !== '') { + $randString = $policy['rand']; + } elseif (isset($policy['emp_policy_id'])) { + $randString = $policy['emp_policy_id']; + } + + $emp_policy_id = isset($policy['emp_policy_id']) ? $policy['emp_policy_id'] : ''; + $hospital_link = ChatbotHelper::getHospitalLink($emp_policy_id); + + $safeName = isset($policy['policy_name']) ? htmlspecialchars($policy['policy_name'], ENT_QUOTES, 'UTF-8') : 'Policy'; + + if ($hospital_link) { + $parts[] = "🔹 {$safeName}
"; + } else { + $parts[] = "🔹 {$safeName} — No Data found, please contact support team"; + } + + log_message('error', 'Hospital link for policy ' . $emp_policy_id . ': ' . $hospital_link); + } + + $message = "Access hospital details for your policies below:

" . implode('

', $parts); + $this->say($message); +} else { + log_message('error', 'No policies found for hospital menu'); + $this->say('No policy found.'); +} + +// After showing links, move to confirmation conversation +$this->bot->startConversation(new doYouWantToContinueConversation()); + + +} + + } diff --git a/app/Helpers/ChatbotHelper.php b/app/Helpers/ChatbotHelper.php index db0e2e3e..72632251 100644 --- a/app/Helpers/ChatbotHelper.php +++ b/app/Helpers/ChatbotHelper.php @@ -32,7 +32,7 @@ class ChatbotHelper $client_branch_id = $chat_session_info['client_branch_id']; $relationship ='Self'; $EmployeeModel = new EmployeeModel(); - return $EmployeeModel->getEmpFamilybyEmpCode(emp_code: $emp_code,client_id: $client_id,emp_status: ['active'],policy_status:['active'],client_branch_id:[ $client_branch_id ],relationship:[$relationship]);//,relationship:[$relationship]; + return $EmployeeModel->getEmpFamilybyEmpCode(emp_code: $emp_code,client_id: $client_id,emp_status: ['active'],policy_status:['active'],client_branch_id:[ $client_branch_id ],relationship:[$relationship],policy_type_id:[2,3,4,5]);//,relationship:[$relationship]; } public static function getHospitalLink($emp_policy_id){ diff --git a/app/Models/EmployeeModel.php b/app/Models/EmployeeModel.php index 1bc55f06..1416c082 100755 --- a/app/Models/EmployeeModel.php +++ b/app/Models/EmployeeModel.php @@ -106,9 +106,9 @@ class EmployeeModel extends Model } - public function getEmpFamilybyEmpCode(string $client_policy_id = null,string $emp_code = null,string $client_id = null,array $emp_status = [],array $policy_status = [],array $relationship = [],array $client_branch_id = []) + public function getEmpFamilybyEmpCode(string $client_policy_id = null,string $emp_code = null,string $client_id = null,array $emp_status = [],array $policy_status = [],array $relationship = [],array $client_branch_id = [],array $policy_type_id = []) { - $result = $this->select(['employees.id as emp_id', 'employees.client_id','employees.client_branch_id', 'employees.relationship', 'employees.relationship_code', 'employees.change_event', 'employees.emp_code', 'employees.name', 'employees.email_personal', 'employees.email_corporate', 'employees.mobile', 'employees.gender', 'employees.dob', 'employees.doj', 'employees.basic_pay', 'employees.band', 'employees.designation', 'employees.emp_status','employees.unit','employees.file_id','employee_polices.id as emp_policy_id', 'employee_polices.employee_id', 'employee_polices.client_policy_id', 'employee_polices.tpa_id', 'employee_polices.uhid', 'employee_polices.batch_code', 'employee_polices.status', 'employee_polices.pre_existing_alignments', 'employee_polices.basic_cover_si', 'employee_polices.date_coverage', 'employee_polices.policy_end_date', 'employee_polices.days', 'employee_polices.premium', 'employee_polices.rata_premimum', 'employee_polices.gst', 'employee_polices.date_of_exit', 'employee_polices.reason_for_exit','policy_type.long_name as policy_name','client_policy.is_addon', 'employee_polices.payable_employee','employee_polices.rand_string','employee_polices.claim_status']) + $result = $this->select(['employees.id as emp_id', 'employees.client_id','employees.client_branch_id', 'employees.relationship', 'employees.relationship_code', 'employees.change_event', 'employees.emp_code', 'employees.name', 'employees.email_personal', 'employees.email_corporate', 'employees.mobile', 'employees.gender', 'employees.dob', 'employees.doj', 'employees.basic_pay', 'employees.band', 'employees.designation', 'employees.emp_status','employees.unit','employees.file_id','employee_polices.id as emp_policy_id', 'employee_polices.employee_id', 'employee_polices.client_policy_id', 'employee_polices.tpa_id', 'employee_polices.uhid', 'employee_polices.batch_code', 'employee_polices.status', 'employee_polices.pre_existing_alignments', 'employee_polices.basic_cover_si', 'employee_polices.date_coverage', 'employee_polices.policy_end_date', 'employee_polices.days', 'employee_polices.premium', 'employee_polices.rata_premimum', 'employee_polices.gst', 'employee_polices.date_of_exit', 'employee_polices.reason_for_exit','policy_type.long_name as policy_name','client_policy.policy_type_id','client_policy.is_addon', 'employee_polices.payable_employee','employee_polices.rand_string','employee_polices.claim_status']) ->join('employee_polices', 'employee_polices.employee_id = employees.id') ->join('client_policy', 'client_policy.id = employee_polices.client_policy_id') ->join('policy_type', 'policy_type.id = client_policy.policy_type_id','left') @@ -135,6 +135,9 @@ class EmployeeModel extends Model }) ->when(count($policy_status), function($query) use ($policy_status){ return $query->whereIn('employee_polices.status', $policy_status); + }) + ->when(count($policy_type_id), function($query) use ($policy_type_id){ + return $query->whereIn('client_policy.policy_type_id', $policy_type_id); }) ->when($client_id, function($query) use ($client_id){ return $query->where('employees.client_id',$client_id); From 356f8a613a8c05caf25cc4d416a2d137702de7cd Mon Sep 17 00:00:00 2001 From: "venkatesh.r" Date: Thu, 9 Oct 2025 15:02:26 +0530 Subject: [PATCH 03/17] FIX_EXPORT_DEFAULT_VALUE_EMPTY --- app/Helpers/excel_import_export_helper.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Helpers/excel_import_export_helper.php b/app/Helpers/excel_import_export_helper.php index 9c72c973..c7ba2982 100755 --- a/app/Helpers/excel_import_export_helper.php +++ b/app/Helpers/excel_import_export_helper.php @@ -666,12 +666,12 @@ if(!function_exists('generate_insurer_based_excel')){ foreach ($excel_header_array as $header) { $fieldName = $header['db_column_name']; - $defaultValue = isset($header['default_value']) ? $header['default_value'] : null; + $defaultValue = isset($header['default_value']) ? $header['default_value'] : ""; if ($fieldName === 'index') { $value = $serialNumber; } else { - if(empty($fieldName) && !empty($defaultValue)){ + if(empty($fieldName) && $defaultValue != ""){ $value = $defaultValue; }else{ $value = $row->$fieldName ?? ''; From f09da24406e58744652fb3fbb1aca43004627a89 Mon Sep 17 00:00:00 2001 From: velz Date: Thu, 9 Oct 2025 15:50:20 +0530 Subject: [PATCH 04/17] FIX_CHATBOT_TYPES --- app/Controllers/Chatbot/EcardDownloadConversation.php | 2 +- app/Controllers/ChatbotControllerNew.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Controllers/Chatbot/EcardDownloadConversation.php b/app/Controllers/Chatbot/EcardDownloadConversation.php index d0b0f08d..e0d63294 100644 --- a/app/Controllers/Chatbot/EcardDownloadConversation.php +++ b/app/Controllers/Chatbot/EcardDownloadConversation.php @@ -14,7 +14,7 @@ class EcardDownloadConversation extends Conversation public function run() { $this->bot->types(); - sleep(0.5); + // sleep(0.5); $this->showEcardMenu(); } diff --git a/app/Controllers/ChatbotControllerNew.php b/app/Controllers/ChatbotControllerNew.php index 67d31c37..8b0a979b 100644 --- a/app/Controllers/ChatbotControllerNew.php +++ b/app/Controllers/ChatbotControllerNew.php @@ -111,7 +111,7 @@ class ChatbotControllerNew extends BaseController log_message("error","Inside Bot Type Function"); $bot->types(); // Typing indicator for the first message - sleep(0.1); // Delay + // sleep(0.5); // Delay }); // Start the Main Menu when user says "hi" or "start" $this->botman->hears('start|hi|hello|help|help me', function (BotMan $bot) { From 3e13091b34b8ebe927133840aa43e3b230a62a17 Mon Sep 17 00:00:00 2001 From: vadivelJ96 Date: Thu, 9 Oct 2025 16:56:16 +0530 Subject: [PATCH 05/17] CHANGE_Post_app_having_pre_branch_id - VADIVEL J 2025-09-10 --- app/Config/Routes.php | 1 + app/Controllers/ClientController.php | 123 ++++++++++++++-- app/Controllers/TestingController.php | 198 ++++++++++++++++++++++---- app/Views/client_branch.php | 12 +- 4 files changed, 291 insertions(+), 43 deletions(-) diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 9996931c..61aea374 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -700,6 +700,7 @@ $routes->group('test', function($routes) { $routes->get('viewrfq', 'TestingController::viewRFQNonEb'); $routes->get('exportexcel', 'TestingController::exportExcel'); $routes->post('saverfq', 'TestingController::saverfq'); + $routes->get('mapping_client_id_and_branch_id','TestingController::mapping_client_id_and_branch_id'); }); $routes->cli('cli/testcli', 'TestingController::testcli'); diff --git a/app/Controllers/ClientController.php b/app/Controllers/ClientController.php index 9baf11cd..8d3b8063 100755 --- a/app/Controllers/ClientController.php +++ b/app/Controllers/ClientController.php @@ -1098,14 +1098,47 @@ class ClientController extends AdminController } $data['created_by'] = get_session_userid(); + + + // before updating check if pre_branch_id is already existing in the current db + + if(isset($data['pre_branch_id']) && !empty($data['pre_branch_id'])) + { + $existing_pre_branch = $this->clientBranchModel + ->where('pre_branch_id',$data['pre_branch_id']) + //->where('id !=',$post_branch_id) + ->first(); + + if($existing_pre_branch) + { + return $this->respond([ + 'status' => false, + 'code' => 409, + 'message' => 'The pre branch id '.$data['pre_branch_id'].' is already mapped with another branch. Please check.', + ], 409); + } + } + + + $insert = $this->clientBranchModel->insert($data); + $post_branch_id = $insert; + if ($insert) { $level_contact_data = $this->request->getPost('level_contect_data'); $level_contact_data = !empty($level_contact_data) ? json_decode($level_contact_data, true) : null; $this->saveLevelContacts($level_contact_data, $insert); } + if($post_branch_id && isset($data['pre_branch_id']) && !empty($data['pre_branch_id'])) + { + // need to update the client_branch in the pre + $result = $this->updatePreClientBranch($data['pre_branch_id'],$post_branch_id , "create"); + + log_message('error','Pre client_branch update result for pre_branch_id '.$data['pre_branch_id'].' and post_branch_id '.$post_branch_id.' is '.json_encode($result)); + } + if ($insert) { $branchData = $this->clientBranchModel->where('client_id', $this->request->getPost('client_id'))->findAll(); $branchData['role'] = get_role_id(); @@ -1130,7 +1163,11 @@ class ClientController extends AdminController $this->myLogger->logme('error', 'Client branch EDIT function called'); $id = $this->request->getPost('branch_id_primarykey'); $client_id = $this->request->getPost('client_id'); + $pre_branch_id = $this->request->getPost('pre_branch_id') ?? ''; + $data = $this->request->getPost(); + $data['pre_branch_id'] = $pre_branch_id; + $units = $this->request->getPost('units'); $emp_unit_count = 0; @@ -1189,7 +1226,41 @@ class ClientController extends AdminController } $data['updated_by'] = get_session_userid(); + + $post_branch_id = $id; + + // before updating check if pre_branch_id is already existing in the current db + + if(isset($data['pre_branch_id']) && !empty($data['pre_branch_id'])) + { + $existing_pre_branch = $this->clientBranchModel + ->where('pre_branch_id',$data['pre_branch_id']) + ->where('id !=',$post_branch_id) + ->first(); + + if($existing_pre_branch) + { + return $this->respond([ + 'status' => false, + 'code' => 409, + 'message' => 'The pre branch id '.$data['pre_branch_id'].' is already mapped with another branch. Please check.', + ], 409); + } + } + $insert = $this->clientBranchModel->update($id, $data); + + + + if($post_branch_id && isset($data['pre_branch_id']) && !empty($data['pre_branch_id'])) + { + // need to update the client_branch in the pre + $result = $this->updatePreClientBranch($data['pre_branch_id'],$post_branch_id , "update"); + + log_message('error','Pre client_branch update result for pre_branch_id '.$data['pre_branch_id'].' and post_branch_id '.$post_branch_id.' is '.json_encode($result)); + } + + $this->myLogger->logme('error', 'Client branch EDITED by {data}', ['data' => get_session_userid()]); @@ -7107,9 +7178,15 @@ class ClientController extends AdminController $post_branch_id = $value['post_branch_id']; $post_hr_id = $value['post_hr_id']; - $value['pre_client_id'] = $this->getPreClientId($post_branch_id); - $value['pre_branch_id'] = $this->getPreBranchId($post_branch_id); - $value["pre_hr_id"] = $this->getPreHrId($post_branch_id); + $preBranchId = $this->getPreBranchIdByPostBranchId($post_branch_id); + + if (!empty($preBranchId)) { + $value['pre_branch_id'] = $preBranchId; + $value['pre_client_id'] = $this->getPreClientIdByPreBranchId($preBranchId); + $value["pre_hr_id"] = $this->getPreHrIdByPreBranchId($preBranchId); + } + + // INSERT or UPDATE if (empty($value['pk']) || (int)$value['pk'] === 0) { @@ -7176,26 +7253,28 @@ class ClientController extends AdminController } } - private function getPreClientId($post_branch_id){ + private function getPreClientIdByPreBranchId($pre_branch_id){ $db2 = \Config\Database::connect('preDB'); - $pre_client_id = $db2->table('client_branch')->where('post_branch_id',$post_branch_id)->where('is_Active',1)->get()->getResultArray()[0]['client_id']??[]; + $pre_client_id = $db2->table('client_branch')->where('id',$pre_branch_id)->where('is_Active',1)->get()->getResultArray()[0]['client_id']??""; return $pre_client_id; } - private function getPreBranchId($post_branch_id){ - $db2 = \Config\Database::connect('preDB'); - $pre_branch_id = $db2->table('client_branch')->where('post_branch_id',$post_branch_id)->where('is_Active',1)->get()->getResultArray()[0]['id']??[]; - return $pre_branch_id; - } - private function getPreHrId($post_branch_id){ + private function getPreHrIdByPreBranchId($pre_branch_id){ $db2 = \Config\Database::connect('preDB'); $pre_hr_id = $db2->table('client_branch cb') ->select('lc.id') ->join('level_contacts lc','lc.ref_id = cb.id') - ->where('post_branch_id',$post_branch_id)->where('is_Active',1)->get()->getResultArray()[0]['id']??[]; + ->where('cb.id',$pre_branch_id)->where('cb.is_Active',1)->where('lc.is_Active',1)->get()->getResultArray()[0]['id']??""; return $pre_hr_id; } + private function getPreBranchIdByPostBranchId($post_branch_id){ + $db2 = \Config\Database::connect(); + $pre_branch_id = $db2->table('client_branch')->where('id',$post_branch_id)->where('is_Active',1)->get()->getResultArray()[0]['pre_branch_id']??""; + return $pre_branch_id; + } + + // ------------------- DEMO CLIENT FUNCTION -------------------------------------------------------------------------------- public function wipeDemoClient() @@ -7584,6 +7663,26 @@ class ClientController extends AdminController } + private function updatePreClientBranch($pre_branch_id,$post_branch_id ,$operation) + { + + + + $preDB = \Config\Database::connect('preDB'); + + if($operation != 'create'){ + + $builder = $preDB->table('client_branch'); + $builder->where('post_branch_id', $post_branch_id); + $builder->update(['post_branch_id' => null]); + } + + $builder = $preDB->table('client_branch'); + $builder->where('id', $pre_branch_id); + $builder->update(['post_branch_id' => $post_branch_id]); + + return true; + } diff --git a/app/Controllers/TestingController.php b/app/Controllers/TestingController.php index 87310adc..7f8bc7d3 100644 --- a/app/Controllers/TestingController.php +++ b/app/Controllers/TestingController.php @@ -20,7 +20,7 @@ class TestingController extends BaseController { $this->myLogger = \Config\Services::mylogger(); } - + public function saveForm() { // Get JSON input @@ -35,7 +35,7 @@ class TestingController extends BaseController } public function testcli() - { + { echo "hi"; $this->myLogger->logme('error', "test log"); echo "hi 2"; @@ -79,19 +79,19 @@ class TestingController extends BaseController $options->set('debugLayoutBlocks', false); $options->set('debugLayoutInline', false); $options->set('debugLayoutPaddingBox', false); - + // Initialize DomPDF $dompdf = new Dompdf($options); - + // Load HTML content $dompdf->loadHtml($html); - + // Set paper size and orientation $dompdf->setPaper('A4', 'landscape'); // or 'portrait' - + // Render PDF $dompdf->render(); - + // Output PDF to browser $filename = 'ecard_' . date('Y-m-d_H-i-s') . '.pdf'; $dompdf->stream($filename, ['Attachment' => true]); // Set to false for inline view @@ -111,7 +111,7 @@ class TestingController extends BaseController 'POLICY_DATE' => '31/12/2024', 'INSURER_NAME' => 'ZURICH KOTAK GTNERAL INSURANCE COIIPANY lNDlA LIMITED', 'TPA_NAME' => 'HealthIndia Insurance TPA Services Pvt. Ltd.', - 'FRONT_CARD' => base_url() .('public/uploads/template_bg/Nhance_Ecard_working_1_front_3.png'), + 'FRONT_CARD' => base_url() . ('public/uploads/template_bg/Nhance_Ecard_working_1_front_3.png'), 'BACK_CARD' => base_url() . ('public/uploads/template_bg/Nhance_Ecard_working_1_Back_3.png'), 'LEVELS' => 'Level 1: 1800-XXX-XXXX
Level 2: support@company.com' ]; @@ -127,7 +127,7 @@ class TestingController extends BaseController 'POLICY_DATE' => '31/12/2024', 'INSURER_NAME' => 'ABC Insurance Co.', 'TPA_NAME' => 'XYZ TPA Ltd.', - 'FRONT_CARD' => base_url() .('public/uploads/template_bg/Nhance_Ecard_working_1_front_3.png'), + 'FRONT_CARD' => base_url() . ('public/uploads/template_bg/Nhance_Ecard_working_1_front_3.png'), 'BACK_CARD' => base_url() . ('public/uploads/template_bg/Nhance_Ecard_working_1_Back_3.png'), 'LEVELS' => 'Level 1: 1800-XXX-XXXX
Level 2: support@company.com' ]; @@ -157,12 +157,12 @@ class TestingController extends BaseController { // Load your HTML template $template = file_get_contents(WRITEPATH . 'e_card_template/common.html'); - + // Replace placeholders with actual data foreach ($data as $key => $value) { $template = str_replace('{' . $key . '}', $value, $template); } - + return $template; } @@ -225,21 +225,21 @@ class TestingController extends BaseController $employeePolicy = new EmployeePolicyModel(); $data = $employeePolicy - ->select('client_policy.policy_type_id') - ->join('employees', 'employee_polices.employee_id = employees.id') - ->join('client_policy', 'employee_polices.client_policy_id = client_policy.id') - ->where('employees.is_active', 1) - ->where('employees.emp_status', ['active', 'expired']) - ->where('employee_polices.is_active', 1) - ->where('employee_polices.status', ['active', 'expired']) - ->where('employees.client_id', $client_id) - ->where('employees.emp_code', $emp_code) - ->groupBy('employee_polices.client_policy_id') - ->findAll(); - + ->select('client_policy.policy_type_id') + ->join('employees', 'employee_polices.employee_id = employees.id') + ->join('client_policy', 'employee_polices.client_policy_id = client_policy.id') + ->where('employees.is_active', 1) + ->where('employees.emp_status', ['active', 'expired']) + ->where('employee_polices.is_active', 1) + ->where('employee_polices.status', ['active', 'expired']) + ->where('employees.client_id', $client_id) + ->where('employees.emp_code', $emp_code) + ->groupBy('employee_polices.client_policy_id') + ->findAll(); } - public function ptedfitdata($id){ + public function ptedfitdata($id) + { $policy_transaction = new PolicyTransactionController(); $data = $policy_transaction->getInceptionDataForEdit($id); // dd($data); @@ -249,7 +249,7 @@ class TestingController extends BaseController $dataArray = $data['pt_co_share_details']; // Example $cd_ac_pk = 'CD12345'; $role_id = 1; - $team_id = ['6']; + $team_id = ['6']; $insurer_branch = $insurer_branch; return view('pt_calc_table', [ @@ -315,7 +315,7 @@ class TestingController extends BaseController } public function viewRFQNonEb() - { + { $insurerBranchModel = new InsurerBranchModel(); $data['page_name'] = "RFQ NON EB"; $data['insurer'] = $insurerBranchModel->getInsurerBranchesWithInsurerNames(); @@ -323,7 +323,8 @@ class TestingController extends BaseController return $this->loadLayout('view_rfq_non_eb_new', $data); } - public function saverfq(){ + public function saverfq() + { $json = $this->request->getPost('json'); $json = json_encode($json); print_r($json); @@ -342,8 +343,147 @@ class TestingController extends BaseController // print_rr($policy_data['json']); die; $policy_data = json_decode($policy_data['json'], true); $policy_data = array_slice($policy_data, 0, -2); - print_rr($policy_data); die; - dd($policy_data); + print_rr($policy_data); + die; + dd($policy_data); } + + public function mapping_client_id_and_branch_id() + { + + $post_clients_list = $this->getNonDuplicatePostClients(); + + $pre_clients_list = $this->getNonDuplicatePreClients(); + + + + if ( + !empty($pre_clients_list) && + !empty($post_clients_list) + ) { + + $postDB = \Config\Database::connect(); + $preDB = \Config\Database::connect('preDB'); + + foreach ($post_clients_list as $post_client) { + + foreach ($pre_clients_list as $pre_client) { + + if (trim($post_client['short_name']) == trim($pre_client['short_name'])) { + + $postDB->table('clients')->where('id', $post_client['id'])->update(['pre_client_id' => $pre_client['id']]); + + $preDB->table('clients')->where('id', $pre_client['id'])->update(['post_client_id' => $post_client['id']]); + + // upto here we updated client_id in both dbs. + + $post_branches = $postDB->table('client_branch') + ->where('client_id', $post_client['id']) + ->get() + ->getResultArray() ?? []; + + $pre_branches = $preDB->table('client_branch') + ->where('client_id', $pre_client['id']) + ->get() + ->getResultArray() ?? []; + + if (!empty($post_branches) && !empty($pre_branches)) { + + + foreach ($post_branches as $post_branch) { + + $pre_branch = $preDB->table('client_branch') + ->where('client_id', $pre_client['id']) + ->where('branch_code', $post_branch['branch_code']) + ->get() + ->getRowArray() ?? []; + + if (!empty($pre_branch)) { + $postDB->table('client_branch')->where('id', $post_branch['id'])->update(['pre_branch_id' => $pre_branch['id']]); + } + } + + foreach ($pre_branches as $pre_branch) { + + $post_branch = $postDB->table('client_branch') + ->where('client_id', $post_client['id']) + ->where('branch_code', $pre_branch['branch_code']) + ->get() + ->getRowArray() ?? []; + + if (!empty($post_branch)) { + $preDB->table('client_branch')->where('id', $pre_branch['id'])->update(['post_branch_id' => $post_branch['id']]); + } + } + } + } + } + } + } + } + + + private function getNonDuplicatePostClients() + { + + + $postDB = \Config\Database::connect(); + + $sql = "SELECT * + FROM clients AS post_clients + WHERE post_clients.client_type = 1 + AND post_clients.is_active = 1 + AND (post_clients.short_name NOT IN + ( + SELECT ir_post_clients.short_name + FROM clients as ir_post_clients + WHERE ir_post_clients.client_type = 1 + AND ir_post_clients.short_name IS NOT NULL + AND TRIM(ir_post_clients.short_name) <> '' + AND ir_post_clients.is_active = 1 + GROUP BY ir_post_clients.short_name + HAVING COUNT(*) > 1) + ) + ORDER BY post_clients.short_name"; + + $binds = []; + + $query = $postDB->query($sql, $binds); + + $results = $query->getResultArray() ?? []; + + return $results; + } + + private function getNonDuplicatePreClients() + { + + $preDB = \Config\Database::connect('preDB'); + + $sql = "SELECT * + FROM clients AS pre_clients + WHERE pre_clients.client_type = 1 + AND pre_clients.is_active = 1 + AND (pre_clients.short_name NOT IN + ( + SELECT ir_pre_clients.short_name + FROM clients as ir_pre_clients + WHERE ir_pre_clients.client_type = 1 + AND ir_pre_clients.short_name IS NOT NULL + AND TRIM(ir_pre_clients.short_name) <> '' + AND ir_pre_clients.is_active = 1 + GROUP BY ir_pre_clients.short_name + HAVING COUNT(*) > 1) + ) + ORDER BY pre_clients.short_name"; + + $binds = []; + + $query = $preDB->query($sql, $binds); + + $results = $query->getResultArray() ?? []; + + return $results; + } } diff --git a/app/Views/client_branch.php b/app/Views/client_branch.php index 940cf017..7b30c166 100755 --- a/app/Views/client_branch.php +++ b/app/Views/client_branch.php @@ -86,13 +86,18 @@
+ + + + + - + - +
@@ -479,6 +484,9 @@ $("#branch_form").submit(function(event) { $('.loader').fadeOut(); $('.loader-mask').delay(350).fadeOut('slow'); console.log('Something Wrong!', 'warning'); + if(xhr.status == 409){ + alert('The Current Branch is Already Existing..!!'); + } }, 300); }, complete: function() { From df84cbba14d4490697dfe03478787e8d8c81955e Mon Sep 17 00:00:00 2001 From: vadivelJ96 Date: Thu, 9 Oct 2025 17:14:02 +0530 Subject: [PATCH 06/17] CHANGE_Post_app_having_pre_branch_id - VADIVEL J 2025-10-09 --- app/Controllers/ClientController.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Controllers/ClientController.php b/app/Controllers/ClientController.php index 36b62d05..63ddac11 100755 --- a/app/Controllers/ClientController.php +++ b/app/Controllers/ClientController.php @@ -1137,7 +1137,7 @@ class ClientController extends AdminController return $this->respond([ 'status' => false, 'code' => 409, - 'message' => 'The pre branch id '.$data['pre_branch_id'].' is already mapped with another branch. Please check.', + 'message' => 'The branch is already mapped with another branch. Please check.', ], 409); } } @@ -1266,7 +1266,7 @@ class ClientController extends AdminController return $this->respond([ 'status' => false, 'code' => 409, - 'message' => 'The pre branch id '.$data['pre_branch_id'].' is already mapped with another branch. Please check.', + 'message' => 'The branch is already mapped with another branch. Please check.', ], 409); } } @@ -7202,7 +7202,7 @@ class ClientController extends AdminController $post_hr_id = $value['post_hr_id']; $preBranchId = $this->getPreBranchIdByPostBranchId($post_branch_id); - + if (!empty($preBranchId)) { $value['pre_branch_id'] = $preBranchId; $value['pre_client_id'] = $this->getPreClientIdByPreBranchId($preBranchId); From 51b74549ac330581e55812cd66a8903be5026ff6 Mon Sep 17 00:00:00 2001 From: vadivelJ96 Date: Thu, 9 Oct 2025 17:56:09 +0530 Subject: [PATCH 07/17] CHANGE_UI_FIX - VADIVEL J 2025-10-09 --- app/Views/client_onboarding.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/Views/client_onboarding.php b/app/Views/client_onboarding.php index 567fc409..4b6693ed 100755 --- a/app/Views/client_onboarding.php +++ b/app/Views/client_onboarding.php @@ -418,7 +418,7 @@
- @@ -434,7 +434,7 @@
- @@ -1156,4 +1156,10 @@ }) + + + $(function() { + $('.select2').select2(); + }); + \ No newline at end of file From 11bef9921f68fa8f761b72e5b7f049ff1bc25122 Mon Sep 17 00:00:00 2001 From: vadivelJ96 Date: Thu, 9 Oct 2025 20:28:57 +0530 Subject: [PATCH 08/17] CHANGE_UI_FIX - VADIVEL J 2025-10-09 --- app/Views/client_onboarding.php | 62 ++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/app/Views/client_onboarding.php b/app/Views/client_onboarding.php index 4b6693ed..70b8e3b5 100755 --- a/app/Views/client_onboarding.php +++ b/app/Views/client_onboarding.php @@ -1043,38 +1043,47 @@ \ No newline at end of file From bbbd968431b37bfeb21e9e0f6fda7d105856cf88 Mon Sep 17 00:00:00 2001 From: vadivelJ96 Date: Fri, 10 Oct 2025 09:48:06 +0530 Subject: [PATCH 09/17] CHANGE_UI_FIX - VADIVEL J 2025-10-10 --- app/Views/client_onboarding.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/Views/client_onboarding.php b/app/Views/client_onboarding.php index 70b8e3b5..b27a9673 100755 --- a/app/Views/client_onboarding.php +++ b/app/Views/client_onboarding.php @@ -1052,6 +1052,9 @@ $('#auto_fetch_branch').html(``); + $('.loader').fadeIn(); + $('.loader-mask').fadeIn(); + $.ajax({ url: "", type: "POST", @@ -1076,6 +1079,8 @@ console.error("Error occurred:", status, error); }, complete: function() { + $('.loader').fadeOut(); + $('.loader-mask').delay(350).fadeOut('slow'); console.log("auto_fetch_client call is completed..!!"); } }); From 16e93fccccde5edcae1bed09f764d13a03a10349 Mon Sep 17 00:00:00 2001 From: vadivelJ96 Date: Fri, 10 Oct 2025 10:56:28 +0530 Subject: [PATCH 10/17] CHANGE_UI_FIX - VADIVEL J 2025-10-10 --- app/Views/client_branch.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/app/Views/client_branch.php b/app/Views/client_branch.php index f5d435b8..f11fcd7a 100755 --- a/app/Views/client_branch.php +++ b/app/Views/client_branch.php @@ -302,6 +302,7 @@ $('#btnBranchAdd').click(function() { $('#district').val(''); $('#branch_city').val(''); $('#branch_form')[0].reset(); + $('#branch_form').parsley().reset(); $('.ac').css('display', 'block'); contactCount = 1 @@ -392,8 +393,15 @@ $("#branch_form").submit(function(event) { $('.loader').fadeIn(); $('.loader-mask').fadeIn(); + + + if (branch_PrimaryKey == '') { + $('#branch_form input[name="pre_branch_id"]').val(''); + } + var formData = new FormData($('#branch_form')[0]); + const jsonString = JSON.stringify(selectedValues); const level_contect_data_json_string = JSON.stringify(level_contect_data); console.log('jsonString', jsonString); @@ -484,7 +492,7 @@ $("#branch_form").submit(function(event) { $('.loader').fadeOut(); $('.loader-mask').delay(350).fadeOut('slow'); console.log('Something Wrong!', 'warning'); - if(xhr.status == 409){ + if(xhr.status === 409){ alert('The Current Branch is Already Existing..!!'); } }, 300); @@ -554,7 +562,7 @@ $('body').on('click', '.btnBranchEdit', function() { $('#district').val(res.data.district); $('#branch_city').val(res.data.city); $('#branch_PrimaryKey').val(res.data.id); - $('#pre_branch_id').val(res.data.pre_branch_id) + $('#pre_branch_id').val(res.data.pre_branch_id??'') if(res.data.sez == 1){ $('#sez').prop('checked', true); From 148c2785647ccec3b0833fec2e8006c2133e3268 Mon Sep 17 00:00:00 2001 From: vadivelJ96 Date: Fri, 10 Oct 2025 12:29:20 +0530 Subject: [PATCH 11/17] CHANGE_UI_FIX - VADIVEL J 2025-10-10 --- app/Views/client_branch.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/app/Views/client_branch.php b/app/Views/client_branch.php index f11fcd7a..f35d5f99 100755 --- a/app/Views/client_branch.php +++ b/app/Views/client_branch.php @@ -302,7 +302,8 @@ $('#btnBranchAdd').click(function() { $('#district').val(''); $('#branch_city').val(''); $('#branch_form')[0].reset(); - $('#branch_form').parsley().reset(); + $('#branch_form').parsley().reset(); + $('#pre_branch_id').val(''); $('.ac').css('display', 'block'); contactCount = 1 @@ -393,12 +394,6 @@ $("#branch_form").submit(function(event) { $('.loader').fadeIn(); $('.loader-mask').fadeIn(); - - - if (branch_PrimaryKey == '') { - $('#branch_form input[name="pre_branch_id"]').val(''); - } - var formData = new FormData($('#branch_form')[0]); From 9e661ad4c2d2fd5bf396b8d59e91cfa05582f81a Mon Sep 17 00:00:00 2001 From: "venkatesh.r" Date: Fri, 10 Oct 2025 15:13:38 +0530 Subject: [PATCH 12/17] FIX_LIVE_ISSUE_GTLI_TERMS : RV --- app/Controllers/EmployeeRestController.php | 23 +++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/app/Controllers/EmployeeRestController.php b/app/Controllers/EmployeeRestController.php index 341bfcf2..1b7310b6 100755 --- a/app/Controllers/EmployeeRestController.php +++ b/app/Controllers/EmployeeRestController.php @@ -2868,14 +2868,14 @@ class EmployeeRestController extends AdminController }else if($ClientPolicyValue['policy_type_id'] == 6) { - $policyGroup = 'gpa'; + $policyGroup = 'other'; $data['ticket_type_id'] = 3; $data['claim_subject'] = "Claim EDLI"; $data['sum_insured_label'] = "Sum Assured"; }else if($ClientPolicyValue['policy_type_id'] == 7) { - $policyGroup = 'gpa'; + $policyGroup = 'other'; $data['ticket_type_id'] = 4; $data['claim_subject'] = "Claim GTLI"; $data['sum_insured_label'] = "Sum Assured"; @@ -2969,9 +2969,6 @@ class EmployeeRestController extends AdminController function policyTermsFiter($terms , $type) { - - - $gpa = [ "sumInsured2" => "Sum Insured", "totalSumInsured" => "Total Sum Assured", @@ -3021,8 +3018,6 @@ class EmployeeRestController extends AdminController "moderntreatmentsasperirdai" => "Modern Treatment " ]; - - $finalarray = []; if($type == 'gpa'){ foreach ($gpa as $key => $value) { @@ -3046,6 +3041,18 @@ class EmployeeRestController extends AdminController $finalarray[$terms->gpa_special_condition_label[$i]] = $terms->gpa_special_condition_input[$i]; } } + }else if($type == 'other'){ + foreach ($terms as $key => $value) { + if($key != "multiple_sum_insured" && $value != ""){ + $result = ucwords(str_replace('_', ' ', $key)); + $finalarray[$result] = $value; + } + } + if(isset(($terms->gpa_special_condition_label)) && is_array($terms->gpa_special_condition_label) && is_array($terms->gpa_special_condition_input)){ + for ($i=0; $i < count($terms->gpa_special_condition_label); $i++) { + $finalarray[$terms->gpa_special_condition_label[$i]] = $terms->gpa_special_condition_input[$i]; + } + } }else{ foreach ($gmc as $key => $value) { if(isset($terms->$key)) @@ -3070,9 +3077,7 @@ class EmployeeRestController extends AdminController } } - return $finalarray; - } From 2dc2447fb6232d83f47d3ac1202a2a81ab58b221 Mon Sep 17 00:00:00 2001 From: venba-Inspriron-3558 Date: Fri, 10 Oct 2025 18:58:15 +0530 Subject: [PATCH 13/17] FIX_75. The system should allow the same HR contact to be linked with different corporates, instead of restricting them to just one. --- app/Config/Routes.php | 1 + app/Controllers/ClientController.php | 9 +++++ app/Models/ClientModel.php | 13 +++++++ app/Views/client_branch.php | 53 +++++++++++++++++++++++++++- 4 files changed, 75 insertions(+), 1 deletion(-) diff --git a/app/Config/Routes.php b/app/Config/Routes.php index d640d843..10fb373c 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -172,6 +172,7 @@ $routes->group("/client", ["filter" => "authMVC"], function ($routes) { $routes->group("others", ["filter" => "authMVC"], function ($routes) { $routes->post("create", "ClientController::createOtherTabContent"); + $routes->post('check-duplicate', 'ClientController::validateDuplicateByClientBranch'); }); }); diff --git a/app/Controllers/ClientController.php b/app/Controllers/ClientController.php index 63ddac11..fb0c5d6f 100755 --- a/app/Controllers/ClientController.php +++ b/app/Controllers/ClientController.php @@ -132,6 +132,15 @@ class ClientController extends AdminController //-------------------------------------------------------------------------------------------------------- + public function validateDuplicateByClientBranch() + { + $request = service('request'); + $value = $request->getPost('value'); + $clientId = $request->getPost('client_id'); + $branchId = $request->getPost('branch_id'); + $isDuplicate = $this->clientModel->isDuplicateByClientBranch($value, $clientId, $branchId); + return $this->response->setJSON(['isDuplicate' => $isDuplicate]); + } public function checkDuplicateTableFieldValue() { $table = $this->request->getPost('table'); diff --git a/app/Models/ClientModel.php b/app/Models/ClientModel.php index 9abe8929..09db986d 100755 --- a/app/Models/ClientModel.php +++ b/app/Models/ClientModel.php @@ -226,5 +226,18 @@ class ClientModel extends Model return $result; } + public function isDuplicateByClientBranch($email, $clientId, $branchId) + { + $builder = $this->db->table('level_contacts lc') + ->select('lc.id') + ->join('client_branch cb', 'lc.ref_id = cb.id', 'left') + ->where('lc.email', $email) + ->where('lc.contact_type', 'client') + ->where('cb.client_id', $clientId) + ->where('lc.ref_id', $branchId) + ->get(); + + return $builder->getNumRows() > 0 ? true : false; + } } diff --git a/app/Views/client_branch.php b/app/Views/client_branch.php index f35d5f99..4db64b3b 100755 --- a/app/Views/client_branch.php +++ b/app/Views/client_branch.php @@ -649,7 +649,7 @@ function appendContactHtml(contact = false, reset = false) {
- +
@@ -972,6 +972,57 @@ function validateInput(input, table, field, submitButId){ } +function validateDuplicateByClientBranch(input, submitButId) { + let value = $(input).val().trim(); + let clientId = $('#client_id_branch').val(); + let branchId = $('#branch_id_primarykey').val(); + console.log(`Ln968 cId: ${clientId} | bId: ${branchId}`); + + // Don't forgot be careful + // 1 Local duplication check (User entered) + let isLocalDuplicate = false; + $('input[name="email[]"]').each(function() { + if (this !== input && $(this).val().trim() === value && value !== '') { + isLocalDuplicate = true; + return false; // break loop + } + }); + + if (isLocalDuplicate) { + console.log(`r u n Local`); + toastr.warning("Email is duplicate!", 'WARNING'); + $('#' + submitButId).prop('disabled', true); + return; // don’t call server if duplicate in UI + } + + // Don't forgot be careful + // 2 Server-side duplicate check (DB) + if (!isLocalDuplicate && value !== '') { + console.log(`r u n Server`); + $.ajax({ + url: '', + type: 'POST', + data: { + client_id: clientId, + branch_id: branchId, + value: value + }, + dataType: 'json', + success: function(response) { + if (response.isDuplicate) { + toastr.warning("Email already exists!", 'WARNING'); + $('#' + submitButId).prop('disabled', true); + } else { + $('#' + submitButId).prop('disabled', false); + } + }, + error: function(xhr, status, error) { + console.error('AJAX Error:', error); + } + }); + } +} + function getContactsData() { const contacts = []; From d0c7ea1143502251bbdb7e1ad5f05c201f4235bf Mon Sep 17 00:00:00 2001 From: venba-Inspriron-3558 Date: Sat, 11 Oct 2025 12:00:29 +0530 Subject: [PATCH 14/17] FIX_resolved - Email duplication based on ClientBrach vvj reported --- app/Views/client_branch.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Views/client_branch.php b/app/Views/client_branch.php index 4db64b3b..024c3741 100755 --- a/app/Views/client_branch.php +++ b/app/Views/client_branch.php @@ -198,7 +198,7 @@
+ name="email[]" id="email" data-parsley-trigger="change" data-parsley-type="email" onkeyup="validateDuplicateByClientBranch(this, 'branchBtnSubmit')" required>
From 21310082a032c24a4b1ee5a216be878e4aabf01e Mon Sep 17 00:00:00 2001 From: "venkatesh.r" Date: Sat, 11 Oct 2025 15:32:27 +0530 Subject: [PATCH 15/17] CHANGE_EB_EXCEL_CHANGE : RV --- app/Controllers/LeadsController.php | 38 ++++-- app/Views/leads_form.php | 176 +++++++++++++++++++++++++--- app/Views/leads_form_handler.php | 1 - app/Views/rfq/gpa.php | 79 ++++++++++--- 4 files changed, 252 insertions(+), 42 deletions(-) diff --git a/app/Controllers/LeadsController.php b/app/Controllers/LeadsController.php index 40afde50..59608e7e 100644 --- a/app/Controllers/LeadsController.php +++ b/app/Controllers/LeadsController.php @@ -138,7 +138,10 @@ class LeadsController extends BaseController $this->cause_of_death = [ 'natural_death' => 'Natural Death', 'suicide' => 'Suicide', - 'accident' => 'Accident' + 'accident' => 'Accident', + 'cardiac_arrest' => 'Cardiac Arrest', + 'septic_shock' => 'Septic shock', + 'heart_attack' => 'Heart Attack', ]; $this->member_data_excel_columns = [ @@ -2408,8 +2411,11 @@ class LeadsController extends BaseController $row = 2; foreach ($claim_details['finyear'] as $record) { $col = 'A'; - foreach ($record as $value) { + foreach ($record as $array_key => $value) { $label = ucwords(str_replace('_', ' ', ($value ?? ""))); + if(in_array($array_key, ['sum_insured', 'claim_amount', 'settled'])){ + $label = formatIndianCurrency(intval($label)); + } $sheet->setCellValue($col . $row, $label); $col++; } @@ -2427,19 +2433,27 @@ class LeadsController extends BaseController } // Enable wrap text for all cells - $maxColLetter = chr(64 + count($headers)); // Last column letter - $sheet->getStyle("A2:{$maxColLetter}{$row}")->getAlignment()->setWrapText(true); + // $maxColLetter = chr(64 + count($headers)); // Last column letter + // $sheet->getStyle("A2:{$maxColLetter}{$row}")->getAlignment()->setWrapText(true); - // Optional: center vertically for neatness - $sheet->getStyle("A2:{$maxColLetter}{$row}")->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER); + // // Optional: center vertically for neatness + // $sheet->getStyle("A2:{$maxColLetter}{$row}")->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER); - // Optional: Make row height auto (helps when wrap text is on) - for ($i = 2; $i < $row; $i++) { - $sheet->getRowDimension($i)->setRowHeight(-1); - } + $maxColLetter = chr(64 + count($headers)); + $dataRange = "A1:{$maxColLetter}" . ($row - 1); - } - } + $sheet->getStyle($dataRange)->getAlignment() + ->setWrapText(true) + ->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER) + ->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER); + + // Optional: Make row height auto (helps when wrap text is on) + for ($i = 2; $i < $row; $i++) { + $sheet->getRowDimension($i)->setRowHeight(-1); + } + + } + } // Save to temporary location $uploadFilePath = WRITEPATH . 'tmp/' . $filename; diff --git a/app/Views/leads_form.php b/app/Views/leads_form.php index 12ef9a30..52902934 100644 --- a/app/Views/leads_form.php +++ b/app/Views/leads_form.php @@ -1862,6 +1862,7 @@ let claimData = []; $(".claim-row").each(function() { + let year = $(this).find("[name='first_year[]']").val(); let claimAmount = $(this).find("[name='first_claim_amount[]']").val(); let claimStatus = $(this).find("[name='first_claim_status[]']").val(); @@ -1869,13 +1870,22 @@ let causeOfDeath = $(this).find("[name='first_cause_of_death[]']").val(); let deathDate = $(this).find("[name='first_death_date[]']").val(); + let emp_id = $(this).find("[name='emp_id[]']").val(); + let emp_name = $(this).find("[name='emp_name[]']").val(); + let gender = $(this).find("[name='gender[]']").val(); + let designation = $(this).find("[name='designation[]']").val(); + let sum_insured = $(this).find("[name='sum_insured[]']").val(); + claimData.push({ "year": year, - "claim_amount": claimAmount, - "status": claimStatus, - "claim_type": claimType, + "emp_id": emp_id, + "emp_name": emp_name, + "gender": gender, + "designation": designation, + "sum_insured": sum_insured, + "death_date": deathDate, "cause_of_death": causeOfDeath, - "death_date": deathDate + "settled": claimAmount, }); }); @@ -1893,6 +1903,93 @@ //----------------------------------------------------------------------------------------------------------- + // do not remove this + // function appendThreeYearsClaims(count) { + + // // let count = $('#appendAreaForClaim').data('count'); + // console.log("count", count); + + // let policy_type_id = $('#policy_type_id_' + count).val() + // console.log('policy_type_id', policy_type_id); + + // console.log('claimIndex from parent', claimIndex); + // let increment = claimIndex; + + // let claimsFields = ` + //
+ + //
+ // + // + //
+ //
+ // + // + //
+ //
+ // + // + //
+ // + // + // + //
+ //
+ // x + // + + //
+ //
+ //
+ // `; + + // // Append new claim fields + // let referenceDiv = document.getElementById('appendAreaForClaim_' + count); + + // if (referenceDiv) { + // referenceDiv.insertAdjacentHTML('beforeend', claimsFields); + // } else { + // console.error('Element not found: appendAreaForClaim_' + count); + // } + + // // Increment claim index + // console.log("claim index " + claimIndex); + // claimIndex++; + // console.log("after claim index " + claimIndex); + + // if (policy_type_id == 1) { + // $('.gpaClaimFileds').show(); + // $('.lifeClaimFields').hide(); + // } else if (policy_type_id == 6 || policy_type_id == 7) { + // $('.gpaClaimFileds').hide(); + // $('.lifeClaimFields').show(); + // } + + // // Initialize Select2 for the newly added fields + // $("#first_year_" + increment).select2(); + // $("#claim_type_" + increment).select2(); + // $("#first_cause_of_death_" + increment).select2(); + + // toggleRequiredFields(); + // } + function appendThreeYearsClaims(count) { // let count = $('#appendAreaForClaim').data('count'); @@ -1916,15 +2013,46 @@ } ?>
+
- - + +
+ +
- - + +
-