myLogger = \Config\Services::mylogger(); $this->clientModel = new ClientModel(); $this->userModel = new UserModel(); $this->clientBranchModel = new ClientBranchModel(); $this->clientPolicyModel = new ClientPolicyModel(); $this->levelContactModel = new LevelContactModel(); $this->leadsModel = new LeadsModel(); $this->policyTypeModel = new PolicyTypeModel(); $this->kycEntityTypeModel = new KYCEntityTypeModel(); $this->policyTransactionStatusModel = new PolicyTransactionStatusModel(); $this->insurerBranchModel = new InsurerBranchModel(); $this->tpaBranchModel = new TPABranchModel(); $this->RFQModel = new RFQModel(); $this->insurerModel = new InsurerModel(); $this->occupancyModel = new OccupancyMasterModel(); $this->leadFilesModel = new LeadFilesModel(); $this->leadInstallmentPaymentDetails = new LeadInstallmentPaymentDetails(); $this->issuer = [1 => 'JIBS', 2 => 'Nhance']; $this->clientType = [1 => 'Group', 2 => 'Individual']; $this->leadType = [1 => 'Fresh', 2 => 'Renewal', 3 => 'Roll Over']; $data = $this->kycEntityTypeModel->where('is_active', 1)->findAll(); $this->buisnessType = array_column($data, 'name', 'id'); // $this->buisnessType = [1 => 'Public Sector', 2 => 'Private Sector',3=> 'Trust',4 => 'Proprietorship',5 => 'Partnership',6 => 'Private',7 => 'Individual']; $this->leadsStatus = [ 'queued' => 'In-Queued', 'rfq_created' => 'RFQ Created', 'rfq_sent' => 'RFQ Sent', 'qcr_created' => 'QCR Created', 'qcr_sent' => 'QCR Sent', 'lost' => 'Lost', 'co_insurer_pending' => 'Co-Insurer Pending', 'won' => 'Won', 'completed_with_corrections' => 'Completed with Corrections', 'completed_without_corrections' => 'Completed without Corrections', ]; $this->claim_type_for_gpa = [ 'nil' => 'Nil', 'accident_death' => 'Accident Death', 'permanent_total_disablement' => 'Permanent Total Disablement', 'permanent_partial_disablement' => 'Permanent Partial Disablement', 'temporary_total_disablement_benefit' => 'Temporary Total Disablement benefit' ]; $this->cause_of_death = [ 'natural_death' => 'Natural Death', 'suicide' => 'Suicide', 'accident' => 'Accident' ]; } public function viewLeadsList() { $data['page_name'] = 'Leads'; // Set basic data $data['issuer'] = $this->issuer; $data['client_type'] = $this->clientType; $data['lead_type'] = $this->leadType; $data['lead_status'] = $this->leadsStatus; // Fetch policy types and entity data $data['policy_type'] = $this->policyTypeModel->where('is_active', 1)->findAll(); $data['entity'] = $this->kycEntityTypeModel->where('is_active', 1)->findAll(); // dd($lastFiveYears); if ($this->request->is('get')) { // Fetch leads data $data['lead_data_list'] = $this->leadsModel->getLeadDataForLising(); // Load layout and pass data $this->loadLayout('lead_filter', $data); } else { $isFromDashboard = $this->request->getPost("is_dashboard"); if (isset($isFromDashboard) && !empty($isFromDashboard) && $isFromDashboard == 1) { $ids = $this->request->getPost('ids'); $ids = array_filter(explode(',', $ids)); if (!empty($ids)) { $idsStr = implode(',', array_map('intval', $ids)); // sanitize IDs to be integers $where = "leads.id IN ($idsStr)"; } else { $where = '1 = 0'; // No valid IDs, return empty result } // dd($where ); $data['lead_data_list'] = $this->leadsModel->getLeadDataForLising($where); $this->loadLayout('lead_filter', $data); } else { $search_data = $this->request->getPost(); $where = []; foreach ($search_data as $search_objects => $key) { if ($key != null && $key != '' && $key != 0 && $search_objects != 'is_dashboard') { $where[$search_objects] = $key; } } $data['lead_data_list'] = $this->leadsModel->getLeadDataForLising($where); $html = view('leads_list', $data); return $this->respond(['status' => true, 'html' => $html], 200); } } } public function createLead() { // print_r($this->request->getPost()); die; $id = $this->request->getPost('id'); $data = $this->prepareLeadData(); // print_r($data); die; if (!$id) { return $this->insertNewLead($data); } else { return $this->updateOldLead($id, $data); } } private function prepareLeadData() { $data = $this->request->getPost(); $data['client_type'] = 1; $data['pan'] = ""; if ($data['lead_type'] != 1) { $client_data = $this->clientModel->where('id', $data['client_id'])->where('is_active', 1)->first(); $data['client_name'] = $client_data['client_name']; $data['client_short_name'] = $client_data['short_name']; $data['entity_type_id'] = $client_data['entity_type_id']; $data['client_type'] = $client_data['client_type']; } else { if(!empty($data['client_id'])){ $data['is_client_created'] = $data['client_id']; }else{ $data['client_id'] = 0; $data['client_branch_id'] = 0; $data['source_policy_id'] = 0; } } $data['client_code'] = generate_client_code(); if ($data['client_code'] == 2) { $data['client_code'] = generate_client_code('IC'); } if (isset($data['lead_form_type'])) { $data = $this->prepareSingleLeadData($data); } else { $data = $this->prepareMultipleLeadData($data); } // print_r($data); die; return $data; } private function prepareSingleLeadData($data) { // print_r($data); die; $index_plus_one = 1; $form_file_name = "file_name_" . $index_plus_one; $form_docs_name = "docs_name_" . $index_plus_one; $leads_file_primary_key = $data['leads_file_id'] ?? []; $multi_file_data = []; if (isset($data[$form_docs_name])) { $files = $this->request->getFileMultiple($form_file_name); $multi_file_data = $this->uploadMultiFiles($files, $data[$form_docs_name], $leads_file_primary_key); } // Separate the insurer and insurer branch, handle missing or invalid data if (isset($data['insurer']) && strpos($data['insurer'], '-') !== false) { list($insurer_branch_id, $insurer_id) = explode('-', $data['insurer']); } else { $insurer_branch_id = 0; $insurer_id = 0; } $data['insurer_id'] = $insurer_id; $data['insurer_branch_id'] = $insurer_branch_id; // Separate the insurer and insurer branch, handle missing or invalid data if (isset($data['tpa']) && strpos($data['tpa'], '-') !== false) { list($tpa_branch_id, $tpa_id) = explode('-', $data['tpa']); } else { $tpa_branch_id = 0; $tpa_id = 0; } $data['tpa_id'] = $tpa_id; $data['tpa_branch_id'] = $tpa_branch_id; if (!empty($data['policy_start_date'])) { $data['policy_start_date'] = change_date_format($data['policy_start_date']); } else { $data['policy_start_date'] = null; } if (!empty($data['policy_end_date'])) { $data['policy_end_date'] = change_date_format($data['policy_end_date']); } else { $data['policy_end_date'] = null; } // $data['file_name'] = file_Upload($files, $uploadFilePath); $data['multi_file_data'] = $multi_file_data ?? null; $processcedData[] = $data; // print_r($data);die(); return $processcedData; } private function prepareMultipleLeadData($data) { // print_r($data); die; $processedData = []; foreach ($data['policy_type_id'] as $index => $value) { $index_plus_one = $index + 1; $form_file_name = "file_name_" . $index_plus_one; $form_docs_name = "docs_name_" . $index_plus_one; $leads_file_primary_key = $data['leads_file_id'] ?? []; $files = $this->request->getFileMultiple($form_file_name); $multi_file_data = $this->uploadMultiFiles($files, $data[$form_docs_name], $leads_file_primary_key); // Separate the insurer and insurer branch, handle missing or invalid data if (isset($data['insurer'][$index]) && strpos($data['insurer'][$index], '-') !== false) { list($insurer_branch_id, $insurer_id) = explode('-', $data['insurer'][$index]); } else { $insurer_branch_id = 0; $insurer_id = 0; } // Separate the insurer and insurer branch, handle missing or invalid data if (isset($data['tpa'][$index]) && strpos($data['tpa'][$index], '-') !== false) { list($tpa_branch_id, $tpa_id) = explode('-', $data['tpa'][$index]); } else { $tpa_branch_id = 0; $tpa_id = 0; } // Separate the insurer and insurer branch, handle missing or invalid data if (isset($data['proposed_insurer'][$index]) && strpos($data['proposed_insurer'][$index], '-') !== false) { list($proposed_insurer_branch_id, $proposed_insurer_id) = explode('-', $data['proposed_insurer'][$index]); } else { $proposed_insurer_branch_id = 0; $proposed_insurer_id = 0; } // Separate the TPA and TPA branch, handle missing or invalid data if (isset($data['proposed_tpa'][$index]) && strpos($data['proposed_tpa'][$index], '-') !== false) { list($proposed_tpa_branch_id, $proposed_tpa_id) = explode('-', $data['proposed_tpa'][$index]); } else { $proposed_tpa_branch_id = 0; $proposed_tpa_id = 0; } if (!empty($data['policy_start_date'][$index])) { $policy_start_date = change_date_format($data['policy_start_date'][$index], 'd/m/Y', 'Y-m-d'); } else { $policy_start_date = null; } if (!empty($data['policy_end_date'][$index])) { $policy_end_date = change_date_format($data['policy_end_date'][$index], 'd/m/Y', 'Y-m-d'); } else { $policy_end_date = null; } if (!empty($data['incurred_claim_date'][$index])) { $incurred_claims_date = change_date_format($data['incurred_claim_date'][$index], 'd/m/Y', 'Y-m-d'); } else { $incurred_claims_date = null; } // if (!empty($data['premium_date'][$index])) { // $premium_date = change_date_format($data['premium_date'][$index], 'd/m/Y', 'Y-m-d'); // } else { // $premium_date = null; // } if (!empty($data['source_policy_start_date']) && $data['lead_type'] == 2) { $data['source_policy_start_date'] = change_date_format($data['source_policy_start_date'], 'd/m/Y', 'Y-m-d'); } else { $data['source_policy_start_date'] = null; } if (!empty($data['source_policy_end_date']) && $data['lead_type'] == 2) { $data['source_policy_end_date'] = change_date_format($data['source_policy_end_date'], 'd/m/Y', 'Y-m-d'); } else { $data['source_policy_end_date'] = null; } // $file_name = file_Upload($files[$index], $uploadFilePath); $last_3_years_claims = $data['finyear']; $processedData[] = [ 'lead_type' => $data['lead_type'], 'issuer' => $data['issuer'], 'client_type' => $data['client_type'], 'client_name' => $data['client_name'], 'client_short_name' => $data['client_short_name'], 'entity_type_id' => $data['entity_type_id'], 'client_code' => $data['client_code'], 'pan' => $data['pan'], 'gst' => $data['gst'], 'branch_name' => $data['branch_name'], 'branch_code' => $data['branch_code'], 'contact_person_name' => $data['contact_person_name'], 'contact_person_mobile' => $data['contact_person_mobile'], 'contact_person_email' => $data['contact_person_email'], 'client_id' => $data['client_id'] ?? 0, 'client_branch_id' => $data['client_branch_id'] ?? 0, 'is_client_created' => $data['is_client_created'] ?? null, 'source_policy_id' => $data['source_policy_id'] ?? 0, 'policy_type_id' => $value, 'salse_person_id' => $data['salse_person_id'] ?? 0, 'insurer_id' => $insurer_id ?? 0, 'insurer_branch_id' => $insurer_branch_id ?? 0, 'tpa_id' => $tpa_id ?? 0, 'tpa_branch_id' => $tpa_branch_id ?? 0, 'policy_start_date' => $policy_start_date, 'policy_end_date' => $policy_end_date, 'no_of_lives' => $data['no_of_lives'][$index] ?? null, 'incurred_claims' => $data['incurred_claims'][$index] ?? 0, 'location' => $data['location'][$index] ?? null, 'proposed_insurer_id' => $proposed_insurer_id ?? 0, 'proposed_insurer_branch_id' => $proposed_insurer_branch_id ?? 0, 'proposed_tpa_id' => $proposed_tpa_id ?? 0, 'proposed_tpa_branch_id' => $proposed_tpa_branch_id ?? 0, 'renewal_emp_count' => $data['renewal_emp_count'][$index] ?? 0, 'renewal_dept_count' => $data['renewal_dept_count'][$index] ?? 0, 'renewal_no_of_lives' => $data['renewal_no_of_lives'][$index] ?? 0, 'incept_emp_count' => $data['incept_emp_count'][$index] ?? 0, 'incept_dept_count' => $data['incept_dept_count'][$index] ?? 0, 'incept_no_of_lives' => $data['incept_no_of_lives'][$index] ?? 0, 'exp_emp_count' => $data['exp_emp_count'][$index] ?? 0, 'exp_dept_count' => $data['exp_dept_count'][$index] ?? 0, 'exp_no_of_lives' => $data['exp_no_of_lives'][$index] ?? 0, 'incurred_claims_date' => $incurred_claims_date, 'paid_claims' => $data['paid_claims'][$index] ?? 0, 'outstanding_claims' => $data['outstanding_claims'][$index] ?? 0, 'policy_run_days' => $data['policy_run_days'][$index] ?? 0, 'premium_at_inception' => $data['premium_at_inception'][$index] ?? 0, 'premium_date' => $data['premium_date'][$index] ?? 0, 'earned_premium' => $data['earned_premium'][$index] ?? 0, 'annualised_claims' => $data['annualised_claims'][$index] ?? 0, 'incurred_claims_ratio' => $data['incurred_claims_ratio'][$index] ?? 0, 'earned_claims_ratio' => $data['earned_claims_ratio'][$index] ?? 0, 'total_si_at_incept' => $data['total_si_at_incept'][$index] ?? 0, 'total_si_at_renewal' => $data['total_si_at_renewal'][$index] ?? 0, 'total_lives_at_incept' => $data['total_lives_at_incept'][$index] ?? 0, 'premium_at_incept' => $data['premium_at_incept'][$index] ?? 0, 'fin_years_claims' => $last_3_years_claims, // 'file_name' => $file_name, 'multi_file_data' => $multi_file_data ?? null, 'status' => $data['status'] ?? null, 'notes' => $data['notes'] ?? null, 'lead_form_type' => $data['lead_form_type'] ?? 1, 'custom_fields' => $data['custom_fields'] ?? null, 'source_policy_start_date' => $data['source_policy_start_date'] ?? null, 'source_policy_end_date' => $data['source_policy_end_date'] ?? null, 'claim_history' => $data['claim_history'] ?? 0 ]; } // print_r($processedData);die(); return $processedData; } private function insertNewLead($data) { $insertCount = []; foreach ($data as $value) { $insert = $this->leadsModel->insert($value); if ($insert) { $this->insertMultiFilesData($value['multi_file_data'], $insert); } $insertCount[] = $insert; $this->insertLeadStatus($insert, $value['status'], 3); 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' => [ 'lead_id' => $insert, ]]); } } if (count($insertCount) > 0) { return $this->respond(['status' => true, 'lead_id' => $insert, 'message' => 'New Lead created successfully', 'data' => $data], 200); } return $this->respond(['status' => false, 'lead_id' => $insert, 'message' => "Failed to create Lead", 'data' => $data], 200); } private function updateOldLead($id, $data) { if ($this->leadsModel->where('id', $id)->set($data[0])->update()) { $this->insertMultiFilesData($data[0]['multi_file_data'], $id, $data[0]['lead_form_type']); $this->insertLeadStatus($id, $data[0]['status'], 3); return $this->respond(['status' => true, 'lead_id' => $id, 'message' => "Lead updated successfully", 'data' => $data], 200); } return $this->respond(['status' => false, 'lead_id' => $id, 'message' => "Failed to update Lead", 'data' => $data], 200); } // Get the Single Lead data for edit uisng ajax ( do not delete) public function getLeadDataForEdit($id) { $data = $this->leadsModel ->where('leads.id', $id) ->where('leads.is_active', 1) ->first(); $data['lead_edit_data'] = $this->leadsModel ->where('leads.id', $id) ->where('leads.is_active', 1) ->first(); if (!empty($data['policy_start_date'])) { $data['policy_start_date'] = change_date_format($data['policy_start_date'], 'Y-m-d', 'd/m/Y'); } else { $data['policy_start_date'] = null; } if (!empty($data['policy_end_date'])) { $data['policy_end_date'] = change_date_format($data['policy_end_date'], 'Y-m-d', 'd/m/Y'); } else { $data['policy_end_date'] = null; } if (!empty($data['incurred_claims_date'])) { $data['incurred_claims_date'] = change_date_format($data['incurred_claims_date'], 'Y-m-d', 'd/m/Y'); } else { $data['incurred_claims_date'] = null; } // if (!empty($data['premium_date'])) { // $data['premium_date'] = change_date_format($data['premium_date'], 'Y-m-d', 'd/m/Y'); // } else { // $data['premium_date'] = null; // } $data['multi_file_data'] = $this->leadFilesModel->where('lead_id', $id)->first() ?? null; $data['lastFiveYears'] = $this->getLastFiveFinancialYears(); $data['gpaClaimType'] = $this->claim_type_for_gpa; $data['causeOfDeath'] = $this->cause_of_death; if (!empty($data['fin_years_claims'])) { $decoded = json_decode($data['fin_years_claims'], true); $data['lead_edit_data']['fin_years_claims_array'] = isset($decoded['finyear']) ? $decoded['finyear'] : []; } else { $data['lead_edit_data']['fin_years_claims_array'] = []; } $data['html'] = $this->generateViewPageHtml($data['policy_type_id'], $data) ?? ""; // print_r($data); die; if ($data) { return $this->respond(['status' => true, 'data' => $data], 200); } else { return $this->respond(['status' => false], 200); } } private function insertLeadStatus($primaryKey, $status, $statusType) { $statusData = [ 'policy_tran_id' => $primaryKey, 'status' => $status, 'status_type' => $statusType, 'created_by' => get_session_userid(), ]; $this->policyTransactionStatusModel->insert($statusData); } public function uploadMultiFiles($files, $docs_names, $primaryKey) { $uploadFilePath = WRITEPATH . 'uploads/lead_files/'; $multi_file_data = []; foreach ($files as $index => $value) { $file_name = file_Upload($value, $uploadFilePath); $multi_file_data[] = [ 'file_name' => $file_name, 'docs_name' => $docs_names[$index], 'id' => $primaryKey[$index] ?? "", ]; } return $multi_file_data; } public function insertMultiFilesData($data, $lead_id, $lead_form_type = null) { log_message('info', 'insertMultiFilesData() called with lead_id: ' . $lead_id); if (!empty($data)) { log_message('info', 'Data is not empty. Total items: ' . count($data)); foreach ($data as $key => $value) { log_message('info', "Processing item at index {$key}: " . json_encode($value)); if (!empty($value['id'])) { log_message('info', "Record with ID {$value['id']} exists. Preparing to update."); $lead_file_data = [ 'lead_id' => $lead_id, 'docs_name' => $value['docs_name'], ]; if (!empty($value['file_name'])) { $lead_file_data['file_name'] = $value['file_name']; log_message('info', "file_name found: {$value['file_name']}"); 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' => [ 'lead_id' => $lead_id, ]]); log_message('info', "calculateMembersDemography JOB PUSHED"); } } log_message('info', "Updating leadFilesModel where id = {$value['id']} with data: " . json_encode($lead_file_data)); $this->leadFilesModel->where('id', $value['id'])->set($lead_file_data)->update(); } else { log_message('info', "No ID found. Preparing to insert new record."); if (!empty($value['file_name'])) { $lead_file_data = [ 'lead_id' => $lead_id, 'docs_name' => $value['docs_name'], 'file_name' => $value['file_name'], ]; log_message('info', "Inserting into leadFilesModel: " . json_encode($lead_file_data)); $this->leadFilesModel->insert($lead_file_data); } else { log_message('warning', "Skipped insert: file_name missing in data at index {$key}"); } } if ($key == 0 && !empty($value['file_name'])) { log_message('info', "Setting first file_name '{$value['file_name']}' to leadsModel for lead_id: {$lead_id}"); $this->leadsModel->where('id', $lead_id)->set('file_name', $value['file_name'])->update(); } } } else { log_message('warning', 'insertMultiFilesData() received empty data array.'); } log_message('info', 'insertMultiFilesData() completed successfully.'); return true; } public function removeMultiFile() { $id = $this->request->getGet('lead_file_id'); if (!empty($id)) { $this->leadFilesModel->where('id', $id)->set(['is_active' => 0])->update(); return $this->respond(['status' => true, 'message' => 'File removed successfully'], 200); } else { return $this->respond(['status' => false, 'message' => 'File could not be removed.'], 200); } } //--------RFQ----------------------------------------------------------------------------------------------- public function viewRFQ($id, $type = 1) { $data['rfq_data'] = $this->RFQModel ->where('lead_id', $id) // ->where('type', $type) ->where('is_active', 1) ->orderBy('id', 'desc') ->first(); // dd($data); $data['rfq_count'] = $this->RFQModel ->where('lead_id', $id) // ->where('type', 1) ->where('is_active', 1) ->countAllResults(); $data['qcr_count'] = $this->RFQModel ->where('lead_id', $id) ->where('type', 2) ->where('is_active', 1) ->countAllResults(); // dd(count($data['rfq_data'])); $data['lead_id'] = $id; $lead_data = $this->leadsModel ->select(' leads.*, 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') ->where('leads.id', $id) ->where('leads.is_active', 1) ->first(); // dd($lead_data); if ($lead_data['lead_type'] != 1) { $client_policy_data = $this->clientPolicyModel->where('is_active', 1)->where('id', $lead_data['source_policy_id'])->first(); if (isset($client_policy_data)) { $data['policy_terms'] = $client_policy_data['policy_terms']; } } $data['question_json'] = $lead_data['question_json']; $data['page_name'] = $type == 2 ? 'QCR' : 'RFQ'; $data['insurer'] = $this->insurerBranchModel->getInsurerBranchesWithInsurerNames(); $data['userList'] = $this->userModel->getUserListForRFQ(); $data['exclusiveUserList'] = $this->userModel->getexclusiveUserListForRFQ(); $data['lead_data'] = $lead_data; $mail_content = '

