diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 96252c3f..87e439ab 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -806,3 +806,11 @@ $routes->group('commission', function($routes) { $routes->get('checkRuleUsage',"RuleImportController::checkRuleUsage"); }); +//BDS BULK UPLOAD + +$routes->group('bds_upload', function($routes) { + $routes->match (['get','post'],'list',"PolicyTransactionController::policyBulkUpload"); + $routes->get('downloadBDSDumpFile',"PolicyTransactionController::downloadBDSDumpFile"); + $routes->get('getBdsDumpFileErrorData',"PolicyTransactionController::getBdsDumpFileErrorData"); + $routes->get('getBdsDumpExcelFileErrors/(:any)',"PolicyTransactionController::getBdsDumpExcelFileErrors/$1"); +}); diff --git a/app/Controllers/EmployeeController.php b/app/Controllers/EmployeeController.php index 0da7f5a7..eee1b16f 100755 --- a/app/Controllers/EmployeeController.php +++ b/app/Controllers/EmployeeController.php @@ -483,6 +483,8 @@ class EmployeeController extends AdminController $filePath = ROOTPATH . 'public/sample_excel/Sample_Member_Data.xlsx'; }else if ($actionType == 'all') { $filePath = ROOTPATH . 'public/sample_excel/sample_multievent_file.xlsx'; + }else if ($actionType == 'bds_upload') { + $filePath = ROOTPATH . 'public/sample_excel/sample_bds_bulk_upload_excel.xlsx'; } // Check if the file exists diff --git a/app/Controllers/JobWorker.php b/app/Controllers/JobWorker.php index eadca406..190a1058 100755 --- a/app/Controllers/JobWorker.php +++ b/app/Controllers/JobWorker.php @@ -179,6 +179,14 @@ class JobWorker extends AdminController 'type' => 'CC', // Handler Category 'handler' => 'App\Controllers\MediAssistApiController', ], + 'bdsDumpExcelFileFormatValidation' => [ + 'type' => 'CC', // Handler Category + 'handler' => 'App\Controllers\PolicyTransactionController', + ], + 'insertBulkBdsData' => [ + 'type' => 'CC', // Handler Category + 'handler' => 'App\Controllers\PolicyTransactionController', + ], ]; diff --git a/app/Controllers/MasterController.php b/app/Controllers/MasterController.php index d2ce1329..fec5dc4e 100755 --- a/app/Controllers/MasterController.php +++ b/app/Controllers/MasterController.php @@ -1980,6 +1980,7 @@ class MasterController extends AdminController 'files' => WRITEPATH . 'uploads/commission/files', 'rules' => WRITEPATH . 'uploads/commission/rules', 'claim_sample_forms' => ROOTPATH . 'public/claim_sample_forms/', + 'bds_dump_excel' => WRITEPATH . 'uploads/bds_dump_excel/', ]; foreach ($folders as $folderName => $folderPath) { diff --git a/app/Controllers/PolicyTransactionController.php b/app/Controllers/PolicyTransactionController.php index 35425655..a430f4af 100644 --- a/app/Controllers/PolicyTransactionController.php +++ b/app/Controllers/PolicyTransactionController.php @@ -37,6 +37,8 @@ use App\Helpers\MailHelper; use App\Helpers\ExcelSanitizeHelper; use App\Models\NhanceBranchModel; + use App\Models\BDSDumpModel; + use App\Models\VehicleModel; use Exception; class PolicyTransactionController extends BaseController @@ -71,6 +73,10 @@ protected $coShareStmtDetailsModel; protected $BdsPlacementModel; protected $nhanceBranchModel; + protected $bdsDumpModel; + protected $vehicleModel; + protected $bds_bulk_upload_excel_file_column; + public function __construct() { @@ -103,12 +109,439 @@ $this->coShareStmtDetailsModel = new COShareStmtDetailsModel(); $this->BdsPlacementModel = new BdsPlacementModel(); $this->nhanceBranchModel = new NhanceBranchModel(); + $this->bdsDumpModel = new BDSDumpModel(); + $this->vehicleModel = new VehicleModel(); $this->invoiceStatus = [ 'pending' => 'Pending', 'generated' => 'Generated', 'sent' => 'Sent', 'payment_received' => 'Payment
Received', ]; + + $this->bds_bulk_upload_excel_file_column = [ + + 'sno' => [ + 'col_idx' => 0, + 'col_cell_name' => 'A', + 'col_name' => 'S.No.', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'nhance_branch' => [ + 'col_idx' => 1, + 'col_cell_name' => 'B', + 'col_name' => 'Nhance Branch', + 'is_mandatory' => true, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => 'check_nhance_branch', + 'params' => ['row', 'nhance_branch_data'] + ], + + 'vehicle_no' => [ + 'col_idx' => 2, + 'col_cell_name' => 'C', + 'col_name' => 'Vehicle No', + 'is_mandatory' => true, + 'data_type' => 'vehicle', + 'format' => null, + 'allowed_values' => null, + 'custom' => 'check_rto_data', + 'params' => ['row', 'rto_master'] + ], + + 'vehicle_type' => [ + 'col_idx' => 3, + 'col_cell_name' => 'D', + 'col_name' => 'Vehicle Type', + 'is_mandatory' => true, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => 'check_vehicle_type', + 'params' => ['row', 'vehicle_type'] + ], + + 'policy_no' => [ + 'col_idx' => 4, + 'col_cell_name' => 'E', + 'col_name' => 'Policy No', + 'is_mandatory' => true, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => 'check_policy_no', + 'params' => ['row', 'pt_data'] + ], + + 'insured_name' => [ + 'col_idx' => 5, + 'col_cell_name' => 'F', + 'col_name' => 'Insured Name', + 'is_mandatory' => true, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'insured_email' => [ + 'col_idx' => 6, + 'col_cell_name' => 'G', + 'col_name' => 'Insured Email', + 'is_mandatory' => true, + 'data_type' => 'email', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'insurer' => [ + 'col_idx' => 7, + 'col_cell_name' => 'H', + 'col_name' => 'Insurer', + 'is_mandatory' => true, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => 'check_insurer_exist', + 'params' => ['row', 'insurer_data'] + ], + + 'insurer_branch' => [ + 'col_idx' => 8, + 'col_cell_name' => 'I', + 'col_name' => 'Insurer Branch', + 'is_mandatory' => true, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => 'check_insurer_branch_exist', + 'params' => ['row', 'insurer_branch_data', 'insurers'] + ], + + 'policy_issue_date' => [ + 'col_idx' => 9, + 'col_cell_name' => 'J', + 'col_name' => 'Policy Issue Date', + 'is_mandatory' => true, + 'data_type' => 'date', + 'format' => 'd/M/Y', + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'policy_start_date' => [ + 'col_idx' => 10, + 'col_cell_name' => 'K', + 'col_name' => 'Policy Start Date', + 'is_mandatory' => true, + 'data_type' => 'date', + 'format' => 'd/M/Y', + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'policy_end_date' => [ + 'col_idx' => 11, + 'col_cell_name' => 'L', + 'col_name' => 'Policy End Date', + 'is_mandatory' => true, + 'data_type' => 'date', + 'format' => 'd/M/Y', + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'revenue_type' => [ + 'col_idx' => 12, + 'col_cell_name' => 'M', + 'col_name' => 'Revenue Type', + 'is_mandatory' => true, + 'data_type' => '', + 'format' => null, + 'allowed_values' => ['NA', 'EA', 'EANR'], + 'custom' => null, + 'params' => null + ], + + 'sales_generated_by' => [ + 'col_idx' => 13, + 'col_cell_name' => 'N', + 'col_name' => 'Sales Generated By', + 'is_mandatory' => true, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => 'check_user_exist', + 'params' => ['row', 'col_key', 'user_data'] + ], + + 'serviced_by' => [ + 'col_idx' => 14, + 'col_cell_name' => 'O', + 'col_name' => 'Serviced By', + 'is_mandatory' => true, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => 'check_user_exist', + 'params' => ['row', 'col_key', 'user_data'] + ], + + 'agent_code' => [ + 'col_idx' => 15, + 'col_cell_name' => 'P', + 'col_name' => 'Agent Code', + 'is_mandatory' => true, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => 'check_agent_exist', + 'params' => ['row', 'agent_data'] + ], + + 'base_premium' => [ + 'col_idx' => 16, + 'col_cell_name' => 'Q', + 'col_name' => 'Base Premium', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'non_commission_premium_amount' => [ + 'col_idx' => 17, + 'col_cell_name' => 'R', + 'col_name' => 'Non commission permium Amount', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'tp_premium' => [ + 'col_idx' => 18, + 'col_cell_name' => 'S', + 'col_name' => 'TP Premium', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'igst' => [ + 'col_idx' => 19, + 'col_cell_name' => 'T', + 'col_name' => 'IGST', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'cgst' => [ + 'col_idx' => 20, + 'col_cell_name' => 'U', + 'col_name' => 'CGST', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'sgst' => [ + 'col_idx' => 21, + 'col_cell_name' => 'V', + 'col_name' => 'SGST', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'stamp_duty' => [ + 'col_idx' => 22, + 'col_cell_name' => 'W', + 'col_name' => 'Stamp Duty', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'total' => [ + 'col_idx' => 23, + 'col_cell_name' => 'X', + 'col_name' => 'Total', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'agreed_amount' => [ + 'col_idx' => 24, + 'col_cell_name' => 'Y', + 'col_name' => 'Agreed Amount', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'agreed_bp_percentage' => [ + 'col_idx' => 25, + 'col_cell_name' => 'Z', + 'col_name' => 'Agreed BP Percentage', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'agreed_tp_percentage' => [ + 'col_idx' => 26, + 'col_cell_name' => 'AA', + 'col_name' => 'Agreed TP Percentage', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'actual_bp_amount' => [ + 'col_idx' => 27, + 'col_cell_name' => 'AB', + 'col_name' => 'Actual BP Amount', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'actual_tp_amount' => [ + 'col_idx' => 28, + 'col_cell_name' => 'AC', + 'col_name' => 'Actual TP Amount', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'actual_bp_percentage' => [ + 'col_idx' => 29, + 'col_cell_name' => 'AD', + 'col_name' => 'Actual BP Percentage', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'actual_tp_percentage' => [ + 'col_idx' => 30, + 'col_cell_name' => 'AE', + 'col_name' => 'Actual TP Percentage', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'actual_bp_brokerage_amount' => [ + 'col_idx' => 31, + 'col_cell_name' => 'AF', + 'col_name' => 'Actual BP Brokerage Amount', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'actual_tp_brokerage_amount' => [ + 'col_idx' => 32, + 'col_cell_name' => 'AG', + 'col_name' => 'Actual TP Brokerage Amount', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'expected_amount' => [ + 'col_idx' => 33, + 'col_cell_name' => 'AH', + 'col_name' => 'Expected Amount', + 'is_mandatory' => true, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + 'rewards' => [ + 'col_idx' => 34, + 'col_cell_name' => 'AI', + 'col_name' => 'Rewards', + 'is_mandatory' => false, + 'data_type' => '', + 'format' => null, + 'allowed_values' => null, + 'custom' => null, + 'params' => null + ], + + ]; + } // Policy Transaction Inception @@ -3207,7 +3640,6 @@ return [$policyList, $policyListByClient]; } - public function reportBDSNew() { // 🧭 Basic Page Info @@ -3318,6 +3750,776 @@ $this->loadLayout('report_bds_filter', $data); } + // ------------ BDS BULK MOTER POLICY UPLOAD ----------------------------------------------------------------------------------------------- + + public function policyBulkUpload() + { + $data['page_name'] = "BDS Bulk File Upload"; + $data['tab_name'] = "BDS File Upload"; + + // $response = $this->insertBulkBdsData(['file_id' => 2]); + // dd($response); + if ($this->request->is('get')) { + + $data['bds_dump_file_data'] = $this->bdsDumpModel + ->select(' + bds_dump_files.id as file_id, + bds_dump_files.file_name, + bds_dump_files.status, + bds_dump_files.created_at, + up.first_name as user_name + ') + ->join('user_profiles as up', 'bds_dump_files.created_by = up.id', 'left') + ->where('bds_dump_files.is_active', 1) + ->orderBy('bds_dump_files.id', 'desc') + ->findAll(); + + return $this->loadLayout('bds_dump_file_list', $data); + } else { + + $filename = ''; + $fileSize = ''; + + //validate uploaded file + $validated = $this->validate([ + 'bds_dump_list' => [ + 'uploaded[bds_dump_list]', + 'mime_in[bds_dump_list,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.oasis.opendocument.spreadsheet]', + 'max_size[bds_dump_list,16384]', + ], + ]); + + if ($validated) { + $avatar = $this->request->getFile('bds_dump_list'); + if (!$avatar) { + $this->myLogger->logme("error", 'File not found'); + return $this->respond(['status' => false, 'code' => 400, 'message' => 'File not found'], 400); + } + + $is_moved = $avatar->move(WRITEPATH . 'uploads/bds_dump_excel/'); + + if ($is_moved) { + $filename = $avatar->getName(); + $fileSize = $avatar->getSize(); // File size in bytes + $fileSize = $fileSize / (1024 * 1024); // Convert to MB + + $this->myLogger->logme("error", 'File move successful'); + } else { + $this->myLogger->logme("error", 'File move failed'); + return $this->respond(['status' => false, 'code' => 500, 'message' => 'File move failed'], 500); + } + } else { + $this->myLogger->logme("error", 'Upload failed Invalid file'); + return $this->respond(['status' => false, 'code' => 404, 'message' => 'Invalid file'], 404); + } + + + $status = 'inprogress'; + $insert_data = [ + 'file_name' => $filename, + 'status' => $status + ]; + + $file_id = $this->bdsDumpModel->insert($insert_data); + $this->myLogger->logme("error", 'claim_dumb_file_id : {file_id}, uploaded success', ['file_id' => $file_id]); + + //after file upload success than call the file formate validation + // $response = $this->bdsDumpExcelFileFormatValidation(["file_id" => $file_id]); + $r = Jobs::addJob(['job_name' => 'bdsDumpExcelFileFormatValidation', 'payload' => ['file_id' => $file_id]]); + + return $this->respond(['status' => true, 'code' => 200, 'message' => 'File uploaded successfully. File being validated'], 200); + } + } + + public function downloadBDSDumpFile($file_id) + { + // $actionType = $this->request->getGet(); + $file_data = $this->bdsDumpModel->where('id', $file_id)->first(); + $fileName = $file_data['file_name']; + + $filePath = WRITEPATH . '/uploads/bds_dump_excel/' . $fileName; + + try { + + // Check if the file exists + if (file_exists($filePath)) { + // Set the appropriate MIME type + $mimeType = mime_content_type($filePath); + + // Send the file to the client for download + return $this->response->download($filePath, null, $mimeType); + } else { + + $data['message'] = 'The Physical File Not Found'; + echo view('errors/404', $data); + } + } catch (\Exception $e) { + // Handle any exceptions + $errorMessage = $e->getMessage(); + $this->myLogger->logme('error', $errorMessage); + // You can return an error response here + echo $errorMessage; + } + } + + public function bdsDumpExcelFileFormatValidation($params) + { + helper('excel_util_helper'); + $file_id = $params['file_id']; + $file = $this->bdsDumpModel->where("id", $file_id)->first(); + + $return = []; + if (empty($file)) { + return array('status' => false, 'message' => 'File not found in Database'); + } + + $file_name_with_path = WRITEPATH . "/uploads/bds_dump_excel/" . $file['file_name']; + + //check physical file exist + if (!file_exists($file_name_with_path)) { + $message = "Physcial file not found"; + $this->myLogger->logme('error', ($message . ' for file id : ' . $file_id)); + $this->bdsDumpModel->where('id', $file_id)->set(['status' => 'failed', 'reason' => json_encode(['error_summary' => array_count_values([5]), 'error_data' => $message])])->update(); + return array('error_summary' => [5], 'error_data' => $message); + } + + // get the BDS dump excel colums + $columns_to_check = $this->bds_bulk_upload_excel_file_column; + $keys = array_keys($columns_to_check); + $allowedHighestColumn = end($columns_to_check); + + // Read the excel file + $excel_data = $this->extractExcelData($file['file_name'], $allowedHighestColumn['col_cell_name']); + $excel_columns = ($excel_data[0]); + // echo '
'; var_dump($excel_columns);
+
+
+            //check no of columns in excel
+            $total_defined_columns = count($columns_to_check);
+            $excel_columns_count = count($excel_columns);
+
+            if($total_defined_columns != $excel_columns_count)
+            {
+                //columns count mismatch
+                $message = "File columns count mismatch. Expected - $total_defined_columns and received - $excel_columns_count";
+                $this->myLogger->logme('error',($message . ' for file id ' . $file_id));
+                $this->bdsDumpModel->where('id', $file_id)->set(['status' => 'failed','reason' => json_encode(['error_summary' => array_count_values([5]),'error_data' => $message])])->update();
+                return  array('error_summary' => [5], 'error_data' => $message);
+            }
+
+            //check columns order in excel
+            $column_count_res = check_columns_name($columns_to_check, $excel_columns);
+
+            if(isset($column_count_res) && count($column_count_res))
+            {   
+                //columns count mismatch
+                $message = implode("\n", $column_count_res);
+                $this->myLogger->logme('error',($message . ' for file id ' . $file_id));
+                $this->bdsDumpModel->where('id', $file_id)->set(['status' => 'failed','reason' => json_encode(['error_summary' => array_count_values([6]), 'error_data' => $message])])->update();
+                return  array('error_summary' => [6], 'error_data' => $message);
+            }
+
+            //Store the error data by this structure
+            $result = ['error_type' => 1, 'error_summary' => [], 'error_data' => []];
+
+            $insurer_data = $this->insurerModel->where('is_active', 1)->findAll();
+            $insurer_branch_data = $this->insurerBranchModel->where('is_active', 1)->findAll();
+            $pt_data = $this->policyTransactionModel->where('is_active', 1)->findAll();
+            $user_data = $this->userModel->where('is_active', 1)->findAll();
+            $agent_data = db_connect()->table('partner_agent')->where('is_active', 1)->get()->getResultArray();
+            $rto_master = db_connect()->table('rto_master')->where('is_active', 1)->get()->getResultArray();
+            $vehicle_type = db_connect()->table('vehicle_type')->where('is_active', 1)->get()->getResultArray();
+            $nhance_branch_data = db_connect()->table('nhance_branch')->where('is_active', 1)->get()->getResultArray();
+
+
+            //remove header
+            unset($excel_data[0]);
+
+            try {
+                foreach ($excel_data as $row_key => $row) {
+
+                    //avoid empty rows
+                    if (check_row_is_empty_or_null($row)) {
+                        break;
+                    }
+
+                    $insurers = [];
+                    foreach ($row as $col_key => $col) 
+                    {
+                        $is_mandatory = $columns_to_check[$keys[$col_key]]['is_mandatory'];
+                        $format = $columns_to_check[$keys[$col_key]]['format'];
+                        $data_type = $columns_to_check[$keys[$col_key]]['data_type'];
+                        $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
+                            }
+                        }
+
+                        //format check
+                        if(isset($format))
+                        {
+                            $validation = validate_excel_value($col, $data_type, $format, $allowed_values);
+                            if (!$validation['status']) {
+                                array_push($result['error_summary'], 2);
+
+                                $result['error_data'][$row_key][$keys[$col_key]]['col_name'] = $column_dispaly_name;
+                                $result['error_data'][$row_key][$keys[$col_key]]['col_idx'] = $column_index;
+                                $result['error_data'][$row_key][$keys[$col_key]]['error'][] = $validation['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); }
+                            $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']; 
+                            }
+
+                            if($res['status'] == true && isset($res['insurer'])){
+                                $insurers = $res['insurer'];
+                            }
+                            
+                        }
+
+                    }//col foreach
+
+                }
+            } catch (\Exception $e) {
+                $errorDetails = [
+                    'error_message' => $e->getMessage(),
+                    'file'          => $e->getFile(),
+                    'line'          => $e->getLine(),
+                    'stack_trace'   => $e->getTraceAsString(),
+                ];
+                $message = "Contact system admin";
+                $this->bdsDumpModel->where('id', $file_id)->set(['status' => 'failed', 'reason' => json_encode(['error_summary' => array_count_values([5]), 'error_data' => $message])])->update();
+                $this->myLogger->logme("error", 'Claim dump file format validation failed due to : ' . json_encode($errorDetails ?? []));
+                return $errorDetails;
+            }
+
+            // return $result;
+
+            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->bdsDumpModel->where('id', $file_id)->set(['status' => $status, 'reason' => $failure_reason])->update();
+                $this->myLogger->logme("error", '{file_id} uploaded failed', ['file_id' => $file_id]);
+            } else { //trigger next data validation via job queue server
+                //proceed next data level validation in JOB queue
+                $r = Jobs::addJob(['job_name' => 'insertBulkBdsData', 'payload' => ['file_id' => $file_id]]);
+                // $response = $this->insertBulkBdsData(['file_id' => $file_id]);
+            }
+
+            return $result;
+        }
+
+        public function insertBulkBdsData($params)
+        {   
+            helper('excel_util_helper');
+            $file_id = $params['file_id'];
+            $file = $this->bdsDumpModel->where("id", $file_id)->first();
+
+            $return = [];
+            if (empty($file)) {
+                return array('status' => false, 'message' => 'File not found in Database');
+            }
+
+            $file_name_with_path = WRITEPATH . "/uploads/bds_dump_excel/" . $file['file_name'];
+
+            //check physical file exist
+            if (!file_exists($file_name_with_path)) {
+                $message = "Physcial file not found";
+                $this->myLogger->logme('error', ($message . ' for file id : ' . $file_id));
+                $this->bdsDumpModel->where('id', $file_id)->set(['status' => 'failed', 'reason' => json_encode(['error_summary' => array_count_values([5]), 'error_data' => $message])])->update();
+                return  array('error_summary' => [5], 'error_data' => $message);
+            }
+
+            // get the BDS dump excel colums
+            $columns_to_check = $this->bds_bulk_upload_excel_file_column;
+            $keys = array_keys($columns_to_check);
+            $allowedHighestColumn = end($columns_to_check);
+
+            // Read the excel file
+            $excel_data = $this->extractExcelData($file['file_name'], $allowedHighestColumn['col_cell_name']);
+            $excel_columns = ($excel_data[0]);
+
+            //remove header
+            unset($excel_data[0]);
+            // dd($excel_data);
+
+            //Store the error data by this structure
+            $result = ['error_type' => 1, 'error_summary' => [], 'error_data' => []];
+
+            $client_data = $this->clientModel->where('is_active', 1)->where('client_type', 1)->findAll();
+            $insurer_data = $this->insurerModel->where('is_active', 1)->findAll();
+            $insurer_branch_data = $this->insurerBranchModel->where('is_active', 1)->findAll();
+            $vehicle_data = $this->vehicleModel->where('is_active', 1)->findAll();
+            $user_data = $this->userModel->where('is_active', 1)->findAll();
+            $agent_data = db_connect()->table('partner_agent')->where('is_active', 1)->get()->getResultArray();
+            $rto_master = db_connect()->table('rto_master')->where('is_active', 1)->get()->getResultArray();
+            $vehicle_type_data = db_connect()->table('vehicle_type')->where('is_active', 1)->get()->getResultArray();
+            $nhance_branch_data = db_connect()->table('nhance_branch')->where('is_active', 1)->get()->getResultArray();
+
+            try {
+
+                $pt_ids = [];
+                foreach ($excel_data as $row_key => $row) {
+
+                    //avoid empty rows
+                    if (check_row_is_empty_or_null($row)) {
+                        break;
+                    }
+
+                    $vehicle_number = trim($row[2]);
+                    $vehicle_type = trim($row[3]);
+                    $client_name = trim($row[5]);
+                    $client_email = trim($row[6]);
+
+                    $insurer_short_name = trim($row[7]);
+                    $insurer_branch_code = trim($row[8]);
+                    $salse_generated_by = trim($row[13]);
+                    $serviced_by = trim($row[14]);
+                    $agent_code = trim($row[15]);
+                    $nhance_branch                     = trim($row[1]);
+                    
+                    $policy_no                         = trim($row[4]);
+                    $policy_issue_date                 = trim($row[9]);
+                    $policy_start_date                 = trim($row[10]);
+                    $policy_end_date                   = trim($row[11]);
+                    $revenue_type                      = trim($row[12]);
+
+                    $base_premium                      = trim($row[16]);
+                    $non_commission_premium_amount     = trim($row[17]);
+                    $tp_premium                        = trim($row[18]);
+                    $igst                              = trim($row[19]);
+                    $cgst                              = trim($row[20]);
+                    $sgst                              = trim($row[21]);
+                    $stamp_duty                        = trim($row[22]);
+                    $total                             = trim($row[23]);
+                    $agreed_amount                     = trim($row[24]);
+                    $agreed_bp_percentage              = trim($row[25]);
+                    $agreed_tp_percentage              = trim($row[26]);
+                    $actual_bp_amount                  = trim($row[27]);
+                    $actual_tp_amount                  = trim($row[28]);
+                    $actual_bp_percentage              = trim($row[29]);
+                    $actual_tp_percentage              = trim($row[30]);
+                    $actual_bp_brokerage_amount        = trim($row[31]);
+                    $actual_tp_brokerage_amount        = trim($row[32]);
+                    $expected_amount                   = trim($row[33]);
+                    $rewards                           = trim($row[34]);
+
+                    $current_insurer_data = check_insurer_exist($row, $insurer_data)['insurer'] ?? null;
+                    $current_insurer_branch_data = check_insurer_branch_exist($row, $insurer_branch_data, $current_insurer_data)['branch'] ?? null;
+
+                    $current_nhance_branch = check_nhance_branch($row, $nhance_branch_data)['branch'] ?? null;
+                    $current_agent_data = check_agent_exist($row, $agent_data)['agent'] ?? null;
+
+                    $salse = check_user_exist($row, 13, $user_data)['user'] ?? null;
+                    $service = check_user_exist($row, 14, $user_data)['user'] ?? null;
+
+                    $gst_amt = calculate_gst_amount($row) ?? null;
+
+                    $vehicle_id = '';
+                    $client_id = '';
+                    foreach ($vehicle_data as $vehicles) {
+                       if($vehicles['vehicle_no'] == $vehicle_number){
+                            $vehicle_id = $vehicles['id'];
+                            $client_id = $vehicles['owner'];
+                       }
+                    }
+
+                    $second_stage_client_id = '';
+                    if(empty($vehicle_id) && empty($client_id)){
+                        foreach ($client_data as $clients) {
+                            if($clients['email'] == $client_email){
+                                $second_stage_client_id = $clients['id'];
+                            }
+                        }
+                    }
+
+                    if(empty($second_stage_client_id)){
+
+                        $client_insert_data = [
+                            'client_name' => $client_name,
+                            'short_name' => $client_name,
+                            'email' => $client_email,
+                            'entity_type_id' => 7,
+                            'client_type' => 2,
+                        ];
+
+                        $client_id = $this->clientModel->insert($client_insert_data);
+
+                        if($client_id){
+
+                            // Pattern: 2 letters + 2 digits
+                            // if (preg_match('/^([A-Z]{2})([0-9]{2})/i', $vehicle_number, $matches)) {
+                            //     $vehicle_state = strtoupper($matches[1]);   // TN
+                            //     $vehicle_state_code = $matches[2];          // 10
+                            // } else {
+                            //     $vehicle_state = null;
+                            //     $vehicle_state_code = null;
+                            // }
+
+                            // $matched_rto_id = ($m = array_values(array_filter($rto_master, fn($r) => strtoupper($r['rto_state']) === $vehicle_state && (int)$r['rto_code'] === (int)$vehicle_state_code)))[0]['id'] ?? null;
+
+                            $matched_rto_id = check_rto_data($row, $rto_master);
+                            $vehicle_type_id = check_vehicle_type($row, $vehicle_type_data);
+
+                            $vehicle_insert_data = [
+                                'vehicle_no' => $vehicle_number,
+                                'vehicle_type' => $vehicle_type_id['vehicle_type']['id'] ?? null,
+                                'owner' => $client_id,
+                                'rto_id' => $matched_rto_id['rto_data']['id'] ?? null,
+                            ];
+
+                            $vehicle_id = $this->vehicleModel->insert($vehicle_insert_data);
+                        }
+                    }
+
+                    $policy_transaction_data = [
+
+                        'issuer'                => 2,
+                        'issuer_branch'         => $current_nhance_branch['id'] ?? null,
+                        'client_id'             => $client_id,
+                        'policy_type_id'        => 8,
+                        'insurer_id'            => $current_insurer_branch_data['insurer_id'] ?? null,
+                        'insurer_branch_id'     => $current_insurer_branch_data['id'] ?? null,
+                        'policy_no'             => $policy_no,
+                        'vehicle_id'            => $vehicle_id,
+                        'issue_type'            => 1,
+                        'policy_issue_date'     => change_date_format($policy_issue_date, 'd/M/Y', 'Y-m-d'),
+                        'policy_start_date'     => change_date_format($policy_start_date, 'd/M/Y', 'Y-m-d'),
+                        'policy_end_date'       => change_date_format($policy_end_date, 'd/M/Y', 'Y-m-d'),
+                        'action_type'           => 'inception',
+                        'revenue_type'          => $revenue_type,
+                        'co_share'              => 0,
+                        'status'                => 'completed',
+                        'renewal_date'          => change_date_format($policy_end_date, 'd/M/Y', 'Y-m-d'),
+                        'policy_holder_name'    => $client_name,
+                        'month'                 => change_date_format($policy_issue_date, 'd/M/Y', 'Y-m-d'),
+                        'sales_generated_by'    => $salse['id'] ?? null,
+                        'serviced_by'           => $service['id'] ?? null,
+                        'agent_id'              => $current_agent_data['id'] ?? null,
+                        'agent_code'            => $current_agent_data['agent_code'] ?? null,
+                        'file_id'               => $params['file_id'],
+
+                        'endorsement_no'        => null,
+                        'client_branch_id'      => null,
+                        'client_policy_id'      => null,
+                        'ct_type'               => null,
+                        'remarks'               => null,
+
+                    ];
+
+                    $co_share_data = [
+
+                        'pt_id'                     => null,
+                        'insurer_id'                => $current_insurer_branch_data['insurer_id'] ?? null,
+                        'insurer_branch_id'         => $current_insurer_branch_data['id'] ?? null,
+                        'co_share_type'             => 1,  
+                        'co_share_per'              => 100,
+
+                        'bp_amt'                    => $base_premium,
+                        'bp_gst_amt'                => $gst_amt,
+                        'bp_igst'                   => $igst ,
+                        'bp_sgst'                   => $sgst,
+                        'bp_cgst'                   => $cgst,
+
+                        'tp_amt'                    => $tp_premium,
+                        'tp_gst_amt'                => 0,
+                        'tp_igst'                   => 0,
+                        'tp_sgst'                   => 0,
+                        'tp_cgst'                   => 0,
+
+                        'tep_amt'                   => 0,
+                        'tep_gst_amt'               => 0,
+                        'tep_igst'                  => 0,
+                        'tep_sgst'                  => 0,
+                        'tep_cgst'                  => 0,
+
+                        'agreed_amt'                => $agreed_amount,
+                        'agreed_bp_per'             => $agreed_bp_percentage,
+                        'agreed_tp_per'             => $agreed_tp_percentage,
+                        'agreed_tep_per'            => 0,
+
+                        'actual_bp_amt'             => $actual_bp_amount,
+                        'actual_tp_amt'             => $actual_tp_amount,
+                        'actual_tep_amt'            => 0,
+
+                        'actual_bp_per'             => $actual_bp_percentage,
+                        'actual_tp_per'             => $actual_tp_percentage,
+                        'actual_tep_per'            => 0,
+
+                        'actual_bp_brokerage_amt'   => $actual_bp_brokerage_amount,
+                        'actual_tp_brokerage_amt'   => $actual_tp_brokerage_amount,
+                        'actual_tep_brokerage_amt'  => 0,
+
+                        'standerd_bp_per'           => 15.00,
+                        'standerd_tp_per'           => 2.50,
+                        'agreed_tep_per'            => 0,
+
+                        'reward'                    => $rewards,
+                        'variance'                  => 0,
+
+                        'remark'                    => null,
+                        'amount'                    => $total,
+                        'stamp_duty'                => $stamp_duty,
+
+                        'cop_amt'                   => $base_premium,
+                        'cotp_amt'                  => $tp_premium,
+                        'cotep_amt'                 => 0.00,
+
+                        'exp_amt'                   => $expected_amount,
+                        'statement_id'              => null,
+
+                        'follower_policy_no'        => null,
+                        'non_comm_per_amt'          => $non_commission_premium_amount,
+
+                        'pt_policy_issue_date'      => change_date_format($policy_issue_date, 'd/M/Y', 'Y-m-d'),
+
+                        'file_id'                   => $params['file_id']
+                    ];
+
+                    if(!empty($vehicle_id) && !empty($client_id)){
+                        $pt_id = $this->policyTransactionModel->insert($policy_transaction_data);
+                        if($pt_id){
+                            $co_share_data['pt_id'] = $pt_id;
+                            $pt_co_share_id = $this->PTCOShareDetailsModel->insert($co_share_data);
+
+                            $client_policy_insert_data = $this->prepareClientPolicyInsertData($policy_transaction_data);
+                            $client_policy_id = $this->clientPolicyModel->insert($client_policy_insert_data);
+                            $this->policyTransactionModel->update($pt_id, ['client_policy_id' => $client_policy_id]);
+                            $pt_ids[] = $pt_id;
+                            $this->myLogger->logme('error', "BDS entry successfully added with pt_id : $pt_id, pt_co_share_id : $pt_co_share_id, client_policy_id :$client_policy_id");
+
+                        }
+                    }else{
+                        $this->myLogger->logme('error', 'Skipped......... , vehicle id and client id missing');
+                    }
+
+                }
+
+            } catch (\Exception $e) {
+                $errorDetails = [
+                    'error_message' => $e->getMessage(),
+                    'file'          => $e->getFile(),
+                    'line'          => $e->getLine(),
+                    'stack_trace'   => $e->getTraceAsString(),
+                ];
+                $message = "Contact system admin";
+                $this->bdsDumpModel->where('id', $file_id)->set(['status' => 'failed', 'reason' => json_encode(['error_summary' => array_count_values([5]), 'error_data' => $message])])->update();
+                $this->myLogger->logme("error", 'Claim dump file format validation failed due to : ' . json_encode($errorDetails ?? []));
+                return $errorDetails;
+            }
+
+            // return $result;
+
+            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->bdsDumpModel->where('id', $file_id)->set(['status' => $status, 'reason' => $failure_reason])->update();
+                $this->myLogger->logme("error", '{file_id} uploaded failed', ['file_id' => $file_id]);
+            } else{
+                $result = count($pt_ids);
+            }
+
+            return $result;
+        }
+
+        public function extractExcelData($file_name, $highestColumn)
+        {
+            // $file_name = "claims_dump_form_client.xlsx";
+            // Load the Excel file
+            $file_name_with_path = WRITEPATH . "/uploads/bds_dump_excel/" . $file_name;
+            $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path);
+            $worksheet = $spreadsheet->getActiveSheet();
+
+            // Get the highest row and column numbers
+            $highestRow = $worksheet->getHighestDataRow();
+            // $highestColumn = $worksheet->getHighestDataColumn();
+            // dd($highestRow, $highestColumn);
+
+            // Get header row (assuming headers are in row 1)
+            // $headerRow = $worksheet->rangeToArray('A1:' . $highestColumn . '1', null, true, false)[0];
+            $excel_data = $worksheet->rangeToArray('A1:' . $highestColumn . $highestRow);
+            // print_rr($excel_data); die;
+
+            //Sanitize the excel data
+            $excel_data = ExcelSanitizeHelper::sanitizeArrayData($excel_data);
+            // dd($excel_data);
+
+            // dd($data);
+            return $excel_data;
+        }
+
+        public function getBdsBulkUploadExcelErrorData($file_id)
+        {
+            try {
+
+                $file = $this->bdsDumpModel->where('id', $file_id)->first();
+                $error_data = json_decode($file['reason']);
+                // dd($error_data);
+
+                $file_name_with_path = WRITEPATH . "/uploads/bds_dump_excel/" . $file['file_name'];
+                // Kint::dump(file_exists($file_name_with_path)); die;
+
+                //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 ' . $file_id));
+                    return 0;
+                }
+
+                $columns_to_check = $this->bds_bulk_upload_excel_file_column;
+                $allowedHighestColumn = end($columns_to_check);
+                // Kint::dump($columns_to_check); die;
+
+                $excel_data = $this->extractExcelData($file['file_name'], $allowedHighestColumn['col_cell_name']);
+                $excelErrorData['excel_header'] = $excel_data[0];
+                unset($excel_data[0]);
+
+                // Kint::dump($excel_data); die;
+                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 getBdsdumpFileErrorData()
+        {
+            $file_id = $this->request->getGet('file_id');
+            $file = $this->bdsDumpModel->where('id', $file_id)->first();
+            if (!isset($file)) {
+                return $this->respond(['status' => false, 'code' => 404, 'message' => 'No data found'], 200);
+            } else {
+                return $this->respond(['status' => true, 'code' => 200, 'data' => $file['reason']], 200);
+            }
+        }
+
+        public function getBdsDumpExcelFileErrors($file_id)
+        {
+            // Render views and capture output
+            $result = $this->getBdsBulkUploadExcelErrorData($file_id) ?? [];
+            // dd($result);
+
+            if ($result != 0) {
+
+                $result['file_id'] = $file_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');
+            }
+        }
     }
