Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
velz 2024-12-23 12:23:52 +05:30
commit cd37e33920
5 changed files with 1037 additions and 312 deletions

View File

@ -126,6 +126,10 @@ class JobWorker extends AdminController
'employeesEnrollmentInsert' => [ 'employeesEnrollmentInsert' => [
'type' => 'CC', // Handler Category 'type' => 'CC', // Handler Category
'handler' => 'App\Controllers\EmployeeServiceController', 'handler' => 'App\Controllers\EmployeeServiceController',
],
'calculateMembersDemography' => [
'type' => 'CC', // Handler Category
'handler' => 'App\Controllers\LeadsController',
] ]
]; ];

View File

@ -4,10 +4,14 @@ namespace App\Controllers;
use CodeIgniter\API\ResponseTrait; use CodeIgniter\API\ResponseTrait;
use Exception;
use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Border; use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Alignment; use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx; use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use App\Models\UserModel; use App\Models\UserModel;
use App\Models\ClientModel; use App\Models\ClientModel;
@ -24,6 +28,8 @@ use App\Models\RFQModel;
use App\Models\InsurerModel; use App\Models\InsurerModel;
use App\Helpers\MailHelper; use App\Helpers\MailHelper;
use App\Helpers\ExcelMergeHelper;
use Google\Service\CloudSearch\PushItem;
use Kint; use Kint;
@ -92,7 +98,9 @@ class LeadsController extends BaseController
{ {
// $d = $this->constructExcelToSaveTemp(24, 1, $propsal_and_insurer = null); // $d = $this->constructExcelToSaveTemp(24, 1, $propsal_and_insurer = null);
// $d = $this->calculateMembersDemography(['lead_id' => 34]); $job_details = new Jobs();
// $r = Jobs::addJob(['job_name' => 'calculateMembersDemography', 'payload' => ['lead_id' => 24]]);
// $d = $this->calculateMembersDemography(['lead_id' => 24]);
//$this->mergeQuoteExcelFileWithMembersListExcelFile(24, 1, $propsal_and_insurer = null); //$this->mergeQuoteExcelFileWithMembersListExcelFile(24, 1, $propsal_and_insurer = null);
// dd($d); // dd($d);
$data['page_name'] = 'Leads'; $data['page_name'] = 'Leads';
@ -148,20 +156,20 @@ class LeadsController extends BaseController
{ {
$data = $this->request->getPost(); $data = $this->request->getPost();
if($data['lead_type'] == 2){ if ($data['lead_type'] == 2) {
$client_data = $this->clientModel->where('id', $data['client_id'])->where('is_active', 1)->first(); $client_data = $this->clientModel->where('id', $data['client_id'])->where('is_active', 1)->first();
$data['client_name'] = $client_data['client_name']; $data['client_name'] = $client_data['client_name'];
$data['client_short_name'] = $client_data['short_name']; $data['client_short_name'] = $client_data['short_name'];
$data['entity_type_id'] = $client_data['entity_type_id']; $data['entity_type_id'] = $client_data['entity_type_id'];
$data['client_type'] = $client_data['client_type']; $data['client_type'] = $client_data['client_type'];
}else{ } else {
$data['client_id'] = 0; $data['client_id'] = 0;
$data['client_branch_id'] = 0; $data['client_branch_id'] = 0;
$data['source_policy_id'] = 0; $data['source_policy_id'] = 0;
} }
$data['client_code'] = generate_client_code(); $data['client_code'] = generate_client_code();
if($data['client_code'] == 2){ if ($data['client_code'] == 2) {
$data['client_code'] = generate_client_code('IC'); $data['client_code'] = generate_client_code('IC');
} }
@ -216,15 +224,15 @@ class LeadsController extends BaseController
$proposed_tpa_id = 0; $proposed_tpa_id = 0;
} }
if(!empty($data['policy_start_date'][$index])){ if (!empty($data['policy_start_date'][$index])) {
$policy_start_date = change_date_format($data['policy_start_date'][$index], 'd/m/Y', 'Y-m-d'); $policy_start_date = change_date_format($data['policy_start_date'][$index], 'd/m/Y', 'Y-m-d');
}else{ } else {
$policy_start_date = null; $policy_start_date = null;
} }
if(!empty($data['policy_end_date'][$index])){ if (!empty($data['policy_end_date'][$index])) {
$policy_end_date = change_date_format($data['policy_end_date'][$index], 'd/m/Y', 'Y-m-d'); $policy_end_date = change_date_format($data['policy_end_date'][$index], 'd/m/Y', 'Y-m-d');
}else{ } else {
$policy_end_date = null; $policy_end_date = null;
} }
@ -311,26 +319,26 @@ class LeadsController extends BaseController
private function insertNewLead($data) private function insertNewLead($data)
{ {
$insertCount = []; $insertCount = [];
foreach($data as $value){ foreach ($data as $value) {
$insert = $this->leadsModel->insert($value); $insert = $this->leadsModel->insert($value);
$insertCount[] = $insert; $insertCount[] = $insert;
$this->insertLeadStatus($insert, $value['status'], 3); $this->insertLeadStatus($insert, $value['status'], 3);
} }
if (count($insertCount) > 0) { if (count($insertCount) > 0) {
return $this->respond(['status' => true, 'lead_id' => $insert, 'message' => 'New Lead created successfully', 'data' =>$data], 200); 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); return $this->respond(['status' => false, 'lead_id' => $insert, 'message' => "Failed to create Lead", 'data' => $data], 200);
} }
private function updateOldLead($id, $data) private function updateOldLead($id, $data)
{ {
if ($this->leadsModel->where('id', $id)->set($data[0])->update()) { if ($this->leadsModel->where('id', $id)->set($data[0])->update()) {
$this->insertLeadStatus($id, $data[0]['status'], 3); $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' => 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); return $this->respond(['status' => false, 'lead_id' => $id, 'message' => "Failed to update Lead", 'data' => $data], 200);
} }
// Get the Single Lead data for edit // Get the Single Lead data for edit
@ -338,28 +346,27 @@ class LeadsController extends BaseController
{ {
$data = $this->leadsModel $data = $this->leadsModel
->where('leads.id', $id) ->where('leads.id', $id)
->where('leads.is_active', 1) ->where('leads.is_active', 1)
->first(); ->first();
if(!empty($data['policy_start_date'])){ if (!empty($data['policy_start_date'])) {
$data['policy_start_date'] = change_date_format($data['policy_start_date'], 'Y-m-d', 'd/m/Y'); $data['policy_start_date'] = change_date_format($data['policy_start_date'], 'Y-m-d', 'd/m/Y');
}else{ } else {
$data['policy_start_date'] = null; $data['policy_start_date'] = null;
} }
if(!empty($data['policy_end_date'])){ if (!empty($data['policy_end_date'])) {
$data['policy_end_date'] = change_date_format($data['policy_end_date'], 'Y-m-d', 'd/m/Y'); $data['policy_end_date'] = change_date_format($data['policy_end_date'], 'Y-m-d', 'd/m/Y');
}else{ } else {
$data['policy_end_date'] = null; $data['policy_end_date'] = null;
} }
if($data){ if ($data) {
return $this->respond(['status' => true, 'data' => $data], 200); return $this->respond(['status' => true, 'data' => $data], 200);
}else{ } else {
return $this->respond(['status' => false], 200); return $this->respond(['status' => false], 200);
} }
} }
private function insertLeadStatus($primaryKey, $status, $statusType) private function insertLeadStatus($primaryKey, $status, $statusType)
@ -377,7 +384,8 @@ class LeadsController extends BaseController
//--------RFQ----------------------------------------------------------------------------------------------- //--------RFQ-----------------------------------------------------------------------------------------------
public function viewRFQ($id, $type = 1){ public function viewRFQ($id, $type = 1)
{
$data['rfq_data'] = $this->RFQModel $data['rfq_data'] = $this->RFQModel
->where('lead_id', $id) ->where('lead_id', $id)
@ -392,10 +400,10 @@ class LeadsController extends BaseController
->countAllResults(); ->countAllResults();
$data['qcr_count'] = $this->RFQModel $data['qcr_count'] = $this->RFQModel
->where('lead_id', $id) ->where('lead_id', $id)
->where('type', 2) ->where('type', 2)
->where('is_active', 1) ->where('is_active', 1)
->countAllResults(); ->countAllResults();
// dd(count($data['rfq_data'])); // dd(count($data['rfq_data']));
@ -409,7 +417,7 @@ class LeadsController extends BaseController
// dd($lead_data); // dd($lead_data);
if($lead_data['lead_type'] == 2){ if ($lead_data['lead_type'] == 2) {
$client_policy_data = $this->clientPolicyModel->where('is_active', 1)->where('id', $lead_data['source_policy_id'])->first(); $client_policy_data = $this->clientPolicyModel->where('is_active', 1)->where('id', $lead_data['source_policy_id'])->first();
$data['policy_terms'] = $client_policy_data['policy_terms']; $data['policy_terms'] = $client_policy_data['policy_terms'];
} }
@ -441,14 +449,14 @@ class LeadsController extends BaseController
$result = $this->RFQModel->insert($data); $result = $this->RFQModel->insert($data);
if ($result) { if ($result) {
return $this->respond(['status' => true, 'id' => $result, 'message' => 'RFQ created successfully', 'data' =>$data], 200); return $this->respond(['status' => true, 'id' => $result, 'message' => 'RFQ created successfully', 'data' => $data], 200);
} }
return $this->respond(['status' => false, 'id' => $result, 'message' => "Failed to create RFQ", 'data' =>$data], 200); return $this->respond(['status' => false, 'id' => $result, 'message' => "Failed to create RFQ", 'data' => $data], 200);
} }
public function createQCR(){ public function createQCR()
{
$data = $this->request->getPost(); $data = $this->request->getPost();
$lead_id = $data['lead_id']; $lead_id = $data['lead_id'];
@ -464,10 +472,10 @@ class LeadsController extends BaseController
$result = $this->RFQModel->insert($data); $result = $this->RFQModel->insert($data);
if ($result) { if ($result) {
return $this->respond(['status' => true, 'id' => $result, 'message' => 'QCR created successfully', 'data' =>$data], 200); 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); return $this->respond(['status' => false, 'id' => $result, 'message' => "Failed to create QCR", 'data' => $data], 200);
} }
@ -475,14 +483,15 @@ class LeadsController extends BaseController
//export main route function //export main route function
public function exportQCRandRFQ($lead_id, $type, $export_type){ public function exportQCRandRFQ($lead_id, $type, $export_type)
$this-> exportExcelForQCRandRFQ($lead_id, $type); {
$this->exportExcelForQCRandRFQ($lead_id, $type);
} }
//FOR EXCEL //FOR EXCEL
public function exportExcelForQCRandRFQ($lead_id, $type) public function exportExcelForQCRandRFQ($lead_id, $type)
{ {
//$filepath = $this->constructExcelToSaveTemp($lead_id, $type); $filepath = $this->constructExcelToSaveTemp($lead_id, $type);
$filepath = $filepath['filePath']; $filepath = $filepath['filePath'];
if (file_exists($filepath)) { if (file_exists($filepath)) {
@ -655,7 +664,7 @@ class LeadsController extends BaseController
]); ]);
if($type == 2){ if ($type == 2) {
$rowNumber += 2; $rowNumber += 2;
@ -694,7 +703,6 @@ class LeadsController extends BaseController
], ],
], ],
]); ]);
} }
// Auto-size columns // Auto-size columns
@ -722,9 +730,7 @@ class LeadsController extends BaseController
{ {
$rfq_data = $this->RFQModel->getRFQTableDataWithLeadIDAndType($lead_id, $type); $rfq_data = $this->RFQModel->getRFQTableDataWithLeadIDAndType($lead_id, $type);
if($source_file_path && $rfq_data['file_name']) if ($source_file_path && $rfq_data['file_name']) {
{
} }
return true; return true;
@ -734,45 +740,42 @@ class LeadsController extends BaseController
{ {
$lead_id = $params['lead_id']; $lead_id = $params['lead_id'];
$lead_data = $this->leadsModel->find($lead_id); $lead_data = $this->leadsModel->find($lead_id);
// print_rr($lead_data); $file_name_with_path = WRITEPATH . "/uploads/lead_files/" . $lead_data['file_name'];
if($lead_data['file_name'])
{ if ($lead_data['file_name']) {
$file_name_with_path = WRITEPATH."/uploads/lead_files/".$lead_data['file_name'];
//check physical file //check physical file
if(!file_exists($file_name_with_path)) if (!file_exists($file_name_with_path)) {
{
//file not found update status and reason //file not found update status and reason
$message = "Lead Physcial file not found"; $message = "Lead Physcial file not found";
// echo $message; // echo $message;
$this->myLogger->logme('error',($message . ' for file ' . $file_name_with_path)); $this->myLogger->logme('error', ($message . ' for file ' . $file_name_with_path));
return ['status' => 'failed','message' => 'no physcial file']; return ['status' => 'failed', 'message' => 'no physical file'];
} }
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path); $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path);
//get members data //get members data
$members_sheet = $spreadsheet->getSheet(0); $members_sheet = $spreadsheet->getSheet(0);
$highestRowAndColumn = $members_sheet->getHighestRowAndColumn(); $highestRowAndColumn = $members_sheet->getHighestRowAndColumn();
// dd($highestRowAndColumn); // dd($highestRowAndColumn);
$members = $members_sheet->rangeToArray('A1:' . $highestRowAndColumn['column'] . $highestRowAndColumn['row']); $members = $members_sheet->rangeToArray('A1:' . $highestRowAndColumn['column'] . $highestRowAndColumn['row']);
// dd($members); // dd($members[6]);
//get age band data //get age band data
$age_band_sheet = $spreadsheet->getSheet(1); $age_band_sheet = $spreadsheet->getSheet(1);
$highestRowAndColumn = $age_band_sheet->getHighestRowAndColumn(); $highestRowAndColumn = $age_band_sheet->getHighestRowAndColumn();
$age_band_data = $age_band_sheet->rangeToArray('A1:' . $highestRowAndColumn['column'] . $highestRowAndColumn['row']); $age_band_data = $age_band_sheet->rangeToArray('A1:' . $highestRowAndColumn['column'] . $highestRowAndColumn['row']);
print_r($age_band_data);
//check age or dob column
$members_heading = $members[0]; //check age or dob column
Kint::dump($members_heading); $members_heading = $members[0];
$available_col = null; $available_col = null;
$col_index = null; $col_index = null;
if (in_array('age', array_map('strtolower',$members_heading))) { if (in_array('age', array_map('strtolower', $members_heading))) {
$available_col = 'age'; $available_col = 'age';
$col_index = array_search('age',array_map('strtolower',$members_heading)); $col_index = array_search('age', array_map('strtolower', $members_heading));
} elseif (in_array('dob', array_map('strtolower', $members_heading))) { } elseif (in_array('dob', array_map('strtolower', $members_heading))) {
$available_col = 'dob'; $available_col = 'dob';
$col_index = array_search('dob', array_map('strtolower', $members_heading)); $col_index = array_search('dob', array_map('strtolower', $members_heading));
@ -780,19 +783,349 @@ class LeadsController extends BaseController
if ($available_col == null) { if ($available_col == null) {
$message = 'No DOB or Age column '; $message = 'No DOB or Age column ';
$this->myLogger->logme('error',($message . $file_name_with_path)); $this->myLogger->logme('error', ($message . $file_name_with_path));
return ['status' => 'failed','message' => $message]; 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()];
} }
//convert age slab data into array try {
$result = $this->generateClassifierSpreadsheet($classifiers, 'writable/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' => 'writable/uploads/lead_files/' . $result['filename'], 'sheets' => []],
];
$outputPath = WRITEPATH . 'uploads/lead_files/Member_Data.xlsx';
$result = ExcelMergeHelper::mergeExcelFiles($filePaths, $outputPath);
if ($result) {
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'];
} }
else }
{
$this->myLogger->logme('error',(' no file found ' . $file_name_with_path)); public function getDemographyData($members, $age_band_data, $members_heading, $available_col, $col_index)
return ['status' => 'failed','message' => 'no file found']; {
$first_loop = 0;
$col_index_si = array_search('si enhancement', 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();
// 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) use ($age_bands) {
// Set headers
$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);
}
// 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 [
'success' => true,
'filepath' => $filepath,
'filename' => $filename,
'fullpath' => realpath($filepath)
];
} 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);
} }
@ -801,7 +1134,7 @@ class LeadsController extends BaseController
{ {
helper('excel_util_helper'); helper('excel_util_helper');
helper('MailHelper'); helper('MailHelper');
helper('ExcelMergeHelper');
$params = $this->request->getGet(); $params = $this->request->getGet();
// print_r($params); die; // print_r($params); die;
$lead_id = $params['lead_id']; $lead_id = $params['lead_id'];
@ -830,7 +1163,7 @@ class LeadsController extends BaseController
$cc_mails = []; $cc_mails = [];
//get CC Mails //get CC Mails
if($recipient_type == 'internal' || $recipient_type == 'placement'){ if ($recipient_type == 'internal' || $recipient_type == 'placement') {
$cc_data = isset($params['cc']) ? $params['cc'] : ""; $cc_data = isset($params['cc']) ? $params['cc'] : "";
$param_cc_mail = json_decode($cc_data, true); $param_cc_mail = json_decode($cc_data, true);
@ -869,12 +1202,28 @@ class LeadsController extends BaseController
//get file path to attach //get file path to attach
$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);
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) . '/' . 'merged_' . $temp_file_name;
$result = ExcelMergeHelper::mergeExcelFiles($filePaths, $outputPath);
// print_rr($result);
}
}
// print_rr($lead_data);
// print_rr($file_info);
// $file_path = WRITEPATH."uploads/excel/sample/correction.xls"; // $file_path = WRITEPATH."uploads/excel/sample/correction.xls";
// $file_name = $file_type.'.xlsx'; // $file_name = $file_type.'.xlsx';
// !dd($file_info); // !dd($file_info);
$file_path = $file_info['filePath']; $file_path = $result;
$file_name = $file_info['fileName']; $file_name = basename($result);
$attachments = [['fileName' => $file_name, 'filePath' => $file_path]]; $attachments = [['fileName' => $file_name, 'filePath' => $file_path]];
//get recipient address //get recipient address
@ -889,9 +1238,9 @@ class LeadsController extends BaseController
// print_r($recipient_data); die; // print_r($recipient_data); die;
} else if($recipient_type == 'client') { } else if ($recipient_type == 'client') {
$recipient_data = [['name' => $lead_data['contact_person_name'], 'email' => $lead_data['contact_person_email']]]; $recipient_data = [['name' => $lead_data['contact_person_name'], 'email' => $lead_data['contact_person_email']]];
}else{ } else {
$recipient_data = [['name' => "Team", 'email' => $params['to']]]; $recipient_data = [['name' => "Team", 'email' => $params['to']]];
} }
// print_r($recipient_data); die; // print_r($recipient_data); die;
@ -899,7 +1248,7 @@ class LeadsController extends BaseController
$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']; $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 = '<div style="width:100%;max-width:600px;margin:0 auto;padding:20px;border:1px solid #e0e0e0;background-color:#f9f9f9;font-family:Arial,sans-serif;color:#333;line-height:1.6"><div style=background-color:#4a90e2;color:#fff;padding:15px;text-align:center><h1 style=margin:0;font-size:24px>Request for Quotation (RFQ)</h1></div><div style=padding:20px;background-color:#fff><h2 style=color:#4a90e2;font-size:20px;margin-top:0>Dear {{RECIPIENT_NAME}},</h2><p>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.<h2 style=color:#4a90e2;font-size:20px;margin-top:20px>RFQ Details</h2><table style=width:100%;border-collapse:collapse;margin-top:20px><tr><th style="border:1px solid #ddd;padding:10px;text-align:left;background-color:#f2f2f2">Client name<td style="border:1px solid #ddd;padding:10px;text-align:left">{{CLIENT_NAME}}<tr><th style="border:1px solid #ddd;padding:10px;text-align:left;background-color:#f2f2f2">Coverage Type<td style="border:1px solid #ddd;padding:10px;text-align:left">{{POLICY_LONG_NAME}}<tr><th style="border:1px solid #ddd;padding:10px;text-align:left;background-color:#f2f2f2">Policy Start Date<td style="border:1px solid #ddd;padding:10px;text-align:left">{{POLICY_START_DATE}}<tr><th style="border:1px solid #ddd;padding:10px;text-align:left;background-color:#f2f2f2">Policy Duration<td style="border:1px solid #ddd;padding:10px;text-align:left">{{DURATION}}</table><div style="margin-top:20px;padding:10px;background-color:#f7f7f7;border-left:4px solid #4a90e2;font-style:italic">Please note: Additional terms and details are included in the attachment for your reference.</div><p>Please feel free to reach out if you require any further information to prepare the quote. We look forward to receiving your proposal.<p>Best regards,<p><strong>Nhance India Pvt Ltd</strong><br></div><div style=margin-top:20px;font-size:12px;color:#777;text-align:center><p>© Nhance India Pvt Ltd. All rights reserved.</div></div>'; $original_message = '<div style="width:100%;max-width:600px;margin:0 auto;padding:20px;border:1px solid #e0e0e0;background-color:#f9f9f9;font-family:Arial,sans-serif;color:#333;line-height:1.6"><div style=background-color:#4a90e2;color:#fff;padding:15px;text-align:center><h1 style=margin:0;font-size:24px>Request for Quotation (RFQ)</h1></div><div style=padding:20px;background-color:#fff><h2 style=color:#4a90e2;font-size:20px;margin-top:0>Dear {{RECIPIENT_NAME}},</h2><p>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.<h2 style=color:#4a90e2;font-size:20px;margin-top:20px>RFQ Details</h2><table style=width:100%;border-collapse:collapse;margin-top:20px><tr><th style="border:1px solid #ddd;padding:10px;text-align:left;background-color:#f2f2f2">Client name<td style="border:1px solid #ddd;padding:10px;text-align:left">{{CLIENT_NAME}}<tr><th style="border:1px solid #ddd;padding:10px;text-align:left;background-color:#f2f2f2">Coverage Type<td style="border:1px solid #ddd;padding:10px;text-align:left">{{POLICY_LONG_NAME}}<tr><th style="border:1px solid #ddd;padding:10px;text-align:left;background-color:#f2f2f2">Policy Start Date<td style="border:1px solid #ddd;padding:10px;text-align:left">{{POLICY_START_DATE}}<tr><th style="border:1px solid #ddd;padding:10px;text-align:left;background-color:#f2f2f2">Policy Duration<td style="border:1px solid #ddd;padding:10px;text-align:left">{{DURATION}}</table><div style="margin-top:20px;padding:10px;background-color:#f7f7f7;border-left:4px solid #4a90e2;font-style:italic">Please note: Additional terms and details are included in the attachment for your reference.</div><p>Please feel free to reach out if you require any further information to prepare the quote. We look forward to receiving your proposal.<p>Best regards,<p><strong>Nhance India Pvt Ltd</strong><br></div><div style=margin-top:20px;font-size:12px;color:#777;text-align:center><p>© Nhance India Pvt Ltd. All rights reserved.</div></div>';
if($recipient_data){ if ($recipient_data) {
foreach ($recipient_data as $recipient) { foreach ($recipient_data as $recipient) {
$message = $original_message; $message = $original_message;
@ -911,13 +1260,13 @@ class LeadsController extends BaseController
// print_rr($message);calculate_days_bw_dates // print_rr($message);calculate_days_bw_dates
$res = MailHelper::send_email(['mail' => $recipient['email'], 'cc'=> $cc_mails, 'subject' => $subject, 'message' => $message, 'attachments' => $attachments, 'reply_to' => $reply_to]); $res = MailHelper::send_email(['mail' => $recipient['email'], 'cc' => $cc_mails, 'subject' => $subject, 'message' => $message, 'attachments' => $attachments, 'reply_to' => $reply_to]);
// !dd($res); // !dd($res);
$result_data[] = ['mail' => $recipient['email'], 'status' => $res]; $result_data[] = ['mail' => $recipient['email'], 'status' => $res];
} }
} }
if($recipient_type == 'placement'){ if ($recipient_type == 'placement') {
list($proposal_key, $insurer_key) = explode('-', $propsal_and_insurer, 2); list($proposal_key, $insurer_key) = explode('-', $propsal_and_insurer, 2);
@ -925,7 +1274,7 @@ class LeadsController extends BaseController
'proposel_name' => $proposal_key, 'proposel_name' => $proposal_key,
'insurer_name' => $insurer_key, 'insurer_name' => $insurer_key,
'insurer' => $params['insurer_and_branch'], 'insurer' => $params['insurer_and_branch'],
] ; ];
$data = [ $data = [
'proposel_data' => json_encode($lead_update_data), 'proposel_data' => json_encode($lead_update_data),
@ -950,12 +1299,11 @@ class LeadsController extends BaseController
$data = $this->levelContactModel->getContactForRFQ(); $data = $this->levelContactModel->getContactForRFQ();
if($data){ if ($data) {
return $this->respond(['status' => true, 'data' => $data], 200); return $this->respond(['status' => true, 'data' => $data], 200);
}else{ } else {
return $this->respond(['status' => false], 200); return $this->respond(['status' => false], 200);
} }
} }
public function getInsurerBranchContacts($insurer_and_branch_id) public function getInsurerBranchContacts($insurer_and_branch_id)
@ -1081,7 +1429,6 @@ class LeadsController extends BaseController
$data['premium_data']['data'] = $premiumData; $data['premium_data']['data'] = $premiumData;
return $data; return $data;
} }
public function convertJsonForQCR($json, $type) public function convertJsonForQCR($json, $type)
@ -1264,7 +1611,7 @@ class LeadsController extends BaseController
$client_policy_id = $this->clientPolicyModel->insert($client_policy_data); $client_policy_id = $this->clientPolicyModel->insert($client_policy_data);
if($client_policy_id){ 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_client_created', $client_id)->update();
} }
@ -1301,7 +1648,7 @@ class LeadsController extends BaseController
// if ($base_policy) { // if ($base_policy) {
// $data['is_addon'] = 3; // Dependent Addon // $data['is_addon'] = 3; // Dependent Addon
// } else { // } else {
$data['is_addon'] = 1; $data['is_addon'] = 1;
// } // }
} }
@ -1328,29 +1675,82 @@ class LeadsController extends BaseController
private function convertQCRJsonToPolicyTerms($data, $policy_type, $proposel_name, $insurer_name) private function convertQCRJsonToPolicyTerms($data, $policy_type, $proposel_name, $insurer_name)
{ {
$GMC_Keys = [ $GMC_Keys = [
"sum_insured", "family_floater", "family_floaters", "age_ratio", "waiverofpreexistingdiseases", "sum_insured",
"maternitycoverage", "twindelivery", "preandpostnatal", "babyday1cover", "9monthwaitingperiodwaived", "family_floater",
"coverfromthedateofjoining", "waiverof1,2,3&4thyearexclusions", "waiverof30dayswaitingperiod", "family_floaters",
"prehospitalizationcover", "congenitaldiseasesinternal", "copayzonewisecopay", "age_ratio",
"bioabsorbablestenttoriclensmultifocallens", "roomrentlimit", "proportionatedeductionclause", "waiverofpreexistingdiseases",
"ailmentcapping", "ambulancecharges", "airambulance", "familytransportationbenefit", "maternitycoverage",
"reasonableandcustomarycharges", "ayudhtreatmentcover", "congenitaldiseasesexternal", "twindelivery",
"optionalparentalcopay", "posthospitalizationcover", "corporatebuffer", "sublimitofcorporatebuffer", "preandpostnatal",
"ayushTreatmentCoverData", "armdcovered", "suminsuredenhancement", "automaticsuminsuredreinstatement", "babyday1cover",
"additionalsicknessbenefit", "lasiksurgery", "midterminclusion", "capd", "organdonorexpenses", "9monthwaitingperiodwaived",
"moderntreatmentsasperirdai", "Wellness", "days_of_discharge", "days_from_dod", "coverfromthedateofjoining",
"special_condition_label", "special_condition_input", "multiple_sum_insured", "waiverof1,2,3&4thyearexclusions",
"cataract", "cataractData" "waiverof30dayswaitingperiod",
"prehospitalizationcover",
"congenitaldiseasesinternal",
"copayzonewisecopay",
"bioabsorbablestenttoriclensmultifocallens",
"roomrentlimit",
"proportionatedeductionclause",
"ailmentcapping",
"ambulancecharges",
"airambulance",
"familytransportationbenefit",
"reasonableandcustomarycharges",
"ayudhtreatmentcover",
"congenitaldiseasesexternal",
"optionalparentalcopay",
"posthospitalizationcover",
"corporatebuffer",
"sublimitofcorporatebuffer",
"ayushTreatmentCoverData",
"armdcovered",
"suminsuredenhancement",
"automaticsuminsuredreinstatement",
"additionalsicknessbenefit",
"lasiksurgery",
"midterminclusion",
"capd",
"organdonorexpenses",
"moderntreatmentsasperirdai",
"Wellness",
"days_of_discharge",
"days_from_dod",
"special_condition_label",
"special_condition_input",
"multiple_sum_insured",
"cataract",
"cataractData"
]; ];
$GPA_Keys = [ $GPA_Keys = [
"sumInsured2", "totalSumInsured", "age_ratio", "accidentalDeathBenefit", "permanentTotalDisablement", "sumInsured2",
"permanentPartialDisablement", "temporaryTotalDisablementBenefit", "accidentalHospitalizationExpenses", "totalSumInsured",
"childrenEducationWelfareFund", "compassionateVisitExpenses", "compassionateVisitExpensesData", "age_ratio",
"brokenBoneExpenses", "brokenBoneExpensesData", "ambulanceCharges", "ambulanceChargesData", "accidentalDeathBenefit",
"burnExpenses", "burnExpensesData", "carriageOfDeadBody", "carriageOfDeadBodyData", "permanentTotalDisablement",
"animalSnakeInsectBite", "terrorism", "worldwideCover", "gpa_special_condition_label", "permanentPartialDisablement",
"gpa_special_condition_input", "multiple_sum_insured" "temporaryTotalDisablementBenefit",
"accidentalHospitalizationExpenses",
"childrenEducationWelfareFund",
"compassionateVisitExpenses",
"compassionateVisitExpensesData",
"brokenBoneExpenses",
"brokenBoneExpensesData",
"ambulanceCharges",
"ambulanceChargesData",
"burnExpenses",
"burnExpensesData",
"carriageOfDeadBody",
"carriageOfDeadBodyData",
"animalSnakeInsectBite",
"terrorism",
"worldwideCover",
"gpa_special_condition_label",
"gpa_special_condition_input",
"multiple_sum_insured"
]; ];
// Select keys based on policy type // Select keys based on policy type
@ -1382,8 +1782,10 @@ class LeadsController extends BaseController
$value = $cellData['value'] ?? ''; $value = $cellData['value'] ?? '';
// Skip unwanted keys // Skip unwanted keys
if (in_array($parentth, ['Sno', 'Item Key', 'Particulars', 'Action']) || if (
in_array($subth, ['Quote Asked'])) { in_array($parentth, ['Sno', 'Item Key', 'Particulars', 'Action']) ||
in_array($subth, ['Quote Asked'])
) {
continue; continue;
} }
@ -1443,7 +1845,6 @@ class LeadsController extends BaseController
} }
return $this->respond(['status' => false, 'message' => 'Failed to create policy', 'data' => $data], 200); return $this->respond(['status' => false, 'message' => 'Failed to create policy', 'data' => $data], 200);
} }
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------