Dear Sir,

Greetings From Nhance India!

Please find attached the {{RFQ_OR_QCR}} for {{POLICY_TYPE}} policy pertaining to {{CLIENT_NAME}}.

Kindly request you to share the competitive quotes at the earliest.

In case of any query, please feel free to contact us.

Thank You!


Best regards,

{{LOGGED_USER_NAME}}
Mobile: {{LOGGED_USER_MOBILE}}
Nhance Logo '; if ($data['lead_data']['policy_end_date'] != null) { $subject = "{{CLIENT_NAME}} _ {{POLICY_TYPE}} _ {{RFQ_OR_QCR}} _ {{POLICY_YEAR}} {{POLICY_END_DATE}}"; } else { $subject = "{{CLIENT_NAME}} _ {{POLICY_TYPE}} _ {{RFQ_OR_QCR}} _ {{POLICY_YEAR}}"; } if ($lead_data['policy_type_id'] == 1) { $data['totalSumAssured'] = $this->handleMemberDataGPATotalSumInsurerFromExcel(['lead_id' => $id]); } else { $data['totalSumAssured'] = []; } $data['mail_content'] = $this->transformMailContent($lead_data, $mail_content, $data['page_name']); $data['subject'] = $this->transformMailContent($lead_data, $subject, $data['page_name']); $data['placement_mail_content'] = $this->transformMailContent($lead_data, $mail_content, 'Placement'); $data['placement_subject'] = $this->transformMailContent($lead_data, $subject, 'Placement'); $data['multi_file_data'] = $this->leadFilesModel->where('lead_id', $id)->where('is_active', 1)->findAll() ?? null; $installment_data['installments'] = $this->leadInstallmentPaymentDetails->where('lead_id', $id)->where('is_active', 1)->findAll() ?? null; $data['lead_data']['installment_data'] = view('rfq/installment_fields', $installment_data) ?? null; $data['attachment_html'] = view('rfq/attachment_files', $data) ?? ""; $data['user_team'] = $this->userModel->select("ut.team_id")->join("user_teams ut", "ut.user_id = user_profiles.id and ut.is_active = 1")->where("user_profiles.is_active", 1)->first()['team_id']; // dd($data); if ($data['lead_data']['lead_form_type'] == 1) { $data['demogrphy_html_data'] = $this->generateDemographyDataTable(['lead_id' => $id]); $this->loadLayout('view_rfq.php', $data); } else if ($data['lead_data']['lead_form_type'] == 2) { $data['occupancy'] = $this->occupancyModel->findAll(); // dd($data['occupancy']); if ($lead_data['lead_type'] != 1 && $data['rfq_count'] == 0) { $client_policy_data = $this->clientPolicyModel->where('is_active', 1)->where('id', $lead_data['source_policy_id'])->first(); if (isset($client_policy_data)) { $data['rfq_data']['json'] = $client_policy_data['placement_json']; } } if (!empty($data['question_json'])) { $data['policies'] = json_decode($data['question_json'], true)['policies']; $data["child_table_data"] = json_decode($data['question_json'], true)['child_table_data']; } $data['product'] = $this->leadsModel->select("policy_type.policy_type")->join('policy_type', 'leads.policy_type_id = policy_type.id')->where('leads.id', $id)->first()['policy_type']; // $data['lead_register_data'] = json_decode($data['lead_data']['custom_fields']); // dd($data['lead_register_data']); // $data['entity_type'] = $this->kycEntityTypeModel->where('is_active', 1)->findAll(); $data['buisness_type'] = $this->buisnessType; // dd($data); $data['client_type'] = $this->clientType; $this->loadLayout('view_rfq_non_eb', $data); } } public function savePolicyInfo() { $data = $this->request->getPost(); $lead_id = $data['lead_id']; $json_data = $data['registration_json']; $existingJson = $this->RFQModel->where('is_active', 1)->where("lead_id", $lead_id)->first()['registration_json'] ?? null; if (empty($existingJson)) { $this->RFQModel ->where('lead_id', $lead_id) ->where('type', 1) ->where('is_active', 1) ->set('is_active', 0) ->update(); $insertData['lead_id'] = $lead_id; $insertData['registration_json'] = json_encode($json_data); $this->RFQModel->insert($insertData); return $this->respond(['status' => true, "message" => "Policy Inforamtion saved"]); } else { return $this->respond(['status' => true, "message" => "Policy Inforamtion Already saved"]); } } public function createRFQ() { $data = $this->request->getPost(); $lead_id = $data['lead_id'] ?? null; if (!$lead_id) { return $this->respond(['status' => false, 'message' => 'Lead ID is required'], 400); } $rfq_created = $this->RFQModel->where('lead_id', $lead_id)->where('is_active', 1)->countAllResults(); $qcr_created = false; $inputJson = json_decode($data['json'], true); if (isset($inputJson['premium_data']) && !empty($inputJson['premium_data'])) { $sortedJson = $this->reorderProposalsByInsurerTotal($inputJson); $data['json'] = json_encode($sortedJson); $qcr_created = true; } if (($data['submit_type'] ?? "") == 'QCR') { $inputJson = json_decode($data['json'], true); $proposal_data = array_pop($inputJson); if (isset($proposal_data['proposal_data']['over_all_column_data'])) { $proposel_count = $proposal_data['proposal_data']['over_all_column_data']; foreach ($proposel_count as $key => $value) { if (!empty($value['insurers'])) { $qcr_created = true; } } } } $data['type'] = 1; // Deactivate existing RFQs for this lead and type if (!isset($data['rfq_primaryKey']) && empty($data['rfq_primaryKey'])) { $this->RFQModel ->where('lead_id', $lead_id) ->where('type', 1) ->where('is_active', 1) ->set('is_active', 0) ->update(); } // Handle registration_json if (empty($data['registration_json'])) { // Fetch the latest registration_json if not provided $latest = $this->RFQModel ->select('registration_json') ->where('lead_id', $lead_id) ->orderBy('id', 'DESC') ->first(); if (!empty($latest['registration_json'])) { $data['registration_json'] = $latest['registration_json']; } } // print_r($data); die; // $data['json'] = ""; if (isset($data['rfq_primaryKey']) && !empty($data['rfq_primaryKey'])) { $this->RFQModel->update($data['rfq_primaryKey'], $data); $insertId = $data['rfq_primaryKey']; $affectedRows = db_connect()->affectedRows(); } else { // Insert new RFQ $insertId = $this->RFQModel->insert($data); } if ($insertId) { if (empty($rfq_created)) { $this->leadsModel->update($lead_id, ['status' => "rfq_created"]); } if ($qcr_created == true) { $this->leadsModel ->where('id', $lead_id) ->whereNotIn('status', ['qcr_sent', 'lost', 'co_insurer_pending', 'won', 'completed_with_corrections', 'completed_without_corrections']) ->set(['status' => "qcr_created"]) ->update(); } $message = ($data['submit_type'] ?? '') == 'QCR' ? 'QCR saved successfully' : 'RFQ saved successfully'; return $this->respond([ 'status' => true, 'id' => $insertId, 'message' => $message, 'data' => $data, 'affectedRows' => $affectedRows ?? null, ], 200); } $message = ($data['submit_type'] ?? '') == 'QCR' ? 'Failed to save QCR' : 'Failed to save RFQ'; return $this->respond([ 'status' => false, 'id' => null, 'message' => $message, 'data' => $data ], 200); } public function createQCR() { $data = $this->request->getPost(); $lead_id = $data['lead_id']; $data['type'] = 2; $this->RFQModel ->where('lead_id', $lead_id) ->where('type', 2) ->where('is_active', 1) ->set('is_active', 0) ->update(); $result = $this->RFQModel->insert($data); if ($result) { return $this->respond(['status' => true, 'id' => $result, 'message' => 'QCR created successfully', 'data' => $data], 200); } return $this->respond(['status' => false, 'id' => $result, 'message' => "Failed to create QCR", 'data' => $data], 200); } public function reorderProposalsByInsurerTotal(array $data): array { if (!isset($data['premium_data']['data'])) return $data; $original = $data['premium_data']['data']; $proposals = []; $others = []; $emptyKeyData = []; foreach ($original as $key => $value) { // Match only keys that look like 'Proposal X' if (preg_match('/^(Proposal\s+\d+|Existing Renewal|Existing Rollover)$/', $key)) { // Get the insurer entry (not 'Quote Asked') foreach ($value as $subKey => $subVal) { if ($subKey !== 'Quote Asked' && isset($subVal['Total'])) { $proposals[$key] = $value; break; } else { $proposals[$key] = $value; } } } else { if ($key === '' && isset($value['']) && is_array($value[''])) { // Capture empty key to push it later $emptyKeyData[$key] = $value; } else { $others[$key] = $value; } } } foreach ($proposals as $proposalKey => &$proposal) { $quoteAsked = $proposal['Quote Asked']; // Keep Quote Asked separately unset($proposal['Quote Asked']); uasort($proposal, function ($a, $b) { return $a['Total'] <=> $b['Total']; // Ascending by Total }); // Add Quote Asked back at the top $proposal = array_merge(['Quote Asked' => $quoteAsked], $proposal); } // Sort proposals by their insurer's total uasort($proposals, function ($a, $b) { $totalA = 0; $totalB = 0; foreach ($a as $key => $val) { if ($key !== 'Quote Asked' && isset($val['Total'])) { $totalA = floatval($val['Total']); break; } } foreach ($b as $key => $val) { if ($key !== 'Quote Asked' && isset($val['Total'])) { $totalB = floatval($val['Total']); break; } } return $totalA <=> $totalB; }); // Merge back the sorted proposals into the full structure $data['premium_data']['data'] = array_merge($others, $proposals, $emptyKeyData); $data = $this->reorderProposalDataByPremiumOrder($data); return $data; } private function reorderProposalDataByPremiumOrder(array $data): array { if (!isset($data['premium_data']['data'], $data['proposal_data']['over_all_column_data'])) { return $data; } $porposalData = $data['premium_data']['data']; $premiumProposals = array_keys($data['premium_data']['data']); $filteredProposals = []; //Reorder the Insurer based on the Premium data insurer foreach ($porposalData as $key => $value) { if(in_array($key, ['Particulars', ""])){ continue; } // Ensure the premium data is an array and not empty if (!is_array($value) || empty($value)) { continue; } // Step 1: Get the premium display_name order (excluding "Quote Asked") $premiumOrder = array_keys(array_diff_key($value, ["Quote Asked" => ""])); // Skip if no valid order found if (empty($premiumOrder)) { continue; } // usort($data['proposal_data']['over_all_column_data'][$key]['insurers'], function($a, $b) use ($premiumOrder) { // return array_search($a['display_name'], $premiumOrder) - array_search($b['display_name'], $premiumOrder); // }); // Step 2: Reorder proposal insurers based on premium order usort($data['proposal_data']['over_all_column_data'][$key]['insurers'], function($a, $b) use ($premiumOrder) { $posA = array_search($a['display_name'] ?? '', $premiumOrder); $posB = array_search($b['display_name'] ?? '', $premiumOrder); // If not found, push to the end $posA = $posA === false ? PHP_INT_MAX : $posA; $posB = $posB === false ? PHP_INT_MAX : $posB; return $posA - $posB; }); } // Collect proposal keys that match the pattern "Proposal X" foreach ($premiumProposals as $key) { if (preg_match('/^(Proposal\s+\d+|Existing Renewal|Existing Rollover)$/', $key) && isset($data['proposal_data']['over_all_column_data'][$key])) { $filteredProposals[$key] = $data['proposal_data']['over_all_column_data'][$key]; } } // dd($premiumProposals, $filteredProposals); $data['proposal_data']['over_all_column_data'] = $filteredProposals; $data = $this->reorderProposalInHeaderAndData($data); return $data; } private function reorderProposalInHeaderAndData(array $data): array { $tableData = $data['table_data']; $sortedProposalOrder = $data['proposal_data']['over_all_column_data']; $headers = $tableData['headers'] ?? []; $dataRows = $tableData['data'] ?? []; // Step 1: Separate static and proposal headers $staticHeaders = []; $proposalHeaders = []; $actionHeader = []; foreach ($headers as $header) { if (in_array($header['parentHeader'], array_keys($sortedProposalOrder))) { $proposalHeaders[$header['parentHeader']] = $header; } else { if ($header['parentHeader'] == "Action") { $actionHeader[] = $header; } else { $staticHeaders[] = $header; } } } //Reorder the SubHeader of the Proposel foreach ($sortedProposalOrder as $proposalKey => $proposalData) { // Skip if insurers or subHeaders are missing if ( !isset($proposalData['insurers']) || !is_array($proposalData['insurers']) || !isset($proposalHeaders[$proposalKey]['subHeaders']) || !is_array($proposalHeaders[$proposalKey]['subHeaders']) ) { continue; } // Keep "Quote Asked" fixed at index 0 $newSubHeaders = ["Quote Asked"]; // Add insurers in the sorted order foreach ($proposalData['insurers'] as $insurer) { if(in_array($insurer['display_name'], $proposalHeaders[$proposalKey]['subHeaders'])){ $newSubHeaders[] = $insurer['display_name']; } } // Replace the subHeaders in the header array $proposalHeaders[$proposalKey]['subHeaders'] = $newSubHeaders; } // dd($staticHeaders, $proposalHeaders, $sortedProposalOrder); // Step 2: Reorder headers $reorderedHeaders = []; foreach ($sortedProposalOrder as $proposalKey => $proposalValue) { if (isset($proposalHeaders[$proposalKey])) { $reorderedHeaders[] = $proposalHeaders[$proposalKey]; } } // print_rr($reorderedHeaders); die; $proposel_count = 1; foreach ($reorderedHeaders as $key => &$value) { if(!in_array($value['parentHeader'], ["Existing Renewal", "Existing Rollover"])){ $value['parentHeader'] = 'Proposal ' . $proposel_count; $proposel_count++; } } unset($value); //merge the all headers $reorderedHeaders = array_merge($staticHeaders, $reorderedHeaders, $actionHeader); // Step 3: Reorder each row's `data` by matching parentth foreach ($dataRows as $dataRowIndex => &$row) { $staticData = []; $proposalData = []; $actionData = []; foreach ($row['data'] as $entry) { if (in_array($entry['parentth'], array_keys($sortedProposalOrder))) { $proposalData[$entry['parentth']][] = $entry; } else { if ($entry['parentth'] == "Action") { $actionData[] = $entry; } else { $staticData[] = $entry; } } } $reorderedProposalData = []; foreach ($sortedProposalOrder as $proposalKey => $proposalValue) { if (isset($proposalData[$proposalKey])) { foreach ($proposalData[$proposalKey] as $entry) { $reorderedProposalData[] = $entry; } } } $dubParTh = ""; $increament = 0; foreach ($reorderedProposalData as $key => &$value) { if ($dubParTh == $value['parentth']) { if(!in_array($value['parentth'], ["Existing Renewal", "Existing Rollover"])){ $value['parentth'] = 'Proposal ' . ($increament); } } else { $dubParTh = $value['parentth']; if(!in_array($value['parentth'], ["Existing Renewal", "Existing Rollover"])){ $increament = $increament + 1; $value['parentth'] = 'Proposal ' . ($increament); } } } unset($value); //Reorder the Row Data based on the Insurer $reorderedProposalData = $this->reorderProposalRowData($reorderedProposalData, $proposalHeaders); // print_rr($reorderedProposalData); die; $row['data'] = array_merge($staticData, $reorderedProposalData, $actionData); } $data['table_data']['headers'] = $reorderedHeaders; $data['table_data']['data'] = $dataRows; $renumberedArray = $this->renumberProposalKeys($data['proposal_data']['over_all_column_data']); $updatedDataSet = $this->renumberProposalKeys($data['premium_data']['data']); $data['proposal_data']['over_all_column_data'] = !empty($renumberedArray) ? $renumberedArray : $data['proposal_data']['over_all_column_data']; $data['premium_data']['data'] = !empty($updatedDataSet) ? $updatedDataSet : $data['premium_data']['data']; return $data; } private function reorderProposalRowData(array $proposalRowData, array $proposalHeaderData): array { $newRowData = []; // Group rows by parentth $groupedRows = []; foreach ($proposalRowData as $row) { if (!isset($row['parentth'])) { continue; // skip invalid rows } $groupedRows[$row['parentth']][] = $row; } // Reorder each group's rows based on header subHeaders foreach ($proposalHeaderData as $proposalKey => $headerInfo) { if ( !isset($groupedRows[$proposalKey]) || !isset($headerInfo['subHeaders']) || !is_array($headerInfo['subHeaders']) ) { continue; } $order = $headerInfo['subHeaders']; $rows = $groupedRows[$proposalKey]; // Sort whole rows according to subth position in $order usort($rows, function ($a, $b) use ($order) { return array_search($a['subth'], $order) - array_search($b['subth'], $order); }); // Append sorted rows to final array $newRowData = array_merge($newRowData, $rows); } return $newRowData; } private function renumberProposalKeys(array $input): array { $result = []; $counter = 1; foreach ($input as $key => $value) { if (strpos($key, 'Proposal') === 0) { $newKey = 'Proposal ' . $counter++; $result[$newKey] = $value; } else { $result[$key] = $value; } } return $result; } public function removeInstallments() { $id = $this->request->getGet('id'); // print_r($id); die; if (!empty($id)) { $this->leadInstallmentPaymentDetails->whereIn('id', $id)->set(['is_active' => 0])->update(); } else { return $this->respond(['status' => false, 'message' => 'Could not be removed.'], 200); } if ($this->request->getGet('lead_id')) { $lead_id = $this->request->getGet('lead_id'); $data = [ 'no_of_installment' => 0, 'is_installment' => 0 ]; $this->leadsModel->where('id', $lead_id)->set($data)->update(); } return $this->respond(['status' => true, 'message' => 'Removed successfully'], 200); } //-----RFQ and QCR EXPORT------------------------------------------------------------------------------------------------ //export main route function public function exportQCRandRFQ($lead_id, $type, $lead_form_type) { $this->exportExcelForQCRandRFQ($lead_id, $type, $lead_form_type); } //FOR EXCEL public function exportExcelForQCRandRFQ($lead_id, $type, $lead_form_type = 1) { if ($lead_form_type == 2) { $filepath = $this->constructNonEbExcelToSaveTemp($lead_id, $type); } else { $filepath = $this->constructExcelToSaveTemp($lead_id, $type); } $lead_data = $this->RFQModel->getRFQTableDataWithLeadIDAndType($lead_id, $type); // dd($filepath); //Excel merging part if ($lead_data['file_name'] != null && $lead_data['file_name'] != '') { $temp_file_path = $filepath['filePath']; $temp_file_name = $filepath['fileName']; $lead_file_path = WRITEPATH . 'uploads/lead_files/' . $lead_data['file_name']; // dd($lead_data, $temp_file_path, $temp_file_name, $lead_file_path); if ($lead_file_path) { $filePaths = [ ['file_path' => $temp_file_path, 'sheets' => []], ['file_path' => $lead_file_path, 'sheets' => []] ]; // $outputPath = dirname($temp_file_path) . '/' . 'merged_' . $temp_file_name; $result = ExcelMergeHelper::mergeExcelFiles($filePaths, $temp_file_path); // print_rr($result); } } $filepath = $filepath['filePath']; if (file_exists($filepath)) { // Set headers to force download header('Content-Description: File Transfer'); header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); header('Content-Disposition: attachment; filename="' . basename($filepath) . '"'); header('Content-Length: ' . filesize($filepath)); header('Pragma: public'); // Output the file content readfile($filepath); // Delete the file after download unlink($filepath); exit; } else { echo "File does not exist."; } } //Construct excel file and save the file to the folder and return file path public function constructExcelToSaveTemp($lead_id, $type, $propsal_and_insurer = null) { helper('excel_util_helper'); $rfq_data = $this->RFQModel->getRFQTableDataWithLeadIDAndType($lead_id, $type); $is_placement = false; $length = 0; // dd($rfq_data, $lead_id, $type, $propsal_and_insurer); // print_r($propsal_and_insurer); die; if ($rfq_data['lead_type'] == 1) { if (in_array($rfq_data['policy_type_id'], [2, 3, 4, 5])) { $lead_data = [ 'Insured' => $rfq_data['client_name'], 'Policy Type' => $this->leadType[$rfq_data['lead_type']] ?? "", 'No of Employees' => $rfq_data['incept_emp_count'], 'No of Dependents' => $rfq_data['incept_dept_count'], 'Total Lives' => $rfq_data['incept_no_of_lives'], 'Period of Insurance ' => !empty($rfq_data['policy_start_date']) && !empty($rfq_data['policy_end_date']) ? date('d-m-Y', strtotime($rfq_data['policy_start_date'])) . ' to ' . date('d-m-Y', strtotime($rfq_data['policy_end_date'])) : "To be decided", // 'Insurer' => $rfq_data['insurer_name'] ?? " - ", // 'TPA' => $rfq_data['tpa_name'] ?? " - ", // 'Policy Run Days' => $rfq_data['policy_run_days'], ]; } else if (in_array($rfq_data['policy_type_id'], [1, 6, 7])) { $lead_data = [ 'Insured' => $rfq_data['client_name'], 'No of Employees at Inception' => $rfq_data['incept_emp_count'], // 'Total Sum Insured at Inception ' => $rfq_data['total_si_at_incept'], 'Policy Period' => !empty($rfq_data['policy_start_date']) && !empty($rfq_data['policy_end_date']) ? date('d-m-Y', strtotime($rfq_data['policy_start_date'])) . ' to ' . date('d-m-Y', strtotime($rfq_data['policy_end_date'])) : "To be decided", // 'Insurer' => $rfq_data['insurer_name'] ?? " - ", // 'TPA' => $rfq_data['tpa_name'] ?? " - ", 'Policy Type' => $this->leadType[$rfq_data['lead_type']] ?? "", ]; } } else { if (in_array($rfq_data['policy_type_id'], [2, 3, 4, 5])) { $lead_data = [ 'Insured' => $rfq_data['client_name'], 'Policy Type' => $this->leadType[$rfq_data['lead_type']] ?? "", 'No of Employees at Inception' => $rfq_data['incept_emp_count'], 'No of Dependents at Inception' => $rfq_data['incept_dept_count'], 'Total Lives at Inception ' => $rfq_data['incept_no_of_lives'], 'No of Employees at Expiry' => $rfq_data['exp_emp_count'], 'No of Dependents at Expiry' => $rfq_data['exp_dept_count'], 'Total Lives at Expiry ' => $rfq_data['exp_no_of_lives'], 'No of Employees at Renewal' => $rfq_data['renewal_emp_count'], 'No of Dependents at Renewal' => $rfq_data['renewal_dept_count'], 'Total Lives at Renewal ' => $rfq_data['renewal_no_of_lives'], 'Period of Insurance ' => !empty($rfq_data['policy_start_date']) && !empty($rfq_data['policy_end_date']) ? date('d-m-Y', strtotime($rfq_data['policy_start_date'])) . ' to ' . date('d-m-Y', strtotime($rfq_data['policy_end_date'])) : "To be decided", 'Insurer' => $rfq_data['insurer_name'] ?? " - ", 'TPA' => $rfq_data['tpa_name'] ?? " - ", 'Policy Run Days' => $rfq_data['policy_run_days'], 'Inception Premium' => formatIndianCurrency($rfq_data['premium_at_inception']), 'Premium as on (' . date('d-m-Y', strtotime($rfq_data['incurred_claims_date'])) . ')' => formatIndianCurrency($rfq_data['premium_date']), 'Earned Premium' => formatIndianCurrency(intval($rfq_data['earned_premium'])), 'Incurred Claims as on (' . date('d-m-Y', strtotime($rfq_data['incurred_claims_date'])) . ')' => formatIndianCurrency($rfq_data['incurred_claims']), 'Annualised Claims' => formatIndianCurrency(intval($rfq_data['annualised_claims'])), 'Incurred Claims Ratio' => $rfq_data['incurred_claims_ratio'] . " %", 'Earned Claims Ratio' => $rfq_data['earned_claims_ratio'] . " %", ]; } else if (in_array($rfq_data['policy_type_id'], [1, 6, 7])) { $lead_data = [ 'Insured' => $rfq_data['client_name'], 'No of Employees at Inception' => $rfq_data['incept_emp_count'], 'Total Lives at Inception' => $rfq_data['total_lives_at_incept'], 'Total Sum Insured at Inception' => $rfq_data['total_si_at_incept'], 'Premium at inception' => $rfq_data['premium_at_incept'], 'No of Employees at Renewal' => $rfq_data['renewal_emp_count'], 'Total Sum Insured at Renewal ' => $rfq_data['total_si_at_renewal'], 'Policy Period' => !empty($rfq_data['policy_start_date']) && !empty($rfq_data['policy_end_date']) ? date('d-m-Y', strtotime($rfq_data['policy_start_date'])) . ' to ' . date('d-m-Y', strtotime($rfq_data['policy_end_date'])) : "To be decided", // 'Insurer' => $rfq_data['insurer_name'] ?? " - ", // 'TPA' => $rfq_data['tpa_name'] ?? " - ", 'Policy Type' => $this->leadType[$rfq_data['lead_type']] ?? "", 'Existing Insurer' => $rfq_data['insurer_name'], // 'TPA ' => $rfq_data['tpa_name'], ]; } } $data = json_decode($rfq_data['json'], true); // dd($data); $sheetName = 'Worksheet'; if ($type == 2) { $sheetName = 'QCR'; // $propsal_and_insurer = "Proposal 1-ICICIPRU-ICICI001"; $data = $this->convertJsonForQCR($data, $type); if ($propsal_and_insurer !== null) { list($proposal_key, $insurer_key) = explode('-', $propsal_and_insurer, 2); $data = $this->transformProposelData($data, $proposal_key, $insurer_key); $is_placement = true; $sheetName = 'Placement'; } } else if ($type == 1) { $sheetName = 'RFQ'; $data = $this->convertJsonForQCR($data, $type); // dd($data); } // dd($data); $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $sheet->setTitle($sheetName); // Start with lead_data at the top $rowNumber = 1; $mergeRange1 = "A{$rowNumber}:B{$rowNumber}"; // $sheet->mergeCells($mergeRange1); $sheet->setCellValue("A{$rowNumber}", "Nhance India Insurance Broking Pvt Ltd"); $sheet->getStyle("A{$rowNumber}")->applyFromArray([ 'font' => [ 'bold' => true, 'size' => 23 ], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, ], ]); // Apply center alignment to the cell // $sheet->getStyle("C{$rowNumber}")->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER); // $sheet->getStyle("C{$rowNumber}")->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER); $rowNumber = $rowNumber + 1; // Initialize max width tracking variables $maxWidthA = 0; $maxWidthB = 0; foreach ($lead_data as $key => $value) { // Merge A:B for key and C:D for value $mergeRangeKey = "A{$rowNumber}:B{$rowNumber}"; // $mergeRangeValue = "C{$rowNumber}"; $sheet->mergeCells($mergeRangeKey); // $sheet->mergeCells($mergeRangeValue); // Set values in merged cells $sheet->setCellValue("A{$rowNumber}", $key); $sheet->setCellValue("C{$rowNumber}", $value); // // Apply styles for alignment and bold text in A:B // $sheet->getStyle($mergeRangeKey)->applyFromArray([ // 'font' => ['bold' => true], // 'alignment' => [ // 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, // 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, // ], // ]); // Apply bold style to B column if the key is "Insured" if ($key == "Insured") { $sheet->getStyle("C{$rowNumber}")->applyFromArray([ 'font' => ['bold' => true], ]); } // Track max width needed for columns $maxWidthA = max($maxWidthA, mb_strlen($key)); $maxWidthB = max($maxWidthB, mb_strlen($value)); $rowNumber++; } // Set column width based on max content length (adjusted for padding) $sheet->getColumnDimension('A')->setWidth($maxWidthA * 1.2); // $sheet->getColumnDimension('B')->setWidth($maxWidthA * 1.5); $sheet->getColumnDimension('C')->setWidth(35); // $rowNumber += 2; // Add headers and subheaders $headers = $data['table_data']['headers']; $sheet->setCellValue("A{$rowNumber}", "Details of Coverage"); $sheet->getStyle("A{$rowNumber}")->applyFromArray([ 'font' => [ 'bold' => true, ], 'fill' => [ 'fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => 'ADD8E6'], ], 'borders' => [ 'allBorders' => [ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN, 'color' => ['argb' => 'FF000000'], // Black color ], ], ]); if($type == 2){ $subheader_count = array_sum( array_map( fn($header) => count(array_filter( $header['subHeaders'], fn($sub) => $sub !== "Quote Asked" )), $data['table_data']['headers'] ) ); }else{ $subheader_count = array_sum(array_map(fn($header) => count($header['subHeaders']), $data['table_data']['headers'])); } if ($is_placement == false) { $subheader_count = $subheader_count - 2; } $headerCount = count($data['table_data']['headers']); $lastColumn = Coordinate::stringFromColumnIndex($subheader_count); // dd( $headerCount, $lastColumn); // Merge cells from A to the last column $mergeRange = "A{$rowNumber}:{$lastColumn}{$rowNumber}"; $sheet->getStyle($mergeRange)->applyFromArray([ 'borders' => [ 'allBorders' => [ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN, 'color' => ['argb' => 'FF000000'], // Black color ], ], ]); $sheet->mergeCells($mergeRange); $rowNumber_for_remove_quote_asked = $rowNumber; $rowNumber = $rowNumber + 1; if ($type == 2) { $subHeaderRow = $rowNumber + 1; } else { // $subHeaderRow = $rowNumber_for_remove_quote_asked; $subHeaderRow = $rowNumber + 1; } $columnLetter = 'A'; $header_actual_count = 0; $headerIndex = 0; foreach ($headers as $header) { // Kint::dump($header); if($is_placement == true){ //for placement proposal only $nxt_ro = $rowNumber + 1; $sheet->mergeCells("C{$rowNumber}:C{$nxt_ro}"); } if (in_array($header['parentHeader'], ['Item Key', 'Action'])) { continue; } if (!in_array($header['parentHeader'], ['Item Key', 'Action', 'Sno', 'Particulars'])) { $header_actual_count++; //Quote asked not showed in the QCR excel so some proposel has only one Quote Asked, So that case avoid the proposel name $subHeaderCount = count($header['subHeaders'] ?? []) ?? 0; if($subHeaderCount <= 1 && $type == 2 && $is_placement == false){ // print_rr($header); continue; } } if ($header['parentHeader'] === 'Sno') { $header['parentHeader'] = 'S.No.'; $sheet->getColumnDimension('A')->setWidth(10); //merge the 2 row cells of the S.No. $nxt_ro = $rowNumber + 1; $sheet->mergeCells("{$columnLetter}{$rowNumber}:{$columnLetter}{$nxt_ro}"); } if ($header['parentHeader'] === 'Particulars') { $sheet->getColumnDimension('B')->setWidth(35); //merge the 2 row cells of the particulars $nxt_ro = $rowNumber + 1; $sheet->mergeCells("{$columnLetter}{$rowNumber}:{$columnLetter}{$nxt_ro}"); } $startColumn = $columnLetter; // Start of the current header range if($type == 2){ $subHeaderCount = count(array_filter($header['subHeaders'], function($subHeader) { return $subHeader !== "Quote Asked"; })); }else{ $subHeaderCount = count($header['subHeaders']); // Number of subheaders for this parent header } // Set parent header value if ($is_placement == true && !in_array($header['parentHeader'], ['Particulars', 'S.No.'])) { $sheet->setCellValue("{$startColumn}{$rowNumber}", "Terms"); } else { if(in_array($header['parentHeader'], ["Existing Renewal", "Existing Rollover"])){ $sheet->setCellValue("{$startColumn}{$rowNumber}", "Existing Terms"); }else if(in_array($header['parentHeader'], ["Particulars", "S.No."])){ $sheet->setCellValue("{$startColumn}{$rowNumber}", $header['parentHeader']); }else{ $headerIndex = $headerIndex + 1; $sheet->setCellValue("{$startColumn}{$rowNumber}", "Proposal Terms " . $headerIndex); } } $sheet->getStyle("{$startColumn}{$rowNumber}")->applyFromArray([ 'font' => ['bold' => true], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, ], ]); // Merge header cells if it spans multiple subheaders if ($subHeaderCount > 1) { $endColumn = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($startColumn) + $subHeaderCount - 1); $sheet->mergeCells("{$startColumn}{$rowNumber}:{$endColumn}{$rowNumber}"); } else { $endColumn = $startColumn; // No merge needed if only one subheader } // Add subheaders foreach ($header['subHeaders'] as $subHeader) { if($type == 2 && in_array($subHeader, ['Quote Asked'])){ continue; } if ($is_placement == false) { $sheet->setCellValue("{$columnLetter}{$subHeaderRow}", $subHeader); } if ($columnLetter != "A" && $columnLetter != "B" && $columnLetter != "C") { $sheet->getColumnDimension($columnLetter)->setWidth(35); } else { $sheet->getColumnDimension('A')->setWidth(10); } if ($is_placement == false) { $sheet->getStyle("{$columnLetter}{$subHeaderRow}")->applyFromArray([ 'font' => ['bold' => true], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, ], ]); } $columnLetter++; // Move to the next column for subheaders // Kint::dump($subHeader); $length++; } } if($header_actual_count == 1 && $type == 1){ $sheet->getColumnDimension('B')->setWidth(80); }else{ $sheet->getColumnDimension('B')->setWidth(35); } // Apply border to the header range $prevColumn1 = $this->getPreviousColumn($columnLetter); $headerRange = "A{$rowNumber}:" . "{$prevColumn1}" . "{$subHeaderRow}"; $sheet->getStyle($headerRange)->applyFromArray([ 'borders' => [ 'allBorders' => [ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN, 'color' => ['argb' => 'FF000000'], // Black color ], ], ]); // Increase row height for headers and subheaders $sheet->getRowDimension($rowNumber)->setRowHeight(25); // Header row height $sheet->getRowDimension($subHeaderRow)->setRowHeight(20); // Subheader row height if ($is_placement == true) { $rowNumber = $subHeaderRow + 1; } else { $rowNumber = $subHeaderRow + 1; } // dd($rowNumber); $column_data = $data['table_data']['data']; $serial_no = 1; $maxColumnWidths = []; // Add table data rows foreach ($column_data as $dataRow) { $columnLetter = 'A'; foreach ($dataRow['data'] as $cellData) { if (in_array($cellData['parentth'], ['Item Key', 'Action'])) { continue; } if($type == 2 && in_array($cellData['subth'], ['Quote Asked'])){ continue; } if ($cellData['parentth'] == 'Sno') { $sheet->setCellValue("{$columnLetter}{$rowNumber}", $serial_no); } else { $sheet->setCellValue("{$columnLetter}{$rowNumber}", $cellData['value']); } $columnLetter++; } $rowNumber++; $serial_no++; } $prevColumn2 = $this->getPreviousColumn($columnLetter); $dataRange = "A" . ($subHeaderRow + 1) . ":" . "{$prevColumn2}" . ($rowNumber - 1); $sheet->getStyle($dataRange)->applyFromArray([ 'borders' => [ 'allBorders' => [ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN, 'color' => ['argb' => 'FF000000'], // Black color ], ], ]); //premium data if ($type == 2) { if($is_placement == true){$columnLetterForPremium = "B";}else{$columnLetterForPremium = "B";} $rowNumber += 2; // Add premium data // dd($data); // $labelArray = ["Premium", "GST (%)", "GST Amount (₹)", "Total"]; $labelArray = ["Premium", "GST Amount (₹)", "Total"]; $premiumData = $data['premium_data']['data']; // dd($premiumData); // $premium = [$labelArray[0]]; // $gst = [$labelArray[1]]; // $gstAmt = [$labelArray[1]]; // $total = [$labelArray[2]]; // if($is_placement == true){ $premium[] = $labelArray[0]; $gstAmt[] = $labelArray[1]; $total[] = $labelArray[2]; // } foreach ($premiumData as $proposal => $insurers) { if ($proposal != 'Particulars') { foreach ($insurers as $insurer => $values) { if($insurer == 'Quote Asked'){ // $premium[] = count($insurers ?? []) > 1 ? $labelArray[0] : ""; // $gst[] = ""; // $gstAmt[] = count($insurers ?? []) > 1 ? $labelArray[1] : ""; // $total[] = count($insurers ?? []) > 1 ? $labelArray[2] : ""; }else{ $premium[] = formatIndianCurrency($values[$labelArray[0]]); // $gst[] = $values[$labelArray[1]]; $gstAmt[] = formatIndianCurrency($values[$labelArray[1]]); $total[] = formatIndianCurrency($values[$labelArray[2]]); } } } } // dd([$premium, $gstAmt, $total]); die; foreach ([$premium, $gstAmt, $total] as $index => $rowData) { $columnLetter = $columnLetterForPremium; foreach ($rowData as $key => $value) { $sheet->setCellValue("{$columnLetter}{$rowNumber}", $value); if (in_array($value, $labelArray)) { $sheet->getStyle("{$columnLetter}{$rowNumber}")->applyFromArray(['font' => ['bold' => true,],]); } $columnLetter++; } $rowNumber++; } if ($is_placement == true) { $prevColumn3 = $this->getPreviousColumn($columnLetter); } else { $prevColumn3 = $this->getPreviousColumn($columnLetter, 2); } $premiumRange = $columnLetterForPremium . ($rowNumber - 3) . ":" . "{$prevColumn3}" . ($rowNumber - 1); // dd($prevColumn3, $premiumRange, $this->getPreviousColumn($columnLetter, 2), $columnLetter, $rowNumber); $sheet->getStyle($premiumRange)->applyFromArray([ 'borders' => [ 'allBorders' => [ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN, 'color' => ['argb' => 'FF000000'], // Black color ], ], ]); } //set imgage and align the row and column if ($type == 2) { if ($is_placement == true) { $columnLetter_img = $this->getPreviousColumn($columnLetter); } else { $columnLetter_img = $this->getPreviousColumn($columnLetter, 2); } } else { $columnLetter_img = $this->getPreviousColumn($columnLetter); } $company_name = $this->getPreviousColumn($columnLetter_img); $mergeRange1 = "A1:{$company_name}1"; $sheet->mergeCells($mergeRange1); $rowCount = count($lead_data); for ($i = 2; $i <= $rowCount + 1; $i++) { $mergeRange1 = "C{$i}:{$columnLetter_img}{$i}"; $sheet->mergeCells($mergeRange1); $sheet->getStyle($mergeRange1)->applyFromArray([ 'borders' => [ 'allBorders' => [ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN, 'color' => ['argb' => 'FF000000'], // Black color ], ], ]); } $sheet->getColumnDimension($columnLetter_img)->setWidth(35); $sheet->getRowDimension(1)->setRowHeight(50); // Adjust as needed $drawing = new Drawing(); $path = ROOTPATH . "public/assets/images/Nhance-Logo-Final.png"; // Use FCPATH for server path $drawing->setPath($path); $drawing->setCoordinates("{$columnLetter_img}1"); // Set position in column B $drawing->setHeight(35); // Adjust image $offsetX = 35; $drawing->setOffsetX($offsetX); // Adjust horizontal offset $drawing->setOffsetY(10); // Adjust vertical offset $drawing->setWorksheet($sheet); //end // Auto-size columns // foreach ($sheet->getColumnIterator() as $column) { // $sheet->getColumnDimension($column->getColumnIndex())->setAutoSize(true); // } $dataRange = $sheet->calculateWorksheetDimension(); $sheet->getStyle($dataRange)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER)->setVertical(Alignment::VERTICAL_CENTER)->setWrapText(true); $sheet->getStyle('A1')->applyFromArray([ 'alignment' => [ 'wrapText' => false, // Disables text wrapping for A1 ], ]); // Apply border to the entire sheet preg_match('/([A-Z]+)(\d+):([A-Z]+)(\d+)/', $dataRange, $matches); if ($matches) { $startColumn = $matches[1]; // A $startRow = $matches[2]; // 1 $endColumn = $matches[3]; // G $endRow = $matches[4]; // 75 // Convert column letter to index, reduce by 1, and convert back $endColumnIndex = Coordinate::columnIndexFromString($endColumn) - 1; $newEndColumn = Coordinate::stringFromColumnIndex($endColumnIndex); // Generate the new range (e.g., "A1:F75" instead of "A1:G75") $newDataRange = "{$startColumn}{$startRow}:{$newEndColumn}{$endRow}"; // $sheet->getStyle($newDataRange)->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN); } $lastRow = count($lead_data) + 1; $leadRange = "A1:{$columnLetter_img}{$lastRow}"; $sheet->getStyle($leadRange)->applyFromArray([ 'borders' => [ 'allBorders' => [ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN, 'color' => ['argb' => 'FF000000'], // Black color ], ], ]); // Set filename $string = ($type == 2) ? ($is_placement == true ? 'Placement' : 'QCR') : 'RFQ'; $current_year = date('Y'); $next_year = $current_year + 1; $policy_year = "$current_year-$next_year"; if (!empty($rfq_data['policy_end_date'])) { $policy_expiry = strtotime($rfq_data['policy_end_date']); $formatted_policy = date("d-m-Y", $policy_expiry); $filename = "{$rfq_data['client_name']}_{$rfq_data['policy_type']}_{$string}_" . $policy_year . '(Due On ' . $formatted_policy . ')' . '.xlsx'; } else { $filename = "{$rfq_data['client_name']}_{$rfq_data['policy_type']}_{$string}_" . $policy_year . '_' . '.xlsx'; } //claim history new sheet; if (!empty($rfq_data['fin_years_claims'])) { $claim_details = json_decode($rfq_data['fin_years_claims'], true) ?? []; if (!empty($claim_details['finyear'])) { // Get headers dynamically $headers = array_map(function ($key) { return ucwords(str_replace('_', ' ', $key)); }, array_keys($claim_details['finyear'][0])); $newSheet = new Worksheet($spreadsheet, 'Claims Experience'); $spreadsheet->addSheet($newSheet); $spreadsheet->setActiveSheetIndexByName('Claims Experience'); $sheet = $spreadsheet->getActiveSheet(); // Set headers $sheet->fromArray($headers, NULL, 'A1'); // Apply background color and bold style to headers $headerCellRange = 'A1:' . chr(64 + count($headers)) . '1'; // e.g., A1:G1 $sheet->getStyle($headerCellRange)->getFont()->setBold(true); $sheet->getStyle($headerCellRange)->getFill()->setFillType(Fill::FILL_SOLID)->getStartColor()->setRGB('ADD8E6'); // Add border to header $sheet->getStyle($headerCellRange)->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN); // Fill data and apply borders $row = 2; foreach ($claim_details['finyear'] as $record) { $col = 'A'; foreach ($record as $value) { $label = ucwords(str_replace('_', ' ', ($value ?? ""))); $sheet->setCellValue($col . $row, $label); $col++; } // Apply border to each data row $sheet->getStyle('A' . $row . ':' . chr(64 + count($headers)) . $row) ->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN); $row++; } // Auto-size all columns based on header count for ($i = 0; $i < count($headers); $i++) { $colLetter = chr(65 + $i); // 'A', 'B', etc. $sheet->getColumnDimension($colLetter)->setAutoSize(true); } // Enable wrap text for all cells $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: 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; $writer = new Xlsx($spreadsheet); $writer->save($uploadFilePath); return [ 'filePath' => $uploadFilePath, 'fileName' => $filename, ]; } //Merge RFQ/QCR file with lead members file public function mergeQuoteExcelFileWithMembersListExcelFile($lead_id, $type, $source_file_path) { $rfq_data = $this->RFQModel->getRFQTableDataWithLeadIDAndType($lead_id, $type); if ($source_file_path && $rfq_data['file_name']) { } return true; } public function calculateMembersDemography($params, $returnType = null) { $lead_id = $params['lead_id']; $lead_data = $this->leadsModel->find($lead_id); $file_name_with_path = WRITEPATH . "/uploads/lead_files/" . $lead_data['file_name']; if (!$lead_data) { return ['status' => 'failed', 'message' => 'Lead data not found']; } if ($lead_data['file_name']) { // $file_name_with_path = WRITEPATH . "/uploads/lead_files/NonPrintableCharacters.xlsx"; //check physical file if (!file_exists($file_name_with_path)) { //file not found update status and reason $message = "Lead Physcial file not found"; // echo $message; $this->myLogger->logme('error', ($message . ' for file ' . $file_name_with_path)); return ['status' => 'failed', 'message' => 'no physical file']; } $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path); //get members data $members_sheet = $spreadsheet->getSheet(0); $highestRowAndColumn = $members_sheet->getHighestRowAndColumn(); // dd($highestRowAndColumn); $uncleaned_members = $members_sheet->rangeToArray('A1:' . $highestRowAndColumn['column'] . $highestRowAndColumn['row']); $members = ExcelSanitizeHelper::sanitizeArrayData($uncleaned_members); //get age band data $age_band_sheet = $spreadsheet->getSheet(1); $highestRowAndColumn = $age_band_sheet->getHighestRowAndColumn(); $age_band_data = $age_band_sheet->rangeToArray('A1:' . $highestRowAndColumn['column'] . $highestRowAndColumn['row']); //check age or dob column $members_heading = $members[0]; $available_col = null; $col_index = null; if (in_array('age', array_map('strtolower', $members_heading))) { $available_col = 'age'; $col_index = array_search('age', array_map('strtolower', $members_heading)); } elseif (in_array('dob', array_map('strtolower', $members_heading))) { $available_col = 'dob'; $col_index = array_search('dob', array_map('strtolower', $members_heading)); } if ($available_col == null) { $message = 'No DOB or Age column '; $this->myLogger->logme('error', ($message . $file_name_with_path)); return ['status' => 'failed', 'message' => $message]; } try { $classifiers = $this->getDemographyData($members, $age_band_data, $members_heading, $available_col, $col_index); } catch (Exception $e) { return ['status' => 'fail', 'message' => $e->getMessage()]; } //for this to view the demography in the RFQ and QCR page to using internal if($returnType == "internal"){ return ['data' => $classifiers]; // print_rr($classifiers); die; } try { $result = $this->generateClassifierSpreadsheet($classifiers, WRITEPATH . 'uploads/lead_files/'); if ($result['success']) { $this->myLogger->logme('error', "Spreadsheet generated successfully!"); echo "Location: " . $result['fullpath'] . "\n"; echo "Filename: " . $result['filename'] . "\n"; $filePaths = [ ['file_path' => WRITEPATH . 'uploads/lead_files/' . $lead_data['file_name'], 'sheets' => [0, 1]], ['file_path' => WRITEPATH . '/uploads/lead_files/' . $result['filename'], 'sheets' => []], ]; $outputPath = WRITEPATH . 'uploads/lead_files/' . $lead_data['file_name']; $result_merge = ExcelMergeHelper::mergeExcelFiles($filePaths, $outputPath); if ($result_merge) { // Call the delete function after the file is successfully created $deleteResponse = $this->deleteGeneratedFile($result['fullpath']); // Add delete message to response $response['deleteMessage'] = $deleteResponse['message']; return ['status' => 'success', 'message' => 'Member_Data Merged Suceesfully']; } } else { echo "Error generating spreadsheet: " . $result['error']; } } catch (Exception $e) { echo "Error: " . $e->getMessage(); return ['status' => 'fail', 'message' => $e->getMessage()]; } } else { $this->myLogger->logme('error', (' no file found ' . $file_name_with_path)); return ['status' => 'failed', 'message' => 'no file found']; } } public function getDemographyData($members, $age_band_data, $members_heading, $available_col, $col_index) { $first_loop = 0; // $col_index_si = array_search('si enhancement', array_map('strtolower', $members_heading)); $col_index_si = array_search('si', array_map('strtolower', $members_heading)); $col_index_relationship = array_search('relationship', array_map('strtolower', $members_heading)); $relations = []; $si_amt = ['general']; // Initialize with 'general' as per first loop condition // First pass - collect unique relations and SI amounts foreach ($members as $member) { if ($first_loop == 0) { $first_loop++; continue; } if ($member == null) { continue; } if (!in_array($member[$col_index_relationship], $relations) && $member[$col_index_relationship] != null) { $relations[] = $member[$col_index_relationship]; } if (!in_array($member[$col_index_si], $si_amt) && $member[$col_index_si] != null) { $si_amt[] = $member[$col_index_si]; } } // Initialize classifier array $classifiers = []; foreach ($si_amt as $si) { $classifiers[$si] = []; // Initialize relation counts including Grand Total row foreach ($relations as $relation) { $classifiers[$si][$relation] = []; foreach ($age_band_data as $age_bands) { foreach ($age_bands as $age_interval) { $classifiers[$si][$relation][$age_interval] = 0; } } // Add Grand Total column for each relation echo('test passed 3.5'); $classifiers[$si][$relation]['Grand Total'] = 0; } // Initialize Grand Total row $classifiers[$si]['Grand Total'] = []; foreach ($age_band_data as $age_bands) { foreach ($age_bands as $age_interval) { $classifiers[$si]['Grand Total'][$age_interval] = 0; } } // Add grand total of grand totals $classifiers[$si]['Grand Total']['Grand Total'] = 0; } // Process members and count them foreach ($members as $member) { if ($first_loop == 0) { $first_loop++; continue; } // Get age $age = $this->getAge($available_col, $member, $col_index); $relation = $member[$col_index_relationship]; $member_si = $member[$col_index_si]; // Find the correct age band (only once per member) $found_band = false; foreach ($age_band_data as $age_bands) { if ($found_band) break; foreach ($age_bands as $age_band) { //get Min and Max Age list($min_age, $max_age) = $this->getAgeRange($age_band); // If age fits in this band if ($age >= $min_age && $age <= $max_age) { // Update counts for general category if (isset($classifiers['general'][$relation][$age_band])) { // Increment count for specific relation and age band $classifiers['general'][$relation][$age_band]++; // Update row total (Grand Total column) $classifiers['general'][$relation]['Grand Total']++; // Update column total (Grand Total row) $classifiers['general']['Grand Total'][$age_band]++; // Update grand total of grand totals $classifiers['general']['Grand Total']['Grand Total']++; } // Update counts for specific SI category if (isset($classifiers[$member_si][$relation][$age_band])) { // Increment count for specific relation and age band $classifiers[$member_si][$relation][$age_band]++; // Update row total (Grand Total column) $classifiers[$member_si][$relation]['Grand Total']++; // Update column total (Grand Total row) $classifiers[$member_si]['Grand Total'][$age_band]++; // Update grand total of grand totals $classifiers[$member_si]['Grand Total']['Grand Total']++; } $found_band = true; break; } } } } return $classifiers; } public function generateClassifierSpreadsheet($classifiers, $outputDir = 'exports') { if (!file_exists($outputDir)) { if (!mkdir($outputDir, 0755, true)) { throw new Exception("Failed to create directory: $outputDir"); } } // Check if directory is writable if (!is_writable($outputDir)) { throw new Exception("Directory is not writable: $outputDir"); } // Generate unique filename $timestamp = date('Y-m-d_His'); $filename = "member_classification_{$timestamp}.xlsx"; $filepath = $outputDir . DIRECTORY_SEPARATOR . $filename; // Check if file already exists (shouldn't happen with timestamp, but just in case) if (file_exists($filepath)) { $counter = 1; while (file_exists($outputDir . DIRECTORY_SEPARATOR . "member_classification_{$timestamp}_{$counter}.xlsx")) { $counter++; } $filename = "member_classification_{$timestamp}_{$counter}.xlsx"; $filepath = $outputDir . DIRECTORY_SEPARATOR . $filename; } $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $sheet->setTitle('Demography_Data'); // Get all age bands $age_bands = array_keys(reset($classifiers['general'])); array_pop($age_bands); // Remove 'Grand Total' $age_bands[] = 'Grand Total'; // Add it back at the end $currentRow = 5; // Start from row 5 to match the example // Function to write section data $writeSectionData = function ($data, $sheet, &$currentRow, $si_type) use ($age_bands) { // Add section header for the SI type $sheet->setCellValue('B' . $currentRow, strtoupper($si_type)); // Style section header $sheet->getStyle('B' . $currentRow)->applyFromArray([ 'font' => ['bold' => true, 'size' => 14], 'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER], ]); $currentRow++; // Move to the next row after the section header // Set headers for the data table $sheet->setCellValue('B' . $currentRow, 'Relationship'); $col = 'C'; foreach ($age_bands as $band) { $sheet->setCellValue($col . $currentRow, $band); $col++; } // Style headers $lastCol = chr(ord('B') + count($age_bands)); $headerRange = 'B' . $currentRow . ':' . $lastCol . $currentRow; $sheet->getStyle($headerRange)->applyFromArray([ 'font' => ['bold' => true], 'borders' => [ 'allBorders' => [ 'borderStyle' => Border::BORDER_THIN, 'color' => ['rgb' => '000000'], ], ], 'alignment' => [ 'horizontal' => Alignment::HORIZONTAL_CENTER, ], ]); $currentRow++; // Write data rows foreach ($data as $relation => $values) { if ($relation !== 'Grand Total') { $sheet->setCellValue('B' . $currentRow, $relation); $col = 'C'; foreach ($age_bands as $band) { $value = $values[$band] ?: ''; // Convert 0 to empty string $sheet->setCellValue($col . $currentRow, $value); $col++; } // Style data row $dataRange = 'B' . $currentRow . ':' . $lastCol . $currentRow; $sheet->getStyle($dataRange)->applyFromArray([ 'borders' => [ 'allBorders' => [ 'borderStyle' => Border::BORDER_THIN, 'color' => ['rgb' => '000000'], ], ], 'alignment' => [ 'horizontal' => Alignment::HORIZONTAL_CENTER, ], ]); $currentRow++; } } // Add Grand Total row $sheet->setCellValue('B' . $currentRow, 'Grand Total'); $col = 'C'; foreach ($age_bands as $band) { $sheet->setCellValue($col . $currentRow, $data['Grand Total'][$band]); $col++; } // Style Grand Total row $totalRange = 'B' . $currentRow . ':' . $lastCol . $currentRow; $sheet->getStyle($totalRange)->applyFromArray([ 'font' => ['bold' => true], 'borders' => [ 'allBorders' => [ 'borderStyle' => Border::BORDER_THIN, 'color' => ['rgb' => '000000'], ], ], 'fill' => [ 'fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => 'F2F2F2'], ], 'alignment' => [ 'horizontal' => Alignment::HORIZONTAL_CENTER, ], ]); $currentRow += 3; // Add gap after each section }; // Write each SI section with gaps foreach ($classifiers as $si_type => $data) { $writeSectionData($data, $sheet, $currentRow, $si_type); } // Auto-size columns foreach (range('B', chr(ord('B') + count($age_bands))) as $col) { $sheet->getColumnDimension($col)->setAutoSize(true); } // Create Excel file try { // Create Excel file $writer = new Xlsx($spreadsheet); $writer->save($filepath); // Verify file was created successfully if (!file_exists($filepath)) { throw new Exception("Failed to create file: $filepath"); } // Return the file info after creation $response = [ 'success' => true, 'filepath' => $filepath, 'filename' => $filename, 'fullpath' => realpath($filepath) ]; return $response; } catch (Exception $e) { return [ 'success' => false, 'error' => $e->getMessage() ]; } } // Function to delete generated file public function deleteGeneratedFile($filePath) { try { if (file_exists($filePath)) { unlink($filePath); // Delete the file return [ 'success' => true, 'message' => "File deleted successfully" ]; } else { return [ 'success' => false, 'message' => "File does not exist" ]; } } catch (Exception $e) { return [ 'success' => false, 'error' => $e->getMessage() ]; } } public function getAge($available_col, $member, $col_index) { if ($available_col == 'age') { $age = $member[$col_index]; } else { $dob = $member[$col_index]; if ($dob == 'DOB') { return; } $dobDate = \DateTime::createFromFormat('d-M-Y', $dob); $currentDate = new \DateTime(); if ($dobDate == false) { $this->myLogger->logme('error', $dob . 'is not valid'); return; } $age = $currentDate->diff($dobDate)->y; } return $age; } public function getAgeRange($age_band) { $age_band = trim($age_band); // Parse age range if (strpos($age_band, '-') === false) { $min_age = (int)filter_var($age_band, FILTER_SANITIZE_NUMBER_INT); $max_age = PHP_INT_MAX; } else { $parts = explode("-", $age_band); $min_age = (int)$parts[0]; $max_age = (int)$parts[1]; } return array($min_age, $max_age); } //this funciton for send mail to insurer and client with either RFQ/QCR public function sendMailWithAttachement() { helper('excel_util_helper'); helper('MailHelper'); helper('ExcelMergeHelper'); $params = $this->request->getPost(); // print_r($params); die; $lead_id = $params['lead_id']; $file_type = $params['file_type']; //rfq or qcr $recipient_type = $params['recipient_type']; //insurer or client or internal or placement $recipient_mail = $params['recipient_mail']; // - only primary key of contacts $recipient_mail = json_decode($params['recipient_mail'], true); // - only primary key of contacts $propsal_and_insurer = isset($params['proposal_insurer']) ? $params['proposal_insurer'] : null; $mail_content = $params['mail_content']; $mail_subject = $params['subject']; $attachment_file_ids = $params['selected_attachment_files']; $from_mail = getenv('email.fromEmail'); if (in_array($recipient_type, ['placement', 'insurer', 'internal'])) { $from_mail = "im@nhanceindia.in"; } else if (in_array($recipient_type, ['client'])) { $from_mail = "bs@nhanceindia.in"; } if ($recipient_type === 'placement') { $lead_data = $this->leadsModel->find($lead_id); $data = []; if (!empty($params['policy_start_date'])) { $converted_start = change_date_format($params['policy_start_date']); // converts to Y-m-d if ($converted_start !== $lead_data['policy_start_date']) { $data['policy_start_date'] = $converted_start; } } if (!empty($params['policy_end_date'])) { $converted_end = change_date_format($params['policy_end_date']); // converts to Y-m-d if ($converted_end !== $lead_data['policy_end_date']) { $data['policy_end_date'] = $converted_end; } } if (!empty($data)) { $this->leadsModel->update($lead_id, $data); } } $result_data = []; // dd($recipient_mail); if ($recipient_type == 'insurer' && (!is_array($recipient_mail) || count($recipient_mail) == 0)) { return $this->respond(['status' => 'failed', 'code' => 400, 'data' => '', 'messgae' => 'Recipient mail not found ! '], 200); } // dd(); //gather lead info $lead_data = $this->leadsModel ->select('leads.*,policy_type.long_name,policy_type.policy_type,user_profiles.email as created_person_email') ->join('policy_type', 'leads.policy_type_id = policy_type.id', 'left') ->join('user_profiles', 'leads.created_by = user_profiles.id', 'left') ->where('leads.id', $lead_id) ->first(); // log_message('error', 'Lead Data' . json_encode($lead_data)); // print_r($lead_data ); die; $cc_mails = []; $bcc_mails = []; //get CC Mails if ($recipient_type == 'internal' || $recipient_type == 'insurer' || $recipient_type == 'client') { $cc_data = isset($params['cc']) ? $params['cc'] : ""; $param_cc_mail = json_decode($cc_data, true); if (isset($param_cc_mail) && is_array($param_cc_mail) && count($param_cc_mail) > 0) { // Fetch user data where ID is in the param_cc_mail array $userData = $this->userModel ->where('is_active', 1) ->whereIn('id', $param_cc_mail) ->findAll(); // print_r($userData); die; // Extract emails from the fetched user data $cc_mails = array_column($userData, 'email'); // print_r(json_encode($cc_mails)); die; // If no emails were found, return an error response // if (empty($cc_mails)) { // return $this->respond(['status' => 'failed','code' => 400,'data' => '','message' => 'No valid CC mail addresses found!'], 200); // } } else { // Handle case where param_cc_mail is not valid // return $this->respond(['status' => 'failed','code' => 400,'data' => '','message' => 'CC mail not found!'], 200); } } else if ($recipient_type == 'placement') { $cc_mails = isset($params['cc']) ? json_decode($params['cc'], true) : ""; } //get BCC Mails if ($recipient_type == 'insurer' || $recipient_type == 'client') { $bcc_data = isset($params['bcc']) ? $params['bcc'] : ""; $param_bcc_mail = json_decode($bcc_data, true); if (isset($param_bcc_mail) && is_array($param_bcc_mail) && count($param_bcc_mail) > 0) { // Fetch user data where ID is in the param_cc_mail array $userData = $this->userModel ->where('is_active', 1) ->whereIn('id', $param_bcc_mail) ->findAll(); // print_r($userData); die; // Extract emails from the fetched user data $bcc_mails = array_column($userData, 'email'); // print_r(json_encode($cc_mails)); die; // If no emails were found, return an error response // if (empty($cc_mails)) { // return $this->respond(['status' => 'failed','code' => 400,'data' => '','message' => 'No valid CC mail addresses found!'], 200); // } } else { // Handle case where param_cc_mail is not valid // return $this->respond(['status' => 'failed','code' => 400,'data' => '','message' => 'CC mail not found!'], 200); } } if ($recipient_type == 'client' && ($lead_data['contact_person_email'] == '' || $lead_data['contact_person_email'] == null)) { return $this->respond(['status' => 'failed', 'code' => 400, 'data' => '', 'messgae' => 'Recipient mail not found ! '], 200); } // dd($lead_data); $reply_to = $lead_data['created_person_email'] ?? ""; //get file path to attach if ($lead_data["lead_form_type"] == 2) { $file_info = $this->constructNonEbExcelToSaveTemp($lead_id, ($file_type == 'rfq' ? 1 : 2), $propsal_and_insurer); } else { $file_info = $this->constructExcelToSaveTemp($lead_id, ($file_type == 'rfq' ? 1 : 2), $propsal_and_insurer); } // $file_info = $this->constructExcelToSaveTemp($lead_id, ($file_type == 'rfq' ? 1 : 2), $propsal_and_insurer); log_message('error', 'File Info' . json_encode($file_info)); if ($lead_data['file_name'] != null && $lead_data['file_name'] != '') { $temp_file_path = $file_info['filePath']; $temp_file_name = $file_info['fileName']; $lead_file_path = WRITEPATH . 'uploads/lead_files/' . $lead_data['file_name']; if ($lead_file_path) { $filePaths = [ ['file_path' => $temp_file_path, 'sheets' => []], ['file_path' => $lead_file_path, 'sheets' => []] ]; $outputPath = dirname($temp_file_path) . '/' . $temp_file_name; $result = ExcelMergeHelper::mergeExcelFiles($filePaths, $outputPath); // print_rr($result); } } else { $result = $file_info['filePath']; // return $this->respond(['status' => 'fail', 'code' => 200, 'messgae' => 'File Not Found'], 200); } // print_rr($result); die; // print_rr($file_info); // $file_path = WRITEPATH."uploads/excel/sample/correction.xls"; // $file_name = $file_type.'.xlsx'; // !dd($file_info); $file_path = $result; $file_name = basename($result); // Attacments part $attachments = [['fileName' => $file_name, 'filePath' => $file_path]]; $other_attachments = $this->handleMultiFileAttachments($attachment_file_ids, $lead_id); $attachments = array_merge($attachments, $other_attachments); // print_r($attachments); die; //get recipient address if ($recipient_type == 'insurer' || $recipient_type == 'placement') { $recipient_data = $this->levelContactModel ->where(['contact_type' => 'insurer', 'is_active' => 1]) ->whereIn('id', $recipient_mail) ->findAll(); } else if ($recipient_type == 'client') { $mailIDS = explode(',', $params['contact_mail']); $recipient_data = []; foreach ($mailIDS as $mail) { $recipient_data[] = ['name' => $lead_data['contact_person_name'], 'email' => $mail]; } } else { $recipient_data = [['name' => "Team", 'email' => $params['to']]]; } // print_r($recipient_data); die; $subject = $file_type == 'rfq' ? 'Request for Quotation from ' . $lead_data['client_name'] . ' for ' . $lead_data['policy_type'] : 'Quotation Comparison Report for ' . $lead_data['policy_type']; $original_message = '

