diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 1531645b..15c4aa0a 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -560,6 +560,8 @@ $routes->cli('cli/send_mail_cli', 'MasterController::testGmailAPIViaCLI'); $routes->cli('cli/sendZeptoMail', 'MasterController::testZeptoSMTP'); $routes->cli('cli/check_bounce_mail_cli', 'MasterController::testCheckBounceMails'); $routes->cli('cli/app_check_list', 'MasterController::appCheckList'); +$routes->cli('cli/reset-token-timeout', 'RestAuthenticationController::resetTokenTimeOut'); +$routes->cli('cli/reset-token-timeout/(:num)', 'RestAuthenticationController::resetTokenTimeOut/$1'); $routes->cli('cli/new_gdrive_token', 'GoogleDriveController::generateNewGoogleDriveAccessToken'); $routes->cli('cli/list-sheet-folder-files', 'GoogleSheetController::listFolderSheetFilesCli'); $routes->cli('cli/list-sheet-folder-files/(:any)', 'GoogleSheetController::listFolderSheetFilesCli/$1'); diff --git a/app/Controllers/ApiServiceController.php b/app/Controllers/ApiServiceController.php index ea3103e9..2c28bb6c 100644 --- a/app/Controllers/ApiServiceController.php +++ b/app/Controllers/ApiServiceController.php @@ -446,6 +446,9 @@ class ApiServiceController extends BaseController if ($tpaID == $this->medi_assist_primary_key) { // MediAssist $mediAssistController = new MediAssistApiController(); return $mediAssistController->IRSubmission($claimId); + }else if ($tpaID == $this->vidal_primary_key) { // Vidal + $vidalApiController = new VidalApiController(); + return $vidalApiController->IRSubmission($claimId); }else{ log_message('error', "This ticket id ( {$claimId} ) TPA has no API service enabled. TPA ID : {$tpaID}"); } diff --git a/app/Controllers/EmployeeRestController.php b/app/Controllers/EmployeeRestController.php index dd2464f0..7d5e4c97 100755 --- a/app/Controllers/EmployeeRestController.php +++ b/app/Controllers/EmployeeRestController.php @@ -2409,13 +2409,16 @@ class EmployeeRestController extends AdminController $client_id = $this->request->getGet('client_id') ?? null; - $data['claim_status'] = $this->claimStatusModel - ->select('id,ticket_type, display_name as claim_status') - ->where('is_active', 1) - ->where('display_name IS NOT NULL OR display_name <> ""') - ->whereIn('claim_status_id',[1,2,3,4]) - ->groupBy('display_name') - ->findAll(); + $data['claim_status'] = $this->claimStatusModel + ->select('id, ticket_type, display_name as claim_status') + ->where('is_active', 1) + ->groupStart() + ->where('display_name IS NOT NULL') + ->orWhere('display_name <>', '') + ->groupEnd() + ->whereIn('ticket_type', [1,2,3,4]) + ->groupBy('display_name') + ->findAll(); if (!empty($client_id)) { @@ -3723,6 +3726,7 @@ class EmployeeRestController extends AdminController if (! empty($emp_ticket_data)) { + $received_relationship = $received_data['relationship'] ?? null; unset($received_data['relationship']); $fetchData = $emp_ticket_data[0]; @@ -3750,8 +3754,8 @@ class EmployeeRestController extends AdminController $fetchData = array_merge($fetchData, $received_data); - // $fetchData['relationship'] = strtolower($fetchData['relationship']) ?? $fetchData['relationship']; - $fetchData['relationship'] = isset($fetchData['relationship']) ? strtolower($fetchData['relationship']) : null; + // $fetchData['relationship'] = isset($fetchData['relationship']) ? strtolower($fetchData['relationship']) : null; + $fetchData['relationship'] = strtolower($received_relationship ?? $fetchData['relationship'] ?? '') ?: null; $fetchData['created_by'] = $fetchData['emp_id']; $fetchData['claim_created_by'] = "USER"; diff --git a/app/Controllers/FhplApiController.php b/app/Controllers/FhplApiController.php index 532776ff..1d280ea5 100644 --- a/app/Controllers/FhplApiController.php +++ b/app/Controllers/FhplApiController.php @@ -85,6 +85,8 @@ class FhplApiController extends BaseController cp.policy_no as policyNo, e.emp_code as memberId, tn.note as disease, + cf.id as fileId, + cf.url as filePath, cf.url as filePath ') ->join('employees e', 'e.id = tm.emp_id', 'left') @@ -102,6 +104,7 @@ class FhplApiController extends BaseController } // Build absolute file path + $file_id = $data['fileId'] ?? null; $filename = basename($data['filePath']); $pdfPath = WRITEPATH . 'uploads/claim_files/' . $filename; @@ -182,6 +185,18 @@ class FhplApiController extends BaseController 'tpa_claim_push_reference_no' => $fhplClaimNo, 'updated_at' => date('Y-m-d H:i:s') ]); + + // Update claim files table that file is sent to tpa for this claim + if(!empty($file_id)){ + + $this->db->table('claim_files') + ->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); + }else{ + log_message('error','HEALTH_INDIA - Claim Push | No file_id found to update claim_files table.'); + } log_message('error', 'FHPL - Claim Push SUCCESS | claimId: '.$claimId.' | claimNO: '.$fhplClaimNo); return ['status' => true, 'message' => 'Claim Push SUCCESS', 'response' => $response]; diff --git a/app/Controllers/HealthIndiaApiController.php b/app/Controllers/HealthIndiaApiController.php index 0552700a..f498f039 100644 --- a/app/Controllers/HealthIndiaApiController.php +++ b/app/Controllers/HealthIndiaApiController.php @@ -105,6 +105,7 @@ class HealthIndiaApiController extends BaseController cp.policy_no as policyNumber, e.emp_code as employeeCode, tn.note as disease, + cf.id as fileId, cf.url as filePath, tm.claim_type as claimType, tm.claim_type as benefitType @@ -130,6 +131,7 @@ class HealthIndiaApiController extends BaseController } // Build absolute file path + $file_id = $data['fileId'] ?? null; $filename = basename($data['filePath']); $pdfPath = WRITEPATH . 'uploads/claim_files/' . $filename; @@ -231,6 +233,18 @@ class HealthIndiaApiController extends BaseController 'updated_at' => date('Y-m-d H:i:s') ]); + // Update claim files table that file is sent to tpa for this claim + if(!empty($file_id)){ + + $this->db->table('claim_files') + ->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); + }else{ + log_message('error','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); return ['status' => true, 'message' => 'Claim Push SUCCESS', 'response' => $response]; } else { diff --git a/app/Controllers/MediAssistApiController.php b/app/Controllers/MediAssistApiController.php index f4ceaff6..65a8992a 100644 --- a/app/Controllers/MediAssistApiController.php +++ b/app/Controllers/MediAssistApiController.php @@ -42,8 +42,9 @@ class MediAssistApiController extends BaseController 'Password:'. getenv('MEDI_ASSIST_API_PASSWORD').'', ]; + $file_id = null; + //Prepare body data - // Fetch the data from DB $data = $this->db->table('ticket_master tm') ->select(' @@ -59,6 +60,7 @@ class MediAssistApiController extends BaseController tm.tpa_no as memberId, tn.note as disease, tn.note as reasonForHospitalization, + cf.id as fileId, cf.url as fileName, cf.url as filePath ') @@ -83,6 +85,7 @@ class MediAssistApiController extends BaseController if ($fileDir) { $downloadUrl = base_url('fileDownload?file_path=').$fileDir; + $file_id = $data['fileId'] ?? null; } else { $downloadUrl = ''; } @@ -152,10 +155,23 @@ class MediAssistApiController extends BaseController log_message('error','MEDI_ASSIST - Claim Push SUCCESS | claimId: '.$claimId.' | claimReferenceNo: '.$claimRef); + // Update claim reference number in ticket_master $this->db->table('ticket_master') ->where('id',$claimId) ->update([ 'tpa_claim_push_reference_no' => $claimRef ]); + // Update claim files table that file is sent to tpa for this claim + if(!empty($file_id)){ + + $this->db->table('claim_files') + ->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); + }else{ + log_message('error','MEDI_ASSIST - Claim Push | No file_id found to update claim_files table.'); + } + return ['status' => true, 'message' => 'Claim Push SUCCESS', 'response' => $response]; } else { @@ -695,16 +711,19 @@ class MediAssistApiController extends BaseController $fileData = $this->db->table('claim_files f') ->where('f.ticket_id', $claimId) ->where('f.docs_for_ir', 1) + ->where('f.file_type', 2) + ->where('f.is_file_sent_to_tpa', 0) ->get() ->getResultArray(); $Attachments = []; + $tpaSentFileIds = []; if (count($fileData)) { foreach ($fileData as $file) { - if (!empty($file['url'])) { + if (!empty($file['url']) && $file['file_type'] == 2) { $filename = basename($file['url']); $fileDir = WRITEPATH . 'uploads/claim_files/' . $filename; @@ -721,6 +740,9 @@ class MediAssistApiController extends BaseController "AttachmentName" => $filename, "AttachmentPath" => $downloadUrl ]; + + $tpaSentFileIds[] = $file['id']; // Collect file IDs to update later + } else { log_message('error',"MEDI_ASSIST - IR Submission Missing File URL → file_id={$file['id']}"); } @@ -767,6 +789,18 @@ class MediAssistApiController extends BaseController log_message('error',"MEDI_ASSIST - IR Submission SUCCESS → ClaimID={$ticket['ClaimID']}"); + // 6. UPDATE FILES AS SENT TO TPA + if(count($tpaSentFileIds) > 0){ + + $this->db->table('claim_files') + ->whereIn('id', $tpaSentFileIds) + ->update(['is_file_sent_to_tpa' => 1]); + + log_message('error',"MEDI_ASSIST - IR Submission | Updating claim_files for file IDs: " . implode(', ', $tpaSentFileIds)); + } else { + log_message('error',"MEDI_ASSIST - IR Submission | No files to update as sent to TPA"); + } + return [ 'status' => true, 'message' => 'IR Submitted successfully', diff --git a/app/Controllers/RestAuthenticationController.php b/app/Controllers/RestAuthenticationController.php index 14600e38..ae85137b 100755 --- a/app/Controllers/RestAuthenticationController.php +++ b/app/Controllers/RestAuthenticationController.php @@ -2326,6 +2326,10 @@ class RestAuthenticationController extends AdminController public function logout() { + return $this->respond([ + 'status' => true, + 'message' => 'Logged out successfully' + ], 200); $authHeader = $this->request->getHeaderLine('Authorization'); if (!$authHeader) { @@ -2373,4 +2377,52 @@ class RestAuthenticationController extends AdminController ], 200); } + public function resetTokenTimeOut($bufferSeconds = null) + { + if (!is_cli()) { + return $this->respond([ + 'status' => false, + 'message' => 'This endpoint is CLI only.' + ], 403); + } + + $envBuffer = (int) (getenv('TOKEN_TIMEOUT_RESET_BUFFER_SECONDS') ?: 300); + $buffer = is_numeric($bufferSeconds) ? (int) $bufferSeconds : $envBuffer; + if ($buffer < 0) { + $buffer = 0; + } + + $cutoffEpoch = time() - $buffer; + $db = db_connect(); + + $db->table('level_contacts') + ->where('token_time_out IS NOT NULL', null, false) + ->where('token_time_out <=', $cutoffEpoch) + ->set(['token_time_out' => null]) + ->update(); + $levelContactsUpdated = $db->affectedRows(); + + $db->table('employees') + ->where('token_time_out IS NOT NULL', null, false) + ->where('token_time_out <=', $cutoffEpoch) + ->set(['token_time_out' => null]) + ->update(); + $employeesUpdated = $db->affectedRows(); + + $result = [ + 'status' => true, + 'message' => 'Token timeout reset completed.', + 'buffer_seconds' => $buffer, + 'cutoff_epoch' => $cutoffEpoch, + 'updated' => [ + 'level_contacts' => $levelContactsUpdated, + 'employees' => $employeesUpdated, + 'total' => $levelContactsUpdated + $employeesUpdated, + ], + ]; + + echo json_encode($result, JSON_UNESCAPED_SLASHES) . PHP_EOL; + return; + } + } \ No newline at end of file diff --git a/app/Controllers/TicketController.php b/app/Controllers/TicketController.php index 928f630a..7aacb3a8 100644 --- a/app/Controllers/TicketController.php +++ b/app/Controllers/TicketController.php @@ -503,6 +503,7 @@ class TicketController extends BaseController 'tm.id', 'tm.ticket_type_id', 'tm.claim_status_id', + 'tm.claim_created_by', 'tm.is_head_approved', 'tcs.claim_status AS status', 'tm.claim_number AS claim_no', @@ -538,6 +539,7 @@ class TicketController extends BaseController 'tm.emp_personal_mail', 'tm.mode_of_intimation', 'tm.claim_type', + 'tm.tpa_claim_type', 'tm.hospital_name', 'tm.doa', 'tm.dod', @@ -640,6 +642,7 @@ class TicketController extends BaseController 'tcs.claim_status AS status', 'tm.claim_number AS claim_no', 'tm.claim_status_id', + 'tm.claim_created_by', 'tm.is_head_approved', 'tm.tpa_id', 'tm.tpa_no', @@ -671,6 +674,7 @@ class TicketController extends BaseController 'tm.emp_personal_mail', 'tm.mode_of_intimation', 'tm.claim_type', + 'tm.tpa_claim_type', 'tm.hospital_name', 'tm.doa', 'tm.dod', @@ -1138,6 +1142,8 @@ class TicketController extends BaseController public function createTicket() { $request_data = $this->request->getPost(); + $approvedLetterFile = $this->request->getFile('approved_letter_file'); + $settleLetterFile = $this->request->getFile('settle_letter_file'); $selected_ticket_type = $this->request->getPost('ticket_type_id'); // 1. Initialize an empty rules array @@ -1453,6 +1459,84 @@ class TicketController extends BaseController $request_data = $this->request->getPost(); $sanitized_data = sanitizeInputArrayAdvanced($request_data); $ticket_data = $this->formatDateForClaim($sanitized_data); + $approvedLetterUrl = trim((string) ($ticket_data['approved_letter'] ?? '')); + $settleLetterUrl = trim((string) ($ticket_data['settle_letter'] ?? '')); + $hasApprovedLetterFile = $approvedLetterFile !== null + && $approvedLetterFile->isValid() + && $approvedLetterFile->getError() !== UPLOAD_ERR_NO_FILE; + $hasSettleLetterFile = $settleLetterFile !== null + && $settleLetterFile->isValid() + && $settleLetterFile->getError() !== UPLOAD_ERR_NO_FILE; + + if ($approvedLetterUrl !== '' && $hasApprovedLetterFile) { + return $this->response->setStatusCode(400)->setJSON([ + 'status' => false, + 'message' => 'Input validation failed', + 'code' => 400, + 'errors' => ['approved_letter' => 'Provide either Approved Letter URL or Approved Letter PDF file, not both.'], + ]); + } + + if ($approvedLetterUrl !== '' && ! $this->isClaimUploadUrl($approvedLetterUrl)) { + return $this->response->setStatusCode(400)->setJSON([ + 'status' => false, + 'message' => 'Input validation failed', + 'code' => 400, + 'errors' => ['approved_letter' => 'Approved Letter URL format is invalid.'], + ]); + } + + if ($settleLetterUrl !== '' && $hasSettleLetterFile) { + return $this->response->setStatusCode(400)->setJSON([ + 'status' => false, + 'message' => 'Input validation failed', + 'code' => 400, + 'errors' => ['settle_letter' => 'Provide either Settle Letter URL or Settle Letter PDF file, not both.'], + ]); + } + + if ($settleLetterUrl !== '' && ! $this->isClaimUploadUrl($settleLetterUrl)) { + return $this->response->setStatusCode(400)->setJSON([ + 'status' => false, + 'message' => 'Input validation failed', + 'code' => 400, + 'errors' => ['settle_letter' => 'Settle Letter URL format is invalid.'], + ]); + } + + $uploadedApprovedLetter = null; + if ($hasApprovedLetterFile) { + $uploadResult = $this->uploadApprovedLetterPdf($approvedLetterFile, 'Approved Letter'); + if (! ($uploadResult['status'] ?? false)) { + return $this->response->setStatusCode(400)->setJSON([ + 'status' => false, + 'message' => 'Input validation failed', + 'code' => 400, + 'errors' => ['approved_letter_file' => $uploadResult['message'] ?? 'Invalid Approved Letter file.'], + ]); + } + $uploadedApprovedLetter = $uploadResult['data']; + $ticket_data['approved_letter'] = ''; + } else { + $ticket_data['approved_letter'] = $approvedLetterUrl; + } + + $uploadedSettleLetter = null; + if ($hasSettleLetterFile) { + $uploadResult = $this->uploadApprovedLetterPdf($settleLetterFile, 'Settle Letter'); + if (! ($uploadResult['status'] ?? false)) { + return $this->response->setStatusCode(400)->setJSON([ + 'status' => false, + 'message' => 'Input validation failed', + 'code' => 400, + 'errors' => ['settle_letter_file' => $uploadResult['message'] ?? 'Invalid Settle Letter file.'], + ]); + } + $uploadedSettleLetter = $uploadResult['data']; + $ticket_data['settle_letter'] = ''; + } else { + $ticket_data['settle_letter'] = $settleLetterUrl; + } // $ticket_data = $this->getLastMatchedStatus($ticket_data, ); // print_rr($ticket_data); die; @@ -1497,6 +1581,37 @@ class TicketController extends BaseController $ticket_data['claim_created_by'] = "CRM"; $return_value = $this->ticketMasterModel->insert($ticket_data); if ($return_value) { + if ($uploadedApprovedLetter !== null) { + $approvedLetterDownloadUrl = $this->createApprovedLetterFileUrl( + (int) $return_value, + (int) ($ticket_data['ticket_type_id'] ?? 1), + $uploadedApprovedLetter, + 'APPROVED_LETTER_PDF' + ); + $ticket_data['approved_letter'] = $approvedLetterDownloadUrl; + } + + if ($uploadedSettleLetter !== null) { + $settleLetterDownloadUrl = $this->createApprovedLetterFileUrl( + (int) $return_value, + (int) ($ticket_data['ticket_type_id'] ?? 1), + $uploadedSettleLetter, + 'SETTLE_LETTER_PDF' + ); + $ticket_data['settle_letter'] = $settleLetterDownloadUrl; + } + + if ($uploadedApprovedLetter !== null || $uploadedSettleLetter !== null) { + $updateUploadedLetterData = []; + if (isset($ticket_data['approved_letter'])) { + $updateUploadedLetterData['approved_letter'] = $ticket_data['approved_letter']; + } + if (isset($ticket_data['settle_letter'])) { + $updateUploadedLetterData['settle_letter'] = $ticket_data['settle_letter']; + } + $this->ticketMasterModel->where('id', $return_value)->set($updateUploadedLetterData)->update(); + } + //mail trigger part $this->putHistoryAfterInsert($ticket_data, $return_value); $mail_responce = $this->sendAutoMailTrigger($return_value); @@ -1515,6 +1630,8 @@ class TicketController extends BaseController { $request_data = $this->request->getPost(); + $approvedLetterFile = $this->request->getFile('approved_letter_file'); + $settleLetterFile = $this->request->getFile('settle_letter_file'); $selected_ticket_type = $this->request->getPost('ticket_type_id'); // 1. Initialize an empty rules array @@ -1830,6 +1947,85 @@ class TicketController extends BaseController $sanitized_data = sanitizeInputArrayAdvanced($request_data); $ticket_data = $this->formatDateForClaim($sanitized_data); $ticket_id = $this->request->getPost('ticket_master_id'); + $approvedLetterUrl = trim((string) ($ticket_data['approved_letter'] ?? '')); + $settleLetterUrl = trim((string) ($ticket_data['settle_letter'] ?? '')); + $hasApprovedLetterFile = $approvedLetterFile !== null + && $approvedLetterFile->isValid() + && $approvedLetterFile->getError() !== UPLOAD_ERR_NO_FILE; + $hasSettleLetterFile = $settleLetterFile !== null + && $settleLetterFile->isValid() + && $settleLetterFile->getError() !== UPLOAD_ERR_NO_FILE; + + if ($approvedLetterUrl !== '' && $hasApprovedLetterFile) { + return $this->response->setStatusCode(400)->setJSON([ + 'status' => false, + 'message' => 'Input validation failed', + 'code' => 400, + 'errors' => ['approved_letter' => 'Provide either Approved Letter URL or Approved Letter PDF file, not both.'], + ]); + } + + if ($approvedLetterUrl !== '' && ! $this->isClaimUploadUrl($approvedLetterUrl)) { + return $this->response->setStatusCode(400)->setJSON([ + 'status' => false, + 'message' => 'Input validation failed', + 'code' => 400, + 'errors' => ['approved_letter' => 'Approved Letter URL format is invalid.'], + ]); + } + + if ($settleLetterUrl !== '' && $hasSettleLetterFile) { + return $this->response->setStatusCode(400)->setJSON([ + 'status' => false, + 'message' => 'Input validation failed', + 'code' => 400, + 'errors' => ['settle_letter' => 'Provide either Settle Letter URL or Settle Letter PDF file, not both.'], + ]); + } + + if ($settleLetterUrl !== '' && ! $this->isClaimUploadUrl($settleLetterUrl)) { + return $this->response->setStatusCode(400)->setJSON([ + 'status' => false, + 'message' => 'Input validation failed', + 'code' => 400, + 'errors' => ['settle_letter' => 'Settle Letter URL format is invalid.'], + ]); + } + + $uploadedApprovedLetter = null; + if ($hasApprovedLetterFile) { + $uploadResult = $this->uploadApprovedLetterPdf($approvedLetterFile, 'Approved Letter'); + if (! ($uploadResult['status'] ?? false)) { + return $this->response->setStatusCode(400)->setJSON([ + 'status' => false, + 'message' => 'Input validation failed', + 'code' => 400, + 'errors' => ['approved_letter_file' => $uploadResult['message'] ?? 'Invalid Approved Letter file.'], + ]); + } + $uploadedApprovedLetter = $uploadResult['data']; + $ticket_data['approved_letter'] = ''; + } else { + $ticket_data['approved_letter'] = $approvedLetterUrl; + } + + $uploadedSettleLetter = null; + if ($hasSettleLetterFile) { + $uploadResult = $this->uploadApprovedLetterPdf($settleLetterFile, 'Settle Letter'); + if (! ($uploadResult['status'] ?? false)) { + return $this->response->setStatusCode(400)->setJSON([ + 'status' => false, + 'message' => 'Input validation failed', + 'code' => 400, + 'errors' => ['settle_letter_file' => $uploadResult['message'] ?? 'Invalid Settle Letter file.'], + ]); + } + $uploadedSettleLetter = $uploadResult['data']; + $ticket_data['settle_letter'] = ''; + } else { + $ticket_data['settle_letter'] = $settleLetterUrl; + } + $old_ticket_data = $this->ticketMasterModel->where('id', $ticket_id)->where('is_active', 1)->first(); $ticket_data['claim_status_id'] = $this->getLastMatchedStatus($ticket_data, $old_ticket_data); $ticket_data['last_updated_by'] = 'USER'; @@ -1840,6 +2036,24 @@ class TicketController extends BaseController $this->myLogger->logme('error', "[UPDATE_CLAIM] New Ticket Data: {data}", ['data' => json_encode($ticket_data, JSON_PRETTY_PRINT)]); if ($ticket_data) { + if ($uploadedApprovedLetter !== null) { + $ticket_data['approved_letter'] = $this->createApprovedLetterFileUrl( + (int) $ticket_id, + (int) ($ticket_data['ticket_type_id'] ?? 1), + $uploadedApprovedLetter, + 'APPROVED_LETTER_PDF' + ); + } + + if ($uploadedSettleLetter !== null) { + $ticket_data['settle_letter'] = $this->createApprovedLetterFileUrl( + (int) $ticket_id, + (int) ($ticket_data['ticket_type_id'] ?? 1), + $uploadedSettleLetter, + 'SETTLE_LETTER_PDF' + ); + } + $return_value = $this->ticketMasterModel->where('id', $ticket_id)->set($ticket_data)->update(); if ($return_value) { @@ -3262,6 +3476,55 @@ class TicketController extends BaseController return strpos($host, '.') !== false; } + private function uploadApprovedLetterPdf($file, string $documentLabel = 'Approved Letter'): array + { + if ($file === null || ! $file->isValid() || $file->getError() === UPLOAD_ERR_NO_FILE) { + return ['status' => false, 'message' => $documentLabel . ' file is missing.']; + } + + $ext = strtolower((string) $file->getClientExtension()); + $mime = strtolower((string) $file->getMimeType()); + $allowedMime = ['application/pdf', 'application/x-pdf']; + + if ($ext !== 'pdf' || (! empty($mime) && ! in_array($mime, $allowedMime, true))) { + return ['status' => false, 'message' => 'Only PDF files are allowed for ' . $documentLabel . ' upload.']; + } + + $uploadPath = WRITEPATH . 'uploads/claim_files/'; + if (! is_dir($uploadPath)) { + mkdir($uploadPath, 0755, true); + } + + $diskFileName = file_Upload_for_lead($file, $uploadPath, ['pdf']); + if (empty($diskFileName)) { + return ['status' => false, 'message' => 'Failed to upload ' . $documentLabel . ' file.']; + } + + return [ + 'status' => true, + 'data' => [ + 'file_name' => $diskFileName, + 'mime_type' => $mime ?: 'application/pdf', + ], + ]; + } + + private function createApprovedLetterFileUrl(int $ticketId, int $ticketTypeId, array $uploadedFile, string $docName = 'APPROVED_LETTER_PDF'): string + { + $fileId = $this->claimFilesModel->insert([ + 'ticket_id' => $ticketId, + 'ticket_type' => $ticketTypeId, + 'file_type' => 3, + 'doc_name' => $docName, + 'file_name' => $uploadedFile['file_name'], + 'url' => $uploadedFile['file_name'], + 'mime_type' => $uploadedFile['mime_type'] ?? 'application/pdf', + 'is_active' => 1, + ]); + + return base_url('downloadClaimFile/' . $fileId); + } + public function upload_url() { @@ -3377,6 +3640,7 @@ class TicketController extends BaseController } } + //get the claim file list data against the ticket id public function getUrlDataByTicketId() { $ticket_id = $this->request->getPost('ticket_id'); @@ -3399,6 +3663,7 @@ class TicketController extends BaseController END AS url ") ->where('ticket_id', $ticket_id) + ->where('file_type !=', 3) // Assuming you want to fetch both URL and file uploads ->where('is_active', 1) ->findAll(); diff --git a/app/Controllers/VidalApiController.php b/app/Controllers/VidalApiController.php index 06a78a57..e09fc9fb 100644 --- a/app/Controllers/VidalApiController.php +++ b/app/Controllers/VidalApiController.php @@ -156,6 +156,7 @@ class VidalApiController extends BaseController e.emp_code as memberId, tn.note as disease, tn.note as reasonForHospitalization, + cf.id as cfFileId, cf.url as fileName, cf.url as filePath, pt.policy_type as typeOfClaim, @@ -195,6 +196,7 @@ class VidalApiController extends BaseController } $fileId = $upload['fileId']; + $tpa_sent_file_id = $data['cfFileId'] ?? null; // $url = 'https://devapigw.vidalhealthtpa.com/partner-integration/api/claims/submit'; $url = getenv('VIDAL_API_BASE_URL').'/claims/submit'; $method = 'POST'; @@ -299,6 +301,18 @@ class VidalApiController extends BaseController ->where('id',$claimId) ->update([ 'tpa_claim_push_reference_no' => $claimInwardNO , 'tpa_claim_id' => $claimNO , 'claim_number' => $claimNO ]); + // Update claim files table that file is sent to tpa for this claim + if(!empty($tpa_sent_file_id)){ + + $this->db->table('claim_files') + ->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); + }else{ + log_message('error','MEDI_ASSIST - Claim Push | No file_id found to update claim_files table.'); + } + return ['status' => true, 'message' => 'Claim Push SUCCESS']; } else { @@ -1664,6 +1678,8 @@ class VidalApiController extends BaseController $fileData = $this->db->table('claim_files f') ->where('f.ticket_id', $claimId) ->where('f.docs_for_ir', 1) + ->where('f.file_type', 2) + ->where('f.is_file_sent_to_tpa', 0) ->get() ->getResultArray(); @@ -1678,6 +1694,7 @@ class VidalApiController extends BaseController // 3. UPLOAD FILES TO VIDAL $fileIdList = []; + $tpaSentFileIds = []; foreach ($fileData as $file) { @@ -1701,6 +1718,7 @@ class VidalApiController extends BaseController } $fileIdList[] = $upload['fileId']; // deeplink URL + $tpaSentFileIds[] = $file['id']; // local file ID for updating } if (empty($fileIdList)) { @@ -1756,6 +1774,18 @@ class VidalApiController extends BaseController log_message('error', "VIDAL - IR Submission SUCCESS → ClaimNO={$ticket['claimNO']}"); + // 6. UPDATE FILES AS SENT TO TPA + if(count($tpaSentFileIds) > 0){ + + $this->db->table('claim_files') + ->whereIn('id', $tpaSentFileIds) + ->update(['is_file_sent_to_tpa' => 1]); + + log_message('error',"VIDAL - IR Submission | Updating claim_files for file IDs: " . implode(', ', $tpaSentFileIds)); + } else { + log_message('error',"VIDAL - IR Submission | No files to update as sent to TPA"); + } + return [ 'status' => true, 'message' => 'IR Submitted successfully', diff --git a/app/Controllers/VoloApiController.php b/app/Controllers/VoloApiController.php index 79320a2b..63e63c6d 100644 --- a/app/Controllers/VoloApiController.php +++ b/app/Controllers/VoloApiController.php @@ -692,6 +692,7 @@ class VoloApiController extends BaseController tm.claim_amount as requestedAmount, tm.tpa_no as memberId, cp.policy_no as policyNo, + cf.id as fileId, cf.url as filePath ') ->join('client_policy cp', 'tm.client_policy_id = cp.id', 'left') @@ -710,6 +711,7 @@ class VoloApiController extends BaseController return ['status' => false, 'message' => 'Claim Push FAILED | File Missing']; } + $file_id = $data['fileId'] ?? null; $filename = basename($data['filePath']); $pdfPath = WRITEPATH . 'uploads/claim_files/' . $filename; if (!is_readable($pdfPath)) { @@ -781,6 +783,18 @@ class VoloApiController extends BaseController ]); log_message('error', '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)){ + + $this->db->table('claim_files') + ->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); + }else{ + log_message('error','VOLO - Claim Push | No file_id found to update claim_files table.'); + } + return ['status' => true, 'message' => 'Claim Push SUCCESS', 'response' => $response]; } diff --git a/app/Helpers/datatable_view_helper.php b/app/Helpers/datatable_view_helper.php new file mode 100644 index 00000000..3089f4b1 --- /dev/null +++ b/app/Helpers/datatable_view_helper.php @@ -0,0 +1,28 @@ + $headerLabels + * @param array $maxLenPerCol Same length as $headerLabels + * @param array $minPx + * @param array $maxPx + * @return array + */ +function nhance_dt_column_widths_px(array $headerLabels, array $maxLenPerCol, array $minPx, array $maxPx): array +{ + $n = count($headerLabels); + $out = []; + for ($i = 0; $i < $n; $i++) { + $chars = max($maxLenPerCol[$i] ?? 0, mb_strlen($headerLabels[$i])); + $px = (int) round($chars * 7.0 + 26); + $out[] = min( + (int) ($maxPx[$i] ?? 640), + max((int) ($minPx[$i] ?? 48), $px) + ); + } + + return $out; +} diff --git a/app/Models/ClaimFilesModel.php b/app/Models/ClaimFilesModel.php index 0d48ce05..055b9b3b 100644 --- a/app/Models/ClaimFilesModel.php +++ b/app/Models/ClaimFilesModel.php @@ -24,6 +24,7 @@ class ClaimFilesModel extends Model 'file_name', 'mime_type', 'docs_for_ir', + 'is_file_sent_to_tpa', ]; // Callbacks diff --git a/app/Views/UserList.php b/app/Views/UserList.php index 0adae2ad..141b3c50 100755 --- a/app/Views/UserList.php +++ b/app/Views/UserList.php @@ -341,6 +341,62 @@ table.dataTable tbody td { +first_name ?? ''))); + $ul_col_max_len[1] = max($ul_col_max_len[1], mb_strlen((string) ($row->email ?? ''))); + $ul_col_max_len[2] = max($ul_col_max_len[2], mb_strlen((string) ($row->mobile ?? ''))); + $ul_col_max_len[3] = max($ul_col_max_len[3], mb_strlen((string) ($row->user_role ?? ''))); + $statusLabel = (($row->is_active ?? 0) == 1) ? 'Active' : 'In-Active'; + $ul_col_max_len[4] = max($ul_col_max_len[4], mb_strlen($statusLabel)); + $ul_col_max_len[5] = max($ul_col_max_len[5], 4); + } +} +$ul_col_min_px = array_fill(0, $ul_col_count, 80); +$ul_col_max_px = array_fill(0, $ul_col_count, 360); +$ul_col_min_px[0] = 72; +$ul_col_max_px[0] = 280; +$ul_col_min_px[5] = 72; +$ul_col_max_px[5] = 96; +$ul_col_width_px = nhance_dt_column_widths_px($ul_header_labels, $ul_col_max_len, $ul_col_min_px, $ul_col_max_px); +?> + + <'col-sm-9'B>>" + // "<'row'<'col-sm-12'tr>>" + // "<'row'<'col-sm-5'i><'col-sm-7'p>>", @@ -1083,8 +1139,15 @@ table.dataTable tbody td { $(this).addClass('active'); loadPartner(); }); - } - }); + }, + columnDefs: [ + + { targets: , width: 'px' }, + + ] + })); + nhanceListDataTableAfterInit(); + nhanceListDataTableBindAdjust(table); function applyBottomRowDropup() { if (!table) return; @@ -1109,12 +1172,12 @@ table.dataTable tbody td { // IMPORTANT — DataTables draw event REF: TTS table.on('draw.dt', function () { - let rowCount = $('#scroll-horizontal-datatable').DataTable().rows({ filter: 'applied' }).count(); + let rowCount = table.rows({ filter: 'applied' }).count(); if (rowCount <= 2) { - $('.dataTables_scrollBody').css('overflow', 'inherit'); + $('#user-table_wrapper .dataTables_scrollBody').css('overflow', 'inherit'); } else { - $('.dataTables_scrollBody').css('overflow', 'auto'); + $('#user-table_wrapper .dataTables_scrollBody').css('overflow', 'auto'); } }); diff --git a/app/Views/add_image_list.php b/app/Views/add_image_list.php index 4417e947..43b32fe5 100755 --- a/app/Views/add_image_list.php +++ b/app/Views/add_image_list.php @@ -1,3 +1,27 @@ +
@@ -22,7 +85,7 @@
--> - +
@@ -338,7 +401,8 @@ $('#add_image_id').val(''); $('#client_id').val(null).trigger('change'); $('#advertise_image').val(''); - table = $('#tickets-table').DataTable({ + nhanceListDataTableBeforeInit(); + table = $('#add-image-list-table').DataTable(nhanceMergeListDataTableOptions({ // dom: "<'row'<'col-sm-1'f><'col-sm-11 text-right'B>>" + // Filter left, button right // "<'row'<'col-sm-12'tr>>" + // "<'row'<'col-sm-5'i><'col-sm-7'p>>", @@ -372,15 +436,22 @@ next: '►' } }, - paging: true - }); + paging: true, + columnDefs: [ + + { targets: , width: 'px' }, + + ], + })); + nhanceListDataTableAfterInit(); + nhanceListDataTableBindAdjust(table); function applyBottomRowDropup() { if (!table) return; const currentRows = table.rows({ page: 'current' }).nodes().toArray(); - $('#tickets-table tbody tr').removeClass('nh-force-dropup'); - $('#tickets-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup'); + $('#add-image-list-table tbody tr').removeClass('nh-force-dropup'); + $('#add-image-list-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup'); const targetCount = Math.min(2, currentRows.length); for (let i = 0; i < targetCount; i++) { @@ -392,7 +463,7 @@ } applyBottomRowDropup(); - $('#tickets-table').on('draw.dt', applyBottomRowDropup); + $('#add-image-list-table').on('draw.dt', applyBottomRowDropup); }); // ✅ Define your modal function separately diff --git a/app/Views/batch_list.php b/app/Views/batch_list.php index 9e5f256b..96d441b0 100755 --- a/app/Views/batch_list.php +++ b/app/Views/batch_list.php @@ -266,7 +266,7 @@ for ($i = 0; $i < $batch_col_count; $i++) { ?> - + - + diff --git a/app/Views/bds_renewal_report_list.php b/app/Views/bds_renewal_report_list.php index 16bb337a..40464f77 100644 --- a/app/Views/bds_renewal_report_list.php +++ b/app/Views/bds_renewal_report_list.php @@ -1,3 +1,41 @@ + $row) { + $bds_col_max_len[0] = max($bds_col_max_len[0], mb_strlen((string) ($index + 1))); + $rm = empty($row['policy_end_date']) ? ' - ' : date('M-Y', strtotime((string) $row['policy_end_date'])); + $bds_col_max_len[1] = max($bds_col_max_len[1], mb_strlen($rm)); + $bds_col_max_len[2] = max($bds_col_max_len[2], mb_strlen((string) ($issuer[$row['issuer']] ?? ' - '))); + $bds_col_max_len[3] = max($bds_col_max_len[3], mb_strlen((string) ($row['policy_no'] ?? ' - '))); + $bds_col_max_len[4] = max($bds_col_max_len[4], mb_strlen((string) ($row['policy_type'] ?? ' - '))); + $bds_col_max_len[5] = max($bds_col_max_len[5], mb_strlen((string) ($row['insurer_name'] ?? ' - '))); + $bds_col_max_len[6] = max($bds_col_max_len[6], mb_strlen((string) ($row['insurer_branch_name'] ?? ' - '))); + $bds_col_max_len[7] = max($bds_col_max_len[7], mb_strlen((string) ($row['client_name'] ?? ' - '))); + $bds_col_max_len[8] = max($bds_col_max_len[8], mb_strlen((string) ($client_type[$row['client_type'] ?? ''] ?? '-'))); + $bds_col_max_len[9] = max($bds_col_max_len[9], mb_strlen((string) ($row['revenue_type'] ?? ' - '))); + $bds_col_max_len[10] = max($bds_col_max_len[10], mb_strlen(empty($row['policy_issue_date']) ? '' : date('d/m/Y', strtotime((string) $row['policy_issue_date'])))); + $bds_col_max_len[11] = max($bds_col_max_len[11], mb_strlen(empty($row['policy_start_date']) ? '' : date('d/m/Y', strtotime((string) $row['policy_start_date'])))); + $bds_col_max_len[12] = max($bds_col_max_len[12], mb_strlen(empty($row['policy_end_date']) ? '' : date('d/m/Y', strtotime((string) $row['policy_end_date'])))); + $bds_col_max_len[13] = max($bds_col_max_len[13], mb_strlen((string) ($row['vehicle_no'] ?? ' - '))); + $bds_col_max_len[14] = max($bds_col_max_len[14], mb_strlen((string) ucfirst((string) ($row['lead_status'] ?? ' - ')))); +} +$bds_col_min_px = array_fill(0, $bds_col_count, 80); +$bds_col_min_px[0] = 48; +$bds_col_max_px = array_fill(0, $bds_col_count, 360); +$bds_col_max_px[0] = 64; +$bds_col_width_px = nhance_dt_column_widths_px($bds_header_labels, $bds_col_max_len, $bds_col_min_px, $bds_col_max_px); +?> + +
@@ -28,7 +98,7 @@ table.dataTable tbody td {
-->
-
Advertisement Image Name 
diff --git a/app/Views/bds_dump_file_list.php b/app/Views/bds_dump_file_list.php index 2d314fb9..b56448fa 100644 --- a/app/Views/bds_dump_file_list.php +++ b/app/Views/bds_dump_file_list.php @@ -45,7 +45,7 @@ ?>
+
- @@ -114,11 +184,11 @@ table.dataTable tbody td { // Datatable document ready $(document).ready(function() { - var ticketsTable = $('#scroll-horizontal-datatable'); + var ticketsTable = $('#bds-renewal-report-list-table'); if (ticketsTable.length) { - ticketsTable.DataTable({ - scrollX: true, + nhanceListDataTableBeforeInit(); + var nhBdsRenewalTable = ticketsTable.DataTable(nhanceMergeListDataTableOptions({ // dom: "<'row'<'col-sm-2'f><'col-sm-10 text-right'B>>" + // Filter left, buttons right // "<'row'<'col-sm-12'tr>>" + // "<'row'<'col-sm-5'i><'col-sm-7'p>>", // Pagination at the bottom, without page length selector @@ -163,7 +233,14 @@ $(document).ready(function() { paging: true, // Enable pagination pageLength: 20, // Set default number of rows per page (optional) ordering: true, - }); + columnDefs: [ + + { targets: , width: 'px' }, + + ], + })); + nhanceListDataTableAfterInit(); + nhanceListDataTableBindAdjust(nhBdsRenewalTable); } else { console.error("Table atet found."); } diff --git a/app/Views/business_team_list.php b/app/Views/business_team_list.php index 3a91bf1e..7172fd1b 100644 --- a/app/Views/business_team_list.php +++ b/app/Views/business_team_list.php @@ -202,7 +202,7 @@ $row){ ?> - + diff --git a/app/Views/cd_master_list.php b/app/Views/cd_master_list.php index 906d86d3..1314066a 100755 --- a/app/Views/cd_master_list.php +++ b/app/Views/cd_master_list.php @@ -1,3 +1,34 @@ + $row) { + $cdm_col_max_len[0] = max($cdm_col_max_len[0], mb_strlen((string) ($index + 1))); + $clientCell = ($row['client_name'] ?? '') . '( ' . ($row['short_name'] ?? '') . ' )'; + $cdm_col_max_len[1] = max($cdm_col_max_len[1], mb_strlen($clientCell)); + $cdm_col_max_len[2] = max($cdm_col_max_len[2], mb_strlen((string) ($row['insurer_name'] ?? ''))); + $cdm_col_max_len[3] = max($cdm_col_max_len[3], mb_strlen((string) ($row['insurer_branch_name'] ?? ''))); + $od = ! empty($row['opening_date']) ? date('d-m-Y', strtotime((string) $row['opening_date'])) : ''; + $cdm_col_max_len[4] = max($cdm_col_max_len[4], mb_strlen($od)); + $cdm_col_max_len[5] = max($cdm_col_max_len[5], mb_strlen((string) ($row['cd_ac_no'] ?? ''))); + $cdm_col_max_len[6] = max($cdm_col_max_len[6], mb_strlen((string) ($row['opening_bal'] ?? ''))); + $du = ! empty($row['created_at']) + ? (date('d-M-Y h:i A', strtotime((string) $row['created_at'])) . ' by ' . ($row['user_name'] ?? '')) + : ''; + $cdm_col_max_len[7] = max($cdm_col_max_len[7], mb_strlen($du)); + $cdm_col_max_len[8] = max($cdm_col_max_len[8], 4); +} +$cdm_col_min_px = [48, 140, 120, 140, 100, 120, 100, 200, 72]; +$cdm_col_max_px = [64, 400, 320, 360, 120, 200, 160, 480, 88]; +$cdm_col_width_px = nhance_dt_column_widths_px($cdm_header_labels, $cdm_col_max_len, $cdm_col_min_px, $cdm_col_max_px); +?> + +
@@ -28,7 +97,7 @@
--> -
@@ -83,7 +153,7 @@ table.dataTable tbody td { $row) { ?>
+
+
@@ -45,7 +114,7 @@ $row){ ?> - + @@ -80,8 +149,8 @@ $(document).ready(function() { - var table = $('#scroll-horizontal-datatable').DataTable({ - scrollX: true, + nhanceListDataTableBeforeInit(); + var table = $('#cd-master-list-table').DataTable(nhanceMergeListDataTableOptions({ // dom: "<'row'<'col-sm-6'f><'col-sm-6 text-right'B>>" + // "<'row'<'col-sm-12'tr>>" + // "<'row'<'col-sm-5'i><'col-sm-7'p>>", @@ -141,7 +210,12 @@ }, paging: true, pageLength: 10, - order: [[0, 'desc']] + order: [[0, 'desc']], + columnDefs: [ + + { targets: , width: 'px' }, + + ], // scrollX: true, // dom: "<'row'<'col-sm-6'f><'col-sm-6 text-right'B>>" + // "<'row'<'col-sm-12'tr>>" + @@ -169,13 +243,15 @@ // searchPlaceholder: "Search..." // }, // paging: true, - }); + })); + nhanceListDataTableAfterInit(); + nhanceListDataTableBindAdjust(table); function applyBottomRowDropup() { if (!table) return; const currentRows = table.rows({ page: 'current' }).nodes().toArray(); - $('#scroll-horizontal-datatable tbody tr').removeClass('nh-force-dropup'); - $('#scroll-horizontal-datatable tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup'); + $('#cd-master-list-table tbody tr').removeClass('nh-force-dropup'); + $('#cd-master-list-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup'); const targetCount = Math.min(2, currentRows.length); for (let i = 0; i < targetCount; i++) { @@ -186,7 +262,7 @@ } } applyBottomRowDropup(); - $('#scroll-horizontal-datatable').on('draw.dt', applyBottomRowDropup); + $('#cd-master-list-table').on('draw.dt', applyBottomRowDropup); }) $(document).ready(function(){ diff --git a/app/Views/claim_dump_file_list.php b/app/Views/claim_dump_file_list.php index 146aaa4b..ab3ca668 100644 --- a/app/Views/claim_dump_file_list.php +++ b/app/Views/claim_dump_file_list.php @@ -155,7 +155,7 @@ ?> - + - +
S.No 
( )
diff --git a/app/Views/claim_mis_file_list.php b/app/Views/claim_mis_file_list.php index d26e91be..dacfbbb4 100644 --- a/app/Views/claim_mis_file_list.php +++ b/app/Views/claim_mis_file_list.php @@ -46,7 +46,7 @@ ?>
' . $file['user_name'] . '' ?> diff --git a/app/Views/client_basic_info.php b/app/Views/client_basic_info.php index 4cf5ab23..ce8b0735 100755 --- a/app/Views/client_basic_info.php +++ b/app/Views/client_basic_info.php @@ -106,6 +106,58 @@ input:checked + .slider:before { .slider.round:before { border-radius: 50%; } + +.hr-processed-options { + display: inline-flex; + align-items: center; + justify-content: flex-start; + gap: 1.25rem; + flex-wrap: nowrap; + white-space: nowrap; + width: auto; + max-width: 100%; +} + +.hr-processed-option { + display: inline-flex; + align-items: center; + justify-content: flex-start; + flex: 0 0 auto; + width: auto; + margin: 0; +} + +.hr-radio-input { + appearance: auto; + -webkit-appearance: radio; + width: 14px; + height: 14px; + margin-top: 0; + margin-right: 0.35rem; + margin-left: 0; + position: static; + float: none; + vertical-align: middle; +} + +.hr-radio-label { + display: inline-block; + width: auto; + margin: 0; + white-space: nowrap; + line-height: 1.2; +} + +#hr_file_processed_by_error_container { + display: block; + width: 100%; + margin-top: 0.25rem; + clear: both; +} + +#hr_file_processed_by_error_container .parsley-errors-list { + margin-bottom: 0; +}
@@ -170,8 +222,10 @@ input:checked + .slider:before { id="client_logo" name="client_logo" accept="image/jpeg, image/jpg, image/png" onchange="PreviewImage0(event);" - data-parsley-max-file-size="200" - data-parsley-file-extension="jpg,jpeg,png" + data-parsley-client-max-file-size="200" + data-parsley-client-file-extension="jpg,jpeg,png" + data-parsley-client-max-file-size-message="Maximum file size allowed is 200KB." + data-parsley-client-file-extension-message="Only JPG, JPEG, PNG files are allowed." data-parsley-errors-container="#client_logo_error_container" />
@@ -198,25 +252,29 @@ input:checked + .slider:before {
- +
- +
- +
- +
@@ -54,9 +136,9 @@ ?> @@ -73,7 +155,8 @@ \ No newline at end of file diff --git a/app/Views/frontend_content_list.php b/app/Views/frontend_content_list.php index 7ea2e54a..695feb65 100644 --- a/app/Views/frontend_content_list.php +++ b/app/Views/frontend_content_list.php @@ -1,8 +1,72 @@ + @@ -10,7 +74,7 @@
-
Insurer Name  - insurer_id}?client_id={$value->client_id}&cd_ac_pk={$value->cd_ac_pk}"); ?>"> - View Deposit + View Deposit
+
@@ -26,7 +90,7 @@ $row) { ?> - + @@ -268,9 +332,9 @@ $('#notes').parsley().validate(); }); - var ticketsTable = $('#user-table'); - table = ticketsTable.DataTable({ - scrollX: true, + var ticketsTable = $('#frontend-content-list-table'); + nhanceListDataTableBeforeInit(); + table = ticketsTable.DataTable(nhanceMergeListDataTableOptions({ // dom: "<'row'<'col-sm-7'f><'col-sm-5 text-right'B>>" + // Filter left, buttons right // "<'row'<'col-sm-12'tr>>" + // "<'row'<'col-sm-5'i><'col-sm-7'p>>", // Pagination at the bottom, without page length selector @@ -322,14 +386,21 @@ paging: true, // Enable pagination pageLength: 10, // Set default number of rows per page (optional) // ordering: false, - }); + columnDefs: [ + + { targets: , width: 'px' }, + + ], + })); + nhanceListDataTableAfterInit(); + nhanceListDataTableBindAdjust(table); function applyBottomRowDropup() { if (!table) return; const currentRows = table.rows({ page: 'current' }).nodes().toArray(); - $('#user-table tbody tr').removeClass('nh-force-dropup'); - $('#user-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup'); + $('#frontend-content-list-table tbody tr').removeClass('nh-force-dropup'); + $('#frontend-content-list-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup'); const targetCount = Math.min(2, currentRows.length); for (let i = 0; i < targetCount; i++) { @@ -340,7 +411,7 @@ } } applyBottomRowDropup(); - $('#user-table').on('draw.dt', applyBottomRowDropup); + $('#frontend-content-list-table').on('draw.dt', applyBottomRowDropup); }); $('.close').click(function(){ resetValues(); }) @@ -691,7 +762,7 @@
- +
- +
- +
@@ -435,8 +452,11 @@ switch (key) { case 'branch_name': + if (v.length < 3) return 'Branch Name must be at least 3 characters.'; + if (!/^[a-zA-Z0-9\s_-]+$/.test(v)) return 'Branch Name can contain letters, numbers, spaces, underscore (_) and hyphen (-).'; return ''; case 'branch_code': + if (!/^[a-zA-Z0-9_-]+$/.test(v)) return 'Branch Code can contain letters, numbers, underscore (_) and hyphen (-).'; return ''; case 'address1': return ''; @@ -458,6 +478,7 @@ if (!contactNamePattern.test(v)) return 'Contact name is invalid Format'; return ''; case 'designation': + if (!/^[A-Za-z0-9\-_\/ ]+$/.test(v)) return 'Designation may only contain letters, numbers, /, -, _ and spaces.'; return ''; case 'email': if (!emailPattern.test(v)) return 'Please enter a valid email format (e.g., name@domain.com).'; @@ -946,19 +967,25 @@
- +
- +
- +
diff --git a/app/Views/insurer_export_templete.php b/app/Views/insurer_export_templete.php index 73d725e1..5edcc832 100755 --- a/app/Views/insurer_export_templete.php +++ b/app/Views/insurer_export_templete.php @@ -111,7 +111,7 @@ $value ){ ?>
- + diff --git a/app/Views/insurer_list.php b/app/Views/insurer_list.php index 1c22b60f..b0611e6b 100755 --- a/app/Views/insurer_list.php +++ b/app/Views/insurer_list.php @@ -1,3 +1,24 @@ + +
@@ -30,7 +89,7 @@
-->
+ id="insurer-list-table"> @@ -71,10 +130,8 @@ -
+
-

+
diff --git a/app/Views/invoice_template.php b/app/Views/invoice_template.php index 865ab921..3a61a602 100644 --- a/app/Views/invoice_template.php +++ b/app/Views/invoice_template.php @@ -359,7 +359,7 @@ body { $page_break_class = (($serial % $records_per_page) == 0 && $serial != count($policies)) ? 'page-break' : ''; ?>

- + diff --git a/app/Views/kyc_list.php b/app/Views/kyc_list.php index 7754f2a8..ec621cd3 100755 --- a/app/Views/kyc_list.php +++ b/app/Views/kyc_list.php @@ -1,3 +1,22 @@ + + +
@@ -50,7 +107,7 @@
-->
Name 
+ id="kyc-list-table"> @@ -83,7 +140,7 @@ + + + diff --git a/app/Views/leads_form.php b/app/Views/leads_form.php index c4b3e57a..1f4811d0 100644 --- a/app/Views/leads_form.php +++ b/app/Views/leads_form.php @@ -689,6 +689,17 @@ //------------------------------ GET DATA ( EDIT, BRANCH, POLICY ) --------------------------------------------------------------------------- //view and edit Lead data function ( NOT IN USE DON'T DELETE ) + function togglePolicyTypeDivider(dataIncrement) { + var $policyType = $('#policy_type_id_' + dataIncrement); + var selectedPolicyText = ($policyType.find('option:selected').text() || '').toLowerCase(); + var isGmcPolicy = selectedPolicyText.indexOf('gmc') !== -1; + var $policyDivider = $('#appendArea_' + dataIncrement).find('hr').first(); + + if ($policyDivider.length) { + $policyDivider.toggle(!isGmcPolicy); + } + } + function getLeadsDataForEdit(input) { $('.loader').fadeIn(); @@ -718,6 +729,7 @@ if (typeof window.refreshLeadsFormValidation === 'function') { window.refreshLeadsFormValidation(); } + togglePolicyTypeDivider(dataIncrement); let policy_type_id = res.data.policy_type_id; let lead_type = res.data.lead_type; @@ -1105,6 +1117,7 @@ if (typeof window.refreshLeadsFormValidation === 'function') { window.refreshLeadsFormValidation(); } + togglePolicyTypeDivider(dataIncrement); console.log("Policy Type ID : ", policy_type_id); if (policy_type_id == 1 || policy_type_id == 6 || policy_type_id == 7) { diff --git a/app/Views/leads_list.php b/app/Views/leads_list.php index 42f32f88..b496dfe4 100644 --- a/app/Views/leads_list.php +++ b/app/Views/leads_list.php @@ -1,3 +1,55 @@ + $row) { + $leads_col_max_len[0] = max($leads_col_max_len[0], mb_strlen((string) ($index + 1))); + $leads_col_max_len[1] = max($leads_col_max_len[1], mb_strlen((string) ($lead_type[$row['lead_type'] ?? ''] ?? '-'))); + $leads_col_max_len[2] = max($leads_col_max_len[2], mb_strlen((string) ($issuer[$row['issuer'] ?? ''] ?? '-'))); + $leads_col_max_len[3] = max($leads_col_max_len[3], mb_strlen((string) ($client_type[$row['client_type'] ?? ''] ?? '-'))); + $clientBranch = (isset($row['client_type']) && (int) $row['client_type'] === 2) + ? (string) ($row['client_name'] ?? '-') + : (string) (($row['client_short_name'] ?? '-') . ' - ' . ($row['branch_name'] ?? '-')); + $leads_col_max_len[4] = max($leads_col_max_len[4], mb_strlen($clientBranch)); + $leads_col_max_len[5] = max($leads_col_max_len[5], mb_strlen((string) ($row['entity_type'] ?? '-'))); + $leads_col_max_len[6] = max($leads_col_max_len[6], mb_strlen((string) ($row['branch_name'] ?? '-'))); + $leads_col_max_len[7] = max($leads_col_max_len[7], mb_strlen((string) ($row['branch_code'] ?? '-'))); + $leads_col_max_len[8] = max($leads_col_max_len[8], mb_strlen((string) ($row['contact_person_name'] ?? '-'))); + $leads_col_max_len[9] = max($leads_col_max_len[9], mb_strlen((string) ($row['contact_person_mobile'] ?? '-'))); + $leads_col_max_len[10] = max($leads_col_max_len[10], mb_strlen((string) ($row['policy_type'] ?? '-'))); + $leads_col_max_len[11] = max($leads_col_max_len[11], mb_strlen((string) ($lead_status[$row['status'] ?? ''] ?? '-'))); + $leads_col_max_len[12] = max($leads_col_max_len[12], 4); + } +} + +$leads_col_min_px = [48, 72, 88, 72, 120, 88, 96, 72, 120, 100, 120, 96, 52]; +$leads_col_max_px = [64, 220, 180, 140, 520, 200, 240, 120, 280, 130, 280, 200, 72]; +$leads_col_width_px = []; +for ($i = 0; $i < $leads_col_count; $i++) { + $chars = max($leads_col_max_len[$i], mb_strlen($leads_header_labels[$i])); + $px = (int) round($chars * 7.0 + 26); + $leads_col_width_px[$i] = min( + $leads_col_max_px[$i], + max($leads_col_min_px[$i], $px) + ); +} +?> @@ -134,7 +240,7 @@
-
Name
+
@@ -158,7 +264,7 @@ $row) {?> - - +
+ <'col-sm-5 text-right'B>>" + // Filter left, buttons right // "<'row'<'col-sm-12'tr>>" + // "<'row'<'col-sm-5'i><'col-sm-7'p>>", // Pagination at the bottom, without page length selector @@ -778,14 +885,21 @@ paging: true, // Enable pagination pageLength: 10, // Set default number of rows per page (optional) // ordering: false, - }); + columnDefs: [ + + { targets: , width: 'px' }, + + ], + })); + nhanceListDataTableAfterInit(); + nhanceListDataTableBindAdjust(table); function applyBottomRowDropup() { if (!table) return; const currentRows = table.rows({ page: 'current' }).nodes().toArray(); - $('#tickets-table tbody tr').removeClass('nh-force-dropup'); - $('#tickets-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup'); + $('#leads-list-table tbody tr').removeClass('nh-force-dropup'); + $('#leads-list-table tbody tr td.table-action-cell .btn-group.dropdown').removeClass('dropup'); const targetCount = Math.min(2, currentRows.length); for (let i = 0; i < targetCount; i++) { diff --git a/app/Views/log_view.php b/app/Views/log_view.php index 1af7ebde..73844e6a 100644 --- a/app/Views/log_view.php +++ b/app/Views/log_view.php @@ -32,7 +32,7 @@ table.dataTable tbody td { $log): ?>
View | diff --git a/app/Views/newClientModal-old.php b/app/Views/newClientModal-old.php index 1e2f3347..b6261894 100644 --- a/app/Views/newClientModal-old.php +++ b/app/Views/newClientModal-old.php @@ -13,16 +13,16 @@
- +
- +
- +
@@ -48,7 +48,7 @@
- +
@@ -72,17 +72,17 @@
- +
- +
- +
@@ -97,7 +97,7 @@
+ data-parsley-error-message="Invalid GST Number. Example: 12ABCDE1234F5Z6" name="gst" data-parsley-trigger="change" data-parsley-pattern="^\d{2}[A-Z]{5}\d{4}[A-Z]{1}[A-Z\d]{1}[Z]{1}[A-Z\d]{1}$" onkeypress="return restrictCharacters(event, /[A-Z0-9]/)" oninput="this.value = this.value.toUpperCase()" required>
@@ -116,6 +116,34 @@ let isGSTValidating = false; let isGSTValid = false; + function restrictCharacters(event, pattern) { + // Allow control keys (Backspace, Tab, Enter, etc.) which have charCode < 32 + // or are navigation keys. + if (event.which < 32 || event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "Delete" || event.key === "Backspace" || event.key === "Tab") { + return true; + } + const char = String.fromCharCode(event.which); + if (!pattern.test(char)) { + event.preventDefault(); + return false; + } + return true; + } + + function onlyNumbers(event) { + const charCode = (event.which) ? event.which : event.keyCode; + // Allow control keys + if (event.which < 32 || event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "Delete" || event.key === "Backspace" || event.key === "Tab") { + return true; + } + // Allow numbers 0-9 + if (charCode > 31 && (charCode < 48 || charCode > 57)) { + event.preventDefault(); + return false; + } + return true; + } + function validateInputForClient(input, table, field) { let owner_type = $('#Owner_type').val(); diff --git a/app/Views/nhance_branch_list.php b/app/Views/nhance_branch_list.php index bd302e8a..dc0190c1 100644 --- a/app/Views/nhance_branch_list.php +++ b/app/Views/nhance_branch_list.php @@ -1,8 +1,66 @@ + @@ -10,7 +68,7 @@
- +
@@ -23,7 +81,7 @@ $row) { ?> - +
-
S.No.
+
@@ -173,7 +238,7 @@ if (isset($outstanting_list)) { ?> $row) { ?> - + @@ -210,11 +275,11 @@ $(document).ready(function() { - var ticketsTable = $('#scroll-horizontal-datatable'); + var ticketsTable = $('#outstanding-report-list-table'); if (ticketsTable.length) { - ticketsTable.DataTable({ - scrollX: true, + nhanceListDataTableBeforeInit(); + var nhOutstandingTable = ticketsTable.DataTable(nhanceMergeListDataTableOptions({ // dom: "<'row'<'col-sm-6'f><'col-sm-6 text-right'B>>" + // Filter left, buttons right // "<'row'<'col-sm-12'tr>>" + // "<'row'<'col-sm-5'i><'col-sm-7'p>>", // Pagination at the bottom, without page length selector @@ -290,8 +355,15 @@ emptyTable: '
No Data found
' }, paging: true, // Enable pagination - pageLength: 25 // Set default number of rows per page (optional) - }); + pageLength: 25, // Set default number of rows per page (optional) + columnDefs: [ + + { targets: , width: 'px' }, + + ], + })); + nhanceListDataTableAfterInit(); + nhanceListDataTableBindAdjust(nhOutstandingTable); } else { console.error("Table not found."); } diff --git a/app/Views/policy_transaction_endorsement_list.php b/app/Views/policy_transaction_endorsement_list.php index 7fbfff67..0f2555fa 100644 --- a/app/Views/policy_transaction_endorsement_list.php +++ b/app/Views/policy_transaction_endorsement_list.php @@ -296,7 +296,7 @@ $row) { ?> - + diff --git a/app/Views/policy_transaction_endorsement_list_2.php b/app/Views/policy_transaction_endorsement_list_2.php index 8e26b2c3..38b7afb4 100644 --- a/app/Views/policy_transaction_endorsement_list_2.php +++ b/app/Views/policy_transaction_endorsement_list_2.php @@ -325,7 +325,7 @@ table.dataTable thead th { $row) { ?> - + diff --git a/app/Views/policy_type_list.php b/app/Views/policy_type_list.php index 7679b722..8f546d68 100755 --- a/app/Views/policy_type_list.php +++ b/app/Views/policy_type_list.php @@ -1,3 +1,26 @@ + + +
@@ -87,7 +152,7 @@
-->
S.No
+ id="policy-type-list-table"> @@ -131,7 +196,7 @@ \ No newline at end of file + diff --git a/app/Views/ticket_form_gmc.php b/app/Views/ticket_form_gmc.php index 4db28f7d..003e4c3b 100644 --- a/app/Views/ticket_form_gmc.php +++ b/app/Views/ticket_form_gmc.php @@ -429,10 +429,26 @@ value="" name="approved_date"> -
Policy Type
+ id="tpa-list-table"> @@ -87,7 +145,10 @@ + \ No newline at end of file diff --git a/public/assets/css/custom.css b/public/assets/css/custom.css index 7f6fc33b..f10a3ec0 100644 --- a/public/assets/css/custom.css +++ b/public/assets/css/custom.css @@ -384,44 +384,46 @@ table.dataTable tbody > tr > td:last-child { padding-right: 1.35rem !important; } +table.dataTable thead > tr > th:last-child { + text-align: left; +} + /* * Action cells: only when the last column contains a Bootstrap dropdown (avoids - * right-aligning numeric/text-only last columns on other listings). + * affecting numeric/text-only last columns that are not row actions). */ table.dataTable tbody > tr > td:last-child:has(.dropdown) { position: relative; - text-align: right; + text-align: left; } table.dataTable tbody > tr > td:last-child:has(.dropdown) .btn-group.dropdown { display: inline-flex; - justify-content: flex-end; + justify-content: flex-start; } /* ----------------------------------------------------------------------------- - * Action column — centered “…” / dropdown (opt-in per row) - * Add class="table-action-cell" on the
Name that wraps .btn-group.dropdown - * (any column position; overrides last-column right-align above). + * Action column — left-aligned “…” / dropdown (footer.js adds .table-action-cell) * ----------------------------------------------------------------------------- */ table.dataTable tbody > tr > td.table-action-cell { - text-align: center !important; + text-align: left !important; vertical-align: middle !important; } table.dataTable tbody > tr > td.table-action-cell .btn-group.dropdown { display: inline-flex !important; - justify-content: center !important; + justify-content: flex-start !important; float: none !important; margin-right: 0 !important; /* Prevent global dropdown margin shifting anchor */ } table.dataTable tbody > tr > td:last-child.table-action-cell:has(.dropdown), table.dataTable tbody > tr > td.table-action-cell:has(.dropdown) { - text-align: center !important; + text-align: left !important; } table.dataTable tbody > tr > td:last-child.table-action-cell:has(.dropdown) .btn-group.dropdown { - justify-content: center !important; + justify-content: flex-start !important; } /* Dropdown menu stacks above row borders / scroll quirks */ diff --git a/public/assets/js/pages/nhance-list-datatable.js b/public/assets/js/pages/nhance-list-datatable.js new file mode 100644 index 00000000..3c66c140 --- /dev/null +++ b/public/assets/js/pages/nhance-list-datatable.js @@ -0,0 +1,111 @@ +/** + * Shared list DataTable behavior (aligned with batch_list.php): + * - Temporarily neutralize scroll defaults during init + * - Force scrollX/Y/Collapse off, autoWidth/responsive false + * - Sync horizontal scroll between scrollHead and scrollBody when present + * - columns.adjust on draw, resize, and after first paint + */ +(function (window, $) { + "use strict"; + if (typeof $ === "undefined" || !$ || !$.fn || !$.fn.DataTable) { + return; + } + + var _savedDefaults = null; + + window.nhanceListDataTableBeforeInit = function () { + _savedDefaults = { + scrollX: $.fn.dataTable.defaults.scrollX, + scrollY: $.fn.dataTable.defaults.scrollY, + scrollCollapse: $.fn.dataTable.defaults.scrollCollapse, + bScrollCollapse: $.fn.dataTable.defaults.bScrollCollapse, + sScrollX: $.fn.dataTable.defaults.sScrollX, + sScrollY: $.fn.dataTable.defaults.sScrollY, + sScrollXInner: $.fn.dataTable.defaults.sScrollXInner, + }; + $.extend($.fn.dataTable.defaults, { + scrollX: false, + scrollY: false, + scrollCollapse: false, + bScrollCollapse: false, + sScrollX: "", + sScrollY: "", + sScrollXInner: "", + }); + }; + + window.nhanceListDataTableAfterInit = function () { + if (_savedDefaults) { + $.extend($.fn.dataTable.defaults, _savedDefaults); + _savedDefaults = null; + } + }; + + window.nhanceListDataTableBaseInitComplete = function () { + return function () { + var api = this.api(); + var $wrap = $(api.table().container()); + var $body = $wrap.find(".dataTables_scrollBody"); + var $head = $wrap.find(".dataTables_scrollHead"); + if ($body.length && $head.length) { + $body.off("scroll.nhanceListHScroll").on("scroll.nhanceListHScroll", function () { + $head.scrollLeft($(this).scrollLeft()); + }); + $head.off("scroll.nhanceListHScroll").on("scroll.nhanceListHScroll", function () { + $body.scrollLeft($(this).scrollLeft()); + }); + } + }; + }; + + /** + * Merge page-specific DataTable options with batch_list-style list defaults. + * User initComplete runs after base scroll sync. + */ + window.nhanceMergeListDataTableOptions = function (userOptions) { + userOptions = userOptions || {}; + var userInit = userOptions.initComplete; + var merged = $.extend(true, {}, userOptions); + /* DataTables maps these to oScroll *before* pb()/tb() runs. CamelCase alone is not enough if + sScrollX/sScrollY were set via defaults, Hungarian options, or truthy strings. */ + merged.scrollX = false; + merged.scrollY = false; + merged.scrollCollapse = false; + merged.sScrollX = ""; + merged.sScrollY = ""; + merged.sScrollXInner = ""; + merged.bScrollCollapse = false; + merged.autoWidth = false; + merged.responsive = false; + if (merged.paging === undefined) { + merged.paging = true; + } + var baseInit = window.nhanceListDataTableBaseInitComplete(); + merged.initComplete = function () { + baseInit.call(this); + if (typeof userInit === "function") { + userInit.call(this); + } + }; + return merged; + }; + + window.nhanceListDataTableBindAdjust = function (dtApi) { + if (!dtApi || !dtApi.on) { + return; + } + var tid = $(dtApi.table().node()).attr("id") || "nhance_dt"; + var resizeNs = "resize.nhanceListDt_" + tid; + + dtApi.columns.adjust(); + dtApi.on("draw.dt", function () { + dtApi.columns.adjust(); + }); + $(window).off(resizeNs).on(resizeNs, function () { + dtApi.columns.adjust(); + }); + setTimeout(function () { + dtApi.columns.adjust(); + }, 0); + }; +})(window, jQuery);