View File

@ -4,90 +4,215 @@ namespace App\Helpers;
use Exception; use Exception;
use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx; use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
class ExcelMergeHelper class ExcelMergeHelper
{ {
/**
* Merge multiple Excel files into a single spreadsheet. protected static $logger;
*
* @param array $filesToMerge Array of files to merge. public static function initialize()
* @param string $outputPath Path to save the merged file. {
* @return bool True if merge successful, false otherwise. self::$logger = \Config\Services::mylogger();
*/ }
public static function mergeExcelFiles(array $filesToMerge, string $outputPath): bool public static function mergeExcelFiles(array $filesToMerge, string $outputPath)
{ {
try { try {
// Validate input: If no files are provided, throw an error. self::initialize();
if (empty($filesToMerge)) { if (empty($filesToMerge)) {
throw new Exception("No files provided for merging"); throw new Exception("No files provided for merging.");
} }
// Initialize the base spreadsheet (starting with null, will be created with the first file) // Validate files exist and are readable
$spreadsheet = null; foreach ($filesToMerge as $fileData) {
if (!file_exists($fileData['file_path'])) {
// Loop through the files to merge throw new Exception("File not found: " . $fileData['file_path']);
foreach ($filesToMerge as $filePath => $sheetsToMerge) { }
// Load the current file if (!is_readable($fileData['file_path'])) {
$currentSpreadsheet = IOFactory::load($filePath); throw new Exception("File not readable: " . $fileData['file_path']);
// Debugging: Log the number of sheets in the current file
error_log("File: $filePath has " . $currentSpreadsheet->getSheetCount() . " sheets.");
// If this is the first file, initialize the base spreadsheet
if ($spreadsheet === null) {
$spreadsheet = $currentSpreadsheet;
// If specific sheets are provided for the first file, remove the others
if (!is_null($sheetsToMerge) && !empty($sheetsToMerge)) {
$sheetCount = $spreadsheet->getSheetCount();
for ($i = $sheetCount - 1; $i >= 0; $i--) {
if (!in_array($i, $sheetsToMerge)) {
$spreadsheet->removeSheetByIndex($i);
}
}
}
} else {
// If we are not working with the first file, we need to merge specified sheets
if (is_null($sheetsToMerge) || empty($sheetsToMerge)) {
// If no specific sheets, merge all sheets
$sheetsToMerge = range(0, $currentSpreadsheet->getSheetCount() - 1);
}
// Merge the specified sheets from the current file
foreach ($sheetsToMerge as $sheetIndex) {
// Check if sheet index is within bounds
if ($sheetIndex < 0 || $sheetIndex >= $currentSpreadsheet->getSheetCount()) {
throw new Exception("Invalid sheet index $sheetIndex in file $filePath");
}
// Retrieve the sheet to copy
$sheetToCopy = $currentSpreadsheet->getSheet($sheetIndex);
// Handle sheet name collision by renaming the sheet with a counter
$baseName = $sheetToCopy->getTitle();
$sheetName = $baseName;
$counter = 1;
while ($spreadsheet->sheetNameExists($sheetName)) {
$sheetName = $baseName . '_merged_' . $counter;
$counter++;
}
$sheetToCopy->setTitle($sheetName);
// Clone and add the sheet to the base spreadsheet
$spreadsheet->addSheet(clone $sheetToCopy);
}
} }
} }
// Save the merged file self::$logger->logme('error',"Creating new spreadsheet...");
$writer = new Xlsx($spreadsheet); $mergedSpreadsheet = new Spreadsheet();
$firstSheet = true;
foreach ($filesToMerge as $fileIndex => $fileData) {
$filePath = $fileData['file_path'];
$sheetsToMerge = $fileData['sheets'];
self::$logger->logme('error',"Processing file $fileIndex: $filePath");
try {
self::$logger->logme('error',"Attempting to load file: $filePath");
$reader = IOFactory::createReaderForFile($filePath);
$reader->setReadDataOnly(true); // This can help with memory usage
self::$logger->logme('error',"Reader created successfully");
$currentSpreadsheet = $reader->load($filePath);
self::$logger->logme('error',"File loaded successfully");
$sheetCount = $currentSpreadsheet->getSheetCount();
self::$logger->logme('error',"File $filePath has $sheetCount sheets.");
if (empty($sheetsToMerge)) {
$sheetsToMerge = range(0, $sheetCount - 1);
}
foreach ($sheetsToMerge as $sourceSheetIndex) {
self::$logger->logme('error',"Processing sheet index: $sourceSheetIndex");
if ($sourceSheetIndex < 0 || $sourceSheetIndex >= $sheetCount) {
self::$logger->logme('error',"Invalid sheet index $sourceSheetIndex in file $filePath");
continue;
}
try {
$sourceSheet = $currentSpreadsheet->getSheet($sourceSheetIndex);
self::$logger->logme('error',"Source sheet loaded");
$baseName = $sourceSheet->getTitle();
self::$logger->logme('error',"Processing sheet: $baseName");
$newSheetName = $baseName;
$counter = 1;
while ($mergedSpreadsheet->sheetNameExists($newSheetName)) {
$newSheetName = $baseName . '_' . $fileIndex . '_' . $counter;
$counter++;
}
self::$logger->logme('error',"New sheet name will be: $newSheetName");
if ($firstSheet) {
$targetSheet = $mergedSpreadsheet->getActiveSheet();
$targetSheet->setTitle($newSheetName);
$firstSheet = false;
self::$logger->logme('error',"Using first sheet");
} else {
$targetSheet = new Worksheet($mergedSpreadsheet, $newSheetName);
$mergedSpreadsheet->addSheet($targetSheet);
self::$logger->logme('error',"Created new sheet");
}
self::$logger->logme('error',"Starting content copy for sheet: $newSheetName");
self::copyWorksheetContent($sourceSheet, $targetSheet);
self::$logger->logme('error',"Content copied successfully for sheet: $newSheetName");
} catch (Exception $e) {
self::$logger->logme('error',"Error processing sheet $sourceSheetIndex: " . $e->getMessage());
self::$logger->logme('error',"Error trace: " . $e->getTraceAsString());
continue;
}
}
// Free up memory
$currentSpreadsheet->disconnectWorksheets();
unset($currentSpreadsheet);
self::$logger->logme('error',"Cleaned up spreadsheet resources");
} catch (Exception $e) {
self::$logger->logme('error',"Error processing file $filePath: " . $e->getMessage());
self::$logger->logme('error',"Error trace: " . $e->getTraceAsString());
continue;
}
self::$logger->logme('error',"Current sheet names in merged spreadsheet:");
foreach ($mergedSpreadsheet->getSheetNames() as $name) {
self::$logger->logme('error'," - $name");
}
}
if ($mergedSpreadsheet->getSheetCount() === 0) {
throw new Exception("No sheets were successfully merged.");
}
self::$logger->logme('error',"Setting active sheet to index 0");
$mergedSpreadsheet->setActiveSheetIndex(0);
self::$logger->logme('error',"Preparing to save merged file to: $outputPath");
// Ensure output directory exists
$outputDir = dirname($outputPath);
if (!is_dir($outputDir)) {
mkdir($outputDir, 0777, true);
}
if (!is_writable($outputDir)) {
throw new Exception("Output directory is not writable: $outputDir");
}
if (ob_get_length()) {
ob_end_clean();
}
self::$logger->logme('error',"Creating Excel writer");
$writer = new Xlsx($mergedSpreadsheet);
self::$logger->logme('error',"Saving file...");
$writer->save($outputPath); $writer->save($outputPath);
return true; // Return true if merge was successful // Free up memory
$mergedSpreadsheet->disconnectWorksheets();
unset($mergedSpreadsheet);
self::$logger->logme('error',"Merge successful. File saved at: $outputPath");
return $outputPath;
} catch (Exception $e) { } catch (Exception $e) {
// Log the error (optional) and return false on failure self::$logger->logme('error',"Excel Merge Error: " . $e->getMessage());
error_log("Excel Merge Error: " . $e->getMessage()); self::$logger->logme('error',"Error trace: " . $e->getTraceAsString());
return false; throw $e;
}
}
private static function copyWorksheetContent($sourceSheet, $targetSheet)
{
try {
self::$logger->logme('error',"Starting copyWorksheetContent");
// Get the highest row and column indexes
$highestRow = $sourceSheet->getHighestRow();
$highestColumn = $sourceSheet->getHighestColumn();
self::$logger->logme('error',"Copying data from range A1:{$highestColumn}{$highestRow}");
// Copy cell values only first for better performance
foreach ($sourceSheet->getRowIterator() as $row) {
$cellIterator = $row->getCellIterator();
$cellIterator->setIterateOnlyExistingCells(true);
foreach ($cellIterator as $cell) {
$column = $cell->getColumn();
$rowIndex = $cell->getRow();
$targetSheet->setCellValue($column . $rowIndex, $cell->getValue());
}
}
self::$logger->logme('error',"Basic cell values copied");
// Copy column dimensions
foreach ($sourceSheet->getColumnDimensions() as $columnId => $sourceDim) {
$targetSheet->getColumnDimension($columnId)
->setWidth($sourceDim->getWidth())
->setVisible($sourceDim->getVisible())
->setAutoSize($sourceDim->getAutoSize());
}
self::$logger->logme('error',"Column dimensions copied");
// Copy row dimensions
foreach ($sourceSheet->getRowDimensions() as $rowId => $sourceDim) {
$targetSheet->getRowDimension($rowId)
->setRowHeight($sourceDim->getRowHeight())
->setVisible($sourceDim->getVisible());
}
self::$logger->logme('error',"Row dimensions copied");
// Copy basic worksheet properties
$targetSheet->setShowGridlines($sourceSheet->getShowGridlines());
$targetSheet->setShowRowColHeaders($sourceSheet->getShowRowColHeaders());
self::$logger->logme('error',"Worksheet properties copied");
} catch (Exception $e) {
self::$logger->logme('error',"Error in copyWorksheetContent: " . $e->getMessage());
self::$logger->logme('error',"Error trace: " . $e->getTraceAsString());
throw $e;
} }
} }
} }