Request for Quotation (RFQ)

Dear {{RECIPIENT_NAME}},

We are reaching out to request a quotation for the following insurance coverage. Please review the details below and provide your quote at your earliest convenience.

RFQ Details

Client name{{CLIENT_NAME}}
Coverage Type{{POLICY_LONG_NAME}}
Policy Start Date{{POLICY_START_DATE}}
Policy Duration{{DURATION}}
Please note: Additional terms and details are included in the attachment for your reference.

Please feel free to reach out if you require any further information to prepare the quote. We look forward to receiving your proposal.

Best regards,

Nhance India Pvt Ltd

© Nhance India Pvt Ltd. All rights reserved.

'; //for mail content if (!empty($mail_content)) { $original_message = $mail_content; } //for mail subject if (!empty($mail_subject)) { $subject = $mail_subject; } // print_r($subject); die; if ($recipient_data) { foreach ($recipient_data as $recipient) { $message = $original_message; $message = str_replace("{{RECIPIENT_NAME}}", $recipient['name'] != "" ? $recipient['name'] : " ", $message); $message = str_replace("{{CLIENT_NAME}}", $lead_data['client_name'] != "" ? $lead_data['client_name'] : "", $message); $message = str_replace("{{POLICY_LONG_NAME}}", $lead_data['long_name'] != "" ? $lead_data['long_name'] : "", $message); $message = str_replace("{{POLICY_START_DATE}}", change_date_format($lead_data['policy_start_date'], 'Y-m-d', 'd-m-Y'), $message); $message = str_replace("{{DURATION}}", calculate_days_bw_dates($lead_data['policy_end_date'] ?? "", $lead_data['policy_start_date'] ?? "")->days, $message) ?? '--'; // print_rr($message);calculate_days_bw_dates $string = implode(", ", $cc_mails); $bcc_string = implode(", ", $bcc_mails); $res = MailHelper::send_email(['from_mail' => $from_mail, 'mail' => $recipient['email'], 'cc' => $string, 'subject' => $subject, 'message' => $message, 'attachments' => $attachments, 'reply_to' => $reply_to, 'bcc' => $bcc_string]); // !dd($res); $result_data[] = ['mail' => $recipient['email'], 'status' => $res]; } } $is_placement = false; if ($recipient_type == 'placement') { $is_placement = true; list($proposal_key, $insurer_key) = explode('-', $propsal_and_insurer, 2); $lead_update_data = [ 'proposel_name' => $proposal_key, 'insurer_name' => $insurer_key, 'insurer' => $params['insurer_and_branch'], ]; $data = [ 'proposel_data' => json_encode($lead_update_data), 'status' => 'won', '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, ]; $this->leadsModel->where('id', $lead_id)->set($data)->update(); if (isset($params['installments']) && !empty($params['installments'])) { $installment_data = json_decode($params['installments'], true); if (!empty($installment_data)) { foreach ($installment_data as $key => $value) { // print_r($value);die $value['payment_date'] = !empty($value['payment_date']) && strtotime($value['payment_date']) ? date('Y/m/d', strtotime($value['payment_date'])) : null; if (isset($value['id']) && !empty($value['id'])) { $this->leadInstallmentPaymentDetails->where('id', $value['id'])->set($value)->update(); } else { $this->leadInstallmentPaymentDetails->insert($value); } } } } } if ($recipient_type == 'client') { $this->leadsModel ->where('id', $lead_id) ->whereNotIn('status', ['lost', 'co_insurer_pending', 'won', 'completed_with_corrections', 'completed_without_corrections']) ->set(['status' => "qcr_sent"]) ->update(); } if ($recipient_type == 'insurer') { $this->leadsModel ->where('id', $lead_id) ->whereNotIn('status', ['qcr_created', 'qcr_sent', 'lost', 'co_insurer_pending', 'won', 'completed_with_corrections', 'completed_without_corrections']) ->set(['status' => "rfq_sent"]) ->update(); } //delete attachment file unlink($file_path); return $this->respond(['status' => 'success', 'code' => 200, 'data' => $result_data, 'is_placement' => $is_placement], 200); } public function getLevelContects() { $data = $this->levelContactModel->getContactForRFQ(); if ($data) { return $this->respond(['status' => true, 'data' => $data], 200); } else { return $this->respond(['status' => false], 200); } } public function getInsurerBranchContacts($insurer_and_branch_id) { if (strpos($insurer_and_branch_id, '-') === false) { return $this->respond(['status' => false, 'message' => 'Invalid ID format'], 400); } // Split the insurer_and_branch_id list($insurerBranchId, $insurerId) = explode('-', $insurer_and_branch_id); $data = $this->levelContactModel->getContactForRFQ($insurerId, $insurerBranchId); if (!empty($data)) { return $this->respond(['status' => true, 'data' => $data], 200); } else { return $this->respond(['status' => false, 'data' => $data, 'message' => 'No contacts were found for the selected insurer.'], 200); } } public function transformProposelData($data, $proposel, $insurer) { // print_r($data['premium_data']['data']); die; $headerData = []; // Default headers: S. No and Particulars $defaultHeaders = [ [ 'parentHeader' => 'Sno', 'subHeaders' => ['-'] ], [ 'parentHeader' => 'Particulars', 'subHeaders' => ['-'] ] ]; // Add default headers to the result $headerData = array_merge($headerData, $defaultHeaders); foreach ($data['table_data']['headers'] as $header) { // Check if the parentHeader matches the target proposal if ($header['parentHeader'] === $proposel) { // Check if subHeaders contain the target insurer key foreach ($header['subHeaders'] as $subHeader) { if ($subHeader === $insurer) { $headerData[] = [ 'parentHeader' => $header['parentHeader'], 'subHeaders' => [ // 'Quote Asked', // Default value $subHeader // Matched insurer key ] ]; break; } } } } $columnData = []; foreach ($data['table_data']['data'] as $entry) { $sno = $entry['SNO']; $items = $entry['items']; $dataEntry = $entry['data']; $result = [ "SNO" => $sno, "items" => $items, "data" => [] ]; foreach ($dataEntry as $item) { // Include Sno and Particulars by default if (in_array($item['parentth'], ['Sno', 'Particulars'])) { $result['data'][] = [ "parentth" => $item['parentth'], "subth" => $item['subth'], "value" => $item['value'], "input_value" => $item['input_value'] ]; } // Include Proposal with Quote Asked by default /* For proposel do not remove it */ // if ($item['parentth'] === $proposel && $item['subth'] === "Quote Asked") { // $result['data'][] = [ // "parentth" => $item['parentth'], // "subth" => $item['subth'], // "value" => $item['value'], // "input_value" => $item['input_value'] // ]; // } // Example of including matching specific proposals and insurers if ($item['parentth'] === $proposel && $item['subth'] === $insurer) { $result['data'][] = [ "parentth" => $item['parentth'], "subth" => $item['subth'], "value" => $item['value'], "input_value" => $item['input_value'] ]; } } // Add to the final result $columnData[] = $result; } $premiumData = []; foreach ($data['premium_data']['data'] as $key => $value) { if ($key === $proposel) { // $premiumData[$key]['Quote Asked'] = $value['Quote Asked']; $premiumData[$key][$insurer] = $value[$insurer]; } } $data['table_data']['headers'] = $headerData; $data['table_data']['data'] = $columnData; $data['premium_data']['data'] = $premiumData; return $data; } public function convertJsonForQCR($json, $type) { if ($json) { // Deep copy of JSON $first_json = json_decode(json_encode($json), true); // dd($first_json); if ($type == 2) { // Column-wise Check: Remove headers and relevant data if qcr == 0 foreach ($json['proposal_data']['over_all_column_data'] as $proposalKey => $proposalData) { if (($proposalData['qcr'] == 0 || $proposalData['qcr'] === false) || ($proposalData['stc'] == 0 || $proposalData['stc'] === false)) { // Remove matching parentHeader in headers foreach ($first_json['table_data']['headers'] as $index => $header) { if ($header['parentHeader'] === $proposalKey) { unset($first_json['table_data']['headers'][$index]); } } // Remove data entries with matching parentth foreach ($first_json['table_data']['data'] as &$item) { $item['data'] = array_values(array_filter($item['data'], function ($entry) use ($proposalKey) { return $entry['parentth'] !== $proposalKey; })); } // Remove proposalKey from over_all_column_data unset($first_json['proposal_data']['over_all_column_data'][$proposalKey]); if ($type == 2) { // Remove proposalKey from premium_data unset($first_json['premium_data']['data'][$proposalKey]); } } // Insurer Check: Remove subHeaders and relevant data for insurers with qcr == 0 foreach ($proposalData['insurers'] as $insurerIndex => $insurer) { if (($insurer['qcr'] === 0 || $insurer['qcr'] === false) || ($insurer['stc'] === 0 || $insurer['stc'] === false)) { foreach ($first_json['table_data']['headers'] as &$header) { if (isset($header['subHeaders'])) { $header['subHeaders'] = array_values(array_filter($header['subHeaders'], function ($sub) use ($insurer) { return $sub !== $insurer['display_name']; })); } } foreach ($first_json['table_data']['data'] as &$item) { $item['data'] = array_values(array_filter($item['data'], function ($entry) use ($insurer) { return $entry['subth'] !== $insurer['display_name']; })); } // Remove insurer from proposal's insurers array unset($first_json['proposal_data']['over_all_column_data'][$proposalKey]['insurers'][$insurerIndex]); if ($type == 2) { unset($first_json['premium_data']['data'][$proposalKey][$insurer['display_name']]); } } } } // Row-wise Check: Remove rows if qcr == 0 for actions foreach ($first_json['table_data']['data'] as $rowKey => $rowData) { foreach ($rowData['data'] as $data) { if ($data['parentth'] === "Action" && (isset($data['input_value']['qcr']) && $data['input_value']['qcr'] == 0) || (isset($data['input_value']['stc']) && $data['input_value']['stc'] == 0)) { unset($first_json['table_data']['data'][$rowKey]); break; } } } // Reindex arrays to maintain proper structure $first_json['table_data']['headers'] = array_values($first_json['table_data']['headers']); $first_json['table_data']['data'] = array_values($first_json['table_data']['data']); $first_json['proposal_data']['over_all_column_data'] = array_map(function ($proposal) { $proposal['insurers'] = array_values($proposal['insurers']); return $proposal; }, $first_json['proposal_data']['over_all_column_data']); } else { //remove insurer as Subheaders for RFQ foreach ($first_json['table_data']['headers'] as &$header) { $header['subHeaders'] = array_filter($header['subHeaders'], function ($subHeader) { return in_array($subHeader, ['Quote Asked', '-']); }); } //Remove insurer Row wise data for RFQ foreach ($first_json['table_data']['data'] as &$row) { // Filter the inner data array $row['data'] = array_filter( $row['data'], function ($item) { return in_array($item['subth'], ['Quote Asked', '-']); } ); $row['data'] = array_values($row['data']); } // Ensure to unset the reference after the loop unset($row); // Remove insurers from Proposal Data key for RFQ foreach ($first_json['proposal_data']['over_all_column_data'] as $key => &$proposal) { if (isset($proposal['insurers'])) { // Set the insurers array to empty $proposal['insurers'] = []; } } // Ensure to reset the reference unset($proposal); } return $first_json; } return null; } //----- Featch Lead data and insert Client ------------------------------------------------------------------------------------------- public function featchLeadDataAndInsertClient($lead_id) { try { $data = $this->leadsModel->where('leads.id', $lead_id)->where('leads.is_active', 1)->first(); if (!$data) { $this->myLogger->logme('featchLeadDataAndInsertClient', "Lead not found or inactive", ['lead_id' => $lead_id]); return $this->respond(['status' => false, 'message' => 'Failed to create Client', 'data' => null], 200); } $result = $this->createClientWithLeadData($data); if ($result) { $policy_data = $this->clientPolicyModel->where('client_id', $result)->where('is_active', 1)->first(); return $this->respond([ 'status' => true, 'message' => 'New Client created successfully', 'client_id' => $result, 'data' => $data, 'client_policy_id' => $policy_data['id'] ?? null, ], 200); } $this->myLogger->logme('featchLeadDataAndInsertClient', "Client creation failed after processing", ['lead_id' => $lead_id]); return $this->respond(['status' => false, 'message' => 'Failed to create client', 'data' => $data], 200); } catch (\Throwable $e) { $this->myLogger->logme('error', 'featchLeadDataAndInsertClient failed'); return $this->respond(['status' => false, 'message' => 'Internal server error', 'error' => $e->getMessage()], 500); } } public function createClientWithLeadData($data) { try { $client_data = $this->prepareClientData($data); $client_id = $this->clientModel->insert($client_data); if ($client_id) { $this->createClientBranchAndContactWithLeadData($data, $client_id); $this->leadsModel->where('id', $data['id'])->set('is_client_created', $client_id)->update(); } return $client_id; } catch (\Throwable $e) { $this->myLogger->logme('error', 'createClientWithLeadData failed'); return false; } } public function createClientBranchAndContactWithLeadData($data, $client_id) { try { $branch_data = $this->prepareClientBranchData($data, $client_id); $branch_id = $this->clientBranchModel->insert($branch_data); if ($branch_id) { $this->leadsModel->where('id', $data['id'])->set('is_client_created', $client_id)->update(); $contact_data = $this->prepareContactData($data, $branch_id); $this->levelContactModel->insert($contact_data); $this->createClientPolicyWithLeadData($data, $client_id, $branch_id); } return $branch_id; } catch (\Throwable $e) { $this->myLogger->logme('error', 'createClientBranchAndContactWithLeadData failed'); return false; } } public function createClientPolicyWithLeadData($data, $client_id, $branch_id) { try { $client_policy_data = $this->prepareClientPolicyData($data, $client_id, $branch_id); $client_policy_id = $this->clientPolicyModel->insert($client_policy_data); if ($client_policy_id) { $this->leadsModel->where('id', $data['id'])->set('is_client_created', $client_id)->update(); $this->leadsModel->where('id', $data['id'])->set('is_policy_created', $client_policy_id)->update(); } return $client_policy_id; } catch (\Throwable $e) { $this->myLogger->logme('error', 'createClientPolicyWithLeadData failed'); return false; } } private function prepareClientData($data) { return [ 'client_type' => $data['client_type'] ?? null, 'entity_type_id' => $data['entity_type_id'] ?? null, 'client_code' => $data['client_code'] ?? null, 'client_name' => $data['client_name'] ?? null, 'short_name' => $data['client_short_name'] ?? null, 'pan' => $data['pan'] ?? null, ]; } private function prepareClientBranchData($data, $client_id) { $default_unit = trim(($data['client_short_name'] ?? '') . '-' . ($data['branch_code'] ?? ''), '-'); return [ 'client_id' => $client_id, 'branch_name' => $data['branch_name'], 'branch_code' => $data['branch_code'], 'gst' => $data['gst'], 'units' => json_encode([$default_unit]), ]; } private function prepareContactData($data, $branch_id) { return [ 'name' => $data['contact_person_name'], 'mobile' => $data['contact_person_mobile'], 'email' => $data['contact_person_email'], 'contact_type' => 'client', 'ref_id' => $branch_id, ]; } private function prepareClientPolicyData($data, $client_id, $branch_id) { $proposel_data = json_decode($data['proposel_data'], true); // print_r($proposel_data); die; list($insurer_branch_id, $insurer_id) = explode('-', $proposel_data['insurer'], 2); $client_policy_data = [ 'client_id' => $client_id, 'client_branch_id' => $branch_id, 'policy_type_id' => $data['policy_type_id'], 'insurer_id' => $insurer_id, 'insurer_branch_id' => $insurer_branch_id, 'tpa_id' => $data['tpa_id'], 'tpa_branch_id' => $data['tpa_branch_id'], 'policy_start_date' => $data['policy_start_date'], 'policy_end_date' => $data['policy_end_date'], 'policy_status' => 1, ]; $policy_type_id = $data['policy_type_id']; if (in_array($policy_type_id, [1, 2, 6, 7])) { $client_policy_data['is_addon'] = 1; // Base Policy } elseif (in_array($policy_type_id, [4, 5])) { $client_policy_data['is_addon'] = 2; // SI TOPUP } elseif ($policy_type_id == 3) { // if ($base_policy) { // $data['is_addon'] = 3; // Dependent Addon // } else { $data['is_addon'] = 1; // } } if ($data['lead_form_type'] == 1) { $client_policy_data['policy_terms'] = $this->preparePolicyTermsFromRFQ($data); } else { $placementJson = $this->getPlacementJson($data); if ($placementJson) { $client_policy_data['placement_json'] = $placementJson; $client_policy_data['policy_terms'] = $this->convertNonEbQCRJsonToPolicyTerms(json_decode($placementJson, true)); } } // print_r($client_policy_data); die; return $client_policy_data; } private function preparePolicyTermsFromRFQ($data) { try { $proposel_data = json_decode($data['proposel_data'], true); $QCRData = $this->RFQModel->where('is_active', 1)->where('lead_id', $data['id'])->first(); if (!$QCRData) { throw new \Exception('RFQ Data not found'); } $JSON = json_decode($QCRData['json'], true); $converted_json = $this->transformProposelData($JSON, $proposel_data['proposel_name'], $proposel_data['insurer_name']); // log_message('error', 'Converted JSON: ' . json_encode($converted_json)); return $this->convertQCRJsonToPolicyTerms($converted_json, $data['policy_type_id'], $proposel_data['proposel_name'], $proposel_data['insurer_name']); } catch (\Throwable $e) { $this->myLogger->logme('error', 'preparePolicyTermsFromRFQ'); return null; } } public function featchClientPolicyFromLead($client_id, $branch_id, $lead_id) { $data = $this->leadsModel->where('leads.id', $lead_id)->where('leads.is_active', 1)->first(); if (!$data) { return $this->respond(['status' => false, 'message' => 'Failed to create policy', 'data' => null], 200); } $result = $this->createClientPolicyWithLeadData($data, $client_id, $branch_id); // print_r($result); die; if ($result) { $policy_data = $this->clientPolicyModel->where('id', $result)->where('is_active', 1)->first(); return $this->respond(['status' => true, 'message' => 'New Policy created successfully', 'client_policy_id' => $result, 'data' => $data, 'client_id' => $policy_data['client_id']], 200); } return $this->respond(['status' => false, 'message' => 'Failed to create policy', 'data' => $data], 200); } // --------------------------------------------------------------------------------------------------------------- //Function for convert the RFQ and QCR Json to Policy Terms Json public function convertQCRJsonToPolicyTerms($data, $policy_type, $proposel_name, $insurer_name) { //transform the data into the currernt proposel and insurere ( get single proposel ) $data = $this->transformProposelData($data, $proposel_name, $insurer_name); // Initialize age_ratio based on policy type $age_ratio = $policy_type == 2 ? [ 'self' => ['min' => '18', 'max' => '60'], 'spouse' => ['min' => 0, 'max' => 0], 'child' => ['min' => 0, 'max' => '25'], 'elders' => ['min' => 0, 'max' => 0], ] : [ 'self' => ['min' => '18', 'max' => '60'] ]; foreach ($data['table_data']['data'] as $dataRow) { $item = $dataRow['items'] ?? ''; foreach ($dataRow['data'] as $cellData) { $parentth = $cellData['parentth'] ?? ''; $subth = $cellData['subth'] ?? ''; $input_value = $cellData['input_value'] != "" ? $cellData['input_value'] : ($cellData['value'] ?? ''); $value = $cellData['value'] ?? ''; // Skip unwanted keys if (in_array($parentth, ['Sno', 'Item Key', 'Particulars', 'Action']) || in_array($subth, ['Quote Asked'])) { continue; } switch (true) { // CASE 1: Handle special conditions case str_starts_with($item, 'special_condition') && $parentth === $proposel_name && $subth === $insurer_name: // log_message("error","INPUT".json_encode($input_value)); $parts = explode('-', $input_value); $labelKey = $policy_type == 1 ? 'gpa_special_condition_label' : 'special_condition_label'; $inputKey = $policy_type == 1 ? 'gpa_special_condition_input' : 'special_condition_input'; $terms_array[$labelKey][] = $parts[0] ?? ''; $terms_array[$inputKey][] = $parts[1] ?? ''; break; // CASE 2: Handle sum insured case in_array($item, ['sum_insured', 'sumInsured2']): $si_amt = explode(',', $value); $terms_array[$item] = $si_amt[0] ?? ''; $terms_array['multiple_sum_insured'] = array_slice($si_amt, 1); // Add age_ratio after Sum insured if ($policy_type == 1) { $terms_array['age_ratio'] = $age_ratio; } break; // CASE 3: Handle family floaters case $item === 'family_composition': $terms_array['family_floaters'] = isJsonString($input_value) ? json_decode($input_value, true) : $input_value; // Add age_ratio after family floaters if ($policy_type == 2) { $terms_array['age_ratio'] = $age_ratio; } break; // DEFAULT CASE : default: // $terms_array[$item] = isJsonString($input_value) ? (json_decode($input_value, true)['key'] ?? '') : $value; $terms_array[$item] = $value; break; } } } return json_encode($terms_array); } public function convertNonEbQCRJsonToPolicyTerms($allTableData) { if (!empty($allTableData)) { array_pop($allTableData); // Remove the last item from the array $terms_array = []; foreach ($allTableData as $TableIndex => $tableGroup) { if ($TableIndex == 0) { continue; } foreach ($tableGroup['table_data']['data'] as $dataRow) { $item = $dataRow['items'] ?? ''; foreach ($dataRow['data'] as $cellData) { $parentth = $cellData['parentth'] ?? ''; $subth = $cellData['subth'] ?? ''; $value = $cellData['display_content'] ?? ''; // Skip unwanted keys if (in_array($parentth, ['SNO', 'Particulars', 'Action']) || $subth === 'Sum Insured' || $subth === 'Fidelity Limit') { continue; } // Skip if item matches parentth if ($item === $parentth) { continue; } // Set the value directly, overwriting with latest encountered if (!empty($item) && !empty($value)) { $finalItem = $item; if (strpos($tableGroup['tableId'], 'summary') !== false) { $policy_type = explode('_', $tableGroup['tableId'])[0] ?? ''; $finalItem = $policy_type . ' - ' . $item; } $terms_array[$finalItem] = $value; } } } } return json_encode($terms_array); } else { return null; } } public function getPlacementJson(array $data): ?string { $proposel_data = json_decode($data['proposel_data'], true); $QCRData = $this->RFQModel ->where('is_active', 1) ->where('lead_id', $data['id']) ->first(); if (!$QCRData || empty($QCRData['json'])) { return null; } $jsonArray = json_decode($QCRData['json'], true); $proposalData = array_pop($jsonArray); // Get last item and remove it from the array if (empty($jsonArray)) { return null; } $placement_json_data = array_map(function ($jsonData) use ($proposel_data) { return $this->transformNonEbProposelData( $jsonData, $proposel_data['proposel_name'] ?? '', $proposel_data['insurer_name'] ?? '', null, 1 ); }, $jsonArray); if (!empty($proposalData)) { foreach ($proposalData['proposal_data']['over_all_column_data'] as $key => &$proposal) { // Keep only the required proposal if ($key !== $proposel_data['proposel_name']) { unset($proposalData['proposal_data']['over_all_column_data'][$key]); } else { // Within the matched proposal, filter insurers if (!empty($proposal['insurers'])) { $proposal['insurers'] = array_values(array_filter($proposal['insurers'], function ($insurer) use ($proposel_data) { return $insurer['display_name'] === $proposel_data['insurer_name']; })); } } } unset($proposal); // Good practice after foreach by reference } $placement_json_data[] = $proposalData; return json_encode($placement_json_data); } //------------------------------------------------------------------------------------------------ public function transformMailContent($lead_data, $mail_content, $page_name) { $current_year = date('Y'); $next_year = $current_year + 1; $policy_year = "$current_year-$next_year"; $page_name = $page_name == "QCR" ? "Quote Comparison Report" : $page_name; $log_path = base_url() . '/public/assets/images/Nhance-Logo-Final.png'; // $log_path ='https://venbait.in/nhance/dev/public/assets/images/Nhance-Logo-Final.png'; // dd($log_path); $policy_expiry = strtotime($lead_data['policy_end_date']); $formatted_policy = date("d-m-Y", $policy_expiry); $logged_user_id = get_session_userid(); $logged_user_data = $this->userModel->where("id", $logged_user_id)->where("is_active", 1)->first(); if ($lead_data) { // Replacing placeholders with actual values $message = $mail_content; $message = str_replace("{{CLIENT_NAME}}", $lead_data['client_name'] ?? "Valued Client", $message); $message = str_replace("{{POLICY_LONG_NAME}}", $lead_data['long_name'] ?? $lead_data['policy_type'] ?? "Insurance Policy", $message); $message = str_replace("{{POLICY_TYPE}}", $lead_data['policy_type'] ?? "Insurance Policy", $message); $message = str_replace("{{RFQ_OR_QCR}}", $page_name, $message); $message = str_replace("{{POLICY_YEAR}}", $policy_year, $message); $message = str_replace("{{POLICY_END_DATE}}", " (Due On " . $formatted_policy . ")", $message); $message = str_replace("{{LOGGED_USER_NAME}}", ucfirst($logged_user_data['first_name']) . " " . ucfirst($logged_user_data['last_name']), $message); $message = str_replace("{{LOGGED_USER_EMAIL}}", $logged_user_data['email'], $message); $message = str_replace("{{LOGGED_USER_MOBILE}}", $logged_user_data['mobile'], $message); $message = str_replace("{{LOGO_PATH}}", $log_path, $message); return $message; } else { return ''; // Return empty if no lead data found } } public function getLastFiveFinancialYears() { $currentYear = date('Y'); $currentMonth = date('m'); // In India, the financial year starts from April (04) if ($currentMonth < 4) { $currentYear--; // Adjust year if it's Jan-Mar } $financialYears = []; for ($i = 0; $i < 5; $i++) { $startYear = $currentYear - $i - 1; $endYear = $currentYear - $i; $financialYears[] = "$startYear-$endYear"; } return $financialYears; } // ------------ RFQ NON EB FUNCTIONS----------------------------------------------------------------------------------------- public function rfqNonEB() { $this->loadLayout('view_rfq_non_eb'); } // get lead data for edit bot EB and NON-EB public function getLeadNonEB($type, $id = null) { // Set basic data $data = [ 'issuer' => $this->issuer, 'client_type' => $this->clientType, 'lead_type' => $this->leadType, 'lead_status' => $this->leadsStatus, 'policy_type' => $this->policyTypeModel->where('is_active', 1)->findAll(), 'entity' => $this->kycEntityTypeModel->where('is_active', 1)->findAll(), 'insurer' => $this->insurerBranchModel->getInsurerBranchesWithInsurerNames(), 'tpa' => $this->tpaBranchModel->getTpaBranchesWithTpaNames(), 'lastFiveYears' => $this->getLastFiveFinancialYears(), 'gpaClaimType' => $this->claim_type_for_gpa, 'causeOfDeath' => $this->cause_of_death, 'selected_lead_type' => $type, ]; // Fetch sales team members who are active in team 5 $data['salse_team'] = $this->userModel ->select('user_profiles.*') ->join('user_teams', 'user_profiles.id = user_teams.user_id') ->where('user_teams.team_id', 5) ->where('user_teams.is_active', 1) ->where('user_profiles.is_active', 1) ->findAll(); if (!empty($id)) { $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']['lead_file_count'] = count($data['lead_edit_data']['multi_file_data']); // Decode and merge custom fields if present $custom_fields_data = !empty($data['lead_edit_data']['custom_fields']) ? json_decode($data['lead_edit_data']['custom_fields'], true) : []; if (!empty($custom_fields_data) && is_array($custom_fields_data)) { $data['lead_edit_data'] = array_merge($data['lead_edit_data'], $custom_fields_data); } if (!empty($data['lead_edit_data'])) { foreach (['policy_start_date', 'policy_end_date', 'source_policy_start_date', 'source_policy_end_date', 'incurred_claims_date'] as $dateField) { $data['lead_edit_data'][$dateField] = !empty($data['lead_edit_data'][$dateField]) ? change_date_format($data['lead_edit_data'][$dateField], 'Y-m-d', 'd/m/Y') : null; } $data['lead_edit_data']['fin_years_claims_array'] = !empty($data['lead_edit_data']['fin_years_claims']) ? json_decode($data['lead_edit_data']['fin_years_claims'], true)['finyear'] ?? [] : []; $data['lead_edit_data']['html'] = $this->generateViewPageHtml( $data['lead_edit_data']['policy_type_id'] ?? null, $data ) ?? ""; $html = view('rfq/multi_files', $data); $data['lead_edit_data']['multi_file_html'] = trim($html) !== '' ? $html : null; } if ($data['lead_edit_data']['lead_type'] != 1 && $data['lead_edit_data']['lead_form_type'] == 2) { $data['lead_edit_data']['claims_details_html'] = view('rfq/claims_details_non_eb', $data['lead_edit_data']); } else { $data['lead_edit_data']['claims_details_html'] = ""; } } // dd($data); return $this->loadLayout('leads_form_handler', $data); } public function getPolicyTypeFields() { $policy_type_id = $this->request->getGET('policy_type_id'); $html = $this->generateViewPageHtml($policy_type_id) ?? ""; if (!empty($html)) { return $this->respond(['status' => true, 'code' => 200, 'message' => 'Policy Type FIELDS are found', 'data' => $html], 200); } else { return $this->respond(['status' => false, 'code' => 400, 'message' => 'Fields not found for this policy type'], 200); } } public function generateViewPageHtml($policy_type_id, $data = []) { $data['insurer'] = $this->insurerBranchModel->getInsurerBranchesWithInsurerNames(); $data['tpa'] = $this->tpaBranchModel->getTpaBranchesWithTpaNames(); $viewMap = [ 1 => 'rfq/gpa', 6 => 'rfq/gpa', 7 => 'rfq/gpa', 2 => 'rfq/gmc', 3 => 'rfq/gmc', 4 => 'rfq/gmc', 5 => 'rfq/gmc', 17 => 'rfq/burglary', 22 => 'rfq/car', 23 => 'rfq/cpm', 24 => 'rfq/cyber_crime', 25 => 'rfq/do', 27 => 'rfq/eo', 49 => 'rfq/money', 19 => 'rfq/cgl', 59 => 'rfq/sfsp', 63 => 'rfq/wc', 15 => 'rfq/blu', 16 => 'rfq/bsu', 44 => 'rfq/marine', 45 => 'rfq/marine', 46 => 'rfq/marine', 47 => 'rfq/marine', 50 => 'rfq/office' ]; return isset($viewMap[$policy_type_id]) ? view($viewMap[$policy_type_id], $data) : ""; } // ------------------- RFQ NON EB EXCEL EXPORT FUNCTION --------------------------------------------------------------------------------------- public function constructNonEbExcelToSaveTemp($lead_id, $type, $propsal_and_insurer = null) { $rfq_data = $this->RFQModel->getRFQTableDataWithLeadIDAndType($lead_id, $type); $claim_history = $rfq_data['claim_history']; // dd($claim_history); $lead_data = json_decode($rfq_data['custom_fields'], true) ?? []; $lead_data['claim_history'] = $claim_history; // dd($lead_data); if (!is_array($lead_data)) { $lead_data = []; } if (isset($lead_data['pincode']) && isset($lead_data['address'])) { // Reorder keys: address first, then pincode, then the rest $reordered = ['address' => $lead_data['address'], 'pincode' => $lead_data['pincode']]; // Remove existing keys unset($lead_data['address'], $lead_data['pincode']); // Merge reordered with the rest $lead_data = $reordered + $lead_data; } $lead_data = array_merge(['Insured' => $rfq_data['client_name']], $lead_data); $policy_registration_data = []; if (isset($rfq_data['registration_json']) && !empty($rfq_data['registration_json'])) { $policy_registration_data = json_decode($rfq_data['registration_json'], true); } $jsonData = json_decode($rfq_data['json'], true); $proposalData = end($jsonData); array_pop($jsonData); $length = 0; // dd($jsonData[0]['table_data']['headers']); foreach ($jsonData as $key => $data) { if ($type == 2) { $data = $this->convertNonEbJsonForQCR($data, $type, $proposalData, $key); // Kint::dump($data, 'Second'); if ($propsal_and_insurer !== null) { list($proposal_key, $insurer_key) = explode('-', $propsal_and_insurer, 2); $data = $this->transformNonEbProposelData($data, $proposal_key, $insurer_key, $key); } unset($data['proposalData']); } else if ($type == 1) { $data = $this->convertNonEbJsonForQCR($data, $type, $proposalData, $key); unset($data['proposalData']); } } // dd($data); foreach ($data['table_data']['headers'] as $header) { if ($header['parentHeader'] != "Action") { foreach ($header['subHeaders'] as $subHeader) { // Kint::dump($header['parentHeader']); // Kint::dump($subHeader); $length++; } } } // dd($length); $columnLetterForTitle = Coordinate::stringFromColumnIndex($length - 1); $columnLetterForImage = Coordinate::stringFromColumnIndex($length); // dd($columnLetter); $sheetName = 'Worksheet'; if ($type == 2) { $sheetName = 'QCR'; if ($propsal_and_insurer !== null) { $sheetName = 'Placement'; } } else if ($type == 1) { $sheetName = 'RFQ'; } $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $sheet->setTitle($sheetName); // Start with lead_data at the top $rowNumber = 1; $title = "Nhance India Insurance Broking Pvt Ltd"; $mergeRange1 = "A{$rowNumber}:{$columnLetterForTitle}{$rowNumber}"; $sheet->mergeCells($mergeRange1); $sheet->setCellValue("A{$rowNumber}", $title); $sheet->getStyle("A{$rowNumber}")->applyFromArray([ 'font' => [ 'bold' => true, 'size' => 20 ], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, ], ]); // Calculate title width $maxWidthA = mb_strlen($title); // dd($columnLetterForImage); // Set column width to fit the image properly $sheet->getColumnDimension($columnLetterForImage)->setWidth(40); // Adjust as needed $sheet->getRowDimension($rowNumber)->setRowHeight(40); // Adjust as needed $drawing = new Drawing(); $path = ROOTPATH . "public/assets/images/Nhance-Logo-Final.png"; // Use FCPATH for server path $drawing->setPath($path); $drawing->setCoordinates("{$columnLetterForImage}{$rowNumber}"); // Set position in column C $drawing->setHeight(35); // Adjust image height // Apply center alignment to the cell $sheet->getStyle("{$columnLetterForImage}{$rowNumber}")->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER); $sheet->getStyle("{$columnLetterForImage}{$rowNumber}")->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER); $rowNumber++; // Initialize max width tracking variables $maxWidthB = 0; //Lead Data foreach ($lead_data as $key => $value) { // if ($key == 'risk_location') { // $key == 'risk_details'; // } // Kint::dump($key); // Kint::dump($value); $formattedKey = ucwords(str_replace('_', ' ', $key)); $formattedKey = $formattedKey == "Risk Location" ? "Risk Details" : $formattedKey; $formattedKey = $formattedKey == "Address" ? "Communication Address" : $formattedKey; $formattedValue = ucwords(str_replace("_", " ", $value)); if ($key == "claim_history") { $formattedValue = $value == "1" ? "Yes" : "No"; $formattedKey = "Claim Experience"; } // Kint::dump($formattedValue); // Merge A:B for key $mergeRangeKey = "A{$rowNumber}:{$columnLetterForTitle}{$rowNumber}"; $sheet->mergeCells($mergeRangeKey); // Set values in merged cells $sheet->setCellValue("A{$rowNumber}", $formattedKey); $sheet->setCellValue("{$columnLetterForImage}{$rowNumber}", $formattedValue); // Apply styles for alignment and bold text in A:B $sheet->getStyle($mergeRangeKey)->applyFromArray([ 'font' => ['bold' => true], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, ], ]); // Apply bold style to C column if the key is "Insured" // if ($key === "Insured") { // $sheet->getStyle("C{$rowNumber}")->applyFromArray([ // 'font' => ['bold' => true], // ]); // } // Track max width needed for columns $maxWidthA = max($maxWidthA, mb_strlen($formattedKey)); // Consider title and keys $maxWidthB = max($maxWidthB, mb_strlen((string) $value)); // if (!empty($policy_registration_data)) { // dd($policy_registration_data); // } $rowNumber++; } // die(); // Set column width based on max content length (adjusted for padding) $sheet->getColumnDimension('A')->setWidth($maxWidthA * 1.2); // $sheet->getColumnDimension('B')->setWidth($maxWidthA * 1.2); // $sheet->getColumnDimension('C')->setWidth($maxWidthB * 1.2); // $rowNumber += 1; //Policy Registration if (!empty($policy_registration_data)) { foreach ($policy_registration_data as $key => $value) { // kint::dump($value); $startRow = $rowNumber; // Track where the block starts // Title Row $titleMergeRangeKey = "A{$rowNumber}:{$columnLetterForImage}{$rowNumber}"; $sheet->mergeCells($titleMergeRangeKey); $sheet->setCellValue("A{$rowNumber}", ucfirst($key) . " Policy Details"); // Title Style $sheet->getStyle($titleMergeRangeKey)->applyFromArray([ 'font' => ['bold' => true], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, ], 'fill' => [ 'fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => 'ADD8E6'], ], ]); $rowNumber++; // Move to next row // Policy Type if (isset($value['policyType'])) { $sheet->mergeCells("A{$rowNumber}:{$columnLetterForTitle}{$rowNumber}"); $sheet->setCellValue("A{$rowNumber}", "Policy Type"); $sheet->setCellValue("{$columnLetterForImage}{$rowNumber}", $value['policyType']); $sheet->getStyle("A{$rowNumber}:C{$rowNumber}")->applyFromArray([ 'font' => ['bold' => true], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, ], ]); $rowNumber++; } else { $sheet->mergeCells("A{$rowNumber}:{$columnLetterForTitle}{$rowNumber}"); $sheet->setCellValue("A{$rowNumber}", "Policy Type"); $sheet->setCellValue("{$columnLetterForImage}{$rowNumber}", ucfirst($key) . " Policy"); $sheet->getStyle("A{$rowNumber}:C{$rowNumber}")->applyFromArray([ 'font' => ['bold' => true], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, ], ]); $rowNumber++; } // Type of Business & Nature of Business if (isset($value['productSelection']) && !empty($value['productSelection'])) { // Type of Business $sheet->mergeCells("A{$rowNumber}:{$columnLetterForTitle}{$rowNumber}"); $sheet->setCellValue("A{$rowNumber}", "Type of Business"); $sheet->setCellValue("{$columnLetterForImage}{$rowNumber}", $this->buisnessType[$value['productSelection']['type_of_buisness']] ?? ''); $sheet->getStyle("A{$rowNumber}")->applyFromArray([ 'font' => ['bold' => true], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, ], ]); $rowNumber++; // Nature of Business $sheet->mergeCells("A{$rowNumber}:{$columnLetterForTitle}{$rowNumber}"); $sheet->setCellValue("A{$rowNumber}", "Nature of Business"); $sheet->setCellValue("{$columnLetterForImage}{$rowNumber}", $value['productSelection']['buisness_nature'] ?? ''); $sheet->getStyle("A{$rowNumber}")->applyFromArray([ 'font' => ['bold' => true], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, ], ]); $rowNumber++; } if (isset($value['policyDetails']) && !empty($value['policyDetails'])) { // Type of Business $sheet->mergeCells("A{$rowNumber}:{$columnLetterForTitle}{$rowNumber}"); $sheet->setCellValue("A{$rowNumber}", "Terrorism"); $sheet->setCellValue("{$columnLetterForImage}{$rowNumber}", ucfirst($value['policyDetails']['terrorism'] ?? 'No')); $sheet->getStyle("A{$rowNumber}")->applyFromArray([ 'font' => ['bold' => true], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, ], ]); $rowNumber++; } if (!empty($value['locations'])) { foreach ($value['locations'] as $index => $location) { // Merge title cell $sheet->mergeCells("A{$rowNumber}:{$columnLetterForTitle}{$rowNumber}"); $sheet->setCellValue("A{$rowNumber}", "Risk " . ($location['select_location'] ?? 'Unknown')); // Clean and safe address string $address1 = ucfirst($location['policyRisk']['address1'] ?? ''); $address2 = ucfirst($location['policyRisk']['address2'] ?? ''); $pinCode = $location['policyRisk']['pin_code'] ?? 'No'; $fullAddress = "{$address1}, {$address2}, {$pinCode}"; $sheet->setCellValue("{$columnLetterForImage}{$rowNumber}", $fullAddress); // Style the title cell $sheet->getStyle("A{$rowNumber}")->applyFromArray([ 'font' => ['bold' => true], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, ], ]); $rowNumber++; } } $endRow = $rowNumber; // Block ends at previous row // Apply border to the whole block $sheet->getStyle("A{$startRow}:{$columnLetterForImage}{$endRow}")->applyFromArray([ 'borders' => [ 'allBorders' => [ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN, 'color' => ['argb' => '000000'], ], ], ]); // $rowNumber += 1; // Add space before the next block } $rowNumber--; // die(); } //Table Data foreach ($jsonData as $key => $data) { // Kint::dump($data, 'First'); if ($type == 2) { $data = $this->convertNonEbJsonForQCR($data, $type, $proposalData, $key); // Kint::dump($data, 'Second'); if ($propsal_and_insurer !== null) { list($proposal_key, $insurer_key) = explode('-', $propsal_and_insurer, 2); $data = $this->transformNonEbProposelData($data, $proposal_key, $insurer_key, $key); } unset($data['proposalData']); } else if ($type == 1) { $data = $this->convertNonEbJsonForQCR($data, $type, $proposalData, $key); unset($data['proposalData']); } // dd($data); // Add headers and subheaders $headers = $data['table_data']['headers']; // dd($headers); $rowNumber = $rowNumber + 1; $subHeaderRow = $rowNumber + 1; $columnLetter = 'A'; foreach ($headers as $header) { if (in_array($header['parentHeader'], ['Action'])) { continue; } $sheet->getColumnDimension($columnLetter)->setWidth(60); $sheet->getColumnDimension('C')->setWidth(35); if ($header['parentHeader'] == 'Policy') { // $header['parentHeader'] = 'S.No.'; $sheet->getColumnDimension('A')->setWidth(10); } if ($header['parentHeader'] === 'Particulars') { $sheet->getColumnDimension('B')->setWidth(60); } if (strpos($header['parentHeader'], 'Proposal') === 0) { $sheet->getColumnDimension('C')->setWidth(60); $sheet->getColumnDimension('D')->setWidth(35); } $startColumn = $columnLetter; // Start of the current header range $subHeaderCount = count($header['subHeaders']); // Number of subheaders for this parent header // Kint::dump($subHeaderCount); // Set parent header value $sheet->setCellValue("{$startColumn}{$rowNumber}", $header['parentHeader']); $sheet->getStyle("{$startColumn}{$rowNumber}")->applyFromArray([ 'font' => ['bold' => true], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, ], 'fill' => [ 'fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => 'ADD8E6'], ], ]); // Merge header cells if it spans multiple subheaders if ($subHeaderCount > 1) { $endColumn = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($startColumn) + $subHeaderCount - 1); $sheet->mergeCells("{$startColumn}{$rowNumber}:{$endColumn}{$rowNumber}"); } else { $endColumn = $startColumn; // No merge needed if only one subheader } // Kint::dump($header); // Add subheaders foreach ($header['subHeaders'] as $subHeader) { $sheet->setCellValue("{$columnLetter}{$subHeaderRow}", $subHeader); if ($columnLetter != "A" && $columnLetter != "B" && $columnLetter != "C" && $columnLetter != "D") { $sheet->getColumnDimension($columnLetter)->setWidth(35); } else { $sheet->getColumnDimension('A')->setWidth(10); } $sheet->getStyle("{$columnLetter}{$subHeaderRow}")->applyFromArray([ 'font' => ['bold' => true], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, ], ]); $columnLetter++; // Move to the next column for subheaders } } // For the subheader row, merge B and C and set the value $sheet->setCellValue("B{$subHeaderRow}", "Sum Insured"); $sheet->mergeCells("B{$subHeaderRow}:C{$subHeaderRow}"); $sheet->getStyle("B{$subHeaderRow}:C{$subHeaderRow}")->applyFromArray([ 'font' => ['bold' => true], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, ], ]); // Apply border to the header range $prevColumn4 = $this->getPreviousColumn($columnLetter); $headerRange = "A{$rowNumber}:" . "{$prevColumn4}" . "{$subHeaderRow}"; $sheet->getStyle($headerRange)->applyFromArray([ 'borders' => [ 'allBorders' => [ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN, 'color' => ['argb' => 'FF000000'], // Black color ], ], ]); // Increase row height for headers and subheaders $sheet->getRowDimension($rowNumber)->setRowHeight(25); // Header row height $sheet->getRowDimension($subHeaderRow)->setRowHeight(20); // Subheader row height // $rowNumber = $subHeaderRow + 2; $rowNumber = $subHeaderRow + 1; $column_data = $data['table_data']['data']; // dd($column_data); $serial_no = 1; $maxColumnWidths = []; $RowSpanEnable = false; // Add table data rows foreach ($column_data as $dataRow) { $columnLetter = 'A'; $hasPolicy = in_array('Policy', array_column($dataRow['data'], 'parentth')); // Kint::dump($hasPolicy); foreach ($dataRow['data'] as $cellData) { if (in_array($cellData['parentth'], ['Action'])) { continue; } if ($cellData['parentth'] == 'SNO') { $sheet->setCellValue("{$columnLetter}{$rowNumber}", $serial_no); } else if ($cellData['parentth'] == 'Policy') { $mergeStart = $rowNumber; // Start row for merging $mergeEnd = $rowNumber + ($cellData['rowspan'] - 1); // End row for merging $sheet->setCellValue("{$columnLetter}{$mergeStart}", $dataRow['SNO']); $sheet->mergeCells("{$columnLetter}{$mergeStart}:{$columnLetter}{$mergeEnd}"); $sheet->getStyle("{$columnLetter}{$mergeStart}:{$columnLetter}{$mergeEnd}") ->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER); } else { if (!$hasPolicy && $key == 0) { $RowSpanEnable = true; $columnLetter++; $sheet->setCellValue("{$columnLetter}{$rowNumber}", $cellData['display_content']); } else { $sheet->setCellValue("{$columnLetter}{$rowNumber}", $cellData['display_content']); } } if (!($key === 0 && !$hasPolicy)) { $columnLetter++; } } $rowNumber++; $serial_no++; } if ($key == 0 && $RowSpanEnable == true) { $columnLetter++; } // dd($columnLetter); $prevColumn5 = $this->getPreviousColumn($columnLetter); $dataRange = "A" . ($subHeaderRow + 1) . ":" . "{$prevColumn5}" . ($rowNumber - 1); $sheet->getStyle($dataRange)->applyFromArray([ 'borders' => [ 'allBorders' => [ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN, 'color' => ['argb' => 'FF000000'], // Black color ], ], ]); // Auto-size columns // foreach ($sheet->getColumnIterator() as $column) { // $sheet->getColumnDimension($column->getColumnIndex())->setAutoSize(true); // } $dataRange = $sheet->calculateWorksheetDimension(); $sheet->getStyle($dataRange)->getAlignment() ->setHorizontal(Alignment::HORIZONTAL_CENTER) ->setVertical(Alignment::VERTICAL_CENTER) ->setWrapText(true); $sheet->getStyle('A1')->applyFromArray([ 'alignment' => [ 'wrapText' => false, // Disables text wrapping for A1 ], ]); // Apply border to the entire sheet preg_match('/([A-Z]+)(\d+):([A-Z]+)(\d+)/', $dataRange, $matches); if ($matches) { $startColumn = $matches[1]; // A $startRow = $matches[2]; // 1 $endColumn = $matches[3]; // G $endRow = $matches[4]; // 75 // Convert column letter to index, reduce by 1, and convert back $endColumnIndex = Coordinate::columnIndexFromString($endColumn) - 1; $newEndColumn = Coordinate::stringFromColumnIndex($endColumnIndex); // Generate the new range (e.g., "A1:F75" instead of "A1:G75") $newDataRange = "{$startColumn}{$startRow}:{$newEndColumn}{$endRow}"; // $sheet->getStyle($newDataRange)->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN); } $lastRow = count($lead_data) + 1; $leadRange = "A1:{$columnLetterForImage}{$lastRow}"; $sheet->getStyle($leadRange)->applyFromArray([ 'borders' => [ 'allBorders' => [ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN, 'color' => ['argb' => 'FF000000'], // Black color ], ], ]); } $columnWidth = $sheet->getColumnDimension("C")->getWidth(); // e.g., 20 $cellPixelWidth = $columnWidth * 7; // Approximate conversion (1 unit ≈ 7 pixels) $imagePixelWidth = 250; // Approximate width of your image (in pixels) $offsetX = max(0, ($cellPixelWidth - $imagePixelWidth) / 2); $offsetX = $offsetX + 97; if ($length >= 4) { $offsetX = 35; } else if ($length == 3) { $offsetX = 140; } // dd($offsetX, $cellPixelWidth, $imagePixelWidth); $drawing->setOffsetX($offsetX); // Dynamically center $drawing->setOffsetY(10); // Dynamically center $drawing->setWorksheet($sheet); $sheet->getStyle('C1')->getAlignment() ->setHorizontal(Alignment::HORIZONTAL_CENTER) ->setVertical(Alignment::VERTICAL_CENTER); if (!empty($rfq_data['fin_years_claims']) && $claim_history == 1) { $claim_details = json_decode($rfq_data['fin_years_claims'], true) ?? []; if (!empty($claim_details['finyear'])) { // Get headers dynamically $headers = array_map(function ($key) { return ucwords(str_replace('_', ' ', $key)); }, array_keys($claim_details['finyear'][0])); $newSheet = new Worksheet($spreadsheet, 'Claims Experience'); $spreadsheet->addSheet($newSheet); $spreadsheet->setActiveSheetIndexByName('Claims Experience'); $sheet = $spreadsheet->getActiveSheet(); // Set headers $sheet->fromArray($headers, NULL, 'A1'); // Apply background color and bold style to headers $headerCellRange = 'A1:' . chr(64 + count($headers)) . '1'; // e.g., A1:G1 $sheet->getStyle($headerCellRange)->getFont()->setBold(true); $sheet->getStyle($headerCellRange)->getFill()->setFillType(Fill::FILL_SOLID)->getStartColor()->setRGB('ADD8E6'); // Add border to header $sheet->getStyle($headerCellRange)->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN); // Fill data and apply borders $row = 2; foreach ($claim_details['finyear'] as $record) { $col = 'A'; foreach ($record as $value) { $sheet->setCellValue($col . $row, $value); $col++; } // Apply border to each data row $sheet->getStyle('A' . $row . ':' . chr(64 + count($headers)) . $row) ->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN); $row++; } // Auto-size all columns based on header count for ($i = 0; $i < count($headers); $i++) { $colLetter = chr(65 + $i); // 'A', 'B', etc. $sheet->getColumnDimension($colLetter)->setAutoSize(true); } // Enable wrap text for all cells $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: Make row height auto (helps when wrap text is on) for ($i = 2; $i < $row; $i++) { $sheet->getRowDimension($i)->setRowHeight(-1); } } } // dd($rowNumber); // Set filename $string = ($type == 2) ? 'QCR' : 'RFQ'; $filename = "{$string}_{$rfq_data['client_short_name']}_{$rfq_data['policy_type']}_" . date('YmdHis') . '.xlsx'; // Save to temporary location $uploadFilePath = WRITEPATH . 'tmp/' . $filename; $writer = new Xlsx($spreadsheet); $writer->save($uploadFilePath); return [ 'filePath' => $uploadFilePath, 'fileName' => $filename, ]; } public function convertNonEbJsonForQCR($jsonArr, $type, $proposeldata, $indexOfTheTable) { $first_json = $jsonArr; $first_json = array_merge($first_json, $proposeldata); if ($type == 2) { // Column-wise Check: Remove headers and relevant data if qcr == 0 foreach ($first_json['proposal_data']['over_all_column_data'] as $proposalKey => $proposalData) { if ((isset($proposalData['qcr']) && isset($proposalData['stc'])) && ($proposalData['qcr'] == 0 || $proposalData['qcr'] === false) || ($proposalData['stc'] == 0 || $proposalData['stc'] === false)) { // Remove matching parentHeader in headers foreach ($first_json['table_data']['headers'] as $index => $header) { if ($header['parentHeader'] === $proposalKey) { unset($first_json['table_data']['headers'][$index]); } } // Remove data entries with matching parentth foreach ($first_json['table_data']['data'] as &$item) { $item['data'] = array_values(array_filter($item['data'], function ($entry) use ($proposalKey) { return $entry['parentth'] !== $proposalKey; })); } // Remove proposalKey from over_all_column_data unset($first_json['proposal_data']['over_all_column_data'][$proposalKey]); if ($type == 2) { // Remove proposalKey from premium_data unset($first_json['premium_data']['data'][$proposalKey]); } } // Insurer Check: Remove subHeaders and relevant data for insurers with qcr == 0 foreach ($proposalData['insurers'] as $insurerIndex => $insurer) { $qcr = $insurer['qcr'] ?? null; $stc = $insurer['stc'] ?? null; if (($qcr === 0 || $qcr === false) || ($stc === 0 || $stc === false)) { foreach ($first_json['table_data']['headers'] as &$header) { if (isset($header['subHeaders'])) { $header['subHeaders'] = array_values(array_filter($header['subHeaders'], function ($sub) use ($insurer) { return $sub !== $insurer['display_name']; })); } } foreach ($first_json['table_data']['data'] as &$item) { $item['data'] = array_values(array_filter($item['data'], function ($entry) use ($insurer) { return $entry['subth'] !== $insurer['display_name']; })); } // Remove insurer from proposal's insurers array unset($first_json['proposal_data']['over_all_column_data'][$proposalKey]['insurers'][$insurerIndex]); if ($type == 2) { unset($first_json['premium_data']['data'][$proposalKey][$insurer['display_name']]); } } } } // Row-wise Check: Remove rows if qcr == 0 for actions $groupedRows = []; foreach ($first_json['table_data']['data'] as $rowKey => $rowData) { $groupedRows[$rowData['row_id']][] = $rowData; foreach ($rowData['data'] as $keyIndex => $data) { if ($indexOfTheTable == 0) { if ($data['parentth'] == "Policy" && $data['input_value'] != "Checked") { unset($first_json['table_data']['data'][$rowKey]); break; } } else { if ( isset($data['parentth'], $data['input_value']['qcr'], $data['input_value']['stc']) && $data['parentth'] === "Action" && ($data['input_value']['qcr'] == 0 || $data['input_value']['stc'] == 0) ) { unset($first_json['table_data']['data'][$rowKey]); break; } } } } $finalRows = []; if (!empty($groupedRows)) { // Loop through each row_id group and check for Policy status foreach ($groupedRows as $rowId => $rows) { $hasPolicy = false; $isChecked = false; foreach ($rows as $row) { foreach ($row['data'] as $cell) { if ($cell['parentth'] === 'Policy') { $hasPolicy = true; if (trim(strtolower($cell['input_value'])) === 'checked') { $isChecked = true; } break 2; // Found Policy, no need to continue further } } } // Step 3: If parent Policy is "Checked", retain the entire group if (!$hasPolicy || $isChecked) { foreach ($rows as $r) { $finalRows[] = $r; } } } if (!empty($finalRows)) { // Update the original data $first_json['table_data']['data'] = array_values($finalRows); } } // Reindex arrays to maintain proper structure $first_json['table_data']['headers'] = array_values($first_json['table_data']['headers']); $first_json['table_data']['data'] = array_values($first_json['table_data']['data']); $first_json['proposal_data']['over_all_column_data'] = array_map(function ($proposal) { $proposal['insurers'] = array_values($proposal['insurers']); return $proposal; }, $first_json['proposal_data']['over_all_column_data']); } else { //remove insurer as Subheaders for RFQ foreach ($first_json['table_data']['headers'] as &$header) { // Ensure 'subHeaders' exists and is an array before filtering if (isset($header['subHeaders']) && is_array($header['subHeaders'])) { $header['subHeaders'] = array_filter($header['subHeaders'], function ($subHeader) { return in_array($subHeader, ['Sum Insured', '-'], true); }); } } // Kint::dump($header); //Remove insurer Row wise data for RFQ $groupedRows = []; foreach ($first_json['table_data']['data'] as &$row) { // Filter the inner data array $row['data'] = array_filter( $row['data'], function ($item) { return in_array($item['subth'], ['Sum Insured', '-', "Liability Limit"]); } ); $row['data'] = array_values($row['data']); $groupedRows[$row['row_id']][] = $row; } // Ensure to unset the reference after the loop unset($row); $finalRows = []; if (!empty($groupedRows)) { // Loop through each row_id group and check for Policy status foreach ($groupedRows as $rowId => $rows) { $hasPolicy = false; $isChecked = false; foreach ($rows as $row) { foreach ($row['data'] as $cell) { if ($cell['parentth'] === 'Policy') { $hasPolicy = true; if (trim(strtolower($cell['input_value'])) === 'checked') { $isChecked = true; } break 2; // Found Policy, no need to continue further } } } // Step 3: If parent Policy is "Checked", retain the entire group if (!$hasPolicy || $isChecked) { foreach ($rows as $r) { $finalRows[] = $r; } } } if (!empty($finalRows)) { // Update the original data $first_json['table_data']['data'] = array_values($finalRows); } } // Remove insurers from Proposal Data key for RFQ foreach ($proposeldata['proposal_data']['over_all_column_data'] as $key => &$proposal) { if (isset($proposal['insurers'])) { // Set the insurers array to empty $proposal['insurers'] = []; } } // Ensure to reset the reference unset($proposal); } return $first_json; return null; } public function transformNonEbProposelData(&$data, $proposal, $insurer, $tableCount = null, $actionColumn = null) { // Kint::dump($data, $proposal, $insurer, $tableCount); // Initialize headers with defaults $headerData = []; // Add the first two default headers only once $headerData[] = [ 'parentHeader' => $data['table_data']['headers'][0]['parentHeader'], 'subHeaders' => ['-'] ]; $headerData[] = [ 'parentHeader' => $data['table_data']['headers'][1]['parentHeader'], 'subHeaders' => ['-'] ]; $second_table_name = $data['table_data']['headers'][1]['parentHeader'] ?? ""; // Loop through the headers to find matching proposal and insurer foreach ($data['table_data']['headers'] as $header) { if ($header['parentHeader'] === $proposal) { foreach ($header['subHeaders'] as $subHeader) { if ($subHeader === $insurer) { $headerData[] = [ 'parentHeader' => $header['parentHeader'], 'subHeaders' => ['Sum Insured', $subHeader] ]; break 2; // Exit both loops after match is found } } } } // Update the original data's headers $data['table_data']['headers'] = $headerData; if (!empty($actionColumn)) { $data['table_data']['headers'][] = [ 'parentHeader' => "Action", 'subHeaders' => ['-'] ]; } foreach ($data['table_data']['data'] as &$entry) { $sno = $entry['SNO']; $items = $entry['items']; $row_id = $entry['row_id']; $filteredData = []; foreach ($entry['data'] as $item) { // Always include SNO and Particulars if (in_array($item['parentth'], ['S.NO', "Policy", "", 'Particulars', $second_table_name])) { $filteredData[] = $item; } // Include Proposal with Sum Insured if ($item['parentth'] === $proposal && ($item['subth'] === "Sum Insured" || $item['subth'] === "Liability Limit")) { $filteredData[] = $item; } // Include specific proposal and insurer if ($item['parentth'] === $proposal && $item['subth'] === $insurer) { $filteredData[] = $item; } if (!empty($actionColumn)) { if ($item['parentth'] === "Action") { $filteredData[] = $item; } } } // Update the entry with filtered data $entry['SNO'] = $sno; $entry['items'] = $items; $entry['row_id'] = $row_id; $entry['data'] = $filteredData; } unset($entry); // kint::dump($data); return $data; } public function getPreviousColumn($columnLetter, $decrement = 1) { $colIndex = Coordinate::columnIndexFromString($columnLetter); $colIndex = max(1, $colIndex - $decrement); // ensure column index doesn't go below 1 return Coordinate::stringFromColumnIndex($colIndex); } public function handleMultiFileAttachments($json_string, $lead_id) { log_message('error', 'handleMultiFileAttachments called with lead_id: ' . $lead_id); $attachments = []; if (!empty($json_string)) { log_message('error', 'json_string is not empty'); $fileIds = json_decode($json_string, true); log_message('error', 'Decoded fileIds: ' . print_r($fileIds, true)); $lead_file_path = WRITEPATH . 'uploads/lead_files/'; log_message('error', 'Lead file path: ' . $lead_file_path); foreach ($fileIds as $id) { log_message('error', 'Processing file ID: ' . $id); $lead_file = $this->leadFilesModel ->where('lead_id', $lead_id) ->where('id', $id) ->where('is_active', 1) ->first(); if ($lead_file) { log_message('error', 'Found lead file: ' . print_r($lead_file, true)); $fullPath = $lead_file_path . $lead_file['file_name']; log_message('error', 'Full file path: ' . $fullPath); if (file_exists($fullPath)) { log_message('error', 'File exists at path: ' . $fullPath); if (!empty($lead_file['file_name'])) { log_message('error', 'File name is not empty: ' . $lead_file['file_name']); $attachments[] = [ 'fileName' => $lead_file['file_name'], 'filePath' => $fullPath ]; } else { log_message('warning', 'File name is empty for ID: ' . $id); } } else { log_message('warning', 'File does not exist at path: ' . $fullPath); } } else { log_message('warning', 'No active lead file found for ID: ' . $id . ' and lead_id: ' . $lead_id); } } } else { log_message('error', 'json_string is empty'); } log_message('error', 'Attachments prepared: ' . print_r($attachments, true)); return $attachments; } public function handleMemberDataGPATotalSumInsurerFromExcel($params) { $lead_id = $params['lead_id']; $lead_data = $this->leadsModel->find($lead_id); // dd($lead_data); $file_name_with_path = WRITEPATH . "/uploads/lead_files/" . $lead_data['file_name']; // dd($file_name_with_path); if (!$lead_data) { return ['status' => 'failed', 'message' => 'Lead data not found']; } if ($lead_data['file_name']) { //check physical file if (!file_exists($file_name_with_path)) { $message = "Lead Physcial file not found"; $this->myLogger->logme('error', ($message . ' for file ' . $file_name_with_path)); return ['status' => 'failed', 'message' => 'no physical file']; } $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path); //get members data $members_sheet = $spreadsheet->getSheet(0); $highestRowAndColumn = $members_sheet->getHighestRowAndColumn(); // dd($highestRowAndColumn); $uncleaned_members = $members_sheet->rangeToArray('A1:' . $highestRowAndColumn['column'] . $highestRowAndColumn['row']); // dd($uncleaned_members); $members = ExcelSanitizeHelper::sanitizeArrayData($uncleaned_members); // dd($members); // Check column headings $members_heading = $members[0]; $available_col = []; $lower_headers = array_map('strtolower', $members_heading); foreach ($lower_headers as $index => $header) { if (preg_match('/^sa\s*-\s*option\s*\d*$/i', $header)) { $column_name = $members_heading[$index]; $sum = 0; for ($i = 1; $i < count($members); $i++) { $cell_raw = $members[$i][$index] ?? ''; $cell_clean = preg_replace('/[^0-9.\-]/', '', $cell_raw); // remove non-numeric chars if ($cell_clean !== '' && is_numeric($cell_clean)) { $sum += (float) $cell_clean; } } $available_col[] = $sum; } } // dd($available_col); return $available_col; } return []; } public function generateDemographyDataTable($param) { $returnData = $this->calculateMembersDemography($param, "internal"); $html = ""; if (isset($returnData['data'])) { $data = $returnData['data']; foreach ($data as $category => $records) { // Extract all column headers (age groups) dynamically $allColumns = []; foreach ($records as $person => $ages) { $allColumns = array_merge($allColumns, array_keys($ages)); } $allColumns = array_unique($allColumns); $allColumns = array_values($allColumns); // reset index $category = ucfirst($category); // Start table with clean styling $html .= "

{$category}

"; $html .= ""; // Table header with light background $html .= ""; $html .= ""; foreach ($allColumns as $col) { $html .= ""; } $html .= ""; // Table rows with clean styling foreach ($records as $relation => $ages) { $html .= ""; $html .= ""; foreach ($allColumns as $col) { $value = isset($ages[$col]) ? $ages[$col] : "-"; $html .= ""; } $html .= ""; } $html .= "
Relation{$col}
{$relation}{$value}
"; } } return $html; } }