FIX_Staff level pending export excel

This commit is contained in:
sanjeev.p 2025-12-26 15:04:43 +05:30
parent 2899e39c8a
commit a9d7d353bf
4 changed files with 1310 additions and 498 deletions

View File

@ -49,6 +49,10 @@ $routes->group('api', ['filter' => 'appSignature'], function ($routes) {
$routes->post('master/updatePaymentMode/(:num)', 'MasterController::updatePaymentMode/$1');
$routes->post('master/updatePaymentModeStatus/(:num)', 'MasterController::updatePaymentModeStatus/$1');
$routes->get('master/getAllPOS', 'MasterController::getAllPOS');
$routes->get('master/getAllEndorsement', 'MasterController::getAllEndorsement');
$routes->post('master/createEndorsement', 'MasterController::createEndorsement');
$routes->post('master/updateEndorsement/(:num)', 'MasterController::updateEndorsement/$1');
$routes->post('master/updateEndorsementStatus/(:num)', 'MasterController::updateEndorsementStatus/$1');
@ -136,24 +140,29 @@ $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");
//DASHBOARD Season 3 EXPORT EXCEL
//DASHBOARD Season 1 EXPORT EXCEL (ManagerDashboard - staffLevelPendingSummaryData)
$routes->get("dashboard/downloadStaffPendingSummaryExcel", "ExcelExportController::downloadStaffPendingSummaryExcel");
$routes->get("dashboard/downloadStaffPendingSummaryExcelByID", "ExcelExportController::downloadStaffPendingSummaryExcelByID");
//DASHBOARD Season 2 EXPORT EXCEL (businessDashboard)
$routes->get("dashboard/downloadBrokerPoliciesExcel", "ExcelExportController::downloadBrokerPoliciesExcel");
$routes->get("dashboard/downloadInsurerPoliciesExcel", "ExcelExportController::downloadInsurerPoliciesExcel");
$routes->get("dashboard/downloadProductPoliciesExcel", "ExcelExportController::downloadProductPoliciesExcel");
//DASHBOARD Season 4 EXPORT EXCEL
//DASHBOARD Season 3 EXPORT EXCEL (partnerDashboard)
$routes->get("dashboard/downloadT50AgentPoliciesExcel", "ExcelExportController::downloadT50AgentPoliciesExcel"); // whole agent but top 50
$routes->get("dashboard/downloadAgentMonthlyPoliciesExcel", "ExcelExportController::downloadAgentMonthlyPoliciesExcel"); // particular Agent
$routes->get("dashboard/downloadLowPremiumAgentExcel", "ExcelExportController::downloadLowPremiumAgentExcel");
$routes->get("dashboard/downloadAgentsWithoutPoliciesExcel", "ExcelExportController::downloadAgentsWithoutPoliciesExcel");
//DASHBOARD Season 4 EXPORT EXCEL AS ZIP (partnerDashboard - 3Excel in Zip Folder)
$routes->get("dashboard/downloadExcelAsZIP", "ExcelExportController::downloadExcelAsZIP");
//DASHBOARD Season 5 EXPORT EXCEL
//DASHBOARD Season 5 EXPORT EXCEL (productivityDashboard)
$routes->get("dashboard/downloadStaffAndProductPoliciesExcel", "ExcelExportController::downloadStaffAndProductPoliciesExcel");
@ -205,7 +214,6 @@ $routes->get("processjob", "JobWorker::processJob");
$routes->get('testPolicy', 'QuotationController::testPolicy');
@ -219,4 +227,3 @@ $routes->get("processjob", "JobWorker::processJob");

View File

@ -78,6 +78,7 @@ class ExcelExportController extends ResourceController
$sheet->getStyle($lastCol . $totalRowNumber)->getNumberFormat()->setFormatCode('#,##0.00');
}
// 5. Auto-size
for ($i = 1; $i <= $columnCount; $i++) {
$col = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($i);
@ -783,7 +784,7 @@ class ExcelExportController extends ResourceController
$serialNo = 1; // Start counter at 1
// 2. Loop through and prepend the serial number
foreach ($rawData as $row) {
foreach ($data as $row) {
// We create a new array for each row
$finalData[] = [
$serialNo++,
@ -1033,7 +1034,8 @@ class ExcelExportController extends ResourceController
return $this->response->download($zipFileName, $zipData);
}
// GENERATE ZIP
private function generateExcelBinary(array $header, array $data, string $title, bool $showTotal = true): string
{
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
@ -1086,6 +1088,227 @@ class ExcelExportController extends ResourceController
return $excelBinary;
}
public function downloadStaffPendingSummaryExcel()
{
try{
$managerId = $this->request->getGet('manager_id');
// --- ADDED VALIDATION (Simplified logic for clarity) ---
if (empty($managerId)) {
$msg = "Missing: manager_id";
$ref = ['debug_msg' => $msg];
return $this->response->setJSON(['status' => 'error', 'code' => 400, 'data' => [], 'message' => 'Missing required parameters', 'ref' => $ref])->setStatusCode(200);
}
$data = $this->getStaffPendingSummaryExcel($managerId);
if (empty($data)) {
throw new \RuntimeException('No summary found.', 404);
}
// Define column headers
$header = ['S.No', 'Staff Name', 'Today Assigned', 'Pending', 'In Progress', 'Completed', 'Previous Pending'];
// Initialize totals
$sums = array_fill(2, 5, 0); // Start from index 2, cover 5 columns
$finalData = [];
$serialNo = 1;
// Process data and calculate sums
foreach ($data as $row) {
// Convert row to indexed array values to ensure merge works correctly
$rowData = array_values($row);
// Add Serial Number
$finalData[] = array_merge([$serialNo++], $rowData);
// Summing columns index 2 to 6
for ($i = 2; $i <= 6; $i++) {
// Use index $i-1 because $row doesn't have S.No yet, but $rowData does
$sums[$i] += (int)($rowData[$i - 1] ?? 0);
}
}
// Create the Total Row
$totalRow = array_fill(0, count($header), ''); // Create empty row
$totalRow[1] = 'Total:'; // Label under "Staff Name"
foreach ($sums as $index => $sumValue) {
// This ensures that even if the sum is 0, it puts the digit '0' in the cell
$totalRow[$index] = $sumValue;
}
// Fill sums into the total row
foreach ($sums as $index => $sumValue) {
$totalRow[$index] = $sumValue;
}
// Add to final data
$finalData[] = $totalRow;
$fileName = 'Staff_Level_Pending_Summary.xlsx';
// --- CALL CENTRALIZED FUNCTION ---
$this->streamExcelFile(
$header,
$finalData,
"Staff Level Pending Summary",
$fileName,
true
);
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);
}
}
public function downloadStaffPendingSummaryExcelByID()
{
// try{
$managerId = $this->request->getGet('manager_id');
$staffId = $this->request->getGet('staff_id');
$status = $this->request->getGet('status');
// --- ADDED VALIDATION (Simplified logic for clarity) ---
if (empty($managerId) || empty($staffId) || empty($status)) {
$msg = "Missing: ";
$msg .= empty($managerId) ? "manager_id " : "";
$msg .= empty($staffId) ? "staff_id " : "";
$msg .= empty($status) ? "status " : "";
$ref = ['debug_msg' => $msg];
// $ref = ['debug_msg' => 'Missing required parameters: manager_id, broker_id, and month must be provided.'];
return $this->response->setJSON(['status' => 'error','code' => 400,'data' => [],'message' => 'Missing required parameters','ref' => $ref])->setStatusCode(200);
}
$data = $this->getStaffPendingSummaryExcelByID($managerId,$staffId,$status);
if (empty($data)) {
throw new \RuntimeException('No summary found.', 404);
}
// Define column headers
$header = ['S.No', 'Staff Name', 'REG Number','Received Date'];
// Initialize totals
// Initialize totals
$lastIndex = count(reset($data)) - 1;
// usort($data, function($a, $b) use ($lastIndex) {
// return (float)$a[$lastIndex] <=> (float)$b[$lastIndex];
// });
usort($data, function($a, $b) use ($lastIndex) {
return (float)$b[$lastIndex] <=> (float)$a[$lastIndex];
});
$finalData = [];
$serialNo = 1;
foreach ($data as $row) {
$finalData[] = array_merge([$serialNo++], $row);
}
$staffName = $finalData[0][1] ?? 'Staff';
$fileName = $staffName.'_'.$status.'_Summary.xlsx';
// Calculate and append total
$cleanStaffName = str_replace(' ', '_', strtolower($staffName));
$cleanStatus = ucwords(str_replace('_', ' ', strtolower($status)));
$fileName = $cleanStaffName . '_' . $cleanStatus . '_Summary.xlsx';
// --- CALL CENTRALIZED FUNCTION ---
$this->streamExcelFile(
$header,
$finalData,
$cleanStaffName ." ". $cleanStatus." Summary",
$fileName,
false
);
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);
// }
}
/**
@ -1602,4 +1825,119 @@ class ExcelExportController extends ResourceController
return $data;
}
private function getStaffPendingSummaryExcel($managerId): array
{
$data = [];
try {
$results = $this->db->table('partner_enquiry pe')
->select("
ps.name AS staff_name,
COUNT(pe.id) AS total_assigned,
SUM(CASE WHEN DATE(pe.created_on) = CURDATE() THEN 1 ELSE 0 END) AS today_assigned,
SUM(CASE WHEN pe.enquiry_status = 'Assigned' AND DATE(pe.created_on) = CURDATE() THEN 1 ELSE 0 END) AS today_pending,
SUM(CASE WHEN pe.enquiry_status = 'In progress' AND DATE(pe.created_on) = CURDATE() THEN 1 ELSE 0 END) AS today_in_progress,
SUM(CASE WHEN pe.enquiry_status = 'Completed' AND DATE(pe.created_on) = CURDATE() THEN 1 ELSE 0 END) AS today_completed,
SUM(CASE WHEN pe.enquiry_status != 'Completed' THEN 1 ELSE 0 END) AS previous_total_pending,
")
->join('partner_staff ps', 'ps.id = pe.assigned_to', 'left')
->where('pe.manager_id', $managerId)
->where('pe.is_active', 1)
->where('pe.assigned_to IS NOT NULL')
->where('pe.assigned_to !=', 0)
->groupBy('pe.assigned_to')
->orderBy('ps.name', 'ASC')
->get()
->getResultArray();
// Restructure data for PhpSpreadsheet (2D array of values)
foreach ($results as $row) {
unset($row['total_assigned']);
$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;
}
private function getStaffPendingSummaryExcelByID($managerId, $staffId, $status): array
{
try {
$builder = $this->db->table('partner_enquiry pe');
// Note: Change 'received_date' back to 'created_on' or update the loop below
$builder->select("
ps.name AS staff_name,
CONCAT('\t', pe.reg_no) AS reg_no,
DATE_FORMAT(pe.created_on, '%d-%m-%Y %h:%i %p') AS created_on
", false);
$builder->join('partner_staff ps', 'ps.id = pe.assigned_to', 'left');
$builder->where('pe.manager_id', $managerId);
$builder->where('pe.assigned_to', $staffId);
$builder->where('pe.is_active', 1);
// Date boundaries
$todayStart = date('Y-m-d 00:00:00');
$todayEnd = date('Y-m-d 23:59:59');
switch ($status) {
case 'today_assigned':
$builder->where('pe.created_on >=', $todayStart);
$builder->where('pe.created_on <=', $todayEnd);
break;
case 'today_pending':
$builder->where('pe.enquiry_status', 'Assigned');
$builder->where('pe.created_on >=', $todayStart);
$builder->where('pe.created_on <=', $todayEnd);
break;
case 'today_in_progress':
$builder->where('pe.enquiry_status', 'In progress');
$builder->where('pe.created_on >=', $todayStart);
$builder->where('pe.created_on <=', $todayEnd);
break;
case 'today_completed':
$builder->where('pe.enquiry_status', 'Completed');
$builder->where('pe.created_on >=', $todayStart);
$builder->where('pe.created_on <=', $todayEnd);
break;
case 'previous_total_pending':
// "Previous Pending" usually means anything NOT completed from BEFORE today
$builder->where('pe.enquiry_status !=', 'Completed');
$builder->where('pe.created_on <', $todayStart);
break;
}
$results = $builder->get()->getResultArray();
$data = [];
foreach ($results as $row) {
$data[] = [
$row['staff_name'] ?? 'N/A',
$row['reg_no'] ?? '-',
$row['created_on'] ?? '-' // Matches the alias in select
];
}
return $data;
} catch (\Exception $e) {
log_message('error', 'Excel Fetch Error: ' . $e->getMessage());
throw $e;
}
}
}

View File

@ -368,6 +368,118 @@ class MasterController extends ResourceController
//---------------------------------------------------------------------------------------
//Endorsement CRUD Copied As Per Broker CRUD line No 136 ---------------------------------
public function getAllEndorsement()
{
$data = $this->EndorsementTypeModel->where('is_active', 1)->findAll();
return $this->respond(['status' => 200,'message' => 'success','data' => $data]);
}
public function createEndorsement()
{
$input = $this->request->getJSON(true);
if (empty($input['endorsement_type'])) {
return $this->respond([
'status' => 404,
'message' => 'Endorsement type is required'
]);
}
// Duplicate check (Case-insensitive) on endorsement_type
$exists = $this->EndorsementTypeModel
->where('LOWER(endorsement_type)', strtolower($input['endorsement_type']))
->where('is_active', 1)
->first();
if ($exists) {
return $this->respond([
'status' => 404,
'message' => 'Endorsement type already exists'
]);
}
$data = [
'endorsement_type' => $input['endorsement_type'],
'is_active' => 1,
];
$this->EndorsementTypeModel->insert($data);
return $this->respond([
'status' => 200,
'message' => 'Endorsement type created successfully'
]);
}
public function updateEndorsement($id)
{
$input = $this->request->getJSON(true);
if (!$this->EndorsementTypeModel->find($id)) {
return $this->respond([
'status' => 404,
'message' => 'Record not found'
]);
}
// Duplicate check excluding current ID
$checkDuplicate = $this->EndorsementTypeModel
->where('LOWER(endorsement_type)', strtolower($input['endorsement_type']))
->where('id !=', $id)
->where('is_active', 1)
->first();
if ($checkDuplicate) {
return $this->respond([
'status' => 404,
'message' => 'Endorsement type already exists'
]);
}
$data = [
'endorsement_type' => $input['endorsement_type'],
];
$this->EndorsementTypeModel->update($id, $data);
return $this->respond([
'status' => 200,
'message' => 'Endorsement type updated successfully'
]);
}
public function updateEndorsementStatus($id)
{
$input = $this->request->getJSON(true);
if (!isset($input['is_active'])) {
return $this->response->setJSON([
'status' => 404,
'message' => 'is_active field is required'
]);
}
$record = $this->EndorsementTypeModel->find($id);
if (!$record) {
return $this->response->setJSON(['status' => 404, 'message' => 'Record not found']);
}
$status = ($input['is_active'] == 1) ? 0 : 1;
$this->EndorsementTypeModel->update($id, [
'is_active' => $status,
'updated_by' => $input['updated_by'] ?? null,
]);
return $this->response->setJSON([
'status' => 200,
'message' => 'Status updated successfully'
]);
}
//---------------------------------------------------------------------------------------
public function getHistory()

1335
composer.lock generated

File diff suppressed because it is too large Load Diff