View File

@ -10,8 +10,11 @@ class ExcelMergeHelperTest extends TestCase
{ {
// Use the paths you provided // Use the paths you provided
$filePaths = [ $filePaths = [
'/home/venba/Downloads/Financial_Sample.xlsx' => [1,3,2], // ['file_path' =>WRITEPATH.'uploads/lead_files/Member_Data.xlsx','sheets' => []],
'/home/venba/Downloads/enrollment.xlsx' => [] // ['file_path' =>WRITEPATH.'/tmp/RFQ_ABC_GMC_20241220140640.xlsx','sheets' => []],
['file_path' =>'/home/venba/Downloads/enrollment (1).xlsx','sheets' => []],
['file_path' =>'/home/venba/Downloads/Financial_Sample.xlsx','sheets' => []],
]; ];
$outputPath = '/home/venba/Documents/merged_file.xlsx'; // Output path for the merged file $outputPath = '/home/venba/Documents/merged_file.xlsx'; // Output path for the merged file
@ -23,3 +26,12 @@ class ExcelMergeHelperTest extends TestCase
} }
} }
// $temp_file_path = WRITEPATH.'tmp/RFQ_ABC_GMC_20241219172307.xlsx';
// $temp_file_name = 'RFQ_ABC_GMC_20241219172307.xlsx';
// $lead_file_path = WRITEPATH.'uploads/lead_files/Member_Data.xlsx';
// $filePaths = [
// ['file_path' => $temp_file_path,'sheets' =>[]],
// ['file_path' =>$lead_file_path ,'sheets' =>[]]
// ];
// $outputPath = dirname($temp_file_path).'/'.$temp_file_name.'_merged';