diff --git a/app/Helpers/excel_util_helper.php b/app/Helpers/excel_util_helper.php
index 761d69bb..b5334313 100755
--- a/app/Helpers/excel_util_helper.php
+++ b/app/Helpers/excel_util_helper.php
@@ -2948,3 +2948,392 @@ if (!function_exists('validatet_family_floter_rata_premium')) {
         return $family;
     }
 }
+
+
+if (!function_exists('validate_excel_value')) {
+    function validate_excel_value($value, $data_type, $format = null, $allowed_values = null)
+    {
+        switch ($data_type) {
+
+            case 'date':
+                return validate_date_value($value, $format);
+
+            case 'mobile':
+                return validate_mobile_value($value);
+
+            case 'email':
+                return validate_email_value($value);
+
+            case 'vehicle':
+                return validate_indian_vehicle_number($value);
+
+            default:
+                return [
+                    'status' => true,
+                    'error'  => null
+                ];
+        }
+    }
+}
+
+if (!function_exists('validate_date_value')) {
+    function validate_date_value($value, $format)
+    {
+        if(empty($value)) {
+            return ['status' => true, 'error' => null]; // allow empty
+        }
+
+        $d = DateTime::createFromFormat($format, $value);
+
+        if ($d && $d->format($format) === $value) {
+            return ['status' => true, 'error' => null];
+        }
+
+        return [
+            'status' => false,
+            'error'  => "Invalid date format. Expected format: {$format}"
+        ];
+    }
+}
+
+if (!function_exists('validate_mobile_value')) {
+    function validate_mobile_value($value)
+    {
+        if (preg_match('/^[0-9]{10}$/', $value)) {
+            return ['status' => true, 'error' => null];
+        }
+
+        return [
+            'status' => false,
+            'error'  => "Invalid mobile number. Expected 10 digits."
+        ];
+    }
+}
+
+if (!function_exists('validate_email_value')) {
+    function validate_email_value($value)
+    {
+        if (filter_var($value, FILTER_VALIDATE_EMAIL)) {
+            return ['status' => true, 'error' => null];
+        }
+
+        return [
+            'status' => false,
+            'error'  => "Invalid email address."
+        ];
+    }
+}
+
+if (!function_exists('validate_indian_vehicle_number')) {
+    function validate_indian_vehicle_number($number)
+    {
+        $number = strtoupper(trim($number));
+
+        // Normal Format:
+        // 2 letters (state) + 2 digits (district) + 1 or 2 letters (series) + 4 digits
+        $normalPattern = '/^[A-Z]{2}[0-9]{2}[A-Z]{1,2}[0-9]{4}$/';
+
+        // BH Series: 22BH1234AA
+        $bhPattern = '/^[0-9]{2}BH[0-9]{4}[A-Z]{2}$/';
+
+        if (preg_match($normalPattern, $number)) {
+            return ['status' => true, 'error' => null];
+        }
+
+        if (preg_match($bhPattern, $number)) {
+            return ['status' => true, 'error' => null];
+        }
+
+        return [
+            'status' => false,
+            'error'  => "Invalid Vehicle Number"
+        ];
+    }
+}
+
+if (!function_exists('check_user_exist')) {
+    function check_user_exist($row, $col_key, $user_data)
+    {
+        // Get the uploaded value from the column
+        $input_value = trim($row[$col_key]);
+
+        // Loop DB user list
+        foreach ($user_data as $user) {
+
+            // Check if DB has 'first_name' key and matches input
+            if (isset($user['first_name']) && strtolower(trim($user['first_name'])) === strtolower($input_value)) {
+
+                return [
+                    'status' => true,
+                    'error'  => null,
+                    'user'  => $user,
+                ];
+            }
+        }
+
+        // If no user matched
+        return [
+            'status' => false,
+            'error'  => "User '{$input_value}' not found in database."
+        ];
+    }
+}
+
+if (!function_exists('check_agent_exist')) {
+    function check_agent_exist($row, $agent_data)
+    {
+        // Get agent code from the uploaded row
+        $agent_code = trim($row[15]); // or use index if needed
+
+        // Loop agent data from DB
+        foreach ($agent_data as $agent) {
+            // Assuming DB keys: agent_code
+            if (isset($agent['agent_code']) && $agent['agent_code'] == $agent_code) {
+                return [
+                    'status' => true,
+                    'error'  => null,
+                    'agent'  => $agent,
+                ];
+            }
+        }
+
+        // If not matched
+        return [
+            'status' => false,
+            'error'  => "Agent code '{$agent_code}' not found in database."
+        ];
+    }
+}
+
+if (!function_exists('check_rto_data')) {
+    function check_rto_data($row, $rto_master)
+    {
+        // Vehicle number from uploaded row
+        $vehicle_no = strtoupper(trim($row[2]));  // Example: TN10AB1234
+
+        // Must be at least 4 characters to extract RTO
+        if (strlen($vehicle_no) < 4) {
+            return [
+                'status' => false,
+                'error'  => "Invalid vehicle number format: '{$vehicle_no}'"
+            ];
+        }
+
+        // Extract State (first 2 letters) and RTO Code (next 2 digits)
+        $state_code = substr($vehicle_no, 0, 2);    // TN
+        $rto_code   = substr($vehicle_no, 2, 2);    // 10
+
+        // Validate they are correct format
+        if (!ctype_alpha($state_code) || !ctype_digit($rto_code)) {
+            return [
+                'status' => false,
+                'error'  => "Vehicle number '{$vehicle_no}' has invalid state or RTO code."
+            ];
+        }
+
+        // Loop RTO master data
+        foreach ($rto_master as $rto) {
+
+            // Expected DB fields: rto_state, rto_code
+            if (
+                isset($rto['rto_state']) &&
+                isset($rto['rto_code']) &&
+                strtoupper($rto['rto_state']) === $state_code &&
+                (string)$rto['rto_code'] === $rto_code
+            ) {
+                return [
+                    'status' => true,
+                    'error'  => null,
+                    'rto_data'  => $rto
+                ];
+            }
+        }
+
+        // Not found in RTO master
+        return [
+            'status' => false,
+            'error'  => "RTO '{$state_code} {$rto_code}' not found in RTO master."
+        ];
+    }
+}
+
+if (!function_exists('check_vehicle_type')) {
+    function check_vehicle_type($row, $vehicle_type)
+    {
+        // Vehicle type from uploaded Excel row
+        $input_type = strtolower(trim($row[3]));  // Example: CAR
+
+        // Loop vehicle type master
+        foreach ($vehicle_type as $vt) {
+
+            if (isset($vt['vehicle_type']) && strtolower($vt['vehicle_type']) == $input_type) {
+                return [
+                    'status' => true,
+                    'error'  => null,
+                    'vehicle_type'  => $vt,
+                ];
+            }
+        }
+
+        // Not found in master
+        return [
+            'status' => false,
+            'error'  => "Vehicle type '{$input_type}' not found in master."
+        ];
+    }
+}
+
+if (!function_exists('check_policy_no')) {
+    function check_policy_no($row, $pt_data)
+    {
+        // Get policy number from Excel row
+        $policy_no = strtolower(trim($row[4]));
+
+        // Empty policy number
+        if ($policy_no === '') {
+            return [
+                'status' => false,
+                'error'  => "Policy number is empty."
+            ];
+        }
+
+        // Loop all policy transactions (pt_data)
+        foreach ($pt_data as $pt) {
+
+            // Check policy_no exists in DB list
+            if (isset($pt['policy_no']) && strtolower($pt['policy_no']) == $policy_no) {
+                return [
+                    'status' => false,
+                    'error'  => "Duplicate policy number '{$policy_no}' found in database."
+                ];
+            }
+        }
+
+        // If no match found → not duplicate
+        return [
+            'status' => true,
+            'error'  => null
+        ];
+    }
+}
+
+if (!function_exists('check_insurer_exist')) {
+    function check_insurer_exist($row, $insurer_master)
+    {
+        // Get insurer short name from Excel row (col 7)
+        $short_name = strtolower(trim($row[7]));
+
+        foreach ($insurer_master as $insurer) {
+            if (
+                isset($insurer['short_name']) &&
+                strtolower($insurer['short_name']) === $short_name
+            ) {
+                return [
+                    'status'  => true,
+                    'error'   => null,
+                    'insurer' => $insurer   // return entire insurer row for next validation
+                ];
+            }
+        }
+
+        return [
+            'status' => false,
+            'error'  => "Insurer '{$short_name}' not found in database."
+        ];
+    }
+}
+
+if (!function_exists('check_insurer_branch_exist')) {
+    function check_insurer_branch_exist($row, $insurer_branch_master, $insurer)
+    {
+        // Get branch code from Excel row (col 8)
+        $branch_code = strtolower(trim($row[8]));
+
+        // Loop all branches
+        foreach ($insurer_branch_master as $branch) {
+
+            if (
+                isset($insurer['id']) && $branch['insurer_id'] == $insurer['id'] && 
+                strtolower($branch['branch_code']) == $branch_code 
+            ) {
+                return [
+                    'status' => true,
+                    'error'  => null,
+                    'branch' => $branch
+                ];
+            }
+        }
+
+        return [
+            'status' => false,
+            'error'  => "Branch code '{$branch_code}' not found in database."
+        ];
+    }
+}
+
+if (!function_exists('check_nhance_branch')) {
+    function check_nhance_branch($row, $nhance_branch_master)
+    {
+        // Get branch name from Excel row (col 8)
+        $branch_name = strtolower(trim($row[1]));
+
+        // Loop all branches
+        foreach ($nhance_branch_master as $branch) {
+
+            if (
+                isset($branch['branch_name']) &&
+                strtolower($branch['branch_name']) == $branch_name
+            ) {
+                return [
+                    'status' => true,
+                    'error'  => null,
+                    'branch' => $branch
+                ];
+            }
+        }
+
+        return [
+            'status' => false,
+            'error'  => "Branch '{$branch_name}' not found in database."
+        ];
+    }
+}
+
+if (!function_exists('calculate_gst_amount')) {
+    function calculate_gst_amount($row) {
+
+        // Extract values
+        $base_premium                     = (float)trim($row[16]);
+        $non_commission_premium_amount    = (float)trim($row[17]);
+        $tp_premium                       = (float)trim($row[18]);
+        $igst                             = (float)trim($row[19]);
+        $cgst                             = (float)trim($row[20]);
+        $sgst                             = (float)trim($row[21]);
+
+        // Total GST percentage
+        $gst_percentage = $igst + $cgst + $sgst;
+
+        // Step 1: Choose taxable amount
+        if ($non_commission_premium_amount > 0) {
+            // GST on non-commission premium
+            $taxable_amount = $non_commission_premium_amount;
+        } else {
+            // GST on base premium + TP premium
+            $taxable_amount = $base_premium + $tp_premium;
+        }
+
+        // Step 2: GST Amount calculation
+        $gst_amount = ($taxable_amount * $gst_percentage) / 100;
+
+        return round($gst_amount, 2);
+    }
+}
+
+
+
+
+
+
+
+
+
diff --git a/app/Models/BDSDumpModel.php b/app/Models/BDSDumpModel.php
new file mode 100644
index 00000000..d89da194
--- /dev/null
+++ b/app/Models/BDSDumpModel.php
@@ -0,0 +1,55 @@
+
+
+    .reload:hover {
+        cursor: pointer;
+    }
+
+    .table th,
+    .table td {
+        padding: 8px;
+    }
+
+    table.dataTable tbody td {
+        padding: 4px 4px !important;
+    }
+
+    .addbtnStyle{
+        margin-left: 20px !important;
+    }
+
+    .dataTables_filter {
+        position: absolute;
+    }
+
+    .dataTables_length label {height: 21px !important;}
+
+
+
+
+
+ + + + + + + + + + + + + $file) { + ?> + + + + + + + + + + + +
S.No File nameUser/TimeStatusAction
+ + ' . $file['user_name'] . '' ?> + + + + + + + + + + + + + + + +
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/public/sample_excel/sample_bds_bulk_upload_excel.xlsx b/public/sample_excel/sample_bds_bulk_upload_excel.xlsx new file mode 100644 index 00000000..0bd3d537 Binary files /dev/null and b/public/sample_excel/sample_bds_bulk_upload_excel.xlsx differ