diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 697ee8a6..78a80888 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -824,6 +824,7 @@ $routes->group("/ticket", ["filter" => "authMVC"], function ($routes) { $routes->get('feedback-list','TicketController::feedbackList'); $routes->match(['get', 'post'], 'claim-upload','TicketController::claimDumpUpload'); $routes->get('remove','TicketController::removeTicket'); + $routes->get('tpa-claim-push-logs','TicketController::getTpaClaimPushLogs'); $routes->get('new/(:any)','TicketController::ticket_form/$1'); $routes->post('create','TicketController::createTicket'); $routes->post('update','TicketController::updateTicket'); diff --git a/app/Controllers/ApiServiceController.php b/app/Controllers/ApiServiceController.php index 18eac66a..735cbfb0 100644 --- a/app/Controllers/ApiServiceController.php +++ b/app/Controllers/ApiServiceController.php @@ -50,7 +50,9 @@ class ApiServiceController extends BaseController // Push Claims public function pushClaims($claimId) { - + helper('tpa_claim_push_log'); + init_tpa_claim_push_logs($claimId); + $data = $this->db->table('ticket_master tm') ->select('tm.id,tm.tpa_id ')->where('tm.id', $claimId)->get()->getRowArray(); // single record @@ -79,7 +81,7 @@ class ApiServiceController extends BaseController $voloApiController = new VoloApiController(); return $voloApiController->SubmitClaim($claimId); }else{ - log_message('error', "This ticket id ( {$claimId} ) TPA has no API service enabled. TPA ID : {$tpaID}"); + tpa_claim_push_log($claimId, "This ticket id ( {$claimId} ) TPA has no API service enabled. TPA ID : {$tpaID}"); } } diff --git a/app/Controllers/FhplApiController.php b/app/Controllers/FhplApiController.php index 6d684e1c..16bc30ed 100644 --- a/app/Controllers/FhplApiController.php +++ b/app/Controllers/FhplApiController.php @@ -70,7 +70,7 @@ class FhplApiController extends BaseController public function SubmitClaim($claimId = null) // 515 { - helper('api'); + helper(['api', 'tpa_claim_push_log']); $data = $this->db->table('ticket_master tm') ->select(' @@ -99,7 +99,7 @@ class FhplApiController extends BaseController if (count($data) && $data['filePath'] == null) { - log_message('error', "FHPL - Claim Push FAILED | claimId: '.$claimId.' - Claim or File Missing"); + tpa_claim_push_log($claimId, "FHPL - Claim Push FAILED | claimId: {$claimId} - Claim or File Missing"); return ['status' => false, 'message' => 'Claim Push FAILED | Claim or File Missing']; } @@ -109,7 +109,7 @@ class FhplApiController extends BaseController $pdfPath = WRITEPATH . 'uploads/claim_files/' . $filename; if (!file_exists($pdfPath)) { - log_message('error', "FHPL - Claim Push FAILED | claimId: '.$claimId.' - PDF not found on server"); + tpa_claim_push_log($claimId, "FHPL - Claim Push FAILED | claimId: {$claimId} - PDF not found on server"); return ['status' => false, 'message' => 'Claim Push FAILED | PDF not found on server']; } @@ -119,7 +119,7 @@ class FhplApiController extends BaseController // Generate FHPL Token $tokenResponse = $this->generateAuthToken(); if (empty($tokenResponse['data']['access_token'])) { - log_message('error', "FHPL - Claim Push FAILED | claimId: '.$claimId.' - FHPL Token generation failed"); + tpa_claim_push_log($claimId, "FHPL - Claim Push FAILED | claimId: {$claimId} - FHPL Token generation failed"); return ['status' => false, 'message' => 'Claim Push FAILED | FHPL Token generation failed']; } $token = $tokenResponse['data']['access_token']; @@ -154,14 +154,14 @@ class FhplApiController extends BaseController "Content-Type: application/json" ]; - log_message('error', 'FHPL - Claim Push | claimId: '.$claimId.' | payload: '.json_encode($body)); + tpa_claim_push_log($claimId, 'FHPL - Claim Push | claimId: '.$claimId.' | payload: '.json_encode($body)); $response = call_third_party_api($url, 'POST', $headers, $body); - log_message('error', 'FHPL - Claim Push RESPONSE | ' . json_encode($response)); + tpa_claim_push_log($claimId, 'FHPL - Claim Push RESPONSE | ' . json_encode($response)); if($response['status'] != true){ - log_message('error', 'FHPL - Claim Push FAILED | claimId: '.$claimId.' | response: '.json_encode($response)); + tpa_claim_push_log($claimId, 'FHPL - Claim Push FAILED | claimId: '.$claimId.' | response: '.json_encode($response)); $this->db->table('ticket_master') ->where('id',$claimId) ->update([ 'tpa_push_response' => json_encode($response) ]); @@ -193,15 +193,15 @@ class FhplApiController extends BaseController ->where('id', $file_id) ->update([ 'is_file_sent_to_tpa' => 1 ]); - log_message('error','HEALTH_INDIA - Claim Push | Updating claim_files table for file_id: '.$file_id); + tpa_claim_push_log($claimId, 'FHPL - Claim Push | Updating claim_files table for file_id: '.$file_id); }else{ - log_message('error','HEALTH_INDIA - Claim Push | No file_id found to update claim_files table.'); + tpa_claim_push_log($claimId, 'FHPL - Claim Push | No file_id found to update claim_files table.'); } - log_message('error', 'FHPL - Claim Push SUCCESS | claimId: '.$claimId.' | claimNO: '.$fhplClaimNo); + tpa_claim_push_log($claimId, 'FHPL - Claim Push SUCCESS | claimId: '.$claimId.' | claimNO: '.$fhplClaimNo); return ['status' => true, 'message' => 'Claim Push SUCCESS', 'response' => $response]; }else { - log_message('error', 'FHPL - Claim Push API SUCCESS BUT claimsInfo EMPTY | response: '.json_encode($response)); + tpa_claim_push_log($claimId, 'FHPL - Claim Push API SUCCESS BUT claimsInfo EMPTY | response: '.json_encode($response)); return ['status' => false, 'message' => 'Claim Push API SUCCESS BUT claimsInfo EMPTY']; } } diff --git a/app/Controllers/HealthIndiaApiController.php b/app/Controllers/HealthIndiaApiController.php index 46b67043..485e81d9 100644 --- a/app/Controllers/HealthIndiaApiController.php +++ b/app/Controllers/HealthIndiaApiController.php @@ -84,9 +84,9 @@ class HealthIndiaApiController extends BaseController public function SubmitClaim($claimId = null) { - helper('api'); + helper(['api', 'tpa_claim_push_log']); - log_message('error', 'HEALTH_INDIA - Claim Push | Started for claimId: ' . $claimId); + tpa_claim_push_log($claimId, 'HEALTH_INDIA - Claim Push | Started for claimId: ' . $claimId); $data = $this->db->table('ticket_master tm') ->select(' @@ -121,12 +121,12 @@ class HealthIndiaApiController extends BaseController // dd($data); if (!$data) { - log_message('error', "HEALTH_INDIA - Claim Push FAILED | claimId: {$claimId} - Claim not found"); + tpa_claim_push_log($claimId, "HEALTH_INDIA - Claim Push FAILED | claimId: {$claimId} - Claim not found"); return ['status' => false, 'message' => 'Claim Push FAILED | Claim not found']; } if ($data['filePath'] == null) { - log_message('error', "HEALTH_INDIA - Claim Push FAILED | claimId: {$claimId} - File Missing"); + tpa_claim_push_log($claimId, "HEALTH_INDIA - Claim Push FAILED | claimId: {$claimId} - File Missing"); return ['status' => false, 'message' => 'Claim Push FAILED | File Missing']; } @@ -136,7 +136,7 @@ class HealthIndiaApiController extends BaseController $pdfPath = WRITEPATH . 'uploads/claim_files/' . $filename; if (!file_exists($pdfPath)) { - log_message('error', "HEALTH_INDIA - Claim Push FAILED | claimId: {$claimId} - PDF not found on server at path: {$pdfPath}"); + tpa_claim_push_log($claimId, "HEALTH_INDIA - Claim Push FAILED | claimId: {$claimId} - PDF not found on server at path: {$pdfPath}"); return ['status' => false, 'message' => 'Claim Push FAILED | PDF not found on server']; } @@ -146,7 +146,7 @@ class HealthIndiaApiController extends BaseController // Generate Health India Token $tokenResponse = $this->generateAuthToken(); if (empty($tokenResponse['data']['result'][0]['access_token'])) { - log_message('error', "HEALTH_INDIA - Claim Push FAILED | claimId: {$claimId} - Token generation failed"); + tpa_claim_push_log($claimId, "HEALTH_INDIA - Claim Push FAILED | claimId: {$claimId} - Token generation failed"); return; } $token = $tokenResponse['data']['result'][0]['access_token']; @@ -206,14 +206,14 @@ class HealthIndiaApiController extends BaseController "Content-Type: application/json" ]; - log_message('error', 'HEALTH_INDIA - Claim Push | claimId: ' . $claimId . ' | URL: ' . $url ); + tpa_claim_push_log($claimId, 'HEALTH_INDIA - Claim Push | claimId: ' . $claimId . ' | URL: ' . $url); $response = call_third_party_api($url, 'POST', $headers, $body); // dd($response); if ($response['status'] != true) { - log_message('error', 'HEALTH_INDIA - Claim Push FAILED | claimId: ' . $claimId . ' | response: ' . json_encode($response)); + tpa_claim_push_log($claimId, 'HEALTH_INDIA - Claim Push FAILED | claimId: ' . $claimId . ' | response: ' . json_encode($response)); $this->db->table('ticket_master') ->where('id', $claimId) ->update(['tpa_push_response' => json_encode($response)]); @@ -240,15 +240,15 @@ class HealthIndiaApiController extends BaseController ->where('id', $file_id) ->update([ 'is_file_sent_to_tpa' => 1 ]); - log_message('error','HEALTH_INDIA - Claim Push | Updating claim_files table for file_id: '.$file_id); + tpa_claim_push_log($claimId, 'HEALTH_INDIA - Claim Push | Updating claim_files table for file_id: '.$file_id); }else{ - log_message('error','HEALTH_INDIA - Claim Push | No file_id found to update claim_files table.'); + tpa_claim_push_log($claimId, 'HEALTH_INDIA - Claim Push | No file_id found to update claim_files table.'); } - log_message('error', 'HEALTH_INDIA - Claim Push SUCCESS | claimId: ' . $claimId . ' | CCN: ' . $ccn . ' | CCN_EXT: ' . $ccnExt); + tpa_claim_push_log($claimId, 'HEALTH_INDIA - Claim Push SUCCESS | claimId: ' . $claimId . ' | CCN: ' . $ccn . ' | CCN_EXT: ' . $ccnExt); return ['status' => true, 'message' => 'Claim Push SUCCESS', 'response' => $response]; } else { - log_message('error', 'HEALTH_INDIA - Claim Push API SUCCESS BUT CCN EMPTY | claimId: ' . $claimId . ' | response: ' . json_encode($response)); + tpa_claim_push_log($claimId, 'HEALTH_INDIA - Claim Push API SUCCESS BUT CCN EMPTY | claimId: ' . $claimId . ' | response: ' . json_encode($response)); return ['status' => false, 'message' => 'Claim Push API SUCCESS BUT CCN EMPTY']; } diff --git a/app/Controllers/MediAssistApiController.php b/app/Controllers/MediAssistApiController.php index cb39d93c..a05b8853 100644 --- a/app/Controllers/MediAssistApiController.php +++ b/app/Controllers/MediAssistApiController.php @@ -30,7 +30,7 @@ class MediAssistApiController extends BaseController public function SubmitClaim ($claimId = null) { - helper('api'); + helper(['api', 'tpa_claim_push_log']); // $url = ''. getenv('MEDI_ASSIST_API_BASE_URL').'/SubmitClaim'; $url = getenv('MEDI_ASSIST_API_BASE_URL_CLAIMSUBMIT'); @@ -133,14 +133,14 @@ class MediAssistApiController extends BaseController // ] // ]; - log_message('error','MEDI_ASSIST - Claim Push | claimId: '.$claimId.' | payload: '.json_encode($body)); + tpa_claim_push_log($claimId, 'MEDI_ASSIST - Claim Push | claimId: '.$claimId.' | payload: '.json_encode($body)); $response = call_third_party_api($url, $method, $headers, $body); if($response['status'] != true){ - log_message('error','MEDI_ASSIST - Claim Push FAILED | claimId: '.$claimId.' | response: '.json_encode($response)); + tpa_claim_push_log($claimId, 'MEDI_ASSIST - Claim Push FAILED | claimId: '.$claimId.' | response: '.json_encode($response)); $this->db->table('ticket_master') ->where('id',$claimId) ->update([ 'tpa_push_response' => json_encode($response) ]); @@ -153,7 +153,7 @@ class MediAssistApiController extends BaseController if(!empty($claimRef)){ - log_message('error','MEDI_ASSIST - Claim Push SUCCESS | claimId: '.$claimId.' | claimReferenceNo: '.$claimRef); + tpa_claim_push_log($claimId, 'MEDI_ASSIST - Claim Push SUCCESS | claimId: '.$claimId.' | claimReferenceNo: '.$claimRef); // Update claim reference number in ticket_master $this->db->table('ticket_master') @@ -167,15 +167,15 @@ class MediAssistApiController extends BaseController ->where('id', $file_id) ->update([ 'is_file_sent_to_tpa' => 1 ]); - log_message('error','MEDI_ASSIST - Claim Push | Updating claim_files table for file_id: '.$file_id); + tpa_claim_push_log($claimId, 'MEDI_ASSIST - Claim Push | Updating claim_files table for file_id: '.$file_id); }else{ - log_message('error','MEDI_ASSIST - Claim Push | No file_id found to update claim_files table.'); + tpa_claim_push_log($claimId, 'MEDI_ASSIST - Claim Push | No file_id found to update claim_files table.'); } return ['status' => true, 'message' => 'Claim Push SUCCESS', 'response' => $response]; } else { - log_message('error','MEDI_ASSIST - Claim Push API Failed | claimReferenceNo EMPTY | claimId: '.$claimId.' | response: '.json_encode($response)); + tpa_claim_push_log($claimId, 'MEDI_ASSIST - Claim Push API Failed | claimReferenceNo EMPTY | claimId: '.$claimId.' | response: '.json_encode($response)); return ['status' => false, 'message' => 'Claim Push API Failed', 'response' => $response]; } diff --git a/app/Controllers/SalesController.php b/app/Controllers/SalesController.php index 659299cd..edf64242 100644 --- a/app/Controllers/SalesController.php +++ b/app/Controllers/SalesController.php @@ -2028,6 +2028,35 @@ private function buildOppAchievement($db, array $sales_manager_ids, $branchId, s ORDER BY l.created_at DESC ", [$uid, $fyStart, $fyEnd])->getResultArray(); + // ── Lost Leads for this user in FY (Opportunities tab — toggle off) ── + $lossLeads = $db->query(" + SELECT + l.id AS opportunities_id, + l.actual_lead_id, + COALESCE(l.lead_form_type, 1) AS lead_form_type_id, + l.lead_type AS lead_type_id, + sal.company_name AS company, + l.client_name AS client_name, + CASE WHEN COALESCE(l.lead_form_type, 1) = 1 THEN 'EB' ELSE 'Non-EB' END AS lead_form_type, + CASE + WHEN l.lead_type = 1 THEN 'Fresh' + WHEN l.lead_type = 2 THEN 'Renewal' + WHEN l.lead_type = 3 THEN 'Roll Over' + ELSE '' + END AS lead_type, + l.created_at AS created_at, + l.status, + l.lost_reason AS lost_reason + FROM leads l + INNER JOIN sales_actual_leads sal + ON sal.lead_id = l.actual_lead_id + WHERE l.status = 'lost' + AND sal.assigned_to = ? + AND l.created_at >= ? + AND l.created_at <= ? + ORDER BY l.created_at DESC + ", [$uid, $fyStart, $fyEnd])->getResultArray(); + // -- NOTE: AND TRIM(sal.company_name) = TRIM(l.client_name) $result[$uid] = [ 'total_policies' => $totalPolicies, @@ -2035,6 +2064,7 @@ private function buildOppAchievement($db, array $sales_manager_ids, $branchId, s 'target_amt' => $targetAmt, 'policies' => $policies, 'won_leads' => $wonLeads, // for Table 2 in modal Tab 2 + 'loss_leads' => $lossLeads, ]; } diff --git a/app/Controllers/TicketController.php b/app/Controllers/TicketController.php index 4421fb71..a3e0e01c 100644 --- a/app/Controllers/TicketController.php +++ b/app/Controllers/TicketController.php @@ -509,6 +509,7 @@ class TicketController extends BaseController 'tm.is_head_approved', 'tcs.claim_status AS status', 'tm.claim_number AS claim_no', + 'tm.tpa_claim_push_reference_no', 'tm.tpa_id', 'tm.tpa_no', 'tm.emp_name', @@ -650,6 +651,7 @@ class TicketController extends BaseController 'tm.ticket_type_id', 'tcs.claim_status AS status', 'tm.claim_number AS claim_no', + 'tm.tpa_claim_push_reference_no', 'tm.claim_status_id', 'tm.claim_created_by', 'tm.is_head_approved', @@ -2535,6 +2537,43 @@ class TicketController extends BaseController } + public function getTpaClaimPushLogs() + { + $ticketId = $this->request->getGet('ticket_id'); + + if (empty($ticketId)) { + return $this->respond([ + 'status' => false, + 'message' => 'ticket_id is required', + ], 400); + } + + $ticket = $this->ticketMasterModel + ->select('id, tpa_claim_push_logs') + ->where('id', $ticketId) + ->where('is_active', 1) + ->first(); + + if (!$ticket) { + return $this->respond([ + 'status' => false, + 'message' => 'Claim not found', + ], 404); + } + + $logs = trim((string) ($ticket['tpa_claim_push_logs'] ?? '')); + + return $this->respond([ + 'status' => true, + 'message' => 'TPA claim push logs fetched successfully', + 'data' => [ + 'ticket_id' => (int) $ticketId, + 'logs' => $logs, + 'has_logs' => $logs !== '', + ], + ], 200); + } + //---- Email Trigger Part---------------------------------------------------------------------------------------------- public function constructMailContent($ticket_id, $status_id = null) diff --git a/app/Controllers/VidalApiController.php b/app/Controllers/VidalApiController.php index 889ae745..0fec2c73 100644 --- a/app/Controllers/VidalApiController.php +++ b/app/Controllers/VidalApiController.php @@ -41,13 +41,14 @@ class VidalApiController extends BaseController - function uploadFileToVidal($filePath,$filename) + function uploadFileToVidal($filePath, $filename, $claimId = null) { + helper('tpa_claim_push_log'); // $apiUrl = "https://devapigw.vidalhealthtpa.com/partner-integration/api/files/upload-url"; $apiUrl = getenv('VIDAL_API_BASE_URL').'/files/upload-url'; $subscriptionKey = getenv('VIDAL_API_SUBSCRIPTION_KEY'); - log_message('error', "VIDAL - Claim Push | Starting file upload process for filename: $filename | Path: $filePath"); + tpa_claim_push_log($claimId, "VIDAL - Claim Push | Starting file upload process for filename: $filename | Path: $filePath"); // Step 1: Get signed URL from Vidal API // $filePath = '/opt/lampp/htdocs/nhance/writable/uploads/claim_files/1760013019_73d94af7b96ddc2e3d51.png'; @@ -57,7 +58,7 @@ class VidalApiController extends BaseController "Ocp-Apim-Subscription-Key: $subscriptionKey" ]; - log_message('error', "VIDAL - Claim Push | Requesting signed URL from Vidal API: $apiUrl | Payload: $payload"); + tpa_claim_push_log($claimId, "VIDAL - Claim Push | Requesting signed URL from Vidal API: $apiUrl | Payload: $payload"); $ch = curl_init($apiUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); @@ -67,7 +68,7 @@ class VidalApiController extends BaseController $response = curl_exec($ch); if (curl_errno($ch)) { - log_message('error', "VIDAL - Claim Push Curl error while requesting signed URL: " . curl_error($ch)); + tpa_claim_push_log($claimId, "VIDAL - Claim Push Curl error while requesting signed URL: " . curl_error($ch)); return ["status" => false, "message" => curl_error($ch)]; } curl_close($ch); @@ -75,14 +76,14 @@ class VidalApiController extends BaseController $responseData = json_decode($response, true); if (!isset($responseData['data']['signedUrl']) || !isset($responseData['data']['fileId'])) { - log_message('error', "VIDAL - Claim Push | Invalid signed URL response received: " . json_encode($responseData)); + tpa_claim_push_log($claimId, "VIDAL - Claim Push | Invalid signed URL response received: " . json_encode($responseData)); return ["status" => false, "message" => "Invalid signed URL response", "response" => $responseData]; } $signedUrl = $responseData['data']['signedUrl']; $fileId = $responseData['data']['fileId']; - log_message('error', "VIDAL - Claim Push | Received signed URL & fileId. fileId: $fileId"); + tpa_claim_push_log($claimId, "VIDAL - Claim Push | Received signed URL & fileId. fileId: $fileId"); // Step 2: Upload file to signed URL using PUT (Azure Blob) $fileSize = filesize($filePath); @@ -107,12 +108,12 @@ class VidalApiController extends BaseController curl_close($ch2); if ($curlErr) { - log_message('error', "VIDAL - Claim Push | Curl error during file upload: $curlErr"); + tpa_claim_push_log($claimId, "VIDAL - Claim Push | Curl error during file upload: $curlErr"); return ["status" => false, "message" => "File upload failed", "data" => $curlErr]; } if ($httpCode !== 200 && $httpCode !== 201) { - log_message('error', "VIDAL - Claim Push | File upload failed with HTTP Code: $httpCode | Response: $uploadResponse"); + tpa_claim_push_log($claimId, "VIDAL - Claim Push | File upload failed with HTTP Code: $httpCode | Response: $uploadResponse"); return [ "status" => false, "message" => "File upload failed", @@ -133,7 +134,7 @@ class VidalApiController extends BaseController public function SubmitClaim ($claimId = null) //515 { - helper('api'); + helper(['api', 'tpa_claim_push_log']); // Fetch the data from DB $data = $this->db->table('ticket_master tm') @@ -174,7 +175,7 @@ class VidalApiController extends BaseController ->getRowArray(); // single record if (count($data) && $data['filePath'] == null) { - log_message('error', "VIDAL - Claim Push | Submit claim failed - Claim or File Missing"); + tpa_claim_push_log($claimId, "VIDAL - Claim Push | Submit claim failed - Claim or File Missing"); return ['status' => false, 'message' => 'Claim Push FAILED | Claim or File Missing']; } @@ -185,9 +186,9 @@ class VidalApiController extends BaseController // dd($data); // Upload file first - $upload = $this->uploadFileToVidal($filePath,$filename); + $upload = $this->uploadFileToVidal($filePath, $filename, $claimId); if ($upload['status'] !== true) { - log_message('error', "VIDAL - Claim Push | Submit claim failed - File upload failed"); + tpa_claim_push_log($claimId, "VIDAL - Claim Push | Submit claim failed - File upload failed"); return $this->response->setJSON([ 'status' => false, 'message' => 'File upload failed', @@ -247,7 +248,7 @@ class VidalApiController extends BaseController ]; // dd($body); - log_message('error', 'VIDAL - Claim Push | claimId: '.$claimId.' | payload: '.json_encode($body)); + tpa_claim_push_log($claimId, 'VIDAL - Claim Push | claimId: '.$claimId.' | payload: '.json_encode($body)); // $body = [ // 'policyNo' => "351500/D0534/PP/20-20/PC", @@ -279,7 +280,7 @@ class VidalApiController extends BaseController $response = call_third_party_api($url, $method, $headers, $body); if($response['status'] != true){ - log_message('error', 'VIDAL - Claim Push FAILED | claimId: '.$claimId.' | response: '.json_encode($response)); + tpa_claim_push_log($claimId, 'VIDAL - Claim Push FAILED | claimId: '.$claimId.' | response: '.json_encode($response)); $this->db->table('ticket_master') ->where('id',$claimId) ->update([ 'tpa_push_response' => json_encode($response) ]); @@ -295,7 +296,7 @@ class VidalApiController extends BaseController if(!empty($claimNO) && !empty($claimInwardNO)){ - log_message('error', 'VIDAL - Claim Push SUCCESS | claimId: '.$claimId.' | claimNO: '.$claimNO.' | claimInwardNO: '.$claimInwardNO); + tpa_claim_push_log($claimId, 'VIDAL - Claim Push SUCCESS | claimId: '.$claimId.' | claimNO: '.$claimNO.' | claimInwardNO: '.$claimInwardNO); $this->db->table('ticket_master') ->where('id',$claimId) @@ -308,19 +309,19 @@ class VidalApiController extends BaseController ->where('id', $tpa_sent_file_id) ->update([ 'is_file_sent_to_tpa' => 1 ]); - log_message('error','MEDI_ASSIST - Claim Push | Updating claim_files table for file_id: '.$tpa_sent_file_id); + tpa_claim_push_log($claimId, 'VIDAL - Claim Push | Updating claim_files table for file_id: '.$tpa_sent_file_id); }else{ - log_message('error','MEDI_ASSIST - Claim Push | No file_id found to update claim_files table.'); + tpa_claim_push_log($claimId, 'VIDAL - Claim Push | No file_id found to update claim_files table.'); } return ['status' => true, 'message' => 'Claim Push SUCCESS']; } else { - log_message('error', 'VIDAL - Claim Push API SUCCESS BUT claimNO,claimInwardNO EMPTY | claimId: '.$claimId.' | response: '.json_encode($response)); + tpa_claim_push_log($claimId, 'VIDAL - Claim Push API SUCCESS BUT claimNO,claimInwardNO EMPTY | claimId: '.$claimId.' | response: '.json_encode($response)); return ['status' => false, 'message' => 'Claim Push API SUCCESS BUT claimNO,claimInwardNO EMPTY']; } }else{ - log_message('error', 'VIDAL - Claim Push API FAILED | claimId: '.$claimId.' | response: '.json_encode($response)); + tpa_claim_push_log($claimId, 'VIDAL - Claim Push API FAILED | claimId: '.$claimId.' | response: '.json_encode($response)); return ['status' => false, 'message' => 'Claim Push API FAILED']; } diff --git a/app/Controllers/VoloApiController.php b/app/Controllers/VoloApiController.php index b1bc0a4b..c256ecfa 100644 --- a/app/Controllers/VoloApiController.php +++ b/app/Controllers/VoloApiController.php @@ -682,7 +682,7 @@ class VoloApiController extends BaseController */ public function SubmitClaim($claimId = null) { - helper('api'); + helper(['api', 'tpa_claim_push_log']); $data = $this->db->table('ticket_master tm') ->select(' @@ -702,12 +702,12 @@ class VoloApiController extends BaseController ->getRowArray(); if (!$data) { - log_message('error', 'VOLO - Claim Push FAILED | claimId: ' . $claimId . ' | claim not found'); + tpa_claim_push_log($claimId, 'VOLO - Claim Push FAILED | claimId: ' . $claimId . ' | claim not found'); return ['status' => false, 'message' => 'Claim Push FAILED | Claim not found']; } if (empty($data['filePath'])) { - log_message('error', 'VOLO - Claim Push FAILED | claimId: ' . $claimId . ' | file missing'); + tpa_claim_push_log($claimId, 'VOLO - Claim Push FAILED | claimId: ' . $claimId . ' | file missing'); return ['status' => false, 'message' => 'Claim Push FAILED | File Missing']; } @@ -715,7 +715,7 @@ class VoloApiController extends BaseController $filename = basename($data['filePath']); $pdfPath = WRITEPATH . 'uploads/claim_files/' . $filename; if (!is_readable($pdfPath)) { - log_message('error', 'VOLO - Claim Push FAILED | claimId: ' . $claimId . ' | PDF not readable'); + tpa_claim_push_log($claimId, 'VOLO - Claim Push FAILED | claimId: ' . $claimId . ' | PDF not readable'); return ['status' => false, 'message' => 'Claim Push FAILED | PDF not found on server']; } @@ -723,13 +723,13 @@ class VoloApiController extends BaseController $entityId = $this->resolveEntityId($data['policyNo'] ?? ''); if ($entityId === null) { - log_message('error', 'VOLO - Claim Push FAILED | claimId: ' . $claimId . ' | entity id not resolved'); + tpa_claim_push_log($claimId, 'VOLO - Claim Push FAILED | claimId: ' . $claimId . ' | entity id not resolved'); return ['status' => false, 'message' => 'Claim Push FAILED | entity id not resolved']; } $hospitalId = getenv('VOLO_DEFAULT_HOSPITAL_ID'); if ($hospitalId === false || $hospitalId === '') { - log_message('error', 'VOLO - Claim Push FAILED | claimId: ' . $claimId . ' | VOLO_DEFAULT_HOSPITAL_ID not set'); + tpa_claim_push_log($claimId, 'VOLO - Claim Push FAILED | claimId: ' . $claimId . ' | VOLO_DEFAULT_HOSPITAL_ID not set'); return ['status' => false, 'message' => 'Claim Push FAILED | hospital id not configured']; } @@ -754,12 +754,12 @@ class VoloApiController extends BaseController 'insurerPolicyNumber' => (string) ($data['policyNo'] ?? ''), ]; - log_message('error', 'VOLO - Claim Push | claimId: ' . $claimId . ' | payload: ' . json_encode($payload)); + tpa_claim_push_log($claimId, 'VOLO - Claim Push | claimId: ' . $claimId . ' | payload: ' . json_encode($payload)); $response = $this->intimateClaim($payload); if (empty($response['status'])) { - log_message('error', 'VOLO - Claim Push FAILED | claimId: ' . $claimId . ' | ' . json_encode($response)); + tpa_claim_push_log($claimId, 'VOLO - Claim Push FAILED | claimId: ' . $claimId . ' | ' . json_encode($response)); $this->db->table('ticket_master') ->where('id', $claimId) ->update(['tpa_push_response' => json_encode($response)]); @@ -781,7 +781,7 @@ class VoloApiController extends BaseController 'tpa_claim_id' => $ref, 'updated_at' => date('Y-m-d H:i:s'), ]); - log_message('error', 'VOLO - Claim Push SUCCESS | claimId: ' . $claimId . ' | ref: ' . $ref); + tpa_claim_push_log($claimId, 'VOLO - Claim Push SUCCESS | claimId: ' . $claimId . ' | ref: ' . $ref); // Update claim files table that file is sent to tpa for this claim if(!empty($file_id)){ @@ -790,15 +790,15 @@ class VoloApiController extends BaseController ->where('id', $file_id) ->update([ 'is_file_sent_to_tpa' => 1 ]); - log_message('error','VOLO - Claim Push | Updating claim_files table for file_id: '.$file_id); + tpa_claim_push_log($claimId, 'VOLO - Claim Push | Updating claim_files table for file_id: '.$file_id); }else{ - log_message('error','VOLO - Claim Push | No file_id found to update claim_files table.'); + tpa_claim_push_log($claimId, 'VOLO - Claim Push | No file_id found to update claim_files table.'); } return ['status' => true, 'message' => 'Claim Push SUCCESS', 'response' => $response]; } - log_message('error', 'VOLO - Claim Push empty reference | claimId: ' . $claimId . ' | ' . json_encode($response)); + tpa_claim_push_log($claimId, 'VOLO - Claim Push empty reference | claimId: ' . $claimId . ' | ' . json_encode($response)); return ['status' => false, 'message' => 'Claim Push API response missing reference', 'response' => $response]; } diff --git a/app/Helpers/tpa_claim_push_log_helper.php b/app/Helpers/tpa_claim_push_log_helper.php new file mode 100644 index 00000000..cf9b2cc9 --- /dev/null +++ b/app/Helpers/tpa_claim_push_log_helper.php @@ -0,0 +1,48 @@ +table('ticket_master') + ->where('id', $claimId) + ->update(['tpa_claim_push_logs' => "[{$started}] Claim push started\n"]); + } +} + +if (!function_exists('tpa_claim_push_log')) { + /** + * Write to application log and append the same line to ticket_master.tpa_claim_push_logs. + */ + function tpa_claim_push_log($claimId, string $message, string $level = 'error'): void + { + log_message($level, $message); + + if ($claimId === null || $claimId === '') { + return; + } + + $timestamp = date('Y-m-d H:i:s'); + $line = "[{$timestamp}] {$message}\n"; + + $db = \Config\Database::connect(); + $row = $db->table('ticket_master') + ->select('tpa_claim_push_logs') + ->where('id', $claimId) + ->get() + ->getRowArray(); + + $existing = $row['tpa_claim_push_logs'] ?? ''; + $db->table('ticket_master') + ->where('id', $claimId) + ->update(['tpa_claim_push_logs' => $existing . $line]); + } +} diff --git a/app/Models/ClaimsCollectionV2DashboardModel.php b/app/Models/ClaimsCollectionV2DashboardModel.php index d459d79a..447dcee0 100644 --- a/app/Models/ClaimsCollectionV2DashboardModel.php +++ b/app/Models/ClaimsCollectionV2DashboardModel.php @@ -46,6 +46,9 @@ class ClaimsCollectionV2DashboardModel extends Model 229 => 'cataract_avg_exceeded_amount', 230 => 'hospital_city_wise_si_limit_cataract', 231 => 'total_incurred_by_cliam_status', + 232 => 'inception_emp_lives', + 233 => 'current_emp_lives', + 234 => 'claim_value_by_month', ]; /** @@ -83,6 +86,9 @@ class ClaimsCollectionV2DashboardModel extends Model 'cataract_avg_exceeded_amount' => 'Cataract avg exceeded amount', 'hospital_city_wise_si_limit_cataract' => 'Hospital city wise SI Limit - Cataract', 'total_incurred_by_cliam_status' => 'Total Incurred by Cliam Status ', + 'inception_emp_lives' => 'Inception Employees & Lives', + 'current_emp_lives' => 'Current Employees & Lives', + 'claim_value_by_month' => 'Claim Value by Month', ]; protected function runKpiQuery(string $sql, int $policyId): array @@ -2083,6 +2089,92 @@ WHERE tm.client_policy_id = :policy_id: AND tm.is_active = 1 GROUP BY tcs.display_name, totals.total_count, totals.total_value -- ORDER BY claim_count DESC; +SQL; + return $this->runKpiQuery($sql, $policyId); + } + + /** Metabase #232: Inception Employees & Lives */ + public function inception_emp_lives(int $policyId): array + { + $sql = <<<'SQL' +SELECT + COUNT(DISTINCT CASE + WHEN e.relationship = 'Self' THEN e.id + END) AS inception_emp, + + COUNT(DISTINCT e.id) AS inception_lives + +FROM employee_polices ep +JOIN employees e ON e.id = ep.employee_id +WHERE ep.client_policy_id = :policy_id: + AND LOWER(e.change_event) LIKE '%inception%' + AND ep.is_active = 1 + AND e.is_active = 1; +SQL; + return $this->runKpiQuery($sql, $policyId); + } + + /** Metabase #233: Current Employees & Lives */ + public function current_emp_lives(int $policyId): array + { + $sql = <<<'SQL' +SELECT + COUNT(DISTINCT CASE + WHEN e.relationship = 'Self' THEN e.id + END) AS current_emp, + + COUNT(DISTINCT e.id) AS current_lives, + + ROUND( + COUNT(DISTINCT e.id) + / NULLIF(COUNT(DISTINCT CASE + WHEN e.relationship = 'Self' THEN e.id + END), 0) + , 2) AS avg_family_size + +FROM employee_polices ep +JOIN employees e ON e.id = ep.employee_id +WHERE ep.client_policy_id = :policy_id: + AND ep.status = 'active' + AND ep.is_active = 1 + AND e.emp_status = 'active' + AND e.is_active = 1; +SQL; + return $this->runKpiQuery($sql, $policyId); + } + + /** Metabase #234: Claim Value by Month */ + public function claim_value_by_month(int $policyId): array + { + $sql = <<<'SQL' +SELECT + DATE_FORMAT(tm.created_at, '%b %Y') AS claim_month, + DATE_FORMAT(tm.created_at, '%Y-%m') AS month_sort, + -- COUNT(tm.id) AS claim_count, + -- CONCAT(ROUND(COUNT(tm.id) / totals.total_count * 100, 2), '%') AS count_pct, + + COALESCE(SUM(CAST(NULLIF(tm.claim_amount, '') AS DECIMAL(15,2))), 0) + AS claim_value + -- CONCAT(ROUND( + -- COALESCE(SUM(CAST(NULLIF(tm.claim_amount, '') AS DECIMAL(15,2))), 0) + -- / NULLIF(totals.total_value, 0) * 100 + -- , 2), '%') AS value_pct +FROM ticket_master tm +JOIN ( + SELECT + COUNT(id) AS total_count, + COALESCE(SUM(CAST(NULLIF(claim_amount, '') AS DECIMAL(15,2))), 0) AS total_value + FROM ticket_master + WHERE client_policy_id = :policy_id: AND is_active = 1 +) totals ON 1=1 +WHERE tm.client_policy_id = :policy_id: + AND tm.is_active = 1 +GROUP BY + DATE_FORMAT(tm.created_at, '%b %Y'), + DATE_FORMAT(tm.created_at, '%Y-%m'), + totals.total_count, + totals.total_value +ORDER BY month_sort; SQL; return $this->runKpiQuery($sql, $policyId); } diff --git a/app/Views/sales/branch_level_dashboard_view.php b/app/Views/sales/branch_level_dashboard_view.php index eba15043..09be0731 100644 --- a/app/Views/sales/branch_level_dashboard_view.php +++ b/app/Views/sales/branch_level_dashboard_view.php @@ -230,6 +230,17 @@ .opp-card { background: #f8fafd; border-radius: 12px; padding: 16px; border: 1px solid #e4eaf5; text-align: center; } .opp-card-val { font-size: 22px; font-weight: 800; color: #0f172a; } .opp-card-lbl { font-size: 11px; color: #7c8db0; font-weight: 700; margin-top: 4px; letter-spacing: .04em; } + .opp-section-head { display: flex; justify-content: space-between; align-items: center; margin: 24px 0 12px; gap: 12px; flex-wrap: wrap; } + .opp-section-head .split-section-title { margin: 0; } + .opp-toggle-wrap { display: flex; align-items: center; gap: 10px; flex-shrink: 0; } + .opp-toggle-lbl { font-size: 12px; font-weight: 700; color: #94a3b8; transition: color .2s; } + .opp-toggle-lbl.active { color: #0f172a; } + .opp-toggle-switch { position: relative; display: inline-block; width: 44px; height: 24px; flex-shrink: 0; } + .opp-toggle-switch input { opacity: 0; width: 0; height: 0; } + .opp-toggle-slider { position: absolute; cursor: pointer; inset: 0; background: #cbd5e1; border-radius: 99px; transition: background .2s; } + .opp-toggle-slider::before { content: ""; position: absolute; height: 18px; width: 18px; left: 3px; bottom: 3px; background: #fff; border-radius: 50%; transition: transform .2s; box-shadow: 0 1px 3px rgba(15,23,42,0.15); } + .opp-toggle-switch input:checked + .opp-toggle-slider { background: #4f46e5; } + .opp-toggle-switch input:checked + .opp-toggle-slider::before { transform: translateX(20px); } @media(max-width:900px) { .list-col-head,.achieve-row { grid-template-columns: 220px 1fr 110px 110px 110px; } .col-lbl:nth-child(6),.col-lbl:nth-child(7),.achieve-row>*:nth-child(6),.achieve-row>*:nth-child(7) { display: none; } } @media(max-width:640px) { .list-col-head { display: none; } .achieve-row { grid-template-columns: 1fr auto; gap: 12px; padding: 14px 16px; } .achieve-row>*:not(:nth-child(1)):not(:nth-child(7)) { display: none; } .section-head { flex-direction: column; align-items: flex-start; gap: 12px; } .modal-summary { grid-template-columns: repeat(2,1fr); } .target-edit-panel { grid-template-columns: 1fr; } .opp-summary-cards { grid-template-columns: 1fr 1fr; } } @@ -502,7 +513,9 @@ const TEAM = ; const OPP_DATA = ; /* OPP_DATA shape per userId: { total_policies, total_exp_amt, target_amt, - policies: [{ policy_no, issue_date, amount, created_at }] } */ + policies: [{ policy_no, issue_date, amount, created_at }], + won_leads: [...], loss_leads: [...] } */ +let currentModalOppUserId = null; /* ── JS Helpers ── */ const ACT_ICONS = {Call:'📞',Email:'✉️',Meeting:'📅',Visit:'🚗',Demo:'🖥️','Share Docs':'📄','To Do':'✓'}; @@ -545,6 +558,89 @@ function redirectToOpportunity(leadTypeId, actualLeadId, opportunityId) { + encodeURIComponent(opportunityId); } +function escOppCell(text) { + return String(text ?? '') + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +} + +function updateOppTableHeader(showWon) { + const headRow = document.getElementById('oppTableHead'); + if (!headRow) return; + + if (showWon) { + headRow.innerHTML = + '
| Company | ' + 'Opportunity Type | ' + 'Date | ' + '
|---|---|---|
| No leads found | ||