View File

@ -0,0 +1,183 @@
<?php
namespace Tests\unit;
use Exception;
use CodeIgniter\Test\CIUnitTestCase;
use App\Controllers\LeadsController;
class LeadsControllerTest extends CIUnitTestCase
{
protected $leadsController;
protected function setUp(): void
{
parent::setUp();
$this->leadsController = new LeadsController();
}
public function testGetDemographyDataBasicScenario()
{
echo('passed 0');
// Arrange
$members = [
// Header row
['Name', 'Age', 'Relationship', 'SI Enhancement'],
// Data rows
['John', '25', 'Self', '100000'],
['Jane', '23', 'Spouse', '100000'],
['Kid', '5', 'Child', '50000']
];
echo('passed 1');
$age_band_data = [
['0-17', '18-35', '36-45', 'Above 46']
];
echo('passed 2');
$members_heading = ['Name', 'Age', 'Relationship', 'SI Enhancement'];
$available_col = 'age';print_rr($available_col);
$col_index = 1;
echo('passed 3');
try{
echo('Inside try');
// Act
echo('passed 3.5');
$result = $this->leadsController->getDemographyData($members,$age_band_data,$members_heading,$available_col,$col_index);
echo('passed 4');
} catch (Exception $e) {
echo "Message: " . $e->getMessage() . "\n";
echo "File: " . $e->getFile() . "\n";
echo "Line: " . $e->getLine() . "\n";
// Optionally, print the full stack trace
echo "Stack trace: " . $e->getTraceAsString() . "\n";
}
var_dump($result);
// Assert
$this->assertIsArray($result);
$this->assertArrayHasKey('general', $result);
$this->assertArrayHasKey('100000', $result);
$this->assertArrayHasKey('50000', $result);
// Check counts for general category
$this->assertEquals(1, $result['general']['Self']['18-35']);
$this->assertEquals(1, $result['general']['Spouse']['18-35']);
$this->assertEquals(1, $result['general']['Child']['0-17']);
}
public function testGetDemographyDataWithDOB()
{
// Arrange
$members = [
// Header row
['Name', 'DOB', 'Relationship', 'SI Enhancement'],
// Data rows
['John', '01-Jan-1995', 'Self', '100000'],
['Jane', '01-Jan-1998', 'Spouse', '100000']
];
$age_band_data = [
['18-35', '36-45', '46+']
];
$members_heading = ['Name', 'DOB', 'Relationship', 'SI Enhancement'];
$available_col = 'dob';
$col_index = 1;
// Act
$result = $this->leadsController->getDemographyData(
$members,
$age_band_data,
$members_heading,
$available_col,
$col_index
);
// Assert
$this->assertIsArray($result);
$this->assertArrayHasKey('general', $result);
$this->assertArrayHasKey('100000', $result);
// Both members should be in 18-35 age band
$this->assertEquals(1, $result['general']['Self']['18-35']);
$this->assertEquals(1, $result['general']['Spouse']['18-35']);
}
public function testGetDemographyDataWithEmptyMembers()
{
// Arrange
$members = [
// Only header row
['Name', 'Age', 'Relationship', 'SI Enhancement']
];
$age_band_data = [
['0-17', '18-35', '36-45', '46+']
];
$members_heading = ['Name', 'Age', 'Relationship', 'SI Enhancement'];
$available_col = 'age';
$col_index = 1;
// Act
$result = $this->leadsController->getDemographyData(
$members,
$age_band_data,
$members_heading,
$available_col,
$col_index
);
// Assert
$this->assertIsArray($result);
$this->assertArrayHasKey('general', $result);
// Check that all totals are zero
$this->assertEquals(0, $result['general']['Grand Total']['Grand Total']);
}
public function testGetDemographyDataWithMultipleSIBands()
{
// Arrange
$members = [
// Header row
['Name', 'Age', 'Relationship', 'SI Enhancement'],
// Data rows with different SI amounts
['John', '25', 'Self', '100000'],
['Jane', '23', 'Spouse', '200000'],
['Kid1', '5', 'Child', '100000'],
['Kid2', '7', 'Child', '200000']
];
$age_band_data = [
['0-17', '18-35', '36-45', '46+']
];
$members_heading = ['Name', 'Age', 'Relationship', 'SI Enhancement'];
$available_col = 'age';
$col_index = 1;
// Act
$result = $this->leadsController->getDemographyData(
$members,
$age_band_data,
$members_heading,
$available_col,
$col_index
);
// Assert
$this->assertIsArray($result);
$this->assertArrayHasKey('100000', $result);
$this->assertArrayHasKey('200000', $result);
// Check counts for different SI bands
$this->assertEquals(1, $result['100000']['Self']['18-35']);
$this->assertEquals(1, $result['200000']['Spouse']['18-35']);
$this->assertEquals(1, $result['100000']['Child']['0-17']);
$this->assertEquals(1, $result['200000']['Child']['0-17']);
// Check general category totals
$this->assertEquals(2, $result['general']['Child']['0-17']);
$this->assertEquals(2, $result['general']['Child']['Grand Total']);
}
}