diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 34cca86..c5573cb 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -94,7 +94,7 @@ $routes->group('api', ['filter' => 'appSignature'], function ($routes) { $routes->get('enquiry/getQuickQuoteEnquiryList', 'EnquiryController::getQuickQuoteEnquiryList'); $routes->get('enquiry/updateEnquiryInProgress', 'EnquiryController::updateEnquiryInProgress'); $routes->get('enquiry/updateEnquiryStatus', 'EnquiryController::updateEnquiryStatus'); - $routes->get('enquiry/checkVehicleDuplicate', 'EnquiryController::checkVehicleDuplicate'); + $routes->get('enquiry/checkVehicleDuplicate', 'EnquiryController::checkVehicleDuplicate'); // VALIDATION //Proposal @@ -132,13 +132,24 @@ $routes->group('api', ['filter' => 'appSignature'], function ($routes) { $routes->get('dashboard/staffDashboard', 'DashboardController::staffDashboard'); $routes->get('dashboard/agentDashboard', 'DashboardController::agentDashboard'); + //DASHBOARD Season 2 $routes->get("dashboard/businessDashboard", "DashboardController::businessDashboard"); $routes->get("dashboard/partnerDashboard", "DashboardController::partnerDashboard"); $routes->get("dashboard/productivityDashboard", "DashboardController::productivityDashboard"); - $routes->get("dashboard/downloadBrokerPoliciesExcel", "DashboardController::downloadBrokerPoliciesExcel"); - $routes->get("dashboard/downloadInsurerPoliciesExcel", "DashboardController::downloadInsurerPoliciesExcel"); - $routes->get("dashboard/downloadProductPoliciesExcel", "DashboardController::downloadProductPoliciesExcel"); + //DASHBOARD Season 3 EXPORT EXCEL + $routes->get("dashboard/downloadBrokerPoliciesExcel", "ExcelExportController::downloadBrokerPoliciesExcel"); + $routes->get("dashboard/downloadInsurerPoliciesExcel", "ExcelExportController::downloadInsurerPoliciesExcel"); + $routes->get("dashboard/downloadProductPoliciesExcel", "ExcelExportController::downloadProductPoliciesExcel"); + + //DASHBOARD Season 4 EXPORT EXCEL + $routes->get("dashboard/downloadAgentMonthlyPoliciesExcel", "ExcelExportController::downloadAgentMonthlyPoliciesExcel"); + $routes->get("dashboard/downloadLowPremiumAgentExcel", "ExcelExportController::downloadLowPremiumAgentExcel"); + $routes->get("dashboard/downloadAgentsWithoutPoliciesExcel", "ExcelExportController::downloadAgentsWithoutPoliciesExcel"); + + //DASHBOARD Season 5 EXPORT EXCEL + $routes->get("dashboard/downloadStaffAndProductPoliciesExcel", "ExcelExportController::downloadStaffAndProductPoliciesExcel"); + //invoice @@ -149,6 +160,7 @@ $routes->group('api', ['filter' => 'appSignature'], function ($routes) { $routes->post('invoice/commission-rate-list', 'InvoiceController::getCommissionRateList'); + // SALES EXECUTIVE $routes->get('salesExecutive/executiveList', 'SalesExecutive::salesExecutiveList'); $routes->get('salesExecutive/findExecutive', 'SalesExecutive::findSalesExecutive'); $routes->post('salesExecutive/createExecutive', 'SalesExecutive::createSalesExecutive'); @@ -156,7 +168,6 @@ $routes->group('api', ['filter' => 'appSignature'], function ($routes) { $routes->post('salesExecutive/changeExecutiveStatus', 'SalesExecutive::changeSalesExecutiveStatus'); - }); @@ -167,7 +178,7 @@ $routes->group('api', ['filter' => 'appSignature'], function ($routes) { $routes->get("policyCommissionCalculationAndGeminiPolicyRead", "PolicyController::policyCommissionCalculationAndGeminiPolicyRead"); }); - + $routes->cli('cli/processjob', 'JobWorker::processJob'); $routes->cli('cli/processjobs', 'JobWorker::processJobs'); $routes->get("processjob", "JobWorker::processJob"); @@ -192,4 +203,3 @@ $routes->get("processjob", "JobWorker::processJob"); - diff --git a/app/Controllers/DashboardController.php b/app/Controllers/DashboardController.php index 7ea291b..f392ab7 100644 --- a/app/Controllers/DashboardController.php +++ b/app/Controllers/DashboardController.php @@ -3,9 +3,6 @@ namespace App\Controllers; use CodeIgniter\RESTful\ResourceController; -use PhpOffice\PhpSpreadsheet\Spreadsheet; -use PhpOffice\PhpSpreadsheet\Writer\Xlsx; -use PhpOffice\PhpSpreadsheet\Style\Border; class DashboardController extends ResourceController { @@ -813,7 +810,7 @@ class DashboardController extends ResourceController pa.id AS agent_id, pa.name AS agent_name, pa.agent_code, - COUNT(pp.id) AS policy_count, + COUNT(pp.policy_number) AS policy_count, SUM(pp.premium_amount) AS total_premium_amount "); @@ -1066,1219 +1063,4 @@ class DashboardController extends ResourceController return array_values($final); } - // Function to generate the Excel file - public function downloadBrokerPoliciesExcel() - { - try{ - $managerId = $this->request->getGet('manager_id'); - $brokerId = $this->request->getGet('broker_id'); - $month = $this->request->getGet('month'); - - // --- ADDED VALIDATION (Simplified logic for clarity) --- - if (empty($managerId) || empty($brokerId) || empty($month)) { - $msg = "Missing: "; - $msg .= empty($managerId) ? "manager_id " : ""; - $msg .= empty($brokerId) ? "broker_id " : ""; - $msg .= empty($month) ? "month " : ""; - $ref = ['debug_msg' => $msg]; - // $ref = ['message' => 'Missing required parameters: manager_id, broker_id, and month must be provided.']; - // Status code remains 200, but JSON code is 400 as per your preference - return $this->response->setJSON([ - 'status' => 'error', - 'code' => 400, - 'data' => [], - 'message' => 'Missing required parameters', - 'ref' => $ref - ])->setStatusCode(200); - } - - $data = $this->getBrokerPoliciesData($managerId, $brokerId, $month); - // Define column headers - $header = ['Broker Name', 'Issue Date', 'Policy Number', 'Premium Amount']; - - // --- 1. MODIFIED LOGIC: Throw RuntimeException if no data --- - if (empty($data)) { - throw new \RuntimeException('No policies found for this broker for the specified month.', 404); - } - - $grandTotal = 0; - foreach ($data as $row) { $grandTotal += (float)$row[3]; } - - // Create and append the "Total" row - $totalRow = ['','','Total:',$grandTotal]; - $data[] = $totalRow; - - // Determine file name and date string - $monthName = ($month === 'current') ? date('Ym') : date('Ym', strtotime('-1 month')); - $brokerName = $data[0][0]; - - // 2. Prepare PhpSpreadsheet (assuming $spreadsheet, $writer, etc. are created here) - while (ob_get_level() > 0) { - ob_end_clean(); - } - - // Create Spreadsheet - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - - // Title - $sheet->mergeCells('A1:D1'); - $sheet->setCellValue('A1', "Broker Policies Details for $month"); - $sheet->getStyle('A1')->getAlignment()->setHorizontal('center'); - - // Headers - $sheet->fromArray($header, NULL, 'A2'); - - // Data - $sheet->fromArray($data, NULL, 'A3'); - - // File Name - $fileName = $brokerName . '_Policies_Details_' . $monthName . '.xlsx'; - - // 1. Define the target row number (Must be the first step!) - $totalRowNumber = count($data) + 2; - - // 2. Set the 'TOTAL:' label in Column C - $sheet->setCellValue('C' . $totalRowNumber, 'TOTAL:'); - - // 3. Apply bold formatting to the label and the sum (Columns C and D) - $sheet->getStyle('C' . $totalRowNumber . ':D' . $totalRowNumber)->getFont()->setBold(true); - - // 4. Align the label to the right for a clean look next to the sum - $sheet->getStyle('C' . $totalRowNumber)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_RIGHT); - - // HTTP Headers - header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); - header("Content-Disposition: attachment; filename=\"{$fileName}\""); - header("Cache-Control: max-age=0"); - - // Output File - $writer = new Xlsx($spreadsheet); - $writer->save('php://output'); - - return; // STOP CI4 rendering anything else - - } catch (\Throwable $e) { - - // ... (Your error handling remains the same) ... - $ref = []; - // Case 1: No Data Found (Soft Success JSON) - if ($e instanceof \RuntimeException && $e->getCode() === 404) { - $ref['debug_msg'] = 'No Data Found'; - return $this->respond([ - 'status' => 'success', - 'code' => 200, - 'data' => [], - 'message' => 'No Data Found', - 'ref' => $ref - ], 200); - } - - // Case 2: Database or Other Error (Error JSON) - $isDbError = $e instanceof \CodeIgniter\Database\Exceptions\DatabaseException - || $e instanceof \mysqli_sql_exception - || $e instanceof \PDOException; - - if ($isDbError) { - $ref['debug_info'] = $e->getFile() . " / LN : " . $e->getLine(); - $ref['debug_msg'] = 'Database Error Occurred: ' . $e->getMessage(); - $message = 'Database Error Occurred.'; - } else { - $ref['debug_msg'] = 'An unexpected error occurred: ' . $e->getMessage(); - $message = 'Something went wrong. Please try again later.'; - } - - return $this->respond([ - 'status' => 'error', - 'code' => 500, - 'data' => [], - 'message'=> $message, - 'ref' => $ref - ], 200); - } - } - - /** - * Executes the detailed policy query and extracts the data for the spreadsheet. - * @param string $managerId - * @param int $brokerId - * @param string $month ('current' or 'previous') - * @return array - */ - private function getBrokerPoliciesData($managerId, $brokerId, $month): array - { - // --- Correction 1: Initialize Database Connection --- - $db = \Config\Database::connect(); - $data = []; - - try { - $builder = $db->table('partner_policy pp'); - // Note: I removed 'broker_id' from SELECT as it's redundant in the Excel sheet details - $builder->select('pb.name AS broker_name, DATE_FORMAT(pp.issued_date, "%d-%m-%Y") AS issued_date,pp.policy_number, pp.premium_amount'); - $builder->join('partner_enquiry pe', 'pe.id = pp.enquiry_id', 'left'); - $builder->join('partner_brokers pb', 'pb.id = pe.broker_id', 'left'); - - // --- Correction 2: Use Robust Date Range Filtering --- - if ($month === "current") { - // WHERE issued_date >= start_of_current_month AND issued_date < start_of_next_month - $builder->where("pp.issued_date >= DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); - $builder->where("pp.issued_date < DATE_FORMAT(DATE_ADD(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); - } - else if ($month === "previous") { - // WHERE issued_date >= start_of_previous_month AND issued_date < start_of_current_month - $builder->where("pp.issued_date >= DATE_FORMAT(DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); - $builder->where("pp.issued_date < DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); - } - - // Broker and Manager Filter - $builder->where('pp.manager_id', $managerId); - $builder->where('pb.id', $brokerId); - $builder->orderBy('pp.issued_date', 'DESC'); - - $results = $builder->get()->getResultArray(); - - // Restructure data for PhpSpreadsheet (2D array of values) - foreach ($results as $row) { - $data[] = array_values($row); - } - - } catch (DatabaseException $e) { - log_message('error', 'Database Error during Excel fetch: ' . $e->getMessage()); - // Re-throw the exception so it is caught by the main function's catch block - throw $e; - } - - return $data; - } - - // Function to generate the Excel file - public function downloadProductPoliciesExcel() - { - try{ - $managerId = $this->request->getGet('manager_id'); - $vehicleType = $this->request->getGet('vehicle_type'); - $month = $this->request->getGet('month'); - - // --- ADDED VALIDATION (Simplified logic for clarity) --- - if (empty($managerId) || empty($vehicleType) || empty($month)) { - $msg = "Missing: "; - $msg .= empty($managerId) ? "manager_id " : ""; - $msg .= empty($vehicleType) ? "vehicle_type " : ""; - $msg .= empty($month) ? "month " : ""; - $ref = ['debug_msg' => $msg]; - // $ref = ['message' => 'Missing required parameters: manager_id, vehicle_type, and month must be provided.']; - // Status code remains 200, but JSON code is 400 as per your preference - return $this->response->setJSON([ - 'status' => 'error', - 'code' => 400, - 'data' => [], - 'message' => 'Missing required parameters', - 'ref' => $ref - ])->setStatusCode(200); - } - - $data = $this->getProductPoliciesData($managerId, $vehicleType, $month); - // Define column headers - $header = ['Vehicle Type', 'Issue Date', 'Policy Number', 'Premium Amount']; - - // --- 1. MODIFIED LOGIC: Throw RuntimeException if no data --- - if (empty($data)) { - throw new \RuntimeException('No policies found for this vehicle type for the specified month.', 404); - } - - $grandTotal = 0; - foreach ($data as $row) { $grandTotal += (float)$row[3]; } - - // Create and append the "Total" row - $totalRow = ['','','Total:',$grandTotal]; - $data[] = $totalRow; - - // Determine file name and date string - $monthName = ($month === 'current') ? date('Ym') : date('Ym', strtotime('-1 month')); - $vehicleType = $data[0][0]; - - // 2. Prepare PhpSpreadsheet (assuming $spreadsheet, $writer, etc. are created here) - while (ob_get_level() > 0) { - ob_end_clean(); - } - - // Create Spreadsheet - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - - // Title - $sheet->mergeCells('A1:D1'); - $sheet->setCellValue('A1', "Vehicle Type Policies Details for $month"); - $sheet->getStyle('A1')->getAlignment()->setHorizontal('center'); - - // Headers - $sheet->fromArray($header, NULL, 'A2'); - - // Data - $sheet->fromArray($data, NULL, 'A3'); - - // File Name - $fileName = $vehicleType . '_Policies_Details_' . $monthName . '.xlsx'; - - // 1. Define the target row number (Must be the first step!) - $totalRowNumber = count($data) + 2; - - // 2. Set the 'TOTAL:' label in Column C - $sheet->setCellValue('C' . $totalRowNumber, 'TOTAL:'); - - // 3. Apply bold formatting to the label and the sum (Columns C and D) - $sheet->getStyle('C' . $totalRowNumber . ':D' . $totalRowNumber)->getFont()->setBold(true); - - // 4. Align the label to the right for a clean look next to the sum - $sheet->getStyle('C' . $totalRowNumber)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_RIGHT); - - // HTTP Headers - header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); - header("Content-Disposition: attachment; filename=\"{$fileName}\""); - header("Cache-Control: max-age=0"); - - // Output File - $writer = new Xlsx($spreadsheet); - $writer->save('php://output'); - - return; // STOP CI4 rendering anything else - - } catch (\Throwable $e) { - - // ... (Your error handling remains the same) ... - $ref = []; - // Case 1: No Data Found (Soft Success JSON) - if ($e instanceof \RuntimeException && $e->getCode() === 404) { - $ref['debug_msg'] = 'No Data Found'; - return $this->respond([ - 'status' => 'success', - 'code' => 200, - 'data' => [], - 'message' => 'No Data Found', - 'ref' => $ref - ], 200); - } - - // Case 2: Database or Other Error (Error JSON) - $isDbError = $e instanceof \CodeIgniter\Database\Exceptions\DatabaseException - || $e instanceof \mysqli_sql_exception - || $e instanceof \PDOException; - - if ($isDbError) { - $ref['debug_info'] = $e->getFile() . " / LN : " . $e->getLine(); - $ref['debug_msg'] = 'Database Error Occurred: ' . $e->getMessage(); - $message = 'Database Error Occurred.'; - } else { - $ref['debug_msg'] = 'An unexpected error occurred: ' . $e->getMessage(); - $message = 'Something went wrong. Please try again later.'; - } - - return $this->respond([ - 'status' => 'error', - 'code' => 500, - 'data' => [], - 'message'=> $message, - 'ref' => $ref - ], 200); - } - } - - /** - * Executes the detailed policy query and extracts the data for the spreadsheet. - * @param string $managerId - * @param string $vehicleType - * @param string $month ('current' or 'previous') - * @return array - */ - private function getProductPoliciesData($managerId, $vehicleType, $month): array - { - // --- Correction 1: Initialize Database Connection --- - $db = \Config\Database::connect(); - $data = []; - - try { - $builder = $db->table('partner_policy pp'); - // Note: I removed 'broker_id' from SELECT as it's redundant in the Excel sheet details - $builder->select('pp.vehicle_type, DATE_FORMAT(pp.issued_date, "%d-%m-%Y") AS issued_date,pp.policy_number, pp.premium_amount'); - - - // --- Correction 2: Use Robust Date Range Filtering --- - if ($month === "current") { - // WHERE issued_date >= start_of_current_month AND issued_date < start_of_next_month - $builder->where("pp.issued_date >= DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); - $builder->where("pp.issued_date < DATE_FORMAT(DATE_ADD(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); - } - else if ($month === "previous") { - // WHERE issued_date >= start_of_previous_month AND issued_date < start_of_current_month - $builder->where("pp.issued_date >= DATE_FORMAT(DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); - $builder->where("pp.issued_date < DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); - } - - // Broker and Manager Filter - $builder->where('pp.manager_id', $managerId); - $builder->where('pp.vehicle_type', $vehicleType); - - - $results = $builder->get()->getResultArray(); - - // Restructure data for PhpSpreadsheet (2D array of values) - foreach ($results as $row) { - $data[] = array_values($row); - } - - } catch (DatabaseException $e) { - log_message('error', 'Database Error during Excel fetch: ' . $e->getMessage()); - // Re-throw the exception so it is caught by the main function's catch block - throw $e; - } - - return $data; - } - - // Function to generate the Excel file - public function downloadInsurerPoliciesExcel() - { - try{ - $managerId = $this->request->getGet('manager_id'); - $insurerId = $this->request->getGet('insurer_id'); - $month = $this->request->getGet('month'); - - // --- ADDED VALIDATION (Simplified logic for clarity) --- - if (empty($managerId) || empty($insurerId) || empty($month)) { - $msg = "Missing: "; - $msg .= empty($managerId) ? "manager_id " : ""; - $msg .= empty($insurerId) ? "insurer_id " : ""; - $msg .= empty($month) ? "month " : ""; - $ref = ['debug_msg' => $msg]; - // Status code remains 200, but JSON code is 400 as per your preference - return $this->response->setJSON([ - 'status' => 'error', - 'code' => 400, - 'data' => [], - 'message' => 'Missing required parameters', - 'ref' => $ref - ])->setStatusCode(200); - } - - $data = $this->getInsurerPoliciesData($managerId, $insurerId, $month); - - // Define column headers - $header = ['Insurer Name', 'Insurer Short Name','Insured Name', 'Policy Issued Date','Policy Number', 'Premium Amount']; - - // --- 1. MODIFIED LOGIC: Throw RuntimeException if no data --- - if (empty($data)) { - throw new \RuntimeException('No policies found for this insurer for the specified month.', 404); - } - - $grandTotal = 0; - foreach ($data as $row) { $grandTotal += (float)$row[5]; } - - // Create and append the "Total" row - $totalRow = ['','','','','Total:',$grandTotal]; - $data[] = $totalRow; - - // Determine file name and date string - $monthName = ($month === 'current') ? date('Ym') : date('Ym', strtotime('-1 month')); - $InsurerName = $data[0][0]; - - // 2. Prepare PhpSpreadsheet (assuming $spreadsheet, $writer, etc. are created here) - while (ob_get_level() > 0) { - ob_end_clean(); - } - - // Create Spreadsheet - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - - // Title - $sheet->mergeCells('A1:G1'); - $sheet->setCellValue('A1', "Insurer Policies Details for $month"); - $sheet->getStyle('A1')->getAlignment()->setHorizontal('center'); - - // Headers - $sheet->fromArray($header, NULL, 'A2'); - - // Data - $sheet->fromArray($data, NULL, 'A3'); - - // 1. Define the target row number (Must be the first step!) - $totalRowNumber = count($data) + 2; - - // 2. Set the 'TOTAL:' label in Column F - $sheet->setCellValue('E' . $totalRowNumber, 'TOTAL:'); - - // 3. Apply bold formatting to the label and the sum (Columns C and D) - $sheet->getStyle('E' . $totalRowNumber . ':F' . $totalRowNumber)->getFont()->setBold(true); - - // 4. Align the label to the right for a clean look next to the sum - $sheet->getStyle('E' . $totalRowNumber)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_RIGHT); - - // File Name - $fileName = $InsurerName . '_Policies_Details_' . $monthName . '.xlsx'; - - // HTTP Headers - header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); - header("Content-Disposition: attachment; filename=\"{$fileName}\""); - header("Cache-Control: max-age=0"); - - // Output File - $writer = new Xlsx($spreadsheet); - $writer->save('php://output'); - - return; // STOP CI4 rendering anything else - - } catch (\Throwable $e) { - - // ... (Your error handling remains the same) ... - $ref = []; - // Case 1: No Data Found (Soft Success JSON) - if ($e instanceof \RuntimeException && $e->getCode() === 404) { - $ref['debug_msg'] = 'No Data Found'; - return $this->respond([ - 'status' => 'success', - 'code' => 200, - 'data' => [], - 'message' => 'No Data Found', - 'ref' => $ref - ], 200); - } - - // Case 2: Database or Other Error (Error JSON) - $isDbError = $e instanceof \CodeIgniter\Database\Exceptions\DatabaseException - || $e instanceof \mysqli_sql_exception - || $e instanceof \PDOException; - - if ($isDbError) { - $ref['debug_info'] = $e->getFile() . " / LN : " . $e->getLine(); - $ref['debug_msg'] = 'Database Error Occurred: ' . $e->getMessage(); - $message = 'Database Error Occurred.'; - } else { - $ref['debug_msg'] = 'An unexpected error occurred: ' . $e->getMessage(); - $message = 'Something went wrong. Please try again later.'; - } - - return $this->respond([ - 'status' => 'error', - 'code' => 500, - 'data' => [], - 'message'=> $message, - 'ref' => $ref - ], 200); - } - } - - /** - * Executes the detailed policy query and extracts the data for the spreadsheet. - * @param string $managerId - * @param int $insurerId - * @param string $month ('current' or 'previous') - * @return array - */ - private function getInsurerPoliciesData($managerId, $insurerId, $month): array - { - // --- Correction 1: Initialize Database Connection --- - $db = \Config\Database::connect(); - $data = []; - - try { - $builder = $db->table('partner_policy pp'); - // Note: I removed 'broker_id' from SELECT as it's redundant in the Excel sheet details - $builder->select('i.name AS insurer_name,i.short_name,pp.insured_name, DATE_FORMAT(pp.issued_date, "%d-%m-%Y") AS issued_date,pp.policy_number, pp.premium_amount'); - - $builder->join('partner_quotation pq', 'pq.id = pp.quotation_id', 'left'); - $builder->join('insurers i', 'i.id = pq.insurer_id', 'left'); - - - // --- Correction 2: Use Robust Date Range Filtering --- - if ($month === "current") { - // WHERE issued_date >= start_of_current_month AND issued_date < start_of_next_month - $builder->where("pp.issued_date >= DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); - $builder->where("pp.issued_date < DATE_FORMAT(DATE_ADD(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); - } - else if ($month === "previous") { - // WHERE issued_date >= start_of_previous_month AND issued_date < start_of_current_month - $builder->where("pp.issued_date >= DATE_FORMAT(DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); - $builder->where("pp.issued_date < DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); - } - - // Broker and Manager Filter - $builder->where('pp.manager_id', $managerId); - $builder->where('i.id', $insurerId); - $builder->where('i.is_active',1); - $builder->orderBy('pp.issued_date', 'DESC'); - - $results = $builder->get()->getResultArray(); - - // Restructure data for PhpSpreadsheet (2D array of values) - foreach ($results as $row) { - $data[] = array_values($row); - } - - } catch (DatabaseException $e) { - log_message('error', 'Database Error during Excel fetch: ' . $e->getMessage()); - // Re-throw the exception so it is caught by the main function's catch block - throw $e; - } - - return $data; - } - - // Function to generate the Excel file - public function downloadStaffWiseProductPoliciesExcel() - { - try{ - $managerId = $this->request->getGet('manager_id'); - $brokerId = $this->request->getGet('broker_id'); - $month = $this->request->getGet('month'); - - // --- ADDED VALIDATION (Simplified logic for clarity) --- - if (empty($managerId) || empty($brokerId) || empty($month)) { - $ref = ['message' => 'Missing required parameters: manager_id, broker_id, and month must be provided.']; - // Status code remains 200, but JSON code is 400 as per your preference - return $this->response->setJSON([ - 'status' => 'error', - 'code' => 400, - 'data' => [], - 'message' => 'Missing required parameters: manager_id, broker_id, and month must be provided.', - 'ref' => $ref - ])->setStatusCode(200); - } - - $data = $this->getBrokerPoliciesData($managerId, $brokerId, $month); - // Define column headers - $header = ['Broker Name', 'Issue Date', 'Policy Number', 'Premium Amount']; - - // --- 1. MODIFIED LOGIC: Throw RuntimeException if no data --- - if (empty($data)) { - throw new \RuntimeException('No policies found for this broker for the specified month.', 404); - } - - $grandTotal = 0; - foreach ($data as $row) { $grandTotal += (float)$row[3]; } - - // Create and append the "Total" row - $totalRow = ['','','Total:',$grandTotal]; - $data[] = $totalRow; - - // Determine file name and date string - $monthName = ($month === 'current') ? date('Ym') : date('Ym', strtotime('-1 month')); - $brokerName = $data[0][0]; - - // 2. Prepare PhpSpreadsheet (assuming $spreadsheet, $writer, etc. are created here) - while (ob_get_level() > 0) { - ob_end_clean(); - } - - // Create Spreadsheet - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - - // Title - $sheet->mergeCells('A1:D1'); - $sheet->setCellValue('A1', "Broker Policies Details for $month"); - $sheet->getStyle('A1')->getAlignment()->setHorizontal('center'); - - // Headers - $sheet->fromArray($header, NULL, 'A2'); - - // Data - $sheet->fromArray($data, NULL, 'A3'); - - // File Name - $fileName = $brokerName . '_Policies_Details_' . $monthName . '.xlsx'; - - // HTTP Headers - header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); - header("Content-Disposition: attachment; filename=\"{$fileName}\""); - header("Cache-Control: max-age=0"); - - // Output File - $writer = new Xlsx($spreadsheet); - $writer->save('php://output'); - - return; // STOP CI4 rendering anything else - - } catch (\Throwable $e) { - - // ... (Your error handling remains the same) ... - $ref = []; - // Case 1: No Data Found (Soft Success JSON) - if ($e instanceof \RuntimeException && $e->getCode() === 404) { - $ref['message'] = 'No Data Found'; - return $this->respond([ - 'status' => 'success', - 'code' => 200, - 'data' => [], - 'message' => 'No Data Found', - 'ref' => $ref - ], 200); - } - - // Case 2: Database or Other Error (Error JSON) - $isDbError = $e instanceof \CodeIgniter\Database\Exceptions\DatabaseException - || $e instanceof \mysqli_sql_exception - || $e instanceof \PDOException; - - if ($isDbError) { - $ref['debug_info'] = $e->getFile() . " / LN : " . $e->getLine(); - $ref['message'] = 'Database Error Occurred.'; - $message = 'Database Error Occurred.'; - } else { - $ref['message'] = 'An unexpected error occurred: ' . $e->getMessage(); - $message = 'An unexpected error occurred: ' . $e->getMessage(); - } - - return $this->respond([ - 'status' => 'error', - 'code' => 500, - 'data' => [], - 'message'=> $message, - 'ref' => $ref - ], 200); - } - } - - /** - * Executes the detailed policy query and extracts the data for the spreadsheet. - * @param string $managerId - * @param int $brokerId - * @param string $month ('current' or 'previous') - * @return array - */ - private function getStaffWiseProductPoliciesData($managerId, $brokerId, $month): array - { - // --- Correction 1: Initialize Database Connection --- - $db = \Config\Database::connect(); - $data = []; - - try { - $builder = $db->table('partner_policy pp'); - // Note: I removed 'broker_id' from SELECT as it's redundant in the Excel sheet details - $builder->select('pb.name AS broker_name, DATE_FORMAT(pp.issued_date, "%d-%m-%Y") AS issued_date,pp.policy_number, pp.premium_amount'); - $builder->join('partner_enquiry pe', 'pe.id = pp.enquiry_id', 'left'); - $builder->join('partner_brokers pb', 'pb.id = pe.broker_id', 'left'); - - // --- Correction 2: Use Robust Date Range Filtering --- - if ($month === "current") { - // WHERE issued_date >= start_of_current_month AND issued_date < start_of_next_month - $builder->where("pp.issued_date >= DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); - $builder->where("pp.issued_date < DATE_FORMAT(DATE_ADD(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); - } - else if ($month === "previous") { - // WHERE issued_date >= start_of_previous_month AND issued_date < start_of_current_month - $builder->where("pp.issued_date >= DATE_FORMAT(DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); - $builder->where("pp.issued_date < DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); - } - - // Broker and Manager Filter - $builder->where('pp.manager_id', $managerId); - $builder->where('pb.id', $brokerId); - $builder->orderBy('pp.issued_date', 'DESC'); - - $results = $builder->get()->getResultArray(); - - // Restructure data for PhpSpreadsheet (2D array of values) - foreach ($results as $row) { - $data[] = array_values($row); - } - - } catch (DatabaseException $e) { - log_message('error', 'Database Error during Excel fetch: ' . $e->getMessage()); - // Re-throw the exception so it is caught by the main function's catch block - throw $e; - } - - return $data; - } - - // Function to generate the Excel file - public function downloadAgentMonthlyPoliciesExcel() - { - try{ - $managerId = $this->request->getGet('manager_id'); - $brokerId = $this->request->getGet('broker_id'); - $month = $this->request->getGet('month'); - - // --- ADDED VALIDATION (Simplified logic for clarity) --- - if (empty($managerId) || empty($brokerId) || empty($month)) { - $ref = ['message' => 'Missing required parameters: manager_id, broker_id, and month must be provided.']; - // Status code remains 200, but JSON code is 400 as per your preference - return $this->response->setJSON([ - 'status' => 'error', - 'code' => 400, - 'data' => [], - 'ref' => $ref - ])->setStatusCode(200); - } - - $data = $this->getAgentMonthlyPoliciesExcel($managerId, $brokerId, $month); - // Define column headers - $header = ['Partner Name','Partner Code' ,'Issue Date', 'Policy Number', 'Premium Amount']; - - - // --- 1. MODIFIED LOGIC: Throw RuntimeException if no data --- - if (empty($data)) { - throw new \RuntimeException('No policies found for this broker for the specified month.', 404); - } - - $grandTotal = 0; - foreach ($data as $row) { $grandTotal += (float)$row[3]; } - - // Create and append the "Total" row - $totalRow = ['','','Total:',$grandTotal]; - $data[] = $totalRow; - - // Determine file name and date string - $monthName = ($month === 'current') ? date('Ym') : date('Ym', strtotime('-1 month')); - $PartnerName = $data[0][0]; - - // 2. Prepare PhpSpreadsheet (assuming $spreadsheet, $writer, etc. are created here) - while (ob_get_level() > 0) { - ob_end_clean(); - } - - // Create Spreadsheet - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - - // Title - $sheet->mergeCells('A1:F1'); - $sheet->setCellValue('A1', "Partner Policies Details for $month"); - $sheet->getStyle('A1')->getAlignment()->setHorizontal('center'); - - // Headers - $sheet->fromArray($header, NULL, 'A2'); - - // Data - $sheet->fromArray($data, NULL, 'A3'); - - // File Name - $fileName = $PartnerName . '_Policies_Details_' . $monthName . '.xlsx'; - - // HTTP Headers - header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); - header("Content-Disposition: attachment; filename=\"{$fileName}\""); - header("Cache-Control: max-age=0"); - - // Output File - $writer = new Xlsx($spreadsheet); - $writer->save('php://output'); - - return; // STOP CI4 rendering anything else - - } catch (\Throwable $e) { - - // ... (Your error handling remains the same) ... - $ref = []; - // Case 1: No Data Found (Soft Success JSON) - if ($e instanceof \RuntimeException && $e->getCode() === 404) { - $ref['message'] = 'No Data Found'; - return $this->respond([ - 'status' => 'success', - 'code' => 200, - 'data' => [], - 'ref' => $ref - ], 200); - } - - // Case 2: Database or Other Error (Error JSON) - $isDbError = $e instanceof \CodeIgniter\Database\Exceptions\DatabaseException - || $e instanceof \mysqli_sql_exception - || $e instanceof \PDOException; - - if ($isDbError) { - $ref['debug_info'] = $e->getFile() . " / LN : " . $e->getLine(); - $ref['message'] = 'Database Error Occurred.'; - } else { - $ref['message'] = 'An unexpected error occurred: ' . $e->getMessage(); - } - - return $this->respond([ - 'status' => 'error', - 'code' => $e->getCode() ?: 500, - 'data' => [], - 'ref' => $ref - ], 200); - } - } - - /** - * Executes the detailed policy query and extracts the data for the spreadsheet. - * @param string $managerId - * @param int $AgentId - * @param string $month ('current' or 'previous') - * @return array - */ - private function getAgentMonthlyPoliciesExcel($managerId, $AgentId, $month): array - { - // --- Correction 1: Initialize Database Connection --- - $db = \Config\Database::connect(); - $data = []; - - try { - $builder = $db->table('partner_policy pp'); - // Note: I removed 'broker_id' from SELECT as it's redundant in the Excel sheet details - $builder->select('pa.name AS agent_name,pa.agent_code, DATE_FORMAT(pp.issued_date, "%d-%m-%Y") AS issued_date,pp.policy_number, pp.premium_amount'); - $builder->join('partner_agent pa', 'pp.agent_id = pa.id', 'inner'); - $builder->join('partner_enquiry pe', 'pe.id = pp.enquiry_id', 'left'); - - // --- Correction 2: Use Robust Date Range Filtering --- - if ($month === "current") { - // WHERE issued_date >= start_of_current_month AND issued_date < start_of_next_month - $builder->where("pp.issued_date >= DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); - $builder->where("pp.issued_date < DATE_FORMAT(DATE_ADD(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); - } - else if ($month === "previous") { - // WHERE issued_date >= start_of_previous_month AND issued_date < start_of_current_month - $builder->where("pp.issued_date >= DATE_FORMAT(DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); - $builder->where("pp.issued_date < DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); - } - - // Broker and Manager Filter - $builder->where('pp.manager_id', $managerId); - $builder->where('pp.agent_id', $AgentId); - $builder->orderBy('pp.issued_date', 'DESC'); - - $results = $builder->get()->getResultArray(); - - // Restructure data for PhpSpreadsheet (2D array of values) - foreach ($results as $row) { - $data[] = array_values($row); - } - - } catch (DatabaseException $e) { - log_message('error', 'Database Error during Excel fetch: ' . $e->getMessage()); - // Re-throw the exception so it is caught by the main function's catch block - throw $e; - } - - return $data; - } - - // Function to generate the Excel file - public function downloadAgentNoPolicyTimeRange() - { - try{ - $managerId = $this->request->getGet('manager_id'); - $brokerId = $this->request->getGet('broker_id'); - $month = $this->request->getGet('month'); - - // --- ADDED VALIDATION (Simplified logic for clarity) --- - if (empty($managerId) || empty($brokerId) || empty($month)) { - $ref = ['message' => 'Missing required parameters: manager_id, broker_id, and month must be provided.']; - // Status code remains 200, but JSON code is 400 as per your preference - return $this->response->setJSON([ - 'status' => 'error', - 'code' => 400, - 'data' => [], - 'ref' => $ref - ])->setStatusCode(200); - } - - $data = $this->getBrokerPoliciesData($managerId, $brokerId, $month); - // Define column headers - $header = ['Broker Name', 'Issue Date', 'Policy Number', 'Premium Amount']; - - // --- 1. MODIFIED LOGIC: Throw RuntimeException if no data --- - if (empty($data)) { - throw new \RuntimeException('No policies found for this broker for the specified month.', 404); - } - - $grandTotal = 0; - foreach ($data as $row) { $grandTotal += (float)$row[3]; } - - // Create and append the "Total" row - $totalRow = ['','','Total:',$grandTotal]; - $data[] = $totalRow; - - // Determine file name and date string - $monthName = ($month === 'current') ? date('Ym') : date('Ym', strtotime('-1 month')); - $brokerName = $data[0][0]; - - // 2. Prepare PhpSpreadsheet (assuming $spreadsheet, $writer, etc. are created here) - while (ob_get_level() > 0) { - ob_end_clean(); - } - - // Create Spreadsheet - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - - // Title - $sheet->mergeCells('A1:D1'); - $sheet->setCellValue('A1', "Broker Policies Details for $month"); - $sheet->getStyle('A1')->getAlignment()->setHorizontal('center'); - - // Headers - $sheet->fromArray($header, NULL, 'A2'); - - // Data - $sheet->fromArray($data, NULL, 'A3'); - - // File Name - $fileName = $brokerName . '_Policies_Details_' . $monthName . '.xlsx'; - - // HTTP Headers - header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); - header("Content-Disposition: attachment; filename=\"{$fileName}\""); - header("Cache-Control: max-age=0"); - - // Output File - $writer = new Xlsx($spreadsheet); - $writer->save('php://output'); - - return; // STOP CI4 rendering anything else - - } catch (\Throwable $e) { - - // ... (Your error handling remains the same) ... - $ref = []; - // Case 1: No Data Found (Soft Success JSON) - if ($e instanceof \RuntimeException && $e->getCode() === 404) { - $ref['message'] = 'No Data Found'; - return $this->respond([ - 'status' => 'success', - 'code' => 200, - 'data' => [], - 'ref' => $ref - ], 200); - } - - // Case 2: Database or Other Error (Error JSON) - $isDbError = $e instanceof \CodeIgniter\Database\Exceptions\DatabaseException - || $e instanceof \mysqli_sql_exception - || $e instanceof \PDOException; - - if ($isDbError) { - $ref['debug_info'] = $e->getFile() . " / LN : " . $e->getLine(); - $ref['message'] = 'Database Error Occurred.'; - } else { - $ref['message'] = 'An unexpected error occurred: ' . $e->getMessage(); - } - - return $this->respond([ - 'status' => 'error', - 'code' => $e->getCode() ?: 500, - 'data' => [], - 'ref' => $ref - ], 200); - } - } - - /** - * Executes the detailed policy query and extracts the data for the spreadsheet. - * @param string $managerId - * @param int $brokerId - * @param string $month ('current' or 'previous') - * @return array - */ - private function getAgentNoPolicyTimeRange($managerId, $brokerId, $month): array - { - // --- Correction 1: Initialize Database Connection --- - $db = \Config\Database::connect(); - $data = []; - - try { - $builder = $db->table('partner_policy pp'); - // Note: I removed 'broker_id' from SELECT as it's redundant in the Excel sheet details - $builder->select('pb.name AS broker_name, DATE_FORMAT(pp.issued_date, "%d-%m-%Y") AS issued_date,pp.policy_number, pp.premium_amount'); - $builder->join('partner_enquiry pe', 'pe.id = pp.enquiry_id', 'left'); - $builder->join('partner_brokers pb', 'pb.id = pe.broker_id', 'left'); - - // --- Correction 2: Use Robust Date Range Filtering --- - if ($month === "current") { - // WHERE issued_date >= start_of_current_month AND issued_date < start_of_next_month - $builder->where("pp.issued_date >= DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); - $builder->where("pp.issued_date < DATE_FORMAT(DATE_ADD(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); - } - else if ($month === "previous") { - // WHERE issued_date >= start_of_previous_month AND issued_date < start_of_current_month - $builder->where("pp.issued_date >= DATE_FORMAT(DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); - $builder->where("pp.issued_date < DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); - } - - // Broker and Manager Filter - $builder->where('pp.manager_id', $managerId); - $builder->where('pb.id', $brokerId); - $builder->orderBy('pp.issued_date', 'DESC'); - - $results = $builder->get()->getResultArray(); - - // Restructure data for PhpSpreadsheet (2D array of values) - foreach ($results as $row) { - $data[] = array_values($row); - } - - } catch (DatabaseException $e) { - log_message('error', 'Database Error during Excel fetch: ' . $e->getMessage()); - // Re-throw the exception so it is caught by the main function's catch block - throw $e; - } - - return $data; - } - - // Function to generate the Excel file - public function downloadBrokerPoliciesExcel_agentBelow50tPremiumTimeRange() - { - try{ - $managerId = $this->request->getGet('manager_id'); - $brokerId = $this->request->getGet('broker_id'); - $month = $this->request->getGet('month'); - - // --- ADDED VALIDATION (Simplified logic for clarity) --- - if (empty($managerId) || empty($brokerId) || empty($month)) { - $ref = ['message' => 'Missing required parameters: manager_id, broker_id, and month must be provided.']; - // Status code remains 200, but JSON code is 400 as per your preference - return $this->response->setJSON([ - 'status' => 'error', - 'code' => 400, - 'data' => [], - 'ref' => $ref - ])->setStatusCode(200); - } - - $data = $this->getBrokerPoliciesData($managerId, $brokerId, $month); - // Define column headers - $header = ['Broker Name', 'Issue Date', 'Policy Number', 'Premium Amount']; - - $grandTotal = 0; - foreach ($data as $row) { $grandTotal += (float)$row[3]; } - - // Create and append the "Total" row - $totalRow = ['','','Total:',$grandTotal]; - $data[] = $totalRow; - - // --- 1. MODIFIED LOGIC: Throw RuntimeException if no data --- - if (empty($data)) { - throw new \RuntimeException('No policies found for this broker for the specified month.', 404); - } - - // Determine file name and date string - $monthName = ($month === 'current') ? date('Ym') : date('Ym', strtotime('-1 month')); - $brokerName = $data[0][0]; - - // 2. Prepare PhpSpreadsheet (assuming $spreadsheet, $writer, etc. are created here) - while (ob_get_level() > 0) { - ob_end_clean(); - } - - // Create Spreadsheet - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - - // Title - $sheet->mergeCells('A1:D1'); - $sheet->setCellValue('A1', "Broker Policies Details for $month"); - $sheet->getStyle('A1')->getAlignment()->setHorizontal('center'); - - // Headers - $sheet->fromArray($header, NULL, 'A2'); - - // Data - $sheet->fromArray($data, NULL, 'A3'); - - // File Name - $fileName = $brokerName . '_Policies_Details_' . $monthName . '.xlsx'; - - // HTTP Headers - header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); - header("Content-Disposition: attachment; filename=\"{$fileName}\""); - header("Cache-Control: max-age=0"); - - // Output File - $writer = new Xlsx($spreadsheet); - $writer->save('php://output'); - - return; // STOP CI4 rendering anything else - - } catch (\Throwable $e) { - - // ... (Your error handling remains the same) ... - $ref = []; - // Case 1: No Data Found (Soft Success JSON) - if ($e instanceof \RuntimeException && $e->getCode() === 404) { - $ref['message'] = 'No Data Found'; - return $this->respond([ - 'status' => 'success', - 'code' => 200, - 'data' => [], - 'ref' => $ref - ], 200); - } - - // Case 2: Database or Other Error (Error JSON) - $isDbError = $e instanceof \CodeIgniter\Database\Exceptions\DatabaseException - || $e instanceof \mysqli_sql_exception - || $e instanceof \PDOException; - - if ($isDbError) { - $ref['debug_info'] = $e->getFile() . " / LN : " . $e->getLine(); - $ref['message'] = 'Database Error Occurred.'; - } else { - $ref['message'] = 'An unexpected error occurred: ' . $e->getMessage(); - } - - return $this->respond([ - 'status' => 'error', - 'code' => $e->getCode() ?: 500, - 'data' => [], - 'ref' => $ref - ], 200); - } - } - - /** - * Executes the detailed policy query and extracts the data for the spreadsheet. - * @param string $managerId - * @param int $brokerId - * @param string $month ('current' or 'previous') - * @return array - */ - private function getBrokerPoliciesData_agentBelow50tPremiumTimeRange($managerId, $brokerId, $month): array - { - // --- Correction 1: Initialize Database Connection --- - $db = \Config\Database::connect(); - $data = []; - - try { - $builder = $db->table('partner_policy pp'); - // Note: I removed 'broker_id' from SELECT as it's redundant in the Excel sheet details - $builder->select('pb.name AS broker_name, DATE_FORMAT(pp.issued_date, "%d-%m-%Y") AS issued_date,pp.policy_number, pp.premium_amount'); - $builder->join('partner_enquiry pe', 'pe.id = pp.enquiry_id', 'left'); - $builder->join('partner_brokers pb', 'pb.id = pe.broker_id', 'left'); - - // --- Correction 2: Use Robust Date Range Filtering --- - if ($month === "current") { - // WHERE issued_date >= start_of_current_month AND issued_date < start_of_next_month - $builder->where("pp.issued_date >= DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); - $builder->where("pp.issued_date < DATE_FORMAT(DATE_ADD(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); - } - else if ($month === "previous") { - // WHERE issued_date >= start_of_previous_month AND issued_date < start_of_current_month - $builder->where("pp.issued_date >= DATE_FORMAT(DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); - $builder->where("pp.issued_date < DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); - } - - // Broker and Manager Filter - $builder->where('pp.manager_id', $managerId); - $builder->where('pb.id', $brokerId); - $builder->orderBy('pp.issued_date', 'DESC'); - - $results = $builder->get()->getResultArray(); - - // Restructure data for PhpSpreadsheet (2D array of values) - foreach ($results as $row) { - $data[] = array_values($row); - } - - } catch (DatabaseException $e) { - log_message('error', 'Database Error during Excel fetch: ' . $e->getMessage()); - // Re-throw the exception so it is caught by the main function's catch block - throw $e; - } - - return $data; - } - } diff --git a/app/Controllers/ExcelExportController.php b/app/Controllers/ExcelExportController.php new file mode 100644 index 0000000..b46f615 --- /dev/null +++ b/app/Controllers/ExcelExportController.php @@ -0,0 +1,470 @@ +db = \Config\Database::connect(); + } + + + /** + * Centralized function to create the spreadsheet, apply styling, + * set headers, and stream the file output. + * + * @param array $header Column headers (1D array) + * @param array $data Policy data including the total row (2D array) + * @param string $title Spreadsheet title + * @param string $fileName Output file name + * @param string $totalLabelCol Column letter for the 'TOTAL:' label (e.g., 'C' or 'E') + * @param string $totalValueCol Column letter for the total value (e.g., 'D' or 'F') + * @return void + */ + private function streamExcelFile( + array $header, + array $data, + string $title, + string $fileName, + string $totalLabelCol, + string $totalValueCol + ): void + { + // Ensure no output buffering is active before streaming the file + while (ob_get_level() > 0) { + ob_end_clean(); + } + + // Create Spreadsheet + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + + // 1. Title (Merged across the header columns) + $lastCol = $sheet->getHighestColumn(); + $sheet->mergeCells("A1:{$lastCol}1"); + $sheet->setCellValue('A1', $title); + $sheet->getStyle('A1')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER); + + // 2. Headers (Row 2) + $sheet->fromArray($header, NULL, 'A2'); + + // 3. Data (Starting from Row 3) + // Note: The total row MUST be included in the $data array passed to this function. + $sheet->fromArray($data, NULL, 'A3'); + + // 4. Total Row Styling + // Total row number is the count of rows in the $data array (which includes the header, plus 2 for title/headers) + $totalRowNumber = count($data) + 2; + + // Apply bold formatting to the label and the sum + $sheet->getStyle($totalLabelCol . $totalRowNumber . ':' . $totalValueCol . $totalRowNumber)->getFont()->setBold(true); + + // Align the label to the right + $sheet->getStyle($totalLabelCol . $totalRowNumber)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_RIGHT); + + // Auto-size columns for better presentation + for ($col = 'A'; $col <= $lastCol; $col++) { + $sheet->getColumnDimension($col)->setAutoSize(true); + } + + // 5. HTTP Headers + header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + header("Content-Disposition: attachment; filename=\"{$fileName}\""); + header("Cache-Control: max-age=0"); + + // 6. Output File + $writer = new Xlsx($spreadsheet); + $writer->save('php://output'); + + return; + } + + + /** + * Executes the detailed policy query and extracts the data for the spreadsheet. + * @param string $managerId + * @param int $brokerId + * @param string $month ('current' or 'previous') + * @return array + */ + private function getBrokerPoliciesData($managerId, $brokerId, $month): array + { + // --- Correction 1: Initialize Database Connection --- + + $data = []; + + try { + $builder = $this->db->table('partner_policy pp'); + // Note: I removed 'broker_id' from SELECT as it's redundant in the Excel sheet details + $builder->select('pb.name AS broker_name, DATE_FORMAT(pp.issued_date, "%d-%m-%Y") AS issued_date,pp.policy_number, pp.premium_amount'); + $builder->join('partner_enquiry pe', 'pe.id = pp.enquiry_id', 'left'); + $builder->join('partner_brokers pb', 'pb.id = pe.broker_id', 'left'); + + // --- Correction 2: Use Robust Date Range Filtering --- + if ($month === "current") { + // WHERE issued_date >= start_of_current_month AND issued_date < start_of_next_month + $builder->where("pp.issued_date >= DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); + $builder->where("pp.issued_date < DATE_FORMAT(DATE_ADD(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); + } + else if ($month === "previous") { + // WHERE issued_date >= start_of_previous_month AND issued_date < start_of_current_month + $builder->where("pp.issued_date >= DATE_FORMAT(DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); + $builder->where("pp.issued_date < DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); + } + + // Broker and Manager Filter + $builder->where('pp.manager_id', $managerId); + $builder->where('pb.id', $brokerId); + $builder->orderBy('pp.issued_date', 'DESC'); + + $results = $builder->get()->getResultArray(); + + // Restructure data for PhpSpreadsheet (2D array of values) + foreach ($results as $row) { + $data[] = array_values($row); + } + + } catch (DatabaseException $e) { + log_message('error', 'Database Error during Excel fetch: ' . $e->getMessage()); + // Re-throw the exception so it is caught by the main function's catch block + throw $e; + } + + return $data; + } + + + + /** + * Executes the detailed policy query and extracts the data for the spreadsheet. + * @param string $managerId + * @param string $vehicleType + * @param string $month ('current' or 'previous') + * @return array + */ + private function getProductPoliciesData($managerId, $vehicleType, $month): array + { + // --- Correction 1: Initialize Database Connection --- + + $data = []; + + try { + $builder = $this->db->table('partner_policy pp'); + // Note: I removed 'broker_id' from SELECT as it's redundant in the Excel sheet details + $builder->select('pp.vehicle_type, DATE_FORMAT(pp.issued_date, "%d-%m-%Y") AS issued_date,pp.policy_number, pp.premium_amount'); + + + // --- Correction 2: Use Robust Date Range Filtering --- + if ($month === "current") { + // WHERE issued_date >= start_of_current_month AND issued_date < start_of_next_month + $builder->where("pp.issued_date >= DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); + $builder->where("pp.issued_date < DATE_FORMAT(DATE_ADD(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); + } + else if ($month === "previous") { + // WHERE issued_date >= start_of_previous_month AND issued_date < start_of_current_month + $builder->where("pp.issued_date >= DATE_FORMAT(DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); + $builder->where("pp.issued_date < DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); + } + + // Broker and Manager Filter + $builder->where('pp.manager_id', $managerId); + $builder->where('pp.vehicle_type', $vehicleType); + + + $results = $builder->get()->getResultArray(); + + // Restructure data for PhpSpreadsheet (2D array of values) + foreach ($results as $row) { + $data[] = array_values($row); + } + + } catch (DatabaseException $e) { + log_message('error', 'Database Error during Excel fetch: ' . $e->getMessage()); + // Re-throw the exception so it is caught by the main function's catch block + throw $e; + } + + return $data; + } + + + /** + * Executes the detailed policy query and extracts the data for the spreadsheet. + * @param string $managerId + * @param int $insurerId + * @param string $month ('current' or 'previous') + * @return array + */ + private function getInsurerPoliciesData($managerId, $insurerId, $month): array + { + // --- Correction 1: Initialize Database Connection --- + + $data = []; + + try { + $builder = $this->db->table('partner_policy pp'); + // Note: I removed 'broker_id' from SELECT as it's redundant in the Excel sheet details + $builder->select('i.name AS insurer_name,i.short_name,pp.insured_name, DATE_FORMAT(pp.issued_date, "%d-%m-%Y") AS issued_date,pp.policy_number, pp.premium_amount'); + + $builder->join('partner_quotation pq', 'pq.id = pp.quotation_id', 'left'); + $builder->join('insurers i', 'i.id = pq.insurer_id', 'left'); + + + // --- Correction 2: Use Robust Date Range Filtering --- + if ($month === "current") { + // WHERE issued_date >= start_of_current_month AND issued_date < start_of_next_month + $builder->where("pp.issued_date >= DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); + $builder->where("pp.issued_date < DATE_FORMAT(DATE_ADD(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); + } + else if ($month === "previous") { + // WHERE issued_date >= start_of_previous_month AND issued_date < start_of_current_month + $builder->where("pp.issued_date >= DATE_FORMAT(DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); + $builder->where("pp.issued_date < DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); + } + + // Broker and Manager Filter + $builder->where('pp.manager_id', $managerId); + $builder->where('i.id', $insurerId); + $builder->where('i.is_active',1); + $builder->orderBy('pp.issued_date', 'DESC'); + + $results = $builder->get()->getResultArray(); + + // Restructure data for PhpSpreadsheet (2D array of values) + foreach ($results as $row) { + $data[] = array_values($row); + } + + } catch (DatabaseException $e) { + log_message('error', 'Database Error during Excel fetch: ' . $e->getMessage()); + // Re-throw the exception so it is caught by the main function's catch block + throw $e; + } + + return $data; + } + + + + /** + * Executes the detailed policy query and extracts the data for the spreadsheet. + * @param string $managerId + * @param int $brokerId + * @param string $month ('current' or 'previous') + * @return array + */ + private function getStaffAndProductPoliciesExcel($managerId, $executiveId,$vehicleType, $month): array + { + // --- Correction 1: Initialize Database Connection --- + + $data = []; + + try { + $builder = $this->db->table('partner_policy pp'); + + $builder->select('pse.name as sales_executive_name, pp.vehicle_type AS vechile_type,pp.policy_number,DATE_FORMAT(pp.issued_date, "%d-%m-%Y") AS issued_date,pp.premium_amount'); + $builder->join('partner_agent pa', 'pa.id = pp.agent_id', 'left'); + $builder->join('partner_sales_executive pse', 'pse.id = pa.sales_executive_id', 'left'); + + // --- Correction 2: Use Robust Date Range Filtering --- + if ($month === "current") { + // WHERE issued_date >= start_of_current_month AND issued_date < start_of_next_month + $builder->where("pp.issued_date >= DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); + $builder->where("pp.issued_date < DATE_FORMAT(DATE_ADD(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); + } + else if ($month === "previous") { + // WHERE issued_date >= start_of_previous_month AND issued_date < start_of_current_month + $builder->where("pp.issued_date >= DATE_FORMAT(DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); + $builder->where("pp.issued_date < DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); + } + + // Broker and Manager Filter + $builder->where('pp.manager_id', $managerId); + $builder->where('pa.sales_executive_id', $executiveId); + $builder->where('pa.sales_executive_id IS NOT NULL'); + $builder->where('pse.is_active', 1); + $builder->where('pp.vehicle_type', $vehicleType); + $builder->orderBy('pp.issued_date', 'DESC'); + $results = $builder->get()->getResultArray(); + + // Restructure data for PhpSpreadsheet (2D array of values) + foreach ($results as $row) { + $data[] = array_values($row); + } + + } catch (DatabaseException $e) { + log_message('error', 'Database Error during Excel fetch: ' . $e->getMessage()); + // Re-throw the exception so it is caught by the main function's catch block + throw $e; + } + + return $data; + } + + + + /** + * Executes the detailed policy query and extracts the data for the spreadsheet. + * @param string $managerId + * @param int $AgentId + * @param string $month ('current' or 'previous') + * @return array + */ + private function getAgentMonthlyPoliciesExcel($managerId, $AgentId, $month): array + { + // --- Correction 1: Initialize Database Connection --- + + $data = []; + + try { + $builder = $this->db->table('partner_policy pp'); + // Note: I removed 'broker_id' from SELECT as it's redundant in the Excel sheet details + $builder->select('pa.name AS agent_name,pa.agent_code,pp.policy_number,DATE_FORMAT(pp.issued_date, "%d-%m-%Y") AS issued_date,pp.premium_amount'); + + $builder->join('partner_agent pa', 'pp.agent_id = pa.id', 'inner'); + $builder->join('partner_enquiry pe', 'pe.id = pp.enquiry_id', 'left'); + + $builder->where('pp.manager_id', $managerId); + $builder->where('pa.id', $AgentId); + $builder->where('pp.policy_number IS NOT NULL'); + + // --- Correction 2: Use Robust Date Range Filtering --- + if ($month === "current") { + // WHERE issued_date >= start_of_current_month AND issued_date < start_of_next_month + $builder->where("pp.issued_date >= DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); + $builder->where("pp.issued_date < DATE_FORMAT(DATE_ADD(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); + } + else if ($month === "previous") { + // WHERE issued_date >= start_of_previous_month AND issued_date < start_of_current_month + $builder->where("pp.issued_date >= DATE_FORMAT(DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH), '%Y-%m-01')", NULL, FALSE); + $builder->where("pp.issued_date < DATE_FORMAT(CURRENT_DATE(), '%Y-%m-01')", NULL, FALSE); + } + + $builder->orderBy('pp.issued_date', 'DESC'); + + $results = $builder->get()->getResultArray(); + + // Restructure data for PhpSpreadsheet (2D array of values) + foreach ($results as $row) { + $data[] = array_values($row); + } + + } catch (DatabaseException $e) { + log_message('error', 'Database Error during Excel fetch: ' . $e->getMessage()); + // Re-throw the exception so it is caught by the main function's catch block + throw $e; + } + + return $data; + } + + + /** + * Executes the detailed policy query and extracts the data for the spreadsheet. + * @param string $managerId + * @param int $brokerId + * @param string $month ('current' or 'previous') + * @return array + */ + private function getAgentsWithoutPoliciesData($managerId): array + { + + // --- Correction 1: Initialize Database Connection --- + + $data = []; + + try { + $builder = $this->db->table('partner_agent pa'); + // Note: I removed 'broker_id' from SELECT as it's redundant in the Excel sheet details + $builder->select("pa.name AS agent_name,pa.agent_code,pa.email,pa.mobile"); + + $builder->join( + 'partner_policy pp', + "pa.id = pp.agent_id AND pp.issued_date >= DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL 10 DAY)", + 'left' + ); + + // Broker and Manager Filter + $builder->where('pp.manager_id', $managerId); + $builder->where('pp.id', null); // No policy in last 10 days + $builder->orderBy('pa.name', 'ASC'); + // echo $builder->getCompiledSelect(); die; + $results = $builder->get()->getResultArray(); + + + // Restructure data for PhpSpreadsheet (2D array of values) + foreach ($results as $row) { + $data[] = array_values($row); + } + + } catch (DatabaseException $e) { + log_message('error', 'Database Error during Excel fetch: ' . $e->getMessage()); + // Re-throw the exception so it is caught by the main function's catch block + throw $e; + } + + return $data; + } + + + + /** + * Executes the detailed policy query and extracts the data for the spreadsheet. + * @param string $managerId + * @param int $brokerId + * @param string $month ('current' or 'previous') + * @return array + */ + private function getLowPremiumAgentData($managerId): array + { + // --- Correction 1: Initialize Database Connection --- + + $data = []; + + try { + $builder = $this->db->table('partner_policy pp'); + + $builder->select(" + pa.name AS agent_name, + pa.agent_code, + CASE + WHEN pa.is_active = 1 THEN 'Active Agent' + ELSE 'Inactive Agent' + END AS agent_status, + pp.policy_number, + DATE_FORMAT(pp.issued_date, '%d-%m-%Y') AS issued_date, + pp.premium_amount + "); + + $builder->join('partner_agent pa', 'pa.id = pp.agent_id', 'inner'); + // WHERE conditions + $builder->where('pp.manager_id', $managerId); + $builder->where('pa.id', $agentId); + $builder->where('pp.premium_amount <', 50000); + $builder->orderBy('pp.issued_date', 'DESC'); + + $results = $builder->get()->getResultArray(); + + // Restructure data for PhpSpreadsheet (2D array of values) + foreach ($results as $row) { + $data[] = array_values($row); + } + + } catch (DatabaseException $e) { + log_message('error', 'Database Error during Excel fetch: ' . $e->getMessage()); + // Re-throw the exception so it is caught by the main function's catch block + throw $e; + } + + return $data; + } + +}